blob: 89f4d1abffd2e7719e683601d776dbc39f680721 [file] [log] [blame]
Ivan Lozanoffee3342019-08-27 12:03:00 -07001// 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"
Thiébaud Weksteen9e8451e2020-08-13 12:55:59 +020020
21 "android/soong/android"
Ivan Lozanoffee3342019-08-27 12:03:00 -070022)
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
Wen-yi Chu41326c12023-09-22 03:58:59 +000039 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"])
Ivan Lozanoffee3342019-08-27 12:03:00 -070042 }
43}
44
Thiébaud Weksteenc44e7372021-04-07 14:53:06 +020045// 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
Wen-yi Chu41326c12023-09-22 03:58:59 +000060 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"])
Thiébaud Weksteenc44e7372021-04-07 14:53:06 +020063 }
64}
65
Ivan Lozanoffee3342019-08-27 12:03:00 -070066// Test that we reject multiple source files.
67func TestEnforceSingleSourceFile(t *testing.T) {
68
Ivan Lozano43845682020-07-09 21:03:28 -040069 singleSrcError := "srcs can only contain one path for a rust file and source providers prefixed by \":\""
Matthew Maurer1d8e20d2023-11-20 21:18:12 +000070 prebuiltSingleSrcError := "prebuilt libraries can only have one entry in srcs"
Ivan Lozanoffee3342019-08-27 12:03:00 -070071
72 // Test libraries
73 testRustError(t, singleSrcError, `
74 rust_library_host {
75 name: "foo-bar-library",
76 srcs: ["foo.rs", "src/bar.rs"],
77 }`)
78
79 // Test binaries
80 testRustError(t, singleSrcError, `
81 rust_binary_host {
82 name: "foo-bar-binary",
83 srcs: ["foo.rs", "src/bar.rs"],
84 }`)
85
86 // Test proc_macros
87 testRustError(t, singleSrcError, `
88 rust_proc_macro {
89 name: "foo-bar-proc-macro",
90 srcs: ["foo.rs", "src/bar.rs"],
Ivan Lozanoffee3342019-08-27 12:03:00 -070091 }`)
92
93 // Test prebuilts
Matthew Maurer1d8e20d2023-11-20 21:18:12 +000094 testRustError(t, prebuiltSingleSrcError, `
Ivan Lozanoffee3342019-08-27 12:03:00 -070095 rust_prebuilt_dylib {
96 name: "foo-bar-prebuilt",
97 srcs: ["liby.so", "libz.so"],
98 host_supported: true,
99 }`)
100}
Ivan Lozanof900f4b2020-04-28 13:58:45 -0400101
Seth Moore3afac0b2021-10-13 15:32:18 -0700102// Test that we reject _no_ source files.
103func TestEnforceMissingSourceFiles(t *testing.T) {
104
105 singleSrcError := "srcs must not be empty"
106
107 // Test libraries
108 testRustError(t, singleSrcError, `
109 rust_library_host {
110 name: "foo-bar-library",
111 crate_name: "foo",
112 }`)
113
114 // Test binaries
115 testRustError(t, singleSrcError, `
116 rust_binary_host {
117 name: "foo-bar-binary",
118 crate_name: "foo",
119 }`)
120
121 // Test proc_macros
122 testRustError(t, singleSrcError, `
123 rust_proc_macro {
124 name: "foo-bar-proc-macro",
125 crate_name: "foo",
126 }`)
127
128 // Test prebuilts
129 testRustError(t, singleSrcError, `
130 rust_prebuilt_dylib {
131 name: "foo-bar-prebuilt",
132 crate_name: "foo",
133 host_supported: true,
134 }`)
135}
136
Ivan Lozanoa9a1fc02021-08-11 15:13:43 -0400137// Test environment vars for Cargo compat are set.
138func TestCargoCompat(t *testing.T) {
139 ctx := testRust(t, `
140 rust_binary {
141 name: "fizz",
142 srcs: ["foo.rs"],
143 crate_name: "foo",
144 cargo_env_compat: true,
145 cargo_pkg_version: "1.0.0"
146 }`)
147
148 fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Rule("rustc")
149
Wen-yi Chu41326c12023-09-22 03:58:59 +0000150 if !strings.Contains(fizz.Args["envVars"], "CARGO_BIN_NAME=fizz") {
151 t.Fatalf("expected 'CARGO_BIN_NAME=fizz' in envVars, actual envVars: %#v", fizz.Args["envVars"])
Ivan Lozanoa9a1fc02021-08-11 15:13:43 -0400152 }
Wen-yi Chu41326c12023-09-22 03:58:59 +0000153 if !strings.Contains(fizz.Args["envVars"], "CARGO_CRATE_NAME=foo") {
154 t.Fatalf("expected 'CARGO_CRATE_NAME=foo' in envVars, actual envVars: %#v", fizz.Args["envVars"])
Ivan Lozanoa9a1fc02021-08-11 15:13:43 -0400155 }
Wen-yi Chu41326c12023-09-22 03:58:59 +0000156 if !strings.Contains(fizz.Args["envVars"], "CARGO_PKG_VERSION=1.0.0") {
157 t.Fatalf("expected 'CARGO_PKG_VERSION=1.0.0' in envVars, actual envVars: %#v", fizz.Args["envVars"])
Ivan Lozanoa9a1fc02021-08-11 15:13:43 -0400158 }
159}
160
Ivan Lozanof900f4b2020-04-28 13:58:45 -0400161func TestInstallDir(t *testing.T) {
162 ctx := testRust(t, `
163 rust_library_dylib {
164 name: "libfoo",
165 srcs: ["foo.rs"],
166 crate_name: "foo",
167 }
168 rust_binary {
169 name: "fizzbuzz",
170 srcs: ["foo.rs"],
171 }`)
172
173 install_path_lib64 := ctx.ModuleForTests("libfoo",
174 "android_arm64_armv8-a_dylib").Module().(*Module).compiler.(*libraryDecorator).path.String()
175 install_path_lib32 := ctx.ModuleForTests("libfoo",
176 "android_arm_armv7-a-neon_dylib").Module().(*Module).compiler.(*libraryDecorator).path.String()
177 install_path_bin := ctx.ModuleForTests("fizzbuzz",
178 "android_arm64_armv8-a").Module().(*Module).compiler.(*binaryDecorator).path.String()
179
180 if !strings.HasSuffix(install_path_lib64, "system/lib64/libfoo.dylib.so") {
181 t.Fatalf("unexpected install path for 64-bit library: %#v", install_path_lib64)
182 }
183 if !strings.HasSuffix(install_path_lib32, "system/lib/libfoo.dylib.so") {
184 t.Fatalf("unexpected install path for 32-bit library: %#v", install_path_lib32)
185 }
186 if !strings.HasSuffix(install_path_bin, "system/bin/fizzbuzz") {
187 t.Fatalf("unexpected install path for binary: %#v", install_path_bin)
188 }
189}
Thiébaud Weksteen9e8451e2020-08-13 12:55:59 +0200190
191func TestLints(t *testing.T) {
192
193 bp := `
194 // foo uses the default value of lints
195 rust_library {
196 name: "libfoo",
197 srcs: ["foo.rs"],
198 crate_name: "foo",
199 }
200 // bar forces the use of the "android" lint set
201 rust_library {
202 name: "libbar",
203 srcs: ["foo.rs"],
204 crate_name: "bar",
205 lints: "android",
206 }
207 // foobar explicitly disable all lints
208 rust_library {
209 name: "libfoobar",
210 srcs: ["foo.rs"],
211 crate_name: "foobar",
212 lints: "none",
213 }`
214
Thiébaud Weksteen9e8451e2020-08-13 12:55:59 +0200215 var lintTests = []struct {
216 modulePath string
217 fooFlags string
218 }{
219 {"", "${config.RustDefaultLints}"},
220 {"external/", "${config.RustAllowAllLints}"},
221 {"hardware/", "${config.RustVendorLints}"},
222 }
223
224 for _, tc := range lintTests {
225 t.Run("path="+tc.modulePath, func(t *testing.T) {
226
Paul Duffin9e0c3f92021-03-30 22:45:21 +0100227 result := android.GroupFixturePreparers(
228 prepareForRustTest,
229 // Test with the blueprint file in different directories.
230 android.FixtureAddTextFile(tc.modulePath+"Android.bp", bp),
231 ).RunTest(t)
Thiébaud Weksteen9e8451e2020-08-13 12:55:59 +0200232
Paul Duffin9e0c3f92021-03-30 22:45:21 +0100233 r := result.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
Wen-yi Chu41326c12023-09-22 03:58:59 +0000234 android.AssertStringDoesContain(t, "libfoo flags", r.Args["rustcFlags"], tc.fooFlags)
Thiébaud Weksteen9e8451e2020-08-13 12:55:59 +0200235
Paul Duffin9e0c3f92021-03-30 22:45:21 +0100236 r = result.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
Wen-yi Chu41326c12023-09-22 03:58:59 +0000237 android.AssertStringDoesContain(t, "libbar flags", r.Args["rustcFlags"], "${config.RustDefaultLints}")
Thiébaud Weksteen9e8451e2020-08-13 12:55:59 +0200238
Paul Duffin9e0c3f92021-03-30 22:45:21 +0100239 r = result.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
Wen-yi Chu41326c12023-09-22 03:58:59 +0000240 android.AssertStringDoesContain(t, "libfoobar flags", r.Args["rustcFlags"], "${config.RustAllowAllLints}")
Thiébaud Weksteen9e8451e2020-08-13 12:55:59 +0200241 })
242 }
243}
Ivan Lozano042504f2020-08-18 14:31:23 -0400244
245// Test that devices are linking the stdlib dynamically
246func TestStdDeviceLinkage(t *testing.T) {
247 ctx := testRust(t, `
248 rust_binary {
249 name: "fizz",
250 srcs: ["foo.rs"],
251 }
252 rust_library {
253 name: "libfoo",
254 srcs: ["foo.rs"],
255 crate_name: "foo",
256 }`)
257 fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Module().(*Module)
Ivan Lozano2b081132020-09-08 12:46:52 -0400258 fooRlib := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std").Module().(*Module)
Ivan Lozano042504f2020-08-18 14:31:23 -0400259 fooDylib := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").Module().(*Module)
260
261 if !android.InList("libstd", fizz.Properties.AndroidMkDylibs) {
262 t.Errorf("libstd is not linked dynamically for device binaries")
263 }
264 if !android.InList("libstd", fooRlib.Properties.AndroidMkDylibs) {
265 t.Errorf("libstd is not linked dynamically for rlibs")
266 }
267 if !android.InList("libstd", fooDylib.Properties.AndroidMkDylibs) {
268 t.Errorf("libstd is not linked dynamically for dylibs")
269 }
270}
Ivan Lozano45a9e312021-07-27 12:29:12 -0400271
272// Ensure that manual link flags are disallowed.
273func TestManualLinkageRejection(t *testing.T) {
274 // rustc flags
275 testRustError(t, ".* cannot be manually specified", `
276 rust_binary {
277 name: "foo",
278 srcs: [
279 "foo.rs",
280 ],
281 flags: ["-lbar"],
282 }
283 `)
284 testRustError(t, ".* cannot be manually specified", `
285 rust_binary {
286 name: "foo",
287 srcs: [
288 "foo.rs",
289 ],
290 flags: ["--extern=foo"],
291 }
292 `)
293 testRustError(t, ".* cannot be manually specified", `
294 rust_binary {
295 name: "foo",
296 srcs: [
297 "foo.rs",
298 ],
299 flags: ["-Clink-args=foo"],
300 }
301 `)
302 testRustError(t, ".* cannot be manually specified", `
303 rust_binary {
304 name: "foo",
305 srcs: [
306 "foo.rs",
307 ],
308 flags: ["-C link-args=foo"],
309 }
310 `)
311 testRustError(t, ".* cannot be manually specified", `
312 rust_binary {
313 name: "foo",
314 srcs: [
315 "foo.rs",
316 ],
317 flags: ["-L foo/"],
318 }
319 `)
320
321 // lld flags
322 testRustError(t, ".* cannot be manually specified", `
323 rust_binary {
324 name: "foo",
325 srcs: [
326 "foo.rs",
327 ],
328 ld_flags: ["-Wl,-L bar/"],
329 }
330 `)
331 testRustError(t, ".* cannot be manually specified", `
332 rust_binary {
333 name: "foo",
334 srcs: [
335 "foo.rs",
336 ],
337 ld_flags: ["-Wl,-lbar"],
338 }
339 `)
340}