// Copyright 2021 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 cc

import (
	"strings"
	"testing"

	"android/soong/android"

	"github.com/google/blueprint"
)

var NoGlobalThinLTOPreparer = android.GroupFixturePreparers(
	prepareForCcTest,
	android.FixtureModifyEnv(func(env map[string]string) {
		env["GLOBAL_THINLTO"] = "false"
	}))

func TestThinLtoDeps(t *testing.T) {
	t.Parallel()
	bp := `
	cc_library_shared {
		name: "lto_enabled",
		srcs: ["src.c"],
		static_libs: ["foo", "lib_never_lto"],
		shared_libs: ["bar"],
		lto: {
			thin: true,
		}
	}
	cc_library_static {
		name: "foo",
		static_libs: ["baz"],
	}
	cc_library_shared {
		name: "bar",
		static_libs: ["qux"],
	}
	cc_library_static {
		name: "baz",
	}
	cc_library_static {
		name: "qux",
	}
	cc_library_static {
		name: "lib_never_lto",
		lto: {
			never: true,
		},
	}
`

	result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)

	libLto := result.ModuleForTests("lto_enabled", "android_arm64_armv8-a_shared").Module()

	hasDep := func(m android.Module, wantDep android.Module) bool {
		var found bool
		result.VisitDirectDeps(m, func(dep blueprint.Module) {
			if dep == wantDep {
				found = true
			}
		})
		return found
	}

	libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static_lto-thin").Module()
	if !hasDep(libLto, libFoo) {
		t.Errorf("'lto_enabled' missing dependency on thin lto variant of 'foo'")
	}

	libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static_lto-thin").Module()
	if !hasDep(libFoo, libBaz) {
		t.Errorf("'foo' missing dependency on thin lto variant of transitive dep 'baz'")
	}

	libNeverLto := result.ModuleForTests("lib_never_lto", "android_arm64_armv8-a_static_lto-thin").Module()
	if !hasDep(libLto, libNeverLto) {
		t.Errorf("'lto_enabled' missing dependency on NO-thin lto variant of 'lib_never_lto'")
	}

	libBar := result.ModuleForTests("bar", "android_arm64_armv8-a_shared").Module()
	if !hasDep(libLto, libBar) {
		t.Errorf("'lto_enabled' missing dependency on non-thin lto variant of 'bar'")
	}

	barVariants := result.ModuleVariantsForTests("bar")
	for _, v := range barVariants {
		if strings.Contains(v, "lto-thin") {
			t.Errorf("Expected variants for 'bar' to not contain 'lto-thin', but found %q", v)
		}
	}
	quxVariants := result.ModuleVariantsForTests("qux")
	for _, v := range quxVariants {
		if strings.Contains(v, "lto-thin") {
			t.Errorf("Expected variants for 'qux' to not contain 'lto-thin', but found %q", v)
		}
	}
}

func TestThinLtoOnlyOnStaticDep(t *testing.T) {
	t.Parallel()
	bp := `
	cc_library_shared {
		name: "root",
		srcs: ["src.c"],
		static_libs: ["foo"],
	}
	cc_library_shared {
		name: "root_no_lto",
		srcs: ["src.c"],
		static_libs: ["foo"],
		lto: {
			never: true,
		}
	}
	cc_library_static {
		name: "foo",
		srcs: ["foo.c"],
		static_libs: ["baz"],
		lto: {
			thin: true,
		}
	}
	cc_library_static {
		name: "baz",
		srcs: ["baz.c"],
	}
`

	result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)

	libRoot := result.ModuleForTests("root", "android_arm64_armv8-a_shared").Module()
	libRootLtoNever := result.ModuleForTests("root_no_lto", "android_arm64_armv8-a_shared").Module()

	hasDep := func(m android.Module, wantDep android.Module) bool {
		var found bool
		result.VisitDirectDeps(m, func(dep blueprint.Module) {
			if dep == wantDep {
				found = true
			}
		})
		return found
	}

	libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static")
	if !hasDep(libRoot, libFoo.Module()) {
		t.Errorf("'root' missing dependency on thin lto variant of 'foo'")
	}

	if !hasDep(libRootLtoNever, libFoo.Module()) {
		t.Errorf("'root_no_lto' missing dependency on thin lto variant of 'foo'")
	}

	libFooCFlags := libFoo.Rule("cc").Args["cFlags"]
	if w := "-flto=thin -fsplit-lto-unit"; !strings.Contains(libFooCFlags, w) {
		t.Errorf("'foo' expected to have flags %q, but got %q", w, libFooCFlags)
	}

	libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static_lto-thin")
	if !hasDep(libFoo.Module(), libBaz.Module()) {
		t.Errorf("'foo' missing dependency on thin lto variant of transitive dep 'baz'")
	}

	libBazCFlags := libFoo.Rule("cc").Args["cFlags"]
	if w := "-flto=thin -fsplit-lto-unit"; !strings.Contains(libBazCFlags, w) {
		t.Errorf("'baz' expected to have flags %q, but got %q", w, libFooCFlags)
	}
}

func TestLtoDisabledButEnabledForArch(t *testing.T) {
	t.Parallel()
	bp := `
	cc_library {
		name: "libfoo",
		srcs: ["foo.c"],
		lto: {
			never: true,
		},
		target: {
			android_arm: {
				lto: {
					never: false,
					thin: true,
				},
			},
		},
	}`
	result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)

	libFooWithLto := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
	libFooWithoutLto := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("ld")

	android.AssertStringDoesContain(t, "missing flag for LTO in variant that expects it",
		libFooWithLto.Args["ldFlags"], "-flto=thin")
	android.AssertStringDoesNotContain(t, "got flag for LTO in variant that doesn't expect it",
		libFooWithoutLto.Args["ldFlags"], "-flto=thin")
}

func TestLtoDoesNotPropagateToRuntimeLibs(t *testing.T) {
	t.Parallel()
	bp := `
	cc_library {
		name: "runtime_libbar",
		srcs: ["bar.c"],
	}

	cc_library {
		name: "libfoo",
		srcs: ["foo.c"],
		runtime_libs: ["runtime_libbar"],
		lto: {
			thin: true,
		},
	}`

	result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)

	libFoo := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
	libBar := result.ModuleForTests("runtime_libbar", "android_arm_armv7-a-neon_shared").Rule("ld")

	android.AssertStringDoesContain(t, "missing flag for LTO in LTO enabled library",
		libFoo.Args["ldFlags"], "-flto=thin")
	android.AssertStringDoesNotContain(t, "got flag for LTO in runtime_lib",
		libBar.Args["ldFlags"], "-flto=thin")
}
