🌱 Bump github.com/onsi/ginkgo/v2 from 2.23.4 to 2.24.0 (#1133)
Some checks failed
Post / coverage (push) Failing after 38m18s
Post / images (amd64, addon-manager) (push) Failing after 8m14s
Post / images (amd64, placement) (push) Failing after 7m40s
Post / images (amd64, registration) (push) Failing after 7m53s
Post / images (amd64, registration-operator) (push) Failing after 8m5s
Post / images (amd64, work) (push) Failing after 7m48s
Post / images (arm64, addon-manager) (push) Failing after 7m46s
Post / images (arm64, placement) (push) Failing after 7m37s
Post / images (arm64, registration) (push) Failing after 7m26s
Post / images (arm64, registration-operator) (push) Failing after 7m35s
Post / images (arm64, work) (push) Failing after 7m26s
Post / image manifest (addon-manager) (push) Has been skipped
Post / image manifest (placement) (push) Has been skipped
Post / image manifest (registration) (push) Has been skipped
Post / image manifest (registration-operator) (push) Has been skipped
Post / image manifest (work) (push) Has been skipped
Post / trigger clusteradm e2e (push) Has been skipped
Scorecard supply-chain security / Scorecard analysis (push) Failing after 1m41s
Close stale issues and PRs / stale (push) Successful in 35s

Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.23.4 to 2.24.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.23.4...v2.24.0)

---
updated-dependencies:
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-version: 2.24.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
dependabot[bot]
2025-08-20 00:38:19 +00:00
committed by GitHub
parent dba1c359a1
commit 98835ad8a1
27 changed files with 424 additions and 122 deletions

8
go.mod
View File

@@ -15,7 +15,7 @@ require (
github.com/google/cel-go v0.26.0
github.com/google/go-cmp v0.7.0
github.com/mochi-mqtt/server/v2 v2.7.9
github.com/onsi/ginkgo/v2 v2.23.4
github.com/onsi/ginkgo/v2 v2.24.0
github.com/onsi/gomega v1.38.0
github.com/openshift/api v0.0.0-20250710004639-926605d3338b
github.com/openshift/build-machinery-go v0.0.0-20250530140348-dc5b2804eeee
@@ -55,7 +55,7 @@ require (
dario.cat/mergo v1.0.1 // indirect
github.com/BurntSushi/toml v1.5.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.3.0 // indirect
github.com/Masterminds/semver/v3 v3.3.1 // indirect
github.com/Masterminds/sprig/v3 v3.3.0 // indirect
github.com/Microsoft/hcsshim v0.12.9 // indirect
github.com/NYTimes/gziphandler v1.1.1 // indirect
@@ -90,7 +90,7 @@ require (
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-logr/zapr v1.3.0 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
@@ -162,7 +162,7 @@ require (
golang.org/x/term v0.34.0 // indirect
golang.org/x/text v0.28.0 // indirect
golang.org/x/time v0.12.0 // indirect
golang.org/x/tools v0.35.0 // indirect
golang.org/x/tools v0.36.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect

16
go.sum
View File

@@ -12,8 +12,8 @@ github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4=
github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
@@ -135,8 +135,8 @@ github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXE
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
@@ -254,8 +254,8 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
github.com/onsi/ginkgo/v2 v2.24.0 h1:obZz8LAnHicNdbBqvG3ytAFx8fgza+i1IDpBVcHT2YE=
github.com/onsi/ginkgo/v2 v2.24.0/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk=
github.com/onsi/gomega v1.38.0 h1:c/WX+w8SLAinvuKKQFh77WEucCnPk4j2OTUr7lt7BeY=
github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJEB6o=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
@@ -431,8 +431,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -39,9 +39,11 @@ var (
)
// semVerRegex is the regular expression used to parse a semantic version.
const semVerRegex string = `v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?` +
`(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` +
`(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?`
// This is not the official regex from the semver spec. It has been modified to allow for loose handling
// where versions like 2.1 are detected.
const semVerRegex string = `v?(0|[1-9]\d*)(?:\.(0|[1-9]\d*))?(?:\.(0|[1-9]\d*))?` +
`(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?` +
`(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?`
// Version represents a single semantic version.
type Version struct {
@@ -146,8 +148,8 @@ func NewVersion(v string) (*Version, error) {
}
sv := &Version{
metadata: m[8],
pre: m[5],
metadata: m[5],
pre: m[4],
original: v,
}
@@ -158,7 +160,7 @@ func NewVersion(v string) (*Version, error) {
}
if m[2] != "" {
sv.minor, err = strconv.ParseUint(strings.TrimPrefix(m[2], "."), 10, 64)
sv.minor, err = strconv.ParseUint(m[2], 10, 64)
if err != nil {
return nil, fmt.Errorf("Error parsing version segment: %s", err)
}
@@ -167,7 +169,7 @@ func NewVersion(v string) (*Version, error) {
}
if m[3] != "" {
sv.patch, err = strconv.ParseUint(strings.TrimPrefix(m[3], "."), 10, 64)
sv.patch, err = strconv.ParseUint(m[3], 10, 64)
if err != nil {
return nil, fmt.Errorf("Error parsing version segment: %s", err)
}
@@ -612,7 +614,9 @@ func containsOnly(s string, comp string) bool {
func validatePrerelease(p string) error {
eparts := strings.Split(p, ".")
for _, p := range eparts {
if containsOnly(p, num) {
if p == "" {
return ErrInvalidMetadata
} else if containsOnly(p, num) {
if len(p) > 1 && p[0] == '0' {
return ErrSegmentStartsZero
}
@@ -631,7 +635,9 @@ func validatePrerelease(p string) error {
func validateMetadata(m string) error {
eparts := strings.Split(m, ".")
for _, p := range eparts {
if !containsOnly(p, allowed) {
if p == "" {
return ErrInvalidMetadata
} else if !containsOnly(p, allowed) {
return ErrInvalidMetadata
}
}

View File

@@ -1,26 +1,28 @@
version: "2"
run:
timeout: 1m
tests: true
linters:
disable-all: true
enable:
default: none
enable: # please keep this alphabetized
- asasalint
- asciicheck
- copyloopvar
- dupl
- errcheck
- forcetypeassert
- goconst
- gocritic
- gofmt
- goimports
- gosimple
- govet
- ineffassign
- misspell
- musttag
- revive
- staticcheck
- typecheck
- unused
issues:
exclude-use-default: false
max-issues-per-linter: 0
max-same-issues: 10

View File

@@ -77,7 +77,7 @@ func newSink(fn func(prefix, args string), formatter Formatter) logr.LogSink {
write: fn,
}
// For skipping fnlogger.Info and fnlogger.Error.
l.Formatter.AddCallDepth(1)
l.AddCallDepth(1) // via Formatter
return l
}
@@ -164,17 +164,17 @@ type fnlogger struct {
}
func (l fnlogger) WithName(name string) logr.LogSink {
l.Formatter.AddName(name)
l.AddName(name) // via Formatter
return &l
}
func (l fnlogger) WithValues(kvList ...any) logr.LogSink {
l.Formatter.AddValues(kvList)
l.AddValues(kvList) // via Formatter
return &l
}
func (l fnlogger) WithCallDepth(depth int) logr.LogSink {
l.Formatter.AddCallDepth(depth)
l.AddCallDepth(depth) // via Formatter
return &l
}

View File

@@ -1,3 +1,17 @@
## 2.24.0
### Features
Specs can now be decorated with (e.g.) `SemVerConstraint("2.1.0")` and `ginkgo --sem-ver-filter="2.1.1"` will only run constrained specs that match the requested version. Learn more in the docs [here](https://onsi.github.io/ginkgo/#spec-semantic-version-filtering)! Thanks to @Icarus9913 for the PR.
### Fixes
- remove -o from run command [3f5d379]. fixes [#1582](https://github.com/onsi/ginkgo/issues/1582)
### Maintenance
Numerous dependency bumps and documentation fixes
## 2.23.4
Prior to this release Ginkgo would compute the incorrect number of available CPUs when running with `-p` in a linux container. Thanks to @emirot for the fix!

View File

@@ -186,6 +186,20 @@ func GinkgoLabelFilter() string {
return suiteConfig.LabelFilter
}
/*
GinkgoSemVerFilter() returns the semantic version filter configured for this suite via `--sem-ver-filter`.
You can use this to manually check if a set of semantic version constraints would satisfy the filter via:
if (SemVerConstraint("> 2.6.0", "< 2.8.0").MatchesSemVerFilter(GinkgoSemVerFilter())) {
//...
}
*/
func GinkgoSemVerFilter() string {
suiteConfig, _ := GinkgoConfiguration()
return suiteConfig.SemVerFilter
}
/*
PauseOutputInterception() pauses Ginkgo's output interception. This is only relevant
when running in parallel and output to stdout/stderr is being intercepted. You generally
@@ -254,7 +268,7 @@ func RunSpecs(t GinkgoTestingT, description string, args ...any) bool {
}
defer global.PopClone()
suiteLabels := extractSuiteConfiguration(args)
suiteLabels, suiteSemVerConstraints := extractSuiteConfiguration(args)
var reporter reporters.Reporter
if suiteConfig.ParallelTotal == 1 {
@@ -297,7 +311,7 @@ func RunSpecs(t GinkgoTestingT, description string, args ...any) bool {
suitePath, err = filepath.Abs(suitePath)
exitIfErr(err)
passed, hasFocusedTests := global.Suite.Run(description, suiteLabels, suitePath, global.Failer, reporter, writer, outputInterceptor, interrupt_handler.NewInterruptHandler(client), client, internal.RegisterForProgressSignal, suiteConfig)
passed, hasFocusedTests := global.Suite.Run(description, suiteLabels, suiteSemVerConstraints, suitePath, global.Failer, reporter, writer, outputInterceptor, interrupt_handler.NewInterruptHandler(client), client, internal.RegisterForProgressSignal, suiteConfig)
outputInterceptor.Shutdown()
flagSet.ValidateDeprecations(deprecationTracker)
@@ -316,8 +330,9 @@ func RunSpecs(t GinkgoTestingT, description string, args ...any) bool {
return passed
}
func extractSuiteConfiguration(args []any) Labels {
func extractSuiteConfiguration(args []any) (Labels, SemVerConstraints) {
suiteLabels := Labels{}
suiteSemVerConstraints := SemVerConstraints{}
configErrors := []error{}
for _, arg := range args {
switch arg := arg.(type) {
@@ -327,6 +342,8 @@ func extractSuiteConfiguration(args []any) Labels {
reporterConfig = arg
case Labels:
suiteLabels = append(suiteLabels, arg...)
case SemVerConstraints:
suiteSemVerConstraints = append(suiteSemVerConstraints, arg...)
default:
configErrors = append(configErrors, types.GinkgoErrors.UnknownTypePassedToRunSpecs(arg))
}
@@ -342,7 +359,7 @@ func extractSuiteConfiguration(args []any) Labels {
os.Exit(1)
}
return suiteLabels
return suiteLabels, suiteSemVerConstraints
}
func getwd() (string, error) {
@@ -365,7 +382,7 @@ func PreviewSpecs(description string, args ...any) Report {
}
defer global.PopClone()
suiteLabels := extractSuiteConfiguration(args)
suiteLabels, suiteSemVerConstraints := extractSuiteConfiguration(args)
priorDryRun, priorParallelTotal, priorParallelProcess := suiteConfig.DryRun, suiteConfig.ParallelTotal, suiteConfig.ParallelProcess
suiteConfig.DryRun, suiteConfig.ParallelTotal, suiteConfig.ParallelProcess = true, 1, 1
defer func() {
@@ -383,7 +400,7 @@ func PreviewSpecs(description string, args ...any) Report {
suitePath, err = filepath.Abs(suitePath)
exitIfErr(err)
global.Suite.Run(description, suiteLabels, suitePath, global.Failer, reporter, writer, outputInterceptor, interrupt_handler.NewInterruptHandler(client), client, internal.RegisterForProgressSignal, suiteConfig)
global.Suite.Run(description, suiteLabels, suiteSemVerConstraints, suitePath, global.Failer, reporter, writer, outputInterceptor, interrupt_handler.NewInterruptHandler(client), client, internal.RegisterForProgressSignal, suiteConfig)
return global.Suite.GetPreviewReport()
}

View File

@@ -99,6 +99,23 @@ You can learn more here: https://onsi.github.io/ginkgo/#spec-labels
*/
type Labels = internal.Labels
/*
SemVerConstraint decorates specs with SemVerConstraints. Multiple semantic version constraints can be passed to SemVerConstraint and these strings must follow the semantic version constraint rules.
SemVerConstraints can be applied to container and subject nodes, but not setup nodes. You can provide multiple SemVerConstraints to a given node and a spec's semantic version constraints is the union of all semantic version constraints in its node hierarchy.
You can learn more here: https://onsi.github.io/ginkgo/#spec-semantic-version-filtering
You can learn more about decorators here: https://onsi.github.io/ginkgo/#decorator-reference
*/
func SemVerConstraint(semVerConstraints ...string) SemVerConstraints {
return SemVerConstraints(semVerConstraints)
}
/*
SemVerConstraints are the type for spec SemVerConstraint decorators. Use SemVerConstraint(...) to construct SemVerConstraints.
You can learn more here: https://onsi.github.io/ginkgo/#spec-semantic-version-filtering
*/
type SemVerConstraints = internal.SemVerConstraints
/*
PollProgressAfter allows you to override the configured value for --poll-progress-after for a particular node.

View File

@@ -20,6 +20,7 @@ type Offset = ginkgo.Offset
type FlakeAttempts = ginkgo.FlakeAttempts
type MustPassRepeatedly = ginkgo.MustPassRepeatedly
type Labels = ginkgo.Labels
type SemVerConstraints = ginkgo.SemVerConstraints
type PollProgressAfter = ginkgo.PollProgressAfter
type PollProgressInterval = ginkgo.PollProgressInterval
type NodeTimeout = ginkgo.NodeTimeout
@@ -35,3 +36,4 @@ const OncePerOrdered = ginkgo.OncePerOrdered
const SuppressProgressReporting = ginkgo.SuppressProgressReporting
var Label = ginkgo.Label
var SemVerConstraint = ginkgo.SemVerConstraint

View File

@@ -29,7 +29,6 @@ func BuildBuildCommand() command.Command {
var errors []error
cliConfig, goFlagsConfig, errors = types.VetAndInitializeCLIAndGoConfig(cliConfig, goFlagsConfig)
command.AbortIfErrors("Ginkgo detected configuration issues:", errors)
buildSpecs(args, cliConfig, goFlagsConfig)
},
}

View File

@@ -2,6 +2,7 @@ package ginkgo
import (
"context"
"io"
"testing"
"github.com/onsi/ginkgo/v2/internal/testingtproxy"
@@ -69,6 +70,8 @@ type GinkgoTInterface interface {
Skipf(format string, args ...any)
Skipped() bool
TempDir() string
Attr(key, value string)
Output() io.Writer
}
/*

View File

@@ -56,7 +56,7 @@ This function sets the `Skip` property on specs by applying Ginkgo's focus polic
*Note:* specs with pending nodes are Skipped when created by NewSpec.
*/
func ApplyFocusToSpecs(specs Specs, description string, suiteLabels Labels, suiteConfig types.SuiteConfig) (Specs, bool) {
func ApplyFocusToSpecs(specs Specs, description string, suiteLabels Labels, suiteSemVerConstraints SemVerConstraints, suiteConfig types.SuiteConfig) (Specs, bool) {
focusString := strings.Join(suiteConfig.FocusStrings, "|")
skipString := strings.Join(suiteConfig.SkipStrings, "|")
@@ -84,6 +84,13 @@ func ApplyFocusToSpecs(specs Specs, description string, suiteLabels Labels, suit
})
}
if suiteConfig.SemVerFilter != "" {
semVerFilter, _ := types.ParseSemVerFilter(suiteConfig.SemVerFilter)
skipChecks = append(skipChecks, func(spec Spec) bool {
return !semVerFilter(UnionOfSemVerConstraints(suiteSemVerConstraints, spec.Nodes.UnionOfSemVerConstraints()))
})
}
if len(suiteConfig.FocusFiles) > 0 {
focusFilters, _ := types.ParseFileFilters(suiteConfig.FocusFiles)
skipChecks = append(skipChecks, func(spec Spec) bool { return !focusFilters.Matches(spec.Nodes.CodeLocations()) })

View File

@@ -112,19 +112,21 @@ func newGroup(suite *Suite) *group {
func (g *group) initialReportForSpec(spec Spec) types.SpecReport {
return types.SpecReport{
ContainerHierarchyTexts: spec.Nodes.WithType(types.NodeTypeContainer).Texts(),
ContainerHierarchyLocations: spec.Nodes.WithType(types.NodeTypeContainer).CodeLocations(),
ContainerHierarchyLabels: spec.Nodes.WithType(types.NodeTypeContainer).Labels(),
LeafNodeLocation: spec.FirstNodeWithType(types.NodeTypeIt).CodeLocation,
LeafNodeType: types.NodeTypeIt,
LeafNodeText: spec.FirstNodeWithType(types.NodeTypeIt).Text,
LeafNodeLabels: []string(spec.FirstNodeWithType(types.NodeTypeIt).Labels),
ParallelProcess: g.suite.config.ParallelProcess,
RunningInParallel: g.suite.isRunningInParallel(),
IsSerial: spec.Nodes.HasNodeMarkedSerial(),
IsInOrderedContainer: !spec.Nodes.FirstNodeMarkedOrdered().IsZero(),
MaxFlakeAttempts: spec.Nodes.GetMaxFlakeAttempts(),
MaxMustPassRepeatedly: spec.Nodes.GetMaxMustPassRepeatedly(),
ContainerHierarchyTexts: spec.Nodes.WithType(types.NodeTypeContainer).Texts(),
ContainerHierarchyLocations: spec.Nodes.WithType(types.NodeTypeContainer).CodeLocations(),
ContainerHierarchyLabels: spec.Nodes.WithType(types.NodeTypeContainer).Labels(),
ContainerHierarchySemVerConstraints: spec.Nodes.WithType(types.NodeTypeContainer).SemVerConstraints(),
LeafNodeLocation: spec.FirstNodeWithType(types.NodeTypeIt).CodeLocation,
LeafNodeType: types.NodeTypeIt,
LeafNodeText: spec.FirstNodeWithType(types.NodeTypeIt).Text,
LeafNodeLabels: []string(spec.FirstNodeWithType(types.NodeTypeIt).Labels),
LeafNodeSemVerConstraints: []string(spec.FirstNodeWithType(types.NodeTypeIt).SemVerConstraints),
ParallelProcess: g.suite.config.ParallelProcess,
RunningInParallel: g.suite.isRunningInParallel(),
IsSerial: spec.Nodes.HasNodeMarkedSerial(),
IsInOrderedContainer: !spec.Nodes.FirstNodeMarkedOrdered().IsZero(),
MaxFlakeAttempts: spec.Nodes.GetMaxFlakeAttempts(),
MaxMustPassRepeatedly: spec.Nodes.GetMaxMustPassRepeatedly(),
}
}

View File

@@ -55,6 +55,7 @@ type Node struct {
FlakeAttempts int
MustPassRepeatedly int
Labels Labels
SemVerConstraints SemVerConstraints
PollProgressAfter time.Duration
PollProgressInterval time.Duration
NodeTimeout time.Duration
@@ -86,6 +87,7 @@ type MustPassRepeatedly uint
type Offset uint
type Done chan<- any // Deprecated Done Channel for asynchronous testing
type Labels []string
type SemVerConstraints []string
type PollProgressInterval time.Duration
type PollProgressAfter time.Duration
type NodeTimeout time.Duration
@@ -96,20 +98,32 @@ func (l Labels) MatchesLabelFilter(query string) bool {
return types.MustParseLabelFilter(query)(l)
}
func UnionOfLabels(labels ...Labels) Labels {
out := Labels{}
seen := map[string]bool{}
for _, labelSet := range labels {
for _, label := range labelSet {
if !seen[label] {
seen[label] = true
out = append(out, label)
func (svc SemVerConstraints) MatchesSemVerFilter(version string) bool {
return types.MustParseSemVerFilter(version)(svc)
}
func unionOf[S ~[]E, E comparable](slices ...S) S {
out := S{}
seen := map[E]bool{}
for _, slice := range slices {
for _, item := range slice {
if !seen[item] {
seen[item] = true
out = append(out, item)
}
}
}
return out
}
func UnionOfLabels(labels ...Labels) Labels {
return unionOf(labels...)
}
func UnionOfSemVerConstraints(semVerConstraints ...SemVerConstraints) SemVerConstraints {
return unionOf(semVerConstraints...)
}
func PartitionDecorations(args ...any) ([]any, []any) {
decorations := []any{}
remainingArgs := []any{}
@@ -151,6 +165,8 @@ func isDecoration(arg any) bool {
return true
case t == reflect.TypeOf(Labels{}):
return true
case t == reflect.TypeOf(SemVerConstraints{}):
return true
case t == reflect.TypeOf(PollProgressInterval(0)):
return true
case t == reflect.TypeOf(PollProgressAfter(0)):
@@ -191,6 +207,7 @@ func NewNode(deprecationTracker *types.DeprecationTracker, nodeType types.NodeTy
NodeType: nodeType,
Text: text,
Labels: Labels{},
SemVerConstraints: SemVerConstraints{},
CodeLocation: types.NewCodeLocation(baseOffset),
NestingLevel: -1,
PollProgressAfter: -1,
@@ -221,6 +238,7 @@ func NewNode(deprecationTracker *types.DeprecationTracker, nodeType types.NodeTy
}
labelsSeen := map[string]bool{}
semVerConstraintsSeen := map[string]bool{}
trackedFunctionError := false
args = remainingArgs
remainingArgs = []any{}
@@ -311,6 +329,18 @@ func NewNode(deprecationTracker *types.DeprecationTracker, nodeType types.NodeTy
appendError(err)
}
}
case t == reflect.TypeOf(SemVerConstraints{}):
if !nodeType.Is(types.NodeTypesForContainerAndIt) {
appendError(types.GinkgoErrors.InvalidDecoratorForNodeType(node.CodeLocation, nodeType, "SemVerConstraint"))
}
for _, semVerConstraint := range arg.(SemVerConstraints) {
if !semVerConstraintsSeen[semVerConstraint] {
semVerConstraintsSeen[semVerConstraint] = true
semVerConstraint, err := types.ValidateAndCleanupSemVerConstraint(semVerConstraint, node.CodeLocation)
node.SemVerConstraints = append(node.SemVerConstraints, semVerConstraint)
appendError(err)
}
}
case t.Kind() == reflect.Func:
if nodeType.Is(types.NodeTypeContainer) {
if node.Body != nil {
@@ -824,6 +854,32 @@ func (n Nodes) UnionOfLabels() []string {
return out
}
func (n Nodes) SemVerConstraints() [][]string {
out := make([][]string, len(n))
for i := range n {
if n[i].SemVerConstraints == nil {
out[i] = []string{}
} else {
out[i] = []string(n[i].SemVerConstraints)
}
}
return out
}
func (n Nodes) UnionOfSemVerConstraints() []string {
out := []string{}
seen := map[string]bool{}
for i := range n {
for _, constraint := range n[i].SemVerConstraints {
if !seen[constraint] {
seen[constraint] = true
out = append(out, constraint)
}
}
}
return out
}
func (n Nodes) CodeLocations() []types.CodeLocation {
out := make([]types.CodeLocation, len(n))
for i := range n {
@@ -928,7 +984,7 @@ func unrollInterfaceSlice(args any) []any {
out := []any{}
for i := 0; i < v.Len(); i++ {
el := reflect.ValueOf(v.Index(i).Interface())
if el.Kind() == reflect.Slice && el.Type() != reflect.TypeOf(Labels{}) {
if el.Kind() == reflect.Slice && el.Type() != reflect.TypeOf(Labels{}) && el.Type() != reflect.TypeOf(SemVerConstraints{}) {
out = append(out, unrollInterfaceSlice(el.Interface())...)
} else {
out = append(out, v.Index(i).Interface())

View File

@@ -104,13 +104,13 @@ func (suite *Suite) BuildTree() error {
return nil
}
func (suite *Suite) Run(description string, suiteLabels Labels, suitePath string, failer *Failer, reporter reporters.Reporter, writer WriterInterface, outputInterceptor OutputInterceptor, interruptHandler interrupt_handler.InterruptHandlerInterface, client parallel_support.Client, progressSignalRegistrar ProgressSignalRegistrar, suiteConfig types.SuiteConfig) (bool, bool) {
func (suite *Suite) Run(description string, suiteLabels Labels, suiteSemVerConstraints SemVerConstraints, suitePath string, failer *Failer, reporter reporters.Reporter, writer WriterInterface, outputInterceptor OutputInterceptor, interruptHandler interrupt_handler.InterruptHandlerInterface, client parallel_support.Client, progressSignalRegistrar ProgressSignalRegistrar, suiteConfig types.SuiteConfig) (bool, bool) {
if suite.phase != PhaseBuildTree {
panic("cannot run before building the tree = call suite.BuildTree() first")
}
ApplyNestedFocusPolicyToTree(suite.tree)
specs := GenerateSpecsFromTreeRoot(suite.tree)
specs, hasProgrammaticFocus := ApplyFocusToSpecs(specs, description, suiteLabels, suiteConfig)
specs, hasProgrammaticFocus := ApplyFocusToSpecs(specs, description, suiteLabels, suiteSemVerConstraints, suiteConfig)
suite.phase = PhaseRun
suite.client = client
@@ -127,7 +127,7 @@ func (suite *Suite) Run(description string, suiteLabels Labels, suitePath string
cancelProgressHandler := progressSignalRegistrar(suite.handleProgressSignal)
success := suite.runSpecs(description, suiteLabels, suitePath, hasProgrammaticFocus, specs)
success := suite.runSpecs(description, suiteLabels, suiteSemVerConstraints, suitePath, hasProgrammaticFocus, specs)
cancelProgressHandler()
@@ -428,13 +428,14 @@ func (suite *Suite) processCurrentSpecReport() {
}
}
func (suite *Suite) runSpecs(description string, suiteLabels Labels, suitePath string, hasProgrammaticFocus bool, specs Specs) bool {
func (suite *Suite) runSpecs(description string, suiteLabels Labels, suiteSemVerConstraints SemVerConstraints, suitePath string, hasProgrammaticFocus bool, specs Specs) bool {
numSpecsThatWillBeRun := specs.CountWithoutSkip()
suite.report = types.Report{
SuitePath: suitePath,
SuiteDescription: description,
SuiteLabels: suiteLabels,
SuiteSemVerConstraints: suiteSemVerConstraints,
SuiteConfig: suite.config,
SuiteHasProgrammaticFocus: hasProgrammaticFocus,
PreRunStats: types.PreRunStats{

View File

@@ -229,3 +229,9 @@ func (t *ginkgoTestingTProxy) ParallelTotal() int {
func (t *ginkgoTestingTProxy) AttachProgressReporter(f func() string) func() {
return t.attachProgressReporter(f)
}
func (t *ginkgoTestingTProxy) Output() io.Writer {
return t.writer
}
func (t *ginkgoTestingTProxy) Attr(key, value string) {
t.addReportEntry(key, value, internal.Offset(1), types.ReportEntryVisibilityFailureOrVerbose)
}

View File

@@ -72,6 +72,9 @@ func (r *DefaultReporter) SuiteWillBegin(report types.Report) {
if len(report.SuiteLabels) > 0 {
r.emit(r.f("{{coral}}[%s]{{/}} ", strings.Join(report.SuiteLabels, ", ")))
}
if len(report.SuiteSemVerConstraints) > 0 {
r.emit(r.f("{{coral}}[%s]{{/}} ", strings.Join(report.SuiteSemVerConstraints, ", ")))
}
r.emit(r.f("- %d/%d specs ", report.PreRunStats.SpecsThatWillRun, report.PreRunStats.TotalSpecs))
if report.SuiteConfig.ParallelTotal > 1 {
r.emit(r.f("- %d procs ", report.SuiteConfig.ParallelTotal))
@@ -87,6 +90,13 @@ func (r *DefaultReporter) SuiteWillBegin(report types.Report) {
bannerWidth = len(labels) + 2
}
}
if len(report.SuiteSemVerConstraints) > 0 {
semVerConstraints := strings.Join(report.SuiteSemVerConstraints, ", ")
r.emitBlock(r.f("{{coral}}[%s]{{/}} ", semVerConstraints))
if len(semVerConstraints)+2 > bannerWidth {
bannerWidth = len(semVerConstraints) + 2
}
}
r.emitBlock(strings.Repeat("=", bannerWidth))
out := r.f("Random Seed: {{bold}}%d{{/}}", report.SuiteConfig.RandomSeed)
@@ -698,8 +708,8 @@ func (r *DefaultReporter) cycleJoin(elements []string, joiner string) string {
}
func (r *DefaultReporter) codeLocationBlock(report types.SpecReport, highlightColor string, veryVerbose bool, usePreciseFailureLocation bool) string {
texts, locations, labels := []string{}, []types.CodeLocation{}, [][]string{}
texts, locations, labels = append(texts, report.ContainerHierarchyTexts...), append(locations, report.ContainerHierarchyLocations...), append(labels, report.ContainerHierarchyLabels...)
texts, locations, labels, semVerConstraints := []string{}, []types.CodeLocation{}, [][]string{}, [][]string{}
texts, locations, labels, semVerConstraints = append(texts, report.ContainerHierarchyTexts...), append(locations, report.ContainerHierarchyLocations...), append(labels, report.ContainerHierarchyLabels...), append(semVerConstraints, report.ContainerHierarchySemVerConstraints...)
if report.LeafNodeType.Is(types.NodeTypesForSuiteLevelNodes) {
texts = append(texts, r.f("[%s] %s", report.LeafNodeType, report.LeafNodeText))
@@ -707,6 +717,7 @@ func (r *DefaultReporter) codeLocationBlock(report types.SpecReport, highlightCo
texts = append(texts, r.f(report.LeafNodeText))
}
labels = append(labels, report.LeafNodeLabels)
semVerConstraints = append(semVerConstraints, report.LeafNodeSemVerConstraints)
locations = append(locations, report.LeafNodeLocation)
failureLocation := report.Failure.FailureNodeLocation
@@ -720,6 +731,7 @@ func (r *DefaultReporter) codeLocationBlock(report types.SpecReport, highlightCo
texts = append([]string{fmt.Sprintf("TOP-LEVEL [%s]", report.Failure.FailureNodeType)}, texts...)
locations = append([]types.CodeLocation{failureLocation}, locations...)
labels = append([][]string{{}}, labels...)
semVerConstraints = append([][]string{{}}, semVerConstraints...)
highlightIndex = 0
case types.FailureNodeInContainer:
i := report.Failure.FailureNodeContainerIndex
@@ -747,6 +759,9 @@ func (r *DefaultReporter) codeLocationBlock(report types.SpecReport, highlightCo
if len(labels[i]) > 0 {
out += r.f(" {{coral}}[%s]{{/}}", strings.Join(labels[i], ", "))
}
if len(semVerConstraints[i]) > 0 {
out += r.f(" {{coral}}[%s]{{/}}", strings.Join(semVerConstraints[i], ", "))
}
out += "\n"
out += r.fi(uint(i), "{{gray}}%s{{/}}\n", locations[i])
}
@@ -770,6 +785,10 @@ func (r *DefaultReporter) codeLocationBlock(report types.SpecReport, highlightCo
if len(flattenedLabels) > 0 {
out += r.f(" {{coral}}[%s]{{/}}", strings.Join(flattenedLabels, ", "))
}
flattenedSemVerConstraints := report.SemVerConstraints()
if len(flattenedSemVerConstraints) > 0 {
out += r.f(" {{coral}}[%s]{{/}}", strings.Join(flattenedSemVerConstraints, ", "))
}
out += "\n"
if usePreciseFailureLocation {
out += r.f("{{gray}}%s{{/}}", failureLocation)

View File

@@ -36,6 +36,9 @@ type JunitReportConfig struct {
// Enable OmitSpecLabels to prevent labels from appearing in the spec name
OmitSpecLabels bool
// Enable OmitSpecSemVerConstraints to prevent semantic version constraints from appearing in the spec name
OmitSpecSemVerConstraints bool
// Enable OmitLeafNodeType to prevent the spec leaf node type from appearing in the spec name
OmitLeafNodeType bool
@@ -169,9 +172,11 @@ func GenerateJUnitReportWithConfig(report types.Report, dst string, config Junit
{"SuiteHasProgrammaticFocus", fmt.Sprintf("%t", report.SuiteHasProgrammaticFocus)},
{"SpecialSuiteFailureReason", strings.Join(report.SpecialSuiteFailureReasons, ",")},
{"SuiteLabels", fmt.Sprintf("[%s]", strings.Join(report.SuiteLabels, ","))},
{"SuiteSemVerConstraints", fmt.Sprintf("[%s]", strings.Join(report.SuiteSemVerConstraints, ","))},
{"RandomSeed", fmt.Sprintf("%d", report.SuiteConfig.RandomSeed)},
{"RandomizeAllSpecs", fmt.Sprintf("%t", report.SuiteConfig.RandomizeAllSpecs)},
{"LabelFilter", report.SuiteConfig.LabelFilter},
{"SemVerFilter", report.SuiteConfig.SemVerFilter},
{"FocusStrings", strings.Join(report.SuiteConfig.FocusStrings, ",")},
{"SkipStrings", strings.Join(report.SuiteConfig.SkipStrings, ",")},
{"FocusFiles", strings.Join(report.SuiteConfig.FocusFiles, ";")},
@@ -207,6 +212,10 @@ func GenerateJUnitReportWithConfig(report types.Report, dst string, config Junit
owner = matches[1]
}
}
semVerConstraints := spec.SemVerConstraints()
if len(semVerConstraints) > 0 && !config.OmitSpecSemVerConstraints {
name = name + " [" + strings.Join(semVerConstraints, ", ") + "]"
}
name = strings.TrimSpace(name)
test := JUnitTestCase{

View File

@@ -38,9 +38,13 @@ func GenerateTeamcityReport(report types.Report, dst string) error {
name := report.SuiteDescription
labels := report.SuiteLabels
semVerConstraints := report.SuiteSemVerConstraints
if len(labels) > 0 {
name = name + " [" + strings.Join(labels, ", ") + "]"
}
if len(semVerConstraints) > 0 {
name = name + " [" + strings.Join(semVerConstraints, ", ") + "]"
}
fmt.Fprintf(f, "##teamcity[testSuiteStarted name='%s']\n", tcEscape(name))
for _, spec := range report.SpecReports {
name := fmt.Sprintf("[%s]", spec.LeafNodeType)
@@ -51,6 +55,10 @@ func GenerateTeamcityReport(report types.Report, dst string) error {
if len(labels) > 0 {
name = name + " [" + strings.Join(labels, ", ") + "]"
}
semVerConstraints := spec.SemVerConstraints()
if len(semVerConstraints) > 0 {
name = name + " [" + strings.Join(semVerConstraints, ", ") + "]"
}
name = tcEscape(name)
fmt.Fprintf(f, "##teamcity[testStarted name='%s']\n", name)

View File

@@ -24,6 +24,7 @@ type SuiteConfig struct {
FocusFiles []string
SkipFiles []string
LabelFilter string
SemVerFilter string
FailOnPending bool
FailOnEmpty bool
FailFast bool
@@ -308,6 +309,8 @@ var SuiteConfigFlags = GinkgoFlags{
{KeyPath: "S.LabelFilter", Name: "label-filter", SectionKey: "filter", UsageArgument: "expression",
Usage: "If set, ginkgo will only run specs with labels that match the label-filter. The passed-in expression can include boolean operations (!, &&, ||, ','), groupings via '()', and regular expressions '/regexp/'. e.g. '(cat || dog) && !fruit'"},
{KeyPath: "S.SemVerFilter", Name: "sem-ver-filter", SectionKey: "filter", UsageArgument: "version",
Usage: "If set, ginkgo will only run specs with semantic version constraints that are satisfied by the provided version. e.g. '2.1.0'"},
{KeyPath: "S.FocusStrings", Name: "focus", SectionKey: "filter",
Usage: "If set, ginkgo will only run specs that match this regular expression. Can be specified multiple times, values are ORed."},
{KeyPath: "S.SkipStrings", Name: "skip", SectionKey: "filter",
@@ -443,6 +446,13 @@ func VetConfig(flagSet GinkgoFlagSet, suiteConfig SuiteConfig, reporterConfig Re
}
}
if suiteConfig.SemVerFilter != "" {
_, err := ParseSemVerFilter(suiteConfig.SemVerFilter)
if err != nil {
errors = append(errors, err)
}
}
switch strings.ToLower(suiteConfig.OutputInterceptorMode) {
case "", "dup", "swap", "none":
default:
@@ -573,6 +583,9 @@ var GoBuildFlags = GinkgoFlags{
Usage: "print the name of the temporary work directory and do not delete it when exiting."},
{KeyPath: "Go.X", Name: "x", SectionKey: "go-build",
Usage: "print the commands."},
}
var GoBuildOFlags = GinkgoFlags{
{KeyPath: "Go.O", Name: "o", SectionKey: "go-build",
Usage: "output binary path (including name)."},
}
@@ -673,7 +686,7 @@ func GenerateGoTestCompileArgs(goFlagsConfig GoFlagsConfig, packageToBuild strin
args := []string{"test", "-c", packageToBuild}
goArgs, err := GenerateFlagArgs(
GoBuildFlags,
GoBuildFlags.CopyAppend(GoBuildOFlags...),
map[string]any{
"Go": &goFlagsConfig,
},
@@ -763,6 +776,7 @@ func BuildWatchCommandFlagSet(suiteConfig *SuiteConfig, reporterConfig *Reporter
func BuildBuildCommandFlagSet(cliConfig *CLIConfig, goFlagsConfig *GoFlagsConfig) (GinkgoFlagSet, error) {
flags := GinkgoCLISharedFlags
flags = flags.CopyAppend(GoBuildFlags...)
flags = flags.CopyAppend(GoBuildOFlags...)
bindings := map[string]any{
"C": cliConfig,

View File

@@ -432,6 +432,24 @@ func (g ginkgoErrors) InvalidEmptyLabel(cl CodeLocation) error {
}
}
func (g ginkgoErrors) InvalidSemVerConstraint(semVerConstraint, errMsg string, cl CodeLocation) error {
return GinkgoError{
Heading: "Invalid SemVerConstraint",
Message: fmt.Sprintf("'%s' is an invalid SemVerConstraint: %s", semVerConstraint, errMsg),
CodeLocation: cl,
DocLink: "spec-semantic-version-filtering",
}
}
func (g ginkgoErrors) InvalidEmptySemVerConstraint(cl CodeLocation) error {
return GinkgoError{
Heading: "Invalid Empty SemVerConstraint",
Message: "SemVerConstraint cannot be empty",
CodeLocation: cl,
DocLink: "spec-semantic-version-filtering",
}
}
/* Table errors */
func (g ginkgoErrors) MultipleEntryBodyFunctionsForTable(cl CodeLocation) error {
return GinkgoError{

View File

@@ -0,0 +1,60 @@
package types
import (
"fmt"
"github.com/Masterminds/semver/v3"
)
type SemVerFilter func([]string) bool
func MustParseSemVerFilter(input string) SemVerFilter {
filter, err := ParseSemVerFilter(input)
if err != nil {
panic(err)
}
return filter
}
func ParseSemVerFilter(filterVersion string) (SemVerFilter, error) {
if filterVersion == "" {
return func(_ []string) bool { return true }, nil
}
targetVersion, err := semver.NewVersion(filterVersion)
if err != nil {
return nil, fmt.Errorf("invalid filter version: %w", err)
}
return func(constraints []string) bool {
// unconstrained specs always run
if len(constraints) == 0 {
return true
}
for _, constraintStr := range constraints {
constraint, err := semver.NewConstraint(constraintStr)
if err != nil {
return false
}
if !constraint.Check(targetVersion) {
return false
}
}
return true
}, nil
}
func ValidateAndCleanupSemVerConstraint(semVerConstraint string, cl CodeLocation) (string, error) {
if len(semVerConstraint) == 0 {
return "", GinkgoErrors.InvalidEmptySemVerConstraint(cl)
}
_, err := semver.NewConstraint(semVerConstraint)
if err != nil {
return "", GinkgoErrors.InvalidSemVerConstraint(semVerConstraint, err.Error(), cl)
}
return semVerConstraint, nil
}

View File

@@ -30,6 +30,9 @@ type Report struct {
//SuiteLabels captures any labels attached to the suite by the DSL's RunSpecs() function
SuiteLabels []string
//SuiteSemVerConstraints captures any semVerConstraints attached to the suite by the DSL's RunSpecs() function
SuiteSemVerConstraints []string
//SuiteSucceeded captures the success or failure status of the test run
//If true, the test run is considered successful.
//If false, the test run is considered unsuccessful
@@ -129,13 +132,18 @@ type SpecReport struct {
// all Describe/Context/When containers in this spec's hierarchy
ContainerHierarchyLabels [][]string
// LeafNodeType, LeadNodeLocation, LeafNodeLabels and LeafNodeText capture the NodeType, CodeLocation, and text
// ContainerHierarchySemVerConstraints is a slice containing the semVerConstraints of
// all Describe/Context/When containers in this spec's hierarchy
ContainerHierarchySemVerConstraints [][]string
// LeafNodeType, LeafNodeLocation, LeafNodeLabels, LeafNodeSemVerConstraints and LeafNodeText capture the NodeType, CodeLocation, and text
// of the Ginkgo node being tested (typically an NodeTypeIt node, though this can also be
// one of the NodeTypesForSuiteLevelNodes node types)
LeafNodeType NodeType
LeafNodeLocation CodeLocation
LeafNodeLabels []string
LeafNodeText string
LeafNodeType NodeType
LeafNodeLocation CodeLocation
LeafNodeLabels []string
LeafNodeSemVerConstraints []string
LeafNodeText string
// State captures whether the spec has passed, failed, etc.
State SpecState
@@ -198,48 +206,52 @@ type SpecReport struct {
func (report SpecReport) MarshalJSON() ([]byte, error) {
//All this to avoid emitting an empty Failure struct in the JSON
out := struct {
ContainerHierarchyTexts []string
ContainerHierarchyLocations []CodeLocation
ContainerHierarchyLabels [][]string
LeafNodeType NodeType
LeafNodeLocation CodeLocation
LeafNodeLabels []string
LeafNodeText string
State SpecState
StartTime time.Time
EndTime time.Time
RunTime time.Duration
ParallelProcess int
Failure *Failure `json:",omitempty"`
NumAttempts int
MaxFlakeAttempts int
MaxMustPassRepeatedly int
CapturedGinkgoWriterOutput string `json:",omitempty"`
CapturedStdOutErr string `json:",omitempty"`
ReportEntries ReportEntries `json:",omitempty"`
ProgressReports []ProgressReport `json:",omitempty"`
AdditionalFailures []AdditionalFailure `json:",omitempty"`
SpecEvents SpecEvents `json:",omitempty"`
ContainerHierarchyTexts []string
ContainerHierarchyLocations []CodeLocation
ContainerHierarchyLabels [][]string
ContainerHierarchySemVerConstraints [][]string
LeafNodeType NodeType
LeafNodeLocation CodeLocation
LeafNodeLabels []string
LeafNodeSemVerConstraints []string
LeafNodeText string
State SpecState
StartTime time.Time
EndTime time.Time
RunTime time.Duration
ParallelProcess int
Failure *Failure `json:",omitempty"`
NumAttempts int
MaxFlakeAttempts int
MaxMustPassRepeatedly int
CapturedGinkgoWriterOutput string `json:",omitempty"`
CapturedStdOutErr string `json:",omitempty"`
ReportEntries ReportEntries `json:",omitempty"`
ProgressReports []ProgressReport `json:",omitempty"`
AdditionalFailures []AdditionalFailure `json:",omitempty"`
SpecEvents SpecEvents `json:",omitempty"`
}{
ContainerHierarchyTexts: report.ContainerHierarchyTexts,
ContainerHierarchyLocations: report.ContainerHierarchyLocations,
ContainerHierarchyLabels: report.ContainerHierarchyLabels,
LeafNodeType: report.LeafNodeType,
LeafNodeLocation: report.LeafNodeLocation,
LeafNodeLabels: report.LeafNodeLabels,
LeafNodeText: report.LeafNodeText,
State: report.State,
StartTime: report.StartTime,
EndTime: report.EndTime,
RunTime: report.RunTime,
ParallelProcess: report.ParallelProcess,
Failure: nil,
ReportEntries: nil,
NumAttempts: report.NumAttempts,
MaxFlakeAttempts: report.MaxFlakeAttempts,
MaxMustPassRepeatedly: report.MaxMustPassRepeatedly,
CapturedGinkgoWriterOutput: report.CapturedGinkgoWriterOutput,
CapturedStdOutErr: report.CapturedStdOutErr,
ContainerHierarchyTexts: report.ContainerHierarchyTexts,
ContainerHierarchyLocations: report.ContainerHierarchyLocations,
ContainerHierarchyLabels: report.ContainerHierarchyLabels,
ContainerHierarchySemVerConstraints: report.ContainerHierarchySemVerConstraints,
LeafNodeType: report.LeafNodeType,
LeafNodeLocation: report.LeafNodeLocation,
LeafNodeLabels: report.LeafNodeLabels,
LeafNodeSemVerConstraints: report.LeafNodeSemVerConstraints,
LeafNodeText: report.LeafNodeText,
State: report.State,
StartTime: report.StartTime,
EndTime: report.EndTime,
RunTime: report.RunTime,
ParallelProcess: report.ParallelProcess,
Failure: nil,
ReportEntries: nil,
NumAttempts: report.NumAttempts,
MaxFlakeAttempts: report.MaxFlakeAttempts,
MaxMustPassRepeatedly: report.MaxMustPassRepeatedly,
CapturedGinkgoWriterOutput: report.CapturedGinkgoWriterOutput,
CapturedStdOutErr: report.CapturedStdOutErr,
}
if !report.Failure.IsZero() {
@@ -312,6 +324,28 @@ func (report SpecReport) Labels() []string {
return out
}
// SemVerConstraints returns a deduped set of all the spec's SemVerConstraints.
func (report SpecReport) SemVerConstraints() []string {
out := []string{}
seen := map[string]bool{}
for _, semVerConstraints := range report.ContainerHierarchySemVerConstraints {
for _, semVerConstraint := range semVerConstraints {
if !seen[semVerConstraint] {
seen[semVerConstraint] = true
out = append(out, semVerConstraint)
}
}
}
for _, semVerConstraint := range report.LeafNodeSemVerConstraints {
if !seen[semVerConstraint] {
seen[semVerConstraint] = true
out = append(out, semVerConstraint)
}
}
return out
}
// MatchesLabelFilter returns true if the spec satisfies the passed in label filter query
func (report SpecReport) MatchesLabelFilter(query string) (bool, error) {
filter, err := ParseLabelFilter(query)
@@ -321,6 +355,15 @@ func (report SpecReport) MatchesLabelFilter(query string) (bool, error) {
return filter(report.Labels()), nil
}
// MatchesSemVerFilter returns true if the spec satisfies the passed in label filter query
func (report SpecReport) MatchesSemVerFilter(version string) (bool, error) {
filter, err := ParseSemVerFilter(version)
if err != nil {
return false, err
}
return filter(report.SemVerConstraints()), nil
}
// FileName() returns the name of the file containing the spec
func (report SpecReport) FileName() string {
return report.LeafNodeLocation.FileName

View File

@@ -1,3 +1,3 @@
package types
const VERSION = "2.23.4"
const VERSION = "2.24.0"

View File

@@ -85,6 +85,7 @@ type event struct {
// TODO: Experiment with storing only the second word of event.node (unsafe.Pointer).
// Type can be recovered from the sole bit in typ.
// [Tried this, wasn't faster. --adonovan]
// Preorder visits all the nodes of the files supplied to New in
// depth-first order. It calls f(n) for each node n before it visits

View File

@@ -12,8 +12,6 @@ package inspector
import (
"go/ast"
"math"
_ "unsafe"
)
const (

8
vendor/modules.txt vendored
View File

@@ -14,7 +14,7 @@ github.com/BurntSushi/toml/internal
# github.com/Masterminds/goutils v1.1.1
## explicit
github.com/Masterminds/goutils
# github.com/Masterminds/semver/v3 v3.3.0
# github.com/Masterminds/semver/v3 v3.3.1
## explicit; go 1.21
github.com/Masterminds/semver/v3
# github.com/Masterminds/sprig/v3 v3.3.0
@@ -229,7 +229,7 @@ github.com/fxamacker/cbor/v2
# github.com/ghodss/yaml v1.0.0
## explicit
github.com/ghodss/yaml
# github.com/go-logr/logr v1.4.2
# github.com/go-logr/logr v1.4.3
## explicit; go 1.18
github.com/go-logr/logr
github.com/go-logr/logr/funcr
@@ -384,7 +384,7 @@ github.com/modern-go/reflect2
# github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822
## explicit
github.com/munnerz/goautoneg
# github.com/onsi/ginkgo/v2 v2.23.4
# github.com/onsi/ginkgo/v2 v2.24.0
## explicit; go 1.23.0
github.com/onsi/ginkgo/v2
github.com/onsi/ginkgo/v2/config
@@ -815,7 +815,7 @@ golang.org/x/text/unicode/norm
# golang.org/x/time v0.12.0
## explicit; go 1.23.0
golang.org/x/time/rate
# golang.org/x/tools v0.35.0
# golang.org/x/tools v0.36.0
## explicit; go 1.23.0
golang.org/x/tools/cover
golang.org/x/tools/go/ast/edge