2019-08-28 03:03:00 +08:00
|
|
|
// Copyright 2019 The Android Open Source Project
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
package rust
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
2019-09-04 04:49:39 +08:00
|
|
|
"runtime"
|
2019-09-25 04:23:50 +08:00
|
|
|
"strings"
|
2019-08-28 03:03:00 +08:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"android/soong/android"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
buildDir string
|
|
|
|
)
|
|
|
|
|
|
|
|
func setUp() {
|
|
|
|
var err error
|
|
|
|
buildDir, err = ioutil.TempDir("", "soong_rust_test")
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func tearDown() {
|
|
|
|
os.RemoveAll(buildDir)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMain(m *testing.M) {
|
|
|
|
run := func() int {
|
|
|
|
setUp()
|
|
|
|
defer tearDown()
|
|
|
|
|
|
|
|
return m.Run()
|
|
|
|
}
|
|
|
|
|
|
|
|
os.Exit(run())
|
|
|
|
}
|
|
|
|
|
2019-12-14 12:41:13 +08:00
|
|
|
func testConfig(bp string) android.Config {
|
|
|
|
bp = bp + GatherRequiredDepsForTest()
|
|
|
|
|
|
|
|
fs := map[string][]byte{
|
|
|
|
"foo.rs": nil,
|
|
|
|
"src/bar.rs": nil,
|
|
|
|
"liby.so": nil,
|
|
|
|
"libz.so": nil,
|
|
|
|
}
|
|
|
|
|
|
|
|
return android.TestArchConfig(buildDir, nil, bp, fs)
|
|
|
|
}
|
|
|
|
|
2019-08-28 03:03:00 +08:00
|
|
|
func testRust(t *testing.T, bp string) *android.TestContext {
|
2019-09-04 04:49:39 +08:00
|
|
|
// TODO (b/140435149)
|
|
|
|
if runtime.GOOS != "linux" {
|
|
|
|
t.Skip("Only the Linux toolchain is supported for Rust")
|
|
|
|
}
|
|
|
|
|
2019-08-28 03:03:00 +08:00
|
|
|
t.Helper()
|
2019-12-14 12:41:13 +08:00
|
|
|
config := testConfig(bp)
|
2019-08-28 03:03:00 +08:00
|
|
|
|
|
|
|
t.Helper()
|
2019-12-14 12:41:13 +08:00
|
|
|
ctx := CreateTestContext()
|
|
|
|
ctx.Register(config)
|
2019-08-28 03:03:00 +08:00
|
|
|
|
|
|
|
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
|
|
|
|
android.FailIfErrored(t, errs)
|
|
|
|
_, errs = ctx.PrepareBuildActions(config)
|
|
|
|
android.FailIfErrored(t, errs)
|
|
|
|
|
|
|
|
return ctx
|
|
|
|
}
|
|
|
|
|
|
|
|
func testRustError(t *testing.T, pattern string, bp string) {
|
2019-09-04 04:49:39 +08:00
|
|
|
// TODO (b/140435149)
|
|
|
|
if runtime.GOOS != "linux" {
|
|
|
|
t.Skip("Only the Linux toolchain is supported for Rust")
|
|
|
|
}
|
|
|
|
|
2019-08-28 03:03:00 +08:00
|
|
|
t.Helper()
|
2019-12-14 12:41:13 +08:00
|
|
|
config := testConfig(bp)
|
2019-08-28 03:03:00 +08:00
|
|
|
|
2019-12-14 12:41:13 +08:00
|
|
|
ctx := CreateTestContext()
|
|
|
|
ctx.Register(config)
|
2019-08-28 03:03:00 +08:00
|
|
|
|
|
|
|
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
|
|
|
|
if len(errs) > 0 {
|
|
|
|
android.FailIfNoMatchingErrors(t, pattern, errs)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
_, errs = ctx.PrepareBuildActions(config)
|
|
|
|
if len(errs) > 0 {
|
|
|
|
android.FailIfNoMatchingErrors(t, pattern, errs)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test that we can extract the lib name from a lib path.
|
|
|
|
func TestLibNameFromFilePath(t *testing.T) {
|
2019-10-19 05:49:46 +08:00
|
|
|
libBarPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/libbar.so")
|
|
|
|
libLibPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/liblib.dylib.so")
|
|
|
|
|
|
|
|
libBarName := libNameFromFilePath(libBarPath)
|
|
|
|
libLibName := libNameFromFilePath(libLibPath)
|
|
|
|
|
2019-08-28 03:03:00 +08:00
|
|
|
expectedResult := "bar"
|
2019-10-19 05:49:46 +08:00
|
|
|
if libBarName != expectedResult {
|
|
|
|
t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libBarName)
|
|
|
|
}
|
2019-08-28 03:03:00 +08:00
|
|
|
|
2019-10-19 05:49:46 +08:00
|
|
|
expectedResult = "lib.dylib"
|
|
|
|
if libLibName != expectedResult {
|
|
|
|
t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libLibPath)
|
2019-08-28 03:03:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test that we can extract the link path from a lib path.
|
|
|
|
func TestLinkPathFromFilePath(t *testing.T) {
|
|
|
|
barPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/libbar.so")
|
|
|
|
libName := linkPathFromFilePath(barPath)
|
|
|
|
expectedResult := "out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/"
|
|
|
|
|
|
|
|
if libName != expectedResult {
|
|
|
|
t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libName)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test to make sure dependencies are being picked up correctly.
|
|
|
|
func TestDepsTracking(t *testing.T) {
|
|
|
|
ctx := testRust(t, `
|
2019-10-19 05:49:46 +08:00
|
|
|
rust_library_host_static {
|
|
|
|
name: "libstatic",
|
|
|
|
srcs: ["foo.rs"],
|
2019-11-01 10:38:29 +08:00
|
|
|
crate_name: "static",
|
2019-10-19 05:49:46 +08:00
|
|
|
}
|
|
|
|
rust_library_host_shared {
|
|
|
|
name: "libshared",
|
|
|
|
srcs: ["foo.rs"],
|
2019-11-01 10:38:29 +08:00
|
|
|
crate_name: "shared",
|
2019-10-19 05:49:46 +08:00
|
|
|
}
|
2019-08-28 03:03:00 +08:00
|
|
|
rust_library_host_dylib {
|
2019-10-19 05:49:46 +08:00
|
|
|
name: "libdylib",
|
2019-08-28 03:03:00 +08:00
|
|
|
srcs: ["foo.rs"],
|
2019-11-01 10:38:29 +08:00
|
|
|
crate_name: "dylib",
|
2019-08-28 03:03:00 +08:00
|
|
|
}
|
|
|
|
rust_library_host_rlib {
|
2019-10-19 05:49:46 +08:00
|
|
|
name: "librlib",
|
2019-08-28 03:03:00 +08:00
|
|
|
srcs: ["foo.rs"],
|
2019-11-01 10:38:29 +08:00
|
|
|
crate_name: "rlib",
|
2019-08-28 03:03:00 +08:00
|
|
|
}
|
|
|
|
rust_proc_macro {
|
|
|
|
name: "libpm",
|
|
|
|
srcs: ["foo.rs"],
|
2019-11-01 10:38:29 +08:00
|
|
|
crate_name: "pm",
|
2019-08-28 03:03:00 +08:00
|
|
|
}
|
|
|
|
rust_binary_host {
|
|
|
|
name: "fizz-buzz",
|
2019-10-19 05:49:46 +08:00
|
|
|
dylibs: ["libdylib"],
|
|
|
|
rlibs: ["librlib"],
|
2019-08-28 03:03:00 +08:00
|
|
|
proc_macros: ["libpm"],
|
2019-10-19 05:49:46 +08:00
|
|
|
static_libs: ["libstatic"],
|
|
|
|
shared_libs: ["libshared"],
|
2019-08-28 03:03:00 +08:00
|
|
|
srcs: ["foo.rs"],
|
|
|
|
}
|
|
|
|
`)
|
|
|
|
module := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
|
|
|
|
|
|
|
|
// Since dependencies are added to AndroidMk* properties, we can check these to see if they've been picked up.
|
2019-10-19 05:49:46 +08:00
|
|
|
if !android.InList("libdylib", module.Properties.AndroidMkDylibs) {
|
2019-08-28 03:03:00 +08:00
|
|
|
t.Errorf("Dylib dependency not detected (dependency missing from AndroidMkDylibs)")
|
|
|
|
}
|
|
|
|
|
2019-10-19 05:49:46 +08:00
|
|
|
if !android.InList("librlib", module.Properties.AndroidMkRlibs) {
|
2019-08-28 03:03:00 +08:00
|
|
|
t.Errorf("Rlib dependency not detected (dependency missing from AndroidMkRlibs)")
|
|
|
|
}
|
|
|
|
|
|
|
|
if !android.InList("libpm", module.Properties.AndroidMkProcMacroLibs) {
|
|
|
|
t.Errorf("Proc_macro dependency not detected (dependency missing from AndroidMkProcMacroLibs)")
|
|
|
|
}
|
|
|
|
|
2019-10-19 05:49:46 +08:00
|
|
|
if !android.InList("libshared", module.Properties.AndroidMkSharedLibs) {
|
|
|
|
t.Errorf("Shared library dependency not detected (dependency missing from AndroidMkSharedLibs)")
|
|
|
|
}
|
|
|
|
|
|
|
|
if !android.InList("libstatic", module.Properties.AndroidMkStaticLibs) {
|
|
|
|
t.Errorf("Static library dependency not detected (dependency missing from AndroidMkStaticLibs)")
|
|
|
|
}
|
2019-08-28 03:03:00 +08:00
|
|
|
}
|
2019-09-25 04:23:50 +08:00
|
|
|
|
|
|
|
// Test to make sure proc_macros use host variants when building device modules.
|
|
|
|
func TestProcMacroDeviceDeps(t *testing.T) {
|
|
|
|
ctx := testRust(t, `
|
|
|
|
rust_library_host_rlib {
|
|
|
|
name: "libbar",
|
|
|
|
srcs: ["foo.rs"],
|
2019-11-01 10:38:29 +08:00
|
|
|
crate_name: "bar",
|
2019-09-25 04:23:50 +08:00
|
|
|
}
|
2019-11-01 01:44:40 +08:00
|
|
|
// Make a dummy libstd to let resolution go through
|
|
|
|
rust_library_dylib {
|
|
|
|
name: "libstd",
|
|
|
|
crate_name: "std",
|
|
|
|
srcs: ["foo.rs"],
|
|
|
|
no_stdlibs: true,
|
|
|
|
}
|
|
|
|
rust_library_dylib {
|
|
|
|
name: "libterm",
|
|
|
|
crate_name: "term",
|
|
|
|
srcs: ["foo.rs"],
|
|
|
|
no_stdlibs: true,
|
|
|
|
}
|
|
|
|
rust_library_dylib {
|
|
|
|
name: "libtest",
|
|
|
|
crate_name: "test",
|
|
|
|
srcs: ["foo.rs"],
|
|
|
|
no_stdlibs: true,
|
|
|
|
}
|
2019-09-25 04:23:50 +08:00
|
|
|
rust_proc_macro {
|
|
|
|
name: "libpm",
|
|
|
|
rlibs: ["libbar"],
|
|
|
|
srcs: ["foo.rs"],
|
2019-11-01 10:38:29 +08:00
|
|
|
crate_name: "pm",
|
2019-09-25 04:23:50 +08:00
|
|
|
}
|
|
|
|
rust_binary {
|
|
|
|
name: "fizz-buzz",
|
|
|
|
proc_macros: ["libpm"],
|
|
|
|
srcs: ["foo.rs"],
|
|
|
|
}
|
|
|
|
`)
|
|
|
|
rustc := ctx.ModuleForTests("libpm", "linux_glibc_x86_64").Rule("rustc")
|
|
|
|
|
|
|
|
if !strings.Contains(rustc.Args["libFlags"], "libbar/linux_glibc_x86_64") {
|
|
|
|
t.Errorf("Proc_macro is not using host variant of dependent modules.")
|
|
|
|
}
|
|
|
|
}
|
2019-11-01 01:44:40 +08:00
|
|
|
|
|
|
|
// Test that no_stdlibs suppresses dependencies on rust standard libraries
|
|
|
|
func TestNoStdlibs(t *testing.T) {
|
|
|
|
ctx := testRust(t, `
|
|
|
|
rust_binary {
|
|
|
|
name: "fizz-buzz",
|
|
|
|
srcs: ["foo.rs"],
|
|
|
|
no_stdlibs: true,
|
|
|
|
}`)
|
2019-11-21 08:39:12 +08:00
|
|
|
module := ctx.ModuleForTests("fizz-buzz", "android_arm64_armv8-a").Module().(*Module)
|
2019-11-01 01:44:40 +08:00
|
|
|
|
|
|
|
if android.InList("libstd", module.Properties.AndroidMkDylibs) {
|
|
|
|
t.Errorf("no_stdlibs did not suppress dependency on libstd")
|
|
|
|
}
|
|
|
|
}
|