// 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)
})

var PrepareForTestVintfFragmentModules = FixtureRegisterWithContext(func(ctx RegistrationContext) {
	registerVintfFragmentComponents(ctx)
})

// 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,
	PrepareForTestVintfFragmentModules,
)

// 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
})

// PrepareForTestWithBuildFlag returns a FixturePreparer that sets the given flag to the given value.
func PrepareForTestWithBuildFlag(flag, value string) FixturePreparer {
	return FixtureModifyProductVariables(func(variables FixtureProductVariables) {
		if variables.BuildFlags == nil {
			variables.BuildFlags = make(map[string]string)
		}
		variables.BuildFlags[flag] = value
	})
}

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

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

	// The list of singletons registered for the test.
	singletons sortableComponents

	// The order in which the mutators and singletons will be run in this test
	// context; for debugging.
	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) otherModuleProvider(m blueprint.Module, p blueprint.AnyProviderKey) (any, bool) {
	return ctx.Context.ModuleProvider(m, p)
}

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) PostApexMutators(f RegisterMutatorFunc) {
	ctx.postApex = append(ctx.postApex, f)
}

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

func (ctx *TestContext) OtherModuleProviderAdaptor() OtherModuleProviderContext {
	return NewOtherModuleProviderAdaptor(func(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
		return ctx.otherModuleProvider(module, provider)
	})
}

func (ctx *TestContext) OtherModulePropertyErrorf(module Module, property string, fmt_ string, args ...interface{}) {
	panic(fmt.Sprintf(fmt_, args...))
}

// 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 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() {
		// 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()

	mutators := collateRegisteredMutators(ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.postApex, 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.mutatorOrder = componentsToNames(mutators)
	ctx.singletonOrder = componentsToNames(singletons)
}

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) RegisterParallelSingletonModuleType(name string, factory SingletonModuleFactory) {
	s, m := SingletonModuleFactoryAdaptor(name, factory)
	ctx.RegisterParallelSingletonType(name, s)
	ctx.RegisterModuleType(name, m)
}

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

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

// 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
//   - 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.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.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()
}

func allOutputs(p BuildParams) []string {
	outputs := append(WritablePaths(nil), p.Outputs...)
	outputs = append(outputs, p.ImplicitOutputs...)
	if p.Output != nil {
		outputs = append(outputs, p.Output)
	}
	return outputs.Strings()
}

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

// 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 outDir usually looks something like: /tmp/testFoo2345/001
	//
	// Replace any usage of the outDir 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 outDir/.. 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() {
		outputFullPaths = append(outputFullPaths, allOutputs(p)...)
	}
	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 checks if module base outputFiles property has any output
// files can be used to return.
// 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(ctx *TestContext, t *testing.T, tag string) Paths {
	outputFiles := OtherModuleProviderOrDefault(ctx.OtherModuleProviderAdaptor(), m.Module(), OutputFilesProvider)
	if tag == "" && outputFiles.DefaultOutputFiles != nil {
		return outputFiles.DefaultOutputFiles.RelativeToTop()
	} else if taggedOutputFiles, hasTag := outputFiles.TaggedOutputFiles[tag]; hasTag {
		return taggedOutputFiles.RelativeToTop()
	}

	t.Fatal(fmt.Errorf("No test output file has been set for tag %q", tag))
	return nil
}

// 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 SetTrimmedApexEnabledForTests(config Config) {
	config.productVariables.TrimmedApex = new(bool)
	*config.productVariables.TrimmedApex = 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()
	aconfigUpdateAndroidMkEntries(ctx, mod.(Module), &entriesList)
	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.Fatalf("module does not implement AndroidMkDataProvider: " + mod.Name())
	}
	data := p.AndroidMk()
	data.fillInData(ctx, mod)
	aconfigUpdateAndroidMkData(ctx, mod.(Module), &data)
	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 {
		if strings.HasSuffix(soongOutDir, testOutSoongSubDir) {
			// The path is in the soong out dir so indicate that in the relative path.
			return filepath.Join(TestOutSoongDir, rel)
		} else {
			// Handle the PathForArbitraryOutput case
			return filepath.Join(testOutDir, 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)
}

func EnsureListContainsSuffix(t *testing.T, result []string, expected string) {
	t.Helper()
	if !SuffixInList(result, expected) {
		t.Errorf("%q is not found in %v", expected, result)
	}
}

type panickingConfigAndErrorContext struct {
	ctx *TestContext
}

func (ctx *panickingConfigAndErrorContext) OtherModulePropertyErrorf(module Module, property, fmt string, args ...interface{}) {
	panic(ctx.ctx.PropertyErrorf(module, property, fmt, args...).Error())
}

func (ctx *panickingConfigAndErrorContext) Config() Config {
	return ctx.ctx.Config()
}

func (ctx *panickingConfigAndErrorContext) HasMutatorFinished(mutatorName string) bool {
	return ctx.ctx.HasMutatorFinished(mutatorName)
}

func (ctx *panickingConfigAndErrorContext) otherModuleProvider(m blueprint.Module, p blueprint.AnyProviderKey) (any, bool) {
	return ctx.ctx.otherModuleProvider(m, p)
}

func PanickingConfigAndErrorContext(ctx *TestContext) ConfigurableEvaluatorContext {
	return &panickingConfigAndErrorContext{
		ctx: ctx,
	}
}
