// Copyright 2019 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package android

import (
	"reflect"
	"runtime"
	"testing"

	"github.com/google/blueprint/proptools"
)

type Named struct {
	A *string `android:"arch_variant"`
	B *string
}

type NamedAllFiltered struct {
	A *string
}

type NamedNoneFiltered struct {
	A *string `android:"arch_variant"`
}

func TestFilterArchStruct(t *testing.T) {
	tests := []struct {
		name     string
		in       interface{}
		out      interface{}
		filtered bool
	}{
		// Property tests
		{
			name: "basic",
			in: &struct {
				A *string `android:"arch_variant"`
				B *string
			}{},
			out: &struct {
				A *string
			}{},
			filtered: true,
		},
		{
			name: "all filtered",
			in: &struct {
				A *string
			}{},
			out:      nil,
			filtered: true,
		},
		{
			name: "none filtered",
			in: &struct {
				A *string `android:"arch_variant"`
			}{},
			out: &struct {
				A *string `android:"arch_variant"`
			}{},
			filtered: false,
		},

		// Sub-struct tests
		{
			name: "substruct",
			in: &struct {
				A struct {
					A *string `android:"arch_variant"`
					B *string
				} `android:"arch_variant"`
			}{},
			out: &struct {
				A struct {
					A *string
				}
			}{},
			filtered: true,
		},
		{
			name: "substruct all filtered",
			in: &struct {
				A struct {
					A *string
				} `android:"arch_variant"`
			}{},
			out:      nil,
			filtered: true,
		},
		{
			name: "substruct none filtered",
			in: &struct {
				A struct {
					A *string `android:"arch_variant"`
				} `android:"arch_variant"`
			}{},
			out: &struct {
				A struct {
					A *string `android:"arch_variant"`
				} `android:"arch_variant"`
			}{},
			filtered: false,
		},

		// Named sub-struct tests
		{
			name: "named substruct",
			in: &struct {
				A Named `android:"arch_variant"`
			}{},
			out: &struct {
				A struct {
					A *string
				}
			}{},
			filtered: true,
		},
		{
			name: "substruct all filtered",
			in: &struct {
				A NamedAllFiltered `android:"arch_variant"`
			}{},
			out:      nil,
			filtered: true,
		},
		{
			name: "substruct none filtered",
			in: &struct {
				A NamedNoneFiltered `android:"arch_variant"`
			}{},
			out: &struct {
				A NamedNoneFiltered `android:"arch_variant"`
			}{},
			filtered: false,
		},

		// Pointer to sub-struct tests
		{
			name: "pointer substruct",
			in: &struct {
				A *struct {
					A *string `android:"arch_variant"`
					B *string
				} `android:"arch_variant"`
			}{},
			out: &struct {
				A *struct {
					A *string
				}
			}{},
			filtered: true,
		},
		{
			name: "pointer substruct all filtered",
			in: &struct {
				A *struct {
					A *string
				} `android:"arch_variant"`
			}{},
			out:      nil,
			filtered: true,
		},
		{
			name: "pointer substruct none filtered",
			in: &struct {
				A *struct {
					A *string `android:"arch_variant"`
				} `android:"arch_variant"`
			}{},
			out: &struct {
				A *struct {
					A *string `android:"arch_variant"`
				} `android:"arch_variant"`
			}{},
			filtered: false,
		},

		// Pointer to named sub-struct tests
		{
			name: "pointer named substruct",
			in: &struct {
				A *Named `android:"arch_variant"`
			}{},
			out: &struct {
				A *struct {
					A *string
				}
			}{},
			filtered: true,
		},
		{
			name: "pointer substruct all filtered",
			in: &struct {
				A *NamedAllFiltered `android:"arch_variant"`
			}{},
			out:      nil,
			filtered: true,
		},
		{
			name: "pointer substruct none filtered",
			in: &struct {
				A *NamedNoneFiltered `android:"arch_variant"`
			}{},
			out: &struct {
				A *NamedNoneFiltered `android:"arch_variant"`
			}{},
			filtered: false,
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			out, filtered := proptools.FilterPropertyStruct(reflect.TypeOf(test.in), filterArchStruct)
			if filtered != test.filtered {
				t.Errorf("expected filtered %v, got %v", test.filtered, filtered)
			}
			expected := reflect.TypeOf(test.out)
			if out != expected {
				t.Errorf("expected type %v, got %v", expected, out)
			}
		})
	}
}

type archTestModule struct {
	ModuleBase
	props struct {
		Deps []string
	}
}

func (m *archTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
}

func (m *archTestModule) DepsMutator(ctx BottomUpMutatorContext) {
	ctx.AddDependency(ctx.Module(), nil, m.props.Deps...)
}

func archTestModuleFactory() Module {
	m := &archTestModule{}
	m.AddProperties(&m.props)
	InitAndroidArchModule(m, HostAndDeviceSupported, MultilibBoth)
	return m
}

func TestArchMutator(t *testing.T) {
	var buildOSVariants []string
	var buildOS32Variants []string
	switch runtime.GOOS {
	case "linux":
		buildOSVariants = []string{"linux_glibc_x86_64", "linux_glibc_x86"}
		buildOS32Variants = []string{"linux_glibc_x86"}
	case "darwin":
		buildOSVariants = []string{"darwin_x86_64"}
		buildOS32Variants = nil
	}

	bp := `
		module {
			name: "foo",
		}

		module {
			name: "bar",
			host_supported: true,
		}

		module {
			name: "baz",
			device_supported: false,
		}

		module {
			name: "qux",
			host_supported: true,
			compile_multilib: "32",
		}
	`

	mockFS := map[string][]byte{
		"Android.bp": []byte(bp),
	}

	testCases := []struct {
		name        string
		config      func(Config)
		fooVariants []string
		barVariants []string
		bazVariants []string
		quxVariants []string
	}{
		{
			name:        "normal",
			config:      nil,
			fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"},
			barVariants: append(buildOSVariants, "android_arm64_armv8-a", "android_arm_armv7-a-neon"),
			bazVariants: nil,
			quxVariants: append(buildOS32Variants, "android_arm_armv7-a-neon"),
		},
		{
			name: "host-only",
			config: func(config Config) {
				config.BuildOSTarget = Target{}
				config.BuildOSCommonTarget = Target{}
				config.Targets[Android] = nil
			},
			fooVariants: nil,
			barVariants: buildOSVariants,
			bazVariants: nil,
			quxVariants: buildOS32Variants,
		},
	}

	enabledVariants := func(ctx *TestContext, name string) []string {
		var ret []string
		variants := ctx.ModuleVariantsForTests(name)
		for _, variant := range variants {
			m := ctx.ModuleForTests(name, variant)
			if m.Module().Enabled() {
				ret = append(ret, variant)
			}
		}
		return ret
	}

	for _, tt := range testCases {
		t.Run(tt.name, func(t *testing.T) {
			ctx := NewTestArchContext()
			ctx.RegisterModuleType("module", ModuleFactoryAdaptor(archTestModuleFactory))
			ctx.MockFileSystem(mockFS)
			ctx.Register()
			config := TestArchConfig(buildDir, nil)
			if tt.config != nil {
				tt.config(config)
			}

			_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
			FailIfErrored(t, errs)
			_, errs = ctx.PrepareBuildActions(config)
			FailIfErrored(t, errs)

			if g, w := enabledVariants(ctx, "foo"), tt.fooVariants; !reflect.DeepEqual(w, g) {
				t.Errorf("want foo variants:\n%q\ngot:\n%q\n", w, g)
			}

			if g, w := enabledVariants(ctx, "bar"), tt.barVariants; !reflect.DeepEqual(w, g) {
				t.Errorf("want bar variants:\n%q\ngot:\n%q\n", w, g)
			}

			if g, w := enabledVariants(ctx, "baz"), tt.bazVariants; !reflect.DeepEqual(w, g) {
				t.Errorf("want baz variants:\n%q\ngot:\n%q\n", w, g)
			}

			if g, w := enabledVariants(ctx, "qux"), tt.quxVariants; !reflect.DeepEqual(w, g) {
				t.Errorf("want qux variants:\n%q\ngot:\n%q\n", w, g)
			}
		})
	}
}
