Compare commits
42 commits
Author | SHA1 | Date | |
---|---|---|---|
|
db10285368 | ||
|
8454a6ebf3 | ||
|
c318042e96 | ||
|
db9bebb802 | ||
|
fff2c16751 | ||
|
c59d01ab51 | ||
|
62df98a3c8 | ||
|
5c39a23eb2 | ||
|
dbc396b0db | ||
|
86eb045808 | ||
|
c7e309f421 | ||
|
49877b7d41 | ||
|
82b40a53f0 | ||
|
a9d99067ee | ||
|
e7f9c0cba9 | ||
|
fbaf218dfb | ||
|
6a1cf25c87 | ||
|
4aaec87d32 | ||
|
895d810b6c | ||
|
511e76a0ac | ||
|
8be66da88a | ||
|
6d20f347f7 | ||
|
74b12c36b1 | ||
|
269e0208c1 | ||
|
4acb0d54a9 | ||
|
5f667555dc | ||
|
2b6025e67d | ||
|
5ec22fab98 | ||
|
f196aa9ed7 | ||
|
bb5408f5e2 | ||
|
ea8e48f3b8 | ||
|
3dc3b09a8e | ||
|
3fa2a20fe4 | ||
|
c6a2a23ddb | ||
|
9da3b96b1f | ||
|
976dc26dcc | ||
|
fe692040aa | ||
|
0b2dd44d94 | ||
|
df8fc2fba1 | ||
|
6dc4bf93b9 | ||
|
4ffb509939 | ||
|
1a15c4a5aa |
69 changed files with 15614 additions and 9140 deletions
|
@ -1 +1 @@
|
|||
0.21.0
|
||||
0.23.0
|
||||
|
|
25
.github/main.yml
vendored
Normal file
25
.github/main.yml
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
name: CI
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup Go for use with actions
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.16
|
||||
- name: Install goimports
|
||||
run: go get golang.org/x/tools/cmd/goimports
|
||||
- name: Set env with list of directories in repo containin go code
|
||||
run: echo GO_USR_DIRS=$(go list -f {{.Dir}} ./... | grep -E -v "/gen-go/|/vendor/") >> $GITHUB_ENV
|
||||
- name: Run goimports check
|
||||
run: test -z "`for d in $GO_USR_DIRS; do goimports -d $d/*.go | tee /dev/stderr; done`"
|
||||
- name: Create aurora/mesos docker cluster
|
||||
run: docker-compose up -d
|
||||
- name: Run tests
|
||||
run: go test -timeout 35m -race -coverprofile=coverage.txt -covermode=atomic -v github.com/paypal/gorealis
|
57
.github/workflows/codeql-analysis.yml
vendored
Normal file
57
.github/workflows/codeql-analysis.yml
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ main ]
|
||||
schedule:
|
||||
- cron: '34 4 * * 3'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'go' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||
# Learn more:
|
||||
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
- run: go build examples/client.go
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
30
.github/workflows/main.yml
vendored
Normal file
30
.github/workflows/main.yml
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup Go for use with actions
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.16
|
||||
- name: Install goimports
|
||||
run: go get golang.org/x/tools/cmd/goimports
|
||||
- name: Set env with list of directories in repo containin go code
|
||||
run: echo GO_USR_DIRS=$(go list -f {{.Dir}} ./... | grep -E -v "/gen-go/|/vendor/") >> $GITHUB_ENV
|
||||
- name: Run goimports check
|
||||
run: test -z "`for d in $GO_USR_DIRS; do goimports -d $d/*.go | tee /dev/stderr; done`"
|
||||
- name: Create aurora/mesos docker cluster
|
||||
run: docker-compose up -d
|
||||
- name: Run tests
|
||||
run: go test -timeout 35m -race -coverprofile=coverage.txt -covermode=atomic -v github.com/paypal/gorealis
|
71
.golangci.yml
Normal file
71
.golangci.yml
Normal file
|
@ -0,0 +1,71 @@
|
|||
# This file contains all available configuration options
|
||||
# with their default values.
|
||||
|
||||
# options for analysis running
|
||||
run:
|
||||
# default concurrency is a available CPU number
|
||||
concurrency: 4
|
||||
|
||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||
deadline: 1m
|
||||
|
||||
# exit code when at least one issue was found, default is 1
|
||||
issues-exit-code: 1
|
||||
|
||||
# include test files or not, default is true
|
||||
tests: true
|
||||
|
||||
skip-dirs:
|
||||
- gen-go/
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
# colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
|
||||
format: colored-line-number
|
||||
|
||||
# print lines of code with issue, default is true
|
||||
print-issued-lines: true
|
||||
|
||||
# print linter name in the end of issue text, default is true
|
||||
print-linter-name: true
|
||||
|
||||
|
||||
# all available settings of specific linters
|
||||
linters-settings:
|
||||
errcheck:
|
||||
# report about not checking of errors in type assetions: `a := b.(MyStruct)`;
|
||||
# default is false: such cases aren't reported by default.
|
||||
check-type-assertions: true
|
||||
|
||||
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
|
||||
# default is false: such cases aren't reported by default.
|
||||
check-blank: true
|
||||
govet:
|
||||
# report about shadowed variables
|
||||
check-shadowing: true
|
||||
goconst:
|
||||
# minimal length of string constant, 3 by default
|
||||
min-len: 3
|
||||
# minimal occurrences count to trigger, 3 by default
|
||||
min-occurrences: 2
|
||||
misspell:
|
||||
# Correct spellings using locale preferences for US or UK.
|
||||
# Default is to use a neutral variety of English.
|
||||
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
||||
locale: US
|
||||
lll:
|
||||
# max line length, lines longer will be reported. Default is 120.
|
||||
# '\t' is counted as 1 character by default, and can be changed with the tab-width option
|
||||
line-length: 120
|
||||
# tab width in spaces. Default to 1.
|
||||
tab-width: 4
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- govet
|
||||
- goimports
|
||||
- golint
|
||||
- lll
|
||||
- goconst
|
||||
enable-all: false
|
||||
fast: false
|
32
.travis.yml
32
.travis.yml
|
@ -1,32 +0,0 @@
|
|||
sudo: required
|
||||
|
||||
language: go
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- master-v2.0
|
||||
- future
|
||||
|
||||
go:
|
||||
- "1.10.x"
|
||||
|
||||
env:
|
||||
global:
|
||||
- GO_USR_DIRS=$(go list -f {{.Dir}} ./... | grep -E -v "/gen-go/|/vendor/")
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
before_install:
|
||||
- go get golang.org/x/tools/cmd/goimports
|
||||
- test -z "`for d in $GO_USR_DIRS; do goimports -d $d/*.go | tee /dev/stderr; done`"
|
||||
|
||||
install:
|
||||
- docker-compose up -d
|
||||
|
||||
script:
|
||||
- go test -race -coverprofile=coverage.txt -covermode=atomic -v github.com/paypal/gorealis
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
56
CHANGELOG.md
56
CHANGELOG.md
|
@ -1,3 +1,55 @@
|
|||
1.25.1 (unreleased)
|
||||
|
||||
1.25.0
|
||||
|
||||
* Add priority api
|
||||
|
||||
1.24.0
|
||||
|
||||
* enable default sla for slaDrain
|
||||
* Changes Travis CI badge to Github Actions badge
|
||||
* Bug fix for auto paused update monitor
|
||||
* Adds support for running CI on github actions
|
||||
|
||||
1.23.0
|
||||
|
||||
* First release tested against Aurora Scheduler 0.23.0
|
||||
|
||||
1.22.5
|
||||
|
||||
* Upgrading to thrift 0.14.0
|
||||
|
||||
1.22.4
|
||||
|
||||
* Updates which result in a no-op now return a response value so that the caller may analyze it to determine what happened
|
||||
|
||||
1.22.3
|
||||
|
||||
* Contains a monitor timeout fix. Previously an error was being left unchecked which made a specific monitor timining out not be handled properly.
|
||||
|
||||
1.22.2
|
||||
|
||||
* Bug fix: Change in retry mechanism created a deadlock. This release reverts that particular change.
|
||||
|
||||
1.22.1
|
||||
|
||||
* Adding safeguards against setting multiple constraints with the same name for a single task.
|
||||
|
||||
1.22.0
|
||||
|
||||
* CreateService and StartJobUpdate do not continue retrying if a timeout has been encountered
|
||||
by the HTTP client. Instead they now return an error that conforms to the Timedout interface.
|
||||
Users can check for a Timedout error by using `realis.IsTimeout(err)`.
|
||||
* New API function VariableBatchStep has been added which returns the current batch at which
|
||||
a Variable Batch Update configured Update is currently in.
|
||||
* Added new PauseUpdateMonitor which monitors an update until it is an `ROLL_FORWARD_PAUSED` state.
|
||||
* Added variableBatchStep command to sample client to be used for testing new VariableBatchStep api.
|
||||
* JobUpdateStatus has changed function signature from:
|
||||
`JobUpdateStatus(updateKey aurora.JobUpdateKey, desiredStatuses map[aurora.JobUpdateStatus]bool, interval, timeout time.Duration) (aurora.JobUpdateStatus, error)`
|
||||
to
|
||||
`JobUpdateStatus(updateKey aurora.JobUpdateKey, desiredStatuses []aurora.JobUpdateStatus, interval, timeout time.Duration) (aurora.JobUpdateStatus, error)`
|
||||
* Added TerminalUpdateStates function which returns an slice containing all UpdateStates which are considered terminal states.
|
||||
|
||||
1.21.0
|
||||
|
||||
* Version numbering change. Future versions will be labled X.Y.Z where X is the major version, Y is the Aurora version the library has been tested against (e.g. 21 -> 0.21.0), and X is the minor revision.
|
||||
|
@ -5,4 +57,6 @@
|
|||
* `aurora.ACTIVE_STATES`, `aurora.SLAVE_ASSIGNED_STATES`, `aurora.LIVE_STATES`, `aurora.TERMINAL_STATES`, `aurora.ACTIVE_JOB_UPDATE_STATES`, `aurora.AWAITNG_PULSE_JOB_UPDATE_STATES` are all now generated as a slices.
|
||||
* Please use `realis.ActiveStates`, `realis.SlaveAssignedStates`,`realis.LiveStates`, `realis.TerminalStates`, `realis.ActiveJobUpdateStates`, `realis.AwaitingPulseJobUpdateStates` in their places when map representations are needed.
|
||||
* `GetInstanceIds(key *aurora.JobKey, states map[aurora.ScheduleStatus]bool) (map[int32]bool, error)` has changed signature to ` GetInstanceIds(key *aurora.JobKey, states []aurora.ScheduleStatus) ([]int32, error)`
|
||||
* Adding support for GPU as resource.
|
||||
* Adding support for GPU as resource.
|
||||
* Changing compose environment to Aurora snapshot in order to support staggered update.
|
||||
* Adding staggered updates API.
|
||||
|
|
64
Gopkg.lock
generated
64
Gopkg.lock
generated
|
@ -1,64 +0,0 @@
|
|||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
digest = "1:89696c38cec777120b8b1bb5e2d363d655cf2e1e7d8c851919aaa0fd576d9b86"
|
||||
name = "github.com/apache/thrift"
|
||||
packages = ["lib/go/thrift"]
|
||||
pruneopts = ""
|
||||
revision = "384647d290e2e4a55a14b1b7ef1b7e66293a2c33"
|
||||
version = "v0.12.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:56c130d885a4aacae1dd9c7b71cfe39912c7ebc1ff7d2b46083c8812996dc43b"
|
||||
name = "github.com/davecgh/go-spew"
|
||||
packages = ["spew"]
|
||||
pruneopts = ""
|
||||
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:df48fb76fb2a40edea0c9b3d960bc95e326660d82ff1114e1f88001f7a236b40"
|
||||
name = "github.com/pkg/errors"
|
||||
packages = ["."]
|
||||
pruneopts = ""
|
||||
revision = "e881fd58d78e04cf6d0de1217f8707c8cc2249bc"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:256484dbbcd271f9ecebc6795b2df8cad4c458dd0f5fd82a8c2fa0c29f233411"
|
||||
name = "github.com/pmezard/go-difflib"
|
||||
packages = ["difflib"]
|
||||
pruneopts = ""
|
||||
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:78bea5e26e82826dacc5fd64a1013a6711b7075ec8072819b89e6ad76cb8196d"
|
||||
name = "github.com/samuel/go-zookeeper"
|
||||
packages = ["zk"]
|
||||
pruneopts = ""
|
||||
revision = "471cd4e61d7a78ece1791fa5faa0345dc8c7d5a5"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:2d0dc026c4aef5e2f3a0e06a4dabe268b840d8f63190cf6894e02134a03f52c5"
|
||||
name = "github.com/stretchr/testify"
|
||||
packages = [
|
||||
"assert",
|
||||
"require",
|
||||
]
|
||||
pruneopts = ""
|
||||
revision = "b91bfb9ebec76498946beb6af7c0230c7cc7ba6c"
|
||||
version = "v1.2.0"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
input-imports = [
|
||||
"github.com/apache/thrift/lib/go/thrift",
|
||||
"github.com/pkg/errors",
|
||||
"github.com/samuel/go-zookeeper/zk",
|
||||
"github.com/stretchr/testify/assert",
|
||||
"github.com/stretchr/testify/require",
|
||||
]
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
16
Gopkg.toml
16
Gopkg.toml
|
@ -1,16 +0,0 @@
|
|||
[[constraint]]
|
||||
name = "github.com/apache/thrift"
|
||||
version = "0.12.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/pkg/errors"
|
||||
revision = "e881fd58d78e04cf6d0de1217f8707c8cc2249bc"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/samuel/go-zookeeper"
|
||||
revision = "471cd4e61d7a78ece1791fa5faa0345dc8c7d5a5"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/stretchr/testify"
|
||||
version = "1.2.0"
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
# gorealis [](https://godoc.org/github.com/paypal/gorealis) [](https://travis-ci.org/paypal/gorealis) [](https://codecov.io/gh/paypal/gorealis)
|
||||
# gorealis [](https://godoc.org/github.com/paypal/gorealis)  [](https://codecov.io/gh/paypal/gorealis)
|
||||
|
||||
Go library for interacting with [Apache Aurora](https://github.com/apache/aurora).
|
||||
Version 1 of Go library for interacting with [Aurora Scheduler](https://github.com/aurora-scheduler/aurora).
|
||||
|
||||
Version 2 of this library can be found [here](https://github.com/aurora-scheduler/gorealis).
|
||||
|
||||
### Aurora version compatibility
|
||||
Please see [.auroraversion](./.auroraversion) to see the latest Aurora version against which this
|
||||
|
@ -14,7 +16,7 @@ library has been tested.
|
|||
|
||||
## Projects using gorealis
|
||||
|
||||
* [australis](https://github.com/rdelval/australis)
|
||||
* [australis](https://github.com/aurora-scheduler/australis)
|
||||
|
||||
## Contributions
|
||||
Contributions are always welcome. Please raise an issue to discuss a contribution before it is made.
|
||||
|
|
|
@ -716,9 +716,40 @@ struct JobUpdateKey {
|
|||
2: string id
|
||||
}
|
||||
|
||||
/** Limits the amount of active changes being made to instances to groupSize. */
|
||||
struct QueueJobUpdateStrategy {
|
||||
1: i32 groupSize
|
||||
}
|
||||
|
||||
/** Similar to Queue strategy but will not start a new group until all instances in an active
|
||||
* group have finished updating.
|
||||
*/
|
||||
struct BatchJobUpdateStrategy {
|
||||
1: i32 groupSize
|
||||
/* Update will pause automatically after each batch completes */
|
||||
2: bool autopauseAfterBatch
|
||||
}
|
||||
|
||||
/** Same as Batch strategy but each time an active group completes, the size of the next active
|
||||
* group may change.
|
||||
*/
|
||||
struct VariableBatchJobUpdateStrategy {
|
||||
1: list<i32> groupSizes
|
||||
/* Update will pause automatically after each batch completes */
|
||||
2: bool autopauseAfterBatch
|
||||
}
|
||||
|
||||
union JobUpdateStrategy {
|
||||
1: QueueJobUpdateStrategy queueStrategy
|
||||
2: BatchJobUpdateStrategy batchStrategy
|
||||
3: VariableBatchJobUpdateStrategy varBatchStrategy
|
||||
}
|
||||
|
||||
/** Job update thresholds and limits. */
|
||||
struct JobUpdateSettings {
|
||||
/** Max number of instances being updated at any given moment. */
|
||||
/** Deprecated, please set value inside of desired update strategy instead.
|
||||
* Max number of instances being updated at any given moment.
|
||||
*/
|
||||
1: i32 updateGroupSize
|
||||
|
||||
/** Max number of instance failures to tolerate before marking instance as FAILED. */
|
||||
|
@ -736,7 +767,7 @@ struct JobUpdateSettings {
|
|||
/** Instance IDs to act on. All instances will be affected if this is not set. */
|
||||
7: set<Range> updateOnlyTheseInstances
|
||||
|
||||
/**
|
||||
/** Deprecated, please set updateStrategy to the Batch strategy instead.
|
||||
* If true, use updateGroupSize as strict batching boundaries, and avoid proceeding to another
|
||||
* batch until the preceding batch finishes updating.
|
||||
*/
|
||||
|
@ -755,6 +786,9 @@ struct JobUpdateSettings {
|
|||
* differs between the old and new task configurations, updates will use the newest configuration.
|
||||
*/
|
||||
10: optional bool slaAware
|
||||
|
||||
/** Update strategy to be used for the update. See JobUpdateStrategy for choices. */
|
||||
11: optional JobUpdateStrategy updateStrategy
|
||||
}
|
||||
|
||||
/** Event marking a state transition in job update lifecycle. */
|
||||
|
|
|
@ -21,6 +21,8 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Cluster contains the definition of the clusters.json file used by the default Aurora
|
||||
// client for configuration
|
||||
type Cluster struct {
|
||||
Name string `json:"name"`
|
||||
AgentRoot string `json:"slave_root"`
|
||||
|
@ -33,7 +35,8 @@ type Cluster struct {
|
|||
AuthMechanism string `json:"auth_mechanism"`
|
||||
}
|
||||
|
||||
// Loads clusters.json file traditionally located at /etc/aurora/clusters.json
|
||||
// LoadClusters loads clusters.json file traditionally located at /etc/aurora/clusters.json
|
||||
// for use with a gorealis client
|
||||
func LoadClusters(config string) (map[string]Cluster, error) {
|
||||
|
||||
file, err := os.Open(config)
|
||||
|
|
17
container.go
17
container.go
|
@ -18,31 +18,40 @@ import (
|
|||
"github.com/paypal/gorealis/gen-go/apache/aurora"
|
||||
)
|
||||
|
||||
// Container is an interface that defines a single function needed to create
|
||||
// an Aurora container type. It exists because the code must support both Mesos
|
||||
// and Docker containers.
|
||||
type Container interface {
|
||||
Build() *aurora.Container
|
||||
}
|
||||
|
||||
// MesosContainer is a Mesos style container that can be used by Aurora Jobs.
|
||||
type MesosContainer struct {
|
||||
container *aurora.MesosContainer
|
||||
}
|
||||
|
||||
// DockerContainer is a vanilla Docker style container that can be used by Aurora Jobs.
|
||||
type DockerContainer struct {
|
||||
container *aurora.DockerContainer
|
||||
}
|
||||
|
||||
// NewDockerContainer creates a new Aurora compatible Docker container configuration.
|
||||
func NewDockerContainer() DockerContainer {
|
||||
return DockerContainer{container: aurora.NewDockerContainer()}
|
||||
}
|
||||
|
||||
// Build creates an Aurora container based upon the configuration provided.
|
||||
func (c DockerContainer) Build() *aurora.Container {
|
||||
return &aurora.Container{Docker: c.container}
|
||||
}
|
||||
|
||||
// Image adds the name of a Docker image to be used by the Job when running.
|
||||
func (c DockerContainer) Image(image string) DockerContainer {
|
||||
c.container.Image = image
|
||||
return c
|
||||
}
|
||||
|
||||
// AddParameter adds a parameter to be passed to Docker when the container is run.
|
||||
func (c DockerContainer) AddParameter(name, value string) DockerContainer {
|
||||
c.container.Parameters = append(c.container.Parameters, &aurora.DockerParameter{
|
||||
Name: name,
|
||||
|
@ -51,14 +60,17 @@ func (c DockerContainer) AddParameter(name, value string) DockerContainer {
|
|||
return c
|
||||
}
|
||||
|
||||
// NewMesosContainer creates a Mesos style container to be configured and built for use by an Aurora Job.
|
||||
func NewMesosContainer() MesosContainer {
|
||||
return MesosContainer{container: aurora.NewMesosContainer()}
|
||||
}
|
||||
|
||||
// Build creates a Mesos style Aurora container configuration to be passed on to the Aurora Job.
|
||||
func (c MesosContainer) Build() *aurora.Container {
|
||||
return &aurora.Container{Mesos: c.container}
|
||||
}
|
||||
|
||||
// DockerImage configures the Mesos container to use a specific Docker image when being run.
|
||||
func (c MesosContainer) DockerImage(name, tag string) MesosContainer {
|
||||
if c.container.Image == nil {
|
||||
c.container.Image = aurora.NewImage()
|
||||
|
@ -68,11 +80,12 @@ func (c MesosContainer) DockerImage(name, tag string) MesosContainer {
|
|||
return c
|
||||
}
|
||||
|
||||
func (c MesosContainer) AppcImage(name, imageId string) MesosContainer {
|
||||
// AppcImage configures the Mesos container to use an image in the Appc format to run the container.
|
||||
func (c MesosContainer) AppcImage(name, imageID string) MesosContainer {
|
||||
if c.container.Image == nil {
|
||||
c.container.Image = aurora.NewImage()
|
||||
}
|
||||
|
||||
c.container.Image.Appc = &aurora.AppcImage{Name: name, ImageId: imageId}
|
||||
c.container.Image.Appc = &aurora.AppcImage{Name: name, ImageId: imageID}
|
||||
return c
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ services:
|
|||
ipv4_address: 192.168.33.2
|
||||
|
||||
master:
|
||||
image: rdelvalle/mesos-master:1.5.1
|
||||
image: aurorascheduler/mesos-master:1.7.2
|
||||
restart: on-failure
|
||||
ports:
|
||||
- "5050:5050"
|
||||
|
@ -32,12 +32,13 @@ services:
|
|||
- zk
|
||||
|
||||
agent-one:
|
||||
image: rdelvalle/mesos-agent:1.5.1
|
||||
image: aurorascheduler/mesos-agent:1.7.2
|
||||
pid: host
|
||||
restart: on-failure
|
||||
ports:
|
||||
- "5051:5051"
|
||||
environment:
|
||||
MESOS_ATTRIBUTES: 'zone:west'
|
||||
MESOS_MASTER: zk://192.168.33.2:2181/mesos
|
||||
MESOS_CONTAINERIZERS: docker,mesos
|
||||
MESOS_PORT: 5051
|
||||
|
@ -56,12 +57,13 @@ services:
|
|||
- zk
|
||||
|
||||
agent-two:
|
||||
image: rdelvalle/mesos-agent:1.5.1
|
||||
image: aurorascheduler/mesos-agent:1.7.2
|
||||
pid: host
|
||||
restart: on-failure
|
||||
ports:
|
||||
- "5061:5061"
|
||||
environment:
|
||||
MESOS_ATTRIBUTES: 'zone:east'
|
||||
MESOS_MASTER: zk://192.168.33.2:2181/mesos
|
||||
MESOS_CONTAINERIZERS: docker,mesos
|
||||
MESOS_HOSTNAME: localhost
|
||||
|
@ -80,7 +82,7 @@ services:
|
|||
- zk
|
||||
|
||||
aurora-one:
|
||||
image: rdelvalle/aurora:0.21.0
|
||||
image: aurorascheduler/scheduler:0.23.0
|
||||
pid: host
|
||||
ports:
|
||||
- "8081:8081"
|
||||
|
|
|
@ -88,12 +88,6 @@ On Ubuntu, restarting the aurora-scheduler can be achieved by running the follow
|
|||
$ sudo service aurora-scheduler restart
|
||||
```
|
||||
|
||||
### Using a custom client
|
||||
Pystachio does not yet support launching tasks using custom executors. Therefore, a custom
|
||||
client must be used in order to launch tasks using a custom executor. In this case,
|
||||
we will be using [gorealis](https://github.com/paypal/gorealis) to launch a task with
|
||||
the compose executor on Aurora.
|
||||
|
||||
## Using [dce-go](https://github.com/paypal/dce-go)
|
||||
Instead of manually configuring Aurora to run the docker-compose executor, one can follow the instructions provided [here](https://github.com/paypal/dce-go/blob/develop/docs/environment.md) to quickly create a DCE environment that would include mesos, aurora, golang1.7, docker, docker-compose and DCE installed.
|
||||
|
||||
|
@ -107,80 +101,12 @@ Mesos endpoint --> http://192.168.33.8:5050
|
|||
|
||||
### Installing Go
|
||||
|
||||
#### Linux
|
||||
Follow the instructions at the official golang website: [golang.org/doc/install](https://golang.org/doc/install)
|
||||
|
||||
##### Ubuntu
|
||||
### Installing docker-compose
|
||||
|
||||
###### Adding a PPA and install via apt-get
|
||||
```
|
||||
$ sudo add-apt-repository ppa:ubuntu-lxc/lxd-stable
|
||||
$ sudo apt-get update
|
||||
$ sudo apt-get install golang
|
||||
```
|
||||
|
||||
###### Configuring the GOPATH
|
||||
|
||||
Configure the environment to be able to compile and run Go code.
|
||||
```
|
||||
$ mkdir $HOME/go
|
||||
$ echo export GOPATH=$HOME/go >> $HOME/.bashrc
|
||||
$ echo export GOROOT=/usr/lib/go >> $HOME/.bashrc
|
||||
$ echo export PATH=$PATH:$GOPATH/bin >> $HOME/.bashrc
|
||||
$ echo export PATH=$PATH:$GOROOT/bin >> $HOME/.bashrc
|
||||
```
|
||||
|
||||
Finally we must reload the .bashrc configuration:
|
||||
```
|
||||
$ source $HOME/.bashrc
|
||||
```
|
||||
|
||||
#### OS X
|
||||
|
||||
One way to install go on OS X is by using [Homebrew](http://brew.sh/)
|
||||
|
||||
##### Installing Homebrew
|
||||
Run the following command from the terminal to install Hombrew:
|
||||
```
|
||||
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||
```
|
||||
|
||||
##### Installing Go using Hombrew
|
||||
|
||||
Run the following command from the terminal to install Go:
|
||||
```
|
||||
$ brew install go
|
||||
```
|
||||
|
||||
##### Configuring the GOPATH
|
||||
|
||||
Configure the environment to be able to compile and run Go code.
|
||||
```
|
||||
$ mkdir $HOME/go
|
||||
$ echo export GOPATH=$HOME/go >> $HOME/.profile
|
||||
$ echo export GOROOT=/usr/local/opt/go/libexec >> $HOME/.profile
|
||||
$ echo export PATH=$PATH:$GOPATH/bin >> $HOME/.profile
|
||||
$ echo export PATH=$PATH:$GOROOT/bin >> $HOME/.profile
|
||||
```
|
||||
|
||||
Finally we must reload the .profile configuration:
|
||||
```
|
||||
$ source $HOME/.profile
|
||||
```
|
||||
|
||||
#### Windows
|
||||
|
||||
Download and run the msi installer from https://golang.org/dl/
|
||||
|
||||
## Installing Docker Compose (if manually configured Aurora)
|
||||
To show Aurora's new multi executor feature, we need to use at least one custom executor.
|
||||
In this case we will be using the [docker-compose-executor](https://github.com/mesos/docker-compose-executor).
|
||||
|
||||
In order to run the docker-compose executor, each agent must have docker-compose installed on it.
|
||||
|
||||
This can be done using pip:
|
||||
```
|
||||
$ sudo pip install docker-compose
|
||||
```
|
||||
Agents which will run dce-go will need docker-compose in order to sucessfully run the executor.
|
||||
Instructions for installing docker-compose on various platforms may be found on Docker's webiste: [docs.docker.com/compose/install/](https://docs.docker.com/compose/install/)
|
||||
|
||||
## Downloading gorealis
|
||||
Finally, we must get `gorealis` using the `go get` command:
|
||||
|
@ -192,7 +118,7 @@ go get github.com/paypal/gorealis
|
|||
# Creating Aurora Jobs
|
||||
|
||||
## Creating a thermos job
|
||||
To demonstrate that we are able to run jobs using different executors on the
|
||||
To demonstrate that we are able to run jobs using different executors on the
|
||||
same scheduler, we'll first launch a thermos job using the default Aurora Client.
|
||||
|
||||
We can use a sample job for this:
|
||||
|
@ -259,8 +185,8 @@ go run $GOPATH/src/github.com/paypal/gorealis/examples/client.go -executor=compo
|
|||
```
|
||||
|
||||
If everything went according to plan, a new job will be shown in the Aurora UI.
|
||||
We can further investigate inside the Mesos task sandbox. Inside the sandbox, under
|
||||
the sample-app folder, we can find a docker-compose.yml-generated.yml. If we inspect this file,
|
||||
We can further investigate inside the Mesos task sandbox. Inside the sandbox, under
|
||||
the sample-app folder, we can find a docker-compose.yml-generated.yml. If we inspect this file,
|
||||
we can find the port at which we can find the web server we launched.
|
||||
|
||||
Under Web->Ports, we find the port Mesos allocated. We can then navigate to:
|
||||
|
@ -269,10 +195,10 @@ Under Web->Ports, we find the port Mesos allocated. We can then navigate to:
|
|||
A message from the executor should greet us.
|
||||
|
||||
## Creating a Thermos job using gorealis
|
||||
It is also possible to create a thermos job using gorealis. To do this, however,
|
||||
It is also possible to create a thermos job using gorealis. To do this, however,
|
||||
a thermos payload is required. A thermos payload consists of a JSON blob that details
|
||||
the entire task as it exists inside the Aurora Scheduler. *Creating the blob is unfortunately
|
||||
out of the scope of what gorealis does*, so a thermos payload must be generated beforehand or
|
||||
out of the scope of what gorealis does*, so a thermos payload must be generated beforehand or
|
||||
retrieved from the structdump of an existing task for testing purposes.
|
||||
|
||||
A sample thermos JSON payload may be found [here](../examples/thermos_payload.json) in the examples folder.
|
||||
|
|
|
@ -57,4 +57,19 @@ updateJob := realis.NewUpdateJob(job)
|
|||
updateJob.InstanceCount(1)
|
||||
updateJob.Ram(128)
|
||||
msg, err := r.UpdateJob(updateJob, "")
|
||||
```
|
||||
```
|
||||
|
||||
|
||||
* Handling a timeout scenario:
|
||||
|
||||
When sending an API call to Aurora, the call may timeout at the client side.
|
||||
This means that the time limit has been reached while waiting for the scheduler
|
||||
to reply. In such a case it is recommended that the timeout is increased through
|
||||
the use of the `realis.TimeoutMS()` option.
|
||||
|
||||
As these timeouts cannot be totally avoided, there exists a mechanism to mitigate such
|
||||
scenarios. The `StartJobUpdate` and `CreateService` API will return an error that
|
||||
implements the Timeout interface.
|
||||
|
||||
An error can be checked to see if it is a Timeout error by using the `realis.IsTimeout()`
|
||||
function.
|
|
@ -1,6 +1,6 @@
|
|||
# Using the Sample client
|
||||
|
||||
## Usage:
|
||||
## Usage:
|
||||
```
|
||||
Usage of ./client:
|
||||
-cluster string
|
||||
|
|
21
errors.go
21
errors.go
|
@ -23,6 +23,8 @@ type timeout interface {
|
|||
Timedout() bool
|
||||
}
|
||||
|
||||
// IsTimeout returns true if the error being passed as an argument implements the Timeout interface
|
||||
// and the Timedout function returns true.
|
||||
func IsTimeout(err error) bool {
|
||||
temp, ok := err.(timeout)
|
||||
return ok && temp.Timedout()
|
||||
|
@ -61,41 +63,42 @@ func (r *retryErr) RetryCount() int {
|
|||
return r.retryCount
|
||||
}
|
||||
|
||||
// Helper function for testing verification to avoid whitebox testing
|
||||
// ToRetryCount is a helper function for testing verification to avoid whitebox testing
|
||||
// as well as keeping retryErr as a private.
|
||||
// Should NOT be used under any other context.
|
||||
func ToRetryCount(err error) *retryErr {
|
||||
if retryErr, ok := err.(*retryErr); ok {
|
||||
return retryErr
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newRetryError(err error, retryCount int) *retryErr {
|
||||
return &retryErr{error: err, timedout: true, retryCount: retryCount}
|
||||
}
|
||||
|
||||
// Temporary errors indicate that the action may and should be retried.
|
||||
// Temporary errors indicate that the action may or should be retried.
|
||||
type temporary interface {
|
||||
Temporary() bool
|
||||
}
|
||||
|
||||
// IsTemporary indicates whether the error passed in as an argument implements the temporary interface
|
||||
// and if the Temporary function returns true.
|
||||
func IsTemporary(err error) bool {
|
||||
temp, ok := err.(temporary)
|
||||
return ok && temp.Temporary()
|
||||
}
|
||||
|
||||
type TemporaryErr struct {
|
||||
type temporaryErr struct {
|
||||
error
|
||||
temporary bool
|
||||
}
|
||||
|
||||
func (t *TemporaryErr) Temporary() bool {
|
||||
func (t *temporaryErr) Temporary() bool {
|
||||
return t.temporary
|
||||
}
|
||||
|
||||
// Retrying after receiving this error is advised
|
||||
func NewTemporaryError(err error) *TemporaryErr {
|
||||
return &TemporaryErr{error: err, temporary: true}
|
||||
// NewTemporaryError creates a new error which satisfies the Temporary interface.
|
||||
func NewTemporaryError(err error) *temporaryErr {
|
||||
return &temporaryErr{error: err, temporary: true}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ var cmd, executor, url, clustersConfig, clusterName, updateId, username, passwor
|
|||
var caCertsPath string
|
||||
var clientKey, clientCert string
|
||||
|
||||
var CONNECTION_TIMEOUT = 20000
|
||||
var ConnectionTimeout = 20000
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&cmd, "cmd", "", "Job request type to send to Aurora Scheduler")
|
||||
|
@ -82,7 +82,7 @@ func main() {
|
|||
clientOptions := []realis.ClientOption{
|
||||
realis.BasicAuth(username, password),
|
||||
realis.ThriftJSON(),
|
||||
realis.TimeoutMS(CONNECTION_TIMEOUT),
|
||||
realis.TimeoutMS(ConnectionTimeout),
|
||||
realis.BackOff(realis.Backoff{
|
||||
Steps: 2,
|
||||
Duration: 10 * time.Second,
|
||||
|
@ -92,7 +92,6 @@ func main() {
|
|||
realis.Debug(),
|
||||
}
|
||||
|
||||
//check if zkUrl is available.
|
||||
if zkUrl != "" {
|
||||
fmt.Println("zkUrl: ", zkUrl)
|
||||
clientOptions = append(clientOptions, realis.ZKUrl(zkUrl))
|
||||
|
@ -112,7 +111,7 @@ func main() {
|
|||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
monitor = &realis.Monitor{r}
|
||||
monitor = &realis.Monitor{Client: r}
|
||||
defer r.Close()
|
||||
|
||||
switch executor {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// Autogenerated by Thrift Compiler (0.12.0)
|
||||
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
||||
// Code generated by Thrift Compiler (0.14.0). DO NOT EDIT.
|
||||
|
||||
package aurora
|
||||
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
// Autogenerated by Thrift Compiler (0.12.0)
|
||||
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
||||
// Code generated by Thrift Compiler (0.14.0). DO NOT EDIT.
|
||||
|
||||
package aurora
|
||||
|
||||
import (
|
||||
import(
|
||||
"bytes"
|
||||
"context"
|
||||
"reflect"
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/apache/thrift/lib/go/thrift"
|
||||
)
|
||||
|
||||
|
@ -15,7 +14,7 @@ import (
|
|||
var _ = thrift.ZERO
|
||||
var _ = fmt.Printf
|
||||
var _ = context.Background
|
||||
var _ = reflect.DeepEqual
|
||||
var _ = time.Now
|
||||
var _ = bytes.Equal
|
||||
|
||||
const AURORA_EXECUTOR_NAME = "AuroraExecutor"
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,22 +1,22 @@
|
|||
// Autogenerated by Thrift Compiler (0.12.0)
|
||||
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
||||
// Code generated by Thrift Compiler (0.14.0). DO NOT EDIT.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"github.com/apache/thrift/lib/go/thrift"
|
||||
"apache/aurora"
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"github.com/apache/thrift/lib/go/thrift"
|
||||
"apache/aurora"
|
||||
)
|
||||
|
||||
var _ = aurora.GoUnusedProtection__
|
||||
|
||||
func Usage() {
|
||||
fmt.Fprintln(os.Stderr, "Usage of ", os.Args[0], " [-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]:")
|
||||
|
@ -175,19 +175,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "CreateJob requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg162 := flag.Arg(1)
|
||||
mbTrans163 := thrift.NewTMemoryBufferLen(len(arg162))
|
||||
defer mbTrans163.Close()
|
||||
_, err164 := mbTrans163.WriteString(arg162)
|
||||
if err164 != nil {
|
||||
arg213 := flag.Arg(1)
|
||||
mbTrans214 := thrift.NewTMemoryBufferLen(len(arg213))
|
||||
defer mbTrans214.Close()
|
||||
_, err215 := mbTrans214.WriteString(arg213)
|
||||
if err215 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory165 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt166 := factory165.GetProtocol(mbTrans163)
|
||||
factory216 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt217 := factory216.GetProtocol(mbTrans214)
|
||||
argvalue0 := aurora.NewJobConfiguration()
|
||||
err167 := argvalue0.Read(jsProt166)
|
||||
if err167 != nil {
|
||||
err218 := argvalue0.Read(context.Background(), jsProt217)
|
||||
if err218 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -200,19 +200,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "ScheduleCronJob requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg168 := flag.Arg(1)
|
||||
mbTrans169 := thrift.NewTMemoryBufferLen(len(arg168))
|
||||
defer mbTrans169.Close()
|
||||
_, err170 := mbTrans169.WriteString(arg168)
|
||||
if err170 != nil {
|
||||
arg219 := flag.Arg(1)
|
||||
mbTrans220 := thrift.NewTMemoryBufferLen(len(arg219))
|
||||
defer mbTrans220.Close()
|
||||
_, err221 := mbTrans220.WriteString(arg219)
|
||||
if err221 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory171 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt172 := factory171.GetProtocol(mbTrans169)
|
||||
factory222 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt223 := factory222.GetProtocol(mbTrans220)
|
||||
argvalue0 := aurora.NewJobConfiguration()
|
||||
err173 := argvalue0.Read(jsProt172)
|
||||
if err173 != nil {
|
||||
err224 := argvalue0.Read(context.Background(), jsProt223)
|
||||
if err224 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -225,19 +225,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "DescheduleCronJob requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg174 := flag.Arg(1)
|
||||
mbTrans175 := thrift.NewTMemoryBufferLen(len(arg174))
|
||||
defer mbTrans175.Close()
|
||||
_, err176 := mbTrans175.WriteString(arg174)
|
||||
if err176 != nil {
|
||||
arg225 := flag.Arg(1)
|
||||
mbTrans226 := thrift.NewTMemoryBufferLen(len(arg225))
|
||||
defer mbTrans226.Close()
|
||||
_, err227 := mbTrans226.WriteString(arg225)
|
||||
if err227 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory177 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt178 := factory177.GetProtocol(mbTrans175)
|
||||
factory228 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt229 := factory228.GetProtocol(mbTrans226)
|
||||
argvalue0 := aurora.NewJobKey()
|
||||
err179 := argvalue0.Read(jsProt178)
|
||||
if err179 != nil {
|
||||
err230 := argvalue0.Read(context.Background(), jsProt229)
|
||||
if err230 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -250,19 +250,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "StartCronJob requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg180 := flag.Arg(1)
|
||||
mbTrans181 := thrift.NewTMemoryBufferLen(len(arg180))
|
||||
defer mbTrans181.Close()
|
||||
_, err182 := mbTrans181.WriteString(arg180)
|
||||
if err182 != nil {
|
||||
arg231 := flag.Arg(1)
|
||||
mbTrans232 := thrift.NewTMemoryBufferLen(len(arg231))
|
||||
defer mbTrans232.Close()
|
||||
_, err233 := mbTrans232.WriteString(arg231)
|
||||
if err233 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory183 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt184 := factory183.GetProtocol(mbTrans181)
|
||||
factory234 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt235 := factory234.GetProtocol(mbTrans232)
|
||||
argvalue0 := aurora.NewJobKey()
|
||||
err185 := argvalue0.Read(jsProt184)
|
||||
if err185 != nil {
|
||||
err236 := argvalue0.Read(context.Background(), jsProt235)
|
||||
if err236 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -275,36 +275,36 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "RestartShards requires 2 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg186 := flag.Arg(1)
|
||||
mbTrans187 := thrift.NewTMemoryBufferLen(len(arg186))
|
||||
defer mbTrans187.Close()
|
||||
_, err188 := mbTrans187.WriteString(arg186)
|
||||
if err188 != nil {
|
||||
arg237 := flag.Arg(1)
|
||||
mbTrans238 := thrift.NewTMemoryBufferLen(len(arg237))
|
||||
defer mbTrans238.Close()
|
||||
_, err239 := mbTrans238.WriteString(arg237)
|
||||
if err239 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory189 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt190 := factory189.GetProtocol(mbTrans187)
|
||||
factory240 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt241 := factory240.GetProtocol(mbTrans238)
|
||||
argvalue0 := aurora.NewJobKey()
|
||||
err191 := argvalue0.Read(jsProt190)
|
||||
if err191 != nil {
|
||||
err242 := argvalue0.Read(context.Background(), jsProt241)
|
||||
if err242 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
value0 := argvalue0
|
||||
arg192 := flag.Arg(2)
|
||||
mbTrans193 := thrift.NewTMemoryBufferLen(len(arg192))
|
||||
defer mbTrans193.Close()
|
||||
_, err194 := mbTrans193.WriteString(arg192)
|
||||
if err194 != nil {
|
||||
arg243 := flag.Arg(2)
|
||||
mbTrans244 := thrift.NewTMemoryBufferLen(len(arg243))
|
||||
defer mbTrans244.Close()
|
||||
_, err245 := mbTrans244.WriteString(arg243)
|
||||
if err245 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory195 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt196 := factory195.GetProtocol(mbTrans193)
|
||||
factory246 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt247 := factory246.GetProtocol(mbTrans244)
|
||||
containerStruct1 := aurora.NewAuroraSchedulerManagerRestartShardsArgs()
|
||||
err197 := containerStruct1.ReadField2(jsProt196)
|
||||
if err197 != nil {
|
||||
err248 := containerStruct1.ReadField2(context.Background(), jsProt247)
|
||||
if err248 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -318,36 +318,36 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "KillTasks requires 3 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg198 := flag.Arg(1)
|
||||
mbTrans199 := thrift.NewTMemoryBufferLen(len(arg198))
|
||||
defer mbTrans199.Close()
|
||||
_, err200 := mbTrans199.WriteString(arg198)
|
||||
if err200 != nil {
|
||||
arg249 := flag.Arg(1)
|
||||
mbTrans250 := thrift.NewTMemoryBufferLen(len(arg249))
|
||||
defer mbTrans250.Close()
|
||||
_, err251 := mbTrans250.WriteString(arg249)
|
||||
if err251 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory201 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt202 := factory201.GetProtocol(mbTrans199)
|
||||
factory252 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt253 := factory252.GetProtocol(mbTrans250)
|
||||
argvalue0 := aurora.NewJobKey()
|
||||
err203 := argvalue0.Read(jsProt202)
|
||||
if err203 != nil {
|
||||
err254 := argvalue0.Read(context.Background(), jsProt253)
|
||||
if err254 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
value0 := argvalue0
|
||||
arg204 := flag.Arg(2)
|
||||
mbTrans205 := thrift.NewTMemoryBufferLen(len(arg204))
|
||||
defer mbTrans205.Close()
|
||||
_, err206 := mbTrans205.WriteString(arg204)
|
||||
if err206 != nil {
|
||||
arg255 := flag.Arg(2)
|
||||
mbTrans256 := thrift.NewTMemoryBufferLen(len(arg255))
|
||||
defer mbTrans256.Close()
|
||||
_, err257 := mbTrans256.WriteString(arg255)
|
||||
if err257 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory207 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt208 := factory207.GetProtocol(mbTrans205)
|
||||
factory258 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt259 := factory258.GetProtocol(mbTrans256)
|
||||
containerStruct1 := aurora.NewAuroraSchedulerManagerKillTasksArgs()
|
||||
err209 := containerStruct1.ReadField2(jsProt208)
|
||||
if err209 != nil {
|
||||
err260 := containerStruct1.ReadField2(context.Background(), jsProt259)
|
||||
if err260 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -363,25 +363,25 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "AddInstances requires 2 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg211 := flag.Arg(1)
|
||||
mbTrans212 := thrift.NewTMemoryBufferLen(len(arg211))
|
||||
defer mbTrans212.Close()
|
||||
_, err213 := mbTrans212.WriteString(arg211)
|
||||
if err213 != nil {
|
||||
arg262 := flag.Arg(1)
|
||||
mbTrans263 := thrift.NewTMemoryBufferLen(len(arg262))
|
||||
defer mbTrans263.Close()
|
||||
_, err264 := mbTrans263.WriteString(arg262)
|
||||
if err264 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory214 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt215 := factory214.GetProtocol(mbTrans212)
|
||||
factory265 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt266 := factory265.GetProtocol(mbTrans263)
|
||||
argvalue0 := aurora.NewInstanceKey()
|
||||
err216 := argvalue0.Read(jsProt215)
|
||||
if err216 != nil {
|
||||
err267 := argvalue0.Read(context.Background(), jsProt266)
|
||||
if err267 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
value0 := argvalue0
|
||||
tmp1, err217 := (strconv.Atoi(flag.Arg(2)))
|
||||
if err217 != nil {
|
||||
tmp1, err268 := (strconv.Atoi(flag.Arg(2)))
|
||||
if err268 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -395,19 +395,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "ReplaceCronTemplate requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg218 := flag.Arg(1)
|
||||
mbTrans219 := thrift.NewTMemoryBufferLen(len(arg218))
|
||||
defer mbTrans219.Close()
|
||||
_, err220 := mbTrans219.WriteString(arg218)
|
||||
if err220 != nil {
|
||||
arg269 := flag.Arg(1)
|
||||
mbTrans270 := thrift.NewTMemoryBufferLen(len(arg269))
|
||||
defer mbTrans270.Close()
|
||||
_, err271 := mbTrans270.WriteString(arg269)
|
||||
if err271 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory221 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt222 := factory221.GetProtocol(mbTrans219)
|
||||
factory272 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt273 := factory272.GetProtocol(mbTrans270)
|
||||
argvalue0 := aurora.NewJobConfiguration()
|
||||
err223 := argvalue0.Read(jsProt222)
|
||||
if err223 != nil {
|
||||
err274 := argvalue0.Read(context.Background(), jsProt273)
|
||||
if err274 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -420,19 +420,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "StartJobUpdate requires 2 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg224 := flag.Arg(1)
|
||||
mbTrans225 := thrift.NewTMemoryBufferLen(len(arg224))
|
||||
defer mbTrans225.Close()
|
||||
_, err226 := mbTrans225.WriteString(arg224)
|
||||
if err226 != nil {
|
||||
arg275 := flag.Arg(1)
|
||||
mbTrans276 := thrift.NewTMemoryBufferLen(len(arg275))
|
||||
defer mbTrans276.Close()
|
||||
_, err277 := mbTrans276.WriteString(arg275)
|
||||
if err277 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory227 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt228 := factory227.GetProtocol(mbTrans225)
|
||||
factory278 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt279 := factory278.GetProtocol(mbTrans276)
|
||||
argvalue0 := aurora.NewJobUpdateRequest()
|
||||
err229 := argvalue0.Read(jsProt228)
|
||||
if err229 != nil {
|
||||
err280 := argvalue0.Read(context.Background(), jsProt279)
|
||||
if err280 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -447,19 +447,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "PauseJobUpdate requires 2 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg231 := flag.Arg(1)
|
||||
mbTrans232 := thrift.NewTMemoryBufferLen(len(arg231))
|
||||
defer mbTrans232.Close()
|
||||
_, err233 := mbTrans232.WriteString(arg231)
|
||||
if err233 != nil {
|
||||
arg282 := flag.Arg(1)
|
||||
mbTrans283 := thrift.NewTMemoryBufferLen(len(arg282))
|
||||
defer mbTrans283.Close()
|
||||
_, err284 := mbTrans283.WriteString(arg282)
|
||||
if err284 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory234 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt235 := factory234.GetProtocol(mbTrans232)
|
||||
factory285 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt286 := factory285.GetProtocol(mbTrans283)
|
||||
argvalue0 := aurora.NewJobUpdateKey()
|
||||
err236 := argvalue0.Read(jsProt235)
|
||||
if err236 != nil {
|
||||
err287 := argvalue0.Read(context.Background(), jsProt286)
|
||||
if err287 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -474,19 +474,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "ResumeJobUpdate requires 2 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg238 := flag.Arg(1)
|
||||
mbTrans239 := thrift.NewTMemoryBufferLen(len(arg238))
|
||||
defer mbTrans239.Close()
|
||||
_, err240 := mbTrans239.WriteString(arg238)
|
||||
if err240 != nil {
|
||||
arg289 := flag.Arg(1)
|
||||
mbTrans290 := thrift.NewTMemoryBufferLen(len(arg289))
|
||||
defer mbTrans290.Close()
|
||||
_, err291 := mbTrans290.WriteString(arg289)
|
||||
if err291 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory241 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt242 := factory241.GetProtocol(mbTrans239)
|
||||
factory292 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt293 := factory292.GetProtocol(mbTrans290)
|
||||
argvalue0 := aurora.NewJobUpdateKey()
|
||||
err243 := argvalue0.Read(jsProt242)
|
||||
if err243 != nil {
|
||||
err294 := argvalue0.Read(context.Background(), jsProt293)
|
||||
if err294 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -501,19 +501,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "AbortJobUpdate requires 2 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg245 := flag.Arg(1)
|
||||
mbTrans246 := thrift.NewTMemoryBufferLen(len(arg245))
|
||||
defer mbTrans246.Close()
|
||||
_, err247 := mbTrans246.WriteString(arg245)
|
||||
if err247 != nil {
|
||||
arg296 := flag.Arg(1)
|
||||
mbTrans297 := thrift.NewTMemoryBufferLen(len(arg296))
|
||||
defer mbTrans297.Close()
|
||||
_, err298 := mbTrans297.WriteString(arg296)
|
||||
if err298 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory248 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt249 := factory248.GetProtocol(mbTrans246)
|
||||
factory299 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt300 := factory299.GetProtocol(mbTrans297)
|
||||
argvalue0 := aurora.NewJobUpdateKey()
|
||||
err250 := argvalue0.Read(jsProt249)
|
||||
if err250 != nil {
|
||||
err301 := argvalue0.Read(context.Background(), jsProt300)
|
||||
if err301 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -528,19 +528,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "RollbackJobUpdate requires 2 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg252 := flag.Arg(1)
|
||||
mbTrans253 := thrift.NewTMemoryBufferLen(len(arg252))
|
||||
defer mbTrans253.Close()
|
||||
_, err254 := mbTrans253.WriteString(arg252)
|
||||
if err254 != nil {
|
||||
arg303 := flag.Arg(1)
|
||||
mbTrans304 := thrift.NewTMemoryBufferLen(len(arg303))
|
||||
defer mbTrans304.Close()
|
||||
_, err305 := mbTrans304.WriteString(arg303)
|
||||
if err305 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory255 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt256 := factory255.GetProtocol(mbTrans253)
|
||||
factory306 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt307 := factory306.GetProtocol(mbTrans304)
|
||||
argvalue0 := aurora.NewJobUpdateKey()
|
||||
err257 := argvalue0.Read(jsProt256)
|
||||
if err257 != nil {
|
||||
err308 := argvalue0.Read(context.Background(), jsProt307)
|
||||
if err308 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -555,19 +555,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "PulseJobUpdate requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg259 := flag.Arg(1)
|
||||
mbTrans260 := thrift.NewTMemoryBufferLen(len(arg259))
|
||||
defer mbTrans260.Close()
|
||||
_, err261 := mbTrans260.WriteString(arg259)
|
||||
if err261 != nil {
|
||||
arg310 := flag.Arg(1)
|
||||
mbTrans311 := thrift.NewTMemoryBufferLen(len(arg310))
|
||||
defer mbTrans311.Close()
|
||||
_, err312 := mbTrans311.WriteString(arg310)
|
||||
if err312 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory262 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt263 := factory262.GetProtocol(mbTrans260)
|
||||
factory313 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt314 := factory313.GetProtocol(mbTrans311)
|
||||
argvalue0 := aurora.NewJobUpdateKey()
|
||||
err264 := argvalue0.Read(jsProt263)
|
||||
if err264 != nil {
|
||||
err315 := argvalue0.Read(context.Background(), jsProt314)
|
||||
if err315 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -598,19 +598,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "GetTasksStatus requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg266 := flag.Arg(1)
|
||||
mbTrans267 := thrift.NewTMemoryBufferLen(len(arg266))
|
||||
defer mbTrans267.Close()
|
||||
_, err268 := mbTrans267.WriteString(arg266)
|
||||
if err268 != nil {
|
||||
arg317 := flag.Arg(1)
|
||||
mbTrans318 := thrift.NewTMemoryBufferLen(len(arg317))
|
||||
defer mbTrans318.Close()
|
||||
_, err319 := mbTrans318.WriteString(arg317)
|
||||
if err319 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory269 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt270 := factory269.GetProtocol(mbTrans267)
|
||||
factory320 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt321 := factory320.GetProtocol(mbTrans318)
|
||||
argvalue0 := aurora.NewTaskQuery()
|
||||
err271 := argvalue0.Read(jsProt270)
|
||||
if err271 != nil {
|
||||
err322 := argvalue0.Read(context.Background(), jsProt321)
|
||||
if err322 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -623,19 +623,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "GetTasksWithoutConfigs requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg272 := flag.Arg(1)
|
||||
mbTrans273 := thrift.NewTMemoryBufferLen(len(arg272))
|
||||
defer mbTrans273.Close()
|
||||
_, err274 := mbTrans273.WriteString(arg272)
|
||||
if err274 != nil {
|
||||
arg323 := flag.Arg(1)
|
||||
mbTrans324 := thrift.NewTMemoryBufferLen(len(arg323))
|
||||
defer mbTrans324.Close()
|
||||
_, err325 := mbTrans324.WriteString(arg323)
|
||||
if err325 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory275 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt276 := factory275.GetProtocol(mbTrans273)
|
||||
factory326 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt327 := factory326.GetProtocol(mbTrans324)
|
||||
argvalue0 := aurora.NewTaskQuery()
|
||||
err277 := argvalue0.Read(jsProt276)
|
||||
if err277 != nil {
|
||||
err328 := argvalue0.Read(context.Background(), jsProt327)
|
||||
if err328 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -648,19 +648,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "GetPendingReason requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg278 := flag.Arg(1)
|
||||
mbTrans279 := thrift.NewTMemoryBufferLen(len(arg278))
|
||||
defer mbTrans279.Close()
|
||||
_, err280 := mbTrans279.WriteString(arg278)
|
||||
if err280 != nil {
|
||||
arg329 := flag.Arg(1)
|
||||
mbTrans330 := thrift.NewTMemoryBufferLen(len(arg329))
|
||||
defer mbTrans330.Close()
|
||||
_, err331 := mbTrans330.WriteString(arg329)
|
||||
if err331 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory281 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt282 := factory281.GetProtocol(mbTrans279)
|
||||
factory332 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt333 := factory332.GetProtocol(mbTrans330)
|
||||
argvalue0 := aurora.NewTaskQuery()
|
||||
err283 := argvalue0.Read(jsProt282)
|
||||
if err283 != nil {
|
||||
err334 := argvalue0.Read(context.Background(), jsProt333)
|
||||
if err334 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -673,19 +673,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "GetConfigSummary requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg284 := flag.Arg(1)
|
||||
mbTrans285 := thrift.NewTMemoryBufferLen(len(arg284))
|
||||
defer mbTrans285.Close()
|
||||
_, err286 := mbTrans285.WriteString(arg284)
|
||||
if err286 != nil {
|
||||
arg335 := flag.Arg(1)
|
||||
mbTrans336 := thrift.NewTMemoryBufferLen(len(arg335))
|
||||
defer mbTrans336.Close()
|
||||
_, err337 := mbTrans336.WriteString(arg335)
|
||||
if err337 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory287 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt288 := factory287.GetProtocol(mbTrans285)
|
||||
factory338 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt339 := factory338.GetProtocol(mbTrans336)
|
||||
argvalue0 := aurora.NewJobKey()
|
||||
err289 := argvalue0.Read(jsProt288)
|
||||
if err289 != nil {
|
||||
err340 := argvalue0.Read(context.Background(), jsProt339)
|
||||
if err340 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -718,19 +718,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "PopulateJobConfig requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg292 := flag.Arg(1)
|
||||
mbTrans293 := thrift.NewTMemoryBufferLen(len(arg292))
|
||||
defer mbTrans293.Close()
|
||||
_, err294 := mbTrans293.WriteString(arg292)
|
||||
if err294 != nil {
|
||||
arg343 := flag.Arg(1)
|
||||
mbTrans344 := thrift.NewTMemoryBufferLen(len(arg343))
|
||||
defer mbTrans344.Close()
|
||||
_, err345 := mbTrans344.WriteString(arg343)
|
||||
if err345 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory295 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt296 := factory295.GetProtocol(mbTrans293)
|
||||
factory346 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt347 := factory346.GetProtocol(mbTrans344)
|
||||
argvalue0 := aurora.NewJobConfiguration()
|
||||
err297 := argvalue0.Read(jsProt296)
|
||||
if err297 != nil {
|
||||
err348 := argvalue0.Read(context.Background(), jsProt347)
|
||||
if err348 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -743,19 +743,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "GetJobUpdateSummaries requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg298 := flag.Arg(1)
|
||||
mbTrans299 := thrift.NewTMemoryBufferLen(len(arg298))
|
||||
defer mbTrans299.Close()
|
||||
_, err300 := mbTrans299.WriteString(arg298)
|
||||
if err300 != nil {
|
||||
arg349 := flag.Arg(1)
|
||||
mbTrans350 := thrift.NewTMemoryBufferLen(len(arg349))
|
||||
defer mbTrans350.Close()
|
||||
_, err351 := mbTrans350.WriteString(arg349)
|
||||
if err351 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory301 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt302 := factory301.GetProtocol(mbTrans299)
|
||||
factory352 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt353 := factory352.GetProtocol(mbTrans350)
|
||||
argvalue0 := aurora.NewJobUpdateQuery()
|
||||
err303 := argvalue0.Read(jsProt302)
|
||||
if err303 != nil {
|
||||
err354 := argvalue0.Read(context.Background(), jsProt353)
|
||||
if err354 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -768,19 +768,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "GetJobUpdateDetails requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg304 := flag.Arg(1)
|
||||
mbTrans305 := thrift.NewTMemoryBufferLen(len(arg304))
|
||||
defer mbTrans305.Close()
|
||||
_, err306 := mbTrans305.WriteString(arg304)
|
||||
if err306 != nil {
|
||||
arg355 := flag.Arg(1)
|
||||
mbTrans356 := thrift.NewTMemoryBufferLen(len(arg355))
|
||||
defer mbTrans356.Close()
|
||||
_, err357 := mbTrans356.WriteString(arg355)
|
||||
if err357 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory307 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt308 := factory307.GetProtocol(mbTrans305)
|
||||
factory358 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt359 := factory358.GetProtocol(mbTrans356)
|
||||
argvalue0 := aurora.NewJobUpdateQuery()
|
||||
err309 := argvalue0.Read(jsProt308)
|
||||
if err309 != nil {
|
||||
err360 := argvalue0.Read(context.Background(), jsProt359)
|
||||
if err360 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -793,19 +793,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "GetJobUpdateDiff requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg310 := flag.Arg(1)
|
||||
mbTrans311 := thrift.NewTMemoryBufferLen(len(arg310))
|
||||
defer mbTrans311.Close()
|
||||
_, err312 := mbTrans311.WriteString(arg310)
|
||||
if err312 != nil {
|
||||
arg361 := flag.Arg(1)
|
||||
mbTrans362 := thrift.NewTMemoryBufferLen(len(arg361))
|
||||
defer mbTrans362.Close()
|
||||
_, err363 := mbTrans362.WriteString(arg361)
|
||||
if err363 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory313 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt314 := factory313.GetProtocol(mbTrans311)
|
||||
factory364 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt365 := factory364.GetProtocol(mbTrans362)
|
||||
argvalue0 := aurora.NewJobUpdateRequest()
|
||||
err315 := argvalue0.Read(jsProt314)
|
||||
if err315 != nil {
|
||||
err366 := argvalue0.Read(context.Background(), jsProt365)
|
||||
if err366 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
// Autogenerated by Thrift Compiler (0.12.0)
|
||||
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
||||
// Code generated by Thrift Compiler (0.14.0). DO NOT EDIT.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"github.com/apache/thrift/lib/go/thrift"
|
||||
"apache/aurora"
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"github.com/apache/thrift/lib/go/thrift"
|
||||
"apache/aurora"
|
||||
)
|
||||
|
||||
var _ = aurora.GoUnusedProtection__
|
||||
|
||||
func Usage() {
|
||||
fmt.Fprintln(os.Stderr, "Usage of ", os.Args[0], " [-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]:")
|
||||
|
@ -179,19 +179,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "GetTasksStatus requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg81 := flag.Arg(1)
|
||||
mbTrans82 := thrift.NewTMemoryBufferLen(len(arg81))
|
||||
defer mbTrans82.Close()
|
||||
_, err83 := mbTrans82.WriteString(arg81)
|
||||
if err83 != nil {
|
||||
arg132 := flag.Arg(1)
|
||||
mbTrans133 := thrift.NewTMemoryBufferLen(len(arg132))
|
||||
defer mbTrans133.Close()
|
||||
_, err134 := mbTrans133.WriteString(arg132)
|
||||
if err134 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory84 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt85 := factory84.GetProtocol(mbTrans82)
|
||||
factory135 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt136 := factory135.GetProtocol(mbTrans133)
|
||||
argvalue0 := aurora.NewTaskQuery()
|
||||
err86 := argvalue0.Read(jsProt85)
|
||||
if err86 != nil {
|
||||
err137 := argvalue0.Read(context.Background(), jsProt136)
|
||||
if err137 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -204,19 +204,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "GetTasksWithoutConfigs requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg87 := flag.Arg(1)
|
||||
mbTrans88 := thrift.NewTMemoryBufferLen(len(arg87))
|
||||
defer mbTrans88.Close()
|
||||
_, err89 := mbTrans88.WriteString(arg87)
|
||||
if err89 != nil {
|
||||
arg138 := flag.Arg(1)
|
||||
mbTrans139 := thrift.NewTMemoryBufferLen(len(arg138))
|
||||
defer mbTrans139.Close()
|
||||
_, err140 := mbTrans139.WriteString(arg138)
|
||||
if err140 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory90 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt91 := factory90.GetProtocol(mbTrans88)
|
||||
factory141 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt142 := factory141.GetProtocol(mbTrans139)
|
||||
argvalue0 := aurora.NewTaskQuery()
|
||||
err92 := argvalue0.Read(jsProt91)
|
||||
if err92 != nil {
|
||||
err143 := argvalue0.Read(context.Background(), jsProt142)
|
||||
if err143 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -229,19 +229,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "GetPendingReason requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg93 := flag.Arg(1)
|
||||
mbTrans94 := thrift.NewTMemoryBufferLen(len(arg93))
|
||||
defer mbTrans94.Close()
|
||||
_, err95 := mbTrans94.WriteString(arg93)
|
||||
if err95 != nil {
|
||||
arg144 := flag.Arg(1)
|
||||
mbTrans145 := thrift.NewTMemoryBufferLen(len(arg144))
|
||||
defer mbTrans145.Close()
|
||||
_, err146 := mbTrans145.WriteString(arg144)
|
||||
if err146 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory96 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt97 := factory96.GetProtocol(mbTrans94)
|
||||
factory147 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt148 := factory147.GetProtocol(mbTrans145)
|
||||
argvalue0 := aurora.NewTaskQuery()
|
||||
err98 := argvalue0.Read(jsProt97)
|
||||
if err98 != nil {
|
||||
err149 := argvalue0.Read(context.Background(), jsProt148)
|
||||
if err149 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -254,19 +254,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "GetConfigSummary requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg99 := flag.Arg(1)
|
||||
mbTrans100 := thrift.NewTMemoryBufferLen(len(arg99))
|
||||
defer mbTrans100.Close()
|
||||
_, err101 := mbTrans100.WriteString(arg99)
|
||||
if err101 != nil {
|
||||
arg150 := flag.Arg(1)
|
||||
mbTrans151 := thrift.NewTMemoryBufferLen(len(arg150))
|
||||
defer mbTrans151.Close()
|
||||
_, err152 := mbTrans151.WriteString(arg150)
|
||||
if err152 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory102 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt103 := factory102.GetProtocol(mbTrans100)
|
||||
factory153 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt154 := factory153.GetProtocol(mbTrans151)
|
||||
argvalue0 := aurora.NewJobKey()
|
||||
err104 := argvalue0.Read(jsProt103)
|
||||
if err104 != nil {
|
||||
err155 := argvalue0.Read(context.Background(), jsProt154)
|
||||
if err155 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -299,19 +299,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "PopulateJobConfig requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg107 := flag.Arg(1)
|
||||
mbTrans108 := thrift.NewTMemoryBufferLen(len(arg107))
|
||||
defer mbTrans108.Close()
|
||||
_, err109 := mbTrans108.WriteString(arg107)
|
||||
if err109 != nil {
|
||||
arg158 := flag.Arg(1)
|
||||
mbTrans159 := thrift.NewTMemoryBufferLen(len(arg158))
|
||||
defer mbTrans159.Close()
|
||||
_, err160 := mbTrans159.WriteString(arg158)
|
||||
if err160 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory110 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt111 := factory110.GetProtocol(mbTrans108)
|
||||
factory161 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt162 := factory161.GetProtocol(mbTrans159)
|
||||
argvalue0 := aurora.NewJobConfiguration()
|
||||
err112 := argvalue0.Read(jsProt111)
|
||||
if err112 != nil {
|
||||
err163 := argvalue0.Read(context.Background(), jsProt162)
|
||||
if err163 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -324,19 +324,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "GetJobUpdateSummaries requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg113 := flag.Arg(1)
|
||||
mbTrans114 := thrift.NewTMemoryBufferLen(len(arg113))
|
||||
defer mbTrans114.Close()
|
||||
_, err115 := mbTrans114.WriteString(arg113)
|
||||
if err115 != nil {
|
||||
arg164 := flag.Arg(1)
|
||||
mbTrans165 := thrift.NewTMemoryBufferLen(len(arg164))
|
||||
defer mbTrans165.Close()
|
||||
_, err166 := mbTrans165.WriteString(arg164)
|
||||
if err166 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory116 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt117 := factory116.GetProtocol(mbTrans114)
|
||||
factory167 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt168 := factory167.GetProtocol(mbTrans165)
|
||||
argvalue0 := aurora.NewJobUpdateQuery()
|
||||
err118 := argvalue0.Read(jsProt117)
|
||||
if err118 != nil {
|
||||
err169 := argvalue0.Read(context.Background(), jsProt168)
|
||||
if err169 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -349,19 +349,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "GetJobUpdateDetails requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg119 := flag.Arg(1)
|
||||
mbTrans120 := thrift.NewTMemoryBufferLen(len(arg119))
|
||||
defer mbTrans120.Close()
|
||||
_, err121 := mbTrans120.WriteString(arg119)
|
||||
if err121 != nil {
|
||||
arg170 := flag.Arg(1)
|
||||
mbTrans171 := thrift.NewTMemoryBufferLen(len(arg170))
|
||||
defer mbTrans171.Close()
|
||||
_, err172 := mbTrans171.WriteString(arg170)
|
||||
if err172 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory122 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt123 := factory122.GetProtocol(mbTrans120)
|
||||
factory173 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt174 := factory173.GetProtocol(mbTrans171)
|
||||
argvalue0 := aurora.NewJobUpdateQuery()
|
||||
err124 := argvalue0.Read(jsProt123)
|
||||
if err124 != nil {
|
||||
err175 := argvalue0.Read(context.Background(), jsProt174)
|
||||
if err175 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
@ -374,19 +374,19 @@ func main() {
|
|||
fmt.Fprintln(os.Stderr, "GetJobUpdateDiff requires 1 args")
|
||||
flag.Usage()
|
||||
}
|
||||
arg125 := flag.Arg(1)
|
||||
mbTrans126 := thrift.NewTMemoryBufferLen(len(arg125))
|
||||
defer mbTrans126.Close()
|
||||
_, err127 := mbTrans126.WriteString(arg125)
|
||||
if err127 != nil {
|
||||
arg176 := flag.Arg(1)
|
||||
mbTrans177 := thrift.NewTMemoryBufferLen(len(arg176))
|
||||
defer mbTrans177.Close()
|
||||
_, err178 := mbTrans177.WriteString(arg176)
|
||||
if err178 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
factory128 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt129 := factory128.GetProtocol(mbTrans126)
|
||||
factory179 := thrift.NewTJSONProtocolFactory()
|
||||
jsProt180 := factory179.GetProtocol(mbTrans177)
|
||||
argvalue0 := aurora.NewJobUpdateRequest()
|
||||
err130 := argvalue0.Read(jsProt129)
|
||||
if err130 != nil {
|
||||
err181 := argvalue0.Read(context.Background(), jsProt180)
|
||||
if err181 != nil {
|
||||
Usage()
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#! /bin/bash
|
||||
|
||||
THRIFT_VER=0.9.3
|
||||
THRIFT_VER=0.14.0
|
||||
|
||||
if [[ $(thrift -version | grep -e $THRIFT_VER -c) -ne 1 ]]; then
|
||||
echo "Warning: This wrapper has only been tested with version" $THRIFT_VER;
|
||||
|
|
12
go.mod
Normal file
12
go.mod
Normal file
|
@ -0,0 +1,12 @@
|
|||
module github.com/paypal/gorealis
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/apache/thrift v0.14.0
|
||||
github.com/davecgh/go-spew v1.1.0 // indirect
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/samuel/go-zookeeper v0.0.0-20171117190445-471cd4e61d7a
|
||||
github.com/stretchr/testify v1.7.0
|
||||
)
|
30
go.sum
Normal file
30
go.sum
Normal file
|
@ -0,0 +1,30 @@
|
|||
github.com/apache/thrift v0.13.0 h1:5hryIiq9gtn+MiLVn0wP37kb/uTeRZgN08WoCsAhIhI=
|
||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apache/thrift v0.14.0 h1:vqZ2DP42i8th2OsgCcYZkirtbzvpZEFx53LiWDJXIAs=
|
||||
github.com/apache/thrift v0.14.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pkg/errors v0.0.0-20171216070316-e881fd58d78e h1:+RHxT/gm0O3UF7nLJbdNzAmULvCFt4XfXHWzh3XI/zs=
|
||||
github.com/pkg/errors v0.0.0-20171216070316-e881fd58d78e/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/ridv/thrift v0.12.1 h1:b80V1Oa2Mbd++jrlJZbJsIybO5/MCfbXKzd1A5v4aSo=
|
||||
github.com/ridv/thrift v0.12.1/go.mod h1:yTMRF94RCZjO1fY1xt69yncvMbQCPdRL8BhbwIrjPx8=
|
||||
github.com/ridv/thrift v0.13.1 h1:/8XnTRUqJJeiuqoL7mfnJQmXQa4GJn9tUCiP7+i6Y9o=
|
||||
github.com/ridv/thrift v0.13.1/go.mod h1:yTMRF94RCZjO1fY1xt69yncvMbQCPdRL8BhbwIrjPx8=
|
||||
github.com/ridv/thrift v0.13.2 h1:Q3Smr8poXd7VkWZPHvdJZzlQCJO+b5W37ECfoUL4qHc=
|
||||
github.com/ridv/thrift v0.13.2/go.mod h1:yTMRF94RCZjO1fY1xt69yncvMbQCPdRL8BhbwIrjPx8=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20171117190445-471cd4e61d7a h1:EYL2xz/Zdo0hyqdZMXR4lmT2O11jDLTPCEqIe/FR6W4=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20171117190445-471cd4e61d7a/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.0 h1:LThGCOvhuJic9Gyd1VBCkhyUXmO8vKaBFvBsJ2k03rg=
|
||||
github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
21
helpers.go
Normal file
21
helpers.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
package realis
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/paypal/gorealis/gen-go/apache/aurora"
|
||||
)
|
||||
|
||||
func (r *realisClient) jobExists(key aurora.JobKey) (bool, error) {
|
||||
resp, err := r.client.GetConfigSummary(context.TODO(), &key)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return resp == nil ||
|
||||
resp.GetResult_() == nil ||
|
||||
resp.GetResult_().GetConfigSummaryResult_() == nil ||
|
||||
resp.GetResult_().GetConfigSummaryResult_().GetSummary() == nil ||
|
||||
resp.GetResponseCode() != aurora.ResponseCode_OK,
|
||||
nil
|
||||
}
|
160
job.go
160
job.go
|
@ -20,6 +20,9 @@ import (
|
|||
"github.com/paypal/gorealis/gen-go/apache/aurora"
|
||||
)
|
||||
|
||||
// Job inteface is used to define a set of functions an Aurora Job object
|
||||
// must implemement.
|
||||
// TODO(rdelvalle): Consider getting rid of the Job interface
|
||||
type Job interface {
|
||||
// Set Job Key environment.
|
||||
Environment(env string) Job
|
||||
|
@ -59,26 +62,30 @@ type Job interface {
|
|||
PartitionPolicy(policy *aurora.PartitionPolicy) Job
|
||||
Tier(tier string) Job
|
||||
SlaPolicy(policy *aurora.SlaPolicy) Job
|
||||
Priority(priority int32) Job
|
||||
}
|
||||
|
||||
type ResourceType int
|
||||
type resourceType int
|
||||
|
||||
const (
|
||||
CPU ResourceType = iota
|
||||
CPU resourceType = iota
|
||||
RAM
|
||||
DISK
|
||||
GPU
|
||||
)
|
||||
|
||||
// Structure to collect all information pertaining to an Aurora job.
|
||||
const portNamePrefix = "org.apache.aurora.port."
|
||||
|
||||
// AuroraJob is a structure to collect all information pertaining to an Aurora job.
|
||||
type AuroraJob struct {
|
||||
jobConfig *aurora.JobConfiguration
|
||||
resources map[ResourceType]*aurora.Resource
|
||||
metadata map[string]*aurora.Metadata
|
||||
portCount int
|
||||
jobConfig *aurora.JobConfiguration
|
||||
resources map[resourceType]*aurora.Resource
|
||||
metadata map[string]*aurora.Metadata
|
||||
constraints map[string]*aurora.Constraint
|
||||
portCount int
|
||||
}
|
||||
|
||||
// Create a Job object with everything initialized.
|
||||
// NewJob is used to create a Job object with everything initialized.
|
||||
func NewJob() Job {
|
||||
jobConfig := aurora.NewJobConfiguration()
|
||||
taskConfig := aurora.NewTaskConfig()
|
||||
|
@ -98,7 +105,7 @@ func NewJob() Job {
|
|||
ramMb := aurora.NewResource()
|
||||
diskMb := aurora.NewResource()
|
||||
|
||||
resources := map[ResourceType]*aurora.Resource{CPU: numCpus, RAM: ramMb, DISK: diskMb}
|
||||
resources := map[resourceType]*aurora.Resource{CPU: numCpus, RAM: ramMb, DISK: diskMb}
|
||||
taskConfig.Resources = []*aurora.Resource{numCpus, ramMb, diskMb}
|
||||
|
||||
numCpus.NumCpus = new(float64)
|
||||
|
@ -106,37 +113,38 @@ func NewJob() Job {
|
|||
diskMb.DiskMb = new(int64)
|
||||
|
||||
return &AuroraJob{
|
||||
jobConfig: jobConfig,
|
||||
resources: resources,
|
||||
metadata: make(map[string]*aurora.Metadata),
|
||||
portCount: 0,
|
||||
jobConfig: jobConfig,
|
||||
resources: resources,
|
||||
metadata: make(map[string]*aurora.Metadata),
|
||||
constraints: make(map[string]*aurora.Constraint),
|
||||
portCount: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Set Job Key environment.
|
||||
// Environment sets the Job Key environment.
|
||||
func (j *AuroraJob) Environment(env string) Job {
|
||||
j.jobConfig.Key.Environment = env
|
||||
return j
|
||||
}
|
||||
|
||||
// Set Job Key Role.
|
||||
// Role sets the Job Key role.
|
||||
func (j *AuroraJob) Role(role string) Job {
|
||||
j.jobConfig.Key.Role = role
|
||||
|
||||
//Will be deprecated
|
||||
// Will be deprecated
|
||||
identity := &aurora.Identity{User: role}
|
||||
j.jobConfig.Owner = identity
|
||||
j.jobConfig.TaskConfig.Owner = identity
|
||||
return j
|
||||
}
|
||||
|
||||
// Set Job Key Name.
|
||||
// Name sets the Job Key Name.
|
||||
func (j *AuroraJob) Name(name string) Job {
|
||||
j.jobConfig.Key.Name = name
|
||||
return j
|
||||
}
|
||||
|
||||
// Set name of the executor that will the task will be configured to.
|
||||
// ExecutorName sets the name of the executor that will the task will be configured to.
|
||||
func (j *AuroraJob) ExecutorName(name string) Job {
|
||||
|
||||
if j.jobConfig.TaskConfig.ExecutorConfig == nil {
|
||||
|
@ -147,7 +155,7 @@ func (j *AuroraJob) ExecutorName(name string) Job {
|
|||
return j
|
||||
}
|
||||
|
||||
// Will be included as part of entire task inside the scheduler that will be serialized.
|
||||
// ExecutorData sets the data blob that will be passed to the Mesos executor.
|
||||
func (j *AuroraJob) ExecutorData(data string) Job {
|
||||
|
||||
if j.jobConfig.TaskConfig.ExecutorConfig == nil {
|
||||
|
@ -158,81 +166,91 @@ func (j *AuroraJob) ExecutorData(data string) Job {
|
|||
return j
|
||||
}
|
||||
|
||||
// CPU sets the amount of CPU each task will use in an Aurora Job.
|
||||
func (j *AuroraJob) CPU(cpus float64) Job {
|
||||
*j.resources[CPU].NumCpus = cpus
|
||||
return j
|
||||
}
|
||||
|
||||
// RAM sets the amount of RAM each task will use in an Aurora Job.
|
||||
func (j *AuroraJob) RAM(ram int64) Job {
|
||||
*j.resources[RAM].RamMb = ram
|
||||
return j
|
||||
}
|
||||
|
||||
// Disk sets the amount of Disk each task will use in an Aurora Job.
|
||||
func (j *AuroraJob) Disk(disk int64) Job {
|
||||
*j.resources[DISK].DiskMb = disk
|
||||
return j
|
||||
}
|
||||
|
||||
// GPU sets the amount of GPU each task will use in an Aurora Job.
|
||||
func (j *AuroraJob) GPU(gpu int64) Job {
|
||||
// GPU resource must be set explicitly since the scheduler by default
|
||||
// rejects jobs with GPU resources attached to it.
|
||||
if _, ok := j.resources[GPU]; !ok {
|
||||
j.resources[GPU] = &aurora.Resource{}
|
||||
j.JobConfig().GetTaskConfig().Resources = append(j.JobConfig().GetTaskConfig().Resources, j.resources[GPU])
|
||||
j.JobConfig().GetTaskConfig().Resources = append(
|
||||
j.JobConfig().GetTaskConfig().Resources,
|
||||
j.resources[GPU])
|
||||
}
|
||||
|
||||
j.resources[GPU].NumGpus = &gpu
|
||||
return j
|
||||
}
|
||||
|
||||
// How many failures to tolerate before giving up.
|
||||
// MaxFailure sets how many failures to tolerate before giving up per Job.
|
||||
func (j *AuroraJob) MaxFailure(maxFail int32) Job {
|
||||
j.jobConfig.TaskConfig.MaxTaskFailures = maxFail
|
||||
return j
|
||||
}
|
||||
|
||||
// How many instances of the job to run
|
||||
// InstanceCount sets how many instances of the task to run for this Job.
|
||||
func (j *AuroraJob) InstanceCount(instCount int32) Job {
|
||||
j.jobConfig.InstanceCount = instCount
|
||||
return j
|
||||
}
|
||||
|
||||
// CronSchedule allows the user to configure a cron schedule for this job to run in.
|
||||
func (j *AuroraJob) CronSchedule(cron string) Job {
|
||||
j.jobConfig.CronSchedule = &cron
|
||||
return j
|
||||
}
|
||||
|
||||
// CronCollisionPolicy allows the user to decide what happens if two or more instances
|
||||
// of the same Cron job need to run.
|
||||
func (j *AuroraJob) CronCollisionPolicy(policy aurora.CronCollisionPolicy) Job {
|
||||
j.jobConfig.CronCollisionPolicy = policy
|
||||
return j
|
||||
}
|
||||
|
||||
// How many instances of the job to run
|
||||
// GetInstanceCount returns how many tasks this Job contains.
|
||||
func (j *AuroraJob) GetInstanceCount() int32 {
|
||||
return j.jobConfig.InstanceCount
|
||||
}
|
||||
|
||||
// Restart the job's tasks if they fail
|
||||
// IsService returns true if the job is a long term running job or false if it is an ad-hoc job.
|
||||
func (j *AuroraJob) IsService(isService bool) Job {
|
||||
j.jobConfig.TaskConfig.IsService = isService
|
||||
return j
|
||||
}
|
||||
|
||||
// Get the current job configurations key to use for some realis calls.
|
||||
// JobKey returns the job's configuration key.
|
||||
func (j *AuroraJob) JobKey() *aurora.JobKey {
|
||||
return j.jobConfig.Key
|
||||
}
|
||||
|
||||
// Get the current job configurations key to use for some realis calls.
|
||||
// JobConfig returns the job's configuration.
|
||||
func (j *AuroraJob) JobConfig() *aurora.JobConfiguration {
|
||||
return j.jobConfig
|
||||
}
|
||||
|
||||
// TaskConfig returns the job's task(shard) configuration.
|
||||
func (j *AuroraJob) TaskConfig() *aurora.TaskConfig {
|
||||
return j.jobConfig.TaskConfig
|
||||
}
|
||||
|
||||
// Add a list of URIs with the same extract and cache configuration. Scheduler must have
|
||||
// AddURIs adds a list of URIs with the same extract and cache configuration. Scheduler must have
|
||||
// --enable_mesos_fetcher flag enabled. Currently there is no duplicate detection.
|
||||
func (j *AuroraJob) AddURIs(extract bool, cache bool, values ...string) Job {
|
||||
for _, value := range values {
|
||||
|
@ -242,30 +260,32 @@ func (j *AuroraJob) AddURIs(extract bool, cache bool, values ...string) Job {
|
|||
return j
|
||||
}
|
||||
|
||||
// Adds a Mesos label to the job. Note that Aurora will add the
|
||||
// AddLabel adds a Mesos label to the job. Note that Aurora will add the
|
||||
// prefix "org.apache.aurora.metadata." to the beginning of each key.
|
||||
func (j *AuroraJob) AddLabel(key string, value string) Job {
|
||||
if _, ok := j.metadata[key]; ok {
|
||||
j.metadata[key].Value = value
|
||||
} else {
|
||||
j.metadata[key] = &aurora.Metadata{Key: key, Value: value}
|
||||
if _, ok := j.metadata[key]; !ok {
|
||||
j.metadata[key] = &aurora.Metadata{Key: key}
|
||||
j.jobConfig.TaskConfig.Metadata = append(j.jobConfig.TaskConfig.Metadata, j.metadata[key])
|
||||
}
|
||||
|
||||
j.metadata[key].Value = value
|
||||
return j
|
||||
}
|
||||
|
||||
// Add a named port to the job configuration These are random ports as it's
|
||||
// AddNamedPorts adds a named port to the job configuration These are random ports as it's
|
||||
// not currently possible to request specific ports using Aurora.
|
||||
func (j *AuroraJob) AddNamedPorts(names ...string) Job {
|
||||
j.portCount += len(names)
|
||||
for _, name := range names {
|
||||
j.jobConfig.TaskConfig.Resources = append(j.jobConfig.TaskConfig.Resources, &aurora.Resource{NamedPort: &name})
|
||||
j.jobConfig.TaskConfig.Resources = append(
|
||||
j.jobConfig.TaskConfig.Resources,
|
||||
&aurora.Resource{NamedPort: &name})
|
||||
}
|
||||
|
||||
return j
|
||||
}
|
||||
|
||||
// Adds a request for a number of ports to the job configuration. The names chosen for these ports
|
||||
// AddPorts adds a request for a number of ports to the job configuration. The names chosen for these ports
|
||||
// will be org.apache.aurora.port.X, where X is the current port count for the job configuration
|
||||
// starting at 0. These are random ports as it's not currently possible to request
|
||||
// specific ports using Aurora.
|
||||
|
@ -273,79 +293,99 @@ func (j *AuroraJob) AddPorts(num int) Job {
|
|||
start := j.portCount
|
||||
j.portCount += num
|
||||
for i := start; i < j.portCount; i++ {
|
||||
portName := "org.apache.aurora.port." + strconv.Itoa(i)
|
||||
j.jobConfig.TaskConfig.Resources = append(j.jobConfig.TaskConfig.Resources, &aurora.Resource{NamedPort: &portName})
|
||||
portName := portNamePrefix + strconv.Itoa(i)
|
||||
j.jobConfig.TaskConfig.Resources = append(
|
||||
j.jobConfig.TaskConfig.Resources,
|
||||
&aurora.Resource{NamedPort: &portName})
|
||||
}
|
||||
|
||||
return j
|
||||
}
|
||||
|
||||
// AddValueConstraint allows the user to add a value constrain to the job to limit which agents the job's
|
||||
// tasks can be run on. If the name matches a constraint that was previously set, the previous value will be
|
||||
// overwritten. In case the previous constraint attached to the name was of type limit, the constraint will be clobbered
|
||||
// by this new Value constraint.
|
||||
// From Aurora Docs:
|
||||
// Add a Value constraint
|
||||
// name - Mesos slave attribute that the constraint is matched against.
|
||||
// If negated = true , treat this as a 'not' - to avoid specific values.
|
||||
// Values - list of values we look for in attribute name
|
||||
func (j *AuroraJob) AddValueConstraint(name string, negated bool, values ...string) Job {
|
||||
j.jobConfig.TaskConfig.Constraints = append(j.jobConfig.TaskConfig.Constraints,
|
||||
&aurora.Constraint{
|
||||
Name: name,
|
||||
Constraint: &aurora.TaskConstraint{
|
||||
Value: &aurora.ValueConstraint{
|
||||
Negated: negated,
|
||||
Values: values,
|
||||
},
|
||||
Limit: nil,
|
||||
},
|
||||
})
|
||||
if _, ok := j.constraints[name]; !ok {
|
||||
j.constraints[name] = &aurora.Constraint{Name: name}
|
||||
j.jobConfig.TaskConfig.Constraints = append(j.jobConfig.TaskConfig.Constraints, j.constraints[name])
|
||||
}
|
||||
|
||||
j.constraints[name].Constraint = &aurora.TaskConstraint{
|
||||
Value: &aurora.ValueConstraint{
|
||||
Negated: negated,
|
||||
Values: values,
|
||||
},
|
||||
Limit: nil,
|
||||
}
|
||||
|
||||
return j
|
||||
}
|
||||
|
||||
// AddLimitConstraint allows the user to limit how many tasks form the same Job are run on a single host.
|
||||
// If the name matches a constraint that was previously set, the previous value will be
|
||||
// overwritten. In case the previous constraint attached to the name was of type Value, the constraint will be clobbered
|
||||
// by this new Limit constraint.
|
||||
// From Aurora Docs:
|
||||
// A constraint that specifies the maximum number of active tasks on a host with
|
||||
// a matching attribute that may be scheduled simultaneously.
|
||||
func (j *AuroraJob) AddLimitConstraint(name string, limit int32) Job {
|
||||
j.jobConfig.TaskConfig.Constraints = append(j.jobConfig.TaskConfig.Constraints,
|
||||
&aurora.Constraint{
|
||||
Name: name,
|
||||
Constraint: &aurora.TaskConstraint{
|
||||
Value: nil,
|
||||
Limit: &aurora.LimitConstraint{Limit: limit},
|
||||
},
|
||||
})
|
||||
if _, ok := j.constraints[name]; !ok {
|
||||
j.constraints[name] = &aurora.Constraint{Name: name}
|
||||
j.jobConfig.TaskConfig.Constraints = append(j.jobConfig.TaskConfig.Constraints, j.constraints[name])
|
||||
}
|
||||
|
||||
j.constraints[name].Constraint = &aurora.TaskConstraint{
|
||||
Value: nil,
|
||||
Limit: &aurora.LimitConstraint{Limit: limit},
|
||||
}
|
||||
|
||||
return j
|
||||
}
|
||||
|
||||
// AddDedicatedConstraint is a convenience function that allows the user to
|
||||
// add a dedicated constraint to a Job configuration.
|
||||
// In case a previous dedicated constraint was set, it will be clobbered by this new value.
|
||||
func (j *AuroraJob) AddDedicatedConstraint(role, name string) Job {
|
||||
j.AddValueConstraint("dedicated", false, role+"/"+name)
|
||||
|
||||
return j
|
||||
}
|
||||
|
||||
// Set a container to run for the job configuration to run.
|
||||
// Container sets a container to run for the job configuration to run.
|
||||
func (j *AuroraJob) Container(container Container) Job {
|
||||
j.jobConfig.TaskConfig.Container = container.Build()
|
||||
|
||||
return j
|
||||
}
|
||||
|
||||
// Set a partition policy for the job configuration to implement.
|
||||
// PartitionPolicy sets a partition policy for the job configuration to implement.
|
||||
func (j *AuroraJob) PartitionPolicy(policy *aurora.PartitionPolicy) Job {
|
||||
j.jobConfig.TaskConfig.PartitionPolicy = policy
|
||||
return j
|
||||
}
|
||||
|
||||
// Set the Tier for the Job.
|
||||
// Tier sets the Tier for the Job.
|
||||
func (j *AuroraJob) Tier(tier string) Job {
|
||||
j.jobConfig.TaskConfig.Tier = &tier
|
||||
|
||||
return j
|
||||
}
|
||||
|
||||
// Set an SlaPolicy for the Job.
|
||||
// SlaPolicy sets an SlaPolicy for the Job.
|
||||
func (j *AuroraJob) SlaPolicy(policy *aurora.SlaPolicy) Job {
|
||||
j.jobConfig.TaskConfig.SlaPolicy = policy
|
||||
|
||||
return j
|
||||
}
|
||||
|
||||
func (j *AuroraJob) Priority(priority int32) Job {
|
||||
j.jobConfig.TaskConfig.Priority = priority
|
||||
return j
|
||||
}
|
||||
|
|
24
logger.go
24
logger.go
|
@ -14,65 +14,73 @@
|
|||
|
||||
package realis
|
||||
|
||||
type Logger interface {
|
||||
type logger interface {
|
||||
Println(v ...interface{})
|
||||
Printf(format string, v ...interface{})
|
||||
Print(v ...interface{})
|
||||
}
|
||||
|
||||
// NoopLogger is a logger that can be attached to the client which will not print anything.
|
||||
type NoopLogger struct{}
|
||||
|
||||
// Printf is a NOOP function here.
|
||||
func (NoopLogger) Printf(format string, a ...interface{}) {}
|
||||
|
||||
// Print is a NOOP function here.
|
||||
func (NoopLogger) Print(a ...interface{}) {}
|
||||
|
||||
// Println is a NOOP function here.
|
||||
func (NoopLogger) Println(a ...interface{}) {}
|
||||
|
||||
// LevelLogger is a logger that can be configured to output different levels of information: Debug and Trace.
|
||||
// Trace should only be enabled when very in depth information about the sequence of events a function took is needed.
|
||||
type LevelLogger struct {
|
||||
Logger
|
||||
logger
|
||||
debug bool
|
||||
trace bool
|
||||
}
|
||||
|
||||
// EnableDebug enables debug level logging for the LevelLogger
|
||||
func (l *LevelLogger) EnableDebug(enable bool) {
|
||||
l.debug = enable
|
||||
}
|
||||
|
||||
// EnableTrace enables trace level logging for the LevelLogger
|
||||
func (l *LevelLogger) EnableTrace(enable bool) {
|
||||
l.trace = enable
|
||||
}
|
||||
|
||||
func (l LevelLogger) DebugPrintf(format string, a ...interface{}) {
|
||||
func (l LevelLogger) debugPrintf(format string, a ...interface{}) {
|
||||
if l.debug {
|
||||
l.Printf("[DEBUG] "+format, a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l LevelLogger) DebugPrint(a ...interface{}) {
|
||||
func (l LevelLogger) debugPrint(a ...interface{}) {
|
||||
if l.debug {
|
||||
l.Print(append([]interface{}{"[DEBUG] "}, a...)...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l LevelLogger) DebugPrintln(a ...interface{}) {
|
||||
func (l LevelLogger) debugPrintln(a ...interface{}) {
|
||||
if l.debug {
|
||||
l.Println(append([]interface{}{"[DEBUG] "}, a...)...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l LevelLogger) TracePrintf(format string, a ...interface{}) {
|
||||
func (l LevelLogger) tracePrintf(format string, a ...interface{}) {
|
||||
if l.trace {
|
||||
l.Printf("[TRACE] "+format, a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l LevelLogger) TracePrint(a ...interface{}) {
|
||||
func (l LevelLogger) tracePrint(a ...interface{}) {
|
||||
if l.trace {
|
||||
l.Print(append([]interface{}{"[TRACE] "}, a...)...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l LevelLogger) TracePrintln(a ...interface{}) {
|
||||
func (l LevelLogger) tracePrintln(a ...interface{}) {
|
||||
if l.trace {
|
||||
l.Println(append([]interface{}{"[TRACE] "}, a...)...)
|
||||
}
|
||||
|
|
169
monitors.go
169
monitors.go
|
@ -12,35 +12,41 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Collection of monitors to create synchronicity
|
||||
package realis
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/paypal/gorealis/gen-go/apache/aurora"
|
||||
"github.com/paypal/gorealis/response"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Monitor is a wrapper for the Realis client which allows us to have functions
|
||||
// with the same name for Monitoring purposes.
|
||||
// TODO(rdelvalle): Deprecate monitors and instead add prefix Monitor to
|
||||
// all functions in this file like it is done in V2.
|
||||
type Monitor struct {
|
||||
Client Realis
|
||||
}
|
||||
|
||||
// Polls the scheduler every certain amount of time to see if the update has succeeded
|
||||
func (m *Monitor) JobUpdate(updateKey aurora.JobUpdateKey, interval int, timeout int) (bool, error) {
|
||||
// JobUpdate polls the scheduler every certain amount of time to see if the update has entered a terminal state.
|
||||
func (m *Monitor) JobUpdate(
|
||||
updateKey aurora.JobUpdateKey,
|
||||
interval int,
|
||||
timeout int) (bool, error) {
|
||||
|
||||
status, err := m.JobUpdateStatus(updateKey,
|
||||
map[aurora.JobUpdateStatus]bool{
|
||||
aurora.JobUpdateStatus_ROLLED_FORWARD: true,
|
||||
aurora.JobUpdateStatus_ROLLED_BACK: true,
|
||||
aurora.JobUpdateStatus_ABORTED: true,
|
||||
aurora.JobUpdateStatus_ERROR: true,
|
||||
aurora.JobUpdateStatus_FAILED: true,
|
||||
},
|
||||
updateQ := aurora.JobUpdateQuery{
|
||||
Key: &updateKey,
|
||||
Limit: 1,
|
||||
UpdateStatuses: TerminalUpdateStates(),
|
||||
}
|
||||
updateSummaries, err := m.JobUpdateQuery(
|
||||
updateQ,
|
||||
time.Duration(interval)*time.Second,
|
||||
time.Duration(timeout)*time.Second)
|
||||
|
||||
status := updateSummaries[0].State.Status
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@ -52,22 +58,39 @@ func (m *Monitor) JobUpdate(updateKey aurora.JobUpdateKey, interval int, timeout
|
|||
switch status {
|
||||
case aurora.JobUpdateStatus_ROLLED_FORWARD:
|
||||
return true, nil
|
||||
case aurora.JobUpdateStatus_ROLLED_BACK, aurora.JobUpdateStatus_ABORTED, aurora.JobUpdateStatus_ERROR, aurora.JobUpdateStatus_FAILED:
|
||||
case aurora.JobUpdateStatus_ROLLED_BACK,
|
||||
aurora.JobUpdateStatus_ABORTED,
|
||||
aurora.JobUpdateStatus_ERROR,
|
||||
aurora.JobUpdateStatus_FAILED:
|
||||
return false, errors.Errorf("bad terminal state for update: %v", status)
|
||||
default:
|
||||
return false, errors.Errorf("unexpected update state: %v", status)
|
||||
}
|
||||
}
|
||||
|
||||
// JobUpdateStatus polls the scheduler every certain amount of time to see if the update has entered a specified state.
|
||||
func (m *Monitor) JobUpdateStatus(updateKey aurora.JobUpdateKey,
|
||||
desiredStatuses map[aurora.JobUpdateStatus]bool,
|
||||
interval time.Duration,
|
||||
timeout time.Duration) (aurora.JobUpdateStatus, error) {
|
||||
|
||||
desiredStatuses []aurora.JobUpdateStatus,
|
||||
interval, timeout time.Duration) (aurora.JobUpdateStatus, error) {
|
||||
updateQ := aurora.JobUpdateQuery{
|
||||
Key: &updateKey,
|
||||
Limit: 1,
|
||||
Key: &updateKey,
|
||||
Limit: 1,
|
||||
UpdateStatuses: desiredStatuses,
|
||||
}
|
||||
summary, err := m.JobUpdateQuery(updateQ, interval, timeout)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return summary[0].State.Status, nil
|
||||
}
|
||||
|
||||
// JobUpdateQuery polls the scheduler every certain amount of time to see if the query call returns any results.
|
||||
func (m *Monitor) JobUpdateQuery(
|
||||
updateQuery aurora.JobUpdateQuery,
|
||||
interval time.Duration,
|
||||
timeout time.Duration) ([]*aurora.JobUpdateSummary, error) {
|
||||
|
||||
ticker := time.NewTicker(interval)
|
||||
defer ticker.Stop()
|
||||
timer := time.NewTimer(timeout)
|
||||
|
@ -78,38 +101,103 @@ func (m *Monitor) JobUpdateStatus(updateKey aurora.JobUpdateKey,
|
|||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
respDetail, cliErr = m.Client.JobUpdateDetails(updateQ)
|
||||
respDetail, cliErr = m.Client.GetJobUpdateSummaries(&updateQuery)
|
||||
if cliErr != nil {
|
||||
return aurora.JobUpdateStatus(-1), cliErr
|
||||
return nil, cliErr
|
||||
}
|
||||
|
||||
updateDetail := response.JobUpdateDetails(respDetail)
|
||||
|
||||
if len(updateDetail) == 0 {
|
||||
m.Client.RealisConfig().logger.Println("No update found")
|
||||
return aurora.JobUpdateStatus(-1), errors.New("No update found for " + updateKey.String())
|
||||
}
|
||||
status := updateDetail[0].Update.Summary.State.Status
|
||||
|
||||
if _, ok := desiredStatuses[status]; ok {
|
||||
return status, nil
|
||||
updateSummaries := respDetail.Result_.GetJobUpdateSummariesResult_.UpdateSummaries
|
||||
if len(updateSummaries) >= 1 {
|
||||
return updateSummaries, nil
|
||||
}
|
||||
|
||||
case <-timer.C:
|
||||
return aurora.JobUpdateStatus(-1), newTimedoutError(errors.New("job update monitor timed out"))
|
||||
return nil, newTimedoutError(errors.New("job update monitor timed out"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Monitor a Job until all instances enter one of the LIVE_STATES
|
||||
// AutoPausedUpdateMonitor is a special monitor for auto pause enabled batch updates. This monitor ensures that the update
|
||||
// being monitored is capable of auto pausing and has auto pausing enabled. After verifying this information,
|
||||
// the monitor watches for the job to enter the ROLL_FORWARD_PAUSED state and calculates the current batch
|
||||
// the update is in using information from the update configuration.
|
||||
func (m *Monitor) AutoPausedUpdateMonitor(key aurora.JobUpdateKey, interval, timeout time.Duration) (int, error) {
|
||||
key.Job = &aurora.JobKey{
|
||||
Role: key.Job.Role,
|
||||
Environment: key.Job.Environment,
|
||||
Name: key.Job.Name,
|
||||
}
|
||||
query := aurora.JobUpdateQuery{
|
||||
UpdateStatuses: aurora.ACTIVE_JOB_UPDATE_STATES,
|
||||
Limit: 1,
|
||||
Key: &key,
|
||||
}
|
||||
|
||||
response, err := m.Client.JobUpdateDetails(query)
|
||||
if err != nil {
|
||||
return -1, errors.Wrap(err, "unable to get information about update")
|
||||
}
|
||||
|
||||
// TODO (rdelvalle): check for possible nil values when going down the list of structs
|
||||
updateDetails := response.Result_.GetJobUpdateDetailsResult_.DetailsList
|
||||
if len(updateDetails) == 0 {
|
||||
return -1, errors.Errorf("details for update could not be found")
|
||||
}
|
||||
|
||||
updateStrategy := updateDetails[0].Update.Instructions.Settings.UpdateStrategy
|
||||
|
||||
var batchSizes []int32
|
||||
switch {
|
||||
case updateStrategy.IsSetVarBatchStrategy():
|
||||
batchSizes = updateStrategy.VarBatchStrategy.GroupSizes
|
||||
if !updateStrategy.VarBatchStrategy.AutopauseAfterBatch {
|
||||
return -1, errors.Errorf("update does not have auto pause enabled")
|
||||
}
|
||||
case updateStrategy.IsSetBatchStrategy():
|
||||
batchSizes = []int32{updateStrategy.BatchStrategy.GroupSize}
|
||||
if !updateStrategy.BatchStrategy.AutopauseAfterBatch {
|
||||
return -1, errors.Errorf("update does not have auto pause enabled")
|
||||
}
|
||||
default:
|
||||
return -1, errors.Errorf("update is not using a batch update strategy")
|
||||
}
|
||||
|
||||
query.UpdateStatuses = append(TerminalUpdateStates(), aurora.JobUpdateStatus_ROLL_FORWARD_PAUSED)
|
||||
summary, err := m.JobUpdateQuery(query, interval, timeout)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
if !(summary[0].State.Status == aurora.JobUpdateStatus_ROLL_FORWARD_PAUSED ||
|
||||
summary[0].State.Status == aurora.JobUpdateStatus_ROLLED_FORWARD) {
|
||||
return -1, errors.Errorf("update is in a terminal state %v", summary[0].State.Status)
|
||||
}
|
||||
|
||||
updatingInstances := make(map[int32]struct{})
|
||||
for _, e := range updateDetails[0].InstanceEvents {
|
||||
// We only care about INSTANCE_UPDATING actions because we only care that they've been attempted
|
||||
if e != nil && e.GetAction() == aurora.JobUpdateAction_INSTANCE_UPDATING {
|
||||
updatingInstances[e.GetInstanceId()] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
return calculateCurrentBatch(int32(len(updatingInstances)), batchSizes), nil
|
||||
}
|
||||
|
||||
// Instances will monitor a Job until all instances enter one of the LIVE_STATES
|
||||
func (m *Monitor) Instances(key *aurora.JobKey, instances int32, interval, timeout int) (bool, error) {
|
||||
return m.ScheduleStatus(key, instances, LiveStates, interval, timeout)
|
||||
}
|
||||
|
||||
// Monitor a Job until all instances enter a desired status.
|
||||
// ScheduleStatus will monitor a Job until all instances enter a desired status.
|
||||
// Defaults sets of desired statuses provided by the thrift API include:
|
||||
// ACTIVE_STATES, SLAVE_ASSIGNED_STATES, LIVE_STATES, and TERMINAL_STATES
|
||||
func (m *Monitor) ScheduleStatus(key *aurora.JobKey, instanceCount int32, desiredStatuses map[aurora.ScheduleStatus]bool, interval, timeout int) (bool, error) {
|
||||
func (m *Monitor) ScheduleStatus(
|
||||
key *aurora.JobKey,
|
||||
instanceCount int32,
|
||||
desiredStatuses map[aurora.ScheduleStatus]bool,
|
||||
interval int,
|
||||
timeout int) (bool, error) {
|
||||
|
||||
ticker := time.NewTicker(time.Second * time.Duration(interval))
|
||||
defer ticker.Stop()
|
||||
|
@ -142,9 +230,13 @@ func (m *Monitor) ScheduleStatus(key *aurora.JobKey, instanceCount int32, desire
|
|||
}
|
||||
}
|
||||
|
||||
// Monitor host status until all hosts match the status provided. Returns a map where the value is true if the host
|
||||
// HostMaintenance will monitor host status until all hosts match the status provided.
|
||||
// Returns a map where the value is true if the host
|
||||
// is in one of the desired mode(s) or false if it is not as of the time when the monitor exited.
|
||||
func (m *Monitor) HostMaintenance(hosts []string, modes []aurora.MaintenanceMode, interval, timeout int) (map[string]bool, error) {
|
||||
func (m *Monitor) HostMaintenance(
|
||||
hosts []string,
|
||||
modes []aurora.MaintenanceMode,
|
||||
interval, timeout int) (map[string]bool, error) {
|
||||
|
||||
// Transform modes to monitor for into a set for easy lookup
|
||||
desiredMode := make(map[aurora.MaintenanceMode]struct{})
|
||||
|
@ -153,7 +245,8 @@ func (m *Monitor) HostMaintenance(hosts []string, modes []aurora.MaintenanceMode
|
|||
}
|
||||
|
||||
// Turn slice into a host set to eliminate duplicates.
|
||||
// We also can't use a simple count because multiple modes means we can have multiple matches for a single host.
|
||||
// We also can't use a simple count because multiple modes means
|
||||
// we can have multiple matches for a single host.
|
||||
// I.e. host A transitions from ACTIVE to DRAINING to DRAINED while monitored
|
||||
remainingHosts := make(map[string]struct{})
|
||||
for _, host := range hosts {
|
||||
|
|
309
realis_admin.go
Normal file
309
realis_admin.go
Normal file
|
@ -0,0 +1,309 @@
|
|||
package realis
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/paypal/gorealis/gen-go/apache/aurora"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// TODO(rdelvalle): Consider moving these functions to another interface. It would be a backwards incompatible change,
|
||||
// but would add safety.
|
||||
|
||||
// Set a list of nodes to DRAINING. This means nothing will be able to be scheduled on them and any existing
|
||||
// tasks will be killed and re-scheduled elsewhere in the cluster. Tasks from DRAINING nodes are not guaranteed
|
||||
// to return to running unless there is enough capacity in the cluster to run them.
|
||||
func (r *realisClient) DrainHosts(hosts ...string) (*aurora.Response, *aurora.DrainHostsResult_, error) {
|
||||
|
||||
var result *aurora.DrainHostsResult_
|
||||
|
||||
if len(hosts) == 0 {
|
||||
return nil, nil, errors.New("no hosts provided to drain")
|
||||
}
|
||||
|
||||
drainList := aurora.NewHosts()
|
||||
drainList.HostNames = hosts
|
||||
|
||||
r.logger.debugPrintf("DrainHosts Thrift Payload: %v\n", drainList)
|
||||
|
||||
resp, retryErr := r.thriftCallWithRetries(
|
||||
false,
|
||||
func() (*aurora.Response, error) {
|
||||
return r.adminClient.DrainHosts(context.TODO(), drainList)
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
if retryErr != nil {
|
||||
return resp, result, errors.Wrap(retryErr, "Unable to recover connection")
|
||||
}
|
||||
|
||||
if resp.GetResult_() != nil {
|
||||
result = resp.GetResult_().GetDrainHostsResult_()
|
||||
}
|
||||
|
||||
return resp, result, nil
|
||||
}
|
||||
|
||||
// Start SLA Aware Drain.
|
||||
// defaultSlaPolicy is the fallback SlaPolicy to use if a task does not have an SlaPolicy.
|
||||
// After timeoutSecs, tasks will be forcefully drained without checking SLA.
|
||||
func (r *realisClient) SLADrainHosts(
|
||||
policy *aurora.SlaPolicy,
|
||||
timeout int64,
|
||||
hosts ...string) (*aurora.DrainHostsResult_, error) {
|
||||
var result *aurora.DrainHostsResult_
|
||||
|
||||
if len(hosts) == 0 {
|
||||
return nil, errors.New("no hosts provided to drain")
|
||||
}
|
||||
|
||||
if policy == nil || policy.CountSetFieldsSlaPolicy() == 0 {
|
||||
policy = &defaultSlaPolicy
|
||||
r.logger.Printf("Warning: start draining with default sla policy %v", policy)
|
||||
}
|
||||
|
||||
if timeout < 0 {
|
||||
r.logger.Printf("Warning: timeout %d secs is invalid, draining with default timeout %d secs",
|
||||
timeout,
|
||||
defaultSlaDrainTimeoutSecs)
|
||||
timeout = defaultSlaDrainTimeoutSecs
|
||||
}
|
||||
|
||||
drainList := aurora.NewHosts()
|
||||
drainList.HostNames = hosts
|
||||
|
||||
r.logger.debugPrintf("SLADrainHosts Thrift Payload: %v\n", drainList)
|
||||
|
||||
resp, retryErr := r.thriftCallWithRetries(
|
||||
false,
|
||||
func() (*aurora.Response, error) {
|
||||
return r.adminClient.SlaDrainHosts(context.TODO(), drainList, policy, timeout)
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
if retryErr != nil {
|
||||
return result, errors.Wrap(retryErr, "Unable to recover connection")
|
||||
}
|
||||
|
||||
if resp.GetResult_() != nil {
|
||||
result = resp.GetResult_().GetDrainHostsResult_()
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *realisClient) StartMaintenance(hosts ...string) (*aurora.Response, *aurora.StartMaintenanceResult_, error) {
|
||||
|
||||
var result *aurora.StartMaintenanceResult_
|
||||
|
||||
if len(hosts) == 0 {
|
||||
return nil, nil, errors.New("no hosts provided to start maintenance on")
|
||||
}
|
||||
|
||||
hostList := aurora.NewHosts()
|
||||
hostList.HostNames = hosts
|
||||
|
||||
r.logger.debugPrintf("StartMaintenance Thrift Payload: %v\n", hostList)
|
||||
|
||||
resp, retryErr := r.thriftCallWithRetries(
|
||||
false,
|
||||
func() (*aurora.Response, error) {
|
||||
return r.adminClient.StartMaintenance(context.TODO(), hostList)
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
if retryErr != nil {
|
||||
return resp, result, errors.Wrap(retryErr, "Unable to recover connection")
|
||||
}
|
||||
|
||||
if resp.GetResult_() != nil {
|
||||
result = resp.GetResult_().GetStartMaintenanceResult_()
|
||||
}
|
||||
|
||||
return resp, result, nil
|
||||
}
|
||||
|
||||
func (r *realisClient) EndMaintenance(hosts ...string) (*aurora.Response, *aurora.EndMaintenanceResult_, error) {
|
||||
|
||||
var result *aurora.EndMaintenanceResult_
|
||||
|
||||
if len(hosts) == 0 {
|
||||
return nil, nil, errors.New("no hosts provided to end maintenance on")
|
||||
}
|
||||
|
||||
hostList := aurora.NewHosts()
|
||||
hostList.HostNames = hosts
|
||||
|
||||
r.logger.debugPrintf("EndMaintenance Thrift Payload: %v\n", hostList)
|
||||
|
||||
resp, retryErr := r.thriftCallWithRetries(
|
||||
false,
|
||||
func() (*aurora.Response, error) {
|
||||
return r.adminClient.EndMaintenance(context.TODO(), hostList)
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
if retryErr != nil {
|
||||
return resp, result, errors.Wrap(retryErr, "Unable to recover connection")
|
||||
}
|
||||
|
||||
if resp.GetResult_() != nil {
|
||||
result = resp.GetResult_().GetEndMaintenanceResult_()
|
||||
}
|
||||
|
||||
return resp, result, nil
|
||||
}
|
||||
|
||||
func (r *realisClient) MaintenanceStatus(hosts ...string) (*aurora.Response, *aurora.MaintenanceStatusResult_, error) {
|
||||
|
||||
var result *aurora.MaintenanceStatusResult_
|
||||
|
||||
if len(hosts) == 0 {
|
||||
return nil, nil, errors.New("no hosts provided to get maintenance status from")
|
||||
}
|
||||
|
||||
hostList := aurora.NewHosts()
|
||||
hostList.HostNames = hosts
|
||||
|
||||
r.logger.debugPrintf("MaintenanceStatus Thrift Payload: %v\n", hostList)
|
||||
|
||||
// Make thrift call. If we encounter an error sending the call, attempt to reconnect
|
||||
// and continue trying to resend command until we run out of retries.
|
||||
resp, retryErr := r.thriftCallWithRetries(
|
||||
false,
|
||||
func() (*aurora.Response, error) {
|
||||
return r.adminClient.MaintenanceStatus(context.TODO(), hostList)
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
if retryErr != nil {
|
||||
return resp, result, errors.Wrap(retryErr, "Unable to recover connection")
|
||||
}
|
||||
|
||||
if resp.GetResult_() != nil {
|
||||
result = resp.GetResult_().GetMaintenanceStatusResult_()
|
||||
}
|
||||
|
||||
return resp, result, nil
|
||||
}
|
||||
|
||||
// SetQuota sets a quota aggregate for the given role
|
||||
// TODO(zircote) Currently investigating an error that is returned
|
||||
// from thrift calls that include resources for `NamedPort` and `NumGpu`
|
||||
func (r *realisClient) SetQuota(role string, cpu *float64, ramMb *int64, diskMb *int64) (*aurora.Response, error) {
|
||||
quota := &aurora.ResourceAggregate{
|
||||
Resources: []*aurora.Resource{{NumCpus: cpu}, {RamMb: ramMb}, {DiskMb: diskMb}},
|
||||
}
|
||||
|
||||
resp, retryErr := r.thriftCallWithRetries(
|
||||
false,
|
||||
func() (*aurora.Response, error) {
|
||||
return r.adminClient.SetQuota(context.TODO(), role, quota)
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
if retryErr != nil {
|
||||
return resp, errors.Wrap(retryErr, "Unable to set role quota")
|
||||
}
|
||||
return resp, retryErr
|
||||
|
||||
}
|
||||
|
||||
// GetQuota returns the resource aggregate for the given role
|
||||
func (r *realisClient) GetQuota(role string) (*aurora.Response, error) {
|
||||
|
||||
resp, retryErr := r.thriftCallWithRetries(
|
||||
false,
|
||||
func() (*aurora.Response, error) {
|
||||
return r.adminClient.GetQuota(context.TODO(), role)
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
if retryErr != nil {
|
||||
return resp, errors.Wrap(retryErr, "Unable to get role quota")
|
||||
}
|
||||
return resp, retryErr
|
||||
}
|
||||
|
||||
// Force Aurora Scheduler to perform a snapshot and write to Mesos log
|
||||
func (r *realisClient) Snapshot() error {
|
||||
|
||||
_, retryErr := r.thriftCallWithRetries(
|
||||
false,
|
||||
func() (*aurora.Response, error) {
|
||||
return r.adminClient.Snapshot(context.TODO())
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
if retryErr != nil {
|
||||
return errors.Wrap(retryErr, "Unable to recover connection")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Force Aurora Scheduler to write backup file to a file in the backup directory
|
||||
func (r *realisClient) PerformBackup() error {
|
||||
|
||||
_, retryErr := r.thriftCallWithRetries(
|
||||
false,
|
||||
func() (*aurora.Response, error) {
|
||||
return r.adminClient.PerformBackup(context.TODO())
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
if retryErr != nil {
|
||||
return errors.Wrap(retryErr, "Unable to recover connection")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *realisClient) ForceImplicitTaskReconciliation() error {
|
||||
|
||||
_, retryErr := r.thriftCallWithRetries(
|
||||
false,
|
||||
func() (*aurora.Response, error) {
|
||||
return r.adminClient.TriggerImplicitTaskReconciliation(context.TODO())
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
if retryErr != nil {
|
||||
return errors.Wrap(retryErr, "Unable to recover connection")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *realisClient) ForceExplicitTaskReconciliation(batchSize *int32) error {
|
||||
|
||||
if batchSize != nil && *batchSize < 1 {
|
||||
return errors.New("invalid batch size")
|
||||
}
|
||||
settings := aurora.NewExplicitReconciliationSettings()
|
||||
|
||||
settings.BatchSize = batchSize
|
||||
|
||||
_, retryErr := r.thriftCallWithRetries(false,
|
||||
func() (*aurora.Response, error) {
|
||||
return r.adminClient.TriggerExplicitTaskReconciliation(context.TODO(), settings)
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
if retryErr != nil {
|
||||
return errors.Wrap(retryErr, "Unable to recover connection")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -35,11 +35,13 @@ var r realis.Realis
|
|||
var monitor *realis.Monitor
|
||||
var thermosPayload []byte
|
||||
|
||||
const auroraURL = "http://192.168.33.7:8081"
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
|
||||
// New configuration to connect to docker container
|
||||
r, err = realis.NewRealisClient(realis.SchedulerUrl("http://192.168.33.7:8081"),
|
||||
r, err = realis.NewRealisClient(realis.SchedulerUrl(auroraURL),
|
||||
realis.BasicAuth("aurora", "secret"),
|
||||
realis.TimeoutMS(20000))
|
||||
|
||||
|
@ -63,42 +65,69 @@ func TestMain(m *testing.M) {
|
|||
}
|
||||
|
||||
func TestNonExistentEndpoint(t *testing.T) {
|
||||
backoff := realis.Backoff{ // Reduce penalties for this test to make it quick
|
||||
Steps: 5,
|
||||
Duration: 1 * time.Second,
|
||||
// Reduce penalties for this test to make it quick
|
||||
backoff := realis.Backoff{
|
||||
Steps: 3,
|
||||
Duration: 200 * time.Millisecond,
|
||||
Factor: 1.0,
|
||||
Jitter: 0.1}
|
||||
|
||||
// Attempt to connect to a bad endpoint
|
||||
r, err := realis.NewRealisClient(realis.SchedulerUrl("http://192.168.33.7:8081/doesntexist/"),
|
||||
realis.TimeoutMS(200),
|
||||
realis.BackOff(backoff),
|
||||
)
|
||||
defer r.Close()
|
||||
|
||||
taskQ := &aurora.TaskQuery{}
|
||||
badEndpoint := "http://idontexist.local:8081/api"
|
||||
|
||||
_, err = r.GetTasksWithoutConfigs(taskQ)
|
||||
t.Run("WithRetries", func(t *testing.T) {
|
||||
// Attempt to connect to a bad endpoint
|
||||
badClient, err := realis.NewRealisClient(
|
||||
realis.SchedulerUrl(badEndpoint),
|
||||
realis.TimeoutMS(200000),
|
||||
realis.BackOff(backoff),
|
||||
)
|
||||
|
||||
// Check that we do error out of retrying
|
||||
assert.Error(t, err)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, badClient)
|
||||
defer badClient.Close()
|
||||
|
||||
// Check that the error before this one was a a retry error
|
||||
// TODO: Consider bubbling up timeout behaving error all the way up to the user.
|
||||
retryErr := realis.ToRetryCount(errors.Cause(err))
|
||||
assert.NotNil(t, retryErr, "error passed in is not a retry error")
|
||||
_, err = badClient.GetTasksWithoutConfigs(taskQ)
|
||||
|
||||
assert.Equal(t, backoff.Steps, retryErr.RetryCount(), "retry count is incorrect")
|
||||
// Check that we do error out of retrying
|
||||
require.Error(t, err)
|
||||
// Check that the error before this one was a a retry error
|
||||
// TODO: Consider bubbling up timeout behaving error all the way up to the user.
|
||||
retryErr := realis.ToRetryCount(errors.Cause(err))
|
||||
require.NotNil(t, retryErr, "error passed in is not a retry error")
|
||||
|
||||
assert.Equal(t, backoff.Steps, retryErr.RetryCount(), "retry count is incorrect")
|
||||
})
|
||||
|
||||
t.Run("FailOnLookup", func(t *testing.T) {
|
||||
// Attempt to connect to a bad endpoint
|
||||
badClient, err := realis.NewRealisClient(
|
||||
realis.SchedulerUrl(badEndpoint),
|
||||
realis.TimeoutMS(200000),
|
||||
realis.BackOff(backoff),
|
||||
realis.FailOnPermanentErrors(),
|
||||
)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, badClient)
|
||||
defer badClient.Close()
|
||||
|
||||
_, err = badClient.GetTasksWithoutConfigs(taskQ)
|
||||
|
||||
// Check that we do error out of retrying
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestThriftBinary(t *testing.T) {
|
||||
r, err := realis.NewRealisClient(realis.SchedulerUrl("http://192.168.33.7:8081"),
|
||||
r, err := realis.NewRealisClient(realis.SchedulerUrl(auroraURL),
|
||||
realis.BasicAuth("aurora", "secret"),
|
||||
realis.TimeoutMS(20000),
|
||||
realis.ThriftBinary())
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
defer r.Close()
|
||||
|
||||
role := "all"
|
||||
taskQ := &aurora.TaskQuery{
|
||||
|
@ -107,20 +136,17 @@ func TestThriftBinary(t *testing.T) {
|
|||
|
||||
// Perform a simple API call to test Thrift Binary
|
||||
_, err = r.GetTasksWithoutConfigs(taskQ)
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
r.Close()
|
||||
|
||||
}
|
||||
|
||||
func TestThriftJSON(t *testing.T) {
|
||||
r, err := realis.NewRealisClient(realis.SchedulerUrl("http://192.168.33.7:8081"),
|
||||
r, err := realis.NewRealisClient(realis.SchedulerUrl(auroraURL),
|
||||
realis.BasicAuth("aurora", "secret"),
|
||||
realis.TimeoutMS(20000),
|
||||
realis.ThriftJSON())
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
defer r.Close()
|
||||
|
||||
role := "all"
|
||||
taskQ := &aurora.TaskQuery{
|
||||
|
@ -132,16 +158,15 @@ func TestThriftJSON(t *testing.T) {
|
|||
|
||||
assert.NoError(t, err)
|
||||
|
||||
r.Close()
|
||||
|
||||
}
|
||||
|
||||
func TestNoopLogger(t *testing.T) {
|
||||
r, err := realis.NewRealisClient(realis.SchedulerUrl("http://192.168.33.7:8081"),
|
||||
r, err := realis.NewRealisClient(realis.SchedulerUrl(auroraURL),
|
||||
realis.BasicAuth("aurora", "secret"),
|
||||
realis.SetLogger(realis.NoopLogger{}))
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
defer r.Close()
|
||||
|
||||
role := "all"
|
||||
taskQ := &aurora.TaskQuery{
|
||||
|
@ -150,35 +175,26 @@ func TestNoopLogger(t *testing.T) {
|
|||
|
||||
// Perform a simple API call to test Thrift Binary
|
||||
_, err = r.GetTasksWithoutConfigs(taskQ)
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
r.Close()
|
||||
}
|
||||
|
||||
func TestLeaderFromZK(t *testing.T) {
|
||||
cluster := realis.GetDefaultClusterFromZKUrl("192.168.33.2:2181")
|
||||
url, err := realis.LeaderFromZK(*cluster)
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Address stored inside of ZK might be different than the one we connect to in our tests.
|
||||
assert.Equal(t, "http://192.168.33.7:8081", url)
|
||||
}
|
||||
|
||||
func TestRealisClient_ReestablishConn(t *testing.T) {
|
||||
|
||||
// Test that we're able to tear down the old connection and create a new one.
|
||||
err := r.ReestablishConn()
|
||||
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestGetCACerts(t *testing.T) {
|
||||
certs, err := realis.GetCerts("./examples/certs")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, len(certs.Subjects()), 2)
|
||||
|
||||
}
|
||||
|
||||
func TestRealisClient_CreateJob_Thermos(t *testing.T) {
|
||||
|
||||
role := "vagrant"
|
||||
|
@ -196,7 +212,7 @@ func TestRealisClient_CreateJob_Thermos(t *testing.T) {
|
|||
AddPorts(1)
|
||||
|
||||
_, err := r.CreateJob(job)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Test Instances Monitor
|
||||
success, err := monitor.Instances(job.JobKey(), job.GetInstanceCount(), 1, 50)
|
||||
|
@ -224,7 +240,7 @@ func TestRealisClient_CreateJob_Thermos(t *testing.T) {
|
|||
status, err := r.GetTaskStatus(&aurora.TaskQuery{
|
||||
JobKeys: []*aurora.JobKey{job.JobKey()},
|
||||
Statuses: []aurora.ScheduleStatus{aurora.ScheduleStatus_RUNNING}})
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, status)
|
||||
assert.Len(t, status, 2)
|
||||
|
||||
|
@ -233,7 +249,7 @@ func TestRealisClient_CreateJob_Thermos(t *testing.T) {
|
|||
|
||||
t.Run("AddInstances", func(t *testing.T) {
|
||||
_, err := r.AddInstances(aurora.InstanceKey{JobKey: job.JobKey(), InstanceId: 0}, 2)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
success, err := monitor.Instances(job.JobKey(), 4, 1, 50)
|
||||
assert.True(t, success)
|
||||
assert.NoError(t, err)
|
||||
|
@ -241,7 +257,7 @@ func TestRealisClient_CreateJob_Thermos(t *testing.T) {
|
|||
|
||||
t.Run("KillInstances", func(t *testing.T) {
|
||||
_, err := r.KillInstances(job.JobKey(), 2, 3)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
success, err := monitor.Instances(job.JobKey(), 2, 1, 50)
|
||||
assert.True(t, success)
|
||||
assert.NoError(t, err)
|
||||
|
@ -249,7 +265,7 @@ func TestRealisClient_CreateJob_Thermos(t *testing.T) {
|
|||
|
||||
t.Run("RestartInstances", func(t *testing.T) {
|
||||
_, err := r.RestartInstances(job.JobKey(), 0)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
success, err := monitor.Instances(job.JobKey(), 2, 1, 50)
|
||||
assert.True(t, success)
|
||||
assert.NoError(t, err)
|
||||
|
@ -257,7 +273,7 @@ func TestRealisClient_CreateJob_Thermos(t *testing.T) {
|
|||
|
||||
t.Run("RestartJobs", func(t *testing.T) {
|
||||
_, err := r.RestartJob(job.JobKey())
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
success, err := monitor.Instances(job.JobKey(), 2, 1, 50)
|
||||
assert.True(t, success)
|
||||
assert.NoError(t, err)
|
||||
|
@ -266,16 +282,68 @@ func TestRealisClient_CreateJob_Thermos(t *testing.T) {
|
|||
// Tasks must exist for it to, be killed
|
||||
t.Run("KillJob", func(t *testing.T) {
|
||||
_, err := r.KillJob(job.JobKey())
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
success, err := monitor.Instances(job.JobKey(), 0, 1, 50)
|
||||
assert.True(t, success)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Duplicate_Metadata", func(t *testing.T) {
|
||||
job.Name("thermos_duplicate_metadata").
|
||||
AddLabel("hostname", "cookie").
|
||||
AddLabel("hostname", "candy").
|
||||
AddLabel("hostname", "popcorn").
|
||||
AddLabel("hostname", "chips").
|
||||
AddLabel("chips", "chips")
|
||||
|
||||
_, err := r.CreateJob(job)
|
||||
require.NoError(t, err)
|
||||
|
||||
success, err := monitor.Instances(job.JobKey(), 2, 1, 50)
|
||||
assert.True(t, success)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = r.KillJob(job.JobKey())
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Duplicate_constraints", func(t *testing.T) {
|
||||
job.Name("thermos_duplicate_constraints").
|
||||
AddValueConstraint("zone", false, "east", "west").
|
||||
AddValueConstraint("zone", false, "east").
|
||||
AddValueConstraint("zone", true, "west")
|
||||
|
||||
_, err := r.CreateJob(job)
|
||||
require.NoError(t, err)
|
||||
|
||||
success, err := monitor.Instances(job.JobKey(), 2, 1, 50)
|
||||
assert.True(t, success)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = r.KillJob(job.JobKey())
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Overwrite_constraints", func(t *testing.T) {
|
||||
job.Name("thermos_overwrite_constraints").
|
||||
AddLimitConstraint("zone", 1).
|
||||
AddValueConstraint("zone", true, "west", "east").
|
||||
AddLimitConstraint("zone", 2)
|
||||
|
||||
_, err := r.CreateJob(job)
|
||||
require.NoError(t, err)
|
||||
|
||||
success, err := monitor.Instances(job.JobKey(), 2, 1, 50)
|
||||
assert.True(t, success)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = r.KillJob(job.JobKey())
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
// Test configuring an executor that doesn't exist for CreateJob API
|
||||
func TestRealisClient_CreateJob_ExecutorDoesNotExist(t *testing.T) {
|
||||
|
||||
// Create a single job
|
||||
job := realis.NewJob().
|
||||
Environment("prod").
|
||||
|
@ -313,7 +381,7 @@ func TestRealisClient_GetPendingReason(t *testing.T) {
|
|||
InstanceCount(1)
|
||||
|
||||
resp, err := r.CreateJob(job)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, aurora.ResponseCode_OK, resp.ResponseCode)
|
||||
|
||||
taskQ := &aurora.TaskQuery{
|
||||
|
@ -326,7 +394,7 @@ func TestRealisClient_GetPendingReason(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Len(t, reasons, 1)
|
||||
|
||||
resp, err = r.KillJob(job.JobKey())
|
||||
_, err = r.KillJob(job.JobKey())
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
|
@ -356,7 +424,7 @@ func TestRealisClient_CreateService_WithPulse_Thermos(t *testing.T) {
|
|||
job.InstanceCount(2)
|
||||
|
||||
_, result, err := r.CreateService(job, settings)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
|
||||
updateQ := aurora.JobUpdateQuery{
|
||||
Key: result.GetKey(),
|
||||
|
@ -376,13 +444,13 @@ pulseLoop:
|
|||
case <-ticker.C:
|
||||
|
||||
_, err = r.PulseJobUpdate(result.GetKey())
|
||||
assert.Nil(t, err, "unable to pulse job update")
|
||||
assert.NoError(t, err, "unable to pulse job update")
|
||||
|
||||
respDetail, err := r.JobUpdateDetails(updateQ)
|
||||
assert.Nil(t, err)
|
||||
assert.NoError(t, err)
|
||||
|
||||
updateDetails = response.JobUpdateDetails(respDetail)
|
||||
assert.Len(t, updateDetails, 1, "No update found")
|
||||
require.Len(t, updateDetails, 1, "No update found")
|
||||
|
||||
status := updateDetails[0].Update.Summary.State.Status
|
||||
if _, ok := realis.ActiveJobUpdateStates[status]; !ok {
|
||||
|
@ -401,7 +469,8 @@ pulseLoop:
|
|||
_, err := r.AbortJobUpdate(*updateDetails[0].GetUpdate().GetSummary().GetKey(), "")
|
||||
assert.NoError(t, err)
|
||||
_, err = r.KillJob(job.JobKey())
|
||||
require.NoError(t, err, "timed out during pulse update test")
|
||||
assert.NoError(t, err, "timed out during pulse update test")
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -431,7 +500,7 @@ func TestRealisClient_CreateService(t *testing.T) {
|
|||
job.InstanceCount(3)
|
||||
|
||||
_, result, err := r.CreateService(job, settings)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, result)
|
||||
|
||||
// Test asking the scheduler to backup a Snapshot
|
||||
|
@ -455,12 +524,73 @@ func TestRealisClient_CreateService(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
require.NoError(t, mErr)
|
||||
assert.True(t, ok)
|
||||
assert.NoError(t, mErr)
|
||||
|
||||
// Kill task test task after confirming it came up fine
|
||||
_, err = r.KillJob(job.JobKey())
|
||||
assert.NoError(t, err)
|
||||
|
||||
success, err := monitor.Instances(job.JobKey(), 0, 1, 50)
|
||||
require.NoError(t, mErr)
|
||||
assert.True(t, success)
|
||||
|
||||
// Create a client which will timeout and close the connection before receiving an answer
|
||||
timeoutClient, err := realis.NewRealisClient(
|
||||
realis.SchedulerUrl(auroraURL),
|
||||
realis.BasicAuth("aurora", "secret"),
|
||||
realis.TimeoutMS(5),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
defer timeoutClient.Close()
|
||||
|
||||
// Test case where http connection timeouts out.
|
||||
t.Run("TimeoutError", func(t *testing.T) {
|
||||
job.Name("createService_timeout")
|
||||
|
||||
// Make sure a timedout error was returned
|
||||
_, _, err = timeoutClient.CreateService(job, settings)
|
||||
require.Error(t, err)
|
||||
assert.True(t, realis.IsTimeout(err))
|
||||
|
||||
updateReceivedQuery := aurora.JobUpdateQuery{
|
||||
Role: &job.JobKey().Role,
|
||||
JobKey: job.JobKey(),
|
||||
UpdateStatuses: aurora.ACTIVE_JOB_UPDATE_STATES,
|
||||
Limit: 1}
|
||||
|
||||
updateSummaries, err := monitor.JobUpdateQuery(updateReceivedQuery, time.Second*1, time.Second*50)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, updateSummaries, 1)
|
||||
|
||||
r.AbortJobUpdate(*updateSummaries[0].Key, "Cleaning up")
|
||||
_, err = r.KillJob(job.JobKey())
|
||||
assert.NoError(t, err)
|
||||
|
||||
})
|
||||
|
||||
// Test case where http connection timeouts out.
|
||||
t.Run("TimeoutError_BadPayload", func(t *testing.T) {
|
||||
// Illegal payload
|
||||
job.InstanceCount(-1)
|
||||
job.Name("createService_timeout_bad_payload")
|
||||
|
||||
// Make sure a timedout error was returned
|
||||
_, _, err = timeoutClient.CreateService(job, settings)
|
||||
require.Error(t, err)
|
||||
assert.True(t, realis.IsTimeout(err))
|
||||
|
||||
summary, err := r.GetJobUpdateSummaries(
|
||||
&aurora.JobUpdateQuery{
|
||||
Role: &job.JobKey().Role,
|
||||
JobKey: job.JobKey(),
|
||||
UpdateStatuses: aurora.ACTIVE_JOB_UPDATE_STATES})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Payload should have been rejected, no update should exist
|
||||
require.Len(t, summary.GetResult_().GetGetJobUpdateSummariesResult_().GetUpdateSummaries(), 0)
|
||||
})
|
||||
}
|
||||
|
||||
// Test configuring an executor that doesn't exist for CreateJob API
|
||||
|
@ -482,9 +612,9 @@ func TestRealisClient_CreateService_ExecutorDoesNotExist(t *testing.T) {
|
|||
job.InstanceCount(3)
|
||||
|
||||
resp, result, err := r.CreateService(job, settings)
|
||||
assert.Error(t, err)
|
||||
require.Error(t, err)
|
||||
assert.Nil(t, result)
|
||||
assert.Equal(t, aurora.ResponseCode_INVALID_REQUEST, resp.GetResponseCode())
|
||||
require.Equal(t, aurora.ResponseCode_INVALID_REQUEST, resp.GetResponseCode())
|
||||
}
|
||||
|
||||
func TestRealisClient_ScheduleCronJob_Thermos(t *testing.T) {
|
||||
|
@ -508,23 +638,23 @@ func TestRealisClient_ScheduleCronJob_Thermos(t *testing.T) {
|
|||
IsService(false)
|
||||
|
||||
_, err = r.ScheduleCronJob(job)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("Start", func(t *testing.T) {
|
||||
_, err := r.StartCronJob(job.JobKey())
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Deschedule", func(t *testing.T) {
|
||||
_, err := r.DescheduleCronJob(job.JobKey())
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
func TestRealisClient_StartMaintenance(t *testing.T) {
|
||||
hosts := []string{"localhost"}
|
||||
|
||||
_, _, err := r.StartMaintenance(hosts...)
|
||||
assert.NoError(t, err, "unable to start maintenance")
|
||||
require.NoError(t, err, "unable to start maintenance")
|
||||
|
||||
// Monitor change to DRAINING and DRAINED mode
|
||||
hostResults, err := monitor.HostMaintenance(
|
||||
|
@ -532,11 +662,11 @@ func TestRealisClient_StartMaintenance(t *testing.T) {
|
|||
[]aurora.MaintenanceMode{aurora.MaintenanceMode_SCHEDULED},
|
||||
1,
|
||||
50)
|
||||
assert.Equal(t, map[string]bool{"localhost": true}, hostResults)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, map[string]bool{"localhost": true}, hostResults)
|
||||
|
||||
_, _, err = r.EndMaintenance(hosts...)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Monitor change to DRAINING and DRAINED mode
|
||||
_, err = monitor.HostMaintenance(
|
||||
|
@ -562,8 +692,8 @@ func TestRealisClient_DrainHosts(t *testing.T) {
|
|||
[]aurora.MaintenanceMode{aurora.MaintenanceMode_DRAINED, aurora.MaintenanceMode_DRAINING},
|
||||
1,
|
||||
50)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, map[string]bool{"localhost": true}, hostResults)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("MonitorNonExistentHost", func(t *testing.T) {
|
||||
|
@ -575,13 +705,13 @@ func TestRealisClient_DrainHosts(t *testing.T) {
|
|||
1)
|
||||
|
||||
// Assert monitor returned an error that was not nil, and also a list of the non-transitioned hosts
|
||||
assert.Error(t, err)
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, map[string]bool{"localhost": true, "IMAGINARY_HOST": false}, hostResults)
|
||||
})
|
||||
|
||||
t.Run("EndMaintenance", func(t *testing.T) {
|
||||
_, _, err := r.EndMaintenance(hosts...)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Monitor change to DRAINING and DRAINED mode
|
||||
_, err = monitor.HostMaintenance(
|
||||
|
@ -599,7 +729,7 @@ func TestRealisClient_SLADrainHosts(t *testing.T) {
|
|||
policy := aurora.SlaPolicy{PercentageSlaPolicy: &aurora.PercentageSlaPolicy{Percentage: 50.0}}
|
||||
|
||||
_, err := r.SLADrainHosts(&policy, 30, hosts...)
|
||||
assert.NoError(t, err, "unable to drain host with SLA policy")
|
||||
require.NoError(t, err, "unable to drain host with SLA policy")
|
||||
|
||||
// Monitor change to DRAINING and DRAINED mode
|
||||
hostResults, err := monitor.HostMaintenance(
|
||||
|
@ -607,12 +737,59 @@ func TestRealisClient_SLADrainHosts(t *testing.T) {
|
|||
[]aurora.MaintenanceMode{aurora.MaintenanceMode_DRAINED, aurora.MaintenanceMode_DRAINING},
|
||||
1,
|
||||
50)
|
||||
assert.Equal(t, map[string]bool{"localhost": true}, hostResults)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, map[string]bool{"localhost": true}, hostResults)
|
||||
|
||||
_, _, err = r.EndMaintenance(hosts...)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Monitor change to DRAINING and DRAINED mode
|
||||
_, err = monitor.HostMaintenance(
|
||||
hosts,
|
||||
[]aurora.MaintenanceMode{aurora.MaintenanceMode_NONE},
|
||||
5,
|
||||
10)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// slaDrainHosts goes with default policy if no policy is specified
|
||||
_, err = r.SLADrainHosts(nil, 30, hosts...)
|
||||
require.NoError(t, err, "unable to drain host with SLA policy")
|
||||
|
||||
// Monitor change to DRAINING and DRAINED mode
|
||||
hostResults, err = monitor.HostMaintenance(
|
||||
hosts,
|
||||
[]aurora.MaintenanceMode{aurora.MaintenanceMode_DRAINED, aurora.MaintenanceMode_DRAINING},
|
||||
1,
|
||||
50)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, map[string]bool{"localhost": true}, hostResults)
|
||||
|
||||
_, _, err = r.EndMaintenance(hosts...)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Monitor change to DRAINING and DRAINED mode
|
||||
_, err = monitor.HostMaintenance(
|
||||
hosts,
|
||||
[]aurora.MaintenanceMode{aurora.MaintenanceMode_NONE},
|
||||
5,
|
||||
10)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = r.SLADrainHosts(&aurora.SlaPolicy{}, 30, hosts...)
|
||||
require.NoError(t, err, "unable to drain host with SLA policy")
|
||||
|
||||
// Monitor change to DRAINING and DRAINED mode
|
||||
hostResults, err = monitor.HostMaintenance(
|
||||
hosts,
|
||||
[]aurora.MaintenanceMode{aurora.MaintenanceMode_DRAINED, aurora.MaintenanceMode_DRAINING},
|
||||
1,
|
||||
50)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, map[string]bool{"localhost": true}, hostResults)
|
||||
|
||||
_, _, err = r.EndMaintenance(hosts...)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Monitor change to DRAINING and DRAINED mode
|
||||
_, err = monitor.HostMaintenance(
|
||||
hosts,
|
||||
|
@ -689,13 +866,10 @@ func TestRealisClient_Quota(t *testing.T) {
|
|||
switch true {
|
||||
case res.DiskMb != nil:
|
||||
assert.Equal(t, disk, *res.DiskMb)
|
||||
break
|
||||
case res.NumCpus != nil:
|
||||
assert.Equal(t, cpu, *res.NumCpus)
|
||||
break
|
||||
case res.RamMb != nil:
|
||||
assert.Equal(t, ram, *res.RamMb)
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -748,7 +922,7 @@ func TestRealisClient_PartitionPolicy(t *testing.T) {
|
|||
}
|
||||
|
||||
// Clean up after finishing test
|
||||
_, err = r.KillJob(job.JobKey())
|
||||
r.KillJob(job.JobKey())
|
||||
}
|
||||
|
||||
func TestAuroraJob_UpdateSlaPolicy(t *testing.T) {
|
||||
|
@ -799,7 +973,7 @@ func TestAuroraJob_UpdateSlaPolicy(t *testing.T) {
|
|||
settings.MinWaitInInstanceRunningMs = 5 * 1000
|
||||
|
||||
_, result, err := r.CreateService(job, settings)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, result)
|
||||
|
||||
var ok bool
|
||||
|
@ -813,8 +987,8 @@ func TestAuroraJob_UpdateSlaPolicy(t *testing.T) {
|
|||
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
assert.True(t, ok)
|
||||
assert.NoError(t, mErr)
|
||||
assert.True(t, ok)
|
||||
|
||||
// Kill task test task after confirming it came up fine
|
||||
_, err = r.KillJob(job.JobKey())
|
||||
|
@ -823,3 +997,121 @@ func TestAuroraJob_UpdateSlaPolicy(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealisClient_UpdateStrategies(t *testing.T) {
|
||||
|
||||
// Create a single job
|
||||
job := realis.NewJob().
|
||||
Environment("prod").
|
||||
Role("vagrant").
|
||||
ExecutorName(aurora.AURORA_EXECUTOR_NAME).
|
||||
ExecutorData(string(thermosPayload)).
|
||||
CPU(.01).
|
||||
RAM(4).
|
||||
Disk(10).
|
||||
InstanceCount(6).
|
||||
IsService(true)
|
||||
|
||||
strategies := []struct {
|
||||
UpdateJob *realis.UpdateJob
|
||||
Name string
|
||||
}{
|
||||
{
|
||||
UpdateJob: realis.NewDefaultUpdateJob(job.TaskConfig()).
|
||||
QueueUpdateStrategy(aurora.QueueJobUpdateStrategy{GroupSize: 2}).
|
||||
InstanceCount(6).
|
||||
WatchTime(1000),
|
||||
Name: "Queue",
|
||||
},
|
||||
{
|
||||
UpdateJob: realis.NewDefaultUpdateJob(job.TaskConfig()).
|
||||
BatchUpdateStrategy(aurora.BatchJobUpdateStrategy{GroupSize: 2}).
|
||||
InstanceCount(6).
|
||||
WatchTime(1000),
|
||||
Name: "Batch",
|
||||
},
|
||||
{
|
||||
UpdateJob: realis.NewDefaultUpdateJob(job.TaskConfig()).
|
||||
VariableBatchStrategy(aurora.VariableBatchJobUpdateStrategy{GroupSizes: []int32{1, 2, 3}}).
|
||||
InstanceCount(6).
|
||||
WatchTime(1000),
|
||||
Name: "VarBatch",
|
||||
},
|
||||
}
|
||||
|
||||
for _, strategy := range strategies {
|
||||
t.Run("TestRealisClient_UpdateStrategies_"+strategy.Name, func(t *testing.T) {
|
||||
job.Name("update_strategies_" + strategy.Name)
|
||||
resp, err := r.StartJobUpdate(strategy.UpdateJob, "")
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
assert.NotNil(t, resp.GetResult_())
|
||||
assert.NotNil(t, resp.GetResult_().GetStartJobUpdateResult_())
|
||||
assert.NotNil(t, resp.GetResult_().GetStartJobUpdateResult_().GetKey())
|
||||
|
||||
var ok bool
|
||||
var mErr error
|
||||
key := *resp.GetResult_().GetStartJobUpdateResult_().GetKey()
|
||||
|
||||
if ok, mErr = monitor.JobUpdate(key, 5, 240); !ok || mErr != nil {
|
||||
// Update may already be in a terminal state so don't check for error
|
||||
_, err := r.AbortJobUpdate(key, "Monitor timed out.")
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
_, err = r.KillJob(job.JobKey())
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealisClient_BatchAwareAutoPause(t *testing.T) {
|
||||
// Create a single job
|
||||
job := realis.NewJob().
|
||||
Environment("prod").
|
||||
Role("vagrant").
|
||||
Name("BatchAwareAutoPauseTest").
|
||||
ExecutorName(aurora.AURORA_EXECUTOR_NAME).
|
||||
ExecutorData(string(thermosPayload)).
|
||||
CPU(.01).
|
||||
RAM(4).
|
||||
Disk(10).
|
||||
InstanceCount(6).
|
||||
IsService(true)
|
||||
updateGroups := []int32{1, 2, 3}
|
||||
strategy := realis.NewDefaultUpdateJob(job.TaskConfig()).
|
||||
VariableBatchStrategy(aurora.VariableBatchJobUpdateStrategy{
|
||||
GroupSizes: updateGroups,
|
||||
AutopauseAfterBatch: true,
|
||||
}).
|
||||
InstanceCount(6).
|
||||
WatchTime(1000)
|
||||
|
||||
resp, err := r.StartJobUpdate(strategy, "")
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, resp.GetResult_())
|
||||
require.NotNil(t, resp.GetResult_().GetStartJobUpdateResult_())
|
||||
require.NotNil(t, resp.GetResult_().GetStartJobUpdateResult_().GetKey())
|
||||
|
||||
key := *resp.GetResult_().GetStartJobUpdateResult_().GetKey()
|
||||
|
||||
for i := range updateGroups {
|
||||
curStep, mErr := monitor.AutoPausedUpdateMonitor(key, time.Second*5, time.Second*240)
|
||||
if mErr != nil {
|
||||
// Update may already be in a terminal state so don't check for error
|
||||
_, err := r.AbortJobUpdate(key, "Monitor timed out.")
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
assert.Equal(t, i, curStep)
|
||||
|
||||
if i != len(updateGroups)-1 {
|
||||
_, err = r.ResumeJobUpdate(&key, "auto resuming test")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
_, err = r.KillJob(job.JobKey())
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
|
|
@ -36,6 +36,10 @@ func ScheduleStatusResult(resp *aurora.Response) *aurora.ScheduleStatusResult_ {
|
|||
}
|
||||
|
||||
func JobUpdateSummaries(resp *aurora.Response) []*aurora.JobUpdateSummary {
|
||||
if resp.GetResult_() == nil || resp.GetResult_().GetGetJobUpdateSummariesResult_() == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return resp.GetResult_().GetGetJobUpdateSummariesResult_().GetUpdateSummaries()
|
||||
}
|
||||
|
||||
|
|
205
retry.go
205
retry.go
|
@ -26,9 +26,11 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Backoff determines how the retry mechanism should react after each failure and how many failures it should
|
||||
// tolerate.
|
||||
type Backoff struct {
|
||||
Duration time.Duration // the base duration
|
||||
Factor float64 // Duration is multipled by factor each iteration
|
||||
Factor float64 // Duration is multiplied by a factor each iteration
|
||||
Jitter float64 // The amount of jitter applied each iteration
|
||||
Steps int // Exit with error after this many steps
|
||||
}
|
||||
|
@ -50,19 +52,16 @@ func Jitter(duration time.Duration, maxFactor float64) time.Duration {
|
|||
// if the loop should be aborted.
|
||||
type ConditionFunc func() (done bool, err error)
|
||||
|
||||
// Modified version of the Kubernetes exponential-backoff code.
|
||||
// ExponentialBackoff repeats a condition check with exponential backoff.
|
||||
//
|
||||
// It checks the condition up to Steps times, increasing the wait by multiplying
|
||||
// the previous duration by Factor.
|
||||
// ExponentialBackoff is a modified version of the Kubernetes exponential-backoff code.
|
||||
// It repeats a condition check with exponential backoff and checks the condition up to
|
||||
// Steps times, increasing the wait by multiplying the previous duration by Factor.
|
||||
//
|
||||
// If Jitter is greater than zero, a random amount of each duration is added
|
||||
// (between duration and duration*(1+jitter)).
|
||||
//
|
||||
// If the condition never returns true, ErrWaitTimeout is returned. Errors
|
||||
// do not cause the function to return.
|
||||
|
||||
func ExponentialBackoff(backoff Backoff, logger Logger, condition ConditionFunc) error {
|
||||
func ExponentialBackoff(backoff Backoff, logger logger, condition ConditionFunc) error {
|
||||
var err error
|
||||
var ok bool
|
||||
var curStep int
|
||||
|
@ -77,7 +76,8 @@ func ExponentialBackoff(backoff Backoff, logger Logger, condition ConditionFunc)
|
|||
adjusted = Jitter(duration, backoff.Jitter)
|
||||
}
|
||||
|
||||
logger.Printf("A retriable error occurred during function call, backing off for %v before retrying\n", adjusted)
|
||||
logger.Printf(
|
||||
"A retryable error occurred during function call, backing off for %v before retrying\n", adjusted)
|
||||
time.Sleep(adjusted)
|
||||
duration = time.Duration(float64(duration) * backoff.Factor)
|
||||
}
|
||||
|
@ -94,10 +94,9 @@ func ExponentialBackoff(backoff Backoff, logger Logger, condition ConditionFunc)
|
|||
// If the error is temporary, continue retrying.
|
||||
if !IsTemporary(err) {
|
||||
return err
|
||||
} else {
|
||||
// Print out the temporary error we experienced.
|
||||
logger.Println(err)
|
||||
}
|
||||
// Print out the temporary error we experienced.
|
||||
logger.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,18 +107,31 @@ func ExponentialBackoff(backoff Backoff, logger Logger, condition ConditionFunc)
|
|||
// Provide more information to the user wherever possible
|
||||
if err != nil {
|
||||
return newRetryError(errors.Wrap(err, "ran out of retries"), curStep)
|
||||
} else {
|
||||
return newRetryError(errors.New("ran out of retries"), curStep)
|
||||
}
|
||||
|
||||
return newRetryError(errors.New("ran out of retries"), curStep)
|
||||
}
|
||||
|
||||
type auroraThriftCall func() (resp *aurora.Response, err error)
|
||||
|
||||
// verifyOntimeout defines the type of function that will be used to verify whether a Thirft call to the Scheduler
|
||||
// made it to the scheduler or not. In general, these types of functions will have to interact with the scheduler
|
||||
// through the very same Thrift API which previously encountered a time out from the client.
|
||||
// This means that the functions themselves should be kept to a minimum number of Thrift calls.
|
||||
// It should also be noted that this is a best effort mechanism and
|
||||
// is likely to fail for the same reasons that the original call failed.
|
||||
type verifyOnTimeout func() (*aurora.Response, bool)
|
||||
|
||||
// Duplicates the functionality of ExponentialBackoff but is specifically targeted towards ThriftCalls.
|
||||
func (r *realisClient) thriftCallWithRetries(thriftCall auroraThriftCall) (*aurora.Response, error) {
|
||||
func (r *realisClient) thriftCallWithRetries(
|
||||
returnOnTimeout bool,
|
||||
thriftCall auroraThriftCall,
|
||||
verifyOnTimeout verifyOnTimeout) (*aurora.Response, error) {
|
||||
|
||||
var resp *aurora.Response
|
||||
var clientErr error
|
||||
var curStep int
|
||||
timeouts := 0
|
||||
|
||||
backoff := r.config.backoff
|
||||
duration := backoff.Duration
|
||||
|
@ -133,7 +145,10 @@ func (r *realisClient) thriftCallWithRetries(thriftCall auroraThriftCall) (*auro
|
|||
adjusted = Jitter(duration, backoff.Jitter)
|
||||
}
|
||||
|
||||
r.logger.Printf("A retriable error occurred during thrift call, backing off for %v before retry %v\n", adjusted, curStep)
|
||||
r.logger.Printf(
|
||||
"A retryable error occurred during thrift call, backing off for %v before retry %v",
|
||||
adjusted,
|
||||
curStep)
|
||||
|
||||
time.Sleep(adjusted)
|
||||
duration = time.Duration(float64(duration) * backoff.Factor)
|
||||
|
@ -148,84 +163,132 @@ func (r *realisClient) thriftCallWithRetries(thriftCall auroraThriftCall) (*auro
|
|||
|
||||
resp, clientErr = thriftCall()
|
||||
|
||||
r.logger.TracePrintf("Aurora Thrift Call ended resp: %v clientErr: %v\n", resp, clientErr)
|
||||
r.logger.tracePrintf("Aurora Thrift Call ended resp: %v clientErr: %v", resp, clientErr)
|
||||
}()
|
||||
|
||||
// Check if our thrift call is returning an error. This is a retriable event as we don't know
|
||||
// if it was caused by network issues.
|
||||
// Check if our thrift call is returning an error.
|
||||
if clientErr != nil {
|
||||
|
||||
// Print out the error to the user
|
||||
r.logger.Printf("Client Error: %v\n", clientErr)
|
||||
r.logger.Printf("Client Error: %v", clientErr)
|
||||
|
||||
// Determine if error is a temporary URL error by going up the stack
|
||||
e, ok := clientErr.(thrift.TTransportException)
|
||||
if ok {
|
||||
r.logger.DebugPrint("Encountered a transport exception")
|
||||
temporary, timedout := isConnectionError(clientErr)
|
||||
if !temporary && r.RealisConfig().failOnPermanentErrors {
|
||||
return nil, errors.Wrap(clientErr, "permanent connection error")
|
||||
}
|
||||
|
||||
e, ok := e.Err().(*url.Error)
|
||||
if ok {
|
||||
// EOF error occurs when the server closes the read buffer of the client. This is common
|
||||
// when the server is overloaded and should be retried. All other errors that are permanent
|
||||
// will not be retried.
|
||||
if e.Err != io.EOF && !e.Temporary() {
|
||||
return nil, errors.Wrap(clientErr, "Permanent connection error")
|
||||
}
|
||||
}
|
||||
// There exists a corner case where thrift payload was received by Aurora but
|
||||
// connection timed out before Aurora was able to reply.
|
||||
// Users can take special action on a timeout by using IsTimedout and reacting accordingly
|
||||
// if they have configured the client to return on a timeout.
|
||||
if timedout && returnOnTimeout {
|
||||
return resp, newTimedoutError(errors.New("client connection closed before server answer"))
|
||||
}
|
||||
|
||||
// In the future, reestablish connection should be able to check if it is actually possible
|
||||
// to make a thrift call to Aurora. For now, a reconnect should always lead to a retry.
|
||||
r.ReestablishConn()
|
||||
|
||||
} else {
|
||||
|
||||
// If there was no client error, but the response is nil, something went wrong.
|
||||
// Ideally, we'll never encounter this but we're placing a safeguard here.
|
||||
if resp == nil {
|
||||
return nil, errors.New("Response from aurora is nil")
|
||||
// Ignoring error due to the fact that an error should be retried regardless
|
||||
reestablishErr := r.ReestablishConn()
|
||||
if reestablishErr != nil {
|
||||
r.logger.debugPrintf("error re-establishing connection ", reestablishErr)
|
||||
}
|
||||
|
||||
// Check Response Code from thrift and make a decision to continue retrying or not.
|
||||
switch responseCode := resp.GetResponseCode(); responseCode {
|
||||
// If users did not opt for a return on timeout in order to react to a timedout error,
|
||||
// attempt to verify that the call made it to the scheduler after the connection was re-established.
|
||||
if timedout {
|
||||
timeouts++
|
||||
r.logger.debugPrintf(
|
||||
"Client closed connection %d times before server responded, "+
|
||||
"consider increasing connection timeout",
|
||||
timeouts)
|
||||
|
||||
// If the thrift call succeeded, stop retrying
|
||||
case aurora.ResponseCode_OK:
|
||||
return resp, nil
|
||||
|
||||
// If the response code is transient, continue retrying
|
||||
case aurora.ResponseCode_ERROR_TRANSIENT:
|
||||
r.logger.Println("Aurora replied with Transient error code, retrying")
|
||||
continue
|
||||
|
||||
// Failure scenarios, these indicate a bad payload or a bad config. Stop retrying.
|
||||
case aurora.ResponseCode_INVALID_REQUEST,
|
||||
aurora.ResponseCode_ERROR,
|
||||
aurora.ResponseCode_AUTH_FAILED,
|
||||
aurora.ResponseCode_JOB_UPDATING_ERROR:
|
||||
r.logger.Printf("Terminal Response Code %v from Aurora, won't retry\n", resp.GetResponseCode().String())
|
||||
return resp, errors.New(response.CombineMessage(resp))
|
||||
|
||||
// The only case that should fall down to here is a WARNING response code.
|
||||
// It is currently not used as a response in the scheduler so it is unknown how to handle it.
|
||||
default:
|
||||
r.logger.DebugPrintf("unhandled response code %v received from Aurora\n", responseCode)
|
||||
return nil, errors.Errorf("unhandled response code from Aurora %v\n", responseCode.String())
|
||||
// Allow caller to provide a function which checks if the original call was successful before
|
||||
// it timed out.
|
||||
if verifyOnTimeout != nil {
|
||||
if verifyResp, ok := verifyOnTimeout(); ok {
|
||||
r.logger.Print("verified that the call went through successfully after a client timeout")
|
||||
// Response here might be different than the original as it is no longer constructed
|
||||
// by the scheduler but mimicked.
|
||||
// This is OK since the scheduler is very unlikely to change responses at this point in its
|
||||
// development cycle but we must be careful to not return an incorrectly constructed response.
|
||||
return verifyResp, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Retry the thrift payload
|
||||
continue
|
||||
}
|
||||
|
||||
// If there was no client error, but the response is nil, something went wrong.
|
||||
// Ideally, we'll never encounter this but we're placing a safeguard here.
|
||||
if resp == nil {
|
||||
return nil, errors.New("response from aurora is nil")
|
||||
}
|
||||
|
||||
// Check Response Code from thrift and make a decision to continue retrying or not.
|
||||
switch responseCode := resp.GetResponseCode(); responseCode {
|
||||
|
||||
// If the thrift call succeeded, stop retrying
|
||||
case aurora.ResponseCode_OK:
|
||||
return resp, nil
|
||||
|
||||
// If the response code is transient, continue retrying
|
||||
case aurora.ResponseCode_ERROR_TRANSIENT:
|
||||
r.logger.Println("Aurora replied with Transient error code, retrying")
|
||||
continue
|
||||
|
||||
// Failure scenarios, these indicate a bad payload or a bad config. Stop retrying.
|
||||
case aurora.ResponseCode_INVALID_REQUEST,
|
||||
aurora.ResponseCode_ERROR,
|
||||
aurora.ResponseCode_AUTH_FAILED,
|
||||
aurora.ResponseCode_JOB_UPDATING_ERROR:
|
||||
r.logger.Printf("Terminal Response Code %v from Aurora, won't retry\n", resp.GetResponseCode().String())
|
||||
return resp, errors.New(response.CombineMessage(resp))
|
||||
|
||||
// The only case that should fall down to here is a WARNING response code.
|
||||
// It is currently not used as a response in the scheduler so it is unknown how to handle it.
|
||||
default:
|
||||
r.logger.debugPrintf("unhandled response code %v received from Aurora\n", responseCode)
|
||||
return nil, errors.Errorf("unhandled response code from Aurora %v", responseCode.String())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
r.logger.DebugPrintf("it took %v retries to complete this operation\n", curStep)
|
||||
|
||||
if curStep > 1 {
|
||||
r.config.logger.Printf("retried this thrift call %d time(s)", curStep)
|
||||
r.config.logger.Printf("this thrift call was retried %d time(s)", curStep)
|
||||
}
|
||||
|
||||
// Provide more information to the user wherever possible.
|
||||
if clientErr != nil {
|
||||
return nil, newRetryError(errors.Wrap(clientErr, "ran out of retries, including latest error"), curStep)
|
||||
} else {
|
||||
return nil, newRetryError(errors.New("ran out of retries"), curStep)
|
||||
}
|
||||
|
||||
return nil, newRetryError(errors.New("ran out of retries"), curStep)
|
||||
}
|
||||
|
||||
// isConnectionError processes the error received by the client.
|
||||
// The return values indicate weather this was determined to be a temporary error
|
||||
// and weather it was determined to be a timeout error
|
||||
func isConnectionError(err error) (bool, bool) {
|
||||
|
||||
// Determine if error is a temporary URL error by going up the stack
|
||||
transportException, ok := err.(thrift.TTransportException)
|
||||
if !ok {
|
||||
return false, false
|
||||
}
|
||||
|
||||
urlError, ok := transportException.Err().(*url.Error)
|
||||
if !ok {
|
||||
return false, false
|
||||
}
|
||||
|
||||
// EOF error occurs when the server closes the read buffer of the client. This is common
|
||||
// when the server is overloaded and we consider it temporary.
|
||||
// All other which are not temporary as per the member function Temporary(),
|
||||
// are considered not temporary (permanent).
|
||||
if urlError.Err != io.EOF && !urlError.Temporary() {
|
||||
return false, false
|
||||
}
|
||||
|
||||
return true, urlError.Timeout()
|
||||
}
|
||||
|
|
13
runTests.sh
Executable file
13
runTests.sh
Executable file
|
@ -0,0 +1,13 @@
|
|||
#!/bin/bash
|
||||
|
||||
docker-compose up -d
|
||||
|
||||
# If running docker-compose up gives any error, don't do anything.
|
||||
if [ $? -ne 0 ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Since we run our docker compose setup in bridge mode to be able to run on MacOS, we have to launch a Docker container within the bridge network in order to avoid any routing issues.
|
||||
docker run --rm -t -v $(pwd):/go/src/github.com/paypal/gorealis --network gorealis_aurora_cluster golang:1.10-stretch go test -v github.com/paypal/gorealis $@
|
||||
|
||||
docker-compose down
|
2
runTestsMac.sh
Executable file → Normal file
2
runTestsMac.sh
Executable file → Normal file
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Since we run our docker compose setup in bridge mode to be able to run on MacOS, we have to launch a Docker container within the bridge network in order to avoid any routing issues.
|
||||
docker run -t -v $(pwd):/go/src/github.com/paypal/gorealis --network gorealis_aurora_cluster golang:1.10-stretch go test -v github.com/paypal/gorealis $@
|
||||
docker run --rm -t -w /gorealis -v $GOPATH/pkg:/go/pkg -v $(pwd):/gorealis --network gorealis_aurora_cluster golang:1.16-buster go test -v github.com/paypal/gorealis $@
|
||||
|
|
49
updatejob.go
49
updatejob.go
|
@ -18,20 +18,25 @@ import (
|
|||
"github.com/paypal/gorealis/gen-go/apache/aurora"
|
||||
)
|
||||
|
||||
// Structure to collect all information required to create job update
|
||||
// UpdateJob is a structure to collect all information required to create job update.
|
||||
type UpdateJob struct {
|
||||
Job // SetInstanceCount for job is hidden, access via full qualifier
|
||||
req *aurora.JobUpdateRequest
|
||||
}
|
||||
|
||||
// Create a default UpdateJob object.
|
||||
// NewDefaultUpdateJob creates an UpdateJob object with opinionated default settings.
|
||||
func NewDefaultUpdateJob(config *aurora.TaskConfig) *UpdateJob {
|
||||
|
||||
req := aurora.NewJobUpdateRequest()
|
||||
req.TaskConfig = config
|
||||
req.Settings = NewUpdateSettings()
|
||||
|
||||
job := NewJob().(*AuroraJob)
|
||||
job, ok := NewJob().(*AuroraJob)
|
||||
if !ok {
|
||||
// This should never happen but it is here as a safeguard
|
||||
return nil
|
||||
}
|
||||
|
||||
job.jobConfig.TaskConfig = config
|
||||
|
||||
// Rebuild resource map from TaskConfig
|
||||
|
@ -69,13 +74,18 @@ func NewDefaultUpdateJob(config *aurora.TaskConfig) *UpdateJob {
|
|||
return &UpdateJob{Job: job, req: req}
|
||||
}
|
||||
|
||||
// NewUpdateJob creates an UpdateJob object wihtout default settings.
|
||||
func NewUpdateJob(config *aurora.TaskConfig, settings *aurora.JobUpdateSettings) *UpdateJob {
|
||||
|
||||
req := aurora.NewJobUpdateRequest()
|
||||
req.TaskConfig = config
|
||||
req.Settings = settings
|
||||
|
||||
job := NewJob().(*AuroraJob)
|
||||
job, ok := NewJob().(*AuroraJob)
|
||||
if !ok {
|
||||
// This should never happen but it is here as a safeguard
|
||||
return nil
|
||||
}
|
||||
job.jobConfig.TaskConfig = config
|
||||
|
||||
// Rebuild resource map from TaskConfig
|
||||
|
@ -106,50 +116,65 @@ func NewUpdateJob(config *aurora.TaskConfig, settings *aurora.JobUpdateSettings)
|
|||
return &UpdateJob{Job: job, req: req}
|
||||
}
|
||||
|
||||
// Set instance count the job will have after the update.
|
||||
// InstanceCount sets instance count the job will have after the update.
|
||||
func (u *UpdateJob) InstanceCount(inst int32) *UpdateJob {
|
||||
u.req.InstanceCount = inst
|
||||
return u
|
||||
}
|
||||
|
||||
// Max number of instances being updated at any given moment.
|
||||
// BatchSize sets the max number of instances being updated at any given moment.
|
||||
func (u *UpdateJob) BatchSize(size int32) *UpdateJob {
|
||||
u.req.Settings.UpdateGroupSize = size
|
||||
return u
|
||||
}
|
||||
|
||||
// Minimum number of seconds a shard must remain in RUNNING state before considered a success.
|
||||
// WatchTime sets the minimum number of seconds a shard must remain in RUNNING state before considered a success.
|
||||
func (u *UpdateJob) WatchTime(ms int32) *UpdateJob {
|
||||
u.req.Settings.MinWaitInInstanceRunningMs = ms
|
||||
return u
|
||||
}
|
||||
|
||||
// Wait for all instances in a group to be done before moving on.
|
||||
// WaitForBatchCompletion configures the job update to wait for all instances in a group to be done before moving on.
|
||||
func (u *UpdateJob) WaitForBatchCompletion(batchWait bool) *UpdateJob {
|
||||
u.req.Settings.WaitForBatchCompletion = batchWait
|
||||
return u
|
||||
}
|
||||
|
||||
// Max number of instance failures to tolerate before marking instance as FAILED.
|
||||
// MaxPerInstanceFailures sets the max number of instance failures to tolerate before marking instance as FAILED.
|
||||
func (u *UpdateJob) MaxPerInstanceFailures(inst int32) *UpdateJob {
|
||||
u.req.Settings.MaxPerInstanceFailures = inst
|
||||
return u
|
||||
}
|
||||
|
||||
// Max number of FAILED instances to tolerate before terminating the update.
|
||||
// MaxFailedInstances sets the max number of FAILED instances to tolerate before terminating the update.
|
||||
func (u *UpdateJob) MaxFailedInstances(inst int32) *UpdateJob {
|
||||
u.req.Settings.MaxFailedInstances = inst
|
||||
return u
|
||||
}
|
||||
|
||||
// When False, prevents auto rollback of a failed update.
|
||||
// RollbackOnFail configure the job to rollback automatically after a job update fails.
|
||||
func (u *UpdateJob) RollbackOnFail(rollback bool) *UpdateJob {
|
||||
u.req.Settings.RollbackOnFailure = rollback
|
||||
return u
|
||||
}
|
||||
|
||||
func NewUpdateSettings() *aurora.JobUpdateSettings {
|
||||
// NewUpdateSettings return an opinionated set of job update settings.
|
||||
func (u *UpdateJob) BatchUpdateStrategy(strategy aurora.BatchJobUpdateStrategy) *UpdateJob {
|
||||
u.req.Settings.UpdateStrategy = &aurora.JobUpdateStrategy{BatchStrategy: &strategy}
|
||||
return u
|
||||
}
|
||||
|
||||
func (u *UpdateJob) QueueUpdateStrategy(strategy aurora.QueueJobUpdateStrategy) *UpdateJob {
|
||||
u.req.Settings.UpdateStrategy = &aurora.JobUpdateStrategy{QueueStrategy: &strategy}
|
||||
return u
|
||||
}
|
||||
|
||||
func (u *UpdateJob) VariableBatchStrategy(strategy aurora.VariableBatchJobUpdateStrategy) *UpdateJob {
|
||||
u.req.Settings.UpdateStrategy = &aurora.JobUpdateStrategy{VarBatchStrategy: &strategy}
|
||||
return u
|
||||
}
|
||||
|
||||
func NewUpdateSettings() *aurora.JobUpdateSettings {
|
||||
us := new(aurora.JobUpdateSettings)
|
||||
// Mirrors defaults set by Pystachio
|
||||
us.UpdateGroupSize = 1
|
||||
|
|
106
util.go
106
util.go
|
@ -1,18 +1,47 @@
|
|||
package realis
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/paypal/gorealis/gen-go/apache/aurora"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const apiPath = "/api"
|
||||
|
||||
// ActiveStates - States a task may be in when active.
|
||||
var ActiveStates = make(map[aurora.ScheduleStatus]bool)
|
||||
|
||||
// SlaveAssignedStates - States a task may be in when it has already been assigned to a Mesos agent.
|
||||
var SlaveAssignedStates = make(map[aurora.ScheduleStatus]bool)
|
||||
|
||||
// LiveStates - States a task may be in when it is live (e.g. able to take traffic)
|
||||
var LiveStates = make(map[aurora.ScheduleStatus]bool)
|
||||
|
||||
// TerminalStates - Set of states a task may not transition away from.
|
||||
var TerminalStates = make(map[aurora.ScheduleStatus]bool)
|
||||
|
||||
// ActiveJobUpdateStates - States a Job Update may be in where it is considered active.
|
||||
var ActiveJobUpdateStates = make(map[aurora.JobUpdateStatus]bool)
|
||||
|
||||
// TerminalUpdateStates returns a slice containing all the terminal states an update may be in.
|
||||
// This is a function in order to avoid having a slice that can be accidentally mutated.
|
||||
func TerminalUpdateStates() []aurora.JobUpdateStatus {
|
||||
return []aurora.JobUpdateStatus{
|
||||
aurora.JobUpdateStatus_ROLLED_FORWARD,
|
||||
aurora.JobUpdateStatus_ROLLED_BACK,
|
||||
aurora.JobUpdateStatus_ABORTED,
|
||||
aurora.JobUpdateStatus_ERROR,
|
||||
aurora.JobUpdateStatus_FAILED,
|
||||
}
|
||||
}
|
||||
|
||||
// AwaitingPulseJobUpdateStates - States a job update may be in where it is waiting for a pulse.
|
||||
var AwaitingPulseJobUpdateStates = make(map[aurora.JobUpdateStatus]bool)
|
||||
|
||||
func init() {
|
||||
|
@ -40,14 +69,57 @@ func init() {
|
|||
}
|
||||
}
|
||||
|
||||
func validateAndPopulateAuroraURL(urlStr string) (string, error) {
|
||||
|
||||
// If no protocol defined, assume http
|
||||
if !strings.Contains(urlStr, "://") {
|
||||
urlStr = "http://" + urlStr
|
||||
// createCertPool will attempt to load certificates into a certificate pool from a given directory.
|
||||
// Only files with an extension contained in the extension map are considered.
|
||||
// This function ignores any files that cannot be read successfully or cannot be added to the certPool
|
||||
// successfully.
|
||||
func createCertPool(path string, extensions map[string]struct{}) (*x509.CertPool, error) {
|
||||
_, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to load certificates")
|
||||
}
|
||||
|
||||
u, err := url.Parse(urlStr)
|
||||
caFiles, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
certPool := x509.NewCertPool()
|
||||
loadedCerts := 0
|
||||
for _, cert := range caFiles {
|
||||
// Skip directories
|
||||
if cert.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Skip any files that do not contain the right extension
|
||||
if _, ok := extensions[filepath.Ext(cert.Name())]; !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
pem, err := ioutil.ReadFile(filepath.Join(path, cert.Name()))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if certPool.AppendCertsFromPEM(pem) {
|
||||
loadedCerts++
|
||||
}
|
||||
}
|
||||
if loadedCerts == 0 {
|
||||
return nil, errors.New("no certificates were able to be successfully loaded")
|
||||
}
|
||||
return certPool, nil
|
||||
}
|
||||
|
||||
func validateAuroraURL(location string) (string, error) {
|
||||
|
||||
// If no protocol defined, assume http
|
||||
if !strings.Contains(location, "://") {
|
||||
location = "http://" + location
|
||||
}
|
||||
|
||||
u, err := url.Parse(location)
|
||||
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error parsing url")
|
||||
|
@ -67,9 +139,29 @@ func validateAndPopulateAuroraURL(urlStr string) (string, error) {
|
|||
return "", errors.Errorf("only protocols http and https are supported %v\n", u.Scheme)
|
||||
}
|
||||
|
||||
if u.Path != "/api" {
|
||||
// This could theoretically be elsewhere but we'll be strict for the sake of simplicity
|
||||
if u.Path != apiPath {
|
||||
return "", errors.Errorf("expected /api path %v\n", u.Path)
|
||||
}
|
||||
|
||||
return u.String(), nil
|
||||
}
|
||||
|
||||
func calculateCurrentBatch(updatingInstances int32, batchSizes []int32) int {
|
||||
for i, size := range batchSizes {
|
||||
updatingInstances -= size
|
||||
if updatingInstances <= 0 {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
// Overflow batches
|
||||
batchCount := len(batchSizes) - 1
|
||||
lastBatchIndex := len(batchSizes) - 1
|
||||
batchCount += int(updatingInstances / batchSizes[lastBatchIndex])
|
||||
|
||||
if updatingInstances%batchSizes[lastBatchIndex] != 0 {
|
||||
batchCount++
|
||||
}
|
||||
return batchCount
|
||||
}
|
||||
|
|
114
util_test.go
Normal file
114
util_test.go
Normal file
|
@ -0,0 +1,114 @@
|
|||
/**
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package realis
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAuroraURLValidator(t *testing.T) {
|
||||
t.Run("badURL", func(t *testing.T) {
|
||||
url, err := validateAuroraURL("http://badurl.com/badpath")
|
||||
assert.Empty(t, url)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("URLHttp", func(t *testing.T) {
|
||||
url, err := validateAuroraURL("http://goodurl.com:8081/api")
|
||||
assert.Equal(t, "http://goodurl.com:8081/api", url)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("URLHttps", func(t *testing.T) {
|
||||
url, err := validateAuroraURL("https://goodurl.com:8081/api")
|
||||
assert.Equal(t, "https://goodurl.com:8081/api", url)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("URLNoPath", func(t *testing.T) {
|
||||
url, err := validateAuroraURL("http://goodurl.com:8081")
|
||||
assert.Equal(t, "http://goodurl.com:8081/api", url)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("ipAddrNoPath", func(t *testing.T) {
|
||||
url, err := validateAuroraURL("http://192.168.1.33:8081")
|
||||
assert.Equal(t, "http://192.168.1.33:8081/api", url)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("URLNoProtocol", func(t *testing.T) {
|
||||
url, err := validateAuroraURL("goodurl.com:8081/api")
|
||||
assert.Equal(t, "http://goodurl.com:8081/api", url)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("URLNoProtocolNoPathNoPort", func(t *testing.T) {
|
||||
url, err := validateAuroraURL("goodurl.com")
|
||||
assert.Equal(t, "http://goodurl.com:8081/api", url)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestCurrentBatchCalculator(t *testing.T) {
|
||||
t.Run("singleBatchOverflow", func(t *testing.T) {
|
||||
curBatch := calculateCurrentBatch(10, []int32{2})
|
||||
assert.Equal(t, 4, curBatch)
|
||||
})
|
||||
|
||||
t.Run("noInstancesUpdating", func(t *testing.T) {
|
||||
curBatch := calculateCurrentBatch(0, []int32{2})
|
||||
assert.Equal(t, 0, curBatch)
|
||||
})
|
||||
|
||||
t.Run("evenMatchSingleBatch", func(t *testing.T) {
|
||||
curBatch := calculateCurrentBatch(2, []int32{2})
|
||||
assert.Equal(t, 0, curBatch)
|
||||
})
|
||||
|
||||
t.Run("moreInstancesThanBatches", func(t *testing.T) {
|
||||
curBatch := calculateCurrentBatch(5, []int32{1, 2})
|
||||
assert.Equal(t, 2, curBatch)
|
||||
})
|
||||
|
||||
t.Run("moreInstancesThanBatchesDecreasing", func(t *testing.T) {
|
||||
curBatch := calculateCurrentBatch(5, []int32{2, 1})
|
||||
assert.Equal(t, 3, curBatch)
|
||||
})
|
||||
|
||||
t.Run("unevenFit", func(t *testing.T) {
|
||||
curBatch := calculateCurrentBatch(2, []int32{1, 2})
|
||||
assert.Equal(t, 1, curBatch)
|
||||
})
|
||||
|
||||
t.Run("halfWay", func(t *testing.T) {
|
||||
curBatch := calculateCurrentBatch(1, []int32{1, 2})
|
||||
assert.Equal(t, 0, curBatch)
|
||||
})
|
||||
}
|
||||
|
||||
func TestCertPoolCreator(t *testing.T) {
|
||||
extensions := map[string]struct{}{".crt": {}}
|
||||
|
||||
_, err := createCertPool("examples/certs", extensions)
|
||||
assert.NoError(t, err)
|
||||
|
||||
t.Run("badDir", func(t *testing.T) {
|
||||
_, err := createCertPool("idontexist", extensions)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
26
vendor/github.com/stretchr/testify/.travis.yml
generated
vendored
26
vendor/github.com/stretchr/testify/.travis.yml
generated
vendored
|
@ -2,14 +2,18 @@ language: go
|
|||
|
||||
sudo: false
|
||||
|
||||
go:
|
||||
- 1.7
|
||||
- 1.8
|
||||
- 1.9
|
||||
- tip
|
||||
|
||||
script:
|
||||
- ./.travis.gogenerate.sh
|
||||
- ./.travis.gofmt.sh
|
||||
- ./.travis.govet.sh
|
||||
- go test -v -race ./...
|
||||
matrix:
|
||||
include:
|
||||
- go: "1.8.x"
|
||||
- go: "1.9.x"
|
||||
- go: "1.10.x"
|
||||
- go: "1.11.x"
|
||||
env: GO111MODULE=off
|
||||
- go: "1.11.x"
|
||||
env: GO111MODULE=on
|
||||
- go: tip
|
||||
script:
|
||||
- ./.travis.gogenerate.sh
|
||||
- ./.travis.gofmt.sh
|
||||
- ./.travis.govet.sh
|
||||
- go test -v -race $(go list ./... | grep -v vendor)
|
||||
|
|
8
vendor/github.com/stretchr/testify/Gopkg.lock
generated
vendored
8
vendor/github.com/stretchr/testify/Gopkg.lock
generated
vendored
|
@ -10,16 +10,18 @@
|
|||
[[projects]]
|
||||
name = "github.com/pmezard/go-difflib"
|
||||
packages = ["difflib"]
|
||||
revision = "d8ed2627bdf02c080bf22230dbb337003b7aba2d"
|
||||
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/stretchr/objx"
|
||||
packages = ["."]
|
||||
revision = "cbeaeb16a013161a98496fad62933b1d21786672"
|
||||
revision = "facf9a85c22f48d2f52f2380e4efce1768749a89"
|
||||
version = "v0.1"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "6bd8fb1f11a0d3df245fc01bd8853f6dac40b83457e780f7978ca30244647c7b"
|
||||
inputs-digest = "448ddae4702c6aded2555faafd390c537789bb1c483f70b0431e6634f73f2090"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
|
36
vendor/github.com/stretchr/testify/Gopkg.toml
generated
vendored
36
vendor/github.com/stretchr/testify/Gopkg.toml
generated
vendored
|
@ -1,26 +1,16 @@
|
|||
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
|
||||
[prune]
|
||||
unused-packages = true
|
||||
non-go = true
|
||||
go-tests = true
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/davecgh/go-spew"
|
||||
version = ">=1.0.0, <=3.0.0-g6d21280"
|
||||
version = "~1.1.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/pmezard/go-difflib"
|
||||
version = "~1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/stretchr/objx"
|
||||
version = "~0.1.0"
|
||||
|
|
35
vendor/github.com/stretchr/testify/LICENSE
generated
vendored
35
vendor/github.com/stretchr/testify/LICENSE
generated
vendored
|
@ -1,22 +1,21 @@
|
|||
Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell
|
||||
MIT License
|
||||
|
||||
Please consider promoting this project if you find it useful.
|
||||
Copyright (c) 2012-2018 Mat Ryer and Tyler Bunnell
|
||||
|
||||
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:
|
||||
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 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.
|
||||
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.
|
||||
|
|
56
vendor/github.com/stretchr/testify/README.md
generated
vendored
56
vendor/github.com/stretchr/testify/README.md
generated
vendored
|
@ -9,7 +9,6 @@ Features include:
|
|||
|
||||
* [Easy assertions](#assert-package)
|
||||
* [Mocking](#mock-package)
|
||||
* [HTTP response trapping](#http-package)
|
||||
* [Testing suite interfaces and functions](#suite-package)
|
||||
|
||||
Get started:
|
||||
|
@ -106,14 +105,6 @@ The `require` package provides same global functions as the `assert` package, bu
|
|||
|
||||
See [t.FailNow](http://golang.org/pkg/testing/#T.FailNow) for details.
|
||||
|
||||
|
||||
[`http`](http://godoc.org/github.com/stretchr/testify/http "API documentation") package
|
||||
---------------------------------------------------------------------------------------
|
||||
|
||||
The `http` package contains test objects useful for testing code that relies on the `net/http` package. Check out the [(deprecated) API documentation for the `http` package](http://godoc.org/github.com/stretchr/testify/http).
|
||||
|
||||
We recommend you use [httptest](http://golang.org/pkg/net/http/httptest) instead.
|
||||
|
||||
[`mock`](http://godoc.org/github.com/stretchr/testify/mock "API documentation") package
|
||||
----------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -173,6 +164,29 @@ func TestSomething(t *testing.T) {
|
|||
// assert that the expectations were met
|
||||
testObj.AssertExpectations(t)
|
||||
|
||||
|
||||
}
|
||||
|
||||
// TestSomethingElse is a second example of how to use our test object to
|
||||
// make assertions about some target code we are testing.
|
||||
// This time using a placeholder. Placeholders might be used when the
|
||||
// data being passed in is normally dynamically generated and cannot be
|
||||
// predicted beforehand (eg. containing hashes that are time sensitive)
|
||||
func TestSomethingElse(t *testing.T) {
|
||||
|
||||
// create an instance of our test object
|
||||
testObj := new(MyMockedObject)
|
||||
|
||||
// setup expectations with a placeholder in the argument list
|
||||
testObj.On("DoSomething", mock.Anything).Return(true, nil)
|
||||
|
||||
// call the code we are testing
|
||||
targetFuncThatDoesSomethingWithObj(testObj)
|
||||
|
||||
// assert that the expectations were met
|
||||
testObj.AssertExpectations(t)
|
||||
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -268,14 +282,15 @@ Installation
|
|||
|
||||
To install Testify, use `go get`:
|
||||
|
||||
* Latest version: go get github.com/stretchr/testify
|
||||
* Specific version: go get gopkg.in/stretchr/testify.v1
|
||||
go get github.com/stretchr/testify
|
||||
|
||||
This will then make the following packages available to you:
|
||||
|
||||
github.com/stretchr/testify/assert
|
||||
github.com/stretchr/testify/require
|
||||
github.com/stretchr/testify/mock
|
||||
github.com/stretchr/testify/http
|
||||
github.com/stretchr/testify/suite
|
||||
github.com/stretchr/testify/http (deprecated)
|
||||
|
||||
Import the `testify/assert` package into your code using this template:
|
||||
|
||||
|
@ -303,10 +318,10 @@ To update Testify to the latest version, use `go get -u github.com/stretchr/test
|
|||
|
||||
------
|
||||
|
||||
Version History
|
||||
===============
|
||||
Supported go versions
|
||||
==================
|
||||
|
||||
* 1.0 - New package versioning strategy adopted.
|
||||
We support the three major Go versions, which are 1.9, 1.10, and 1.11 at the moment.
|
||||
|
||||
------
|
||||
|
||||
|
@ -319,14 +334,7 @@ When submitting an issue, we ask that you please include a complete test functio
|
|||
|
||||
------
|
||||
|
||||
Licence
|
||||
License
|
||||
=======
|
||||
Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell
|
||||
|
||||
Please consider promoting this project if you find it useful.
|
||||
|
||||
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.
|
||||
This project is licensed under the terms of the MIT license.
|
||||
|
|
201
vendor/github.com/stretchr/testify/assert/assertion_format.go
generated
vendored
201
vendor/github.com/stretchr/testify/assert/assertion_format.go
generated
vendored
|
@ -13,6 +13,9 @@ import (
|
|||
|
||||
// Conditionf uses a Comparison to assert a complex condition.
|
||||
func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Condition(t, comp, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -22,14 +25,18 @@ func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bo
|
|||
// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted")
|
||||
// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted")
|
||||
// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Contains(t, s, contains, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
|
||||
func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return DirExists(t, path, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -37,10 +44,11 @@ func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
|
|||
// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
|
||||
// the number of appearances of each of them in both lists should match.
|
||||
//
|
||||
// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted"))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
|
||||
func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -48,9 +56,10 @@ func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string
|
|||
// a slice or a channel with len == 0.
|
||||
//
|
||||
// assert.Emptyf(t, obj, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Empty(t, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -58,12 +67,13 @@ func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) boo
|
|||
//
|
||||
// assert.Equalf(t, 123, 123, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
//
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses). Function equality
|
||||
// cannot be determined and will always fail.
|
||||
func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Equal(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -72,9 +82,10 @@ func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, ar
|
|||
//
|
||||
// actualObj, err := SomeFunction()
|
||||
// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -82,9 +93,10 @@ func EqualErrorf(t TestingT, theError error, errString string, msg string, args
|
|||
// and equal.
|
||||
//
|
||||
// assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -94,62 +106,80 @@ func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg stri
|
|||
// if assert.Errorf(t, err, "error message %s", "formatted") {
|
||||
// assert.Equal(t, expectedErrorf, err)
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Errorf(t TestingT, err error, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Error(t, err, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Exactlyf asserts that two objects are equal in value and type.
|
||||
//
|
||||
// assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Failf reports a failure through
|
||||
func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Fail(t, failureMessage, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// FailNowf fails test
|
||||
func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Falsef asserts that the specified value is false.
|
||||
//
|
||||
// assert.Falsef(t, myBool, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return False(t, value, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
|
||||
func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return FileExists(t, path, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// HTTPBodyContainsf asserts that a specified handler returns a
|
||||
// body that contains a string.
|
||||
//
|
||||
// assert.HTTPBodyContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// HTTPBodyNotContainsf asserts that a specified handler returns a
|
||||
// body that does not contain a string.
|
||||
//
|
||||
// assert.HTTPBodyNotContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -159,6 +189,9 @@ func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, u
|
|||
//
|
||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
||||
func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPError(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -168,6 +201,9 @@ func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string,
|
|||
//
|
||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
||||
func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -177,6 +213,9 @@ func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url stri
|
|||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -184,51 +223,69 @@ func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url strin
|
|||
//
|
||||
// assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject))
|
||||
func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// InDeltaf asserts that the two numerals are within delta of each other.
|
||||
//
|
||||
// assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
|
||||
func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDeltaMapValues(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// InDeltaSlicef is the same as InDelta, except it compares two slices.
|
||||
func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// InEpsilonf asserts that expected and actual have a relative error less than epsilon
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
|
||||
func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// IsTypef asserts that the specified objects are of the same type.
|
||||
func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// JSONEqf asserts that two JSON strings are equivalent.
|
||||
//
|
||||
// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -236,18 +293,20 @@ func JSONEqf(t TestingT, expected string, actual string, msg string, args ...int
|
|||
// Lenf also fails if the object has a type that len() not accept.
|
||||
//
|
||||
// assert.Lenf(t, mySlice, 3, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Len(t, object, length, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Nilf asserts that the specified object is nil.
|
||||
//
|
||||
// assert.Nilf(t, err, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Nil(t, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -257,9 +316,10 @@ func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool
|
|||
// if assert.NoErrorf(t, err, "error message %s", "formatted") {
|
||||
// assert.Equal(t, expectedObj, actualObj)
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NoError(t, err, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -269,9 +329,10 @@ func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool {
|
|||
// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted")
|
||||
// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted")
|
||||
// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotContains(t, s, contains, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -281,9 +342,10 @@ func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, a
|
|||
// if assert.NotEmptyf(t, obj, "error message %s", "formatted") {
|
||||
// assert.Equal(t, "two", obj[1])
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotEmpty(t, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -291,29 +353,32 @@ func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{})
|
|||
//
|
||||
// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
//
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses).
|
||||
func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// NotNilf asserts that the specified object is not nil.
|
||||
//
|
||||
// assert.NotNilf(t, err, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotNil(t, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
|
||||
//
|
||||
// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotPanics(t, f, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -321,9 +386,10 @@ func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bo
|
|||
//
|
||||
// assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting")
|
||||
// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -331,23 +397,28 @@ func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ..
|
|||
// elements given in the specified subset(array, slice...).
|
||||
//
|
||||
// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// NotZerof asserts that i is not the zero value for its type and returns the truth.
|
||||
// NotZerof asserts that i is not the zero value for its type.
|
||||
func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotZero(t, i, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Panicsf asserts that the code inside the specified PanicTestFunc panics.
|
||||
//
|
||||
// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Panics(t, f, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -355,9 +426,10 @@ func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool
|
|||
// the recovered panic value equals the expected panic value.
|
||||
//
|
||||
// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -365,9 +437,10 @@ func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg str
|
|||
//
|
||||
// assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting")
|
||||
// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Regexp(t, rx, str, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -375,31 +448,37 @@ func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...in
|
|||
// elements given in the specified subset(array, slice...).
|
||||
//
|
||||
// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Subset(t, list, subset, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Truef asserts that the specified value is true.
|
||||
//
|
||||
// assert.Truef(t, myBool, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Truef(t TestingT, value bool, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return True(t, value, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// WithinDurationf asserts that the two times are within duration delta of each other.
|
||||
//
|
||||
// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Zerof asserts that i is the zero value for its type and returns the truth.
|
||||
// Zerof asserts that i is the zero value for its type.
|
||||
func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Zero(t, i, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
|
1
vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl
generated
vendored
1
vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl
generated
vendored
|
@ -1,4 +1,5 @@
|
|||
{{.CommentFormat}}
|
||||
func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool {
|
||||
if h, ok := t.(tHelper); ok { h.Helper() }
|
||||
return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}})
|
||||
}
|
||||
|
|
402
vendor/github.com/stretchr/testify/assert/assertion_forward.go
generated
vendored
402
vendor/github.com/stretchr/testify/assert/assertion_forward.go
generated
vendored
|
@ -13,11 +13,17 @@ import (
|
|||
|
||||
// Condition uses a Comparison to assert a complex condition.
|
||||
func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Condition(a.t, comp, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Conditionf uses a Comparison to assert a complex condition.
|
||||
func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Conditionf(a.t, comp, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -27,9 +33,10 @@ func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}
|
|||
// a.Contains("Hello World", "World")
|
||||
// a.Contains(["Hello", "World"], "World")
|
||||
// a.Contains({"Hello": "World"}, "Hello")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Contains(a.t, s, contains, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -39,19 +46,26 @@ func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ..
|
|||
// a.Containsf("Hello World", "World", "error message %s", "formatted")
|
||||
// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted")
|
||||
// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Containsf(a.t, s, contains, msg, args...)
|
||||
}
|
||||
|
||||
// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
|
||||
func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return DirExists(a.t, path, msgAndArgs...)
|
||||
}
|
||||
|
||||
// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
|
||||
func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return DirExistsf(a.t, path, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -59,10 +73,11 @@ func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bo
|
|||
// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
|
||||
// the number of appearances of each of them in both lists should match.
|
||||
//
|
||||
// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2])
|
||||
func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return ElementsMatch(a.t, listA, listB, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -70,10 +85,11 @@ func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndA
|
|||
// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
|
||||
// the number of appearances of each of them in both lists should match.
|
||||
//
|
||||
// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted"))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
|
||||
func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return ElementsMatchf(a.t, listA, listB, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -81,9 +97,10 @@ func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg st
|
|||
// a slice or a channel with len == 0.
|
||||
//
|
||||
// a.Empty(obj)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Empty(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -91,9 +108,10 @@ func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
|
|||
// a slice or a channel with len == 0.
|
||||
//
|
||||
// a.Emptyf(obj, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Emptyf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -101,12 +119,13 @@ func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{})
|
|||
//
|
||||
// a.Equal(123, 123)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
//
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses). Function equality
|
||||
// cannot be determined and will always fail.
|
||||
func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Equal(a.t, expected, actual, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -115,9 +134,10 @@ func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs
|
|||
//
|
||||
// actualObj, err := SomeFunction()
|
||||
// a.EqualError(err, expectedErrorString)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return EqualError(a.t, theError, errString, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -126,9 +146,10 @@ func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...
|
|||
//
|
||||
// actualObj, err := SomeFunction()
|
||||
// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return EqualErrorf(a.t, theError, errString, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -136,9 +157,10 @@ func (a *Assertions) EqualErrorf(theError error, errString string, msg string, a
|
|||
// and equal.
|
||||
//
|
||||
// a.EqualValues(uint32(123), int32(123))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return EqualValues(a.t, expected, actual, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -146,9 +168,10 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn
|
|||
// and equal.
|
||||
//
|
||||
// a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return EqualValuesf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -156,12 +179,13 @@ func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg
|
|||
//
|
||||
// a.Equalf(123, 123, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
//
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses). Function equality
|
||||
// cannot be determined and will always fail.
|
||||
func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Equalf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -171,9 +195,10 @@ func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string
|
|||
// if a.Error(err) {
|
||||
// assert.Equal(t, expectedError, err)
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Error(a.t, err, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -183,115 +208,150 @@ func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool {
|
|||
// if a.Errorf(err, "error message %s", "formatted") {
|
||||
// assert.Equal(t, expectedErrorf, err)
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Errorf(a.t, err, msg, args...)
|
||||
}
|
||||
|
||||
// Exactly asserts that two objects are equal in value and type.
|
||||
//
|
||||
// a.Exactly(int32(123), int64(123))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Exactly(a.t, expected, actual, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Exactlyf asserts that two objects are equal in value and type.
|
||||
//
|
||||
// a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Exactlyf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
// Fail reports a failure through
|
||||
func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Fail(a.t, failureMessage, msgAndArgs...)
|
||||
}
|
||||
|
||||
// FailNow fails test
|
||||
func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return FailNow(a.t, failureMessage, msgAndArgs...)
|
||||
}
|
||||
|
||||
// FailNowf fails test
|
||||
func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return FailNowf(a.t, failureMessage, msg, args...)
|
||||
}
|
||||
|
||||
// Failf reports a failure through
|
||||
func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Failf(a.t, failureMessage, msg, args...)
|
||||
}
|
||||
|
||||
// False asserts that the specified value is false.
|
||||
//
|
||||
// a.False(myBool)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return False(a.t, value, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Falsef asserts that the specified value is false.
|
||||
//
|
||||
// a.Falsef(myBool, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Falsef(a.t, value, msg, args...)
|
||||
}
|
||||
|
||||
// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
|
||||
func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return FileExists(a.t, path, msgAndArgs...)
|
||||
}
|
||||
|
||||
// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
|
||||
func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return FileExistsf(a.t, path, msg, args...)
|
||||
}
|
||||
|
||||
// HTTPBodyContains asserts that a specified handler returns a
|
||||
// body that contains a string.
|
||||
//
|
||||
// a.HTTPBodyContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
||||
// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...)
|
||||
}
|
||||
|
||||
// HTTPBodyContainsf asserts that a specified handler returns a
|
||||
// body that contains a string.
|
||||
//
|
||||
// a.HTTPBodyContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...)
|
||||
}
|
||||
|
||||
// HTTPBodyNotContains asserts that a specified handler returns a
|
||||
// body that does not contain a string.
|
||||
//
|
||||
// a.HTTPBodyNotContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
||||
// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...)
|
||||
}
|
||||
|
||||
// HTTPBodyNotContainsf asserts that a specified handler returns a
|
||||
// body that does not contain a string.
|
||||
//
|
||||
// a.HTTPBodyNotContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -301,6 +361,9 @@ func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method strin
|
|||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPError(a.t, handler, method, url, values, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -310,6 +373,9 @@ func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url stri
|
|||
//
|
||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
||||
func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPErrorf(a.t, handler, method, url, values, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -319,6 +385,9 @@ func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url str
|
|||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -328,6 +397,9 @@ func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url s
|
|||
//
|
||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
||||
func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPRedirectf(a.t, handler, method, url, values, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -337,6 +409,9 @@ func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url
|
|||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -346,6 +421,9 @@ func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url st
|
|||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPSuccessf(a.t, handler, method, url, values, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -353,6 +431,9 @@ func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url s
|
|||
//
|
||||
// a.Implements((*MyInterface)(nil), new(MyObject))
|
||||
func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Implements(a.t, interfaceObject, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -360,96 +441,129 @@ func (a *Assertions) Implements(interfaceObject interface{}, object interface{},
|
|||
//
|
||||
// a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject))
|
||||
func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Implementsf(a.t, interfaceObject, object, msg, args...)
|
||||
}
|
||||
|
||||
// InDelta asserts that the two numerals are within delta of each other.
|
||||
//
|
||||
// a.InDelta(math.Pi, (22 / 7.0), 0.01)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDelta(a.t, expected, actual, delta, msgAndArgs...)
|
||||
}
|
||||
|
||||
// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
|
||||
func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...)
|
||||
}
|
||||
|
||||
// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
|
||||
func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...)
|
||||
}
|
||||
|
||||
// InDeltaSlice is the same as InDelta, except it compares two slices.
|
||||
func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...)
|
||||
}
|
||||
|
||||
// InDeltaSlicef is the same as InDelta, except it compares two slices.
|
||||
func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDeltaSlicef(a.t, expected, actual, delta, msg, args...)
|
||||
}
|
||||
|
||||
// InDeltaf asserts that the two numerals are within delta of each other.
|
||||
//
|
||||
// a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDeltaf(a.t, expected, actual, delta, msg, args...)
|
||||
}
|
||||
|
||||
// InEpsilon asserts that expected and actual have a relative error less than epsilon
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...)
|
||||
}
|
||||
|
||||
// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
|
||||
func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...)
|
||||
}
|
||||
|
||||
// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
|
||||
func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...)
|
||||
}
|
||||
|
||||
// InEpsilonf asserts that expected and actual have a relative error less than epsilon
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InEpsilonf(a.t, expected, actual, epsilon, msg, args...)
|
||||
}
|
||||
|
||||
// IsType asserts that the specified objects are of the same type.
|
||||
func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsType(a.t, expectedType, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
// IsTypef asserts that the specified objects are of the same type.
|
||||
func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsTypef(a.t, expectedType, object, msg, args...)
|
||||
}
|
||||
|
||||
// JSONEq asserts that two JSON strings are equivalent.
|
||||
//
|
||||
// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return JSONEq(a.t, expected, actual, msgAndArgs...)
|
||||
}
|
||||
|
||||
// JSONEqf asserts that two JSON strings are equivalent.
|
||||
//
|
||||
// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return JSONEqf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -457,9 +571,10 @@ func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ..
|
|||
// Len also fails if the object has a type that len() not accept.
|
||||
//
|
||||
// a.Len(mySlice, 3)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Len(a.t, object, length, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -467,27 +582,30 @@ func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface
|
|||
// Lenf also fails if the object has a type that len() not accept.
|
||||
//
|
||||
// a.Lenf(mySlice, 3, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Lenf(a.t, object, length, msg, args...)
|
||||
}
|
||||
|
||||
// Nil asserts that the specified object is nil.
|
||||
//
|
||||
// a.Nil(err)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Nil(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Nilf asserts that the specified object is nil.
|
||||
//
|
||||
// a.Nilf(err, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Nilf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -497,9 +615,10 @@ func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) b
|
|||
// if a.NoError(err) {
|
||||
// assert.Equal(t, expectedObj, actualObj)
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NoError(a.t, err, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -509,9 +628,10 @@ func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool {
|
|||
// if a.NoErrorf(err, "error message %s", "formatted") {
|
||||
// assert.Equal(t, expectedObj, actualObj)
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NoErrorf(a.t, err, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -521,9 +641,10 @@ func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool {
|
|||
// a.NotContains("Hello World", "Earth")
|
||||
// a.NotContains(["Hello", "World"], "Earth")
|
||||
// a.NotContains({"Hello": "World"}, "Earth")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotContains(a.t, s, contains, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -533,9 +654,10 @@ func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs
|
|||
// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted")
|
||||
// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted")
|
||||
// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotContainsf(a.t, s, contains, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -545,9 +667,10 @@ func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg strin
|
|||
// if a.NotEmpty(obj) {
|
||||
// assert.Equal(t, "two", obj[1])
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotEmpty(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -557,9 +680,10 @@ func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) boo
|
|||
// if a.NotEmptyf(obj, "error message %s", "formatted") {
|
||||
// assert.Equal(t, "two", obj[1])
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotEmptyf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -567,11 +691,12 @@ func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface
|
|||
//
|
||||
// a.NotEqual(obj1, obj2)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
//
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses).
|
||||
func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotEqual(a.t, expected, actual, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -579,47 +704,52 @@ func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndAr
|
|||
//
|
||||
// a.NotEqualf(obj1, obj2, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
//
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses).
|
||||
func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotEqualf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
// NotNil asserts that the specified object is not nil.
|
||||
//
|
||||
// a.NotNil(err)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotNil(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
// NotNilf asserts that the specified object is not nil.
|
||||
//
|
||||
// a.NotNilf(err, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotNilf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
|
||||
//
|
||||
// a.NotPanics(func(){ RemainCalm() })
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotPanics(a.t, f, msgAndArgs...)
|
||||
}
|
||||
|
||||
// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
|
||||
//
|
||||
// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotPanicsf(a.t, f, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -627,9 +757,10 @@ func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}
|
|||
//
|
||||
// a.NotRegexp(regexp.MustCompile("starts"), "it's starting")
|
||||
// a.NotRegexp("^start", "it's not starting")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotRegexp(a.t, rx, str, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -637,9 +768,10 @@ func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...in
|
|||
//
|
||||
// a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting")
|
||||
// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotRegexpf(a.t, rx, str, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -647,9 +779,10 @@ func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, arg
|
|||
// elements given in the specified subset(array, slice...).
|
||||
//
|
||||
// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotSubset(a.t, list, subset, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -657,28 +790,36 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs
|
|||
// elements given in the specified subset(array, slice...).
|
||||
//
|
||||
// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotSubsetf(a.t, list, subset, msg, args...)
|
||||
}
|
||||
|
||||
// NotZero asserts that i is not the zero value for its type and returns the truth.
|
||||
// NotZero asserts that i is not the zero value for its type.
|
||||
func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotZero(a.t, i, msgAndArgs...)
|
||||
}
|
||||
|
||||
// NotZerof asserts that i is not the zero value for its type and returns the truth.
|
||||
// NotZerof asserts that i is not the zero value for its type.
|
||||
func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotZerof(a.t, i, msg, args...)
|
||||
}
|
||||
|
||||
// Panics asserts that the code inside the specified PanicTestFunc panics.
|
||||
//
|
||||
// a.Panics(func(){ GoCrazy() })
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Panics(a.t, f, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -686,9 +827,10 @@ func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
|||
// the recovered panic value equals the expected panic value.
|
||||
//
|
||||
// a.PanicsWithValue("crazy error", func(){ GoCrazy() })
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return PanicsWithValue(a.t, expected, f, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -696,18 +838,20 @@ func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgA
|
|||
// the recovered panic value equals the expected panic value.
|
||||
//
|
||||
// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return PanicsWithValuef(a.t, expected, f, msg, args...)
|
||||
}
|
||||
|
||||
// Panicsf asserts that the code inside the specified PanicTestFunc panics.
|
||||
//
|
||||
// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Panicsf(a.t, f, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -715,9 +859,10 @@ func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) b
|
|||
//
|
||||
// a.Regexp(regexp.MustCompile("start"), "it's starting")
|
||||
// a.Regexp("start...$", "it's not starting")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Regexp(a.t, rx, str, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -725,9 +870,10 @@ func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...inter
|
|||
//
|
||||
// a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting")
|
||||
// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Regexpf(a.t, rx, str, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -735,9 +881,10 @@ func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args .
|
|||
// elements given in the specified subset(array, slice...).
|
||||
//
|
||||
// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Subset(a.t, list, subset, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -745,54 +892,65 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...
|
|||
// elements given in the specified subset(array, slice...).
|
||||
//
|
||||
// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Subsetf(a.t, list, subset, msg, args...)
|
||||
}
|
||||
|
||||
// True asserts that the specified value is true.
|
||||
//
|
||||
// a.True(myBool)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return True(a.t, value, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Truef asserts that the specified value is true.
|
||||
//
|
||||
// a.Truef(myBool, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Truef(a.t, value, msg, args...)
|
||||
}
|
||||
|
||||
// WithinDuration asserts that the two times are within duration delta of each other.
|
||||
//
|
||||
// a.WithinDuration(time.Now(), time.Now(), 10*time.Second)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
|
||||
}
|
||||
|
||||
// WithinDurationf asserts that the two times are within duration delta of each other.
|
||||
//
|
||||
// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return WithinDurationf(a.t, expected, actual, delta, msg, args...)
|
||||
}
|
||||
|
||||
// Zero asserts that i is the zero value for its type and returns the truth.
|
||||
// Zero asserts that i is the zero value for its type.
|
||||
func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Zero(a.t, i, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Zerof asserts that i is the zero value for its type and returns the truth.
|
||||
// Zerof asserts that i is the zero value for its type.
|
||||
func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Zerof(a.t, i, msg, args...)
|
||||
}
|
||||
|
|
1
vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl
generated
vendored
1
vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl
generated
vendored
|
@ -1,4 +1,5 @@
|
|||
{{.CommentWithoutT "a"}}
|
||||
func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool {
|
||||
if h, ok := a.t.(tHelper); ok { h.Helper() }
|
||||
return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}})
|
||||
}
|
||||
|
|
308
vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
308
vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
|
@ -27,6 +27,22 @@ type TestingT interface {
|
|||
Errorf(format string, args ...interface{})
|
||||
}
|
||||
|
||||
// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful
|
||||
// for table driven tests.
|
||||
type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) bool
|
||||
|
||||
// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful
|
||||
// for table driven tests.
|
||||
type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool
|
||||
|
||||
// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful
|
||||
// for table driven tests.
|
||||
type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool
|
||||
|
||||
// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful
|
||||
// for table driven tests.
|
||||
type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool
|
||||
|
||||
// Comparison a custom function that returns true on success and false on failure
|
||||
type Comparison func() (success bool)
|
||||
|
||||
|
@ -38,21 +54,23 @@ type Comparison func() (success bool)
|
|||
//
|
||||
// This function does no assertion of any kind.
|
||||
func ObjectsAreEqual(expected, actual interface{}) bool {
|
||||
|
||||
if expected == nil || actual == nil {
|
||||
return expected == actual
|
||||
}
|
||||
if exp, ok := expected.([]byte); ok {
|
||||
act, ok := actual.([]byte)
|
||||
if !ok {
|
||||
return false
|
||||
} else if exp == nil || act == nil {
|
||||
return exp == nil && act == nil
|
||||
}
|
||||
return bytes.Equal(exp, act)
|
||||
}
|
||||
return reflect.DeepEqual(expected, actual)
|
||||
|
||||
exp, ok := expected.([]byte)
|
||||
if !ok {
|
||||
return reflect.DeepEqual(expected, actual)
|
||||
}
|
||||
|
||||
act, ok := actual.([]byte)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if exp == nil || act == nil {
|
||||
return exp == nil && act == nil
|
||||
}
|
||||
return bytes.Equal(exp, act)
|
||||
}
|
||||
|
||||
// ObjectsAreEqualValues gets whether two objects are equal, or if their
|
||||
|
@ -156,27 +174,16 @@ func isTest(name, prefix string) bool {
|
|||
return !unicode.IsLower(rune)
|
||||
}
|
||||
|
||||
// getWhitespaceString returns a string that is long enough to overwrite the default
|
||||
// output from the go testing framework.
|
||||
func getWhitespaceString() string {
|
||||
|
||||
_, file, line, ok := runtime.Caller(1)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
parts := strings.Split(file, "/")
|
||||
file = parts[len(parts)-1]
|
||||
|
||||
return strings.Repeat(" ", len(fmt.Sprintf("%s:%d: ", file, line)))
|
||||
|
||||
}
|
||||
|
||||
func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
|
||||
if len(msgAndArgs) == 0 || msgAndArgs == nil {
|
||||
return ""
|
||||
}
|
||||
if len(msgAndArgs) == 1 {
|
||||
return msgAndArgs[0].(string)
|
||||
msg := msgAndArgs[0]
|
||||
if msgAsStr, ok := msg.(string); ok {
|
||||
return msgAsStr
|
||||
}
|
||||
return fmt.Sprintf("%+v", msg)
|
||||
}
|
||||
if len(msgAndArgs) > 1 {
|
||||
return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
|
||||
|
@ -195,7 +202,7 @@ func indentMessageLines(message string, longestLabelLen int) string {
|
|||
// no need to align first line because it starts at the correct location (after the label)
|
||||
if i != 0 {
|
||||
// append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab
|
||||
outBuf.WriteString("\n\r\t" + strings.Repeat(" ", longestLabelLen+1) + "\t")
|
||||
outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t")
|
||||
}
|
||||
outBuf.WriteString(scanner.Text())
|
||||
}
|
||||
|
@ -209,6 +216,9 @@ type failNower interface {
|
|||
|
||||
// FailNow fails test
|
||||
func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Fail(t, failureMessage, msgAndArgs...)
|
||||
|
||||
// We cannot extend TestingT with FailNow() and
|
||||
|
@ -227,8 +237,11 @@ func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool
|
|||
|
||||
// Fail reports a failure through
|
||||
func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
content := []labeledContent{
|
||||
{"Error Trace", strings.Join(CallerInfo(), "\n\r\t\t\t")},
|
||||
{"Error Trace", strings.Join(CallerInfo(), "\n\t\t\t")},
|
||||
{"Error", failureMessage},
|
||||
}
|
||||
|
||||
|
@ -244,7 +257,7 @@ func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
|
|||
content = append(content, labeledContent{"Messages", message})
|
||||
}
|
||||
|
||||
t.Errorf("%s", "\r"+getWhitespaceString()+labeledOutput(content...))
|
||||
t.Errorf("\n%s", ""+labeledOutput(content...))
|
||||
|
||||
return false
|
||||
}
|
||||
|
@ -256,7 +269,7 @@ type labeledContent struct {
|
|||
|
||||
// labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner:
|
||||
//
|
||||
// \r\t{{label}}:{{align_spaces}}\t{{content}}\n
|
||||
// \t{{label}}:{{align_spaces}}\t{{content}}\n
|
||||
//
|
||||
// The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label.
|
||||
// If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this
|
||||
|
@ -272,7 +285,7 @@ func labeledOutput(content ...labeledContent) string {
|
|||
}
|
||||
var output string
|
||||
for _, v := range content {
|
||||
output += "\r\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n"
|
||||
output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n"
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
@ -281,6 +294,9 @@ func labeledOutput(content ...labeledContent) string {
|
|||
//
|
||||
// assert.Implements(t, (*MyInterface)(nil), new(MyObject))
|
||||
func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
interfaceType := reflect.TypeOf(interfaceObject).Elem()
|
||||
|
||||
if object == nil {
|
||||
|
@ -295,6 +311,9 @@ func Implements(t TestingT, interfaceObject interface{}, object interface{}, msg
|
|||
|
||||
// IsType asserts that the specified objects are of the same type.
|
||||
func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) {
|
||||
return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...)
|
||||
|
@ -307,12 +326,13 @@ func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs
|
|||
//
|
||||
// assert.Equal(t, 123, 123)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
//
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses). Function equality
|
||||
// cannot be determined and will always fail.
|
||||
func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if err := validateEqualArgs(expected, actual); err != nil {
|
||||
return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)",
|
||||
expected, actual, err), msgAndArgs...)
|
||||
|
@ -350,9 +370,10 @@ func formatUnequalValues(expected, actual interface{}) (e string, a string) {
|
|||
// and equal.
|
||||
//
|
||||
// assert.EqualValues(t, uint32(123), int32(123))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if !ObjectsAreEqualValues(expected, actual) {
|
||||
diff := diff(expected, actual)
|
||||
|
@ -369,15 +390,16 @@ func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interfa
|
|||
// Exactly asserts that two objects are equal in value and type.
|
||||
//
|
||||
// assert.Exactly(t, int32(123), int64(123))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
aType := reflect.TypeOf(expected)
|
||||
bType := reflect.TypeOf(actual)
|
||||
|
||||
if aType != bType {
|
||||
return Fail(t, fmt.Sprintf("Types expected to match exactly\n\r\t%v != %v", aType, bType), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...)
|
||||
}
|
||||
|
||||
return Equal(t, expected, actual, msgAndArgs...)
|
||||
|
@ -387,15 +409,27 @@ func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}
|
|||
// NotNil asserts that the specified object is not nil.
|
||||
//
|
||||
// assert.NotNil(t, err)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if !isNil(object) {
|
||||
return true
|
||||
}
|
||||
return Fail(t, "Expected value not to be nil.", msgAndArgs...)
|
||||
}
|
||||
|
||||
// containsKind checks if a specified kind in the slice of kinds.
|
||||
func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool {
|
||||
for i := 0; i < len(kinds); i++ {
|
||||
if kind == kinds[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// isNil checks if a specified object is nil or not, without Failing.
|
||||
func isNil(object interface{}) bool {
|
||||
if object == nil {
|
||||
|
@ -404,7 +438,14 @@ func isNil(object interface{}) bool {
|
|||
|
||||
value := reflect.ValueOf(object)
|
||||
kind := value.Kind()
|
||||
if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
|
||||
isNilableKind := containsKind(
|
||||
[]reflect.Kind{
|
||||
reflect.Chan, reflect.Func,
|
||||
reflect.Interface, reflect.Map,
|
||||
reflect.Ptr, reflect.Slice},
|
||||
kind)
|
||||
|
||||
if isNilableKind && value.IsNil() {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -414,9 +455,10 @@ func isNil(object interface{}) bool {
|
|||
// Nil asserts that the specified object is nil.
|
||||
//
|
||||
// assert.Nil(t, err)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if isNil(object) {
|
||||
return true
|
||||
}
|
||||
|
@ -455,9 +497,10 @@ func isEmpty(object interface{}) bool {
|
|||
// a slice or a channel with len == 0.
|
||||
//
|
||||
// assert.Empty(t, obj)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
pass := isEmpty(object)
|
||||
if !pass {
|
||||
|
@ -474,9 +517,10 @@ func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
|||
// if assert.NotEmpty(t, obj) {
|
||||
// assert.Equal(t, "two", obj[1])
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
pass := !isEmpty(object)
|
||||
if !pass {
|
||||
|
@ -503,9 +547,10 @@ func getLen(x interface{}) (ok bool, length int) {
|
|||
// Len also fails if the object has a type that len() not accept.
|
||||
//
|
||||
// assert.Len(t, mySlice, 3)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
ok, l := getLen(object)
|
||||
if !ok {
|
||||
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...)
|
||||
|
@ -520,9 +565,15 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{})
|
|||
// True asserts that the specified value is true.
|
||||
//
|
||||
// assert.True(t, myBool)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if h, ok := t.(interface {
|
||||
Helper()
|
||||
}); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if value != true {
|
||||
return Fail(t, "Should be true", msgAndArgs...)
|
||||
|
@ -535,9 +586,10 @@ func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
|||
// False asserts that the specified value is false.
|
||||
//
|
||||
// assert.False(t, myBool)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if value != false {
|
||||
return Fail(t, "Should be false", msgAndArgs...)
|
||||
|
@ -551,11 +603,12 @@ func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
|||
//
|
||||
// assert.NotEqual(t, obj1, obj2)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
//
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses).
|
||||
func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if err := validateEqualArgs(expected, actual); err != nil {
|
||||
return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)",
|
||||
expected, actual, err), msgAndArgs...)
|
||||
|
@ -613,9 +666,10 @@ func includeElement(list interface{}, element interface{}) (ok, found bool) {
|
|||
// assert.Contains(t, "Hello World", "World")
|
||||
// assert.Contains(t, ["Hello", "World"], "World")
|
||||
// assert.Contains(t, {"Hello": "World"}, "Hello")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
ok, found := includeElement(s, contains)
|
||||
if !ok {
|
||||
|
@ -635,9 +689,10 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo
|
|||
// assert.NotContains(t, "Hello World", "Earth")
|
||||
// assert.NotContains(t, ["Hello", "World"], "Earth")
|
||||
// assert.NotContains(t, {"Hello": "World"}, "Earth")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
ok, found := includeElement(s, contains)
|
||||
if !ok {
|
||||
|
@ -655,9 +710,10 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{})
|
|||
// elements given in the specified subset(array, slice...).
|
||||
//
|
||||
// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if subset == nil {
|
||||
return true // we consider nil to be equal to the nil set
|
||||
}
|
||||
|
@ -698,9 +754,10 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
|
|||
// elements given in the specified subset(array, slice...).
|
||||
//
|
||||
// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if subset == nil {
|
||||
return Fail(t, fmt.Sprintf("nil is the empty set which is a subset of every set"), msgAndArgs...)
|
||||
}
|
||||
|
@ -741,10 +798,11 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
|
|||
// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
|
||||
// the number of appearances of each of them in both lists should match.
|
||||
//
|
||||
// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2])
|
||||
func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if isEmpty(listA) && isEmpty(listB) {
|
||||
return true
|
||||
}
|
||||
|
@ -795,6 +853,9 @@ func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface
|
|||
|
||||
// Condition uses a Comparison to assert a complex condition.
|
||||
func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
result := comp()
|
||||
if !result {
|
||||
Fail(t, "Condition failed!", msgAndArgs...)
|
||||
|
@ -831,12 +892,13 @@ func didPanic(f PanicTestFunc) (bool, interface{}) {
|
|||
// Panics asserts that the code inside the specified PanicTestFunc panics.
|
||||
//
|
||||
// assert.Panics(t, func(){ GoCrazy() })
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if funcDidPanic, panicValue := didPanic(f); !funcDidPanic {
|
||||
return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
|
||||
}
|
||||
|
||||
return true
|
||||
|
@ -846,16 +908,17 @@ func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
|||
// the recovered panic value equals the expected panic value.
|
||||
//
|
||||
// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() })
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
funcDidPanic, panicValue := didPanic(f)
|
||||
if !funcDidPanic {
|
||||
return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
|
||||
}
|
||||
if panicValue != expected {
|
||||
return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%v\n\r\tPanic value:\t%v", f, expected, panicValue), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v", f, expected, panicValue), msgAndArgs...)
|
||||
}
|
||||
|
||||
return true
|
||||
|
@ -864,12 +927,13 @@ func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndAr
|
|||
// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
|
||||
//
|
||||
// assert.NotPanics(t, func(){ RemainCalm() })
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if funcDidPanic, panicValue := didPanic(f); funcDidPanic {
|
||||
return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v", f, panicValue), msgAndArgs...)
|
||||
}
|
||||
|
||||
return true
|
||||
|
@ -878,9 +942,10 @@ func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
|||
// WithinDuration asserts that the two times are within duration delta of each other.
|
||||
//
|
||||
// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
dt := expected.Sub(actual)
|
||||
if dt < -delta || dt > delta {
|
||||
|
@ -929,9 +994,10 @@ func toFloat(x interface{}) (float64, bool) {
|
|||
// InDelta asserts that the two numerals are within delta of each other.
|
||||
//
|
||||
// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
af, aok := toFloat(expected)
|
||||
bf, bok := toFloat(actual)
|
||||
|
@ -958,6 +1024,9 @@ func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs
|
|||
|
||||
// InDeltaSlice is the same as InDelta, except it compares two slices.
|
||||
func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if expected == nil || actual == nil ||
|
||||
reflect.TypeOf(actual).Kind() != reflect.Slice ||
|
||||
reflect.TypeOf(expected).Kind() != reflect.Slice {
|
||||
|
@ -979,6 +1048,9 @@ func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAn
|
|||
|
||||
// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
|
||||
func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if expected == nil || actual == nil ||
|
||||
reflect.TypeOf(actual).Kind() != reflect.Map ||
|
||||
reflect.TypeOf(expected).Kind() != reflect.Map {
|
||||
|
@ -989,7 +1061,7 @@ func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, m
|
|||
actualMap := reflect.ValueOf(actual)
|
||||
|
||||
if expectedMap.Len() != actualMap.Len() {
|
||||
return Fail(t, "Arguments must have the same numbe of keys", msgAndArgs...)
|
||||
return Fail(t, "Arguments must have the same number of keys", msgAndArgs...)
|
||||
}
|
||||
|
||||
for _, k := range expectedMap.MapKeys() {
|
||||
|
@ -1035,9 +1107,10 @@ func calcRelativeError(expected, actual interface{}) (float64, error) {
|
|||
}
|
||||
|
||||
// InEpsilon asserts that expected and actual have a relative error less than epsilon
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
actualEpsilon, err := calcRelativeError(expected, actual)
|
||||
if err != nil {
|
||||
return Fail(t, err.Error(), msgAndArgs...)
|
||||
|
@ -1052,6 +1125,9 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd
|
|||
|
||||
// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
|
||||
func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if expected == nil || actual == nil ||
|
||||
reflect.TypeOf(actual).Kind() != reflect.Slice ||
|
||||
reflect.TypeOf(expected).Kind() != reflect.Slice {
|
||||
|
@ -1081,9 +1157,10 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m
|
|||
// if assert.NoError(t, err) {
|
||||
// assert.Equal(t, expectedObj, actualObj)
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if err != nil {
|
||||
return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...)
|
||||
}
|
||||
|
@ -1097,9 +1174,10 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
|||
// if assert.Error(t, err) {
|
||||
// assert.Equal(t, expectedError, err)
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
return Fail(t, "An error is expected but got nil.", msgAndArgs...)
|
||||
|
@ -1113,9 +1191,10 @@ func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
|||
//
|
||||
// actualObj, err := SomeFunction()
|
||||
// assert.EqualError(t, err, expectedErrorString)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if !Error(t, theError, msgAndArgs...) {
|
||||
return false
|
||||
}
|
||||
|
@ -1148,9 +1227,10 @@ func matchRegexp(rx interface{}, str interface{}) bool {
|
|||
//
|
||||
// assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
|
||||
// assert.Regexp(t, "start...$", "it's not starting")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
match := matchRegexp(rx, str)
|
||||
|
||||
|
@ -1165,9 +1245,10 @@ func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface
|
|||
//
|
||||
// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
|
||||
// assert.NotRegexp(t, "^start", "it's not starting")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
match := matchRegexp(rx, str)
|
||||
|
||||
if match {
|
||||
|
@ -1178,16 +1259,22 @@ func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interf
|
|||
|
||||
}
|
||||
|
||||
// Zero asserts that i is the zero value for its type and returns the truth.
|
||||
// Zero asserts that i is the zero value for its type.
|
||||
func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
|
||||
return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// NotZero asserts that i is not the zero value for its type and returns the truth.
|
||||
// NotZero asserts that i is not the zero value for its type.
|
||||
func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
|
||||
return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...)
|
||||
}
|
||||
|
@ -1196,6 +1283,9 @@ func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
|
|||
|
||||
// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
|
||||
func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
info, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
|
@ -1211,6 +1301,9 @@ func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
|
|||
|
||||
// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
|
||||
func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
info, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
|
@ -1227,9 +1320,10 @@ func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
|
|||
// JSONEq asserts that two JSON strings are equivalent.
|
||||
//
|
||||
// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
var expectedJSONAsInterface, actualJSONAsInterface interface{}
|
||||
|
||||
if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil {
|
||||
|
@ -1255,7 +1349,7 @@ func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) {
|
|||
}
|
||||
|
||||
// diff returns a diff of both values as long as both are of the same type and
|
||||
// are a struct, map, slice or array. Otherwise it returns an empty string.
|
||||
// are a struct, map, slice, array or string. Otherwise it returns an empty string.
|
||||
func diff(expected interface{}, actual interface{}) string {
|
||||
if expected == nil || actual == nil {
|
||||
return ""
|
||||
|
@ -1268,12 +1362,18 @@ func diff(expected interface{}, actual interface{}) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array {
|
||||
if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String {
|
||||
return ""
|
||||
}
|
||||
|
||||
e := spewConfig.Sdump(expected)
|
||||
a := spewConfig.Sdump(actual)
|
||||
var e, a string
|
||||
if et != reflect.TypeOf("") {
|
||||
e = spewConfig.Sdump(expected)
|
||||
a = spewConfig.Sdump(actual)
|
||||
} else {
|
||||
e = expected.(string)
|
||||
a = actual.(string)
|
||||
}
|
||||
|
||||
diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
|
||||
A: difflib.SplitLines(e),
|
||||
|
@ -1310,3 +1410,7 @@ var spewConfig = spew.ConfigState{
|
|||
DisableCapacities: true,
|
||||
SortKeys: true,
|
||||
}
|
||||
|
||||
type tHelper interface {
|
||||
Helper()
|
||||
}
|
||||
|
|
226
vendor/github.com/stretchr/testify/assert/assertions_test.go
generated
vendored
226
vendor/github.com/stretchr/testify/assert/assertions_test.go
generated
vendored
|
@ -2,6 +2,7 @@ package assert
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
@ -174,6 +175,8 @@ func TestIsType(t *testing.T) {
|
|||
|
||||
}
|
||||
|
||||
type myType string
|
||||
|
||||
func TestEqual(t *testing.T) {
|
||||
|
||||
mockT := new(testing.T)
|
||||
|
@ -199,6 +202,9 @@ func TestEqual(t *testing.T) {
|
|||
if !Equal(mockT, uint64(123), uint64(123)) {
|
||||
t.Error("Equal should return true")
|
||||
}
|
||||
if !Equal(mockT, myType("1"), myType("1")) {
|
||||
t.Error("Equal should return true")
|
||||
}
|
||||
if !Equal(mockT, &struct{}{}, &struct{}{}) {
|
||||
t.Error("Equal should return true (pointer equality is based on equality of underlying value)")
|
||||
}
|
||||
|
@ -206,6 +212,9 @@ func TestEqual(t *testing.T) {
|
|||
if Equal(mockT, m["bar"], "something") {
|
||||
t.Error("Equal should return false")
|
||||
}
|
||||
if Equal(mockT, myType("1"), myType("2")) {
|
||||
t.Error("Equal should return false")
|
||||
}
|
||||
}
|
||||
|
||||
// bufferT implements TestingT. Its implementation of Errorf writes the output that would be produced by
|
||||
|
@ -250,6 +259,21 @@ func (t *bufferT) Errorf(format string, args ...interface{}) {
|
|||
t.buf.WriteString(decorate(fmt.Sprintf(format, args...)))
|
||||
}
|
||||
|
||||
func TestStringEqual(t *testing.T) {
|
||||
for i, currCase := range []struct {
|
||||
equalWant string
|
||||
equalGot string
|
||||
msgAndArgs []interface{}
|
||||
want string
|
||||
}{
|
||||
{equalWant: "hi, \nmy name is", equalGot: "what,\nmy name is", want: "\tassertions.go:\\d+: \n\t+Error Trace:\t\n\t+Error:\\s+Not equal:\\s+\n\\s+expected: \"hi, \\\\nmy name is\"\n\\s+actual\\s+: \"what,\\\\nmy name is\"\n\\s+Diff:\n\\s+-+ Expected\n\\s+\\++ Actual\n\\s+@@ -1,2 \\+1,2 @@\n\\s+-hi, \n\\s+\\+what,\n\\s+my name is"},
|
||||
} {
|
||||
mockT := &bufferT{}
|
||||
Equal(mockT, currCase.equalWant, currCase.equalGot, currCase.msgAndArgs...)
|
||||
Regexp(t, regexp.MustCompile(currCase.want), mockT.buf.String(), "Case %d", i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEqualFormatting(t *testing.T) {
|
||||
for i, currCase := range []struct {
|
||||
equalWant string
|
||||
|
@ -257,8 +281,10 @@ func TestEqualFormatting(t *testing.T) {
|
|||
msgAndArgs []interface{}
|
||||
want string
|
||||
}{
|
||||
{equalWant: "want", equalGot: "got", want: "\tassertions.go:[0-9]+: \r \r\tError Trace:\t\n\t\t\r\tError: \tNot equal: \n\t\t\r\t \texpected: \"want\"\n\t\t\r\t \tactual : \"got\"\n"},
|
||||
{equalWant: "want", equalGot: "got", msgAndArgs: []interface{}{"hello, %v!", "world"}, want: "\tassertions.go:[0-9]+: \r \r\tError Trace:\t\n\t\t\r\tError: \tNot equal: \n\t\t\r\t \texpected: \"want\"\n\t\t\r\t \tactual : \"got\"\n\t\t\r\tMessages: \thello, world!\n"},
|
||||
{equalWant: "want", equalGot: "got", want: "\tassertions.go:\\d+: \n\t+Error Trace:\t\n\t+Error:\\s+Not equal:\\s+\n\\s+expected: \"want\"\n\\s+actual\\s+: \"got\"\n\\s+Diff:\n\\s+-+ Expected\n\\s+\\++ Actual\n\\s+@@ -1 \\+1 @@\n\\s+-want\n\\s+\\+got\n"},
|
||||
{equalWant: "want", equalGot: "got", msgAndArgs: []interface{}{"hello, %v!", "world"}, want: "\tassertions.go:[0-9]+: \n\t+Error Trace:\t\n\t+Error:\\s+Not equal:\\s+\n\\s+expected: \"want\"\n\\s+actual\\s+: \"got\"\n\\s+Diff:\n\\s+-+ Expected\n\\s+\\++ Actual\n\\s+@@ -1 \\+1 @@\n\\s+-want\n\\s+\\+got\n\\s+Messages:\\s+hello, world!\n"},
|
||||
{equalWant: "want", equalGot: "got", msgAndArgs: []interface{}{123}, want: "\tassertions.go:[0-9]+: \n\t+Error Trace:\t\n\t+Error:\\s+Not equal:\\s+\n\\s+expected: \"want\"\n\\s+actual\\s+: \"got\"\n\\s+Diff:\n\\s+-+ Expected\n\\s+\\++ Actual\n\\s+@@ -1 \\+1 @@\n\\s+-want\n\\s+\\+got\n\\s+Messages:\\s+123\n"},
|
||||
{equalWant: "want", equalGot: "got", msgAndArgs: []interface{}{struct{ a string }{"hello"}}, want: "\tassertions.go:[0-9]+: \n\t+Error Trace:\t\n\t+Error:\\s+Not equal:\\s+\n\\s+expected: \"want\"\n\\s+actual\\s+: \"got\"\n\\s+Diff:\n\\s+-+ Expected\n\\s+\\++ Actual\n\\s+@@ -1 \\+1 @@\n\\s+-want\n\\s+\\+got\n\\s+Messages:\\s+{a:hello}\n"},
|
||||
} {
|
||||
mockT := &bufferT{}
|
||||
Equal(mockT, currCase.equalWant, currCase.equalGot, currCase.msgAndArgs...)
|
||||
|
@ -1579,3 +1605,199 @@ func TestEqualArgsValidation(t *testing.T) {
|
|||
err := validateEqualArgs(time.Now, time.Now)
|
||||
EqualError(t, err, "cannot take func type as argument")
|
||||
}
|
||||
|
||||
func ExampleComparisonAssertionFunc() {
|
||||
t := &testing.T{} // provided by test
|
||||
|
||||
adder := func(x, y int) int {
|
||||
return x + y
|
||||
}
|
||||
|
||||
type args struct {
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
expect int
|
||||
assertion ComparisonAssertionFunc
|
||||
}{
|
||||
{"2+2=4", args{2, 2}, 4, Equal},
|
||||
{"2+2!=5", args{2, 2}, 5, NotEqual},
|
||||
{"2+3==5", args{2, 3}, 5, Exactly},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.assertion(t, tt.expect, adder(tt.args.x, tt.args.y))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestComparisonAssertionFunc(t *testing.T) {
|
||||
type iface interface {
|
||||
Name() string
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
expect interface{}
|
||||
got interface{}
|
||||
assertion ComparisonAssertionFunc
|
||||
}{
|
||||
{"implements", (*iface)(nil), t, Implements},
|
||||
{"isType", (*testing.T)(nil), t, IsType},
|
||||
{"equal", t, t, Equal},
|
||||
{"equalValues", t, t, EqualValues},
|
||||
{"exactly", t, t, Exactly},
|
||||
{"notEqual", t, nil, NotEqual},
|
||||
{"notContains", []int{1, 2, 3}, 4, NotContains},
|
||||
{"subset", []int{1, 2, 3, 4}, []int{2, 3}, Subset},
|
||||
{"notSubset", []int{1, 2, 3, 4}, []int{0, 3}, NotSubset},
|
||||
{"elementsMatch", []byte("abc"), []byte("bac"), ElementsMatch},
|
||||
{"regexp", "^t.*y$", "testify", Regexp},
|
||||
{"notRegexp", "^t.*y$", "Testify", NotRegexp},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.assertion(t, tt.expect, tt.got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleValueAssertionFunc() {
|
||||
t := &testing.T{} // provided by test
|
||||
|
||||
dumbParse := func(input string) interface{} {
|
||||
var x interface{}
|
||||
json.Unmarshal([]byte(input), &x)
|
||||
return x
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
arg string
|
||||
assertion ValueAssertionFunc
|
||||
}{
|
||||
{"true is not nil", "true", NotNil},
|
||||
{"empty string is nil", "", Nil},
|
||||
{"zero is not nil", "0", NotNil},
|
||||
{"zero is zero", "0", Zero},
|
||||
{"false is zero", "false", Zero},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.assertion(t, dumbParse(tt.arg))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValueAssertionFunc(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
value interface{}
|
||||
assertion ValueAssertionFunc
|
||||
}{
|
||||
{"notNil", true, NotNil},
|
||||
{"nil", nil, Nil},
|
||||
{"empty", []int{}, Empty},
|
||||
{"notEmpty", []int{1}, NotEmpty},
|
||||
{"zero", false, Zero},
|
||||
{"notZero", 42, NotZero},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.assertion(t, tt.value)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleBoolAssertionFunc() {
|
||||
t := &testing.T{} // provided by test
|
||||
|
||||
isOkay := func(x int) bool {
|
||||
return x >= 42
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
arg int
|
||||
assertion BoolAssertionFunc
|
||||
}{
|
||||
{"-1 is bad", -1, False},
|
||||
{"42 is good", 42, True},
|
||||
{"41 is bad", 41, False},
|
||||
{"45 is cool", 45, True},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.assertion(t, isOkay(tt.arg))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoolAssertionFunc(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
value bool
|
||||
assertion BoolAssertionFunc
|
||||
}{
|
||||
{"true", true, True},
|
||||
{"false", false, False},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.assertion(t, tt.value)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleErrorAssertionFunc() {
|
||||
t := &testing.T{} // provided by test
|
||||
|
||||
dumbParseNum := func(input string, v interface{}) error {
|
||||
return json.Unmarshal([]byte(input), v)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
arg string
|
||||
assertion ErrorAssertionFunc
|
||||
}{
|
||||
{"1.2 is number", "1.2", NoError},
|
||||
{"1.2.3 not number", "1.2.3", Error},
|
||||
{"true is not number", "true", Error},
|
||||
{"3 is number", "3", NoError},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var x float64
|
||||
tt.assertion(t, dumbParseNum(tt.arg, &x))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorAssertionFunc(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
err error
|
||||
assertion ErrorAssertionFunc
|
||||
}{
|
||||
{"noError", nil, NoError},
|
||||
{"error", errors.New("whoops"), Error},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.assertion(t, tt.err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
22
vendor/github.com/stretchr/testify/assert/http_assertions.go
generated
vendored
22
vendor/github.com/stretchr/testify/assert/http_assertions.go
generated
vendored
|
@ -12,10 +12,11 @@ import (
|
|||
// an error if building a new request fails.
|
||||
func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) {
|
||||
w := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
|
||||
req, err := http.NewRequest(method, url, nil)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
req.URL.RawQuery = values.Encode()
|
||||
handler(w, req)
|
||||
return w.Code, nil
|
||||
}
|
||||
|
@ -26,6 +27,9 @@ func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (
|
|||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
code, err := httpCode(handler, method, url, values)
|
||||
if err != nil {
|
||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||
|
@ -46,6 +50,9 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value
|
|||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
code, err := httpCode(handler, method, url, values)
|
||||
if err != nil {
|
||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||
|
@ -66,6 +73,9 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu
|
|||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
code, err := httpCode(handler, method, url, values)
|
||||
if err != nil {
|
||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||
|
@ -95,10 +105,13 @@ func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) s
|
|||
// HTTPBodyContains asserts that a specified handler returns a
|
||||
// body that contains a string.
|
||||
//
|
||||
// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
||||
// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
body := HTTPBody(handler, method, url, values)
|
||||
|
||||
contains := strings.Contains(body, fmt.Sprint(str))
|
||||
|
@ -112,10 +125,13 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string,
|
|||
// HTTPBodyNotContains asserts that a specified handler returns a
|
||||
// body that does not contain a string.
|
||||
//
|
||||
// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
||||
// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
body := HTTPBody(handler, method, url, values)
|
||||
|
||||
contains := strings.Contains(body, fmt.Sprint(str))
|
||||
|
|
29
vendor/github.com/stretchr/testify/assert/http_assertions_test.go
generated
vendored
29
vendor/github.com/stretchr/testify/assert/http_assertions_test.go
generated
vendored
|
@ -89,6 +89,35 @@ func httpHelloName(w http.ResponseWriter, r *http.Request) {
|
|||
w.Write([]byte(fmt.Sprintf("Hello, %s!", name)))
|
||||
}
|
||||
|
||||
func TestHTTPRequestWithNoParams(t *testing.T) {
|
||||
var got *http.Request
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {
|
||||
got = r
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
True(t, HTTPSuccess(t, handler, "GET", "/url", nil))
|
||||
|
||||
Empty(t, got.URL.Query())
|
||||
Equal(t, "/url", got.URL.RequestURI())
|
||||
}
|
||||
|
||||
func TestHTTPRequestWithParams(t *testing.T) {
|
||||
var got *http.Request
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {
|
||||
got = r
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
params := url.Values{}
|
||||
params.Add("id", "12345")
|
||||
|
||||
True(t, HTTPSuccess(t, handler, "GET", "/url", params))
|
||||
|
||||
Equal(t, url.Values{"id": []string{"12345"}}, got.URL.Query())
|
||||
Equal(t, "/url?id=12345", got.URL.String())
|
||||
Equal(t, "/url?id=12345", got.URL.RequestURI())
|
||||
}
|
||||
|
||||
func TestHttpBody(t *testing.T) {
|
||||
assert := New(t)
|
||||
mockT := new(testing.T)
|
||||
|
|
7
vendor/github.com/stretchr/testify/go.mod
generated
vendored
Normal file
7
vendor/github.com/stretchr/testify/go.mod
generated
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
module github.com/stretchr/testify
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.0
|
||||
github.com/pmezard/go-difflib v1.0.0
|
||||
github.com/stretchr/objx v0.1.0
|
||||
)
|
6
vendor/github.com/stretchr/testify/go.sum
generated
vendored
Normal file
6
vendor/github.com/stretchr/testify/go.sum
generated
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
130
vendor/github.com/stretchr/testify/mock/mock.go
generated
vendored
130
vendor/github.com/stretchr/testify/mock/mock.go
generated
vendored
|
@ -42,6 +42,9 @@ type Call struct {
|
|||
// this method is called.
|
||||
ReturnArguments Arguments
|
||||
|
||||
// Holds the caller info for the On() call
|
||||
callerInfo []string
|
||||
|
||||
// The number of times to return the return arguments when setting
|
||||
// expectations. 0 means to always return the value.
|
||||
Repeatability int
|
||||
|
@ -64,12 +67,13 @@ type Call struct {
|
|||
RunFn func(Arguments)
|
||||
}
|
||||
|
||||
func newCall(parent *Mock, methodName string, methodArguments ...interface{}) *Call {
|
||||
func newCall(parent *Mock, methodName string, callerInfo []string, methodArguments ...interface{}) *Call {
|
||||
return &Call{
|
||||
Parent: parent,
|
||||
Method: methodName,
|
||||
Arguments: methodArguments,
|
||||
ReturnArguments: make([]interface{}, 0),
|
||||
callerInfo: callerInfo,
|
||||
Repeatability: 0,
|
||||
WaitFor: nil,
|
||||
RunFn: nil,
|
||||
|
@ -172,6 +176,7 @@ func (c *Call) Maybe() *Call {
|
|||
// Mock.
|
||||
// On("MyMethod", 1).Return(nil).
|
||||
// On("MyOtherMethod", 'a', 'b', 'c').Return(errors.New("Some Error"))
|
||||
//go:noinline
|
||||
func (c *Call) On(methodName string, arguments ...interface{}) *Call {
|
||||
return c.Parent.On(methodName, arguments...)
|
||||
}
|
||||
|
@ -187,6 +192,10 @@ type Mock struct {
|
|||
// Holds the calls that were made to this mocked object.
|
||||
Calls []Call
|
||||
|
||||
// test is An optional variable that holds the test struct, to be used when an
|
||||
// invalid mock call was made.
|
||||
test TestingT
|
||||
|
||||
// TestData holds any data that might be useful for testing. Testify ignores
|
||||
// this data completely allowing you to do whatever you like with it.
|
||||
testData objx.Map
|
||||
|
@ -209,6 +218,27 @@ func (m *Mock) TestData() objx.Map {
|
|||
Setting expectations
|
||||
*/
|
||||
|
||||
// Test sets the test struct variable of the mock object
|
||||
func (m *Mock) Test(t TestingT) {
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
m.test = t
|
||||
}
|
||||
|
||||
// fail fails the current test with the given formatted format and args.
|
||||
// In case that a test was defined, it uses the test APIs for failing a test,
|
||||
// otherwise it uses panic.
|
||||
func (m *Mock) fail(format string, args ...interface{}) {
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
|
||||
if m.test == nil {
|
||||
panic(fmt.Sprintf(format, args...))
|
||||
}
|
||||
m.test.Errorf(format, args...)
|
||||
m.test.FailNow()
|
||||
}
|
||||
|
||||
// On starts a description of an expectation of the specified method
|
||||
// being called.
|
||||
//
|
||||
|
@ -222,7 +252,7 @@ func (m *Mock) On(methodName string, arguments ...interface{}) *Call {
|
|||
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
c := newCall(m, methodName, arguments...)
|
||||
c := newCall(m, methodName, assert.CallerInfo(), arguments...)
|
||||
m.ExpectedCalls = append(m.ExpectedCalls, c)
|
||||
return c
|
||||
}
|
||||
|
@ -245,27 +275,25 @@ func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *
|
|||
return -1, nil
|
||||
}
|
||||
|
||||
func (m *Mock) findClosestCall(method string, arguments ...interface{}) (bool, *Call) {
|
||||
diffCount := 0
|
||||
func (m *Mock) findClosestCall(method string, arguments ...interface{}) (*Call, string) {
|
||||
var diffCount int
|
||||
var closestCall *Call
|
||||
var err string
|
||||
|
||||
for _, call := range m.expectedCalls() {
|
||||
if call.Method == method {
|
||||
|
||||
_, tempDiffCount := call.Arguments.Diff(arguments)
|
||||
errInfo, tempDiffCount := call.Arguments.Diff(arguments)
|
||||
if tempDiffCount < diffCount || diffCount == 0 {
|
||||
diffCount = tempDiffCount
|
||||
closestCall = call
|
||||
err = errInfo
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if closestCall == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, closestCall
|
||||
return closestCall, err
|
||||
}
|
||||
|
||||
func callString(method string, arguments Arguments, includeArgumentValues bool) string {
|
||||
|
@ -312,6 +340,7 @@ func (m *Mock) Called(arguments ...interface{}) Arguments {
|
|||
// If Call.WaitFor is set, blocks until the channel is closed or receives a message.
|
||||
func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Arguments {
|
||||
m.mutex.Lock()
|
||||
//TODO: could combine expected and closes in single loop
|
||||
found, call := m.findExpectedCall(methodName, arguments...)
|
||||
|
||||
if found < 0 {
|
||||
|
@ -322,13 +351,18 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen
|
|||
// b) the arguments are not what was expected, or
|
||||
// c) the developer has forgotten to add an accompanying On...Return pair.
|
||||
|
||||
closestFound, closestCall := m.findClosestCall(methodName, arguments...)
|
||||
closestCall, mismatch := m.findClosestCall(methodName, arguments...)
|
||||
m.mutex.Unlock()
|
||||
|
||||
if closestFound {
|
||||
panic(fmt.Sprintf("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n\n%s\n", callString(methodName, arguments, true), callString(methodName, closestCall.Arguments, true), diffArguments(closestCall.Arguments, arguments)))
|
||||
if closestCall != nil {
|
||||
m.fail("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n\n%s\nDiff: %s",
|
||||
callString(methodName, arguments, true),
|
||||
callString(methodName, closestCall.Arguments, true),
|
||||
diffArguments(closestCall.Arguments, arguments),
|
||||
strings.TrimSpace(mismatch),
|
||||
)
|
||||
} else {
|
||||
panic(fmt.Sprintf("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", methodName, methodName, callString(methodName, arguments, true), assert.CallerInfo()))
|
||||
m.fail("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", methodName, methodName, callString(methodName, arguments, true), assert.CallerInfo())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -340,7 +374,7 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen
|
|||
call.totalCalls++
|
||||
|
||||
// add the call
|
||||
m.Calls = append(m.Calls, *newCall(m, methodName, arguments...))
|
||||
m.Calls = append(m.Calls, *newCall(m, methodName, assert.CallerInfo(), arguments...))
|
||||
m.mutex.Unlock()
|
||||
|
||||
// block if specified
|
||||
|
@ -378,6 +412,9 @@ type assertExpectationser interface {
|
|||
//
|
||||
// Calls may have occurred in any order.
|
||||
func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
for _, obj := range testObjects {
|
||||
if m, ok := obj.(Mock); ok {
|
||||
t.Logf("Deprecated mock.AssertExpectationsForObjects(myMock.Mock) use mock.AssertExpectationsForObjects(myMock)")
|
||||
|
@ -385,6 +422,7 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
|
|||
}
|
||||
m := obj.(assertExpectationser)
|
||||
if !m.AssertExpectations(t) {
|
||||
t.Logf("Expectations didn't match for Mock: %+v", reflect.TypeOf(m))
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -394,6 +432,9 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
|
|||
// AssertExpectations asserts that everything specified with On and Return was
|
||||
// in fact called as expected. Calls may have occurred in any order.
|
||||
func (m *Mock) AssertExpectations(t TestingT) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
var somethingMissing bool
|
||||
|
@ -405,13 +446,14 @@ func (m *Mock) AssertExpectations(t TestingT) bool {
|
|||
if !expectedCall.optional && !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments) && expectedCall.totalCalls == 0 {
|
||||
somethingMissing = true
|
||||
failedExpectations++
|
||||
t.Logf("\u274C\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
|
||||
t.Logf("FAIL:\t%s(%s)\n\t\tat: %s", expectedCall.Method, expectedCall.Arguments.String(), expectedCall.callerInfo)
|
||||
} else {
|
||||
if expectedCall.Repeatability > 0 {
|
||||
somethingMissing = true
|
||||
failedExpectations++
|
||||
t.Logf("FAIL:\t%s(%s)\n\t\tat: %s", expectedCall.Method, expectedCall.Arguments.String(), expectedCall.callerInfo)
|
||||
} else {
|
||||
t.Logf("\u2705\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
|
||||
t.Logf("PASS:\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -425,6 +467,9 @@ func (m *Mock) AssertExpectations(t TestingT) bool {
|
|||
|
||||
// AssertNumberOfCalls asserts that the method was called expectedCalls times.
|
||||
func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls int) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
var actualCalls int
|
||||
|
@ -439,11 +484,22 @@ func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls
|
|||
// AssertCalled asserts that the method was called.
|
||||
// It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method.
|
||||
func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
if !assert.True(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method should have been called with %d argument(s), but was not.", methodName, len(arguments))) {
|
||||
t.Logf("%v", m.expectedCalls())
|
||||
return false
|
||||
if !m.methodWasCalled(methodName, arguments) {
|
||||
var calledWithArgs []string
|
||||
for _, call := range m.calls() {
|
||||
calledWithArgs = append(calledWithArgs, fmt.Sprintf("%v", call.Arguments))
|
||||
}
|
||||
if len(calledWithArgs) == 0 {
|
||||
return assert.Fail(t, "Should have called with given arguments",
|
||||
fmt.Sprintf("Expected %q to have been called with:\n%v\nbut no actual calls happened", methodName, arguments))
|
||||
}
|
||||
return assert.Fail(t, "Should have called with given arguments",
|
||||
fmt.Sprintf("Expected %q to have been called with:\n%v\nbut actual calls were:\n %v", methodName, arguments, strings.Join(calledWithArgs, "\n")))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -451,11 +507,14 @@ func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interfac
|
|||
// AssertNotCalled asserts that the method was not called.
|
||||
// It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method.
|
||||
func (m *Mock) AssertNotCalled(t TestingT, methodName string, arguments ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
if !assert.False(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method was called with %d argument(s), but should NOT have been.", methodName, len(arguments))) {
|
||||
t.Logf("%v", m.expectedCalls())
|
||||
return false
|
||||
if m.methodWasCalled(methodName, arguments) {
|
||||
return assert.Fail(t, "Should not have called with given arguments",
|
||||
fmt.Sprintf("Expected %q to not have been called with:\n%v\nbut actually it was.", methodName, arguments))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -495,7 +554,7 @@ type Arguments []interface{}
|
|||
const (
|
||||
// Anything is used in Diff and Assert when the argument being tested
|
||||
// shouldn't be taken into consideration.
|
||||
Anything string = "mock.Anything"
|
||||
Anything = "mock.Anything"
|
||||
)
|
||||
|
||||
// AnythingOfTypeArgument is a string that contains the type of an argument
|
||||
|
@ -598,6 +657,7 @@ func (args Arguments) Is(objects ...interface{}) bool {
|
|||
//
|
||||
// Returns the diff string and number of differences found.
|
||||
func (args Arguments) Diff(objects []interface{}) (string, int) {
|
||||
//TODO: could return string as error and nil for No difference
|
||||
|
||||
var output = "\n"
|
||||
var differences int
|
||||
|
@ -609,25 +669,30 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
|
|||
|
||||
for i := 0; i < maxArgCount; i++ {
|
||||
var actual, expected interface{}
|
||||
var actualFmt, expectedFmt string
|
||||
|
||||
if len(objects) <= i {
|
||||
actual = "(Missing)"
|
||||
actualFmt = "(Missing)"
|
||||
} else {
|
||||
actual = objects[i]
|
||||
actualFmt = fmt.Sprintf("(%[1]T=%[1]v)", actual)
|
||||
}
|
||||
|
||||
if len(args) <= i {
|
||||
expected = "(Missing)"
|
||||
expectedFmt = "(Missing)"
|
||||
} else {
|
||||
expected = args[i]
|
||||
expectedFmt = fmt.Sprintf("(%[1]T=%[1]v)", expected)
|
||||
}
|
||||
|
||||
if matcher, ok := expected.(argumentMatcher); ok {
|
||||
if matcher.Matches(actual) {
|
||||
output = fmt.Sprintf("%s\t%d: \u2705 %s matched by %s\n", output, i, actual, matcher)
|
||||
output = fmt.Sprintf("%s\t%d: PASS: %s matched by %s\n", output, i, actualFmt, matcher)
|
||||
} else {
|
||||
differences++
|
||||
output = fmt.Sprintf("%s\t%d: \u2705 %s not matched by %s\n", output, i, actual, matcher)
|
||||
output = fmt.Sprintf("%s\t%d: FAIL: %s not matched by %s\n", output, i, actualFmt, matcher)
|
||||
}
|
||||
} else if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() {
|
||||
|
||||
|
@ -635,7 +700,7 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
|
|||
if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) {
|
||||
// not match
|
||||
differences++
|
||||
output = fmt.Sprintf("%s\t%d: \u274C type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actual)
|
||||
output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt)
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -644,11 +709,11 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
|
|||
|
||||
if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) {
|
||||
// match
|
||||
output = fmt.Sprintf("%s\t%d: \u2705 %s == %s\n", output, i, actual, expected)
|
||||
output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt)
|
||||
} else {
|
||||
// not match
|
||||
differences++
|
||||
output = fmt.Sprintf("%s\t%d: \u274C %s != %s\n", output, i, actual, expected)
|
||||
output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -665,6 +730,9 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
|
|||
// Assert compares the arguments with the specified objects and fails if
|
||||
// they do not exactly match.
|
||||
func (args Arguments) Assert(t TestingT, objects ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
// get the differences
|
||||
diff, diffCount := args.Diff(objects)
|
||||
|
@ -812,3 +880,7 @@ var spewConfig = spew.ConfigState{
|
|||
DisableCapacities: true,
|
||||
SortKeys: true,
|
||||
}
|
||||
|
||||
type tHelper interface {
|
||||
Helper()
|
||||
}
|
||||
|
|
169
vendor/github.com/stretchr/testify/mock/mock_test.go
generated
vendored
169
vendor/github.com/stretchr/testify/mock/mock_test.go
generated
vendored
|
@ -3,6 +3,8 @@ package mock
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -30,6 +32,7 @@ func (i *TestExampleImplementation) TheExampleMethod(a, b, c int) (int, error) {
|
|||
return args.Int(0), errors.New("Whoops")
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func (i *TestExampleImplementation) TheExampleMethod2(yesorno bool) {
|
||||
i.Called(yesorno)
|
||||
}
|
||||
|
@ -90,6 +93,34 @@ func (i *TestExampleImplementation) TheExampleMethodFuncType(fn ExampleFuncType)
|
|||
return args.Error(0)
|
||||
}
|
||||
|
||||
// MockTestingT mocks a test struct
|
||||
type MockTestingT struct {
|
||||
logfCount, errorfCount, failNowCount int
|
||||
}
|
||||
|
||||
const mockTestingTFailNowCalled = "FailNow was called"
|
||||
|
||||
func (m *MockTestingT) Logf(string, ...interface{}) {
|
||||
m.logfCount++
|
||||
}
|
||||
|
||||
func (m *MockTestingT) Errorf(string, ...interface{}) {
|
||||
m.errorfCount++
|
||||
}
|
||||
|
||||
// FailNow mocks the FailNow call.
|
||||
// It panics in order to mimic the FailNow behavior in the sense that
|
||||
// the execution stops.
|
||||
// When expecting this method, the call that invokes it should use the following code:
|
||||
//
|
||||
// assert.PanicsWithValue(t, mockTestingTFailNowCalled, func() {...})
|
||||
func (m *MockTestingT) FailNow() {
|
||||
m.failNowCount++
|
||||
|
||||
// this function should panic now to stop the execution as expected
|
||||
panic(mockTestingTFailNowCalled)
|
||||
}
|
||||
|
||||
/*
|
||||
Mock
|
||||
*/
|
||||
|
@ -119,6 +150,8 @@ func Test_Mock_Chained_On(t *testing.T) {
|
|||
// make a test impl object
|
||||
var mockedService = new(TestExampleImplementation)
|
||||
|
||||
// determine our current line number so we can assert the expected calls callerInfo properly
|
||||
_, _, line, _ := runtime.Caller(0)
|
||||
mockedService.
|
||||
On("TheExampleMethod", 1, 2, 3).
|
||||
Return(0).
|
||||
|
@ -126,17 +159,19 @@ func Test_Mock_Chained_On(t *testing.T) {
|
|||
Return(nil)
|
||||
|
||||
expectedCalls := []*Call{
|
||||
&Call{
|
||||
{
|
||||
Parent: &mockedService.Mock,
|
||||
Method: "TheExampleMethod",
|
||||
Arguments: []interface{}{1, 2, 3},
|
||||
ReturnArguments: []interface{}{0},
|
||||
callerInfo: []string{fmt.Sprintf("mock_test.go:%d", line+2)},
|
||||
},
|
||||
&Call{
|
||||
{
|
||||
Parent: &mockedService.Mock,
|
||||
Method: "TheExampleMethod3",
|
||||
Arguments: []interface{}{AnythingOfType("*mock.ExampleType")},
|
||||
ReturnArguments: []interface{}{nil},
|
||||
callerInfo: []string{fmt.Sprintf("mock_test.go:%d", line+4)},
|
||||
},
|
||||
}
|
||||
assert.Equal(t, expectedCalls, mockedService.ExpectedCalls)
|
||||
|
@ -198,6 +233,34 @@ func Test_Mock_On_WithIntArgMatcher(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestMock_WithTest(t *testing.T) {
|
||||
var (
|
||||
mockedService TestExampleImplementation
|
||||
mockedTest MockTestingT
|
||||
)
|
||||
|
||||
mockedService.Test(&mockedTest)
|
||||
mockedService.On("TheExampleMethod", 1, 2, 3).Return(0, nil)
|
||||
|
||||
// Test that on an expected call, the test was not failed
|
||||
|
||||
mockedService.TheExampleMethod(1, 2, 3)
|
||||
|
||||
// Assert that Errorf and FailNow were not called
|
||||
assert.Equal(t, 0, mockedTest.errorfCount)
|
||||
assert.Equal(t, 0, mockedTest.failNowCount)
|
||||
|
||||
// Test that on unexpected call, the mocked test was called to fail the test
|
||||
|
||||
assert.PanicsWithValue(t, mockTestingTFailNowCalled, func() {
|
||||
mockedService.TheExampleMethod(1, 1, 1)
|
||||
})
|
||||
|
||||
// Assert that Errorf and FailNow were called once
|
||||
assert.Equal(t, 1, mockedTest.errorfCount)
|
||||
assert.Equal(t, 1, mockedTest.failNowCount)
|
||||
}
|
||||
|
||||
func Test_Mock_On_WithPtrArgMatcher(t *testing.T) {
|
||||
var mockedService TestExampleImplementation
|
||||
|
||||
|
@ -1125,8 +1188,8 @@ func Test_Arguments_Diff(t *testing.T) {
|
|||
diff, count = args.Diff([]interface{}{"Hello World", 456, "false"})
|
||||
|
||||
assert.Equal(t, 2, count)
|
||||
assert.Contains(t, diff, `%!s(int=456) != %!s(int=123)`)
|
||||
assert.Contains(t, diff, `false != %!s(bool=true)`)
|
||||
assert.Contains(t, diff, `(int=456) != (int=123)`)
|
||||
assert.Contains(t, diff, `(string=false) != (bool=true)`)
|
||||
|
||||
}
|
||||
|
||||
|
@ -1138,7 +1201,7 @@ func Test_Arguments_Diff_DifferentNumberOfArgs(t *testing.T) {
|
|||
diff, count = args.Diff([]interface{}{"string", 456, "false", "extra"})
|
||||
|
||||
assert.Equal(t, 3, count)
|
||||
assert.Contains(t, diff, `extra != (Missing)`)
|
||||
assert.Contains(t, diff, `(string=extra) != (Missing)`)
|
||||
|
||||
}
|
||||
|
||||
|
@ -1180,7 +1243,7 @@ func Test_Arguments_Diff_WithAnythingOfTypeArgument_Failing(t *testing.T) {
|
|||
diff, count = args.Diff([]interface{}{"string", 123, true})
|
||||
|
||||
assert.Equal(t, 1, count)
|
||||
assert.Contains(t, diff, `string != type int - %!s(int=123)`)
|
||||
assert.Contains(t, diff, `string != type int - (int=123)`)
|
||||
|
||||
}
|
||||
|
||||
|
@ -1192,14 +1255,14 @@ func Test_Arguments_Diff_WithArgMatcher(t *testing.T) {
|
|||
|
||||
diff, count := args.Diff([]interface{}{"string", 124, true})
|
||||
assert.Equal(t, 1, count)
|
||||
assert.Contains(t, diff, `%!s(int=124) not matched by func(int) bool`)
|
||||
assert.Contains(t, diff, `(int=124) not matched by func(int) bool`)
|
||||
|
||||
diff, count = args.Diff([]interface{}{"string", false, true})
|
||||
assert.Equal(t, 1, count)
|
||||
assert.Contains(t, diff, `%!s(bool=false) not matched by func(int) bool`)
|
||||
assert.Contains(t, diff, `(bool=false) not matched by func(int) bool`)
|
||||
|
||||
diff, count = args.Diff([]interface{}{"string", 123, false})
|
||||
assert.Contains(t, diff, `%!s(int=123) matched by func(int) bool`)
|
||||
assert.Contains(t, diff, `(int=123) matched by func(int) bool`)
|
||||
|
||||
diff, count = args.Diff([]interface{}{"string", 123, true})
|
||||
assert.Equal(t, 0, count)
|
||||
|
@ -1260,7 +1323,7 @@ func Test_Arguments_Bool(t *testing.T) {
|
|||
func Test_WaitUntil_Parallel(t *testing.T) {
|
||||
|
||||
// make a test impl object
|
||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
||||
var mockedService = new(TestExampleImplementation)
|
||||
|
||||
ch1 := make(chan time.Time)
|
||||
ch2 := make(chan time.Time)
|
||||
|
@ -1323,6 +1386,37 @@ func (s *timer) GetTime(i int) string {
|
|||
return s.Called(i).Get(0).(string)
|
||||
}
|
||||
|
||||
type tCustomLogger struct {
|
||||
*testing.T
|
||||
logs []string
|
||||
errs []string
|
||||
}
|
||||
|
||||
func (tc *tCustomLogger) Logf(format string, args ...interface{}) {
|
||||
tc.T.Logf(format, args...)
|
||||
tc.logs = append(tc.logs, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (tc *tCustomLogger) Errorf(format string, args ...interface{}) {
|
||||
tc.errs = append(tc.errs, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (tc *tCustomLogger) FailNow() {}
|
||||
|
||||
func TestLoggingAssertExpectations(t *testing.T) {
|
||||
m := new(timer)
|
||||
m.On("GetTime", 0).Return("")
|
||||
tcl := &tCustomLogger{t, []string{}, []string{}}
|
||||
|
||||
AssertExpectationsForObjects(tcl, m, new(TestExampleImplementation))
|
||||
|
||||
require.Equal(t, 1, len(tcl.errs))
|
||||
assert.Regexp(t, regexp.MustCompile("(?s)FAIL: 0 out of 1 expectation\\(s\\) were met.*The code you are testing needs to make 1 more call\\(s\\).*"), tcl.errs[0])
|
||||
require.Equal(t, 2, len(tcl.logs))
|
||||
assert.Regexp(t, regexp.MustCompile("(?s)FAIL:\tGetTime\\(int\\).*"), tcl.logs[0])
|
||||
require.Equal(t, "Expectations didn't match for Mock: *mock.timer", tcl.logs[1])
|
||||
}
|
||||
|
||||
func TestAfterTotalWaitTimeWhileExecution(t *testing.T) {
|
||||
waitDuration := 1
|
||||
total, waitMs := 5, time.Millisecond*time.Duration(waitDuration)
|
||||
|
@ -1342,11 +1436,64 @@ func TestAfterTotalWaitTimeWhileExecution(t *testing.T) {
|
|||
elapsedTime := end.Sub(start)
|
||||
assert.True(t, elapsedTime > waitMs, fmt.Sprintf("Total elapsed time:%v should be atleast greater than %v", elapsedTime, waitMs))
|
||||
assert.Equal(t, total, len(results))
|
||||
for i, _ := range results {
|
||||
for i := range results {
|
||||
assert.Equal(t, fmt.Sprintf("Time%d", i), results[i], "Return value of method should be same")
|
||||
}
|
||||
}
|
||||
|
||||
func TestArgumentMatcherToPrintMismatch(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
matchingExp := regexp.MustCompile(
|
||||
`\s+mock: Unexpected Method Call\s+-*\s+GetTime\(int\)\s+0: 1\s+The closest call I have is:\s+GetTime\(mock.argumentMatcher\)\s+0: mock.argumentMatcher\{.*?\}\s+Diff:.*\(int=1\) not matched by func\(int\) bool`)
|
||||
assert.Regexp(t, matchingExp, r)
|
||||
}
|
||||
}()
|
||||
|
||||
m := new(timer)
|
||||
m.On("GetTime", MatchedBy(func(i int) bool { return false })).Return("SomeTime").Once()
|
||||
|
||||
res := m.GetTime(1)
|
||||
require.Equal(t, "SomeTime", res)
|
||||
m.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestClosestCallMismatchedArgumentInformationShowsTheClosest(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
matchingExp := regexp.MustCompile(unexpectedCallRegex(`TheExampleMethod(int,int,int)`, `0: 1\s+1: 1\s+2: 2`, `0: 1\s+1: 1\s+2: 1`, `0: PASS: \(int=1\) == \(int=1\)\s+1: PASS: \(int=1\) == \(int=1\)\s+2: FAIL: \(int=2\) != \(int=1\)`))
|
||||
assert.Regexp(t, matchingExp, r)
|
||||
}
|
||||
}()
|
||||
|
||||
m := new(TestExampleImplementation)
|
||||
m.On("TheExampleMethod", 1, 1, 1).Return(1, nil).Once()
|
||||
m.On("TheExampleMethod", 2, 2, 2).Return(2, nil).Once()
|
||||
|
||||
m.TheExampleMethod(1, 1, 2)
|
||||
}
|
||||
|
||||
func TestClosestCallMismatchedArgumentValueInformation(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
matchingExp := regexp.MustCompile(unexpectedCallRegex(`GetTime(int)`, "0: 1", "0: 999", `0: FAIL: \(int=1\) != \(int=999\)`))
|
||||
assert.Regexp(t, matchingExp, r)
|
||||
}
|
||||
}()
|
||||
|
||||
m := new(timer)
|
||||
m.On("GetTime", 999).Return("SomeTime").Once()
|
||||
|
||||
_ = m.GetTime(1)
|
||||
}
|
||||
|
||||
func unexpectedCallRegex(method, calledArg, expectedArg, diff string) string {
|
||||
rMethod := regexp.QuoteMeta(method)
|
||||
return fmt.Sprintf(`\s+mock: Unexpected Method Call\s+-*\s+%s\s+%s\s+The closest call I have is:\s+%s\s+%s\s+Diff: %s`,
|
||||
rMethod, calledArg, rMethod, expectedArg, diff)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func ConcurrencyTestMethod(m *Mock) {
|
||||
m.Called()
|
||||
}
|
||||
|
|
852
vendor/github.com/stretchr/testify/require/require.go
generated
vendored
852
vendor/github.com/stretchr/testify/require/require.go
generated
vendored
File diff suppressed because it is too large
Load diff
6
vendor/github.com/stretchr/testify/require/require.go.tmpl
generated
vendored
6
vendor/github.com/stretchr/testify/require/require.go.tmpl
generated
vendored
|
@ -1,6 +1,6 @@
|
|||
{{.Comment}}
|
||||
func {{.DocInfo.Name}}(t TestingT, {{.Params}}) {
|
||||
if !assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) {
|
||||
t.FailNow()
|
||||
}
|
||||
if assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { return }
|
||||
if h, ok := t.(tHelper); ok { h.Helper() }
|
||||
t.FailNow()
|
||||
}
|
||||
|
|
402
vendor/github.com/stretchr/testify/require/require_forward.go
generated
vendored
402
vendor/github.com/stretchr/testify/require/require_forward.go
generated
vendored
|
@ -14,11 +14,17 @@ import (
|
|||
|
||||
// Condition uses a Comparison to assert a complex condition.
|
||||
func (a *Assertions) Condition(comp assert.Comparison, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Condition(a.t, comp, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Conditionf uses a Comparison to assert a complex condition.
|
||||
func (a *Assertions) Conditionf(comp assert.Comparison, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Conditionf(a.t, comp, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -28,9 +34,10 @@ func (a *Assertions) Conditionf(comp assert.Comparison, msg string, args ...inte
|
|||
// a.Contains("Hello World", "World")
|
||||
// a.Contains(["Hello", "World"], "World")
|
||||
// a.Contains({"Hello": "World"}, "Hello")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Contains(a.t, s, contains, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -40,19 +47,26 @@ func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ..
|
|||
// a.Containsf("Hello World", "World", "error message %s", "formatted")
|
||||
// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted")
|
||||
// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Containsf(a.t, s, contains, msg, args...)
|
||||
}
|
||||
|
||||
// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
|
||||
func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
DirExists(a.t, path, msgAndArgs...)
|
||||
}
|
||||
|
||||
// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
|
||||
func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
DirExistsf(a.t, path, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -60,10 +74,11 @@ func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) {
|
|||
// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
|
||||
// the number of appearances of each of them in both lists should match.
|
||||
//
|
||||
// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2])
|
||||
func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
ElementsMatch(a.t, listA, listB, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -71,10 +86,11 @@ func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndA
|
|||
// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
|
||||
// the number of appearances of each of them in both lists should match.
|
||||
//
|
||||
// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted"))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
|
||||
func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
ElementsMatchf(a.t, listA, listB, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -82,9 +98,10 @@ func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg st
|
|||
// a slice or a channel with len == 0.
|
||||
//
|
||||
// a.Empty(obj)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Empty(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -92,9 +109,10 @@ func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) {
|
|||
// a slice or a channel with len == 0.
|
||||
//
|
||||
// a.Emptyf(obj, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Emptyf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -102,12 +120,13 @@ func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{})
|
|||
//
|
||||
// a.Equal(123, 123)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
//
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses). Function equality
|
||||
// cannot be determined and will always fail.
|
||||
func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Equal(a.t, expected, actual, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -116,9 +135,10 @@ func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs
|
|||
//
|
||||
// actualObj, err := SomeFunction()
|
||||
// a.EqualError(err, expectedErrorString)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
EqualError(a.t, theError, errString, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -127,9 +147,10 @@ func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...
|
|||
//
|
||||
// actualObj, err := SomeFunction()
|
||||
// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
EqualErrorf(a.t, theError, errString, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -137,9 +158,10 @@ func (a *Assertions) EqualErrorf(theError error, errString string, msg string, a
|
|||
// and equal.
|
||||
//
|
||||
// a.EqualValues(uint32(123), int32(123))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
EqualValues(a.t, expected, actual, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -147,9 +169,10 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn
|
|||
// and equal.
|
||||
//
|
||||
// a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
EqualValuesf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -157,12 +180,13 @@ func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg
|
|||
//
|
||||
// a.Equalf(123, 123, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
//
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses). Function equality
|
||||
// cannot be determined and will always fail.
|
||||
func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Equalf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -172,9 +196,10 @@ func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string
|
|||
// if a.Error(err) {
|
||||
// assert.Equal(t, expectedError, err)
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Error(err error, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Error(a.t, err, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -184,115 +209,150 @@ func (a *Assertions) Error(err error, msgAndArgs ...interface{}) {
|
|||
// if a.Errorf(err, "error message %s", "formatted") {
|
||||
// assert.Equal(t, expectedErrorf, err)
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Errorf(err error, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Errorf(a.t, err, msg, args...)
|
||||
}
|
||||
|
||||
// Exactly asserts that two objects are equal in value and type.
|
||||
//
|
||||
// a.Exactly(int32(123), int64(123))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Exactly(a.t, expected, actual, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Exactlyf asserts that two objects are equal in value and type.
|
||||
//
|
||||
// a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Exactlyf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
// Fail reports a failure through
|
||||
func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Fail(a.t, failureMessage, msgAndArgs...)
|
||||
}
|
||||
|
||||
// FailNow fails test
|
||||
func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
FailNow(a.t, failureMessage, msgAndArgs...)
|
||||
}
|
||||
|
||||
// FailNowf fails test
|
||||
func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
FailNowf(a.t, failureMessage, msg, args...)
|
||||
}
|
||||
|
||||
// Failf reports a failure through
|
||||
func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Failf(a.t, failureMessage, msg, args...)
|
||||
}
|
||||
|
||||
// False asserts that the specified value is false.
|
||||
//
|
||||
// a.False(myBool)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) False(value bool, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
False(a.t, value, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Falsef asserts that the specified value is false.
|
||||
//
|
||||
// a.Falsef(myBool, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Falsef(a.t, value, msg, args...)
|
||||
}
|
||||
|
||||
// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
|
||||
func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
FileExists(a.t, path, msgAndArgs...)
|
||||
}
|
||||
|
||||
// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
|
||||
func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
FileExistsf(a.t, path, msg, args...)
|
||||
}
|
||||
|
||||
// HTTPBodyContains asserts that a specified handler returns a
|
||||
// body that contains a string.
|
||||
//
|
||||
// a.HTTPBodyContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
||||
// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...)
|
||||
}
|
||||
|
||||
// HTTPBodyContainsf asserts that a specified handler returns a
|
||||
// body that contains a string.
|
||||
//
|
||||
// a.HTTPBodyContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...)
|
||||
}
|
||||
|
||||
// HTTPBodyNotContains asserts that a specified handler returns a
|
||||
// body that does not contain a string.
|
||||
//
|
||||
// a.HTTPBodyNotContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
||||
// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...)
|
||||
}
|
||||
|
||||
// HTTPBodyNotContainsf asserts that a specified handler returns a
|
||||
// body that does not contain a string.
|
||||
//
|
||||
// a.HTTPBodyNotContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -302,6 +362,9 @@ func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method strin
|
|||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
HTTPError(a.t, handler, method, url, values, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -311,6 +374,9 @@ func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url stri
|
|||
//
|
||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
||||
func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
HTTPErrorf(a.t, handler, method, url, values, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -320,6 +386,9 @@ func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url str
|
|||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -329,6 +398,9 @@ func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url s
|
|||
//
|
||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
||||
func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
HTTPRedirectf(a.t, handler, method, url, values, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -338,6 +410,9 @@ func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url
|
|||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -347,6 +422,9 @@ func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url st
|
|||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
HTTPSuccessf(a.t, handler, method, url, values, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -354,6 +432,9 @@ func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url s
|
|||
//
|
||||
// a.Implements((*MyInterface)(nil), new(MyObject))
|
||||
func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Implements(a.t, interfaceObject, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -361,96 +442,129 @@ func (a *Assertions) Implements(interfaceObject interface{}, object interface{},
|
|||
//
|
||||
// a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject))
|
||||
func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Implementsf(a.t, interfaceObject, object, msg, args...)
|
||||
}
|
||||
|
||||
// InDelta asserts that the two numerals are within delta of each other.
|
||||
//
|
||||
// a.InDelta(math.Pi, (22 / 7.0), 0.01)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
InDelta(a.t, expected, actual, delta, msgAndArgs...)
|
||||
}
|
||||
|
||||
// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
|
||||
func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...)
|
||||
}
|
||||
|
||||
// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
|
||||
func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...)
|
||||
}
|
||||
|
||||
// InDeltaSlice is the same as InDelta, except it compares two slices.
|
||||
func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...)
|
||||
}
|
||||
|
||||
// InDeltaSlicef is the same as InDelta, except it compares two slices.
|
||||
func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
InDeltaSlicef(a.t, expected, actual, delta, msg, args...)
|
||||
}
|
||||
|
||||
// InDeltaf asserts that the two numerals are within delta of each other.
|
||||
//
|
||||
// a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
InDeltaf(a.t, expected, actual, delta, msg, args...)
|
||||
}
|
||||
|
||||
// InEpsilon asserts that expected and actual have a relative error less than epsilon
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...)
|
||||
}
|
||||
|
||||
// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
|
||||
func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...)
|
||||
}
|
||||
|
||||
// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
|
||||
func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...)
|
||||
}
|
||||
|
||||
// InEpsilonf asserts that expected and actual have a relative error less than epsilon
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
InEpsilonf(a.t, expected, actual, epsilon, msg, args...)
|
||||
}
|
||||
|
||||
// IsType asserts that the specified objects are of the same type.
|
||||
func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
IsType(a.t, expectedType, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
// IsTypef asserts that the specified objects are of the same type.
|
||||
func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
IsTypef(a.t, expectedType, object, msg, args...)
|
||||
}
|
||||
|
||||
// JSONEq asserts that two JSON strings are equivalent.
|
||||
//
|
||||
// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
JSONEq(a.t, expected, actual, msgAndArgs...)
|
||||
}
|
||||
|
||||
// JSONEqf asserts that two JSON strings are equivalent.
|
||||
//
|
||||
// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
JSONEqf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -458,9 +572,10 @@ func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ..
|
|||
// Len also fails if the object has a type that len() not accept.
|
||||
//
|
||||
// a.Len(mySlice, 3)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Len(a.t, object, length, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -468,27 +583,30 @@ func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface
|
|||
// Lenf also fails if the object has a type that len() not accept.
|
||||
//
|
||||
// a.Lenf(mySlice, 3, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Lenf(a.t, object, length, msg, args...)
|
||||
}
|
||||
|
||||
// Nil asserts that the specified object is nil.
|
||||
//
|
||||
// a.Nil(err)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Nil(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Nilf asserts that the specified object is nil.
|
||||
//
|
||||
// a.Nilf(err, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Nilf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -498,9 +616,10 @@ func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) {
|
|||
// if a.NoError(err) {
|
||||
// assert.Equal(t, expectedObj, actualObj)
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NoError(a.t, err, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -510,9 +629,10 @@ func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) {
|
|||
// if a.NoErrorf(err, "error message %s", "formatted") {
|
||||
// assert.Equal(t, expectedObj, actualObj)
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NoErrorf(a.t, err, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -522,9 +642,10 @@ func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) {
|
|||
// a.NotContains("Hello World", "Earth")
|
||||
// a.NotContains(["Hello", "World"], "Earth")
|
||||
// a.NotContains({"Hello": "World"}, "Earth")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotContains(a.t, s, contains, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -534,9 +655,10 @@ func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs
|
|||
// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted")
|
||||
// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted")
|
||||
// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotContainsf(a.t, s, contains, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -546,9 +668,10 @@ func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg strin
|
|||
// if a.NotEmpty(obj) {
|
||||
// assert.Equal(t, "two", obj[1])
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotEmpty(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -558,9 +681,10 @@ func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) {
|
|||
// if a.NotEmptyf(obj, "error message %s", "formatted") {
|
||||
// assert.Equal(t, "two", obj[1])
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotEmptyf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -568,11 +692,12 @@ func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface
|
|||
//
|
||||
// a.NotEqual(obj1, obj2)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
//
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses).
|
||||
func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotEqual(a.t, expected, actual, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -580,47 +705,52 @@ func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndAr
|
|||
//
|
||||
// a.NotEqualf(obj1, obj2, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
//
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses).
|
||||
func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotEqualf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
// NotNil asserts that the specified object is not nil.
|
||||
//
|
||||
// a.NotNil(err)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotNil(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
// NotNilf asserts that the specified object is not nil.
|
||||
//
|
||||
// a.NotNilf(err, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotNilf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
|
||||
//
|
||||
// a.NotPanics(func(){ RemainCalm() })
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotPanics(f assert.PanicTestFunc, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotPanics(a.t, f, msgAndArgs...)
|
||||
}
|
||||
|
||||
// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
|
||||
//
|
||||
// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotPanicsf(f assert.PanicTestFunc, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotPanicsf(a.t, f, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -628,9 +758,10 @@ func (a *Assertions) NotPanicsf(f assert.PanicTestFunc, msg string, args ...inte
|
|||
//
|
||||
// a.NotRegexp(regexp.MustCompile("starts"), "it's starting")
|
||||
// a.NotRegexp("^start", "it's not starting")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotRegexp(a.t, rx, str, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -638,9 +769,10 @@ func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...in
|
|||
//
|
||||
// a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting")
|
||||
// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotRegexpf(a.t, rx, str, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -648,9 +780,10 @@ func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, arg
|
|||
// elements given in the specified subset(array, slice...).
|
||||
//
|
||||
// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotSubset(a.t, list, subset, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -658,28 +791,36 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs
|
|||
// elements given in the specified subset(array, slice...).
|
||||
//
|
||||
// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotSubsetf(a.t, list, subset, msg, args...)
|
||||
}
|
||||
|
||||
// NotZero asserts that i is not the zero value for its type and returns the truth.
|
||||
// NotZero asserts that i is not the zero value for its type.
|
||||
func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotZero(a.t, i, msgAndArgs...)
|
||||
}
|
||||
|
||||
// NotZerof asserts that i is not the zero value for its type and returns the truth.
|
||||
// NotZerof asserts that i is not the zero value for its type.
|
||||
func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotZerof(a.t, i, msg, args...)
|
||||
}
|
||||
|
||||
// Panics asserts that the code inside the specified PanicTestFunc panics.
|
||||
//
|
||||
// a.Panics(func(){ GoCrazy() })
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Panics(a.t, f, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -687,9 +828,10 @@ func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) {
|
|||
// the recovered panic value equals the expected panic value.
|
||||
//
|
||||
// a.PanicsWithValue("crazy error", func(){ GoCrazy() })
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) PanicsWithValue(expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
PanicsWithValue(a.t, expected, f, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -697,18 +839,20 @@ func (a *Assertions) PanicsWithValue(expected interface{}, f assert.PanicTestFun
|
|||
// the recovered panic value equals the expected panic value.
|
||||
//
|
||||
// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) PanicsWithValuef(expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
PanicsWithValuef(a.t, expected, f, msg, args...)
|
||||
}
|
||||
|
||||
// Panicsf asserts that the code inside the specified PanicTestFunc panics.
|
||||
//
|
||||
// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Panicsf(a.t, f, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -716,9 +860,10 @@ func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interfa
|
|||
//
|
||||
// a.Regexp(regexp.MustCompile("start"), "it's starting")
|
||||
// a.Regexp("start...$", "it's not starting")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Regexp(a.t, rx, str, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -726,9 +871,10 @@ func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...inter
|
|||
//
|
||||
// a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting")
|
||||
// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Regexpf(a.t, rx, str, msg, args...)
|
||||
}
|
||||
|
||||
|
@ -736,9 +882,10 @@ func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args .
|
|||
// elements given in the specified subset(array, slice...).
|
||||
//
|
||||
// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Subset(a.t, list, subset, msgAndArgs...)
|
||||
}
|
||||
|
||||
|
@ -746,54 +893,65 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...
|
|||
// elements given in the specified subset(array, slice...).
|
||||
//
|
||||
// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Subsetf(a.t, list, subset, msg, args...)
|
||||
}
|
||||
|
||||
// True asserts that the specified value is true.
|
||||
//
|
||||
// a.True(myBool)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) True(value bool, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
True(a.t, value, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Truef asserts that the specified value is true.
|
||||
//
|
||||
// a.Truef(myBool, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) Truef(value bool, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Truef(a.t, value, msg, args...)
|
||||
}
|
||||
|
||||
// WithinDuration asserts that the two times are within duration delta of each other.
|
||||
//
|
||||
// a.WithinDuration(time.Now(), time.Now(), 10*time.Second)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
|
||||
}
|
||||
|
||||
// WithinDurationf asserts that the two times are within duration delta of each other.
|
||||
//
|
||||
// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
WithinDurationf(a.t, expected, actual, delta, msg, args...)
|
||||
}
|
||||
|
||||
// Zero asserts that i is the zero value for its type and returns the truth.
|
||||
// Zero asserts that i is the zero value for its type.
|
||||
func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Zero(a.t, i, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Zerof asserts that i is the zero value for its type and returns the truth.
|
||||
// Zerof asserts that i is the zero value for its type.
|
||||
func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Zerof(a.t, i, msg, args...)
|
||||
}
|
||||
|
|
1
vendor/github.com/stretchr/testify/require/require_forward.go.tmpl
generated
vendored
1
vendor/github.com/stretchr/testify/require/require_forward.go.tmpl
generated
vendored
|
@ -1,4 +1,5 @@
|
|||
{{.CommentWithoutT "a"}}
|
||||
func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) {
|
||||
if h, ok := a.t.(tHelper); ok { h.Helper() }
|
||||
{{.DocInfo.Name}}(a.t, {{.ForwardedParams}})
|
||||
}
|
||||
|
|
20
vendor/github.com/stretchr/testify/require/requirements.go
generated
vendored
20
vendor/github.com/stretchr/testify/require/requirements.go
generated
vendored
|
@ -6,4 +6,24 @@ type TestingT interface {
|
|||
FailNow()
|
||||
}
|
||||
|
||||
type tHelper interface {
|
||||
Helper()
|
||||
}
|
||||
|
||||
// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful
|
||||
// for table driven tests.
|
||||
type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{})
|
||||
|
||||
// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful
|
||||
// for table driven tests.
|
||||
type ValueAssertionFunc func(TestingT, interface{}, ...interface{})
|
||||
|
||||
// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful
|
||||
// for table driven tests.
|
||||
type BoolAssertionFunc func(TestingT, bool, ...interface{})
|
||||
|
||||
// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful
|
||||
// for table driven tests.
|
||||
type ErrorAssertionFunc func(TestingT, error, ...interface{})
|
||||
|
||||
//go:generate go run ../_codegen/main.go -output-package=require -template=require.go.tmpl -include-format-funcs
|
||||
|
|
197
vendor/github.com/stretchr/testify/require/requirements_test.go
generated
vendored
197
vendor/github.com/stretchr/testify/require/requirements_test.go
generated
vendored
|
@ -1,6 +1,7 @@
|
|||
package require
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -367,3 +368,199 @@ func TestJSONEq_ArraysOfDifferentOrder(t *testing.T) {
|
|||
t.Error("Check should fail")
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleComparisonAssertionFunc() {
|
||||
t := &testing.T{} // provided by test
|
||||
|
||||
adder := func(x, y int) int {
|
||||
return x + y
|
||||
}
|
||||
|
||||
type args struct {
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
expect int
|
||||
assertion ComparisonAssertionFunc
|
||||
}{
|
||||
{"2+2=4", args{2, 2}, 4, Equal},
|
||||
{"2+2!=5", args{2, 2}, 5, NotEqual},
|
||||
{"2+3==5", args{2, 3}, 5, Exactly},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.assertion(t, tt.expect, adder(tt.args.x, tt.args.y))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestComparisonAssertionFunc(t *testing.T) {
|
||||
type iface interface {
|
||||
Name() string
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
expect interface{}
|
||||
got interface{}
|
||||
assertion ComparisonAssertionFunc
|
||||
}{
|
||||
{"implements", (*iface)(nil), t, Implements},
|
||||
{"isType", (*testing.T)(nil), t, IsType},
|
||||
{"equal", t, t, Equal},
|
||||
{"equalValues", t, t, EqualValues},
|
||||
{"exactly", t, t, Exactly},
|
||||
{"notEqual", t, nil, NotEqual},
|
||||
{"notContains", []int{1, 2, 3}, 4, NotContains},
|
||||
{"subset", []int{1, 2, 3, 4}, []int{2, 3}, Subset},
|
||||
{"notSubset", []int{1, 2, 3, 4}, []int{0, 3}, NotSubset},
|
||||
{"elementsMatch", []byte("abc"), []byte("bac"), ElementsMatch},
|
||||
{"regexp", "^t.*y$", "testify", Regexp},
|
||||
{"notRegexp", "^t.*y$", "Testify", NotRegexp},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.assertion(t, tt.expect, tt.got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleValueAssertionFunc() {
|
||||
t := &testing.T{} // provided by test
|
||||
|
||||
dumbParse := func(input string) interface{} {
|
||||
var x interface{}
|
||||
json.Unmarshal([]byte(input), &x)
|
||||
return x
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
arg string
|
||||
assertion ValueAssertionFunc
|
||||
}{
|
||||
{"true is not nil", "true", NotNil},
|
||||
{"empty string is nil", "", Nil},
|
||||
{"zero is not nil", "0", NotNil},
|
||||
{"zero is zero", "0", Zero},
|
||||
{"false is zero", "false", Zero},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.assertion(t, dumbParse(tt.arg))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValueAssertionFunc(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
value interface{}
|
||||
assertion ValueAssertionFunc
|
||||
}{
|
||||
{"notNil", true, NotNil},
|
||||
{"nil", nil, Nil},
|
||||
{"empty", []int{}, Empty},
|
||||
{"notEmpty", []int{1}, NotEmpty},
|
||||
{"zero", false, Zero},
|
||||
{"notZero", 42, NotZero},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.assertion(t, tt.value)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleBoolAssertionFunc() {
|
||||
t := &testing.T{} // provided by test
|
||||
|
||||
isOkay := func(x int) bool {
|
||||
return x >= 42
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
arg int
|
||||
assertion BoolAssertionFunc
|
||||
}{
|
||||
{"-1 is bad", -1, False},
|
||||
{"42 is good", 42, True},
|
||||
{"41 is bad", 41, False},
|
||||
{"45 is cool", 45, True},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.assertion(t, isOkay(tt.arg))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoolAssertionFunc(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
value bool
|
||||
assertion BoolAssertionFunc
|
||||
}{
|
||||
{"true", true, True},
|
||||
{"false", false, False},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.assertion(t, tt.value)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleErrorAssertionFunc() {
|
||||
t := &testing.T{} // provided by test
|
||||
|
||||
dumbParseNum := func(input string, v interface{}) error {
|
||||
return json.Unmarshal([]byte(input), v)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
arg string
|
||||
assertion ErrorAssertionFunc
|
||||
}{
|
||||
{"1.2 is number", "1.2", NoError},
|
||||
{"1.2.3 not number", "1.2.3", Error},
|
||||
{"true is not number", "true", Error},
|
||||
{"3 is number", "3", NoError},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var x float64
|
||||
tt.assertion(t, dumbParseNum(tt.arg, &x))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorAssertionFunc(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
err error
|
||||
assertion ErrorAssertionFunc
|
||||
}{
|
||||
{"noError", nil, NoError},
|
||||
{"error", errors.New("whoops"), Error},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.assertion(t, tt.err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
24
vendor/github.com/stretchr/testify/suite/suite.go
generated
vendored
24
vendor/github.com/stretchr/testify/suite/suite.go
generated
vendored
|
@ -55,10 +55,32 @@ func (suite *Suite) Assert() *assert.Assertions {
|
|||
return suite.Assertions
|
||||
}
|
||||
|
||||
func failOnPanic(t *testing.T) {
|
||||
r := recover()
|
||||
if r != nil {
|
||||
t.Errorf("test panicked: %v", r)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
// Run provides suite functionality around golang subtests. It should be
|
||||
// called in place of t.Run(name, func(t *testing.T)) in test suite code.
|
||||
// The passed-in func will be executed as a subtest with a fresh instance of t.
|
||||
// Provides compatibility with go test pkg -run TestSuite/TestName/SubTestName.
|
||||
func (suite *Suite) Run(name string, subtest func()) bool {
|
||||
oldT := suite.T()
|
||||
defer suite.SetT(oldT)
|
||||
return oldT.Run(name, func(t *testing.T) {
|
||||
suite.SetT(t)
|
||||
subtest()
|
||||
})
|
||||
}
|
||||
|
||||
// Run takes a testing suite and runs all of the tests attached
|
||||
// to it.
|
||||
func Run(t *testing.T, suite TestingSuite) {
|
||||
suite.SetT(t)
|
||||
defer failOnPanic(t)
|
||||
|
||||
if setupAllSuite, ok := suite.(SetupAllSuite); ok {
|
||||
setupAllSuite.SetupSuite()
|
||||
|
@ -84,6 +106,8 @@ func Run(t *testing.T, suite TestingSuite) {
|
|||
F: func(t *testing.T) {
|
||||
parentT := suite.T()
|
||||
suite.SetT(t)
|
||||
defer failOnPanic(t)
|
||||
|
||||
if setupTestSuite, ok := suite.(SetupTestSuite); ok {
|
||||
setupTestSuite.SetupTest()
|
||||
}
|
||||
|
|
134
vendor/github.com/stretchr/testify/suite/suite_test.go
generated
vendored
134
vendor/github.com/stretchr/testify/suite/suite_test.go
generated
vendored
|
@ -42,6 +42,99 @@ func (s *SuiteRequireTwice) TestRequireTwo() {
|
|||
r.Equal(1, 2)
|
||||
}
|
||||
|
||||
type panickingSuite struct {
|
||||
Suite
|
||||
panicInSetupSuite bool
|
||||
panicInSetupTest bool
|
||||
panicInBeforeTest bool
|
||||
panicInTest bool
|
||||
panicInAfterTest bool
|
||||
panicInTearDownTest bool
|
||||
panicInTearDownSuite bool
|
||||
}
|
||||
|
||||
func (s *panickingSuite) SetupSuite() {
|
||||
if s.panicInSetupSuite {
|
||||
panic("oops in setup suite")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *panickingSuite) SetupTest() {
|
||||
if s.panicInSetupTest {
|
||||
panic("oops in setup test")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *panickingSuite) BeforeTest(_, _ string) {
|
||||
if s.panicInBeforeTest {
|
||||
panic("oops in before test")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *panickingSuite) Test() {
|
||||
if s.panicInTest {
|
||||
panic("oops in test")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *panickingSuite) AfterTest(_, _ string) {
|
||||
if s.panicInAfterTest {
|
||||
panic("oops in after test")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *panickingSuite) TearDownTest() {
|
||||
if s.panicInTearDownTest {
|
||||
panic("oops in tear down test")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *panickingSuite) TearDownSuite() {
|
||||
if s.panicInTearDownSuite {
|
||||
panic("oops in tear down suite")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSuiteRecoverPanic(t *testing.T) {
|
||||
ok := true
|
||||
panickingTests := []testing.InternalTest{
|
||||
{
|
||||
Name: "TestPanicInSetupSuite",
|
||||
F: func(t *testing.T) { Run(t, &panickingSuite{panicInSetupSuite: true}) },
|
||||
},
|
||||
{
|
||||
Name: "TestPanicInSetupTest",
|
||||
F: func(t *testing.T) { Run(t, &panickingSuite{panicInSetupTest: true}) },
|
||||
},
|
||||
{
|
||||
Name: "TestPanicInBeforeTest",
|
||||
F: func(t *testing.T) { Run(t, &panickingSuite{panicInBeforeTest: true}) },
|
||||
},
|
||||
{
|
||||
Name: "TestPanicInTest",
|
||||
F: func(t *testing.T) { Run(t, &panickingSuite{panicInTest: true}) },
|
||||
},
|
||||
{
|
||||
Name: "TestPanicInAfterTest",
|
||||
F: func(t *testing.T) { Run(t, &panickingSuite{panicInAfterTest: true}) },
|
||||
},
|
||||
{
|
||||
Name: "TestPanicInTearDownTest",
|
||||
F: func(t *testing.T) { Run(t, &panickingSuite{panicInTearDownTest: true}) },
|
||||
},
|
||||
{
|
||||
Name: "TestPanicInTearDownSuite",
|
||||
F: func(t *testing.T) { Run(t, &panickingSuite{panicInTearDownSuite: true}) },
|
||||
},
|
||||
}
|
||||
|
||||
require.NotPanics(t, func() {
|
||||
ok = testing.RunTests(allTestsFilter, panickingTests)
|
||||
})
|
||||
|
||||
assert.False(t, ok)
|
||||
}
|
||||
|
||||
// This suite is intended to store values to make sure that only
|
||||
// testing-suite-related methods are run. It's also a fully
|
||||
// functional example of a testing suite, using setup/teardown methods
|
||||
|
@ -59,6 +152,7 @@ type SuiteTester struct {
|
|||
TearDownTestRunCount int
|
||||
TestOneRunCount int
|
||||
TestTwoRunCount int
|
||||
TestSubtestRunCount int
|
||||
NonTestMethodRunCount int
|
||||
|
||||
SuiteNameBefore []string
|
||||
|
@ -153,6 +247,27 @@ func (suite *SuiteTester) NonTestMethod() {
|
|||
suite.NonTestMethodRunCount++
|
||||
}
|
||||
|
||||
func (suite *SuiteTester) TestSubtest() {
|
||||
suite.TestSubtestRunCount++
|
||||
|
||||
for _, t := range []struct {
|
||||
testName string
|
||||
}{
|
||||
{"first"},
|
||||
{"second"},
|
||||
} {
|
||||
suiteT := suite.T()
|
||||
suite.Run(t.testName, func() {
|
||||
// We should get a different *testing.T for subtests, so that
|
||||
// go test recognizes them as proper subtests for output formatting
|
||||
// and running individual subtests
|
||||
subTestT := suite.T()
|
||||
suite.NotEqual(subTestT, suiteT)
|
||||
})
|
||||
suite.Equal(suiteT, suite.T())
|
||||
}
|
||||
}
|
||||
|
||||
// TestRunSuite will be run by the 'go test' command, so within it, we
|
||||
// can run our suite using the Run(*testing.T, TestingSuite) function.
|
||||
func TestRunSuite(t *testing.T) {
|
||||
|
@ -168,18 +283,20 @@ func TestRunSuite(t *testing.T) {
|
|||
assert.Equal(t, suiteTester.SetupSuiteRunCount, 1)
|
||||
assert.Equal(t, suiteTester.TearDownSuiteRunCount, 1)
|
||||
|
||||
assert.Equal(t, len(suiteTester.SuiteNameAfter), 3)
|
||||
assert.Equal(t, len(suiteTester.SuiteNameBefore), 3)
|
||||
assert.Equal(t, len(suiteTester.TestNameAfter), 3)
|
||||
assert.Equal(t, len(suiteTester.TestNameBefore), 3)
|
||||
assert.Equal(t, len(suiteTester.SuiteNameAfter), 4)
|
||||
assert.Equal(t, len(suiteTester.SuiteNameBefore), 4)
|
||||
assert.Equal(t, len(suiteTester.TestNameAfter), 4)
|
||||
assert.Equal(t, len(suiteTester.TestNameBefore), 4)
|
||||
|
||||
assert.Contains(t, suiteTester.TestNameAfter, "TestOne")
|
||||
assert.Contains(t, suiteTester.TestNameAfter, "TestTwo")
|
||||
assert.Contains(t, suiteTester.TestNameAfter, "TestSkip")
|
||||
assert.Contains(t, suiteTester.TestNameAfter, "TestSubtest")
|
||||
|
||||
assert.Contains(t, suiteTester.TestNameBefore, "TestOne")
|
||||
assert.Contains(t, suiteTester.TestNameBefore, "TestTwo")
|
||||
assert.Contains(t, suiteTester.TestNameBefore, "TestSkip")
|
||||
assert.Contains(t, suiteTester.TestNameBefore, "TestSubtest")
|
||||
|
||||
for _, suiteName := range suiteTester.SuiteNameAfter {
|
||||
assert.Equal(t, "SuiteTester", suiteName)
|
||||
|
@ -197,15 +314,16 @@ func TestRunSuite(t *testing.T) {
|
|||
assert.False(t, when.IsZero())
|
||||
}
|
||||
|
||||
// There are three test methods (TestOne, TestTwo, and TestSkip), so
|
||||
// There are four test methods (TestOne, TestTwo, TestSkip, and TestSubtest), so
|
||||
// the SetupTest and TearDownTest methods (which should be run once for
|
||||
// each test) should have been run three times.
|
||||
assert.Equal(t, suiteTester.SetupTestRunCount, 3)
|
||||
assert.Equal(t, suiteTester.TearDownTestRunCount, 3)
|
||||
// each test) should have been run four times.
|
||||
assert.Equal(t, suiteTester.SetupTestRunCount, 4)
|
||||
assert.Equal(t, suiteTester.TearDownTestRunCount, 4)
|
||||
|
||||
// Each test should have been run once.
|
||||
assert.Equal(t, suiteTester.TestOneRunCount, 1)
|
||||
assert.Equal(t, suiteTester.TestTwoRunCount, 1)
|
||||
assert.Equal(t, suiteTester.TestSubtestRunCount, 1)
|
||||
|
||||
// Methods that don't match the test method identifier shouldn't
|
||||
// have been run at all.
|
||||
|
|
42
zk.go
42
zk.go
|
@ -24,14 +24,14 @@ import (
|
|||
"github.com/samuel/go-zookeeper/zk"
|
||||
)
|
||||
|
||||
type Endpoint struct {
|
||||
type endpoint struct {
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
}
|
||||
|
||||
type ServiceInstance struct {
|
||||
Service Endpoint `json:"serviceEndpoint"`
|
||||
AdditionalEndpoints map[string]Endpoint `json:"additionalEndpoints"`
|
||||
type serviceInstance struct {
|
||||
Service endpoint `json:"serviceEndpoint"`
|
||||
AdditionalEndpoints map[string]endpoint `json:"additionalEndpoints"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
|
@ -40,47 +40,54 @@ type zkConfig struct {
|
|||
path string
|
||||
backoff Backoff
|
||||
timeout time.Duration
|
||||
logger Logger
|
||||
logger logger
|
||||
}
|
||||
|
||||
// ZKOpt - Configuration option for the Zookeeper client used.
|
||||
type ZKOpt func(z *zkConfig)
|
||||
|
||||
// ZKEndpoints - Endpoints on which a Zookeeper instance is running to be used by the client.
|
||||
func ZKEndpoints(endpoints ...string) ZKOpt {
|
||||
return func(z *zkConfig) {
|
||||
z.endpoints = endpoints
|
||||
}
|
||||
}
|
||||
|
||||
// ZKPath - Path to look for information in when connected to Zookeeper.
|
||||
func ZKPath(path string) ZKOpt {
|
||||
return func(z *zkConfig) {
|
||||
z.path = path
|
||||
}
|
||||
}
|
||||
|
||||
// ZKBackoff - Configuration for Retry mechanism used when connecting to Zookeeper.
|
||||
// TODO(rdelvalle): Determine if this is really necessary as the ZK library already has a retry built in.
|
||||
func ZKBackoff(b Backoff) ZKOpt {
|
||||
return func(z *zkConfig) {
|
||||
z.backoff = b
|
||||
}
|
||||
}
|
||||
|
||||
// ZKTimeout - How long to wait on a response from the Zookeeper instance before considering it dead.
|
||||
func ZKTimeout(d time.Duration) ZKOpt {
|
||||
return func(z *zkConfig) {
|
||||
z.timeout = d
|
||||
}
|
||||
}
|
||||
|
||||
func ZKLogger(l Logger) ZKOpt {
|
||||
// ZKLogger - Attach a logger to the Zookeeper client in order to debug issues.
|
||||
func ZKLogger(l logger) ZKOpt {
|
||||
return func(z *zkConfig) {
|
||||
z.logger = l
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieves current Aurora leader from ZK.
|
||||
// LeaderFromZK - Retrieves current Aurora leader from ZK.
|
||||
func LeaderFromZK(cluster Cluster) (string, error) {
|
||||
return LeaderFromZKOpts(ZKEndpoints(strings.Split(cluster.ZK, ",")...), ZKPath(cluster.SchedZKPath))
|
||||
}
|
||||
|
||||
// Retrieves current Aurora leader from ZK with a custom configuration.
|
||||
// LeaderFromZKOpts - Retrieves current Aurora leader from ZK with a custom configuration.
|
||||
func LeaderFromZKOpts(options ...ZKOpt) (string, error) {
|
||||
var leaderURL string
|
||||
|
||||
|
@ -103,7 +110,7 @@ func LeaderFromZKOpts(options ...ZKOpt) (string, error) {
|
|||
|
||||
c, _, err := zk.Connect(config.endpoints, config.timeout, func(c *zk.Conn) { c.SetLogger(config.logger) })
|
||||
if err != nil {
|
||||
return false, NewTemporaryError(errors.Wrap(err, "Failed to connect to Zookeeper"))
|
||||
return false, NewTemporaryError(errors.Wrap(err, "failed to connect to Zookeeper"))
|
||||
}
|
||||
|
||||
defer c.Close()
|
||||
|
@ -117,11 +124,10 @@ func LeaderFromZKOpts(options ...ZKOpt) (string, error) {
|
|||
return false, errors.Wrapf(err, "path %s is an invalid Zookeeper path", config.path)
|
||||
}
|
||||
|
||||
return false, NewTemporaryError(errors.Wrapf(err, "Path %s doesn't exist on Zookeeper ", config.path))
|
||||
return false, NewTemporaryError(errors.Wrapf(err, "path %s doesn't exist on Zookeeper ", config.path))
|
||||
}
|
||||
|
||||
// Search for the leader through all the children in the given path
|
||||
serviceInst := new(ServiceInstance)
|
||||
for _, child := range children {
|
||||
|
||||
// Only the leader will start with member_
|
||||
|
@ -134,19 +140,21 @@ func LeaderFromZKOpts(options ...ZKOpt) (string, error) {
|
|||
return false, errors.Wrapf(err, "path %s is an invalid Zookeeper path", childPath)
|
||||
}
|
||||
|
||||
return false, NewTemporaryError(errors.Wrap(err, "Error fetching contents of leader"))
|
||||
return false, NewTemporaryError(errors.Wrap(err, "unable to fetch contents of leader"))
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(data), serviceInst)
|
||||
var serviceInst serviceInstance
|
||||
err = json.Unmarshal([]byte(data), &serviceInst)
|
||||
if err != nil {
|
||||
return false, NewTemporaryError(errors.Wrap(err, "Unable to unmarshall contents of leader"))
|
||||
return false, NewTemporaryError(errors.Wrap(err, "unable to unmarshal contents of leader"))
|
||||
}
|
||||
|
||||
// Should only be one endpoint.
|
||||
// This should never be encountered as it would indicate Aurora
|
||||
// writing bad info into Zookeeper but is kept here as a safety net.
|
||||
if len(serviceInst.AdditionalEndpoints) > 1 {
|
||||
return false, NewTemporaryError(errors.New("ambiguous endpoints in json blob, Aurora wrote bad info to ZK"))
|
||||
return false,
|
||||
NewTemporaryError(errors.New("ambiguous endpoints in json blob, Aurora wrote bad info to ZK"))
|
||||
}
|
||||
|
||||
var scheme, host, port string
|
||||
|
@ -162,11 +170,11 @@ func LeaderFromZKOpts(options ...ZKOpt) (string, error) {
|
|||
}
|
||||
|
||||
// Leader data might not be available yet, try to fetch again.
|
||||
return false, NewTemporaryError(errors.New("No leader found"))
|
||||
return false, NewTemporaryError(errors.New("no leader found"))
|
||||
})
|
||||
|
||||
if retryErr != nil {
|
||||
config.logger.Printf("Failed to determine leader after %v attempts", config.backoff.Steps)
|
||||
config.logger.Printf("failed to determine leader after %v attempts", config.backoff.Steps)
|
||||
return "", retryErr
|
||||
}
|
||||
|
||||
|
|
|
@ -24,11 +24,12 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var backoff realis.Backoff = realis.Backoff{ // Reduce penalties for this test to make it quick
|
||||
var backoff = realis.Backoff{ // Reduce penalties for this test to make it quick
|
||||
Steps: 5,
|
||||
Duration: 1 * time.Second,
|
||||
Factor: 1.0,
|
||||
Jitter: 0.1}
|
||||
Jitter: 0.1,
|
||||
}
|
||||
|
||||
// Test for behavior when no endpoints are given to the ZK leader finding function.
|
||||
func TestZKNoEndpoints(t *testing.T) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue