Home | History | Annotate | Download | only in gotestrunner
      1 // Copyright 2015 Google Inc. All rights reserved.
      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 
     15 package main
     16 
     17 import (
     18 	"bufio"
     19 	"bytes"
     20 	"flag"
     21 	"fmt"
     22 	"io"
     23 	"io/ioutil"
     24 	"os"
     25 	"os/exec"
     26 	"path/filepath"
     27 	"runtime"
     28 	"syscall"
     29 )
     30 
     31 var (
     32 	chdir = flag.String("p", "", "Change to a path before executing test")
     33 	touch = flag.String("f", "", "Write a file on success")
     34 )
     35 
     36 // This will copy the stdout from the test process to our stdout
     37 // unless it only contains "PASS\n".
     38 func handleStdout(stdout io.Reader) {
     39 	reader := bufio.NewReader(stdout)
     40 
     41 	// This is intentionally 6 instead of 5 to check for EOF
     42 	buf, _ := reader.Peek(6)
     43 	if bytes.Equal(buf, []byte("PASS\n")) {
     44 		return
     45 	}
     46 
     47 	io.Copy(os.Stdout, reader)
     48 }
     49 
     50 func main() {
     51 	flag.Parse()
     52 
     53 	if flag.NArg() == 0 {
     54 		fmt.Fprintln(os.Stderr, "error: must pass at least one test executable")
     55 		os.Exit(1)
     56 	}
     57 
     58 	test, err := filepath.Abs(flag.Arg(0))
     59 	if err != nil {
     60 		fmt.Fprintln(os.Stderr, "error: Failed to locate test binary:", err)
     61 	}
     62 
     63 	cmd := exec.Command(test, flag.Args()[1:]...)
     64 	if *chdir != "" {
     65 		cmd.Dir = *chdir
     66 
     67 		// GOROOT is commonly a relative path in Android, make it
     68 		// absolute if we're changing directories.
     69 		if absRoot, err := filepath.Abs(runtime.GOROOT()); err == nil {
     70 			os.Setenv("GOROOT", absRoot)
     71 		} else {
     72 			fmt.Fprintln(os.Stderr, "error: Failed to locate GOROOT:", err)
     73 		}
     74 	}
     75 
     76 	cmd.Stderr = os.Stderr
     77 	stdout, err := cmd.StdoutPipe()
     78 	if err != nil {
     79 		fmt.Fprintln(os.Stderr, err)
     80 		os.Exit(1)
     81 	}
     82 
     83 	err = cmd.Start()
     84 	if err != nil {
     85 		fmt.Fprintln(os.Stderr, err)
     86 		os.Exit(1)
     87 	}
     88 
     89 	handleStdout(stdout)
     90 
     91 	if err = cmd.Wait(); err != nil {
     92 		if e, ok := err.(*exec.ExitError); ok {
     93 			if status, ok := e.Sys().(syscall.WaitStatus); ok && status.Exited() {
     94 				os.Exit(status.ExitStatus())
     95 			} else if status.Signaled() {
     96 				fmt.Fprintf(os.Stderr, "test got signal %s\n", status.Signal())
     97 				os.Exit(1)
     98 			}
     99 		}
    100 		fmt.Fprintln(os.Stderr, err)
    101 		os.Exit(1)
    102 	}
    103 
    104 	if *touch != "" {
    105 		err = ioutil.WriteFile(*touch, []byte{}, 0666)
    106 		if err != nil {
    107 			panic(err)
    108 		}
    109 	}
    110 
    111 	os.Exit(0)
    112 }
    113