"path"
"path/filepath"
"strings"
+ "sync"
"testing"
"unicode"
)
var installdir, androiddir string
var libSuffix, libgoname string
-func init() {
+func TestMain(m *testing.M) {
GOOS = goEnv("GOOS")
GOARCH = goEnv("GOARCH")
GOROOT = goEnv("GOROOT")
if GOOS == "windows" {
exeSuffix = ".exe"
}
+
+ st := m.Run()
+
+ os.Remove(libgoname)
+ os.RemoveAll("pkg")
+ cleanupHeaders()
+ cleanupAndroid()
+
+ os.Exit(st)
}
func goEnv(key string) string {
return runwithenv(t, gopathEnv, args...)
}
-func createHeaders(t *testing.T) {
- rungocmd(t,
- "go", "install",
- "-buildmode=c-shared", "-installsuffix",
- "testcshared", "libgo",
- )
+func createHeaders() error {
+ args := []string{"go", "install", "-buildmode=c-shared",
+ "-installsuffix", "testcshared", "libgo"}
+ cmd := exec.Command(args[0], args[1:]...)
+ cmd.Env = gopathEnv
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ return fmt.Errorf("command failed: %v\n%v\n%s\n", args, err, out)
+ }
- rungocmd(t,
- "go", "build",
- "-buildmode=c-shared", "-installsuffix",
- "testcshared", "-o", libgoname,
- filepath.Join("src", "libgo", "libgo.go"),
- )
- adbPush(t, libgoname)
+ args = []string{"go", "build", "-buildmode=c-shared",
+ "-installsuffix", "testcshared",
+ "-o", libgoname,
+ filepath.Join("src", "libgo", "libgo.go")}
+ cmd = exec.Command(args[0], args[1:]...)
+ cmd.Env = gopathEnv
+ out, err = cmd.CombinedOutput()
+ if err != nil {
+ return fmt.Errorf("command failed: %v\n%v\n%s\n", args, err, out)
+ }
- if GOOS == "linux" || GOOS == "android" {
- f, err := elf.Open(libgoname)
+ if GOOS == "android" {
+ args = []string{"adb", "push", libgoname, fmt.Sprintf("%s/%s", androiddir, libgoname)}
+ cmd = exec.Command(args[0], args[1:]...)
+ out, err = cmd.CombinedOutput()
if err != nil {
- t.Fatal("elf.Open failed: ", err)
- }
- defer f.Close()
- if hasDynTag(t, f, elf.DT_TEXTREL) {
- t.Fatalf("%s has DT_TEXTREL flag", libgoname)
+ return fmt.Errorf("adb command failed: %v\n%s\n", err, out)
}
}
+
+ return nil
+}
+
+var (
+ headersOnce sync.Once
+ headersErr error
+)
+
+func createHeadersOnce(t *testing.T) {
+ headersOnce.Do(func() {
+ headersErr = createHeaders()
+ })
+ if headersErr != nil {
+ t.Fatal(headersErr)
+ }
}
func cleanupHeaders() {
os.Remove("libgo.h")
}
+var (
+ androidOnce sync.Once
+ androidErr error
+)
+
func setupAndroid(t *testing.T) {
if GOOS != "android" {
return
}
- adbRun(t, nil, "mkdir", "-p", androiddir)
+ androidOnce.Do(func() {
+ cmd := exec.Command("adb", "shell", "mkdir", "-p", androiddir)
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ androidErr = fmt.Errorf("setupAndroid failed: %v\n%s\n", err, out)
+ }
+ })
+ if androidErr != nil {
+ t.Fatal(androidErr)
+ }
}
-func cleanupAndroid(t *testing.T) {
+func cleanupAndroid() {
if GOOS != "android" {
return
}
- adbRun(t, nil, "rm", "-rf", androiddir)
+ cmd := exec.Command("adb", "shell", "rm", "-rf", androiddir)
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ log.Fatalf("cleanupAndroid failed: %v\n%s\n", err, out)
+ }
}
// test0: exported symbols in shared lib are accessible.
bin := cmdToRun(cmd)
setupAndroid(t)
- defer cleanupAndroid(t)
- createHeaders(t)
- defer cleanupHeaders()
+ createHeadersOnce(t)
run(t, append(cc, "-I", installdir, "-o", cmd, "main0.c", libgoname)...)
adbPush(t, cmd)
- defer os.Remove(libgoname)
defer os.Remove("testp")
out := runwithldlibrarypath(t, bin...)
bin := cmdToRun(cmd)
setupAndroid(t)
- defer cleanupAndroid(t)
- createHeaders(t)
- defer cleanupHeaders()
+ createHeadersOnce(t)
run(t, append(cc, "-o", cmd, "main1.c", "-ldl")...)
adbPush(t, cmd)
- defer os.Remove(libgoname)
defer os.Remove(cmd)
out := runExe(t, nil, append(bin, "./"+libgoname)...)
bin := cmdToRun(cmd)
setupAndroid(t)
- defer cleanupAndroid(t)
rungocmd(t,
"go", "build",
bin := cmdToRun(cmd)
setupAndroid(t)
- defer cleanupAndroid(t)
- createHeaders(t)
- defer cleanupHeaders()
+ createHeadersOnce(t)
run(t, append(cc, "-o", cmd, "main3.c", "-ldl")...)
adbPush(t, cmd)
- defer os.Remove(libgoname)
defer os.Remove(cmd)
out := runExe(t, nil, append(bin, "./"+libgoname)...)
bin := cmdToRun(cmd)
setupAndroid(t)
- defer cleanupAndroid(t)
rungocmd(t,
"go", "build",
bin := cmdToRun(cmd)
setupAndroid(t)
- defer cleanupAndroid(t)
rungocmd(t,
"go", "build",
return
}
- defer func() {
- os.RemoveAll("pkg")
- }()
-
- createHeaders(t)
- defer cleanupHeaders()
+ createHeadersOnce(t)
f, err := elf.Open(libgoname)
if err != nil {
- t.Fatal("elf.Open failed: ", err)
+ t.Fatalf("elf.Open failed: %v", err)
}
defer f.Close()
- if hasDynTag(t, f, elf.DT_TEXTREL) {
- t.Errorf("%s has DT_TEXTREL flag", libgoname)
- }
-}
-func hasDynTag(t *testing.T, f *elf.File, tag elf.DynTag) bool {
ds := f.SectionByType(elf.SHT_DYNAMIC)
if ds == nil {
- t.Error("no SHT_DYNAMIC section")
- return false
+ t.Fatalf("no SHT_DYNAMIC section")
}
d, err := ds.Data()
if err != nil {
- t.Errorf("can't read SHT_DYNAMIC contents: %v", err)
- return false
+ t.Fatalf("can't read SHT_DYNAMIC contents: %v", err)
}
for len(d) > 0 {
- var t elf.DynTag
+ var tag elf.DynTag
switch f.Class {
case elf.ELFCLASS32:
- t = elf.DynTag(f.ByteOrder.Uint32(d[:4]))
+ tag = elf.DynTag(f.ByteOrder.Uint32(d[:4]))
d = d[8:]
case elf.ELFCLASS64:
- t = elf.DynTag(f.ByteOrder.Uint64(d[:8]))
+ tag = elf.DynTag(f.ByteOrder.Uint64(d[:8]))
d = d[16:]
}
- if t == tag {
- return true
+ if tag == elf.DT_TEXTREL {
+ t.Fatalf("%s has DT_TEXTREL flag", libgoname)
}
}
- return false
}