blob: 32eddc161ce0f96c583663fea2216ee536eeb450 [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 "io/ioutil"
19 "os"
Ivan Lozanoc0083612019-09-03 13:49:39 -070020 "runtime"
Ivan Lozanob9040d62019-09-24 13:23:50 -070021 "strings"
Ivan Lozanoffee3342019-08-27 12:03:00 -070022 "testing"
23
24 "android/soong/android"
Colin Crossf28329d2020-02-15 11:00:10 -080025 "android/soong/cc"
Ivan Lozanoffee3342019-08-27 12:03:00 -070026)
27
28var (
29 buildDir string
30)
31
32func setUp() {
33 var err error
34 buildDir, err = ioutil.TempDir("", "soong_rust_test")
35 if err != nil {
36 panic(err)
37 }
38}
39
40func tearDown() {
41 os.RemoveAll(buildDir)
42}
43
44func TestMain(m *testing.M) {
45 run := func() int {
46 setUp()
47 defer tearDown()
48
49 return m.Run()
50 }
51
52 os.Exit(run())
53}
54
Colin Cross98be1bb2019-12-13 20:41:13 -080055func testConfig(bp string) android.Config {
56 bp = bp + GatherRequiredDepsForTest()
57
58 fs := map[string][]byte{
59 "foo.rs": nil,
60 "src/bar.rs": nil,
61 "liby.so": nil,
62 "libz.so": nil,
63 }
64
Colin Crossf28329d2020-02-15 11:00:10 -080065 cc.GatherRequiredFilesForTest(fs)
66
Colin Cross98be1bb2019-12-13 20:41:13 -080067 return android.TestArchConfig(buildDir, nil, bp, fs)
68}
69
Ivan Lozanoffee3342019-08-27 12:03:00 -070070func testRust(t *testing.T, bp string) *android.TestContext {
Ivan Lozanoc0083612019-09-03 13:49:39 -070071 // TODO (b/140435149)
72 if runtime.GOOS != "linux" {
73 t.Skip("Only the Linux toolchain is supported for Rust")
74 }
75
Ivan Lozanoffee3342019-08-27 12:03:00 -070076 t.Helper()
Colin Cross98be1bb2019-12-13 20:41:13 -080077 config := testConfig(bp)
Ivan Lozanoffee3342019-08-27 12:03:00 -070078
79 t.Helper()
Colin Cross98be1bb2019-12-13 20:41:13 -080080 ctx := CreateTestContext()
81 ctx.Register(config)
Ivan Lozanoffee3342019-08-27 12:03:00 -070082
83 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
84 android.FailIfErrored(t, errs)
85 _, errs = ctx.PrepareBuildActions(config)
86 android.FailIfErrored(t, errs)
87
88 return ctx
89}
90
91func testRustError(t *testing.T, pattern string, bp string) {
Ivan Lozanoc0083612019-09-03 13:49:39 -070092 // TODO (b/140435149)
93 if runtime.GOOS != "linux" {
94 t.Skip("Only the Linux toolchain is supported for Rust")
95 }
96
Ivan Lozanoffee3342019-08-27 12:03:00 -070097 t.Helper()
Colin Cross98be1bb2019-12-13 20:41:13 -080098 config := testConfig(bp)
Ivan Lozanoffee3342019-08-27 12:03:00 -070099
Colin Cross98be1bb2019-12-13 20:41:13 -0800100 ctx := CreateTestContext()
101 ctx.Register(config)
Ivan Lozanoffee3342019-08-27 12:03:00 -0700102
103 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
104 if len(errs) > 0 {
105 android.FailIfNoMatchingErrors(t, pattern, errs)
106 return
107 }
108
109 _, errs = ctx.PrepareBuildActions(config)
110 if len(errs) > 0 {
111 android.FailIfNoMatchingErrors(t, pattern, errs)
112 return
113 }
114
115 t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
116}
117
118// Test that we can extract the lib name from a lib path.
119func TestLibNameFromFilePath(t *testing.T) {
Ivan Lozanod648c432020-02-06 12:05:10 -0500120 libBarPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/libbar.so.so")
Ivan Lozano52767be2019-10-18 14:49:46 -0700121 libLibPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/liblib.dylib.so")
Ivan Lozanoffee3342019-08-27 12:03:00 -0700122
Ivan Lozano52767be2019-10-18 14:49:46 -0700123 libBarName := libNameFromFilePath(libBarPath)
124 libLibName := libNameFromFilePath(libLibPath)
125
Ivan Lozanod648c432020-02-06 12:05:10 -0500126 expectedResult := "bar.so"
Ivan Lozano52767be2019-10-18 14:49:46 -0700127 if libBarName != expectedResult {
128 t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libBarName)
129 }
130
131 expectedResult = "lib.dylib"
132 if libLibName != expectedResult {
133 t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libLibPath)
Ivan Lozanoffee3342019-08-27 12:03:00 -0700134 }
135}
136
137// Test that we can extract the link path from a lib path.
138func TestLinkPathFromFilePath(t *testing.T) {
139 barPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/libbar.so")
140 libName := linkPathFromFilePath(barPath)
141 expectedResult := "out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/"
142
143 if libName != expectedResult {
144 t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libName)
145 }
146}
147
Ivan Lozanoffee3342019-08-27 12:03:00 -0700148// Test to make sure dependencies are being picked up correctly.
149func TestDepsTracking(t *testing.T) {
150 ctx := testRust(t, `
Ivan Lozano52767be2019-10-18 14:49:46 -0700151 rust_library_host_static {
152 name: "libstatic",
153 srcs: ["foo.rs"],
Ivan Lozanoad8b18b2019-10-31 19:38:29 -0700154 crate_name: "static",
Ivan Lozano52767be2019-10-18 14:49:46 -0700155 }
156 rust_library_host_shared {
157 name: "libshared",
158 srcs: ["foo.rs"],
Ivan Lozanoad8b18b2019-10-31 19:38:29 -0700159 crate_name: "shared",
Ivan Lozano52767be2019-10-18 14:49:46 -0700160 }
Ivan Lozanoffee3342019-08-27 12:03:00 -0700161 rust_library_host_dylib {
Ivan Lozano52767be2019-10-18 14:49:46 -0700162 name: "libdylib",
Ivan Lozanoffee3342019-08-27 12:03:00 -0700163 srcs: ["foo.rs"],
Ivan Lozanoad8b18b2019-10-31 19:38:29 -0700164 crate_name: "dylib",
Ivan Lozanoffee3342019-08-27 12:03:00 -0700165 }
166 rust_library_host_rlib {
Ivan Lozano52767be2019-10-18 14:49:46 -0700167 name: "librlib",
Ivan Lozanoffee3342019-08-27 12:03:00 -0700168 srcs: ["foo.rs"],
Ivan Lozanoad8b18b2019-10-31 19:38:29 -0700169 crate_name: "rlib",
Ivan Lozanoffee3342019-08-27 12:03:00 -0700170 }
171 rust_proc_macro {
172 name: "libpm",
173 srcs: ["foo.rs"],
Ivan Lozanoad8b18b2019-10-31 19:38:29 -0700174 crate_name: "pm",
Ivan Lozanoffee3342019-08-27 12:03:00 -0700175 }
176 rust_binary_host {
177 name: "fizz-buzz",
Ivan Lozano52767be2019-10-18 14:49:46 -0700178 dylibs: ["libdylib"],
179 rlibs: ["librlib"],
Ivan Lozanoffee3342019-08-27 12:03:00 -0700180 proc_macros: ["libpm"],
Ivan Lozano52767be2019-10-18 14:49:46 -0700181 static_libs: ["libstatic"],
182 shared_libs: ["libshared"],
Ivan Lozanoffee3342019-08-27 12:03:00 -0700183 srcs: ["foo.rs"],
184 }
185 `)
186 module := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
187
188 // Since dependencies are added to AndroidMk* properties, we can check these to see if they've been picked up.
Ivan Lozano52767be2019-10-18 14:49:46 -0700189 if !android.InList("libdylib", module.Properties.AndroidMkDylibs) {
Ivan Lozanoffee3342019-08-27 12:03:00 -0700190 t.Errorf("Dylib dependency not detected (dependency missing from AndroidMkDylibs)")
191 }
192
Ivan Lozano52767be2019-10-18 14:49:46 -0700193 if !android.InList("librlib", module.Properties.AndroidMkRlibs) {
Ivan Lozanoffee3342019-08-27 12:03:00 -0700194 t.Errorf("Rlib dependency not detected (dependency missing from AndroidMkRlibs)")
195 }
196
197 if !android.InList("libpm", module.Properties.AndroidMkProcMacroLibs) {
198 t.Errorf("Proc_macro dependency not detected (dependency missing from AndroidMkProcMacroLibs)")
199 }
200
Ivan Lozano52767be2019-10-18 14:49:46 -0700201 if !android.InList("libshared", module.Properties.AndroidMkSharedLibs) {
202 t.Errorf("Shared library dependency not detected (dependency missing from AndroidMkSharedLibs)")
203 }
204
205 if !android.InList("libstatic", module.Properties.AndroidMkStaticLibs) {
206 t.Errorf("Static library dependency not detected (dependency missing from AndroidMkStaticLibs)")
207 }
Ivan Lozanoffee3342019-08-27 12:03:00 -0700208}
Ivan Lozanob9040d62019-09-24 13:23:50 -0700209
210// Test to make sure proc_macros use host variants when building device modules.
211func TestProcMacroDeviceDeps(t *testing.T) {
212 ctx := testRust(t, `
213 rust_library_host_rlib {
214 name: "libbar",
215 srcs: ["foo.rs"],
Ivan Lozanoad8b18b2019-10-31 19:38:29 -0700216 crate_name: "bar",
Ivan Lozanob9040d62019-09-24 13:23:50 -0700217 }
218 rust_proc_macro {
219 name: "libpm",
220 rlibs: ["libbar"],
221 srcs: ["foo.rs"],
Ivan Lozanoad8b18b2019-10-31 19:38:29 -0700222 crate_name: "pm",
Ivan Lozanob9040d62019-09-24 13:23:50 -0700223 }
224 rust_binary {
225 name: "fizz-buzz",
226 proc_macros: ["libpm"],
227 srcs: ["foo.rs"],
228 }
229 `)
230 rustc := ctx.ModuleForTests("libpm", "linux_glibc_x86_64").Rule("rustc")
231
232 if !strings.Contains(rustc.Args["libFlags"], "libbar/linux_glibc_x86_64") {
233 t.Errorf("Proc_macro is not using host variant of dependent modules.")
234 }
235}
Matthew Maurer99020b02019-10-31 10:44:40 -0700236
237// Test that no_stdlibs suppresses dependencies on rust standard libraries
238func TestNoStdlibs(t *testing.T) {
239 ctx := testRust(t, `
240 rust_binary {
241 name: "fizz-buzz",
242 srcs: ["foo.rs"],
Ivan Lozano9d1df102020-04-28 10:10:23 -0400243 no_stdlibs: true,
Matthew Maurer99020b02019-10-31 10:44:40 -0700244 }`)
Colin Cross7113d202019-11-20 16:39:12 -0800245 module := ctx.ModuleForTests("fizz-buzz", "android_arm64_armv8-a").Module().(*Module)
Matthew Maurer99020b02019-10-31 10:44:40 -0700246
247 if android.InList("libstd", module.Properties.AndroidMkDylibs) {
248 t.Errorf("no_stdlibs did not suppress dependency on libstd")
249 }
250}
Ivan Lozano9d1df102020-04-28 10:10:23 -0400251
252// Test that libraries provide both 32-bit and 64-bit variants.
253func TestMultilib(t *testing.T) {
254 ctx := testRust(t, `
255 rust_library_rlib {
256 name: "libfoo",
257 srcs: ["foo.rs"],
258 crate_name: "foo",
259 }`)
260
261 _ = ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib")
262 _ = ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_rlib")
263}