github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/misc/android/go_android_exec.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This program can be used as go_android_GOARCH_exec by the Go tool. 6 // It executes binaries on an android device using adb. 7 package main 8 9 import ( 10 "bytes" 11 "fmt" 12 "io" 13 "log" 14 "os" 15 "os/exec" 16 "path/filepath" 17 "runtime" 18 "strconv" 19 "strings" 20 ) 21 22 func run(args ...string) string { 23 buf := new(bytes.Buffer) 24 cmd := exec.Command("adb", args...) 25 cmd.Stdout = io.MultiWriter(os.Stdout, buf) 26 cmd.Stderr = os.Stderr 27 log.Printf("adb %s", strings.Join(args, " ")) 28 err := cmd.Run() 29 if err != nil { 30 log.Fatalf("adb %s: %v", strings.Join(args, " "), err) 31 } 32 return buf.String() 33 } 34 35 func main() { 36 log.SetFlags(0) 37 log.SetPrefix("go_android_exec: ") 38 39 // Determine thepackage by examining the current working 40 // directory, which will look something like 41 // "$GOROOT/src/mime/multipart". We extract everything 42 // after the $GOROOT to run on the same relative directory 43 // on the target device. 44 // 45 // TODO(crawshaw): Pick useful subdir when we are not 46 // inside a GOROOT, e.g. we are in a GOPATH. 47 cwd, err := os.Getwd() 48 if err != nil { 49 log.Fatal(err) 50 } 51 subdir, err := filepath.Rel(runtime.GOROOT(), cwd) 52 if err != nil { 53 log.Fatal(err) 54 } 55 subdir = filepath.ToSlash(subdir) 56 57 // Binary names can conflict. 58 // E.g. template.test from the {html,text}/template packages. 59 binName := filepath.Base(os.Args[1]) 60 deviceGoroot := "/data/local/tmp/goroot" 61 deviceBin := fmt.Sprintf("%s/%s-%d", deviceGoroot, binName, os.Getpid()) 62 63 // The push of the binary happens in parallel with other tests. 64 // Unfortunately, a simultaneous call to adb shell hold open 65 // file descriptors, so it is necessary to push then move to 66 // avoid a "text file busy" error on execution. 67 // https://code.google.com/p/android/issues/detail?id=65857 68 run("push", os.Args[1], deviceBin+"-tmp") 69 run("shell", "cp '"+deviceBin+"-tmp' '"+deviceBin+"'") 70 run("shell", "rm '"+deviceBin+"-tmp'") 71 72 // The adb shell command will return an exit code of 0 regardless 73 // of the command run. E.g. 74 // $ adb shell false 75 // $ echo $? 76 // 0 77 // https://code.google.com/p/android/issues/detail?id=3254 78 // So we append the exitcode to the output and parse it from there. 79 const exitstr = "exitcode=" 80 cmd := `export TMPDIR="/data/local/tmp"` + 81 `; export GOROOT="` + deviceGoroot + `"` + 82 `; cd "$GOROOT/` + subdir + `"` + 83 "; '" + deviceBin + "' " + strings.Join(os.Args[2:], " ") + 84 "; echo -n " + exitstr + "$?" 85 output := run("shell", cmd) 86 run("shell", "rm '"+deviceBin+"'") // cleanup 87 output = output[strings.LastIndex(output, "\n")+1:] 88 if !strings.HasPrefix(output, exitstr) { 89 log.Fatalf("no exit code: %q", output) 90 } 91 code, err := strconv.Atoi(output[len(exitstr):]) 92 if err != nil { 93 log.Fatalf("bad exit code: %v", err) 94 } 95 os.Exit(code) 96 }