pax_global_header00006660000000000000000000000064141063057540014517gustar00rootroot0000000000000052 comment=36558e1d2c6749f95421fea0483357d439a2e936 check-1.6.0/000077500000000000000000000000001410630575400126005ustar00rootroot00000000000000check-1.6.0/.circleci/000077500000000000000000000000001410630575400144335ustar00rootroot00000000000000check-1.6.0/.circleci/config.yml000066400000000000000000000013421410630575400164230ustar00rootroot00000000000000version: 2.1 jobs: test: docker: - image: "cimg/go:1.16" steps: - checkout - restore_cache: keys: - v3-{{ checksum "go.mod" }}-{{ .Branch }} - v3-{{ checksum "go.mod" }}- - v3- - run: go generate - run: .gobincache/golangci-lint run - run: go test -race ./... - run: .gobincache/goveralls -service=CircleCI - save_cache: when: always key: v3-{{ checksum "go.mod" }}-{{ .Branch }} paths: - ~/go/bin/ - ~/go/pkg/ - ~/go/src/ - ~/.cache/go-build/ - ~/.cache/golangci-lint/ - .gobincache/ workflows: default: jobs: - test check-1.6.0/.gitattributes000066400000000000000000000007251410630575400154770ustar00rootroot00000000000000# /name - apply (* doesn't match /) to file "name" beginning in project root # na/me - apply (* doesn't match /) to file "na/me" anywhere # name - apply (* do match /) to file "name" anywhere # name/** - apply … to dir … # **/name - apply (* doesn't match /) to file "name" in any dir including project root # na/**/me - apply (* doesn't match /) to file "na/me", "na/*/me", "na/*/*/me", … go.sum binary *.*.go binary check-1.6.0/.github/000077500000000000000000000000001410630575400141405ustar00rootroot00000000000000check-1.6.0/.github/commitlint.config.js000066400000000000000000000001101410630575400201110ustar00rootroot00000000000000module.exports = { extends: ['@commitlint/config-conventional'], }; check-1.6.0/.github/dependabot.yml000066400000000000000000000005161410630575400167720ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: 'github-actions' directory: '/' schedule: interval: 'daily' commit-message: prefix: 'chore(ci):' - package-ecosystem: 'gomod' directory: '/' schedule: interval: 'daily' commit-message: prefix: 'chore(deps):' open-pull-requests-limit: 10 check-1.6.0/.github/workflows/000077500000000000000000000000001410630575400161755ustar00rootroot00000000000000check-1.6.0/.github/workflows/CI&CD.yml000066400000000000000000000017121410630575400174710ustar00rootroot00000000000000name: CI/CD on: push: branches: master tags: v* pull_request: branches: master env: GO_VERSION: '^1.16' jobs: test: runs-on: 'ubuntu-latest' timeout-minutes: 30 steps: - uses: actions/setup-go@v2 with: go-version: ${{ env.GO_VERSION }} - uses: actions/checkout@v2 - uses: actions/cache@v2 with: path: | ~/go/bin ~/go/pkg ~/go/src ~/.cache/go-build ~/.cache/golangci-lint .gobincache key: v3-test-${{ runner.os }}-${{ hashFiles('go.mod') }} restore-keys: | v3-test-${{ runner.os }}- - run: go generate - run: .gobincache/golangci-lint run - run: go test -race ./... - name: Report code coverage env: COVERALLS_TOKEN: ${{ secrets.COVERALLS_TOKEN }} if: env.COVERALLS_TOKEN run: .gobincache/goveralls -service=GitHub check-1.6.0/.github/workflows/Create-GitHub-Release.yml000066400000000000000000000013021410630575400226550ustar00rootroot00000000000000name: Create GitHub Release on: push: tags: v* jobs: create-release: runs-on: ubuntu-latest timeout-minutes: 3 steps: - name: Checkout uses: actions/checkout@v2 - name: Generate changelog id: changelog uses: metcalfc/changelog-generator@v1.0.0 with: myToken: ${{ secrets.GITHUB_TOKEN }} - name: Create Release uses: actions/create-release@latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ github.ref }} release_name: ${{ github.ref }} body: ${{ steps.changelog.outputs.changelog }} draft: false prerelease: false check-1.6.0/.github/workflows/Lint-PR-name.yml000066400000000000000000000007221410630575400210640ustar00rootroot00000000000000name: Lint PR name on: pull_request: branches: master types: [ opened, edited, synchronize, reopened ] jobs: lint-PR-name: runs-on: ubuntu-latest timeout-minutes: 3 steps: - uses: actions/checkout@v2 - name: Install Dependencies run: npm install @commitlint/config-conventional - uses: JulienKode/pull-request-name-linter-action@v0.2.0 with: configuration-path: '.github/commitlint.config.js' check-1.6.0/.github/workflows/Update-Go-doc.yml000066400000000000000000000003451410630575400212520ustar00rootroot00000000000000name: Update Go module doc on: push: tags: v* jobs: update-doc: runs-on: ubuntu-latest timeout-minutes: 3 steps: - name: Pull new module version uses: andrewslotin/go-proxy-pull-action@master check-1.6.0/.github/workflows/codeql-analysis.yml000066400000000000000000000037201410630575400220120ustar00rootroot00000000000000name: "CodeQL" on: push: branches: [master] #pull_request: # The branches below must be a subset of the branches above #branches: [master] schedule: - cron: '0 12 * * 5' jobs: analyze: name: Analyze runs-on: ubuntu-latest strategy: fail-fast: false matrix: # Override automatic language detection by changing the below list # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] language: ['go'] # Learn more... # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection steps: - name: Checkout repository uses: actions/checkout@v2 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. fetch-depth: 2 # If this run was triggered by a pull request event, then checkout # the head of the pull request instead of the merge commit. - run: git checkout HEAD^2 if: ${{ github.event_name == 'pull_request' }} # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v1 with: languages: ${{ matrix.language }} # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild uses: github/codeql-action/autobuild@v1 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines # and modify them (or add more) to build your code if your project # uses a compiled language #- run: | # make bootstrap # make release - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v1 check-1.6.0/.gitignore000066400000000000000000000011431410630575400145670ustar00rootroot00000000000000# /name - exclude path (* doesn't match /) to file/dir "name" beginning in project root # na/me - exclude path (* doesn't match /) to file/dir "na/me" anywhere # name - exclude path (* do match /) to file/dir "name" anywhere # name/ - exclude path … to dir … # **/name - exclude path (* doesn't match /) to file/dir "name" in any dir including project root # na/**/me - exclude path (* doesn't match /) to file/dir "na/me", "na/*/me", "na/*/*/me", … # !name - include previously excluded path … /.circleci/config-local.yml /.gobincache/ /cover.out check-1.6.0/.golangci.yml000066400000000000000000000765651410630575400152070ustar00rootroot00000000000000# 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 #timeout: 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 # list of build tags, all linters use it. Default is empty list. build-tags: - integration # which dirs to skip: issues from them won't be reported; # can use regexp here: generated.*, regexp is applied on full path; # default value is empty list, but default dirs are skipped independently # from this option's value (see skip-dirs-use-default). # "/" will be replaced by current OS file path separator to properly work # on Windows. skip-dirs: #- old # default is true. Enables skipping of directories: # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ #skip-dirs-use-default: true # which files to skip: they will be analyzed, but issues from them # won't be reported. Default value is empty list, but there is # no need to include all autogenerated files, we confidently recognize # autogenerated files. If it's not please let us know. # "/" will be replaced by current OS file path separator to properly work # on Windows. skip-files: - "\\.[\\w-]+\\.go$" # by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules": # If invoked with -mod=readonly, the go command is disallowed from the implicit # automatic updating of go.mod described above. Instead, it fails when any changes # to go.mod are needed. This setting is most useful to check that go.mod does # not need updates, such as in a continuous integration and testing system. # If invoked with -mod=vendor, the go command assumes that the vendor # directory holds the correct copies of dependencies and ignores # the dependency descriptions in go.mod. modules-download-mode: readonly # Allow multiple parallel golangci-lint instances running. # If false (default) - golangci-lint acquires file lock on start. #allow-parallel-runners: false # output configuration options output: # colored-line-number|line-number|json|tab|checkstyle|code-climate|junit-xml|github-actions # 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 # make issues output unique by line, default is true #uniq-by-line: true # add a prefix to the output file references; default is no prefix #path-prefix: "" # sorts results by: filepath, line and column sort-results: false # all available settings of specific linters linters-settings: cyclop: # the maximal code complexity to report max-complexity: 15 # the maximal average package complexity. If it's higher than 0.0 (float) the check is enabled (default 0.0) #package-average: 0.0 # should ignore tests (default false) #skip-tests: false dogsled: # checks assignments with too many blank identifiers; default is 2 #max-blank-identifiers: 2 dupl: # tokens count to trigger issue, 150 by default threshold: 100 errcheck: # report about not checking of errors in type assertions: `a := b.(MyStruct)`; # default is false: such cases aren't reported by default. #check-type-assertions: false # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`; # default is false: such cases aren't reported by default. #check-blank: false # [deprecated] comma-separated list of pairs of the form pkg:regex # the regex is used to ignore names within pkg. (default "fmt:.*"). # see https://github.com/kisielk/errcheck#the-deprecated-method for details #ignore: fmt:.*,io/ioutil:^Read.* # path to a file containing a list of functions to exclude from checking # see https://github.com/kisielk/errcheck#excluding-functions for details #exclude: .errcheck.excludes errorlint: # Check whether fmt.Errorf uses the %w verb for formatting errors. See the readme for caveats errorf: true # Check for plain type assertions and type switches asserts: true # Check for plain error comparisons comparison: true exhaustive: # check switch statements in generated files also check-generated: false # indicates that switch statements are to be considered exhaustive if a # 'default' case is present, even if all enum members aren't listed in the # switch default-signifies-exhaustive: false exhaustivestruct: # Struct Patterns is list of expressions to match struct packages and names # The struct packages have the form example.com/package.ExampleStruct # The matching patterns can use matching syntax from https://pkg.go.dev/path#Match # If this list is empty, all structs are tested. struct-patterns: - 'github.com/*/*.ExampleTypeToAlwaysFillAllFields' forbidigo: # Forbid the following identifiers (identifiers are written using regexp): forbid: - ^print(ln)?$ #- 'fmt\.Print.*' # Exclude godoc examples from forbidigo checks. Default is true. exclude_godoc_examples: false funlen: lines: 60 statements: 40 gci: # put imports beginning with prefix after 3rd-party packages; # only support one prefix # if not set, use goimports.local-prefixes #local-prefixes: github.com/org/project gocognit: # minimal code complexity to report, 30 by default (but we recommend 10-20) min-complexity: 20 nestif: # minimal complexity of if statements to report, 5 by default min-complexity: 4 goconst: # minimal length of string constant, 3 by default #min-len: 3 # minimal occurrences count to trigger, 3 by default #min-occurrences: 3 gocritic: # Which checks should be enabled; can't be combined with 'disabled-checks'; # See https://go-critic.github.io/overview#checks-overview # To check which checks are enabled run `GL_DEBUG=gocritic golangci-lint run` # By default list of stable checks is used. #enabled-checks: # - rangeValCopy # Which checks should be disabled; can't be combined with 'enabled-checks'; default is empty disabled-checks: - hugeParam # premature optimization - paramTypeCombine # questionable - switchTrue # questionable - yodaStyleExpr # questionable # Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks. # Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags". enabled-tags: - diagnostic - style - performance - experimental - opinionated #disabled-tags: # Settings passed to gocritic. # The settings key is the name of a supported gocritic checker. # The list of supported checkers can be find in https://go-critic.github.io/overview. settings: captLocal: # must be valid enabled check name # whether to restrict checker to params only (default true) paramsOnly: false elseif: # whether to skip balanced if-else pairs (default true) #skipBalanced: true hugeParam: # size in bytes that makes the warning trigger (default 80) #sizeThreshold: 80 nestingReduce: # min number of statements inside a branch to trigger a warning (default 5) #bodyWidth: 5 rangeExprCopy: # size in bytes that makes the warning trigger (default 512) #sizeThreshold: 512 # whether to check test functions (default true) #skipTestFuncs: true rangeValCopy: # size in bytes that makes the warning trigger (default 128) #sizeThreshold: 32 # whether to check test functions (default true) #skipTestFuncs: true ruleguard: # path to a gorules file for the ruleguard checker rules: 'build/gorules/rules.go' # Run `golangci-lint cache clean` when it changes! truncateCmp: # whether to skip int/uint/uintptr types (default true) skipArchDependent: false underef: # whether to skip (*x).method() calls where x is a pointer receiver (default true) skipRecvDeref: false unnamedResult: # whether to check exported functions checkExported: true gocyclo: # minimal code complexity to report, 30 by default (but we recommend 10-20) min-complexity: 15 godot: # comments to be checked: `declarations`, `toplevel`, or `all` scope: declarations # list of regexps for excluding particular comment lines from check exclude: # example: exclude comments which contain numbers - ':$' # check that each sentence starts with a capital letter capital: false godox: # report any comments starting with keywords, this is useful for TODO or FIXME comments that # might be left in the code accidentally and should be resolved before merging keywords: # default keywords are TODO, BUG, and FIXME, these can be overwritten by this setting - BUG # marks issues that should be moved to issue tracker before merging - FIXME # marks issues that should be resolved before merging - DEBUG # marks temporary code that should be removed before merging gofmt: # simplify code: gofmt with `-s` option, true by default simplify: true gofumpt: # Choose whether or not to use the extra rules that are disabled # by default extra-rules: false goheader: values: const: # define here const type values in format k:v, for example: # COMPANY: MY COMPANY regexp: # define here regexp type values, for example # AUTHOR: .*@mycompany\.com template: # |- # put here copyright header template for source code files, for example: # Note: {{ YEAR }} is a builtin value that returns the year relative to the current machine time. # # {{ AUTHOR }} {{ COMPANY }} {{ YEAR }} # SPDX-License-Identifier: Apache-2.0 # 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. template-path: # also as alternative of directive 'template' you may put the path to file with the template source goimports: # put imports beginning with prefix after 3rd-party packages; # it's a comma-separated list of prefixes local-prefixes: github.com/powerman/check gomnd: settings: mnd: # the list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description. checks: argument,case,condition,operation,return,assign # ignored-numbers: 1000 # ignored-files: magic_.*.go # ignored-functions: math.* gomoddirectives: # Allow local `replace` directives. Default is false. replace-local: false # List of allowed `replace` directives. Default is empty. replace-allow-list: #- launchpad.net/gocheck # Allow to not explain why the version has been retracted in the `retract` directives. Default is false. retract-allow-no-explanation: false # Forbid the use of the `exclude` directives. Default is false. exclude-forbidden: false gomodguard: allowed: modules: # List of allowed modules # - gopkg.in/yaml.v2 domains: # List of allowed module domains # - golang.org blocked: modules: # List of blocked modules # - github.com/uudashr/go-module: # Blocked module # recommendations: # Recommended modules that should be used instead (Optional) # - golang.org/x/mod # reason: "`mod` is the official go.mod parser library." # Reason why the recommended module should be used (Optional) versions: # List of blocked module version constraints - github.com/cenkalti/backoff: version: "< 4.0.0" # - github.com/mitchellh/go-homedir: # Blocked module with version constraint # version: "< 1.1.0" # Version constraint, see https://github.com/Masterminds/semver#basic-comparisons # reason: "testing if blocked version constraint works." # Reason why the version constraint exists. (Optional) local_replace_directives: false # Set to true to raise lint issues for packages that are loaded from a local path via replace directive gosec: # To select a subset of rules to run. # Available rules: https://github.com/securego/gosec#available-rules includes: #- G401 #- G306 #- G101 # To specify a set of rules to explicitly exclude. # Available rules: https://github.com/securego/gosec#available-rules excludes: #- G204 # To specify the configuration of rules. # The configuration of rules is not fully documented by gosec: # https://github.com/securego/gosec#configuration # https://github.com/securego/gosec/blob/569328eade2ccbad4ce2d0f21ee158ab5356a5cf/rules/rulelist.go#L60-L102 config: #G306: "0600" #G101: # pattern: "(?i)example" # ignore_entropy: false # entropy_threshold: "80.0" # per_char_threshold: "3.0" # truncate: "32" gosimple: # Select the Go version to target. The default is '1.13'. go: "1.16" # https://staticcheck.io/docs/options#checks checks: [ "all" ] govet: # report about shadowed variables check-shadowing: true # settings per analyzer settings: printf: # analyzer name, run `go tool vet help` to see all analyzers funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer #- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof #- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf #- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf #- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf # enable or disable analyzers by name # run `go tool vet help` to see all analyzers #enable: # - atomicalign enable-all: true disable: - fieldalignment #- shadow #disable-all: false depguard: list-type: blacklist include-go-root: true packages: #- log - github.com/go-errors/errors #- github.com/pkg/errors - github.com/prometheus/client_golang/prometheus/promauto - github.com/prometheus/common/log - github.com/golang/protobuf packages-with-error-message: # specify an error message to output when a blacklisted package is used #- log: "logging is allowed only by github.com/powerman/structlog" ifshort: # Maximum length of variable declaration measured in number of lines, after which linter won't suggest using short syntax. # Has higher priority than max-decl-chars. max-decl-lines: 1 # Maximum length of variable declaration measured in number of characters, after which linter won't suggest using short syntax. max-decl-chars: 30 importas: # if set to `true`, force to use alias. no-unaliased: true # List of aliases alias: # using `servingv1` alias for `knative.dev/serving/pkg/apis/serving/v1` package #- pkg: knative.dev/serving/pkg/apis/serving/v1 # alias: servingv1 # using `autoscalingv1alpha1` alias for `knative.dev/serving/pkg/apis/autoscaling/v1alpha1` package #- pkg: knative.dev/serving/pkg/apis/autoscaling/v1alpha1 # alias: autoscalingv1alpha1 # You can specify the package path by regular expression, # and alias by regular expression expansion syntax like below. # see https://github.com/julz/importas#use-regular-expression for details #- pkg: knative.dev/serving/pkg/apis/(\w+)/(v[\w\d]+) # alias: $1$2 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: 1 makezero: # Allow only slices initialized with a length of zero. Default is false. #always: false maligned: # print struct with more effective memory layout or not, false by default suggest-new: true 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 #ignore-words: # - someword nakedret: # make an issue if func has more lines of code than this setting and it has naked returns; default is 30 #max-func-lines: 30 prealloc: # XXX: we don't recommend using this linter before doing performance profiling. # For most programs usage of prealloc will be a premature optimization. # Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them. # True by default. #simple: true #range-loops: true # Report preallocation suggestions on range loops, true by default #for-loops: false # Report preallocation suggestions on for loops, false by default promlinter: # Promlinter cannot infer all metrics name in static analysis. # Enable strict mode will also include the errors caused by failing to parse the args. strict: false # Please refer to https://github.com/yeya24/promlinter#usage for detailed usage. disabled-linters: # - "Help" # - "MetricUnits" # - "Counter" # - "HistogramSummaryReserved" # - "MetricTypeInName" # - "ReservedChars" # - "CamelCase" # - "lintUnitAbbreviations" predeclared: # comma-separated list of predeclared identifiers to not report on ignore: "" # include method names and field names (i.e., qualified names) in checks q: false nolintlint: # Enable to ensure that nolint directives are all used. Default is true. allow-unused: false # Disable to ensure that nolint directives don't have a leading space. Default is true. allow-leading-space: false # Exclude following linters from requiring an explanation. Default is []. allow-no-explanation: [] # Enable to require an explanation of nonzero length after each nolint directive. Default is false. require-explanation: true # Enable to require nolint directives to mention the specific linter being suppressed. Default is false. require-specific: true rowserrcheck: packages: - github.com/jmoiron/sqlx - github.com/powerman/sqlxx revive: # see https://github.com/mgechev/revive#available-rules for details. ignore-generated-header: true severity: warning rules: # Rules ported from golint: - name: context-keys-type - name: time-naming - name: var-declaration - name: unexported-return - name: errorf - name: blank-imports - name: context-as-argument - name: dot-imports - name: error-return - name: error-strings - name: error-naming #- name: exported - name: if-return - name: increment-decrement - name: var-naming #arguments: # First list element is a whitelist, second is a blacklist. # - ["ID"] # whitelist # - ["VM"] # blacklist - name: package-comments - name: range - name: receiver-naming - name: indent-error-flow # Rules not available in golint: #- name: argument-limit # arguments: 4 #- name: cyclomatic # arguments: 15 #- name: max-public-structs # arguments: 3 #- name: file-header # arguments: "This is the text that must appear at the top of source files." - name: empty-block - name: superfluous-else - name: confusing-naming - name: get-return - name: modifies-parameter - name: confusing-results - name: deep-exit - name: unused-parameter - name: unreachable-code #- name: add-constant # arguments: # - maxLitCount: "3" # allowStrs: '""' # allowInts: "0,1,2" # allowFloats: "0.0,0.,1.0,1.,2.0,2." - name: flag-parameter - name: unnecessary-stmt - name: struct-tag - name: modifies-value-receiver - name: constant-logical-expr - name: bool-literal-in-expr - name: redefines-builtin-id #- name: function-result-limit # arguments: 3 - name: imports-blacklist # arguments: ["crypto/md5", "crypto/sha1"] - name: range-val-in-closure - name: range-val-address - name: waitgroup-by-value - name: atomic - name: empty-lines #- name: line-length-limit # arguments: 80 - name: call-to-gc - name: duplicated-imports #- name: import-shadowing # See https://github.com/mgechev/revive/issues/534 - name: bare-return - name: unused-receiver #- name: unhandled-error # arguments: # - os.Setenv # - os.Unsetenv # - fmt.Print # - fmt.Printf # - fmt.Println #- name: cognitive-complexity # arguments: 15 - name: string-of-int - name: string-format arguments: - ["fmt.Errorf[0]", "/(^|[^\\.!?])$/", "must not end in punctuation"] - ["panic", "/^[^\\n]*$/", "must not contain line breaks"] - name: early-return - name: unconditional-recursion - name: identical-branches - name: defer # Options: call-chain, loop, method-call, recover, return. # By default all enabled. #arguments: [["loop","recover","return"]] - name: unexported-naming #- name: function-length # arguments: [40, 60] staticcheck: # Select the Go version to target. The default is '1.13'. go: "1.16" # https://staticcheck.io/docs/options#checks checks: [ "all" ] stylecheck: # Select the Go version to target. The default is '1.13'. go: "1.16" # https://staticcheck.io/docs/options#checks checks: [ "all" ] # [ "all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022" ] # https://staticcheck.io/docs/options#dot_import_whitelist dot-import-whitelist: - fmt # https://staticcheck.io/docs/options#initialisms initialisms: [ "ACL", "API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "QPS", "RAM", "RPC", "SLA", "SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", "UDP", "UI", "GID", "UID", "UUID", "URI", "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS" ] # https://staticcheck.io/docs/options#http_status_code_whitelist http-status-code-whitelist: [ "200", "400", "404", "500" ] tagliatelle: # check the struck tag name case case: # use the struct field name to check the name of the struct tag use-field-name: true rules: # any struct tag type can be used. # support string case: `camel`, `pascal`, `kebab`, `snake`, `goCamel`, `goPascal`, `goKebab`, `goSnake`, `upper`, `lower` json: snake yaml: camel xml: camel bson: camel avro: snake mapstructure: kebab testpackage: # regexp pattern to skip files #skip-regexp: (export|internal)_test\.go thelper: # The following configurations enable all checks. It can be omitted because all checks are enabled by default. # You can enable only required checks deleting unnecessary checks. test: first: true name: true begin: true benchmark: first: true name: true begin: true tb: first: true name: true begin: true unparam: # Inspect exported functions, default is false. Set to true if no external program/library imports your code. # XXX: if you enable this setting, unparam will report a lot of false-positives in text editors: # if it's called for subdir of a project it can't find external interfaces. All text editor integrations # with golangci-lint call it on a directory with the changed file. #check-exported: false unused: # Select the Go version to target. The default is '1.13'. go: "1.16" whitespace: multi-if: false # Enforces newlines (or comments) after every multi-line if statement multi-func: false # Enforces newlines (or comments) after every multi-line function signature wrapcheck: # An array of strings that specify substrings of signatures to ignore. # If this set, it will override the default set of ignored signatures. # See https://github.com/tomarrell/wrapcheck#configuration for more information. ignoreSigs: #- .Errorf( #- errors.New( #- errors.Unwrap( #- .Wrap( #- .Wrapf( #- .WithMessage( wsl: # See https://github.com/bombsimon/wsl/blob/master/doc/configuration.md for # documentation of available settings. These are the defaults for # `golangci-lint`. allow-assign-and-anything: false allow-assign-and-call: true allow-cuddle-declarations: false allow-multiline-assign: true allow-separated-leading-comment: false allow-trailing-comment: false force-case-trailing-whitespace: 0 force-err-cuddling: false force-short-decl-cuddling: false strict-append: true # The custom section can be used to define linter plugins to be loaded at runtime. # See README doc for more info. custom: # Each custom linter should have a unique name. #example: # The path to the plugin *.so. Can be absolute or local. Required for each custom linter #path: /path/to/example.so # The description of the linter. Optional, just for documentation purposes. #description: This is an example usage of a plugin linter. # Intended to point to the repo location of the linter. Optional, just for documentation purposes. #original-url: github.com/golangci/example-linter linters: #disable-all: true #enable: # - megacheck # - govet enable-all: true disable: - dogsled # questionable - dupl - golint # deprecated - ifshort # questionable - interfacer # deprecated - lll - maligned # premature optimization - nlreturn - paralleltest # questionable - prealloc - scopelint # deprecated - wrapcheck # enable after implementing https://github.com/tomarrell/wrapcheck/issues/1 - wsl # questionable #presets: # - bugs # - unused fast: false issues: # List of regexps of issue texts to exclude, empty list by default. # But independently from this option we use default exclude patterns, # it can be disabled by `exclude-use-default: false`. To list all # excluded by default patterns execute `golangci-lint run --help` exclude: - "declaration of \"(log|err|ctx)\" shadows" # - "Potential file inclusion via variable" # [DEFAULT] gosec: False positive is triggered by 'src, err := ioutil.ReadFile(filename)' # Excluding configuration per-path, per-linter, per-text and per-source exclude-rules: # Exclude some linters from running on tests files. - path: _test\.go|testing(_.*)?\.go linters: - bodyclose - dupl - errcheck - forcetypeassert - funlen - gochecknoglobals - gochecknoinits - goconst - gocyclo - gosec - maligned - path: _test\.go|testing(_.*)?\.go text: "(unnamedResult|exitAfterDefer|rangeValCopy|unnecessaryBlock)" linters: - gocritic - path: _test\.go text: '"t" shadows' linters: - govet # Files with go:embed directives are designed to contain global constants. - path: ^(.*/)?embed.go$ linters: - gochecknoglobals # Exclude known linters from partially hard-vendored code, # which is impossible to exclude via "nolint" comments. #- path: internal/hmac/ # text: "weak cryptographic primitive" # linters: # - gosec # Exclude some staticcheck messages #- linters: # - staticcheck # text: "SA9003:" # Exclude lll issues for long lines with go:generate #- linters: # - lll # source: "^//go:generate " # Independently from option `exclude` we use default exclude patterns, # it can be disabled by this option. To list all # excluded by default patterns execute `golangci-lint run --help`. # Default value for this option is true. exclude-use-default: false # The default value is false. If set to true exclude and exclude-rules # regular expressions become case sensitive. #exclude-case-sensitive: false # The list of ids of default excludes to include or disable. By default it's empty. include: #- EXC0002 # disable excluding of issues about comments from golint # Maximum issues count per one linter. Set to 0 to disable. Default is 50. max-issues-per-linter: 0 # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. max-same-issues: 0 # Show only new issues: if there are unstaged changes or untracked files, # only those changes are analyzed, else only changes in HEAD~ are analyzed. # It's a super-useful option for integration of golangci-lint into existing # large codebase. It's not practical to fix all existing issues at the moment # of integration: much better don't allow issues in new code. # Default is false. #new: false # Show only new issues created after git revision `REV` #new-from-rev: REV # Show only new issues created in git patch with set file path. #new-from-patch: path/to/patch/file # Fix found issues (if it's supported by the linter) fix: false severity: # Default value is empty string. # Set the default severity for issues. If severity rules are defined and the issues # do not match or no severity is provided to the rule this will be the default # severity applied. Severities should match the supported severity names of the # selected out format. # - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity # - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#severity # - Github: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message default-severity: error # The default value is false. # If set to true severity-rules regular expressions become case sensitive. #case-sensitive: false # Default value is empty list. # When a list of severity rules are provided, severity information will be added to lint # issues. Severity rules have the same filtering capability as exclude rules except you # are allowed to specify one matcher per severity rule. # Only affects out formats that support setting severity information. rules: #- linters: # - dupl # severity: info check-1.6.0/LICENSE000066400000000000000000000020531410630575400136050ustar00rootroot00000000000000MIT License Copyright (c) 2017 Alex Efros 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. check-1.6.0/README.md000066400000000000000000000061061410630575400140620ustar00rootroot00000000000000# check [![GoDoc](https://godoc.org/github.com/powerman/check?status.svg)](http://godoc.org/github.com/powerman/check) [![Go Report Card](https://goreportcard.com/badge/github.com/powerman/check)](https://goreportcard.com/report/github.com/powerman/check) [![CircleCI](https://circleci.com/gh/powerman/check.svg?style=svg)](https://circleci.com/gh/powerman/check) [![Coverage Status](https://coveralls.io/repos/github/powerman/check/badge.svg?branch=master)](https://coveralls.io/github/powerman/check?branch=master) Helpers to complement Go [testing](https://golang.org/pkg/testing/) package. Write tests with ease and fun! This package is like [testify/assert](https://godoc.org/github.com/test-go/testify/assert) on steroids. :) ## Features - Compelling output from failed tests: - Very easy-to-read dumps for expected and actual values. - Same text diff you loved in testify/assert. - Also visual diff in [GoConvey](http://goconvey.co/) web UI, if you use it (recommended). - Statistics with amount of passed/failed checks. - Colored output in terminal. - 100% compatible with testing package - check package just provide convenient wrappers for `*testing.T` methods and doesn't introduce new concepts like BDD, custom test suite or unusual execution flow. - All checks you may ever need! :) - Very easy to add your own check functions. - Concise, handy and consistent API, without dot-import! ## Quickstart Just wrap each (including subtests) `*testing.T` using `check.T()` and write tests as usually with testing package. Call new methods provided by this package to have more clean/concise test code and cool dump/diff. ```go import "github.com/powerman/check" func TestSomething(tt *testing.T) { t := check.T(tt) t.Equal(2, 2) t.Log("You can use new t just like usual *testing.T") t.Run("Subtests/Parallel example", func(tt *testing.T) { t := check.T(tt) t.Parallel() t.NotEqual(2, 3, "should not be 3!") obj, err := NewObj() if t.Nil(err) { t.Match(obj.field, `^\d+$`) } }) } ``` To get optional statistics about executed checkers add: ```go func TestMain(m *testing.M) { check.TestMain(m) } ``` When use goconvey tool, to get nice diff in web UI [add](https://github.com/smartystreets/goconvey/issues/513): ```go import _ "github.com/smartystreets/goconvey/convey" ``` ## Installation Require [Go 1.9](https://golang.org/doc/go1.9#test-helper). ``` go get github.com/powerman/check ``` ## TODO - Doc: - [ ] Add testable examples. - [ ] Show how text diff and stats looks like (both text and screenshot with colors). - [ ] Show how `goconvey` diff looks like. - Questionable: - [ ] Support custom checkers from gocheck etc.? - [ ] Provide a way to force binary dump for utf8.Valid `string`/`[]byte`? - [ ] Count skipped tests (will have to overload `Skip`, `Skipf`, `SkipNow`)? - Complicated: - [ ] Show line of source_test.go with failed test (like gocheck). - [ ] Auto-detect missed `t:=check.T(tt)` - try to intercept `Run()` and `Parallel()` for detecting using wrong `t` (looks like golangci-lint's tparallel catch at least `Parallel()` case). check-1.6.0/check.go000066400000000000000000001207541410630575400142150ustar00rootroot00000000000000package check import ( "bytes" "encoding/json" "fmt" "math" "reflect" "regexp" "strings" "testing" "time" pkgerrors "github.com/pkg/errors" "github.com/powerman/deepequal" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" ) //nolint:gochecknoglobals // Const. var ( typString = reflect.TypeOf("") typBytes = reflect.TypeOf([]byte(nil)) typFloat64 = reflect.TypeOf(0.0) ) // C wraps *testing.T to make it convenient to call checkers in test. type C struct { *testing.T todo bool must bool } const ( nameActual = "Actual" nameExpected = "Expected" ) // Parallel implements an internal workaround which have no visible // effect, so you should just call t.Parallel() as you usually do - it // will work as expected. func (t *C) Parallel() { t.Helper() // Goconvey anyway doesn't provide -test.cpu= and mixed output of // parallel tests result in reporting failed tests at wrong places // and with wrong failed tests count in web UI. if !flags.detect().conveyJSON { t.T.Parallel() } } // T creates and returns new *C, which wraps given tt and supposed to be // used inplace of it, providing you with access to many useful helpers in // addition to standard methods of *testing.T. // // It's convenient to rename Test function's arg from t to something // else, create wrapped variable with usual name t and use only t: // // func TestSomething(tt *testing.T) { // t := check.T(tt) // // use only t in test and don't touch tt anymore // } func T(tt *testing.T) *C { //nolint:thelper // With check we name it tt! return &C{T: tt} } // TODO creates and returns new *C, which have only one difference from // original one: every passing check is now handled as failed and vice // versa (this doesn't affect boolean value returned by check). // You can continue using both old and new *C at same time. // // Swapping passed/failed gives you ability to temporary mark some failed // test as passed. For example, this may be useful to avoid broken builds // in CI. This is often better than commenting, deleting or skipping // broken test because it will continue to execute, and eventually when // reason why it fails will be fixed this test will became failed again - // notifying you the mark can and should be removed from this test now. // // func TestSomething(tt *testing.T) { // t := check.T(tt) // // Normal tests. // t.True(true) // // If you need to mark just one/few broken tests: // t.TODO().True(false) // t.True(true) // // If there are several broken tests mixed with working ones: // todo := t.TODO() // t.True(true) // todo.True(false) // t.True(true) // if todo.True(false) { // panic("never here") // } // // If all tests below this point are broken: // t = t.TODO() // t.True(false) // ... // } func (t *C) TODO() *C { return &C{T: t.T, todo: true, must: t.must} } // MustAll creates and returns new *C, which have only one difference from // original one: every failed check will interrupt test using t.FailNow. // You can continue using both old and new *C at same time. // // This provides an easy way to turn all checks into assertion. func (t *C) MustAll() *C { return &C{T: t.T, todo: t.todo, must: true} } func (t *C) pass() { statsMu.Lock() defer statsMu.Unlock() if stats[t.T] == nil { stats[t.T] = newTestStat(t.Name(), false) } if t.todo { stats[t.T].forged.value++ } else { stats[t.T].passed.value++ } } func (t *C) fail() { statsMu.Lock() defer statsMu.Unlock() if stats[t.T] == nil { stats[t.T] = newTestStat(t.Name(), false) } stats[t.T].failed.value++ } func (t *C) report(ok bool, msg []interface{}, checker string, name []string, args []interface{}) bool { //nolint:revive // False positive. t.Helper() if ok != t.todo { t.pass() return ok } if t.todo { checker = "TODO " + checker } dump := make([]dump, 0, len(args)) for _, arg := range args { dump = append(dump, newDump(arg)) } failure := new(bytes.Buffer) fmt.Fprintf(failure, "%s\nChecker: %s%s%s\n", format(msg...), ansiYellow, checker, ansiReset, ) failureShort := failure.String() // Reverse order to show Actual: last. for i := len(dump) - 1; i >= 0; i-- { fmt.Fprintf(failure, "%-10s", name[i]+":") switch name[i] { case nameActual: fmt.Fprint(failure, ansiRed) default: fmt.Fprint(failure, ansiGreen) } fmt.Fprintf(failure, "%s%s", dump[i], ansiReset) } failureLong := failure.String() wantDiff := len(dump) == 2 && name[0] == nameActual && name[1] == nameExpected if wantDiff { //nolint:nestif // No idea how to simplify. if reportToGoConvey(dump[0].String(), dump[1].String(), failureShort) == nil { t.Fail() } else { fmt.Fprintf(failure, "\n%s", colouredDiff(dump[0].diff(dump[1]))) t.Errorf("%s\n", failure) } } else { if reportToGoConvey("", "", failureLong) == nil { t.Fail() } else { t.Errorf("%s\n", failure) } } t.fail() if t.must { t.FailNow() } return ok } func (t *C) reportShould1(funcName string, actual interface{}, msg []interface{}, ok bool) bool { t.Helper() return t.report(ok, msg, "Should "+funcName, []string{nameActual}, []interface{}{actual}) } func (t *C) reportShould2(funcName string, actual, expected interface{}, msg []interface{}, ok bool) bool { t.Helper() return t.report(ok, msg, "Should "+funcName, []string{nameActual, nameExpected}, []interface{}{actual, expected}) } func (t *C) report0(msg []interface{}, ok bool) bool { t.Helper() return t.report(ok, msg, callerFuncName(1), []string{}, []interface{}{}) } func (t *C) report1(actual interface{}, msg []interface{}, ok bool) bool { t.Helper() return t.report(ok, msg, callerFuncName(1), []string{nameActual}, []interface{}{actual}) } func (t *C) report2(actual, expected interface{}, msg []interface{}, ok bool) bool { t.Helper() checker, arg2Name := callerFuncName(1), nameExpected if strings.Contains(checker, "Match") { arg2Name = "Regex" } return t.report(ok, msg, checker, []string{nameActual, arg2Name}, []interface{}{actual, expected}) } func (t *C) report3(actual, expected1, expected2 interface{}, msg []interface{}, ok bool) bool { t.Helper() checker, arg2Name, arg3Name := callerFuncName(1), "arg1", "arg2" switch { case strings.Contains(checker, "Between"): arg2Name, arg3Name = "Min", "Max" case strings.Contains(checker, "Delta"): arg2Name, arg3Name = nameExpected, "Delta" case strings.Contains(checker, "SMAPE"): arg2Name, arg3Name = nameExpected, "SMAPE" } return t.report(ok, msg, checker, []string{nameActual, arg2Name, arg3Name}, []interface{}{actual, expected1, expected2}) } // Must interrupt test using t.FailNow if called with false value. // // This provides an easy way to turn any check into assertion: // // t.Must(t.Nil(err)) func (t *C) Must(continueTest bool, msg ...interface{}) { //nolint:revive // False positive. t.Helper() t.report0(msg, continueTest) if !continueTest { t.FailNow() } } type ( // ShouldFunc1 is like Nil or Zero. ShouldFunc1 func(t *C, actual interface{}) bool // ShouldFunc2 is like Equal or Match. ShouldFunc2 func(t *C, actual, expected interface{}) bool ) // Should use user-provided check function to do actual check. // // anyShouldFunc must have type ShouldFunc1 or ShouldFunc2. It should // return true if check was successful. There is no need to call t.Error // in anyShouldFunc - this will be done automatically when it returns. // // args must contain at least 1 element for ShouldFunc1 and at least // 2 elements for ShouldFunc2. // Rest of elements will be processed as usual msg ...interface{} param. // // Example: // // func bePositive(_ *check.C, actual interface{}) bool { // return actual.(int) > 0 // } // func TestCustomCheck(tt *testing.T) { // t := check.T(tt) // t.Should(bePositive, 42, "custom check!!!") // } func (t *C) Should(anyShouldFunc interface{}, args ...interface{}) bool { t.Helper() switch f := anyShouldFunc.(type) { case func(t *C, actual interface{}) bool: return t.should1(f, args...) case func(t *C, actual, expected interface{}) bool: return t.should2(f, args...) default: panic("anyShouldFunc is not a ShouldFunc1 or ShouldFunc2") } } func (t *C) should1(f ShouldFunc1, args ...interface{}) bool { t.Helper() if len(args) < 1 { panic("not enough params for " + funcName(f)) } actual, msg := args[0], args[1:] return t.reportShould1(funcName(f), actual, msg, f(t, actual)) } func (t *C) should2(f ShouldFunc2, args ...interface{}) bool { t.Helper() const minArgs = 2 if len(args) < minArgs { panic("not enough params for " + funcName(f)) } actual, expected, msg := args[0], args[1], args[2:] return t.reportShould2(funcName(f), actual, expected, msg, f(t, actual, expected)) } // Nil checks for actual == nil. // // There is one subtle difference between this check and Go `== nil` (if // this surprises you then you should read // https://golang.org/doc/faq#nil_error first): // // var intPtr *int // var empty interface{} // var notEmpty interface{} = intPtr // t.True(intPtr == nil) // TRUE // t.True(empty == nil) // TRUE // t.True(notEmpty == nil) // FALSE // // When you call this function your actual value will be stored in // interface{} argument, and this makes any typed nil pointer value `!= // nil` inside this function (just like in example above happens with // notEmpty variable). // // As it is very common case to check some typed pointer using Nil this // check has to work around and detect nil even if usual `== nil` return // false. But this has nasty side effect: if actual value already was of // interface type and contains some typed nil pointer (which is usually // bad thing and should be avoid) then Nil check will pass (which may be // not what you want/expect): // // t.Nil(nil) // TRUE // t.Nil(intPtr) // TRUE // t.Nil(empty) // TRUE // t.Nil(notEmpty) // WARNING: also TRUE! // // Second subtle case is less usual: uintptr(0) is sorta nil, but not // really, so Nil(uintptr(0)) will fail. Nil(unsafe.Pointer(nil)) will // also fail, for the same reason. Please do not use this and consider // this behaviour undefined, because it may change in the future. func (t *C) Nil(actual interface{}, msg ...interface{}) bool { t.Helper() return t.report1(actual, msg, isNil(actual)) } func isNil(actual interface{}) bool { switch val := reflect.ValueOf(actual); val.Kind() { case reflect.Invalid: return actual == nil case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice: return val.IsNil() case reflect.Uintptr, reflect.UnsafePointer: // Subtle cases documented above. case reflect.Interface: // ??? // Can't be nil: case reflect.Struct, reflect.Array, reflect.Bool, reflect.String: case reflect.Complex128, reflect.Complex64, reflect.Float32, reflect.Float64: case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int8: case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint8: } return false } // NotNil checks for actual != nil. // // See Nil about subtle case in check logic. func (t *C) NotNil(actual interface{}, msg ...interface{}) bool { t.Helper() return t.report0(msg, !isNil(actual)) } // Error is equivalent to Log followed by Fail. // // It is like t.Errorf with TODO() and statistics support. func (t *C) Error(msg ...interface{}) { t.Helper() t.report0(msg, false) } // True checks for cond == true. // // This can be useful to use your own custom checks, but this way you // won't get nice dump/diff for actual/expected values. You'll still have // statistics about passed/failed checks and it's shorter than usual: // // if !cond { // t.Errorf(msg...) // } func (t *C) True(cond bool, msg ...interface{}) bool { t.Helper() return t.report0(msg, cond) } // False checks for cond == false. func (t *C) False(cond bool, msg ...interface{}) bool { t.Helper() return t.report0(msg, !cond) } // Equal checks for actual == expected. // // Note: For time.Time it uses actual.Equal(expected) instead. func (t *C) Equal(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.report2(actual, expected, msg, isEqual(actual, expected)) } func isEqual(actual, expected interface{}) bool { switch actual := actual.(type) { case time.Time: return actual.Equal(expected.(time.Time)) default: return actual == expected } } // EQ is a synonym for Equal. func (t *C) EQ(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.Equal(actual, expected, msg...) } // NotEqual checks for actual != expected. func (t *C) NotEqual(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.report2(actual, expected, msg, !isEqual(actual, expected)) } // NE is a synonym for NotEqual. func (t *C) NE(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.NotEqual(actual, expected, msg...) } // BytesEqual checks for bytes.Equal(actual, expected). // // Hint: BytesEqual([]byte{}, []byte(nil)) is true (unlike DeepEqual). func (t *C) BytesEqual(actual, expected []byte, msg ...interface{}) bool { t.Helper() return t.report2(actual, expected, msg, bytes.Equal(actual, expected)) } // NotBytesEqual checks for !bytes.Equal(actual, expected). // // Hint: NotBytesEqual([]byte{}, []byte(nil)) is false (unlike NotDeepEqual). func (t *C) NotBytesEqual(actual, expected []byte, msg ...interface{}) bool { t.Helper() return t.report1(actual, msg, !bytes.Equal(actual, expected)) } // DeepEqual checks for reflect.DeepEqual(actual, expected). // It will also use Equal method for types which implements it // (e.g. time.Time, decimal.Decimal, etc.). // It will use proto.Equal for protobuf messages. func (t *C) DeepEqual(actual, expected interface{}, msg ...interface{}) bool { t.Helper() protoActual, proto1 := actual.(protoreflect.ProtoMessage) protoExpected, proto2 := expected.(protoreflect.ProtoMessage) if proto1 && proto2 { return t.report2(actual, expected, msg, proto.Equal(protoActual, protoExpected)) } return t.report2(actual, expected, msg, deepequal.DeepEqual(actual, expected)) } // NotDeepEqual checks for !reflect.DeepEqual(actual, expected). // It will also use Equal method for types which implements it // (e.g. time.Time, decimal.Decimal, etc.). // It will use proto.Equal for protobuf messages. func (t *C) NotDeepEqual(actual, expected interface{}, msg ...interface{}) bool { t.Helper() protoActual, proto1 := actual.(protoreflect.ProtoMessage) protoExpected, proto2 := expected.(protoreflect.ProtoMessage) if proto1 && proto2 { return t.report1(actual, msg, !proto.Equal(protoActual, protoExpected)) } return t.report1(actual, msg, !deepequal.DeepEqual(actual, expected)) } // Match checks for regex.MatchString(actual). // // Regex type can be either *regexp.Regexp or string. // // Actual type can be: // - string - will match with actual // - []byte - will match with string(actual) // - []rune - will match with string(actual) // - fmt.Stringer - will match with actual.String() // - error - will match with actual.Error() // - nil - will not match (even with empty regex) func (t *C) Match(actual, regex interface{}, msg ...interface{}) bool { t.Helper() ok := isMatch(&actual, regex) return t.report2(actual, regex, msg, ok) } // isMatch updates actual to be a real string used for matching, to make // dump easier to understand, but this result in losing type information. func isMatch(actual *interface{}, regex interface{}) bool { //nolint:gocritic // False positive. if *actual == nil { return false } if !stringify(actual) { panic("actual is not a string, []byte, []rune, fmt.Stringer, error or nil") } s := (*actual).(string) //nolint:forcetypeassert // False positive. switch v := regex.(type) { case *regexp.Regexp: return v.MatchString(s) case string: return regexp.MustCompile(v).MatchString(s) } panic("regex is not a *regexp.Regexp or string") } func stringify(arg *interface{}) bool { //nolint:gocritic // False positive. switch v := (*arg).(type) { case nil: return false case error: *arg = v.Error() case fmt.Stringer: *arg = v.String() default: typ := reflect.TypeOf(*arg) switch typ.Kind() { //nolint:exhaustive // Covered by default case. case reflect.String: case reflect.Slice: switch typ.Elem().Kind() { //nolint:exhaustive // Covered by default case. case reflect.Uint8, reflect.Int32: default: return false } default: return false } *arg = reflect.ValueOf(*arg).Convert(typString).Interface() } return true } // NotMatch checks for !regex.MatchString(actual). // // See Match about supported actual/regex types and check logic. func (t *C) NotMatch(actual, regex interface{}, msg ...interface{}) bool { t.Helper() ok := !isMatch(&actual, regex) return t.report2(actual, regex, msg, ok) } // Contains checks is actual contains substring/element expected. // // Element of array/slice/map is checked using == expected. // // Type of expected depends on type of actual: // - if actual is a string, then expected should be a string // - if actual is an array, then expected should have array's element type // - if actual is a slice, then expected should have slice's element type // - if actual is a map, then expected should have map's value type // // Hint: In a map it looks for a value, if you need to look for a key - // use HasKey instead. func (t *C) Contains(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.report2(actual, expected, msg, isContains(actual, expected)) } func isContains(actual, expected interface{}) (found bool) { switch valActual := reflect.ValueOf(actual); valActual.Kind() { //nolint:exhaustive // Covered by default case. case reflect.String: strActual := valActual.Convert(typString).Interface().(string) //nolint:forcetypeassert // False positive. valExpected := reflect.ValueOf(expected) if valExpected.Kind() != reflect.String { panic("expected underlying type is not a string") } strExpected := valExpected.Convert(typString).Interface().(string) //nolint:forcetypeassert // False positive. found = strings.Contains(strActual, strExpected) case reflect.Map: if valActual.Type().Elem() != reflect.TypeOf(expected) { panic("expected type not match actual element type") } keys := valActual.MapKeys() for i := 0; i < len(keys) && !found; i++ { found = valActual.MapIndex(keys[i]).Interface() == expected } case reflect.Slice, reflect.Array: if valActual.Type().Elem() != reflect.TypeOf(expected) { panic("expected type not match actual element type") } for i := 0; i < valActual.Len() && !found; i++ { found = valActual.Index(i).Interface() == expected } default: panic("actual is not a string, array, slice or map") } return found } // NotContains checks is actual not contains substring/element expected. // // See Contains about supported actual/expected types and check logic. func (t *C) NotContains(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.report2(actual, expected, msg, !isContains(actual, expected)) } // HasKey checks is actual has key expected. func (t *C) HasKey(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.report2(actual, expected, msg, hasKey(actual, expected)) } func hasKey(actual, expected interface{}) bool { return reflect.ValueOf(actual).MapIndex(reflect.ValueOf(expected)).IsValid() } // NotHasKey checks is actual has no key expected. func (t *C) NotHasKey(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.report2(actual, expected, msg, !hasKey(actual, expected)) } // Zero checks is actual is zero value of it's type. func (t *C) Zero(actual interface{}, msg ...interface{}) bool { t.Helper() return t.report1(actual, msg, isZero(actual)) } func isZero(actual interface{}) bool { if isNil(actual) { return true } else if typ := reflect.TypeOf(actual); typ.Comparable() { // Not Func, Map, Slice, Array with non-comparable // elements, Struct with non-comparable fields. return actual == reflect.Zero(typ).Interface() } else if typ.Kind() == reflect.Array { zero := true val := reflect.ValueOf(actual) for i := 0; i < val.Len() && zero; i++ { zero = isZero(val.Index(i).Interface()) } return zero } // Func, Struct with non-comparable fields. // Non-nil Map, Slice. return false } // NotZero checks is actual is not zero value of it's type. func (t *C) NotZero(actual interface{}, msg ...interface{}) bool { t.Helper() return t.report1(actual, msg, !isZero(actual)) } // Len checks is len(actual) == expected. func (t *C) Len(actual interface{}, expected int, msg ...interface{}) bool { t.Helper() l := reflect.ValueOf(actual).Len() return t.report2(l, expected, msg, l == expected) } // NotLen checks is len(actual) != expected. func (t *C) NotLen(actual interface{}, expected int, msg ...interface{}) bool { t.Helper() l := reflect.ValueOf(actual).Len() return t.report2(l, expected, msg, l != expected) } // Err checks is actual error is the same as expected error. // // It tries to recursively unwrap actual before checking using // errors.Unwrap() and github.com/pkg/errors.Cause(). // // It will use proto.Equal for gRPC status errors. // // They may be a different instances, but must have same type and value. // // Checking for nil is okay, but using Nil(actual) instead is more clean. func (t *C) Err(actual, expected error, msg ...interface{}) bool { t.Helper() actual2 := unwrapErr(actual) equal := fmt.Sprintf("%#v", actual2) == fmt.Sprintf("%#v", expected) _, proto1 := actual2.(interface{ GRPCStatus() *status.Status }) //nolint:errorlint // False positive. _, proto2 := expected.(interface{ GRPCStatus() *status.Status }) //nolint:errorlint // False positive. if proto1 || proto2 { equal = proto.Equal(status.Convert(actual2).Proto(), status.Convert(expected).Proto()) } return t.report2(actual, expected, msg, equal) } func unwrapErr(err error) (actual error) { defer func() { _ = recover() }() actual = err for { actual = pkgerrors.Cause(actual) wrapped, ok := actual.(interface{ Unwrap() error }) //nolint:errorlint // False positive. if !ok { break } unwrapped := wrapped.Unwrap() if unwrapped == nil { break } actual = unwrapped } return actual } // NotErr checks is actual error is not the same as expected error. // // It tries to recursively unwrap actual before checking using // errors.Unwrap() and github.com/pkg/errors.Cause(). // // It will use !proto.Equal for gRPC status errors. // // They must have either different types or values (or one should be nil). // Different instances with same type and value will be considered the // same error, and so is both nil. func (t *C) NotErr(actual, expected error, msg ...interface{}) bool { t.Helper() actual2 := unwrapErr(actual) notEqual := fmt.Sprintf("%#v", actual2) != fmt.Sprintf("%#v", expected) _, proto1 := actual2.(interface{ GRPCStatus() *status.Status }) //nolint:errorlint // False positive. _, proto2 := expected.(interface{ GRPCStatus() *status.Status }) //nolint:errorlint // False positive. if proto1 || proto2 { notEqual = !proto.Equal(status.Convert(actual2).Proto(), status.Convert(expected).Proto()) } return t.report1(actual, msg, notEqual) } // Panic checks is actual() panics. // // It is able to detect panic(nil)… but you should try to avoid using this. func (t *C) Panic(actual func(), msg ...interface{}) bool { t.Helper() didPanic := true func() { defer func() { _ = recover() }() actual() didPanic = false }() return t.report0(msg, didPanic) } // NotPanic checks is actual() don't panics. // // It is able to detect panic(nil)… but you should try to avoid using this. func (t *C) NotPanic(actual func(), msg ...interface{}) bool { t.Helper() didPanic := true func() { defer func() { _ = recover() }() actual() didPanic = false }() return t.report0(msg, !didPanic) } // PanicMatch checks is actual() panics and panic text match regex. // // Regex type can be either *regexp.Regexp or string. // // In case of panic(nil) it will match like panic(""). func (t *C) PanicMatch(actual func(), regex interface{}, msg ...interface{}) bool { t.Helper() var panicVal interface{} didPanic := true func() { defer func() { panicVal = recover() }() actual() didPanic = false }() if !didPanic { return t.report0(msg, false) } switch panicVal.(type) { case string, error: default: panicVal = fmt.Sprintf("%#v", panicVal) } ok := isMatch(&panicVal, regex) return t.report2(panicVal, regex, msg, ok) } // PanicNotMatch checks is actual() panics and panic text not match regex. // // Regex type can be either *regexp.Regexp or string. // // In case of panic(nil) it will match like panic(""). func (t *C) PanicNotMatch(actual func(), regex interface{}, msg ...interface{}) bool { t.Helper() var panicVal interface{} didPanic := true func() { defer func() { panicVal = recover() }() actual() didPanic = false }() if !didPanic { return t.report0(msg, false) } switch panicVal.(type) { case string, error: default: panicVal = fmt.Sprintf("%#v", panicVal) } ok := !isMatch(&panicVal, regex) return t.report2(panicVal, regex, msg, ok) } // Less checks for actual < expected. // // Both actual and expected must be either: // - signed integers // - unsigned integers // - floats // - strings // - time.Time func (t *C) Less(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.report2(actual, expected, msg, isLess(actual, expected)) } func isLess(actual, expected interface{}) bool { switch v1, v2 := reflect.ValueOf(actual), reflect.ValueOf(expected); v1.Kind() { //nolint:exhaustive // Covered by default case. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return v1.Int() < v2.Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return v1.Uint() < v2.Uint() case reflect.Float32, reflect.Float64: return v1.Float() < v2.Float() case reflect.String: return v1.String() < v2.String() default: if actualTime, ok := actual.(time.Time); ok { return actualTime.Before(expected.(time.Time)) } } panic("actual is not a number, string or time.Time") } // LT is a synonym for Less. func (t *C) LT(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.Less(actual, expected, msg...) } // LessOrEqual checks for actual <= expected. // // Both actual and expected must be either: // - signed integers // - unsigned integers // - floats // - strings // - time.Time func (t *C) LessOrEqual(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.report2(actual, expected, msg, !isGreater(actual, expected)) } func isGreater(actual, expected interface{}) bool { switch v1, v2 := reflect.ValueOf(actual), reflect.ValueOf(expected); v1.Kind() { //nolint:exhaustive // Covered by default case. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return v1.Int() > v2.Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return v1.Uint() > v2.Uint() case reflect.Float32, reflect.Float64: return v1.Float() > v2.Float() case reflect.String: return v1.String() > v2.String() default: if actualTime, ok := actual.(time.Time); ok { return actualTime.After(expected.(time.Time)) } } panic("actual is not a number, string or time.Time") } // LE is a synonym for LessOrEqual. func (t *C) LE(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.LessOrEqual(actual, expected, msg...) } // Greater checks for actual > expected. // // Both actual and expected must be either: // - signed integers // - unsigned integers // - floats // - strings // - time.Time func (t *C) Greater(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.report2(actual, expected, msg, isGreater(actual, expected)) } // GT is a synonym for Greater. func (t *C) GT(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.Greater(actual, expected, msg...) } // GreaterOrEqual checks for actual >= expected. // // Both actual and expected must be either: // - signed integers // - unsigned integers // - floats // - strings // - time.Time func (t *C) GreaterOrEqual(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.report2(actual, expected, msg, !isLess(actual, expected)) } // GE is a synonym for GreaterOrEqual. func (t *C) GE(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.GreaterOrEqual(actual, expected, msg...) } // Between checks for min < actual < max. // // All three actual, min and max must be either: // - signed integers // - unsigned integers // - floats // - strings // - time.Time func (t *C) Between(actual, min, max interface{}, msg ...interface{}) bool { t.Helper() return t.report3(actual, min, max, msg, isBetween(actual, min, max)) } func isBetween(actual, min, max interface{}) bool { switch v, vmin, vmax := reflect.ValueOf(actual), reflect.ValueOf(min), reflect.ValueOf(max); v.Kind() { //nolint:exhaustive // Covered by default case. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return vmin.Int() < v.Int() && v.Int() < vmax.Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return vmin.Uint() < v.Uint() && v.Uint() < vmax.Uint() case reflect.Float32, reflect.Float64: return vmin.Float() < v.Float() && v.Float() < vmax.Float() case reflect.String: return vmin.String() < v.String() && v.String() < vmax.String() default: if actualTime, ok := actual.(time.Time); ok { minTime := min.(time.Time) //nolint:forcetypeassert // Want panic. maxTime := max.(time.Time) //nolint:forcetypeassert // Want panic. return minTime.Before(actualTime) && actualTime.Before(maxTime) } } panic("actual is not a number, string or time.Time") } // NotBetween checks for actual <= min or max <= actual. // // All three actual, min and max must be either: // - signed integers // - unsigned integers // - floats // - strings // - time.Time func (t *C) NotBetween(actual, min, max interface{}, msg ...interface{}) bool { t.Helper() return t.report3(actual, min, max, msg, !isBetween(actual, min, max)) } // BetweenOrEqual checks for min <= actual <= max. // // All three actual, min and max must be either: // - signed integers // - unsigned integers // - floats // - strings // - time.Time func (t *C) BetweenOrEqual(actual, min, max interface{}, msg ...interface{}) bool { t.Helper() return t.report3(actual, min, max, msg, isBetween(actual, min, max) || isEqual(actual, min) || isEqual(actual, max)) } // NotBetweenOrEqual checks for actual < min or max < actual. // // All three actual, min and max must be either: // - signed integers // - unsigned integers // - floats // - strings // - time.Time func (t *C) NotBetweenOrEqual(actual, min, max interface{}, msg ...interface{}) bool { t.Helper() return t.report3(actual, min, max, msg, !(isBetween(actual, min, max) || isEqual(actual, min) || isEqual(actual, max))) } // InDelta checks for expected-delta <= actual <= expected+delta. // // All three actual, expected and delta must be either: // - signed integers // - unsigned integers // - floats // - time.Time (in this case delta must be time.Duration) func (t *C) InDelta(actual, expected, delta interface{}, msg ...interface{}) bool { t.Helper() return t.report3(actual, expected, delta, msg, isInDelta(actual, expected, delta)) } func isInDelta(actual, expected, delta interface{}) bool { switch v, e, d := reflect.ValueOf(actual), reflect.ValueOf(expected), reflect.ValueOf(delta); v.Kind() { //nolint:exhaustive // Covered by default case. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: min, max := e.Int()-d.Int(), e.Int()+d.Int() return min <= v.Int() && v.Int() <= max case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: min, max := e.Uint()-d.Uint(), e.Uint()+d.Uint() return min <= v.Uint() && v.Uint() <= max case reflect.Float32, reflect.Float64: min, max := e.Float()-d.Float(), e.Float()+d.Float() return min <= v.Float() && v.Float() <= max default: if actualTime, ok := actual.(time.Time); ok { expectedTime := expected.(time.Time) //nolint:forcetypeassert // Want panic. dur := delta.(time.Duration) //nolint:forcetypeassert // Want panic. minTime, maxTime := expectedTime.Add(-dur), expectedTime.Add(dur) return minTime.Before(actualTime) && actualTime.Before(maxTime) || actualTime.Equal(minTime) || actualTime.Equal(maxTime) } } panic("actual is not a number or time.Time") } // NotInDelta checks for actual < expected-delta or expected+delta < actual. // // All three actual, expected and delta must be either: // - signed integers // - unsigned integers // - floats // - time.Time (in this case delta must be time.Duration) func (t *C) NotInDelta(actual, expected, delta interface{}, msg ...interface{}) bool { t.Helper() return t.report3(actual, expected, delta, msg, !isInDelta(actual, expected, delta)) } // InSMAPE checks that actual and expected have a symmetric mean absolute // percentage error (SMAPE) is less than given smape. // // Both actual and expected must be either: // - signed integers // - unsigned integers // - floats // // Allowed smape values are: 0.0 < smape < 100.0. // // Used formula returns SMAPE value between 0 and 100 (percents): // - 0.0 when actual == expected // - ~0.5 when they differs in ~1% // - ~5 when they differs in ~10% // - ~20 when they differs in 1.5 times // - ~33 when they differs in 2 times // - 50.0 when they differs in 3 times // - ~82 when they differs in 10 times // - 99.0+ when actual and expected differs in 200+ times // - 100.0 when only one of actual or expected is 0 or one of them is // positive while another is negative func (t *C) InSMAPE(actual, expected interface{}, smape float64, msg ...interface{}) bool { t.Helper() return t.report3(actual, expected, smape, msg, isInSMAPE(actual, expected, smape)) } func isInSMAPE(actual, expected interface{}, smape float64) bool { if !(0 < smape && smape < 100) { panic("smape is not in allowed range: 0 < smape < 100") } a := reflect.ValueOf(actual).Convert(typFloat64).Float() e := reflect.ValueOf(expected).Convert(typFloat64).Float() if a == 0 && e == 0 { return true // avoid division by zero in legal use case } return 100*math.Abs(e-a)/(math.Abs(e)+math.Abs(a)) < smape } // NotInSMAPE checks that actual and expected have a symmetric mean // absolute percentage error (SMAPE) is greater than or equal to given // smape. // // See InSMAPE about supported actual/expected types and check logic. func (t *C) NotInSMAPE(actual, expected interface{}, smape float64, msg ...interface{}) bool { t.Helper() return t.report3(actual, expected, smape, msg, !isInSMAPE(actual, expected, smape)) } // HasPrefix checks for strings.HasPrefix(actual, expected). // // Both actual and expected may have any of these types: // - string - will use as is // - []byte - will convert with string() // - []rune - will convert with string() // - fmt.Stringer - will convert with actual.String() // - error - will convert with actual.Error() // - nil - check will always fail func (t *C) HasPrefix(actual, expected interface{}, msg ...interface{}) bool { t.Helper() ok := isHasPrefix(&actual, &expected) return t.report2(actual, expected, msg, ok) } // isHasPrefix updates actual and expected to be a real string used for check, // to make dump easier to understand, but this result in losing type information. func isHasPrefix(actual, expected *interface{}) bool { //nolint:gocritic // False positive. if *actual == nil || *expected == nil { return false } if !stringify(actual) { panic("actual is not a string, []byte, []rune, fmt.Stringer, error or nil") } if !stringify(expected) { panic("expected is not a string, []byte, []rune, fmt.Stringer, error or nil") } return strings.HasPrefix((*actual).(string), (*expected).(string)) } // NotHasPrefix checks for !strings.HasPrefix(actual, expected). // // See HasPrefix about supported actual/expected types and check logic. func (t *C) NotHasPrefix(actual, expected interface{}, msg ...interface{}) bool { t.Helper() ok := !isHasPrefix(&actual, &expected) return t.report2(actual, expected, msg, ok) } // HasSuffix checks for strings.HasSuffix(actual, expected). // // Both actual and expected may have any of these types: // - string - will use as is // - []byte - will convert with string() // - []rune - will convert with string() // - fmt.Stringer - will convert with actual.String() // - error - will convert with actual.Error() // - nil - check will always fail func (t *C) HasSuffix(actual, expected interface{}, msg ...interface{}) bool { t.Helper() ok := isHasSuffix(&actual, &expected) return t.report2(actual, expected, msg, ok) } // isHasSuffix updates actual and expected to be a real string used for check, // to make dump easier to understand, but this result in losing type information. func isHasSuffix(actual, expected *interface{}) bool { //nolint:gocritic // False positive. if *actual == nil || *expected == nil { return false } if !stringify(actual) { panic("actual is not a string, []byte, []rune, fmt.Stringer, error or nil") } if !stringify(expected) { panic("expected is not a string, []byte, []rune, fmt.Stringer, error or nil") } return strings.HasSuffix((*actual).(string), (*expected).(string)) } // NotHasSuffix checks for !strings.HasSuffix(actual, expected). // // See HasSuffix about supported actual/expected types and check logic. func (t *C) NotHasSuffix(actual, expected interface{}, msg ...interface{}) bool { t.Helper() ok := !isHasSuffix(&actual, &expected) return t.report2(actual, expected, msg, ok) } // JSONEqual normalize formatting of actual and expected (if they're valid // JSON) and then checks for bytes.Equal(actual, expected). // // Both actual and expected may have any of these types: // - string // - []byte // - json.RawMessage // - *json.RawMessage // - nil // // In case any of actual or expected is nil or empty or (for string or // []byte) is invalid JSON - check will fail. func (t *C) JSONEqual(actual, expected interface{}, msg ...interface{}) bool { t.Helper() ok := isJSONEqual(actual, expected) if !ok { if buf := jsonify(actual); len(buf) != 0 { actual = buf } if buf := jsonify(expected); len(buf) != 0 { expected = buf } } return t.report2(actual, expected, msg, ok) } func isJSONEqual(actual, expected interface{}) bool { jsonActual, jsonExpected := jsonify(actual), jsonify(expected) return len(jsonActual) != 0 && len(jsonExpected) != 0 && bytes.Equal(jsonActual, jsonExpected) } func jsonify(arg interface{}) json.RawMessage { switch v := (arg).(type) { case nil: return nil case json.RawMessage: return v case *json.RawMessage: if v == nil { return nil } return *v } buf := reflect.ValueOf(arg).Convert(typBytes).Interface().([]byte) //nolint:forcetypeassert // Want panic. var v interface{} err := json.Unmarshal(buf, &v) if err != nil { return nil } buf, err = json.Marshal(v) if err != nil { return nil } return buf } // HasType checks is actual has same type as expected. func (t *C) HasType(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.report2(actual, expected, msg, reflect.TypeOf(actual) == reflect.TypeOf(expected)) } // NotHasType checks is actual has not same type as expected. func (t *C) NotHasType(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.report2(actual, expected, msg, reflect.TypeOf(actual) != reflect.TypeOf(expected)) } // Implements checks is actual implements interface pointed by expected. // // You must use pointer to interface type in expected: // // t.Implements(os.Stdin, (*io.Reader)(nil)) func (t *C) Implements(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.report2(actual, expected, msg, isImplements(actual, expected)) } func isImplements(actual, expected interface{}) bool { typActual := reflect.TypeOf(actual) if typActual.Kind() != reflect.Ptr { typActual = reflect.PtrTo(typActual) } return typActual.Implements(reflect.TypeOf(expected).Elem()) } // NotImplements checks is actual does not implements interface pointed by expected. // // You must use pointer to interface type in expected: // // t.NotImplements(os.Stdin, (*fmt.Stringer)(nil)) func (t *C) NotImplements(actual, expected interface{}, msg ...interface{}) bool { t.Helper() return t.report2(actual, expected, msg, !isImplements(actual, expected)) } check-1.6.0/check_test.go000066400000000000000000001350371410630575400152540ustar00rootroot00000000000000//nolint:goerr113 // It's just a test. package check_test import ( "encoding/json" "errors" "fmt" "io" "net" "os" "reflect" "regexp" "testing" "time" pkgerrors "github.com/pkg/errors" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/timestamppb" "github.com/powerman/check" ) func init() { time.Local = time.UTC } type ( myInt int myString string myStruct struct { i int s string } myError struct{ s string } ) func (e myError) Error() string { return e.s } var ( // Zero values for standard types. zBool bool zInt int zInt8 int8 zInt16 int16 zInt32 int32 zInt64 int64 zUint uint zUint8 uint8 zUint16 uint16 zUint32 uint32 zUint64 uint64 zUintptr uintptr zFloat32 float32 zFloat64 float64 zArray0 [0]int zArray1 [1]int zChan chan int zFunc func() zIface interface{} zMap map[int]int zSlice []int zString string zStruct struct{} // zUnsafe unsafe.Pointer // don't like to import unsafe. zBoolPtr *bool zIntPtr *int zInt8Ptr *int8 zInt16Ptr *int16 zInt32Ptr *int32 zInt64Ptr *int64 zUintPtr *uint zUint8Ptr *uint8 zUint16Ptr *uint16 zUint32Ptr *uint32 zUint64Ptr *uint64 zUintptrPtr *uintptr zFloat32Ptr *float32 zFloat64Ptr *float64 zArray0Ptr *[0]int zArray1Ptr *[1]int zChanPtr *chan int zFuncPtr *func() zIfacePtr *interface{} zMapPtr *map[int]int zSlicePtr *[]int zStringPtr *string zStructPtr *struct{} // zUnsafePtr *unsafe.Pointer // don't like to import unsafe // Zero values for named types. zMyInt myInt zMyString myString zJSON json.RawMessage zJSONPtr *json.RawMessage zTime time.Time zProto emptypb.Empty // Initialized but otherwise zero-like values. vChan = make(chan int) vFunc = func() {} vIface interface{} = zIntPtr vMap = make(map[int]int) vSlice = make([]int, 0) // Non-zero values. xBool = true xInt = -42 xInt8 int8 = -8 xInt16 int16 = -16 xInt32 int32 = -32 xInt64 int64 = -64 xUint uint = 42 xUint8 uint8 = 8 xUint16 uint16 = 16 xUint32 uint32 = 32 xUint64 uint64 = 64 xUintptr uintptr = 0xDEADBEEF xFloat32 float32 = -3.2 xFloat64 = 6.4 xArray1 = [1]int{-1} xChan = make(chan int, 1) xFunc = func() { panic(nil) } xIface io.Reader = os.Stdin xMap = map[int]int{2: -2, 3: -3, 5: -5} xSlice = []int{3, 5, 8} xString = "" xStruct = myStruct{i: 10, s: "ten"} // xUnsafe = unsafe.Pointer(&xUintptr) // don't like to import unsafe. xBoolPtr = &xBool xIntPtr = &xInt xInt8Ptr = &xInt8 xInt16Ptr = &xInt16 xInt32Ptr = &xInt32 xInt64Ptr = &xInt64 xUintPtr = &xUint xUint8Ptr = &xUint8 xUint16Ptr = &xUint16 xUint32Ptr = &xUint32 xUint64Ptr = &xUint64 xUintptrPtr = &xUintptr xFloat32Ptr = &xFloat32 xFloat64Ptr = &xFloat64 xArray1Ptr = &xArray1 xChanPtr = &xChan xFuncPtr = &xFunc xIfacePtr = &xIface xMapPtr = &xMap xSlicePtr = &xSlice xStringPtr = &xString xStructPtr = &xStruct // xUnsafePtr *unsafe.Pointer = &xUnsafe // don't like to import unsafe. xMyInt myInt = 31337 xMyString myString = "xyz" xJSON json.RawMessage = []byte(`{"s":"ten","i":10}`) xJSONPtr = &xJSON xTime = time.Now() xTimeEST = xTime.In(func() *time.Location { loc, _ := time.LoadLocation("EST"); return loc }()) xProto = timestamppb.Now() xGRPCErr = status.Error(codes.Unknown, "unknown") ) func TestTODO(tt *testing.T) { t := check.T(tt) // Normal tests. t.True(true) // If you need to mark just one/few broken tests: t.TODO().True(false) t.True(true) // If there are several broken tests mixed with working ones: todo := t.TODO() t.True(true) todo.True(false) t.True(true) if todo.True(false) { panic("never here") } // If all tests below this point are broken: t = t.TODO() t.True(false) // Second TODO() doesn't switch it off: t = t.TODO() t.True(false) } func TestError(tt *testing.T) { t := check.T(tt) t = t.TODO() t.Error() t.Error("message") t.Error("format: %q", "message") } func TestMustAll(tt *testing.T) { t := check.T(tt).MustAll() t.Nil(nil) t.NotNil(false) t.TODO().Nil(false) t.TODO().NotNil(nil) } func TestMust(tt *testing.T) { t := check.T(tt) t.Must(t.Nil(nil)) t.Must(t.NotNil(false)) } func bePositive(_ *check.C, actual interface{}) bool { return actual.(int) > 0 } func beEqual(_ *check.C, actual, expected interface{}) bool { return actual == expected } func TestCheckerShould(tt *testing.T) { t := check.T(tt) t.Should(bePositive, 42, "custom check!!!") t.Panic(func() { t.Should(bePositive, "42", "bad arg type") }) t.TODO().Should(func(_ *check.C, _ interface{}) bool { return false }, 42) t.Should(beEqual, 123, 123) t.TODO().Should(beEqual, 123, 124) t.Panic(func() { t.Should(func() {}, nil) }) t.Panic(func() { t.Should(bePositive) }) t.Panic(func() { t.Should(beEqual, nil) }) } func TestCheckerNilTrue(tt *testing.T) { t := check.T(tt) todo := t.TODO() // Ensure expected values t.Equal(zBool, false) // gometalinter hates zBool==false t.True(zInt == 0) t.True(zInt8 == 0) t.True(zInt16 == 0) t.True(zInt32 == 0) t.True(zInt64 == 0) t.True(zUint == 0) t.True(zUint8 == 0) t.True(zUint16 == 0) t.True(zUint32 == 0) t.True(zUint64 == 0) t.True(zUintptr == 0) t.True(zFloat32 == 0) t.True(zFloat64 == 0) t.True(zArray0 == [0]int{}) t.True(zArray1 == [1]int{}) t.True(zChan == nil) t.True(zFunc == nil) t.True(zIface == nil) t.True(zMap == nil) t.True(zSlice == nil) t.True(zString == "") t.True(zStruct == struct{}{}) // // t.True(zUnsafe == nil) t.True(zBoolPtr == nil) t.True(zIntPtr == nil) t.True(zInt8Ptr == nil) t.True(zInt16Ptr == nil) t.True(zInt32Ptr == nil) t.True(zInt64Ptr == nil) t.True(zUintPtr == nil) t.True(zUint8Ptr == nil) t.True(zUint16Ptr == nil) t.True(zUint32Ptr == nil) t.True(zUint64Ptr == nil) t.True(zUintptrPtr == nil) t.True(zFloat32Ptr == nil) t.True(zFloat64Ptr == nil) t.True(zArray0Ptr == nil) t.True(zArray1Ptr == nil) t.True(zChanPtr == nil) t.True(zFuncPtr == nil) t.True(zIfacePtr == nil) t.True(zMapPtr == nil) t.True(zSlicePtr == nil) t.True(zStringPtr == nil) t.True(zStructPtr == nil) // // t.True(zUnsafePtr == nil) t.True(zMyInt == 0) t.True(zMyString == "") t.True(zJSON == nil) t.True(zJSONPtr == nil) t.True(zTime == time.Time{}) t.False(vChan == nil) t.False(vFunc == nil) t.False(vIface == nil) t.False(vMap == nil) t.False(vSlice == nil) // Subtle case when t.Nil() differs from == nil. zIface = zIntPtr t.Nil(zIface) t.False(zIface == nil) zIface = nil t.Nil(zIface) t.True(zIface == nil) cases := []struct { equalNil bool isNil bool actual interface{} }{ {true, true, nil}, {false, false, zBool}, {false, false, zInt}, {false, false, zInt8}, {false, false, zInt16}, {false, false, zInt32}, {false, false, zInt64}, {false, false, zUint}, {false, false, zUint8}, {false, false, zUint16}, {false, false, zUint32}, {false, false, zUint64}, {false, false, zUintptr}, {false, false, zFloat32}, {false, false, zFloat64}, {false, false, zArray0}, {false, false, zArray1}, {false, true, zChan}, {false, true, zFunc}, {true, true, zIface}, {false, true, zMap}, {false, true, zSlice}, {false, false, zString}, {false, false, zStruct}, // {false, false, zUnsafe}, {false, true, zBoolPtr}, {false, true, zIntPtr}, {false, true, zInt8Ptr}, {false, true, zInt16Ptr}, {false, true, zInt32Ptr}, {false, true, zInt64Ptr}, {false, true, zUintPtr}, {false, true, zUint8Ptr}, {false, true, zUint16Ptr}, {false, true, zUint32Ptr}, {false, true, zUint64Ptr}, {false, true, zUintptrPtr}, {false, true, zFloat32Ptr}, {false, true, zFloat64Ptr}, {false, true, zArray0Ptr}, {false, true, zArray1Ptr}, {false, true, zChanPtr}, {false, true, zFuncPtr}, {false, true, zIfacePtr}, {false, true, zMapPtr}, {false, true, zSlicePtr}, {false, true, zStringPtr}, {false, true, zStructPtr}, // {false, true, zUnsafePtr}, {false, false, zMyInt}, {false, false, zMyString}, {false, true, zJSON}, {false, true, zJSONPtr}, {false, false, zTime}, {false, false, vChan}, {false, false, vFunc}, {false, true, vIface}, // WARNING false-positive (documented) {false, false, vMap}, {false, false, vSlice}, } for i, v := range cases { msg := fmt.Sprintf("case %d: %#v", i, v.actual) if v.equalNil { t.True(v.actual == nil, msg) } else { t.False(v.actual == nil, msg) } if v.isNil { t.Nil(v.actual, msg) todo.NotNil(v.actual, msg) } else { todo.Nil(v.actual, msg) t.NotNil(v.actual, msg) } } } func TestCheckerEqual(tt *testing.T) { t := check.T(tt) todo := t.TODO() cases := []struct { comparable bool actual interface{} actual2 interface{} }{ {true, zBool, xBool}, {true, zInt, xInt}, {true, zInt8, xInt8}, {true, zInt16, xInt16}, {true, zInt32, xInt32}, {true, zInt64, xInt64}, {true, zUint, xUint}, {true, zUint8, xUint8}, {true, zUint16, xUint16}, {true, zUint32, xUint32}, {true, zUint64, xUint64}, {true, zUintptr, xUintptr}, {true, zFloat32, xFloat32}, {true, zFloat64, xFloat64}, {true, zArray0, xArray1}, {true, zArray1, xArray1}, {true, zChan, xChan}, {false, zFunc, xFunc}, {true, zIface, xIface}, {false, zMap, xMap}, {false, zSlice, xSlice}, {true, zString, xString}, {true, zStruct, xStruct}, {true, zBoolPtr, xBoolPtr}, {true, zIntPtr, xIntPtr}, {true, zInt8Ptr, xInt8Ptr}, {true, zInt16Ptr, xInt16Ptr}, {true, zInt32Ptr, xInt32Ptr}, {true, zInt64Ptr, xInt64Ptr}, {true, zUintPtr, xUintPtr}, {true, zUint8Ptr, xUint8Ptr}, {true, zUint16Ptr, xUint16Ptr}, {true, zUint32Ptr, xUint32Ptr}, {true, zUint64Ptr, xUint64Ptr}, {true, zUintptrPtr, xUintptrPtr}, {true, zFloat32Ptr, xFloat32Ptr}, {true, zFloat64Ptr, xFloat64Ptr}, {true, zArray0Ptr, xArray1Ptr}, {true, zArray1Ptr, xArray1Ptr}, {true, zChanPtr, xChanPtr}, {true, zFuncPtr, xFuncPtr}, {true, zIfacePtr, xIfacePtr}, {true, zMapPtr, xMapPtr}, {true, zSlicePtr, xSlicePtr}, {true, zStringPtr, xStringPtr}, {true, zStructPtr, xStructPtr}, {true, zMyInt, xMyInt}, {true, zMyString, xMyString}, {false, zJSON, xJSON}, {true, zJSONPtr, xJSONPtr}, {true, zTime, xTime}, {false, zProto, xProto}, //nolint:govet // This is dirty (copylocks), but it's a test. {true, vChan, xChan}, {false, vFunc, xFunc}, {true, vIface, xIface}, {false, vMap, xMap}, {false, vSlice, xSlice}, {true, "one\ntwo\nend", "one\nTWO\nend"}, {true, io.EOF, io.ErrUnexpectedEOF}, {true, t, tt}, {true, int64(42), int32(42)}, {false, []byte{}, []byte(nil)}, } for _, v := range cases { if v.comparable { t.Equal(v.actual, v.actual) t.EQ(v.actual, v.actual) t.DeepEqual(v.actual, v.actual) todo.NotEqual(v.actual, v.actual) todo.NE(v.actual, v.actual) todo.NotDeepEqual(v.actual, v.actual) t.Equal(v.actual2, v.actual2) t.EQ(v.actual2, v.actual2) t.DeepEqual(v.actual2, v.actual2) todo.NotEqual(v.actual2, v.actual2) todo.NE(v.actual2, v.actual2) todo.NotDeepEqual(v.actual2, v.actual2) todo.Equal(v.actual, v.actual2) todo.EQ(v.actual, v.actual2) todo.DeepEqual(v.actual, v.actual2) t.NotEqual(v.actual, v.actual2) t.NE(v.actual, v.actual2) t.NotDeepEqual(v.actual, v.actual2) } else { t.Panic(func() { t.Equal(v.actual, v.actual) }) t.Panic(func() { t.EQ(v.actual, v.actual) }) t.Panic(func() { t.NotEqual(v.actual, v.actual) }) t.Panic(func() { t.NE(v.actual, v.actual) }) if reflect.TypeOf(v.actual).Kind() != reflect.Func { t.DeepEqual(v.actual, v.actual) todo.NotDeepEqual(v.actual, v.actual) t.DeepEqual(v.actual2, v.actual2) todo.NotDeepEqual(v.actual2, v.actual2) todo.DeepEqual(v.actual, v.actual2) t.NotDeepEqual(v.actual, v.actual2) } } } // No alternative value for .actual2. t.Equal(nil, nil) t.EQ(nil, nil) t.DeepEqual(nil, nil) todo.NotEqual(nil, nil) todo.NE(nil, nil) todo.NotDeepEqual(nil, nil) // Equal match, DeepEqual not match. t.False(xTime == xTimeEST) t.Equal(xTime, xTimeEST) t.EQ(xTime, xTimeEST) t.DeepEqual(xTime, xTimeEST) todo.NotEqual(xTime, xTimeEST) todo.NE(xTime, xTimeEST) todo.NotDeepEqual(xTime, xTimeEST) // Equal not match or panic, DeepEqual match. type notComparable struct { s string is []int } cases = []struct { comparable bool actual interface{} actual2 interface{} }{ {true, io.EOF, errors.New("EOF")}, {true, &testing.T{}, &testing.T{}}, {false, []byte{2, 5}, []byte{2, 5}}, {false, notComparable{"a", []int{3, 5}}, notComparable{"a", []int{3, 5}}}, {false, zProto, zProto}, //nolint:govet // This is dirty (copylocks), but it's a test. {false, xGRPCErr, xGRPCErr}, } for _, v := range cases { if v.comparable { t.False(v.actual == v.actual2) todo.Equal(v.actual, v.actual2) todo.EQ(v.actual, v.actual2) t.NotEqual(v.actual, v.actual2) t.NE(v.actual, v.actual2) } t.DeepEqual(v.actual, v.actual2) todo.NotDeepEqual(v.actual, v.actual2) } } func TestCheckerBytesEqual(tt *testing.T) { t := check.T(tt) todo := t.TODO() cases := []struct { equal bool actual []byte expected []byte }{ {true, nil, nil}, {true, []byte(nil), []byte(nil)}, {true, []byte{}, []byte{}}, {true, []byte(nil), nil}, {true, []byte{}, nil}, {true, []byte(nil), []byte{}}, {true, []byte{0}, []byte{0}}, {false, []byte{0}, nil}, {false, []byte{0}, []byte(nil)}, {false, []byte{0}, []byte{}}, {false, []byte{0}, []byte{0, 0}}, } for _, v := range cases { if v.equal { t.BytesEqual(v.actual, v.expected) todo.NotBytesEqual(v.actual, v.expected) } else { todo.BytesEqual(v.actual, v.expected) t.NotBytesEqual(v.actual, v.expected) } } } func TestCheckerMatch(tt *testing.T) { t := check.T(tt) todo := t.TODO() types := []struct { actual bool expected bool zero interface{} }{ {true, false, nil}, {false, false, zBool}, {false, false, zInt}, {false, false, zInt8}, {false, false, zInt16}, {false, false, zInt32}, {false, false, zInt64}, {false, false, zUint}, {false, false, zUint8}, {false, false, zUint16}, {false, false, zUint32}, {false, false, zUint64}, {false, false, zUintptr}, {false, false, zFloat32}, {false, false, zFloat64}, {false, false, zArray0}, {false, false, zArray1}, {false, false, zChan}, {false, false, zFunc}, {false, false, zIface}, {false, false, zMap}, {false, false, zSlice}, {true, true, zString}, {false, false, zStruct}, {false, false, zBoolPtr}, {false, false, zIntPtr}, {false, false, zInt8Ptr}, {false, false, zInt16Ptr}, {false, false, zInt32Ptr}, {false, false, zInt64Ptr}, {false, false, zUintPtr}, {false, false, zUint8Ptr}, {false, false, zUint16Ptr}, {false, false, zUint32Ptr}, {false, false, zUint64Ptr}, {false, false, zUintptrPtr}, {false, false, zFloat32Ptr}, {false, false, zFloat64Ptr}, {false, false, zArray0Ptr}, {false, false, zArray1Ptr}, {false, false, zChanPtr}, {false, false, zFuncPtr}, {false, false, zIfacePtr}, {false, false, zMapPtr}, {false, false, zSlicePtr}, {false, false, zStringPtr}, {false, false, zStructPtr}, {false, false, zMyInt}, {true, false, zMyString}, {true, false, zJSON}, {false, false, zJSONPtr}, {true, false, zTime}, {true, false, time.Sunday}, {true, false, errors.New("")}, {true, false, []byte(nil)}, {true, false, []rune(nil)}, {true, true, regexp.MustCompile("")}, // it's also a Stringer {false, false, (*regexp.Regexp)(nil)}, {false, false, regexp.Regexp{}}, } for i, va := range types { for j, ve := range types { msg := fmt.Sprintf("case %d/%d: %#v, %#v", i, j, va.zero, ve.zero) switch va.zero.(type) { case nil: todo.Match(va.zero, ve.zero, msg) default: if va.actual && ve.expected { t.Match(va.zero, ve.zero, msg) } else { t.Panic(func() { t.Match(va.zero, ve.zero) }, msg) } } } } cases := []struct { actual interface{} regexMatch interface{} regexNotMatch interface{} }{ {"", `^$`, `.`}, {myString("Test"), regexp.MustCompile(`st$`), regexp.MustCompile(`ST$`)}, {[]byte(nil), `^$`, `nil`}, {[]byte("Test"), regexp.MustCompile(`st$`), regexp.MustCompile(`ST$`)}, {[]rune(nil), `^$`, `nil`}, {[]rune("Test"), regexp.MustCompile(`st$`), regexp.MustCompile(`ST$`)}, {zTime, `00:00:00`, `01:01:01`}, {time.Sunday, regexp.MustCompile(`^Sun`), regexp.MustCompile(`Sun$`)}, {errors.New(""), `^$`, `nil`}, {io.EOF, regexp.MustCompile(`^EO`), regexp.MustCompile(`EO$`)}, } for _, v := range cases { t.Match(v.actual, v.regexMatch) todo.Match(v.actual, v.regexNotMatch) } // No value for .regexMatch. todo.Match(nil, ``) todo.Match(nil, regexp.MustCompile(``)) t.NotMatch(nil, ``) t.NotMatch(nil, regexp.MustCompile(``)) } func TestCheckerContains(tt *testing.T) { t := check.T(tt) failures := []struct { panic bool actual interface{} expected interface{} }{ {true, nil, nil}, {true, zBool, zBool}, {true, zInt, zInt}, {true, zInt8, zInt8}, {true, zInt16, zInt16}, {true, zInt32, zInt32}, {true, zInt64, zInt64}, {true, zUint, zUint}, {true, zUint8, zUint8}, {true, zUint16, zUint16}, {true, zUint32, zUint32}, {true, zUint64, zUint64}, {true, zUintptr, zUintptr}, {true, zFloat32, zFloat32}, {true, zFloat64, zFloat64}, {true, zArray0, zBool}, {false, zArray0, xInt}, {true, zArray1, zBool}, {false, zArray1, xInt}, {true, zChan, zChan}, {true, zFunc, zFunc}, {true, zIface, zIface}, {true, zMap, zBool}, {false, zMap, xInt}, {true, zSlice, zBool}, {false, zSlice, xInt}, {true, zString, zBool}, {false, zString, xString}, {true, zStruct, zStruct}, {true, zBoolPtr, zBoolPtr}, {true, zIntPtr, zIntPtr}, {true, zInt8Ptr, zInt8Ptr}, {true, zInt16Ptr, zInt16Ptr}, {true, zInt32Ptr, zInt32Ptr}, {true, zInt64Ptr, zInt64Ptr}, {true, zUintPtr, zUintPtr}, {true, zUint8Ptr, zUint8Ptr}, {true, zUint16Ptr, zUint16Ptr}, {true, zUint32Ptr, zUint32Ptr}, {true, zUint64Ptr, zUint64Ptr}, {true, zUintptrPtr, zUintptrPtr}, {true, zFloat32Ptr, zFloat32Ptr}, {true, zFloat64Ptr, zFloat64Ptr}, {true, zArray0Ptr, zArray0Ptr}, {true, zArray1Ptr, zArray1Ptr}, {true, zChanPtr, zChanPtr}, {true, zFuncPtr, zFuncPtr}, {true, zIfacePtr, zIfacePtr}, {true, zMapPtr, zMapPtr}, {true, zSlicePtr, zSlicePtr}, {true, zStringPtr, zStringPtr}, {true, zStructPtr, zStructPtr}, {true, zMyInt, zMyInt}, {true, zMyString, zBool}, {false, zMyString, xString}, {true, zJSON, zBool}, {false, zJSON, xUint8}, {true, zJSONPtr, zJSONPtr}, {true, zTime, zTime}, } for i, v := range failures { msg := fmt.Sprintf("case %d: %#v, %#v", i, v.actual, v.expected) if v.panic { t.Panic(func() { t.Contains(v.actual, v.expected) }, msg) } else { t.NotContains(v.actual, v.expected, msg) } } t.Contains("", "") t.Contains("Test", "") t.Contains(myString("Test"), "es") t.Contains([...]time.Time{zTime, xTime, xTimeEST}, xTime) t.Contains([]*time.Time{&zTime, &xTime, &xTimeEST}, &xTime) t.Contains([]byte("Test"), byte('e')) t.Contains([]rune("Test"), 'e') t.Contains(map[int]string{2: "two", 5: "five", 10: "ten"}, "five") t.Contains(map[string]int{"two": 2, "five": 5, "ten": 10}, 5) t.NotContains(map[string]int{"two": 2, "five": 5, "ten": 10}, 0) } func TestCheckerHasKey(tt *testing.T) { t := check.T(tt) failures := []struct { panic bool actual interface{} expected interface{} }{ {true, nil, nil}, {true, zBool, zBool}, {true, zInt, zInt}, {true, zInt8, zInt8}, {true, zInt16, zInt16}, {true, zInt32, zInt32}, {true, zInt64, zInt64}, {true, zUint, zUint}, {true, zUint8, zUint8}, {true, zUint16, zUint16}, {true, zUint32, zUint32}, {true, zUint64, zUint64}, {true, zUintptr, zUintptr}, {true, zFloat32, zFloat32}, {true, zFloat64, zFloat64}, {true, zArray0, zArray0}, {true, zArray1, zArray1}, {true, zChan, zChan}, {true, zFunc, zFunc}, {true, zIface, zIface}, {true, zMap, zBool}, {false, zMap, zInt}, {true, zSlice, zSlice}, {true, zString, zString}, {true, zStruct, zStruct}, {true, zBoolPtr, zBoolPtr}, {true, zIntPtr, zIntPtr}, {true, zInt8Ptr, zInt8Ptr}, {true, zInt16Ptr, zInt16Ptr}, {true, zInt32Ptr, zInt32Ptr}, {true, zInt64Ptr, zInt64Ptr}, {true, zUintPtr, zUintPtr}, {true, zUint8Ptr, zUint8Ptr}, {true, zUint16Ptr, zUint16Ptr}, {true, zUint32Ptr, zUint32Ptr}, {true, zUint64Ptr, zUint64Ptr}, {true, zUintptrPtr, zUintptrPtr}, {true, zFloat32Ptr, zFloat32Ptr}, {true, zFloat64Ptr, zFloat64Ptr}, {true, zArray0Ptr, zArray0Ptr}, {true, zArray1Ptr, zArray1Ptr}, {true, zChanPtr, zChanPtr}, {true, zFuncPtr, zFuncPtr}, {true, zIfacePtr, zIfacePtr}, {true, zMapPtr, zMapPtr}, {true, zSlicePtr, zSlicePtr}, {true, zStringPtr, zStringPtr}, {true, zStructPtr, zStructPtr}, {true, zMyInt, zMyInt}, {true, zMyString, zMyString}, {true, zJSON, zJSON}, {true, zJSONPtr, zJSONPtr}, {true, zTime, zTime}, } for i, v := range failures { msg := fmt.Sprintf("case %d: %#v, %#v", i, v.actual, v.expected) if v.panic { t.Panic(func() { t.HasKey(v.actual, v.expected) }, msg) } else { t.NotHasKey(v.actual, v.expected, msg) } } t.HasKey(map[int]string{2: "two", 5: "five", 10: "ten"}, 5) t.HasKey(map[string]int{"two": 2, "five": 5, "ten": 10}, "five") t.NotHasKey(map[string]int{"two": 2, "five": 5, "ten": 10}, "") } func TestCheckerZero(tt *testing.T) { t := check.T(tt) todo := t.TODO() cases := []struct { zero interface{} notzero interface{} }{ {zBool, xBool}, {zInt, xInt}, {zInt8, xInt8}, {zInt16, xInt16}, {zInt32, xInt32}, {zInt64, xInt64}, {zUint, xUint}, {zUint8, xUint8}, {zUint16, xUint16}, {zUint32, xUint32}, {zUint64, xUint64}, {zUintptr, xUintptr}, {zFloat32, xFloat32}, {zFloat64, xFloat64}, {zArray0, xArray1}, {zArray1, xArray1}, {zChan, xChan}, {zFunc, xFunc}, {zIface, xIface}, {zMap, xMap}, {zSlice, xSlice}, {zString, xString}, {zStruct, xStruct}, {zBoolPtr, xBoolPtr}, {zIntPtr, xIntPtr}, {zInt8Ptr, xInt8Ptr}, {zInt16Ptr, xInt16Ptr}, {zInt32Ptr, xInt32Ptr}, {zInt64Ptr, xInt64Ptr}, {zUintPtr, xUintPtr}, {zUint8Ptr, xUint8Ptr}, {zUint16Ptr, xUint16Ptr}, {zUint32Ptr, xUint32Ptr}, {zUint64Ptr, xUint64Ptr}, {zUintptrPtr, xUintptrPtr}, {zFloat32Ptr, xFloat32Ptr}, {zFloat64Ptr, xFloat64Ptr}, {zArray0Ptr, xArray1Ptr}, {zArray1Ptr, xArray1Ptr}, {zChanPtr, xChanPtr}, {zFuncPtr, xFuncPtr}, {zIfacePtr, xIfacePtr}, {zMapPtr, xMapPtr}, {zSlicePtr, xSlicePtr}, {zStringPtr, xStringPtr}, {zStructPtr, xStructPtr}, {zMyInt, xMyInt}, {zMyString, xMyString}, {zJSON, xJSON}, {zJSONPtr, xJSONPtr}, {zTime, xTime}, {nil, vChan}, {nil, vFunc}, {vIface, xIface}, {nil, vMap}, {nil, vSlice}, {[0][]int{}, [1][]int{{1}}}, {[2][]int{nil, nil}, [2][]int{nil, {}}}, {[2][2][2]int{1: {1: {1: 0}}}, [2][2][2]int{1: {1: {1: 1}}}}, } for i, v := range cases { msg := fmt.Sprintf("case %d: %#v, %#v", i, v.zero, v.notzero) t.Zero(v.zero, msg) todo.Zero(v.notzero, msg) t.NotZero(v.notzero, msg) todo.NotZero(v.zero, msg) } t.Zero(nil) todo.NotZero(nil) } func TestCheckerLen(tt *testing.T) { t := check.T(tt) todo := t.TODO() cases := []struct { panic bool actual interface{} len int }{ {true, nil, 0}, {true, zBool, 0}, {true, zInt, 0}, {true, zInt8, 0}, {true, zInt16, 0}, {true, zInt32, 0}, {true, zInt64, 0}, {true, zUint, 0}, {true, zUint8, 0}, {true, zUint16, 0}, {true, zUint32, 0}, {true, zUint64, 0}, {true, zUintptr, 0}, {true, zFloat32, 0}, {true, zFloat64, 0}, {false, zArray0, 1}, {false, zArray1, 0}, {false, zChan, 1}, {true, zFunc, 0}, {true, zIface, 0}, {false, zMap, 1}, {false, zSlice, 1}, {false, zString, 1}, {true, zStruct, 0}, {true, zBoolPtr, 0}, {true, zIntPtr, 0}, {true, zInt8Ptr, 0}, {true, zInt16Ptr, 0}, {true, zInt32Ptr, 0}, {true, zInt64Ptr, 0}, {true, zUintPtr, 0}, {true, zUint8Ptr, 0}, {true, zUint16Ptr, 0}, {true, zUint32Ptr, 0}, {true, zUint64Ptr, 0}, {true, zUintptrPtr, 0}, {true, zFloat32Ptr, 0}, {true, zFloat64Ptr, 0}, {true, zArray0Ptr, 0}, {true, zArray1Ptr, 0}, {true, zChanPtr, 0}, {true, zFuncPtr, 0}, {true, zIfacePtr, 0}, {true, zMapPtr, 0}, {true, zSlicePtr, 0}, {true, zStringPtr, 0}, {true, zStructPtr, 0}, {true, zMyInt, 0}, {false, zMyString, 1}, {false, zJSON, 1}, {true, zJSONPtr, 0}, {true, zTime, 0}, } for _, v := range cases { if v.panic { t.Panic(func() { t.Len(v.actual, v.len) }) } else { todo.Len(v.actual, v.len) t.NotLen(v.actual, v.len) } } t.Len(zArray0, 0) t.Len(zArray1, 1) c := make(chan int, 5) t.Len(c, 0) todo.NotLen(c, 0) c <- 42 t.Len(c, 1) todo.NotLen(c, 1) m := make(map[string]int, 10) t.Len(m, 0) m["one"] = 1 m["ten"] = 10 t.Len(m, 2) t.Len(json.RawMessage("тест"), 8) t.Len([]rune("тест"), 4) t.Len(myString("test"), 4) t.Len("тест", 8) } func TestCheckerOrdered(t *testing.T) { cases := []struct { panic bool min interface{} mid interface{} max interface{} }{ {true, nil, nil, nil}, {true, zBool, xBool, xBool}, {false, xInt, xInt + 1, xInt + 2}, {false, xInt8, xInt8 + 1, xInt8 + 2}, {false, xInt16, xInt16 + 1, xInt16 + 2}, {false, xInt32, xInt32 + 1, xInt32 + 2}, {false, xInt64, xInt64 + 1, xInt64 + 2}, {false, xUint, xUint + 1, xUint + 2}, {false, xUint8, xUint8 + 1, xUint8 + 2}, {false, xUint16, xUint16 + 1, xUint16 + 2}, {false, xUint32, xUint32 + 1, xUint32 + 2}, {false, xUint64, xUint64 + 1, xUint64 + 2}, {false, xUintptr, xUintptr + 1, xUintptr + 2}, {false, xFloat32, xFloat32 + 1, xFloat32 + 2}, {false, xFloat64, xFloat64 + 1, xFloat64 + 2}, {true, zArray0, zArray0, zArray0}, {true, zArray1, xArray1, xArray1}, {true, zChan, xChan, xChan}, {true, zFunc, xFunc, xFunc}, {true, zIface, xIface, xIface}, {true, zMap, xMap, xMap}, {true, zSlice, xSlice, xSlice}, {false, xString, xString + "1", xString + "2"}, {true, zStruct, xStruct, xStruct}, {true, zBoolPtr, xBoolPtr, xBoolPtr}, {true, zIntPtr, xIntPtr, xIntPtr}, {true, zInt8Ptr, xInt8Ptr, xInt8Ptr}, {true, zInt16Ptr, xInt16Ptr, xInt16Ptr}, {true, zInt32Ptr, xInt32Ptr, xInt32Ptr}, {true, zInt64Ptr, xInt64Ptr, xInt64Ptr}, {true, zUintPtr, xUintPtr, xUintPtr}, {true, zUint8Ptr, xUint8Ptr, xUint8Ptr}, {true, zUint16Ptr, xUint16Ptr, xUint16Ptr}, {true, zUint32Ptr, xUint32Ptr, xUint32Ptr}, {true, zUint64Ptr, xUint64Ptr, xUint64Ptr}, {true, zUintptrPtr, xUintptrPtr, xUintptrPtr}, {true, zFloat32Ptr, xFloat32Ptr, xFloat32Ptr}, {true, zFloat64Ptr, xFloat64Ptr, xFloat64Ptr}, {true, zArray0Ptr, zArray0Ptr, zArray0Ptr}, {true, zArray1Ptr, xArray1Ptr, xArray1Ptr}, {true, zChanPtr, xChanPtr, xChanPtr}, {true, zFuncPtr, xFuncPtr, xFuncPtr}, {true, zIfacePtr, xIfacePtr, xIfacePtr}, {true, zMapPtr, xMapPtr, xMapPtr}, {true, zSlicePtr, xSlicePtr, xSlicePtr}, {true, zStringPtr, xStringPtr, xStringPtr}, {true, zStructPtr, xStructPtr, xStructPtr}, {false, xMyInt, xMyInt + 1, xMyInt + 2}, {false, xMyString, xMyString + "1", xMyString + "2"}, {true, xJSON, xJSON, xJSON}, {true, xJSONPtr, xJSONPtr, xJSONPtr}, {false, xTime, xTime.Add(time.Millisecond), xTime.Add(time.Second)}, } t.Run("Less", func(tt *testing.T) { t := check.T(tt) todo := t.TODO() t.Parallel() for _, v := range cases { actual, expected := v.min, v.max if v.panic { t.Panic(func() { t.Less(actual, expected) }) t.Panic(func() { t.LT(actual, expected) }) t.Panic(func() { t.LessOrEqual(actual, expected) }) t.Panic(func() { t.LE(actual, expected) }) } else { t.Less(actual, expected) t.LT(actual, expected) t.LessOrEqual(actual, expected) t.LessOrEqual(actual, actual) t.LE(actual, expected) t.LE(actual, actual) actual, expected = expected, actual todo.Less(actual, expected) todo.LT(actual, expected) todo.LessOrEqual(actual, expected) todo.LE(actual, expected) } } }) t.Run("Greater", func(tt *testing.T) { t := check.T(tt) todo := t.TODO() t.Parallel() for _, v := range cases { actual, expected := v.min, v.max if v.panic { t.Panic(func() { t.Greater(actual, expected) }) t.Panic(func() { t.GT(actual, expected) }) t.Panic(func() { t.GreaterOrEqual(actual, expected) }) t.Panic(func() { t.GE(actual, expected) }) } else { todo.Greater(actual, expected) todo.GT(actual, expected) todo.GreaterOrEqual(actual, expected) todo.GE(actual, expected) actual, expected = expected, actual t.Greater(actual, expected) t.GT(actual, expected) t.GreaterOrEqual(actual, expected) t.GreaterOrEqual(actual, actual) t.GE(actual, expected) t.GE(actual, actual) } } }) t.Run("Between", func(tt *testing.T) { t := check.T(tt) todo := t.TODO() t.Parallel() for _, v := range cases { min, mid, max := v.min, v.mid, v.max if v.panic { t.Panic(func() { t.Between(mid, min, max) }) t.Panic(func() { t.BetweenOrEqual(mid, min, max) }) t.Panic(func() { t.NotBetween(min, mid, max) }) t.Panic(func() { t.NotBetweenOrEqual(min, mid, max) }) } else { t.Between(mid, min, max) t.BetweenOrEqual(mid, min, max) t.BetweenOrEqual(mid, mid, max) t.BetweenOrEqual(mid, min, mid) todo.NotBetween(mid, min, max) todo.NotBetweenOrEqual(mid, min, max) todo.NotBetweenOrEqual(mid, mid, max) todo.NotBetweenOrEqual(mid, min, mid) t.NotBetween(min, mid, max) t.NotBetween(max, min, mid) t.NotBetweenOrEqual(min, mid, max) t.NotBetweenOrEqual(max, min, mid) todo.Between(min, mid, max) todo.Between(max, min, mid) todo.BetweenOrEqual(min, mid, max) todo.BetweenOrEqual(max, min, mid) } } }) } func TestCheckerApprox(t *testing.T) { cases := []struct { panic bool actual interface{} expected interface{} delta interface{} smape float64 }{ {true, nil, nil, nil, 0}, {true, zBool, xBool, xBool, 0}, {false, xInt, xInt + 5, 7, 10.0}, {false, xInt8, xInt8 + 5, 7, 50.0}, {false, xInt16, xInt16 + 5, 7, 20.0}, {false, xInt32, xInt32 + 5, 7, 10.0}, {false, xInt64, xInt64 + 5, 7, 5.0}, {false, xUint, xUint + 5, uint(7), 6.0}, {false, xUint8, xUint8 + 5, uint(7), 30.0}, {false, xUint16, xUint16 + 5, uint(7), 20.0}, {false, xUint32, xUint32 + 5, uint(7), 10.0}, {false, xUint64, xUint64 + 5, uint(7), 5.0}, {false, xUintptr, xUintptr + 5, uint(7), 0.0000001}, {false, xFloat32, xFloat32 - 5, 7.0, 50.0}, {false, xFloat64, xFloat64 + 5, 7.0, 33.0}, {true, zArray0, zArray0, zArray0, 0}, {true, zArray1, xArray1, xArray1, 0}, {true, zChan, xChan, xChan, 0}, {true, zFunc, xFunc, xFunc, 0}, {true, zIface, xIface, xIface, 0}, {true, zMap, xMap, xMap, 0}, {true, zSlice, xSlice, xSlice, 0}, {true, xString, xString, xString, 0}, {true, zStruct, xStruct, xStruct, 0}, {true, zBoolPtr, xBoolPtr, xBoolPtr, 0}, {true, zIntPtr, xIntPtr, xIntPtr, 0}, {true, zInt8Ptr, xInt8Ptr, xInt8Ptr, 0}, {true, zInt16Ptr, xInt16Ptr, xInt16Ptr, 0}, {true, zInt32Ptr, xInt32Ptr, xInt32Ptr, 0}, {true, zInt64Ptr, xInt64Ptr, xInt64Ptr, 0}, {true, zUintPtr, xUintPtr, xUintPtr, 0}, {true, zUint8Ptr, xUint8Ptr, xUint8Ptr, 0}, {true, zUint16Ptr, xUint16Ptr, xUint16Ptr, 0}, {true, zUint32Ptr, xUint32Ptr, xUint32Ptr, 0}, {true, zUint64Ptr, xUint64Ptr, xUint64Ptr, 0}, {true, zUintptrPtr, xUintptrPtr, xUintptrPtr, 0}, {true, zFloat32Ptr, xFloat32Ptr, xFloat32Ptr, 0}, {true, zFloat64Ptr, xFloat64Ptr, xFloat64Ptr, 0}, {true, zArray0Ptr, zArray0Ptr, zArray0Ptr, 0}, {true, zArray1Ptr, xArray1Ptr, xArray1Ptr, 0}, {true, zChanPtr, xChanPtr, xChanPtr, 0}, {true, zFuncPtr, xFuncPtr, xFuncPtr, 0}, {true, zIfacePtr, xIfacePtr, xIfacePtr, 0}, {true, zMapPtr, xMapPtr, xMapPtr, 0}, {true, zSlicePtr, xSlicePtr, xSlicePtr, 0}, {true, zStringPtr, xStringPtr, xStringPtr, 0}, {true, zStructPtr, xStructPtr, xStructPtr, 0}, {false, xMyInt, xMyInt + 5, 7, 0.01}, {true, xMyString, xMyString, xMyString, 0}, {true, xJSON, xJSON, xJSON, 0}, {true, xJSONPtr, xJSONPtr, xJSONPtr, 0}, {false, xTime, xTime.Add(5 * time.Second), 7 * time.Second, 0}, } t.Run("Delta", func(tt *testing.T) { t := check.T(tt) todo := t.TODO() t.Parallel() for _, v := range cases { if v.panic { t.Panic(func() { t.InDelta(v.actual, v.expected, v.delta) }) t.Panic(func() { t.NotInDelta(v.actual, v.expected, v.delta) }) } else { t.InDelta(v.actual, v.expected, v.delta) t.InDelta(v.expected, v.actual, v.delta) todo.NotInDelta(v.actual, v.expected, v.delta) todo.NotInDelta(v.expected, v.actual, v.delta) t.NotInDelta(v.actual, v.expected, half(v.delta)) t.NotInDelta(v.expected, v.actual, half(v.delta)) todo.InDelta(v.actual, v.expected, half(v.delta)) todo.InDelta(v.expected, v.actual, half(v.delta)) } } }) t.Run("SMAPE", func(tt *testing.T) { t := check.T(tt) todo := t.TODO() t.Parallel() for _, v := range cases { if v.panic || v.smape == 0 { t.Panic(func() { t.InSMAPE(v.actual, v.expected, v.smape) }) t.Panic(func() { t.NotInSMAPE(v.actual, v.expected, v.smape) }) } else { t.InSMAPE(v.actual, v.expected, v.smape) t.InSMAPE(v.expected, v.actual, v.smape) todo.NotInSMAPE(v.actual, v.expected, v.smape) todo.NotInSMAPE(v.expected, v.actual, v.smape) t.NotInSMAPE(v.actual, v.expected, half(v.smape).(float64)) t.NotInSMAPE(v.expected, v.actual, half(v.smape).(float64)) todo.InSMAPE(v.actual, v.expected, half(v.smape).(float64)) todo.InSMAPE(v.expected, v.actual, half(v.smape).(float64)) } } t.InSMAPE(0, 0, 0.5) t.InSMAPE(0.0, 0.0, 0.5) }) } func half(v interface{}) interface{} { if v, ok := v.(time.Duration); ok { return v / 2 } switch val := reflect.ValueOf(v); val.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return val.Int() / 2 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return val.Uint() / 2 case reflect.Float32, reflect.Float64: return val.Float() / 2 case reflect.Complex128, reflect.Complex64: // ??? // No meaningful "half": case reflect.Array, reflect.Slice, reflect.Map, reflect.Struct, reflect.Bool, reflect.String: case reflect.Chan, reflect.Func, reflect.Interface, reflect.Invalid: case reflect.Ptr, reflect.UnsafePointer: } panic(fmt.Sprintf("can't get half from %#v", v)) } func TestCheckerSubstring(t *testing.T) { cases := []struct { panic bool actual interface{} prefix string suffix string }{ {true, xBool, "", ""}, {true, xInt, "", ""}, {true, xInt8, "", ""}, {true, xInt16, "", ""}, {true, xInt32, "", ""}, {true, xInt64, "", ""}, {true, xUint, "", ""}, {true, xUint8, "", ""}, {true, xUint16, "", ""}, {true, xUint32, "", ""}, {true, xUint64, "", ""}, {true, xUintptr, "", ""}, {true, xFloat32, "", ""}, {true, xFloat64, "", ""}, {true, zArray0, "", ""}, {true, xArray1, "", ""}, {true, xChan, "", ""}, {true, xFunc, "", ""}, {true, xIface, "", ""}, {true, xMap, "", ""}, {true, xSlice, "", ""}, {false, xString, ""}, {true, xStruct, "", ""}, {true, xBoolPtr, "", ""}, {true, xIntPtr, "", ""}, {true, xInt8Ptr, "", ""}, {true, xInt16Ptr, "", ""}, {true, xInt32Ptr, "", ""}, {true, xInt64Ptr, "", ""}, {true, xUintPtr, "", ""}, {true, xUint8Ptr, "", ""}, {true, xUint16Ptr, "", ""}, {true, xUint32Ptr, "", ""}, {true, xUint64Ptr, "", ""}, {true, xUintptrPtr, "", ""}, {true, xFloat32Ptr, "", ""}, {true, xFloat64Ptr, "", ""}, {true, zArray0Ptr, "", ""}, {true, xArray1Ptr, "", ""}, {true, xChanPtr, "", ""}, {true, xFuncPtr, "", ""}, {true, xIfacePtr, "", ""}, {true, xMapPtr, "", ""}, {true, xSlicePtr, "", ""}, {true, xStringPtr, "", ""}, {true, xStructPtr, "", ""}, {true, xMyInt, "", ""}, {false, xMyString, "xy", "yz"}, {false, xJSON, "{", "}"}, {true, xJSONPtr, "", ""}, {false, zTime, "0001-01-01", "UTC"}, {false, []byte("String"), "Str", "ing"}, {false, []rune("Symbol"), "Sym", "bol"}, {false, time.Sunday, "Sun", "day"}, {false, io.EOF, "EO", "OF"}, } substrings := []struct { prefix interface{} suffix interface{} }{ {"Sunday", "Monday"}, {[]byte("Sunday"), []byte("Monday")}, {[]rune("Sunday"), []rune("Monday")}, {time.Sunday, time.Monday}, {errors.New("Sunday"), errors.New("Monday")}, } t.Run("HasPrefix", func(tt *testing.T) { t := check.T(tt) todo := t.TODO() t.Parallel() for i, v := range cases { msg := fmt.Sprintf("case %d: %#v, %#v, %#v", i, v.actual, v.prefix, v.suffix) if v.panic { t.Panic(func() { t.HasPrefix(v.actual, v.prefix) }, msg) t.Panic(func() { t.NotHasPrefix(v.actual, v.prefix) }, msg) t.Panic(func() { t.HasPrefix("", v.actual) }, msg) t.Panic(func() { t.NotHasPrefix("", v.actual) }, msg) } else { t.HasPrefix(v.actual, v.prefix, msg) todo.HasPrefix(v.actual, v.suffix, msg) t.NotHasPrefix(v.actual, v.suffix, msg) todo.NotHasPrefix(v.actual, v.prefix, msg) } } for _, v := range substrings { t.HasPrefix("Sunday Monday", v.prefix) todo.NotHasPrefix("Sunday Monday", v.prefix) } todo.HasPrefix(nil, "") t.NotHasPrefix(nil, "") todo.HasPrefix("", nil) t.NotHasPrefix("", nil) t.HasPrefix("", "") todo.NotHasPrefix("", "") t.HasPrefix("x", "") todo.NotHasPrefix("x", "") }) t.Run("HasSuffix", func(tt *testing.T) { t := check.T(tt) todo := t.TODO() t.Parallel() for i, v := range cases { msg := fmt.Sprintf("case %d: %#v, %#v, %#v", i, v.actual, v.suffix, v.suffix) if v.panic { t.Panic(func() { t.HasSuffix(v.actual, v.suffix) }, msg) t.Panic(func() { t.NotHasSuffix(v.actual, v.suffix) }, msg) t.Panic(func() { t.HasSuffix("", v.actual) }, msg) t.Panic(func() { t.NotHasSuffix("", v.actual) }, msg) } else { t.HasSuffix(v.actual, v.suffix, msg) todo.HasSuffix(v.actual, v.prefix, msg) t.NotHasSuffix(v.actual, v.prefix, msg) todo.NotHasSuffix(v.actual, v.suffix, msg) } } for _, v := range substrings { t.HasSuffix("Sunday Monday", v.suffix) todo.NotHasSuffix("Sunday Monday", v.suffix) } todo.HasSuffix(nil, "") t.NotHasSuffix(nil, "") todo.HasSuffix("", nil) t.NotHasSuffix("", nil) t.HasSuffix("", "") todo.NotHasSuffix("", "") t.HasSuffix("x", "") todo.NotHasSuffix("x", "") }) } func TestJSONEqual(tt *testing.T) { t := check.T(tt) todo := t.TODO() cases := []struct { panic bool json interface{} }{ {false, nil}, {true, zBool}, {true, zInt}, {true, zInt8}, {true, zInt16}, {true, zInt32}, {true, zInt64}, {true, zUint}, {true, zUint8}, {true, zUint16}, {true, zUint32}, {true, zUint64}, {true, zUintptr}, {true, zFloat32}, {true, zFloat64}, {true, zArray0}, {true, zArray1}, {true, zChan}, {true, zFunc}, {false, zIface}, // nil {true, zMap}, {true, zSlice}, {false, zString}, {true, zStruct}, {true, zBoolPtr}, {true, zIntPtr}, {true, zInt8Ptr}, {true, zInt16Ptr}, {true, zInt32Ptr}, {true, zInt64Ptr}, {true, zUintPtr}, {true, zUint8Ptr}, {true, zUint16Ptr}, {true, zUint32Ptr}, {true, zUint64Ptr}, {true, zUintptrPtr}, {true, zFloat32Ptr}, {true, zFloat64Ptr}, {true, zArray0Ptr}, {true, zArray1Ptr}, {true, zChanPtr}, {true, zFuncPtr}, {true, zIfacePtr}, {true, zMapPtr}, {true, zSlicePtr}, {true, zStringPtr}, {true, zStructPtr}, {true, zMyInt}, {false, zMyString}, {false, zJSON}, {false, zJSONPtr}, {true, zTime}, {false, []byte(nil)}, {false, []byte{}}, } for i, v := range cases { if v.panic { t.Panic(func() { t.JSONEqual(v.json, `{}`, i) }) t.Panic(func() { t.JSONEqual(`{}`, v.json) }) } else { todo.JSONEqual(v.json, v.json) } } invalid := `{"a":1,"b":[2]` invalidRaw := json.RawMessage(invalid) todo.JSONEqual(invalid, invalid) todo.JSONEqual([]byte(invalid), []byte(invalid)) todo.JSONEqual(&invalidRaw, invalid) todo.JSONEqual(&invalidRaw, invalid+"}") todo.JSONEqual(invalidRaw, []byte(invalid)) t.JSONEqual(invalidRaw, invalidRaw) t.JSONEqual(&invalidRaw, &invalidRaw) t.JSONEqual(&invalidRaw, invalidRaw) t.JSONEqual(invalidRaw, &invalidRaw) validRaw := json.RawMessage(invalid + "}") valid := []interface{}{ `{ "b" : [ 2],"a" :1} `, []byte(` { "b": [2 ],"a": 1}`), validRaw, &validRaw, } for _, actual := range valid { for _, expected := range valid { t.JSONEqual(actual, expected) } } } func TestHasType(tt *testing.T) { t := check.T(tt) todo := t.TODO() vs := []interface{}{ zBool, zInt, zInt8, zInt16, zInt32, zInt64, zUint, zUint8, zUint16, zUint32, zUint64, zUintptr, zFloat32, zFloat64, zArray0, zArray1, zChan, zFunc, zIface, // nil zMap, zSlice, zString, zStruct, zBoolPtr, zIntPtr, zInt8Ptr, zInt16Ptr, zInt32Ptr, zInt64Ptr, zUintPtr, zUint8Ptr, zUint16Ptr, zUint32Ptr, zUint64Ptr, zUintptrPtr, zFloat32Ptr, zFloat64Ptr, zArray0Ptr, zArray1Ptr, zChanPtr, zFuncPtr, zIfacePtr, zMapPtr, zSlicePtr, zStringPtr, zStructPtr, zMyInt, zMyString, zJSON, zJSONPtr, zTime, } for i, actual := range vs { for j, expected := range vs { if i == j { t.HasType(actual, expected) todo.NotHasType(actual, expected) } else { t.NotHasType(actual, expected) todo.HasType(actual, expected) } } } t.HasType(vChan, zChan) t.HasType(vFunc, zFunc) t.HasType(vIface, zIntPtr) t.HasType(vMap, zMap) t.HasType(vSlice, zSlice) var reader io.Reader t.HasType(reader, nil) t.HasType(&reader, (*io.Reader)(nil)) t.NotHasType(&reader, nil) t.HasType(os.Stdin, (*os.File)(nil)) t.NotHasType(os.Stdin, &reader) t.HasType(true, zBool) t.HasType(42, zInt) t.HasType("test", zString) t.HasType([]byte("test"), []byte(nil)) t.HasType([]byte("test"), []byte{}) t.HasType(new(int), zIntPtr) t.NotHasType(json.RawMessage([]byte("test")), []byte("test")) } func TestCheckers(t *testing.T) { t.Run("Err", func(tt *testing.T) { t := check.T(tt) todo := t.TODO() t.Parallel() cases := []struct { err bool deepEqual bool equal bool actual error expected error }{ {true, true, true, nil, nil}, {false, false, false, (*net.OpError)(nil), &net.OpError{}}, {false, false, false, (*net.OpError)(nil), nil}, {false, false, false, nil, (*net.OpError)(nil)}, {true, true, true, (*net.OpError)(nil), (*net.OpError)(nil)}, {true, true, false, &net.OpError{}, &net.OpError{}}, {true, true, true, io.EOF, io.EOF}, {true, true, false, io.EOF, errors.New("EOF")}, {false, false, false, pkgerrors.New("EOF"), io.EOF}, {false, false, false, pkgerrors.New("EOF"), errors.New("EOF")}, {true, true, false, pkgerrors.New("EOF"), pkgerrors.New("EOF")}, {true, false, false, pkgerrors.WithStack(io.EOF), io.EOF}, {true, false, false, pkgerrors.Wrap(io.EOF, "wrapped"), io.EOF}, {true, false, false, pkgerrors.Wrap(io.EOF, "wrapped"), errors.New("EOF")}, {true, false, false, pkgerrors.Wrap(pkgerrors.Wrap(io.EOF, "wrapped"), "wrapped2"), io.EOF}, {true, false, false, fmt.Errorf("wrapped: %w", io.EOF), io.EOF}, {true, false, false, fmt.Errorf("wrapped: %w", io.EOF), errors.New("EOF")}, {true, false, false, fmt.Errorf("wrapped2: %w", fmt.Errorf("wrapped: %w", io.EOF)), io.EOF}, {true, false, false, fmt.Errorf("wrapped2: %w", pkgerrors.Wrap(io.EOF, "wrapped")), io.EOF}, {true, false, false, pkgerrors.Wrap(fmt.Errorf("wrapped: %w", io.EOF), "wrapped2"), io.EOF}, {true, false, false, pkgerrors.Wrap(pkgerrors.Wrap(fmt.Errorf("wrapped4: %w", fmt.Errorf("wrapped3: %w", pkgerrors.Wrap(fmt.Errorf("wrapped: %w", io.EOF), "wrapped2"))), "wrapped5"), "wrapped6"), io.EOF}, {false, false, false, io.EOF, &myError{"EOF"}}, {true, true, true, xGRPCErr, xGRPCErr}, {true, true, false, xGRPCErr, status.Error(codes.Unknown, "unknown")}, {false, false, false, xGRPCErr, nil}, } for _, v := range cases { t.Run("", func(tt *testing.T) { t := check.T(tt) if v.err { t.Err(v.actual, v.expected) todo.NotErr(v.actual, v.expected) } else { todo.Err(v.actual, v.expected) t.NotErr(v.actual, v.expected) } if v.equal { t.Equal(v.actual, v.expected) } else { t.NotEqual(v.actual, v.expected) } if v.deepEqual { t.DeepEqual(v.actual, v.expected) } else { t.NotDeepEqual(v.actual, v.expected) } }) } }) t.Run("Panic", func(tt *testing.T) { t := check.T(tt) todo := t.TODO() t.Parallel() todo.Panic(func() {}) t.NotPanic(func() {}) t.Panic(func() { panic(nil) }) //nolint:govet // Testing nil panic. todo.NotPanic(func() { panic(nil) }) //nolint:govet // Testing nil panic. t.Panic(func() { panic("") }) t.Panic(func() { panic("oops") }) t.Panic(func() { panic(t) }) todo.NotPanic(func() { panic("") }) todo.NotPanic(func() { panic("oops") }) todo.NotPanic(func() { panic(t) }) }) t.Run("PanicMatch", func(tt *testing.T) { t := check.T(tt) todo := t.TODO() t.Parallel() t.Panic(func() { t.PanicMatch(func() { panic(0) }, nil) }) t.Panic(func() { t.PanicMatch(func() { panic(0) }, t) }) t.NotPanic(func() { t.PanicMatch(func() { panic(0) }, `0`) }) todo.PanicMatch(func() {}, ``) todo.PanicNotMatch(func() {}, ``) todo.PanicMatch(func() {}, `test`) todo.PanicNotMatch(func() {}, `test`) t.PanicMatch(func() { panic(nil) }, ``) //nolint:govet // Testing nil panic. todo.PanicNotMatch(func() { panic(nil) }, ``) //nolint:govet // Testing nil panic. t.PanicMatch(func() { panic(nil) }, `^$`) //nolint:govet // Testing nil panic. todo.PanicNotMatch(func() { panic(nil) }, `^$`) //nolint:govet // Testing nil panic. t.PanicNotMatch(func() { panic(nil) }, `test`) //nolint:govet // Testing nil panic. todo.PanicMatch(func() { panic(nil) }, `test`) //nolint:govet // Testing nil panic. t.PanicMatch(func() { panic("") }, regexp.MustCompile(`^$`)) t.PanicMatch(func() { panic("oops") }, `(?i)Oops`) t.PanicMatch(func() { panic(t) }, `^&check.C{`) t.PanicNotMatch(func() { panic("") }, regexp.MustCompile(`.`)) t.PanicNotMatch(func() { panic("oops") }, `(?-i)Oops`) todo.PanicNotMatch(func() { panic(t) }, `^&check.C{`) }) t.Run("Implements", func(tt *testing.T) { t := check.T(tt) t.Parallel() t.Implements(t, (*testing.TB)(nil)) t.Implements(os.Stdin, (*io.Reader)(nil)) t.Implements(os.Stdin, &xIface) t.Implements(*os.Stdin, (*io.Reader)(nil)) t.Implements(time.Time{}, (*fmt.Stringer)(nil)) t.Implements(&time.Time{}, (*fmt.Stringer)(nil)) t.NotImplements(os.Stdin, (*fmt.Stringer)(nil)) t.NotImplements(&os.Stdin, (*io.Reader)(nil)) t.NotImplements(new(int), (*io.Reader)(nil)) }) } check-1.6.0/color.go000066400000000000000000000015651410630575400142540ustar00rootroot00000000000000package check import ( "os" "strings" ) //nolint:gochecknoglobals // By design. var ( ansiGreen = "\033[32m" ansiYellow = "\033[33m" ansiRed = "\033[31m" ansiReset = "\033[0m" ) func init() { //nolint:gochecknoinits // By design. if !wantColor() { ansiGreen, ansiYellow, ansiRed, ansiReset = "", "", "", "" } } func wantColor() bool { return strings.Contains(os.Getenv("TERM"), "color") && (isTerminal() || os.Getenv("GO_TEST_COLOR") != "") } func colouredDiff(diff string) string { lines := strings.SplitAfter(diff, "\n") for i := range lines { switch { case strings.HasPrefix(lines[i], "--- "): case strings.HasPrefix(lines[i], "+++ "): case strings.HasPrefix(lines[i], "-"): lines[i] = ansiGreen + lines[i] + ansiReset case strings.HasPrefix(lines[i], "+"): lines[i] = ansiRed + lines[i] + ansiReset } } return strings.Join(lines, "") } check-1.6.0/color_bsd.go000066400000000000000000000003401410630575400150720ustar00rootroot00000000000000// +build darwin dragonfly freebsd netbsd openbsd package check import ( "os" "golang.org/x/sys/unix" ) func isTerminal() bool { _, err := unix.IoctlGetTermios(int(os.Stdout.Fd()), unix.TIOCGETA) return err == nil } check-1.6.0/color_linux.go000066400000000000000000000002741410630575400154670ustar00rootroot00000000000000// +build linux package check import ( "os" "golang.org/x/sys/unix" ) func isTerminal() bool { _, err := unix.IoctlGetTermios(int(os.Stdout.Fd()), unix.TCGETS) return err == nil } check-1.6.0/color_other.go000066400000000000000000000002001410630575400154360ustar00rootroot00000000000000// +build !linux,!darwin,!dragonfly,!freebsd,!netbsd,!openbsd,!windows package check func isTerminal() bool { return false } check-1.6.0/color_windows.go000066400000000000000000000003041410630575400160140ustar00rootroot00000000000000// +build windows package check import ( "os" "syscall" ) func isTerminal() bool { var mode uint32 err := syscall.GetConsoleMode(syscall.Handle(os.Stdout.Fd()), &mode) return err == nil } check-1.6.0/doc.go000066400000000000000000000114251410630575400136770ustar00rootroot00000000000000// Package check provide helpers to complement Go testing package. // // Features // // This package is like testify/assert on steroids. :) // // - Compelling output from failed tests: // - Very easy-to-read dumps for expected and actual values. // - Same text diff you loved in testify/assert. // - Also visual diff in GoConvey web UI, if you use it (recommended). // - Statistics with amount of passed/failed checks. // - Colored output in terminal. // - 100% compatible with testing package - check package just provide // convenient wrappers for *testing.T methods and doesn't introduce // new concepts like BDD, custom test suite or unusual execution flow. // - All checks you may ever need! :) // - Very easy to add your own check functions. // - Concise, handy and consistent API, without dot-import! // // Quickstart // // Just wrap each (including subtests) *testing.T using check.T() and write // tests as usually with testing package. Call new methods provided by // this package to have more clean/concise test code and cool dump/diff. // // import "github.com/powerman/check" // // func TestSomething(tt *testing.T) { // t := check.T(tt) // t.Equal(2, 2) // t.Log("You can use new t just like usual *testing.T") // t.Run("Subtests/Parallel example", func(tt *testing.T) { // t := check.T(tt) // t.Parallel() // t.NotEqual(2, 3, "should not be 3!") // obj, err := NewObj() // if t.Nil(err) { // t.Match(obj.field, `^\d+$`) // } // }) // } // // To get optional statistics about executed checkers add: // // func TestMain(m *testing.M) { check.TestMain(m) } // // When use goconvey tool, to get nice diff in web UI add: // // import _ "github.com/smartystreets/goconvey/convey" // // Hints // // ★ How to check for errors: // // // If you just want nil: // t.Nil(err) // t.Err(err, nil) // // // Check for (absence of) concrete (possibly wrapped) error: // t.Err(err, io.EOF) // t.NotErr(err, io.EOF) // nil is not io.EOF, so it's ok too // // // When need to match by error's text: // t.Match(err, "file.*permission") // // // Use Equal ONLY when checking for same instance: // t.Equal(io.EOF, io.EOF) // this works // t.Equal(io.EOF, errors.New("EOF")) // this doesn't work! // t.Err(io.EOF, errors.New("EOF")) // this works // t.DeepEqual(io.EOF, errors.New("EOF")) // this works too // // ★ Each check returns bool, so you can easily skip problematic code: // // if t.Nil(err) { // t.Match(obj.field, `^\d+$`) // } // // ★ You can turn any check into assertion to stop test immediately: // // t.Must(t.Nil(err)) // // ★ You can turn all checks into assertions to stop test immediately: // // t = t.MustAll() // t.Nil(err) // // ★ You can provide extra description to each check: // // t.Equal(got, want, "Just msg: will Print(), % isn't special") // t.Equal(got, want, "Msg with args: will Printf(): %v", extra) // // ★ There are short synonyms for checks implementing usual ==, !=, etc.: // // t.EQ(got, want) // same as t.Equal // t.NE(got, want) // same as t.NotEqual // t.LT(got, want) // same as t.Less // t.LE(got, want) // same as t.LessOrEqual // t.GT(got, want) // same as t.Greater // t.GE(got, want) // same as t.GreaterOrEqual // // ★ If you need custom check, which isn't available out-of-box - see // Should checker, it'll let you plug in your own checker with ease. // // ★ It will panic when called with arg of wrong type - because this // means bug in your test. // // ★ If you don't see colors in `go test` output it may happens because of // two reasons: either your $TERM doesn't contain substring "color" or // you're running `go test path/to/your/package`. To force colored output // in last case just set this environment variable: // // export GO_TEST_COLOR=1 // // Contents // // There are few special functions (assertion, custom checkers, etc.). // // Error // Must // MustAll // Should // TODO // // Everything else are just trivial (mostly) checkers which works in // obvious way and accept values of any types which makes sense (and // panics on everything else). // // Nil NotNil // Zero NotZero // True False // // Equal NotEqual EQ NE // DeepEqual NotDeepEqual // Err NotErr // BytesEqual NotBytesEqual // JSONEqual // // Greater LessOrEqual GT LE // Less GreaterOrEqual LT GE // Between NotBetween // BetweenOrEqual NotBetweenOrEqual // InDelta NotInDelta // InSMAPE NotInSMAPE // // Len NotLen // Match NotMatch // HasPrefix NotHasPrefix // HasSuffix NotHasSuffix // HasKey NotHasKey // Contains NotContains // // HasType NotHasType // Implements NotImplements // // Panic NotPanic // PanicMatch PanicNotMatch package check check-1.6.0/dump.go000066400000000000000000000074341410630575400141040ustar00rootroot00000000000000package check import ( "bytes" "encoding/json" "fmt" "reflect" "strconv" "strings" "unicode/utf8" "github.com/davecgh/go-spew/spew" "github.com/pmezard/go-difflib/difflib" ) //nolint:gochecknoglobals // Const. var spewCfg = spew.ConfigState{ Indent: " ", DisablePointerAddresses: true, DisableCapacities: true, SortKeys: true, SpewKeys: true, } type dump struct { dump string indirectType reflect.Type } // String returns dump of value given to newDump. func (v dump) String() string { return v.dump } func (v dump) diff(expected dump) string { if v.indirectType != expected.indirectType { return "" } if !strings.ContainsRune(v.dump[:len(v.dump)-1], '\n') && !strings.ContainsRune(expected.dump[:len(expected.dump)-1], '\n') { return "" } diff, err := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ A: difflib.SplitLines(expected.dump), B: difflib.SplitLines(v.dump), FromFile: "Expected", FromDate: "", ToFile: "Actual", ToDate: "", Context: 1, }) if err != nil { return "" } return "Diff:\n" + diff } // newDump prepare i dump using spew.Sdump in most cases and custom // improved dump for these cases: // - nil: remove "(interface{})" prefix // - byte: use 0xFF instead of decimal // - rune: use quoted char instead of number for valid runes // - string: use this instead of quoted single-line: // - valid utf8: don't quote ", show multiline strings on separate lines // - invalid utf8: use hexdump like for []byte // - []byte: same as string instead of hexdump for valid utf8 // - []rune: use quoted char instead of number for valid runes in list // - json.RawMessage: indent, then same as string. func newDump(i interface{}) (d dump) { //nolint:gocyclo,gocognit,funlen,cyclop // By design. d.dump = spewCfg.Sdump(i) if i == nil { d.dump = "\n" return d } val := reflect.ValueOf(i) typ := reflect.TypeOf(i) kind := typ.Kind() if kind == reflect.Ptr { if val.IsNil() { return d } val = val.Elem() typ = typ.Elem() kind = typ.Kind() } d.indirectType = typ switch { case typ == reflect.TypeOf(json.RawMessage(nil)): v := val.Bytes() var buf bytes.Buffer if json.Indent(&buf, v, "", " ") == nil { d.dump = fmt.Sprintf("(%T) (len=%d) '\n%s\n'\n", i, len(v), buf.String()) } case kind == reflect.Uint8: v := byte(val.Uint()) d.dump = fmt.Sprintf("(%T) 0x%02X\n", i, v) case kind == reflect.Int32: v := rune(val.Int()) if utf8.ValidRune(v) { d.dump = fmt.Sprintf("(%T) %q\n", i, v) } case kind == reflect.Slice && typ.Elem().Kind() == reflect.Int32: valid := true for k := 0; k < val.Len() && valid; k++ { valid = valid && utf8.ValidRune(rune(val.Index(k).Int())) } if valid { d.dump = fmt.Sprintf("(%T) %q\n", i, i) } case kind == reflect.String: v := val.String() if utf8.ValidString(v) { d.dump = fmt.Sprintf("(%T) (len=%d) %s\n", i, len(v), quote(v)) } else { d.dump = strings.Replace(spewCfg.Sdump([]byte(v)), "([]uint8)", fmt.Sprintf("(%T)", i), 1) } case kind == reflect.Slice && typ.Elem().Kind() == reflect.Uint8: v := val.Bytes() if len(v) > 0 && utf8.Valid(v) || len(v) == 0 && !val.IsNil() { d.dump = fmt.Sprintf("(%T) (len=%d) %s\n", i, len(v), quote(string(v))) } } return d } // quote like %#v, except keep \n and " unquoted for readability. func quote(s string) string { r := []rune(strconv.Quote(s)) q := r[:0] var multiline, esc bool for _, c := range r[1 : len(r)-1] { if esc { esc = false switch c { case 'n': c = '\n' multiline = true case '"': default: q = append(q, '\\') } } else if c == '\\' { esc = true continue } q = append(q, c) } if multiline { return fmt.Sprintf("'\n%s\n'", string(q)) } return fmt.Sprintf("'%s'", string(q)) } check-1.6.0/dump_test.go000066400000000000000000000056321410630575400151410ustar00rootroot00000000000000package check //nolint:testpackage // Testing unexported identifiers. import ( "encoding/json" "io" "testing" "time" _ "github.com/smartystreets/goconvey/convey" ) func TestDump(tt *testing.T) { t := T(tt) type ( myBool bool myInt int myInt32 int32 myInt64 int64 myUint uint myUint64 uint64 myByte byte myRune rune myUintptr uintptr myFloat64 float64 myString string myRunes []rune myBytes []byte myStruct struct { i int s string } ) var ( j = json.RawMessage(`[{"key":"one","value":1},{"key":"two","value":2}]`) jnil *json.RawMessage ) cases := []struct { improved bool i interface{} }{ {true, nil}, {false, true}, {false, myBool(true)}, {false, -42}, {false, myInt(-42)}, {false, int32(-32)}, {false, myInt32(-32)}, {false, int64(-64)}, {false, myInt64(-64)}, {false, uint(42)}, {false, myUint(42)}, {false, uint64(64)}, {false, myUint64(64)}, {true, byte(10)}, {true, myByte(10)}, {true, byte(255)}, {true, myByte(255)}, {true, rune(0)}, {true, myRune(0)}, {true, ' '}, {true, myRune(' ')}, {true, ' '}, {true, myRune(' ')}, {true, '\n'}, {true, myRune('\n')}, {true, '€'}, {true, myRune('€')}, {false, uintptr(0)}, {false, myUintptr(0)}, {false, uintptr(42)}, {false, myUintptr(42)}, {false, 0.0}, {false, myFloat64(0.0)}, {false, time.Monday}, {false, [0]int{}}, {false, [2]int{}}, {false, []int(nil)}, {false, []int{}}, {false, []int{1: 0}}, {false, chan int(nil)}, {false, make(chan int)}, {false, chan<- int(make(chan int, 2))}, {false, (func())(nil)}, //nolint:gocritic // False positive. {false, func(i int) int { return 0 }}, {false, io.EOF}, {false, map[int]int(nil)}, {false, map[int]int{2: 0}}, {false, make(map[int]int, 2)}, {false, (*int)(nil)}, {true, ""}, {true, myString("")}, {true, " "}, {true, myString(" ")}, {true, "\\`'\""}, {true, myString("\\`'\"")}, {true, "€"}, {true, myString("€")}, {true, "\x01\x02\x03\n\xff\xff"}, {true, myString("\x01\x02\x03\n\xff\xff")}, {true, "line1\nline2"}, {true, myString("line1\nline2")}, {false, []byte(nil)}, {false, myBytes(nil)}, {true, []byte{}}, {true, myBytes{}}, {false, []byte("\x01\x02\x03\n\xff\xff")}, {false, myBytes("\x01\x02\x03\n\xff\xff")}, {true, []byte("line1\nvery long line2")}, {true, myBytes("line1\nvery long line2")}, {true, j}, {true, myBytes(j)}, {false, jnil}, {true, &j}, {true, []rune{}}, {true, myRunes{}}, {true, []rune{0, ' ', ' ', '\n', '€'}}, {true, myRunes{0, ' ', ' ', '\n', '€'}}, {false, time.Time{}}, {false, time.Now()}, {false, struct { i int s string }{0, ""}}, {false, myStruct{0, ""}}, } for _, v := range cases { dumpOld, dumpNew := spewCfg.Sdump(v.i), newDump(v.i).String() if v.improved { t.NotEqual(dumpNew, dumpOld) } else { t.Equal(dumpNew, dumpOld) } } } check-1.6.0/flags.go000066400000000000000000000005461410630575400142300ustar00rootroot00000000000000package check import ( "flag" "sync" ) type peekFlags struct { sync.Once conveyJSON bool } //nolint:gochecknoglobals // By design. var flags peekFlags func (p *peekFlags) detect() *peekFlags { flags.Do(func() { flag.Visit(func(f *flag.Flag) { if f.Name == "convey-json" { p.conveyJSON = f.Value.String() == "true" } }) }) return p } check-1.6.0/go.mod000066400000000000000000000006651410630575400137150ustar00rootroot00000000000000module github.com/powerman/check go 1.16 require ( github.com/davecgh/go-spew v1.1.1 github.com/golangci/golangci-lint v1.41.1 github.com/mattn/goveralls v0.0.9 github.com/pkg/errors v0.9.1 github.com/pmezard/go-difflib v1.0.0 github.com/powerman/deepequal v0.1.0 github.com/smartystreets/goconvey v1.6.4 golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 google.golang.org/grpc v1.38.0 google.golang.org/protobuf v1.27.0 ) check-1.6.0/go.sum000066400000000000000000003203311410630575400137350ustar00rootroot000000000000004d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a h1:wFEQiK85fRsEVF0CRrPAos5LoAryUsIX1kPW/WrIqFw= 4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo= bitbucket.org/creachadair/shell v0.0.6/go.mod h1:8Qqi/cYk7vPnsOePHroKXDJYmb5x7ENhtiFtfZq8K+M= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.60.0/go.mod h1:yw2G51M9IfRboUH61Us8GqCeF1PzPblB823Mn2q2eAU= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/pubsub v1.5.0/go.mod h1:ZEwJccE3z93Z2HWvstpri00jOg7oO4UZDtKhwDwqF0w= cloud.google.com/go/spanner v1.7.0/go.mod h1:sd3K2gZ9Fd0vMPLXzeCrF6fq4i63Q7aTLW/lBIfBkIk= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OpenPeeDeeP/depguard v1.0.1 h1:VlW4R6jmBIv3/u1JNlawEvJMM4J+dPORPaZasQee8Us= github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/ashanbrown/forbidigo v1.2.0 h1:RMlEFupPCxQ1IogYOQUnIQwGEUGK8g5vAPMRyJoSxbc= github.com/ashanbrown/forbidigo v1.2.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI= github.com/ashanbrown/makezero v0.0.0-20210520155254-b6261585ddde h1:YOsoVXsZQPA9aOTy1g0lAJv5VzZUvwQuZqug8XPeqfM= github.com/ashanbrown/makezero v0.0.0-20210520155254-b6261585ddde/go.mod h1:oG9Dnez7/ESBqc4EdrdNlryeo7d0KcW1ftXHm7nU/UU= github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.36.30/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bkielbasa/cyclop v1.2.0 h1:7Jmnh0yL2DjKfw28p86YTd/B4lRGcNuu12sKE35sM7A= github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= github.com/bombsimon/wsl/v3 v3.3.0 h1:Mka/+kRLoQJq7g2rggtgQsjuI/K5Efd87WX96EWFxjM= github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charithe/durationcheck v0.0.8 h1:cnZrThioNW9gSV5JsRIXmkyHUbcDH7Y9hkzFDVc9/j0= github.com/charithe/durationcheck v0.0.8/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af h1:spmv8nSH9h5oCQf40jt/ufBCt9j0/58u4G+rkeMqXGI= github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af/go.mod h1:Qjyv4H3//PWVzTeCezG2b9IRn6myJxJSr4TD/xo6ojU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/daixiang0/gci v0.2.8 h1:1mrIGMBQsBu0P7j7m1M8Lb+ZeZxsZL+jyGX4YoMJJpg= github.com/daixiang0/gci v0.2.8/go.mod h1:+4dZ7TISfSmqfAGv59ePaHfNzgGtIkHAhhdKggP1JAc= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denis-tingajkin/go-header v0.4.2 h1:jEeSF4sdv8/3cT/WY8AgDHUoItNSoEZ7qg9dX7pc218= github.com/denis-tingajkin/go-header v0.4.2/go.mod h1:eLRHAVXzE5atsKAnNRDB90WHCFFnBUn4RN0nRcs1LJA= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/esimonov/ifshort v1.0.2 h1:K5s1W2fGfkoWXsFlxBNqT6J0ZCncPaKrGM5qe0bni68= github.com/esimonov/ifshort v1.0.2/go.mod h1:yZqNJUrNn20K8Q9n2CrjTKYyVEmX209Hgu+M1LBpeZE= github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw= github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3nqZCxaQ2Ze/sM= github.com/fzipp/gocyclo v0.3.1 h1:A9UeX3HJSXTBzvHzhqoYVuE0eAhe+aM8XBCCwsPMZOc= github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASxc7x3E= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-critic/go-critic v0.5.6 h1:siUR1+322iVikWXoV75I1YRfNaC/yaLzhdF9Zwd8Tus= github.com/go-critic/go-critic v0.5.6/go.mod h1:cVjj0DfqewQVIlIAGexPCaGaZDAqGE29PYDDADIVNEo= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= github.com/go-toolsmith/astcopy v1.0.0 h1:OMgl1b1MEpjFQ1m5ztEO06rz5CUd3oBv9RF7+DyvdG8= github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= github.com/go-toolsmith/astequal v1.0.0 h1:4zxD8j3JRFNyLN46lodQuqz3xdKSrur7U/sr0SDS/gQ= github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k= github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU= github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg= github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= github.com/go-toolsmith/pkgload v1.0.0 h1:4DFWWMXVfbcN5So1sBNW9+yeiMqLFGl1wFLTL5R0Tgg= github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc= github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= github.com/go-toolsmith/typep v1.0.2 h1:8xdsa1+FSIH/RhEkgnD1j2CJOy5mNllW1Q9tRiYwvlk= github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b h1:khEcpUM4yFcxg4/FHQWkvVRmgijNXRfzkIDHh23ggEo= github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY= github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613 h1:9kfjN3AdxcbsZBf8NjltjWihK2QfBBBZuv91cMFfDHw= github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8= github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a h1:iR3fYXUjHCR97qWS8ch1y9zPNsgXThGwjKPrYfqMPks= github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= github.com/golangci/golangci-lint v1.41.1 h1:KH28pTSqRu6DTXIAANl1sPXNCmqg4VEH21z6G9Wj4SM= github.com/golangci/golangci-lint v1.41.1/go.mod h1:LPtcY3aAAU8wydHrKpnanx9Og8K/cblZSyGmI5CJZUk= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= github.com/golangci/misspell v0.3.5 h1:pLzmVdl3VxTOncgzHcvLOKirdvcx/TydsClUQXTehjo= github.com/golangci/misspell v0.3.5/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= github.com/golangci/revgrep v0.0.0-20210208091834-cd28932614b5 h1:c9Mqqrm/Clj5biNaG7rABrmwUq88nHh0uABo2b/WYmc= github.com/golangci/revgrep v0.0.0-20210208091834-cd28932614b5/go.mod h1:LK+zW4MpyytAWQRz0M4xnzEk50lSvqDQKfx304apFkY= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= github.com/google/certificate-transparency-go v1.1.1/go.mod h1:FDKqPvSXawb2ecErVRrD+nfy23RCzyl7eqVCEmlT1Zs= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200507031123-427632fa3b1c/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/trillian v1.3.11/go.mod h1:0tPraVHrSDkA3BO6vKX67zgLXs6SsOAbHEivX+9mPgw= github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= github.com/gordonklaus/ineffassign v0.0.0-20210225214923-2e10b2664254 h1:Nb2aRlC404yz7gQIfRZxX9/MLvQiqXyiBTJtgAy6yrI= github.com/gordonklaus/ineffassign v0.0.0-20210225214923-2e10b2664254/go.mod h1:M9mZEtGIsR1oDaZagNPNG9iq9n2HrhZ17dsXk73V3Lw= github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw= github.com/gostaticanalysis/analysisutil v0.4.1 h1:/7clKqrVfiVwiBQLM0Uke4KvXnO6JcCTS7HwF2D6wG8= github.com/gostaticanalysis/analysisutil v0.4.1/go.mod h1:18U/DLpRgIUd459wGxVHE0fRgmo1UgHDcbw7F5idXu0= github.com/gostaticanalysis/comment v1.3.0/go.mod h1:xMicKDx7XRXYdVwY9f9wQpDJVnqWxw9wCauCMKp+IBI= github.com/gostaticanalysis/comment v1.4.1 h1:xHopR5L2lRz6OsjH4R2HG5wRhW9ySl3FsHIvi5pcXwc= github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= github.com/gostaticanalysis/forcetypeassert v0.0.0-20200621232751-01d4955beaa5 h1:rx8127mFPqXXsfPSo8BwnIU97MKFZc89WHAHt8PwDVY= github.com/gostaticanalysis/forcetypeassert v0.0.0-20200621232751-01d4955beaa5/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM= github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4= github.com/jingyugao/rowserrcheck v1.1.0 h1:u6h4eiNuCLqk73Ic5TXQq9yZS+uEXTdusn7c3w1Mr6A= github.com/jingyugao/rowserrcheck v1.1.0/go.mod h1:TOQpc2SLx6huPfoFGK3UOnEG+u02D3C1GeosjupAKCA= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julz/importas v0.0.0-20210419104244-841f0c0fe66d h1:XeSMXURZPtUffuWAaq90o6kLgZdgu+QA8wk4MPC8ikI= github.com/julz/importas v0.0.0-20210419104244-841f0c0fe66d/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.6.0 h1:YTDO4pNy7AUN/021p+JGHycQyYNIyMoenM1YDVK6RlY= github.com/kisielk/errcheck v1.6.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kulti/thelper v0.4.0 h1:2Nx7XbdbE/BYZeoip2mURKUdtHQRuy6Ug+wR7K9ywNM= github.com/kulti/thelper v0.4.0/go.mod h1:vMu2Cizjy/grP+jmsvOFDx1kYP6+PD1lqg4Yu5exl2U= github.com/kunwardeep/paralleltest v1.0.2 h1:/jJRv0TiqPoEy/Y8dQxCFJhD56uS/pnvtatgTZBHokU= github.com/kunwardeep/paralleltest v1.0.2/go.mod h1:ZPqNm1fVHPllh5LPVujzbVz1JN2GhLxSfY+oqUsvG30= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/kyoh86/exportloopref v0.1.8 h1:5Ry/at+eFdkX9Vsdw3qU4YkvGtzuVfzT4X7S77LoN/M= github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg= github.com/ldez/gomoddirectives v0.2.1 h1:9pAcW9KRZW7HQjFwbozNvFMcNVwdCBufU7os5QUwLIY= github.com/ldez/gomoddirectives v0.2.1/go.mod h1:sGicqkRgBOg//JfpXwkB9Hj0X5RyJ7mlACM5B9f6Me4= github.com/ldez/tagliatelle v0.2.0 h1:693V8Bf1NdShJ8eu/s84QySA0J2VWBanVBa2WwXD/Wk= github.com/ldez/tagliatelle v0.2.0/go.mod h1:8s6WJQwEYHbKZDsp/LjArytKOG8qaMrKQQ3mFukHs88= github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/maratori/testpackage v1.0.1 h1:QtJ5ZjqapShm0w5DosRjg0PRlSdAdlx+W6cCKoALdbQ= github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU= github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 h1:pWxk9e//NbPwfxat7RXkts09K+dEBJWakUWwICVqYbA= github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/mattn/goveralls v0.0.9 h1:XmIwwrO9a9pqSW6IpI89BSCShzQxx0j/oKnnvELQNME= github.com/mattn/goveralls v0.0.9/go.mod h1:FRbM1PS8oVsOe9JtdzAAXM+DsvDMMHcM1C7drGJD8HY= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81 h1:QASJXOGm2RZ5Ardbc86qNFvby9AqkLDibfChMtAg5QM= github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= github.com/mgechev/revive v1.0.7 h1:5kEWTY/W5a0Eiqnkn2BAWsRZpxbs1ft15PsyNC7Rml8= github.com/mgechev/revive v1.0.7/go.mod h1:vuE5ox/4L/HDd63MCcCk3H6wTLQ6XXezRphJ8cJJOxY= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/moricho/tparallel v0.2.1 h1:95FytivzT6rYzdJLdtfn6m1bfFJylOJK41+lgv/EHf4= github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k= github.com/mozilla/scribe v0.0.0-20180711195314-fb71baf557c1/go.mod h1:FIczTrinKo8VaLxe6PWTPEXRXDIHz2QAwiaBaP5/4a8= github.com/mozilla/tls-observatory v0.0.0-20210209181001-cf43108d6880/go.mod h1:FUqVoUPHSEdDR0MnFM3Dh8AU0pZHLXUD127SAJGER/s= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo= github.com/mwitkow/go-proto-validators v0.2.0/go.mod h1:ZfA1hW+UH/2ZHOWvQ3HnQaU0DtnpXu850MZiy+YUgcc= github.com/nakabonne/nestif v0.3.0 h1:+yOViDGhg8ygGrmII72nV9B/zGxY188TYpfolntsaPw= github.com/nakabonne/nestif v0.3.0/go.mod h1:dI314BppzXjJ4HsCnbo7XzrJHPszZsjnk5wEBSYHI2c= github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA= github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nishanths/exhaustive v0.1.0 h1:kVlMw8h2LHPMGUVqUj6230oQjjTMFjwcZrnkhXzFfl8= github.com/nishanths/exhaustive v0.1.0/go.mod h1:S1j9110vxV1ECdCudXRkeMnFQ/DQk9ajLT0Uf2MYZQQ= github.com/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc/go.mod h1:62PewwiQTlm/7Rj+cxVYqZvDIUc+JjZq6GHAC1fsObQ= github.com/nishanths/predeclared v0.2.1 h1:1TXtjmy4f3YCFjTxRd8zcFHOmoUir+gp0ESzjFzG2sw= github.com/nishanths/predeclared v0.2.1/go.mod h1:HvkGJcA3naj4lOwnFXFDkFxVtSqQMB9sbB1usJ+xjQE= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.1 h1:foqVmeWDD6yYpK+Yz3fHyNIxFYNxswxqNFjSKe+vI54= github.com/onsi/ginkgo v1.16.1/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.11.0 h1:+CqWgvj0OZycCaqclBD1pxKHAU+tOkHmQIWvDHq2aug= github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d h1:CdDQnGF8Nq9ocOS/xlSptM1N3BbrA6/kmaep5ggwaIA= github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/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 v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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/polyfloyd/go-errorlint v0.0.0-20210510181950-ab96adb96fea h1:Sk6Xawg57ZkjXmFYD1xCHSKN6FtYM+km51MM7Lveyyc= github.com/polyfloyd/go-errorlint v0.0.0-20210510181950-ab96adb96fea/go.mod h1:wi9BfjxjF/bwiZ701TzmfKu6UKC357IOAtNr0Td0Lvw= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/powerman/deepequal v0.1.0 h1:sVwtyTsBuYIvdbLR1O2wzRY63YgPqdGZmk/o80l+C/U= github.com/powerman/deepequal v0.1.0/go.mod h1:3k7aG/slufBhUANdN67o/UPg8i5YaiJ6FmibWX0cn04= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/pseudomuto/protoc-gen-doc v1.3.2/go.mod h1:y5+P6n3iGrbKG+9O04V5ld71in3v/bX88wUwgt+U8EA= github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3Q8ViKSAXT0Q= github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= github.com/quasilyte/go-ruleguard v0.3.1-0.20210203134552-1b5a410e1cc8/go.mod h1:KsAh3x0e7Fkpgs+Q9pNLS5XpFSvYCEVl5gP9Pp1xp30= github.com/quasilyte/go-ruleguard v0.3.4 h1:F6l5p6+7WBcTKS7foNQ4wqA39zjn2+RbdbyzGxIq1B0= github.com/quasilyte/go-ruleguard v0.3.4/go.mod h1:57FZgMnoo6jqxkYKmVj5Fc8vOt0rVzoE/UNAmFFIPqA= github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/go-ruleguard/dsl v0.3.2/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc= github.com/quasilyte/go-ruleguard/rules v0.0.0-20210203162857-b223e0831f88/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 h1:L8QM9bvf68pVdQ3bCFZMDmnt9yqcMBro1pC7F+IPYMY= github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryancurrah/gomodguard v1.2.2 h1:ZJQeYHZ2kaJpojoQBaGqpsn5g7GMcePY36uUGW1umbs= github.com/ryancurrah/gomodguard v1.2.2/go.mod h1:tpI+C/nzvfUR3bF28b5QHpTn/jM/zlGniI++6ZlIWeE= github.com/ryanrolds/sqlclosecheck v0.3.0 h1:AZx+Bixh8zdUBxUA1NxbxVAS78vTPq4rCb8OUZI9xFw= github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sanposhiho/wastedassign/v2 v2.0.6 h1:+6/hQIHKNJAUixEj6EmOngGIisyeI+T3335lYTyxRoA= github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/securego/gosec/v2 v2.8.0 h1:iHg9cVmHWf5n6/ijUJ4F10h5bKlNtvXmcWzRw0lxiKE= github.com/securego/gosec/v2 v2.8.0/go.mod h1:hJZ6NT5TqoY+jmOsaxAV4cXoEdrMRLVaNPnSpUCvCZs= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= github.com/shirou/gopsutil/v3 v3.21.5/go.mod h1:ghfMypLDrFSWN2c9cDYFLHyynQ+QUht0cv/18ZqVczw= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sonatard/noctx v0.0.1 h1:VC1Qhl6Oxx9vvWo3UDgrGXYCeKCe3Wbw7qAWL6FrmTY= github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI= github.com/sourcegraph/go-diff v0.6.1 h1:hmA1LzxW0n1c3Q4YbrFgg4P99GSnebYa3x8gr0HZqLQ= github.com/sourcegraph/go-diff v0.6.1/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/ssgreg/nlreturn/v2 v2.1.0 h1:6/s4Rc49L6Uo6RLjhWZGBpWWjfzk2yrf1nIW8m4wgVA= github.com/ssgreg/nlreturn/v2 v2.1.0/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v0.0.0-20170130113145-4d4bfba8f1d1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b h1:HxLVTlqcHhFAz3nWUcuvpH7WuOMv8LQoCWmruLfFH2U= github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= github.com/tetafro/godot v1.4.7 h1:zBaoSY4JRVVz33y/qnODsdaKj2yAaMr91HCbqHCifVc= github.com/tetafro/godot v1.4.7/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= github.com/timakin/bodyclose v0.0.0-20200424151742-cb6215831a94 h1:ig99OeTyDwQWhPe2iw9lwfQVF1KB3Q4fpP3X7/2VBG8= github.com/timakin/bodyclose v0.0.0-20200424151742-cb6215831a94/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek= github.com/tklauser/numcpus v0.2.1/go.mod h1:9aU+wOc6WjUIZEwWMP62PL/41d65P+iks1gBkr4QyP8= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tomarrell/wrapcheck/v2 v2.1.0 h1:LTzwrYlgBUwi9JldazhbJN84fN9nS2UNGrZIo2syqxE= github.com/tomarrell/wrapcheck/v2 v2.1.0/go.mod h1:crK5eI4RGSUrb9duDTQ5GqcukbKZvi85vX6nbhsBAeI= github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= github.com/tommy-muehle/go-mnd/v2 v2.4.0 h1:1t0f8Uiaq+fqKteUR4N9Umr6E99R+lDnLnq7PwX2PPE= github.com/tommy-muehle/go-mnd/v2 v2.4.0/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ultraware/funlen v0.0.3 h1:5ylVWm8wsNwH5aWo9438pwvsK0QiqVuUrt9bn7S/iLA= github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= github.com/ultraware/whitespace v0.0.4 h1:If7Va4cM03mpgrNH9k49/VOicWpGoG70XPBFFODYDsg= github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/uudashr/gocognit v1.0.1 h1:MoG2fZ0b/Eo7NXoIwCVFLG5JED3qgQz5/NEE+rOsjPs= github.com/uudashr/gocognit v1.0.1/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA= github.com/valyala/quicktemplate v1.6.3/go.mod h1:fwPzK2fHuYEODzJ9pkw0ipCPNHZ2tD5KW4lOuSdPKzY= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/viki-org/dnscache v0.0.0-20130720023526-c70c1f23c5d8/go.mod h1:dniwbG03GafCjFohMDmz6Zc6oCuiqgH6tGNyXTkHzXE= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yeya24/promlinter v0.1.0 h1:goWULN0jH5Yajmu/K+v1xCqIREeB+48OiJ2uu2ssc7U= github.com/yeya24/promlinter v0.1.0/go.mod h1:rs5vtZzeBHqqMwXqFScncpCF6u06lezhZepno9AB1Oc= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20200513171258-e048e166ab9c/go.mod h1:xCI7ZzBfRuGgBXyXO6yfWfDmlWd35khcWpUa4L0xI/k= go.mozilla.org/mozlog v0.0.0-20170222151521-4bb13139d403/go.mod h1:jHoPAGnDrCy6kaI2tAze5Prf0Nr0w/oNkROt2lw3n3o= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210217105451-b926d437f341/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190307163923-6a08e3108db3/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190321232350-e250d351ecad/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190916130336-e45ffcd953cc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200625211823-6506e20df31f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200630154851-b2d8b0336632/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200706234117-b22de6825cf7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200831203904-5a2aa26beb65/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201011145850-ed2f50202694/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201028025901-8cd080b735b3/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201114224030-61ea331ec02b/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201118003311-bd56c0adb394/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210104081019-d8d6ddbec6ee/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3 h1:L69ShwSZEyCsLKoAxDKeMvLDZkumEe8gXUZAjab0tX8= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181107211654-5fc9ac540362/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200707001353-8e8330bf89df h1:HWF6nM8ruGdu1K8IXFR+i2oT3YP+iBfZzCbC9zUfcWo= google.golang.org/genproto v0.0.0-20200707001353-8e8330bf89df/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.27.0 h1:KhgSLlr/moiqjv0qUsSnLvdUL7NH7PHW8aZGn7Jpjko= google.golang.org/protobuf v1.27.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.6/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.2.0 h1:ws8AfbgTX3oIczLPNPCu5166oBg9ST2vNs0rcht+mDE= honnef.co/go/tools v0.2.0/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= mvdan.cc/gofumpt v0.1.1 h1:bi/1aS/5W00E2ny5q65w9SnKpWEF/UIOqDYBILpo9rA= mvdan.cc/gofumpt v0.1.1/go.mod h1:yXG1r1WqZVKWbVRtBWKWX9+CxGYfA51nSomhM0woR48= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= mvdan.cc/unparam v0.0.0-20210104141923-aac4ce9116a7 h1:HT3e4Krq+IE44tiN36RvVEb6tvqeIdtsVSsxmNPqlFU= mvdan.cc/unparam v0.0.0-20210104141923-aac4ce9116a7/go.mod h1:hBpJkZE8H/sb+VRFvw2+rBpHNsTBcvSpk61hr8mzXZE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= check-1.6.0/goconvey.go000066400000000000000000000015321410630575400147610ustar00rootroot00000000000000package check import ( "bytes" "encoding/json" "errors" "fmt" "os" "github.com/smartystreets/goconvey/convey/reporting" ) var errNoGoConvey = errors.New("goconvey not detected") func reportToGoConvey(actual, expected, failure string) error { if !flags.detect().conveyJSON { return errNoGoConvey } testFile, testLine, funcLine := callerTestFileLines() report := reporting.ScopeResult{ File: testFile, Line: funcLine, Assertions: []*reporting.AssertionResult{{ File: testFile, Line: testLine, Expected: expected, Actual: actual, Failure: failure, }}, } var buf bytes.Buffer fmt.Fprintln(&buf, reporting.OpenJson) if err := json.NewEncoder(&buf).Encode(report); err != nil { return err } fmt.Fprintln(&buf, ",") fmt.Fprintln(&buf, reporting.CloseJson) _, err := buf.WriteTo(os.Stdout) return err } check-1.6.0/stats.go000066400000000000000000000045711410630575400142740ustar00rootroot00000000000000package check import ( "fmt" "os" "sort" "strings" "sync" "testing" ) type counter struct { name string value int force bool color string size int } func (c counter) String() (s string) { if c.value != 0 || c.force { color := c.color if c.value == 0 { color = ansiReset } s = fmt.Sprintf("%s%*d %s%s", color, c.size, c.value, c.name, ansiReset) } else { s = strings.Repeat(" ", c.size+1+len(c.name)) } return s } type testStat struct { name string passed counter forged counter failed counter } func newTestStat(desc string, force bool) *testStat { return &testStat{ name: desc, passed: counter{force: force, name: "passed", color: ansiGreen}, forged: counter{force: force, name: "todo", color: ansiYellow}, failed: counter{force: force, name: "failed", color: ansiRed}, } } func (c testStat) String() string { return fmt.Sprintf("checks: %s %s %s\t%s", c.passed, c.forged, c.failed, c.name) } //nolint:gochecknoglobals // By design. var ( statsMu sync.Mutex stats = map[*testing.T]*testStat{} ) // Report output statistics about passed/failed checks. // It should be called from TestMain after m.Run(), for ex.: // // func TestMain(m *testing.M) { // code := m.Run() // check.Report() // os.Exit(code) // } // // If this is all you need - just use TestMain instead. func Report() { statsMu.Lock() defer statsMu.Unlock() total := newTestStat("(total)", true) ts := make([]*testing.T, 0, len(stats)) for t := range stats { ts = append(ts, t) total.passed.value += stats[t].passed.value total.forged.value += stats[t].forged.value total.failed.value += stats[t].failed.value } total.passed.size = digits(total.passed.value) total.forged.size = digits(total.forged.value) total.failed.size = digits(total.failed.value) if testing.Verbose() { sort.Slice(ts, func(a, b int) bool { return ts[a].Name() < ts[b].Name() }) for _, t := range ts { stats[t].passed.size = total.passed.size stats[t].forged.size = total.forged.size stats[t].failed.size = total.failed.size fmt.Printf(" %s\n", stats[t]) } } fmt.Printf(" %s\n", total) } // TestMain provides same default implementation as used by testing // package with extra Report call to output statistics. Usage: // // func TestMain(m *testing.M) { check.TestMain(m) } func TestMain(m *testing.M) { code := m.Run() Report() os.Exit(code) //nolint:revive // By design. } check-1.6.0/stats_main_test.go000066400000000000000000000001731410630575400163310ustar00rootroot00000000000000package check_test import ( "testing" "github.com/powerman/check" ) func TestMain(m *testing.M) { check.TestMain(m) } check-1.6.0/tools.go000066400000000000000000000003661410630575400142740ustar00rootroot00000000000000// +build tools generate //go:generate sh -c "GOBIN=$PWD/.gobincache go install $(sed -n 's/.*_ \"\\(.*\\)\".*/\\1/p' <$GOFILE)" package tools import ( _ "github.com/golangci/golangci-lint/cmd/golangci-lint" _ "github.com/mattn/goveralls" ) check-1.6.0/util.go000066400000000000000000000026031410630575400141050ustar00rootroot00000000000000package check import ( "fmt" "math" "path/filepath" "reflect" "runtime" "strings" ) func callerTestFileLines() (file string, line int, funcLine int) { pc, file, line, ok := runtime.Caller(0) myfile := file for stack := 1; ok && samePackage(myfile, file); stack++ { pc, file, line, ok = runtime.Caller(stack) } if f := runtime.FuncForPC(pc); f != nil { _, funcLine = f.FileLine(f.Entry()) } return file, line, funcLine } func samePackage(basefile, file string) bool { return filepath.Dir(basefile) == filepath.Dir(file) && !strings.HasSuffix(file, "_test.go") } func callerFuncName(stack int) string { pc, _, _, _ := runtime.Caller(stack + 1) return strings.TrimPrefix(funcNameAt(pc), "(*C).") } func funcName(f interface{}) string { return funcNameAt(reflect.ValueOf(f).Pointer()) } func funcNameAt(pc uintptr) string { name := "" if f := runtime.FuncForPC(pc); f != nil { name = f.Name() if i := strings.LastIndex(name, "/"); i != -1 { name = name[i+1:] } if i := strings.Index(name, "."); i != -1 { name = name[i+1:] } } return name } func format(msg ...interface{}) string { if len(msg) > 1 { return fmt.Sprintf(msg[0].(string), msg[1:]...) } return fmt.Sprint(msg...) } // digits return amount of decimal digits in number. func digits(number int) int { if number == 0 { return 1 } return int(math.Floor(math.Log10(float64(number)) + 1)) } check-1.6.0/util_test.go000066400000000000000000000012171410630575400151440ustar00rootroot00000000000000package check //nolint:testpackage // Testing unexported identifiers. import ( "regexp" "testing" ) func TestFormat(tt *testing.T) { t := T(tt) cases := []struct { args []interface{} want string }{ {[]interface{}{}, ""}, {[]interface{}{"msg"}, "msg"}, {[]interface{}{"%s", "msg"}, "msg"}, {[]interface{}{"one", "two"}, "one%!(EXTRA string=two)"}, {[]interface{}{42}, "42"}, {[]interface{}{regexp.MustCompile(".*")}, ".*"}, } for i, v := range cases { t.Equal(format(v.args...), v.want, i) } } func TestCaller(tt *testing.T) { t := T(tt) t.Equal(callerFuncName(0), "TestCaller") t.Equal(callerFuncName(1000), "") }