// 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 LTOPreparer = android.GroupFixturePreparers(
	prepareForCcTest,
)

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

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"],
	}
	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 := LTOPreparer.RunTestWithBp(t, bp)

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

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

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

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

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

	barVariants := result.ModuleVariantsForTests("bar")
	for _, v := range barVariants {
		if strings.Contains(v, "lto-none") {
			t.Errorf("Expected variants for 'bar' to not contain 'lto-none', but found %q", v)
		}
	}
	quxVariants := result.ModuleVariantsForTests("qux")
	for _, v := range quxVariants {
		if strings.Contains(v, "lto-none") {
			t.Errorf("Expected variants for 'qux' to not contain 'lto-none', 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 := LTOPreparer.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()

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

	if !hasDep(result, libRootLtoNever, libFoo.Module()) {
		t.Errorf("'root_no_lto' missing dependency on the default 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")
	if !hasDep(result, libFoo.Module(), libBaz.Module()) {
		t.Errorf("'foo' missing dependency on the default 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 := LTOPreparer.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 := LTOPreparer.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")
}
