blob: 3be9ee7b937de20e24c3d660aea0020cd6cb0a53 [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"
25)
26
27var (
28 buildDir string
29)
30
31func setUp() {
32 var err error
33 buildDir, err = ioutil.TempDir("", "soong_rust_test")
34 if err != nil {
35 panic(err)
36 }
37}
38
39func tearDown() {
40 os.RemoveAll(buildDir)
41}
42
43func TestMain(m *testing.M) {
44 run := func() int {
45 setUp()
46 defer tearDown()
47
48 return m.Run()
49 }
50
51 os.Exit(run())
52}
53
Colin Cross98be1bb2019-12-13 20:41:13 -080054func testConfig(bp string) android.Config {
55 bp = bp + GatherRequiredDepsForTest()
56
57 fs := map[string][]byte{
58 "foo.rs": nil,
59 "src/bar.rs": nil,
60 "liby.so": nil,
61 "libz.so": nil,
62 }
63
64 return android.TestArchConfig(buildDir, nil, bp, fs)
65}
66
Ivan Lozanoffee3342019-08-27 12:03:00 -070067func testRust(t *testing.T, bp string) *android.TestContext {
Ivan Lozanoc0083612019-09-03 13:49:39 -070068 // TODO (b/140435149)
69 if runtime.GOOS != "linux" {
70 t.Skip("Only the Linux toolchain is supported for Rust")
71 }
72
Ivan Lozanoffee3342019-08-27 12:03:00 -070073 t.Helper()
Colin Cross98be1bb2019-12-13 20:41:13 -080074 config := testConfig(bp)
Ivan Lozanoffee3342019-08-27 12:03:00 -070075
76 t.Helper()
Colin Cross98be1bb2019-12-13 20:41:13 -080077 ctx := CreateTestContext()
78 ctx.Register(config)
Ivan Lozanoffee3342019-08-27 12:03:00 -070079
80 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
81 android.FailIfErrored(t, errs)
82 _, errs = ctx.PrepareBuildActions(config)
83 android.FailIfErrored(t, errs)
84
85 return ctx
86}
87
88func testRustError(t *testing.T, pattern string, bp string) {
Ivan Lozanoc0083612019-09-03 13:49:39 -070089 // TODO (b/140435149)
90 if runtime.GOOS != "linux" {
91 t.Skip("Only the Linux toolchain is supported for Rust")
92 }
93
Ivan Lozanoffee3342019-08-27 12:03:00 -070094 t.Helper()
Colin Cross98be1bb2019-12-13 20:41:13 -080095 config := testConfig(bp)
Ivan Lozanoffee3342019-08-27 12:03:00 -070096
Colin Cross98be1bb2019-12-13 20:41:13 -080097 ctx := CreateTestContext()
98 ctx.Register(config)
Ivan Lozanoffee3342019-08-27 12:03:00 -070099
100 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
101 if len(errs) > 0 {
102 android.FailIfNoMatchingErrors(t, pattern, errs)
103 return
104 }
105
106 _, errs = ctx.PrepareBuildActions(config)
107 if len(errs) > 0 {
108 android.FailIfNoMatchingErrors(t, pattern, errs)
109 return
110 }
111
112 t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
113}
114
115// Test that we can extract the lib name from a lib path.
116func TestLibNameFromFilePath(t *testing.T) {
Ivan Lozano52767be2019-10-18 14:49:46 -0700117 libBarPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/libbar.so")
118 libLibPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/liblib.dylib.so")
Ivan Lozanoffee3342019-08-27 12:03:00 -0700119
Ivan Lozano52767be2019-10-18 14:49:46 -0700120 libBarName := libNameFromFilePath(libBarPath)
121 libLibName := libNameFromFilePath(libLibPath)
122
123 expectedResult := "bar"
124 if libBarName != expectedResult {
125 t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libBarName)
126 }
127
128 expectedResult = "lib.dylib"
129 if libLibName != expectedResult {
130 t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libLibPath)
Ivan Lozanoffee3342019-08-27 12:03:00 -0700131 }
132}
133
134// Test that we can extract the link path from a lib path.
135func TestLinkPathFromFilePath(t *testing.T) {
136 barPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/libbar.so")
137 libName := linkPathFromFilePath(barPath)
138 expectedResult := "out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/"
139
140 if libName != expectedResult {
141 t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libName)
142 }
143}
144
Ivan Lozanoffee3342019-08-27 12:03:00 -0700145// Test to make sure dependencies are being picked up correctly.
146func TestDepsTracking(t *testing.T) {
147 ctx := testRust(t, `
Ivan Lozano52767be2019-10-18 14:49:46 -0700148 rust_library_host_static {
149 name: "libstatic",
150 srcs: ["foo.rs"],
Ivan Lozanoad8b18b2019-10-31 19:38:29 -0700151 crate_name: "static",
Ivan Lozano52767be2019-10-18 14:49:46 -0700152 }
153 rust_library_host_shared {
154 name: "libshared",
155 srcs: ["foo.rs"],
Ivan Lozanoad8b18b2019-10-31 19:38:29 -0700156 crate_name: "shared",
Ivan Lozano52767be2019-10-18 14:49:46 -0700157 }
Ivan Lozanoffee3342019-08-27 12:03:00 -0700158 rust_library_host_dylib {
Ivan Lozano52767be2019-10-18 14:49:46 -0700159 name: "libdylib",
Ivan Lozanoffee3342019-08-27 12:03:00 -0700160 srcs: ["foo.rs"],
Ivan Lozanoad8b18b2019-10-31 19:38:29 -0700161 crate_name: "dylib",
Ivan Lozanoffee3342019-08-27 12:03:00 -0700162 }
163 rust_library_host_rlib {
Ivan Lozano52767be2019-10-18 14:49:46 -0700164 name: "librlib",
Ivan Lozanoffee3342019-08-27 12:03:00 -0700165 srcs: ["foo.rs"],
Ivan Lozanoad8b18b2019-10-31 19:38:29 -0700166 crate_name: "rlib",
Ivan Lozanoffee3342019-08-27 12:03:00 -0700167 }
168 rust_proc_macro {
169 name: "libpm",
170 srcs: ["foo.rs"],
Ivan Lozanoad8b18b2019-10-31 19:38:29 -0700171 crate_name: "pm",
Ivan Lozanoffee3342019-08-27 12:03:00 -0700172 }
173 rust_binary_host {
174 name: "fizz-buzz",
Ivan Lozano52767be2019-10-18 14:49:46 -0700175 dylibs: ["libdylib"],
176 rlibs: ["librlib"],
Ivan Lozanoffee3342019-08-27 12:03:00 -0700177 proc_macros: ["libpm"],
Ivan Lozano52767be2019-10-18 14:49:46 -0700178 static_libs: ["libstatic"],
179 shared_libs: ["libshared"],
Ivan Lozanoffee3342019-08-27 12:03:00 -0700180 srcs: ["foo.rs"],
181 }
182 `)
183 module := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
184
185 // 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 -0700186 if !android.InList("libdylib", module.Properties.AndroidMkDylibs) {
Ivan Lozanoffee3342019-08-27 12:03:00 -0700187 t.Errorf("Dylib dependency not detected (dependency missing from AndroidMkDylibs)")
188 }
189
Ivan Lozano52767be2019-10-18 14:49:46 -0700190 if !android.InList("librlib", module.Properties.AndroidMkRlibs) {
Ivan Lozanoffee3342019-08-27 12:03:00 -0700191 t.Errorf("Rlib dependency not detected (dependency missing from AndroidMkRlibs)")
192 }
193
194 if !android.InList("libpm", module.Properties.AndroidMkProcMacroLibs) {
195 t.Errorf("Proc_macro dependency not detected (dependency missing from AndroidMkProcMacroLibs)")
196 }
197
Ivan Lozano52767be2019-10-18 14:49:46 -0700198 if !android.InList("libshared", module.Properties.AndroidMkSharedLibs) {
199 t.Errorf("Shared library dependency not detected (dependency missing from AndroidMkSharedLibs)")
200 }
201
202 if !android.InList("libstatic", module.Properties.AndroidMkStaticLibs) {
203 t.Errorf("Static library dependency not detected (dependency missing from AndroidMkStaticLibs)")
204 }
Ivan Lozanoffee3342019-08-27 12:03:00 -0700205}
Ivan Lozanob9040d62019-09-24 13:23:50 -0700206
207// Test to make sure proc_macros use host variants when building device modules.
208func TestProcMacroDeviceDeps(t *testing.T) {
209 ctx := testRust(t, `
210 rust_library_host_rlib {
211 name: "libbar",
212 srcs: ["foo.rs"],
Ivan Lozanoad8b18b2019-10-31 19:38:29 -0700213 crate_name: "bar",
Ivan Lozanob9040d62019-09-24 13:23:50 -0700214 }
Matthew Maurer99020b02019-10-31 10:44:40 -0700215 // Make a dummy libstd to let resolution go through
216 rust_library_dylib {
217 name: "libstd",
218 crate_name: "std",
219 srcs: ["foo.rs"],
220 no_stdlibs: true,
221 }
222 rust_library_dylib {
223 name: "libterm",
224 crate_name: "term",
225 srcs: ["foo.rs"],
226 no_stdlibs: true,
227 }
228 rust_library_dylib {
229 name: "libtest",
230 crate_name: "test",
231 srcs: ["foo.rs"],
232 no_stdlibs: true,
233 }
Ivan Lozanob9040d62019-09-24 13:23:50 -0700234 rust_proc_macro {
235 name: "libpm",
236 rlibs: ["libbar"],
237 srcs: ["foo.rs"],
Ivan Lozanoad8b18b2019-10-31 19:38:29 -0700238 crate_name: "pm",
Ivan Lozanob9040d62019-09-24 13:23:50 -0700239 }
240 rust_binary {
241 name: "fizz-buzz",
242 proc_macros: ["libpm"],
243 srcs: ["foo.rs"],
244 }
245 `)
246 rustc := ctx.ModuleForTests("libpm", "linux_glibc_x86_64").Rule("rustc")
247
248 if !strings.Contains(rustc.Args["libFlags"], "libbar/linux_glibc_x86_64") {
249 t.Errorf("Proc_macro is not using host variant of dependent modules.")
250 }
251}
Matthew Maurer99020b02019-10-31 10:44:40 -0700252
253// Test that no_stdlibs suppresses dependencies on rust standard libraries
254func TestNoStdlibs(t *testing.T) {
255 ctx := testRust(t, `
256 rust_binary {
257 name: "fizz-buzz",
258 srcs: ["foo.rs"],
259 no_stdlibs: true,
260 }`)
Colin Cross7113d202019-11-20 16:39:12 -0800261 module := ctx.ModuleForTests("fizz-buzz", "android_arm64_armv8-a").Module().(*Module)
Matthew Maurer99020b02019-10-31 10:44:40 -0700262
263 if android.InList("libstd", module.Properties.AndroidMkDylibs) {
264 t.Errorf("no_stdlibs did not suppress dependency on libstd")
265 }
266}