podman

Форк
0
161 строка · 5.6 Кб
1
package internal
2

3
import (
4
	"fmt"
5
	"reflect"
6

7
	"github.com/onsi/gomega/format"
8
	"github.com/onsi/gomega/types"
9
)
10

11
type Assertion struct {
12
	actuals     []interface{} // actual value plus all extra values
13
	actualIndex int           // value to pass to the matcher
14
	vet         vetinari      // the vet to call before calling Gomega matcher
15
	offset      int
16
	g           *Gomega
17
}
18

19
// ...obligatory discworld reference, as "vetineer" doesn't sound ... quite right.
20
type vetinari func(assertion *Assertion, optionalDescription ...interface{}) bool
21

22
func NewAssertion(actualInput interface{}, g *Gomega, offset int, extra ...interface{}) *Assertion {
23
	return &Assertion{
24
		actuals:     append([]interface{}{actualInput}, extra...),
25
		actualIndex: 0,
26
		vet:         (*Assertion).vetActuals,
27
		offset:      offset,
28
		g:           g,
29
	}
30
}
31

32
func (assertion *Assertion) WithOffset(offset int) types.Assertion {
33
	assertion.offset = offset
34
	return assertion
35
}
36

37
func (assertion *Assertion) Error() types.Assertion {
38
	return &Assertion{
39
		actuals:     assertion.actuals,
40
		actualIndex: len(assertion.actuals) - 1,
41
		vet:         (*Assertion).vetError,
42
		offset:      assertion.offset,
43
		g:           assertion.g,
44
	}
45
}
46

47
func (assertion *Assertion) Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
48
	assertion.g.THelper()
49
	vetOptionalDescription("Assertion", optionalDescription...)
50
	return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, true, optionalDescription...)
51
}
52

53
func (assertion *Assertion) ShouldNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
54
	assertion.g.THelper()
55
	vetOptionalDescription("Assertion", optionalDescription...)
56
	return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
57
}
58

59
func (assertion *Assertion) To(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
60
	assertion.g.THelper()
61
	vetOptionalDescription("Assertion", optionalDescription...)
62
	return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, true, optionalDescription...)
63
}
64

65
func (assertion *Assertion) ToNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
66
	assertion.g.THelper()
67
	vetOptionalDescription("Assertion", optionalDescription...)
68
	return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
69
}
70

71
func (assertion *Assertion) NotTo(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
72
	assertion.g.THelper()
73
	vetOptionalDescription("Assertion", optionalDescription...)
74
	return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
75
}
76

77
func (assertion *Assertion) buildDescription(optionalDescription ...interface{}) string {
78
	switch len(optionalDescription) {
79
	case 0:
80
		return ""
81
	case 1:
82
		if describe, ok := optionalDescription[0].(func() string); ok {
83
			return describe() + "\n"
84
		}
85
	}
86
	return fmt.Sprintf(optionalDescription[0].(string), optionalDescription[1:]...) + "\n"
87
}
88

89
func (assertion *Assertion) match(matcher types.GomegaMatcher, desiredMatch bool, optionalDescription ...interface{}) bool {
90
	actualInput := assertion.actuals[assertion.actualIndex]
91
	matches, err := matcher.Match(actualInput)
92
	assertion.g.THelper()
93
	if err != nil {
94
		description := assertion.buildDescription(optionalDescription...)
95
		assertion.g.Fail(description+err.Error(), 2+assertion.offset)
96
		return false
97
	}
98
	if matches != desiredMatch {
99
		var message string
100
		if desiredMatch {
101
			message = matcher.FailureMessage(actualInput)
102
		} else {
103
			message = matcher.NegatedFailureMessage(actualInput)
104
		}
105
		description := assertion.buildDescription(optionalDescription...)
106
		assertion.g.Fail(description+message, 2+assertion.offset)
107
		return false
108
	}
109

110
	return true
111
}
112

113
// vetActuals vets the actual values, with the (optional) exception of a
114
// specific value, such as the first value in case non-error assertions, or the
115
// last value in case of Error()-based assertions.
116
func (assertion *Assertion) vetActuals(optionalDescription ...interface{}) bool {
117
	success, message := vetActuals(assertion.actuals, assertion.actualIndex)
118
	if success {
119
		return true
120
	}
121

122
	description := assertion.buildDescription(optionalDescription...)
123
	assertion.g.THelper()
124
	assertion.g.Fail(description+message, 2+assertion.offset)
125
	return false
126
}
127

128
// vetError vets the actual values, except for the final error value, in case
129
// the final error value is non-zero. Otherwise, it doesn't vet the actual
130
// values, as these are allowed to take on any values unless there is a non-zero
131
// error value.
132
func (assertion *Assertion) vetError(optionalDescription ...interface{}) bool {
133
	if err := assertion.actuals[assertion.actualIndex]; err != nil {
134
		// Go error result idiom: all other actual values must be zero values.
135
		return assertion.vetActuals(optionalDescription...)
136
	}
137
	return true
138
}
139

140
// vetActuals vets a slice of actual values, optionally skipping a particular
141
// value slice element, such as the first or last value slice element.
142
func vetActuals(actuals []interface{}, skipIndex int) (bool, string) {
143
	for i, actual := range actuals {
144
		if i == skipIndex {
145
			continue
146
		}
147
		if actual != nil {
148
			zeroValue := reflect.Zero(reflect.TypeOf(actual)).Interface()
149
			if !reflect.DeepEqual(zeroValue, actual) {
150
				var message string
151
				if err, ok := actual.(error); ok {
152
					message = fmt.Sprintf("Unexpected error: %s\n%s", err, format.Object(err, 1))
153
				} else {
154
					message = fmt.Sprintf("Unexpected non-nil/non-zero argument at index %d:\n\t<%T>: %#v", i, actual, actual)
155
				}
156
				return false, message
157
			}
158
		}
159
	}
160
	return true, ""
161
}
162

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

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

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

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