rebase: bump the github-dependencies group across 1 directory with 9 updates

Bumps the github-dependencies group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [github.com/IBM/keyprotect-go-client](https://github.com/IBM/keyprotect-go-client) | `0.12.2` | `0.14.1` |
| [github.com/aws/aws-sdk-go](https://github.com/aws/aws-sdk-go) | `1.53.14` | `1.54.6` |
| [github.com/aws/aws-sdk-go-v2/service/sts](https://github.com/aws/aws-sdk-go-v2) | `1.28.1` | `1.29.1` |
| [github.com/hashicorp/vault/api](https://github.com/hashicorp/vault) | `1.12.0` | `1.14.0` |
| [github.com/kubernetes-csi/csi-lib-utils](https://github.com/kubernetes-csi/csi-lib-utils) | `0.17.0` | `0.18.1` |
| [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) | `2.17.1` | `2.19.0` |
| [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) | `1.18.0` | `1.19.1` |
| [github.com/Azure/azure-sdk-for-go/sdk/azidentity](https://github.com/Azure/azure-sdk-for-go) | `1.6.0` | `1.7.0` |

Updates `github.com/IBM/keyprotect-go-client` from 0.12.2 to 0.14.1
- [Release notes](https://github.com/IBM/keyprotect-go-client/releases)
- [Changelog](https://github.com/IBM/keyprotect-go-client/blob/master/CHANGELOG.md)
- [Commits](https://github.com/IBM/keyprotect-go-client/compare/v0.12.2...v0.14.1)

Updates `github.com/aws/aws-sdk-go` from 1.53.14 to 1.54.6
- [Release notes](https://github.com/aws/aws-sdk-go/releases)
- [Commits](https://github.com/aws/aws-sdk-go/compare/v1.53.14...v1.54.6)

Updates `github.com/aws/aws-sdk-go-v2/service/sts` from 1.28.1 to 1.29.1
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/ecr/v1.28.1...service/s3/v1.29.1)

Updates `github.com/hashicorp/vault/api` from 1.12.0 to 1.14.0
- [Release notes](https://github.com/hashicorp/vault/releases)
- [Changelog](https://github.com/hashicorp/vault/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/vault/compare/v1.12.0...v1.14.0)

Updates `github.com/kubernetes-csi/csi-lib-utils` from 0.17.0 to 0.18.1
- [Release notes](https://github.com/kubernetes-csi/csi-lib-utils/releases)
- [Commits](https://github.com/kubernetes-csi/csi-lib-utils/compare/v0.17.0...v0.18.1)

Updates `github.com/onsi/ginkgo/v2` from 2.17.1 to 2.19.0
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.17.1...v2.19.0)

Updates `github.com/onsi/gomega` from 1.32.0 to 1.33.1
- [Release notes](https://github.com/onsi/gomega/releases)
- [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/gomega/compare/v1.32.0...v1.33.1)

Updates `github.com/prometheus/client_golang` from 1.18.0 to 1.19.1
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.18.0...v1.19.1)

Updates `github.com/Azure/azure-sdk-for-go/sdk/azidentity` from 1.6.0 to 1.7.0
- [Release notes](https://github.com/Azure/azure-sdk-for-go/releases)
- [Changelog](https://github.com/Azure/azure-sdk-for-go/blob/main/documentation/release.md)
- [Commits](https://github.com/Azure/azure-sdk-for-go/compare/sdk/azcore/v1.6.0...sdk/azcore/v1.7.0)

---
updated-dependencies:
- dependency-name: github.com/IBM/keyprotect-go-client
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-dependencies
- dependency-name: github.com/aws/aws-sdk-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-dependencies
- dependency-name: github.com/aws/aws-sdk-go-v2/service/sts
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-dependencies
- dependency-name: github.com/hashicorp/vault/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-dependencies
- dependency-name: github.com/kubernetes-csi/csi-lib-utils
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-dependencies
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-dependencies
- dependency-name: github.com/onsi/gomega
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-dependencies
- dependency-name: github.com/prometheus/client_golang
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-dependencies
- dependency-name: github.com/Azure/azure-sdk-for-go/sdk/azidentity
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot]
2024-06-24 20:58:34 +00:00
committed by mergify[bot]
parent 29dde7abc2
commit 171ba6a65d
193 changed files with 6071 additions and 2336 deletions

View File

@ -1,3 +1,48 @@
## 2.19.0
### Features
[Label Sets](https://onsi.github.io/ginkgo/#label-sets) allow for more expressive and flexible label filtering.
## 2.18.0
### Features
- Add --slience-skips and --force-newlines [f010b65]
- fail when no tests were run and --fail-on-empty was set [d80eebe]
### Fixes
- Fix table entry context edge case [42013d6]
### Maintenance
- Bump golang.org/x/tools from 0.20.0 to 0.21.0 (#1406) [fcf1fd7]
- Bump github.com/onsi/gomega from 1.33.0 to 1.33.1 (#1399) [8bb14fd]
- Bump golang.org/x/net from 0.24.0 to 0.25.0 (#1407) [04bfad7]
## 2.17.3
### Fixes
`ginkgo watch` now ignores hidden files [bde6e00]
## 2.17.2
### Fixes
- fix: close files [32259c8]
- fix github output log level for skipped specs [780e7a3]
### Maintenance
- Bump github.com/google/pprof [d91fe4e]
- Bump github.com/go-task/slim-sprig to v3 [8cb662e]
- Bump golang.org/x/net in /integration/_fixtures/version_mismatch_fixture (#1391) [3134422]
- Bump github-pages from 230 to 231 in /docs (#1384) [eca81b4]
- Bump golang.org/x/tools from 0.19.0 to 0.20.0 (#1383) [760def8]
- Bump golang.org/x/net from 0.23.0 to 0.24.0 (#1381) [4ce33f4]
- Fix test for gomega version bump [f2fcd97]
- Bump github.com/onsi/gomega from 1.30.0 to 1.33.0 (#1390) [fd622d2]
- Bump golang.org/x/tools from 0.17.0 to 0.19.0 (#1368) [5474a26]
- Bump github-pages from 229 to 230 in /docs (#1359) [e6d1170]
- Bump google.golang.org/protobuf from 1.28.0 to 1.33.0 (#1374) [7f447b2]
- Bump golang.org/x/net from 0.20.0 to 0.23.0 (#1380) [f15239a]
## 2.17.1
### Fixes

View File

@ -6,8 +6,10 @@ Your contributions to Ginkgo are essential for its long-term maintenance and imp
- Ensure adequate test coverage:
- When adding to the Ginkgo library, add unit and/or integration tests (under the `integration` folder).
- When adding to the Ginkgo CLI, note that there are very few unit tests. Please add an integration test.
- Make sure all the tests succeed via `ginkgo -r -p`
- Vet your changes via `go vet ./...`
- Update the documentation. Ginkgo uses `godoc` comments and documentation in `docs/index.md`. You can run `bundle exec jekyll serve` in the `docs` directory to preview your changes.
- Run `make` or:
- Install ginkgo locally via `go install ./...`
- Make sure all the tests succeed via `ginkgo -r -p`
- Vet your changes via `go vet ./...`
- Update the documentation. Ginkgo uses `godoc` comments and documentation in `docs/index.md`. You can run `bundle && bundle exec jekyll serve` in the `docs` directory to preview your changes.
Thanks for supporting Ginkgo!
Thanks for supporting Ginkgo!

11
vendor/github.com/onsi/ginkgo/v2/Makefile generated vendored Normal file
View File

@ -0,0 +1,11 @@
# default task since it's first
.PHONY: all
all: vet test
.PHONY: test
test:
go run github.com/onsi/ginkgo/v2/ginkgo -r -p
.PHONY: vet
vet:
go vet ./...

View File

@ -7,7 +7,7 @@ import (
"os"
"text/template"
sprig "github.com/go-task/slim-sprig"
sprig "github.com/go-task/slim-sprig/v3"
"github.com/onsi/ginkgo/v2/ginkgo/command"
"github.com/onsi/ginkgo/v2/ginkgo/internal"
"github.com/onsi/ginkgo/v2/types"

View File

@ -10,7 +10,7 @@ import (
"strings"
"text/template"
sprig "github.com/go-task/slim-sprig"
sprig "github.com/go-task/slim-sprig/v3"
"github.com/onsi/ginkgo/v2/ginkgo/command"
"github.com/onsi/ginkgo/v2/ginkgo/internal"
"github.com/onsi/ginkgo/v2/types"
@ -174,6 +174,7 @@ func moduleName(modRoot string) string {
if err != nil {
return ""
}
defer modFile.Close()
mod := make([]byte, 128)
_, err = modFile.Read(mod)

View File

@ -161,6 +161,7 @@ func MergeAndCleanupCoverProfiles(profiles []string, destination string) error {
if err != nil {
return err
}
defer dst.Close()
err = DumpCoverProfiles(merged, dst)
if err != nil {
return err
@ -196,6 +197,7 @@ func MergeProfiles(profilePaths []string, destination string) error {
return fmt.Errorf("Could not open profile: %s\n%s", profilePath, err.Error())
}
prof, err := profile.Parse(proFile)
_ = proFile.Close()
if err != nil {
return fmt.Errorf("Could not parse profile: %s\n%s", profilePath, err.Error())
}

View File

@ -4,6 +4,7 @@ import (
"fmt"
"os"
"regexp"
"strings"
"time"
)
@ -79,6 +80,10 @@ func (p *PackageHash) computeHashes() (codeHash string, codeModifiedTime time.Ti
continue
}
if isHiddenFile(info) {
continue
}
if goTestRegExp.MatchString(info.Name()) {
testHash += p.hashForFileInfo(info)
if info.ModTime().After(testModifiedTime) {
@ -103,6 +108,10 @@ func (p *PackageHash) computeHashes() (codeHash string, codeModifiedTime time.Ti
return
}
func isHiddenFile(info os.FileInfo) bool {
return strings.HasPrefix(info.Name(), ".") || strings.HasPrefix(info.Name(), "_")
}
func (p *PackageHash) hashForFileInfo(info os.FileInfo) string {
return fmt.Sprintf("%s_%d_%d", info.Name(), info.Size(), info.ModTime().UnixNano())
}

View File

@ -489,10 +489,15 @@ func (suite *Suite) runSpecs(description string, suiteLabels Labels, suitePath s
newGroup(suite).run(specs.AtIndices(groupedSpecIndices[groupedSpecIdx]))
}
if specs.HasAnySpecsMarkedPending() && suite.config.FailOnPending {
if suite.config.FailOnPending && specs.HasAnySpecsMarkedPending() {
suite.report.SpecialSuiteFailureReasons = append(suite.report.SpecialSuiteFailureReasons, "Detected pending specs and --fail-on-pending is set")
suite.report.SuiteSucceeded = false
}
if suite.config.FailOnEmpty && specs.CountWithoutSkip() == 0 {
suite.report.SpecialSuiteFailureReasons = append(suite.report.SpecialSuiteFailureReasons, "Detected no specs ran and --fail-on-empty is set")
suite.report.SuiteSucceeded = false
}
}
if ranBeforeSuite {

View File

@ -202,6 +202,11 @@ func (r *DefaultReporter) DidRun(report types.SpecReport) {
v := r.conf.Verbosity()
inParallel := report.RunningInParallel
//should we completely omit this spec?
if report.State.Is(types.SpecStateSkipped) && r.conf.SilenceSkips {
return
}
header := r.specDenoter
if report.LeafNodeType.Is(types.NodeTypesForSuiteLevelNodes) {
header = fmt.Sprintf("[%s]", report.LeafNodeType)
@ -278,9 +283,12 @@ func (r *DefaultReporter) DidRun(report types.SpecReport) {
}
}
// If we have no content to show, jsut emit the header and return
// If we have no content to show, just emit the header and return
if !reportHasContent {
r.emit(r.f(highlightColor + header + "{{/}}"))
if r.conf.ForceNewlines {
r.emit("\n")
}
return
}
@ -419,7 +427,11 @@ func (r *DefaultReporter) emitFailure(indent uint, state types.SpecState, failur
highlightColor := r.highlightColorForState(state)
r.emitBlock(r.fi(indent, highlightColor+"[%s] %s{{/}}", r.humanReadableState(state), failure.Message))
if r.conf.GithubOutput {
r.emitBlock(r.fi(indent, "::error file=%s,line=%d::%s %s", failure.Location.FileName, failure.Location.LineNumber, failure.FailureNodeType, failure.TimelineLocation.Time.Format(types.GINKGO_TIME_FORMAT)))
level := "error"
if state.Is(types.SpecStateSkipped) {
level = "notice"
}
r.emitBlock(r.fi(indent, "::%s file=%s,line=%d::%s %s", level, failure.Location.FileName, failure.Location.LineNumber, failure.FailureNodeType, failure.TimelineLocation.Time.Format(types.GINKGO_TIME_FORMAT)))
} else {
r.emitBlock(r.fi(indent, highlightColor+"In {{bold}}[%s]{{/}}"+highlightColor+" at: {{bold}}%s{{/}} {{gray}}@ %s{{/}}\n", failure.FailureNodeType, failure.Location, failure.TimelineLocation.Time.Format(types.GINKGO_TIME_FORMAT)))
}

View File

@ -177,6 +177,7 @@ func GenerateJUnitReportWithConfig(report types.Report, dst string, config Junit
{"FocusFiles", strings.Join(report.SuiteConfig.FocusFiles, ";")},
{"SkipFiles", strings.Join(report.SuiteConfig.SkipFiles, ";")},
{"FailOnPending", fmt.Sprintf("%t", report.SuiteConfig.FailOnPending)},
{"FailOnEmpty", fmt.Sprintf("%t", report.SuiteConfig.FailOnEmpty)},
{"FailFast", fmt.Sprintf("%t", report.SuiteConfig.FailFast)},
{"FlakeAttempts", fmt.Sprintf("%d", report.SuiteConfig.FlakeAttempts)},
{"DryRun", fmt.Sprintf("%t", report.SuiteConfig.DryRun)},
@ -324,6 +325,7 @@ func MergeAndCleanupJUnitReports(sources []string, dst string) ([]string, error)
continue
}
err = xml.NewDecoder(f).Decode(&report)
_ = f.Close()
if err != nil {
messages = append(messages, fmt.Sprintf("Could not decode %s:\n%s", source, err.Error()))
continue

View File

@ -269,11 +269,15 @@ func generateTable(description string, isSubtree bool, args ...interface{}) {
internalNodeArgs = append(internalNodeArgs, entry.decorations...)
hasContext := false
if internalBodyType.NumIn() > 0. {
if internalBodyType.NumIn() > 0 {
if internalBodyType.In(0).Implements(specContextType) {
hasContext = true
} else if internalBodyType.In(0).Implements(contextType) && (len(entry.parameters) == 0 || !reflect.TypeOf(entry.parameters[0]).Implements(contextType)) {
} else if internalBodyType.In(0).Implements(contextType) {
hasContext = true
if len(entry.parameters) > 0 && reflect.TypeOf(entry.parameters[0]) != nil && reflect.TypeOf(entry.parameters[0]).Implements(contextType) {
// we allow you to pass in a non-nil context
hasContext = false
}
}
}

View File

@ -25,6 +25,7 @@ type SuiteConfig struct {
SkipFiles []string
LabelFilter string
FailOnPending bool
FailOnEmpty bool
FailFast bool
FlakeAttempts int
MustPassRepeatedly int
@ -90,6 +91,8 @@ type ReporterConfig struct {
FullTrace bool
ShowNodeEvents bool
GithubOutput bool
SilenceSkips bool
ForceNewlines bool
JSONReport string
JUnitReport string
@ -275,6 +278,8 @@ var SuiteConfigFlags = GinkgoFlags{
Usage: "If set, ginkgo will stop running a test suite after a failure occurs."},
{KeyPath: "S.FlakeAttempts", Name: "flake-attempts", SectionKey: "failure", UsageDefaultValue: "0 - failed tests are not retried", DeprecatedName: "flakeAttempts", DeprecatedDocLink: "changed-command-line-flags",
Usage: "Make up to this many attempts to run each spec. If any of the attempts succeed, the suite will not be failed."},
{KeyPath: "S.FailOnEmpty", Name: "fail-on-empty", SectionKey: "failure",
Usage: "If set, ginkgo will mark the test suite as failed if no specs are run."},
{KeyPath: "S.DryRun", Name: "dry-run", SectionKey: "debug", DeprecatedName: "dryRun", DeprecatedDocLink: "changed-command-line-flags",
Usage: "If set, ginkgo will walk the test hierarchy without actually running anything. Best paired with -v."},
@ -334,6 +339,10 @@ var ReporterConfigFlags = GinkgoFlags{
Usage: "If set, default reporter prints node > Enter and < Exit events when specs fail"},
{KeyPath: "R.GithubOutput", Name: "github-output", SectionKey: "output",
Usage: "If set, default reporter prints easier to manage output in Github Actions."},
{KeyPath: "R.SilenceSkips", Name: "silence-skips", SectionKey: "output",
Usage: "If set, default reporter will not print out skipped tests."},
{KeyPath: "R.ForceNewlines", Name: "force-newlines", SectionKey: "output",
Usage: "If set, default reporter will ensure a newline appears after each test."},
{KeyPath: "R.JSONReport", Name: "json-report", UsageArgument: "filename.json", SectionKey: "output",
Usage: "If set, Ginkgo will generate a JSON-formatted test report at the specified location."},

View File

@ -45,6 +45,83 @@ func orAction(a, b LabelFilter) LabelFilter {
return func(labels []string) bool { return a(labels) || b(labels) }
}
func labelSetFor(key string, labels []string) map[string]bool {
key = strings.ToLower(strings.TrimSpace(key))
out := map[string]bool{}
for _, label := range labels {
components := strings.SplitN(label, ":", 2)
if len(components) < 2 {
continue
}
if key == strings.ToLower(strings.TrimSpace(components[0])) {
out[strings.ToLower(strings.TrimSpace(components[1]))] = true
}
}
return out
}
func isEmptyLabelSetAction(key string) LabelFilter {
return func(labels []string) bool {
return len(labelSetFor(key, labels)) == 0
}
}
func containsAnyLabelSetAction(key string, expectedValues []string) LabelFilter {
return func(labels []string) bool {
set := labelSetFor(key, labels)
for _, value := range expectedValues {
if set[value] {
return true
}
}
return false
}
}
func containsAllLabelSetAction(key string, expectedValues []string) LabelFilter {
return func(labels []string) bool {
set := labelSetFor(key, labels)
for _, value := range expectedValues {
if !set[value] {
return false
}
}
return true
}
}
func consistsOfLabelSetAction(key string, expectedValues []string) LabelFilter {
return func(labels []string) bool {
set := labelSetFor(key, labels)
if len(set) != len(expectedValues) {
return false
}
for _, value := range expectedValues {
if !set[value] {
return false
}
}
return true
}
}
func isSubsetOfLabelSetAction(key string, expectedValues []string) LabelFilter {
expectedSet := map[string]bool{}
for _, value := range expectedValues {
expectedSet[value] = true
}
return func(labels []string) bool {
set := labelSetFor(key, labels)
for value := range set {
if !expectedSet[value] {
return false
}
}
return true
}
}
type lfToken uint
const (
@ -58,6 +135,9 @@ const (
lfTokenOr
lfTokenRegexp
lfTokenLabel
lfTokenSetKey
lfTokenSetOperation
lfTokenSetArgument
lfTokenEOF
)
@ -71,6 +151,8 @@ func (l lfToken) Precedence() int {
return 2
case lfTokenNot:
return 3
case lfTokenSetOperation:
return 4
}
return -1
}
@ -93,6 +175,12 @@ func (l lfToken) String() string {
return "/regexp/"
case lfTokenLabel:
return "label"
case lfTokenSetKey:
return "set_key"
case lfTokenSetOperation:
return "set_operation"
case lfTokenSetArgument:
return "set_argument"
case lfTokenEOF:
return "EOF"
}
@ -148,6 +236,35 @@ func (tn *treeNode) constructLabelFilter(input string) (LabelFilter, error) {
return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, tn.location, fmt.Sprintf("RegExp compilation error: %s", err))
}
return matchLabelRegexAction(re), nil
case lfTokenSetOperation:
tokenSetOperation := strings.ToLower(tn.value)
if tokenSetOperation == "isempty" {
return isEmptyLabelSetAction(tn.leftNode.value), nil
}
if tn.rightNode == nil {
return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, tn.location, fmt.Sprintf("Set operation '%s' is missing an argument.", tn.value))
}
rawValues := strings.Split(tn.rightNode.value, ",")
values := make([]string, len(rawValues))
for i := range rawValues {
values[i] = strings.ToLower(strings.TrimSpace(rawValues[i]))
if strings.ContainsAny(values[i], "&|!,()/") {
return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, tn.rightNode.location, fmt.Sprintf("Invalid label value '%s' in set operation argument.", values[i]))
} else if values[i] == "" {
return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, tn.rightNode.location, "Empty label value in set operation argument.")
}
}
switch tokenSetOperation {
case "containsany":
return containsAnyLabelSetAction(tn.leftNode.value, values), nil
case "containsall":
return containsAllLabelSetAction(tn.leftNode.value, values), nil
case "consistsof":
return consistsOfLabelSetAction(tn.leftNode.value, values), nil
case "issubsetof":
return isSubsetOfLabelSetAction(tn.leftNode.value, values), nil
}
}
if tn.rightNode == nil {
@ -203,7 +320,17 @@ func (tn *treeNode) toString(indent int) string {
return out
}
var validSetOperations = map[string]string{
"containsany": "containsAny",
"containsall": "containsAll",
"consistsof": "consistsOf",
"issubsetof": "isSubsetOf",
"isempty": "isEmpty",
}
func tokenize(input string) func() (*treeNode, error) {
lastToken := lfTokenInvalid
lastValue := ""
runes, i := []rune(input), 0
peekIs := func(r rune) bool {
@ -233,6 +360,53 @@ func tokenize(input string) func() (*treeNode, error) {
}
node := &treeNode{location: i}
defer func() {
lastToken = node.token
lastValue = node.value
}()
if lastToken == lfTokenSetKey {
//we should get a valid set operation next
value, n := consumeUntil(" )")
if validSetOperations[strings.ToLower(value)] == "" {
return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i, fmt.Sprintf("Invalid set operation '%s'.", value))
}
i += n
node.token, node.value = lfTokenSetOperation, value
return node, nil
}
if lastToken == lfTokenSetOperation {
//we should get an argument next, if we aren't isempty
var arg = ""
origI := i
if runes[i] == '{' {
i += 1
value, n := consumeUntil("}")
if i+n >= len(runes) {
return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i-1, "Missing closing '}' in set operation argument?")
}
i += n + 1
arg = value
} else {
value, n := consumeUntil("&|!,()/")
i += n
arg = strings.TrimSpace(value)
}
if strings.ToLower(lastValue) == "isempty" && arg != "" {
return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, origI, fmt.Sprintf("isEmpty does not take arguments, was passed '%s'.", arg))
}
if arg == "" && strings.ToLower(lastValue) != "isempty" {
if i < len(runes) && runes[i] == '/' {
return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, origI, "Set operations do not support regular expressions.")
} else {
return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, origI, fmt.Sprintf("Set operation '%s' requires an argument.", lastValue))
}
}
// note that we sent an empty SetArgument token if we are isempty
node.token, node.value = lfTokenSetArgument, arg
return node, nil
}
switch runes[i] {
case '&':
if !peekIs('&') {
@ -264,8 +438,38 @@ func tokenize(input string) func() (*treeNode, error) {
i += n + 1
node.token, node.value = lfTokenRegexp, value
default:
value, n := consumeUntil("&|!,()/")
value, n := consumeUntil("&|!,()/:")
i += n
value = strings.TrimSpace(value)
//are we the beginning of a set operation?
if i < len(runes) && runes[i] == ':' {
if peekIs(' ') {
if value == "" {
return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i, "Missing set key.")
}
i += 1
//we are the beginning of a set operation
node.token, node.value = lfTokenSetKey, value
return node, nil
}
additionalValue, n := consumeUntil("&|!,()/")
additionalValue = strings.TrimSpace(additionalValue)
if additionalValue == ":" {
return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i, "Missing set operation.")
}
i += n
value += additionalValue
}
valueToCheckForSetOperation := strings.ToLower(value)
for setOperation := range validSetOperations {
idx := strings.Index(valueToCheckForSetOperation, " "+setOperation)
if idx > 0 {
return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i-n+idx+1, fmt.Sprintf("Looks like you are using the set operator '%s' but did not provide a set key. Did you forget the ':'?", validSetOperations[setOperation]))
}
}
node.token, node.value = lfTokenLabel, strings.TrimSpace(value)
}
return node, nil
@ -307,7 +511,7 @@ LOOP:
switch node.token {
case lfTokenEOF:
break LOOP
case lfTokenLabel, lfTokenRegexp:
case lfTokenLabel, lfTokenRegexp, lfTokenSetKey:
if current.rightNode != nil {
return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, node.location, "Found two adjacent labels. You need an operator between them.")
}
@ -326,6 +530,18 @@ LOOP:
node.setLeftNode(nodeToStealFrom.rightNode)
nodeToStealFrom.setRightNode(node)
current = node
case lfTokenSetOperation:
if current.rightNode == nil {
return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, node.location, fmt.Sprintf("Set operation '%s' missing left hand operand.", node.value))
}
node.setLeftNode(current.rightNode)
current.setRightNode(node)
current = node
case lfTokenSetArgument:
if current.rightNode != nil {
return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, node.location, fmt.Sprintf("Unexpected set argument '%s'.", node.token))
}
current.setRightNode(node)
case lfTokenCloseGroup:
firstUnmatchedOpenNode := current.firstUnmatchedOpenNode()
if firstUnmatchedOpenNode == nil {
@ -354,5 +570,14 @@ func ValidateAndCleanupLabel(label string, cl CodeLocation) (string, error) {
if strings.ContainsAny(out, "&|!,()/") {
return "", GinkgoErrors.InvalidLabel(label, cl)
}
if out[0] == ':' {
return "", GinkgoErrors.InvalidLabel(label, cl)
}
if strings.Contains(out, ":") {
components := strings.SplitN(out, ":", 2)
if len(components) < 2 || components[1] == "" {
return "", GinkgoErrors.InvalidLabel(label, cl)
}
}
return out, nil
}

View File

@ -1,3 +1,3 @@
package types
const VERSION = "2.17.1"
const VERSION = "2.19.0"

View File

@ -1,3 +1,22 @@
## 1.33.1
### Fixes
- fix confusing eventually docs [3a66379]
### Maintenance
- Bump github.com/onsi/ginkgo/v2 from 2.17.1 to 2.17.2 [e9bc35a]
## 1.33.0
### Features
`Receive` not accepts `Receive(<POINTER>, MATCHER>)`, allowing you to pick out a specific value on the channel that satisfies the provided matcher and is stored in the provided pointer.
### Maintenance
- Bump github.com/onsi/ginkgo/v2 from 2.15.0 to 2.17.1 (#745) [9999deb]
- Bump github-pages from 229 to 230 in /docs (#735) [cb5ff21]
- Bump golang.org/x/net from 0.20.0 to 0.23.0 (#746) [bac6596]
## 1.32.0
### Maintenance

View File

@ -22,7 +22,7 @@ import (
"github.com/onsi/gomega/types"
)
const GOMEGA_VERSION = "1.32.0"
const GOMEGA_VERSION = "1.33.1"
const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler.
If you're using Ginkgo then you probably forgot to put your assertion in an It().
@ -372,11 +372,11 @@ You can ensure that you get a number of consecutive successful tries before succ
Finally, in addition to passing timeouts and a context to Eventually you can be more explicit with Eventually's chaining configuration methods:
Eventually(..., "1s", "2s", ctx).Should(...)
Eventually(..., "10s", "2s", ctx).Should(...)
is equivalent to
Eventually(...).WithTimeout(time.Second).WithPolling(2*time.Second).WithContext(ctx).Should(...)
Eventually(...).WithTimeout(10*time.Second).WithPolling(2*time.Second).WithContext(ctx).Should(...)
*/
func Eventually(actualOrCtx interface{}, args ...interface{}) AsyncAssertion {
ensureDefaultGomegaIsConfigured()

View File

@ -194,20 +194,21 @@ func BeClosed() types.GomegaMatcher {
//
// will repeatedly attempt to pull values out of `c` until a value matching "bar" is received.
//
// Finally, if you want to have a reference to the value *sent* to the channel you can pass the `Receive` matcher a pointer to a variable of the appropriate type:
// Furthermore, if you want to have a reference to the value *sent* to the channel you can pass the `Receive` matcher a pointer to a variable of the appropriate type:
//
// var myThing thing
// Eventually(thingChan).Should(Receive(&myThing))
// Expect(myThing.Sprocket).Should(Equal("foo"))
// Expect(myThing.IsValid()).Should(BeTrue())
//
// Finally, if you want to match the received object as well as get the actual received value into a variable, so you can reason further about the value received,
// you can pass a pointer to a variable of the approriate type first, and second a matcher:
//
// var myThing thing
// Eventually(thingChan).Should(Receive(&myThing, ContainSubstring("bar")))
func Receive(args ...interface{}) types.GomegaMatcher {
var arg interface{}
if len(args) > 0 {
arg = args[0]
}
return &matchers.ReceiveMatcher{
Arg: arg,
Args: args,
}
}

View File

@ -3,6 +3,7 @@
package matchers
import (
"errors"
"fmt"
"reflect"
@ -10,7 +11,7 @@ import (
)
type ReceiveMatcher struct {
Arg interface{}
Args []interface{}
receivedValue reflect.Value
channelClosed bool
}
@ -29,16 +30,39 @@ func (matcher *ReceiveMatcher) Match(actual interface{}) (success bool, err erro
var subMatcher omegaMatcher
var hasSubMatcher bool
var resultReference interface{}
if matcher.Arg != nil {
subMatcher, hasSubMatcher = (matcher.Arg).(omegaMatcher)
if !hasSubMatcher {
argType := reflect.TypeOf(matcher.Arg)
if argType.Kind() != reflect.Ptr {
return false, fmt.Errorf("Cannot assign a value from the channel:\n%s\nTo:\n%s\nYou need to pass a pointer!", format.Object(actual, 1), format.Object(matcher.Arg, 1))
}
// Valid arg formats are as follows, always with optional POINTER before
// optional MATCHER:
// - Receive()
// - Receive(POINTER)
// - Receive(MATCHER)
// - Receive(POINTER, MATCHER)
args := matcher.Args
if len(args) > 0 {
arg := args[0]
_, isSubMatcher := arg.(omegaMatcher)
if !isSubMatcher && reflect.ValueOf(arg).Kind() == reflect.Ptr {
// Consume optional POINTER arg first, if it ain't no matcher ;)
resultReference = arg
args = args[1:]
}
}
if len(args) > 0 {
arg := args[0]
subMatcher, hasSubMatcher = arg.(omegaMatcher)
if !hasSubMatcher {
// At this point we assume the dev user wanted to assign a received
// value, so [POINTER,]MATCHER.
return false, fmt.Errorf("Cannot assign a value from the channel:\n%s\nTo:\n%s\nYou need to pass a pointer!", format.Object(actual, 1), format.Object(arg, 1))
}
// Consume optional MATCHER arg.
args = args[1:]
}
if len(args) > 0 {
// If there are still args present, reject all.
return false, errors.New("Receive matcher expects at most an optional pointer and/or an optional matcher")
}
winnerIndex, value, open := reflect.Select([]reflect.SelectCase{
{Dir: reflect.SelectRecv, Chan: channelValue},
@ -58,16 +82,20 @@ func (matcher *ReceiveMatcher) Match(actual interface{}) (success bool, err erro
}
if hasSubMatcher {
if didReceive {
matcher.receivedValue = value
return subMatcher.Match(matcher.receivedValue.Interface())
if !didReceive {
return false, nil
}
return false, nil
matcher.receivedValue = value
if match, err := subMatcher.Match(matcher.receivedValue.Interface()); err != nil || !match {
return match, err
}
// if we received a match, then fall through in order to handle an
// optional assignment of the received value to the specified reference.
}
if didReceive {
if matcher.Arg != nil {
outValue := reflect.ValueOf(matcher.Arg)
if resultReference != nil {
outValue := reflect.ValueOf(resultReference)
if value.Type().AssignableTo(outValue.Elem().Type()) {
outValue.Elem().Set(value)
@ -77,7 +105,7 @@ func (matcher *ReceiveMatcher) Match(actual interface{}) (success bool, err erro
outValue.Elem().Set(value.Elem())
return true, nil
} else {
return false, fmt.Errorf("Cannot assign a value from the channel:\n%s\nType:\n%s\nTo:\n%s", format.Object(actual, 1), format.Object(value.Interface(), 1), format.Object(matcher.Arg, 1))
return false, fmt.Errorf("Cannot assign a value from the channel:\n%s\nType:\n%s\nTo:\n%s", format.Object(actual, 1), format.Object(value.Interface(), 1), format.Object(resultReference, 1))
}
}
@ -88,7 +116,11 @@ func (matcher *ReceiveMatcher) Match(actual interface{}) (success bool, err erro
}
func (matcher *ReceiveMatcher) FailureMessage(actual interface{}) (message string) {
subMatcher, hasSubMatcher := (matcher.Arg).(omegaMatcher)
var matcherArg interface{}
if len(matcher.Args) > 0 {
matcherArg = matcher.Args[len(matcher.Args)-1]
}
subMatcher, hasSubMatcher := (matcherArg).(omegaMatcher)
closedAddendum := ""
if matcher.channelClosed {
@ -105,7 +137,11 @@ func (matcher *ReceiveMatcher) FailureMessage(actual interface{}) (message strin
}
func (matcher *ReceiveMatcher) NegatedFailureMessage(actual interface{}) (message string) {
subMatcher, hasSubMatcher := (matcher.Arg).(omegaMatcher)
var matcherArg interface{}
if len(matcher.Args) > 0 {
matcherArg = matcher.Args[len(matcher.Args)-1]
}
subMatcher, hasSubMatcher := (matcherArg).(omegaMatcher)
closedAddendum := ""
if matcher.channelClosed {