istio

Форк
0
/
failer.go 
149 строк · 3.5 Кб
1
// Copyright Istio Authors.
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 test
16

17
import (
18
	"errors"
19
	"fmt"
20
	"os"
21
	"runtime"
22
	"sync"
23
	"testing"
24

25
	"istio.io/istio/pkg/log"
26
)
27

28
var (
29
	_ Failer = &testing.T{}
30
	_ Failer = &testing.B{}
31
	_ Failer = &errorWrapper{}
32
)
33

34
// Failer is an interface to be provided to test functions of the form XXXOrFail. This is a
35
// substitute for testing.TB, which cannot be implemented outside of the testing
36
// package.
37
type Failer interface {
38
	Fail()
39
	FailNow()
40
	Fatal(args ...any)
41
	Fatalf(format string, args ...any)
42
	Log(args ...any)
43
	Logf(format string, args ...any)
44
	TempDir() string
45
	Helper()
46
	Cleanup(func())
47
	Skip(args ...any)
48
}
49

50
// Fuzzer abstracts *testing.F
51
type Fuzzer interface {
52
	Fuzz(ff any)
53
	Add(args ...any)
54
}
55

56
// errorWrapper is a Failer that can be used to just extract an `error`. This allows mixing
57
// functions that take in a Failer and those that take an error.
58
// The function must be called within a goroutine, or calls to Fatal will try to terminate the outer
59
// test context, which will cause the test to panic. The Wrap function handles this automatically
60
type errorWrapper struct {
61
	mu      sync.RWMutex
62
	failed  error
63
	cleanup func()
64
}
65

66
// Wrap executes a function with a fake Failer, and returns an error if the test failed. This allows
67
// calling functions that take a Failer and using them with functions that expect an error, or
68
// allowing calling functions that would cause a test to immediately fail to instead return an error.
69
// Wrap handles Cleanup() and short-circuiting of Fatal() just like the real testing.T.
70
func Wrap(f func(t Failer)) error {
71
	done := make(chan struct{})
72
	w := &errorWrapper{}
73
	go func() {
74
		defer close(done)
75
		f(w)
76
	}()
77
	<-done
78
	return w.ToErrorCleanup()
79
}
80

81
// ToErrorCleanup returns any errors encountered and executes any cleanup actions
82
func (e *errorWrapper) ToErrorCleanup() error {
83
	e.mu.RLock()
84
	defer e.mu.RUnlock()
85
	if e.cleanup != nil {
86
		e.cleanup()
87
	}
88
	return e.failed
89
}
90

91
func (e *errorWrapper) Fail() {
92
	e.Fatal("fail called")
93
}
94

95
func (e *errorWrapper) FailNow() {
96
	e.Fatal("fail now called")
97
}
98

99
func (e *errorWrapper) Fatal(args ...any) {
100
	e.mu.Lock()
101
	defer e.mu.Unlock()
102
	if e.failed == nil {
103
		e.failed = errors.New(fmt.Sprint(args...))
104
	}
105
	runtime.Goexit()
106
}
107

108
func (e *errorWrapper) Fatalf(format string, args ...any) {
109
	e.Fatal(fmt.Sprintf(format, args...))
110
}
111

112
func (e *errorWrapper) Helper() {
113
}
114

115
func (e *errorWrapper) Skip(args ...any) {
116
	e.Fatal(args...)
117
}
118

119
func (e *errorWrapper) Cleanup(f func()) {
120
	e.mu.Lock()
121
	defer e.mu.Unlock()
122
	oldCleanup := e.cleanup
123
	e.cleanup = func() {
124
		if oldCleanup != nil {
125
			defer func() {
126
				oldCleanup()
127
			}()
128
		}
129
		f()
130
	}
131
}
132

133
func (e *errorWrapper) Log(args ...any) {
134
	log.Info(fmt.Sprint(args...))
135
}
136

137
func (e *errorWrapper) Logf(format string, args ...any) {
138
	log.Infof(format, args...)
139
}
140

141
func (e *errorWrapper) TempDir() string {
142
	tempDir, err := os.MkdirTemp("", "test")
143
	if err == nil {
144
		e.Cleanup(func() {
145
			os.RemoveAll(tempDir)
146
		})
147
	}
148
	return tempDir
149
}
150

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.