testing: implement testing.TempDir
TODO: enable test on windows and wasi once os.Readdir and os.RemoveAll are implemented there
Этот коммит содержится в:
родитель
b406422277
коммит
b24af78327
4 изменённых файлов: 204 добавлений и 0 удалений
10
src/testing/is_wasi_no_test.go
Обычный файл
10
src/testing/is_wasi_no_test.go
Обычный файл
|
@ -0,0 +1,10 @@
|
||||||
|
// Copyright 2016 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.
|
||||||
|
//
|
||||||
|
//go:build !wasi
|
||||||
|
// +build !wasi
|
||||||
|
|
||||||
|
package testing_test
|
||||||
|
|
||||||
|
const isWASI = false
|
10
src/testing/is_wasi_test.go
Обычный файл
10
src/testing/is_wasi_test.go
Обычный файл
|
@ -0,0 +1,10 @@
|
||||||
|
// Copyright 2016 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.
|
||||||
|
//
|
||||||
|
//go:build wasi
|
||||||
|
// +build wasi
|
||||||
|
|
||||||
|
package testing_test
|
||||||
|
|
||||||
|
const isWASI = true
|
|
@ -15,6 +15,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode"
|
||||||
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Testing flags.
|
// Testing flags.
|
||||||
|
@ -58,6 +60,10 @@ type common struct {
|
||||||
name string // Name of test or benchmark.
|
name string // Name of test or benchmark.
|
||||||
start time.Time // Time test or benchmark started
|
start time.Time // Time test or benchmark started
|
||||||
duration time.Duration
|
duration time.Duration
|
||||||
|
|
||||||
|
tempDir string
|
||||||
|
tempDirErr error
|
||||||
|
tempDirSeq int32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Short reports whether the -test.short flag is set.
|
// Short reports whether the -test.short flag is set.
|
||||||
|
@ -258,6 +264,70 @@ func (c *common) Cleanup(f func()) {
|
||||||
c.cleanups = append(c.cleanups, f)
|
c.cleanups = append(c.cleanups, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TempDir returns a temporary directory for the test to use.
|
||||||
|
// The directory is automatically removed by Cleanup when the test and
|
||||||
|
// all its subtests complete.
|
||||||
|
// Each subsequent call to t.TempDir returns a unique directory;
|
||||||
|
// if the directory creation fails, TempDir terminates the test by calling Fatal.
|
||||||
|
func (c *common) TempDir() string {
|
||||||
|
// Use a single parent directory for all the temporary directories
|
||||||
|
// created by a test, each numbered sequentially.
|
||||||
|
var nonExistent bool
|
||||||
|
if c.tempDir == "" { // Usually the case with js/wasm
|
||||||
|
nonExistent = true
|
||||||
|
} else {
|
||||||
|
_, err := os.Stat(c.tempDir)
|
||||||
|
nonExistent = os.IsNotExist(err)
|
||||||
|
if err != nil && !nonExistent {
|
||||||
|
c.Fatalf("TempDir: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if nonExistent {
|
||||||
|
c.Helper()
|
||||||
|
|
||||||
|
// Drop unusual characters (such as path separators or
|
||||||
|
// characters interacting with globs) from the directory name to
|
||||||
|
// avoid surprising os.MkdirTemp behavior.
|
||||||
|
mapper := func(r rune) rune {
|
||||||
|
if r < utf8.RuneSelf {
|
||||||
|
const allowed = "!#$%&()+,-.=@^_{}~ "
|
||||||
|
if '0' <= r && r <= '9' ||
|
||||||
|
'a' <= r && r <= 'z' ||
|
||||||
|
'A' <= r && r <= 'Z' {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
if strings.ContainsRune(allowed, r) {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
} else if unicode.IsLetter(r) || unicode.IsNumber(r) {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
pattern := strings.Map(mapper, c.Name())
|
||||||
|
c.tempDir, c.tempDirErr = os.MkdirTemp("", pattern)
|
||||||
|
if c.tempDirErr == nil {
|
||||||
|
c.Cleanup(func() {
|
||||||
|
if err := os.RemoveAll(c.tempDir); err != nil {
|
||||||
|
c.Errorf("TempDir RemoveAll cleanup: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.tempDirErr != nil {
|
||||||
|
c.Fatalf("TempDir: %v", c.tempDirErr)
|
||||||
|
}
|
||||||
|
seq := c.tempDirSeq
|
||||||
|
c.tempDirSeq++
|
||||||
|
dir := fmt.Sprintf("%s%c%03d", c.tempDir, os.PathSeparator, seq)
|
||||||
|
if err := os.Mkdir(dir, 0777); err != nil {
|
||||||
|
c.Fatalf("TempDir: %v", err)
|
||||||
|
}
|
||||||
|
return dir
|
||||||
|
}
|
||||||
|
|
||||||
// runCleanup is called at the end of the test.
|
// runCleanup is called at the end of the test.
|
||||||
func (c *common) runCleanup() {
|
func (c *common) runCleanup() {
|
||||||
for {
|
for {
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
//go:build !windows
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
// TODO: implement readdir for windows, then enable this file
|
||||||
|
|
||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
@ -6,6 +11,7 @@ package testing_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,3 +22,111 @@ import (
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
os.Exit(m.Run())
|
os.Exit(m.Run())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTempDirInCleanup(t *testing.T) {
|
||||||
|
if isWASI {
|
||||||
|
t.Log("Skipping. TODO: implement RemoveAll for wasi")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var dir string
|
||||||
|
|
||||||
|
t.Run("test", func(t *testing.T) {
|
||||||
|
t.Cleanup(func() {
|
||||||
|
dir = t.TempDir()
|
||||||
|
})
|
||||||
|
_ = t.TempDir()
|
||||||
|
})
|
||||||
|
|
||||||
|
fi, err := os.Stat(dir)
|
||||||
|
if fi != nil {
|
||||||
|
t.Fatalf("Directory %q from user Cleanup still exists", dir)
|
||||||
|
}
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTempDirInBenchmark(t *testing.T) {
|
||||||
|
testing.Benchmark(func(b *testing.B) {
|
||||||
|
if !b.Run("test", func(b *testing.B) {
|
||||||
|
// Add a loop so that the test won't fail. See issue 38677.
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_ = b.TempDir()
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
t.Fatal("Sub test failure in a benchmark")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTempDir(t *testing.T) {
|
||||||
|
if isWASI {
|
||||||
|
t.Log("Skipping. TODO: implement RemoveAll for wasi")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testTempDir(t)
|
||||||
|
t.Run("InSubtest", testTempDir)
|
||||||
|
t.Run("test/subtest", testTempDir)
|
||||||
|
t.Run("test\\subtest", testTempDir)
|
||||||
|
t.Run("test:subtest", testTempDir)
|
||||||
|
t.Run("test/..", testTempDir)
|
||||||
|
t.Run("../test", testTempDir)
|
||||||
|
t.Run("test[]", testTempDir)
|
||||||
|
t.Run("test*", testTempDir)
|
||||||
|
t.Run("äöüéè", testTempDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTempDir(t *testing.T) {
|
||||||
|
dirCh := make(chan string, 1)
|
||||||
|
t.Cleanup(func() {
|
||||||
|
// Verify directory has been removed.
|
||||||
|
select {
|
||||||
|
case dir := <-dirCh:
|
||||||
|
fi, err := os.Stat(dir)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
// All good
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Errorf("directory %q still exists: %v, isDir=%v", dir, fi, fi.IsDir())
|
||||||
|
default:
|
||||||
|
if !t.Failed() {
|
||||||
|
t.Fatal("never received dir channel")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
if dir == "" {
|
||||||
|
t.Fatal("expected dir")
|
||||||
|
}
|
||||||
|
dir2 := t.TempDir()
|
||||||
|
if dir == dir2 {
|
||||||
|
t.Fatal("subsequent calls to TempDir returned the same directory")
|
||||||
|
}
|
||||||
|
if filepath.Dir(dir) != filepath.Dir(dir2) {
|
||||||
|
t.Fatalf("calls to TempDir do not share a parent; got %q, %q", dir, dir2)
|
||||||
|
}
|
||||||
|
dirCh <- dir
|
||||||
|
fi, err := os.Stat(dir)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !fi.IsDir() {
|
||||||
|
t.Errorf("dir %q is not a dir", dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
glob := filepath.Join(dir, "*.txt")
|
||||||
|
if _, err := filepath.Glob(glob); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.Remove(dir)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected files in TempDir")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче