Skip to content

Commit

Permalink
cmd/go: convert TestTestCacheInputs to a script test
Browse files Browse the repository at this point in the history
Updates #28387
Updates #30316

Change-Id: I48c6dd8619ea9602e9617ce11dfa05f1c70a485d
Reviewed-on: https://go-review.googlesource.com/c/go/+/207958
Reviewed-by: Jay Conrod <jayconrod@google.com>
  • Loading branch information
Bryan C. Mills committed Nov 19, 2019
1 parent 96c9f3a commit 104f07c
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 208 deletions.
116 changes: 0 additions & 116 deletions src/cmd/go/go_test.go
Expand Up @@ -4870,122 +4870,6 @@ func TestTestCache(t *testing.T) {
}
}

func TestTestCacheInputs(t *testing.T) {
tooSlow(t)

if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") {
t.Skip("GODEBUG gocacheverify")
}
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.makeTempdir()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
tg.setenv("GOCACHE", tg.path("cache"))

defer os.Remove(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"))
defer os.Remove(filepath.Join(tg.pwd(), "testdata/src/testcache/script.sh"))
tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), []byte("x"), 0644))
old := time.Now().Add(-1 * time.Minute)
tg.must(os.Chtimes(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), old, old))
info, err := os.Stat(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"))
if err != nil {
t.Fatal(err)
}
t.Logf("file.txt: old=%v, info.ModTime=%v", old, info.ModTime()) // help debug when Chtimes lies about succeeding
tg.setenv("TESTKEY", "x")

tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/script.sh"), []byte("#!/bin/sh\nexit 0\n"), 0755))
tg.must(os.Chtimes(filepath.Join(tg.pwd(), "testdata/src/testcache/script.sh"), old, old))

tg.run("test", "testcache")
tg.run("test", "testcache")
tg.grepStdout(`\(cached\)`, "did not cache")

tg.setenv("TESTKEY", "y")
tg.run("test", "testcache")
tg.grepStdoutNot(`\(cached\)`, "did not notice env var change")
tg.run("test", "testcache")
tg.grepStdout(`\(cached\)`, "did not cache")

tg.run("test", "testcache", "-run=FileSize")
tg.run("test", "testcache", "-run=FileSize")
tg.grepStdout(`\(cached\)`, "did not cache")
tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), []byte("xxx"), 0644))
tg.run("test", "testcache", "-run=FileSize")
tg.grepStdoutNot(`\(cached\)`, "did not notice file size change")
tg.run("test", "testcache", "-run=FileSize")
tg.grepStdout(`\(cached\)`, "did not cache")

tg.run("test", "testcache", "-run=Chdir")
tg.run("test", "testcache", "-run=Chdir")
tg.grepStdout(`\(cached\)`, "did not cache")
tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), []byte("xxxxx"), 0644))
tg.run("test", "testcache", "-run=Chdir")
tg.grepStdoutNot(`\(cached\)`, "did not notice file size change")
tg.run("test", "testcache", "-run=Chdir")
tg.grepStdout(`\(cached\)`, "did not cache")

tg.must(os.Chtimes(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), old, old))
tg.run("test", "testcache", "-run=FileContent")
tg.run("test", "testcache", "-run=FileContent")
tg.grepStdout(`\(cached\)`, "did not cache")
tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), []byte("yyy"), 0644))
old2 := old.Add(10 * time.Second)
tg.must(os.Chtimes(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), old2, old2))
tg.run("test", "testcache", "-run=FileContent")
tg.grepStdoutNot(`\(cached\)`, "did not notice file content change")
tg.run("test", "testcache", "-run=FileContent")
tg.grepStdout(`\(cached\)`, "did not cache")

tg.run("test", "testcache", "-run=DirList")
tg.run("test", "testcache", "-run=DirList")
tg.grepStdout(`\(cached\)`, "did not cache")
tg.must(os.Remove(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt")))
tg.run("test", "testcache", "-run=DirList")
tg.grepStdoutNot(`\(cached\)`, "did not notice directory change")
tg.run("test", "testcache", "-run=DirList")
tg.grepStdout(`\(cached\)`, "did not cache")

tg.tempFile("file.txt", "")
tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/testcachetmp_test.go"), []byte(`package testcache
import (
"os"
"testing"
)
func TestExternalFile(t *testing.T) {
os.Open(`+fmt.Sprintf("%q", tg.path("file.txt"))+`)
_, err := os.Stat(`+fmt.Sprintf("%q", tg.path("file.txt"))+`)
if err != nil {
t.Fatal(err)
}
}
`), 0666))
defer os.Remove(filepath.Join(tg.pwd(), "testdata/src/testcache/testcachetmp_test.go"))
tg.run("test", "testcache", "-run=ExternalFile")
tg.run("test", "testcache", "-run=ExternalFile")
tg.grepStdout(`\(cached\)`, "did not cache")
tg.must(os.Remove(filepath.Join(tg.tempdir, "file.txt")))
tg.run("test", "testcache", "-run=ExternalFile")
tg.grepStdout(`\(cached\)`, "did not cache")

switch runtime.GOOS {
case "plan9", "windows":
// no shell scripts
default:
tg.run("test", "testcache", "-run=Exec")
tg.run("test", "testcache", "-run=Exec")
tg.grepStdout(`\(cached\)`, "did not cache")
tg.must(os.Chtimes(filepath.Join(tg.pwd(), "testdata/src/testcache/script.sh"), old2, old2))
tg.run("test", "testcache", "-run=Exec")
tg.grepStdoutNot(`\(cached\)`, "did not notice script change")
tg.run("test", "testcache", "-run=Exec")
tg.grepStdout(`\(cached\)`, "did not cache")
}
}

func TestTestVet(t *testing.T) {
tooSlow(t)
tg := testgo(t)
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/go/testdata/script/cache_vet.txt
@@ -1,7 +1,7 @@
env GO111MODULE=off

[short] skip
[GODEBUG:gocacheverify] skip
[GODEBUG:gocacheverify=1] skip
[gccgo] skip # gccgo has no standard packages

# Start with a clean build cache:
Expand Down
230 changes: 230 additions & 0 deletions src/cmd/go/testdata/script/test_cache_inputs.txt
@@ -0,0 +1,230 @@
env GO111MODULE=off

# Test that cached test results are invalidated in response to
# changes to the external inputs to the test.

[short] skip
[GODEBUG:gocacheverify=1] skip

# We're testing cache behavior, so start with a clean GOCACHE.
env GOCACHE=$WORK/cache

# Build a helper binary to invoke os.Chtimes.
go build -o mkold$GOEXE mkold.go

# Make test input files appear to be a minute old.
exec ./mkold$GOEXE 1m testcache/file.txt
exec ./mkold$GOEXE 1m testcache/script.sh

# If the test reads an environment variable, changes to that variable
# should invalidate cached test results.
env TESTKEY=x
go test testcache -run=TestLookupEnv
go test testcache -run=TestLookupEnv
stdout '\(cached\)'

env TESTKEY=y
go test testcache -run=TestLookupEnv
! stdout '\(cached\)'
go test testcache -run=TestLookupEnv
stdout '\(cached\)'

# If the test stats a file, changes to the file should invalidate the cache.
go test testcache -run=FileSize
go test testcache -run=FileSize
stdout '\(cached\)'

cp 4x.txt testcache/file.txt
go test testcache -run=FileSize
! stdout '\(cached\)'
go test testcache -run=FileSize
stdout '\(cached\)'

# Files should be tracked even if the test changes its working directory.
go test testcache -run=Chdir
go test testcache -run=Chdir
stdout '\(cached\)'
cp 6x.txt testcache/file.txt
go test testcache -run=Chdir
! stdout '\(cached\)'
go test testcache -run=Chdir
stdout '\(cached\)'

# The content of files should affect caching, provided that the mtime also changes.
exec ./mkold$GOEXE 1m testcache/file.txt
go test testcache -run=FileContent
go test testcache -run=FileContent
stdout '\(cached\)'
cp 2y.txt testcache/file.txt
exec ./mkold$GOEXE 50s testcache/file.txt
go test testcache -run=FileContent
! stdout '\(cached\)'
go test testcache -run=FileContent
stdout '\(cached\)'

# Directory contents read via os.ReadDirNames should affect caching.
go test testcache -run=DirList
go test testcache -run=DirList
stdout '\(cached\)'
rm testcache/file.txt
go test testcache -run=DirList
! stdout '\(cached\)'
go test testcache -run=DirList
stdout '\(cached\)'

# Files outside GOROOT and GOPATH should not affect caching.
env TEST_EXTERNAL_FILE=$WORK/external.txt
go test testcache -run=ExternalFile
go test testcache -run=ExternalFile
stdout '\(cached\)'

rm $WORK/external.txt
go test testcache -run=ExternalFile
stdout '\(cached\)'

# Executables within GOROOT and GOPATH should affect caching,
# even if the test does not stat them explicitly.

[!exec:/bin/sh] skip
chmod 0755 ./testcache/script.sh

exec ./mkold$GOEXEC 1m testcache/script.sh
go test testcache -run=Exec
go test testcache -run=Exec
stdout '\(cached\)'

exec ./mkold$GOEXE 50s testcache/script.sh
go test testcache -run=Exec
! stdout '\(cached\)'
go test testcache -run=Exec
stdout '\(cached\)'

-- testcache/file.txt --
xx
-- 4x.txt --
xxxx
-- 6x.txt --
xxxxxx
-- 2y.txt --
yy
-- $WORK/external.txt --
This file is outside of GOPATH.
-- testcache/script.sh --
#!/bin/sh
exit 0
-- testcache/testcache_test.go --
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package testcache

import (
"io/ioutil"
"os"
"testing"
)

func TestChdir(t *testing.T) {
os.Chdir("..")
defer os.Chdir("testcache")
info, err := os.Stat("testcache/file.txt")
if err != nil {
t.Fatal(err)
}
if info.Size()%2 != 1 {
t.Fatal("even file")
}
}

func TestOddFileContent(t *testing.T) {
f, err := os.Open("file.txt")
if err != nil {
t.Fatal(err)
}
data, err := ioutil.ReadAll(f)
f.Close()
if err != nil {
t.Fatal(err)
}
if len(data)%2 != 1 {
t.Fatal("even file")
}
}

func TestOddFileSize(t *testing.T) {
info, err := os.Stat("file.txt")
if err != nil {
t.Fatal(err)
}
if info.Size()%2 != 1 {
t.Fatal("even file")
}
}

func TestOddGetenv(t *testing.T) {
val := os.Getenv("TESTKEY")
if len(val)%2 != 1 {
t.Fatal("even env value")
}
}

func TestLookupEnv(t *testing.T) {
_, ok := os.LookupEnv("TESTKEY")
if !ok {
t.Fatal("env missing")
}
}

func TestDirList(t *testing.T) {
f, err := os.Open(".")
if err != nil {
t.Fatal(err)
}
f.Readdirnames(-1)
f.Close()
}

func TestExec(t *testing.T) {
// Note: not using os/exec to make sure there is no unexpected stat.
p, err := os.StartProcess("./script.sh", []string{"script"}, new(os.ProcAttr))
if err != nil {
t.Fatal(err)
}
ps, err := p.Wait()
if err != nil {
t.Fatal(err)
}
if !ps.Success() {
t.Fatalf("script failed: %v", err)
}
}

func TestExternalFile(t *testing.T) {
os.Open(os.Getenv("TEST_EXTERNAL_FILE"))
_, err := os.Stat(os.Getenv("TEST_EXTERNAL_FILE"))
if err != nil {
t.Fatal(err)
}
}
-- mkold.go --
package main

import (
"log"
"os"
"time"
)

func main() {
d, err := time.ParseDuration(os.Args[1])
if err != nil {
log.Fatal(err)
}
path := os.Args[2]
old := time.Now().Add(-d)
err = os.Chtimes(path, old, old)
if err != nil {
log.Fatal(err)
}
}

0 comments on commit 104f07c

Please sign in to comment.