// Copyright 2019 The Android Open Source Project
//
// 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 rust

import (
	"path/filepath"
	"strings"

	"android/soong/android"
	"android/soong/tradefed"
)

type TestProperties struct {
	// the name of the test configuration (for example "AndroidTest.xml") that should be
	// installed with the module.
	Test_config *string `android:"arch_variant"`

	// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
	// should be installed with the module.
	Test_config_template *string `android:"arch_variant"`

	// list of compatibility suites (for example "cts", "vts") that the module should be
	// installed into.
	Test_suites []string `android:"arch_variant"`

	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
	// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
	// explicitly.
	Auto_gen_config *bool
}

// A test module is a binary module with extra --test compiler flag
// and different default installation directory.
// In golang, inheriance is written as a component.
type testDecorator struct {
	*binaryDecorator
	Properties TestProperties
	testConfig android.Path
}

func (test *testDecorator) nativeCoverage() bool {
	return true
}

func NewRustTest(hod android.HostOrDeviceSupported) (*Module, *testDecorator) {
	module := newModule(hod, android.MultilibFirst)

	test := &testDecorator{
		binaryDecorator: &binaryDecorator{
			baseCompiler: NewBaseCompiler("nativetest", "nativetest64", InstallInData),
		},
	}

	module.compiler = test

	return module, test
}

func (test *testDecorator) compilerProps() []interface{} {
	return append(test.binaryDecorator.compilerProps(), &test.Properties)
}

func (test *testDecorator) getMutatedModuleSubName(moduleName string) string {
	stem := String(test.baseCompiler.Properties.Stem)
	if stem != "" && !strings.HasSuffix(moduleName, "_"+stem) {
		// Avoid repeated suffix in the module name.
		return "_" + stem
	}
	return ""
}

func (test *testDecorator) install(ctx ModuleContext, file android.Path) {
	name := ctx.ModuleName()
	path := test.baseCompiler.relativeInstallPath()
	// on device, use mutated module name
	name = name + test.getMutatedModuleSubName(name)
	if !ctx.Device() { // on host, use mutated module name + arch type + stem name
		stem := String(test.baseCompiler.Properties.Stem)
		if stem == "" {
			stem = name
		}
		name = filepath.Join(name, ctx.Arch().ArchType.String(), stem)
	}
	test.testConfig = tradefed.AutoGenRustTestConfig(ctx, name,
		test.Properties.Test_config,
		test.Properties.Test_config_template,
		test.Properties.Test_suites,
		test.Properties.Auto_gen_config)
	// default relative install path is module name
	if path == "" {
		test.baseCompiler.relative = ctx.ModuleName()
	}
	test.binaryDecorator.install(ctx, file)
}

func (test *testDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
	flags = test.binaryDecorator.compilerFlags(ctx, flags)
	flags.RustFlags = append(flags.RustFlags, "--test")
	return flags
}

func init() {
	// Rust tests are binary files built with --test.
	android.RegisterModuleType("rust_test", RustTestFactory)
	android.RegisterModuleType("rust_test_host", RustTestHostFactory)
}

func RustTestFactory() android.Module {
	module, _ := NewRustTest(android.HostAndDeviceSupported)
	return module.Init()
}

func RustTestHostFactory() android.Module {
	module, _ := NewRustTest(android.HostSupported)
	return module.Init()
}

func (test *testDecorator) testPerSrc() bool {
	return true
}

func (test *testDecorator) srcs() []string {
	return test.binaryDecorator.Properties.Srcs
}

func (test *testDecorator) setSrc(name, src string) {
	test.binaryDecorator.Properties.Srcs = []string{src}
	test.baseCompiler.Properties.Stem = StringPtr(name)
}

func (test *testDecorator) unsetSrc() {
	test.binaryDecorator.Properties.Srcs = nil
	test.baseCompiler.Properties.Stem = StringPtr("")
}

type testPerSrc interface {
	testPerSrc() bool
	srcs() []string
	setSrc(string, string)
	unsetSrc()
}

var _ testPerSrc = (*testDecorator)(nil)

func TestPerSrcMutator(mctx android.BottomUpMutatorContext) {
	if m, ok := mctx.Module().(*Module); ok {
		if test, ok := m.compiler.(testPerSrc); ok {
			numTests := len(test.srcs())
			if test.testPerSrc() && numTests > 0 {
				if duplicate, found := android.CheckDuplicate(test.srcs()); found {
					mctx.PropertyErrorf("srcs", "found a duplicate entry %q", duplicate)
					return
				}
				// Rust compiler always compiles one source file at a time and
				// uses the crate name as output file name.
				// Cargo uses the test source file name as default crate name,
				// but that can be redefined.
				// So when there are multiple source files, the source file names will
				// be the output file names, but when there is only one test file,
				// use the crate name.
				testNames := make([]string, numTests)
				for i, src := range test.srcs() {
					testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
				}
				crateName := m.compiler.crateName()
				if numTests == 1 && crateName != "" {
					testNames[0] = crateName
				}
				// TODO(chh): Add an "all tests" variation like cc/test.go?
				tests := mctx.CreateLocalVariations(testNames...)
				for i, src := range test.srcs() {
					tests[i].(*Module).compiler.(testPerSrc).setSrc(testNames[i], src)
				}
			}
		}
	}
}
