mirror of
https://github.com/1Password/onepassword-operator.git
synced 2025-10-22 15:38:06 +00:00
Update packages and add vendor directory
This commit is contained in:
7
vendor/github.com/onsi/ginkgo/.gitignore
generated
vendored
Normal file
7
vendor/github.com/onsi/ginkgo/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
.DS_Store
|
||||
TODO
|
||||
tmp/**/*
|
||||
*.coverprofile
|
||||
.vscode
|
||||
.idea/
|
||||
*.log
|
24
vendor/github.com/onsi/ginkgo/.travis.yml
generated
vendored
Normal file
24
vendor/github.com/onsi/ginkgo/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
language: go
|
||||
go:
|
||||
- tip
|
||||
- 1.16.x
|
||||
- 1.15.x
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $GOPATH/pkg/mod
|
||||
|
||||
# allow internal package imports, necessary for forked repositories
|
||||
go_import_path: github.com/onsi/ginkgo
|
||||
|
||||
install:
|
||||
- GO111MODULE="off" go get -v -t ./...
|
||||
- GO111MODULE="off" go get golang.org/x/tools/cmd/cover
|
||||
- GO111MODULE="off" go get github.com/onsi/gomega
|
||||
- GO111MODULE="off" go install github.com/onsi/ginkgo/ginkgo
|
||||
- export PATH=$GOPATH/bin:$PATH
|
||||
|
||||
script:
|
||||
- GO111MODULE="on" go mod tidy && git diff --exit-code go.mod go.sum
|
||||
- go vet
|
||||
- ginkgo -r --randomizeAllSpecs --randomizeSuites --race --trace
|
393
vendor/github.com/onsi/ginkgo/CHANGELOG.md
generated
vendored
Normal file
393
vendor/github.com/onsi/ginkgo/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,393 @@
|
||||
## 1.16.5
|
||||
|
||||
Ginkgo 2.0 now has a Release Candidate. 1.16.5 advertises the existence of the RC.
|
||||
1.16.5 deprecates GinkgoParallelNode in favor of GinkgoParallelProcess
|
||||
|
||||
You can silence the RC advertisement by setting an `ACK_GINKG_RC=true` environment variable or creating a file in your home directory called `.ack-ginkgo-rc`
|
||||
|
||||
## 1.16.4
|
||||
|
||||
### Fixes
|
||||
1.16.4 retracts 1.16.3. There are no code changes. The 1.16.3 tag was associated with the wrong commit and an attempt to change it after-the-fact has proven problematic. 1.16.4 retracts 1.16.3 in Ginkgo's go.mod and creates a new, correctly tagged, release.
|
||||
|
||||
## 1.16.3
|
||||
|
||||
### Features
|
||||
- Measure is now deprecated and emits a deprecation warning.
|
||||
|
||||
## 1.16.2
|
||||
|
||||
### Fixes
|
||||
- Deprecations can be suppressed by setting an `ACK_GINKGO_DEPRECATIONS=<semver>` environment variable.
|
||||
|
||||
## 1.16.1
|
||||
|
||||
### Fixes
|
||||
- Supress --stream deprecation warning on windows (#793)
|
||||
|
||||
## 1.16.0
|
||||
|
||||
### Features
|
||||
- Advertise Ginkgo 2.0. Introduce deprecations. [9ef1913]
|
||||
- Update README.md to advertise that Ginkgo 2.0 is coming.
|
||||
- Backport the 2.0 DeprecationTracker and start alerting users
|
||||
about upcoming deprecations.
|
||||
|
||||
- Add slim-sprig template functions to bootstrap/generate (#775) [9162b86]
|
||||
|
||||
### Fixes
|
||||
- Fix accidental reference to 1488 (#784) [9fb7fe4]
|
||||
|
||||
## 1.15.2
|
||||
|
||||
### Fixes
|
||||
- ignore blank `-focus` and `-skip` flags (#780) [e90a4a0]
|
||||
|
||||
## 1.15.1
|
||||
|
||||
### Fixes
|
||||
- reporters/junit: Use `system-out` element instead of `passed` (#769) [9eda305]
|
||||
|
||||
## 1.15.0
|
||||
|
||||
### Features
|
||||
- Adds 'outline' command to print the outline of specs/containers in a file (#754) [071c369] [6803cc3] [935b538] [06744e8] [0c40583]
|
||||
- Add support for using template to generate tests (#752) [efb9e69]
|
||||
- Add a Chinese Doc #755 (#756) [5207632]
|
||||
- cli: allow multiple -focus and -skip flags (#736) [9a782fb]
|
||||
|
||||
### Fixes
|
||||
- Add _internal to filename of tests created with internal flag (#751) [43c12da]
|
||||
|
||||
## 1.14.2
|
||||
|
||||
### Fixes
|
||||
- correct handling windows backslash in import path (#721) [97f3d51]
|
||||
- Add additional methods to GinkgoT() to improve compatibility with the testing.TB interface [b5fe44d]
|
||||
|
||||
## 1.14.1
|
||||
|
||||
### Fixes
|
||||
- Discard exported method declaration when running ginkgo bootstrap (#558) [f4b0240]
|
||||
|
||||
## 1.14.0
|
||||
|
||||
### Features
|
||||
- Defer running top-level container nodes until RunSpecs is called [d44dedf]
|
||||
- [Document Ginkgo lifecycle](http://onsi.github.io/ginkgo/#understanding-ginkgos-lifecycle)
|
||||
- Add `extensions/globals` package (#692) [3295c8f] - this can be helpful in contexts where you are test-driving your test-generation code (see [#692](https://github.com/onsi/ginkgo/pull/692))
|
||||
- Print Skip reason in JUnit reporter if one was provided [820dfab]
|
||||
|
||||
## 1.13.0
|
||||
|
||||
### Features
|
||||
- Add a version of table.Entry that allows dumping the entry parameters. (#689) [21eaef2]
|
||||
|
||||
### Fixes
|
||||
- Ensure integration tests pass in an environment sans GOPATH [606fba2]
|
||||
- Add books package (#568) [fc0e44e]
|
||||
- doc(readme): installation via "tools package" (#677) [83bb20e]
|
||||
- Solve the undefined: unix.Dup2 compile error on mips64le (#680) [0624f75]
|
||||
- Import package without dot (#687) [6321024]
|
||||
- Fix integration tests to stop require GOPATH (#686) [a912ec5]
|
||||
|
||||
## 1.12.3
|
||||
|
||||
### Fixes
|
||||
- Print correct code location of failing table test (#666) [c6d7afb]
|
||||
|
||||
## 1.12.2
|
||||
|
||||
### Fixes
|
||||
- Update dependencies [ea4a036]
|
||||
|
||||
## 1.12.1
|
||||
|
||||
### Fixes
|
||||
- Make unfocus ("blur") much faster (#674) [8b18061]
|
||||
- Fix typo (#673) [7fdcbe8]
|
||||
- Test against 1.14 and remove 1.12 [d5c2ad6]
|
||||
- Test if a coverprofile content is empty before checking its latest character (#670) [14d9fa2]
|
||||
- replace tail package with maintained one. this fixes go get errors (#667) [4ba33d4]
|
||||
- improve ginkgo performance - makes progress on #644 [a14f98e]
|
||||
- fix convert integration tests [1f8ba69]
|
||||
- fix typo succesful -> successful (#663) [1ea49cf]
|
||||
- Fix invalid link (#658) [b886136]
|
||||
- convert utility : Include comments from source (#657) [1077c6d]
|
||||
- Explain what BDD means [d79e7fb]
|
||||
- skip race detector test on unsupported platform (#642) [f8ab89d]
|
||||
- Use Dup2 from golang.org/x/sys/unix instead of syscallDup (#638) [5d53c55]
|
||||
- Fix missing newline in combined coverage file (#641) [6a07ea2]
|
||||
- check if a spec is run before returning SpecSummary (#645) [8850000]
|
||||
|
||||
## 1.12.0
|
||||
|
||||
### Features
|
||||
- Add module definition (#630) [78916ab]
|
||||
|
||||
## 1.11.0
|
||||
|
||||
### Features
|
||||
- Add syscall for riscv64 architecture [f66e896]
|
||||
- teamcity reporter: output location of test failure as well as test definition (#626) [9869142]
|
||||
- teamcity reporter: output newline after every service message (#625) [3cfa02d]
|
||||
- Add support for go module when running `generate` command (#578) [9c89e3f]
|
||||
|
||||
## 1.10.3
|
||||
|
||||
### Fixes
|
||||
- Set go_import_path in travis.yml to allow internal packages in forks (#607) [3b721db]
|
||||
- Add integration test [d90e0dc]
|
||||
- Fix coverage files combining [e5dde8c]
|
||||
- A new CLI option: -ginkgo.reportFile <file path> (#601) [034fd25]
|
||||
|
||||
## 1.10.2
|
||||
|
||||
### Fixes
|
||||
- speed up table entry generateIt() (#609) [5049dc5]
|
||||
- Fix. Write errors to stderr instead of stdout (#610) [7bb3091]
|
||||
|
||||
## 1.10.1
|
||||
|
||||
### Fixes
|
||||
- stack backtrace: fix skipping (#600) [2a4c0bd]
|
||||
|
||||
## 1.10.0
|
||||
|
||||
### Fixes
|
||||
- stack backtrace: fix alignment and skipping [66915d6]
|
||||
- fix typo in documentation [8f97b93]
|
||||
|
||||
## 1.9.0
|
||||
|
||||
### Features
|
||||
- Option to print output into report, when tests have passed [0545415]
|
||||
|
||||
### Fixes
|
||||
- Fixed typos in comments [0ecbc58]
|
||||
- gofmt code [a7f8bfb]
|
||||
- Simplify code [7454d00]
|
||||
- Simplify concatenation, incrementation and function assignment [4825557]
|
||||
- Avoid unnecessary conversions [9d9403c]
|
||||
- JUnit: include more detailed information about panic [19cca4b]
|
||||
- Print help to stdout when the user asks for help [4cb7441]
|
||||
|
||||
|
||||
## 1.8.0
|
||||
|
||||
### New Features
|
||||
- allow config of the vet flag for `go test` (#562) [3cd45fa]
|
||||
- Support projects using go modules [d56ee76]
|
||||
|
||||
### Fixes and Minor Improvements
|
||||
- chore(godoc): fixes typos in Measurement funcs [dbaca8e]
|
||||
- Optimize focus to avoid allocations [f493786]
|
||||
- Ensure generated test file names are underscored [505cc35]
|
||||
|
||||
## 1.7.0
|
||||
|
||||
### New Features
|
||||
- Add JustAfterEach (#484) [0d4f080]
|
||||
|
||||
### Fixes
|
||||
- Correctly round suite time in junit reporter [2445fc1]
|
||||
- Avoid using -i argument to go test for Golang 1.10+ [46bbc26]
|
||||
|
||||
## 1.6.0
|
||||
|
||||
### New Features
|
||||
- add --debug flag to emit node output to files (#499) [39febac]
|
||||
|
||||
### Fixes
|
||||
- fix: for `go vet` to pass [69338ec]
|
||||
- docs: fix for contributing instructions [7004cb1]
|
||||
- consolidate and streamline contribution docs (#494) [d848015]
|
||||
- Make generated Junit file compatable with "Maven Surefire" (#488) [e51bee6]
|
||||
- all: gofmt [000d317]
|
||||
- Increase eventually timeout to 30s [c73579c]
|
||||
- Clarify asynchronous test behaviour [294d8f4]
|
||||
- Travis badge should only show master [26d2143]
|
||||
|
||||
## 1.5.0 5/10/2018
|
||||
|
||||
### New Features
|
||||
- Supports go v1.10 (#443, #446, #451) [e873237, 468e89e, e37dbfe, a37f4c0, c0b857d, bca5260, 4177ca8]
|
||||
- Add a When() synonym for Context() (#386) [747514b, 7484dad, 7354a07, dd826c8]
|
||||
- Re-add noisySkippings flag [652e15c]
|
||||
- Allow coverage to be displayed for focused specs (#367) [11459a8]
|
||||
- Handle -outputdir flag (#364) [228e3a8]
|
||||
- Handle -coverprofile flag (#355) [43392d5]
|
||||
|
||||
### Fixes
|
||||
- When using custom reporters register the custom reporters *before* the default reporter. This allows users to see the output of any print statements in their customer reporters. (#365) [8382b23]
|
||||
- When running a test and calculating the coverage using the `-coverprofile` and `-outputdir` flags, Ginkgo fails with an error if the directory does not exist. This is due to an [issue in go 1.10](https://github.com/golang/go/issues/24588) (#446) [b36a6e0]
|
||||
- `unfocus` command ignores vendor folder (#459) [e5e551c, c556e43, a3b6351, 9a820dd]
|
||||
- Ignore packages whose tests are all ignored by go (#456) [7430ca7, 6d8be98]
|
||||
- Increase the threshold when checking time measuments (#455) [2f714bf, 68f622c]
|
||||
- Fix race condition in coverage tests (#423) [a5a8ff7, ab9c08b]
|
||||
- Add an extra new line after reporting spec run completion for test2json [874520d]
|
||||
- added name name field to junit reported testsuite [ae61c63]
|
||||
- Do not set the run time of a spec when the dryRun flag is used (#438) [457e2d9, ba8e856]
|
||||
- Process FWhen and FSpecify when unfocusing (#434) [9008c7b, ee65bd, df87dfe]
|
||||
- Synchronise the access to the state of specs to avoid race conditions (#430) [7d481bc, ae6829d]
|
||||
- Added Duration on GinkgoTestDescription (#383) [5f49dad, 528417e, 0747408, 329d7ed]
|
||||
- Fix Ginkgo stack trace on failure for Specify (#415) [b977ede, 65ca40e, 6c46eb8]
|
||||
- Update README with Go 1.6+, Golang -> Go (#409) [17f6b97, bc14b66, 20d1598]
|
||||
- Use fmt.Errorf instead of errors.New(fmt.Sprintf (#401) [a299f56, 44e2eaa]
|
||||
- Imports in generated code should follow conventions (#398) [0bec0b0, e8536d8]
|
||||
- Prevent data race error when Recording a benchmark value from multiple go routines (#390) [c0c4881, 7a241e9]
|
||||
- Replace GOPATH in Environment [4b883f0]
|
||||
|
||||
|
||||
## 1.4.0 7/16/2017
|
||||
|
||||
- `ginkgo` now provides a hint if you accidentally forget to run `ginkgo bootstrap` to generate a `*_suite_test.go` file that actually invokes the Ginkgo test runner. [#345](https://github.com/onsi/ginkgo/pull/345)
|
||||
- thanks to improvements in `go test -c` `ginkgo` no longer needs to fix Go's compilation output to ensure compilation errors are expressed relative to the CWD. [#357]
|
||||
- `ginkgo watch -watchRegExp=...` allows you to specify a custom regular expression to watch. Only files matching the regular expression are watched for changes (the default is `\.go$`) [#356]
|
||||
- `ginkgo` now always emits compilation output. Previously, only failed compilation output was printed out. [#277]
|
||||
- `ginkgo -requireSuite` now fails the test run if there are `*_test.go` files but `go test` fails to detect any tests. Typically this means you forgot to run `ginkgo bootstrap` to generate a suite file. [#344]
|
||||
- `ginkgo -timeout=DURATION` allows you to adjust the timeout for the entire test suite (default is 24 hours) [#248]
|
||||
|
||||
## 1.3.0 3/28/2017
|
||||
|
||||
Improvements:
|
||||
|
||||
- Significantly improved parallel test distribution. Now instead of pre-sharding test cases across workers (which can result in idle workers and poor test performance) Ginkgo uses a shared queue to keep all workers busy until all tests are complete. This improves test-time performance and consistency.
|
||||
- `Skip(message)` can be used to skip the current test.
|
||||
- Added `extensions/table` - a Ginkgo DSL for [Table Driven Tests](http://onsi.github.io/ginkgo/#table-driven-tests)
|
||||
- Add `GinkgoRandomSeed()` - shorthand for `config.GinkgoConfig.RandomSeed`
|
||||
- Support for retrying flaky tests with `--flakeAttempts`
|
||||
- `ginkgo ./...` now recurses as you'd expect
|
||||
- Added `Specify` a synonym for `It`
|
||||
- Support colorise on Windows
|
||||
- Broader support for various go compilation flags in the `ginkgo` CLI
|
||||
|
||||
Bug Fixes:
|
||||
|
||||
- Ginkgo tests now fail when you `panic(nil)` (#167)
|
||||
|
||||
## 1.2.0 5/31/2015
|
||||
|
||||
Improvements
|
||||
|
||||
- `ginkgo -coverpkg` calls down to `go test -coverpkg` (#160)
|
||||
- `ginkgo -afterSuiteHook COMMAND` invokes the passed-in `COMMAND` after a test suite completes (#152)
|
||||
- Relaxed requirement for Go 1.4+. `ginkgo` now works with Go v1.3+ (#166)
|
||||
|
||||
## 1.2.0-beta
|
||||
|
||||
Ginkgo now requires Go 1.4+
|
||||
|
||||
Improvements:
|
||||
|
||||
- Call reporters in reverse order when announcing spec completion -- allows custom reporters to emit output before the default reporter does.
|
||||
- Improved focus behavior. Now, this:
|
||||
|
||||
```golang
|
||||
FDescribe("Some describe", func() {
|
||||
It("A", func() {})
|
||||
|
||||
FIt("B", func() {})
|
||||
})
|
||||
```
|
||||
|
||||
will run `B` but *not* `A`. This tends to be a common usage pattern when in the thick of writing and debugging tests.
|
||||
- When `SIGINT` is received, Ginkgo will emit the contents of the `GinkgoWriter` before running the `AfterSuite`. Useful for debugging stuck tests.
|
||||
- When `--progress` is set, Ginkgo will write test progress (in particular, Ginkgo will say when it is about to run a BeforeEach, AfterEach, It, etc...) to the `GinkgoWriter`. This is useful for debugging stuck tests and tests that generate many logs.
|
||||
- Improved output when an error occurs in a setup or teardown block.
|
||||
- When `--dryRun` is set, Ginkgo will walk the spec tree and emit to its reporter *without* actually running anything. Best paired with `-v` to understand which specs will run in which order.
|
||||
- Add `By` to help document long `It`s. `By` simply writes to the `GinkgoWriter`.
|
||||
- Add support for precompiled tests:
|
||||
- `ginkgo build <path-to-package>` will now compile the package, producing a file named `package.test`
|
||||
- The compiled `package.test` file can be run directly. This runs the tests in series.
|
||||
- To run precompiled tests in parallel, you can run: `ginkgo -p package.test`
|
||||
- Support `bootstrap`ping and `generate`ing [Agouti](http://agouti.org) specs.
|
||||
- `ginkgo generate` and `ginkgo bootstrap` now honor the package name already defined in a given directory
|
||||
- The `ginkgo` CLI ignores `SIGQUIT`. Prevents its stack dump from interlacing with the underlying test suite's stack dump.
|
||||
- The `ginkgo` CLI now compiles tests into a temporary directory instead of the package directory. This necessitates upgrading to Go v1.4+.
|
||||
- `ginkgo -notify` now works on Linux
|
||||
|
||||
Bug Fixes:
|
||||
|
||||
- If --skipPackages is used and all packages are skipped, Ginkgo should exit 0.
|
||||
- Fix tempfile leak when running in parallel
|
||||
- Fix incorrect failure message when a panic occurs during a parallel test run
|
||||
- Fixed an issue where a pending test within a focused context (or a focused test within a pending context) would skip all other tests.
|
||||
- Be more consistent about handling SIGTERM as well as SIGINT
|
||||
- When interupted while concurrently compiling test suites in the background, Ginkgo now cleans up the compiled artifacts.
|
||||
- Fixed a long standing bug where `ginkgo -p` would hang if a process spawned by one of the Ginkgo parallel nodes does not exit. (Hooray!)
|
||||
|
||||
## 1.1.0 (8/2/2014)
|
||||
|
||||
No changes, just dropping the beta.
|
||||
|
||||
## 1.1.0-beta (7/22/2014)
|
||||
New Features:
|
||||
|
||||
- `ginkgo watch` now monitors packages *and their dependencies* for changes. The depth of the dependency tree can be modified with the `-depth` flag.
|
||||
- Test suites with a programmatic focus (`FIt`, `FDescribe`, etc...) exit with non-zero status code, even when they pass. This allows CI systems to detect accidental commits of focused test suites.
|
||||
- `ginkgo -p` runs the testsuite in parallel with an auto-detected number of nodes.
|
||||
- `ginkgo -tags=TAG_LIST` passes a list of tags down to the `go build` command.
|
||||
- `ginkgo --failFast` aborts the test suite after the first failure.
|
||||
- `ginkgo generate file_1 file_2` can take multiple file arguments.
|
||||
- Ginkgo now summarizes any spec failures that occurred at the end of the test run.
|
||||
- `ginkgo --randomizeSuites` will run tests *suites* in random order using the generated/passed-in seed.
|
||||
|
||||
Improvements:
|
||||
|
||||
- `ginkgo -skipPackage` now takes a comma-separated list of strings. If the *relative path* to a package matches one of the entries in the comma-separated list, that package is skipped.
|
||||
- `ginkgo --untilItFails` no longer recompiles between attempts.
|
||||
- Ginkgo now panics when a runnable node (`It`, `BeforeEach`, `JustBeforeEach`, `AfterEach`, `Measure`) is nested within another runnable node. This is always a mistake. Any test suites that panic because of this change should be fixed.
|
||||
|
||||
Bug Fixes:
|
||||
|
||||
- `ginkgo boostrap` and `ginkgo generate` no longer fail when dealing with `hyphen-separated-packages`.
|
||||
- parallel specs are now better distributed across nodes - fixed a crashing bug where (for example) distributing 11 tests across 7 nodes would panic
|
||||
|
||||
## 1.0.0 (5/24/2014)
|
||||
New Features:
|
||||
|
||||
- Add `GinkgoParallelNode()` - shorthand for `config.GinkgoConfig.ParallelNode`
|
||||
|
||||
Improvements:
|
||||
|
||||
- When compilation fails, the compilation output is rewritten to present a correct *relative* path. Allows ⌘-clicking in iTerm open the file in your text editor.
|
||||
- `--untilItFails` and `ginkgo watch` now generate new random seeds between test runs, unless a particular random seed is specified.
|
||||
|
||||
Bug Fixes:
|
||||
|
||||
- `-cover` now generates a correctly combined coverprofile when running with in parallel with multiple `-node`s.
|
||||
- Print out the contents of the `GinkgoWriter` when `BeforeSuite` or `AfterSuite` fail.
|
||||
- Fix all remaining race conditions in Ginkgo's test suite.
|
||||
|
||||
## 1.0.0-beta (4/14/2014)
|
||||
Breaking changes:
|
||||
|
||||
- `thirdparty/gomocktestreporter` is gone. Use `GinkgoT()` instead
|
||||
- Modified the Reporter interface
|
||||
- `watch` is now a subcommand, not a flag.
|
||||
|
||||
DSL changes:
|
||||
|
||||
- `BeforeSuite` and `AfterSuite` for setting up and tearing down test suites.
|
||||
- `AfterSuite` is triggered on interrupt (`^C`) as well as exit.
|
||||
- `SynchronizedBeforeSuite` and `SynchronizedAfterSuite` for setting up and tearing down singleton resources across parallel nodes.
|
||||
|
||||
CLI changes:
|
||||
|
||||
- `watch` is now a subcommand, not a flag
|
||||
- `--nodot` flag can be passed to `ginkgo generate` and `ginkgo bootstrap` to avoid dot imports. This explicitly imports all exported identifiers in Ginkgo and Gomega. Refreshing this list can be done by running `ginkgo nodot`
|
||||
- Additional arguments can be passed to specs. Pass them after the `--` separator
|
||||
- `--skipPackage` flag takes a regexp and ignores any packages with package names passing said regexp.
|
||||
- `--trace` flag prints out full stack traces when errors occur, not just the line at which the error occurs.
|
||||
|
||||
Misc:
|
||||
|
||||
- Start using semantic versioning
|
||||
- Start maintaining changelog
|
||||
|
||||
Major refactor:
|
||||
|
||||
- Pull out Ginkgo's internal to `internal`
|
||||
- Rename `example` everywhere to `spec`
|
||||
- Much more!
|
33
vendor/github.com/onsi/ginkgo/CONTRIBUTING.md
generated
vendored
Normal file
33
vendor/github.com/onsi/ginkgo/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# Contributing to Ginkgo
|
||||
|
||||
Your contributions to Ginkgo are essential for its long-term maintenance and improvement.
|
||||
|
||||
- Please **open an issue first** - describe what problem you are trying to solve and give the community a forum for input and feedback ahead of investing time in writing code!
|
||||
- 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.
|
||||
- Update the documentation. Ginko uses `godoc` comments and documentation on the `gh-pages` branch.
|
||||
If relevant, please submit a docs PR to that branch alongside your code PR.
|
||||
|
||||
Thanks for supporting Ginkgo!
|
||||
|
||||
## Setup
|
||||
|
||||
Fork the repo, then:
|
||||
|
||||
```
|
||||
go get github.com/onsi/ginkgo
|
||||
go get github.com/onsi/gomega/...
|
||||
cd $GOPATH/src/github.com/onsi/ginkgo
|
||||
git remote add fork git@github.com:<NAME>/ginkgo.git
|
||||
|
||||
ginkgo -r -p # ensure tests are green
|
||||
go vet ./... # ensure linter is happy
|
||||
```
|
||||
|
||||
## Making the PR
|
||||
- go to a new branch `git checkout -b my-feature`
|
||||
- make your changes
|
||||
- run tests and linter again (see above)
|
||||
- `git push fork`
|
||||
- open PR 🎉
|
20
vendor/github.com/onsi/ginkgo/LICENSE
generated
vendored
Normal file
20
vendor/github.com/onsi/ginkgo/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2013-2014 Onsi Fakhouri
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
169
vendor/github.com/onsi/ginkgo/README.md
generated
vendored
Normal file
169
vendor/github.com/onsi/ginkgo/README.md
generated
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||

|
||||
|
||||
[](https://github.com/onsi/ginkgo/actions?query=workflow%3Atest+branch%3Amaster)
|
||||
|
||||
Jump to the [docs](https://onsi.github.io/ginkgo/) | [中文文档](https://ke-chain.github.io/ginkgodoc) to learn more. To start rolling your Ginkgo tests *now* [keep reading](#set-me-up)!
|
||||
|
||||
If you have a question, comment, bug report, feature request, etc. please open a GitHub issue, or visit the [Ginkgo Slack channel](https://app.slack.com/client/T029RQSE6/CQQ50BBNW).
|
||||
|
||||
# Ginkgo 2.0 Release Candidate is available!
|
||||
|
||||
An effort is underway to develop and deliver Ginkgo 2.0. The work is happening in the [ver2](https://github.com/onsi/ginkgo/tree/ver2) branch and a changelog and migration guide is being maintained on that branch [here](https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md). Issue [#711](https://github.com/onsi/ginkgo/issues/711) is the central place for discussion.
|
||||
|
||||
As described in the [changelog](https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md) and [proposal](https://docs.google.com/document/d/1h28ZknXRsTLPNNiOjdHIO-F2toCzq4xoZDXbfYaBdoQ/edit#), Ginkgo 2.0 will clean up the Ginkgo codebase, deprecate and remove some v1 functionality, and add several new much-requested features. To help users get ready for the migration, Ginkgo v1 has started emitting deprecation warnings for features that will no longer be supported with links to documentation for how to migrate away from these features. If you have concerns or comments please chime in on [#711](https://github.com/onsi/ginkgo/issues/711).
|
||||
|
||||
Please start exploring and using the V2 release! To get started follow the [Using the Release Candidate](https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md#using-the-beta) directions in the migration guide.
|
||||
|
||||
## TLDR
|
||||
Ginkgo builds on Go's `testing` package, allowing expressive [Behavior-Driven Development](https://en.wikipedia.org/wiki/Behavior-driven_development) ("BDD") style tests.
|
||||
It is typically (and optionally) paired with the [Gomega](https://github.com/onsi/gomega) matcher library.
|
||||
|
||||
```go
|
||||
Describe("the strings package", func() {
|
||||
Context("strings.Contains()", func() {
|
||||
When("the string contains the substring in the middle", func() {
|
||||
It("returns `true`", func() {
|
||||
Expect(strings.Contains("Ginkgo is awesome", "is")).To(BeTrue())
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Feature List
|
||||
|
||||
- Ginkgo uses Go's `testing` package and can live alongside your existing `testing` tests. It's easy to [bootstrap](https://onsi.github.io/ginkgo/#bootstrapping-a-suite) and start writing your [first tests](https://onsi.github.io/ginkgo/#adding-specs-to-a-suite)
|
||||
|
||||
- Ginkgo allows you to write tests in Go using expressive [Behavior-Driven Development](https://en.wikipedia.org/wiki/Behavior-driven_development) ("BDD") style:
|
||||
- Nestable [`Describe`, `Context` and `When` container blocks](https://onsi.github.io/ginkgo/#organizing-specs-with-containers-describe-and-context)
|
||||
- [`BeforeEach` and `AfterEach` blocks](https://onsi.github.io/ginkgo/#extracting-common-setup-beforeeach) for setup and teardown
|
||||
- [`It` and `Specify` blocks](https://onsi.github.io/ginkgo/#individual-specs-it) that hold your assertions
|
||||
- [`JustBeforeEach` blocks](https://onsi.github.io/ginkgo/#separating-creation-and-configuration-justbeforeeach) that separate creation from configuration (also known as the subject action pattern).
|
||||
- [`BeforeSuite` and `AfterSuite` blocks](https://onsi.github.io/ginkgo/#global-setup-and-teardown-beforesuite-and-aftersuite) to prep for and cleanup after a suite.
|
||||
|
||||
- A comprehensive test runner that lets you:
|
||||
- Mark specs as [pending](https://onsi.github.io/ginkgo/#pending-specs)
|
||||
- [Focus](https://onsi.github.io/ginkgo/#focused-specs) individual specs, and groups of specs, either programmatically or on the command line
|
||||
- Run your tests in [random order](https://onsi.github.io/ginkgo/#spec-permutation), and then reuse random seeds to replicate the same order.
|
||||
- Break up your test suite into parallel processes for straightforward [test parallelization](https://onsi.github.io/ginkgo/#parallel-specs)
|
||||
|
||||
- `ginkgo`: a command line interface with plenty of handy command line arguments for [running your tests](https://onsi.github.io/ginkgo/#running-tests) and [generating](https://onsi.github.io/ginkgo/#generators) test files. Here are a few choice examples:
|
||||
- `ginkgo -nodes=N` runs your tests in `N` parallel processes and print out coherent output in realtime
|
||||
- `ginkgo -cover` runs your tests using Go's code coverage tool
|
||||
- `ginkgo convert` converts an XUnit-style `testing` package to a Ginkgo-style package
|
||||
- `ginkgo -focus="REGEXP"` and `ginkgo -skip="REGEXP"` allow you to specify a subset of tests to run via regular expression
|
||||
- `ginkgo -r` runs all tests suites under the current directory
|
||||
- `ginkgo -v` prints out identifying information for each tests just before it runs
|
||||
|
||||
And much more: run `ginkgo help` for details!
|
||||
|
||||
The `ginkgo` CLI is convenient, but purely optional -- Ginkgo works just fine with `go test`
|
||||
|
||||
- `ginkgo watch` [watches](https://onsi.github.io/ginkgo/#watching-for-changes) packages *and their dependencies* for changes, then reruns tests. Run tests immediately as you develop!
|
||||
|
||||
- Built-in support for testing [asynchronicity](https://onsi.github.io/ginkgo/#asynchronous-tests)
|
||||
|
||||
- Built-in support for [benchmarking](https://onsi.github.io/ginkgo/#benchmark-tests) your code. Control the number of benchmark samples as you gather runtimes and other, arbitrary, bits of numerical information about your code.
|
||||
|
||||
- [Completions for Sublime Text](https://github.com/onsi/ginkgo-sublime-completions): just use [Package Control](https://sublime.wbond.net/) to install `Ginkgo Completions`.
|
||||
|
||||
- [Completions for VSCode](https://github.com/onsi/vscode-ginkgo): just use VSCode's extension installer to install `vscode-ginkgo`.
|
||||
|
||||
- [Ginkgo tools for VSCode](https://marketplace.visualstudio.com/items?itemName=joselitofilho.ginkgotestexplorer): just use VSCode's extension installer to install `ginkgoTestExplorer`.
|
||||
|
||||
- Straightforward support for third-party testing libraries such as [Gomock](https://code.google.com/p/gomock/) and [Testify](https://github.com/stretchr/testify). Check out the [docs](https://onsi.github.io/ginkgo/#third-party-integrations) for details.
|
||||
|
||||
- A modular architecture that lets you easily:
|
||||
- Write [custom reporters](https://onsi.github.io/ginkgo/#writing-custom-reporters) (for example, Ginkgo comes with a [JUnit XML reporter](https://onsi.github.io/ginkgo/#generating-junit-xml-output) and a TeamCity reporter).
|
||||
- [Adapt an existing matcher library (or write your own!)](https://onsi.github.io/ginkgo/#using-other-matcher-libraries) to work with Ginkgo
|
||||
|
||||
## [Gomega](https://github.com/onsi/gomega): Ginkgo's Preferred Matcher Library
|
||||
|
||||
Ginkgo is best paired with Gomega. Learn more about Gomega [here](https://onsi.github.io/gomega/)
|
||||
|
||||
## [Agouti](https://github.com/sclevine/agouti): A Go Acceptance Testing Framework
|
||||
|
||||
Agouti allows you run WebDriver integration tests. Learn more about Agouti [here](https://agouti.org)
|
||||
|
||||
## Getting Started
|
||||
|
||||
You'll need the Go command-line tools. Follow the [installation instructions](https://golang.org/doc/install) if you don't have it installed.
|
||||
|
||||
### Global installation
|
||||
To install the Ginkgo command line interface:
|
||||
```bash
|
||||
go get -u github.com/onsi/ginkgo/ginkgo
|
||||
```
|
||||
Note that this will install it to `$GOBIN`, which will need to be in the `$PATH` (or equivalent). Run `go help install` for more information.
|
||||
|
||||
### Go module ["tools package"](https://github.com/golang/go/issues/25922):
|
||||
Create (or update) a file called `tools/tools.go` with the following contents:
|
||||
```go
|
||||
// +build tools
|
||||
|
||||
package tools
|
||||
|
||||
import (
|
||||
_ "github.com/onsi/ginkgo/ginkgo"
|
||||
)
|
||||
|
||||
// This file imports packages that are used when running go generate, or used
|
||||
// during the development process but not otherwise depended on by built code.
|
||||
```
|
||||
The Ginkgo command can then be run via `go run github.com/onsi/ginkgo/ginkgo`.
|
||||
This approach allows the version of Ginkgo to be maintained under source control for reproducible results,
|
||||
and is well suited to automated test pipelines.
|
||||
|
||||
### Bootstrapping
|
||||
```bash
|
||||
cd path/to/package/you/want/to/test
|
||||
|
||||
ginkgo bootstrap # set up a new ginkgo suite
|
||||
ginkgo generate # will create a sample test file. edit this file and add your tests then...
|
||||
|
||||
go test # to run your tests
|
||||
|
||||
ginkgo # also runs your tests
|
||||
|
||||
```
|
||||
|
||||
## I'm new to Go: What are my testing options?
|
||||
|
||||
Of course, I heartily recommend [Ginkgo](https://github.com/onsi/ginkgo) and [Gomega](https://github.com/onsi/gomega). Both packages are seeing heavy, daily, production use on a number of projects and boast a mature and comprehensive feature-set.
|
||||
|
||||
With that said, it's great to know what your options are :)
|
||||
|
||||
### What Go gives you out of the box
|
||||
|
||||
Testing is a first class citizen in Go, however Go's built-in testing primitives are somewhat limited: The [testing](https://golang.org/pkg/testing) package provides basic XUnit style tests and no assertion library.
|
||||
|
||||
### Matcher libraries for Go's XUnit style tests
|
||||
|
||||
A number of matcher libraries have been written to augment Go's built-in XUnit style tests. Here are two that have gained traction:
|
||||
|
||||
- [testify](https://github.com/stretchr/testify)
|
||||
- [gocheck](https://labix.org/gocheck)
|
||||
|
||||
You can also use Ginkgo's matcher library [Gomega](https://github.com/onsi/gomega) in [XUnit style tests](https://onsi.github.io/gomega/#using-gomega-with-golangs-xunitstyle-tests)
|
||||
|
||||
### BDD style testing frameworks
|
||||
|
||||
There are a handful of BDD-style testing frameworks written for Go. Here are a few:
|
||||
|
||||
- [Ginkgo](https://github.com/onsi/ginkgo) ;)
|
||||
- [GoConvey](https://github.com/smartystreets/goconvey)
|
||||
- [Goblin](https://github.com/franela/goblin)
|
||||
- [Mao](https://github.com/azer/mao)
|
||||
- [Zen](https://github.com/pranavraja/zen)
|
||||
|
||||
Finally, @shageman has [put together](https://github.com/shageman/gotestit) a comprehensive comparison of Go testing libraries.
|
||||
|
||||
Go explore!
|
||||
|
||||
## License
|
||||
|
||||
Ginkgo is MIT-Licensed
|
||||
|
||||
## Contributing
|
||||
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md)
|
17
vendor/github.com/onsi/ginkgo/RELEASING.md
generated
vendored
Normal file
17
vendor/github.com/onsi/ginkgo/RELEASING.md
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
A Ginkgo release is a tagged git sha and a GitHub release. To cut a release:
|
||||
|
||||
1. Ensure CHANGELOG.md is up to date.
|
||||
- Use `git log --pretty=format:'- %s [%h]' HEAD...vX.X.X` to list all the commits since the last release
|
||||
- Categorize the changes into
|
||||
- Breaking Changes (requires a major version)
|
||||
- New Features (minor version)
|
||||
- Fixes (fix version)
|
||||
- Maintenance (which in general should not be mentioned in `CHANGELOG.md` as they have no user impact)
|
||||
1. Update `VERSION` in `config/config.go`
|
||||
1. Commit, push, and release:
|
||||
```
|
||||
git commit -m "vM.m.p"
|
||||
git push
|
||||
gh release create "vM.m.p"
|
||||
git fetch --tags origin master
|
||||
```
|
232
vendor/github.com/onsi/ginkgo/config/config.go
generated
vendored
Normal file
232
vendor/github.com/onsi/ginkgo/config/config.go
generated
vendored
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
Ginkgo accepts a number of configuration options.
|
||||
|
||||
These are documented [here](http://onsi.github.io/ginkgo/#the-ginkgo-cli)
|
||||
|
||||
You can also learn more via
|
||||
|
||||
ginkgo help
|
||||
|
||||
or (I kid you not):
|
||||
|
||||
go test -asdf
|
||||
*/
|
||||
package config
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"time"
|
||||
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const VERSION = "1.16.5"
|
||||
|
||||
type GinkgoConfigType struct {
|
||||
RandomSeed int64
|
||||
RandomizeAllSpecs bool
|
||||
RegexScansFilePath bool
|
||||
FocusStrings []string
|
||||
SkipStrings []string
|
||||
SkipMeasurements bool
|
||||
FailOnPending bool
|
||||
FailFast bool
|
||||
FlakeAttempts int
|
||||
EmitSpecProgress bool
|
||||
DryRun bool
|
||||
DebugParallel bool
|
||||
|
||||
ParallelNode int
|
||||
ParallelTotal int
|
||||
SyncHost string
|
||||
StreamHost string
|
||||
}
|
||||
|
||||
var GinkgoConfig = GinkgoConfigType{}
|
||||
|
||||
type DefaultReporterConfigType struct {
|
||||
NoColor bool
|
||||
SlowSpecThreshold float64
|
||||
NoisyPendings bool
|
||||
NoisySkippings bool
|
||||
Succinct bool
|
||||
Verbose bool
|
||||
FullTrace bool
|
||||
ReportPassed bool
|
||||
ReportFile string
|
||||
}
|
||||
|
||||
var DefaultReporterConfig = DefaultReporterConfigType{}
|
||||
|
||||
func processPrefix(prefix string) string {
|
||||
if prefix != "" {
|
||||
prefix += "."
|
||||
}
|
||||
return prefix
|
||||
}
|
||||
|
||||
type flagFunc func(string)
|
||||
|
||||
func (f flagFunc) String() string { return "" }
|
||||
func (f flagFunc) Set(s string) error { f(s); return nil }
|
||||
|
||||
func Flags(flagSet *flag.FlagSet, prefix string, includeParallelFlags bool) {
|
||||
prefix = processPrefix(prefix)
|
||||
flagSet.Int64Var(&(GinkgoConfig.RandomSeed), prefix+"seed", time.Now().Unix(), "The seed used to randomize the spec suite.")
|
||||
flagSet.BoolVar(&(GinkgoConfig.RandomizeAllSpecs), prefix+"randomizeAllSpecs", false, "If set, ginkgo will randomize all specs together. By default, ginkgo only randomizes the top level Describe, Context and When groups.")
|
||||
flagSet.BoolVar(&(GinkgoConfig.SkipMeasurements), prefix+"skipMeasurements", false, "If set, ginkgo will skip any measurement specs.")
|
||||
flagSet.BoolVar(&(GinkgoConfig.FailOnPending), prefix+"failOnPending", false, "If set, ginkgo will mark the test suite as failed if any specs are pending.")
|
||||
flagSet.BoolVar(&(GinkgoConfig.FailFast), prefix+"failFast", false, "If set, ginkgo will stop running a test suite after a failure occurs.")
|
||||
|
||||
flagSet.BoolVar(&(GinkgoConfig.DryRun), prefix+"dryRun", false, "If set, ginkgo will walk the test hierarchy without actually running anything. Best paired with -v.")
|
||||
|
||||
flagSet.Var(flagFunc(flagFocus), prefix+"focus", "If set, ginkgo will only run specs that match this regular expression. Can be specified multiple times, values are ORed.")
|
||||
flagSet.Var(flagFunc(flagSkip), prefix+"skip", "If set, ginkgo will only run specs that do not match this regular expression. Can be specified multiple times, values are ORed.")
|
||||
|
||||
flagSet.BoolVar(&(GinkgoConfig.RegexScansFilePath), prefix+"regexScansFilePath", false, "If set, ginkgo regex matching also will look at the file path (code location).")
|
||||
|
||||
flagSet.IntVar(&(GinkgoConfig.FlakeAttempts), prefix+"flakeAttempts", 1, "Make up to this many attempts to run each spec. Please note that if any of the attempts succeed, the suite will not be failed. But any failures will still be recorded.")
|
||||
|
||||
flagSet.BoolVar(&(GinkgoConfig.EmitSpecProgress), prefix+"progress", false, "If set, ginkgo will emit progress information as each spec runs to the GinkgoWriter.")
|
||||
|
||||
flagSet.BoolVar(&(GinkgoConfig.DebugParallel), prefix+"debug", false, "If set, ginkgo will emit node output to files when running in parallel.")
|
||||
|
||||
if includeParallelFlags {
|
||||
flagSet.IntVar(&(GinkgoConfig.ParallelNode), prefix+"parallel.node", 1, "This worker node's (one-indexed) node number. For running specs in parallel.")
|
||||
flagSet.IntVar(&(GinkgoConfig.ParallelTotal), prefix+"parallel.total", 1, "The total number of worker nodes. For running specs in parallel.")
|
||||
flagSet.StringVar(&(GinkgoConfig.SyncHost), prefix+"parallel.synchost", "", "The address for the server that will synchronize the running nodes.")
|
||||
flagSet.StringVar(&(GinkgoConfig.StreamHost), prefix+"parallel.streamhost", "", "The address for the server that the running nodes should stream data to.")
|
||||
}
|
||||
|
||||
flagSet.BoolVar(&(DefaultReporterConfig.NoColor), prefix+"noColor", false, "If set, suppress color output in default reporter.")
|
||||
flagSet.Float64Var(&(DefaultReporterConfig.SlowSpecThreshold), prefix+"slowSpecThreshold", 5.0, "(in seconds) Specs that take longer to run than this threshold are flagged as slow by the default reporter.")
|
||||
flagSet.BoolVar(&(DefaultReporterConfig.NoisyPendings), prefix+"noisyPendings", true, "If set, default reporter will shout about pending tests.")
|
||||
flagSet.BoolVar(&(DefaultReporterConfig.NoisySkippings), prefix+"noisySkippings", true, "If set, default reporter will shout about skipping tests.")
|
||||
flagSet.BoolVar(&(DefaultReporterConfig.Verbose), prefix+"v", false, "If set, default reporter print out all specs as they begin.")
|
||||
flagSet.BoolVar(&(DefaultReporterConfig.Succinct), prefix+"succinct", false, "If set, default reporter prints out a very succinct report")
|
||||
flagSet.BoolVar(&(DefaultReporterConfig.FullTrace), prefix+"trace", false, "If set, default reporter prints out the full stack trace when a failure occurs")
|
||||
flagSet.BoolVar(&(DefaultReporterConfig.ReportPassed), prefix+"reportPassed", false, "If set, default reporter prints out captured output of passed tests.")
|
||||
flagSet.StringVar(&(DefaultReporterConfig.ReportFile), prefix+"reportFile", "", "Override the default reporter output file path.")
|
||||
|
||||
}
|
||||
|
||||
func BuildFlagArgs(prefix string, ginkgo GinkgoConfigType, reporter DefaultReporterConfigType) []string {
|
||||
prefix = processPrefix(prefix)
|
||||
result := make([]string, 0)
|
||||
|
||||
if ginkgo.RandomSeed > 0 {
|
||||
result = append(result, fmt.Sprintf("--%sseed=%d", prefix, ginkgo.RandomSeed))
|
||||
}
|
||||
|
||||
if ginkgo.RandomizeAllSpecs {
|
||||
result = append(result, fmt.Sprintf("--%srandomizeAllSpecs", prefix))
|
||||
}
|
||||
|
||||
if ginkgo.SkipMeasurements {
|
||||
result = append(result, fmt.Sprintf("--%sskipMeasurements", prefix))
|
||||
}
|
||||
|
||||
if ginkgo.FailOnPending {
|
||||
result = append(result, fmt.Sprintf("--%sfailOnPending", prefix))
|
||||
}
|
||||
|
||||
if ginkgo.FailFast {
|
||||
result = append(result, fmt.Sprintf("--%sfailFast", prefix))
|
||||
}
|
||||
|
||||
if ginkgo.DryRun {
|
||||
result = append(result, fmt.Sprintf("--%sdryRun", prefix))
|
||||
}
|
||||
|
||||
for _, s := range ginkgo.FocusStrings {
|
||||
result = append(result, fmt.Sprintf("--%sfocus=%s", prefix, s))
|
||||
}
|
||||
|
||||
for _, s := range ginkgo.SkipStrings {
|
||||
result = append(result, fmt.Sprintf("--%sskip=%s", prefix, s))
|
||||
}
|
||||
|
||||
if ginkgo.FlakeAttempts > 1 {
|
||||
result = append(result, fmt.Sprintf("--%sflakeAttempts=%d", prefix, ginkgo.FlakeAttempts))
|
||||
}
|
||||
|
||||
if ginkgo.EmitSpecProgress {
|
||||
result = append(result, fmt.Sprintf("--%sprogress", prefix))
|
||||
}
|
||||
|
||||
if ginkgo.DebugParallel {
|
||||
result = append(result, fmt.Sprintf("--%sdebug", prefix))
|
||||
}
|
||||
|
||||
if ginkgo.ParallelNode != 0 {
|
||||
result = append(result, fmt.Sprintf("--%sparallel.node=%d", prefix, ginkgo.ParallelNode))
|
||||
}
|
||||
|
||||
if ginkgo.ParallelTotal != 0 {
|
||||
result = append(result, fmt.Sprintf("--%sparallel.total=%d", prefix, ginkgo.ParallelTotal))
|
||||
}
|
||||
|
||||
if ginkgo.StreamHost != "" {
|
||||
result = append(result, fmt.Sprintf("--%sparallel.streamhost=%s", prefix, ginkgo.StreamHost))
|
||||
}
|
||||
|
||||
if ginkgo.SyncHost != "" {
|
||||
result = append(result, fmt.Sprintf("--%sparallel.synchost=%s", prefix, ginkgo.SyncHost))
|
||||
}
|
||||
|
||||
if ginkgo.RegexScansFilePath {
|
||||
result = append(result, fmt.Sprintf("--%sregexScansFilePath", prefix))
|
||||
}
|
||||
|
||||
if reporter.NoColor {
|
||||
result = append(result, fmt.Sprintf("--%snoColor", prefix))
|
||||
}
|
||||
|
||||
if reporter.SlowSpecThreshold > 0 {
|
||||
result = append(result, fmt.Sprintf("--%sslowSpecThreshold=%.5f", prefix, reporter.SlowSpecThreshold))
|
||||
}
|
||||
|
||||
if !reporter.NoisyPendings {
|
||||
result = append(result, fmt.Sprintf("--%snoisyPendings=false", prefix))
|
||||
}
|
||||
|
||||
if !reporter.NoisySkippings {
|
||||
result = append(result, fmt.Sprintf("--%snoisySkippings=false", prefix))
|
||||
}
|
||||
|
||||
if reporter.Verbose {
|
||||
result = append(result, fmt.Sprintf("--%sv", prefix))
|
||||
}
|
||||
|
||||
if reporter.Succinct {
|
||||
result = append(result, fmt.Sprintf("--%ssuccinct", prefix))
|
||||
}
|
||||
|
||||
if reporter.FullTrace {
|
||||
result = append(result, fmt.Sprintf("--%strace", prefix))
|
||||
}
|
||||
|
||||
if reporter.ReportPassed {
|
||||
result = append(result, fmt.Sprintf("--%sreportPassed", prefix))
|
||||
}
|
||||
|
||||
if reporter.ReportFile != "" {
|
||||
result = append(result, fmt.Sprintf("--%sreportFile=%s", prefix, reporter.ReportFile))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// flagFocus implements the -focus flag.
|
||||
func flagFocus(arg string) {
|
||||
if arg != "" {
|
||||
GinkgoConfig.FocusStrings = append(GinkgoConfig.FocusStrings, arg)
|
||||
}
|
||||
}
|
||||
|
||||
// flagSkip implements the -skip flag.
|
||||
func flagSkip(arg string) {
|
||||
if arg != "" {
|
||||
GinkgoConfig.SkipStrings = append(GinkgoConfig.SkipStrings, arg)
|
||||
}
|
||||
}
|
190
vendor/github.com/onsi/ginkgo/formatter/formatter.go
generated
vendored
Normal file
190
vendor/github.com/onsi/ginkgo/formatter/formatter.go
generated
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
package formatter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const COLS = 80
|
||||
|
||||
type ColorMode uint8
|
||||
|
||||
const (
|
||||
ColorModeNone ColorMode = iota
|
||||
ColorModeTerminal
|
||||
ColorModePassthrough
|
||||
)
|
||||
|
||||
var SingletonFormatter = New(ColorModeTerminal)
|
||||
|
||||
func F(format string, args ...interface{}) string {
|
||||
return SingletonFormatter.F(format, args...)
|
||||
}
|
||||
|
||||
func Fi(indentation uint, format string, args ...interface{}) string {
|
||||
return SingletonFormatter.Fi(indentation, format, args...)
|
||||
}
|
||||
|
||||
func Fiw(indentation uint, maxWidth uint, format string, args ...interface{}) string {
|
||||
return SingletonFormatter.Fiw(indentation, maxWidth, format, args...)
|
||||
}
|
||||
|
||||
type Formatter struct {
|
||||
ColorMode ColorMode
|
||||
colors map[string]string
|
||||
styleRe *regexp.Regexp
|
||||
preserveColorStylingTags bool
|
||||
}
|
||||
|
||||
func NewWithNoColorBool(noColor bool) Formatter {
|
||||
if noColor {
|
||||
return New(ColorModeNone)
|
||||
}
|
||||
return New(ColorModeTerminal)
|
||||
}
|
||||
|
||||
func New(colorMode ColorMode) Formatter {
|
||||
f := Formatter{
|
||||
ColorMode: colorMode,
|
||||
colors: map[string]string{
|
||||
"/": "\x1b[0m",
|
||||
"bold": "\x1b[1m",
|
||||
"underline": "\x1b[4m",
|
||||
|
||||
"red": "\x1b[38;5;9m",
|
||||
"orange": "\x1b[38;5;214m",
|
||||
"coral": "\x1b[38;5;204m",
|
||||
"magenta": "\x1b[38;5;13m",
|
||||
"green": "\x1b[38;5;10m",
|
||||
"dark-green": "\x1b[38;5;28m",
|
||||
"yellow": "\x1b[38;5;11m",
|
||||
"light-yellow": "\x1b[38;5;228m",
|
||||
"cyan": "\x1b[38;5;14m",
|
||||
"gray": "\x1b[38;5;243m",
|
||||
"light-gray": "\x1b[38;5;246m",
|
||||
"blue": "\x1b[38;5;12m",
|
||||
},
|
||||
}
|
||||
colors := []string{}
|
||||
for color := range f.colors {
|
||||
colors = append(colors, color)
|
||||
}
|
||||
f.styleRe = regexp.MustCompile("{{(" + strings.Join(colors, "|") + ")}}")
|
||||
return f
|
||||
}
|
||||
|
||||
func (f Formatter) F(format string, args ...interface{}) string {
|
||||
return f.Fi(0, format, args...)
|
||||
}
|
||||
|
||||
func (f Formatter) Fi(indentation uint, format string, args ...interface{}) string {
|
||||
return f.Fiw(indentation, 0, format, args...)
|
||||
}
|
||||
|
||||
func (f Formatter) Fiw(indentation uint, maxWidth uint, format string, args ...interface{}) string {
|
||||
out := fmt.Sprintf(f.style(format), args...)
|
||||
|
||||
if indentation == 0 && maxWidth == 0 {
|
||||
return out
|
||||
}
|
||||
|
||||
lines := strings.Split(out, "\n")
|
||||
|
||||
if maxWidth != 0 {
|
||||
outLines := []string{}
|
||||
|
||||
maxWidth = maxWidth - indentation*2
|
||||
for _, line := range lines {
|
||||
if f.length(line) <= maxWidth {
|
||||
outLines = append(outLines, line)
|
||||
continue
|
||||
}
|
||||
outWords := []string{}
|
||||
length := uint(0)
|
||||
words := strings.Split(line, " ")
|
||||
for _, word := range words {
|
||||
wordLength := f.length(word)
|
||||
if length+wordLength <= maxWidth {
|
||||
length += wordLength
|
||||
outWords = append(outWords, word)
|
||||
continue
|
||||
}
|
||||
outLines = append(outLines, strings.Join(outWords, " "))
|
||||
outWords = []string{word}
|
||||
length = wordLength
|
||||
}
|
||||
if len(outWords) > 0 {
|
||||
outLines = append(outLines, strings.Join(outWords, " "))
|
||||
}
|
||||
}
|
||||
|
||||
lines = outLines
|
||||
}
|
||||
|
||||
if indentation == 0 {
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
padding := strings.Repeat(" ", int(indentation))
|
||||
for i := range lines {
|
||||
if lines[i] != "" {
|
||||
lines[i] = padding + lines[i]
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
func (f Formatter) length(styled string) uint {
|
||||
n := uint(0)
|
||||
inStyle := false
|
||||
for _, b := range styled {
|
||||
if inStyle {
|
||||
if b == 'm' {
|
||||
inStyle = false
|
||||
}
|
||||
continue
|
||||
}
|
||||
if b == '\x1b' {
|
||||
inStyle = true
|
||||
continue
|
||||
}
|
||||
n += 1
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (f Formatter) CycleJoin(elements []string, joiner string, cycle []string) string {
|
||||
if len(elements) == 0 {
|
||||
return ""
|
||||
}
|
||||
n := len(cycle)
|
||||
out := ""
|
||||
for i, text := range elements {
|
||||
out += cycle[i%n] + text
|
||||
if i < len(elements)-1 {
|
||||
out += joiner
|
||||
}
|
||||
}
|
||||
out += "{{/}}"
|
||||
return f.style(out)
|
||||
}
|
||||
|
||||
func (f Formatter) style(s string) string {
|
||||
switch f.ColorMode {
|
||||
case ColorModeNone:
|
||||
return f.styleRe.ReplaceAllString(s, "")
|
||||
case ColorModePassthrough:
|
||||
return s
|
||||
case ColorModeTerminal:
|
||||
return f.styleRe.ReplaceAllStringFunc(s, func(match string) string {
|
||||
if out, ok := f.colors[strings.Trim(match, "{}")]; ok {
|
||||
return out
|
||||
}
|
||||
return match
|
||||
})
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
681
vendor/github.com/onsi/ginkgo/ginkgo_dsl.go
generated
vendored
Normal file
681
vendor/github.com/onsi/ginkgo/ginkgo_dsl.go
generated
vendored
Normal file
@@ -0,0 +1,681 @@
|
||||
/*
|
||||
Ginkgo is a BDD-style testing framework for Golang
|
||||
|
||||
The godoc documentation describes Ginkgo's API. More comprehensive documentation (with examples!) is available at http://onsi.github.io/ginkgo/
|
||||
|
||||
Ginkgo's preferred matcher library is [Gomega](http://github.com/onsi/gomega)
|
||||
|
||||
Ginkgo on Github: http://github.com/onsi/ginkgo
|
||||
|
||||
Ginkgo is MIT-Licensed
|
||||
*/
|
||||
package ginkgo
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/onsi/ginkgo/config"
|
||||
"github.com/onsi/ginkgo/internal/codelocation"
|
||||
"github.com/onsi/ginkgo/internal/global"
|
||||
"github.com/onsi/ginkgo/internal/remote"
|
||||
"github.com/onsi/ginkgo/internal/testingtproxy"
|
||||
"github.com/onsi/ginkgo/internal/writer"
|
||||
"github.com/onsi/ginkgo/reporters"
|
||||
"github.com/onsi/ginkgo/reporters/stenographer"
|
||||
colorable "github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
var deprecationTracker = types.NewDeprecationTracker()
|
||||
|
||||
const GINKGO_VERSION = config.VERSION
|
||||
const GINKGO_PANIC = `
|
||||
Your test failed.
|
||||
Ginkgo panics to prevent subsequent assertions from running.
|
||||
Normally Ginkgo rescues this panic so you shouldn't see it.
|
||||
|
||||
But, if you make an assertion in a goroutine, Ginkgo can't capture the panic.
|
||||
To circumvent this, you should call
|
||||
|
||||
defer GinkgoRecover()
|
||||
|
||||
at the top of the goroutine that caused this panic.
|
||||
`
|
||||
|
||||
func init() {
|
||||
config.Flags(flag.CommandLine, "ginkgo", true)
|
||||
GinkgoWriter = writer.New(os.Stdout)
|
||||
}
|
||||
|
||||
//GinkgoWriter implements an io.Writer
|
||||
//When running in verbose mode any writes to GinkgoWriter will be immediately printed
|
||||
//to stdout. Otherwise, GinkgoWriter will buffer any writes produced during the current test and flush them to screen
|
||||
//only if the current test fails.
|
||||
var GinkgoWriter io.Writer
|
||||
|
||||
//The interface by which Ginkgo receives *testing.T
|
||||
type GinkgoTestingT interface {
|
||||
Fail()
|
||||
}
|
||||
|
||||
//GinkgoRandomSeed returns the seed used to randomize spec execution order. It is
|
||||
//useful for seeding your own pseudorandom number generators (PRNGs) to ensure
|
||||
//consistent executions from run to run, where your tests contain variability (for
|
||||
//example, when selecting random test data).
|
||||
func GinkgoRandomSeed() int64 {
|
||||
return config.GinkgoConfig.RandomSeed
|
||||
}
|
||||
|
||||
//GinkgoParallelNode is deprecated, use GinkgoParallelProcess instead
|
||||
func GinkgoParallelNode() int {
|
||||
deprecationTracker.TrackDeprecation(types.Deprecations.ParallelNode(), codelocation.New(1))
|
||||
return GinkgoParallelProcess()
|
||||
}
|
||||
|
||||
//GinkgoParallelProcess returns the parallel process number for the current ginkgo process
|
||||
//The process number is 1-indexed
|
||||
func GinkgoParallelProcess() int {
|
||||
return config.GinkgoConfig.ParallelNode
|
||||
}
|
||||
|
||||
//Some matcher libraries or legacy codebases require a *testing.T
|
||||
//GinkgoT implements an interface analogous to *testing.T and can be used if
|
||||
//the library in question accepts *testing.T through an interface
|
||||
//
|
||||
// For example, with testify:
|
||||
// assert.Equal(GinkgoT(), 123, 123, "they should be equal")
|
||||
//
|
||||
// Or with gomock:
|
||||
// gomock.NewController(GinkgoT())
|
||||
//
|
||||
// GinkgoT() takes an optional offset argument that can be used to get the
|
||||
// correct line number associated with the failure.
|
||||
func GinkgoT(optionalOffset ...int) GinkgoTInterface {
|
||||
offset := 3
|
||||
if len(optionalOffset) > 0 {
|
||||
offset = optionalOffset[0]
|
||||
}
|
||||
failedFunc := func() bool {
|
||||
return CurrentGinkgoTestDescription().Failed
|
||||
}
|
||||
nameFunc := func() string {
|
||||
return CurrentGinkgoTestDescription().FullTestText
|
||||
}
|
||||
return testingtproxy.New(GinkgoWriter, Fail, Skip, failedFunc, nameFunc, offset)
|
||||
}
|
||||
|
||||
//The interface returned by GinkgoT(). This covers most of the methods
|
||||
//in the testing package's T.
|
||||
type GinkgoTInterface interface {
|
||||
Cleanup(func())
|
||||
Setenv(key, value string)
|
||||
Error(args ...interface{})
|
||||
Errorf(format string, args ...interface{})
|
||||
Fail()
|
||||
FailNow()
|
||||
Failed() bool
|
||||
Fatal(args ...interface{})
|
||||
Fatalf(format string, args ...interface{})
|
||||
Helper()
|
||||
Log(args ...interface{})
|
||||
Logf(format string, args ...interface{})
|
||||
Name() string
|
||||
Parallel()
|
||||
Skip(args ...interface{})
|
||||
SkipNow()
|
||||
Skipf(format string, args ...interface{})
|
||||
Skipped() bool
|
||||
TempDir() string
|
||||
}
|
||||
|
||||
//Custom Ginkgo test reporters must implement the Reporter interface.
|
||||
//
|
||||
//The custom reporter is passed in a SuiteSummary when the suite begins and ends,
|
||||
//and a SpecSummary just before a spec begins and just after a spec ends
|
||||
type Reporter reporters.Reporter
|
||||
|
||||
//Asynchronous specs are given a channel of the Done type. You must close or write to the channel
|
||||
//to tell Ginkgo that your async test is done.
|
||||
type Done chan<- interface{}
|
||||
|
||||
//GinkgoTestDescription represents the information about the current running test returned by CurrentGinkgoTestDescription
|
||||
// FullTestText: a concatenation of ComponentTexts and the TestText
|
||||
// ComponentTexts: a list of all texts for the Describes & Contexts leading up to the current test
|
||||
// TestText: the text in the actual It or Measure node
|
||||
// IsMeasurement: true if the current test is a measurement
|
||||
// FileName: the name of the file containing the current test
|
||||
// LineNumber: the line number for the current test
|
||||
// Failed: if the current test has failed, this will be true (useful in an AfterEach)
|
||||
type GinkgoTestDescription struct {
|
||||
FullTestText string
|
||||
ComponentTexts []string
|
||||
TestText string
|
||||
|
||||
IsMeasurement bool
|
||||
|
||||
FileName string
|
||||
LineNumber int
|
||||
|
||||
Failed bool
|
||||
Duration time.Duration
|
||||
}
|
||||
|
||||
//CurrentGinkgoTestDescripton returns information about the current running test.
|
||||
func CurrentGinkgoTestDescription() GinkgoTestDescription {
|
||||
summary, ok := global.Suite.CurrentRunningSpecSummary()
|
||||
if !ok {
|
||||
return GinkgoTestDescription{}
|
||||
}
|
||||
|
||||
subjectCodeLocation := summary.ComponentCodeLocations[len(summary.ComponentCodeLocations)-1]
|
||||
|
||||
return GinkgoTestDescription{
|
||||
ComponentTexts: summary.ComponentTexts[1:],
|
||||
FullTestText: strings.Join(summary.ComponentTexts[1:], " "),
|
||||
TestText: summary.ComponentTexts[len(summary.ComponentTexts)-1],
|
||||
IsMeasurement: summary.IsMeasurement,
|
||||
FileName: subjectCodeLocation.FileName,
|
||||
LineNumber: subjectCodeLocation.LineNumber,
|
||||
Failed: summary.HasFailureState(),
|
||||
Duration: summary.RunTime,
|
||||
}
|
||||
}
|
||||
|
||||
//Measurement tests receive a Benchmarker.
|
||||
//
|
||||
//You use the Time() function to time how long the passed in body function takes to run
|
||||
//You use the RecordValue() function to track arbitrary numerical measurements.
|
||||
//The RecordValueWithPrecision() function can be used alternatively to provide the unit
|
||||
//and resolution of the numeric measurement.
|
||||
//The optional info argument is passed to the test reporter and can be used to
|
||||
// provide the measurement data to a custom reporter with context.
|
||||
//
|
||||
//See http://onsi.github.io/ginkgo/#benchmark_tests for more details
|
||||
type Benchmarker interface {
|
||||
Time(name string, body func(), info ...interface{}) (elapsedTime time.Duration)
|
||||
RecordValue(name string, value float64, info ...interface{})
|
||||
RecordValueWithPrecision(name string, value float64, units string, precision int, info ...interface{})
|
||||
}
|
||||
|
||||
//RunSpecs is the entry point for the Ginkgo test runner.
|
||||
//You must call this within a Golang testing TestX(t *testing.T) function.
|
||||
//
|
||||
//To bootstrap a test suite you can use the Ginkgo CLI:
|
||||
//
|
||||
// ginkgo bootstrap
|
||||
func RunSpecs(t GinkgoTestingT, description string) bool {
|
||||
specReporters := []Reporter{buildDefaultReporter()}
|
||||
if config.DefaultReporterConfig.ReportFile != "" {
|
||||
reportFile := config.DefaultReporterConfig.ReportFile
|
||||
specReporters[0] = reporters.NewJUnitReporter(reportFile)
|
||||
specReporters = append(specReporters, buildDefaultReporter())
|
||||
}
|
||||
return runSpecsWithCustomReporters(t, description, specReporters)
|
||||
}
|
||||
|
||||
//To run your tests with Ginkgo's default reporter and your custom reporter(s), replace
|
||||
//RunSpecs() with this method.
|
||||
func RunSpecsWithDefaultAndCustomReporters(t GinkgoTestingT, description string, specReporters []Reporter) bool {
|
||||
deprecationTracker.TrackDeprecation(types.Deprecations.CustomReporter())
|
||||
specReporters = append(specReporters, buildDefaultReporter())
|
||||
return runSpecsWithCustomReporters(t, description, specReporters)
|
||||
}
|
||||
|
||||
//To run your tests with your custom reporter(s) (and *not* Ginkgo's default reporter), replace
|
||||
//RunSpecs() with this method. Note that parallel tests will not work correctly without the default reporter
|
||||
func RunSpecsWithCustomReporters(t GinkgoTestingT, description string, specReporters []Reporter) bool {
|
||||
deprecationTracker.TrackDeprecation(types.Deprecations.CustomReporter())
|
||||
return runSpecsWithCustomReporters(t, description, specReporters)
|
||||
}
|
||||
|
||||
func runSpecsWithCustomReporters(t GinkgoTestingT, description string, specReporters []Reporter) bool {
|
||||
writer := GinkgoWriter.(*writer.Writer)
|
||||
writer.SetStream(config.DefaultReporterConfig.Verbose)
|
||||
reporters := make([]reporters.Reporter, len(specReporters))
|
||||
for i, reporter := range specReporters {
|
||||
reporters[i] = reporter
|
||||
}
|
||||
passed, hasFocusedTests := global.Suite.Run(t, description, reporters, writer, config.GinkgoConfig)
|
||||
|
||||
if deprecationTracker.DidTrackDeprecations() {
|
||||
fmt.Fprintln(colorable.NewColorableStderr(), deprecationTracker.DeprecationsReport())
|
||||
}
|
||||
|
||||
if passed && hasFocusedTests && strings.TrimSpace(os.Getenv("GINKGO_EDITOR_INTEGRATION")) == "" {
|
||||
fmt.Println("PASS | FOCUSED")
|
||||
os.Exit(types.GINKGO_FOCUS_EXIT_CODE)
|
||||
}
|
||||
return passed
|
||||
}
|
||||
|
||||
func buildDefaultReporter() Reporter {
|
||||
remoteReportingServer := config.GinkgoConfig.StreamHost
|
||||
if remoteReportingServer == "" {
|
||||
stenographer := stenographer.New(!config.DefaultReporterConfig.NoColor, config.GinkgoConfig.FlakeAttempts > 1, colorable.NewColorableStdout())
|
||||
return reporters.NewDefaultReporter(config.DefaultReporterConfig, stenographer)
|
||||
} else {
|
||||
debugFile := ""
|
||||
if config.GinkgoConfig.DebugParallel {
|
||||
debugFile = fmt.Sprintf("ginkgo-node-%d.log", config.GinkgoConfig.ParallelNode)
|
||||
}
|
||||
return remote.NewForwardingReporter(config.DefaultReporterConfig, remoteReportingServer, &http.Client{}, remote.NewOutputInterceptor(), GinkgoWriter.(*writer.Writer), debugFile)
|
||||
}
|
||||
}
|
||||
|
||||
//Skip notifies Ginkgo that the current spec was skipped.
|
||||
func Skip(message string, callerSkip ...int) {
|
||||
skip := 0
|
||||
if len(callerSkip) > 0 {
|
||||
skip = callerSkip[0]
|
||||
}
|
||||
|
||||
global.Failer.Skip(message, codelocation.New(skip+1))
|
||||
panic(GINKGO_PANIC)
|
||||
}
|
||||
|
||||
//Fail notifies Ginkgo that the current spec has failed. (Gomega will call Fail for you automatically when an assertion fails.)
|
||||
func Fail(message string, callerSkip ...int) {
|
||||
skip := 0
|
||||
if len(callerSkip) > 0 {
|
||||
skip = callerSkip[0]
|
||||
}
|
||||
|
||||
global.Failer.Fail(message, codelocation.New(skip+1))
|
||||
panic(GINKGO_PANIC)
|
||||
}
|
||||
|
||||
//GinkgoRecover should be deferred at the top of any spawned goroutine that (may) call `Fail`
|
||||
//Since Gomega assertions call fail, you should throw a `defer GinkgoRecover()` at the top of any goroutine that
|
||||
//calls out to Gomega
|
||||
//
|
||||
//Here's why: Ginkgo's `Fail` method records the failure and then panics to prevent
|
||||
//further assertions from running. This panic must be recovered. Ginkgo does this for you
|
||||
//if the panic originates in a Ginkgo node (an It, BeforeEach, etc...)
|
||||
//
|
||||
//Unfortunately, if a panic originates on a goroutine *launched* from one of these nodes there's no
|
||||
//way for Ginkgo to rescue the panic. To do this, you must remember to `defer GinkgoRecover()` at the top of such a goroutine.
|
||||
func GinkgoRecover() {
|
||||
e := recover()
|
||||
if e != nil {
|
||||
global.Failer.Panic(codelocation.New(1), e)
|
||||
}
|
||||
}
|
||||
|
||||
//Describe blocks allow you to organize your specs. A Describe block can contain any number of
|
||||
//BeforeEach, AfterEach, JustBeforeEach, It, and Measurement blocks.
|
||||
//
|
||||
//In addition you can nest Describe, Context and When blocks. Describe, Context and When blocks are functionally
|
||||
//equivalent. The difference is purely semantic -- you typically Describe the behavior of an object
|
||||
//or method and, within that Describe, outline a number of Contexts and Whens.
|
||||
func Describe(text string, body func()) bool {
|
||||
global.Suite.PushContainerNode(text, body, types.FlagTypeNone, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can focus the tests within a describe block using FDescribe
|
||||
func FDescribe(text string, body func()) bool {
|
||||
global.Suite.PushContainerNode(text, body, types.FlagTypeFocused, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark the tests within a describe block as pending using PDescribe
|
||||
func PDescribe(text string, body func()) bool {
|
||||
global.Suite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark the tests within a describe block as pending using XDescribe
|
||||
func XDescribe(text string, body func()) bool {
|
||||
global.Suite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//Context blocks allow you to organize your specs. A Context block can contain any number of
|
||||
//BeforeEach, AfterEach, JustBeforeEach, It, and Measurement blocks.
|
||||
//
|
||||
//In addition you can nest Describe, Context and When blocks. Describe, Context and When blocks are functionally
|
||||
//equivalent. The difference is purely semantic -- you typical Describe the behavior of an object
|
||||
//or method and, within that Describe, outline a number of Contexts and Whens.
|
||||
func Context(text string, body func()) bool {
|
||||
global.Suite.PushContainerNode(text, body, types.FlagTypeNone, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can focus the tests within a describe block using FContext
|
||||
func FContext(text string, body func()) bool {
|
||||
global.Suite.PushContainerNode(text, body, types.FlagTypeFocused, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark the tests within a describe block as pending using PContext
|
||||
func PContext(text string, body func()) bool {
|
||||
global.Suite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark the tests within a describe block as pending using XContext
|
||||
func XContext(text string, body func()) bool {
|
||||
global.Suite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//When blocks allow you to organize your specs. A When block can contain any number of
|
||||
//BeforeEach, AfterEach, JustBeforeEach, It, and Measurement blocks.
|
||||
//
|
||||
//In addition you can nest Describe, Context and When blocks. Describe, Context and When blocks are functionally
|
||||
//equivalent. The difference is purely semantic -- you typical Describe the behavior of an object
|
||||
//or method and, within that Describe, outline a number of Contexts and Whens.
|
||||
func When(text string, body func()) bool {
|
||||
global.Suite.PushContainerNode("when "+text, body, types.FlagTypeNone, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can focus the tests within a describe block using FWhen
|
||||
func FWhen(text string, body func()) bool {
|
||||
global.Suite.PushContainerNode("when "+text, body, types.FlagTypeFocused, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark the tests within a describe block as pending using PWhen
|
||||
func PWhen(text string, body func()) bool {
|
||||
global.Suite.PushContainerNode("when "+text, body, types.FlagTypePending, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark the tests within a describe block as pending using XWhen
|
||||
func XWhen(text string, body func()) bool {
|
||||
global.Suite.PushContainerNode("when "+text, body, types.FlagTypePending, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//It blocks contain your test code and assertions. You cannot nest any other Ginkgo blocks
|
||||
//within an It block.
|
||||
//
|
||||
//Ginkgo will normally run It blocks synchronously. To perform asynchronous tests, pass a
|
||||
//function that accepts a Done channel. When you do this, you can also provide an optional timeout.
|
||||
func It(text string, body interface{}, timeout ...float64) bool {
|
||||
validateBodyFunc(body, codelocation.New(1))
|
||||
global.Suite.PushItNode(text, body, types.FlagTypeNone, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can focus individual Its using FIt
|
||||
func FIt(text string, body interface{}, timeout ...float64) bool {
|
||||
validateBodyFunc(body, codelocation.New(1))
|
||||
global.Suite.PushItNode(text, body, types.FlagTypeFocused, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark Its as pending using PIt
|
||||
func PIt(text string, _ ...interface{}) bool {
|
||||
global.Suite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark Its as pending using XIt
|
||||
func XIt(text string, _ ...interface{}) bool {
|
||||
global.Suite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
|
||||
return true
|
||||
}
|
||||
|
||||
//Specify blocks are aliases for It blocks and allow for more natural wording in situations
|
||||
//which "It" does not fit into a natural sentence flow. All the same protocols apply for Specify blocks
|
||||
//which apply to It blocks.
|
||||
func Specify(text string, body interface{}, timeout ...float64) bool {
|
||||
validateBodyFunc(body, codelocation.New(1))
|
||||
global.Suite.PushItNode(text, body, types.FlagTypeNone, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can focus individual Specifys using FSpecify
|
||||
func FSpecify(text string, body interface{}, timeout ...float64) bool {
|
||||
validateBodyFunc(body, codelocation.New(1))
|
||||
global.Suite.PushItNode(text, body, types.FlagTypeFocused, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark Specifys as pending using PSpecify
|
||||
func PSpecify(text string, is ...interface{}) bool {
|
||||
global.Suite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark Specifys as pending using XSpecify
|
||||
func XSpecify(text string, is ...interface{}) bool {
|
||||
global.Suite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
|
||||
return true
|
||||
}
|
||||
|
||||
//By allows you to better document large Its.
|
||||
//
|
||||
//Generally you should try to keep your Its short and to the point. This is not always possible, however,
|
||||
//especially in the context of integration tests that capture a particular workflow.
|
||||
//
|
||||
//By allows you to document such flows. By must be called within a runnable node (It, BeforeEach, Measure, etc...)
|
||||
//By will simply log the passed in text to the GinkgoWriter. If By is handed a function it will immediately run the function.
|
||||
func By(text string, callbacks ...func()) {
|
||||
preamble := "\x1b[1mSTEP\x1b[0m"
|
||||
if config.DefaultReporterConfig.NoColor {
|
||||
preamble = "STEP"
|
||||
}
|
||||
fmt.Fprintln(GinkgoWriter, preamble+": "+text)
|
||||
if len(callbacks) == 1 {
|
||||
callbacks[0]()
|
||||
}
|
||||
if len(callbacks) > 1 {
|
||||
panic("just one callback per By, please")
|
||||
}
|
||||
}
|
||||
|
||||
//Measure blocks run the passed in body function repeatedly (determined by the samples argument)
|
||||
//and accumulate metrics provided to the Benchmarker by the body function.
|
||||
//
|
||||
//The body function must have the signature:
|
||||
// func(b Benchmarker)
|
||||
func Measure(text string, body interface{}, samples int) bool {
|
||||
deprecationTracker.TrackDeprecation(types.Deprecations.Measure(), codelocation.New(1))
|
||||
global.Suite.PushMeasureNode(text, body, types.FlagTypeNone, codelocation.New(1), samples)
|
||||
return true
|
||||
}
|
||||
|
||||
//You can focus individual Measures using FMeasure
|
||||
func FMeasure(text string, body interface{}, samples int) bool {
|
||||
deprecationTracker.TrackDeprecation(types.Deprecations.Measure(), codelocation.New(1))
|
||||
global.Suite.PushMeasureNode(text, body, types.FlagTypeFocused, codelocation.New(1), samples)
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark Measurements as pending using PMeasure
|
||||
func PMeasure(text string, _ ...interface{}) bool {
|
||||
deprecationTracker.TrackDeprecation(types.Deprecations.Measure(), codelocation.New(1))
|
||||
global.Suite.PushMeasureNode(text, func(b Benchmarker) {}, types.FlagTypePending, codelocation.New(1), 0)
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark Measurements as pending using XMeasure
|
||||
func XMeasure(text string, _ ...interface{}) bool {
|
||||
deprecationTracker.TrackDeprecation(types.Deprecations.Measure(), codelocation.New(1))
|
||||
global.Suite.PushMeasureNode(text, func(b Benchmarker) {}, types.FlagTypePending, codelocation.New(1), 0)
|
||||
return true
|
||||
}
|
||||
|
||||
//BeforeSuite blocks are run just once before any specs are run. When running in parallel, each
|
||||
//parallel node process will call BeforeSuite.
|
||||
//
|
||||
//BeforeSuite blocks can be made asynchronous by providing a body function that accepts a Done channel
|
||||
//
|
||||
//You may only register *one* BeforeSuite handler per test suite. You typically do so in your bootstrap file at the top level.
|
||||
func BeforeSuite(body interface{}, timeout ...float64) bool {
|
||||
validateBodyFunc(body, codelocation.New(1))
|
||||
global.Suite.SetBeforeSuiteNode(body, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
//AfterSuite blocks are *always* run after all the specs regardless of whether specs have passed or failed.
|
||||
//Moreover, if Ginkgo receives an interrupt signal (^C) it will attempt to run the AfterSuite before exiting.
|
||||
//
|
||||
//When running in parallel, each parallel node process will call AfterSuite.
|
||||
//
|
||||
//AfterSuite blocks can be made asynchronous by providing a body function that accepts a Done channel
|
||||
//
|
||||
//You may only register *one* AfterSuite handler per test suite. You typically do so in your bootstrap file at the top level.
|
||||
func AfterSuite(body interface{}, timeout ...float64) bool {
|
||||
validateBodyFunc(body, codelocation.New(1))
|
||||
global.Suite.SetAfterSuiteNode(body, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
//SynchronizedBeforeSuite blocks are primarily meant to solve the problem of setting up singleton external resources shared across
|
||||
//nodes when running tests in parallel. For example, say you have a shared database that you can only start one instance of that
|
||||
//must be used in your tests. When running in parallel, only one node should set up the database and all other nodes should wait
|
||||
//until that node is done before running.
|
||||
//
|
||||
//SynchronizedBeforeSuite accomplishes this by taking *two* function arguments. The first is only run on parallel node #1. The second is
|
||||
//run on all nodes, but *only* after the first function completes successfully. Ginkgo also makes it possible to send data from the first function (on Node 1)
|
||||
//to the second function (on all the other nodes).
|
||||
//
|
||||
//The functions have the following signatures. The first function (which only runs on node 1) has the signature:
|
||||
//
|
||||
// func() []byte
|
||||
//
|
||||
//or, to run asynchronously:
|
||||
//
|
||||
// func(done Done) []byte
|
||||
//
|
||||
//The byte array returned by the first function is then passed to the second function, which has the signature:
|
||||
//
|
||||
// func(data []byte)
|
||||
//
|
||||
//or, to run asynchronously:
|
||||
//
|
||||
// func(data []byte, done Done)
|
||||
//
|
||||
//Here's a simple pseudo-code example that starts a shared database on Node 1 and shares the database's address with the other nodes:
|
||||
//
|
||||
// var dbClient db.Client
|
||||
// var dbRunner db.Runner
|
||||
//
|
||||
// var _ = SynchronizedBeforeSuite(func() []byte {
|
||||
// dbRunner = db.NewRunner()
|
||||
// err := dbRunner.Start()
|
||||
// Ω(err).ShouldNot(HaveOccurred())
|
||||
// return []byte(dbRunner.URL)
|
||||
// }, func(data []byte) {
|
||||
// dbClient = db.NewClient()
|
||||
// err := dbClient.Connect(string(data))
|
||||
// Ω(err).ShouldNot(HaveOccurred())
|
||||
// })
|
||||
func SynchronizedBeforeSuite(node1Body interface{}, allNodesBody interface{}, timeout ...float64) bool {
|
||||
global.Suite.SetSynchronizedBeforeSuiteNode(
|
||||
node1Body,
|
||||
allNodesBody,
|
||||
codelocation.New(1),
|
||||
parseTimeout(timeout...),
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
//SynchronizedAfterSuite blocks complement the SynchronizedBeforeSuite blocks in solving the problem of setting up
|
||||
//external singleton resources shared across nodes when running tests in parallel.
|
||||
//
|
||||
//SynchronizedAfterSuite accomplishes this by taking *two* function arguments. The first runs on all nodes. The second runs only on parallel node #1
|
||||
//and *only* after all other nodes have finished and exited. This ensures that node 1, and any resources it is running, remain alive until
|
||||
//all other nodes are finished.
|
||||
//
|
||||
//Both functions have the same signature: either func() or func(done Done) to run asynchronously.
|
||||
//
|
||||
//Here's a pseudo-code example that complements that given in SynchronizedBeforeSuite. Here, SynchronizedAfterSuite is used to tear down the shared database
|
||||
//only after all nodes have finished:
|
||||
//
|
||||
// var _ = SynchronizedAfterSuite(func() {
|
||||
// dbClient.Cleanup()
|
||||
// }, func() {
|
||||
// dbRunner.Stop()
|
||||
// })
|
||||
func SynchronizedAfterSuite(allNodesBody interface{}, node1Body interface{}, timeout ...float64) bool {
|
||||
global.Suite.SetSynchronizedAfterSuiteNode(
|
||||
allNodesBody,
|
||||
node1Body,
|
||||
codelocation.New(1),
|
||||
parseTimeout(timeout...),
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
//BeforeEach blocks are run before It blocks. When multiple BeforeEach blocks are defined in nested
|
||||
//Describe and Context blocks the outermost BeforeEach blocks are run first.
|
||||
//
|
||||
//Like It blocks, BeforeEach blocks can be made asynchronous by providing a body function that accepts
|
||||
//a Done channel
|
||||
func BeforeEach(body interface{}, timeout ...float64) bool {
|
||||
validateBodyFunc(body, codelocation.New(1))
|
||||
global.Suite.PushBeforeEachNode(body, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
//JustBeforeEach blocks are run before It blocks but *after* all BeforeEach blocks. For more details,
|
||||
//read the [documentation](http://onsi.github.io/ginkgo/#separating_creation_and_configuration_)
|
||||
//
|
||||
//Like It blocks, BeforeEach blocks can be made asynchronous by providing a body function that accepts
|
||||
//a Done channel
|
||||
func JustBeforeEach(body interface{}, timeout ...float64) bool {
|
||||
validateBodyFunc(body, codelocation.New(1))
|
||||
global.Suite.PushJustBeforeEachNode(body, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
//JustAfterEach blocks are run after It blocks but *before* all AfterEach blocks. For more details,
|
||||
//read the [documentation](http://onsi.github.io/ginkgo/#separating_creation_and_configuration_)
|
||||
//
|
||||
//Like It blocks, JustAfterEach blocks can be made asynchronous by providing a body function that accepts
|
||||
//a Done channel
|
||||
func JustAfterEach(body interface{}, timeout ...float64) bool {
|
||||
validateBodyFunc(body, codelocation.New(1))
|
||||
global.Suite.PushJustAfterEachNode(body, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
//AfterEach blocks are run after It blocks. When multiple AfterEach blocks are defined in nested
|
||||
//Describe and Context blocks the innermost AfterEach blocks are run first.
|
||||
//
|
||||
//Like It blocks, AfterEach blocks can be made asynchronous by providing a body function that accepts
|
||||
//a Done channel
|
||||
func AfterEach(body interface{}, timeout ...float64) bool {
|
||||
validateBodyFunc(body, codelocation.New(1))
|
||||
global.Suite.PushAfterEachNode(body, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
func validateBodyFunc(body interface{}, cl types.CodeLocation) {
|
||||
t := reflect.TypeOf(body)
|
||||
if t.Kind() != reflect.Func {
|
||||
return
|
||||
}
|
||||
|
||||
if t.NumOut() > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if t.NumIn() == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if t.In(0) == reflect.TypeOf(make(Done)) {
|
||||
deprecationTracker.TrackDeprecation(types.Deprecations.Async(), cl)
|
||||
}
|
||||
}
|
||||
|
||||
func parseTimeout(timeout ...float64) time.Duration {
|
||||
if len(timeout) == 0 {
|
||||
return global.DefaultTimeout
|
||||
} else {
|
||||
return time.Duration(timeout[0] * float64(time.Second))
|
||||
}
|
||||
}
|
48
vendor/github.com/onsi/ginkgo/internal/codelocation/code_location.go
generated
vendored
Normal file
48
vendor/github.com/onsi/ginkgo/internal/codelocation/code_location.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
package codelocation
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
func New(skip int) types.CodeLocation {
|
||||
_, file, line, _ := runtime.Caller(skip + 1)
|
||||
stackTrace := PruneStack(string(debug.Stack()), skip+1)
|
||||
return types.CodeLocation{FileName: file, LineNumber: line, FullStackTrace: stackTrace}
|
||||
}
|
||||
|
||||
// PruneStack removes references to functions that are internal to Ginkgo
|
||||
// and the Go runtime from a stack string and a certain number of stack entries
|
||||
// at the beginning of the stack. The stack string has the format
|
||||
// as returned by runtime/debug.Stack. The leading goroutine information is
|
||||
// optional and always removed if present. Beware that runtime/debug.Stack
|
||||
// adds itself as first entry, so typically skip must be >= 1 to remove that
|
||||
// entry.
|
||||
func PruneStack(fullStackTrace string, skip int) string {
|
||||
stack := strings.Split(fullStackTrace, "\n")
|
||||
// Ensure that the even entries are the method names and the
|
||||
// the odd entries the source code information.
|
||||
if len(stack) > 0 && strings.HasPrefix(stack[0], "goroutine ") {
|
||||
// Ignore "goroutine 29 [running]:" line.
|
||||
stack = stack[1:]
|
||||
}
|
||||
// The "+1" is for skipping over the initial entry, which is
|
||||
// runtime/debug.Stack() itself.
|
||||
if len(stack) > 2*(skip+1) {
|
||||
stack = stack[2*(skip+1):]
|
||||
}
|
||||
prunedStack := []string{}
|
||||
re := regexp.MustCompile(`\/ginkgo\/|\/pkg\/testing\/|\/pkg\/runtime\/`)
|
||||
for i := 0; i < len(stack)/2; i++ {
|
||||
// We filter out based on the source code file name.
|
||||
if !re.Match([]byte(stack[i*2+1])) {
|
||||
prunedStack = append(prunedStack, stack[i*2])
|
||||
prunedStack = append(prunedStack, stack[i*2+1])
|
||||
}
|
||||
}
|
||||
return strings.Join(prunedStack, "\n")
|
||||
}
|
151
vendor/github.com/onsi/ginkgo/internal/containernode/container_node.go
generated
vendored
Normal file
151
vendor/github.com/onsi/ginkgo/internal/containernode/container_node.go
generated
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
package containernode
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"sort"
|
||||
|
||||
"github.com/onsi/ginkgo/internal/leafnodes"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
type subjectOrContainerNode struct {
|
||||
containerNode *ContainerNode
|
||||
subjectNode leafnodes.SubjectNode
|
||||
}
|
||||
|
||||
func (n subjectOrContainerNode) text() string {
|
||||
if n.containerNode != nil {
|
||||
return n.containerNode.Text()
|
||||
} else {
|
||||
return n.subjectNode.Text()
|
||||
}
|
||||
}
|
||||
|
||||
type CollatedNodes struct {
|
||||
Containers []*ContainerNode
|
||||
Subject leafnodes.SubjectNode
|
||||
}
|
||||
|
||||
type ContainerNode struct {
|
||||
text string
|
||||
flag types.FlagType
|
||||
codeLocation types.CodeLocation
|
||||
|
||||
setupNodes []leafnodes.BasicNode
|
||||
subjectAndContainerNodes []subjectOrContainerNode
|
||||
}
|
||||
|
||||
func New(text string, flag types.FlagType, codeLocation types.CodeLocation) *ContainerNode {
|
||||
return &ContainerNode{
|
||||
text: text,
|
||||
flag: flag,
|
||||
codeLocation: codeLocation,
|
||||
}
|
||||
}
|
||||
|
||||
func (container *ContainerNode) Shuffle(r *rand.Rand) {
|
||||
sort.Sort(container)
|
||||
permutation := r.Perm(len(container.subjectAndContainerNodes))
|
||||
shuffledNodes := make([]subjectOrContainerNode, len(container.subjectAndContainerNodes))
|
||||
for i, j := range permutation {
|
||||
shuffledNodes[i] = container.subjectAndContainerNodes[j]
|
||||
}
|
||||
container.subjectAndContainerNodes = shuffledNodes
|
||||
}
|
||||
|
||||
func (node *ContainerNode) BackPropagateProgrammaticFocus() bool {
|
||||
if node.flag == types.FlagTypePending {
|
||||
return false
|
||||
}
|
||||
|
||||
shouldUnfocus := false
|
||||
for _, subjectOrContainerNode := range node.subjectAndContainerNodes {
|
||||
if subjectOrContainerNode.containerNode != nil {
|
||||
shouldUnfocus = subjectOrContainerNode.containerNode.BackPropagateProgrammaticFocus() || shouldUnfocus
|
||||
} else {
|
||||
shouldUnfocus = (subjectOrContainerNode.subjectNode.Flag() == types.FlagTypeFocused) || shouldUnfocus
|
||||
}
|
||||
}
|
||||
|
||||
if shouldUnfocus {
|
||||
if node.flag == types.FlagTypeFocused {
|
||||
node.flag = types.FlagTypeNone
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
return node.flag == types.FlagTypeFocused
|
||||
}
|
||||
|
||||
func (node *ContainerNode) Collate() []CollatedNodes {
|
||||
return node.collate([]*ContainerNode{})
|
||||
}
|
||||
|
||||
func (node *ContainerNode) collate(enclosingContainers []*ContainerNode) []CollatedNodes {
|
||||
collated := make([]CollatedNodes, 0)
|
||||
|
||||
containers := make([]*ContainerNode, len(enclosingContainers))
|
||||
copy(containers, enclosingContainers)
|
||||
containers = append(containers, node)
|
||||
|
||||
for _, subjectOrContainer := range node.subjectAndContainerNodes {
|
||||
if subjectOrContainer.containerNode != nil {
|
||||
collated = append(collated, subjectOrContainer.containerNode.collate(containers)...)
|
||||
} else {
|
||||
collated = append(collated, CollatedNodes{
|
||||
Containers: containers,
|
||||
Subject: subjectOrContainer.subjectNode,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return collated
|
||||
}
|
||||
|
||||
func (node *ContainerNode) PushContainerNode(container *ContainerNode) {
|
||||
node.subjectAndContainerNodes = append(node.subjectAndContainerNodes, subjectOrContainerNode{containerNode: container})
|
||||
}
|
||||
|
||||
func (node *ContainerNode) PushSubjectNode(subject leafnodes.SubjectNode) {
|
||||
node.subjectAndContainerNodes = append(node.subjectAndContainerNodes, subjectOrContainerNode{subjectNode: subject})
|
||||
}
|
||||
|
||||
func (node *ContainerNode) PushSetupNode(setupNode leafnodes.BasicNode) {
|
||||
node.setupNodes = append(node.setupNodes, setupNode)
|
||||
}
|
||||
|
||||
func (node *ContainerNode) SetupNodesOfType(nodeType types.SpecComponentType) []leafnodes.BasicNode {
|
||||
nodes := []leafnodes.BasicNode{}
|
||||
for _, setupNode := range node.setupNodes {
|
||||
if setupNode.Type() == nodeType {
|
||||
nodes = append(nodes, setupNode)
|
||||
}
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
func (node *ContainerNode) Text() string {
|
||||
return node.text
|
||||
}
|
||||
|
||||
func (node *ContainerNode) CodeLocation() types.CodeLocation {
|
||||
return node.codeLocation
|
||||
}
|
||||
|
||||
func (node *ContainerNode) Flag() types.FlagType {
|
||||
return node.flag
|
||||
}
|
||||
|
||||
//sort.Interface
|
||||
|
||||
func (node *ContainerNode) Len() int {
|
||||
return len(node.subjectAndContainerNodes)
|
||||
}
|
||||
|
||||
func (node *ContainerNode) Less(i, j int) bool {
|
||||
return node.subjectAndContainerNodes[i].text() < node.subjectAndContainerNodes[j].text()
|
||||
}
|
||||
|
||||
func (node *ContainerNode) Swap(i, j int) {
|
||||
node.subjectAndContainerNodes[i], node.subjectAndContainerNodes[j] = node.subjectAndContainerNodes[j], node.subjectAndContainerNodes[i]
|
||||
}
|
92
vendor/github.com/onsi/ginkgo/internal/failer/failer.go
generated
vendored
Normal file
92
vendor/github.com/onsi/ginkgo/internal/failer/failer.go
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
package failer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
type Failer struct {
|
||||
lock *sync.Mutex
|
||||
failure types.SpecFailure
|
||||
state types.SpecState
|
||||
}
|
||||
|
||||
func New() *Failer {
|
||||
return &Failer{
|
||||
lock: &sync.Mutex{},
|
||||
state: types.SpecStatePassed,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Failer) Panic(location types.CodeLocation, forwardedPanic interface{}) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
if f.state == types.SpecStatePassed {
|
||||
f.state = types.SpecStatePanicked
|
||||
f.failure = types.SpecFailure{
|
||||
Message: "Test Panicked",
|
||||
Location: location,
|
||||
ForwardedPanic: fmt.Sprintf("%v", forwardedPanic),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Failer) Timeout(location types.CodeLocation) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
if f.state == types.SpecStatePassed {
|
||||
f.state = types.SpecStateTimedOut
|
||||
f.failure = types.SpecFailure{
|
||||
Message: "Timed out",
|
||||
Location: location,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Failer) Fail(message string, location types.CodeLocation) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
if f.state == types.SpecStatePassed {
|
||||
f.state = types.SpecStateFailed
|
||||
f.failure = types.SpecFailure{
|
||||
Message: message,
|
||||
Location: location,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Failer) Drain(componentType types.SpecComponentType, componentIndex int, componentCodeLocation types.CodeLocation) (types.SpecFailure, types.SpecState) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
failure := f.failure
|
||||
outcome := f.state
|
||||
if outcome != types.SpecStatePassed {
|
||||
failure.ComponentType = componentType
|
||||
failure.ComponentIndex = componentIndex
|
||||
failure.ComponentCodeLocation = componentCodeLocation
|
||||
}
|
||||
|
||||
f.state = types.SpecStatePassed
|
||||
f.failure = types.SpecFailure{}
|
||||
|
||||
return failure, outcome
|
||||
}
|
||||
|
||||
func (f *Failer) Skip(message string, location types.CodeLocation) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
if f.state == types.SpecStatePassed {
|
||||
f.state = types.SpecStateSkipped
|
||||
f.failure = types.SpecFailure{
|
||||
Message: message,
|
||||
Location: location,
|
||||
}
|
||||
}
|
||||
}
|
22
vendor/github.com/onsi/ginkgo/internal/global/init.go
generated
vendored
Normal file
22
vendor/github.com/onsi/ginkgo/internal/global/init.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
package global
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/onsi/ginkgo/internal/failer"
|
||||
"github.com/onsi/ginkgo/internal/suite"
|
||||
)
|
||||
|
||||
const DefaultTimeout = time.Duration(1 * time.Second)
|
||||
|
||||
var Suite *suite.Suite
|
||||
var Failer *failer.Failer
|
||||
|
||||
func init() {
|
||||
InitializeGlobals()
|
||||
}
|
||||
|
||||
func InitializeGlobals() {
|
||||
Failer = failer.New()
|
||||
Suite = suite.New(Failer)
|
||||
}
|
103
vendor/github.com/onsi/ginkgo/internal/leafnodes/benchmarker.go
generated
vendored
Normal file
103
vendor/github.com/onsi/ginkgo/internal/leafnodes/benchmarker.go
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
package leafnodes
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"sync"
|
||||
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
type benchmarker struct {
|
||||
mu sync.Mutex
|
||||
measurements map[string]*types.SpecMeasurement
|
||||
orderCounter int
|
||||
}
|
||||
|
||||
func newBenchmarker() *benchmarker {
|
||||
return &benchmarker{
|
||||
measurements: make(map[string]*types.SpecMeasurement),
|
||||
}
|
||||
}
|
||||
|
||||
func (b *benchmarker) Time(name string, body func(), info ...interface{}) (elapsedTime time.Duration) {
|
||||
t := time.Now()
|
||||
body()
|
||||
elapsedTime = time.Since(t)
|
||||
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
measurement := b.getMeasurement(name, "Fastest Time", "Slowest Time", "Average Time", "s", 3, info...)
|
||||
measurement.Results = append(measurement.Results, elapsedTime.Seconds())
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (b *benchmarker) RecordValue(name string, value float64, info ...interface{}) {
|
||||
b.mu.Lock()
|
||||
measurement := b.getMeasurement(name, "Smallest", " Largest", " Average", "", 3, info...)
|
||||
defer b.mu.Unlock()
|
||||
measurement.Results = append(measurement.Results, value)
|
||||
}
|
||||
|
||||
func (b *benchmarker) RecordValueWithPrecision(name string, value float64, units string, precision int, info ...interface{}) {
|
||||
b.mu.Lock()
|
||||
measurement := b.getMeasurement(name, "Smallest", " Largest", " Average", units, precision, info...)
|
||||
defer b.mu.Unlock()
|
||||
measurement.Results = append(measurement.Results, value)
|
||||
}
|
||||
|
||||
func (b *benchmarker) getMeasurement(name string, smallestLabel string, largestLabel string, averageLabel string, units string, precision int, info ...interface{}) *types.SpecMeasurement {
|
||||
measurement, ok := b.measurements[name]
|
||||
if !ok {
|
||||
var computedInfo interface{}
|
||||
computedInfo = nil
|
||||
if len(info) > 0 {
|
||||
computedInfo = info[0]
|
||||
}
|
||||
measurement = &types.SpecMeasurement{
|
||||
Name: name,
|
||||
Info: computedInfo,
|
||||
Order: b.orderCounter,
|
||||
SmallestLabel: smallestLabel,
|
||||
LargestLabel: largestLabel,
|
||||
AverageLabel: averageLabel,
|
||||
Units: units,
|
||||
Precision: precision,
|
||||
Results: make([]float64, 0),
|
||||
}
|
||||
b.measurements[name] = measurement
|
||||
b.orderCounter++
|
||||
}
|
||||
|
||||
return measurement
|
||||
}
|
||||
|
||||
func (b *benchmarker) measurementsReport() map[string]*types.SpecMeasurement {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
for _, measurement := range b.measurements {
|
||||
measurement.Smallest = math.MaxFloat64
|
||||
measurement.Largest = -math.MaxFloat64
|
||||
sum := float64(0)
|
||||
sumOfSquares := float64(0)
|
||||
|
||||
for _, result := range measurement.Results {
|
||||
if result > measurement.Largest {
|
||||
measurement.Largest = result
|
||||
}
|
||||
if result < measurement.Smallest {
|
||||
measurement.Smallest = result
|
||||
}
|
||||
sum += result
|
||||
sumOfSquares += result * result
|
||||
}
|
||||
|
||||
n := float64(len(measurement.Results))
|
||||
measurement.Average = sum / n
|
||||
measurement.StdDeviation = math.Sqrt(sumOfSquares/n - (sum/n)*(sum/n))
|
||||
}
|
||||
|
||||
return b.measurements
|
||||
}
|
19
vendor/github.com/onsi/ginkgo/internal/leafnodes/interfaces.go
generated
vendored
Normal file
19
vendor/github.com/onsi/ginkgo/internal/leafnodes/interfaces.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
package leafnodes
|
||||
|
||||
import (
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
type BasicNode interface {
|
||||
Type() types.SpecComponentType
|
||||
Run() (types.SpecState, types.SpecFailure)
|
||||
CodeLocation() types.CodeLocation
|
||||
}
|
||||
|
||||
type SubjectNode interface {
|
||||
BasicNode
|
||||
|
||||
Text() string
|
||||
Flag() types.FlagType
|
||||
Samples() int
|
||||
}
|
47
vendor/github.com/onsi/ginkgo/internal/leafnodes/it_node.go
generated
vendored
Normal file
47
vendor/github.com/onsi/ginkgo/internal/leafnodes/it_node.go
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
package leafnodes
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/onsi/ginkgo/internal/failer"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
type ItNode struct {
|
||||
runner *runner
|
||||
|
||||
flag types.FlagType
|
||||
text string
|
||||
}
|
||||
|
||||
func NewItNode(text string, body interface{}, flag types.FlagType, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer, componentIndex int) *ItNode {
|
||||
return &ItNode{
|
||||
runner: newRunner(body, codeLocation, timeout, failer, types.SpecComponentTypeIt, componentIndex),
|
||||
flag: flag,
|
||||
text: text,
|
||||
}
|
||||
}
|
||||
|
||||
func (node *ItNode) Run() (outcome types.SpecState, failure types.SpecFailure) {
|
||||
return node.runner.run()
|
||||
}
|
||||
|
||||
func (node *ItNode) Type() types.SpecComponentType {
|
||||
return types.SpecComponentTypeIt
|
||||
}
|
||||
|
||||
func (node *ItNode) Text() string {
|
||||
return node.text
|
||||
}
|
||||
|
||||
func (node *ItNode) Flag() types.FlagType {
|
||||
return node.flag
|
||||
}
|
||||
|
||||
func (node *ItNode) CodeLocation() types.CodeLocation {
|
||||
return node.runner.codeLocation
|
||||
}
|
||||
|
||||
func (node *ItNode) Samples() int {
|
||||
return 1
|
||||
}
|
62
vendor/github.com/onsi/ginkgo/internal/leafnodes/measure_node.go
generated
vendored
Normal file
62
vendor/github.com/onsi/ginkgo/internal/leafnodes/measure_node.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
package leafnodes
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/onsi/ginkgo/internal/failer"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
type MeasureNode struct {
|
||||
runner *runner
|
||||
|
||||
text string
|
||||
flag types.FlagType
|
||||
samples int
|
||||
benchmarker *benchmarker
|
||||
}
|
||||
|
||||
func NewMeasureNode(text string, body interface{}, flag types.FlagType, codeLocation types.CodeLocation, samples int, failer *failer.Failer, componentIndex int) *MeasureNode {
|
||||
benchmarker := newBenchmarker()
|
||||
|
||||
wrappedBody := func() {
|
||||
reflect.ValueOf(body).Call([]reflect.Value{reflect.ValueOf(benchmarker)})
|
||||
}
|
||||
|
||||
return &MeasureNode{
|
||||
runner: newRunner(wrappedBody, codeLocation, 0, failer, types.SpecComponentTypeMeasure, componentIndex),
|
||||
|
||||
text: text,
|
||||
flag: flag,
|
||||
samples: samples,
|
||||
benchmarker: benchmarker,
|
||||
}
|
||||
}
|
||||
|
||||
func (node *MeasureNode) Run() (outcome types.SpecState, failure types.SpecFailure) {
|
||||
return node.runner.run()
|
||||
}
|
||||
|
||||
func (node *MeasureNode) MeasurementsReport() map[string]*types.SpecMeasurement {
|
||||
return node.benchmarker.measurementsReport()
|
||||
}
|
||||
|
||||
func (node *MeasureNode) Type() types.SpecComponentType {
|
||||
return types.SpecComponentTypeMeasure
|
||||
}
|
||||
|
||||
func (node *MeasureNode) Text() string {
|
||||
return node.text
|
||||
}
|
||||
|
||||
func (node *MeasureNode) Flag() types.FlagType {
|
||||
return node.flag
|
||||
}
|
||||
|
||||
func (node *MeasureNode) CodeLocation() types.CodeLocation {
|
||||
return node.runner.codeLocation
|
||||
}
|
||||
|
||||
func (node *MeasureNode) Samples() int {
|
||||
return node.samples
|
||||
}
|
117
vendor/github.com/onsi/ginkgo/internal/leafnodes/runner.go
generated
vendored
Normal file
117
vendor/github.com/onsi/ginkgo/internal/leafnodes/runner.go
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
package leafnodes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/onsi/ginkgo/internal/codelocation"
|
||||
"github.com/onsi/ginkgo/internal/failer"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
type runner struct {
|
||||
isAsync bool
|
||||
asyncFunc func(chan<- interface{})
|
||||
syncFunc func()
|
||||
codeLocation types.CodeLocation
|
||||
timeoutThreshold time.Duration
|
||||
nodeType types.SpecComponentType
|
||||
componentIndex int
|
||||
failer *failer.Failer
|
||||
}
|
||||
|
||||
func newRunner(body interface{}, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer, nodeType types.SpecComponentType, componentIndex int) *runner {
|
||||
bodyType := reflect.TypeOf(body)
|
||||
if bodyType.Kind() != reflect.Func {
|
||||
panic(fmt.Sprintf("Expected a function but got something else at %v", codeLocation))
|
||||
}
|
||||
|
||||
runner := &runner{
|
||||
codeLocation: codeLocation,
|
||||
timeoutThreshold: timeout,
|
||||
failer: failer,
|
||||
nodeType: nodeType,
|
||||
componentIndex: componentIndex,
|
||||
}
|
||||
|
||||
switch bodyType.NumIn() {
|
||||
case 0:
|
||||
runner.syncFunc = body.(func())
|
||||
return runner
|
||||
case 1:
|
||||
if !(bodyType.In(0).Kind() == reflect.Chan && bodyType.In(0).Elem().Kind() == reflect.Interface) {
|
||||
panic(fmt.Sprintf("Must pass a Done channel to function at %v", codeLocation))
|
||||
}
|
||||
|
||||
wrappedBody := func(done chan<- interface{}) {
|
||||
bodyValue := reflect.ValueOf(body)
|
||||
bodyValue.Call([]reflect.Value{reflect.ValueOf(done)})
|
||||
}
|
||||
|
||||
runner.isAsync = true
|
||||
runner.asyncFunc = wrappedBody
|
||||
return runner
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Too many arguments to function at %v", codeLocation))
|
||||
}
|
||||
|
||||
func (r *runner) run() (outcome types.SpecState, failure types.SpecFailure) {
|
||||
if r.isAsync {
|
||||
return r.runAsync()
|
||||
} else {
|
||||
return r.runSync()
|
||||
}
|
||||
}
|
||||
|
||||
func (r *runner) runAsync() (outcome types.SpecState, failure types.SpecFailure) {
|
||||
done := make(chan interface{}, 1)
|
||||
|
||||
go func() {
|
||||
finished := false
|
||||
|
||||
defer func() {
|
||||
if e := recover(); e != nil || !finished {
|
||||
r.failer.Panic(codelocation.New(2), e)
|
||||
select {
|
||||
case <-done:
|
||||
break
|
||||
default:
|
||||
close(done)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
r.asyncFunc(done)
|
||||
finished = true
|
||||
}()
|
||||
|
||||
// If this goroutine gets no CPU time before the select block,
|
||||
// the <-done case may complete even if the test took longer than the timeoutThreshold.
|
||||
// This can cause flaky behaviour, but we haven't seen it in the wild.
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(r.timeoutThreshold):
|
||||
r.failer.Timeout(r.codeLocation)
|
||||
}
|
||||
|
||||
failure, outcome = r.failer.Drain(r.nodeType, r.componentIndex, r.codeLocation)
|
||||
return
|
||||
}
|
||||
func (r *runner) runSync() (outcome types.SpecState, failure types.SpecFailure) {
|
||||
finished := false
|
||||
|
||||
defer func() {
|
||||
if e := recover(); e != nil || !finished {
|
||||
r.failer.Panic(codelocation.New(2), e)
|
||||
}
|
||||
|
||||
failure, outcome = r.failer.Drain(r.nodeType, r.componentIndex, r.codeLocation)
|
||||
}()
|
||||
|
||||
r.syncFunc()
|
||||
finished = true
|
||||
|
||||
return
|
||||
}
|
48
vendor/github.com/onsi/ginkgo/internal/leafnodes/setup_nodes.go
generated
vendored
Normal file
48
vendor/github.com/onsi/ginkgo/internal/leafnodes/setup_nodes.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
package leafnodes
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/onsi/ginkgo/internal/failer"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
type SetupNode struct {
|
||||
runner *runner
|
||||
}
|
||||
|
||||
func (node *SetupNode) Run() (outcome types.SpecState, failure types.SpecFailure) {
|
||||
return node.runner.run()
|
||||
}
|
||||
|
||||
func (node *SetupNode) Type() types.SpecComponentType {
|
||||
return node.runner.nodeType
|
||||
}
|
||||
|
||||
func (node *SetupNode) CodeLocation() types.CodeLocation {
|
||||
return node.runner.codeLocation
|
||||
}
|
||||
|
||||
func NewBeforeEachNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer, componentIndex int) *SetupNode {
|
||||
return &SetupNode{
|
||||
runner: newRunner(body, codeLocation, timeout, failer, types.SpecComponentTypeBeforeEach, componentIndex),
|
||||
}
|
||||
}
|
||||
|
||||
func NewAfterEachNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer, componentIndex int) *SetupNode {
|
||||
return &SetupNode{
|
||||
runner: newRunner(body, codeLocation, timeout, failer, types.SpecComponentTypeAfterEach, componentIndex),
|
||||
}
|
||||
}
|
||||
|
||||
func NewJustBeforeEachNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer, componentIndex int) *SetupNode {
|
||||
return &SetupNode{
|
||||
runner: newRunner(body, codeLocation, timeout, failer, types.SpecComponentTypeJustBeforeEach, componentIndex),
|
||||
}
|
||||
}
|
||||
|
||||
func NewJustAfterEachNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer, componentIndex int) *SetupNode {
|
||||
return &SetupNode{
|
||||
runner: newRunner(body, codeLocation, timeout, failer, types.SpecComponentTypeJustAfterEach, componentIndex),
|
||||
}
|
||||
}
|
55
vendor/github.com/onsi/ginkgo/internal/leafnodes/suite_nodes.go
generated
vendored
Normal file
55
vendor/github.com/onsi/ginkgo/internal/leafnodes/suite_nodes.go
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
package leafnodes
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/onsi/ginkgo/internal/failer"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
type SuiteNode interface {
|
||||
Run(parallelNode int, parallelTotal int, syncHost string) bool
|
||||
Passed() bool
|
||||
Summary() *types.SetupSummary
|
||||
}
|
||||
|
||||
type simpleSuiteNode struct {
|
||||
runner *runner
|
||||
outcome types.SpecState
|
||||
failure types.SpecFailure
|
||||
runTime time.Duration
|
||||
}
|
||||
|
||||
func (node *simpleSuiteNode) Run(parallelNode int, parallelTotal int, syncHost string) bool {
|
||||
t := time.Now()
|
||||
node.outcome, node.failure = node.runner.run()
|
||||
node.runTime = time.Since(t)
|
||||
|
||||
return node.outcome == types.SpecStatePassed
|
||||
}
|
||||
|
||||
func (node *simpleSuiteNode) Passed() bool {
|
||||
return node.outcome == types.SpecStatePassed
|
||||
}
|
||||
|
||||
func (node *simpleSuiteNode) Summary() *types.SetupSummary {
|
||||
return &types.SetupSummary{
|
||||
ComponentType: node.runner.nodeType,
|
||||
CodeLocation: node.runner.codeLocation,
|
||||
State: node.outcome,
|
||||
RunTime: node.runTime,
|
||||
Failure: node.failure,
|
||||
}
|
||||
}
|
||||
|
||||
func NewBeforeSuiteNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer) SuiteNode {
|
||||
return &simpleSuiteNode{
|
||||
runner: newRunner(body, codeLocation, timeout, failer, types.SpecComponentTypeBeforeSuite, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func NewAfterSuiteNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer) SuiteNode {
|
||||
return &simpleSuiteNode{
|
||||
runner: newRunner(body, codeLocation, timeout, failer, types.SpecComponentTypeAfterSuite, 0),
|
||||
}
|
||||
}
|
90
vendor/github.com/onsi/ginkgo/internal/leafnodes/synchronized_after_suite_node.go
generated
vendored
Normal file
90
vendor/github.com/onsi/ginkgo/internal/leafnodes/synchronized_after_suite_node.go
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
package leafnodes
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/onsi/ginkgo/internal/failer"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
type synchronizedAfterSuiteNode struct {
|
||||
runnerA *runner
|
||||
runnerB *runner
|
||||
|
||||
outcome types.SpecState
|
||||
failure types.SpecFailure
|
||||
runTime time.Duration
|
||||
}
|
||||
|
||||
func NewSynchronizedAfterSuiteNode(bodyA interface{}, bodyB interface{}, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer) SuiteNode {
|
||||
return &synchronizedAfterSuiteNode{
|
||||
runnerA: newRunner(bodyA, codeLocation, timeout, failer, types.SpecComponentTypeAfterSuite, 0),
|
||||
runnerB: newRunner(bodyB, codeLocation, timeout, failer, types.SpecComponentTypeAfterSuite, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func (node *synchronizedAfterSuiteNode) Run(parallelNode int, parallelTotal int, syncHost string) bool {
|
||||
node.outcome, node.failure = node.runnerA.run()
|
||||
|
||||
if parallelNode == 1 {
|
||||
if parallelTotal > 1 {
|
||||
node.waitUntilOtherNodesAreDone(syncHost)
|
||||
}
|
||||
|
||||
outcome, failure := node.runnerB.run()
|
||||
|
||||
if node.outcome == types.SpecStatePassed {
|
||||
node.outcome, node.failure = outcome, failure
|
||||
}
|
||||
}
|
||||
|
||||
return node.outcome == types.SpecStatePassed
|
||||
}
|
||||
|
||||
func (node *synchronizedAfterSuiteNode) Passed() bool {
|
||||
return node.outcome == types.SpecStatePassed
|
||||
}
|
||||
|
||||
func (node *synchronizedAfterSuiteNode) Summary() *types.SetupSummary {
|
||||
return &types.SetupSummary{
|
||||
ComponentType: node.runnerA.nodeType,
|
||||
CodeLocation: node.runnerA.codeLocation,
|
||||
State: node.outcome,
|
||||
RunTime: node.runTime,
|
||||
Failure: node.failure,
|
||||
}
|
||||
}
|
||||
|
||||
func (node *synchronizedAfterSuiteNode) waitUntilOtherNodesAreDone(syncHost string) {
|
||||
for {
|
||||
if node.canRun(syncHost) {
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
func (node *synchronizedAfterSuiteNode) canRun(syncHost string) bool {
|
||||
resp, err := http.Get(syncHost + "/RemoteAfterSuiteData")
|
||||
if err != nil || resp.StatusCode != http.StatusOK {
|
||||
return false
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
afterSuiteData := types.RemoteAfterSuiteData{}
|
||||
err = json.Unmarshal(body, &afterSuiteData)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return afterSuiteData.CanRun
|
||||
}
|
181
vendor/github.com/onsi/ginkgo/internal/leafnodes/synchronized_before_suite_node.go
generated
vendored
Normal file
181
vendor/github.com/onsi/ginkgo/internal/leafnodes/synchronized_before_suite_node.go
generated
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
package leafnodes
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/onsi/ginkgo/internal/failer"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
type synchronizedBeforeSuiteNode struct {
|
||||
runnerA *runner
|
||||
runnerB *runner
|
||||
|
||||
data []byte
|
||||
|
||||
outcome types.SpecState
|
||||
failure types.SpecFailure
|
||||
runTime time.Duration
|
||||
}
|
||||
|
||||
func NewSynchronizedBeforeSuiteNode(bodyA interface{}, bodyB interface{}, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer) SuiteNode {
|
||||
node := &synchronizedBeforeSuiteNode{}
|
||||
|
||||
node.runnerA = newRunner(node.wrapA(bodyA), codeLocation, timeout, failer, types.SpecComponentTypeBeforeSuite, 0)
|
||||
node.runnerB = newRunner(node.wrapB(bodyB), codeLocation, timeout, failer, types.SpecComponentTypeBeforeSuite, 0)
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
func (node *synchronizedBeforeSuiteNode) Run(parallelNode int, parallelTotal int, syncHost string) bool {
|
||||
t := time.Now()
|
||||
defer func() {
|
||||
node.runTime = time.Since(t)
|
||||
}()
|
||||
|
||||
if parallelNode == 1 {
|
||||
node.outcome, node.failure = node.runA(parallelTotal, syncHost)
|
||||
} else {
|
||||
node.outcome, node.failure = node.waitForA(syncHost)
|
||||
}
|
||||
|
||||
if node.outcome != types.SpecStatePassed {
|
||||
return false
|
||||
}
|
||||
node.outcome, node.failure = node.runnerB.run()
|
||||
|
||||
return node.outcome == types.SpecStatePassed
|
||||
}
|
||||
|
||||
func (node *synchronizedBeforeSuiteNode) runA(parallelTotal int, syncHost string) (types.SpecState, types.SpecFailure) {
|
||||
outcome, failure := node.runnerA.run()
|
||||
|
||||
if parallelTotal > 1 {
|
||||
state := types.RemoteBeforeSuiteStatePassed
|
||||
if outcome != types.SpecStatePassed {
|
||||
state = types.RemoteBeforeSuiteStateFailed
|
||||
}
|
||||
json := (types.RemoteBeforeSuiteData{
|
||||
Data: node.data,
|
||||
State: state,
|
||||
}).ToJSON()
|
||||
http.Post(syncHost+"/BeforeSuiteState", "application/json", bytes.NewBuffer(json))
|
||||
}
|
||||
|
||||
return outcome, failure
|
||||
}
|
||||
|
||||
func (node *synchronizedBeforeSuiteNode) waitForA(syncHost string) (types.SpecState, types.SpecFailure) {
|
||||
failure := func(message string) types.SpecFailure {
|
||||
return types.SpecFailure{
|
||||
Message: message,
|
||||
Location: node.runnerA.codeLocation,
|
||||
ComponentType: node.runnerA.nodeType,
|
||||
ComponentIndex: node.runnerA.componentIndex,
|
||||
ComponentCodeLocation: node.runnerA.codeLocation,
|
||||
}
|
||||
}
|
||||
for {
|
||||
resp, err := http.Get(syncHost + "/BeforeSuiteState")
|
||||
if err != nil || resp.StatusCode != http.StatusOK {
|
||||
return types.SpecStateFailed, failure("Failed to fetch BeforeSuite state")
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return types.SpecStateFailed, failure("Failed to read BeforeSuite state")
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
beforeSuiteData := types.RemoteBeforeSuiteData{}
|
||||
err = json.Unmarshal(body, &beforeSuiteData)
|
||||
if err != nil {
|
||||
return types.SpecStateFailed, failure("Failed to decode BeforeSuite state")
|
||||
}
|
||||
|
||||
switch beforeSuiteData.State {
|
||||
case types.RemoteBeforeSuiteStatePassed:
|
||||
node.data = beforeSuiteData.Data
|
||||
return types.SpecStatePassed, types.SpecFailure{}
|
||||
case types.RemoteBeforeSuiteStateFailed:
|
||||
return types.SpecStateFailed, failure("BeforeSuite on Node 1 failed")
|
||||
case types.RemoteBeforeSuiteStateDisappeared:
|
||||
return types.SpecStateFailed, failure("Node 1 disappeared before completing BeforeSuite")
|
||||
}
|
||||
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
func (node *synchronizedBeforeSuiteNode) Passed() bool {
|
||||
return node.outcome == types.SpecStatePassed
|
||||
}
|
||||
|
||||
func (node *synchronizedBeforeSuiteNode) Summary() *types.SetupSummary {
|
||||
return &types.SetupSummary{
|
||||
ComponentType: node.runnerA.nodeType,
|
||||
CodeLocation: node.runnerA.codeLocation,
|
||||
State: node.outcome,
|
||||
RunTime: node.runTime,
|
||||
Failure: node.failure,
|
||||
}
|
||||
}
|
||||
|
||||
func (node *synchronizedBeforeSuiteNode) wrapA(bodyA interface{}) interface{} {
|
||||
typeA := reflect.TypeOf(bodyA)
|
||||
if typeA.Kind() != reflect.Func {
|
||||
panic("SynchronizedBeforeSuite expects a function as its first argument")
|
||||
}
|
||||
|
||||
takesNothing := typeA.NumIn() == 0
|
||||
takesADoneChannel := typeA.NumIn() == 1 && typeA.In(0).Kind() == reflect.Chan && typeA.In(0).Elem().Kind() == reflect.Interface
|
||||
returnsBytes := typeA.NumOut() == 1 && typeA.Out(0).Kind() == reflect.Slice && typeA.Out(0).Elem().Kind() == reflect.Uint8
|
||||
|
||||
if !((takesNothing || takesADoneChannel) && returnsBytes) {
|
||||
panic("SynchronizedBeforeSuite's first argument should be a function that returns []byte and either takes no arguments or takes a Done channel.")
|
||||
}
|
||||
|
||||
if takesADoneChannel {
|
||||
return func(done chan<- interface{}) {
|
||||
out := reflect.ValueOf(bodyA).Call([]reflect.Value{reflect.ValueOf(done)})
|
||||
node.data = out[0].Interface().([]byte)
|
||||
}
|
||||
}
|
||||
|
||||
return func() {
|
||||
out := reflect.ValueOf(bodyA).Call([]reflect.Value{})
|
||||
node.data = out[0].Interface().([]byte)
|
||||
}
|
||||
}
|
||||
|
||||
func (node *synchronizedBeforeSuiteNode) wrapB(bodyB interface{}) interface{} {
|
||||
typeB := reflect.TypeOf(bodyB)
|
||||
if typeB.Kind() != reflect.Func {
|
||||
panic("SynchronizedBeforeSuite expects a function as its second argument")
|
||||
}
|
||||
|
||||
returnsNothing := typeB.NumOut() == 0
|
||||
takesBytesOnly := typeB.NumIn() == 1 && typeB.In(0).Kind() == reflect.Slice && typeB.In(0).Elem().Kind() == reflect.Uint8
|
||||
takesBytesAndDone := typeB.NumIn() == 2 &&
|
||||
typeB.In(0).Kind() == reflect.Slice && typeB.In(0).Elem().Kind() == reflect.Uint8 &&
|
||||
typeB.In(1).Kind() == reflect.Chan && typeB.In(1).Elem().Kind() == reflect.Interface
|
||||
|
||||
if !((takesBytesOnly || takesBytesAndDone) && returnsNothing) {
|
||||
panic("SynchronizedBeforeSuite's second argument should be a function that returns nothing and either takes []byte or ([]byte, Done)")
|
||||
}
|
||||
|
||||
if takesBytesAndDone {
|
||||
return func(done chan<- interface{}) {
|
||||
reflect.ValueOf(bodyB).Call([]reflect.Value{reflect.ValueOf(node.data), reflect.ValueOf(done)})
|
||||
}
|
||||
}
|
||||
|
||||
return func() {
|
||||
reflect.ValueOf(bodyB).Call([]reflect.Value{reflect.ValueOf(node.data)})
|
||||
}
|
||||
}
|
249
vendor/github.com/onsi/ginkgo/internal/remote/aggregator.go
generated
vendored
Normal file
249
vendor/github.com/onsi/ginkgo/internal/remote/aggregator.go
generated
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
|
||||
Aggregator is a reporter used by the Ginkgo CLI to aggregate and present parallel test output
|
||||
coherently as tests complete. You shouldn't need to use this in your code. To run tests in parallel:
|
||||
|
||||
ginkgo -nodes=N
|
||||
|
||||
where N is the number of nodes you desire.
|
||||
*/
|
||||
package remote
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/onsi/ginkgo/config"
|
||||
"github.com/onsi/ginkgo/reporters/stenographer"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
type configAndSuite struct {
|
||||
config config.GinkgoConfigType
|
||||
summary *types.SuiteSummary
|
||||
}
|
||||
|
||||
type Aggregator struct {
|
||||
nodeCount int
|
||||
config config.DefaultReporterConfigType
|
||||
stenographer stenographer.Stenographer
|
||||
result chan bool
|
||||
|
||||
suiteBeginnings chan configAndSuite
|
||||
aggregatedSuiteBeginnings []configAndSuite
|
||||
|
||||
beforeSuites chan *types.SetupSummary
|
||||
aggregatedBeforeSuites []*types.SetupSummary
|
||||
|
||||
afterSuites chan *types.SetupSummary
|
||||
aggregatedAfterSuites []*types.SetupSummary
|
||||
|
||||
specCompletions chan *types.SpecSummary
|
||||
completedSpecs []*types.SpecSummary
|
||||
|
||||
suiteEndings chan *types.SuiteSummary
|
||||
aggregatedSuiteEndings []*types.SuiteSummary
|
||||
specs []*types.SpecSummary
|
||||
|
||||
startTime time.Time
|
||||
}
|
||||
|
||||
func NewAggregator(nodeCount int, result chan bool, config config.DefaultReporterConfigType, stenographer stenographer.Stenographer) *Aggregator {
|
||||
aggregator := &Aggregator{
|
||||
nodeCount: nodeCount,
|
||||
result: result,
|
||||
config: config,
|
||||
stenographer: stenographer,
|
||||
|
||||
suiteBeginnings: make(chan configAndSuite),
|
||||
beforeSuites: make(chan *types.SetupSummary),
|
||||
afterSuites: make(chan *types.SetupSummary),
|
||||
specCompletions: make(chan *types.SpecSummary),
|
||||
suiteEndings: make(chan *types.SuiteSummary),
|
||||
}
|
||||
|
||||
go aggregator.mux()
|
||||
|
||||
return aggregator
|
||||
}
|
||||
|
||||
func (aggregator *Aggregator) SpecSuiteWillBegin(config config.GinkgoConfigType, summary *types.SuiteSummary) {
|
||||
aggregator.suiteBeginnings <- configAndSuite{config, summary}
|
||||
}
|
||||
|
||||
func (aggregator *Aggregator) BeforeSuiteDidRun(setupSummary *types.SetupSummary) {
|
||||
aggregator.beforeSuites <- setupSummary
|
||||
}
|
||||
|
||||
func (aggregator *Aggregator) AfterSuiteDidRun(setupSummary *types.SetupSummary) {
|
||||
aggregator.afterSuites <- setupSummary
|
||||
}
|
||||
|
||||
func (aggregator *Aggregator) SpecWillRun(specSummary *types.SpecSummary) {
|
||||
//noop
|
||||
}
|
||||
|
||||
func (aggregator *Aggregator) SpecDidComplete(specSummary *types.SpecSummary) {
|
||||
aggregator.specCompletions <- specSummary
|
||||
}
|
||||
|
||||
func (aggregator *Aggregator) SpecSuiteDidEnd(summary *types.SuiteSummary) {
|
||||
aggregator.suiteEndings <- summary
|
||||
}
|
||||
|
||||
func (aggregator *Aggregator) mux() {
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case configAndSuite := <-aggregator.suiteBeginnings:
|
||||
aggregator.registerSuiteBeginning(configAndSuite)
|
||||
case setupSummary := <-aggregator.beforeSuites:
|
||||
aggregator.registerBeforeSuite(setupSummary)
|
||||
case setupSummary := <-aggregator.afterSuites:
|
||||
aggregator.registerAfterSuite(setupSummary)
|
||||
case specSummary := <-aggregator.specCompletions:
|
||||
aggregator.registerSpecCompletion(specSummary)
|
||||
case suite := <-aggregator.suiteEndings:
|
||||
finished, passed := aggregator.registerSuiteEnding(suite)
|
||||
if finished {
|
||||
aggregator.result <- passed
|
||||
break loop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (aggregator *Aggregator) registerSuiteBeginning(configAndSuite configAndSuite) {
|
||||
aggregator.aggregatedSuiteBeginnings = append(aggregator.aggregatedSuiteBeginnings, configAndSuite)
|
||||
|
||||
if len(aggregator.aggregatedSuiteBeginnings) == 1 {
|
||||
aggregator.startTime = time.Now()
|
||||
}
|
||||
|
||||
if len(aggregator.aggregatedSuiteBeginnings) != aggregator.nodeCount {
|
||||
return
|
||||
}
|
||||
|
||||
aggregator.stenographer.AnnounceSuite(configAndSuite.summary.SuiteDescription, configAndSuite.config.RandomSeed, configAndSuite.config.RandomizeAllSpecs, aggregator.config.Succinct)
|
||||
|
||||
totalNumberOfSpecs := 0
|
||||
if len(aggregator.aggregatedSuiteBeginnings) > 0 {
|
||||
totalNumberOfSpecs = configAndSuite.summary.NumberOfSpecsBeforeParallelization
|
||||
}
|
||||
|
||||
aggregator.stenographer.AnnounceTotalNumberOfSpecs(totalNumberOfSpecs, aggregator.config.Succinct)
|
||||
aggregator.stenographer.AnnounceAggregatedParallelRun(aggregator.nodeCount, aggregator.config.Succinct)
|
||||
aggregator.flushCompletedSpecs()
|
||||
}
|
||||
|
||||
func (aggregator *Aggregator) registerBeforeSuite(setupSummary *types.SetupSummary) {
|
||||
aggregator.aggregatedBeforeSuites = append(aggregator.aggregatedBeforeSuites, setupSummary)
|
||||
aggregator.flushCompletedSpecs()
|
||||
}
|
||||
|
||||
func (aggregator *Aggregator) registerAfterSuite(setupSummary *types.SetupSummary) {
|
||||
aggregator.aggregatedAfterSuites = append(aggregator.aggregatedAfterSuites, setupSummary)
|
||||
aggregator.flushCompletedSpecs()
|
||||
}
|
||||
|
||||
func (aggregator *Aggregator) registerSpecCompletion(specSummary *types.SpecSummary) {
|
||||
aggregator.completedSpecs = append(aggregator.completedSpecs, specSummary)
|
||||
aggregator.specs = append(aggregator.specs, specSummary)
|
||||
aggregator.flushCompletedSpecs()
|
||||
}
|
||||
|
||||
func (aggregator *Aggregator) flushCompletedSpecs() {
|
||||
if len(aggregator.aggregatedSuiteBeginnings) != aggregator.nodeCount {
|
||||
return
|
||||
}
|
||||
|
||||
for _, setupSummary := range aggregator.aggregatedBeforeSuites {
|
||||
aggregator.announceBeforeSuite(setupSummary)
|
||||
}
|
||||
|
||||
for _, specSummary := range aggregator.completedSpecs {
|
||||
aggregator.announceSpec(specSummary)
|
||||
}
|
||||
|
||||
for _, setupSummary := range aggregator.aggregatedAfterSuites {
|
||||
aggregator.announceAfterSuite(setupSummary)
|
||||
}
|
||||
|
||||
aggregator.aggregatedBeforeSuites = []*types.SetupSummary{}
|
||||
aggregator.completedSpecs = []*types.SpecSummary{}
|
||||
aggregator.aggregatedAfterSuites = []*types.SetupSummary{}
|
||||
}
|
||||
|
||||
func (aggregator *Aggregator) announceBeforeSuite(setupSummary *types.SetupSummary) {
|
||||
aggregator.stenographer.AnnounceCapturedOutput(setupSummary.CapturedOutput)
|
||||
if setupSummary.State != types.SpecStatePassed {
|
||||
aggregator.stenographer.AnnounceBeforeSuiteFailure(setupSummary, aggregator.config.Succinct, aggregator.config.FullTrace)
|
||||
}
|
||||
}
|
||||
|
||||
func (aggregator *Aggregator) announceAfterSuite(setupSummary *types.SetupSummary) {
|
||||
aggregator.stenographer.AnnounceCapturedOutput(setupSummary.CapturedOutput)
|
||||
if setupSummary.State != types.SpecStatePassed {
|
||||
aggregator.stenographer.AnnounceAfterSuiteFailure(setupSummary, aggregator.config.Succinct, aggregator.config.FullTrace)
|
||||
}
|
||||
}
|
||||
|
||||
func (aggregator *Aggregator) announceSpec(specSummary *types.SpecSummary) {
|
||||
if aggregator.config.Verbose && specSummary.State != types.SpecStatePending && specSummary.State != types.SpecStateSkipped {
|
||||
aggregator.stenographer.AnnounceSpecWillRun(specSummary)
|
||||
}
|
||||
|
||||
aggregator.stenographer.AnnounceCapturedOutput(specSummary.CapturedOutput)
|
||||
|
||||
switch specSummary.State {
|
||||
case types.SpecStatePassed:
|
||||
if specSummary.IsMeasurement {
|
||||
aggregator.stenographer.AnnounceSuccessfulMeasurement(specSummary, aggregator.config.Succinct)
|
||||
} else if specSummary.RunTime.Seconds() >= aggregator.config.SlowSpecThreshold {
|
||||
aggregator.stenographer.AnnounceSuccessfulSlowSpec(specSummary, aggregator.config.Succinct)
|
||||
} else {
|
||||
aggregator.stenographer.AnnounceSuccessfulSpec(specSummary)
|
||||
}
|
||||
|
||||
case types.SpecStatePending:
|
||||
aggregator.stenographer.AnnouncePendingSpec(specSummary, aggregator.config.NoisyPendings && !aggregator.config.Succinct)
|
||||
case types.SpecStateSkipped:
|
||||
aggregator.stenographer.AnnounceSkippedSpec(specSummary, aggregator.config.Succinct || !aggregator.config.NoisySkippings, aggregator.config.FullTrace)
|
||||
case types.SpecStateTimedOut:
|
||||
aggregator.stenographer.AnnounceSpecTimedOut(specSummary, aggregator.config.Succinct, aggregator.config.FullTrace)
|
||||
case types.SpecStatePanicked:
|
||||
aggregator.stenographer.AnnounceSpecPanicked(specSummary, aggregator.config.Succinct, aggregator.config.FullTrace)
|
||||
case types.SpecStateFailed:
|
||||
aggregator.stenographer.AnnounceSpecFailed(specSummary, aggregator.config.Succinct, aggregator.config.FullTrace)
|
||||
}
|
||||
}
|
||||
|
||||
func (aggregator *Aggregator) registerSuiteEnding(suite *types.SuiteSummary) (finished bool, passed bool) {
|
||||
aggregator.aggregatedSuiteEndings = append(aggregator.aggregatedSuiteEndings, suite)
|
||||
if len(aggregator.aggregatedSuiteEndings) < aggregator.nodeCount {
|
||||
return false, false
|
||||
}
|
||||
|
||||
aggregatedSuiteSummary := &types.SuiteSummary{}
|
||||
aggregatedSuiteSummary.SuiteSucceeded = true
|
||||
|
||||
for _, suiteSummary := range aggregator.aggregatedSuiteEndings {
|
||||
if !suiteSummary.SuiteSucceeded {
|
||||
aggregatedSuiteSummary.SuiteSucceeded = false
|
||||
}
|
||||
|
||||
aggregatedSuiteSummary.NumberOfSpecsThatWillBeRun += suiteSummary.NumberOfSpecsThatWillBeRun
|
||||
aggregatedSuiteSummary.NumberOfTotalSpecs += suiteSummary.NumberOfTotalSpecs
|
||||
aggregatedSuiteSummary.NumberOfPassedSpecs += suiteSummary.NumberOfPassedSpecs
|
||||
aggregatedSuiteSummary.NumberOfFailedSpecs += suiteSummary.NumberOfFailedSpecs
|
||||
aggregatedSuiteSummary.NumberOfPendingSpecs += suiteSummary.NumberOfPendingSpecs
|
||||
aggregatedSuiteSummary.NumberOfSkippedSpecs += suiteSummary.NumberOfSkippedSpecs
|
||||
aggregatedSuiteSummary.NumberOfFlakedSpecs += suiteSummary.NumberOfFlakedSpecs
|
||||
}
|
||||
|
||||
aggregatedSuiteSummary.RunTime = time.Since(aggregator.startTime)
|
||||
|
||||
aggregator.stenographer.SummarizeFailures(aggregator.specs)
|
||||
aggregator.stenographer.AnnounceSpecRunCompletion(aggregatedSuiteSummary, aggregator.config.Succinct)
|
||||
|
||||
return true, aggregatedSuiteSummary.SuiteSucceeded
|
||||
}
|
147
vendor/github.com/onsi/ginkgo/internal/remote/forwarding_reporter.go
generated
vendored
Normal file
147
vendor/github.com/onsi/ginkgo/internal/remote/forwarding_reporter.go
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
package remote
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/onsi/ginkgo/internal/writer"
|
||||
"github.com/onsi/ginkgo/reporters"
|
||||
"github.com/onsi/ginkgo/reporters/stenographer"
|
||||
|
||||
"github.com/onsi/ginkgo/config"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
//An interface to net/http's client to allow the injection of fakes under test
|
||||
type Poster interface {
|
||||
Post(url string, bodyType string, body io.Reader) (resp *http.Response, err error)
|
||||
}
|
||||
|
||||
/*
|
||||
The ForwardingReporter is a Ginkgo reporter that forwards information to
|
||||
a Ginkgo remote server.
|
||||
|
||||
When streaming parallel test output, this repoter is automatically installed by Ginkgo.
|
||||
|
||||
This is accomplished by passing in the GINKGO_REMOTE_REPORTING_SERVER environment variable to `go test`, the Ginkgo test runner
|
||||
detects this environment variable (which should contain the host of the server) and automatically installs a ForwardingReporter
|
||||
in place of Ginkgo's DefaultReporter.
|
||||
*/
|
||||
|
||||
type ForwardingReporter struct {
|
||||
serverHost string
|
||||
poster Poster
|
||||
outputInterceptor OutputInterceptor
|
||||
debugMode bool
|
||||
debugFile *os.File
|
||||
nestedReporter *reporters.DefaultReporter
|
||||
}
|
||||
|
||||
func NewForwardingReporter(config config.DefaultReporterConfigType, serverHost string, poster Poster, outputInterceptor OutputInterceptor, ginkgoWriter *writer.Writer, debugFile string) *ForwardingReporter {
|
||||
reporter := &ForwardingReporter{
|
||||
serverHost: serverHost,
|
||||
poster: poster,
|
||||
outputInterceptor: outputInterceptor,
|
||||
}
|
||||
|
||||
if debugFile != "" {
|
||||
var err error
|
||||
reporter.debugMode = true
|
||||
reporter.debugFile, err = os.Create(debugFile)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if !config.Verbose {
|
||||
//if verbose is true then the GinkgoWriter emits to stdout. Don't _also_ redirect GinkgoWriter output as that will result in duplication.
|
||||
ginkgoWriter.AndRedirectTo(reporter.debugFile)
|
||||
}
|
||||
outputInterceptor.StreamTo(reporter.debugFile) //This is not working
|
||||
|
||||
stenographer := stenographer.New(false, true, reporter.debugFile)
|
||||
config.Succinct = false
|
||||
config.Verbose = true
|
||||
config.FullTrace = true
|
||||
reporter.nestedReporter = reporters.NewDefaultReporter(config, stenographer)
|
||||
}
|
||||
|
||||
return reporter
|
||||
}
|
||||
|
||||
func (reporter *ForwardingReporter) post(path string, data interface{}) {
|
||||
encoded, _ := json.Marshal(data)
|
||||
buffer := bytes.NewBuffer(encoded)
|
||||
reporter.poster.Post(reporter.serverHost+path, "application/json", buffer)
|
||||
}
|
||||
|
||||
func (reporter *ForwardingReporter) SpecSuiteWillBegin(conf config.GinkgoConfigType, summary *types.SuiteSummary) {
|
||||
data := struct {
|
||||
Config config.GinkgoConfigType `json:"config"`
|
||||
Summary *types.SuiteSummary `json:"suite-summary"`
|
||||
}{
|
||||
conf,
|
||||
summary,
|
||||
}
|
||||
|
||||
reporter.outputInterceptor.StartInterceptingOutput()
|
||||
if reporter.debugMode {
|
||||
reporter.nestedReporter.SpecSuiteWillBegin(conf, summary)
|
||||
reporter.debugFile.Sync()
|
||||
}
|
||||
reporter.post("/SpecSuiteWillBegin", data)
|
||||
}
|
||||
|
||||
func (reporter *ForwardingReporter) BeforeSuiteDidRun(setupSummary *types.SetupSummary) {
|
||||
output, _ := reporter.outputInterceptor.StopInterceptingAndReturnOutput()
|
||||
reporter.outputInterceptor.StartInterceptingOutput()
|
||||
setupSummary.CapturedOutput = output
|
||||
if reporter.debugMode {
|
||||
reporter.nestedReporter.BeforeSuiteDidRun(setupSummary)
|
||||
reporter.debugFile.Sync()
|
||||
}
|
||||
reporter.post("/BeforeSuiteDidRun", setupSummary)
|
||||
}
|
||||
|
||||
func (reporter *ForwardingReporter) SpecWillRun(specSummary *types.SpecSummary) {
|
||||
if reporter.debugMode {
|
||||
reporter.nestedReporter.SpecWillRun(specSummary)
|
||||
reporter.debugFile.Sync()
|
||||
}
|
||||
reporter.post("/SpecWillRun", specSummary)
|
||||
}
|
||||
|
||||
func (reporter *ForwardingReporter) SpecDidComplete(specSummary *types.SpecSummary) {
|
||||
output, _ := reporter.outputInterceptor.StopInterceptingAndReturnOutput()
|
||||
reporter.outputInterceptor.StartInterceptingOutput()
|
||||
specSummary.CapturedOutput = output
|
||||
if reporter.debugMode {
|
||||
reporter.nestedReporter.SpecDidComplete(specSummary)
|
||||
reporter.debugFile.Sync()
|
||||
}
|
||||
reporter.post("/SpecDidComplete", specSummary)
|
||||
}
|
||||
|
||||
func (reporter *ForwardingReporter) AfterSuiteDidRun(setupSummary *types.SetupSummary) {
|
||||
output, _ := reporter.outputInterceptor.StopInterceptingAndReturnOutput()
|
||||
reporter.outputInterceptor.StartInterceptingOutput()
|
||||
setupSummary.CapturedOutput = output
|
||||
if reporter.debugMode {
|
||||
reporter.nestedReporter.AfterSuiteDidRun(setupSummary)
|
||||
reporter.debugFile.Sync()
|
||||
}
|
||||
reporter.post("/AfterSuiteDidRun", setupSummary)
|
||||
}
|
||||
|
||||
func (reporter *ForwardingReporter) SpecSuiteDidEnd(summary *types.SuiteSummary) {
|
||||
reporter.outputInterceptor.StopInterceptingAndReturnOutput()
|
||||
if reporter.debugMode {
|
||||
reporter.nestedReporter.SpecSuiteDidEnd(summary)
|
||||
reporter.debugFile.Sync()
|
||||
}
|
||||
reporter.post("/SpecSuiteDidEnd", summary)
|
||||
}
|
13
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor.go
generated
vendored
Normal file
13
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
package remote
|
||||
|
||||
import "os"
|
||||
|
||||
/*
|
||||
The OutputInterceptor is used by the ForwardingReporter to
|
||||
intercept and capture all stdin and stderr output during a test run.
|
||||
*/
|
||||
type OutputInterceptor interface {
|
||||
StartInterceptingOutput() error
|
||||
StopInterceptingAndReturnOutput() (string, error)
|
||||
StreamTo(*os.File)
|
||||
}
|
82
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_unix.go
generated
vendored
Normal file
82
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_unix.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
// +build freebsd openbsd netbsd dragonfly darwin linux solaris
|
||||
|
||||
package remote
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/nxadm/tail"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func NewOutputInterceptor() OutputInterceptor {
|
||||
return &outputInterceptor{}
|
||||
}
|
||||
|
||||
type outputInterceptor struct {
|
||||
redirectFile *os.File
|
||||
streamTarget *os.File
|
||||
intercepting bool
|
||||
tailer *tail.Tail
|
||||
doneTailing chan bool
|
||||
}
|
||||
|
||||
func (interceptor *outputInterceptor) StartInterceptingOutput() error {
|
||||
if interceptor.intercepting {
|
||||
return errors.New("Already intercepting output!")
|
||||
}
|
||||
interceptor.intercepting = true
|
||||
|
||||
var err error
|
||||
|
||||
interceptor.redirectFile, err = ioutil.TempFile("", "ginkgo-output")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// This might call Dup3 if the dup2 syscall is not available, e.g. on
|
||||
// linux/arm64 or linux/riscv64
|
||||
unix.Dup2(int(interceptor.redirectFile.Fd()), 1)
|
||||
unix.Dup2(int(interceptor.redirectFile.Fd()), 2)
|
||||
|
||||
if interceptor.streamTarget != nil {
|
||||
interceptor.tailer, _ = tail.TailFile(interceptor.redirectFile.Name(), tail.Config{Follow: true})
|
||||
interceptor.doneTailing = make(chan bool)
|
||||
|
||||
go func() {
|
||||
for line := range interceptor.tailer.Lines {
|
||||
interceptor.streamTarget.Write([]byte(line.Text + "\n"))
|
||||
}
|
||||
close(interceptor.doneTailing)
|
||||
}()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (interceptor *outputInterceptor) StopInterceptingAndReturnOutput() (string, error) {
|
||||
if !interceptor.intercepting {
|
||||
return "", errors.New("Not intercepting output!")
|
||||
}
|
||||
|
||||
interceptor.redirectFile.Close()
|
||||
output, err := ioutil.ReadFile(interceptor.redirectFile.Name())
|
||||
os.Remove(interceptor.redirectFile.Name())
|
||||
|
||||
interceptor.intercepting = false
|
||||
|
||||
if interceptor.streamTarget != nil {
|
||||
interceptor.tailer.Stop()
|
||||
interceptor.tailer.Cleanup()
|
||||
<-interceptor.doneTailing
|
||||
interceptor.streamTarget.Sync()
|
||||
}
|
||||
|
||||
return string(output), err
|
||||
}
|
||||
|
||||
func (interceptor *outputInterceptor) StreamTo(out *os.File) {
|
||||
interceptor.streamTarget = out
|
||||
}
|
36
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_win.go
generated
vendored
Normal file
36
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_win.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// +build windows
|
||||
|
||||
package remote
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
)
|
||||
|
||||
func NewOutputInterceptor() OutputInterceptor {
|
||||
return &outputInterceptor{}
|
||||
}
|
||||
|
||||
type outputInterceptor struct {
|
||||
intercepting bool
|
||||
}
|
||||
|
||||
func (interceptor *outputInterceptor) StartInterceptingOutput() error {
|
||||
if interceptor.intercepting {
|
||||
return errors.New("Already intercepting output!")
|
||||
}
|
||||
interceptor.intercepting = true
|
||||
|
||||
// not working on windows...
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (interceptor *outputInterceptor) StopInterceptingAndReturnOutput() (string, error) {
|
||||
// not working on windows...
|
||||
interceptor.intercepting = false
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (interceptor *outputInterceptor) StreamTo(*os.File) {}
|
224
vendor/github.com/onsi/ginkgo/internal/remote/server.go
generated
vendored
Normal file
224
vendor/github.com/onsi/ginkgo/internal/remote/server.go
generated
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
|
||||
The remote package provides the pieces to allow Ginkgo test suites to report to remote listeners.
|
||||
This is used, primarily, to enable streaming parallel test output but has, in principal, broader applications (e.g. streaming test output to a browser).
|
||||
|
||||
*/
|
||||
|
||||
package remote
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/onsi/ginkgo/internal/spec_iterator"
|
||||
|
||||
"github.com/onsi/ginkgo/config"
|
||||
"github.com/onsi/ginkgo/reporters"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
/*
|
||||
Server spins up on an automatically selected port and listens for communication from the forwarding reporter.
|
||||
It then forwards that communication to attached reporters.
|
||||
*/
|
||||
type Server struct {
|
||||
listener net.Listener
|
||||
reporters []reporters.Reporter
|
||||
alives []func() bool
|
||||
lock *sync.Mutex
|
||||
beforeSuiteData types.RemoteBeforeSuiteData
|
||||
parallelTotal int
|
||||
counter int
|
||||
}
|
||||
|
||||
//Create a new server, automatically selecting a port
|
||||
func NewServer(parallelTotal int) (*Server, error) {
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Server{
|
||||
listener: listener,
|
||||
lock: &sync.Mutex{},
|
||||
alives: make([]func() bool, parallelTotal),
|
||||
beforeSuiteData: types.RemoteBeforeSuiteData{Data: nil, State: types.RemoteBeforeSuiteStatePending},
|
||||
parallelTotal: parallelTotal,
|
||||
}, nil
|
||||
}
|
||||
|
||||
//Start the server. You don't need to `go s.Start()`, just `s.Start()`
|
||||
func (server *Server) Start() {
|
||||
httpServer := &http.Server{}
|
||||
mux := http.NewServeMux()
|
||||
httpServer.Handler = mux
|
||||
|
||||
//streaming endpoints
|
||||
mux.HandleFunc("/SpecSuiteWillBegin", server.specSuiteWillBegin)
|
||||
mux.HandleFunc("/BeforeSuiteDidRun", server.beforeSuiteDidRun)
|
||||
mux.HandleFunc("/AfterSuiteDidRun", server.afterSuiteDidRun)
|
||||
mux.HandleFunc("/SpecWillRun", server.specWillRun)
|
||||
mux.HandleFunc("/SpecDidComplete", server.specDidComplete)
|
||||
mux.HandleFunc("/SpecSuiteDidEnd", server.specSuiteDidEnd)
|
||||
|
||||
//synchronization endpoints
|
||||
mux.HandleFunc("/BeforeSuiteState", server.handleBeforeSuiteState)
|
||||
mux.HandleFunc("/RemoteAfterSuiteData", server.handleRemoteAfterSuiteData)
|
||||
mux.HandleFunc("/counter", server.handleCounter)
|
||||
mux.HandleFunc("/has-counter", server.handleHasCounter) //for backward compatibility
|
||||
|
||||
go httpServer.Serve(server.listener)
|
||||
}
|
||||
|
||||
//Stop the server
|
||||
func (server *Server) Close() {
|
||||
server.listener.Close()
|
||||
}
|
||||
|
||||
//The address the server can be reached it. Pass this into the `ForwardingReporter`.
|
||||
func (server *Server) Address() string {
|
||||
return "http://" + server.listener.Addr().String()
|
||||
}
|
||||
|
||||
//
|
||||
// Streaming Endpoints
|
||||
//
|
||||
|
||||
//The server will forward all received messages to Ginkgo reporters registered with `RegisterReporters`
|
||||
func (server *Server) readAll(request *http.Request) []byte {
|
||||
defer request.Body.Close()
|
||||
body, _ := ioutil.ReadAll(request.Body)
|
||||
return body
|
||||
}
|
||||
|
||||
func (server *Server) RegisterReporters(reporters ...reporters.Reporter) {
|
||||
server.reporters = reporters
|
||||
}
|
||||
|
||||
func (server *Server) specSuiteWillBegin(writer http.ResponseWriter, request *http.Request) {
|
||||
body := server.readAll(request)
|
||||
|
||||
var data struct {
|
||||
Config config.GinkgoConfigType `json:"config"`
|
||||
Summary *types.SuiteSummary `json:"suite-summary"`
|
||||
}
|
||||
|
||||
json.Unmarshal(body, &data)
|
||||
|
||||
for _, reporter := range server.reporters {
|
||||
reporter.SpecSuiteWillBegin(data.Config, data.Summary)
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) beforeSuiteDidRun(writer http.ResponseWriter, request *http.Request) {
|
||||
body := server.readAll(request)
|
||||
var setupSummary *types.SetupSummary
|
||||
json.Unmarshal(body, &setupSummary)
|
||||
|
||||
for _, reporter := range server.reporters {
|
||||
reporter.BeforeSuiteDidRun(setupSummary)
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) afterSuiteDidRun(writer http.ResponseWriter, request *http.Request) {
|
||||
body := server.readAll(request)
|
||||
var setupSummary *types.SetupSummary
|
||||
json.Unmarshal(body, &setupSummary)
|
||||
|
||||
for _, reporter := range server.reporters {
|
||||
reporter.AfterSuiteDidRun(setupSummary)
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) specWillRun(writer http.ResponseWriter, request *http.Request) {
|
||||
body := server.readAll(request)
|
||||
var specSummary *types.SpecSummary
|
||||
json.Unmarshal(body, &specSummary)
|
||||
|
||||
for _, reporter := range server.reporters {
|
||||
reporter.SpecWillRun(specSummary)
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) specDidComplete(writer http.ResponseWriter, request *http.Request) {
|
||||
body := server.readAll(request)
|
||||
var specSummary *types.SpecSummary
|
||||
json.Unmarshal(body, &specSummary)
|
||||
|
||||
for _, reporter := range server.reporters {
|
||||
reporter.SpecDidComplete(specSummary)
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) specSuiteDidEnd(writer http.ResponseWriter, request *http.Request) {
|
||||
body := server.readAll(request)
|
||||
var suiteSummary *types.SuiteSummary
|
||||
json.Unmarshal(body, &suiteSummary)
|
||||
|
||||
for _, reporter := range server.reporters {
|
||||
reporter.SpecSuiteDidEnd(suiteSummary)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Synchronization Endpoints
|
||||
//
|
||||
|
||||
func (server *Server) RegisterAlive(node int, alive func() bool) {
|
||||
server.lock.Lock()
|
||||
defer server.lock.Unlock()
|
||||
server.alives[node-1] = alive
|
||||
}
|
||||
|
||||
func (server *Server) nodeIsAlive(node int) bool {
|
||||
server.lock.Lock()
|
||||
defer server.lock.Unlock()
|
||||
alive := server.alives[node-1]
|
||||
if alive == nil {
|
||||
return true
|
||||
}
|
||||
return alive()
|
||||
}
|
||||
|
||||
func (server *Server) handleBeforeSuiteState(writer http.ResponseWriter, request *http.Request) {
|
||||
if request.Method == "POST" {
|
||||
dec := json.NewDecoder(request.Body)
|
||||
dec.Decode(&(server.beforeSuiteData))
|
||||
} else {
|
||||
beforeSuiteData := server.beforeSuiteData
|
||||
if beforeSuiteData.State == types.RemoteBeforeSuiteStatePending && !server.nodeIsAlive(1) {
|
||||
beforeSuiteData.State = types.RemoteBeforeSuiteStateDisappeared
|
||||
}
|
||||
enc := json.NewEncoder(writer)
|
||||
enc.Encode(beforeSuiteData)
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) handleRemoteAfterSuiteData(writer http.ResponseWriter, request *http.Request) {
|
||||
afterSuiteData := types.RemoteAfterSuiteData{
|
||||
CanRun: true,
|
||||
}
|
||||
for i := 2; i <= server.parallelTotal; i++ {
|
||||
afterSuiteData.CanRun = afterSuiteData.CanRun && !server.nodeIsAlive(i)
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(writer)
|
||||
enc.Encode(afterSuiteData)
|
||||
}
|
||||
|
||||
func (server *Server) handleCounter(writer http.ResponseWriter, request *http.Request) {
|
||||
c := spec_iterator.Counter{}
|
||||
server.lock.Lock()
|
||||
c.Index = server.counter
|
||||
server.counter++
|
||||
server.lock.Unlock()
|
||||
|
||||
json.NewEncoder(writer).Encode(c)
|
||||
}
|
||||
|
||||
func (server *Server) handleHasCounter(writer http.ResponseWriter, request *http.Request) {
|
||||
writer.Write([]byte(""))
|
||||
}
|
247
vendor/github.com/onsi/ginkgo/internal/spec/spec.go
generated
vendored
Normal file
247
vendor/github.com/onsi/ginkgo/internal/spec/spec.go
generated
vendored
Normal file
@@ -0,0 +1,247 @@
|
||||
package spec
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"sync"
|
||||
|
||||
"github.com/onsi/ginkgo/internal/containernode"
|
||||
"github.com/onsi/ginkgo/internal/leafnodes"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
type Spec struct {
|
||||
subject leafnodes.SubjectNode
|
||||
focused bool
|
||||
announceProgress bool
|
||||
|
||||
containers []*containernode.ContainerNode
|
||||
|
||||
state types.SpecState
|
||||
runTime time.Duration
|
||||
startTime time.Time
|
||||
failure types.SpecFailure
|
||||
previousFailures bool
|
||||
|
||||
stateMutex *sync.Mutex
|
||||
}
|
||||
|
||||
func New(subject leafnodes.SubjectNode, containers []*containernode.ContainerNode, announceProgress bool) *Spec {
|
||||
spec := &Spec{
|
||||
subject: subject,
|
||||
containers: containers,
|
||||
focused: subject.Flag() == types.FlagTypeFocused,
|
||||
announceProgress: announceProgress,
|
||||
stateMutex: &sync.Mutex{},
|
||||
}
|
||||
|
||||
spec.processFlag(subject.Flag())
|
||||
for i := len(containers) - 1; i >= 0; i-- {
|
||||
spec.processFlag(containers[i].Flag())
|
||||
}
|
||||
|
||||
return spec
|
||||
}
|
||||
|
||||
func (spec *Spec) processFlag(flag types.FlagType) {
|
||||
if flag == types.FlagTypeFocused {
|
||||
spec.focused = true
|
||||
} else if flag == types.FlagTypePending {
|
||||
spec.setState(types.SpecStatePending)
|
||||
}
|
||||
}
|
||||
|
||||
func (spec *Spec) Skip() {
|
||||
spec.setState(types.SpecStateSkipped)
|
||||
}
|
||||
|
||||
func (spec *Spec) Failed() bool {
|
||||
return spec.getState() == types.SpecStateFailed || spec.getState() == types.SpecStatePanicked || spec.getState() == types.SpecStateTimedOut
|
||||
}
|
||||
|
||||
func (spec *Spec) Passed() bool {
|
||||
return spec.getState() == types.SpecStatePassed
|
||||
}
|
||||
|
||||
func (spec *Spec) Flaked() bool {
|
||||
return spec.getState() == types.SpecStatePassed && spec.previousFailures
|
||||
}
|
||||
|
||||
func (spec *Spec) Pending() bool {
|
||||
return spec.getState() == types.SpecStatePending
|
||||
}
|
||||
|
||||
func (spec *Spec) Skipped() bool {
|
||||
return spec.getState() == types.SpecStateSkipped
|
||||
}
|
||||
|
||||
func (spec *Spec) Focused() bool {
|
||||
return spec.focused
|
||||
}
|
||||
|
||||
func (spec *Spec) IsMeasurement() bool {
|
||||
return spec.subject.Type() == types.SpecComponentTypeMeasure
|
||||
}
|
||||
|
||||
func (spec *Spec) Summary(suiteID string) *types.SpecSummary {
|
||||
componentTexts := make([]string, len(spec.containers)+1)
|
||||
componentCodeLocations := make([]types.CodeLocation, len(spec.containers)+1)
|
||||
|
||||
for i, container := range spec.containers {
|
||||
componentTexts[i] = container.Text()
|
||||
componentCodeLocations[i] = container.CodeLocation()
|
||||
}
|
||||
|
||||
componentTexts[len(spec.containers)] = spec.subject.Text()
|
||||
componentCodeLocations[len(spec.containers)] = spec.subject.CodeLocation()
|
||||
|
||||
runTime := spec.runTime
|
||||
if runTime == 0 && !spec.startTime.IsZero() {
|
||||
runTime = time.Since(spec.startTime)
|
||||
}
|
||||
|
||||
return &types.SpecSummary{
|
||||
IsMeasurement: spec.IsMeasurement(),
|
||||
NumberOfSamples: spec.subject.Samples(),
|
||||
ComponentTexts: componentTexts,
|
||||
ComponentCodeLocations: componentCodeLocations,
|
||||
State: spec.getState(),
|
||||
RunTime: runTime,
|
||||
Failure: spec.failure,
|
||||
Measurements: spec.measurementsReport(),
|
||||
SuiteID: suiteID,
|
||||
}
|
||||
}
|
||||
|
||||
func (spec *Spec) ConcatenatedString() string {
|
||||
s := ""
|
||||
for _, container := range spec.containers {
|
||||
s += container.Text() + " "
|
||||
}
|
||||
|
||||
return s + spec.subject.Text()
|
||||
}
|
||||
|
||||
func (spec *Spec) Run(writer io.Writer) {
|
||||
if spec.getState() == types.SpecStateFailed {
|
||||
spec.previousFailures = true
|
||||
}
|
||||
|
||||
spec.startTime = time.Now()
|
||||
defer func() {
|
||||
spec.runTime = time.Since(spec.startTime)
|
||||
}()
|
||||
|
||||
for sample := 0; sample < spec.subject.Samples(); sample++ {
|
||||
spec.runSample(sample, writer)
|
||||
|
||||
if spec.getState() != types.SpecStatePassed {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (spec *Spec) getState() types.SpecState {
|
||||
spec.stateMutex.Lock()
|
||||
defer spec.stateMutex.Unlock()
|
||||
return spec.state
|
||||
}
|
||||
|
||||
func (spec *Spec) setState(state types.SpecState) {
|
||||
spec.stateMutex.Lock()
|
||||
defer spec.stateMutex.Unlock()
|
||||
spec.state = state
|
||||
}
|
||||
|
||||
func (spec *Spec) runSample(sample int, writer io.Writer) {
|
||||
spec.setState(types.SpecStatePassed)
|
||||
spec.failure = types.SpecFailure{}
|
||||
innerMostContainerIndexToUnwind := -1
|
||||
|
||||
defer func() {
|
||||
for i := innerMostContainerIndexToUnwind; i >= 0; i-- {
|
||||
container := spec.containers[i]
|
||||
for _, justAfterEach := range container.SetupNodesOfType(types.SpecComponentTypeJustAfterEach) {
|
||||
spec.announceSetupNode(writer, "JustAfterEach", container, justAfterEach)
|
||||
justAfterEachState, justAfterEachFailure := justAfterEach.Run()
|
||||
if justAfterEachState != types.SpecStatePassed && spec.state == types.SpecStatePassed {
|
||||
spec.state = justAfterEachState
|
||||
spec.failure = justAfterEachFailure
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i := innerMostContainerIndexToUnwind; i >= 0; i-- {
|
||||
container := spec.containers[i]
|
||||
for _, afterEach := range container.SetupNodesOfType(types.SpecComponentTypeAfterEach) {
|
||||
spec.announceSetupNode(writer, "AfterEach", container, afterEach)
|
||||
afterEachState, afterEachFailure := afterEach.Run()
|
||||
if afterEachState != types.SpecStatePassed && spec.getState() == types.SpecStatePassed {
|
||||
spec.setState(afterEachState)
|
||||
spec.failure = afterEachFailure
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
for i, container := range spec.containers {
|
||||
innerMostContainerIndexToUnwind = i
|
||||
for _, beforeEach := range container.SetupNodesOfType(types.SpecComponentTypeBeforeEach) {
|
||||
spec.announceSetupNode(writer, "BeforeEach", container, beforeEach)
|
||||
s, f := beforeEach.Run()
|
||||
spec.failure = f
|
||||
spec.setState(s)
|
||||
if spec.getState() != types.SpecStatePassed {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, container := range spec.containers {
|
||||
for _, justBeforeEach := range container.SetupNodesOfType(types.SpecComponentTypeJustBeforeEach) {
|
||||
spec.announceSetupNode(writer, "JustBeforeEach", container, justBeforeEach)
|
||||
s, f := justBeforeEach.Run()
|
||||
spec.failure = f
|
||||
spec.setState(s)
|
||||
if spec.getState() != types.SpecStatePassed {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spec.announceSubject(writer, spec.subject)
|
||||
s, f := spec.subject.Run()
|
||||
spec.failure = f
|
||||
spec.setState(s)
|
||||
}
|
||||
|
||||
func (spec *Spec) announceSetupNode(writer io.Writer, nodeType string, container *containernode.ContainerNode, setupNode leafnodes.BasicNode) {
|
||||
if spec.announceProgress {
|
||||
s := fmt.Sprintf("[%s] %s\n %s\n", nodeType, container.Text(), setupNode.CodeLocation().String())
|
||||
writer.Write([]byte(s))
|
||||
}
|
||||
}
|
||||
|
||||
func (spec *Spec) announceSubject(writer io.Writer, subject leafnodes.SubjectNode) {
|
||||
if spec.announceProgress {
|
||||
nodeType := ""
|
||||
switch subject.Type() {
|
||||
case types.SpecComponentTypeIt:
|
||||
nodeType = "It"
|
||||
case types.SpecComponentTypeMeasure:
|
||||
nodeType = "Measure"
|
||||
}
|
||||
s := fmt.Sprintf("[%s] %s\n %s\n", nodeType, subject.Text(), subject.CodeLocation().String())
|
||||
writer.Write([]byte(s))
|
||||
}
|
||||
}
|
||||
|
||||
func (spec *Spec) measurementsReport() map[string]*types.SpecMeasurement {
|
||||
if !spec.IsMeasurement() || spec.Failed() {
|
||||
return map[string]*types.SpecMeasurement{}
|
||||
}
|
||||
|
||||
return spec.subject.(*leafnodes.MeasureNode).MeasurementsReport()
|
||||
}
|
144
vendor/github.com/onsi/ginkgo/internal/spec/specs.go
generated
vendored
Normal file
144
vendor/github.com/onsi/ginkgo/internal/spec/specs.go
generated
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
package spec
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Specs struct {
|
||||
specs []*Spec
|
||||
names []string
|
||||
|
||||
hasProgrammaticFocus bool
|
||||
RegexScansFilePath bool
|
||||
}
|
||||
|
||||
func NewSpecs(specs []*Spec) *Specs {
|
||||
names := make([]string, len(specs))
|
||||
for i, spec := range specs {
|
||||
names[i] = spec.ConcatenatedString()
|
||||
}
|
||||
return &Specs{
|
||||
specs: specs,
|
||||
names: names,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Specs) Specs() []*Spec {
|
||||
return e.specs
|
||||
}
|
||||
|
||||
func (e *Specs) HasProgrammaticFocus() bool {
|
||||
return e.hasProgrammaticFocus
|
||||
}
|
||||
|
||||
func (e *Specs) Shuffle(r *rand.Rand) {
|
||||
sort.Sort(e)
|
||||
permutation := r.Perm(len(e.specs))
|
||||
shuffledSpecs := make([]*Spec, len(e.specs))
|
||||
names := make([]string, len(e.specs))
|
||||
for i, j := range permutation {
|
||||
shuffledSpecs[i] = e.specs[j]
|
||||
names[i] = e.names[j]
|
||||
}
|
||||
e.specs = shuffledSpecs
|
||||
e.names = names
|
||||
}
|
||||
|
||||
func (e *Specs) ApplyFocus(description string, focus, skip []string) {
|
||||
if len(focus)+len(skip) == 0 {
|
||||
e.applyProgrammaticFocus()
|
||||
} else {
|
||||
e.applyRegExpFocusAndSkip(description, focus, skip)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Specs) applyProgrammaticFocus() {
|
||||
e.hasProgrammaticFocus = false
|
||||
for _, spec := range e.specs {
|
||||
if spec.Focused() && !spec.Pending() {
|
||||
e.hasProgrammaticFocus = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if e.hasProgrammaticFocus {
|
||||
for _, spec := range e.specs {
|
||||
if !spec.Focused() {
|
||||
spec.Skip()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// toMatch returns a byte[] to be used by regex matchers. When adding new behaviours to the matching function,
|
||||
// this is the place which we append to.
|
||||
func (e *Specs) toMatch(description string, i int) []byte {
|
||||
if i > len(e.names) {
|
||||
return nil
|
||||
}
|
||||
if e.RegexScansFilePath {
|
||||
return []byte(
|
||||
description + " " +
|
||||
e.names[i] + " " +
|
||||
e.specs[i].subject.CodeLocation().FileName)
|
||||
} else {
|
||||
return []byte(
|
||||
description + " " +
|
||||
e.names[i])
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Specs) applyRegExpFocusAndSkip(description string, focus, skip []string) {
|
||||
var focusFilter, skipFilter *regexp.Regexp
|
||||
if len(focus) > 0 {
|
||||
focusFilter = regexp.MustCompile(strings.Join(focus, "|"))
|
||||
}
|
||||
if len(skip) > 0 {
|
||||
skipFilter = regexp.MustCompile(strings.Join(skip, "|"))
|
||||
}
|
||||
|
||||
for i, spec := range e.specs {
|
||||
matchesFocus := true
|
||||
matchesSkip := false
|
||||
|
||||
toMatch := e.toMatch(description, i)
|
||||
|
||||
if focusFilter != nil {
|
||||
matchesFocus = focusFilter.Match(toMatch)
|
||||
}
|
||||
|
||||
if skipFilter != nil {
|
||||
matchesSkip = skipFilter.Match(toMatch)
|
||||
}
|
||||
|
||||
if !matchesFocus || matchesSkip {
|
||||
spec.Skip()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Specs) SkipMeasurements() {
|
||||
for _, spec := range e.specs {
|
||||
if spec.IsMeasurement() {
|
||||
spec.Skip()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//sort.Interface
|
||||
|
||||
func (e *Specs) Len() int {
|
||||
return len(e.specs)
|
||||
}
|
||||
|
||||
func (e *Specs) Less(i, j int) bool {
|
||||
return e.names[i] < e.names[j]
|
||||
}
|
||||
|
||||
func (e *Specs) Swap(i, j int) {
|
||||
e.names[i], e.names[j] = e.names[j], e.names[i]
|
||||
e.specs[i], e.specs[j] = e.specs[j], e.specs[i]
|
||||
}
|
55
vendor/github.com/onsi/ginkgo/internal/spec_iterator/index_computer.go
generated
vendored
Normal file
55
vendor/github.com/onsi/ginkgo/internal/spec_iterator/index_computer.go
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
package spec_iterator
|
||||
|
||||
func ParallelizedIndexRange(length int, parallelTotal int, parallelNode int) (startIndex int, count int) {
|
||||
if length == 0 {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
// We have more nodes than tests. Trivial case.
|
||||
if parallelTotal >= length {
|
||||
if parallelNode > length {
|
||||
return 0, 0
|
||||
} else {
|
||||
return parallelNode - 1, 1
|
||||
}
|
||||
}
|
||||
|
||||
// This is the minimum amount of tests that a node will be required to run
|
||||
minTestsPerNode := length / parallelTotal
|
||||
|
||||
// This is the maximum amount of tests that a node will be required to run
|
||||
// The algorithm guarantees that this would be equal to at least the minimum amount
|
||||
// and at most one more
|
||||
maxTestsPerNode := minTestsPerNode
|
||||
if length%parallelTotal != 0 {
|
||||
maxTestsPerNode++
|
||||
}
|
||||
|
||||
// Number of nodes that will have to run the maximum amount of tests per node
|
||||
numMaxLoadNodes := length % parallelTotal
|
||||
|
||||
// Number of nodes that precede the current node and will have to run the maximum amount of tests per node
|
||||
var numPrecedingMaxLoadNodes int
|
||||
if parallelNode > numMaxLoadNodes {
|
||||
numPrecedingMaxLoadNodes = numMaxLoadNodes
|
||||
} else {
|
||||
numPrecedingMaxLoadNodes = parallelNode - 1
|
||||
}
|
||||
|
||||
// Number of nodes that precede the current node and will have to run the minimum amount of tests per node
|
||||
var numPrecedingMinLoadNodes int
|
||||
if parallelNode <= numMaxLoadNodes {
|
||||
numPrecedingMinLoadNodes = 0
|
||||
} else {
|
||||
numPrecedingMinLoadNodes = parallelNode - numMaxLoadNodes - 1
|
||||
}
|
||||
|
||||
// Evaluate the test start index and number of tests to run
|
||||
startIndex = numPrecedingMaxLoadNodes*maxTestsPerNode + numPrecedingMinLoadNodes*minTestsPerNode
|
||||
if parallelNode > numMaxLoadNodes {
|
||||
count = minTestsPerNode
|
||||
} else {
|
||||
count = maxTestsPerNode
|
||||
}
|
||||
return
|
||||
}
|
59
vendor/github.com/onsi/ginkgo/internal/spec_iterator/parallel_spec_iterator.go
generated
vendored
Normal file
59
vendor/github.com/onsi/ginkgo/internal/spec_iterator/parallel_spec_iterator.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
package spec_iterator
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/onsi/ginkgo/internal/spec"
|
||||
)
|
||||
|
||||
type ParallelIterator struct {
|
||||
specs []*spec.Spec
|
||||
host string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
func NewParallelIterator(specs []*spec.Spec, host string) *ParallelIterator {
|
||||
return &ParallelIterator{
|
||||
specs: specs,
|
||||
host: host,
|
||||
client: &http.Client{},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ParallelIterator) Next() (*spec.Spec, error) {
|
||||
resp, err := s.client.Get(s.host + "/counter")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("unexpected status code %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
var counter Counter
|
||||
err = json.NewDecoder(resp.Body).Decode(&counter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if counter.Index >= len(s.specs) {
|
||||
return nil, ErrClosed
|
||||
}
|
||||
|
||||
return s.specs[counter.Index], nil
|
||||
}
|
||||
|
||||
func (s *ParallelIterator) NumberOfSpecsPriorToIteration() int {
|
||||
return len(s.specs)
|
||||
}
|
||||
|
||||
func (s *ParallelIterator) NumberOfSpecsToProcessIfKnown() (int, bool) {
|
||||
return -1, false
|
||||
}
|
||||
|
||||
func (s *ParallelIterator) NumberOfSpecsThatWillBeRunIfKnown() (int, bool) {
|
||||
return -1, false
|
||||
}
|
45
vendor/github.com/onsi/ginkgo/internal/spec_iterator/serial_spec_iterator.go
generated
vendored
Normal file
45
vendor/github.com/onsi/ginkgo/internal/spec_iterator/serial_spec_iterator.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
package spec_iterator
|
||||
|
||||
import (
|
||||
"github.com/onsi/ginkgo/internal/spec"
|
||||
)
|
||||
|
||||
type SerialIterator struct {
|
||||
specs []*spec.Spec
|
||||
index int
|
||||
}
|
||||
|
||||
func NewSerialIterator(specs []*spec.Spec) *SerialIterator {
|
||||
return &SerialIterator{
|
||||
specs: specs,
|
||||
index: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SerialIterator) Next() (*spec.Spec, error) {
|
||||
if s.index >= len(s.specs) {
|
||||
return nil, ErrClosed
|
||||
}
|
||||
|
||||
spec := s.specs[s.index]
|
||||
s.index += 1
|
||||
return spec, nil
|
||||
}
|
||||
|
||||
func (s *SerialIterator) NumberOfSpecsPriorToIteration() int {
|
||||
return len(s.specs)
|
||||
}
|
||||
|
||||
func (s *SerialIterator) NumberOfSpecsToProcessIfKnown() (int, bool) {
|
||||
return len(s.specs), true
|
||||
}
|
||||
|
||||
func (s *SerialIterator) NumberOfSpecsThatWillBeRunIfKnown() (int, bool) {
|
||||
count := 0
|
||||
for _, s := range s.specs {
|
||||
if !s.Skipped() && !s.Pending() {
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
return count, true
|
||||
}
|
47
vendor/github.com/onsi/ginkgo/internal/spec_iterator/sharded_parallel_spec_iterator.go
generated
vendored
Normal file
47
vendor/github.com/onsi/ginkgo/internal/spec_iterator/sharded_parallel_spec_iterator.go
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
package spec_iterator
|
||||
|
||||
import "github.com/onsi/ginkgo/internal/spec"
|
||||
|
||||
type ShardedParallelIterator struct {
|
||||
specs []*spec.Spec
|
||||
index int
|
||||
maxIndex int
|
||||
}
|
||||
|
||||
func NewShardedParallelIterator(specs []*spec.Spec, total int, node int) *ShardedParallelIterator {
|
||||
startIndex, count := ParallelizedIndexRange(len(specs), total, node)
|
||||
|
||||
return &ShardedParallelIterator{
|
||||
specs: specs,
|
||||
index: startIndex,
|
||||
maxIndex: startIndex + count,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ShardedParallelIterator) Next() (*spec.Spec, error) {
|
||||
if s.index >= s.maxIndex {
|
||||
return nil, ErrClosed
|
||||
}
|
||||
|
||||
spec := s.specs[s.index]
|
||||
s.index += 1
|
||||
return spec, nil
|
||||
}
|
||||
|
||||
func (s *ShardedParallelIterator) NumberOfSpecsPriorToIteration() int {
|
||||
return len(s.specs)
|
||||
}
|
||||
|
||||
func (s *ShardedParallelIterator) NumberOfSpecsToProcessIfKnown() (int, bool) {
|
||||
return s.maxIndex - s.index, true
|
||||
}
|
||||
|
||||
func (s *ShardedParallelIterator) NumberOfSpecsThatWillBeRunIfKnown() (int, bool) {
|
||||
count := 0
|
||||
for i := s.index; i < s.maxIndex; i += 1 {
|
||||
if !s.specs[i].Skipped() && !s.specs[i].Pending() {
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
return count, true
|
||||
}
|
20
vendor/github.com/onsi/ginkgo/internal/spec_iterator/spec_iterator.go
generated
vendored
Normal file
20
vendor/github.com/onsi/ginkgo/internal/spec_iterator/spec_iterator.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
package spec_iterator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/onsi/ginkgo/internal/spec"
|
||||
)
|
||||
|
||||
var ErrClosed = errors.New("no more specs to run")
|
||||
|
||||
type SpecIterator interface {
|
||||
Next() (*spec.Spec, error)
|
||||
NumberOfSpecsPriorToIteration() int
|
||||
NumberOfSpecsToProcessIfKnown() (int, bool)
|
||||
NumberOfSpecsThatWillBeRunIfKnown() (int, bool)
|
||||
}
|
||||
|
||||
type Counter struct {
|
||||
Index int `json:"index"`
|
||||
}
|
15
vendor/github.com/onsi/ginkgo/internal/specrunner/random_id.go
generated
vendored
Normal file
15
vendor/github.com/onsi/ginkgo/internal/specrunner/random_id.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
package specrunner
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func randomID() string {
|
||||
b := make([]byte, 8)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%x-%x-%x-%x", b[0:2], b[2:4], b[4:6], b[6:8])
|
||||
}
|
411
vendor/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go
generated
vendored
Normal file
411
vendor/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go
generated
vendored
Normal file
@@ -0,0 +1,411 @@
|
||||
package specrunner
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/onsi/ginkgo/internal/spec_iterator"
|
||||
|
||||
"github.com/onsi/ginkgo/config"
|
||||
"github.com/onsi/ginkgo/internal/leafnodes"
|
||||
"github.com/onsi/ginkgo/internal/spec"
|
||||
Writer "github.com/onsi/ginkgo/internal/writer"
|
||||
"github.com/onsi/ginkgo/reporters"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
|
||||
"time"
|
||||
)
|
||||
|
||||
type SpecRunner struct {
|
||||
description string
|
||||
beforeSuiteNode leafnodes.SuiteNode
|
||||
iterator spec_iterator.SpecIterator
|
||||
afterSuiteNode leafnodes.SuiteNode
|
||||
reporters []reporters.Reporter
|
||||
startTime time.Time
|
||||
suiteID string
|
||||
runningSpec *spec.Spec
|
||||
writer Writer.WriterInterface
|
||||
config config.GinkgoConfigType
|
||||
interrupted bool
|
||||
processedSpecs []*spec.Spec
|
||||
lock *sync.Mutex
|
||||
}
|
||||
|
||||
func New(description string, beforeSuiteNode leafnodes.SuiteNode, iterator spec_iterator.SpecIterator, afterSuiteNode leafnodes.SuiteNode, reporters []reporters.Reporter, writer Writer.WriterInterface, config config.GinkgoConfigType) *SpecRunner {
|
||||
return &SpecRunner{
|
||||
description: description,
|
||||
beforeSuiteNode: beforeSuiteNode,
|
||||
iterator: iterator,
|
||||
afterSuiteNode: afterSuiteNode,
|
||||
reporters: reporters,
|
||||
writer: writer,
|
||||
config: config,
|
||||
suiteID: randomID(),
|
||||
lock: &sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) Run() bool {
|
||||
if runner.config.DryRun {
|
||||
runner.performDryRun()
|
||||
return true
|
||||
}
|
||||
|
||||
runner.reportSuiteWillBegin()
|
||||
signalRegistered := make(chan struct{})
|
||||
go runner.registerForInterrupts(signalRegistered)
|
||||
<-signalRegistered
|
||||
|
||||
suitePassed := runner.runBeforeSuite()
|
||||
|
||||
if suitePassed {
|
||||
suitePassed = runner.runSpecs()
|
||||
}
|
||||
|
||||
runner.blockForeverIfInterrupted()
|
||||
|
||||
suitePassed = runner.runAfterSuite() && suitePassed
|
||||
|
||||
runner.reportSuiteDidEnd(suitePassed)
|
||||
|
||||
return suitePassed
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) performDryRun() {
|
||||
runner.reportSuiteWillBegin()
|
||||
|
||||
if runner.beforeSuiteNode != nil {
|
||||
summary := runner.beforeSuiteNode.Summary()
|
||||
summary.State = types.SpecStatePassed
|
||||
runner.reportBeforeSuite(summary)
|
||||
}
|
||||
|
||||
for {
|
||||
spec, err := runner.iterator.Next()
|
||||
if err == spec_iterator.ErrClosed {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println("failed to iterate over tests:\n" + err.Error())
|
||||
break
|
||||
}
|
||||
|
||||
runner.processedSpecs = append(runner.processedSpecs, spec)
|
||||
|
||||
summary := spec.Summary(runner.suiteID)
|
||||
runner.reportSpecWillRun(summary)
|
||||
if summary.State == types.SpecStateInvalid {
|
||||
summary.State = types.SpecStatePassed
|
||||
}
|
||||
runner.reportSpecDidComplete(summary, false)
|
||||
}
|
||||
|
||||
if runner.afterSuiteNode != nil {
|
||||
summary := runner.afterSuiteNode.Summary()
|
||||
summary.State = types.SpecStatePassed
|
||||
runner.reportAfterSuite(summary)
|
||||
}
|
||||
|
||||
runner.reportSuiteDidEnd(true)
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) runBeforeSuite() bool {
|
||||
if runner.beforeSuiteNode == nil || runner.wasInterrupted() {
|
||||
return true
|
||||
}
|
||||
|
||||
runner.writer.Truncate()
|
||||
conf := runner.config
|
||||
passed := runner.beforeSuiteNode.Run(conf.ParallelNode, conf.ParallelTotal, conf.SyncHost)
|
||||
if !passed {
|
||||
runner.writer.DumpOut()
|
||||
}
|
||||
runner.reportBeforeSuite(runner.beforeSuiteNode.Summary())
|
||||
return passed
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) runAfterSuite() bool {
|
||||
if runner.afterSuiteNode == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
runner.writer.Truncate()
|
||||
conf := runner.config
|
||||
passed := runner.afterSuiteNode.Run(conf.ParallelNode, conf.ParallelTotal, conf.SyncHost)
|
||||
if !passed {
|
||||
runner.writer.DumpOut()
|
||||
}
|
||||
runner.reportAfterSuite(runner.afterSuiteNode.Summary())
|
||||
return passed
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) runSpecs() bool {
|
||||
suiteFailed := false
|
||||
skipRemainingSpecs := false
|
||||
for {
|
||||
spec, err := runner.iterator.Next()
|
||||
if err == spec_iterator.ErrClosed {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println("failed to iterate over tests:\n" + err.Error())
|
||||
suiteFailed = true
|
||||
break
|
||||
}
|
||||
|
||||
runner.processedSpecs = append(runner.processedSpecs, spec)
|
||||
|
||||
if runner.wasInterrupted() {
|
||||
break
|
||||
}
|
||||
if skipRemainingSpecs {
|
||||
spec.Skip()
|
||||
}
|
||||
|
||||
if !spec.Skipped() && !spec.Pending() {
|
||||
if passed := runner.runSpec(spec); !passed {
|
||||
suiteFailed = true
|
||||
}
|
||||
} else if spec.Pending() && runner.config.FailOnPending {
|
||||
runner.reportSpecWillRun(spec.Summary(runner.suiteID))
|
||||
suiteFailed = true
|
||||
runner.reportSpecDidComplete(spec.Summary(runner.suiteID), spec.Failed())
|
||||
} else {
|
||||
runner.reportSpecWillRun(spec.Summary(runner.suiteID))
|
||||
runner.reportSpecDidComplete(spec.Summary(runner.suiteID), spec.Failed())
|
||||
}
|
||||
|
||||
if spec.Failed() && runner.config.FailFast {
|
||||
skipRemainingSpecs = true
|
||||
}
|
||||
}
|
||||
|
||||
return !suiteFailed
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) runSpec(spec *spec.Spec) (passed bool) {
|
||||
maxAttempts := 1
|
||||
if runner.config.FlakeAttempts > 0 {
|
||||
// uninitialized configs count as 1
|
||||
maxAttempts = runner.config.FlakeAttempts
|
||||
}
|
||||
|
||||
for i := 0; i < maxAttempts; i++ {
|
||||
runner.reportSpecWillRun(spec.Summary(runner.suiteID))
|
||||
runner.runningSpec = spec
|
||||
spec.Run(runner.writer)
|
||||
runner.runningSpec = nil
|
||||
runner.reportSpecDidComplete(spec.Summary(runner.suiteID), spec.Failed())
|
||||
if !spec.Failed() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) CurrentSpecSummary() (*types.SpecSummary, bool) {
|
||||
if runner.runningSpec == nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return runner.runningSpec.Summary(runner.suiteID), true
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) registerForInterrupts(signalRegistered chan struct{}) {
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||
close(signalRegistered)
|
||||
|
||||
<-c
|
||||
signal.Stop(c)
|
||||
runner.markInterrupted()
|
||||
go runner.registerForHardInterrupts()
|
||||
runner.writer.DumpOutWithHeader(`
|
||||
Received interrupt. Emitting contents of GinkgoWriter...
|
||||
---------------------------------------------------------
|
||||
`)
|
||||
if runner.afterSuiteNode != nil {
|
||||
fmt.Fprint(os.Stderr, `
|
||||
---------------------------------------------------------
|
||||
Received interrupt. Running AfterSuite...
|
||||
^C again to terminate immediately
|
||||
`)
|
||||
runner.runAfterSuite()
|
||||
}
|
||||
runner.reportSuiteDidEnd(false)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) registerForHardInterrupts() {
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||
|
||||
<-c
|
||||
fmt.Fprintln(os.Stderr, "\nReceived second interrupt. Shutting down.")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) blockForeverIfInterrupted() {
|
||||
runner.lock.Lock()
|
||||
interrupted := runner.interrupted
|
||||
runner.lock.Unlock()
|
||||
|
||||
if interrupted {
|
||||
select {}
|
||||
}
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) markInterrupted() {
|
||||
runner.lock.Lock()
|
||||
defer runner.lock.Unlock()
|
||||
runner.interrupted = true
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) wasInterrupted() bool {
|
||||
runner.lock.Lock()
|
||||
defer runner.lock.Unlock()
|
||||
return runner.interrupted
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) reportSuiteWillBegin() {
|
||||
runner.startTime = time.Now()
|
||||
summary := runner.suiteWillBeginSummary()
|
||||
for _, reporter := range runner.reporters {
|
||||
reporter.SpecSuiteWillBegin(runner.config, summary)
|
||||
}
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) reportBeforeSuite(summary *types.SetupSummary) {
|
||||
for _, reporter := range runner.reporters {
|
||||
reporter.BeforeSuiteDidRun(summary)
|
||||
}
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) reportAfterSuite(summary *types.SetupSummary) {
|
||||
for _, reporter := range runner.reporters {
|
||||
reporter.AfterSuiteDidRun(summary)
|
||||
}
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) reportSpecWillRun(summary *types.SpecSummary) {
|
||||
runner.writer.Truncate()
|
||||
|
||||
for _, reporter := range runner.reporters {
|
||||
reporter.SpecWillRun(summary)
|
||||
}
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) reportSpecDidComplete(summary *types.SpecSummary, failed bool) {
|
||||
if len(summary.CapturedOutput) == 0 {
|
||||
summary.CapturedOutput = string(runner.writer.Bytes())
|
||||
}
|
||||
for i := len(runner.reporters) - 1; i >= 1; i-- {
|
||||
runner.reporters[i].SpecDidComplete(summary)
|
||||
}
|
||||
|
||||
if failed {
|
||||
runner.writer.DumpOut()
|
||||
}
|
||||
|
||||
runner.reporters[0].SpecDidComplete(summary)
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) reportSuiteDidEnd(success bool) {
|
||||
summary := runner.suiteDidEndSummary(success)
|
||||
summary.RunTime = time.Since(runner.startTime)
|
||||
for _, reporter := range runner.reporters {
|
||||
reporter.SpecSuiteDidEnd(summary)
|
||||
}
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) countSpecsThatRanSatisfying(filter func(ex *spec.Spec) bool) (count int) {
|
||||
count = 0
|
||||
|
||||
for _, spec := range runner.processedSpecs {
|
||||
if filter(spec) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) suiteDidEndSummary(success bool) *types.SuiteSummary {
|
||||
numberOfSpecsThatWillBeRun := runner.countSpecsThatRanSatisfying(func(ex *spec.Spec) bool {
|
||||
return !ex.Skipped() && !ex.Pending()
|
||||
})
|
||||
|
||||
numberOfPendingSpecs := runner.countSpecsThatRanSatisfying(func(ex *spec.Spec) bool {
|
||||
return ex.Pending()
|
||||
})
|
||||
|
||||
numberOfSkippedSpecs := runner.countSpecsThatRanSatisfying(func(ex *spec.Spec) bool {
|
||||
return ex.Skipped()
|
||||
})
|
||||
|
||||
numberOfPassedSpecs := runner.countSpecsThatRanSatisfying(func(ex *spec.Spec) bool {
|
||||
return ex.Passed()
|
||||
})
|
||||
|
||||
numberOfFlakedSpecs := runner.countSpecsThatRanSatisfying(func(ex *spec.Spec) bool {
|
||||
return ex.Flaked()
|
||||
})
|
||||
|
||||
numberOfFailedSpecs := runner.countSpecsThatRanSatisfying(func(ex *spec.Spec) bool {
|
||||
return ex.Failed()
|
||||
})
|
||||
|
||||
if runner.beforeSuiteNode != nil && !runner.beforeSuiteNode.Passed() && !runner.config.DryRun {
|
||||
var known bool
|
||||
numberOfSpecsThatWillBeRun, known = runner.iterator.NumberOfSpecsThatWillBeRunIfKnown()
|
||||
if !known {
|
||||
numberOfSpecsThatWillBeRun = runner.iterator.NumberOfSpecsPriorToIteration()
|
||||
}
|
||||
numberOfFailedSpecs = numberOfSpecsThatWillBeRun
|
||||
}
|
||||
|
||||
return &types.SuiteSummary{
|
||||
SuiteDescription: runner.description,
|
||||
SuiteSucceeded: success,
|
||||
SuiteID: runner.suiteID,
|
||||
|
||||
NumberOfSpecsBeforeParallelization: runner.iterator.NumberOfSpecsPriorToIteration(),
|
||||
NumberOfTotalSpecs: len(runner.processedSpecs),
|
||||
NumberOfSpecsThatWillBeRun: numberOfSpecsThatWillBeRun,
|
||||
NumberOfPendingSpecs: numberOfPendingSpecs,
|
||||
NumberOfSkippedSpecs: numberOfSkippedSpecs,
|
||||
NumberOfPassedSpecs: numberOfPassedSpecs,
|
||||
NumberOfFailedSpecs: numberOfFailedSpecs,
|
||||
NumberOfFlakedSpecs: numberOfFlakedSpecs,
|
||||
}
|
||||
}
|
||||
|
||||
func (runner *SpecRunner) suiteWillBeginSummary() *types.SuiteSummary {
|
||||
numTotal, known := runner.iterator.NumberOfSpecsToProcessIfKnown()
|
||||
if !known {
|
||||
numTotal = -1
|
||||
}
|
||||
|
||||
numToRun, known := runner.iterator.NumberOfSpecsThatWillBeRunIfKnown()
|
||||
if !known {
|
||||
numToRun = -1
|
||||
}
|
||||
|
||||
return &types.SuiteSummary{
|
||||
SuiteDescription: runner.description,
|
||||
SuiteID: runner.suiteID,
|
||||
|
||||
NumberOfSpecsBeforeParallelization: runner.iterator.NumberOfSpecsPriorToIteration(),
|
||||
NumberOfTotalSpecs: numTotal,
|
||||
NumberOfSpecsThatWillBeRun: numToRun,
|
||||
NumberOfPendingSpecs: -1,
|
||||
NumberOfSkippedSpecs: -1,
|
||||
NumberOfPassedSpecs: -1,
|
||||
NumberOfFailedSpecs: -1,
|
||||
NumberOfFlakedSpecs: -1,
|
||||
}
|
||||
}
|
227
vendor/github.com/onsi/ginkgo/internal/suite/suite.go
generated
vendored
Normal file
227
vendor/github.com/onsi/ginkgo/internal/suite/suite.go
generated
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
package suite
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/onsi/ginkgo/internal/spec_iterator"
|
||||
|
||||
"github.com/onsi/ginkgo/config"
|
||||
"github.com/onsi/ginkgo/internal/containernode"
|
||||
"github.com/onsi/ginkgo/internal/failer"
|
||||
"github.com/onsi/ginkgo/internal/leafnodes"
|
||||
"github.com/onsi/ginkgo/internal/spec"
|
||||
"github.com/onsi/ginkgo/internal/specrunner"
|
||||
"github.com/onsi/ginkgo/internal/writer"
|
||||
"github.com/onsi/ginkgo/reporters"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
type ginkgoTestingT interface {
|
||||
Fail()
|
||||
}
|
||||
|
||||
type deferredContainerNode struct {
|
||||
text string
|
||||
body func()
|
||||
flag types.FlagType
|
||||
codeLocation types.CodeLocation
|
||||
}
|
||||
|
||||
type Suite struct {
|
||||
topLevelContainer *containernode.ContainerNode
|
||||
currentContainer *containernode.ContainerNode
|
||||
|
||||
deferredContainerNodes []deferredContainerNode
|
||||
|
||||
containerIndex int
|
||||
beforeSuiteNode leafnodes.SuiteNode
|
||||
afterSuiteNode leafnodes.SuiteNode
|
||||
runner *specrunner.SpecRunner
|
||||
failer *failer.Failer
|
||||
running bool
|
||||
expandTopLevelNodes bool
|
||||
}
|
||||
|
||||
func New(failer *failer.Failer) *Suite {
|
||||
topLevelContainer := containernode.New("[Top Level]", types.FlagTypeNone, types.CodeLocation{})
|
||||
|
||||
return &Suite{
|
||||
topLevelContainer: topLevelContainer,
|
||||
currentContainer: topLevelContainer,
|
||||
failer: failer,
|
||||
containerIndex: 1,
|
||||
deferredContainerNodes: []deferredContainerNode{},
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *Suite) Run(t ginkgoTestingT, description string, reporters []reporters.Reporter, writer writer.WriterInterface, config config.GinkgoConfigType) (bool, bool) {
|
||||
if config.ParallelTotal < 1 {
|
||||
panic("ginkgo.parallel.total must be >= 1")
|
||||
}
|
||||
|
||||
if config.ParallelNode > config.ParallelTotal || config.ParallelNode < 1 {
|
||||
panic("ginkgo.parallel.node is one-indexed and must be <= ginkgo.parallel.total")
|
||||
}
|
||||
|
||||
suite.expandTopLevelNodes = true
|
||||
for _, deferredNode := range suite.deferredContainerNodes {
|
||||
suite.PushContainerNode(deferredNode.text, deferredNode.body, deferredNode.flag, deferredNode.codeLocation)
|
||||
}
|
||||
|
||||
r := rand.New(rand.NewSource(config.RandomSeed))
|
||||
suite.topLevelContainer.Shuffle(r)
|
||||
iterator, hasProgrammaticFocus := suite.generateSpecsIterator(description, config)
|
||||
suite.runner = specrunner.New(description, suite.beforeSuiteNode, iterator, suite.afterSuiteNode, reporters, writer, config)
|
||||
|
||||
suite.running = true
|
||||
success := suite.runner.Run()
|
||||
if !success {
|
||||
t.Fail()
|
||||
}
|
||||
return success, hasProgrammaticFocus
|
||||
}
|
||||
|
||||
func (suite *Suite) generateSpecsIterator(description string, config config.GinkgoConfigType) (spec_iterator.SpecIterator, bool) {
|
||||
specsSlice := []*spec.Spec{}
|
||||
suite.topLevelContainer.BackPropagateProgrammaticFocus()
|
||||
for _, collatedNodes := range suite.topLevelContainer.Collate() {
|
||||
specsSlice = append(specsSlice, spec.New(collatedNodes.Subject, collatedNodes.Containers, config.EmitSpecProgress))
|
||||
}
|
||||
|
||||
specs := spec.NewSpecs(specsSlice)
|
||||
specs.RegexScansFilePath = config.RegexScansFilePath
|
||||
|
||||
if config.RandomizeAllSpecs {
|
||||
specs.Shuffle(rand.New(rand.NewSource(config.RandomSeed)))
|
||||
}
|
||||
|
||||
specs.ApplyFocus(description, config.FocusStrings, config.SkipStrings)
|
||||
|
||||
if config.SkipMeasurements {
|
||||
specs.SkipMeasurements()
|
||||
}
|
||||
|
||||
var iterator spec_iterator.SpecIterator
|
||||
|
||||
if config.ParallelTotal > 1 {
|
||||
iterator = spec_iterator.NewParallelIterator(specs.Specs(), config.SyncHost)
|
||||
resp, err := http.Get(config.SyncHost + "/has-counter")
|
||||
if err != nil || resp.StatusCode != http.StatusOK {
|
||||
iterator = spec_iterator.NewShardedParallelIterator(specs.Specs(), config.ParallelTotal, config.ParallelNode)
|
||||
}
|
||||
} else {
|
||||
iterator = spec_iterator.NewSerialIterator(specs.Specs())
|
||||
}
|
||||
|
||||
return iterator, specs.HasProgrammaticFocus()
|
||||
}
|
||||
|
||||
func (suite *Suite) CurrentRunningSpecSummary() (*types.SpecSummary, bool) {
|
||||
if !suite.running {
|
||||
return nil, false
|
||||
}
|
||||
return suite.runner.CurrentSpecSummary()
|
||||
}
|
||||
|
||||
func (suite *Suite) SetBeforeSuiteNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration) {
|
||||
if suite.beforeSuiteNode != nil {
|
||||
panic("You may only call BeforeSuite once!")
|
||||
}
|
||||
suite.beforeSuiteNode = leafnodes.NewBeforeSuiteNode(body, codeLocation, timeout, suite.failer)
|
||||
}
|
||||
|
||||
func (suite *Suite) SetAfterSuiteNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration) {
|
||||
if suite.afterSuiteNode != nil {
|
||||
panic("You may only call AfterSuite once!")
|
||||
}
|
||||
suite.afterSuiteNode = leafnodes.NewAfterSuiteNode(body, codeLocation, timeout, suite.failer)
|
||||
}
|
||||
|
||||
func (suite *Suite) SetSynchronizedBeforeSuiteNode(bodyA interface{}, bodyB interface{}, codeLocation types.CodeLocation, timeout time.Duration) {
|
||||
if suite.beforeSuiteNode != nil {
|
||||
panic("You may only call BeforeSuite once!")
|
||||
}
|
||||
suite.beforeSuiteNode = leafnodes.NewSynchronizedBeforeSuiteNode(bodyA, bodyB, codeLocation, timeout, suite.failer)
|
||||
}
|
||||
|
||||
func (suite *Suite) SetSynchronizedAfterSuiteNode(bodyA interface{}, bodyB interface{}, codeLocation types.CodeLocation, timeout time.Duration) {
|
||||
if suite.afterSuiteNode != nil {
|
||||
panic("You may only call AfterSuite once!")
|
||||
}
|
||||
suite.afterSuiteNode = leafnodes.NewSynchronizedAfterSuiteNode(bodyA, bodyB, codeLocation, timeout, suite.failer)
|
||||
}
|
||||
|
||||
func (suite *Suite) PushContainerNode(text string, body func(), flag types.FlagType, codeLocation types.CodeLocation) {
|
||||
/*
|
||||
We defer walking the container nodes (which immediately evaluates the `body` function)
|
||||
until `RunSpecs` is called. We do this by storing off the deferred container nodes. Then, when
|
||||
`RunSpecs` is called we actually go through and add the container nodes to the test structure.
|
||||
|
||||
This allows us to defer calling all the `body` functions until _after_ the top level functions
|
||||
have been walked, _after_ func init()s have been called, and _after_ `go test` has called `flag.Parse()`.
|
||||
|
||||
This allows users to load up configuration information in the `TestX` go test hook just before `RunSpecs`
|
||||
is invoked and solves issues like #693 and makes the lifecycle easier to reason about.
|
||||
|
||||
*/
|
||||
if !suite.expandTopLevelNodes {
|
||||
suite.deferredContainerNodes = append(suite.deferredContainerNodes, deferredContainerNode{text, body, flag, codeLocation})
|
||||
return
|
||||
}
|
||||
|
||||
container := containernode.New(text, flag, codeLocation)
|
||||
suite.currentContainer.PushContainerNode(container)
|
||||
|
||||
previousContainer := suite.currentContainer
|
||||
suite.currentContainer = container
|
||||
suite.containerIndex++
|
||||
|
||||
body()
|
||||
|
||||
suite.containerIndex--
|
||||
suite.currentContainer = previousContainer
|
||||
}
|
||||
|
||||
func (suite *Suite) PushItNode(text string, body interface{}, flag types.FlagType, codeLocation types.CodeLocation, timeout time.Duration) {
|
||||
if suite.running {
|
||||
suite.failer.Fail("You may only call It from within a Describe, Context or When", codeLocation)
|
||||
}
|
||||
suite.currentContainer.PushSubjectNode(leafnodes.NewItNode(text, body, flag, codeLocation, timeout, suite.failer, suite.containerIndex))
|
||||
}
|
||||
|
||||
func (suite *Suite) PushMeasureNode(text string, body interface{}, flag types.FlagType, codeLocation types.CodeLocation, samples int) {
|
||||
if suite.running {
|
||||
suite.failer.Fail("You may only call Measure from within a Describe, Context or When", codeLocation)
|
||||
}
|
||||
suite.currentContainer.PushSubjectNode(leafnodes.NewMeasureNode(text, body, flag, codeLocation, samples, suite.failer, suite.containerIndex))
|
||||
}
|
||||
|
||||
func (suite *Suite) PushBeforeEachNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration) {
|
||||
if suite.running {
|
||||
suite.failer.Fail("You may only call BeforeEach from within a Describe, Context or When", codeLocation)
|
||||
}
|
||||
suite.currentContainer.PushSetupNode(leafnodes.NewBeforeEachNode(body, codeLocation, timeout, suite.failer, suite.containerIndex))
|
||||
}
|
||||
|
||||
func (suite *Suite) PushJustBeforeEachNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration) {
|
||||
if suite.running {
|
||||
suite.failer.Fail("You may only call JustBeforeEach from within a Describe, Context or When", codeLocation)
|
||||
}
|
||||
suite.currentContainer.PushSetupNode(leafnodes.NewJustBeforeEachNode(body, codeLocation, timeout, suite.failer, suite.containerIndex))
|
||||
}
|
||||
|
||||
func (suite *Suite) PushJustAfterEachNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration) {
|
||||
if suite.running {
|
||||
suite.failer.Fail("You may only call JustAfterEach from within a Describe or Context", codeLocation)
|
||||
}
|
||||
suite.currentContainer.PushSetupNode(leafnodes.NewJustAfterEachNode(body, codeLocation, timeout, suite.failer, suite.containerIndex))
|
||||
}
|
||||
|
||||
func (suite *Suite) PushAfterEachNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration) {
|
||||
if suite.running {
|
||||
suite.failer.Fail("You may only call AfterEach from within a Describe, Context or When", codeLocation)
|
||||
}
|
||||
suite.currentContainer.PushSetupNode(leafnodes.NewAfterEachNode(body, codeLocation, timeout, suite.failer, suite.containerIndex))
|
||||
}
|
109
vendor/github.com/onsi/ginkgo/internal/testingtproxy/testing_t_proxy.go
generated
vendored
Normal file
109
vendor/github.com/onsi/ginkgo/internal/testingtproxy/testing_t_proxy.go
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
package testingtproxy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
type failFunc func(message string, callerSkip ...int)
|
||||
type skipFunc func(message string, callerSkip ...int)
|
||||
type failedFunc func() bool
|
||||
type nameFunc func() string
|
||||
|
||||
func New(writer io.Writer, fail failFunc, skip skipFunc, failed failedFunc, name nameFunc, offset int) *ginkgoTestingTProxy {
|
||||
return &ginkgoTestingTProxy{
|
||||
fail: fail,
|
||||
offset: offset,
|
||||
writer: writer,
|
||||
skip: skip,
|
||||
failed: failed,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
type ginkgoTestingTProxy struct {
|
||||
fail failFunc
|
||||
skip skipFunc
|
||||
failed failedFunc
|
||||
name nameFunc
|
||||
offset int
|
||||
writer io.Writer
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) Cleanup(func()) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) Setenv(kev, value string) {
|
||||
fmt.Println("Setenv is a noop for Ginkgo at the moment but will be implemented in V2")
|
||||
// No-op until Cleanup is implemented
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) Error(args ...interface{}) {
|
||||
t.fail(fmt.Sprintln(args...), t.offset)
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) Errorf(format string, args ...interface{}) {
|
||||
t.fail(fmt.Sprintf(format, args...), t.offset)
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) Fail() {
|
||||
t.fail("failed", t.offset)
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) FailNow() {
|
||||
t.fail("failed", t.offset)
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) Failed() bool {
|
||||
return t.failed()
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) Fatal(args ...interface{}) {
|
||||
t.fail(fmt.Sprintln(args...), t.offset)
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) Fatalf(format string, args ...interface{}) {
|
||||
t.fail(fmt.Sprintf(format, args...), t.offset)
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) Helper() {
|
||||
// No-op
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) Log(args ...interface{}) {
|
||||
fmt.Fprintln(t.writer, args...)
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) Logf(format string, args ...interface{}) {
|
||||
t.Log(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) Name() string {
|
||||
return t.name()
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) Parallel() {
|
||||
// No-op
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) Skip(args ...interface{}) {
|
||||
t.skip(fmt.Sprintln(args...), t.offset)
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) SkipNow() {
|
||||
t.skip("skip", t.offset)
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) Skipf(format string, args ...interface{}) {
|
||||
t.skip(fmt.Sprintf(format, args...), t.offset)
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) Skipped() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *ginkgoTestingTProxy) TempDir() string {
|
||||
// No-op
|
||||
return ""
|
||||
}
|
36
vendor/github.com/onsi/ginkgo/internal/writer/fake_writer.go
generated
vendored
Normal file
36
vendor/github.com/onsi/ginkgo/internal/writer/fake_writer.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
package writer
|
||||
|
||||
type FakeGinkgoWriter struct {
|
||||
EventStream []string
|
||||
}
|
||||
|
||||
func NewFake() *FakeGinkgoWriter {
|
||||
return &FakeGinkgoWriter{
|
||||
EventStream: []string{},
|
||||
}
|
||||
}
|
||||
|
||||
func (writer *FakeGinkgoWriter) AddEvent(event string) {
|
||||
writer.EventStream = append(writer.EventStream, event)
|
||||
}
|
||||
|
||||
func (writer *FakeGinkgoWriter) Truncate() {
|
||||
writer.EventStream = append(writer.EventStream, "TRUNCATE")
|
||||
}
|
||||
|
||||
func (writer *FakeGinkgoWriter) DumpOut() {
|
||||
writer.EventStream = append(writer.EventStream, "DUMP")
|
||||
}
|
||||
|
||||
func (writer *FakeGinkgoWriter) DumpOutWithHeader(header string) {
|
||||
writer.EventStream = append(writer.EventStream, "DUMP_WITH_HEADER: "+header)
|
||||
}
|
||||
|
||||
func (writer *FakeGinkgoWriter) Bytes() []byte {
|
||||
writer.EventStream = append(writer.EventStream, "BYTES")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (writer *FakeGinkgoWriter) Write(data []byte) (n int, err error) {
|
||||
return 0, nil
|
||||
}
|
89
vendor/github.com/onsi/ginkgo/internal/writer/writer.go
generated
vendored
Normal file
89
vendor/github.com/onsi/ginkgo/internal/writer/writer.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
package writer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type WriterInterface interface {
|
||||
io.Writer
|
||||
|
||||
Truncate()
|
||||
DumpOut()
|
||||
DumpOutWithHeader(header string)
|
||||
Bytes() []byte
|
||||
}
|
||||
|
||||
type Writer struct {
|
||||
buffer *bytes.Buffer
|
||||
outWriter io.Writer
|
||||
lock *sync.Mutex
|
||||
stream bool
|
||||
redirector io.Writer
|
||||
}
|
||||
|
||||
func New(outWriter io.Writer) *Writer {
|
||||
return &Writer{
|
||||
buffer: &bytes.Buffer{},
|
||||
lock: &sync.Mutex{},
|
||||
outWriter: outWriter,
|
||||
stream: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Writer) AndRedirectTo(writer io.Writer) {
|
||||
w.redirector = writer
|
||||
}
|
||||
|
||||
func (w *Writer) SetStream(stream bool) {
|
||||
w.lock.Lock()
|
||||
defer w.lock.Unlock()
|
||||
w.stream = stream
|
||||
}
|
||||
|
||||
func (w *Writer) Write(b []byte) (n int, err error) {
|
||||
w.lock.Lock()
|
||||
defer w.lock.Unlock()
|
||||
|
||||
n, err = w.buffer.Write(b)
|
||||
if w.redirector != nil {
|
||||
w.redirector.Write(b)
|
||||
}
|
||||
if w.stream {
|
||||
return w.outWriter.Write(b)
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (w *Writer) Truncate() {
|
||||
w.lock.Lock()
|
||||
defer w.lock.Unlock()
|
||||
w.buffer.Reset()
|
||||
}
|
||||
|
||||
func (w *Writer) DumpOut() {
|
||||
w.lock.Lock()
|
||||
defer w.lock.Unlock()
|
||||
if !w.stream {
|
||||
w.buffer.WriteTo(w.outWriter)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Writer) Bytes() []byte {
|
||||
w.lock.Lock()
|
||||
defer w.lock.Unlock()
|
||||
b := w.buffer.Bytes()
|
||||
copied := make([]byte, len(b))
|
||||
copy(copied, b)
|
||||
return copied
|
||||
}
|
||||
|
||||
func (w *Writer) DumpOutWithHeader(header string) {
|
||||
w.lock.Lock()
|
||||
defer w.lock.Unlock()
|
||||
if !w.stream && w.buffer.Len() > 0 {
|
||||
w.outWriter.Write([]byte(header))
|
||||
w.buffer.WriteTo(w.outWriter)
|
||||
}
|
||||
}
|
87
vendor/github.com/onsi/ginkgo/reporters/default_reporter.go
generated
vendored
Normal file
87
vendor/github.com/onsi/ginkgo/reporters/default_reporter.go
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
Ginkgo's Default Reporter
|
||||
|
||||
A number of command line flags are available to tweak Ginkgo's default output.
|
||||
|
||||
These are documented [here](http://onsi.github.io/ginkgo/#running_tests)
|
||||
*/
|
||||
package reporters
|
||||
|
||||
import (
|
||||
"github.com/onsi/ginkgo/config"
|
||||
"github.com/onsi/ginkgo/reporters/stenographer"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
type DefaultReporter struct {
|
||||
config config.DefaultReporterConfigType
|
||||
stenographer stenographer.Stenographer
|
||||
specSummaries []*types.SpecSummary
|
||||
}
|
||||
|
||||
func NewDefaultReporter(config config.DefaultReporterConfigType, stenographer stenographer.Stenographer) *DefaultReporter {
|
||||
return &DefaultReporter{
|
||||
config: config,
|
||||
stenographer: stenographer,
|
||||
}
|
||||
}
|
||||
|
||||
func (reporter *DefaultReporter) SpecSuiteWillBegin(config config.GinkgoConfigType, summary *types.SuiteSummary) {
|
||||
reporter.stenographer.AnnounceSuite(summary.SuiteDescription, config.RandomSeed, config.RandomizeAllSpecs, reporter.config.Succinct)
|
||||
if config.ParallelTotal > 1 {
|
||||
reporter.stenographer.AnnounceParallelRun(config.ParallelNode, config.ParallelTotal, reporter.config.Succinct)
|
||||
} else {
|
||||
reporter.stenographer.AnnounceNumberOfSpecs(summary.NumberOfSpecsThatWillBeRun, summary.NumberOfTotalSpecs, reporter.config.Succinct)
|
||||
}
|
||||
}
|
||||
|
||||
func (reporter *DefaultReporter) BeforeSuiteDidRun(setupSummary *types.SetupSummary) {
|
||||
if setupSummary.State != types.SpecStatePassed {
|
||||
reporter.stenographer.AnnounceBeforeSuiteFailure(setupSummary, reporter.config.Succinct, reporter.config.FullTrace)
|
||||
}
|
||||
}
|
||||
|
||||
func (reporter *DefaultReporter) AfterSuiteDidRun(setupSummary *types.SetupSummary) {
|
||||
if setupSummary.State != types.SpecStatePassed {
|
||||
reporter.stenographer.AnnounceAfterSuiteFailure(setupSummary, reporter.config.Succinct, reporter.config.FullTrace)
|
||||
}
|
||||
}
|
||||
|
||||
func (reporter *DefaultReporter) SpecWillRun(specSummary *types.SpecSummary) {
|
||||
if reporter.config.Verbose && !reporter.config.Succinct && specSummary.State != types.SpecStatePending && specSummary.State != types.SpecStateSkipped {
|
||||
reporter.stenographer.AnnounceSpecWillRun(specSummary)
|
||||
}
|
||||
}
|
||||
|
||||
func (reporter *DefaultReporter) SpecDidComplete(specSummary *types.SpecSummary) {
|
||||
switch specSummary.State {
|
||||
case types.SpecStatePassed:
|
||||
if specSummary.IsMeasurement {
|
||||
reporter.stenographer.AnnounceSuccessfulMeasurement(specSummary, reporter.config.Succinct)
|
||||
} else if specSummary.RunTime.Seconds() >= reporter.config.SlowSpecThreshold {
|
||||
reporter.stenographer.AnnounceSuccessfulSlowSpec(specSummary, reporter.config.Succinct)
|
||||
} else {
|
||||
reporter.stenographer.AnnounceSuccessfulSpec(specSummary)
|
||||
if reporter.config.ReportPassed {
|
||||
reporter.stenographer.AnnounceCapturedOutput(specSummary.CapturedOutput)
|
||||
}
|
||||
}
|
||||
case types.SpecStatePending:
|
||||
reporter.stenographer.AnnouncePendingSpec(specSummary, reporter.config.NoisyPendings && !reporter.config.Succinct)
|
||||
case types.SpecStateSkipped:
|
||||
reporter.stenographer.AnnounceSkippedSpec(specSummary, reporter.config.Succinct || !reporter.config.NoisySkippings, reporter.config.FullTrace)
|
||||
case types.SpecStateTimedOut:
|
||||
reporter.stenographer.AnnounceSpecTimedOut(specSummary, reporter.config.Succinct, reporter.config.FullTrace)
|
||||
case types.SpecStatePanicked:
|
||||
reporter.stenographer.AnnounceSpecPanicked(specSummary, reporter.config.Succinct, reporter.config.FullTrace)
|
||||
case types.SpecStateFailed:
|
||||
reporter.stenographer.AnnounceSpecFailed(specSummary, reporter.config.Succinct, reporter.config.FullTrace)
|
||||
}
|
||||
|
||||
reporter.specSummaries = append(reporter.specSummaries, specSummary)
|
||||
}
|
||||
|
||||
func (reporter *DefaultReporter) SpecSuiteDidEnd(summary *types.SuiteSummary) {
|
||||
reporter.stenographer.SummarizeFailures(reporter.specSummaries)
|
||||
reporter.stenographer.AnnounceSpecRunCompletion(summary, reporter.config.Succinct)
|
||||
}
|
59
vendor/github.com/onsi/ginkgo/reporters/fake_reporter.go
generated
vendored
Normal file
59
vendor/github.com/onsi/ginkgo/reporters/fake_reporter.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
package reporters
|
||||
|
||||
import (
|
||||
"github.com/onsi/ginkgo/config"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
//FakeReporter is useful for testing purposes
|
||||
type FakeReporter struct {
|
||||
Config config.GinkgoConfigType
|
||||
|
||||
BeginSummary *types.SuiteSummary
|
||||
BeforeSuiteSummary *types.SetupSummary
|
||||
SpecWillRunSummaries []*types.SpecSummary
|
||||
SpecSummaries []*types.SpecSummary
|
||||
AfterSuiteSummary *types.SetupSummary
|
||||
EndSummary *types.SuiteSummary
|
||||
|
||||
SpecWillRunStub func(specSummary *types.SpecSummary)
|
||||
SpecDidCompleteStub func(specSummary *types.SpecSummary)
|
||||
}
|
||||
|
||||
func NewFakeReporter() *FakeReporter {
|
||||
return &FakeReporter{
|
||||
SpecWillRunSummaries: make([]*types.SpecSummary, 0),
|
||||
SpecSummaries: make([]*types.SpecSummary, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func (fakeR *FakeReporter) SpecSuiteWillBegin(config config.GinkgoConfigType, summary *types.SuiteSummary) {
|
||||
fakeR.Config = config
|
||||
fakeR.BeginSummary = summary
|
||||
}
|
||||
|
||||
func (fakeR *FakeReporter) BeforeSuiteDidRun(setupSummary *types.SetupSummary) {
|
||||
fakeR.BeforeSuiteSummary = setupSummary
|
||||
}
|
||||
|
||||
func (fakeR *FakeReporter) SpecWillRun(specSummary *types.SpecSummary) {
|
||||
if fakeR.SpecWillRunStub != nil {
|
||||
fakeR.SpecWillRunStub(specSummary)
|
||||
}
|
||||
fakeR.SpecWillRunSummaries = append(fakeR.SpecWillRunSummaries, specSummary)
|
||||
}
|
||||
|
||||
func (fakeR *FakeReporter) SpecDidComplete(specSummary *types.SpecSummary) {
|
||||
if fakeR.SpecDidCompleteStub != nil {
|
||||
fakeR.SpecDidCompleteStub(specSummary)
|
||||
}
|
||||
fakeR.SpecSummaries = append(fakeR.SpecSummaries, specSummary)
|
||||
}
|
||||
|
||||
func (fakeR *FakeReporter) AfterSuiteDidRun(setupSummary *types.SetupSummary) {
|
||||
fakeR.AfterSuiteSummary = setupSummary
|
||||
}
|
||||
|
||||
func (fakeR *FakeReporter) SpecSuiteDidEnd(summary *types.SuiteSummary) {
|
||||
fakeR.EndSummary = summary
|
||||
}
|
178
vendor/github.com/onsi/ginkgo/reporters/junit_reporter.go
generated
vendored
Normal file
178
vendor/github.com/onsi/ginkgo/reporters/junit_reporter.go
generated
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
|
||||
JUnit XML Reporter for Ginkgo
|
||||
|
||||
For usage instructions: http://onsi.github.io/ginkgo/#generating_junit_xml_output
|
||||
|
||||
*/
|
||||
|
||||
package reporters
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/onsi/ginkgo/config"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
type JUnitTestSuite struct {
|
||||
XMLName xml.Name `xml:"testsuite"`
|
||||
TestCases []JUnitTestCase `xml:"testcase"`
|
||||
Name string `xml:"name,attr"`
|
||||
Tests int `xml:"tests,attr"`
|
||||
Failures int `xml:"failures,attr"`
|
||||
Errors int `xml:"errors,attr"`
|
||||
Time float64 `xml:"time,attr"`
|
||||
}
|
||||
|
||||
type JUnitTestCase struct {
|
||||
Name string `xml:"name,attr"`
|
||||
ClassName string `xml:"classname,attr"`
|
||||
FailureMessage *JUnitFailureMessage `xml:"failure,omitempty"`
|
||||
Skipped *JUnitSkipped `xml:"skipped,omitempty"`
|
||||
Time float64 `xml:"time,attr"`
|
||||
SystemOut string `xml:"system-out,omitempty"`
|
||||
}
|
||||
|
||||
type JUnitFailureMessage struct {
|
||||
Type string `xml:"type,attr"`
|
||||
Message string `xml:",chardata"`
|
||||
}
|
||||
|
||||
type JUnitSkipped struct {
|
||||
Message string `xml:",chardata"`
|
||||
}
|
||||
|
||||
type JUnitReporter struct {
|
||||
suite JUnitTestSuite
|
||||
filename string
|
||||
testSuiteName string
|
||||
ReporterConfig config.DefaultReporterConfigType
|
||||
}
|
||||
|
||||
//NewJUnitReporter creates a new JUnit XML reporter. The XML will be stored in the passed in filename.
|
||||
func NewJUnitReporter(filename string) *JUnitReporter {
|
||||
return &JUnitReporter{
|
||||
filename: filename,
|
||||
}
|
||||
}
|
||||
|
||||
func (reporter *JUnitReporter) SpecSuiteWillBegin(ginkgoConfig config.GinkgoConfigType, summary *types.SuiteSummary) {
|
||||
reporter.suite = JUnitTestSuite{
|
||||
Name: summary.SuiteDescription,
|
||||
TestCases: []JUnitTestCase{},
|
||||
}
|
||||
reporter.testSuiteName = summary.SuiteDescription
|
||||
reporter.ReporterConfig = config.DefaultReporterConfig
|
||||
}
|
||||
|
||||
func (reporter *JUnitReporter) SpecWillRun(specSummary *types.SpecSummary) {
|
||||
}
|
||||
|
||||
func (reporter *JUnitReporter) BeforeSuiteDidRun(setupSummary *types.SetupSummary) {
|
||||
reporter.handleSetupSummary("BeforeSuite", setupSummary)
|
||||
}
|
||||
|
||||
func (reporter *JUnitReporter) AfterSuiteDidRun(setupSummary *types.SetupSummary) {
|
||||
reporter.handleSetupSummary("AfterSuite", setupSummary)
|
||||
}
|
||||
|
||||
func failureMessage(failure types.SpecFailure) string {
|
||||
return fmt.Sprintf("%s\n%s\n%s", failure.ComponentCodeLocation.String(), failure.Message, failure.Location.String())
|
||||
}
|
||||
|
||||
func (reporter *JUnitReporter) handleSetupSummary(name string, setupSummary *types.SetupSummary) {
|
||||
if setupSummary.State != types.SpecStatePassed {
|
||||
testCase := JUnitTestCase{
|
||||
Name: name,
|
||||
ClassName: reporter.testSuiteName,
|
||||
}
|
||||
|
||||
testCase.FailureMessage = &JUnitFailureMessage{
|
||||
Type: reporter.failureTypeForState(setupSummary.State),
|
||||
Message: failureMessage(setupSummary.Failure),
|
||||
}
|
||||
testCase.SystemOut = setupSummary.CapturedOutput
|
||||
testCase.Time = setupSummary.RunTime.Seconds()
|
||||
reporter.suite.TestCases = append(reporter.suite.TestCases, testCase)
|
||||
}
|
||||
}
|
||||
|
||||
func (reporter *JUnitReporter) SpecDidComplete(specSummary *types.SpecSummary) {
|
||||
testCase := JUnitTestCase{
|
||||
Name: strings.Join(specSummary.ComponentTexts[1:], " "),
|
||||
ClassName: reporter.testSuiteName,
|
||||
}
|
||||
if reporter.ReporterConfig.ReportPassed && specSummary.State == types.SpecStatePassed {
|
||||
testCase.SystemOut = specSummary.CapturedOutput
|
||||
}
|
||||
if specSummary.State == types.SpecStateFailed || specSummary.State == types.SpecStateTimedOut || specSummary.State == types.SpecStatePanicked {
|
||||
testCase.FailureMessage = &JUnitFailureMessage{
|
||||
Type: reporter.failureTypeForState(specSummary.State),
|
||||
Message: failureMessage(specSummary.Failure),
|
||||
}
|
||||
if specSummary.State == types.SpecStatePanicked {
|
||||
testCase.FailureMessage.Message += fmt.Sprintf("\n\nPanic: %s\n\nFull stack:\n%s",
|
||||
specSummary.Failure.ForwardedPanic,
|
||||
specSummary.Failure.Location.FullStackTrace)
|
||||
}
|
||||
testCase.SystemOut = specSummary.CapturedOutput
|
||||
}
|
||||
if specSummary.State == types.SpecStateSkipped || specSummary.State == types.SpecStatePending {
|
||||
testCase.Skipped = &JUnitSkipped{}
|
||||
if specSummary.Failure.Message != "" {
|
||||
testCase.Skipped.Message = failureMessage(specSummary.Failure)
|
||||
}
|
||||
}
|
||||
testCase.Time = specSummary.RunTime.Seconds()
|
||||
reporter.suite.TestCases = append(reporter.suite.TestCases, testCase)
|
||||
}
|
||||
|
||||
func (reporter *JUnitReporter) SpecSuiteDidEnd(summary *types.SuiteSummary) {
|
||||
reporter.suite.Tests = summary.NumberOfSpecsThatWillBeRun
|
||||
reporter.suite.Time = math.Trunc(summary.RunTime.Seconds()*1000) / 1000
|
||||
reporter.suite.Failures = summary.NumberOfFailedSpecs
|
||||
reporter.suite.Errors = 0
|
||||
if reporter.ReporterConfig.ReportFile != "" {
|
||||
reporter.filename = reporter.ReporterConfig.ReportFile
|
||||
fmt.Printf("\nJUnit path was configured: %s\n", reporter.filename)
|
||||
}
|
||||
filePath, _ := filepath.Abs(reporter.filename)
|
||||
dirPath := filepath.Dir(filePath)
|
||||
err := os.MkdirAll(dirPath, os.ModePerm)
|
||||
if err != nil {
|
||||
fmt.Printf("\nFailed to create JUnit directory: %s\n\t%s", filePath, err.Error())
|
||||
}
|
||||
file, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to create JUnit report file: %s\n\t%s", filePath, err.Error())
|
||||
}
|
||||
defer file.Close()
|
||||
file.WriteString(xml.Header)
|
||||
encoder := xml.NewEncoder(file)
|
||||
encoder.Indent(" ", " ")
|
||||
err = encoder.Encode(reporter.suite)
|
||||
if err == nil {
|
||||
fmt.Fprintf(os.Stdout, "\nJUnit report was created: %s\n", filePath)
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr,"\nFailed to generate JUnit report data:\n\t%s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (reporter *JUnitReporter) failureTypeForState(state types.SpecState) string {
|
||||
switch state {
|
||||
case types.SpecStateFailed:
|
||||
return "Failure"
|
||||
case types.SpecStateTimedOut:
|
||||
return "Timeout"
|
||||
case types.SpecStatePanicked:
|
||||
return "Panic"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
15
vendor/github.com/onsi/ginkgo/reporters/reporter.go
generated
vendored
Normal file
15
vendor/github.com/onsi/ginkgo/reporters/reporter.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
package reporters
|
||||
|
||||
import (
|
||||
"github.com/onsi/ginkgo/config"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
type Reporter interface {
|
||||
SpecSuiteWillBegin(config config.GinkgoConfigType, summary *types.SuiteSummary)
|
||||
BeforeSuiteDidRun(setupSummary *types.SetupSummary)
|
||||
SpecWillRun(specSummary *types.SpecSummary)
|
||||
SpecDidComplete(specSummary *types.SpecSummary)
|
||||
AfterSuiteDidRun(setupSummary *types.SetupSummary)
|
||||
SpecSuiteDidEnd(summary *types.SuiteSummary)
|
||||
}
|
64
vendor/github.com/onsi/ginkgo/reporters/stenographer/console_logging.go
generated
vendored
Normal file
64
vendor/github.com/onsi/ginkgo/reporters/stenographer/console_logging.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
package stenographer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (s *consoleStenographer) colorize(colorCode string, format string, args ...interface{}) string {
|
||||
var out string
|
||||
|
||||
if len(args) > 0 {
|
||||
out = fmt.Sprintf(format, args...)
|
||||
} else {
|
||||
out = format
|
||||
}
|
||||
|
||||
if s.color {
|
||||
return fmt.Sprintf("%s%s%s", colorCode, out, defaultStyle)
|
||||
} else {
|
||||
return out
|
||||
}
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) printBanner(text string, bannerCharacter string) {
|
||||
fmt.Fprintln(s.w, text)
|
||||
fmt.Fprintln(s.w, strings.Repeat(bannerCharacter, len(text)))
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) printNewLine() {
|
||||
fmt.Fprintln(s.w, "")
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) printDelimiter() {
|
||||
fmt.Fprintln(s.w, s.colorize(grayColor, "%s", strings.Repeat("-", 30)))
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) print(indentation int, format string, args ...interface{}) {
|
||||
fmt.Fprint(s.w, s.indent(indentation, format, args...))
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) println(indentation int, format string, args ...interface{}) {
|
||||
fmt.Fprintln(s.w, s.indent(indentation, format, args...))
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) indent(indentation int, format string, args ...interface{}) string {
|
||||
var text string
|
||||
|
||||
if len(args) > 0 {
|
||||
text = fmt.Sprintf(format, args...)
|
||||
} else {
|
||||
text = format
|
||||
}
|
||||
|
||||
stringArray := strings.Split(text, "\n")
|
||||
padding := ""
|
||||
if indentation >= 0 {
|
||||
padding = strings.Repeat(" ", indentation)
|
||||
}
|
||||
for i, s := range stringArray {
|
||||
stringArray[i] = fmt.Sprintf("%s%s", padding, s)
|
||||
}
|
||||
|
||||
return strings.Join(stringArray, "\n")
|
||||
}
|
142
vendor/github.com/onsi/ginkgo/reporters/stenographer/fake_stenographer.go
generated
vendored
Normal file
142
vendor/github.com/onsi/ginkgo/reporters/stenographer/fake_stenographer.go
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
package stenographer
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
func NewFakeStenographerCall(method string, args ...interface{}) FakeStenographerCall {
|
||||
return FakeStenographerCall{
|
||||
Method: method,
|
||||
Args: args,
|
||||
}
|
||||
}
|
||||
|
||||
type FakeStenographer struct {
|
||||
calls []FakeStenographerCall
|
||||
lock *sync.Mutex
|
||||
}
|
||||
|
||||
type FakeStenographerCall struct {
|
||||
Method string
|
||||
Args []interface{}
|
||||
}
|
||||
|
||||
func NewFakeStenographer() *FakeStenographer {
|
||||
stenographer := &FakeStenographer{
|
||||
lock: &sync.Mutex{},
|
||||
}
|
||||
stenographer.Reset()
|
||||
return stenographer
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) Calls() []FakeStenographerCall {
|
||||
stenographer.lock.Lock()
|
||||
defer stenographer.lock.Unlock()
|
||||
|
||||
return stenographer.calls
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) Reset() {
|
||||
stenographer.lock.Lock()
|
||||
defer stenographer.lock.Unlock()
|
||||
|
||||
stenographer.calls = make([]FakeStenographerCall, 0)
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) CallsTo(method string) []FakeStenographerCall {
|
||||
stenographer.lock.Lock()
|
||||
defer stenographer.lock.Unlock()
|
||||
|
||||
results := make([]FakeStenographerCall, 0)
|
||||
for _, call := range stenographer.calls {
|
||||
if call.Method == method {
|
||||
results = append(results, call)
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) registerCall(method string, args ...interface{}) {
|
||||
stenographer.lock.Lock()
|
||||
defer stenographer.lock.Unlock()
|
||||
|
||||
stenographer.calls = append(stenographer.calls, NewFakeStenographerCall(method, args...))
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) AnnounceSuite(description string, randomSeed int64, randomizingAll bool, succinct bool) {
|
||||
stenographer.registerCall("AnnounceSuite", description, randomSeed, randomizingAll, succinct)
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) AnnounceAggregatedParallelRun(nodes int, succinct bool) {
|
||||
stenographer.registerCall("AnnounceAggregatedParallelRun", nodes, succinct)
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) AnnounceParallelRun(node int, nodes int, succinct bool) {
|
||||
stenographer.registerCall("AnnounceParallelRun", node, nodes, succinct)
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) AnnounceNumberOfSpecs(specsToRun int, total int, succinct bool) {
|
||||
stenographer.registerCall("AnnounceNumberOfSpecs", specsToRun, total, succinct)
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) AnnounceTotalNumberOfSpecs(total int, succinct bool) {
|
||||
stenographer.registerCall("AnnounceTotalNumberOfSpecs", total, succinct)
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) AnnounceSpecRunCompletion(summary *types.SuiteSummary, succinct bool) {
|
||||
stenographer.registerCall("AnnounceSpecRunCompletion", summary, succinct)
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) AnnounceSpecWillRun(spec *types.SpecSummary) {
|
||||
stenographer.registerCall("AnnounceSpecWillRun", spec)
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) AnnounceBeforeSuiteFailure(summary *types.SetupSummary, succinct bool, fullTrace bool) {
|
||||
stenographer.registerCall("AnnounceBeforeSuiteFailure", summary, succinct, fullTrace)
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) AnnounceAfterSuiteFailure(summary *types.SetupSummary, succinct bool, fullTrace bool) {
|
||||
stenographer.registerCall("AnnounceAfterSuiteFailure", summary, succinct, fullTrace)
|
||||
}
|
||||
func (stenographer *FakeStenographer) AnnounceCapturedOutput(output string) {
|
||||
stenographer.registerCall("AnnounceCapturedOutput", output)
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) AnnounceSuccessfulSpec(spec *types.SpecSummary) {
|
||||
stenographer.registerCall("AnnounceSuccessfulSpec", spec)
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) AnnounceSuccessfulSlowSpec(spec *types.SpecSummary, succinct bool) {
|
||||
stenographer.registerCall("AnnounceSuccessfulSlowSpec", spec, succinct)
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) AnnounceSuccessfulMeasurement(spec *types.SpecSummary, succinct bool) {
|
||||
stenographer.registerCall("AnnounceSuccessfulMeasurement", spec, succinct)
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) AnnouncePendingSpec(spec *types.SpecSummary, noisy bool) {
|
||||
stenographer.registerCall("AnnouncePendingSpec", spec, noisy)
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) AnnounceSkippedSpec(spec *types.SpecSummary, succinct bool, fullTrace bool) {
|
||||
stenographer.registerCall("AnnounceSkippedSpec", spec, succinct, fullTrace)
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) AnnounceSpecTimedOut(spec *types.SpecSummary, succinct bool, fullTrace bool) {
|
||||
stenographer.registerCall("AnnounceSpecTimedOut", spec, succinct, fullTrace)
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) AnnounceSpecPanicked(spec *types.SpecSummary, succinct bool, fullTrace bool) {
|
||||
stenographer.registerCall("AnnounceSpecPanicked", spec, succinct, fullTrace)
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) AnnounceSpecFailed(spec *types.SpecSummary, succinct bool, fullTrace bool) {
|
||||
stenographer.registerCall("AnnounceSpecFailed", spec, succinct, fullTrace)
|
||||
}
|
||||
|
||||
func (stenographer *FakeStenographer) SummarizeFailures(summaries []*types.SpecSummary) {
|
||||
stenographer.registerCall("SummarizeFailures", summaries)
|
||||
}
|
572
vendor/github.com/onsi/ginkgo/reporters/stenographer/stenographer.go
generated
vendored
Normal file
572
vendor/github.com/onsi/ginkgo/reporters/stenographer/stenographer.go
generated
vendored
Normal file
@@ -0,0 +1,572 @@
|
||||
/*
|
||||
The stenographer is used by Ginkgo's reporters to generate output.
|
||||
|
||||
Move along, nothing to see here.
|
||||
*/
|
||||
|
||||
package stenographer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
const defaultStyle = "\x1b[0m"
|
||||
const boldStyle = "\x1b[1m"
|
||||
const redColor = "\x1b[91m"
|
||||
const greenColor = "\x1b[32m"
|
||||
const yellowColor = "\x1b[33m"
|
||||
const cyanColor = "\x1b[36m"
|
||||
const grayColor = "\x1b[90m"
|
||||
const lightGrayColor = "\x1b[37m"
|
||||
|
||||
type cursorStateType int
|
||||
|
||||
const (
|
||||
cursorStateTop cursorStateType = iota
|
||||
cursorStateStreaming
|
||||
cursorStateMidBlock
|
||||
cursorStateEndBlock
|
||||
)
|
||||
|
||||
type Stenographer interface {
|
||||
AnnounceSuite(description string, randomSeed int64, randomizingAll bool, succinct bool)
|
||||
AnnounceAggregatedParallelRun(nodes int, succinct bool)
|
||||
AnnounceParallelRun(node int, nodes int, succinct bool)
|
||||
AnnounceTotalNumberOfSpecs(total int, succinct bool)
|
||||
AnnounceNumberOfSpecs(specsToRun int, total int, succinct bool)
|
||||
AnnounceSpecRunCompletion(summary *types.SuiteSummary, succinct bool)
|
||||
|
||||
AnnounceSpecWillRun(spec *types.SpecSummary)
|
||||
AnnounceBeforeSuiteFailure(summary *types.SetupSummary, succinct bool, fullTrace bool)
|
||||
AnnounceAfterSuiteFailure(summary *types.SetupSummary, succinct bool, fullTrace bool)
|
||||
|
||||
AnnounceCapturedOutput(output string)
|
||||
|
||||
AnnounceSuccessfulSpec(spec *types.SpecSummary)
|
||||
AnnounceSuccessfulSlowSpec(spec *types.SpecSummary, succinct bool)
|
||||
AnnounceSuccessfulMeasurement(spec *types.SpecSummary, succinct bool)
|
||||
|
||||
AnnouncePendingSpec(spec *types.SpecSummary, noisy bool)
|
||||
AnnounceSkippedSpec(spec *types.SpecSummary, succinct bool, fullTrace bool)
|
||||
|
||||
AnnounceSpecTimedOut(spec *types.SpecSummary, succinct bool, fullTrace bool)
|
||||
AnnounceSpecPanicked(spec *types.SpecSummary, succinct bool, fullTrace bool)
|
||||
AnnounceSpecFailed(spec *types.SpecSummary, succinct bool, fullTrace bool)
|
||||
|
||||
SummarizeFailures(summaries []*types.SpecSummary)
|
||||
}
|
||||
|
||||
func New(color bool, enableFlakes bool, writer io.Writer) Stenographer {
|
||||
denoter := "•"
|
||||
if runtime.GOOS == "windows" {
|
||||
denoter = "+"
|
||||
}
|
||||
return &consoleStenographer{
|
||||
color: color,
|
||||
denoter: denoter,
|
||||
cursorState: cursorStateTop,
|
||||
enableFlakes: enableFlakes,
|
||||
w: writer,
|
||||
}
|
||||
}
|
||||
|
||||
type consoleStenographer struct {
|
||||
color bool
|
||||
denoter string
|
||||
cursorState cursorStateType
|
||||
enableFlakes bool
|
||||
w io.Writer
|
||||
}
|
||||
|
||||
var alternatingColors = []string{defaultStyle, grayColor}
|
||||
|
||||
func (s *consoleStenographer) AnnounceSuite(description string, randomSeed int64, randomizingAll bool, succinct bool) {
|
||||
if succinct {
|
||||
s.print(0, "[%d] %s ", randomSeed, s.colorize(boldStyle, description))
|
||||
return
|
||||
}
|
||||
s.printBanner(fmt.Sprintf("Running Suite: %s", description), "=")
|
||||
s.print(0, "Random Seed: %s", s.colorize(boldStyle, "%d", randomSeed))
|
||||
if randomizingAll {
|
||||
s.print(0, " - Will randomize all specs")
|
||||
}
|
||||
s.printNewLine()
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) AnnounceParallelRun(node int, nodes int, succinct bool) {
|
||||
if succinct {
|
||||
s.print(0, "- node #%d ", node)
|
||||
return
|
||||
}
|
||||
s.println(0,
|
||||
"Parallel test node %s/%s.",
|
||||
s.colorize(boldStyle, "%d", node),
|
||||
s.colorize(boldStyle, "%d", nodes),
|
||||
)
|
||||
s.printNewLine()
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) AnnounceAggregatedParallelRun(nodes int, succinct bool) {
|
||||
if succinct {
|
||||
s.print(0, "- %d nodes ", nodes)
|
||||
return
|
||||
}
|
||||
s.println(0,
|
||||
"Running in parallel across %s nodes",
|
||||
s.colorize(boldStyle, "%d", nodes),
|
||||
)
|
||||
s.printNewLine()
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) AnnounceNumberOfSpecs(specsToRun int, total int, succinct bool) {
|
||||
if succinct {
|
||||
s.print(0, "- %d/%d specs ", specsToRun, total)
|
||||
s.stream()
|
||||
return
|
||||
}
|
||||
s.println(0,
|
||||
"Will run %s of %s specs",
|
||||
s.colorize(boldStyle, "%d", specsToRun),
|
||||
s.colorize(boldStyle, "%d", total),
|
||||
)
|
||||
|
||||
s.printNewLine()
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) AnnounceTotalNumberOfSpecs(total int, succinct bool) {
|
||||
if succinct {
|
||||
s.print(0, "- %d specs ", total)
|
||||
s.stream()
|
||||
return
|
||||
}
|
||||
s.println(0,
|
||||
"Will run %s specs",
|
||||
s.colorize(boldStyle, "%d", total),
|
||||
)
|
||||
|
||||
s.printNewLine()
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) AnnounceSpecRunCompletion(summary *types.SuiteSummary, succinct bool) {
|
||||
if succinct && summary.SuiteSucceeded {
|
||||
s.print(0, " %s %s ", s.colorize(greenColor, "SUCCESS!"), summary.RunTime)
|
||||
return
|
||||
}
|
||||
s.printNewLine()
|
||||
color := greenColor
|
||||
if !summary.SuiteSucceeded {
|
||||
color = redColor
|
||||
}
|
||||
s.println(0, s.colorize(boldStyle+color, "Ran %d of %d Specs in %.3f seconds", summary.NumberOfSpecsThatWillBeRun, summary.NumberOfTotalSpecs, summary.RunTime.Seconds()))
|
||||
|
||||
status := ""
|
||||
if summary.SuiteSucceeded {
|
||||
status = s.colorize(boldStyle+greenColor, "SUCCESS!")
|
||||
} else {
|
||||
status = s.colorize(boldStyle+redColor, "FAIL!")
|
||||
}
|
||||
|
||||
flakes := ""
|
||||
if s.enableFlakes {
|
||||
flakes = " | " + s.colorize(yellowColor+boldStyle, "%d Flaked", summary.NumberOfFlakedSpecs)
|
||||
}
|
||||
|
||||
s.print(0,
|
||||
"%s -- %s | %s | %s | %s\n",
|
||||
status,
|
||||
s.colorize(greenColor+boldStyle, "%d Passed", summary.NumberOfPassedSpecs),
|
||||
s.colorize(redColor+boldStyle, "%d Failed", summary.NumberOfFailedSpecs)+flakes,
|
||||
s.colorize(yellowColor+boldStyle, "%d Pending", summary.NumberOfPendingSpecs),
|
||||
s.colorize(cyanColor+boldStyle, "%d Skipped", summary.NumberOfSkippedSpecs),
|
||||
)
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) AnnounceSpecWillRun(spec *types.SpecSummary) {
|
||||
s.startBlock()
|
||||
for i, text := range spec.ComponentTexts[1 : len(spec.ComponentTexts)-1] {
|
||||
s.print(0, s.colorize(alternatingColors[i%2], text)+" ")
|
||||
}
|
||||
|
||||
indentation := 0
|
||||
if len(spec.ComponentTexts) > 2 {
|
||||
indentation = 1
|
||||
s.printNewLine()
|
||||
}
|
||||
index := len(spec.ComponentTexts) - 1
|
||||
s.print(indentation, s.colorize(boldStyle, spec.ComponentTexts[index]))
|
||||
s.printNewLine()
|
||||
s.print(indentation, s.colorize(lightGrayColor, spec.ComponentCodeLocations[index].String()))
|
||||
s.printNewLine()
|
||||
s.midBlock()
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) AnnounceBeforeSuiteFailure(summary *types.SetupSummary, succinct bool, fullTrace bool) {
|
||||
s.announceSetupFailure("BeforeSuite", summary, succinct, fullTrace)
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) AnnounceAfterSuiteFailure(summary *types.SetupSummary, succinct bool, fullTrace bool) {
|
||||
s.announceSetupFailure("AfterSuite", summary, succinct, fullTrace)
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) announceSetupFailure(name string, summary *types.SetupSummary, succinct bool, fullTrace bool) {
|
||||
s.startBlock()
|
||||
var message string
|
||||
switch summary.State {
|
||||
case types.SpecStateFailed:
|
||||
message = "Failure"
|
||||
case types.SpecStatePanicked:
|
||||
message = "Panic"
|
||||
case types.SpecStateTimedOut:
|
||||
message = "Timeout"
|
||||
}
|
||||
|
||||
s.println(0, s.colorize(redColor+boldStyle, "%s [%.3f seconds]", message, summary.RunTime.Seconds()))
|
||||
|
||||
indentation := s.printCodeLocationBlock([]string{name}, []types.CodeLocation{summary.CodeLocation}, summary.ComponentType, 0, summary.State, true)
|
||||
|
||||
s.printNewLine()
|
||||
s.printFailure(indentation, summary.State, summary.Failure, fullTrace)
|
||||
|
||||
s.endBlock()
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) AnnounceCapturedOutput(output string) {
|
||||
if output == "" {
|
||||
return
|
||||
}
|
||||
|
||||
s.startBlock()
|
||||
s.println(0, output)
|
||||
s.midBlock()
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) AnnounceSuccessfulSpec(spec *types.SpecSummary) {
|
||||
s.print(0, s.colorize(greenColor, s.denoter))
|
||||
s.stream()
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) AnnounceSuccessfulSlowSpec(spec *types.SpecSummary, succinct bool) {
|
||||
s.printBlockWithMessage(
|
||||
s.colorize(greenColor, "%s [SLOW TEST:%.3f seconds]", s.denoter, spec.RunTime.Seconds()),
|
||||
"",
|
||||
spec,
|
||||
succinct,
|
||||
)
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) AnnounceSuccessfulMeasurement(spec *types.SpecSummary, succinct bool) {
|
||||
s.printBlockWithMessage(
|
||||
s.colorize(greenColor, "%s [MEASUREMENT]", s.denoter),
|
||||
s.measurementReport(spec, succinct),
|
||||
spec,
|
||||
succinct,
|
||||
)
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) AnnouncePendingSpec(spec *types.SpecSummary, noisy bool) {
|
||||
if noisy {
|
||||
s.printBlockWithMessage(
|
||||
s.colorize(yellowColor, "P [PENDING]"),
|
||||
"",
|
||||
spec,
|
||||
false,
|
||||
)
|
||||
} else {
|
||||
s.print(0, s.colorize(yellowColor, "P"))
|
||||
s.stream()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) AnnounceSkippedSpec(spec *types.SpecSummary, succinct bool, fullTrace bool) {
|
||||
// Skips at runtime will have a non-empty spec.Failure. All others should be succinct.
|
||||
if succinct || spec.Failure == (types.SpecFailure{}) {
|
||||
s.print(0, s.colorize(cyanColor, "S"))
|
||||
s.stream()
|
||||
} else {
|
||||
s.startBlock()
|
||||
s.println(0, s.colorize(cyanColor+boldStyle, "S [SKIPPING]%s [%.3f seconds]", s.failureContext(spec.Failure.ComponentType), spec.RunTime.Seconds()))
|
||||
|
||||
indentation := s.printCodeLocationBlock(spec.ComponentTexts, spec.ComponentCodeLocations, spec.Failure.ComponentType, spec.Failure.ComponentIndex, spec.State, succinct)
|
||||
|
||||
s.printNewLine()
|
||||
s.printSkip(indentation, spec.Failure)
|
||||
s.endBlock()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) AnnounceSpecTimedOut(spec *types.SpecSummary, succinct bool, fullTrace bool) {
|
||||
s.printSpecFailure(fmt.Sprintf("%s... Timeout", s.denoter), spec, succinct, fullTrace)
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) AnnounceSpecPanicked(spec *types.SpecSummary, succinct bool, fullTrace bool) {
|
||||
s.printSpecFailure(fmt.Sprintf("%s! Panic", s.denoter), spec, succinct, fullTrace)
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) AnnounceSpecFailed(spec *types.SpecSummary, succinct bool, fullTrace bool) {
|
||||
s.printSpecFailure(fmt.Sprintf("%s Failure", s.denoter), spec, succinct, fullTrace)
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) SummarizeFailures(summaries []*types.SpecSummary) {
|
||||
failingSpecs := []*types.SpecSummary{}
|
||||
|
||||
for _, summary := range summaries {
|
||||
if summary.HasFailureState() {
|
||||
failingSpecs = append(failingSpecs, summary)
|
||||
}
|
||||
}
|
||||
|
||||
if len(failingSpecs) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
s.printNewLine()
|
||||
s.printNewLine()
|
||||
plural := "s"
|
||||
if len(failingSpecs) == 1 {
|
||||
plural = ""
|
||||
}
|
||||
s.println(0, s.colorize(redColor+boldStyle, "Summarizing %d Failure%s:", len(failingSpecs), plural))
|
||||
for _, summary := range failingSpecs {
|
||||
s.printNewLine()
|
||||
if summary.HasFailureState() {
|
||||
if summary.TimedOut() {
|
||||
s.print(0, s.colorize(redColor+boldStyle, "[Timeout...] "))
|
||||
} else if summary.Panicked() {
|
||||
s.print(0, s.colorize(redColor+boldStyle, "[Panic!] "))
|
||||
} else if summary.Failed() {
|
||||
s.print(0, s.colorize(redColor+boldStyle, "[Fail] "))
|
||||
}
|
||||
s.printSpecContext(summary.ComponentTexts, summary.ComponentCodeLocations, summary.Failure.ComponentType, summary.Failure.ComponentIndex, summary.State, true)
|
||||
s.printNewLine()
|
||||
s.println(0, s.colorize(lightGrayColor, summary.Failure.Location.String()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) startBlock() {
|
||||
if s.cursorState == cursorStateStreaming {
|
||||
s.printNewLine()
|
||||
s.printDelimiter()
|
||||
} else if s.cursorState == cursorStateMidBlock {
|
||||
s.printNewLine()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) midBlock() {
|
||||
s.cursorState = cursorStateMidBlock
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) endBlock() {
|
||||
s.printDelimiter()
|
||||
s.cursorState = cursorStateEndBlock
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) stream() {
|
||||
s.cursorState = cursorStateStreaming
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) printBlockWithMessage(header string, message string, spec *types.SpecSummary, succinct bool) {
|
||||
s.startBlock()
|
||||
s.println(0, header)
|
||||
|
||||
indentation := s.printCodeLocationBlock(spec.ComponentTexts, spec.ComponentCodeLocations, types.SpecComponentTypeInvalid, 0, spec.State, succinct)
|
||||
|
||||
if message != "" {
|
||||
s.printNewLine()
|
||||
s.println(indentation, message)
|
||||
}
|
||||
|
||||
s.endBlock()
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) printSpecFailure(message string, spec *types.SpecSummary, succinct bool, fullTrace bool) {
|
||||
s.startBlock()
|
||||
s.println(0, s.colorize(redColor+boldStyle, "%s%s [%.3f seconds]", message, s.failureContext(spec.Failure.ComponentType), spec.RunTime.Seconds()))
|
||||
|
||||
indentation := s.printCodeLocationBlock(spec.ComponentTexts, spec.ComponentCodeLocations, spec.Failure.ComponentType, spec.Failure.ComponentIndex, spec.State, succinct)
|
||||
|
||||
s.printNewLine()
|
||||
s.printFailure(indentation, spec.State, spec.Failure, fullTrace)
|
||||
s.endBlock()
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) failureContext(failedComponentType types.SpecComponentType) string {
|
||||
switch failedComponentType {
|
||||
case types.SpecComponentTypeBeforeSuite:
|
||||
return " in Suite Setup (BeforeSuite)"
|
||||
case types.SpecComponentTypeAfterSuite:
|
||||
return " in Suite Teardown (AfterSuite)"
|
||||
case types.SpecComponentTypeBeforeEach:
|
||||
return " in Spec Setup (BeforeEach)"
|
||||
case types.SpecComponentTypeJustBeforeEach:
|
||||
return " in Spec Setup (JustBeforeEach)"
|
||||
case types.SpecComponentTypeAfterEach:
|
||||
return " in Spec Teardown (AfterEach)"
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) printSkip(indentation int, spec types.SpecFailure) {
|
||||
s.println(indentation, s.colorize(cyanColor, spec.Message))
|
||||
s.printNewLine()
|
||||
s.println(indentation, spec.Location.String())
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) printFailure(indentation int, state types.SpecState, failure types.SpecFailure, fullTrace bool) {
|
||||
if state == types.SpecStatePanicked {
|
||||
s.println(indentation, s.colorize(redColor+boldStyle, failure.Message))
|
||||
s.println(indentation, s.colorize(redColor, failure.ForwardedPanic))
|
||||
s.println(indentation, failure.Location.String())
|
||||
s.printNewLine()
|
||||
s.println(indentation, s.colorize(redColor, "Full Stack Trace"))
|
||||
s.println(indentation, failure.Location.FullStackTrace)
|
||||
} else {
|
||||
s.println(indentation, s.colorize(redColor, failure.Message))
|
||||
s.printNewLine()
|
||||
s.println(indentation, failure.Location.String())
|
||||
if fullTrace {
|
||||
s.printNewLine()
|
||||
s.println(indentation, s.colorize(redColor, "Full Stack Trace"))
|
||||
s.println(indentation, failure.Location.FullStackTrace)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) printSpecContext(componentTexts []string, componentCodeLocations []types.CodeLocation, failedComponentType types.SpecComponentType, failedComponentIndex int, state types.SpecState, succinct bool) int {
|
||||
startIndex := 1
|
||||
indentation := 0
|
||||
|
||||
if len(componentTexts) == 1 {
|
||||
startIndex = 0
|
||||
}
|
||||
|
||||
for i := startIndex; i < len(componentTexts); i++ {
|
||||
if (state.IsFailure() || state == types.SpecStateSkipped) && i == failedComponentIndex {
|
||||
color := redColor
|
||||
if state == types.SpecStateSkipped {
|
||||
color = cyanColor
|
||||
}
|
||||
blockType := ""
|
||||
switch failedComponentType {
|
||||
case types.SpecComponentTypeBeforeSuite:
|
||||
blockType = "BeforeSuite"
|
||||
case types.SpecComponentTypeAfterSuite:
|
||||
blockType = "AfterSuite"
|
||||
case types.SpecComponentTypeBeforeEach:
|
||||
blockType = "BeforeEach"
|
||||
case types.SpecComponentTypeJustBeforeEach:
|
||||
blockType = "JustBeforeEach"
|
||||
case types.SpecComponentTypeAfterEach:
|
||||
blockType = "AfterEach"
|
||||
case types.SpecComponentTypeIt:
|
||||
blockType = "It"
|
||||
case types.SpecComponentTypeMeasure:
|
||||
blockType = "Measurement"
|
||||
}
|
||||
if succinct {
|
||||
s.print(0, s.colorize(color+boldStyle, "[%s] %s ", blockType, componentTexts[i]))
|
||||
} else {
|
||||
s.println(indentation, s.colorize(color+boldStyle, "%s [%s]", componentTexts[i], blockType))
|
||||
s.println(indentation, s.colorize(grayColor, "%s", componentCodeLocations[i]))
|
||||
}
|
||||
} else {
|
||||
if succinct {
|
||||
s.print(0, s.colorize(alternatingColors[i%2], "%s ", componentTexts[i]))
|
||||
} else {
|
||||
s.println(indentation, componentTexts[i])
|
||||
s.println(indentation, s.colorize(grayColor, "%s", componentCodeLocations[i]))
|
||||
}
|
||||
}
|
||||
indentation++
|
||||
}
|
||||
|
||||
return indentation
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) printCodeLocationBlock(componentTexts []string, componentCodeLocations []types.CodeLocation, failedComponentType types.SpecComponentType, failedComponentIndex int, state types.SpecState, succinct bool) int {
|
||||
indentation := s.printSpecContext(componentTexts, componentCodeLocations, failedComponentType, failedComponentIndex, state, succinct)
|
||||
|
||||
if succinct {
|
||||
if len(componentTexts) > 0 {
|
||||
s.printNewLine()
|
||||
s.print(0, s.colorize(lightGrayColor, "%s", componentCodeLocations[len(componentCodeLocations)-1]))
|
||||
}
|
||||
s.printNewLine()
|
||||
indentation = 1
|
||||
} else {
|
||||
indentation--
|
||||
}
|
||||
|
||||
return indentation
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) orderedMeasurementKeys(measurements map[string]*types.SpecMeasurement) []string {
|
||||
orderedKeys := make([]string, len(measurements))
|
||||
for key, measurement := range measurements {
|
||||
orderedKeys[measurement.Order] = key
|
||||
}
|
||||
return orderedKeys
|
||||
}
|
||||
|
||||
func (s *consoleStenographer) measurementReport(spec *types.SpecSummary, succinct bool) string {
|
||||
if len(spec.Measurements) == 0 {
|
||||
return "Found no measurements"
|
||||
}
|
||||
|
||||
message := []string{}
|
||||
orderedKeys := s.orderedMeasurementKeys(spec.Measurements)
|
||||
|
||||
if succinct {
|
||||
message = append(message, fmt.Sprintf("%s samples:", s.colorize(boldStyle, "%d", spec.NumberOfSamples)))
|
||||
for _, key := range orderedKeys {
|
||||
measurement := spec.Measurements[key]
|
||||
message = append(message, fmt.Sprintf(" %s - %s: %s%s, %s: %s%s ± %s%s, %s: %s%s",
|
||||
s.colorize(boldStyle, "%s", measurement.Name),
|
||||
measurement.SmallestLabel,
|
||||
s.colorize(greenColor, measurement.PrecisionFmt(), measurement.Smallest),
|
||||
measurement.Units,
|
||||
measurement.AverageLabel,
|
||||
s.colorize(cyanColor, measurement.PrecisionFmt(), measurement.Average),
|
||||
measurement.Units,
|
||||
s.colorize(cyanColor, measurement.PrecisionFmt(), measurement.StdDeviation),
|
||||
measurement.Units,
|
||||
measurement.LargestLabel,
|
||||
s.colorize(redColor, measurement.PrecisionFmt(), measurement.Largest),
|
||||
measurement.Units,
|
||||
))
|
||||
}
|
||||
} else {
|
||||
message = append(message, fmt.Sprintf("Ran %s samples:", s.colorize(boldStyle, "%d", spec.NumberOfSamples)))
|
||||
for _, key := range orderedKeys {
|
||||
measurement := spec.Measurements[key]
|
||||
info := ""
|
||||
if measurement.Info != nil {
|
||||
message = append(message, fmt.Sprintf("%v", measurement.Info))
|
||||
}
|
||||
|
||||
message = append(message, fmt.Sprintf("%s:\n%s %s: %s%s\n %s: %s%s\n %s: %s%s ± %s%s",
|
||||
s.colorize(boldStyle, "%s", measurement.Name),
|
||||
info,
|
||||
measurement.SmallestLabel,
|
||||
s.colorize(greenColor, measurement.PrecisionFmt(), measurement.Smallest),
|
||||
measurement.Units,
|
||||
measurement.LargestLabel,
|
||||
s.colorize(redColor, measurement.PrecisionFmt(), measurement.Largest),
|
||||
measurement.Units,
|
||||
measurement.AverageLabel,
|
||||
s.colorize(cyanColor, measurement.PrecisionFmt(), measurement.Average),
|
||||
measurement.Units,
|
||||
s.colorize(cyanColor, measurement.PrecisionFmt(), measurement.StdDeviation),
|
||||
measurement.Units,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(message, "\n")
|
||||
}
|
21
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable/LICENSE
generated
vendored
Normal file
21
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Yasuhiro Matsumoto
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
43
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable/README.md
generated
vendored
Normal file
43
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable/README.md
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
# go-colorable
|
||||
|
||||
Colorable writer for windows.
|
||||
|
||||
For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.)
|
||||
This package is possible to handle escape sequence for ansi color on windows.
|
||||
|
||||
## Too Bad!
|
||||
|
||||

|
||||
|
||||
|
||||
## So Good!
|
||||
|
||||

|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true})
|
||||
logrus.SetOutput(colorable.NewColorableStdout())
|
||||
|
||||
logrus.Info("succeeded")
|
||||
logrus.Warn("not correct")
|
||||
logrus.Error("something error")
|
||||
logrus.Fatal("panic")
|
||||
```
|
||||
|
||||
You can compile above code on non-windows OSs.
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
$ go get github.com/mattn/go-colorable
|
||||
```
|
||||
|
||||
# License
|
||||
|
||||
MIT
|
||||
|
||||
# Author
|
||||
|
||||
Yasuhiro Matsumoto (a.k.a mattn)
|
24
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable/colorable_others.go
generated
vendored
Normal file
24
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable/colorable_others.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
// +build !windows
|
||||
|
||||
package colorable
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
func NewColorable(file *os.File) io.Writer {
|
||||
if file == nil {
|
||||
panic("nil passed instead of *os.File to NewColorable()")
|
||||
}
|
||||
|
||||
return file
|
||||
}
|
||||
|
||||
func NewColorableStdout() io.Writer {
|
||||
return os.Stdout
|
||||
}
|
||||
|
||||
func NewColorableStderr() io.Writer {
|
||||
return os.Stderr
|
||||
}
|
783
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable/colorable_windows.go
generated
vendored
Normal file
783
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable/colorable_windows.go
generated
vendored
Normal file
@@ -0,0 +1,783 @@
|
||||
package colorable
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty"
|
||||
)
|
||||
|
||||
const (
|
||||
foregroundBlue = 0x1
|
||||
foregroundGreen = 0x2
|
||||
foregroundRed = 0x4
|
||||
foregroundIntensity = 0x8
|
||||
foregroundMask = (foregroundRed | foregroundBlue | foregroundGreen | foregroundIntensity)
|
||||
backgroundBlue = 0x10
|
||||
backgroundGreen = 0x20
|
||||
backgroundRed = 0x40
|
||||
backgroundIntensity = 0x80
|
||||
backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity)
|
||||
)
|
||||
|
||||
type wchar uint16
|
||||
type short int16
|
||||
type dword uint32
|
||||
type word uint16
|
||||
|
||||
type coord struct {
|
||||
x short
|
||||
y short
|
||||
}
|
||||
|
||||
type smallRect struct {
|
||||
left short
|
||||
top short
|
||||
right short
|
||||
bottom short
|
||||
}
|
||||
|
||||
type consoleScreenBufferInfo struct {
|
||||
size coord
|
||||
cursorPosition coord
|
||||
attributes word
|
||||
window smallRect
|
||||
maximumWindowSize coord
|
||||
}
|
||||
|
||||
var (
|
||||
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
|
||||
procSetConsoleTextAttribute = kernel32.NewProc("SetConsoleTextAttribute")
|
||||
procSetConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition")
|
||||
procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW")
|
||||
procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute")
|
||||
)
|
||||
|
||||
type Writer struct {
|
||||
out io.Writer
|
||||
handle syscall.Handle
|
||||
lastbuf bytes.Buffer
|
||||
oldattr word
|
||||
}
|
||||
|
||||
func NewColorable(file *os.File) io.Writer {
|
||||
if file == nil {
|
||||
panic("nil passed instead of *os.File to NewColorable()")
|
||||
}
|
||||
|
||||
if isatty.IsTerminal(file.Fd()) {
|
||||
var csbi consoleScreenBufferInfo
|
||||
handle := syscall.Handle(file.Fd())
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
return &Writer{out: file, handle: handle, oldattr: csbi.attributes}
|
||||
} else {
|
||||
return file
|
||||
}
|
||||
}
|
||||
|
||||
func NewColorableStdout() io.Writer {
|
||||
return NewColorable(os.Stdout)
|
||||
}
|
||||
|
||||
func NewColorableStderr() io.Writer {
|
||||
return NewColorable(os.Stderr)
|
||||
}
|
||||
|
||||
var color256 = map[int]int{
|
||||
0: 0x000000,
|
||||
1: 0x800000,
|
||||
2: 0x008000,
|
||||
3: 0x808000,
|
||||
4: 0x000080,
|
||||
5: 0x800080,
|
||||
6: 0x008080,
|
||||
7: 0xc0c0c0,
|
||||
8: 0x808080,
|
||||
9: 0xff0000,
|
||||
10: 0x00ff00,
|
||||
11: 0xffff00,
|
||||
12: 0x0000ff,
|
||||
13: 0xff00ff,
|
||||
14: 0x00ffff,
|
||||
15: 0xffffff,
|
||||
16: 0x000000,
|
||||
17: 0x00005f,
|
||||
18: 0x000087,
|
||||
19: 0x0000af,
|
||||
20: 0x0000d7,
|
||||
21: 0x0000ff,
|
||||
22: 0x005f00,
|
||||
23: 0x005f5f,
|
||||
24: 0x005f87,
|
||||
25: 0x005faf,
|
||||
26: 0x005fd7,
|
||||
27: 0x005fff,
|
||||
28: 0x008700,
|
||||
29: 0x00875f,
|
||||
30: 0x008787,
|
||||
31: 0x0087af,
|
||||
32: 0x0087d7,
|
||||
33: 0x0087ff,
|
||||
34: 0x00af00,
|
||||
35: 0x00af5f,
|
||||
36: 0x00af87,
|
||||
37: 0x00afaf,
|
||||
38: 0x00afd7,
|
||||
39: 0x00afff,
|
||||
40: 0x00d700,
|
||||
41: 0x00d75f,
|
||||
42: 0x00d787,
|
||||
43: 0x00d7af,
|
||||
44: 0x00d7d7,
|
||||
45: 0x00d7ff,
|
||||
46: 0x00ff00,
|
||||
47: 0x00ff5f,
|
||||
48: 0x00ff87,
|
||||
49: 0x00ffaf,
|
||||
50: 0x00ffd7,
|
||||
51: 0x00ffff,
|
||||
52: 0x5f0000,
|
||||
53: 0x5f005f,
|
||||
54: 0x5f0087,
|
||||
55: 0x5f00af,
|
||||
56: 0x5f00d7,
|
||||
57: 0x5f00ff,
|
||||
58: 0x5f5f00,
|
||||
59: 0x5f5f5f,
|
||||
60: 0x5f5f87,
|
||||
61: 0x5f5faf,
|
||||
62: 0x5f5fd7,
|
||||
63: 0x5f5fff,
|
||||
64: 0x5f8700,
|
||||
65: 0x5f875f,
|
||||
66: 0x5f8787,
|
||||
67: 0x5f87af,
|
||||
68: 0x5f87d7,
|
||||
69: 0x5f87ff,
|
||||
70: 0x5faf00,
|
||||
71: 0x5faf5f,
|
||||
72: 0x5faf87,
|
||||
73: 0x5fafaf,
|
||||
74: 0x5fafd7,
|
||||
75: 0x5fafff,
|
||||
76: 0x5fd700,
|
||||
77: 0x5fd75f,
|
||||
78: 0x5fd787,
|
||||
79: 0x5fd7af,
|
||||
80: 0x5fd7d7,
|
||||
81: 0x5fd7ff,
|
||||
82: 0x5fff00,
|
||||
83: 0x5fff5f,
|
||||
84: 0x5fff87,
|
||||
85: 0x5fffaf,
|
||||
86: 0x5fffd7,
|
||||
87: 0x5fffff,
|
||||
88: 0x870000,
|
||||
89: 0x87005f,
|
||||
90: 0x870087,
|
||||
91: 0x8700af,
|
||||
92: 0x8700d7,
|
||||
93: 0x8700ff,
|
||||
94: 0x875f00,
|
||||
95: 0x875f5f,
|
||||
96: 0x875f87,
|
||||
97: 0x875faf,
|
||||
98: 0x875fd7,
|
||||
99: 0x875fff,
|
||||
100: 0x878700,
|
||||
101: 0x87875f,
|
||||
102: 0x878787,
|
||||
103: 0x8787af,
|
||||
104: 0x8787d7,
|
||||
105: 0x8787ff,
|
||||
106: 0x87af00,
|
||||
107: 0x87af5f,
|
||||
108: 0x87af87,
|
||||
109: 0x87afaf,
|
||||
110: 0x87afd7,
|
||||
111: 0x87afff,
|
||||
112: 0x87d700,
|
||||
113: 0x87d75f,
|
||||
114: 0x87d787,
|
||||
115: 0x87d7af,
|
||||
116: 0x87d7d7,
|
||||
117: 0x87d7ff,
|
||||
118: 0x87ff00,
|
||||
119: 0x87ff5f,
|
||||
120: 0x87ff87,
|
||||
121: 0x87ffaf,
|
||||
122: 0x87ffd7,
|
||||
123: 0x87ffff,
|
||||
124: 0xaf0000,
|
||||
125: 0xaf005f,
|
||||
126: 0xaf0087,
|
||||
127: 0xaf00af,
|
||||
128: 0xaf00d7,
|
||||
129: 0xaf00ff,
|
||||
130: 0xaf5f00,
|
||||
131: 0xaf5f5f,
|
||||
132: 0xaf5f87,
|
||||
133: 0xaf5faf,
|
||||
134: 0xaf5fd7,
|
||||
135: 0xaf5fff,
|
||||
136: 0xaf8700,
|
||||
137: 0xaf875f,
|
||||
138: 0xaf8787,
|
||||
139: 0xaf87af,
|
||||
140: 0xaf87d7,
|
||||
141: 0xaf87ff,
|
||||
142: 0xafaf00,
|
||||
143: 0xafaf5f,
|
||||
144: 0xafaf87,
|
||||
145: 0xafafaf,
|
||||
146: 0xafafd7,
|
||||
147: 0xafafff,
|
||||
148: 0xafd700,
|
||||
149: 0xafd75f,
|
||||
150: 0xafd787,
|
||||
151: 0xafd7af,
|
||||
152: 0xafd7d7,
|
||||
153: 0xafd7ff,
|
||||
154: 0xafff00,
|
||||
155: 0xafff5f,
|
||||
156: 0xafff87,
|
||||
157: 0xafffaf,
|
||||
158: 0xafffd7,
|
||||
159: 0xafffff,
|
||||
160: 0xd70000,
|
||||
161: 0xd7005f,
|
||||
162: 0xd70087,
|
||||
163: 0xd700af,
|
||||
164: 0xd700d7,
|
||||
165: 0xd700ff,
|
||||
166: 0xd75f00,
|
||||
167: 0xd75f5f,
|
||||
168: 0xd75f87,
|
||||
169: 0xd75faf,
|
||||
170: 0xd75fd7,
|
||||
171: 0xd75fff,
|
||||
172: 0xd78700,
|
||||
173: 0xd7875f,
|
||||
174: 0xd78787,
|
||||
175: 0xd787af,
|
||||
176: 0xd787d7,
|
||||
177: 0xd787ff,
|
||||
178: 0xd7af00,
|
||||
179: 0xd7af5f,
|
||||
180: 0xd7af87,
|
||||
181: 0xd7afaf,
|
||||
182: 0xd7afd7,
|
||||
183: 0xd7afff,
|
||||
184: 0xd7d700,
|
||||
185: 0xd7d75f,
|
||||
186: 0xd7d787,
|
||||
187: 0xd7d7af,
|
||||
188: 0xd7d7d7,
|
||||
189: 0xd7d7ff,
|
||||
190: 0xd7ff00,
|
||||
191: 0xd7ff5f,
|
||||
192: 0xd7ff87,
|
||||
193: 0xd7ffaf,
|
||||
194: 0xd7ffd7,
|
||||
195: 0xd7ffff,
|
||||
196: 0xff0000,
|
||||
197: 0xff005f,
|
||||
198: 0xff0087,
|
||||
199: 0xff00af,
|
||||
200: 0xff00d7,
|
||||
201: 0xff00ff,
|
||||
202: 0xff5f00,
|
||||
203: 0xff5f5f,
|
||||
204: 0xff5f87,
|
||||
205: 0xff5faf,
|
||||
206: 0xff5fd7,
|
||||
207: 0xff5fff,
|
||||
208: 0xff8700,
|
||||
209: 0xff875f,
|
||||
210: 0xff8787,
|
||||
211: 0xff87af,
|
||||
212: 0xff87d7,
|
||||
213: 0xff87ff,
|
||||
214: 0xffaf00,
|
||||
215: 0xffaf5f,
|
||||
216: 0xffaf87,
|
||||
217: 0xffafaf,
|
||||
218: 0xffafd7,
|
||||
219: 0xffafff,
|
||||
220: 0xffd700,
|
||||
221: 0xffd75f,
|
||||
222: 0xffd787,
|
||||
223: 0xffd7af,
|
||||
224: 0xffd7d7,
|
||||
225: 0xffd7ff,
|
||||
226: 0xffff00,
|
||||
227: 0xffff5f,
|
||||
228: 0xffff87,
|
||||
229: 0xffffaf,
|
||||
230: 0xffffd7,
|
||||
231: 0xffffff,
|
||||
232: 0x080808,
|
||||
233: 0x121212,
|
||||
234: 0x1c1c1c,
|
||||
235: 0x262626,
|
||||
236: 0x303030,
|
||||
237: 0x3a3a3a,
|
||||
238: 0x444444,
|
||||
239: 0x4e4e4e,
|
||||
240: 0x585858,
|
||||
241: 0x626262,
|
||||
242: 0x6c6c6c,
|
||||
243: 0x767676,
|
||||
244: 0x808080,
|
||||
245: 0x8a8a8a,
|
||||
246: 0x949494,
|
||||
247: 0x9e9e9e,
|
||||
248: 0xa8a8a8,
|
||||
249: 0xb2b2b2,
|
||||
250: 0xbcbcbc,
|
||||
251: 0xc6c6c6,
|
||||
252: 0xd0d0d0,
|
||||
253: 0xdadada,
|
||||
254: 0xe4e4e4,
|
||||
255: 0xeeeeee,
|
||||
}
|
||||
|
||||
func (w *Writer) Write(data []byte) (n int, err error) {
|
||||
var csbi consoleScreenBufferInfo
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
|
||||
er := bytes.NewBuffer(data)
|
||||
loop:
|
||||
for {
|
||||
r1, _, err := procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
if r1 == 0 {
|
||||
break loop
|
||||
}
|
||||
|
||||
c1, _, err := er.ReadRune()
|
||||
if err != nil {
|
||||
break loop
|
||||
}
|
||||
if c1 != 0x1b {
|
||||
fmt.Fprint(w.out, string(c1))
|
||||
continue
|
||||
}
|
||||
c2, _, err := er.ReadRune()
|
||||
if err != nil {
|
||||
w.lastbuf.WriteRune(c1)
|
||||
break loop
|
||||
}
|
||||
if c2 != 0x5b {
|
||||
w.lastbuf.WriteRune(c1)
|
||||
w.lastbuf.WriteRune(c2)
|
||||
continue
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
var m rune
|
||||
for {
|
||||
c, _, err := er.ReadRune()
|
||||
if err != nil {
|
||||
w.lastbuf.WriteRune(c1)
|
||||
w.lastbuf.WriteRune(c2)
|
||||
w.lastbuf.Write(buf.Bytes())
|
||||
break loop
|
||||
}
|
||||
if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
|
||||
m = c
|
||||
break
|
||||
}
|
||||
buf.Write([]byte(string(c)))
|
||||
}
|
||||
|
||||
var csbi consoleScreenBufferInfo
|
||||
switch m {
|
||||
case 'A':
|
||||
n, err = strconv.Atoi(buf.String())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
csbi.cursorPosition.y -= short(n)
|
||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||
case 'B':
|
||||
n, err = strconv.Atoi(buf.String())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
csbi.cursorPosition.y += short(n)
|
||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||
case 'C':
|
||||
n, err = strconv.Atoi(buf.String())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
csbi.cursorPosition.x -= short(n)
|
||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||
case 'D':
|
||||
n, err = strconv.Atoi(buf.String())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if n, err = strconv.Atoi(buf.String()); err == nil {
|
||||
var csbi consoleScreenBufferInfo
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
csbi.cursorPosition.x += short(n)
|
||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||
}
|
||||
case 'E':
|
||||
n, err = strconv.Atoi(buf.String())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
csbi.cursorPosition.x = 0
|
||||
csbi.cursorPosition.y += short(n)
|
||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||
case 'F':
|
||||
n, err = strconv.Atoi(buf.String())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
csbi.cursorPosition.x = 0
|
||||
csbi.cursorPosition.y -= short(n)
|
||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||
case 'G':
|
||||
n, err = strconv.Atoi(buf.String())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
csbi.cursorPosition.x = short(n)
|
||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||
case 'H':
|
||||
token := strings.Split(buf.String(), ";")
|
||||
if len(token) != 2 {
|
||||
continue
|
||||
}
|
||||
n1, err := strconv.Atoi(token[0])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
n2, err := strconv.Atoi(token[1])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
csbi.cursorPosition.x = short(n2)
|
||||
csbi.cursorPosition.x = short(n1)
|
||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||
case 'J':
|
||||
n, err := strconv.Atoi(buf.String())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
var cursor coord
|
||||
switch n {
|
||||
case 0:
|
||||
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
|
||||
case 1:
|
||||
cursor = coord{x: csbi.window.left, y: csbi.window.top}
|
||||
case 2:
|
||||
cursor = coord{x: csbi.window.left, y: csbi.window.top}
|
||||
}
|
||||
var count, written dword
|
||||
count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x)
|
||||
procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
||||
procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
||||
case 'K':
|
||||
n, err := strconv.Atoi(buf.String())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
var cursor coord
|
||||
switch n {
|
||||
case 0:
|
||||
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
|
||||
case 1:
|
||||
cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y}
|
||||
case 2:
|
||||
cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y}
|
||||
}
|
||||
var count, written dword
|
||||
count = dword(csbi.size.x - csbi.cursorPosition.x)
|
||||
procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
||||
procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
||||
case 'm':
|
||||
attr := csbi.attributes
|
||||
cs := buf.String()
|
||||
if cs == "" {
|
||||
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(w.oldattr))
|
||||
continue
|
||||
}
|
||||
token := strings.Split(cs, ";")
|
||||
for i := 0; i < len(token); i += 1 {
|
||||
ns := token[i]
|
||||
if n, err = strconv.Atoi(ns); err == nil {
|
||||
switch {
|
||||
case n == 0 || n == 100:
|
||||
attr = w.oldattr
|
||||
case 1 <= n && n <= 5:
|
||||
attr |= foregroundIntensity
|
||||
case n == 7:
|
||||
attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4)
|
||||
case 22 == n || n == 25 || n == 25:
|
||||
attr |= foregroundIntensity
|
||||
case n == 27:
|
||||
attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4)
|
||||
case 30 <= n && n <= 37:
|
||||
attr = (attr & backgroundMask)
|
||||
if (n-30)&1 != 0 {
|
||||
attr |= foregroundRed
|
||||
}
|
||||
if (n-30)&2 != 0 {
|
||||
attr |= foregroundGreen
|
||||
}
|
||||
if (n-30)&4 != 0 {
|
||||
attr |= foregroundBlue
|
||||
}
|
||||
case n == 38: // set foreground color.
|
||||
if i < len(token)-2 && (token[i+1] == "5" || token[i+1] == "05") {
|
||||
if n256, err := strconv.Atoi(token[i+2]); err == nil {
|
||||
if n256foreAttr == nil {
|
||||
n256setup()
|
||||
}
|
||||
attr &= backgroundMask
|
||||
attr |= n256foreAttr[n256]
|
||||
i += 2
|
||||
}
|
||||
} else {
|
||||
attr = attr & (w.oldattr & backgroundMask)
|
||||
}
|
||||
case n == 39: // reset foreground color.
|
||||
attr &= backgroundMask
|
||||
attr |= w.oldattr & foregroundMask
|
||||
case 40 <= n && n <= 47:
|
||||
attr = (attr & foregroundMask)
|
||||
if (n-40)&1 != 0 {
|
||||
attr |= backgroundRed
|
||||
}
|
||||
if (n-40)&2 != 0 {
|
||||
attr |= backgroundGreen
|
||||
}
|
||||
if (n-40)&4 != 0 {
|
||||
attr |= backgroundBlue
|
||||
}
|
||||
case n == 48: // set background color.
|
||||
if i < len(token)-2 && token[i+1] == "5" {
|
||||
if n256, err := strconv.Atoi(token[i+2]); err == nil {
|
||||
if n256backAttr == nil {
|
||||
n256setup()
|
||||
}
|
||||
attr &= foregroundMask
|
||||
attr |= n256backAttr[n256]
|
||||
i += 2
|
||||
}
|
||||
} else {
|
||||
attr = attr & (w.oldattr & foregroundMask)
|
||||
}
|
||||
case n == 49: // reset foreground color.
|
||||
attr &= foregroundMask
|
||||
attr |= w.oldattr & backgroundMask
|
||||
case 90 <= n && n <= 97:
|
||||
attr = (attr & backgroundMask)
|
||||
attr |= foregroundIntensity
|
||||
if (n-90)&1 != 0 {
|
||||
attr |= foregroundRed
|
||||
}
|
||||
if (n-90)&2 != 0 {
|
||||
attr |= foregroundGreen
|
||||
}
|
||||
if (n-90)&4 != 0 {
|
||||
attr |= foregroundBlue
|
||||
}
|
||||
case 100 <= n && n <= 107:
|
||||
attr = (attr & foregroundMask)
|
||||
attr |= backgroundIntensity
|
||||
if (n-100)&1 != 0 {
|
||||
attr |= backgroundRed
|
||||
}
|
||||
if (n-100)&2 != 0 {
|
||||
attr |= backgroundGreen
|
||||
}
|
||||
if (n-100)&4 != 0 {
|
||||
attr |= backgroundBlue
|
||||
}
|
||||
}
|
||||
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(attr))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return len(data) - w.lastbuf.Len(), nil
|
||||
}
|
||||
|
||||
type consoleColor struct {
|
||||
rgb int
|
||||
red bool
|
||||
green bool
|
||||
blue bool
|
||||
intensity bool
|
||||
}
|
||||
|
||||
func (c consoleColor) foregroundAttr() (attr word) {
|
||||
if c.red {
|
||||
attr |= foregroundRed
|
||||
}
|
||||
if c.green {
|
||||
attr |= foregroundGreen
|
||||
}
|
||||
if c.blue {
|
||||
attr |= foregroundBlue
|
||||
}
|
||||
if c.intensity {
|
||||
attr |= foregroundIntensity
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c consoleColor) backgroundAttr() (attr word) {
|
||||
if c.red {
|
||||
attr |= backgroundRed
|
||||
}
|
||||
if c.green {
|
||||
attr |= backgroundGreen
|
||||
}
|
||||
if c.blue {
|
||||
attr |= backgroundBlue
|
||||
}
|
||||
if c.intensity {
|
||||
attr |= backgroundIntensity
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var color16 = []consoleColor{
|
||||
consoleColor{0x000000, false, false, false, false},
|
||||
consoleColor{0x000080, false, false, true, false},
|
||||
consoleColor{0x008000, false, true, false, false},
|
||||
consoleColor{0x008080, false, true, true, false},
|
||||
consoleColor{0x800000, true, false, false, false},
|
||||
consoleColor{0x800080, true, false, true, false},
|
||||
consoleColor{0x808000, true, true, false, false},
|
||||
consoleColor{0xc0c0c0, true, true, true, false},
|
||||
consoleColor{0x808080, false, false, false, true},
|
||||
consoleColor{0x0000ff, false, false, true, true},
|
||||
consoleColor{0x00ff00, false, true, false, true},
|
||||
consoleColor{0x00ffff, false, true, true, true},
|
||||
consoleColor{0xff0000, true, false, false, true},
|
||||
consoleColor{0xff00ff, true, false, true, true},
|
||||
consoleColor{0xffff00, true, true, false, true},
|
||||
consoleColor{0xffffff, true, true, true, true},
|
||||
}
|
||||
|
||||
type hsv struct {
|
||||
h, s, v float32
|
||||
}
|
||||
|
||||
func (a hsv) dist(b hsv) float32 {
|
||||
dh := a.h - b.h
|
||||
switch {
|
||||
case dh > 0.5:
|
||||
dh = 1 - dh
|
||||
case dh < -0.5:
|
||||
dh = -1 - dh
|
||||
}
|
||||
ds := a.s - b.s
|
||||
dv := a.v - b.v
|
||||
return float32(math.Sqrt(float64(dh*dh + ds*ds + dv*dv)))
|
||||
}
|
||||
|
||||
func toHSV(rgb int) hsv {
|
||||
r, g, b := float32((rgb&0xFF0000)>>16)/256.0,
|
||||
float32((rgb&0x00FF00)>>8)/256.0,
|
||||
float32(rgb&0x0000FF)/256.0
|
||||
min, max := minmax3f(r, g, b)
|
||||
h := max - min
|
||||
if h > 0 {
|
||||
if max == r {
|
||||
h = (g - b) / h
|
||||
if h < 0 {
|
||||
h += 6
|
||||
}
|
||||
} else if max == g {
|
||||
h = 2 + (b-r)/h
|
||||
} else {
|
||||
h = 4 + (r-g)/h
|
||||
}
|
||||
}
|
||||
h /= 6.0
|
||||
s := max - min
|
||||
if max != 0 {
|
||||
s /= max
|
||||
}
|
||||
v := max
|
||||
return hsv{h: h, s: s, v: v}
|
||||
}
|
||||
|
||||
type hsvTable []hsv
|
||||
|
||||
func toHSVTable(rgbTable []consoleColor) hsvTable {
|
||||
t := make(hsvTable, len(rgbTable))
|
||||
for i, c := range rgbTable {
|
||||
t[i] = toHSV(c.rgb)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func (t hsvTable) find(rgb int) consoleColor {
|
||||
hsv := toHSV(rgb)
|
||||
n := 7
|
||||
l := float32(5.0)
|
||||
for i, p := range t {
|
||||
d := hsv.dist(p)
|
||||
if d < l {
|
||||
l, n = d, i
|
||||
}
|
||||
}
|
||||
return color16[n]
|
||||
}
|
||||
|
||||
func minmax3f(a, b, c float32) (min, max float32) {
|
||||
if a < b {
|
||||
if b < c {
|
||||
return a, c
|
||||
} else if a < c {
|
||||
return a, b
|
||||
} else {
|
||||
return c, b
|
||||
}
|
||||
} else {
|
||||
if a < c {
|
||||
return b, c
|
||||
} else if b < c {
|
||||
return b, a
|
||||
} else {
|
||||
return c, a
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var n256foreAttr []word
|
||||
var n256backAttr []word
|
||||
|
||||
func n256setup() {
|
||||
n256foreAttr = make([]word, 256)
|
||||
n256backAttr = make([]word, 256)
|
||||
t := toHSVTable(color16)
|
||||
for i, rgb := range color256 {
|
||||
c := t.find(rgb)
|
||||
n256foreAttr[i] = c.foregroundAttr()
|
||||
n256backAttr[i] = c.backgroundAttr()
|
||||
}
|
||||
}
|
57
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable/noncolorable.go
generated
vendored
Normal file
57
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable/noncolorable.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
package colorable
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
type NonColorable struct {
|
||||
out io.Writer
|
||||
lastbuf bytes.Buffer
|
||||
}
|
||||
|
||||
func NewNonColorable(w io.Writer) io.Writer {
|
||||
return &NonColorable{out: w}
|
||||
}
|
||||
|
||||
func (w *NonColorable) Write(data []byte) (n int, err error) {
|
||||
er := bytes.NewBuffer(data)
|
||||
loop:
|
||||
for {
|
||||
c1, _, err := er.ReadRune()
|
||||
if err != nil {
|
||||
break loop
|
||||
}
|
||||
if c1 != 0x1b {
|
||||
fmt.Fprint(w.out, string(c1))
|
||||
continue
|
||||
}
|
||||
c2, _, err := er.ReadRune()
|
||||
if err != nil {
|
||||
w.lastbuf.WriteRune(c1)
|
||||
break loop
|
||||
}
|
||||
if c2 != 0x5b {
|
||||
w.lastbuf.WriteRune(c1)
|
||||
w.lastbuf.WriteRune(c2)
|
||||
continue
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
for {
|
||||
c, _, err := er.ReadRune()
|
||||
if err != nil {
|
||||
w.lastbuf.WriteRune(c1)
|
||||
w.lastbuf.WriteRune(c2)
|
||||
w.lastbuf.Write(buf.Bytes())
|
||||
break loop
|
||||
}
|
||||
if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
|
||||
break
|
||||
}
|
||||
buf.Write([]byte(string(c)))
|
||||
}
|
||||
}
|
||||
return len(data) - w.lastbuf.Len(), nil
|
||||
}
|
9
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/LICENSE
generated
vendored
Normal file
9
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
Copyright (c) Yasuhiro MATSUMOTO <mattn.jp@gmail.com>
|
||||
|
||||
MIT License (Expat)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
37
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/README.md
generated
vendored
Normal file
37
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/README.md
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
# go-isatty
|
||||
|
||||
isatty for golang
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mattn/go-isatty"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if isatty.IsTerminal(os.Stdout.Fd()) {
|
||||
fmt.Println("Is Terminal")
|
||||
} else {
|
||||
fmt.Println("Is Not Terminal")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
$ go get github.com/mattn/go-isatty
|
||||
```
|
||||
|
||||
# License
|
||||
|
||||
MIT
|
||||
|
||||
# Author
|
||||
|
||||
Yasuhiro Matsumoto (a.k.a mattn)
|
2
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/doc.go
generated
vendored
Normal file
2
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/doc.go
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package isatty implements interface to isatty
|
||||
package isatty
|
9
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/isatty_appengine.go
generated
vendored
Normal file
9
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/isatty_appengine.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// +build appengine
|
||||
|
||||
package isatty
|
||||
|
||||
// IsTerminal returns true if the file descriptor is terminal which
|
||||
// is always false on on appengine classic which is a sandboxed PaaS.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
return false
|
||||
}
|
18
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/isatty_bsd.go
generated
vendored
Normal file
18
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/isatty_bsd.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
// +build darwin freebsd openbsd netbsd
|
||||
// +build !appengine
|
||||
|
||||
package isatty
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const ioctlReadTermios = syscall.TIOCGETA
|
||||
|
||||
// IsTerminal return true if the file descriptor is terminal.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
var termios syscall.Termios
|
||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
||||
return err == 0
|
||||
}
|
18
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/isatty_linux.go
generated
vendored
Normal file
18
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/isatty_linux.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
// +build linux
|
||||
// +build !appengine
|
||||
|
||||
package isatty
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const ioctlReadTermios = syscall.TCGETS
|
||||
|
||||
// IsTerminal return true if the file descriptor is terminal.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
var termios syscall.Termios
|
||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
||||
return err == 0
|
||||
}
|
16
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/isatty_solaris.go
generated
vendored
Normal file
16
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/isatty_solaris.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// +build solaris
|
||||
// +build !appengine
|
||||
|
||||
package isatty
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||
// see: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
var termio unix.Termio
|
||||
err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio)
|
||||
return err == nil
|
||||
}
|
19
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/isatty_windows.go
generated
vendored
Normal file
19
vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/isatty_windows.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
// +build windows
|
||||
// +build !appengine
|
||||
|
||||
package isatty
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
var procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
|
||||
|
||||
// IsTerminal return true if the file descriptor is terminal.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
var st uint32
|
||||
r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, fd, uintptr(unsafe.Pointer(&st)), 0)
|
||||
return r != 0 && e == 0
|
||||
}
|
106
vendor/github.com/onsi/ginkgo/reporters/teamcity_reporter.go
generated
vendored
Normal file
106
vendor/github.com/onsi/ginkgo/reporters/teamcity_reporter.go
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
|
||||
TeamCity Reporter for Ginkgo
|
||||
|
||||
Makes use of TeamCity's support for Service Messages
|
||||
http://confluence.jetbrains.com/display/TCD7/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ReportingTests
|
||||
*/
|
||||
|
||||
package reporters
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/onsi/ginkgo/config"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
const (
|
||||
messageId = "##teamcity"
|
||||
)
|
||||
|
||||
type TeamCityReporter struct {
|
||||
writer io.Writer
|
||||
testSuiteName string
|
||||
ReporterConfig config.DefaultReporterConfigType
|
||||
}
|
||||
|
||||
func NewTeamCityReporter(writer io.Writer) *TeamCityReporter {
|
||||
return &TeamCityReporter{
|
||||
writer: writer,
|
||||
}
|
||||
}
|
||||
|
||||
func (reporter *TeamCityReporter) SpecSuiteWillBegin(config config.GinkgoConfigType, summary *types.SuiteSummary) {
|
||||
reporter.testSuiteName = escape(summary.SuiteDescription)
|
||||
fmt.Fprintf(reporter.writer, "%s[testSuiteStarted name='%s']\n", messageId, reporter.testSuiteName)
|
||||
}
|
||||
|
||||
func (reporter *TeamCityReporter) BeforeSuiteDidRun(setupSummary *types.SetupSummary) {
|
||||
reporter.handleSetupSummary("BeforeSuite", setupSummary)
|
||||
}
|
||||
|
||||
func (reporter *TeamCityReporter) AfterSuiteDidRun(setupSummary *types.SetupSummary) {
|
||||
reporter.handleSetupSummary("AfterSuite", setupSummary)
|
||||
}
|
||||
|
||||
func (reporter *TeamCityReporter) handleSetupSummary(name string, setupSummary *types.SetupSummary) {
|
||||
if setupSummary.State != types.SpecStatePassed {
|
||||
testName := escape(name)
|
||||
fmt.Fprintf(reporter.writer, "%s[testStarted name='%s']\n", messageId, testName)
|
||||
message := reporter.failureMessage(setupSummary.Failure)
|
||||
details := reporter.failureDetails(setupSummary.Failure)
|
||||
fmt.Fprintf(reporter.writer, "%s[testFailed name='%s' message='%s' details='%s']\n", messageId, testName, message, details)
|
||||
durationInMilliseconds := setupSummary.RunTime.Seconds() * 1000
|
||||
fmt.Fprintf(reporter.writer, "%s[testFinished name='%s' duration='%v']\n", messageId, testName, durationInMilliseconds)
|
||||
}
|
||||
}
|
||||
|
||||
func (reporter *TeamCityReporter) SpecWillRun(specSummary *types.SpecSummary) {
|
||||
testName := escape(strings.Join(specSummary.ComponentTexts[1:], " "))
|
||||
fmt.Fprintf(reporter.writer, "%s[testStarted name='%s']\n", messageId, testName)
|
||||
}
|
||||
|
||||
func (reporter *TeamCityReporter) SpecDidComplete(specSummary *types.SpecSummary) {
|
||||
testName := escape(strings.Join(specSummary.ComponentTexts[1:], " "))
|
||||
|
||||
if reporter.ReporterConfig.ReportPassed && specSummary.State == types.SpecStatePassed {
|
||||
details := escape(specSummary.CapturedOutput)
|
||||
fmt.Fprintf(reporter.writer, "%s[testPassed name='%s' details='%s']\n", messageId, testName, details)
|
||||
}
|
||||
if specSummary.State == types.SpecStateFailed || specSummary.State == types.SpecStateTimedOut || specSummary.State == types.SpecStatePanicked {
|
||||
message := reporter.failureMessage(specSummary.Failure)
|
||||
details := reporter.failureDetails(specSummary.Failure)
|
||||
fmt.Fprintf(reporter.writer, "%s[testFailed name='%s' message='%s' details='%s']\n", messageId, testName, message, details)
|
||||
}
|
||||
if specSummary.State == types.SpecStateSkipped || specSummary.State == types.SpecStatePending {
|
||||
fmt.Fprintf(reporter.writer, "%s[testIgnored name='%s']\n", messageId, testName)
|
||||
}
|
||||
|
||||
durationInMilliseconds := specSummary.RunTime.Seconds() * 1000
|
||||
fmt.Fprintf(reporter.writer, "%s[testFinished name='%s' duration='%v']\n", messageId, testName, durationInMilliseconds)
|
||||
}
|
||||
|
||||
func (reporter *TeamCityReporter) SpecSuiteDidEnd(summary *types.SuiteSummary) {
|
||||
fmt.Fprintf(reporter.writer, "%s[testSuiteFinished name='%s']\n", messageId, reporter.testSuiteName)
|
||||
}
|
||||
|
||||
func (reporter *TeamCityReporter) failureMessage(failure types.SpecFailure) string {
|
||||
return escape(failure.ComponentCodeLocation.String())
|
||||
}
|
||||
|
||||
func (reporter *TeamCityReporter) failureDetails(failure types.SpecFailure) string {
|
||||
return escape(fmt.Sprintf("%s\n%s", failure.Message, failure.Location.String()))
|
||||
}
|
||||
|
||||
func escape(output string) string {
|
||||
output = strings.Replace(output, "|", "||", -1)
|
||||
output = strings.Replace(output, "'", "|'", -1)
|
||||
output = strings.Replace(output, "\n", "|n", -1)
|
||||
output = strings.Replace(output, "\r", "|r", -1)
|
||||
output = strings.Replace(output, "[", "|[", -1)
|
||||
output = strings.Replace(output, "]", "|]", -1)
|
||||
return output
|
||||
}
|
15
vendor/github.com/onsi/ginkgo/types/code_location.go
generated
vendored
Normal file
15
vendor/github.com/onsi/ginkgo/types/code_location.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type CodeLocation struct {
|
||||
FileName string
|
||||
LineNumber int
|
||||
FullStackTrace string
|
||||
}
|
||||
|
||||
func (codeLocation CodeLocation) String() string {
|
||||
return fmt.Sprintf("%s:%d", codeLocation.FileName, codeLocation.LineNumber)
|
||||
}
|
160
vendor/github.com/onsi/ginkgo/types/deprecation_support.go
generated
vendored
Normal file
160
vendor/github.com/onsi/ginkgo/types/deprecation_support.go
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/onsi/ginkgo/config"
|
||||
"github.com/onsi/ginkgo/formatter"
|
||||
)
|
||||
|
||||
type Deprecation struct {
|
||||
Message string
|
||||
DocLink string
|
||||
Version string
|
||||
}
|
||||
|
||||
type deprecations struct{}
|
||||
|
||||
var Deprecations = deprecations{}
|
||||
|
||||
func (d deprecations) CustomReporter() Deprecation {
|
||||
return Deprecation{
|
||||
Message: "You are using a custom reporter. Support for custom reporters will likely be removed in V2. Most users were using them to generate junit or teamcity reports and this functionality will be merged into the core reporter. In addition, Ginkgo 2.0 will support emitting a JSON-formatted report that users can then manipulate to generate custom reports.\n\n{{red}}{{bold}}If this change will be impactful to you please leave a comment on {{cyan}}{{underline}}https://github.com/onsi/ginkgo/issues/711{{/}}",
|
||||
DocLink: "removed-custom-reporters",
|
||||
Version: "1.16.0",
|
||||
}
|
||||
}
|
||||
|
||||
func (d deprecations) V1Reporter() Deprecation {
|
||||
return Deprecation{
|
||||
Message: "You are using a V1 Ginkgo Reporter. Please update your custom reporter to the new V2 Reporter interface.",
|
||||
DocLink: "changed-reporter-interface",
|
||||
Version: "1.16.0",
|
||||
}
|
||||
}
|
||||
|
||||
func (d deprecations) Async() Deprecation {
|
||||
return Deprecation{
|
||||
Message: "You are passing a Done channel to a test node to test asynchronous behavior. This is deprecated in Ginkgo V2. Your test will run synchronously and the timeout will be ignored.",
|
||||
DocLink: "removed-async-testing",
|
||||
Version: "1.16.0",
|
||||
}
|
||||
}
|
||||
|
||||
func (d deprecations) Measure() Deprecation {
|
||||
return Deprecation{
|
||||
Message: "Measure is deprecated and will be removed in Ginkgo V2. Please migrate to gomega/gmeasure.",
|
||||
DocLink: "removed-measure",
|
||||
Version: "1.16.3",
|
||||
}
|
||||
}
|
||||
|
||||
func (d deprecations) ParallelNode() Deprecation {
|
||||
return Deprecation{
|
||||
Message: "GinkgoParallelNode is deprecated and will be removed in Ginkgo V2. Please use GinkgoParallelProcess instead.",
|
||||
DocLink: "renamed-ginkgoparallelnode",
|
||||
Version: "1.16.5",
|
||||
}
|
||||
}
|
||||
|
||||
func (d deprecations) Convert() Deprecation {
|
||||
return Deprecation{
|
||||
Message: "The convert command is deprecated in Ginkgo V2",
|
||||
DocLink: "removed-ginkgo-convert",
|
||||
Version: "1.16.0",
|
||||
}
|
||||
}
|
||||
|
||||
func (d deprecations) Blur() Deprecation {
|
||||
return Deprecation{
|
||||
Message: "The blur command is deprecated in Ginkgo V2. Use 'ginkgo unfocus' instead.",
|
||||
Version: "1.16.0",
|
||||
}
|
||||
}
|
||||
|
||||
type DeprecationTracker struct {
|
||||
deprecations map[Deprecation][]CodeLocation
|
||||
}
|
||||
|
||||
func NewDeprecationTracker() *DeprecationTracker {
|
||||
return &DeprecationTracker{
|
||||
deprecations: map[Deprecation][]CodeLocation{},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DeprecationTracker) TrackDeprecation(deprecation Deprecation, cl ...CodeLocation) {
|
||||
ackVersion := os.Getenv("ACK_GINKGO_DEPRECATIONS")
|
||||
if deprecation.Version != "" && ackVersion != "" {
|
||||
ack := ParseSemVer(ackVersion)
|
||||
version := ParseSemVer(deprecation.Version)
|
||||
if ack.GreaterThanOrEqualTo(version) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(cl) == 1 {
|
||||
d.deprecations[deprecation] = append(d.deprecations[deprecation], cl[0])
|
||||
} else {
|
||||
d.deprecations[deprecation] = []CodeLocation{}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DeprecationTracker) DidTrackDeprecations() bool {
|
||||
return len(d.deprecations) > 0
|
||||
}
|
||||
|
||||
func (d *DeprecationTracker) DeprecationsReport() string {
|
||||
out := formatter.F("\n{{light-yellow}}You're using deprecated Ginkgo functionality:{{/}}\n")
|
||||
out += formatter.F("{{light-yellow}}============================================={{/}}\n")
|
||||
out += formatter.F("{{bold}}{{green}}Ginkgo 2.0{{/}} is under active development and will introduce several new features, improvements, and a small handful of breaking changes.\n")
|
||||
out += formatter.F("A release candidate for 2.0 is now available and 2.0 should GA in Fall 2021. {{bold}}Please give the RC a try and send us feedback!{{/}}\n")
|
||||
out += formatter.F(" - To learn more, view the migration guide at {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md{{/}}\n")
|
||||
out += formatter.F(" - For instructions on using the Release Candidate visit {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md#using-the-beta{{/}}\n")
|
||||
out += formatter.F(" - To comment, chime in at {{cyan}}{{underline}}https://github.com/onsi/ginkgo/issues/711{{/}}\n\n")
|
||||
|
||||
for deprecation, locations := range d.deprecations {
|
||||
out += formatter.Fi(1, "{{yellow}}"+deprecation.Message+"{{/}}\n")
|
||||
if deprecation.DocLink != "" {
|
||||
out += formatter.Fi(1, "{{bold}}Learn more at:{{/}} {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md#%s{{/}}\n", deprecation.DocLink)
|
||||
}
|
||||
for _, location := range locations {
|
||||
out += formatter.Fi(2, "{{gray}}%s{{/}}\n", location)
|
||||
}
|
||||
}
|
||||
out += formatter.F("\n{{gray}}To silence deprecations that can be silenced set the following environment variable:{{/}}\n")
|
||||
out += formatter.Fi(1, "{{gray}}ACK_GINKGO_DEPRECATIONS=%s{{/}}\n", config.VERSION)
|
||||
return out
|
||||
}
|
||||
|
||||
type SemVer struct {
|
||||
Major int
|
||||
Minor int
|
||||
Patch int
|
||||
}
|
||||
|
||||
func (s SemVer) GreaterThanOrEqualTo(o SemVer) bool {
|
||||
return (s.Major > o.Major) ||
|
||||
(s.Major == o.Major && s.Minor > o.Minor) ||
|
||||
(s.Major == o.Major && s.Minor == o.Minor && s.Patch >= o.Patch)
|
||||
}
|
||||
|
||||
func ParseSemVer(semver string) SemVer {
|
||||
out := SemVer{}
|
||||
semver = strings.TrimFunc(semver, func(r rune) bool {
|
||||
return !(unicode.IsNumber(r) || r == '.')
|
||||
})
|
||||
components := strings.Split(semver, ".")
|
||||
if len(components) > 0 {
|
||||
out.Major, _ = strconv.Atoi(components[0])
|
||||
}
|
||||
if len(components) > 1 {
|
||||
out.Minor, _ = strconv.Atoi(components[1])
|
||||
}
|
||||
if len(components) > 2 {
|
||||
out.Patch, _ = strconv.Atoi(components[2])
|
||||
}
|
||||
return out
|
||||
}
|
30
vendor/github.com/onsi/ginkgo/types/synchronization.go
generated
vendored
Normal file
30
vendor/github.com/onsi/ginkgo/types/synchronization.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
type RemoteBeforeSuiteState int
|
||||
|
||||
const (
|
||||
RemoteBeforeSuiteStateInvalid RemoteBeforeSuiteState = iota
|
||||
|
||||
RemoteBeforeSuiteStatePending
|
||||
RemoteBeforeSuiteStatePassed
|
||||
RemoteBeforeSuiteStateFailed
|
||||
RemoteBeforeSuiteStateDisappeared
|
||||
)
|
||||
|
||||
type RemoteBeforeSuiteData struct {
|
||||
Data []byte
|
||||
State RemoteBeforeSuiteState
|
||||
}
|
||||
|
||||
func (r RemoteBeforeSuiteData) ToJSON() []byte {
|
||||
data, _ := json.Marshal(r)
|
||||
return data
|
||||
}
|
||||
|
||||
type RemoteAfterSuiteData struct {
|
||||
CanRun bool
|
||||
}
|
174
vendor/github.com/onsi/ginkgo/types/types.go
generated
vendored
Normal file
174
vendor/github.com/onsi/ginkgo/types/types.go
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
const GINKGO_FOCUS_EXIT_CODE = 197
|
||||
|
||||
/*
|
||||
SuiteSummary represents the a summary of the test suite and is passed to both
|
||||
Reporter.SpecSuiteWillBegin
|
||||
Reporter.SpecSuiteDidEnd
|
||||
|
||||
this is unfortunate as these two methods should receive different objects. When running in parallel
|
||||
each node does not deterministically know how many specs it will end up running.
|
||||
|
||||
Unfortunately making such a change would break backward compatibility.
|
||||
|
||||
Until Ginkgo 2.0 comes out we will continue to reuse this struct but populate unknown fields
|
||||
with -1.
|
||||
*/
|
||||
type SuiteSummary struct {
|
||||
SuiteDescription string
|
||||
SuiteSucceeded bool
|
||||
SuiteID string
|
||||
|
||||
NumberOfSpecsBeforeParallelization int
|
||||
NumberOfTotalSpecs int
|
||||
NumberOfSpecsThatWillBeRun int
|
||||
NumberOfPendingSpecs int
|
||||
NumberOfSkippedSpecs int
|
||||
NumberOfPassedSpecs int
|
||||
NumberOfFailedSpecs int
|
||||
// Flaked specs are those that failed initially, but then passed on a
|
||||
// subsequent try.
|
||||
NumberOfFlakedSpecs int
|
||||
RunTime time.Duration
|
||||
}
|
||||
|
||||
type SpecSummary struct {
|
||||
ComponentTexts []string
|
||||
ComponentCodeLocations []CodeLocation
|
||||
|
||||
State SpecState
|
||||
RunTime time.Duration
|
||||
Failure SpecFailure
|
||||
IsMeasurement bool
|
||||
NumberOfSamples int
|
||||
Measurements map[string]*SpecMeasurement
|
||||
|
||||
CapturedOutput string
|
||||
SuiteID string
|
||||
}
|
||||
|
||||
func (s SpecSummary) HasFailureState() bool {
|
||||
return s.State.IsFailure()
|
||||
}
|
||||
|
||||
func (s SpecSummary) TimedOut() bool {
|
||||
return s.State == SpecStateTimedOut
|
||||
}
|
||||
|
||||
func (s SpecSummary) Panicked() bool {
|
||||
return s.State == SpecStatePanicked
|
||||
}
|
||||
|
||||
func (s SpecSummary) Failed() bool {
|
||||
return s.State == SpecStateFailed
|
||||
}
|
||||
|
||||
func (s SpecSummary) Passed() bool {
|
||||
return s.State == SpecStatePassed
|
||||
}
|
||||
|
||||
func (s SpecSummary) Skipped() bool {
|
||||
return s.State == SpecStateSkipped
|
||||
}
|
||||
|
||||
func (s SpecSummary) Pending() bool {
|
||||
return s.State == SpecStatePending
|
||||
}
|
||||
|
||||
type SetupSummary struct {
|
||||
ComponentType SpecComponentType
|
||||
CodeLocation CodeLocation
|
||||
|
||||
State SpecState
|
||||
RunTime time.Duration
|
||||
Failure SpecFailure
|
||||
|
||||
CapturedOutput string
|
||||
SuiteID string
|
||||
}
|
||||
|
||||
type SpecFailure struct {
|
||||
Message string
|
||||
Location CodeLocation
|
||||
ForwardedPanic string
|
||||
|
||||
ComponentIndex int
|
||||
ComponentType SpecComponentType
|
||||
ComponentCodeLocation CodeLocation
|
||||
}
|
||||
|
||||
type SpecMeasurement struct {
|
||||
Name string
|
||||
Info interface{}
|
||||
Order int
|
||||
|
||||
Results []float64
|
||||
|
||||
Smallest float64
|
||||
Largest float64
|
||||
Average float64
|
||||
StdDeviation float64
|
||||
|
||||
SmallestLabel string
|
||||
LargestLabel string
|
||||
AverageLabel string
|
||||
Units string
|
||||
Precision int
|
||||
}
|
||||
|
||||
func (s SpecMeasurement) PrecisionFmt() string {
|
||||
if s.Precision == 0 {
|
||||
return "%f"
|
||||
}
|
||||
|
||||
str := strconv.Itoa(s.Precision)
|
||||
|
||||
return "%." + str + "f"
|
||||
}
|
||||
|
||||
type SpecState uint
|
||||
|
||||
const (
|
||||
SpecStateInvalid SpecState = iota
|
||||
|
||||
SpecStatePending
|
||||
SpecStateSkipped
|
||||
SpecStatePassed
|
||||
SpecStateFailed
|
||||
SpecStatePanicked
|
||||
SpecStateTimedOut
|
||||
)
|
||||
|
||||
func (state SpecState) IsFailure() bool {
|
||||
return state == SpecStateTimedOut || state == SpecStatePanicked || state == SpecStateFailed
|
||||
}
|
||||
|
||||
type SpecComponentType uint
|
||||
|
||||
const (
|
||||
SpecComponentTypeInvalid SpecComponentType = iota
|
||||
|
||||
SpecComponentTypeContainer
|
||||
SpecComponentTypeBeforeSuite
|
||||
SpecComponentTypeAfterSuite
|
||||
SpecComponentTypeBeforeEach
|
||||
SpecComponentTypeJustBeforeEach
|
||||
SpecComponentTypeJustAfterEach
|
||||
SpecComponentTypeAfterEach
|
||||
SpecComponentTypeIt
|
||||
SpecComponentTypeMeasure
|
||||
)
|
||||
|
||||
type FlagType uint
|
||||
|
||||
const (
|
||||
FlagTypeNone FlagType = iota
|
||||
FlagTypeFocused
|
||||
FlagTypePending
|
||||
)
|
5
vendor/github.com/onsi/gomega/.gitignore
generated
vendored
Normal file
5
vendor/github.com/onsi/gomega/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.DS_Store
|
||||
*.test
|
||||
.
|
||||
.idea
|
||||
gomega.iml
|
345
vendor/github.com/onsi/gomega/CHANGELOG.md
generated
vendored
Normal file
345
vendor/github.com/onsi/gomega/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,345 @@
|
||||
## 1.19.0
|
||||
|
||||
## Features
|
||||
- New [`HaveEach`](https://onsi.github.io/gomega/#haveeachelement-interface) matcher to ensure that each and every element in an `array`, `slice`, or `map` satisfies the passed in matcher. (#523) [9fc2ae2] (#524) [c8ba582]
|
||||
- Users can now wrap the `Gomega` interface to implement custom behavior on each assertion. (#521) [1f2e714]
|
||||
- [`ContainElement`](https://onsi.github.io/gomega/#containelementelement-interface) now accepts an additional pointer argument. Elements that satisfy the matcher are stored in the pointer enabling developers to easily add subsequent, more detailed, assertions against the matching element. (#527) [1a4e27f]
|
||||
|
||||
## Fixes
|
||||
- update RELEASING instructions to match ginkgo [0917cde]
|
||||
- Bump github.com/onsi/ginkgo/v2 from 2.0.0 to 2.1.3 (#519) [49ab4b0]
|
||||
- Fix CVE-2021-38561 (#534) [f1b4456]
|
||||
- Fix max number of samples in experiments on non-64-bit systems. (#528) [1c84497]
|
||||
- Remove dependency on ginkgo v1.16.4 (#530) [4dea8d5]
|
||||
- Fix for Go 1.18 (#532) [56d2a29]
|
||||
- Document precendence of timeouts (#533) [b607941]
|
||||
|
||||
## 1.18.1
|
||||
|
||||
## Fixes
|
||||
- Add pointer support to HaveField matcher (#495) [79e41a3]
|
||||
|
||||
## 1.18.0
|
||||
|
||||
## Features
|
||||
- Docs now live on the master branch in the docs folder which will make for easier PRs. The docs also use Ginkgo 2.0's new docs html/css/js. [2570272]
|
||||
- New HaveValue matcher can handle actuals that are either values (in which case they are passed on unscathed) or pointers (in which case they are indirected). [Docs here.](https://onsi.github.io/gomega/#working-with-values) (#485) [bdc087c]
|
||||
- Gmeasure has been declared GA [360db9d]
|
||||
|
||||
## Fixes
|
||||
- Gomega now uses ioutil for Go 1.15 and lower (#492) - official support is only for the most recent two major versions of Go but this will unblock users who need to stay on older unsupported versions of Go. [c29c1c0]
|
||||
|
||||
## Maintenace
|
||||
- Remove Travis workflow (#491) [72e6040]
|
||||
- Upgrade to Ginkgo 2.0.0 GA [f383637]
|
||||
- chore: fix description of HaveField matcher (#487) [2b4b2c0]
|
||||
- use tools.go to ensure Ginkgo cli dependencies are included [f58a52b]
|
||||
- remove dockerfile and simplify github actions to match ginkgo's actions [3f8160d]
|
||||
|
||||
## 1.17.0
|
||||
|
||||
### Features
|
||||
- Add HaveField matcher [3a26311]
|
||||
- add Error() assertions on the final error value of multi-return values (#480) [2f96943]
|
||||
- separate out offsets and timeouts (#478) [18a4723]
|
||||
- fix transformation error reporting (#479) [e001fab]
|
||||
- allow transform functions to report errors (#472) [bf93408]
|
||||
|
||||
### Fixes
|
||||
Stop using deprecated ioutil package (#467) [07f405d]
|
||||
|
||||
## 1.16.0
|
||||
|
||||
### Features
|
||||
- feat: HaveHTTPStatus multiple expected values (#465) [aa69f1b]
|
||||
- feat: HaveHTTPHeaderWithValue() matcher (#463) [dd83a96]
|
||||
- feat: HaveHTTPBody matcher (#462) [504e1f2]
|
||||
- feat: formatter for HTTP responses (#461) [e5b3157]
|
||||
|
||||
## 1.15.0
|
||||
|
||||
### Fixes
|
||||
The previous version (1.14.0) introduced a change to allow `Eventually` and `Consistently` to support functions that make assertions. This was accomplished by overriding the global fail handler when running the callbacks passed to `Eventually/Consistently` in order to capture any resulting errors. Issue #457 uncovered a flaw with this approach: when multiple `Eventually`s are running concurrently they race when overriding the singleton global fail handler.
|
||||
|
||||
1.15.0 resolves this by requiring users who want to make assertions in `Eventually/Consistently` call backs to explicitly pass in a function that takes a `Gomega` as an argument. The passed-in `Gomega` instance can be used to make assertions. Any failures will cause `Eventually` to retry the callback. This cleaner interface avoids the issue of swapping out globals but comes at the cost of changing the contract introduced in v1.14.0. As such 1.15.0 introduces a breaking change with respect to 1.14.0 - however we expect that adoption of this feature in 1.14.0 remains limited.
|
||||
|
||||
In addition, 1.15.0 cleans up some of Gomega's internals. Most users shouldn't notice any differences stemming from the refactoring that was made.
|
||||
|
||||
## 1.14.0
|
||||
|
||||
### Features
|
||||
- gmeasure.SamplingConfig now suppers a MinSamplingInterval [e94dbca]
|
||||
- Eventually and Consistently support functions that make assertions [2f04e6e]
|
||||
- Eventually and Consistently now allow their passed-in functions to make assertions.
|
||||
These assertions must pass or the function is considered to have failed and is retried.
|
||||
- Eventually and Consistently can now take functions with no return values. These implicitly return nil
|
||||
if they contain no failed assertion. Otherwise they return an error wrapping the first assertion failure. This allows
|
||||
these functions to be used with the Succeed() matcher.
|
||||
- Introduce InterceptGomegaFailure - an analogue to InterceptGomegaFailures - that captures the first assertion failure
|
||||
and halts execution in its passed-in callback.
|
||||
|
||||
### Fixes
|
||||
- Call Verify GHTTPWithGomega receiver funcs (#454) [496e6fd]
|
||||
- Build a binary with an expected name (#446) [7356360]
|
||||
|
||||
## 1.13.0
|
||||
|
||||
### Features
|
||||
- gmeasure provides BETA support for benchmarking (#447) [8f2dfbf]
|
||||
- Set consistently and eventually defaults on init (#443) [12eb778]
|
||||
|
||||
## 1.12.0
|
||||
|
||||
### Features
|
||||
- Add Satisfy() matcher (#437) [c548f31]
|
||||
- tweak truncation message [3360b8c]
|
||||
- Add format.GomegaStringer (#427) [cc80b6f]
|
||||
- Add Clear() method to gbytes.Buffer [c3c0920]
|
||||
|
||||
### Fixes
|
||||
- Fix error message in BeNumericallyMatcher (#432) [09c074a]
|
||||
- Bump github.com/onsi/ginkgo from 1.12.1 to 1.16.2 (#442) [e5f6ea0]
|
||||
- Bump github.com/golang/protobuf from 1.4.3 to 1.5.2 (#431) [adae3bf]
|
||||
- Bump golang.org/x/net (#441) [3275b35]
|
||||
|
||||
## 1.11.0
|
||||
|
||||
### Features
|
||||
- feature: add index to gstruct element func (#419) [334e00d]
|
||||
- feat(gexec) Add CompileTest functions. Close #410 (#411) [47c613f]
|
||||
|
||||
### Fixes
|
||||
- Check more carefully for nils in WithTransform (#423) [3c60a15]
|
||||
- fix: typo in Makefile [b82522a]
|
||||
- Allow WithTransform function to accept a nil value (#422) [b75d2f2]
|
||||
- fix: print value type for interface{} containers (#409) [f08e2dc]
|
||||
- fix(BeElementOf): consistently flatten expected values [1fa9468]
|
||||
|
||||
## 1.10.5
|
||||
|
||||
### Fixes
|
||||
- fix: collections matchers should display type of expectation (#408) [6b4eb5a]
|
||||
- fix(ContainElements): consistently flatten expected values [073b880]
|
||||
- fix(ConsistOf): consistently flatten expected values [7266efe]
|
||||
|
||||
## 1.10.4
|
||||
|
||||
### Fixes
|
||||
- update golang net library to more recent version without vulnerability (#406) [817a8b9]
|
||||
- Correct spelling: alloted -> allotted (#403) [0bae715]
|
||||
- fix a panic in MessageWithDiff with long message (#402) [ea06b9b]
|
||||
|
||||
## 1.10.3
|
||||
|
||||
### Fixes
|
||||
- updates golang/x/net to fix vulnerability detected by snyk (#394) [c479356]
|
||||
|
||||
## 1.10.2
|
||||
|
||||
### Fixes
|
||||
- Add ExpectWithOffset, EventuallyWithOffset and ConsistentlyWithOffset to WithT (#391) [990941a]
|
||||
|
||||
## 1.10.1
|
||||
|
||||
### Fixes
|
||||
- Update dependencies (#389) [9f5eecd]
|
||||
|
||||
## 1.10.0
|
||||
|
||||
### Features
|
||||
- Add HaveHTTPStatusMatcher (#378) [f335c94]
|
||||
- Changed matcher for content-type in VerifyJSONRepresenting (#377) [6024f5b]
|
||||
- Make ghttp usable with x-unit style tests (#376) [c0be499]
|
||||
- Implement PanicWith matcher (#381) [f8032b4]
|
||||
|
||||
## 1.9.0
|
||||
|
||||
### Features
|
||||
- Add ContainElements matcher (#370) [2f57380]
|
||||
- Output missing and extra elements in ConsistOf failure message [a31eda7]
|
||||
- Document method LargestMatching [7c5a280]
|
||||
|
||||
## 1.8.1
|
||||
|
||||
### Fixes
|
||||
- Fix unexpected MatchError() behaviour (#375) [8ae7b2f]
|
||||
|
||||
## 1.8.0
|
||||
|
||||
### Features
|
||||
- Allow optional description to be lazily evaluated function (#364) [bf64010]
|
||||
- Support wrapped errors (#359) [0a981cb]
|
||||
|
||||
## 1.7.1
|
||||
|
||||
### Fixes
|
||||
- Bump go-yaml version to cover fixed ddos heuristic (#362) [95e431e]
|
||||
|
||||
## 1.7.0
|
||||
|
||||
### Features
|
||||
- export format property variables (#347) [642e5ba]
|
||||
|
||||
### Fixes
|
||||
- minor fix in the documentation of ExpectWithOffset (#358) [beea727]
|
||||
|
||||
## 1.6.0
|
||||
|
||||
### Features
|
||||
|
||||
- Display special chars on error [41e1b26]
|
||||
- Add BeElementOf matcher [6a48b48]
|
||||
|
||||
### Fixes
|
||||
|
||||
- Remove duplication in XML matcher tests [cc1a6cb]
|
||||
- Remove unnecessary conversions (#357) [7bf756a]
|
||||
- Fixed import order (#353) [2e3b965]
|
||||
- Added missing error handling in test (#355) [c98d3eb]
|
||||
- Simplify code (#356) [0001ed9]
|
||||
- Simplify code (#354) [0d9100e]
|
||||
- Fixed typos (#352) [3f647c4]
|
||||
- Add failure message tests to BeElementOf matcher [efe19c3]
|
||||
- Update go-testcov untested sections [37ee382]
|
||||
- Mark all uncovered files so go-testcov ./... works [53b150e]
|
||||
- Reenable gotip in travis [5c249dc]
|
||||
- Fix the typo of comment (#345) [f0e010e]
|
||||
- Optimize contain_element_matcher [abeb93d]
|
||||
|
||||
|
||||
## 1.5.0
|
||||
|
||||
### Features
|
||||
|
||||
- Added MatchKeys matchers [8b909fc]
|
||||
|
||||
### Fixes and Minor Improvements
|
||||
|
||||
- Add type aliases to remove stuttering [03b0461]
|
||||
- Don't run session_test.go on windows (#324) [5533ce8]
|
||||
|
||||
## 1.4.3
|
||||
|
||||
### Fixes:
|
||||
|
||||
- ensure file name and line numbers are correctly reported for XUnit [6fff58f]
|
||||
- Fixed matcher for content-type (#305) [69d9b43]
|
||||
|
||||
## 1.4.2
|
||||
|
||||
### Fixes:
|
||||
|
||||
- Add go.mod and go.sum files to define the gomega go module [f3de367, a085d30]
|
||||
- Work around go vet issue with Go v1.11 (#300) [40dd6ad]
|
||||
- Better output when using with go XUnit-style tests, fixes #255 (#297) [29a4b97]
|
||||
- Fix MatchJSON fail to parse json.RawMessage (#298) [ae19f1b]
|
||||
- show threshold in failure message of BeNumericallyMatcher (#293) [4bbecc8]
|
||||
|
||||
## 1.4.1
|
||||
|
||||
### Fixes:
|
||||
|
||||
- Update documentation formatting and examples (#289) [9be8410]
|
||||
- allow 'Receive' matcher to be used with concrete types (#286) [41673fd]
|
||||
- Fix data race in ghttp server (#283) [7ac6b01]
|
||||
- Travis badge should only show master [cc102ab]
|
||||
|
||||
## 1.4.0
|
||||
|
||||
### Features
|
||||
- Make string pretty diff user configurable (#273) [eb112ce, 649b44d]
|
||||
|
||||
### Fixes
|
||||
- Use httputil.DumpRequest to pretty-print unhandled requests (#278) [a4ff0fc, b7d1a52]
|
||||
- fix typo floa32 > float32 (#272) [041ae3b, 6e33911]
|
||||
- Fix link to documentation on adding your own matchers (#270) [bb2c830, fcebc62]
|
||||
- Use setters and getters to avoid race condition (#262) [13057c3, a9c79f1]
|
||||
- Avoid sending a signal if the process is not alive (#259) [b8043e5, 4fc1762]
|
||||
- Improve message from AssignableToTypeOf when expected value is nil (#281) [9c1fb20]
|
||||
|
||||
## 1.3.0
|
||||
|
||||
Improvements:
|
||||
|
||||
- The `Equal` matcher matches byte slices more performantly.
|
||||
- Improved how `MatchError` matches error strings.
|
||||
- `MatchXML` ignores the order of xml node attributes.
|
||||
- Improve support for XUnit style golang tests. ([#254](https://github.com/onsi/gomega/issues/254))
|
||||
|
||||
Bug Fixes:
|
||||
|
||||
- Diff generation now handles multi-byte sequences correctly.
|
||||
- Multiple goroutines can now call `gexec.Build` concurrently.
|
||||
|
||||
## 1.2.0
|
||||
|
||||
Improvements:
|
||||
|
||||
- Added `BeSent` which attempts to send a value down a channel and fails if the attempt blocks. Can be paired with `Eventually` to safely send a value down a channel with a timeout.
|
||||
- `Ω`, `Expect`, `Eventually`, and `Consistently` now immediately `panic` if there is no registered fail handler. This is always a mistake that can hide failing tests.
|
||||
- `Receive()` no longer errors when passed a closed channel, it's perfectly fine to attempt to read from a closed channel so Ω(c).Should(Receive()) always fails and Ω(c).ShoudlNot(Receive()) always passes with a closed channel.
|
||||
- Added `HavePrefix` and `HaveSuffix` matchers.
|
||||
- `ghttp` can now handle concurrent requests.
|
||||
- Added `Succeed` which allows one to write `Ω(MyFunction()).Should(Succeed())`.
|
||||
- Improved `ghttp`'s behavior around failing assertions and panics:
|
||||
- If a registered handler makes a failing assertion `ghttp` will return `500`.
|
||||
- If a registered handler panics, `ghttp` will return `500` *and* fail the test. This is new behavior that may cause existing code to break. This code is almost certainly incorrect and creating a false positive.
|
||||
- `ghttp` servers can take an `io.Writer`. `ghttp` will write a line to the writer when each request arrives.
|
||||
- Added `WithTransform` matcher to allow munging input data before feeding into the relevant matcher
|
||||
- Added boolean `And`, `Or`, and `Not` matchers to allow creating composite matchers
|
||||
- Added `gbytes.TimeoutCloser`, `gbytes.TimeoutReader`, and `gbytes.TimeoutWriter` - these are convenience wrappers that timeout if the underlying Closer/Reader/Writer does not return within the alloted time.
|
||||
- Added `gbytes.BufferReader` - this constructs a `gbytes.Buffer` that asynchronously reads the passed-in `io.Reader` into its buffer.
|
||||
|
||||
Bug Fixes:
|
||||
- gexec: `session.Wait` now uses `EventuallyWithOffset` to get the right line number in the failure.
|
||||
- `ContainElement` no longer bails if a passed-in matcher errors.
|
||||
|
||||
## 1.0 (8/2/2014)
|
||||
|
||||
No changes. Dropping "beta" from the version number.
|
||||
|
||||
## 1.0.0-beta (7/8/2014)
|
||||
Breaking Changes:
|
||||
|
||||
- Changed OmegaMatcher interface. Instead of having `Match` return failure messages, two new methods `FailureMessage` and `NegatedFailureMessage` are called instead.
|
||||
- Moved and renamed OmegaFailHandler to types.GomegaFailHandler and OmegaMatcher to types.GomegaMatcher. Any references to OmegaMatcher in any custom matchers will need to be changed to point to types.GomegaMatcher
|
||||
|
||||
New Test-Support Features:
|
||||
|
||||
- `ghttp`: supports testing http clients
|
||||
- Provides a flexible fake http server
|
||||
- Provides a collection of chainable http handlers that perform assertions.
|
||||
- `gbytes`: supports making ordered assertions against streams of data
|
||||
- Provides a `gbytes.Buffer`
|
||||
- Provides a `Say` matcher to perform ordered assertions against output data
|
||||
- `gexec`: supports testing external processes
|
||||
- Provides support for building Go binaries
|
||||
- Wraps and starts `exec.Cmd` commands
|
||||
- Makes it easy to assert against stdout and stderr
|
||||
- Makes it easy to send signals and wait for processes to exit
|
||||
- Provides an `Exit` matcher to assert against exit code.
|
||||
|
||||
DSL Changes:
|
||||
|
||||
- `Eventually` and `Consistently` can accept `time.Duration` interval and polling inputs.
|
||||
- The default timeouts for `Eventually` and `Consistently` are now configurable.
|
||||
|
||||
New Matchers:
|
||||
|
||||
- `ConsistOf`: order-independent assertion against the elements of an array/slice or keys of a map.
|
||||
- `BeTemporally`: like `BeNumerically` but for `time.Time`
|
||||
- `HaveKeyWithValue`: asserts a map has a given key with the given value.
|
||||
|
||||
Updated Matchers:
|
||||
|
||||
- `Receive` matcher can take a matcher as an argument and passes only if the channel under test receives an objet that satisfies the passed-in matcher.
|
||||
- Matchers that implement `MatchMayChangeInTheFuture(actual interface{}) bool` can inform `Eventually` and/or `Consistently` when a match has no chance of changing status in the future. For example, `Receive` returns `false` when a channel is closed.
|
||||
|
||||
Misc:
|
||||
|
||||
- Start using semantic versioning
|
||||
- Start maintaining changelog
|
||||
|
||||
Major refactor:
|
||||
|
||||
- Pull out Gomega's internal to `internal`
|
14
vendor/github.com/onsi/gomega/CONTRIBUTING.md
generated
vendored
Normal file
14
vendor/github.com/onsi/gomega/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# Contributing to Gomega
|
||||
|
||||
Your contributions to Gomega are essential for its long-term maintenance and improvement. To make a contribution:
|
||||
|
||||
- Please **open an issue first** - describe what problem you are trying to solve and give the community a forum for input and feedback ahead of investing time in writing code!
|
||||
- Ensure adequate test coverage:
|
||||
- Make sure to add appropriate unit tests
|
||||
- Please run all tests locally (`ginkgo -r -p`) and make sure they go green before submitting the PR
|
||||
- Please run following linter locally `go vet ./...` and make sure output does not contain any warnings
|
||||
- Update the documentation. In addition to standard `godoc` comments Gomega has extensive documentation on the `gh-pages` branch. If relevant, please submit a docs PR to that branch alongside your code PR.
|
||||
|
||||
If you're a committer, check out RELEASING.md to learn how to cut a release.
|
||||
|
||||
Thanks for supporting Gomega!
|
20
vendor/github.com/onsi/gomega/LICENSE
generated
vendored
Normal file
20
vendor/github.com/onsi/gomega/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2013-2014 Onsi Fakhouri
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
vendor/github.com/onsi/gomega/README.md
generated
vendored
Normal file
21
vendor/github.com/onsi/gomega/README.md
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||

|
||||
|
||||
[](https://github.com/onsi/gomega/actions/workflows/test.yml)
|
||||
|
||||
Jump straight to the [docs](http://onsi.github.io/gomega/) to learn about Gomega, including a list of [all available matchers](http://onsi.github.io/gomega/#provided-matchers).
|
||||
|
||||
If you have a question, comment, bug report, feature request, etc. please open a GitHub issue.
|
||||
|
||||
## [Ginkgo](http://github.com/onsi/ginkgo): a BDD Testing Framework for Golang
|
||||
|
||||
Learn more about Ginkgo [here](http://onsi.github.io/ginkgo/)
|
||||
|
||||
## Community Matchers
|
||||
|
||||
A collection of community matchers is available on the [wiki](https://github.com/onsi/gomega/wiki).
|
||||
|
||||
## License
|
||||
|
||||
Gomega is MIT-Licensed
|
||||
|
||||
The `ConsistOf` matcher uses [goraph](https://github.com/amitkgupta/goraph) which is embedded in the source to simplify distribution. goraph has an MIT license.
|
17
vendor/github.com/onsi/gomega/RELEASING.md
generated
vendored
Normal file
17
vendor/github.com/onsi/gomega/RELEASING.md
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
A Gomega release is a tagged sha and a GitHub release. To cut a release:
|
||||
|
||||
1. Ensure CHANGELOG.md is up to date.
|
||||
- Use `git log --pretty=format:'- %s [%h]' HEAD...vX.X.X` to list all the commits since the last release
|
||||
- Categorize the changes into
|
||||
- Breaking Changes (requires a major version)
|
||||
- New Features (minor version)
|
||||
- Fixes (fix version)
|
||||
- Maintenance (which in general should not be mentioned in `CHANGELOG.md` as they have no user impact)
|
||||
1. Update GOMEGA_VERSION in `gomega_dsl.go`
|
||||
1. Commit, push, and release:
|
||||
```
|
||||
git commit -m "vM.m.p"
|
||||
git push
|
||||
gh release create "vM.m.p"
|
||||
git fetch --tags origin master
|
||||
```
|
440
vendor/github.com/onsi/gomega/format/format.go
generated
vendored
Normal file
440
vendor/github.com/onsi/gomega/format/format.go
generated
vendored
Normal file
@@ -0,0 +1,440 @@
|
||||
/*
|
||||
Gomega's format package pretty-prints objects. It explores input objects recursively and generates formatted, indented output with type information.
|
||||
*/
|
||||
|
||||
// untested sections: 4
|
||||
|
||||
package format
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Use MaxDepth to set the maximum recursion depth when printing deeply nested objects
|
||||
var MaxDepth = uint(10)
|
||||
|
||||
// MaxLength of the string representation of an object.
|
||||
// If MaxLength is set to 0, the Object will not be truncated.
|
||||
var MaxLength = 4000
|
||||
|
||||
/*
|
||||
By default, all objects (even those that implement fmt.Stringer and fmt.GoStringer) are recursively inspected to generate output.
|
||||
|
||||
Set UseStringerRepresentation = true to use GoString (for fmt.GoStringers) or String (for fmt.Stringer) instead.
|
||||
|
||||
Note that GoString and String don't always have all the information you need to understand why a test failed!
|
||||
*/
|
||||
var UseStringerRepresentation = false
|
||||
|
||||
/*
|
||||
Print the content of context objects. By default it will be suppressed.
|
||||
|
||||
Set PrintContextObjects = true to enable printing of the context internals.
|
||||
*/
|
||||
var PrintContextObjects = false
|
||||
|
||||
// TruncatedDiff choose if we should display a truncated pretty diff or not
|
||||
var TruncatedDiff = true
|
||||
|
||||
// TruncateThreshold (default 50) specifies the maximum length string to print in string comparison assertion error
|
||||
// messages.
|
||||
var TruncateThreshold uint = 50
|
||||
|
||||
// CharactersAroundMismatchToInclude (default 5) specifies how many contextual characters should be printed before and
|
||||
// after the first diff location in a truncated string assertion error message.
|
||||
var CharactersAroundMismatchToInclude uint = 5
|
||||
|
||||
var contextType = reflect.TypeOf((*context.Context)(nil)).Elem()
|
||||
var timeType = reflect.TypeOf(time.Time{})
|
||||
|
||||
//The default indentation string emitted by the format package
|
||||
var Indent = " "
|
||||
|
||||
var longFormThreshold = 20
|
||||
|
||||
// GomegaStringer allows for custom formating of objects for gomega.
|
||||
type GomegaStringer interface {
|
||||
// GomegaString will be used to custom format an object.
|
||||
// It does not follow UseStringerRepresentation value and will always be called regardless.
|
||||
// It also ignores the MaxLength value.
|
||||
GomegaString() string
|
||||
}
|
||||
|
||||
/*
|
||||
Generates a formatted matcher success/failure message of the form:
|
||||
|
||||
Expected
|
||||
<pretty printed actual>
|
||||
<message>
|
||||
<pretty printed expected>
|
||||
|
||||
If expected is omitted, then the message looks like:
|
||||
|
||||
Expected
|
||||
<pretty printed actual>
|
||||
<message>
|
||||
*/
|
||||
func Message(actual interface{}, message string, expected ...interface{}) string {
|
||||
if len(expected) == 0 {
|
||||
return fmt.Sprintf("Expected\n%s\n%s", Object(actual, 1), message)
|
||||
}
|
||||
return fmt.Sprintf("Expected\n%s\n%s\n%s", Object(actual, 1), message, Object(expected[0], 1))
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Generates a nicely formatted matcher success / failure message
|
||||
|
||||
Much like Message(...), but it attempts to pretty print diffs in strings
|
||||
|
||||
Expected
|
||||
<string>: "...aaaaabaaaaa..."
|
||||
to equal |
|
||||
<string>: "...aaaaazaaaaa..."
|
||||
|
||||
*/
|
||||
|
||||
func MessageWithDiff(actual, message, expected string) string {
|
||||
if TruncatedDiff && len(actual) >= int(TruncateThreshold) && len(expected) >= int(TruncateThreshold) {
|
||||
diffPoint := findFirstMismatch(actual, expected)
|
||||
formattedActual := truncateAndFormat(actual, diffPoint)
|
||||
formattedExpected := truncateAndFormat(expected, diffPoint)
|
||||
|
||||
spacesBeforeFormattedMismatch := findFirstMismatch(formattedActual, formattedExpected)
|
||||
|
||||
tabLength := 4
|
||||
spaceFromMessageToActual := tabLength + len("<string>: ") - len(message)
|
||||
|
||||
paddingCount := spaceFromMessageToActual + spacesBeforeFormattedMismatch
|
||||
if paddingCount < 0 {
|
||||
return Message(formattedActual, message, formattedExpected)
|
||||
}
|
||||
|
||||
padding := strings.Repeat(" ", paddingCount) + "|"
|
||||
return Message(formattedActual, message+padding, formattedExpected)
|
||||
}
|
||||
|
||||
actual = escapedWithGoSyntax(actual)
|
||||
expected = escapedWithGoSyntax(expected)
|
||||
|
||||
return Message(actual, message, expected)
|
||||
}
|
||||
|
||||
func escapedWithGoSyntax(str string) string {
|
||||
withQuotes := fmt.Sprintf("%q", str)
|
||||
return withQuotes[1 : len(withQuotes)-1]
|
||||
}
|
||||
|
||||
func truncateAndFormat(str string, index int) string {
|
||||
leftPadding := `...`
|
||||
rightPadding := `...`
|
||||
|
||||
start := index - int(CharactersAroundMismatchToInclude)
|
||||
if start < 0 {
|
||||
start = 0
|
||||
leftPadding = ""
|
||||
}
|
||||
|
||||
// slice index must include the mis-matched character
|
||||
lengthOfMismatchedCharacter := 1
|
||||
end := index + int(CharactersAroundMismatchToInclude) + lengthOfMismatchedCharacter
|
||||
if end > len(str) {
|
||||
end = len(str)
|
||||
rightPadding = ""
|
||||
|
||||
}
|
||||
return fmt.Sprintf("\"%s\"", leftPadding+str[start:end]+rightPadding)
|
||||
}
|
||||
|
||||
func findFirstMismatch(a, b string) int {
|
||||
aSlice := strings.Split(a, "")
|
||||
bSlice := strings.Split(b, "")
|
||||
|
||||
for index, str := range aSlice {
|
||||
if index > len(bSlice)-1 {
|
||||
return index
|
||||
}
|
||||
if str != bSlice[index] {
|
||||
return index
|
||||
}
|
||||
}
|
||||
|
||||
if len(b) > len(a) {
|
||||
return len(a) + 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
const truncateHelpText = `
|
||||
Gomega truncated this representation as it exceeds 'format.MaxLength'.
|
||||
Consider having the object provide a custom 'GomegaStringer' representation
|
||||
or adjust the parameters in Gomega's 'format' package.
|
||||
|
||||
Learn more here: https://onsi.github.io/gomega/#adjusting-output
|
||||
`
|
||||
|
||||
func truncateLongStrings(s string) string {
|
||||
if MaxLength > 0 && len(s) > MaxLength {
|
||||
var sb strings.Builder
|
||||
for i, r := range s {
|
||||
if i < MaxLength {
|
||||
sb.WriteRune(r)
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
sb.WriteString("...\n")
|
||||
sb.WriteString(truncateHelpText)
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
/*
|
||||
Pretty prints the passed in object at the passed in indentation level.
|
||||
|
||||
Object recurses into deeply nested objects emitting pretty-printed representations of their components.
|
||||
|
||||
Modify format.MaxDepth to control how deep the recursion is allowed to go
|
||||
Set format.UseStringerRepresentation to true to return object.GoString() or object.String() when available instead of
|
||||
recursing into the object.
|
||||
|
||||
Set PrintContextObjects to true to print the content of objects implementing context.Context
|
||||
*/
|
||||
func Object(object interface{}, indentation uint) string {
|
||||
indent := strings.Repeat(Indent, int(indentation))
|
||||
value := reflect.ValueOf(object)
|
||||
return fmt.Sprintf("%s<%s>: %s", indent, formatType(value), formatValue(value, indentation))
|
||||
}
|
||||
|
||||
/*
|
||||
IndentString takes a string and indents each line by the specified amount.
|
||||
*/
|
||||
func IndentString(s string, indentation uint) string {
|
||||
components := strings.Split(s, "\n")
|
||||
result := ""
|
||||
indent := strings.Repeat(Indent, int(indentation))
|
||||
for i, component := range components {
|
||||
result += indent + component
|
||||
if i < len(components)-1 {
|
||||
result += "\n"
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func formatType(v reflect.Value) string {
|
||||
switch v.Kind() {
|
||||
case reflect.Invalid:
|
||||
return "nil"
|
||||
case reflect.Chan:
|
||||
return fmt.Sprintf("%s | len:%d, cap:%d", v.Type(), v.Len(), v.Cap())
|
||||
case reflect.Ptr:
|
||||
return fmt.Sprintf("%s | 0x%x", v.Type(), v.Pointer())
|
||||
case reflect.Slice:
|
||||
return fmt.Sprintf("%s | len:%d, cap:%d", v.Type(), v.Len(), v.Cap())
|
||||
case reflect.Map:
|
||||
return fmt.Sprintf("%s | len:%d", v.Type(), v.Len())
|
||||
default:
|
||||
return fmt.Sprintf("%s", v.Type())
|
||||
}
|
||||
}
|
||||
|
||||
func formatValue(value reflect.Value, indentation uint) string {
|
||||
if indentation > MaxDepth {
|
||||
return "..."
|
||||
}
|
||||
|
||||
if isNilValue(value) {
|
||||
return "nil"
|
||||
}
|
||||
|
||||
if value.CanInterface() {
|
||||
obj := value.Interface()
|
||||
|
||||
// GomegaStringer will take precedence to other representations and disregards UseStringerRepresentation
|
||||
if x, ok := obj.(GomegaStringer); ok {
|
||||
// do not truncate a user-defined GoMegaString() value
|
||||
return x.GomegaString()
|
||||
}
|
||||
|
||||
if UseStringerRepresentation {
|
||||
switch x := obj.(type) {
|
||||
case fmt.GoStringer:
|
||||
return truncateLongStrings(x.GoString())
|
||||
case fmt.Stringer:
|
||||
return truncateLongStrings(x.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !PrintContextObjects {
|
||||
if value.Type().Implements(contextType) && indentation > 1 {
|
||||
return "<suppressed context>"
|
||||
}
|
||||
}
|
||||
|
||||
switch value.Kind() {
|
||||
case reflect.Bool:
|
||||
return fmt.Sprintf("%v", value.Bool())
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return fmt.Sprintf("%v", value.Int())
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return fmt.Sprintf("%v", value.Uint())
|
||||
case reflect.Uintptr:
|
||||
return fmt.Sprintf("0x%x", value.Uint())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return fmt.Sprintf("%v", value.Float())
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
return fmt.Sprintf("%v", value.Complex())
|
||||
case reflect.Chan:
|
||||
return fmt.Sprintf("0x%x", value.Pointer())
|
||||
case reflect.Func:
|
||||
return fmt.Sprintf("0x%x", value.Pointer())
|
||||
case reflect.Ptr:
|
||||
return formatValue(value.Elem(), indentation)
|
||||
case reflect.Slice:
|
||||
return truncateLongStrings(formatSlice(value, indentation))
|
||||
case reflect.String:
|
||||
return truncateLongStrings(formatString(value.String(), indentation))
|
||||
case reflect.Array:
|
||||
return truncateLongStrings(formatSlice(value, indentation))
|
||||
case reflect.Map:
|
||||
return truncateLongStrings(formatMap(value, indentation))
|
||||
case reflect.Struct:
|
||||
if value.Type() == timeType && value.CanInterface() {
|
||||
t, _ := value.Interface().(time.Time)
|
||||
return t.Format(time.RFC3339Nano)
|
||||
}
|
||||
return truncateLongStrings(formatStruct(value, indentation))
|
||||
case reflect.Interface:
|
||||
return formatInterface(value, indentation)
|
||||
default:
|
||||
if value.CanInterface() {
|
||||
return truncateLongStrings(fmt.Sprintf("%#v", value.Interface()))
|
||||
}
|
||||
return truncateLongStrings(fmt.Sprintf("%#v", value))
|
||||
}
|
||||
}
|
||||
|
||||
func formatString(object interface{}, indentation uint) string {
|
||||
if indentation == 1 {
|
||||
s := fmt.Sprintf("%s", object)
|
||||
components := strings.Split(s, "\n")
|
||||
result := ""
|
||||
for i, component := range components {
|
||||
if i == 0 {
|
||||
result += component
|
||||
} else {
|
||||
result += Indent + component
|
||||
}
|
||||
if i < len(components)-1 {
|
||||
result += "\n"
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
} else {
|
||||
return fmt.Sprintf("%q", object)
|
||||
}
|
||||
}
|
||||
|
||||
func formatSlice(v reflect.Value, indentation uint) string {
|
||||
if v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Uint8 && isPrintableString(string(v.Bytes())) {
|
||||
return formatString(v.Bytes(), indentation)
|
||||
}
|
||||
|
||||
l := v.Len()
|
||||
result := make([]string, l)
|
||||
longest := 0
|
||||
for i := 0; i < l; i++ {
|
||||
result[i] = formatValue(v.Index(i), indentation+1)
|
||||
if len(result[i]) > longest {
|
||||
longest = len(result[i])
|
||||
}
|
||||
}
|
||||
|
||||
if longest > longFormThreshold {
|
||||
indenter := strings.Repeat(Indent, int(indentation))
|
||||
return fmt.Sprintf("[\n%s%s,\n%s]", indenter+Indent, strings.Join(result, ",\n"+indenter+Indent), indenter)
|
||||
}
|
||||
return fmt.Sprintf("[%s]", strings.Join(result, ", "))
|
||||
}
|
||||
|
||||
func formatMap(v reflect.Value, indentation uint) string {
|
||||
l := v.Len()
|
||||
result := make([]string, l)
|
||||
|
||||
longest := 0
|
||||
for i, key := range v.MapKeys() {
|
||||
value := v.MapIndex(key)
|
||||
result[i] = fmt.Sprintf("%s: %s", formatValue(key, indentation+1), formatValue(value, indentation+1))
|
||||
if len(result[i]) > longest {
|
||||
longest = len(result[i])
|
||||
}
|
||||
}
|
||||
|
||||
if longest > longFormThreshold {
|
||||
indenter := strings.Repeat(Indent, int(indentation))
|
||||
return fmt.Sprintf("{\n%s%s,\n%s}", indenter+Indent, strings.Join(result, ",\n"+indenter+Indent), indenter)
|
||||
}
|
||||
return fmt.Sprintf("{%s}", strings.Join(result, ", "))
|
||||
}
|
||||
|
||||
func formatStruct(v reflect.Value, indentation uint) string {
|
||||
t := v.Type()
|
||||
|
||||
l := v.NumField()
|
||||
result := []string{}
|
||||
longest := 0
|
||||
for i := 0; i < l; i++ {
|
||||
structField := t.Field(i)
|
||||
fieldEntry := v.Field(i)
|
||||
representation := fmt.Sprintf("%s: %s", structField.Name, formatValue(fieldEntry, indentation+1))
|
||||
result = append(result, representation)
|
||||
if len(representation) > longest {
|
||||
longest = len(representation)
|
||||
}
|
||||
}
|
||||
if longest > longFormThreshold {
|
||||
indenter := strings.Repeat(Indent, int(indentation))
|
||||
return fmt.Sprintf("{\n%s%s,\n%s}", indenter+Indent, strings.Join(result, ",\n"+indenter+Indent), indenter)
|
||||
}
|
||||
return fmt.Sprintf("{%s}", strings.Join(result, ", "))
|
||||
}
|
||||
|
||||
func formatInterface(v reflect.Value, indentation uint) string {
|
||||
return fmt.Sprintf("<%s>%s", formatType(v.Elem()), formatValue(v.Elem(), indentation))
|
||||
}
|
||||
|
||||
func isNilValue(a reflect.Value) bool {
|
||||
switch a.Kind() {
|
||||
case reflect.Invalid:
|
||||
return true
|
||||
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
|
||||
return a.IsNil()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/*
|
||||
Returns true when the string is entirely made of printable runes, false otherwise.
|
||||
*/
|
||||
func isPrintableString(str string) bool {
|
||||
for _, runeValue := range str {
|
||||
if !strconv.IsPrint(runeValue) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
435
vendor/github.com/onsi/gomega/gomega_dsl.go
generated
vendored
Normal file
435
vendor/github.com/onsi/gomega/gomega_dsl.go
generated
vendored
Normal file
@@ -0,0 +1,435 @@
|
||||
/*
|
||||
Gomega is the Ginkgo BDD-style testing framework's preferred matcher library.
|
||||
|
||||
The godoc documentation describes Gomega's API. More comprehensive documentation (with examples!) is available at http://onsi.github.io/gomega/
|
||||
|
||||
Gomega on Github: http://github.com/onsi/gomega
|
||||
|
||||
Learn more about Ginkgo online: http://onsi.github.io/ginkgo
|
||||
|
||||
Ginkgo on Github: http://github.com/onsi/ginkgo
|
||||
|
||||
Gomega is MIT-Licensed
|
||||
*/
|
||||
package gomega
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/onsi/gomega/internal"
|
||||
"github.com/onsi/gomega/types"
|
||||
)
|
||||
|
||||
const GOMEGA_VERSION = "1.19.0"
|
||||
|
||||
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().
|
||||
Alternatively, you may have forgotten to register a fail handler with RegisterFailHandler() or RegisterTestingT().
|
||||
Depending on your vendoring solution you may be inadvertently importing gomega and subpackages (e.g. ghhtp, gexec,...) from different locations.
|
||||
`
|
||||
|
||||
// Gomega describes the essential Gomega DSL. This interface allows libraries
|
||||
// to abstract between the standard package-level function implementations
|
||||
// and alternatives like *WithT.
|
||||
//
|
||||
// The types in the top-level DSL have gotten a bit messy due to earlier depracations that avoid stuttering
|
||||
// and due to an accidental use of a concrete type (*WithT) in an earlier release.
|
||||
//
|
||||
// As of 1.15 both the WithT and Ginkgo variants of Gomega are implemented by the same underlying object
|
||||
// however one (the Ginkgo variant) is exported as an interface (types.Gomega) whereas the other (the withT variant)
|
||||
// is shared as a concrete type (*WithT, which is aliased to *internal.Gomega). 1.15 did not clean this mess up to ensure
|
||||
// that declarations of *WithT in existing code are not broken by the upgrade to 1.15.
|
||||
type Gomega = types.Gomega
|
||||
|
||||
// DefaultGomega supplies the standard package-level implementation
|
||||
var Default = Gomega(internal.NewGomega(internal.FetchDefaultDurationBundle()))
|
||||
|
||||
// NewGomega returns an instance of Gomega wired into the passed-in fail handler.
|
||||
// You generally don't need to use this when using Ginkgo - RegisterFailHandler will wire up the global gomega
|
||||
// However creating a NewGomega with a custom fail handler can be useful in contexts where you want to use Gomega's
|
||||
// rich ecosystem of matchers without causing a test to fail. For example, to aggregate a series of potential failures
|
||||
// or for use in a non-test setting.
|
||||
func NewGomega(fail types.GomegaFailHandler) Gomega {
|
||||
return internal.NewGomega(internalGomega(Default).DurationBundle).ConfigureWithFailHandler(fail)
|
||||
}
|
||||
|
||||
// WithT wraps a *testing.T and provides `Expect`, `Eventually`, and `Consistently` methods. This allows you to leverage
|
||||
// Gomega's rich ecosystem of matchers in standard `testing` test suites.
|
||||
//
|
||||
// Use `NewWithT` to instantiate a `WithT`
|
||||
//
|
||||
// As of 1.15 both the WithT and Ginkgo variants of Gomega are implemented by the same underlying object
|
||||
// however one (the Ginkgo variant) is exported as an interface (types.Gomega) whereas the other (the withT variant)
|
||||
// is shared as a concrete type (*WithT, which is aliased to *internal.Gomega). 1.15 did not clean this mess up to ensure
|
||||
// that declarations of *WithT in existing code are not broken by the upgrade to 1.15.
|
||||
type WithT = internal.Gomega
|
||||
|
||||
// GomegaWithT is deprecated in favor of gomega.WithT, which does not stutter.
|
||||
type GomegaWithT = WithT
|
||||
|
||||
// inner is an interface that allows users to provide a wrapper around Default. The wrapper
|
||||
// must implement the inner interface and return either the original Default or the result of
|
||||
// a call to NewGomega().
|
||||
type inner interface {
|
||||
Inner() Gomega
|
||||
}
|
||||
|
||||
func internalGomega(g Gomega) *internal.Gomega {
|
||||
if v, ok := g.(inner); ok {
|
||||
return v.Inner().(*internal.Gomega)
|
||||
}
|
||||
return g.(*internal.Gomega)
|
||||
}
|
||||
|
||||
// NewWithT takes a *testing.T and returngs a `gomega.WithT` allowing you to use `Expect`, `Eventually`, and `Consistently` along with
|
||||
// Gomega's rich ecosystem of matchers in standard `testing` test suits.
|
||||
//
|
||||
// func TestFarmHasCow(t *testing.T) {
|
||||
// g := gomega.NewWithT(t)
|
||||
//
|
||||
// f := farm.New([]string{"Cow", "Horse"})
|
||||
// g.Expect(f.HasCow()).To(BeTrue(), "Farm should have cow")
|
||||
// }
|
||||
func NewWithT(t types.GomegaTestingT) *WithT {
|
||||
return internal.NewGomega(internalGomega(Default).DurationBundle).ConfigureWithT(t)
|
||||
}
|
||||
|
||||
// NewGomegaWithT is deprecated in favor of gomega.NewWithT, which does not stutter.
|
||||
var NewGomegaWithT = NewWithT
|
||||
|
||||
// RegisterFailHandler connects Ginkgo to Gomega. When a matcher fails
|
||||
// the fail handler passed into RegisterFailHandler is called.
|
||||
func RegisterFailHandler(fail types.GomegaFailHandler) {
|
||||
internalGomega(Default).ConfigureWithFailHandler(fail)
|
||||
}
|
||||
|
||||
// RegisterFailHandlerWithT is deprecated and will be removed in a future release.
|
||||
// users should use RegisterFailHandler, or RegisterTestingT
|
||||
func RegisterFailHandlerWithT(_ types.GomegaTestingT, fail types.GomegaFailHandler) {
|
||||
fmt.Println("RegisterFailHandlerWithT is deprecated. Please use RegisterFailHandler or RegisterTestingT instead.")
|
||||
internalGomega(Default).ConfigureWithFailHandler(fail)
|
||||
}
|
||||
|
||||
// RegisterTestingT connects Gomega to Golang's XUnit style
|
||||
// Testing.T tests. It is now deprecated and you should use NewWithT() instead to get a fresh instance of Gomega for each test.
|
||||
func RegisterTestingT(t types.GomegaTestingT) {
|
||||
internalGomega(Default).ConfigureWithT(t)
|
||||
}
|
||||
|
||||
// InterceptGomegaFailures runs a given callback and returns an array of
|
||||
// failure messages generated by any Gomega assertions within the callback.
|
||||
// Exeuction continues after the first failure allowing users to collect all failures
|
||||
// in the callback.
|
||||
//
|
||||
// This is most useful when testing custom matchers, but can also be used to check
|
||||
// on a value using a Gomega assertion without causing a test failure.
|
||||
func InterceptGomegaFailures(f func()) []string {
|
||||
originalHandler := internalGomega(Default).Fail
|
||||
failures := []string{}
|
||||
internalGomega(Default).Fail = func(message string, callerSkip ...int) {
|
||||
failures = append(failures, message)
|
||||
}
|
||||
defer func() {
|
||||
internalGomega(Default).Fail = originalHandler
|
||||
}()
|
||||
f()
|
||||
return failures
|
||||
}
|
||||
|
||||
// InterceptGomegaFailure runs a given callback and returns the first
|
||||
// failure message generated by any Gomega assertions within the callback, wrapped in an error.
|
||||
//
|
||||
// The callback ceases execution as soon as the first failed assertion occurs, however Gomega
|
||||
// does not register a failure with the FailHandler registered via RegisterFailHandler - it is up
|
||||
// to the user to decide what to do with the returned error
|
||||
func InterceptGomegaFailure(f func()) (err error) {
|
||||
originalHandler := internalGomega(Default).Fail
|
||||
internalGomega(Default).Fail = func(message string, callerSkip ...int) {
|
||||
err = errors.New(message)
|
||||
panic("stop execution")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
internalGomega(Default).Fail = originalHandler
|
||||
if e := recover(); e != nil {
|
||||
if err == nil {
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
f()
|
||||
return err
|
||||
}
|
||||
|
||||
func ensureDefaultGomegaIsConfigured() {
|
||||
if !internalGomega(Default).IsConfigured() {
|
||||
panic(nilGomegaPanic)
|
||||
}
|
||||
}
|
||||
|
||||
// Ω wraps an actual value allowing assertions to be made on it:
|
||||
// Ω("foo").Should(Equal("foo"))
|
||||
//
|
||||
// If Ω is passed more than one argument it will pass the *first* argument to the matcher.
|
||||
// All subsequent arguments will be required to be nil/zero.
|
||||
//
|
||||
// This is convenient if you want to make an assertion on a method/function that returns
|
||||
// a value and an error - a common patter in Go.
|
||||
//
|
||||
// For example, given a function with signature:
|
||||
// func MyAmazingThing() (int, error)
|
||||
//
|
||||
// Then:
|
||||
// Ω(MyAmazingThing()).Should(Equal(3))
|
||||
// Will succeed only if `MyAmazingThing()` returns `(3, nil)`
|
||||
//
|
||||
// Ω and Expect are identical
|
||||
func Ω(actual interface{}, extra ...interface{}) Assertion {
|
||||
ensureDefaultGomegaIsConfigured()
|
||||
return Default.Ω(actual, extra...)
|
||||
}
|
||||
|
||||
// Expect wraps an actual value allowing assertions to be made on it:
|
||||
// Expect("foo").To(Equal("foo"))
|
||||
//
|
||||
// If Expect is passed more than one argument it will pass the *first* argument to the matcher.
|
||||
// All subsequent arguments will be required to be nil/zero.
|
||||
//
|
||||
// This is convenient if you want to make an assertion on a method/function that returns
|
||||
// a value and an error - a common patter in Go.
|
||||
//
|
||||
// For example, given a function with signature:
|
||||
// func MyAmazingThing() (int, error)
|
||||
//
|
||||
// Then:
|
||||
// Expect(MyAmazingThing()).Should(Equal(3))
|
||||
// Will succeed only if `MyAmazingThing()` returns `(3, nil)`
|
||||
//
|
||||
// Expect and Ω are identical
|
||||
func Expect(actual interface{}, extra ...interface{}) Assertion {
|
||||
ensureDefaultGomegaIsConfigured()
|
||||
return Default.Expect(actual, extra...)
|
||||
}
|
||||
|
||||
// ExpectWithOffset wraps an actual value allowing assertions to be made on it:
|
||||
// ExpectWithOffset(1, "foo").To(Equal("foo"))
|
||||
//
|
||||
// Unlike `Expect` and `Ω`, `ExpectWithOffset` takes an additional integer argument
|
||||
// that is used to modify the call-stack offset when computing line numbers. It is
|
||||
// the same as `Expect(...).WithOffset`.
|
||||
//
|
||||
// This is most useful in helper functions that make assertions. If you want Gomega's
|
||||
// error message to refer to the calling line in the test (as opposed to the line in the helper function)
|
||||
// set the first argument of `ExpectWithOffset` appropriately.
|
||||
func ExpectWithOffset(offset int, actual interface{}, extra ...interface{}) Assertion {
|
||||
ensureDefaultGomegaIsConfigured()
|
||||
return Default.ExpectWithOffset(offset, actual, extra...)
|
||||
}
|
||||
|
||||
/*
|
||||
Eventually enables making assertions on asynchronous behavior.
|
||||
|
||||
Eventually checks that an assertion *eventually* passes. Eventually blocks when called and attempts an assertion periodically until it passes or a timeout occurs. Both the timeout and polling interval are configurable as optional arguments.
|
||||
The first optional argument is the timeout (which defaults to 1s), the second is the polling interval (which defaults to 10ms). Both intervals can be specified as time.Duration, parsable duration strings or floats/integers (in which case they are interpreted as seconds).
|
||||
|
||||
Eventually works with any Gomega compatible matcher and supports making assertions against three categories of actual value:
|
||||
|
||||
**Category 1: Making Eventually assertions on values**
|
||||
|
||||
There are several examples of values that can change over time. These can be passed in to Eventually and will be passed to the matcher repeatedly until a match occurs. For example:
|
||||
|
||||
c := make(chan bool)
|
||||
go DoStuff(c)
|
||||
Eventually(c, "50ms").Should(BeClosed())
|
||||
|
||||
will poll the channel repeatedly until it is closed. In this example `Eventually` will block until either the specified timeout of 50ms has elapsed or the channel is closed, whichever comes first.
|
||||
|
||||
Several Gomega libraries allow you to use Eventually in this way. For example, the gomega/gexec package allows you to block until a *gexec.Session exits successfuly via:
|
||||
|
||||
Eventually(session).Should(gexec.Exit(0))
|
||||
|
||||
And the gomega/gbytes package allows you to monitor a streaming *gbytes.Buffer until a given string is seen:
|
||||
|
||||
Eventually(buffer).Should(gbytes.Say("hello there"))
|
||||
|
||||
In these examples, both `session` and `buffer` are designed to be thread-safe when polled by the `Exit` and `Say` matchers. This is not true in general of most raw values, so while it is tempting to do something like:
|
||||
|
||||
// THIS IS NOT THREAD-SAFE
|
||||
var s *string
|
||||
go mutateStringEventually(s)
|
||||
Eventually(s).Should(Equal("I've changed"))
|
||||
|
||||
this will trigger Go's race detector as the goroutine polling via Eventually will race over the value of s with the goroutine mutating the string. For cases like this you can use channels or introduce your own locking around s by passing Eventually a function.
|
||||
|
||||
**Category 2: Make Eventually assertions on functions**
|
||||
|
||||
Eventually can be passed functions that **take no arguments** and **return at least one value**. When configured this way, Eventually will poll the function repeatedly and pass the first returned value to the matcher.
|
||||
|
||||
For example:
|
||||
|
||||
Eventually(func() int {
|
||||
return client.FetchCount()
|
||||
}).Should(BeNumerically(">=", 17))
|
||||
|
||||
will repeatedly poll client.FetchCount until the BeNumerically matcher is satisfied. (Note that this example could have been written as Eventually(client.FetchCount).Should(BeNumerically(">=", 17)))
|
||||
|
||||
If multple values are returned by the function, Eventually will pass the first value to the matcher and require that all others are zero-valued. This allows you to pass Eventually a function that returns a value and an error - a common patternin Go.
|
||||
|
||||
For example, consider a method that returns a value and an error:
|
||||
func FetchFromDB() (string, error)
|
||||
|
||||
Then
|
||||
Eventually(FetchFromDB).Should(Equal("got it"))
|
||||
|
||||
will pass only if and when the returned error is nil *and* the returned string satisfies the matcher.
|
||||
|
||||
It is important to note that the function passed into Eventually is invoked *synchronously* when polled. Eventually does not (in fact, it cannot) kill the function if it takes longer to return than Eventually's configured timeout. You should design your functions with this in mind.
|
||||
|
||||
**Category 3: Making assertions _in_ the function passed into Eventually**
|
||||
|
||||
When testing complex systems it can be valuable to assert that a _set_ of assertions passes Eventually. Eventually supports this by accepting functions that take a single Gomega argument and return zero or more values.
|
||||
|
||||
Here's an example that makes some asssertions and returns a value and error:
|
||||
|
||||
Eventually(func(g Gomega) (Widget, error) {
|
||||
ids, err := client.FetchIDs()
|
||||
g.Expect(err).NotTo(HaveOccurred())
|
||||
g.Expect(ids).To(ContainElement(1138))
|
||||
return client.FetchWidget(1138)
|
||||
}).Should(Equal(expectedWidget))
|
||||
|
||||
will pass only if all the assertions in the polled function pass and the return value satisfied the matcher.
|
||||
|
||||
Eventually also supports a special case polling function that takes a single Gomega argument and returns no values. Eventually assumes such a function is making assertions and is designed to work with the Succeed matcher to validate that all assertions have passed.
|
||||
For example:
|
||||
|
||||
Eventually(func(g Gomega) {
|
||||
model, err := client.Find(1138)
|
||||
g.Expect(err).NotTo(HaveOccurred())
|
||||
g.Expect(model.Reticulate()).To(Succeed())
|
||||
g.Expect(model.IsReticulated()).To(BeTrue())
|
||||
g.Expect(model.Save()).To(Succeed())
|
||||
}).Should(Succeed())
|
||||
|
||||
will rerun the function until all assertions pass.
|
||||
|
||||
`Eventually` specifying a timeout interval (and an optional polling interval) are
|
||||
the same as `Eventually(...).WithTimeout` or `Eventually(...).WithTimeout(...).WithPolling`.
|
||||
*/
|
||||
func Eventually(actual interface{}, intervals ...interface{}) AsyncAssertion {
|
||||
ensureDefaultGomegaIsConfigured()
|
||||
return Default.Eventually(actual, intervals...)
|
||||
}
|
||||
|
||||
// EventuallyWithOffset operates like Eventually but takes an additional
|
||||
// initial argument to indicate an offset in the call stack. This is useful when building helper
|
||||
// functions that contain matchers. To learn more, read about `ExpectWithOffset`.
|
||||
//
|
||||
// `EventuallyWithOffset` is the same as `Eventually(...).WithOffset`.
|
||||
//
|
||||
// `EventuallyWithOffset` specifying a timeout interval (and an optional polling interval) are
|
||||
// the same as `Eventually(...).WithOffset(...).WithTimeout` or
|
||||
// `Eventually(...).WithOffset(...).WithTimeout(...).WithPolling`.
|
||||
func EventuallyWithOffset(offset int, actual interface{}, intervals ...interface{}) AsyncAssertion {
|
||||
ensureDefaultGomegaIsConfigured()
|
||||
return Default.EventuallyWithOffset(offset, actual, intervals...)
|
||||
}
|
||||
|
||||
/*
|
||||
Consistently, like Eventually, enables making assertions on asynchronous behavior.
|
||||
|
||||
Consistently blocks when called for a specified duration. During that duration Consistently repeatedly polls its matcher and ensures that it is satisfied. If the matcher is consistently satisfied, then Consistently will pass. Otherwise Consistently will fail.
|
||||
|
||||
Both the total waiting duration and the polling interval are configurable as optional arguments. The first optional arugment is the duration that Consistently will run for (defaults to 100ms), and the second argument is the polling interval (defaults to 10ms). As with Eventually, these intervals can be passed in as time.Duration, parsable duration strings or an integer or float number of seconds.
|
||||
|
||||
Consistently accepts the same three categories of actual as Eventually, check the Eventually docs to learn more.
|
||||
|
||||
Consistently is useful in cases where you want to assert that something *does not happen* for a period of time. For example, you may want to assert that a goroutine does *not* send data down a channel. In this case you could write:
|
||||
|
||||
Consistently(channel, "200ms").ShouldNot(Receive())
|
||||
|
||||
This will block for 200 milliseconds and repeatedly check the channel and ensure nothing has been received.
|
||||
*/
|
||||
func Consistently(actual interface{}, intervals ...interface{}) AsyncAssertion {
|
||||
ensureDefaultGomegaIsConfigured()
|
||||
return Default.Consistently(actual, intervals...)
|
||||
}
|
||||
|
||||
// ConsistentlyWithOffset operates like Consistently but takes an additional
|
||||
// initial argument to indicate an offset in the call stack. This is useful when building helper
|
||||
// functions that contain matchers. To learn more, read about `ExpectWithOffset`.
|
||||
//
|
||||
// `ConsistentlyWithOffset` is the same as `Consistently(...).WithOffset` and
|
||||
// optional `WithTimeout` and `WithPolling`.
|
||||
func ConsistentlyWithOffset(offset int, actual interface{}, intervals ...interface{}) AsyncAssertion {
|
||||
ensureDefaultGomegaIsConfigured()
|
||||
return Default.ConsistentlyWithOffset(offset, actual, intervals...)
|
||||
}
|
||||
|
||||
// SetDefaultEventuallyTimeout sets the default timeout duration for Eventually. Eventually will repeatedly poll your condition until it succeeds, or until this timeout elapses.
|
||||
func SetDefaultEventuallyTimeout(t time.Duration) {
|
||||
Default.SetDefaultEventuallyTimeout(t)
|
||||
}
|
||||
|
||||
// SetDefaultEventuallyPollingInterval sets the default polling interval for Eventually.
|
||||
func SetDefaultEventuallyPollingInterval(t time.Duration) {
|
||||
Default.SetDefaultEventuallyPollingInterval(t)
|
||||
}
|
||||
|
||||
// SetDefaultConsistentlyDuration sets the default duration for Consistently. Consistently will verify that your condition is satisfied for this long.
|
||||
func SetDefaultConsistentlyDuration(t time.Duration) {
|
||||
Default.SetDefaultConsistentlyDuration(t)
|
||||
}
|
||||
|
||||
// SetDefaultConsistentlyPollingInterval sets the default polling interval for Consistently.
|
||||
func SetDefaultConsistentlyPollingInterval(t time.Duration) {
|
||||
Default.SetDefaultConsistentlyPollingInterval(t)
|
||||
}
|
||||
|
||||
// AsyncAssertion is returned by Eventually and Consistently and polls the actual value passed into Eventually against
|
||||
// the matcher passed to the Should and ShouldNot methods.
|
||||
//
|
||||
// Both Should and ShouldNot take a variadic optionalDescription argument.
|
||||
// This argument allows you to make your failure messages more descriptive.
|
||||
// If a single argument of type `func() string` is passed, this function will be lazily evaluated if a failure occurs
|
||||
// and the returned string is used to annotate the failure message.
|
||||
// Otherwise, this argument is passed on to fmt.Sprintf() and then used to annotate the failure message.
|
||||
//
|
||||
// Both Should and ShouldNot return a boolean that is true if the assertion passed and false if it failed.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// Eventually(myChannel).Should(Receive(), "Something should have come down the pipe.")
|
||||
// Consistently(myChannel).ShouldNot(Receive(), func() string { return "Nothing should have come down the pipe." })
|
||||
type AsyncAssertion = types.AsyncAssertion
|
||||
|
||||
// GomegaAsyncAssertion is deprecated in favor of AsyncAssertion, which does not stutter.
|
||||
type GomegaAsyncAssertion = types.AsyncAssertion
|
||||
|
||||
// Assertion is returned by Ω and Expect and compares the actual value to the matcher
|
||||
// passed to the Should/ShouldNot and To/ToNot/NotTo methods.
|
||||
//
|
||||
// Typically Should/ShouldNot are used with Ω and To/ToNot/NotTo are used with Expect
|
||||
// though this is not enforced.
|
||||
//
|
||||
// All methods take a variadic optionalDescription argument.
|
||||
// This argument allows you to make your failure messages more descriptive.
|
||||
// If a single argument of type `func() string` is passed, this function will be lazily evaluated if a failure occurs
|
||||
// and the returned string is used to annotate the failure message.
|
||||
// Otherwise, this argument is passed on to fmt.Sprintf() and then used to annotate the failure message.
|
||||
//
|
||||
// All methods return a bool that is true if the assertion passed and false if it failed.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// Ω(farm.HasCow()).Should(BeTrue(), "Farm %v should have a cow", farm)
|
||||
type Assertion = types.Assertion
|
||||
|
||||
// GomegaAssertion is deprecated in favor of Assertion, which does not stutter.
|
||||
type GomegaAssertion = types.Assertion
|
||||
|
||||
// OmegaMatcher is deprecated in favor of the better-named and better-organized types.GomegaMatcher but sticks around to support existing code that uses it
|
||||
type OmegaMatcher = types.GomegaMatcher
|
150
vendor/github.com/onsi/gomega/internal/assertion.go
generated
vendored
Normal file
150
vendor/github.com/onsi/gomega/internal/assertion.go
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/onsi/gomega/types"
|
||||
)
|
||||
|
||||
type Assertion struct {
|
||||
actuals []interface{} // actual value plus all extra values
|
||||
actualIndex int // value to pass to the matcher
|
||||
vet vetinari // the vet to call before calling Gomega matcher
|
||||
offset int
|
||||
g *Gomega
|
||||
}
|
||||
|
||||
// ...obligatory discworld reference, as "vetineer" doesn't sound ... quite right.
|
||||
type vetinari func(assertion *Assertion, optionalDescription ...interface{}) bool
|
||||
|
||||
func NewAssertion(actualInput interface{}, g *Gomega, offset int, extra ...interface{}) *Assertion {
|
||||
return &Assertion{
|
||||
actuals: append([]interface{}{actualInput}, extra...),
|
||||
actualIndex: 0,
|
||||
vet: (*Assertion).vetActuals,
|
||||
offset: offset,
|
||||
g: g,
|
||||
}
|
||||
}
|
||||
|
||||
func (assertion *Assertion) WithOffset(offset int) types.Assertion {
|
||||
assertion.offset = offset
|
||||
return assertion
|
||||
}
|
||||
|
||||
func (assertion *Assertion) Error() types.Assertion {
|
||||
return &Assertion{
|
||||
actuals: assertion.actuals,
|
||||
actualIndex: len(assertion.actuals) - 1,
|
||||
vet: (*Assertion).vetError,
|
||||
offset: assertion.offset,
|
||||
g: assertion.g,
|
||||
}
|
||||
}
|
||||
|
||||
func (assertion *Assertion) Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
||||
assertion.g.THelper()
|
||||
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, true, optionalDescription...)
|
||||
}
|
||||
|
||||
func (assertion *Assertion) ShouldNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
||||
assertion.g.THelper()
|
||||
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
|
||||
}
|
||||
|
||||
func (assertion *Assertion) To(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
||||
assertion.g.THelper()
|
||||
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, true, optionalDescription...)
|
||||
}
|
||||
|
||||
func (assertion *Assertion) ToNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
||||
assertion.g.THelper()
|
||||
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
|
||||
}
|
||||
|
||||
func (assertion *Assertion) NotTo(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
||||
assertion.g.THelper()
|
||||
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
|
||||
}
|
||||
|
||||
func (assertion *Assertion) buildDescription(optionalDescription ...interface{}) string {
|
||||
switch len(optionalDescription) {
|
||||
case 0:
|
||||
return ""
|
||||
case 1:
|
||||
if describe, ok := optionalDescription[0].(func() string); ok {
|
||||
return describe() + "\n"
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf(optionalDescription[0].(string), optionalDescription[1:]...) + "\n"
|
||||
}
|
||||
|
||||
func (assertion *Assertion) match(matcher types.GomegaMatcher, desiredMatch bool, optionalDescription ...interface{}) bool {
|
||||
actualInput := assertion.actuals[assertion.actualIndex]
|
||||
matches, err := matcher.Match(actualInput)
|
||||
assertion.g.THelper()
|
||||
if err != nil {
|
||||
description := assertion.buildDescription(optionalDescription...)
|
||||
assertion.g.Fail(description+err.Error(), 2+assertion.offset)
|
||||
return false
|
||||
}
|
||||
if matches != desiredMatch {
|
||||
var message string
|
||||
if desiredMatch {
|
||||
message = matcher.FailureMessage(actualInput)
|
||||
} else {
|
||||
message = matcher.NegatedFailureMessage(actualInput)
|
||||
}
|
||||
description := assertion.buildDescription(optionalDescription...)
|
||||
assertion.g.Fail(description+message, 2+assertion.offset)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// vetActuals vets the actual values, with the (optional) exception of a
|
||||
// specific value, such as the first value in case non-error assertions, or the
|
||||
// last value in case of Error()-based assertions.
|
||||
func (assertion *Assertion) vetActuals(optionalDescription ...interface{}) bool {
|
||||
success, message := vetActuals(assertion.actuals, assertion.actualIndex)
|
||||
if success {
|
||||
return true
|
||||
}
|
||||
|
||||
description := assertion.buildDescription(optionalDescription...)
|
||||
assertion.g.THelper()
|
||||
assertion.g.Fail(description+message, 2+assertion.offset)
|
||||
return false
|
||||
}
|
||||
|
||||
// vetError vets the actual values, except for the final error value, in case
|
||||
// the final error value is non-zero. Otherwise, it doesn't vet the actual
|
||||
// values, as these are allowed to take on any values unless there is a non-zero
|
||||
// error value.
|
||||
func (assertion *Assertion) vetError(optionalDescription ...interface{}) bool {
|
||||
if err := assertion.actuals[assertion.actualIndex]; err != nil {
|
||||
// Go error result idiom: all other actual values must be zero values.
|
||||
return assertion.vetActuals(optionalDescription...)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// vetActuals vets a slice of actual values, optionally skipping a particular
|
||||
// value slice element, such as the first or last value slice element.
|
||||
func vetActuals(actuals []interface{}, skipIndex int) (bool, string) {
|
||||
for i, actual := range actuals {
|
||||
if i == skipIndex {
|
||||
continue
|
||||
}
|
||||
if actual != nil {
|
||||
zeroValue := reflect.Zero(reflect.TypeOf(actual)).Interface()
|
||||
if !reflect.DeepEqual(zeroValue, actual) {
|
||||
message := fmt.Sprintf("Unexpected non-nil/non-zero argument at index %d:\n\t<%T>: %#v", i, actual, actual)
|
||||
return false, message
|
||||
}
|
||||
}
|
||||
}
|
||||
return true, ""
|
||||
}
|
235
vendor/github.com/onsi/gomega/internal/async_assertion.go
generated
vendored
Normal file
235
vendor/github.com/onsi/gomega/internal/async_assertion.go
generated
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/onsi/gomega/types"
|
||||
)
|
||||
|
||||
type AsyncAssertionType uint
|
||||
|
||||
const (
|
||||
AsyncAssertionTypeEventually AsyncAssertionType = iota
|
||||
AsyncAssertionTypeConsistently
|
||||
)
|
||||
|
||||
type AsyncAssertion struct {
|
||||
asyncType AsyncAssertionType
|
||||
|
||||
actualIsFunc bool
|
||||
actualValue interface{}
|
||||
actualFunc func() ([]reflect.Value, error)
|
||||
|
||||
timeoutInterval time.Duration
|
||||
pollingInterval time.Duration
|
||||
offset int
|
||||
g *Gomega
|
||||
}
|
||||
|
||||
func NewAsyncAssertion(asyncType AsyncAssertionType, actualInput interface{}, g *Gomega, timeoutInterval time.Duration, pollingInterval time.Duration, offset int) *AsyncAssertion {
|
||||
out := &AsyncAssertion{
|
||||
asyncType: asyncType,
|
||||
timeoutInterval: timeoutInterval,
|
||||
pollingInterval: pollingInterval,
|
||||
offset: offset,
|
||||
g: g,
|
||||
}
|
||||
|
||||
switch actualType := reflect.TypeOf(actualInput); {
|
||||
case actualType.Kind() != reflect.Func:
|
||||
out.actualValue = actualInput
|
||||
case actualType.NumIn() == 0 && actualType.NumOut() > 0:
|
||||
out.actualIsFunc = true
|
||||
out.actualFunc = func() ([]reflect.Value, error) {
|
||||
return reflect.ValueOf(actualInput).Call([]reflect.Value{}), nil
|
||||
}
|
||||
case actualType.NumIn() == 1 && actualType.In(0).Implements(reflect.TypeOf((*types.Gomega)(nil)).Elem()):
|
||||
out.actualIsFunc = true
|
||||
out.actualFunc = func() (values []reflect.Value, err error) {
|
||||
var assertionFailure error
|
||||
assertionCapturingGomega := NewGomega(g.DurationBundle).ConfigureWithFailHandler(func(message string, callerSkip ...int) {
|
||||
skip := 0
|
||||
if len(callerSkip) > 0 {
|
||||
skip = callerSkip[0]
|
||||
}
|
||||
_, file, line, _ := runtime.Caller(skip + 1)
|
||||
assertionFailure = fmt.Errorf("Assertion in callback at %s:%d failed:\n%s", file, line, message)
|
||||
panic("stop execution")
|
||||
})
|
||||
|
||||
defer func() {
|
||||
if actualType.NumOut() == 0 {
|
||||
if assertionFailure == nil {
|
||||
values = []reflect.Value{reflect.Zero(reflect.TypeOf((*error)(nil)).Elem())}
|
||||
} else {
|
||||
values = []reflect.Value{reflect.ValueOf(assertionFailure)}
|
||||
}
|
||||
} else {
|
||||
err = assertionFailure
|
||||
}
|
||||
if e := recover(); e != nil && assertionFailure == nil {
|
||||
panic(e)
|
||||
}
|
||||
}()
|
||||
|
||||
values = reflect.ValueOf(actualInput).Call([]reflect.Value{reflect.ValueOf(assertionCapturingGomega)})
|
||||
return
|
||||
}
|
||||
default:
|
||||
msg := fmt.Sprintf("The function passed to Gomega's async assertions should either take no arguments and return values, or take a single Gomega interface that it can use to make assertions within the body of the function. When taking a Gomega interface the function can optionally return values or return nothing. The function you passed takes %d arguments and returns %d values.", actualType.NumIn(), actualType.NumOut())
|
||||
g.Fail(msg, offset+4)
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (assertion *AsyncAssertion) WithOffset(offset int) types.AsyncAssertion {
|
||||
assertion.offset = offset
|
||||
return assertion
|
||||
}
|
||||
|
||||
func (assertion *AsyncAssertion) WithTimeout(interval time.Duration) types.AsyncAssertion {
|
||||
assertion.timeoutInterval = interval
|
||||
return assertion
|
||||
}
|
||||
|
||||
func (assertion *AsyncAssertion) WithPolling(interval time.Duration) types.AsyncAssertion {
|
||||
assertion.pollingInterval = interval
|
||||
return assertion
|
||||
}
|
||||
|
||||
func (assertion *AsyncAssertion) Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
||||
assertion.g.THelper()
|
||||
return assertion.match(matcher, true, optionalDescription...)
|
||||
}
|
||||
|
||||
func (assertion *AsyncAssertion) ShouldNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
||||
assertion.g.THelper()
|
||||
return assertion.match(matcher, false, optionalDescription...)
|
||||
}
|
||||
|
||||
func (assertion *AsyncAssertion) buildDescription(optionalDescription ...interface{}) string {
|
||||
switch len(optionalDescription) {
|
||||
case 0:
|
||||
return ""
|
||||
case 1:
|
||||
if describe, ok := optionalDescription[0].(func() string); ok {
|
||||
return describe() + "\n"
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf(optionalDescription[0].(string), optionalDescription[1:]...) + "\n"
|
||||
}
|
||||
|
||||
func (assertion *AsyncAssertion) pollActual() (interface{}, error) {
|
||||
if !assertion.actualIsFunc {
|
||||
return assertion.actualValue, nil
|
||||
}
|
||||
|
||||
values, err := assertion.actualFunc()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
extras := []interface{}{nil}
|
||||
for _, value := range values[1:] {
|
||||
extras = append(extras, value.Interface())
|
||||
}
|
||||
success, message := vetActuals(extras, 0)
|
||||
if !success {
|
||||
return nil, errors.New(message)
|
||||
}
|
||||
|
||||
return values[0].Interface(), nil
|
||||
}
|
||||
|
||||
func (assertion *AsyncAssertion) matcherMayChange(matcher types.GomegaMatcher, value interface{}) bool {
|
||||
if assertion.actualIsFunc {
|
||||
return true
|
||||
}
|
||||
return types.MatchMayChangeInTheFuture(matcher, value)
|
||||
}
|
||||
|
||||
func (assertion *AsyncAssertion) match(matcher types.GomegaMatcher, desiredMatch bool, optionalDescription ...interface{}) bool {
|
||||
timer := time.Now()
|
||||
timeout := time.After(assertion.timeoutInterval)
|
||||
|
||||
var matches bool
|
||||
var err error
|
||||
mayChange := true
|
||||
value, err := assertion.pollActual()
|
||||
if err == nil {
|
||||
mayChange = assertion.matcherMayChange(matcher, value)
|
||||
matches, err = matcher.Match(value)
|
||||
}
|
||||
|
||||
assertion.g.THelper()
|
||||
|
||||
fail := func(preamble string) {
|
||||
errMsg := ""
|
||||
message := ""
|
||||
if err != nil {
|
||||
errMsg = "Error: " + err.Error()
|
||||
} else {
|
||||
if desiredMatch {
|
||||
message = matcher.FailureMessage(value)
|
||||
} else {
|
||||
message = matcher.NegatedFailureMessage(value)
|
||||
}
|
||||
}
|
||||
assertion.g.THelper()
|
||||
description := assertion.buildDescription(optionalDescription...)
|
||||
assertion.g.Fail(fmt.Sprintf("%s after %.3fs.\n%s%s%s", preamble, time.Since(timer).Seconds(), description, message, errMsg), 3+assertion.offset)
|
||||
}
|
||||
|
||||
if assertion.asyncType == AsyncAssertionTypeEventually {
|
||||
for {
|
||||
if err == nil && matches == desiredMatch {
|
||||
return true
|
||||
}
|
||||
|
||||
if !mayChange {
|
||||
fail("No future change is possible. Bailing out early")
|
||||
return false
|
||||
}
|
||||
|
||||
select {
|
||||
case <-time.After(assertion.pollingInterval):
|
||||
value, err = assertion.pollActual()
|
||||
if err == nil {
|
||||
mayChange = assertion.matcherMayChange(matcher, value)
|
||||
matches, err = matcher.Match(value)
|
||||
}
|
||||
case <-timeout:
|
||||
fail("Timed out")
|
||||
return false
|
||||
}
|
||||
}
|
||||
} else if assertion.asyncType == AsyncAssertionTypeConsistently {
|
||||
for {
|
||||
if !(err == nil && matches == desiredMatch) {
|
||||
fail("Failed")
|
||||
return false
|
||||
}
|
||||
|
||||
if !mayChange {
|
||||
return true
|
||||
}
|
||||
|
||||
select {
|
||||
case <-time.After(assertion.pollingInterval):
|
||||
value, err = assertion.pollActual()
|
||||
if err == nil {
|
||||
mayChange = assertion.matcherMayChange(matcher, value)
|
||||
matches, err = matcher.Match(value)
|
||||
}
|
||||
case <-timeout:
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
71
vendor/github.com/onsi/gomega/internal/duration_bundle.go
generated
vendored
Normal file
71
vendor/github.com/onsi/gomega/internal/duration_bundle.go
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
type DurationBundle struct {
|
||||
EventuallyTimeout time.Duration
|
||||
EventuallyPollingInterval time.Duration
|
||||
ConsistentlyDuration time.Duration
|
||||
ConsistentlyPollingInterval time.Duration
|
||||
}
|
||||
|
||||
const (
|
||||
EventuallyTimeoutEnvVarName = "GOMEGA_DEFAULT_EVENTUALLY_TIMEOUT"
|
||||
EventuallyPollingIntervalEnvVarName = "GOMEGA_DEFAULT_EVENTUALLY_POLLING_INTERVAL"
|
||||
|
||||
ConsistentlyDurationEnvVarName = "GOMEGA_DEFAULT_CONSISTENTLY_DURATION"
|
||||
ConsistentlyPollingIntervalEnvVarName = "GOMEGA_DEFAULT_CONSISTENTLY_POLLING_INTERVAL"
|
||||
)
|
||||
|
||||
func FetchDefaultDurationBundle() DurationBundle {
|
||||
return DurationBundle{
|
||||
EventuallyTimeout: durationFromEnv(EventuallyTimeoutEnvVarName, time.Second),
|
||||
EventuallyPollingInterval: durationFromEnv(EventuallyPollingIntervalEnvVarName, 10*time.Millisecond),
|
||||
|
||||
ConsistentlyDuration: durationFromEnv(ConsistentlyDurationEnvVarName, 100*time.Millisecond),
|
||||
ConsistentlyPollingInterval: durationFromEnv(ConsistentlyPollingIntervalEnvVarName, 10*time.Millisecond),
|
||||
}
|
||||
}
|
||||
|
||||
func durationFromEnv(key string, defaultDuration time.Duration) time.Duration {
|
||||
value := os.Getenv(key)
|
||||
if value == "" {
|
||||
return defaultDuration
|
||||
}
|
||||
duration, err := time.ParseDuration(value)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Expected a duration when using %s! Parse error %v", key, err))
|
||||
}
|
||||
return duration
|
||||
}
|
||||
|
||||
func toDuration(input interface{}) time.Duration {
|
||||
duration, ok := input.(time.Duration)
|
||||
if ok {
|
||||
return duration
|
||||
}
|
||||
|
||||
value := reflect.ValueOf(input)
|
||||
kind := reflect.TypeOf(input).Kind()
|
||||
|
||||
if reflect.Int <= kind && kind <= reflect.Int64 {
|
||||
return time.Duration(value.Int()) * time.Second
|
||||
} else if reflect.Uint <= kind && kind <= reflect.Uint64 {
|
||||
return time.Duration(value.Uint()) * time.Second
|
||||
} else if reflect.Float32 <= kind && kind <= reflect.Float64 {
|
||||
return time.Duration(value.Float() * float64(time.Second))
|
||||
} else if reflect.String == kind {
|
||||
duration, err := time.ParseDuration(value.String())
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("%#v is not a valid parsable duration string.", input))
|
||||
}
|
||||
return duration
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("%v is not a valid interval. Must be time.Duration, parsable duration string or a number.", input))
|
||||
}
|
102
vendor/github.com/onsi/gomega/internal/gomega.go
generated
vendored
Normal file
102
vendor/github.com/onsi/gomega/internal/gomega.go
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/onsi/gomega/types"
|
||||
)
|
||||
|
||||
type Gomega struct {
|
||||
Fail types.GomegaFailHandler
|
||||
THelper func()
|
||||
DurationBundle DurationBundle
|
||||
}
|
||||
|
||||
func NewGomega(bundle DurationBundle) *Gomega {
|
||||
return &Gomega{
|
||||
Fail: nil,
|
||||
THelper: nil,
|
||||
DurationBundle: bundle,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Gomega) IsConfigured() bool {
|
||||
return g.Fail != nil && g.THelper != nil
|
||||
}
|
||||
|
||||
func (g *Gomega) ConfigureWithFailHandler(fail types.GomegaFailHandler) *Gomega {
|
||||
g.Fail = fail
|
||||
g.THelper = func() {}
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *Gomega) ConfigureWithT(t types.GomegaTestingT) *Gomega {
|
||||
g.Fail = func(message string, _ ...int) {
|
||||
t.Helper()
|
||||
t.Fatalf("\n%s", message)
|
||||
}
|
||||
g.THelper = t.Helper
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *Gomega) Ω(actual interface{}, extra ...interface{}) types.Assertion {
|
||||
return g.ExpectWithOffset(0, actual, extra...)
|
||||
}
|
||||
|
||||
func (g *Gomega) Expect(actual interface{}, extra ...interface{}) types.Assertion {
|
||||
return g.ExpectWithOffset(0, actual, extra...)
|
||||
}
|
||||
|
||||
func (g *Gomega) ExpectWithOffset(offset int, actual interface{}, extra ...interface{}) types.Assertion {
|
||||
return NewAssertion(actual, g, offset, extra...)
|
||||
}
|
||||
|
||||
func (g *Gomega) Eventually(actual interface{}, intervals ...interface{}) types.AsyncAssertion {
|
||||
return g.EventuallyWithOffset(0, actual, intervals...)
|
||||
}
|
||||
|
||||
func (g *Gomega) EventuallyWithOffset(offset int, actual interface{}, intervals ...interface{}) types.AsyncAssertion {
|
||||
timeoutInterval := g.DurationBundle.EventuallyTimeout
|
||||
pollingInterval := g.DurationBundle.EventuallyPollingInterval
|
||||
if len(intervals) > 0 {
|
||||
timeoutInterval = toDuration(intervals[0])
|
||||
}
|
||||
if len(intervals) > 1 {
|
||||
pollingInterval = toDuration(intervals[1])
|
||||
}
|
||||
|
||||
return NewAsyncAssertion(AsyncAssertionTypeEventually, actual, g, timeoutInterval, pollingInterval, offset)
|
||||
}
|
||||
|
||||
func (g *Gomega) Consistently(actual interface{}, intervals ...interface{}) types.AsyncAssertion {
|
||||
return g.ConsistentlyWithOffset(0, actual, intervals...)
|
||||
}
|
||||
|
||||
func (g *Gomega) ConsistentlyWithOffset(offset int, actual interface{}, intervals ...interface{}) types.AsyncAssertion {
|
||||
timeoutInterval := g.DurationBundle.ConsistentlyDuration
|
||||
pollingInterval := g.DurationBundle.ConsistentlyPollingInterval
|
||||
if len(intervals) > 0 {
|
||||
timeoutInterval = toDuration(intervals[0])
|
||||
}
|
||||
if len(intervals) > 1 {
|
||||
pollingInterval = toDuration(intervals[1])
|
||||
}
|
||||
|
||||
return NewAsyncAssertion(AsyncAssertionTypeConsistently, actual, g, timeoutInterval, pollingInterval, offset)
|
||||
}
|
||||
|
||||
func (g *Gomega) SetDefaultEventuallyTimeout(t time.Duration) {
|
||||
g.DurationBundle.EventuallyTimeout = t
|
||||
}
|
||||
|
||||
func (g *Gomega) SetDefaultEventuallyPollingInterval(t time.Duration) {
|
||||
g.DurationBundle.EventuallyPollingInterval = t
|
||||
}
|
||||
|
||||
func (g *Gomega) SetDefaultConsistentlyDuration(t time.Duration) {
|
||||
g.DurationBundle.ConsistentlyDuration = t
|
||||
}
|
||||
|
||||
func (g *Gomega) SetDefaultConsistentlyPollingInterval(t time.Duration) {
|
||||
g.DurationBundle.ConsistentlyPollingInterval = t
|
||||
}
|
48
vendor/github.com/onsi/gomega/internal/gutil/post_ioutil.go
generated
vendored
Normal file
48
vendor/github.com/onsi/gomega/internal/gutil/post_ioutil.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
//go:build go1.16
|
||||
// +build go1.16
|
||||
|
||||
// Package gutil is a replacement for ioutil, which should not be used in new
|
||||
// code as of Go 1.16. With Go 1.16 and higher, this implementation
|
||||
// uses the ioutil replacement functions in "io" and "os" with some
|
||||
// Gomega specifics. This means that we should not get deprecation warnings
|
||||
// for ioutil when they are added.
|
||||
package gutil
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
func NopCloser(r io.Reader) io.ReadCloser {
|
||||
return io.NopCloser(r)
|
||||
}
|
||||
|
||||
func ReadAll(r io.Reader) ([]byte, error) {
|
||||
return io.ReadAll(r)
|
||||
}
|
||||
|
||||
func ReadDir(dirname string) ([]string, error) {
|
||||
entries, err := os.ReadDir(dirname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var names []string
|
||||
for _, entry := range entries {
|
||||
names = append(names, entry.Name())
|
||||
}
|
||||
|
||||
return names, nil
|
||||
}
|
||||
|
||||
func ReadFile(filename string) ([]byte, error) {
|
||||
return os.ReadFile(filename)
|
||||
}
|
||||
|
||||
func MkdirTemp(dir, pattern string) (string, error) {
|
||||
return os.MkdirTemp(dir, pattern)
|
||||
}
|
||||
|
||||
func WriteFile(filename string, data []byte) error {
|
||||
return os.WriteFile(filename, data, 0644)
|
||||
}
|
47
vendor/github.com/onsi/gomega/internal/gutil/using_ioutil.go
generated
vendored
Normal file
47
vendor/github.com/onsi/gomega/internal/gutil/using_ioutil.go
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
//go:build !go1.16
|
||||
// +build !go1.16
|
||||
|
||||
// Package gutil is a replacement for ioutil, which should not be used in new
|
||||
// code as of Go 1.16. With Go 1.15 and lower, this implementation
|
||||
// uses the ioutil functions, meaning that although Gomega is not officially
|
||||
// supported on these versions, it is still likely to work.
|
||||
package gutil
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
func NopCloser(r io.Reader) io.ReadCloser {
|
||||
return ioutil.NopCloser(r)
|
||||
}
|
||||
|
||||
func ReadAll(r io.Reader) ([]byte, error) {
|
||||
return ioutil.ReadAll(r)
|
||||
}
|
||||
|
||||
func ReadDir(dirname string) ([]string, error) {
|
||||
files, err := ioutil.ReadDir(dirname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var names []string
|
||||
for _, file := range files {
|
||||
names = append(names, file.Name())
|
||||
}
|
||||
|
||||
return names, nil
|
||||
}
|
||||
|
||||
func ReadFile(filename string) ([]byte, error) {
|
||||
return ioutil.ReadFile(filename)
|
||||
}
|
||||
|
||||
func MkdirTemp(dir, pattern string) (string, error) {
|
||||
return ioutil.TempDir(dir, pattern)
|
||||
}
|
||||
|
||||
func WriteFile(filename string, data []byte) error {
|
||||
return ioutil.WriteFile(filename, data, 0644)
|
||||
}
|
580
vendor/github.com/onsi/gomega/matchers.go
generated
vendored
Normal file
580
vendor/github.com/onsi/gomega/matchers.go
generated
vendored
Normal file
@@ -0,0 +1,580 @@
|
||||
package gomega
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/onsi/gomega/matchers"
|
||||
"github.com/onsi/gomega/types"
|
||||
)
|
||||
|
||||
//Equal uses reflect.DeepEqual to compare actual with expected. Equal is strict about
|
||||
//types when performing comparisons.
|
||||
//It is an error for both actual and expected to be nil. Use BeNil() instead.
|
||||
func Equal(expected interface{}) types.GomegaMatcher {
|
||||
return &matchers.EqualMatcher{
|
||||
Expected: expected,
|
||||
}
|
||||
}
|
||||
|
||||
//BeEquivalentTo is more lax than Equal, allowing equality between different types.
|
||||
//This is done by converting actual to have the type of expected before
|
||||
//attempting equality with reflect.DeepEqual.
|
||||
//It is an error for actual and expected to be nil. Use BeNil() instead.
|
||||
func BeEquivalentTo(expected interface{}) types.GomegaMatcher {
|
||||
return &matchers.BeEquivalentToMatcher{
|
||||
Expected: expected,
|
||||
}
|
||||
}
|
||||
|
||||
//BeIdenticalTo uses the == operator to compare actual with expected.
|
||||
//BeIdenticalTo is strict about types when performing comparisons.
|
||||
//It is an error for both actual and expected to be nil. Use BeNil() instead.
|
||||
func BeIdenticalTo(expected interface{}) types.GomegaMatcher {
|
||||
return &matchers.BeIdenticalToMatcher{
|
||||
Expected: expected,
|
||||
}
|
||||
}
|
||||
|
||||
//BeNil succeeds if actual is nil
|
||||
func BeNil() types.GomegaMatcher {
|
||||
return &matchers.BeNilMatcher{}
|
||||
}
|
||||
|
||||
//BeTrue succeeds if actual is true
|
||||
func BeTrue() types.GomegaMatcher {
|
||||
return &matchers.BeTrueMatcher{}
|
||||
}
|
||||
|
||||
//BeFalse succeeds if actual is false
|
||||
func BeFalse() types.GomegaMatcher {
|
||||
return &matchers.BeFalseMatcher{}
|
||||
}
|
||||
|
||||
//HaveOccurred succeeds if actual is a non-nil error
|
||||
//The typical Go error checking pattern looks like:
|
||||
// err := SomethingThatMightFail()
|
||||
// Expect(err).ShouldNot(HaveOccurred())
|
||||
func HaveOccurred() types.GomegaMatcher {
|
||||
return &matchers.HaveOccurredMatcher{}
|
||||
}
|
||||
|
||||
//Succeed passes if actual is a nil error
|
||||
//Succeed is intended to be used with functions that return a single error value. Instead of
|
||||
// err := SomethingThatMightFail()
|
||||
// Expect(err).ShouldNot(HaveOccurred())
|
||||
//
|
||||
//You can write:
|
||||
// Expect(SomethingThatMightFail()).Should(Succeed())
|
||||
//
|
||||
//It is a mistake to use Succeed with a function that has multiple return values. Gomega's Ω and Expect
|
||||
//functions automatically trigger failure if any return values after the first return value are non-zero/non-nil.
|
||||
//This means that Ω(MultiReturnFunc()).ShouldNot(Succeed()) can never pass.
|
||||
func Succeed() types.GomegaMatcher {
|
||||
return &matchers.SucceedMatcher{}
|
||||
}
|
||||
|
||||
//MatchError succeeds if actual is a non-nil error that matches the passed in string/error.
|
||||
//
|
||||
//These are valid use-cases:
|
||||
// Expect(err).Should(MatchError("an error")) //asserts that err.Error() == "an error"
|
||||
// Expect(err).Should(MatchError(SomeError)) //asserts that err == SomeError (via reflect.DeepEqual)
|
||||
//
|
||||
//It is an error for err to be nil or an object that does not implement the Error interface
|
||||
func MatchError(expected interface{}) types.GomegaMatcher {
|
||||
return &matchers.MatchErrorMatcher{
|
||||
Expected: expected,
|
||||
}
|
||||
}
|
||||
|
||||
//BeClosed succeeds if actual is a closed channel.
|
||||
//It is an error to pass a non-channel to BeClosed, it is also an error to pass nil
|
||||
//
|
||||
//In order to check whether or not the channel is closed, Gomega must try to read from the channel
|
||||
//(even in the `ShouldNot(BeClosed())` case). You should keep this in mind if you wish to make subsequent assertions about
|
||||
//values coming down the channel.
|
||||
//
|
||||
//Also, if you are testing that a *buffered* channel is closed you must first read all values out of the channel before
|
||||
//asserting that it is closed (it is not possible to detect that a buffered-channel has been closed until all its buffered values are read).
|
||||
//
|
||||
//Finally, as a corollary: it is an error to check whether or not a send-only channel is closed.
|
||||
func BeClosed() types.GomegaMatcher {
|
||||
return &matchers.BeClosedMatcher{}
|
||||
}
|
||||
|
||||
//Receive succeeds if there is a value to be received on actual.
|
||||
//Actual must be a channel (and cannot be a send-only channel) -- anything else is an error.
|
||||
//
|
||||
//Receive returns immediately and never blocks:
|
||||
//
|
||||
//- If there is nothing on the channel `c` then Expect(c).Should(Receive()) will fail and Ω(c).ShouldNot(Receive()) will pass.
|
||||
//
|
||||
//- If the channel `c` is closed then Expect(c).Should(Receive()) will fail and Ω(c).ShouldNot(Receive()) will pass.
|
||||
//
|
||||
//- If there is something on the channel `c` ready to be read, then Expect(c).Should(Receive()) will pass and Ω(c).ShouldNot(Receive()) will fail.
|
||||
//
|
||||
//If you have a go-routine running in the background that will write to channel `c` you can:
|
||||
// Eventually(c).Should(Receive())
|
||||
//
|
||||
//This will timeout if nothing gets sent to `c` (you can modify the timeout interval as you normally do with `Eventually`)
|
||||
//
|
||||
//A similar use-case is to assert that no go-routine writes to a channel (for a period of time). You can do this with `Consistently`:
|
||||
// Consistently(c).ShouldNot(Receive())
|
||||
//
|
||||
//You can pass `Receive` a matcher. If you do so, it will match the received object against the matcher. For example:
|
||||
// Expect(c).Should(Receive(Equal("foo")))
|
||||
//
|
||||
//When given a matcher, `Receive` will always fail if there is nothing to be received on the channel.
|
||||
//
|
||||
//Passing Receive a matcher is especially useful when paired with Eventually:
|
||||
//
|
||||
// Eventually(c).Should(Receive(ContainSubstring("bar")))
|
||||
//
|
||||
//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:
|
||||
// var myThing thing
|
||||
// Eventually(thingChan).Should(Receive(&myThing))
|
||||
// Expect(myThing.Sprocket).Should(Equal("foo"))
|
||||
// Expect(myThing.IsValid()).Should(BeTrue())
|
||||
func Receive(args ...interface{}) types.GomegaMatcher {
|
||||
var arg interface{}
|
||||
if len(args) > 0 {
|
||||
arg = args[0]
|
||||
}
|
||||
|
||||
return &matchers.ReceiveMatcher{
|
||||
Arg: arg,
|
||||
}
|
||||
}
|
||||
|
||||
//BeSent succeeds if a value can be sent to actual.
|
||||
//Actual must be a channel (and cannot be a receive-only channel) that can sent the type of the value passed into BeSent -- anything else is an error.
|
||||
//In addition, actual must not be closed.
|
||||
//
|
||||
//BeSent never blocks:
|
||||
//
|
||||
//- If the channel `c` is not ready to receive then Expect(c).Should(BeSent("foo")) will fail immediately
|
||||
//- If the channel `c` is eventually ready to receive then Eventually(c).Should(BeSent("foo")) will succeed.. presuming the channel becomes ready to receive before Eventually's timeout
|
||||
//- If the channel `c` is closed then Expect(c).Should(BeSent("foo")) and Ω(c).ShouldNot(BeSent("foo")) will both fail immediately
|
||||
//
|
||||
//Of course, the value is actually sent to the channel. The point of `BeSent` is less to make an assertion about the availability of the channel (which is typically an implementation detail that your test should not be concerned with).
|
||||
//Rather, the point of `BeSent` is to make it possible to easily and expressively write tests that can timeout on blocked channel sends.
|
||||
func BeSent(arg interface{}) types.GomegaMatcher {
|
||||
return &matchers.BeSentMatcher{
|
||||
Arg: arg,
|
||||
}
|
||||
}
|
||||
|
||||
//MatchRegexp succeeds if actual is a string or stringer that matches the
|
||||
//passed-in regexp. Optional arguments can be provided to construct a regexp
|
||||
//via fmt.Sprintf().
|
||||
func MatchRegexp(regexp string, args ...interface{}) types.GomegaMatcher {
|
||||
return &matchers.MatchRegexpMatcher{
|
||||
Regexp: regexp,
|
||||
Args: args,
|
||||
}
|
||||
}
|
||||
|
||||
//ContainSubstring succeeds if actual is a string or stringer that contains the
|
||||
//passed-in substring. Optional arguments can be provided to construct the substring
|
||||
//via fmt.Sprintf().
|
||||
func ContainSubstring(substr string, args ...interface{}) types.GomegaMatcher {
|
||||
return &matchers.ContainSubstringMatcher{
|
||||
Substr: substr,
|
||||
Args: args,
|
||||
}
|
||||
}
|
||||
|
||||
//HavePrefix succeeds if actual is a string or stringer that contains the
|
||||
//passed-in string as a prefix. Optional arguments can be provided to construct
|
||||
//via fmt.Sprintf().
|
||||
func HavePrefix(prefix string, args ...interface{}) types.GomegaMatcher {
|
||||
return &matchers.HavePrefixMatcher{
|
||||
Prefix: prefix,
|
||||
Args: args,
|
||||
}
|
||||
}
|
||||
|
||||
//HaveSuffix succeeds if actual is a string or stringer that contains the
|
||||
//passed-in string as a suffix. Optional arguments can be provided to construct
|
||||
//via fmt.Sprintf().
|
||||
func HaveSuffix(suffix string, args ...interface{}) types.GomegaMatcher {
|
||||
return &matchers.HaveSuffixMatcher{
|
||||
Suffix: suffix,
|
||||
Args: args,
|
||||
}
|
||||
}
|
||||
|
||||
//MatchJSON succeeds if actual is a string or stringer of JSON that matches
|
||||
//the expected JSON. The JSONs are decoded and the resulting objects are compared via
|
||||
//reflect.DeepEqual so things like key-ordering and whitespace shouldn't matter.
|
||||
func MatchJSON(json interface{}) types.GomegaMatcher {
|
||||
return &matchers.MatchJSONMatcher{
|
||||
JSONToMatch: json,
|
||||
}
|
||||
}
|
||||
|
||||
//MatchXML succeeds if actual is a string or stringer of XML that matches
|
||||
//the expected XML. The XMLs are decoded and the resulting objects are compared via
|
||||
//reflect.DeepEqual so things like whitespaces shouldn't matter.
|
||||
func MatchXML(xml interface{}) types.GomegaMatcher {
|
||||
return &matchers.MatchXMLMatcher{
|
||||
XMLToMatch: xml,
|
||||
}
|
||||
}
|
||||
|
||||
//MatchYAML succeeds if actual is a string or stringer of YAML that matches
|
||||
//the expected YAML. The YAML's are decoded and the resulting objects are compared via
|
||||
//reflect.DeepEqual so things like key-ordering and whitespace shouldn't matter.
|
||||
func MatchYAML(yaml interface{}) types.GomegaMatcher {
|
||||
return &matchers.MatchYAMLMatcher{
|
||||
YAMLToMatch: yaml,
|
||||
}
|
||||
}
|
||||
|
||||
//BeEmpty succeeds if actual is empty. Actual must be of type string, array, map, chan, or slice.
|
||||
func BeEmpty() types.GomegaMatcher {
|
||||
return &matchers.BeEmptyMatcher{}
|
||||
}
|
||||
|
||||
//HaveLen succeeds if actual has the passed-in length. Actual must be of type string, array, map, chan, or slice.
|
||||
func HaveLen(count int) types.GomegaMatcher {
|
||||
return &matchers.HaveLenMatcher{
|
||||
Count: count,
|
||||
}
|
||||
}
|
||||
|
||||
//HaveCap succeeds if actual has the passed-in capacity. Actual must be of type array, chan, or slice.
|
||||
func HaveCap(count int) types.GomegaMatcher {
|
||||
return &matchers.HaveCapMatcher{
|
||||
Count: count,
|
||||
}
|
||||
}
|
||||
|
||||
//BeZero succeeds if actual is the zero value for its type or if actual is nil.
|
||||
func BeZero() types.GomegaMatcher {
|
||||
return &matchers.BeZeroMatcher{}
|
||||
}
|
||||
|
||||
//ContainElement succeeds if actual contains the passed in element. By default
|
||||
//ContainElement() uses Equal() to perform the match, however a matcher can be
|
||||
//passed in instead:
|
||||
// Expect([]string{"Foo", "FooBar"}).Should(ContainElement(ContainSubstring("Bar")))
|
||||
//
|
||||
//Actual must be an array, slice or map. For maps, ContainElement searches
|
||||
//through the map's values.
|
||||
//
|
||||
//If you want to have a copy of the matching element(s) found you can pass a
|
||||
//pointer to a variable of the appropriate type. If the variable isn't a slice
|
||||
//or map, then exactly one match will be expected and returned. If the variable
|
||||
//is a slice or map, then at least one match is expected and all matches will be
|
||||
//stored in the variable.
|
||||
//
|
||||
// var findings []string
|
||||
// Expect([]string{"Foo", "FooBar"}).Should(ContainElement(ContainSubString("Bar", &findings)))
|
||||
func ContainElement(element interface{}, result ...interface{}) types.GomegaMatcher {
|
||||
return &matchers.ContainElementMatcher{
|
||||
Element: element,
|
||||
Result: result,
|
||||
}
|
||||
}
|
||||
|
||||
//BeElementOf succeeds if actual is contained in the passed in elements.
|
||||
//BeElementOf() always uses Equal() to perform the match.
|
||||
//When the passed in elements are comprised of a single element that is either an Array or Slice, BeElementOf() behaves
|
||||
//as the reverse of ContainElement() that operates with Equal() to perform the match.
|
||||
// Expect(2).Should(BeElementOf([]int{1, 2}))
|
||||
// Expect(2).Should(BeElementOf([2]int{1, 2}))
|
||||
//Otherwise, BeElementOf() provides a syntactic sugar for Or(Equal(_), Equal(_), ...):
|
||||
// Expect(2).Should(BeElementOf(1, 2))
|
||||
//
|
||||
//Actual must be typed.
|
||||
func BeElementOf(elements ...interface{}) types.GomegaMatcher {
|
||||
return &matchers.BeElementOfMatcher{
|
||||
Elements: elements,
|
||||
}
|
||||
}
|
||||
|
||||
//ConsistOf succeeds if actual contains precisely the elements passed into the matcher. The ordering of the elements does not matter.
|
||||
//By default ConsistOf() uses Equal() to match the elements, however custom matchers can be passed in instead. Here are some examples:
|
||||
//
|
||||
// Expect([]string{"Foo", "FooBar"}).Should(ConsistOf("FooBar", "Foo"))
|
||||
// Expect([]string{"Foo", "FooBar"}).Should(ConsistOf(ContainSubstring("Bar"), "Foo"))
|
||||
// Expect([]string{"Foo", "FooBar"}).Should(ConsistOf(ContainSubstring("Foo"), ContainSubstring("Foo")))
|
||||
//
|
||||
//Actual must be an array, slice or map. For maps, ConsistOf matches against the map's values.
|
||||
//
|
||||
//You typically pass variadic arguments to ConsistOf (as in the examples above). However, if you need to pass in a slice you can provided that it
|
||||
//is the only element passed in to ConsistOf:
|
||||
//
|
||||
// Expect([]string{"Foo", "FooBar"}).Should(ConsistOf([]string{"FooBar", "Foo"}))
|
||||
//
|
||||
//Note that Go's type system does not allow you to write this as ConsistOf([]string{"FooBar", "Foo"}...) as []string and []interface{} are different types - hence the need for this special rule.
|
||||
func ConsistOf(elements ...interface{}) types.GomegaMatcher {
|
||||
return &matchers.ConsistOfMatcher{
|
||||
Elements: elements,
|
||||
}
|
||||
}
|
||||
|
||||
//ContainElements succeeds if actual contains the passed in elements. The ordering of the elements does not matter.
|
||||
//By default ContainElements() uses Equal() to match the elements, however custom matchers can be passed in instead. Here are some examples:
|
||||
//
|
||||
// Expect([]string{"Foo", "FooBar"}).Should(ContainElements("FooBar"))
|
||||
// Expect([]string{"Foo", "FooBar"}).Should(ContainElements(ContainSubstring("Bar"), "Foo"))
|
||||
//
|
||||
//Actual must be an array, slice or map.
|
||||
//For maps, ContainElements searches through the map's values.
|
||||
func ContainElements(elements ...interface{}) types.GomegaMatcher {
|
||||
return &matchers.ContainElementsMatcher{
|
||||
Elements: elements,
|
||||
}
|
||||
}
|
||||
|
||||
//HaveEach succeeds if actual solely contains elements that match the passed in element.
|
||||
//Please note that if actual is empty, HaveEach always will succeed.
|
||||
//By default HaveEach() uses Equal() to perform the match, however a
|
||||
//matcher can be passed in instead:
|
||||
// Expect([]string{"Foo", "FooBar"}).Should(HaveEach(ContainSubstring("Foo")))
|
||||
//
|
||||
//Actual must be an array, slice or map.
|
||||
//For maps, HaveEach searches through the map's values.
|
||||
func HaveEach(element interface{}) types.GomegaMatcher {
|
||||
return &matchers.HaveEachMatcher{
|
||||
Element: element,
|
||||
}
|
||||
}
|
||||
|
||||
//HaveKey succeeds if actual is a map with the passed in key.
|
||||
//By default HaveKey uses Equal() to perform the match, however a
|
||||
//matcher can be passed in instead:
|
||||
// Expect(map[string]string{"Foo": "Bar", "BazFoo": "Duck"}).Should(HaveKey(MatchRegexp(`.+Foo$`)))
|
||||
func HaveKey(key interface{}) types.GomegaMatcher {
|
||||
return &matchers.HaveKeyMatcher{
|
||||
Key: key,
|
||||
}
|
||||
}
|
||||
|
||||
//HaveKeyWithValue succeeds if actual is a map with the passed in key and value.
|
||||
//By default HaveKeyWithValue uses Equal() to perform the match, however a
|
||||
//matcher can be passed in instead:
|
||||
// Expect(map[string]string{"Foo": "Bar", "BazFoo": "Duck"}).Should(HaveKeyWithValue("Foo", "Bar"))
|
||||
// Expect(map[string]string{"Foo": "Bar", "BazFoo": "Duck"}).Should(HaveKeyWithValue(MatchRegexp(`.+Foo$`), "Bar"))
|
||||
func HaveKeyWithValue(key interface{}, value interface{}) types.GomegaMatcher {
|
||||
return &matchers.HaveKeyWithValueMatcher{
|
||||
Key: key,
|
||||
Value: value,
|
||||
}
|
||||
}
|
||||
|
||||
//HaveField succeeds if actual is a struct and the value at the passed in field
|
||||
//matches the passed in matcher. By default HaveField used Equal() to perform the match,
|
||||
//however a matcher can be passed in in stead.
|
||||
//
|
||||
//The field must be a string that resolves to the name of a field in the struct. Structs can be traversed
|
||||
//using the '.' delimiter. If the field ends with '()' a method named field is assumed to exist on the struct and is invoked.
|
||||
//Such methods must take no arguments and return a single value:
|
||||
//
|
||||
// type Book struct {
|
||||
// Title string
|
||||
// Author Person
|
||||
// }
|
||||
// type Person struct {
|
||||
// FirstName string
|
||||
// LastName string
|
||||
// DOB time.Time
|
||||
// }
|
||||
// Expect(book).To(HaveField("Title", "Les Miserables"))
|
||||
// Expect(book).To(HaveField("Title", ContainSubstring("Les"))
|
||||
// Expect(book).To(HaveField("Author.FirstName", Equal("Victor"))
|
||||
// Expect(book).To(HaveField("Author.DOB.Year()", BeNumerically("<", 1900))
|
||||
func HaveField(field string, expected interface{}) types.GomegaMatcher {
|
||||
return &matchers.HaveFieldMatcher{
|
||||
Field: field,
|
||||
Expected: expected,
|
||||
}
|
||||
}
|
||||
|
||||
// HaveValue applies the given matcher to the value of actual, optionally and
|
||||
// repeatedly dereferencing pointers or taking the concrete value of interfaces.
|
||||
// Thus, the matcher will always be applied to non-pointer and non-interface
|
||||
// values only. HaveValue will fail with an error if a pointer or interface is
|
||||
// nil. It will also fail for more than 31 pointer or interface dereferences to
|
||||
// guard against mistakenly applying it to arbitrarily deep linked pointers.
|
||||
//
|
||||
// HaveValue differs from gstruct.PointTo in that it does not expect actual to
|
||||
// be a pointer (as gstruct.PointTo does) but instead also accepts non-pointer
|
||||
// and even interface values.
|
||||
//
|
||||
// actual := 42
|
||||
// Expect(actual).To(HaveValue(42))
|
||||
// Expect(&actual).To(HaveValue(42))
|
||||
func HaveValue(matcher types.GomegaMatcher) types.GomegaMatcher {
|
||||
return &matchers.HaveValueMatcher{
|
||||
Matcher: matcher,
|
||||
}
|
||||
}
|
||||
|
||||
//BeNumerically performs numerical assertions in a type-agnostic way.
|
||||
//Actual and expected should be numbers, though the specific type of
|
||||
//number is irrelevant (float32, float64, uint8, etc...).
|
||||
//
|
||||
//There are six, self-explanatory, supported comparators:
|
||||
// Expect(1.0).Should(BeNumerically("==", 1))
|
||||
// Expect(1.0).Should(BeNumerically("~", 0.999, 0.01))
|
||||
// Expect(1.0).Should(BeNumerically(">", 0.9))
|
||||
// Expect(1.0).Should(BeNumerically(">=", 1.0))
|
||||
// Expect(1.0).Should(BeNumerically("<", 3))
|
||||
// Expect(1.0).Should(BeNumerically("<=", 1.0))
|
||||
func BeNumerically(comparator string, compareTo ...interface{}) types.GomegaMatcher {
|
||||
return &matchers.BeNumericallyMatcher{
|
||||
Comparator: comparator,
|
||||
CompareTo: compareTo,
|
||||
}
|
||||
}
|
||||
|
||||
//BeTemporally compares time.Time's like BeNumerically
|
||||
//Actual and expected must be time.Time. The comparators are the same as for BeNumerically
|
||||
// Expect(time.Now()).Should(BeTemporally(">", time.Time{}))
|
||||
// Expect(time.Now()).Should(BeTemporally("~", time.Now(), time.Second))
|
||||
func BeTemporally(comparator string, compareTo time.Time, threshold ...time.Duration) types.GomegaMatcher {
|
||||
return &matchers.BeTemporallyMatcher{
|
||||
Comparator: comparator,
|
||||
CompareTo: compareTo,
|
||||
Threshold: threshold,
|
||||
}
|
||||
}
|
||||
|
||||
//BeAssignableToTypeOf succeeds if actual is assignable to the type of expected.
|
||||
//It will return an error when one of the values is nil.
|
||||
// Expect(0).Should(BeAssignableToTypeOf(0)) // Same values
|
||||
// Expect(5).Should(BeAssignableToTypeOf(-1)) // different values same type
|
||||
// Expect("foo").Should(BeAssignableToTypeOf("bar")) // different values same type
|
||||
// Expect(struct{ Foo string }{}).Should(BeAssignableToTypeOf(struct{ Foo string }{}))
|
||||
func BeAssignableToTypeOf(expected interface{}) types.GomegaMatcher {
|
||||
return &matchers.AssignableToTypeOfMatcher{
|
||||
Expected: expected,
|
||||
}
|
||||
}
|
||||
|
||||
//Panic succeeds if actual is a function that, when invoked, panics.
|
||||
//Actual must be a function that takes no arguments and returns no results.
|
||||
func Panic() types.GomegaMatcher {
|
||||
return &matchers.PanicMatcher{}
|
||||
}
|
||||
|
||||
//PanicWith succeeds if actual is a function that, when invoked, panics with a specific value.
|
||||
//Actual must be a function that takes no arguments and returns no results.
|
||||
//
|
||||
//By default PanicWith uses Equal() to perform the match, however a
|
||||
//matcher can be passed in instead:
|
||||
// Expect(fn).Should(PanicWith(MatchRegexp(`.+Foo$`)))
|
||||
func PanicWith(expected interface{}) types.GomegaMatcher {
|
||||
return &matchers.PanicMatcher{Expected: expected}
|
||||
}
|
||||
|
||||
//BeAnExistingFile succeeds if a file exists.
|
||||
//Actual must be a string representing the abs path to the file being checked.
|
||||
func BeAnExistingFile() types.GomegaMatcher {
|
||||
return &matchers.BeAnExistingFileMatcher{}
|
||||
}
|
||||
|
||||
//BeARegularFile succeeds if a file exists and is a regular file.
|
||||
//Actual must be a string representing the abs path to the file being checked.
|
||||
func BeARegularFile() types.GomegaMatcher {
|
||||
return &matchers.BeARegularFileMatcher{}
|
||||
}
|
||||
|
||||
//BeADirectory succeeds if a file exists and is a directory.
|
||||
//Actual must be a string representing the abs path to the file being checked.
|
||||
func BeADirectory() types.GomegaMatcher {
|
||||
return &matchers.BeADirectoryMatcher{}
|
||||
}
|
||||
|
||||
//HaveHTTPStatus succeeds if the Status or StatusCode field of an HTTP response matches.
|
||||
//Actual must be either a *http.Response or *httptest.ResponseRecorder.
|
||||
//Expected must be either an int or a string.
|
||||
// Expect(resp).Should(HaveHTTPStatus(http.StatusOK)) // asserts that resp.StatusCode == 200
|
||||
// Expect(resp).Should(HaveHTTPStatus("404 Not Found")) // asserts that resp.Status == "404 Not Found"
|
||||
// Expect(resp).Should(HaveHTTPStatus(http.StatusOK, http.StatusNoContent)) // asserts that resp.StatusCode == 200 || resp.StatusCode == 204
|
||||
func HaveHTTPStatus(expected ...interface{}) types.GomegaMatcher {
|
||||
return &matchers.HaveHTTPStatusMatcher{Expected: expected}
|
||||
}
|
||||
|
||||
// HaveHTTPHeaderWithValue succeeds if the header is found and the value matches.
|
||||
// Actual must be either a *http.Response or *httptest.ResponseRecorder.
|
||||
// Expected must be a string header name, followed by a header value which
|
||||
// can be a string, or another matcher.
|
||||
func HaveHTTPHeaderWithValue(header string, value interface{}) types.GomegaMatcher {
|
||||
return &matchers.HaveHTTPHeaderWithValueMatcher{
|
||||
Header: header,
|
||||
Value: value,
|
||||
}
|
||||
}
|
||||
|
||||
// HaveHTTPBody matches if the body matches.
|
||||
// Actual must be either a *http.Response or *httptest.ResponseRecorder.
|
||||
// Expected must be either a string, []byte, or other matcher
|
||||
func HaveHTTPBody(expected interface{}) types.GomegaMatcher {
|
||||
return &matchers.HaveHTTPBodyMatcher{Expected: expected}
|
||||
}
|
||||
|
||||
//And succeeds only if all of the given matchers succeed.
|
||||
//The matchers are tried in order, and will fail-fast if one doesn't succeed.
|
||||
// Expect("hi").To(And(HaveLen(2), Equal("hi"))
|
||||
//
|
||||
//And(), Or(), Not() and WithTransform() allow matchers to be composed into complex expressions.
|
||||
func And(ms ...types.GomegaMatcher) types.GomegaMatcher {
|
||||
return &matchers.AndMatcher{Matchers: ms}
|
||||
}
|
||||
|
||||
//SatisfyAll is an alias for And().
|
||||
// Expect("hi").Should(SatisfyAll(HaveLen(2), Equal("hi")))
|
||||
func SatisfyAll(matchers ...types.GomegaMatcher) types.GomegaMatcher {
|
||||
return And(matchers...)
|
||||
}
|
||||
|
||||
//Or succeeds if any of the given matchers succeed.
|
||||
//The matchers are tried in order and will return immediately upon the first successful match.
|
||||
// Expect("hi").To(Or(HaveLen(3), HaveLen(2))
|
||||
//
|
||||
//And(), Or(), Not() and WithTransform() allow matchers to be composed into complex expressions.
|
||||
func Or(ms ...types.GomegaMatcher) types.GomegaMatcher {
|
||||
return &matchers.OrMatcher{Matchers: ms}
|
||||
}
|
||||
|
||||
//SatisfyAny is an alias for Or().
|
||||
// Expect("hi").SatisfyAny(Or(HaveLen(3), HaveLen(2))
|
||||
func SatisfyAny(matchers ...types.GomegaMatcher) types.GomegaMatcher {
|
||||
return Or(matchers...)
|
||||
}
|
||||
|
||||
//Not negates the given matcher; it succeeds if the given matcher fails.
|
||||
// Expect(1).To(Not(Equal(2))
|
||||
//
|
||||
//And(), Or(), Not() and WithTransform() allow matchers to be composed into complex expressions.
|
||||
func Not(matcher types.GomegaMatcher) types.GomegaMatcher {
|
||||
return &matchers.NotMatcher{Matcher: matcher}
|
||||
}
|
||||
|
||||
//WithTransform applies the `transform` to the actual value and matches it against `matcher`.
|
||||
//The given transform must be either a function of one parameter that returns one value or a
|
||||
// function of one parameter that returns two values, where the second value must be of the
|
||||
// error type.
|
||||
// var plus1 = func(i int) int { return i + 1 }
|
||||
// Expect(1).To(WithTransform(plus1, Equal(2))
|
||||
//
|
||||
// var failingplus1 = func(i int) (int, error) { return 42, "this does not compute" }
|
||||
// Expect(1).To(WithTransform(failingplus1, Equal(2)))
|
||||
//
|
||||
//And(), Or(), Not() and WithTransform() allow matchers to be composed into complex expressions.
|
||||
func WithTransform(transform interface{}, matcher types.GomegaMatcher) types.GomegaMatcher {
|
||||
return matchers.NewWithTransformMatcher(transform, matcher)
|
||||
}
|
||||
|
||||
//Satisfy matches the actual value against the `predicate` function.
|
||||
//The given predicate must be a function of one paramter that returns bool.
|
||||
// var isEven = func(i int) bool { return i%2 == 0 }
|
||||
// Expect(2).To(Satisfy(isEven))
|
||||
func Satisfy(predicate interface{}) types.GomegaMatcher {
|
||||
return matchers.NewSatisfyMatcher(predicate)
|
||||
}
|
62
vendor/github.com/onsi/gomega/matchers/and.go
generated
vendored
Normal file
62
vendor/github.com/onsi/gomega/matchers/and.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
"github.com/onsi/gomega/types"
|
||||
)
|
||||
|
||||
type AndMatcher struct {
|
||||
Matchers []types.GomegaMatcher
|
||||
|
||||
// state
|
||||
firstFailedMatcher types.GomegaMatcher
|
||||
}
|
||||
|
||||
func (m *AndMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
m.firstFailedMatcher = nil
|
||||
for _, matcher := range m.Matchers {
|
||||
success, err := matcher.Match(actual)
|
||||
if !success || err != nil {
|
||||
m.firstFailedMatcher = matcher
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (m *AndMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return m.firstFailedMatcher.FailureMessage(actual)
|
||||
}
|
||||
|
||||
func (m *AndMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
// not the most beautiful list of matchers, but not bad either...
|
||||
return format.Message(actual, fmt.Sprintf("To not satisfy all of these matchers: %s", m.Matchers))
|
||||
}
|
||||
|
||||
func (m *AndMatcher) MatchMayChangeInTheFuture(actual interface{}) bool {
|
||||
/*
|
||||
Example with 3 matchers: A, B, C
|
||||
|
||||
Match evaluates them: T, F, <?> => F
|
||||
So match is currently F, what should MatchMayChangeInTheFuture() return?
|
||||
Seems like it only depends on B, since currently B MUST change to allow the result to become T
|
||||
|
||||
Match eval: T, T, T => T
|
||||
So match is currently T, what should MatchMayChangeInTheFuture() return?
|
||||
Seems to depend on ANY of them being able to change to F.
|
||||
*/
|
||||
|
||||
if m.firstFailedMatcher == nil {
|
||||
// so all matchers succeeded.. Any one of them changing would change the result.
|
||||
for _, matcher := range m.Matchers {
|
||||
if types.MatchMayChangeInTheFuture(matcher, actual) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false // none of were going to change
|
||||
}
|
||||
// one of the matchers failed.. it must be able to change in order to affect the result
|
||||
return types.MatchMayChangeInTheFuture(m.firstFailedMatcher, actual)
|
||||
}
|
37
vendor/github.com/onsi/gomega/matchers/assignable_to_type_of_matcher.go
generated
vendored
Normal file
37
vendor/github.com/onsi/gomega/matchers/assignable_to_type_of_matcher.go
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
// untested sections: 2
|
||||
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
type AssignableToTypeOfMatcher struct {
|
||||
Expected interface{}
|
||||
}
|
||||
|
||||
func (matcher *AssignableToTypeOfMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
if actual == nil && matcher.Expected == nil {
|
||||
return false, fmt.Errorf("Refusing to compare <nil> to <nil>.\nBe explicit and use BeNil() instead. This is to avoid mistakes where both sides of an assertion are erroneously uninitialized.")
|
||||
} else if matcher.Expected == nil {
|
||||
return false, fmt.Errorf("Refusing to compare type to <nil>.\nBe explicit and use BeNil() instead. This is to avoid mistakes where both sides of an assertion are erroneously uninitialized.")
|
||||
} else if actual == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
actualType := reflect.TypeOf(actual)
|
||||
expectedType := reflect.TypeOf(matcher.Expected)
|
||||
|
||||
return actualType.AssignableTo(expectedType), nil
|
||||
}
|
||||
|
||||
func (matcher *AssignableToTypeOfMatcher) FailureMessage(actual interface{}) string {
|
||||
return format.Message(actual, fmt.Sprintf("to be assignable to the type: %T", matcher.Expected))
|
||||
}
|
||||
|
||||
func (matcher *AssignableToTypeOfMatcher) NegatedFailureMessage(actual interface{}) string {
|
||||
return format.Message(actual, fmt.Sprintf("not to be assignable to the type: %T", matcher.Expected))
|
||||
}
|
14
vendor/github.com/onsi/gomega/matchers/attributes_slice.go
generated
vendored
Normal file
14
vendor/github.com/onsi/gomega/matchers/attributes_slice.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type attributesSlice []xml.Attr
|
||||
|
||||
func (attrs attributesSlice) Len() int { return len(attrs) }
|
||||
func (attrs attributesSlice) Less(i, j int) bool {
|
||||
return strings.Compare(attrs[i].Name.Local, attrs[j].Name.Local) == -1
|
||||
}
|
||||
func (attrs attributesSlice) Swap(i, j int) { attrs[i], attrs[j] = attrs[j], attrs[i] }
|
56
vendor/github.com/onsi/gomega/matchers/be_a_directory.go
generated
vendored
Normal file
56
vendor/github.com/onsi/gomega/matchers/be_a_directory.go
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
// untested sections: 5
|
||||
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
type notADirectoryError struct {
|
||||
os.FileInfo
|
||||
}
|
||||
|
||||
func (t notADirectoryError) Error() string {
|
||||
fileInfo := os.FileInfo(t)
|
||||
switch {
|
||||
case fileInfo.Mode().IsRegular():
|
||||
return "file is a regular file"
|
||||
default:
|
||||
return fmt.Sprintf("file mode is: %s", fileInfo.Mode().String())
|
||||
}
|
||||
}
|
||||
|
||||
type BeADirectoryMatcher struct {
|
||||
expected interface{}
|
||||
err error
|
||||
}
|
||||
|
||||
func (matcher *BeADirectoryMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
actualFilename, ok := actual.(string)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("BeADirectoryMatcher matcher expects a file path")
|
||||
}
|
||||
|
||||
fileInfo, err := os.Stat(actualFilename)
|
||||
if err != nil {
|
||||
matcher.err = err
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if !fileInfo.Mode().IsDir() {
|
||||
matcher.err = notADirectoryError{fileInfo}
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (matcher *BeADirectoryMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, fmt.Sprintf("to be a directory: %s", matcher.err))
|
||||
}
|
||||
|
||||
func (matcher *BeADirectoryMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, fmt.Sprintf("not be a directory"))
|
||||
}
|
56
vendor/github.com/onsi/gomega/matchers/be_a_regular_file.go
generated
vendored
Normal file
56
vendor/github.com/onsi/gomega/matchers/be_a_regular_file.go
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
// untested sections: 5
|
||||
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
type notARegularFileError struct {
|
||||
os.FileInfo
|
||||
}
|
||||
|
||||
func (t notARegularFileError) Error() string {
|
||||
fileInfo := os.FileInfo(t)
|
||||
switch {
|
||||
case fileInfo.IsDir():
|
||||
return "file is a directory"
|
||||
default:
|
||||
return fmt.Sprintf("file mode is: %s", fileInfo.Mode().String())
|
||||
}
|
||||
}
|
||||
|
||||
type BeARegularFileMatcher struct {
|
||||
expected interface{}
|
||||
err error
|
||||
}
|
||||
|
||||
func (matcher *BeARegularFileMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
actualFilename, ok := actual.(string)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("BeARegularFileMatcher matcher expects a file path")
|
||||
}
|
||||
|
||||
fileInfo, err := os.Stat(actualFilename)
|
||||
if err != nil {
|
||||
matcher.err = err
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if !fileInfo.Mode().IsRegular() {
|
||||
matcher.err = notARegularFileError{fileInfo}
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (matcher *BeARegularFileMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, fmt.Sprintf("to be a regular file: %s", matcher.err))
|
||||
}
|
||||
|
||||
func (matcher *BeARegularFileMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, fmt.Sprintf("not be a regular file"))
|
||||
}
|
40
vendor/github.com/onsi/gomega/matchers/be_an_existing_file.go
generated
vendored
Normal file
40
vendor/github.com/onsi/gomega/matchers/be_an_existing_file.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
// untested sections: 3
|
||||
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
type BeAnExistingFileMatcher struct {
|
||||
expected interface{}
|
||||
}
|
||||
|
||||
func (matcher *BeAnExistingFileMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
actualFilename, ok := actual.(string)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("BeAnExistingFileMatcher matcher expects a file path")
|
||||
}
|
||||
|
||||
if _, err = os.Stat(actualFilename); err != nil {
|
||||
switch {
|
||||
case os.IsNotExist(err):
|
||||
return false, nil
|
||||
default:
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (matcher *BeAnExistingFileMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, fmt.Sprintf("to exist"))
|
||||
}
|
||||
|
||||
func (matcher *BeAnExistingFileMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, fmt.Sprintf("not to exist"))
|
||||
}
|
48
vendor/github.com/onsi/gomega/matchers/be_closed_matcher.go
generated
vendored
Normal file
48
vendor/github.com/onsi/gomega/matchers/be_closed_matcher.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
// untested sections: 2
|
||||
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
type BeClosedMatcher struct {
|
||||
}
|
||||
|
||||
func (matcher *BeClosedMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
if !isChan(actual) {
|
||||
return false, fmt.Errorf("BeClosed matcher expects a channel. Got:\n%s", format.Object(actual, 1))
|
||||
}
|
||||
|
||||
channelType := reflect.TypeOf(actual)
|
||||
channelValue := reflect.ValueOf(actual)
|
||||
|
||||
if channelType.ChanDir() == reflect.SendDir {
|
||||
return false, fmt.Errorf("BeClosed matcher cannot determine if a send-only channel is closed or open. Got:\n%s", format.Object(actual, 1))
|
||||
}
|
||||
|
||||
winnerIndex, _, open := reflect.Select([]reflect.SelectCase{
|
||||
{Dir: reflect.SelectRecv, Chan: channelValue},
|
||||
{Dir: reflect.SelectDefault},
|
||||
})
|
||||
|
||||
var closed bool
|
||||
if winnerIndex == 0 {
|
||||
closed = !open
|
||||
} else if winnerIndex == 1 {
|
||||
closed = false
|
||||
}
|
||||
|
||||
return closed, nil
|
||||
}
|
||||
|
||||
func (matcher *BeClosedMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "to be closed")
|
||||
}
|
||||
|
||||
func (matcher *BeClosedMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "to be open")
|
||||
}
|
43
vendor/github.com/onsi/gomega/matchers/be_element_of_matcher.go
generated
vendored
Normal file
43
vendor/github.com/onsi/gomega/matchers/be_element_of_matcher.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
// untested sections: 1
|
||||
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
type BeElementOfMatcher struct {
|
||||
Elements []interface{}
|
||||
}
|
||||
|
||||
func (matcher *BeElementOfMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
if reflect.TypeOf(actual) == nil {
|
||||
return false, fmt.Errorf("BeElement matcher expects actual to be typed")
|
||||
}
|
||||
|
||||
var lastError error
|
||||
for _, m := range flatten(matcher.Elements) {
|
||||
matcher := &EqualMatcher{Expected: m}
|
||||
success, err := matcher.Match(actual)
|
||||
if err != nil {
|
||||
lastError = err
|
||||
continue
|
||||
}
|
||||
if success {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, lastError
|
||||
}
|
||||
|
||||
func (matcher *BeElementOfMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "to be an element of", presentable(matcher.Elements))
|
||||
}
|
||||
|
||||
func (matcher *BeElementOfMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "not to be an element of", presentable(matcher.Elements))
|
||||
}
|
29
vendor/github.com/onsi/gomega/matchers/be_empty_matcher.go
generated
vendored
Normal file
29
vendor/github.com/onsi/gomega/matchers/be_empty_matcher.go
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
// untested sections: 2
|
||||
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
type BeEmptyMatcher struct {
|
||||
}
|
||||
|
||||
func (matcher *BeEmptyMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
length, ok := lengthOf(actual)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("BeEmpty matcher expects a string/array/map/channel/slice. Got:\n%s", format.Object(actual, 1))
|
||||
}
|
||||
|
||||
return length == 0, nil
|
||||
}
|
||||
|
||||
func (matcher *BeEmptyMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "to be empty")
|
||||
}
|
||||
|
||||
func (matcher *BeEmptyMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "not to be empty")
|
||||
}
|
36
vendor/github.com/onsi/gomega/matchers/be_equivalent_to_matcher.go
generated
vendored
Normal file
36
vendor/github.com/onsi/gomega/matchers/be_equivalent_to_matcher.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// untested sections: 2
|
||||
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
type BeEquivalentToMatcher struct {
|
||||
Expected interface{}
|
||||
}
|
||||
|
||||
func (matcher *BeEquivalentToMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
if actual == nil && matcher.Expected == nil {
|
||||
return false, fmt.Errorf("Both actual and expected must not be nil.")
|
||||
}
|
||||
|
||||
convertedActual := actual
|
||||
|
||||
if actual != nil && matcher.Expected != nil && reflect.TypeOf(actual).ConvertibleTo(reflect.TypeOf(matcher.Expected)) {
|
||||
convertedActual = reflect.ValueOf(actual).Convert(reflect.TypeOf(matcher.Expected)).Interface()
|
||||
}
|
||||
|
||||
return reflect.DeepEqual(convertedActual, matcher.Expected), nil
|
||||
}
|
||||
|
||||
func (matcher *BeEquivalentToMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "to be equivalent to", matcher.Expected)
|
||||
}
|
||||
|
||||
func (matcher *BeEquivalentToMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "not to be equivalent to", matcher.Expected)
|
||||
}
|
28
vendor/github.com/onsi/gomega/matchers/be_false_matcher.go
generated
vendored
Normal file
28
vendor/github.com/onsi/gomega/matchers/be_false_matcher.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// untested sections: 2
|
||||
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
type BeFalseMatcher struct {
|
||||
}
|
||||
|
||||
func (matcher *BeFalseMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
if !isBool(actual) {
|
||||
return false, fmt.Errorf("Expected a boolean. Got:\n%s", format.Object(actual, 1))
|
||||
}
|
||||
|
||||
return actual == false, nil
|
||||
}
|
||||
|
||||
func (matcher *BeFalseMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "to be false")
|
||||
}
|
||||
|
||||
func (matcher *BeFalseMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "not to be false")
|
||||
}
|
39
vendor/github.com/onsi/gomega/matchers/be_identical_to.go
generated
vendored
Normal file
39
vendor/github.com/onsi/gomega/matchers/be_identical_to.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
// untested sections: 2
|
||||
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
type BeIdenticalToMatcher struct {
|
||||
Expected interface{}
|
||||
}
|
||||
|
||||
func (matcher *BeIdenticalToMatcher) Match(actual interface{}) (success bool, matchErr error) {
|
||||
if actual == nil && matcher.Expected == nil {
|
||||
return false, fmt.Errorf("Refusing to compare <nil> to <nil>.\nBe explicit and use BeNil() instead. This is to avoid mistakes where both sides of an assertion are erroneously uninitialized.")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if _, ok := r.(runtime.Error); ok {
|
||||
success = false
|
||||
matchErr = nil
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return actual == matcher.Expected, nil
|
||||
}
|
||||
|
||||
func (matcher *BeIdenticalToMatcher) FailureMessage(actual interface{}) string {
|
||||
return format.Message(actual, "to be identical to", matcher.Expected)
|
||||
}
|
||||
|
||||
func (matcher *BeIdenticalToMatcher) NegatedFailureMessage(actual interface{}) string {
|
||||
return format.Message(actual, "not to be identical to", matcher.Expected)
|
||||
}
|
20
vendor/github.com/onsi/gomega/matchers/be_nil_matcher.go
generated
vendored
Normal file
20
vendor/github.com/onsi/gomega/matchers/be_nil_matcher.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// untested sections: 2
|
||||
|
||||
package matchers
|
||||
|
||||
import "github.com/onsi/gomega/format"
|
||||
|
||||
type BeNilMatcher struct {
|
||||
}
|
||||
|
||||
func (matcher *BeNilMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
return isNil(actual), nil
|
||||
}
|
||||
|
||||
func (matcher *BeNilMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "to be nil")
|
||||
}
|
||||
|
||||
func (matcher *BeNilMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "not to be nil")
|
||||
}
|
134
vendor/github.com/onsi/gomega/matchers/be_numerically_matcher.go
generated
vendored
Normal file
134
vendor/github.com/onsi/gomega/matchers/be_numerically_matcher.go
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
// untested sections: 4
|
||||
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
type BeNumericallyMatcher struct {
|
||||
Comparator string
|
||||
CompareTo []interface{}
|
||||
}
|
||||
|
||||
func (matcher *BeNumericallyMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return matcher.FormatFailureMessage(actual, false)
|
||||
}
|
||||
|
||||
func (matcher *BeNumericallyMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return matcher.FormatFailureMessage(actual, true)
|
||||
}
|
||||
|
||||
func (matcher *BeNumericallyMatcher) FormatFailureMessage(actual interface{}, negated bool) (message string) {
|
||||
if len(matcher.CompareTo) == 1 {
|
||||
message = fmt.Sprintf("to be %s", matcher.Comparator)
|
||||
} else {
|
||||
message = fmt.Sprintf("to be within %v of %s", matcher.CompareTo[1], matcher.Comparator)
|
||||
}
|
||||
if negated {
|
||||
message = "not " + message
|
||||
}
|
||||
return format.Message(actual, message, matcher.CompareTo[0])
|
||||
}
|
||||
|
||||
func (matcher *BeNumericallyMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
if len(matcher.CompareTo) == 0 || len(matcher.CompareTo) > 2 {
|
||||
return false, fmt.Errorf("BeNumerically requires 1 or 2 CompareTo arguments. Got:\n%s", format.Object(matcher.CompareTo, 1))
|
||||
}
|
||||
if !isNumber(actual) {
|
||||
return false, fmt.Errorf("Expected a number. Got:\n%s", format.Object(actual, 1))
|
||||
}
|
||||
if !isNumber(matcher.CompareTo[0]) {
|
||||
return false, fmt.Errorf("Expected a number. Got:\n%s", format.Object(matcher.CompareTo[0], 1))
|
||||
}
|
||||
if len(matcher.CompareTo) == 2 && !isNumber(matcher.CompareTo[1]) {
|
||||
return false, fmt.Errorf("Expected a number. Got:\n%s", format.Object(matcher.CompareTo[1], 1))
|
||||
}
|
||||
|
||||
switch matcher.Comparator {
|
||||
case "==", "~", ">", ">=", "<", "<=":
|
||||
default:
|
||||
return false, fmt.Errorf("Unknown comparator: %s", matcher.Comparator)
|
||||
}
|
||||
|
||||
if isFloat(actual) || isFloat(matcher.CompareTo[0]) {
|
||||
var secondOperand float64 = 1e-8
|
||||
if len(matcher.CompareTo) == 2 {
|
||||
secondOperand = toFloat(matcher.CompareTo[1])
|
||||
}
|
||||
success = matcher.matchFloats(toFloat(actual), toFloat(matcher.CompareTo[0]), secondOperand)
|
||||
} else if isInteger(actual) {
|
||||
var secondOperand int64 = 0
|
||||
if len(matcher.CompareTo) == 2 {
|
||||
secondOperand = toInteger(matcher.CompareTo[1])
|
||||
}
|
||||
success = matcher.matchIntegers(toInteger(actual), toInteger(matcher.CompareTo[0]), secondOperand)
|
||||
} else if isUnsignedInteger(actual) {
|
||||
var secondOperand uint64 = 0
|
||||
if len(matcher.CompareTo) == 2 {
|
||||
secondOperand = toUnsignedInteger(matcher.CompareTo[1])
|
||||
}
|
||||
success = matcher.matchUnsignedIntegers(toUnsignedInteger(actual), toUnsignedInteger(matcher.CompareTo[0]), secondOperand)
|
||||
} else {
|
||||
return false, fmt.Errorf("Failed to compare:\n%s\n%s:\n%s", format.Object(actual, 1), matcher.Comparator, format.Object(matcher.CompareTo[0], 1))
|
||||
}
|
||||
|
||||
return success, nil
|
||||
}
|
||||
|
||||
func (matcher *BeNumericallyMatcher) matchIntegers(actual, compareTo, threshold int64) (success bool) {
|
||||
switch matcher.Comparator {
|
||||
case "==", "~":
|
||||
diff := actual - compareTo
|
||||
return -threshold <= diff && diff <= threshold
|
||||
case ">":
|
||||
return (actual > compareTo)
|
||||
case ">=":
|
||||
return (actual >= compareTo)
|
||||
case "<":
|
||||
return (actual < compareTo)
|
||||
case "<=":
|
||||
return (actual <= compareTo)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (matcher *BeNumericallyMatcher) matchUnsignedIntegers(actual, compareTo, threshold uint64) (success bool) {
|
||||
switch matcher.Comparator {
|
||||
case "==", "~":
|
||||
if actual < compareTo {
|
||||
actual, compareTo = compareTo, actual
|
||||
}
|
||||
return actual-compareTo <= threshold
|
||||
case ">":
|
||||
return (actual > compareTo)
|
||||
case ">=":
|
||||
return (actual >= compareTo)
|
||||
case "<":
|
||||
return (actual < compareTo)
|
||||
case "<=":
|
||||
return (actual <= compareTo)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (matcher *BeNumericallyMatcher) matchFloats(actual, compareTo, threshold float64) (success bool) {
|
||||
switch matcher.Comparator {
|
||||
case "~":
|
||||
return math.Abs(actual-compareTo) <= threshold
|
||||
case "==":
|
||||
return (actual == compareTo)
|
||||
case ">":
|
||||
return (actual > compareTo)
|
||||
case ">=":
|
||||
return (actual >= compareTo)
|
||||
case "<":
|
||||
return (actual < compareTo)
|
||||
case "<=":
|
||||
return (actual <= compareTo)
|
||||
}
|
||||
return false
|
||||
}
|
73
vendor/github.com/onsi/gomega/matchers/be_sent_matcher.go
generated
vendored
Normal file
73
vendor/github.com/onsi/gomega/matchers/be_sent_matcher.go
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
// untested sections: 3
|
||||
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
type BeSentMatcher struct {
|
||||
Arg interface{}
|
||||
channelClosed bool
|
||||
}
|
||||
|
||||
func (matcher *BeSentMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
if !isChan(actual) {
|
||||
return false, fmt.Errorf("BeSent expects a channel. Got:\n%s", format.Object(actual, 1))
|
||||
}
|
||||
|
||||
channelType := reflect.TypeOf(actual)
|
||||
channelValue := reflect.ValueOf(actual)
|
||||
|
||||
if channelType.ChanDir() == reflect.RecvDir {
|
||||
return false, fmt.Errorf("BeSent matcher cannot be passed a receive-only channel. Got:\n%s", format.Object(actual, 1))
|
||||
}
|
||||
|
||||
argType := reflect.TypeOf(matcher.Arg)
|
||||
assignable := argType.AssignableTo(channelType.Elem())
|
||||
|
||||
if !assignable {
|
||||
return false, fmt.Errorf("Cannot pass:\n%s to the channel:\n%s\nThe types don't match.", format.Object(matcher.Arg, 1), format.Object(actual, 1))
|
||||
}
|
||||
|
||||
argValue := reflect.ValueOf(matcher.Arg)
|
||||
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
success = false
|
||||
err = fmt.Errorf("Cannot send to a closed channel")
|
||||
matcher.channelClosed = true
|
||||
}
|
||||
}()
|
||||
|
||||
winnerIndex, _, _ := reflect.Select([]reflect.SelectCase{
|
||||
{Dir: reflect.SelectSend, Chan: channelValue, Send: argValue},
|
||||
{Dir: reflect.SelectDefault},
|
||||
})
|
||||
|
||||
var didSend bool
|
||||
if winnerIndex == 0 {
|
||||
didSend = true
|
||||
}
|
||||
|
||||
return didSend, nil
|
||||
}
|
||||
|
||||
func (matcher *BeSentMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "to send:", matcher.Arg)
|
||||
}
|
||||
|
||||
func (matcher *BeSentMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "not to send:", matcher.Arg)
|
||||
}
|
||||
|
||||
func (matcher *BeSentMatcher) MatchMayChangeInTheFuture(actual interface{}) bool {
|
||||
if !isChan(actual) {
|
||||
return false
|
||||
}
|
||||
|
||||
return !matcher.channelClosed
|
||||
}
|
68
vendor/github.com/onsi/gomega/matchers/be_temporally_matcher.go
generated
vendored
Normal file
68
vendor/github.com/onsi/gomega/matchers/be_temporally_matcher.go
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
// untested sections: 3
|
||||
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
type BeTemporallyMatcher struct {
|
||||
Comparator string
|
||||
CompareTo time.Time
|
||||
Threshold []time.Duration
|
||||
}
|
||||
|
||||
func (matcher *BeTemporallyMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, fmt.Sprintf("to be %s", matcher.Comparator), matcher.CompareTo)
|
||||
}
|
||||
|
||||
func (matcher *BeTemporallyMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, fmt.Sprintf("not to be %s", matcher.Comparator), matcher.CompareTo)
|
||||
}
|
||||
|
||||
func (matcher *BeTemporallyMatcher) Match(actual interface{}) (bool, error) {
|
||||
// predicate to test for time.Time type
|
||||
isTime := func(t interface{}) bool {
|
||||
_, ok := t.(time.Time)
|
||||
return ok
|
||||
}
|
||||
|
||||
if !isTime(actual) {
|
||||
return false, fmt.Errorf("Expected a time.Time. Got:\n%s", format.Object(actual, 1))
|
||||
}
|
||||
|
||||
switch matcher.Comparator {
|
||||
case "==", "~", ">", ">=", "<", "<=":
|
||||
default:
|
||||
return false, fmt.Errorf("Unknown comparator: %s", matcher.Comparator)
|
||||
}
|
||||
|
||||
var threshold = time.Millisecond
|
||||
if len(matcher.Threshold) == 1 {
|
||||
threshold = matcher.Threshold[0]
|
||||
}
|
||||
|
||||
return matcher.matchTimes(actual.(time.Time), matcher.CompareTo, threshold), nil
|
||||
}
|
||||
|
||||
func (matcher *BeTemporallyMatcher) matchTimes(actual, compareTo time.Time, threshold time.Duration) (success bool) {
|
||||
switch matcher.Comparator {
|
||||
case "==":
|
||||
return actual.Equal(compareTo)
|
||||
case "~":
|
||||
diff := actual.Sub(compareTo)
|
||||
return -threshold <= diff && diff <= threshold
|
||||
case ">":
|
||||
return actual.After(compareTo)
|
||||
case ">=":
|
||||
return !actual.Before(compareTo)
|
||||
case "<":
|
||||
return actual.Before(compareTo)
|
||||
case "<=":
|
||||
return !actual.After(compareTo)
|
||||
}
|
||||
return false
|
||||
}
|
28
vendor/github.com/onsi/gomega/matchers/be_true_matcher.go
generated
vendored
Normal file
28
vendor/github.com/onsi/gomega/matchers/be_true_matcher.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// untested sections: 2
|
||||
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
type BeTrueMatcher struct {
|
||||
}
|
||||
|
||||
func (matcher *BeTrueMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
if !isBool(actual) {
|
||||
return false, fmt.Errorf("Expected a boolean. Got:\n%s", format.Object(actual, 1))
|
||||
}
|
||||
|
||||
return actual.(bool), nil
|
||||
}
|
||||
|
||||
func (matcher *BeTrueMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "to be true")
|
||||
}
|
||||
|
||||
func (matcher *BeTrueMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "not to be true")
|
||||
}
|
28
vendor/github.com/onsi/gomega/matchers/be_zero_matcher.go
generated
vendored
Normal file
28
vendor/github.com/onsi/gomega/matchers/be_zero_matcher.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
type BeZeroMatcher struct {
|
||||
}
|
||||
|
||||
func (matcher *BeZeroMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
if actual == nil {
|
||||
return true, nil
|
||||
}
|
||||
zeroValue := reflect.Zero(reflect.TypeOf(actual)).Interface()
|
||||
|
||||
return reflect.DeepEqual(zeroValue, actual), nil
|
||||
|
||||
}
|
||||
|
||||
func (matcher *BeZeroMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "to be zero-valued")
|
||||
}
|
||||
|
||||
func (matcher *BeZeroMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "not to be zero-valued")
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user