Colin Cross | af98f58 | 2021-05-12 17:27:32 -0700 | [diff] [blame^] | 1 | // Copyright 2021 Google Inc. All rights reserved. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | package cc |
| 16 | |
| 17 | import ( |
| 18 | "testing" |
| 19 | |
| 20 | "android/soong/android" |
| 21 | ) |
| 22 | |
| 23 | var prepareForAsanTest = android.FixtureAddFile("asan/Android.bp", []byte(` |
| 24 | cc_library_shared { |
| 25 | name: "libclang_rt.asan-aarch64-android", |
| 26 | } |
| 27 | |
| 28 | cc_library_shared { |
| 29 | name: "libclang_rt.asan-arm-android", |
| 30 | } |
| 31 | `)) |
| 32 | |
| 33 | func TestAsan(t *testing.T) { |
| 34 | bp := ` |
| 35 | cc_binary { |
| 36 | name: "bin_with_asan", |
| 37 | host_supported: true, |
| 38 | shared_libs: [ |
| 39 | "libshared", |
| 40 | "libasan", |
| 41 | ], |
| 42 | static_libs: [ |
| 43 | "libstatic", |
| 44 | "libnoasan", |
| 45 | ], |
| 46 | sanitize: { |
| 47 | address: true, |
| 48 | } |
| 49 | } |
| 50 | |
| 51 | cc_binary { |
| 52 | name: "bin_no_asan", |
| 53 | host_supported: true, |
| 54 | shared_libs: [ |
| 55 | "libshared", |
| 56 | "libasan", |
| 57 | ], |
| 58 | static_libs: [ |
| 59 | "libstatic", |
| 60 | "libnoasan", |
| 61 | ], |
| 62 | } |
| 63 | |
| 64 | cc_library_shared { |
| 65 | name: "libshared", |
| 66 | host_supported: true, |
| 67 | shared_libs: ["libtransitive"], |
| 68 | } |
| 69 | |
| 70 | cc_library_shared { |
| 71 | name: "libasan", |
| 72 | host_supported: true, |
| 73 | shared_libs: ["libtransitive"], |
| 74 | sanitize: { |
| 75 | address: true, |
| 76 | } |
| 77 | } |
| 78 | |
| 79 | cc_library_shared { |
| 80 | name: "libtransitive", |
| 81 | host_supported: true, |
| 82 | } |
| 83 | |
| 84 | cc_library_static { |
| 85 | name: "libstatic", |
| 86 | host_supported: true, |
| 87 | } |
| 88 | |
| 89 | cc_library_static { |
| 90 | name: "libnoasan", |
| 91 | host_supported: true, |
| 92 | sanitize: { |
| 93 | address: false, |
| 94 | } |
| 95 | } |
| 96 | ` |
| 97 | |
| 98 | result := android.GroupFixturePreparers( |
| 99 | prepareForCcTest, |
| 100 | prepareForAsanTest, |
| 101 | ).RunTestWithBp(t, bp) |
| 102 | |
| 103 | check := func(t *testing.T, result *android.TestResult, variant string) { |
| 104 | asanVariant := variant + "_asan" |
| 105 | sharedVariant := variant + "_shared" |
| 106 | sharedAsanVariant := sharedVariant + "_asan" |
| 107 | staticVariant := variant + "_static" |
| 108 | staticAsanVariant := staticVariant + "_asan" |
| 109 | |
| 110 | // The binaries, one with asan and one without |
| 111 | binWithAsan := result.ModuleForTests("bin_with_asan", asanVariant) |
| 112 | binNoAsan := result.ModuleForTests("bin_no_asan", variant) |
| 113 | |
| 114 | // Shared libraries that don't request asan |
| 115 | libShared := result.ModuleForTests("libshared", sharedVariant) |
| 116 | libTransitive := result.ModuleForTests("libtransitive", sharedVariant) |
| 117 | |
| 118 | // Shared library that requests asan |
| 119 | libAsan := result.ModuleForTests("libasan", sharedAsanVariant) |
| 120 | |
| 121 | // Static library that uses an asan variant for bin_with_asan and a non-asan variant |
| 122 | // for bin_no_asan. |
| 123 | libStaticAsanVariant := result.ModuleForTests("libstatic", staticAsanVariant) |
| 124 | libStaticNoAsanVariant := result.ModuleForTests("libstatic", staticVariant) |
| 125 | |
| 126 | // Static library that never uses asan. |
| 127 | libNoAsan := result.ModuleForTests("libnoasan", staticVariant) |
| 128 | |
| 129 | // expectSharedLinkDep verifies that the from module links against the to module as a |
| 130 | // shared library. |
| 131 | expectSharedLinkDep := func(from, to android.TestingModule) { |
| 132 | t.Helper() |
| 133 | fromLink := from.Description("link") |
| 134 | toLink := to.Description("strip") |
| 135 | |
| 136 | if g, w := fromLink.OrderOnly.Strings(), toLink.Output.String(); !android.InList(w, g) { |
| 137 | t.Errorf("%s should link against %s, expected %q, got %q", |
| 138 | from.Module(), to.Module(), w, g) |
| 139 | } |
| 140 | } |
| 141 | |
| 142 | // expectStaticLinkDep verifies that the from module links against the to module as a |
| 143 | // static library. |
| 144 | expectStaticLinkDep := func(from, to android.TestingModule) { |
| 145 | t.Helper() |
| 146 | fromLink := from.Description("link") |
| 147 | toLink := to.Description("static link") |
| 148 | |
| 149 | if g, w := fromLink.Implicits.Strings(), toLink.Output.String(); !android.InList(w, g) { |
| 150 | t.Errorf("%s should link against %s, expected %q, got %q", |
| 151 | from.Module(), to.Module(), w, g) |
| 152 | } |
| 153 | |
| 154 | } |
| 155 | |
| 156 | // expectInstallDep verifies that the install rule of the from module depends on the |
| 157 | // install rule of the to module. |
| 158 | expectInstallDep := func(from, to android.TestingModule) { |
| 159 | t.Helper() |
| 160 | fromInstalled := from.Description("install") |
| 161 | toInstalled := to.Description("install") |
| 162 | |
| 163 | // combine implicits and order-only dependencies, host uses implicit but device uses |
| 164 | // order-only. |
| 165 | got := append(fromInstalled.Implicits.Strings(), fromInstalled.OrderOnly.Strings()...) |
| 166 | want := toInstalled.Output.String() |
| 167 | if !android.InList(want, got) { |
| 168 | t.Errorf("%s installation should depend on %s, expected %q, got %q", |
| 169 | from.Module(), to.Module(), want, got) |
| 170 | } |
| 171 | } |
| 172 | |
| 173 | expectSharedLinkDep(binWithAsan, libShared) |
| 174 | expectSharedLinkDep(binWithAsan, libAsan) |
| 175 | expectSharedLinkDep(libShared, libTransitive) |
| 176 | expectSharedLinkDep(libAsan, libTransitive) |
| 177 | |
| 178 | expectStaticLinkDep(binWithAsan, libStaticAsanVariant) |
| 179 | expectStaticLinkDep(binWithAsan, libNoAsan) |
| 180 | |
| 181 | expectInstallDep(binWithAsan, libShared) |
| 182 | expectInstallDep(binWithAsan, libAsan) |
| 183 | expectInstallDep(binWithAsan, libTransitive) |
| 184 | expectInstallDep(libShared, libTransitive) |
| 185 | expectInstallDep(libAsan, libTransitive) |
| 186 | |
| 187 | expectSharedLinkDep(binNoAsan, libShared) |
| 188 | expectSharedLinkDep(binNoAsan, libAsan) |
| 189 | expectSharedLinkDep(libShared, libTransitive) |
| 190 | expectSharedLinkDep(libAsan, libTransitive) |
| 191 | |
| 192 | expectStaticLinkDep(binNoAsan, libStaticNoAsanVariant) |
| 193 | expectStaticLinkDep(binNoAsan, libNoAsan) |
| 194 | |
| 195 | expectInstallDep(binNoAsan, libShared) |
| 196 | expectInstallDep(binNoAsan, libAsan) |
| 197 | expectInstallDep(binNoAsan, libTransitive) |
| 198 | expectInstallDep(libShared, libTransitive) |
| 199 | expectInstallDep(libAsan, libTransitive) |
| 200 | } |
| 201 | |
| 202 | t.Run("host", func(t *testing.T) { check(t, result, result.Config.BuildOSTarget.String()) }) |
| 203 | t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") }) |
| 204 | } |