| // Copyright 2023 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" |
| ) |
| |
| func TestOrderfileProfileSharedLibrary(t *testing.T) { |
| t.Parallel() |
| bp := ` |
| cc_library_shared { |
| name: "libTest", |
| srcs: ["test.c"], |
| orderfile : { |
| instrumentation: true, |
| load_order_file: false, |
| order_file_path: "", |
| }, |
| } |
| ` |
| |
| result := android.GroupFixturePreparers( |
| prepareForCcTest, |
| ).RunTestWithBp(t, bp) |
| |
| expectedCFlag := "-forder-file-instrumentation" |
| |
| libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared") |
| |
| // Check cFlags of orderfile-enabled module |
| cFlags := libTest.Rule("cc").Args["cFlags"] |
| if !strings.Contains(cFlags, expectedCFlag) { |
| t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags) |
| } |
| |
| // Check ldFlags of orderfile-enabled module |
| ldFlags := libTest.Rule("ld").Args["ldFlags"] |
| if !strings.Contains(ldFlags, expectedCFlag) { |
| t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags) |
| } |
| } |
| |
| func TestOrderfileLoadSharedLibrary(t *testing.T) { |
| t.Parallel() |
| bp := ` |
| cc_library_shared { |
| name: "libTest", |
| srcs: ["test.c"], |
| orderfile : { |
| instrumentation: true, |
| load_order_file: true, |
| order_file_path: "libTest.orderfile", |
| }, |
| } |
| ` |
| |
| result := android.GroupFixturePreparers( |
| prepareForCcTest, |
| android.FixtureAddTextFile("toolchain/pgo-profiles/orderfiles/libTest.orderfile", "TEST"), |
| ).RunTestWithBp(t, bp) |
| |
| expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/libTest.orderfile" |
| |
| libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared") |
| |
| // Check ldFlags of orderfile-enabled module |
| ldFlags := libTest.Rule("ld").Args["ldFlags"] |
| if !strings.Contains(ldFlags, expectedCFlag) { |
| t.Errorf("Expected 'libTest' to load orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags) |
| } |
| } |
| |
| func TestOrderfileProfileBinary(t *testing.T) { |
| t.Parallel() |
| bp := ` |
| cc_binary { |
| name: "test", |
| srcs: ["test.c"], |
| orderfile : { |
| instrumentation: true, |
| load_order_file: false, |
| order_file_path: "", |
| }, |
| } |
| ` |
| |
| result := android.GroupFixturePreparers( |
| prepareForCcTest, |
| ).RunTestWithBp(t, bp) |
| |
| expectedCFlag := "-forder-file-instrumentation" |
| |
| test := result.ModuleForTests("test", "android_arm64_armv8-a") |
| |
| // Check cFlags of orderfile-enabled module |
| cFlags := test.Rule("cc").Args["cFlags"] |
| if !strings.Contains(cFlags, expectedCFlag) { |
| t.Errorf("Expected 'test' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags) |
| } |
| |
| // Check ldFlags of orderfile-enabled module |
| ldFlags := test.Rule("ld").Args["ldFlags"] |
| if !strings.Contains(ldFlags, expectedCFlag) { |
| t.Errorf("Expected 'test' to enable orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags) |
| } |
| } |
| |
| func TestOrderfileLoadBinary(t *testing.T) { |
| t.Parallel() |
| bp := ` |
| cc_binary { |
| name: "test", |
| srcs: ["test.c"], |
| orderfile : { |
| instrumentation: true, |
| load_order_file: true, |
| order_file_path: "test.orderfile", |
| }, |
| } |
| ` |
| |
| result := android.GroupFixturePreparers( |
| prepareForCcTest, |
| android.FixtureAddTextFile("toolchain/pgo-profiles/orderfiles/test.orderfile", "TEST"), |
| ).RunTestWithBp(t, bp) |
| |
| expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/test.orderfile" |
| |
| test := result.ModuleForTests("test", "android_arm64_armv8-a") |
| |
| // Check ldFlags of orderfile-enabled module |
| ldFlags := test.Rule("ld").Args["ldFlags"] |
| if !strings.Contains(ldFlags, expectedCFlag) { |
| t.Errorf("Expected 'test' to load orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags) |
| } |
| } |
| |
| // Profile flags should propagate through static libraries |
| func TestOrderfileProfilePropagateStaticDeps(t *testing.T) { |
| t.Parallel() |
| bp := ` |
| cc_library_shared { |
| name: "libTest", |
| srcs: ["test.c"], |
| static_libs: ["libFoo"], |
| orderfile : { |
| instrumentation: true, |
| load_order_file: false, |
| order_file_path: "", |
| }, |
| } |
| |
| cc_library_static { |
| name: "libFoo", |
| srcs: ["foo.c"], |
| static_libs: ["libBar"], |
| } |
| |
| cc_library_static { |
| name: "libBar", |
| srcs: ["bar.c"], |
| } |
| ` |
| |
| result := android.GroupFixturePreparers( |
| prepareForCcTest, |
| ).RunTestWithBp(t, bp) |
| |
| expectedCFlag := "-forder-file-instrumentation" |
| |
| // Check cFlags of orderfile-enabled module |
| libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared") |
| |
| cFlags := libTest.Rule("cc").Args["cFlags"] |
| if !strings.Contains(cFlags, expectedCFlag) { |
| t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags) |
| } |
| |
| // Check cFlags of orderfile variant static libraries |
| libFooOfVariant := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_orderfile") |
| libBarOfVariant := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_orderfile") |
| |
| cFlags = libFooOfVariant.Rule("cc").Args["cFlags"] |
| if !strings.Contains(cFlags, expectedCFlag) { |
| t.Errorf("Expected 'libFooOfVariant' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags) |
| } |
| |
| cFlags = libBarOfVariant.Rule("cc").Args["cFlags"] |
| if !strings.Contains(cFlags, expectedCFlag) { |
| t.Errorf("Expected 'libBarOfVariant' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags) |
| } |
| |
| // Check dependency edge from orderfile-enabled module to orderfile variant static libraries |
| if !hasDirectDep(result, libTest.Module(), libFooOfVariant.Module()) { |
| t.Errorf("libTest missing dependency on orderfile variant of libFoo") |
| } |
| |
| if !hasDirectDep(result, libFooOfVariant.Module(), libBarOfVariant.Module()) { |
| t.Errorf("libTest missing dependency on orderfile variant of libBar") |
| } |
| |
| // Check cFlags of the non-orderfile variant static libraries |
| libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static") |
| libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static") |
| |
| cFlags = libFoo.Rule("cc").Args["cFlags"] |
| if strings.Contains(cFlags, expectedCFlag) { |
| t.Errorf("Expected 'libFoo' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) |
| } |
| |
| cFlags = libBar.Rule("cc").Args["cFlags"] |
| if strings.Contains(cFlags, expectedCFlag) { |
| t.Errorf("Expected 'libBar' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) |
| } |
| |
| // Check no dependency edge from orderfile-enabled module to non-orderfile variant static libraries |
| if hasDirectDep(result, libTest.Module(), libFoo.Module()) { |
| t.Errorf("libTest has dependency on non-orderfile variant of libFoo") |
| } |
| |
| if !hasDirectDep(result, libFoo.Module(), libBar.Module()) { |
| t.Errorf("libTest has dependency on non-orderfile variant of libBar") |
| } |
| } |
| |
| // Load flags should never propagate |
| func TestOrderfileLoadPropagateStaticDeps(t *testing.T) { |
| t.Parallel() |
| bp := ` |
| cc_library_shared { |
| name: "libTest", |
| srcs: ["test.c"], |
| static_libs: ["libFoo"], |
| orderfile : { |
| instrumentation: true, |
| load_order_file: true, |
| order_file_path: "test.orderfile", |
| }, |
| } |
| |
| cc_library_static { |
| name: "libFoo", |
| srcs: ["foo.c"], |
| static_libs: ["libBar"], |
| } |
| |
| cc_library_static { |
| name: "libBar", |
| srcs: ["bar.c"], |
| } |
| ` |
| |
| result := android.GroupFixturePreparers( |
| prepareForCcTest, |
| android.FixtureAddTextFile("toolchain/pgo-profiles/orderfiles/test.orderfile", "TEST"), |
| ).RunTestWithBp(t, bp) |
| |
| expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/test.orderfile" |
| |
| // Check ldFlags of orderfile-enabled module |
| libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared") |
| |
| ldFlags := libTest.Rule("ld").Args["ldFlags"] |
| if !strings.Contains(ldFlags, expectedCFlag) { |
| t.Errorf("Expected 'libTest' to load orderfile, but did not find %q in ldFlags %q", expectedCFlag, ldFlags) |
| } |
| |
| libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static") |
| libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static") |
| |
| // Check dependency edge from orderfile-enabled module to non-orderfile variant static libraries |
| if !hasDirectDep(result, libTest.Module(), libFoo.Module()) { |
| t.Errorf("libTest missing dependency on non-orderfile variant of libFoo") |
| } |
| |
| if !hasDirectDep(result, libFoo.Module(), libBar.Module()) { |
| t.Errorf("libTest missing dependency on non-orderfile variant of libBar") |
| } |
| |
| // Make sure no orderfile variants are created for static libraries because the flags were not propagated |
| libFooVariants := result.ModuleVariantsForTests("libFoo") |
| for _, v := range libFooVariants { |
| if strings.Contains(v, "orderfile") { |
| t.Errorf("Expected variants for 'libFoo' to not contain 'orderfile', but found %q", v) |
| } |
| } |
| |
| libBarVariants := result.ModuleVariantsForTests("libBar") |
| for _, v := range libBarVariants { |
| if strings.Contains(v, "orderfile") { |
| t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v) |
| } |
| } |
| } |
| |
| // Profile flags should not propagate through shared libraries |
| func TestOrderfileProfilePropagateSharedDeps(t *testing.T) { |
| t.Parallel() |
| bp := ` |
| cc_library_shared { |
| name: "libTest", |
| srcs: ["test.c"], |
| shared_libs: ["libFoo"], |
| orderfile : { |
| instrumentation: true, |
| load_order_file: false, |
| order_file_path: "", |
| }, |
| } |
| |
| cc_library_shared { |
| name: "libFoo", |
| srcs: ["foo.c"], |
| static_libs: ["libBar"], |
| } |
| |
| cc_library_static { |
| name: "libBar", |
| srcs: ["bar.c"], |
| } |
| ` |
| |
| result := android.GroupFixturePreparers( |
| prepareForCcTest, |
| ).RunTestWithBp(t, bp) |
| |
| expectedCFlag := "-forder-file-instrumentation" |
| |
| // Check cFlags of orderfile-enabled module |
| libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared") |
| |
| cFlags := libTest.Rule("cc").Args["cFlags"] |
| if !strings.Contains(cFlags, expectedCFlag) { |
| t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags) |
| } |
| |
| // Check cFlags of the static and shared libraries |
| libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_shared") |
| libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static") |
| |
| cFlags = libFoo.Rule("cc").Args["cFlags"] |
| if strings.Contains(cFlags, expectedCFlag) { |
| t.Errorf("Expected 'libFoo' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) |
| } |
| |
| cFlags = libBar.Rule("cc").Args["cFlags"] |
| if strings.Contains(cFlags, expectedCFlag) { |
| t.Errorf("Expected 'libBar' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) |
| } |
| |
| // Check dependency edge from orderfile-enabled module to non-orderfile variant static libraries |
| if !hasDirectDep(result, libTest.Module(), libFoo.Module()) { |
| t.Errorf("libTest missing dependency on non-orderfile variant of libFoo") |
| } |
| |
| if !hasDirectDep(result, libFoo.Module(), libBar.Module()) { |
| t.Errorf("libTest missing dependency on non-orderfile variant of libBar") |
| } |
| |
| // Make sure no orderfile variants are created for libraries because the flags were not propagated |
| libFooVariants := result.ModuleVariantsForTests("libFoo") |
| for _, v := range libFooVariants { |
| if strings.Contains(v, "orderfile") { |
| t.Errorf("Expected variants for 'libFoo' to not contain 'orderfile', but found %q", v) |
| } |
| } |
| |
| libBarVariants := result.ModuleVariantsForTests("libBar") |
| for _, v := range libBarVariants { |
| if strings.Contains(v, "orderfile") { |
| t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v) |
| } |
| } |
| } |
| |
| // Profile flags should not work or be propagated if orderfile flags start at a static library |
| func TestOrderfileProfileStaticLibrary(t *testing.T) { |
| t.Parallel() |
| bp := ` |
| cc_library_static { |
| name: "libTest", |
| srcs: ["test.c"], |
| static_libs: ["libFoo"], |
| orderfile : { |
| instrumentation: true, |
| load_order_file: false, |
| order_file_path: "", |
| }, |
| } |
| |
| cc_library_static { |
| name: "libFoo", |
| srcs: ["foo.c"], |
| static_libs: ["libBar"], |
| } |
| |
| cc_library_static { |
| name: "libBar", |
| srcs: ["bar.c"], |
| } |
| ` |
| |
| result := android.GroupFixturePreparers( |
| prepareForCcTest, |
| ).RunTestWithBp(t, bp) |
| |
| expectedCFlag := "-forder-file-instrumentation" |
| |
| // Check cFlags of module |
| libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_static") |
| |
| cFlags := libTest.Rule("cc").Args["cFlags"] |
| if strings.Contains(cFlags, expectedCFlag) { |
| t.Errorf("Expected 'libTest' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) |
| } |
| |
| // Check cFlags of the static libraries |
| libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static") |
| libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static") |
| |
| cFlags = libFoo.Rule("cc").Args["cFlags"] |
| if strings.Contains(cFlags, expectedCFlag) { |
| t.Errorf("Expected 'libFoo' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) |
| } |
| |
| cFlags = libBar.Rule("cc").Args["cFlags"] |
| if strings.Contains(cFlags, expectedCFlag) { |
| t.Errorf("Expected 'libBar' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) |
| } |
| |
| // Check dependency edge from orderfile-enabled module to non-orderfile variant libraries |
| if !hasDirectDep(result, libTest.Module(), libFoo.Module()) { |
| t.Errorf("libTest missing dependency on non-orderfile variant of libFoo") |
| } |
| |
| if !hasDirectDep(result, libFoo.Module(), libBar.Module()) { |
| t.Errorf("libTest missing dependency on non-orderfile variant of libBar") |
| } |
| |
| // Make sure no orderfile variants are created for static libraries because the flags were not propagated |
| libFooVariants := result.ModuleVariantsForTests("libFoo") |
| for _, v := range libFooVariants { |
| if strings.Contains(v, "orderfile") { |
| t.Errorf("Expected variants for 'libFoo' to not contain 'orderfile', but found %q", v) |
| } |
| } |
| |
| libBarVariants := result.ModuleVariantsForTests("libBar") |
| for _, v := range libBarVariants { |
| if strings.Contains(v, "orderfile") { |
| t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v) |
| } |
| } |
| } |