1// Copyright 2019 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 15package rust 16 17import ( 18 "strings" 19 "testing" 20 21 "android/soong/android" 22) 23 24// Test that feature flags are being correctly generated. 25func TestFeaturesToFlags(t *testing.T) { 26 ctx := testRust(t, ` 27 rust_library_host_dylib { 28 name: "libfoo", 29 srcs: ["foo.rs"], 30 crate_name: "foo", 31 features: [ 32 "fizz", 33 "buzz" 34 ], 35 }`) 36 37 libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc") 38 39 if !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'feature=\"fizz\"'") || 40 !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'feature=\"buzz\"'") { 41 t.Fatalf("missing fizz and buzz feature flags for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"]) 42 } 43} 44 45// Test that cfgs flags are being correctly generated. 46func TestCfgsToFlags(t *testing.T) { 47 ctx := testRust(t, ` 48 rust_library_host { 49 name: "libfoo", 50 srcs: ["foo.rs"], 51 crate_name: "foo", 52 cfgs: [ 53 "std", 54 "cfg1=\"one\"" 55 ], 56 }`) 57 58 libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc") 59 60 if !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'std'") || 61 !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'cfg1=\"one\"'") { 62 t.Fatalf("missing std and cfg1 flags for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"]) 63 } 64} 65 66// Test that we reject multiple source files. 67func TestEnforceSingleSourceFile(t *testing.T) { 68 69 singleSrcError := "srcs can only contain one path for a rust file and source providers prefixed by \":\"" 70 71 // Test libraries 72 testRustError(t, singleSrcError, ` 73 rust_library_host { 74 name: "foo-bar-library", 75 srcs: ["foo.rs", "src/bar.rs"], 76 }`) 77 78 // Test binaries 79 testRustError(t, singleSrcError, ` 80 rust_binary_host { 81 name: "foo-bar-binary", 82 srcs: ["foo.rs", "src/bar.rs"], 83 }`) 84 85 // Test proc_macros 86 testRustError(t, singleSrcError, ` 87 rust_proc_macro { 88 name: "foo-bar-proc-macro", 89 srcs: ["foo.rs", "src/bar.rs"], 90 }`) 91 92 // Test prebuilts 93 testRustError(t, singleSrcError, ` 94 rust_prebuilt_dylib { 95 name: "foo-bar-prebuilt", 96 srcs: ["liby.so", "libz.so"], 97 host_supported: true, 98 }`) 99} 100 101func TestInstallDir(t *testing.T) { 102 ctx := testRust(t, ` 103 rust_library_dylib { 104 name: "libfoo", 105 srcs: ["foo.rs"], 106 crate_name: "foo", 107 } 108 rust_binary { 109 name: "fizzbuzz", 110 srcs: ["foo.rs"], 111 }`) 112 113 install_path_lib64 := ctx.ModuleForTests("libfoo", 114 "android_arm64_armv8-a_dylib").Module().(*Module).compiler.(*libraryDecorator).path.String() 115 install_path_lib32 := ctx.ModuleForTests("libfoo", 116 "android_arm_armv7-a-neon_dylib").Module().(*Module).compiler.(*libraryDecorator).path.String() 117 install_path_bin := ctx.ModuleForTests("fizzbuzz", 118 "android_arm64_armv8-a").Module().(*Module).compiler.(*binaryDecorator).path.String() 119 120 if !strings.HasSuffix(install_path_lib64, "system/lib64/libfoo.dylib.so") { 121 t.Fatalf("unexpected install path for 64-bit library: %#v", install_path_lib64) 122 } 123 if !strings.HasSuffix(install_path_lib32, "system/lib/libfoo.dylib.so") { 124 t.Fatalf("unexpected install path for 32-bit library: %#v", install_path_lib32) 125 } 126 if !strings.HasSuffix(install_path_bin, "system/bin/fizzbuzz") { 127 t.Fatalf("unexpected install path for binary: %#v", install_path_bin) 128 } 129} 130 131func TestLints(t *testing.T) { 132 133 bp := ` 134 // foo uses the default value of lints 135 rust_library { 136 name: "libfoo", 137 srcs: ["foo.rs"], 138 crate_name: "foo", 139 } 140 // bar forces the use of the "android" lint set 141 rust_library { 142 name: "libbar", 143 srcs: ["foo.rs"], 144 crate_name: "bar", 145 lints: "android", 146 } 147 // foobar explicitly disable all lints 148 rust_library { 149 name: "libfoobar", 150 srcs: ["foo.rs"], 151 crate_name: "foobar", 152 lints: "none", 153 }` 154 155 var lintTests = []struct { 156 modulePath string 157 fooFlags string 158 }{ 159 {"", "${config.RustDefaultLints}"}, 160 {"external/", "${config.RustAllowAllLints}"}, 161 {"hardware/", "${config.RustVendorLints}"}, 162 } 163 164 for _, tc := range lintTests { 165 t.Run("path="+tc.modulePath, func(t *testing.T) { 166 167 result := android.GroupFixturePreparers( 168 prepareForRustTest, 169 // Test with the blueprint file in different directories. 170 android.FixtureAddTextFile(tc.modulePath+"Android.bp", bp), 171 ).RunTest(t) 172 173 r := result.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("rustc") 174 android.AssertStringDoesContain(t, "libfoo flags", r.Args["rustcFlags"], tc.fooFlags) 175 176 r = result.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("rustc") 177 android.AssertStringDoesContain(t, "libbar flags", r.Args["rustcFlags"], "${config.RustDefaultLints}") 178 179 r = result.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("rustc") 180 android.AssertStringDoesContain(t, "libfoobar flags", r.Args["rustcFlags"], "${config.RustAllowAllLints}") 181 }) 182 } 183} 184 185// Test that devices are linking the stdlib dynamically 186func TestStdDeviceLinkage(t *testing.T) { 187 ctx := testRust(t, ` 188 rust_binary { 189 name: "fizz", 190 srcs: ["foo.rs"], 191 } 192 rust_library { 193 name: "libfoo", 194 srcs: ["foo.rs"], 195 crate_name: "foo", 196 }`) 197 fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Module().(*Module) 198 fooRlib := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std").Module().(*Module) 199 fooDylib := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").Module().(*Module) 200 201 if !android.InList("libstd", fizz.Properties.AndroidMkDylibs) { 202 t.Errorf("libstd is not linked dynamically for device binaries") 203 } 204 if !android.InList("libstd", fooRlib.Properties.AndroidMkDylibs) { 205 t.Errorf("libstd is not linked dynamically for rlibs") 206 } 207 if !android.InList("libstd", fooDylib.Properties.AndroidMkDylibs) { 208 t.Errorf("libstd is not linked dynamically for dylibs") 209 } 210} 211