Adds stubs_sources property to sdk and unzips the droidstubs srcjar into the snapshot directory. Adds an UnzipToSnapshot method to the SnapshotBuilder which creates a rule that uses zip2zip to repackage the supplied zip content into a temporary zip file that matches what the required snapshot structure. e.g. if the supplied zip contains foo/Foo.java and that needs to be in the snapshot directory java/foo/stubs then it will create a zip that contains java/foo/stubs/foo/Foo.java. The temporary zip that is the output of that rule is added to the zipsToMerge field for merging later. If the zipsToMerge is empty then the snapshot zip is created as before. Otherwise, a temporary zip file is created. That is then merged with the other zip files in zipsToMerge to create the final snapshot zip. Adds prebuilt_stubs_sources for use by the generated .bp module. Bug: 143678475 Test: added conscrypt sdk module and attempted to build it Change-Id: Ie274263af3a08e36a73c61c0dbf0c341fd6967e2
563 lines
16 KiB
Go
563 lines
16 KiB
Go
// Copyright 2019 Google Inc. All rights reserved.
|
|
//
|
|
// 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 sdk
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"android/soong/android"
|
|
"android/soong/apex"
|
|
"android/soong/cc"
|
|
"android/soong/java"
|
|
)
|
|
|
|
func testSdkContext(t *testing.T, bp string) (*android.TestContext, android.Config) {
|
|
config := android.TestArchConfig(buildDir, nil)
|
|
ctx := android.NewTestArchContext()
|
|
|
|
// from android package
|
|
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
|
|
ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
|
|
ctx.BottomUp("prebuilts", android.PrebuiltMutator).Parallel()
|
|
})
|
|
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
|
ctx.TopDown("prebuilt_select", android.PrebuiltSelectModuleMutator).Parallel()
|
|
ctx.BottomUp("prebuilt_postdeps", android.PrebuiltPostDepsMutator).Parallel()
|
|
})
|
|
|
|
// from java package
|
|
ctx.RegisterModuleType("android_app_certificate", android.ModuleFactoryAdaptor(java.AndroidAppCertificateFactory))
|
|
ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(java.LibraryFactory))
|
|
ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(java.ImportFactory))
|
|
ctx.RegisterModuleType("droidstubs", android.ModuleFactoryAdaptor(java.DroidstubsFactory))
|
|
ctx.RegisterModuleType("prebuilt_stubs_sources", android.ModuleFactoryAdaptor(java.PrebuiltStubsSourcesFactory))
|
|
|
|
// from cc package
|
|
ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
|
|
ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(cc.LibrarySharedFactory))
|
|
ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
|
|
ctx.RegisterModuleType("cc_prebuilt_library_shared", android.ModuleFactoryAdaptor(cc.PrebuiltSharedLibraryFactory))
|
|
ctx.RegisterModuleType("cc_prebuilt_library_static", android.ModuleFactoryAdaptor(cc.PrebuiltStaticLibraryFactory))
|
|
ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(cc.LlndkLibraryFactory))
|
|
ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
|
|
ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
|
ctx.BottomUp("image", cc.ImageMutator).Parallel()
|
|
ctx.BottomUp("link", cc.LinkageMutator).Parallel()
|
|
ctx.BottomUp("vndk", cc.VndkMutator).Parallel()
|
|
ctx.BottomUp("test_per_src", cc.TestPerSrcMutator).Parallel()
|
|
ctx.BottomUp("version", cc.VersionMutator).Parallel()
|
|
ctx.BottomUp("begin", cc.BeginMutator).Parallel()
|
|
})
|
|
|
|
// from apex package
|
|
ctx.RegisterModuleType("apex", android.ModuleFactoryAdaptor(apex.BundleFactory))
|
|
ctx.RegisterModuleType("apex_key", android.ModuleFactoryAdaptor(apex.ApexKeyFactory))
|
|
ctx.PostDepsMutators(apex.RegisterPostDepsMutators)
|
|
|
|
// from this package
|
|
ctx.RegisterModuleType("sdk", android.ModuleFactoryAdaptor(ModuleFactory))
|
|
ctx.RegisterModuleType("sdk_snapshot", android.ModuleFactoryAdaptor(SnapshotModuleFactory))
|
|
ctx.PreDepsMutators(RegisterPreDepsMutators)
|
|
ctx.PostDepsMutators(RegisterPostDepsMutators)
|
|
|
|
ctx.Register()
|
|
|
|
bp = bp + `
|
|
apex_key {
|
|
name: "myapex.key",
|
|
public_key: "myapex.avbpubkey",
|
|
private_key: "myapex.pem",
|
|
}
|
|
|
|
android_app_certificate {
|
|
name: "myapex.cert",
|
|
certificate: "myapex",
|
|
}
|
|
` + cc.GatherRequiredDepsForTest(android.Android)
|
|
|
|
ctx.MockFileSystem(map[string][]byte{
|
|
"Android.bp": []byte(bp),
|
|
"build/make/target/product/security": nil,
|
|
"apex_manifest.json": nil,
|
|
"system/sepolicy/apex/myapex-file_contexts": nil,
|
|
"system/sepolicy/apex/myapex2-file_contexts": nil,
|
|
"myapex.avbpubkey": nil,
|
|
"myapex.pem": nil,
|
|
"myapex.x509.pem": nil,
|
|
"myapex.pk8": nil,
|
|
"Test.java": nil,
|
|
"Test.cpp": nil,
|
|
"include/Test.h": nil,
|
|
"aidl/foo/bar/Test.aidl": nil,
|
|
"libfoo.so": nil,
|
|
"stubs-sources/foo/bar/Foo.java": nil,
|
|
"foo/bar/Foo.java": nil,
|
|
})
|
|
|
|
return ctx, config
|
|
}
|
|
|
|
func testSdk(t *testing.T, bp string) (*android.TestContext, android.Config) {
|
|
ctx, config := testSdkContext(t, bp)
|
|
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
|
|
android.FailIfErrored(t, errs)
|
|
_, errs = ctx.PrepareBuildActions(config)
|
|
android.FailIfErrored(t, errs)
|
|
return ctx, config
|
|
}
|
|
|
|
func testSdkError(t *testing.T, pattern, bp string) {
|
|
t.Helper()
|
|
ctx, config := testSdkContext(t, bp)
|
|
_, 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)
|
|
}
|
|
|
|
// ensure that 'result' contains 'expected'
|
|
func ensureContains(t *testing.T, result string, expected string) {
|
|
t.Helper()
|
|
if !strings.Contains(result, expected) {
|
|
t.Errorf("%q is not found in %q", expected, result)
|
|
}
|
|
}
|
|
|
|
// ensures that 'result' does not contain 'notExpected'
|
|
func ensureNotContains(t *testing.T, result string, notExpected string) {
|
|
t.Helper()
|
|
if strings.Contains(result, notExpected) {
|
|
t.Errorf("%q is found in %q", notExpected, result)
|
|
}
|
|
}
|
|
|
|
func ensureListContains(t *testing.T, result []string, expected string) {
|
|
t.Helper()
|
|
if !android.InList(expected, result) {
|
|
t.Errorf("%q is not found in %v", expected, result)
|
|
}
|
|
}
|
|
|
|
func ensureListNotContains(t *testing.T, result []string, notExpected string) {
|
|
t.Helper()
|
|
if android.InList(notExpected, result) {
|
|
t.Errorf("%q is found in %v", notExpected, result)
|
|
}
|
|
}
|
|
|
|
func pathsToStrings(paths android.Paths) []string {
|
|
ret := []string{}
|
|
for _, p := range paths {
|
|
ret = append(ret, p.String())
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func TestBasicSdkWithJava(t *testing.T) {
|
|
ctx, _ := testSdk(t, `
|
|
sdk {
|
|
name: "mysdk",
|
|
java_libs: ["sdkmember"],
|
|
}
|
|
|
|
sdk_snapshot {
|
|
name: "mysdk@1",
|
|
java_libs: ["sdkmember_mysdk_1"],
|
|
}
|
|
|
|
sdk_snapshot {
|
|
name: "mysdk@2",
|
|
java_libs: ["sdkmember_mysdk_2"],
|
|
}
|
|
|
|
java_import {
|
|
name: "sdkmember",
|
|
prefer: false,
|
|
host_supported: true,
|
|
}
|
|
|
|
java_import {
|
|
name: "sdkmember_mysdk_1",
|
|
sdk_member_name: "sdkmember",
|
|
host_supported: true,
|
|
}
|
|
|
|
java_import {
|
|
name: "sdkmember_mysdk_2",
|
|
sdk_member_name: "sdkmember",
|
|
host_supported: true,
|
|
}
|
|
|
|
java_library {
|
|
name: "myjavalib",
|
|
srcs: ["Test.java"],
|
|
libs: ["sdkmember"],
|
|
system_modules: "none",
|
|
sdk_version: "none",
|
|
compile_dex: true,
|
|
host_supported: true,
|
|
}
|
|
|
|
apex {
|
|
name: "myapex",
|
|
java_libs: ["myjavalib"],
|
|
uses_sdks: ["mysdk@1"],
|
|
key: "myapex.key",
|
|
certificate: ":myapex.cert",
|
|
}
|
|
|
|
apex {
|
|
name: "myapex2",
|
|
java_libs: ["myjavalib"],
|
|
uses_sdks: ["mysdk@2"],
|
|
key: "myapex.key",
|
|
certificate: ":myapex.cert",
|
|
}
|
|
`)
|
|
|
|
sdkMemberV1 := ctx.ModuleForTests("sdkmember_mysdk_1", "android_common_myapex").Rule("combineJar").Output
|
|
sdkMemberV2 := ctx.ModuleForTests("sdkmember_mysdk_2", "android_common_myapex2").Rule("combineJar").Output
|
|
|
|
javalibForMyApex := ctx.ModuleForTests("myjavalib", "android_common_myapex")
|
|
javalibForMyApex2 := ctx.ModuleForTests("myjavalib", "android_common_myapex2")
|
|
|
|
// Depending on the uses_sdks value, different libs are linked
|
|
ensureListContains(t, pathsToStrings(javalibForMyApex.Rule("javac").Implicits), sdkMemberV1.String())
|
|
ensureListContains(t, pathsToStrings(javalibForMyApex2.Rule("javac").Implicits), sdkMemberV2.String())
|
|
}
|
|
|
|
func TestBasicSdkWithCc(t *testing.T) {
|
|
ctx, _ := testSdk(t, `
|
|
sdk {
|
|
name: "mysdk",
|
|
native_shared_libs: ["sdkmember"],
|
|
}
|
|
|
|
sdk_snapshot {
|
|
name: "mysdk@1",
|
|
native_shared_libs: ["sdkmember_mysdk_1"],
|
|
}
|
|
|
|
sdk_snapshot {
|
|
name: "mysdk@2",
|
|
native_shared_libs: ["sdkmember_mysdk_2"],
|
|
}
|
|
|
|
cc_prebuilt_library_shared {
|
|
name: "sdkmember",
|
|
srcs: ["libfoo.so"],
|
|
prefer: false,
|
|
system_shared_libs: [],
|
|
stl: "none",
|
|
}
|
|
|
|
cc_prebuilt_library_shared {
|
|
name: "sdkmember_mysdk_1",
|
|
sdk_member_name: "sdkmember",
|
|
srcs: ["libfoo.so"],
|
|
system_shared_libs: [],
|
|
stl: "none",
|
|
}
|
|
|
|
cc_prebuilt_library_shared {
|
|
name: "sdkmember_mysdk_2",
|
|
sdk_member_name: "sdkmember",
|
|
srcs: ["libfoo.so"],
|
|
system_shared_libs: [],
|
|
stl: "none",
|
|
}
|
|
|
|
cc_library_shared {
|
|
name: "mycpplib",
|
|
srcs: ["Test.cpp"],
|
|
shared_libs: ["sdkmember"],
|
|
system_shared_libs: [],
|
|
stl: "none",
|
|
}
|
|
|
|
apex {
|
|
name: "myapex",
|
|
native_shared_libs: ["mycpplib"],
|
|
uses_sdks: ["mysdk@1"],
|
|
key: "myapex.key",
|
|
certificate: ":myapex.cert",
|
|
}
|
|
|
|
apex {
|
|
name: "myapex2",
|
|
native_shared_libs: ["mycpplib"],
|
|
uses_sdks: ["mysdk@2"],
|
|
key: "myapex.key",
|
|
certificate: ":myapex.cert",
|
|
}
|
|
`)
|
|
|
|
sdkMemberV1 := ctx.ModuleForTests("sdkmember_mysdk_1", "android_arm64_armv8-a_core_shared_myapex").Rule("toc").Output
|
|
sdkMemberV2 := ctx.ModuleForTests("sdkmember_mysdk_2", "android_arm64_armv8-a_core_shared_myapex2").Rule("toc").Output
|
|
|
|
cpplibForMyApex := ctx.ModuleForTests("mycpplib", "android_arm64_armv8-a_core_shared_myapex")
|
|
cpplibForMyApex2 := ctx.ModuleForTests("mycpplib", "android_arm64_armv8-a_core_shared_myapex2")
|
|
|
|
// Depending on the uses_sdks value, different libs are linked
|
|
ensureListContains(t, pathsToStrings(cpplibForMyApex.Rule("ld").Implicits), sdkMemberV1.String())
|
|
ensureListContains(t, pathsToStrings(cpplibForMyApex2.Rule("ld").Implicits), sdkMemberV2.String())
|
|
}
|
|
|
|
// Note: This test does not verify that a droidstubs can be referenced, either
|
|
// directly or indirectly from an APEX as droidstubs can never be a part of an
|
|
// apex.
|
|
func TestBasicSdkWithDroidstubs(t *testing.T) {
|
|
testSdk(t, `
|
|
sdk {
|
|
name: "mysdk",
|
|
stubs_sources: ["mystub"],
|
|
}
|
|
sdk_snapshot {
|
|
name: "mysdk@10",
|
|
stubs_sources: ["mystub_mysdk@10"],
|
|
}
|
|
prebuilt_stubs_sources {
|
|
name: "mystub_mysdk@10",
|
|
sdk_member_name: "mystub",
|
|
srcs: ["stubs-sources/foo/bar/Foo.java"],
|
|
}
|
|
droidstubs {
|
|
name: "mystub",
|
|
srcs: ["foo/bar/Foo.java"],
|
|
sdk_version: "none",
|
|
system_modules: "none",
|
|
}
|
|
java_library {
|
|
name: "myjavalib",
|
|
srcs: [":mystub"],
|
|
sdk_version: "none",
|
|
system_modules: "none",
|
|
}
|
|
`)
|
|
}
|
|
|
|
func TestDepNotInRequiredSdks(t *testing.T) {
|
|
testSdkError(t, `module "myjavalib".*depends on "otherlib".*that isn't part of the required SDKs:.*`, `
|
|
sdk {
|
|
name: "mysdk",
|
|
java_libs: ["sdkmember"],
|
|
}
|
|
|
|
sdk_snapshot {
|
|
name: "mysdk@1",
|
|
java_libs: ["sdkmember_mysdk_1"],
|
|
}
|
|
|
|
java_import {
|
|
name: "sdkmember",
|
|
prefer: false,
|
|
host_supported: true,
|
|
}
|
|
|
|
java_import {
|
|
name: "sdkmember_mysdk_1",
|
|
sdk_member_name: "sdkmember",
|
|
host_supported: true,
|
|
}
|
|
|
|
java_library {
|
|
name: "myjavalib",
|
|
srcs: ["Test.java"],
|
|
libs: [
|
|
"sdkmember",
|
|
"otherlib",
|
|
],
|
|
system_modules: "none",
|
|
sdk_version: "none",
|
|
compile_dex: true,
|
|
host_supported: true,
|
|
}
|
|
|
|
// this lib is no in mysdk
|
|
java_library {
|
|
name: "otherlib",
|
|
srcs: ["Test.java"],
|
|
system_modules: "none",
|
|
sdk_version: "none",
|
|
compile_dex: true,
|
|
host_supported: true,
|
|
}
|
|
|
|
apex {
|
|
name: "myapex",
|
|
java_libs: ["myjavalib"],
|
|
uses_sdks: ["mysdk@1"],
|
|
key: "myapex.key",
|
|
certificate: ":myapex.cert",
|
|
}
|
|
`)
|
|
}
|
|
|
|
func TestSdkIsCompileMultilibBoth(t *testing.T) {
|
|
ctx, _ := testSdk(t, `
|
|
sdk {
|
|
name: "mysdk",
|
|
native_shared_libs: ["sdkmember"],
|
|
}
|
|
|
|
cc_library_shared {
|
|
name: "sdkmember",
|
|
srcs: ["Test.cpp"],
|
|
system_shared_libs: [],
|
|
stl: "none",
|
|
}
|
|
`)
|
|
|
|
armOutput := ctx.ModuleForTests("sdkmember", "android_arm_armv7-a-neon_core_shared").Module().(*cc.Module).OutputFile()
|
|
arm64Output := ctx.ModuleForTests("sdkmember", "android_arm64_armv8-a_core_shared").Module().(*cc.Module).OutputFile()
|
|
|
|
var inputs []string
|
|
buildParams := ctx.ModuleForTests("mysdk", "android_common").Module().BuildParamsForTests()
|
|
for _, bp := range buildParams {
|
|
if bp.Input != nil {
|
|
inputs = append(inputs, bp.Input.String())
|
|
}
|
|
}
|
|
|
|
// ensure that both 32/64 outputs are inputs of the sdk snapshot
|
|
ensureListContains(t, inputs, armOutput.String())
|
|
ensureListContains(t, inputs, arm64Output.String())
|
|
}
|
|
|
|
func TestSnapshot(t *testing.T) {
|
|
ctx, config := testSdk(t, `
|
|
sdk {
|
|
name: "mysdk",
|
|
java_libs: ["myjavalib"],
|
|
native_shared_libs: ["mynativelib"],
|
|
stubs_sources: ["myjavaapistubs"],
|
|
}
|
|
|
|
java_library {
|
|
name: "myjavalib",
|
|
srcs: ["Test.java"],
|
|
aidl: {
|
|
export_include_dirs: ["aidl"],
|
|
},
|
|
system_modules: "none",
|
|
sdk_version: "none",
|
|
compile_dex: true,
|
|
host_supported: true,
|
|
}
|
|
|
|
cc_library_shared {
|
|
name: "mynativelib",
|
|
srcs: [
|
|
"Test.cpp",
|
|
"aidl/foo/bar/Test.aidl",
|
|
],
|
|
export_include_dirs: ["include"],
|
|
aidl: {
|
|
export_aidl_headers: true,
|
|
},
|
|
system_shared_libs: [],
|
|
stl: "none",
|
|
}
|
|
|
|
droidstubs {
|
|
name: "myjavaapistubs",
|
|
srcs: ["foo/bar/Foo.java"],
|
|
system_modules: "none",
|
|
sdk_version: "none",
|
|
}
|
|
`)
|
|
|
|
var copySrcs []string
|
|
var copyDests []string
|
|
buildParams := ctx.ModuleForTests("mysdk", "android_common").Module().BuildParamsForTests()
|
|
var zipBp android.BuildParams
|
|
for _, bp := range buildParams {
|
|
ruleString := bp.Rule.String()
|
|
if ruleString == "android/soong/android.Cp" {
|
|
copySrcs = append(copySrcs, bp.Input.String())
|
|
copyDests = append(copyDests, bp.Output.Rel()) // rooted at the snapshot root
|
|
} else if ruleString == "<local rule>:m.mysdk_android_common.snapshot" {
|
|
zipBp = bp
|
|
}
|
|
}
|
|
|
|
buildDir := config.BuildDir()
|
|
ensureListContains(t, copySrcs, "aidl/foo/bar/Test.aidl")
|
|
ensureListContains(t, copySrcs, "include/Test.h")
|
|
ensureListContains(t, copySrcs, filepath.Join(buildDir, ".intermediates/mynativelib/android_arm64_armv8-a_core_shared/gen/aidl/aidl/foo/bar/BnTest.h"))
|
|
ensureListContains(t, copySrcs, filepath.Join(buildDir, ".intermediates/mynativelib/android_arm64_armv8-a_core_shared/gen/aidl/aidl/foo/bar/BpTest.h"))
|
|
ensureListContains(t, copySrcs, filepath.Join(buildDir, ".intermediates/mynativelib/android_arm64_armv8-a_core_shared/gen/aidl/aidl/foo/bar/Test.h"))
|
|
ensureListContains(t, copySrcs, filepath.Join(buildDir, ".intermediates/myjavalib/android_common/turbine-combined/myjavalib.jar"))
|
|
ensureListContains(t, copySrcs, filepath.Join(buildDir, ".intermediates/mynativelib/android_arm64_armv8-a_core_shared/mynativelib.so"))
|
|
|
|
ensureListContains(t, copyDests, "aidl/aidl/foo/bar/Test.aidl")
|
|
ensureListContains(t, copyDests, "arm64/include/include/Test.h")
|
|
ensureListContains(t, copyDests, "arm64/include_gen/mynativelib/aidl/foo/bar/BnTest.h")
|
|
ensureListContains(t, copyDests, "arm64/include_gen/mynativelib/aidl/foo/bar/BpTest.h")
|
|
ensureListContains(t, copyDests, "arm64/include_gen/mynativelib/aidl/foo/bar/Test.h")
|
|
ensureListContains(t, copyDests, "java/myjavalib.jar")
|
|
ensureListContains(t, copyDests, "arm64/lib/mynativelib.so")
|
|
|
|
// Ensure that the droidstubs .srcjar as repackaged into a temporary zip file
|
|
// and then merged together with the intermediate snapshot zip.
|
|
snapshotCreationInputs := zipBp.Implicits.Strings()
|
|
ensureListContains(t, snapshotCreationInputs,
|
|
filepath.Join(buildDir, ".intermediates/mysdk/android_common/tmp/java/myjavaapistubs_stubs_sources.zip"))
|
|
ensureListContains(t, snapshotCreationInputs,
|
|
filepath.Join(buildDir, ".intermediates/mysdk/android_common/mysdk-current.unmerged.zip"))
|
|
actual := zipBp.Output.String()
|
|
expected := filepath.Join(buildDir, ".intermediates/mysdk/android_common/mysdk-current.zip")
|
|
if actual != expected {
|
|
t.Errorf("Expected snapshot output to be %q but was %q", expected, actual)
|
|
}
|
|
}
|
|
|
|
var buildDir string
|
|
|
|
func setUp() {
|
|
var err error
|
|
buildDir, err = ioutil.TempDir("", "soong_sdk_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())
|
|
}
|