# "go test -c -test.bench=XXX errors" should not hang. # "go test -c" should also produce reproducible binaries. # "go test -c" should also appear to write a new binary every time, # even if it's really just updating the mtime on an existing up-to-date binary. [compiler:gccgo] skip [short] skip # Install some commands to compare mtimes env GOBIN=$WORK/tmp/bin go install m/now m/mtime m/before # Initial builds go test -c -test.bench=XXX errors go test -c -o errors2.test errors cmp errors.test$GOEXE errors2.test # // errors2.test has no exeSuffix because -o above doesn't have it # Check errors.test mtime is updated exec $GOBIN/now cp stdout start_time.txt go test -x -c -test.bench=XXX errors ! stderr '[\\/]link|gccgo' # make sure up-to-date test binary is not relinked exec $GOBIN/mtime errors.test$GOEXE cp stdout errors1_mod_time.txt exec $GOBIN/before start_time.txt errors1_mod_time.txt rm start_time.txt errors1_mod_time.txt # Check errors2.test mtime is updated exec $GOBIN/now cp stdout start_time.txt go test -x -c -o errors2.test errors ! stderr '[\\/]link|gccgo' # make sure up-to-date test binary is not relinked exec $GOBIN/mtime errors2.test cp stdout errors2_mod_time.txt exec $GOBIN/before start_time.txt errors2_mod_time.txt -- go.mod -- module m go 1.16 -- now/now.go -- // Writes time.Now() to a file package main import ( "encoding/json" "fmt" "os" "time" ) func main() { if err := json.NewEncoder(os.Stdout).Encode(time.Now()); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } -- mtime/mtime.go -- package main import ( "encoding/json" "fmt" "os" ) func main() { info, err := os.Stat(os.Args[1]) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } if err := json.NewEncoder(os.Stdout).Encode(info.ModTime()); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } -- before/before.go -- package main import ( "encoding/json" "fmt" "os" "time" ) func truncateLike(t, p time.Time) time.Time { nano := p.UnixNano() d := 1 * time.Nanosecond for nano%int64(d) == 0 && d < 1*time.Second { d *= 10 } for nano%int64(d) == 0 && d < 2*time.Second { d *= 2 } return t.Truncate(d) } func main() { var t1 time.Time b1, err := os.ReadFile(os.Args[1]) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } if err := json.Unmarshal(b1, &t1); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } var t2 time.Time b2, err := os.ReadFile(os.Args[2]) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } if err := json.Unmarshal(b2, &t2); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } t1 = truncateLike(t1, t2) if !t1.Before(t2) { fmt.Fprintf(os.Stderr, "time in %v (%v) is not before time in %v (%v)", os.Args[1], t1, os.Args[2], t2) os.Exit(1) } }