Bump github.com/stretchr/testify from 1.8.1 to 1.8.4

Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.1 to 1.8.4.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.8.1...v1.8.4)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot] 2024-02-19 10:11:40 +00:00 committed by GitHub
parent 99c955a3f4
commit ae329e3a94
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 1275 additions and 785 deletions

2
go.mod
View File

@ -8,7 +8,7 @@ require (
github.com/opencontainers/runtime-spec v1.1.0 github.com/opencontainers/runtime-spec v1.1.0
github.com/pelletier/go-toml v1.9.5 github.com/pelletier/go-toml v1.9.5
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.8.1 github.com/stretchr/testify v1.8.4
github.com/urfave/cli/v2 v2.27.1 github.com/urfave/cli/v2 v2.27.1
gitlab.com/nvidia/cloud-native/go-nvlib v0.0.0-20230818092907-09424fdc8884 gitlab.com/nvidia/cloud-native/go-nvlib v0.0.0-20230818092907-09424fdc8884
golang.org/x/mod v0.15.0 golang.org/x/mod v0.15.0

8
go.sum
View File

@ -46,15 +46,11 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=

View File

@ -90,6 +90,23 @@ func EqualErrorf(t TestingT, theError error, errString string, msg string, args
return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...) return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...)
} }
// EqualExportedValuesf asserts that the types of two objects are equal and their public
// fields are also equal. This is useful for comparing structs that have private fields
// that could potentially differ.
//
// type S struct {
// Exported int
// notExported int
// }
// assert.EqualExportedValuesf(t, S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
// assert.EqualExportedValuesf(t, S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return EqualExportedValues(t, expected, actual, append([]interface{}{msg}, args...)...)
}
// EqualValuesf asserts that two objects are equal or convertable to the same types // EqualValuesf asserts that two objects are equal or convertable to the same types
// and equal. // and equal.
// //
@ -155,6 +172,31 @@ func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick
return Eventually(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) return Eventually(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...)
} }
// EventuallyWithTf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. In contrast to Eventually,
// it supplies a CollectT to the condition function, so that the condition
// function can use the CollectT to call other assertions.
// The condition is considered "met" if no errors are raised in a tick.
// The supplied CollectT collects all errors from one tick (if there are any).
// If the condition is not met before waitFor, the collected errors of
// the last tick are copied to t.
//
// externalValue := false
// go func() {
// time.Sleep(8*time.Second)
// externalValue = true
// }()
// assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
func EventuallyWithTf(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return EventuallyWithT(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...)
}
// Exactlyf asserts that two objects are equal in value and type. // Exactlyf asserts that two objects are equal in value and type.
// //
// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted") // assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted")

View File

@ -155,6 +155,40 @@ func (a *Assertions) EqualErrorf(theError error, errString string, msg string, a
return EqualErrorf(a.t, theError, errString, msg, args...) return EqualErrorf(a.t, theError, errString, msg, args...)
} }
// EqualExportedValues asserts that the types of two objects are equal and their public
// fields are also equal. This is useful for comparing structs that have private fields
// that could potentially differ.
//
// type S struct {
// Exported int
// notExported int
// }
// a.EqualExportedValues(S{1, 2}, S{1, 3}) => true
// a.EqualExportedValues(S{1, 2}, S{2, 3}) => false
func (a *Assertions) EqualExportedValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return EqualExportedValues(a.t, expected, actual, msgAndArgs...)
}
// EqualExportedValuesf asserts that the types of two objects are equal and their public
// fields are also equal. This is useful for comparing structs that have private fields
// that could potentially differ.
//
// type S struct {
// Exported int
// notExported int
// }
// a.EqualExportedValuesf(S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
// a.EqualExportedValuesf(S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return EqualExportedValuesf(a.t, expected, actual, msg, args...)
}
// EqualValues asserts that two objects are equal or convertable to the same types // EqualValues asserts that two objects are equal or convertable to the same types
// and equal. // and equal.
// //
@ -288,6 +322,56 @@ func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, ti
return Eventually(a.t, condition, waitFor, tick, msgAndArgs...) return Eventually(a.t, condition, waitFor, tick, msgAndArgs...)
} }
// EventuallyWithT asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. In contrast to Eventually,
// it supplies a CollectT to the condition function, so that the condition
// function can use the CollectT to call other assertions.
// The condition is considered "met" if no errors are raised in a tick.
// The supplied CollectT collects all errors from one tick (if there are any).
// If the condition is not met before waitFor, the collected errors of
// the last tick are copied to t.
//
// externalValue := false
// go func() {
// time.Sleep(8*time.Second)
// externalValue = true
// }()
// a.EventuallyWithT(func(c *assert.CollectT) {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
func (a *Assertions) EventuallyWithT(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return EventuallyWithT(a.t, condition, waitFor, tick, msgAndArgs...)
}
// EventuallyWithTf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. In contrast to Eventually,
// it supplies a CollectT to the condition function, so that the condition
// function can use the CollectT to call other assertions.
// The condition is considered "met" if no errors are raised in a tick.
// The supplied CollectT collects all errors from one tick (if there are any).
// If the condition is not met before waitFor, the collected errors of
// the last tick are copied to t.
//
// externalValue := false
// go func() {
// time.Sleep(8*time.Second)
// externalValue = true
// }()
// a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
func (a *Assertions) EventuallyWithTf(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return EventuallyWithTf(a.t, condition, waitFor, tick, msg, args...)
}
// Eventuallyf asserts that given condition will be met in waitFor time, // Eventuallyf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. // periodically checking target function each tick.
// //

View File

@ -8,7 +8,6 @@ import (
"fmt" "fmt"
"math" "math"
"os" "os"
"path/filepath"
"reflect" "reflect"
"regexp" "regexp"
"runtime" "runtime"
@ -76,6 +75,77 @@ func ObjectsAreEqual(expected, actual interface{}) bool {
return bytes.Equal(exp, act) return bytes.Equal(exp, act)
} }
// copyExportedFields iterates downward through nested data structures and creates a copy
// that only contains the exported struct fields.
func copyExportedFields(expected interface{}) interface{} {
if isNil(expected) {
return expected
}
expectedType := reflect.TypeOf(expected)
expectedKind := expectedType.Kind()
expectedValue := reflect.ValueOf(expected)
switch expectedKind {
case reflect.Struct:
result := reflect.New(expectedType).Elem()
for i := 0; i < expectedType.NumField(); i++ {
field := expectedType.Field(i)
isExported := field.IsExported()
if isExported {
fieldValue := expectedValue.Field(i)
if isNil(fieldValue) || isNil(fieldValue.Interface()) {
continue
}
newValue := copyExportedFields(fieldValue.Interface())
result.Field(i).Set(reflect.ValueOf(newValue))
}
}
return result.Interface()
case reflect.Ptr:
result := reflect.New(expectedType.Elem())
unexportedRemoved := copyExportedFields(expectedValue.Elem().Interface())
result.Elem().Set(reflect.ValueOf(unexportedRemoved))
return result.Interface()
case reflect.Array, reflect.Slice:
result := reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len())
for i := 0; i < expectedValue.Len(); i++ {
index := expectedValue.Index(i)
if isNil(index) {
continue
}
unexportedRemoved := copyExportedFields(index.Interface())
result.Index(i).Set(reflect.ValueOf(unexportedRemoved))
}
return result.Interface()
case reflect.Map:
result := reflect.MakeMap(expectedType)
for _, k := range expectedValue.MapKeys() {
index := expectedValue.MapIndex(k)
unexportedRemoved := copyExportedFields(index.Interface())
result.SetMapIndex(k, reflect.ValueOf(unexportedRemoved))
}
return result.Interface()
default:
return expected
}
}
// ObjectsExportedFieldsAreEqual determines if the exported (public) fields of two objects are
// considered equal. This comparison of only exported fields is applied recursively to nested data
// structures.
//
// This function does no assertion of any kind.
func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool {
expectedCleaned := copyExportedFields(expected)
actualCleaned := copyExportedFields(actual)
return ObjectsAreEqualValues(expectedCleaned, actualCleaned)
}
// ObjectsAreEqualValues gets whether two objects are equal, or if their // ObjectsAreEqualValues gets whether two objects are equal, or if their
// values are equal. // values are equal.
func ObjectsAreEqualValues(expected, actual interface{}) bool { func ObjectsAreEqualValues(expected, actual interface{}) bool {
@ -141,12 +211,11 @@ func CallerInfo() []string {
} }
parts := strings.Split(file, "/") parts := strings.Split(file, "/")
file = parts[len(parts)-1]
if len(parts) > 1 { if len(parts) > 1 {
filename := parts[len(parts)-1]
dir := parts[len(parts)-2] dir := parts[len(parts)-2]
if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" { if (dir != "assert" && dir != "mock" && dir != "require") || filename == "mock_test.go" {
path, _ := filepath.Abs(file) callers = append(callers, fmt.Sprintf("%s:%d", file, line))
callers = append(callers, fmt.Sprintf("%s:%d", path, line))
} }
} }
@ -475,6 +544,50 @@ func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interfa
} }
// EqualExportedValues asserts that the types of two objects are equal and their public
// fields are also equal. This is useful for comparing structs that have private fields
// that could potentially differ.
//
// type S struct {
// Exported int
// notExported int
// }
// assert.EqualExportedValues(t, S{1, 2}, S{1, 3}) => true
// assert.EqualExportedValues(t, S{1, 2}, S{2, 3}) => false
func EqualExportedValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
aType := reflect.TypeOf(expected)
bType := reflect.TypeOf(actual)
if aType != bType {
return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...)
}
if aType.Kind() != reflect.Struct {
return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...)
}
if bType.Kind() != reflect.Struct {
return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...)
}
expected = copyExportedFields(expected)
actual = copyExportedFields(actual)
if !ObjectsAreEqualValues(expected, actual) {
diff := diff(expected, actual)
expected, actual = formatUnequalValues(expected, actual)
return Fail(t, fmt.Sprintf("Not equal (comparing only exported fields): \n"+
"expected: %s\n"+
"actual : %s%s", expected, actual, diff), msgAndArgs...)
}
return true
}
// Exactly asserts that two objects are equal in value and type. // Exactly asserts that two objects are equal in value and type.
// //
// assert.Exactly(t, int32(123), int64(123)) // assert.Exactly(t, int32(123), int64(123))
@ -530,7 +643,7 @@ func isNil(object interface{}) bool {
[]reflect.Kind{ []reflect.Kind{
reflect.Chan, reflect.Func, reflect.Chan, reflect.Func,
reflect.Interface, reflect.Map, reflect.Interface, reflect.Map,
reflect.Ptr, reflect.Slice}, reflect.Ptr, reflect.Slice, reflect.UnsafePointer},
kind) kind)
if isNilableKind && value.IsNil() { if isNilableKind && value.IsNil() {
@ -796,10 +909,10 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{})
ok, found := containsElement(s, contains) ok, found := containsElement(s, contains)
if !ok { if !ok {
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...)
} }
if found { if found {
return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...) return Fail(t, fmt.Sprintf("%#v should not contain %#v", s, contains), msgAndArgs...)
} }
return true return true
@ -818,49 +931,44 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
return true // we consider nil to be equal to the nil set return true // we consider nil to be equal to the nil set
} }
defer func() {
if e := recover(); e != nil {
ok = false
}
}()
listKind := reflect.TypeOf(list).Kind() listKind := reflect.TypeOf(list).Kind()
subsetKind := reflect.TypeOf(subset).Kind()
if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map { if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map {
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
} }
subsetKind := reflect.TypeOf(subset).Kind()
if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map { if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map {
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
} }
subsetValue := reflect.ValueOf(subset)
if subsetKind == reflect.Map && listKind == reflect.Map { if subsetKind == reflect.Map && listKind == reflect.Map {
listValue := reflect.ValueOf(list) subsetMap := reflect.ValueOf(subset)
subsetKeys := subsetValue.MapKeys() actualMap := reflect.ValueOf(list)
for i := 0; i < len(subsetKeys); i++ { for _, k := range subsetMap.MapKeys() {
subsetKey := subsetKeys[i] ev := subsetMap.MapIndex(k)
subsetElement := subsetValue.MapIndex(subsetKey).Interface() av := actualMap.MapIndex(k)
listElement := listValue.MapIndex(subsetKey).Interface()
if !ObjectsAreEqual(subsetElement, listElement) { if !av.IsValid() {
return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, subsetElement), msgAndArgs...) return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...)
}
if !ObjectsAreEqual(ev.Interface(), av.Interface()) {
return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...)
} }
} }
return true return true
} }
for i := 0; i < subsetValue.Len(); i++ { subsetList := reflect.ValueOf(subset)
element := subsetValue.Index(i).Interface() for i := 0; i < subsetList.Len(); i++ {
element := subsetList.Index(i).Interface()
ok, found := containsElement(list, element) ok, found := containsElement(list, element)
if !ok { if !ok {
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", list), msgAndArgs...)
} }
if !found { if !found {
return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, element), msgAndArgs...) return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, element), msgAndArgs...)
} }
} }
@ -879,34 +987,28 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
return Fail(t, "nil is the empty set which is a subset of every set", msgAndArgs...) return Fail(t, "nil is the empty set which is a subset of every set", msgAndArgs...)
} }
defer func() {
if e := recover(); e != nil {
ok = false
}
}()
listKind := reflect.TypeOf(list).Kind() listKind := reflect.TypeOf(list).Kind()
subsetKind := reflect.TypeOf(subset).Kind()
if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map { if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map {
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
} }
subsetKind := reflect.TypeOf(subset).Kind()
if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map { if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map {
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
} }
subsetValue := reflect.ValueOf(subset)
if subsetKind == reflect.Map && listKind == reflect.Map { if subsetKind == reflect.Map && listKind == reflect.Map {
listValue := reflect.ValueOf(list) subsetMap := reflect.ValueOf(subset)
subsetKeys := subsetValue.MapKeys() actualMap := reflect.ValueOf(list)
for i := 0; i < len(subsetKeys); i++ { for _, k := range subsetMap.MapKeys() {
subsetKey := subsetKeys[i] ev := subsetMap.MapIndex(k)
subsetElement := subsetValue.MapIndex(subsetKey).Interface() av := actualMap.MapIndex(k)
listElement := listValue.MapIndex(subsetKey).Interface()
if !ObjectsAreEqual(subsetElement, listElement) { if !av.IsValid() {
return true
}
if !ObjectsAreEqual(ev.Interface(), av.Interface()) {
return true return true
} }
} }
@ -914,8 +1016,9 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...) return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
} }
for i := 0; i < subsetValue.Len(); i++ { subsetList := reflect.ValueOf(subset)
element := subsetValue.Index(i).Interface() for i := 0; i < subsetList.Len(); i++ {
element := subsetList.Index(i).Interface()
ok, found := containsElement(list, element) ok, found := containsElement(list, element)
if !ok { if !ok {
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)
@ -1756,6 +1859,89 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t
} }
} }
// CollectT implements the TestingT interface and collects all errors.
type CollectT struct {
errors []error
}
// Errorf collects the error.
func (c *CollectT) Errorf(format string, args ...interface{}) {
c.errors = append(c.errors, fmt.Errorf(format, args...))
}
// FailNow panics.
func (c *CollectT) FailNow() {
panic("Assertion failed")
}
// Reset clears the collected errors.
func (c *CollectT) Reset() {
c.errors = nil
}
// Copy copies the collected errors to the supplied t.
func (c *CollectT) Copy(t TestingT) {
if tt, ok := t.(tHelper); ok {
tt.Helper()
}
for _, err := range c.errors {
t.Errorf("%v", err)
}
}
// EventuallyWithT asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. In contrast to Eventually,
// it supplies a CollectT to the condition function, so that the condition
// function can use the CollectT to call other assertions.
// The condition is considered "met" if no errors are raised in a tick.
// The supplied CollectT collects all errors from one tick (if there are any).
// If the condition is not met before waitFor, the collected errors of
// the last tick are copied to t.
//
// externalValue := false
// go func() {
// time.Sleep(8*time.Second)
// externalValue = true
// }()
// assert.EventuallyWithT(t, func(c *assert.CollectT) {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
collect := new(CollectT)
ch := make(chan bool, 1)
timer := time.NewTimer(waitFor)
defer timer.Stop()
ticker := time.NewTicker(tick)
defer ticker.Stop()
for tick := ticker.C; ; {
select {
case <-timer.C:
collect.Copy(t)
return Fail(t, "Condition never satisfied", msgAndArgs...)
case <-tick:
tick = nil
collect.Reset()
go func() {
condition(collect)
ch <- len(collect.errors) == 0
}()
case v := <-ch:
if v {
return true
}
tick = ticker.C
}
}
}
// Never asserts that the given condition doesn't satisfy in waitFor time, // Never asserts that the given condition doesn't satisfy in waitFor time,
// periodically checking the target function each tick. // periodically checking the target function each tick.
// //

View File

@ -1,8 +1,9 @@
// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. // Package assert provides a set of comprehensive testing tools for use with the normal Go testing system.
// //
// Example Usage // # Example Usage
// //
// The following is a complete example using assert in a standard test function: // The following is a complete example using assert in a standard test function:
//
// import ( // import (
// "testing" // "testing"
// "github.com/stretchr/testify/assert" // "github.com/stretchr/testify/assert"
@ -33,7 +34,7 @@
// assert.Equal(a, b, "The two words should be the same.") // assert.Equal(a, b, "The two words should be the same.")
// } // }
// //
// Assertions // # Assertions
// //
// Assertions allow you to easily write test code, and are global funcs in the `assert` package. // Assertions allow you to easily write test code, and are global funcs in the `assert` package.
// All assertion functions take, as the first argument, the `*testing.T` object provided by the // All assertion functions take, as the first argument, the `*testing.T` object provided by the

View File

@ -1,9 +1,10 @@
// Package require implements the same assertions as the `assert` package but // Package require implements the same assertions as the `assert` package but
// stops test execution when a test fails. // stops test execution when a test fails.
// //
// Example Usage // # Example Usage
// //
// The following is a complete example using require in a standard test function: // The following is a complete example using require in a standard test function:
//
// import ( // import (
// "testing" // "testing"
// "github.com/stretchr/testify/require" // "github.com/stretchr/testify/require"
@ -18,7 +19,7 @@
// //
// } // }
// //
// Assertions // # Assertions
// //
// The `require` package have same global functions as in the `assert` package, // The `require` package have same global functions as in the `assert` package,
// but instead of returning a boolean result they call `t.FailNow()`. // but instead of returning a boolean result they call `t.FailNow()`.

View File

@ -195,6 +195,46 @@ func EqualErrorf(t TestingT, theError error, errString string, msg string, args
t.FailNow() t.FailNow()
} }
// EqualExportedValues asserts that the types of two objects are equal and their public
// fields are also equal. This is useful for comparing structs that have private fields
// that could potentially differ.
//
// type S struct {
// Exported int
// notExported int
// }
// assert.EqualExportedValues(t, S{1, 2}, S{1, 3}) => true
// assert.EqualExportedValues(t, S{1, 2}, S{2, 3}) => false
func EqualExportedValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if assert.EqualExportedValues(t, expected, actual, msgAndArgs...) {
return
}
t.FailNow()
}
// EqualExportedValuesf asserts that the types of two objects are equal and their public
// fields are also equal. This is useful for comparing structs that have private fields
// that could potentially differ.
//
// type S struct {
// Exported int
// notExported int
// }
// assert.EqualExportedValuesf(t, S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
// assert.EqualExportedValuesf(t, S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if assert.EqualExportedValuesf(t, expected, actual, msg, args...) {
return
}
t.FailNow()
}
// EqualValues asserts that two objects are equal or convertable to the same types // EqualValues asserts that two objects are equal or convertable to the same types
// and equal. // and equal.
// //
@ -364,6 +404,62 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t
t.FailNow() t.FailNow()
} }
// EventuallyWithT asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. In contrast to Eventually,
// it supplies a CollectT to the condition function, so that the condition
// function can use the CollectT to call other assertions.
// The condition is considered "met" if no errors are raised in a tick.
// The supplied CollectT collects all errors from one tick (if there are any).
// If the condition is not met before waitFor, the collected errors of
// the last tick are copied to t.
//
// externalValue := false
// go func() {
// time.Sleep(8*time.Second)
// externalValue = true
// }()
// assert.EventuallyWithT(t, func(c *assert.CollectT) {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
func EventuallyWithT(t TestingT, condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if assert.EventuallyWithT(t, condition, waitFor, tick, msgAndArgs...) {
return
}
t.FailNow()
}
// EventuallyWithTf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. In contrast to Eventually,
// it supplies a CollectT to the condition function, so that the condition
// function can use the CollectT to call other assertions.
// The condition is considered "met" if no errors are raised in a tick.
// The supplied CollectT collects all errors from one tick (if there are any).
// If the condition is not met before waitFor, the collected errors of
// the last tick are copied to t.
//
// externalValue := false
// go func() {
// time.Sleep(8*time.Second)
// externalValue = true
// }()
// assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
func EventuallyWithTf(t TestingT, condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if assert.EventuallyWithTf(t, condition, waitFor, tick, msg, args...) {
return
}
t.FailNow()
}
// Eventuallyf asserts that given condition will be met in waitFor time, // Eventuallyf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. // periodically checking target function each tick.
// //

View File

@ -156,6 +156,40 @@ func (a *Assertions) EqualErrorf(theError error, errString string, msg string, a
EqualErrorf(a.t, theError, errString, msg, args...) EqualErrorf(a.t, theError, errString, msg, args...)
} }
// EqualExportedValues asserts that the types of two objects are equal and their public
// fields are also equal. This is useful for comparing structs that have private fields
// that could potentially differ.
//
// type S struct {
// Exported int
// notExported int
// }
// a.EqualExportedValues(S{1, 2}, S{1, 3}) => true
// a.EqualExportedValues(S{1, 2}, S{2, 3}) => false
func (a *Assertions) EqualExportedValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
EqualExportedValues(a.t, expected, actual, msgAndArgs...)
}
// EqualExportedValuesf asserts that the types of two objects are equal and their public
// fields are also equal. This is useful for comparing structs that have private fields
// that could potentially differ.
//
// type S struct {
// Exported int
// notExported int
// }
// a.EqualExportedValuesf(S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
// a.EqualExportedValuesf(S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
EqualExportedValuesf(a.t, expected, actual, msg, args...)
}
// EqualValues asserts that two objects are equal or convertable to the same types // EqualValues asserts that two objects are equal or convertable to the same types
// and equal. // and equal.
// //
@ -289,6 +323,56 @@ func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, ti
Eventually(a.t, condition, waitFor, tick, msgAndArgs...) Eventually(a.t, condition, waitFor, tick, msgAndArgs...)
} }
// EventuallyWithT asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. In contrast to Eventually,
// it supplies a CollectT to the condition function, so that the condition
// function can use the CollectT to call other assertions.
// The condition is considered "met" if no errors are raised in a tick.
// The supplied CollectT collects all errors from one tick (if there are any).
// If the condition is not met before waitFor, the collected errors of
// the last tick are copied to t.
//
// externalValue := false
// go func() {
// time.Sleep(8*time.Second)
// externalValue = true
// }()
// a.EventuallyWithT(func(c *assert.CollectT) {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
func (a *Assertions) EventuallyWithT(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
EventuallyWithT(a.t, condition, waitFor, tick, msgAndArgs...)
}
// EventuallyWithTf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. In contrast to Eventually,
// it supplies a CollectT to the condition function, so that the condition
// function can use the CollectT to call other assertions.
// The condition is considered "met" if no errors are raised in a tick.
// The supplied CollectT collects all errors from one tick (if there are any).
// If the condition is not met before waitFor, the collected errors of
// the last tick are copied to t.
//
// externalValue := false
// go func() {
// time.Sleep(8*time.Second)
// externalValue = true
// }()
// a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
func (a *Assertions) EventuallyWithTf(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
EventuallyWithTf(a.t, condition, waitFor, tick, msg, args...)
}
// Eventuallyf asserts that given condition will be met in waitFor time, // Eventuallyf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. // periodically checking target function each tick.
// //

4
vendor/modules.txt vendored
View File

@ -38,8 +38,8 @@ github.com/russross/blackfriday/v2
## explicit; go 1.13 ## explicit; go 1.13
github.com/sirupsen/logrus github.com/sirupsen/logrus
github.com/sirupsen/logrus/hooks/test github.com/sirupsen/logrus/hooks/test
# github.com/stretchr/testify v1.8.1 # github.com/stretchr/testify v1.8.4
## explicit; go 1.13 ## explicit; go 1.20
github.com/stretchr/testify/assert github.com/stretchr/testify/assert
github.com/stretchr/testify/require github.com/stretchr/testify/require
# github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 # github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635