Ivan Lozano | 1921e80 | 2021-05-20 13:39:16 -0400 | [diff] [blame] | 1 | // Copyright 2021 The Android Open Source Project |
| 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 rust |
| 16 | |
| 17 | import ( |
| 18 | "fmt" |
| 19 | "path/filepath" |
| 20 | "strings" |
| 21 | "testing" |
| 22 | |
| 23 | "android/soong/android" |
| 24 | "android/soong/cc" |
| 25 | ) |
| 26 | |
| 27 | func TestVendorSnapshotCapture(t *testing.T) { |
| 28 | bp := ` |
| 29 | rust_ffi { |
| 30 | name: "librustvendor_available", |
| 31 | crate_name: "rustvendor_available", |
| 32 | srcs: ["lib.rs"], |
| 33 | vendor_available: true, |
| 34 | include_dirs: ["rust_headers/"], |
| 35 | } |
| 36 | |
| 37 | rust_binary { |
| 38 | name: "vendor_available_bin", |
| 39 | vendor_available: true, |
| 40 | srcs: ["srcs/lib.rs"], |
| 41 | } |
| 42 | |
| 43 | ` |
| 44 | skipTestIfOsNotSupported(t) |
| 45 | result := android.GroupFixturePreparers( |
| 46 | prepareForRustTest, |
| 47 | rustMockedFiles.AddToFixture(), |
| 48 | android.FixtureModifyProductVariables( |
| 49 | func(variables android.FixtureProductVariables) { |
| 50 | variables.DeviceVndkVersion = StringPtr("current") |
| 51 | variables.Platform_vndk_version = StringPtr("29") |
| 52 | }, |
| 53 | ), |
| 54 | ).RunTestWithBp(t, bp) |
| 55 | ctx := result.TestContext |
| 56 | |
| 57 | // Check Vendor snapshot output. |
| 58 | |
| 59 | snapshotDir := "vendor-snapshot" |
| 60 | snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64") |
| 61 | snapshotSingleton := ctx.SingletonForTests("vendor-snapshot") |
| 62 | var jsonFiles []string |
| 63 | for _, arch := range [][]string{ |
| 64 | []string{"arm64", "armv8-a"}, |
| 65 | []string{"arm", "armv7-a-neon"}, |
| 66 | } { |
| 67 | archType := arch[0] |
| 68 | archVariant := arch[1] |
| 69 | archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant) |
| 70 | |
| 71 | // For shared libraries, only non-VNDK vendor_available modules are captured |
| 72 | sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant) |
| 73 | sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared") |
| 74 | cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.so", sharedDir, sharedVariant) |
| 75 | jsonFiles = append(jsonFiles, |
| 76 | filepath.Join(sharedDir, "librustvendor_available.so.json")) |
| 77 | |
| 78 | // For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured. |
| 79 | staticVariant := fmt.Sprintf("android_vendor.29_%s_%s_static", archType, archVariant) |
| 80 | staticDir := filepath.Join(snapshotVariantPath, archDir, "static") |
| 81 | cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.a", staticDir, staticVariant) |
| 82 | jsonFiles = append(jsonFiles, |
| 83 | filepath.Join(staticDir, "librustvendor_available.a.json")) |
| 84 | |
| 85 | // For binary executables, all vendor_available modules are captured. |
| 86 | if archType == "arm64" { |
| 87 | binaryVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant) |
| 88 | binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary") |
| 89 | cc.CheckSnapshot(t, ctx, snapshotSingleton, "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant) |
| 90 | jsonFiles = append(jsonFiles, |
| 91 | filepath.Join(binaryDir, "vendor_available_bin.json")) |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | for _, jsonFile := range jsonFiles { |
| 96 | // verify all json files exist |
| 97 | if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil { |
| 98 | t.Errorf("%q expected but not found; #%v", jsonFile, jsonFiles) |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | // fake snapshot should have all outputs in the normal snapshot. |
| 103 | fakeSnapshotSingleton := ctx.SingletonForTests("vendor-fake-snapshot") |
| 104 | |
| 105 | for _, output := range snapshotSingleton.AllOutputs() { |
| 106 | fakeOutput := strings.Replace(output, "/vendor-snapshot/", "/fake/vendor-snapshot/", 1) |
| 107 | if fakeSnapshotSingleton.MaybeOutput(fakeOutput).Rule == nil { |
| 108 | t.Errorf("%q expected but not found", fakeOutput) |
| 109 | } |
| 110 | } |
| 111 | } |
| 112 | |
| 113 | func TestVendorSnapshotDirected(t *testing.T) { |
| 114 | bp := ` |
| 115 | rust_ffi_shared { |
| 116 | name: "librustvendor_available", |
| 117 | crate_name: "rustvendor_available", |
| 118 | srcs: ["lib.rs"], |
| 119 | vendor_available: true, |
| 120 | } |
| 121 | |
| 122 | rust_ffi_shared { |
| 123 | name: "librustvendor_exclude", |
| 124 | crate_name: "rustvendor_exclude", |
| 125 | srcs: ["lib.rs"], |
| 126 | vendor_available: true, |
| 127 | } |
| 128 | ` |
| 129 | ctx := testRustVndk(t, bp) |
| 130 | ctx.Config().TestProductVariables.VendorSnapshotModules = make(map[string]bool) |
| 131 | ctx.Config().TestProductVariables.VendorSnapshotModules["librustvendor_available"] = true |
| 132 | ctx.Config().TestProductVariables.DirectedVendorSnapshot = true |
| 133 | |
| 134 | // Check Vendor snapshot output. |
| 135 | |
| 136 | snapshotDir := "vendor-snapshot" |
| 137 | snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64") |
| 138 | snapshotSingleton := ctx.SingletonForTests("vendor-snapshot") |
| 139 | |
| 140 | var includeJsonFiles []string |
| 141 | |
| 142 | for _, arch := range [][]string{ |
| 143 | []string{"arm64", "armv8-a"}, |
| 144 | []string{"arm", "armv7-a-neon"}, |
| 145 | } { |
| 146 | archType := arch[0] |
| 147 | archVariant := arch[1] |
| 148 | archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant) |
| 149 | |
| 150 | sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant) |
| 151 | sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared") |
| 152 | |
| 153 | // Included modules |
| 154 | cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.so", sharedDir, sharedVariant) |
| 155 | includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librustvendor_available.so.json")) |
| 156 | |
| 157 | // Excluded modules. Modules not included in the directed vendor snapshot |
| 158 | // are still include as fake modules. |
| 159 | cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librustvendor_exclude", "librustvendor_exclude.so", sharedDir, sharedVariant) |
| 160 | includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librustvendor_exclude.so.json")) |
| 161 | } |
| 162 | |
| 163 | // Verify that each json file for an included module has a rule. |
| 164 | for _, jsonFile := range includeJsonFiles { |
| 165 | if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil { |
| 166 | t.Errorf("include json file %q not found", jsonFile) |
| 167 | } |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | func TestVendorSnapshotExclude(t *testing.T) { |
| 172 | |
| 173 | // This test verifies that the exclude_from_vendor_snapshot property |
| 174 | // makes its way from the Android.bp source file into the module data |
| 175 | // structure. It also verifies that modules are correctly included or |
| 176 | // excluded in the vendor snapshot based on their path (framework or |
| 177 | // vendor) and the exclude_from_vendor_snapshot property. |
| 178 | |
| 179 | // When vendor-specific Rust modules are available, make sure to test |
| 180 | // that they're excluded by path here. See cc.TestVendorSnapshotExclude |
| 181 | // for an example. |
| 182 | |
| 183 | frameworkBp := ` |
| 184 | rust_ffi_shared { |
| 185 | name: "libinclude", |
| 186 | crate_name: "include", |
| 187 | srcs: ["include.rs"], |
| 188 | vendor_available: true, |
| 189 | } |
| 190 | |
| 191 | rust_ffi_shared { |
| 192 | name: "libexclude", |
| 193 | crate_name: "exclude", |
| 194 | srcs: ["exclude.rs"], |
| 195 | vendor_available: true, |
| 196 | exclude_from_vendor_snapshot: true, |
| 197 | } |
| 198 | |
| 199 | rust_ffi_shared { |
| 200 | name: "libavailable_exclude", |
| 201 | crate_name: "available_exclude", |
| 202 | srcs: ["lib.rs"], |
| 203 | vendor_available: true, |
| 204 | exclude_from_vendor_snapshot: true, |
| 205 | } |
| 206 | ` |
| 207 | |
| 208 | mockFS := map[string][]byte{ |
| 209 | "framework/Android.bp": []byte(frameworkBp), |
| 210 | "framework/include.rs": nil, |
| 211 | "framework/exclude.rs": nil, |
| 212 | } |
| 213 | |
| 214 | ctx := testRustVndkFs(t, "", mockFS) |
| 215 | |
| 216 | // Test an include and exclude framework module. |
| 217 | cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "libinclude", false, vendorVariant) |
| 218 | cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "libexclude", true, vendorVariant) |
| 219 | cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "libavailable_exclude", true, vendorVariant) |
| 220 | |
| 221 | // Verify the content of the vendor snapshot. |
| 222 | |
| 223 | snapshotDir := "vendor-snapshot" |
| 224 | snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64") |
| 225 | snapshotSingleton := ctx.SingletonForTests("vendor-snapshot") |
| 226 | |
| 227 | var includeJsonFiles []string |
| 228 | var excludeJsonFiles []string |
| 229 | |
| 230 | for _, arch := range [][]string{ |
| 231 | []string{"arm64", "armv8-a"}, |
| 232 | []string{"arm", "armv7-a-neon"}, |
| 233 | } { |
| 234 | archType := arch[0] |
| 235 | archVariant := arch[1] |
| 236 | archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant) |
| 237 | |
| 238 | sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant) |
| 239 | sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared") |
| 240 | |
| 241 | // Included modules |
| 242 | cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant) |
| 243 | includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json")) |
| 244 | |
| 245 | // Excluded modules |
| 246 | cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant) |
| 247 | excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json")) |
| 248 | cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant) |
| 249 | excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json")) |
| 250 | } |
| 251 | |
| 252 | // Verify that each json file for an included module has a rule. |
| 253 | for _, jsonFile := range includeJsonFiles { |
| 254 | if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil { |
| 255 | t.Errorf("include json file %q not found", jsonFile) |
| 256 | } |
| 257 | } |
| 258 | |
| 259 | // Verify that each json file for an excluded module has no rule. |
| 260 | for _, jsonFile := range excludeJsonFiles { |
| 261 | if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil { |
| 262 | t.Errorf("exclude json file %q found", jsonFile) |
| 263 | } |
| 264 | } |
| 265 | } |