// Copyright 2017 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 (
	"bytes"
	"fmt"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"sync"
	"testing"

	mkparser "android/soong/androidmk/parser"

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

func newTestContextForFixture(config Config) *TestContext {
	ctx := &TestContext{
		Context: &Context{blueprint.NewContext(), config},
	}

	ctx.postDeps = append(ctx.postDeps, registerPathDepsMutator)

	ctx.SetFs(ctx.config.fs)
	if ctx.config.mockBpList != "" {
		ctx.SetModuleListFile(ctx.config.mockBpList)
	}

	return ctx
}

func NewTestContext(config Config) *TestContext {
	ctx := newTestContextForFixture(config)

	nameResolver := NewNameResolver(config)
	ctx.NameResolver = nameResolver
	ctx.SetNameInterface(nameResolver)

	return ctx
}

var PrepareForTestWithArchMutator = GroupFixturePreparers(
	// Configure architecture targets in the fixture config.
	FixtureModifyConfig(modifyTestConfigToSupportArchMutator),

	// Add the arch mutator to the context.
	FixtureRegisterWithContext(func(ctx RegistrationContext) {
		ctx.PreDepsMutators(registerArchMutator)
	}),
)

var PrepareForTestWithDefaults = FixtureRegisterWithContext(func(ctx RegistrationContext) {
	ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
})

var PrepareForTestWithComponentsMutator = FixtureRegisterWithContext(func(ctx RegistrationContext) {
	ctx.PreArchMutators(RegisterComponentsMutator)
})

var PrepareForTestWithPrebuilts = FixtureRegisterWithContext(RegisterPrebuiltMutators)

var PrepareForTestWithOverrides = FixtureRegisterWithContext(func(ctx RegistrationContext) {
	ctx.PostDepsMutators(RegisterOverridePostDepsMutators)
})

var PrepareForTestWithLicenses = GroupFixturePreparers(
	FixtureRegisterWithContext(RegisterLicenseKindBuildComponents),
	FixtureRegisterWithContext(RegisterLicenseBuildComponents),
	FixtureRegisterWithContext(registerLicenseMutators),
)

var PrepareForTestWithGenNotice = FixtureRegisterWithContext(RegisterGenNoticeBuildComponents)

func registerLicenseMutators(ctx RegistrationContext) {
	ctx.PreArchMutators(RegisterLicensesPackageMapper)
	ctx.PreArchMutators(RegisterLicensesPropertyGatherer)
	ctx.PostDepsMutators(RegisterLicensesDependencyChecker)
}

var PrepareForTestWithLicenseDefaultModules = GroupFixturePreparers(
	FixtureAddTextFile("build/soong/licenses/Android.bp", `
		license {
				name: "Android-Apache-2.0",
				package_name: "Android",
				license_kinds: ["SPDX-license-identifier-Apache-2.0"],
				copyright_notice: "Copyright (C) The Android Open Source Project",
				license_text: ["LICENSE"],
		}

		license_kind {
				name: "SPDX-license-identifier-Apache-2.0",
				conditions: ["notice"],
				url: "https://spdx.org/licenses/Apache-2.0.html",
		}

		license_kind {
				name: "legacy_unencumbered",
				conditions: ["unencumbered"],
		}
	`),
	FixtureAddFile("build/soong/licenses/LICENSE", nil),
)

var PrepareForTestWithNamespace = FixtureRegisterWithContext(func(ctx RegistrationContext) {
	registerNamespaceBuildComponents(ctx)
	ctx.PreArchMutators(RegisterNamespaceMutator)
})

var PrepareForTestWithMakevars = FixtureRegisterWithContext(func(ctx RegistrationContext) {
	ctx.RegisterSingletonType("makevars", makeVarsSingletonFunc)
})

// Test fixture preparer that will register most java build components.
//
// Singletons and mutators should only be added here if they are needed for a majority of java
// module types, otherwise they should be added under a separate preparer to allow them to be
// selected only when needed to reduce test execution time.
//
// Module types do not have much of an overhead unless they are used so this should include as many
// module types as possible. The exceptions are those module types that require mutators and/or
// singletons in order to function in which case they should be kept together in a separate
// preparer.
//
// The mutators in this group were chosen because they are needed by the vast majority of tests.
var PrepareForTestWithAndroidBuildComponents = GroupFixturePreparers(
	// Sorted alphabetically as the actual order does not matter as tests automatically enforce the
	// correct order.
	PrepareForTestWithArchMutator,
	PrepareForTestWithComponentsMutator,
	PrepareForTestWithDefaults,
	PrepareForTestWithFilegroup,
	PrepareForTestWithOverrides,
	PrepareForTestWithPackageModule,
	PrepareForTestWithPrebuilts,
	PrepareForTestWithVisibility,
)

// Prepares an integration test with all build components from the android package.
//
// This should only be used by tests that want to run with as much of the build enabled as possible.
var PrepareForIntegrationTestWithAndroid = GroupFixturePreparers(
	PrepareForTestWithAndroidBuildComponents,
)

// Prepares a test that may be missing dependencies by setting allow_missing_dependencies to
// true.
var PrepareForTestWithAllowMissingDependencies = GroupFixturePreparers(
	FixtureModifyProductVariables(func(variables FixtureProductVariables) {
		variables.Allow_missing_dependencies = proptools.BoolPtr(true)
	}),
	FixtureModifyContext(func(ctx *TestContext) {
		ctx.SetAllowMissingDependencies(true)
	}),
)

// Prepares a test that disallows non-existent paths.
var PrepareForTestDisallowNonExistentPaths = FixtureModifyConfig(func(config Config) {
	config.TestAllowNonExistentPaths = false
})

func NewTestArchContext(config Config) *TestContext {
	ctx := NewTestContext(config)
	ctx.preDeps = append(ctx.preDeps, registerArchMutator)
	return ctx
}

type TestContext struct {
	*Context
	preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc
	bp2buildPreArch, bp2buildMutators     []RegisterMutatorFunc
	NameResolver                          *NameResolver

	// The list of pre-singletons and singletons registered for the test.
	preSingletons, singletons sortableComponents

	// The order in which the pre-singletons, mutators and singletons will be run in this test
	// context; for debugging.
	preSingletonOrder, mutatorOrder, singletonOrder []string
}

func (ctx *TestContext) PreArchMutators(f RegisterMutatorFunc) {
	ctx.preArch = append(ctx.preArch, f)
}

func (ctx *TestContext) HardCodedPreArchMutators(f RegisterMutatorFunc) {
	// Register mutator function as normal for testing.
	ctx.PreArchMutators(f)
}

func (ctx *TestContext) PreDepsMutators(f RegisterMutatorFunc) {
	ctx.preDeps = append(ctx.preDeps, f)
}

func (ctx *TestContext) PostDepsMutators(f RegisterMutatorFunc) {
	ctx.postDeps = append(ctx.postDeps, f)
}

func (ctx *TestContext) FinalDepsMutators(f RegisterMutatorFunc) {
	ctx.finalDeps = append(ctx.finalDeps, f)
}

func (ctx *TestContext) RegisterBp2BuildConfig(config Bp2BuildConversionAllowlist) {
	ctx.config.Bp2buildPackageConfig = config
}

// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules
// into Bazel BUILD targets that should run prior to deps and conversion.
func (ctx *TestContext) PreArchBp2BuildMutators(f RegisterMutatorFunc) {
	ctx.bp2buildPreArch = append(ctx.bp2buildPreArch, f)
}

// registeredComponentOrder defines the order in which a sortableComponent type is registered at
// runtime and provides support for reordering the components registered for a test in the same
// way.
type registeredComponentOrder struct {
	// The name of the component type, used for error messages.
	componentType string

	// The names of the registered components in the order in which they were registered.
	namesInOrder []string

	// Maps from the component name to its position in the runtime ordering.
	namesToIndex map[string]int

	// A function that defines the order between two named components that can be used to sort a slice
	// of component names into the same order as they appear in namesInOrder.
	less func(string, string) bool
}

// registeredComponentOrderFromExistingOrder takes an existing slice of sortableComponents and
// creates a registeredComponentOrder that contains a less function that can be used to sort a
// subset of that list of names so it is in the same order as the original sortableComponents.
func registeredComponentOrderFromExistingOrder(componentType string, existingOrder sortableComponents) registeredComponentOrder {
	// Only the names from the existing order are needed for this so create a list of component names
	// in the correct order.
	namesInOrder := componentsToNames(existingOrder)

	// Populate the map from name to position in the list.
	nameToIndex := make(map[string]int)
	for i, n := range namesInOrder {
		nameToIndex[n] = i
	}

	// A function to use to map from a name to an index in the original order.
	indexOf := func(name string) int {
		index, ok := nameToIndex[name]
		if !ok {
			// Should never happen as tests that use components that are not known at runtime do not sort
			// so should never use this function.
			panic(fmt.Errorf("internal error: unknown %s %q should be one of %s", componentType, name, strings.Join(namesInOrder, ", ")))
		}
		return index
	}

	// The less function.
	less := func(n1, n2 string) bool {
		i1 := indexOf(n1)
		i2 := indexOf(n2)
		return i1 < i2
	}

	return registeredComponentOrder{
		componentType: componentType,
		namesInOrder:  namesInOrder,
		namesToIndex:  nameToIndex,
		less:          less,
	}
}

// componentsToNames maps from the slice of components to a slice of their names.
func componentsToNames(components sortableComponents) []string {
	names := make([]string, len(components))
	for i, c := range components {
		names[i] = c.componentName()
	}
	return names
}

// enforceOrdering enforces the supplied components are in the same order as is defined in this
// object.
//
// If the supplied components contains any components that are not registered at runtime, i.e. test
// specific components, then it is impossible to sort them into an order that both matches the
// runtime and also preserves the implicit ordering defined in the test. In that case it will not
// sort the components, instead it will just check that the components are in the correct order.
//
// Otherwise, this will sort the supplied components in place.
func (o *registeredComponentOrder) enforceOrdering(components sortableComponents) {
	// Check to see if the list of components contains any components that are
	// not registered at runtime.
	var unknownComponents []string
	testOrder := componentsToNames(components)
	for _, name := range testOrder {
		if _, ok := o.namesToIndex[name]; !ok {
			unknownComponents = append(unknownComponents, name)
			break
		}
	}

	// If the slice contains some unknown components then it is not possible to
	// sort them into an order that matches the runtime while also preserving the
	// order expected from the test, so in that case don't sort just check that
	// the order of the known mutators does match.
	if len(unknownComponents) > 0 {
		// Check order.
		o.checkTestOrder(testOrder, unknownComponents)
	} else {
		// Sort the components.
		sort.Slice(components, func(i, j int) bool {
			n1 := components[i].componentName()
			n2 := components[j].componentName()
			return o.less(n1, n2)
		})
	}
}

// checkTestOrder checks that the supplied testOrder matches the one defined by this object,
// panicking if it does not.
func (o *registeredComponentOrder) checkTestOrder(testOrder []string, unknownComponents []string) {
	lastMatchingTest := -1
	matchCount := 0
	// Take a copy of the runtime order as it is modified during the comparison.
	runtimeOrder := append([]string(nil), o.namesInOrder...)
	componentType := o.componentType
	for i, j := 0, 0; i < len(testOrder) && j < len(runtimeOrder); {
		test := testOrder[i]
		runtime := runtimeOrder[j]

		if test == runtime {
			testOrder[i] = test + fmt.Sprintf(" <-- matched with runtime %s %d", componentType, j)
			runtimeOrder[j] = runtime + fmt.Sprintf(" <-- matched with test %s %d", componentType, i)
			lastMatchingTest = i
			i += 1
			j += 1
			matchCount += 1
		} else if _, ok := o.namesToIndex[test]; !ok {
			// The test component is not registered globally so assume it is the correct place, treat it
			// as having matched and skip it.
			i += 1
			matchCount += 1
		} else {
			// Assume that the test list is in the same order as the runtime list but the runtime list
			// contains some components that are not present in the tests. So, skip the runtime component
			// to try and find the next one that matches the current test component.
			j += 1
		}
	}

	// If every item in the test order was either test specific or matched one in the runtime then
	// it is in the correct order. Otherwise, it was not so fail.
	if matchCount != len(testOrder) {
		// The test component names were not all matched with a runtime component name so there must
		// either be a component present in the test that is not present in the runtime or they must be
		// in the wrong order.
		testOrder[lastMatchingTest+1] = testOrder[lastMatchingTest+1] + " <--- unmatched"
		panic(fmt.Errorf("the tests uses test specific components %q and so cannot be automatically sorted."+
			" Unfortunately it uses %s components in the wrong order.\n"+
			"test order:\n    %s\n"+
			"runtime order\n    %s\n",
			SortedUniqueStrings(unknownComponents),
			componentType,
			strings.Join(testOrder, "\n    "),
			strings.Join(runtimeOrder, "\n    ")))
	}
}

// registrationSorter encapsulates the information needed to ensure that the test mutators are
// registered, and thereby executed, in the same order as they are at runtime.
//
// It MUST be populated lazily AFTER all package initialization has been done otherwise it will
// only define the order for a subset of all the registered build components that are available for
// the packages being tested.
//
// e.g if this is initialized during say the cc package initialization then any tests run in the
// java package will not sort build components registered by the java package's init() functions.
type registrationSorter struct {
	// Used to ensure that this is only created once.
	once sync.Once

	// The order of pre-singletons
	preSingletonOrder registeredComponentOrder

	// The order of mutators
	mutatorOrder registeredComponentOrder

	// The order of singletons
	singletonOrder registeredComponentOrder
}

// populate initializes this structure from globally registered build components.
//
// Only the first call has any effect.
func (s *registrationSorter) populate() {
	s.once.Do(func() {
		// Create an ordering from the globally registered pre-singletons.
		s.preSingletonOrder = registeredComponentOrderFromExistingOrder("pre-singleton", preSingletons)

		// Created an ordering from the globally registered mutators.
		globallyRegisteredMutators := collateGloballyRegisteredMutators()
		s.mutatorOrder = registeredComponentOrderFromExistingOrder("mutator", globallyRegisteredMutators)

		// Create an ordering from the globally registered singletons.
		globallyRegisteredSingletons := collateGloballyRegisteredSingletons()
		s.singletonOrder = registeredComponentOrderFromExistingOrder("singleton", globallyRegisteredSingletons)
	})
}

// Provides support for enforcing the same order in which build components are registered globally
// to the order in which they are registered during tests.
//
// MUST only be accessed via the globallyRegisteredComponentsOrder func.
var globalRegistrationSorter registrationSorter

// globallyRegisteredComponentsOrder returns the globalRegistrationSorter after ensuring it is
// correctly populated.
func globallyRegisteredComponentsOrder() *registrationSorter {
	globalRegistrationSorter.populate()
	return &globalRegistrationSorter
}

func (ctx *TestContext) Register() {
	globalOrder := globallyRegisteredComponentsOrder()

	// Ensure that the pre-singletons used in the test are in the same order as they are used at
	// runtime.
	globalOrder.preSingletonOrder.enforceOrdering(ctx.preSingletons)
	ctx.preSingletons.registerAll(ctx.Context)

	mutators := collateRegisteredMutators(ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
	// Ensure that the mutators used in the test are in the same order as they are used at runtime.
	globalOrder.mutatorOrder.enforceOrdering(mutators)
	mutators.registerAll(ctx.Context)

	// Ensure that the singletons used in the test are in the same order as they are used at runtime.
	globalOrder.singletonOrder.enforceOrdering(ctx.singletons)
	ctx.singletons.registerAll(ctx.Context)

	// Save the sorted components order away to make them easy to access while debugging.
	ctx.preSingletonOrder = componentsToNames(preSingletons)
	ctx.mutatorOrder = componentsToNames(mutators)
	ctx.singletonOrder = componentsToNames(singletons)
}

// RegisterForBazelConversion prepares a test context for bp2build conversion.
func (ctx *TestContext) RegisterForBazelConversion() {
	ctx.config.BuildMode = Bp2build
	RegisterMutatorsForBazelConversion(ctx.Context, ctx.bp2buildPreArch)
}

// RegisterForApiBazelConversion prepares a test context for API bp2build conversion.
func (ctx *TestContext) RegisterForApiBazelConversion() {
	ctx.config.BuildMode = ApiBp2build
	RegisterMutatorsForApiBazelConversion(ctx.Context, ctx.bp2buildPreArch)
}

func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {
	// This function adapts the old style ParseFileList calls that are spread throughout the tests
	// to the new style that takes a config.
	return ctx.Context.ParseFileList(rootDir, filePaths, ctx.config)
}

func (ctx *TestContext) ParseBlueprintsFiles(rootDir string) (deps []string, errs []error) {
	// This function adapts the old style ParseBlueprintsFiles calls that are spread throughout the
	// tests to the new style that takes a config.
	return ctx.Context.ParseBlueprintsFiles(rootDir, ctx.config)
}

func (ctx *TestContext) RegisterModuleType(name string, factory ModuleFactory) {
	ctx.Context.RegisterModuleType(name, ModuleFactoryAdaptor(factory))
}

func (ctx *TestContext) RegisterSingletonModuleType(name string, factory SingletonModuleFactory) {
	s, m := SingletonModuleFactoryAdaptor(name, factory)
	ctx.RegisterSingletonType(name, s)
	ctx.RegisterModuleType(name, m)
}

func (ctx *TestContext) RegisterSingletonType(name string, factory SingletonFactory) {
	ctx.singletons = append(ctx.singletons, newSingleton(name, factory))
}

func (ctx *TestContext) RegisterPreSingletonType(name string, factory SingletonFactory) {
	ctx.preSingletons = append(ctx.preSingletons, newPreSingleton(name, factory))
}

// ModuleVariantForTests selects a specific variant of the module with the given
// name by matching the variations map against the variations of each module
// variant. A module variant matches the map if every variation that exists in
// both have the same value. Both the module and the map are allowed to have
// extra variations that the other doesn't have. Panics if not exactly one
// module variant matches.
func (ctx *TestContext) ModuleVariantForTests(name string, matchVariations map[string]string) TestingModule {
	modules := []Module{}
	ctx.VisitAllModules(func(m blueprint.Module) {
		if ctx.ModuleName(m) == name {
			am := m.(Module)
			amMut := am.base().commonProperties.DebugMutators
			amVar := am.base().commonProperties.DebugVariations
			matched := true
			for i, mut := range amMut {
				if wantedVar, found := matchVariations[mut]; found && amVar[i] != wantedVar {
					matched = false
					break
				}
			}
			if matched {
				modules = append(modules, am)
			}
		}
	})

	if len(modules) == 0 {
		// Show all the modules or module variants that do exist.
		var allModuleNames []string
		var allVariants []string
		ctx.VisitAllModules(func(m blueprint.Module) {
			allModuleNames = append(allModuleNames, ctx.ModuleName(m))
			if ctx.ModuleName(m) == name {
				allVariants = append(allVariants, m.(Module).String())
			}
		})

		if len(allVariants) == 0 {
			panic(fmt.Errorf("failed to find module %q. All modules:\n  %s",
				name, strings.Join(SortedUniqueStrings(allModuleNames), "\n  ")))
		} else {
			sort.Strings(allVariants)
			panic(fmt.Errorf("failed to find module %q matching %v. All variants:\n  %s",
				name, matchVariations, strings.Join(allVariants, "\n  ")))
		}
	}

	if len(modules) > 1 {
		moduleStrings := []string{}
		for _, m := range modules {
			moduleStrings = append(moduleStrings, m.String())
		}
		sort.Strings(moduleStrings)
		panic(fmt.Errorf("module %q has more than one variant that match %v:\n  %s",
			name, matchVariations, strings.Join(moduleStrings, "\n  ")))
	}

	return newTestingModule(ctx.config, modules[0])
}

func (ctx *TestContext) ModuleForTests(name, variant string) TestingModule {
	var module Module
	ctx.VisitAllModules(func(m blueprint.Module) {
		if ctx.ModuleName(m) == name && ctx.ModuleSubDir(m) == variant {
			module = m.(Module)
		}
	})

	if module == nil {
		// find all the modules that do exist
		var allModuleNames []string
		var allVariants []string
		ctx.VisitAllModules(func(m blueprint.Module) {
			allModuleNames = append(allModuleNames, ctx.ModuleName(m))
			if ctx.ModuleName(m) == name {
				allVariants = append(allVariants, ctx.ModuleSubDir(m))
			}
		})
		sort.Strings(allVariants)

		if len(allVariants) == 0 {
			panic(fmt.Errorf("failed to find module %q. All modules:\n  %s",
				name, strings.Join(SortedUniqueStrings(allModuleNames), "\n  ")))
		} else {
			panic(fmt.Errorf("failed to find module %q variant %q. All variants:\n  %s",
				name, variant, strings.Join(allVariants, "\n  ")))
		}
	}

	return newTestingModule(ctx.config, module)
}

func (ctx *TestContext) ModuleVariantsForTests(name string) []string {
	var variants []string
	ctx.VisitAllModules(func(m blueprint.Module) {
		if ctx.ModuleName(m) == name {
			variants = append(variants, ctx.ModuleSubDir(m))
		}
	})
	return variants
}

// SingletonForTests returns a TestingSingleton for the singleton registered with the given name.
func (ctx *TestContext) SingletonForTests(name string) TestingSingleton {
	allSingletonNames := []string{}
	for _, s := range ctx.Singletons() {
		n := ctx.SingletonName(s)
		if n == name {
			return TestingSingleton{
				baseTestingComponent: newBaseTestingComponent(ctx.config, s.(testBuildProvider)),
				singleton:            s.(*singletonAdaptor).Singleton,
			}
		}
		allSingletonNames = append(allSingletonNames, n)
	}

	panic(fmt.Errorf("failed to find singleton %q."+
		"\nall singletons: %v", name, allSingletonNames))
}

type InstallMakeRule struct {
	Target        string
	Deps          []string
	OrderOnlyDeps []string
}

func parseMkRules(t *testing.T, config Config, nodes []mkparser.Node) []InstallMakeRule {
	var rules []InstallMakeRule
	for _, node := range nodes {
		if mkParserRule, ok := node.(*mkparser.Rule); ok {
			var rule InstallMakeRule

			if targets := mkParserRule.Target.Words(); len(targets) == 0 {
				t.Fatalf("no targets for rule %s", mkParserRule.Dump())
			} else if len(targets) > 1 {
				t.Fatalf("unsupported multiple targets for rule %s", mkParserRule.Dump())
			} else if !targets[0].Const() {
				t.Fatalf("unsupported non-const target for rule %s", mkParserRule.Dump())
			} else {
				rule.Target = normalizeStringRelativeToTop(config, targets[0].Value(nil))
			}

			prereqList := &rule.Deps
			for _, prereq := range mkParserRule.Prerequisites.Words() {
				if !prereq.Const() {
					t.Fatalf("unsupported non-const prerequisite for rule %s", mkParserRule.Dump())
				}

				if prereq.Value(nil) == "|" {
					prereqList = &rule.OrderOnlyDeps
					continue
				}

				*prereqList = append(*prereqList, normalizeStringRelativeToTop(config, prereq.Value(nil)))
			}

			rules = append(rules, rule)
		}
	}

	return rules
}

func (ctx *TestContext) InstallMakeRulesForTesting(t *testing.T) []InstallMakeRule {
	installs := ctx.SingletonForTests("makevars").Singleton().(*makeVarsSingleton).installsForTesting
	buf := bytes.NewBuffer(append([]byte(nil), installs...))
	parser := mkparser.NewParser("makevars", buf)

	nodes, errs := parser.Parse()
	if len(errs) > 0 {
		t.Fatalf("error parsing install rules: %s", errs[0])
	}

	return parseMkRules(t, ctx.config, nodes)
}

// MakeVarVariable provides access to make vars that will be written by the makeVarsSingleton
type MakeVarVariable interface {
	// Name is the name of the variable.
	Name() string

	// Value is the value of the variable.
	Value() string
}

func (v makeVarsVariable) Name() string {
	return v.name
}

func (v makeVarsVariable) Value() string {
	return v.value
}

// PrepareForTestAccessingMakeVars sets up the test so that MakeVarsForTesting will work.
var PrepareForTestAccessingMakeVars = GroupFixturePreparers(
	PrepareForTestWithAndroidMk,
	PrepareForTestWithMakevars,
)

// MakeVarsForTesting returns a filtered list of MakeVarVariable objects that represent the
// variables that will be written out.
//
// It is necessary to use PrepareForTestAccessingMakeVars in tests that want to call this function.
// Along with any other preparers needed to add the make vars.
func (ctx *TestContext) MakeVarsForTesting(filter func(variable MakeVarVariable) bool) []MakeVarVariable {
	vars := ctx.SingletonForTests("makevars").Singleton().(*makeVarsSingleton).varsForTesting
	result := make([]MakeVarVariable, 0, len(vars))
	for _, v := range vars {
		if filter(v) {
			result = append(result, v)
		}
	}

	return result
}

func (ctx *TestContext) Config() Config {
	return ctx.config
}

type testBuildProvider interface {
	BuildParamsForTests() []BuildParams
	RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams
}

type TestingBuildParams struct {
	BuildParams
	RuleParams blueprint.RuleParams

	config Config
}

// RelativeToTop creates a new instance of this which has had any usages of the current test's
// temporary and test specific build directory replaced with a path relative to the notional top.
//
// The parts of this structure which are changed are:
// * BuildParams
//   - Args
//   - All Path, Paths, WritablePath and WritablePaths fields.
//
// * RuleParams
//   - Command
//   - Depfile
//   - Rspfile
//   - RspfileContent
//   - SymlinkOutputs
//   - CommandDeps
//   - CommandOrderOnly
//
// See PathRelativeToTop for more details.
//
// deprecated: this is no longer needed as TestingBuildParams are created in this form.
func (p TestingBuildParams) RelativeToTop() TestingBuildParams {
	// If this is not a valid params then just return it back. That will make it easy to use with the
	// Maybe...() methods.
	if p.Rule == nil {
		return p
	}
	if p.config.config == nil {
		return p
	}
	// Take a copy of the build params and replace any args that contains test specific temporary
	// paths with paths relative to the top.
	bparams := p.BuildParams
	bparams.Depfile = normalizeWritablePathRelativeToTop(bparams.Depfile)
	bparams.Output = normalizeWritablePathRelativeToTop(bparams.Output)
	bparams.Outputs = bparams.Outputs.RelativeToTop()
	bparams.SymlinkOutput = normalizeWritablePathRelativeToTop(bparams.SymlinkOutput)
	bparams.SymlinkOutputs = bparams.SymlinkOutputs.RelativeToTop()
	bparams.ImplicitOutput = normalizeWritablePathRelativeToTop(bparams.ImplicitOutput)
	bparams.ImplicitOutputs = bparams.ImplicitOutputs.RelativeToTop()
	bparams.Input = normalizePathRelativeToTop(bparams.Input)
	bparams.Inputs = bparams.Inputs.RelativeToTop()
	bparams.Implicit = normalizePathRelativeToTop(bparams.Implicit)
	bparams.Implicits = bparams.Implicits.RelativeToTop()
	bparams.OrderOnly = bparams.OrderOnly.RelativeToTop()
	bparams.Validation = normalizePathRelativeToTop(bparams.Validation)
	bparams.Validations = bparams.Validations.RelativeToTop()
	bparams.Args = normalizeStringMapRelativeToTop(p.config, bparams.Args)

	// Ditto for any fields in the RuleParams.
	rparams := p.RuleParams
	rparams.Command = normalizeStringRelativeToTop(p.config, rparams.Command)
	rparams.Depfile = normalizeStringRelativeToTop(p.config, rparams.Depfile)
	rparams.Rspfile = normalizeStringRelativeToTop(p.config, rparams.Rspfile)
	rparams.RspfileContent = normalizeStringRelativeToTop(p.config, rparams.RspfileContent)
	rparams.SymlinkOutputs = normalizeStringArrayRelativeToTop(p.config, rparams.SymlinkOutputs)
	rparams.CommandDeps = normalizeStringArrayRelativeToTop(p.config, rparams.CommandDeps)
	rparams.CommandOrderOnly = normalizeStringArrayRelativeToTop(p.config, rparams.CommandOrderOnly)

	return TestingBuildParams{
		BuildParams: bparams,
		RuleParams:  rparams,
	}
}

func normalizeWritablePathRelativeToTop(path WritablePath) WritablePath {
	if path == nil {
		return nil
	}
	return path.RelativeToTop().(WritablePath)
}

func normalizePathRelativeToTop(path Path) Path {
	if path == nil {
		return nil
	}
	return path.RelativeToTop()
}

// baseTestingComponent provides functionality common to both TestingModule and TestingSingleton.
type baseTestingComponent struct {
	config   Config
	provider testBuildProvider
}

func newBaseTestingComponent(config Config, provider testBuildProvider) baseTestingComponent {
	return baseTestingComponent{config, provider}
}

// A function that will normalize a string containing paths, e.g. ninja command, by replacing
// any references to the test specific temporary build directory that changes with each run to a
// fixed path relative to a notional top directory.
//
// This is similar to StringPathRelativeToTop except that assumes the string is a single path
// containing at most one instance of the temporary build directory at the start of the path while
// this assumes that there can be any number at any position.
func normalizeStringRelativeToTop(config Config, s string) string {
	// The soongOutDir usually looks something like: /tmp/testFoo2345/001
	//
	// Replace any usage of the soongOutDir with out/soong, e.g. replace "/tmp/testFoo2345/001" with
	// "out/soong".
	outSoongDir := filepath.Clean(config.soongOutDir)
	re := regexp.MustCompile(`\Q` + outSoongDir + `\E\b`)
	s = re.ReplaceAllString(s, "out/soong")

	// Replace any usage of the soongOutDir/.. with out, e.g. replace "/tmp/testFoo2345" with
	// "out". This must come after the previous replacement otherwise this would replace
	// "/tmp/testFoo2345/001" with "out/001" instead of "out/soong".
	outDir := filepath.Dir(outSoongDir)
	re = regexp.MustCompile(`\Q` + outDir + `\E\b`)
	s = re.ReplaceAllString(s, "out")

	return s
}

// normalizeStringArrayRelativeToTop creates a new slice constructed by applying
// normalizeStringRelativeToTop to each item in the slice.
func normalizeStringArrayRelativeToTop(config Config, slice []string) []string {
	newSlice := make([]string, len(slice))
	for i, s := range slice {
		newSlice[i] = normalizeStringRelativeToTop(config, s)
	}
	return newSlice
}

// normalizeStringMapRelativeToTop creates a new map constructed by applying
// normalizeStringRelativeToTop to each value in the map.
func normalizeStringMapRelativeToTop(config Config, m map[string]string) map[string]string {
	newMap := map[string]string{}
	for k, v := range m {
		newMap[k] = normalizeStringRelativeToTop(config, v)
	}
	return newMap
}

func (b baseTestingComponent) newTestingBuildParams(bparams BuildParams) TestingBuildParams {
	return TestingBuildParams{
		config:      b.config,
		BuildParams: bparams,
		RuleParams:  b.provider.RuleParamsForTests()[bparams.Rule],
	}.RelativeToTop()
}

func (b baseTestingComponent) maybeBuildParamsFromRule(rule string) (TestingBuildParams, []string) {
	var searchedRules []string
	buildParams := b.provider.BuildParamsForTests()
	for _, p := range buildParams {
		ruleAsString := p.Rule.String()
		searchedRules = append(searchedRules, ruleAsString)
		if strings.Contains(ruleAsString, rule) {
			return b.newTestingBuildParams(p), searchedRules
		}
	}
	return TestingBuildParams{}, searchedRules
}

func (b baseTestingComponent) buildParamsFromRule(rule string) TestingBuildParams {
	p, searchRules := b.maybeBuildParamsFromRule(rule)
	if p.Rule == nil {
		panic(fmt.Errorf("couldn't find rule %q.\nall rules:\n%s", rule, strings.Join(searchRules, "\n")))
	}
	return p
}

func (b baseTestingComponent) maybeBuildParamsFromDescription(desc string) (TestingBuildParams, []string) {
	var searchedDescriptions []string
	for _, p := range b.provider.BuildParamsForTests() {
		searchedDescriptions = append(searchedDescriptions, p.Description)
		if strings.Contains(p.Description, desc) {
			return b.newTestingBuildParams(p), searchedDescriptions
		}
	}
	return TestingBuildParams{}, searchedDescriptions
}

func (b baseTestingComponent) buildParamsFromDescription(desc string) TestingBuildParams {
	p, searchedDescriptions := b.maybeBuildParamsFromDescription(desc)
	if p.Rule == nil {
		panic(fmt.Errorf("couldn't find description %q\nall descriptions:\n%s", desc, strings.Join(searchedDescriptions, "\n")))
	}
	return p
}

func (b baseTestingComponent) maybeBuildParamsFromOutput(file string) (TestingBuildParams, []string) {
	searchedOutputs := WritablePaths(nil)
	for _, p := range b.provider.BuildParamsForTests() {
		outputs := append(WritablePaths(nil), p.Outputs...)
		outputs = append(outputs, p.ImplicitOutputs...)
		if p.Output != nil {
			outputs = append(outputs, p.Output)
		}
		for _, f := range outputs {
			if f.String() == file || f.Rel() == file || PathRelativeToTop(f) == file {
				return b.newTestingBuildParams(p), nil
			}
			searchedOutputs = append(searchedOutputs, f)
		}
	}

	formattedOutputs := []string{}
	for _, f := range searchedOutputs {
		formattedOutputs = append(formattedOutputs,
			fmt.Sprintf("%s (rel=%s)", PathRelativeToTop(f), f.Rel()))
	}

	return TestingBuildParams{}, formattedOutputs
}

func (b baseTestingComponent) buildParamsFromOutput(file string) TestingBuildParams {
	p, searchedOutputs := b.maybeBuildParamsFromOutput(file)
	if p.Rule == nil {
		panic(fmt.Errorf("couldn't find output %q.\nall outputs:\n    %s\n",
			file, strings.Join(searchedOutputs, "\n    ")))
	}
	return p
}

func (b baseTestingComponent) allOutputs() []string {
	var outputFullPaths []string
	for _, p := range b.provider.BuildParamsForTests() {
		outputs := append(WritablePaths(nil), p.Outputs...)
		outputs = append(outputs, p.ImplicitOutputs...)
		if p.Output != nil {
			outputs = append(outputs, p.Output)
		}
		outputFullPaths = append(outputFullPaths, outputs.Strings()...)
	}
	return outputFullPaths
}

// MaybeRule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name.  Returns an empty
// BuildParams if no rule is found.
func (b baseTestingComponent) MaybeRule(rule string) TestingBuildParams {
	r, _ := b.maybeBuildParamsFromRule(rule)
	return r
}

// Rule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name.  Panics if no rule is found.
func (b baseTestingComponent) Rule(rule string) TestingBuildParams {
	return b.buildParamsFromRule(rule)
}

// MaybeDescription finds a call to ctx.Build with BuildParams.Description set to a the given string.  Returns an empty
// BuildParams if no rule is found.
func (b baseTestingComponent) MaybeDescription(desc string) TestingBuildParams {
	p, _ := b.maybeBuildParamsFromDescription(desc)
	return p
}

// Description finds a call to ctx.Build with BuildParams.Description set to a the given string.  Panics if no rule is
// found.
func (b baseTestingComponent) Description(desc string) TestingBuildParams {
	return b.buildParamsFromDescription(desc)
}

// MaybeOutput finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
// value matches the provided string.  Returns an empty BuildParams if no rule is found.
func (b baseTestingComponent) MaybeOutput(file string) TestingBuildParams {
	p, _ := b.maybeBuildParamsFromOutput(file)
	return p
}

// Output finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
// value matches the provided string.  Panics if no rule is found.
func (b baseTestingComponent) Output(file string) TestingBuildParams {
	return b.buildParamsFromOutput(file)
}

// AllOutputs returns all 'BuildParams.Output's and 'BuildParams.Outputs's in their full path string forms.
func (b baseTestingComponent) AllOutputs() []string {
	return b.allOutputs()
}

// TestingModule is wrapper around an android.Module that provides methods to find information about individual
// ctx.Build parameters for verification in tests.
type TestingModule struct {
	baseTestingComponent
	module Module
}

func newTestingModule(config Config, module Module) TestingModule {
	return TestingModule{
		newBaseTestingComponent(config, module),
		module,
	}
}

// Module returns the Module wrapped by the TestingModule.
func (m TestingModule) Module() Module {
	return m.module
}

// VariablesForTestsRelativeToTop returns a copy of the Module.VariablesForTests() with every value
// having any temporary build dir usages replaced with paths relative to a notional top.
func (m TestingModule) VariablesForTestsRelativeToTop() map[string]string {
	return normalizeStringMapRelativeToTop(m.config, m.module.VariablesForTests())
}

// OutputFiles calls OutputFileProducer.OutputFiles on the encapsulated module, exits the test
// immediately if there is an error and otherwise returns the result of calling Paths.RelativeToTop
// on the returned Paths.
func (m TestingModule) OutputFiles(t *testing.T, tag string) Paths {
	producer, ok := m.module.(OutputFileProducer)
	if !ok {
		t.Fatalf("%q must implement OutputFileProducer\n", m.module.Name())
	}
	paths, err := producer.OutputFiles(tag)
	if err != nil {
		t.Fatal(err)
	}

	return paths.RelativeToTop()
}

// TestingSingleton is wrapper around an android.Singleton that provides methods to find information about individual
// ctx.Build parameters for verification in tests.
type TestingSingleton struct {
	baseTestingComponent
	singleton Singleton
}

// Singleton returns the Singleton wrapped by the TestingSingleton.
func (s TestingSingleton) Singleton() Singleton {
	return s.singleton
}

func FailIfErrored(t *testing.T, errs []error) {
	t.Helper()
	if len(errs) > 0 {
		for _, err := range errs {
			t.Error(err)
		}
		t.FailNow()
	}
}

// Fail if no errors that matched the regular expression were found.
//
// Returns true if a matching error was found, false otherwise.
func FailIfNoMatchingErrors(t *testing.T, pattern string, errs []error) bool {
	t.Helper()

	matcher, err := regexp.Compile(pattern)
	if err != nil {
		t.Fatalf("failed to compile regular expression %q because %s", pattern, err)
	}

	found := false
	for _, err := range errs {
		if matcher.FindStringIndex(err.Error()) != nil {
			found = true
			break
		}
	}
	if !found {
		t.Errorf("could not match the expected error regex %q (checked %d error(s))", pattern, len(errs))
		for i, err := range errs {
			t.Errorf("errs[%d] = %q", i, err)
		}
	}

	return found
}

func CheckErrorsAgainstExpectations(t *testing.T, errs []error, expectedErrorPatterns []string) {
	t.Helper()

	if expectedErrorPatterns == nil {
		FailIfErrored(t, errs)
	} else {
		for _, expectedError := range expectedErrorPatterns {
			FailIfNoMatchingErrors(t, expectedError, errs)
		}
		if len(errs) > len(expectedErrorPatterns) {
			t.Errorf("additional errors found, expected %d, found %d",
				len(expectedErrorPatterns), len(errs))
			for i, expectedError := range expectedErrorPatterns {
				t.Errorf("expectedErrors[%d] = %s", i, expectedError)
			}
			for i, err := range errs {
				t.Errorf("errs[%d] = %s", i, err)
			}
			t.FailNow()
		}
	}
}

func SetKatiEnabledForTests(config Config) {
	config.katiEnabled = true
}

func AndroidMkEntriesForTest(t *testing.T, ctx *TestContext, mod blueprint.Module) []AndroidMkEntries {
	t.Helper()
	var p AndroidMkEntriesProvider
	var ok bool
	if p, ok = mod.(AndroidMkEntriesProvider); !ok {
		t.Errorf("module does not implement AndroidMkEntriesProvider: " + mod.Name())
	}

	entriesList := p.AndroidMkEntries()
	for i, _ := range entriesList {
		entriesList[i].fillInEntries(ctx, mod)
	}
	return entriesList
}

func AndroidMkDataForTest(t *testing.T, ctx *TestContext, mod blueprint.Module) AndroidMkData {
	t.Helper()
	var p AndroidMkDataProvider
	var ok bool
	if p, ok = mod.(AndroidMkDataProvider); !ok {
		t.Errorf("module does not implement AndroidMkDataProvider: " + mod.Name())
	}
	data := p.AndroidMk()
	data.fillInData(ctx, mod)
	return data
}

// Normalize the path for testing.
//
// If the path is relative to the build directory then return the relative path
// to avoid tests having to deal with the dynamically generated build directory.
//
// Otherwise, return the supplied path as it is almost certainly a source path
// that is relative to the root of the source tree.
//
// The build and source paths should be distinguishable based on their contents.
//
// deprecated: use PathRelativeToTop instead as it handles make install paths and differentiates
// between output and source properly.
func NormalizePathForTesting(path Path) string {
	if path == nil {
		return "<nil path>"
	}
	p := path.String()
	if w, ok := path.(WritablePath); ok {
		rel, err := filepath.Rel(w.getSoongOutDir(), p)
		if err != nil {
			panic(err)
		}
		return rel
	}
	return p
}

// NormalizePathsForTesting creates a slice of strings where each string is the result of applying
// NormalizePathForTesting to the corresponding Path in the input slice.
//
// deprecated: use PathsRelativeToTop instead as it handles make install paths and differentiates
// between output and source properly.
func NormalizePathsForTesting(paths Paths) []string {
	var result []string
	for _, path := range paths {
		relative := NormalizePathForTesting(path)
		result = append(result, relative)
	}
	return result
}

// PathRelativeToTop returns a string representation of the path relative to a notional top
// directory.
//
// It return "<nil path>" if the supplied path is nil, otherwise it returns the result of calling
// Path.RelativeToTop to obtain a relative Path and then calling Path.String on that to get the
// string representation.
func PathRelativeToTop(path Path) string {
	if path == nil {
		return "<nil path>"
	}
	return path.RelativeToTop().String()
}

// PathsRelativeToTop creates a slice of strings where each string is the result of applying
// PathRelativeToTop to the corresponding Path in the input slice.
func PathsRelativeToTop(paths Paths) []string {
	var result []string
	for _, path := range paths {
		relative := PathRelativeToTop(path)
		result = append(result, relative)
	}
	return result
}

// StringPathRelativeToTop returns a string representation of the path relative to a notional top
// directory.
//
// See Path.RelativeToTop for more details as to what `relative to top` means.
//
// This is provided for processing paths that have already been converted into a string, e.g. paths
// in AndroidMkEntries structures. As a result it needs to be supplied the soong output dir against
// which it can try and relativize paths. PathRelativeToTop must be used for process Path objects.
func StringPathRelativeToTop(soongOutDir string, path string) string {
	ensureTestOnly()

	// A relative path must be a source path so leave it as it is.
	if !filepath.IsAbs(path) {
		return path
	}

	// Check to see if the path is relative to the soong out dir.
	rel, isRel, err := maybeRelErr(soongOutDir, path)
	if err != nil {
		panic(err)
	}

	if isRel {
		// The path is in the soong out dir so indicate that in the relative path.
		return filepath.Join("out/soong", rel)
	}

	// Check to see if the path is relative to the top level out dir.
	outDir := filepath.Dir(soongOutDir)
	rel, isRel, err = maybeRelErr(outDir, path)
	if err != nil {
		panic(err)
	}

	if isRel {
		// The path is in the out dir so indicate that in the relative path.
		return filepath.Join("out", rel)
	}

	// This should never happen.
	panic(fmt.Errorf("internal error: absolute path %s is not relative to the out dir %s", path, outDir))
}

// StringPathsRelativeToTop creates a slice of strings where each string is the result of applying
// StringPathRelativeToTop to the corresponding string path in the input slice.
//
// This is provided for processing paths that have already been converted into a string, e.g. paths
// in AndroidMkEntries structures. As a result it needs to be supplied the soong output dir against
// which it can try and relativize paths. PathsRelativeToTop must be used for process Paths objects.
func StringPathsRelativeToTop(soongOutDir string, paths []string) []string {
	var result []string
	for _, path := range paths {
		relative := StringPathRelativeToTop(soongOutDir, path)
		result = append(result, relative)
	}
	return result
}

// StringRelativeToTop will normalize a string containing paths, e.g. ninja command, by replacing
// any references to the test specific temporary build directory that changes with each run to a
// fixed path relative to a notional top directory.
//
// This is similar to StringPathRelativeToTop except that assumes the string is a single path
// containing at most one instance of the temporary build directory at the start of the path while
// this assumes that there can be any number at any position.
func StringRelativeToTop(config Config, command string) string {
	return normalizeStringRelativeToTop(config, command)
}

// StringsRelativeToTop will return a new slice such that each item in the new slice is the result
// of calling StringRelativeToTop on the corresponding item in the input slice.
func StringsRelativeToTop(config Config, command []string) []string {
	return normalizeStringArrayRelativeToTop(config, command)
}
