From 07919e6b086ff09d005cf8f0485bbe2d878cccc7 Mon Sep 17 00:00:00 2001 From: Volker Schukai <volker.schukai@schukai.com> Date: Tue, 19 Sep 2023 19:25:40 +0200 Subject: [PATCH] fix: add race test #7 --- .devenv/devenv.json | 1 - .devenv/flake.json | 1 - .devenv/gc/shell | 1 - .devenv/gc/shell-3-link | 1 - .devenv/imports.txt | 0 .devenv/profile | 1 - .../github.com/agnivade/levenshtein/@v/list | 1 - .../agnivade/levenshtein/@v/v1.1.1.mod | 8 - .../github.com/arbovm/levenshtein/@v/list | 1 - .../@v/v0.0.0-20160628152529-48b4e1c0c4d0.mod | 1 - .../github.com/davecgh/go-spew/@v/list | 2 - .../github.com/davecgh/go-spew/@v/v1.1.0.mod | 1 - .../github.com/davecgh/go-spew/@v/v1.1.1.info | 1 - .../github.com/davecgh/go-spew/@v/v1.1.1.lock | 0 .../github.com/davecgh/go-spew/@v/v1.1.1.mod | 1 - .../github.com/davecgh/go-spew/@v/v1.1.1.zip | Bin 60320 -> 0 bytes .../davecgh/go-spew/@v/v1.1.1.ziphash | 1 - .../github.com/dgryski/trifles/@v/list | 1 - .../@v/v0.0.0-20200323201526-dd97f9abfb48.mod | 1 - .../github.com/pmezard/go-difflib/@v/list | 1 - .../pmezard/go-difflib/@v/v1.0.0.info | 1 - .../pmezard/go-difflib/@v/v1.0.0.lock | 0 .../pmezard/go-difflib/@v/v1.0.0.mod | 1 - .../pmezard/go-difflib/@v/v1.0.0.zip | Bin 12433 -> 0 bytes .../pmezard/go-difflib/@v/v1.0.0.ziphash | 1 - .../download/github.com/stretchr/objx/@v/list | 3 - .../github.com/stretchr/objx/@v/v0.1.0.mod | 1 - .../github.com/stretchr/objx/@v/v0.4.0.mod | 8 - .../github.com/stretchr/objx/@v/v0.5.0.mod | 5 - .../github.com/stretchr/testify/@v/list | 3 - .../github.com/stretchr/testify/@v/v1.7.1.mod | 10 - .../github.com/stretchr/testify/@v/v1.8.0.mod | 10 - .../stretchr/testify/@v/v1.8.2.info | 1 - .../stretchr/testify/@v/v1.8.2.lock | 0 .../github.com/stretchr/testify/@v/v1.8.2.mod | 10 - .../github.com/stretchr/testify/@v/v1.8.2.zip | Bin 114188 -> 0 bytes .../stretchr/testify/@v/v1.8.2.ziphash | 1 - .../libraries/go/utilities/pathfinder/@v/list | 2 - .../go/utilities/pathfinder/@v/v0.5.2.lock | 0 .../go/utilities/pathfinder/@v/v0.5.2.mod | 10 - .../go/utilities/pathfinder/@v/v0.5.2.zip | Bin 25981 -> 0 bytes .../go/utilities/pathfinder/@v/v0.5.2.ziphash | 1 - .../go/utilities/pathfinder/@v/v0.8.1.info | 1 - .../go/utilities/pathfinder/@v/v0.8.1.lock | 0 .../go/utilities/pathfinder/@v/v0.8.1.mod | 11 - .../go/utilities/pathfinder/@v/v0.8.1.zip | Bin 39099 -> 0 bytes .../go/utilities/pathfinder/@v/v0.8.1.ziphash | 1 - .../cache/download/gopkg.in/check.v1/@v/list | 1 - .../@v/v0.0.0-20161208181325-20d25e280405.mod | 1 - .../cache/download/gopkg.in/yaml.v3/@v/list | 2 - .../@v/v3.0.0-20200313102051-9f266ea9e77c.mod | 5 - .../download/gopkg.in/yaml.v3/@v/v3.0.1.info | 1 - .../download/gopkg.in/yaml.v3/@v/v3.0.1.lock | 0 .../download/gopkg.in/yaml.v3/@v/v3.0.1.mod | 5 - .../download/gopkg.in/yaml.v3/@v/v3.0.1.zip | Bin 104623 -> 0 bytes .../gopkg.in/yaml.v3/@v/v3.0.1.ziphash | 1 - .../libraries/go/utilities/pathfinder@v0.8.1 | 9 - .../sum.golang.org/tile/8/0/x076/690.p/73 | Bin 2336 -> 0 bytes .../sumdb/sum.golang.org/tile/8/1/299.p/146 | Bin 4672 -> 0 bytes .../sumdb/sum.golang.org/tile/8/2/001.p/43 | Bin 1376 -> 0 bytes .../sumdb/sum.golang.org/tile/8/3/000.p/1 | 2 - .devenv/state/go/pkg/mod/cache/lock | 0 .../davecgh/go-spew@v1.1.1/.gitignore | 22 - .../davecgh/go-spew@v1.1.1/.travis.yml | 28 - .../github.com/davecgh/go-spew@v1.1.1/LICENSE | 15 - .../davecgh/go-spew@v1.1.1/README.md | 201 -- .../davecgh/go-spew@v1.1.1/cov_report.sh | 22 - .../davecgh/go-spew@v1.1.1/spew/bypass.go | 145 - .../davecgh/go-spew@v1.1.1/spew/bypasssafe.go | 38 - .../davecgh/go-spew@v1.1.1/spew/common.go | 341 -- .../go-spew@v1.1.1/spew/common_test.go | 298 -- .../davecgh/go-spew@v1.1.1/spew/config.go | 306 -- .../davecgh/go-spew@v1.1.1/spew/doc.go | 211 -- .../davecgh/go-spew@v1.1.1/spew/dump.go | 509 --- .../davecgh/go-spew@v1.1.1/spew/dump_test.go | 1042 ------ .../go-spew@v1.1.1/spew/dumpcgo_test.go | 101 - .../go-spew@v1.1.1/spew/dumpnocgo_test.go | 26 - .../go-spew@v1.1.1/spew/example_test.go | 226 -- .../davecgh/go-spew@v1.1.1/spew/format.go | 419 --- .../go-spew@v1.1.1/spew/format_test.go | 1558 --------- .../go-spew@v1.1.1/spew/internal_test.go | 84 - .../spew/internalunsafe_test.go | 101 - .../davecgh/go-spew@v1.1.1/spew/spew.go | 148 - .../davecgh/go-spew@v1.1.1/spew/spew_test.go | 320 -- .../davecgh/go-spew@v1.1.1/test_coverage.txt | 61 - .../pmezard/go-difflib@v1.0.0/.travis.yml | 5 - .../pmezard/go-difflib@v1.0.0/LICENSE | 27 - .../pmezard/go-difflib@v1.0.0/README.md | 50 - .../go-difflib@v1.0.0/difflib/difflib.go | 772 ----- .../go-difflib@v1.0.0/difflib/difflib_test.go | 426 --- .../stretchr/testify@v1.8.2/.ci.gofmt.sh | 14 - .../stretchr/testify@v1.8.2/.ci.gogenerate.sh | 16 - .../stretchr/testify@v1.8.2/.ci.govet.sh | 5 - .../testify@v1.8.2/.github/dependabot.yml | 10 - .../.github/pull_request_template.md | 15 - .../testify@v1.8.2/.github/workflows/main.yml | 19 - .../stretchr/testify@v1.8.2/.gitignore | 24 - .../stretchr/testify@v1.8.2/CONTRIBUTING.md | 50 - .../stretchr/testify@v1.8.2/LICENSE | 21 - .../stretchr/testify@v1.8.2/MAINTAINERS.md | 9 - .../stretchr/testify@v1.8.2/README.md | 371 -- .../assert/assertion_compare.go | 458 --- .../assert/assertion_compare_can_convert.go | 16 - .../assert/assertion_compare_go1.17_test.go | 182 - .../assert/assertion_compare_legacy.go | 16 - .../assert/assertion_compare_test.go | 449 --- .../testify@v1.8.2/assert/assertion_format.go | 763 ----- .../assert/assertion_format.go.tmpl | 5 - .../assert/assertion_forward.go | 1514 -------- .../assert/assertion_forward.go.tmpl | 5 - .../testify@v1.8.2/assert/assertion_order.go | 81 - .../assert/assertion_order_test.go | 203 -- .../testify@v1.8.2/assert/assertions.go | 1856 ---------- .../testify@v1.8.2/assert/assertions_test.go | 2582 -------------- .../stretchr/testify@v1.8.2/assert/doc.go | 45 - .../stretchr/testify@v1.8.2/assert/errors.go | 10 - .../assert/forward_assertions.go | 16 - .../assert/forward_assertions_test.go | 752 ---- .../testify@v1.8.2/assert/http_assertions.go | 162 - .../assert/http_assertions_test.go | 182 - .../github.com/stretchr/testify@v1.8.2/doc.go | 23 - .../github.com/stretchr/testify@v1.8.2/go.mod | 10 - .../github.com/stretchr/testify@v1.8.2/go.sum | 16 - .../stretchr/testify@v1.8.2/http/doc.go | 2 - .../http/test_response_writer.go | 49 - .../testify@v1.8.2/http/test_round_tripper.go | 18 - .../stretchr/testify@v1.8.2/mock/doc.go | 44 - .../stretchr/testify@v1.8.2/mock/mock.go | 1104 ------ .../stretchr/testify@v1.8.2/mock/mock_test.go | 2084 ----------- .../stretchr/testify@v1.8.2/package_test.go | 13 - .../stretchr/testify@v1.8.2/require/doc.go | 28 - .../require/forward_requirements.go | 16 - .../require/forward_requirements_test.go | 523 --- .../testify@v1.8.2/require/require.go | 1935 ----------- .../testify@v1.8.2/require/require.go.tmpl | 6 - .../testify@v1.8.2/require/require_forward.go | 1515 -------- .../require/require_forward.go.tmpl | 5 - .../testify@v1.8.2/require/requirements.go | 29 - .../require/requirements_test.go | 683 ---- .../stretchr/testify@v1.8.2/suite/doc.go | 65 - .../testify@v1.8.2/suite/interfaces.go | 66 - .../stretchr/testify@v1.8.2/suite/stats.go | 46 - .../testify@v1.8.2/suite/stats_test.go | 29 - .../stretchr/testify@v1.8.2/suite/suite.go | 248 -- .../testify@v1.8.2/suite/suite_test.go | 619 ---- .../.chglog/CHANGELOG.tpl.md | 27 - .../pathfinder@v0.5.2/.chglog/config.yml | 57 - .../go/utilities/pathfinder@v0.5.2/.gitignore | 149 - .../utilities/pathfinder@v0.5.2/CHANGELOG.md | 37 - .../go/utilities/pathfinder@v0.5.2/LICENSE | 662 ---- .../go/utilities/pathfinder@v0.5.2/Makefile | 157 - .../go/utilities/pathfinder@v0.5.2/README.md | 69 - .../go/utilities/pathfinder@v0.5.2/error.go | 39 - .../utilities/pathfinder@v0.5.2/error_test.go | 40 - .../go/utilities/pathfinder@v0.5.2/get.go | 58 - .../utilities/pathfinder@v0.5.2/get_test.go | 100 - .../go/utilities/pathfinder@v0.5.2/go.mod | 10 - .../go/utilities/pathfinder@v0.5.2/go.sum | 14 - .../pathfinder@v0.5.2/pathfinder.iml | 10 - .../utilities/pathfinder@v0.5.2/release.json | 1 - .../go/utilities/pathfinder@v0.5.2/set.go | 154 - .../utilities/pathfinder@v0.5.2/set_test.go | 278 -- .../.chglog/CHANGELOG.tpl.md | 27 - .../pathfinder@v0.8.1/.chglog/config.yml | 57 - .../go/utilities/pathfinder@v0.8.1/.envrc | 3 - .../go/utilities/pathfinder@v0.8.1/.gitignore | 155 - .../pathfinder@v0.8.1/.gitlab-ci.yml | 69 - .../pathfinder@v0.8.1/.idea/.gitignore | 8 - .../pathfinder@v0.8.1/.idea/markdown.xml | 9 - .../pathfinder@v0.8.1/.idea/misc.xml | 6 - .../pathfinder@v0.8.1/.idea/modules.xml | 8 - .../pathfinder@v0.8.1/.idea/pathfinder.iml | 10 - .../utilities/pathfinder@v0.8.1/.idea/vcs.xml | 6 - .../go/utilities/pathfinder@v0.8.1/LICENSE | 662 ---- .../go/utilities/pathfinder@v0.8.1/README.md | 69 - .../utilities/pathfinder@v0.8.1/Taskfile.yml | 59 - .../utilities/pathfinder@v0.8.1/devenv.lock | 190 -- .../go/utilities/pathfinder@v0.8.1/devenv.nix | 638 ---- .../utilities/pathfinder@v0.8.1/devenv.yaml | 7 - .../go/utilities/pathfinder@v0.8.1/error.go | 39 - .../utilities/pathfinder@v0.8.1/error_test.go | 40 - .../go/utilities/pathfinder@v0.8.1/get.go | 74 - .../utilities/pathfinder@v0.8.1/get_test.go | 100 - .../go/utilities/pathfinder@v0.8.1/go.mod | 11 - .../go/utilities/pathfinder@v0.8.1/go.sum | 16 - .../pathfinder@v0.8.1/issue_2_test.go | 151 - .../pathfinder@v0.8.1/issue_7_test.go | 126 - .../pathfinder@v0.8.1/pathfinder.iml | 10 - .../utilities/pathfinder@v0.8.1/release.json | 1 - .../go/utilities/pathfinder@v0.8.1/set.go | 332 -- .../utilities/pathfinder@v0.8.1/set_test.go | 278 -- .../yaml.v3@v3.0.1/.github/workflows/go.yaml | 61 - .../pkg/mod/gopkg.in/yaml.v3@v3.0.1/LICENSE | 50 - .../go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/NOTICE | 13 - .../pkg/mod/gopkg.in/yaml.v3@v3.0.1/README.md | 150 - .../pkg/mod/gopkg.in/yaml.v3@v3.0.1/apic.go | 747 ---- .../pkg/mod/gopkg.in/yaml.v3@v3.0.1/decode.go | 1000 ------ .../gopkg.in/yaml.v3@v3.0.1/decode_test.go | 1771 ---------- .../mod/gopkg.in/yaml.v3@v3.0.1/emitterc.go | 2020 ----------- .../pkg/mod/gopkg.in/yaml.v3@v3.0.1/encode.go | 577 ---- .../gopkg.in/yaml.v3@v3.0.1/encode_test.go | 736 ---- .../yaml.v3@v3.0.1/example_embedded_test.go | 56 - .../go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/go.mod | 5 - .../mod/gopkg.in/yaml.v3@v3.0.1/limit_test.go | 128 - .../mod/gopkg.in/yaml.v3@v3.0.1/node_test.go | 2886 ---------------- .../mod/gopkg.in/yaml.v3@v3.0.1/parserc.go | 1258 ------- .../mod/gopkg.in/yaml.v3@v3.0.1/readerc.go | 434 --- .../mod/gopkg.in/yaml.v3@v3.0.1/resolve.go | 326 -- .../mod/gopkg.in/yaml.v3@v3.0.1/scannerc.go | 3038 ----------------- .../pkg/mod/gopkg.in/yaml.v3@v3.0.1/sorter.go | 134 - .../mod/gopkg.in/yaml.v3@v3.0.1/suite_test.go | 27 - .../mod/gopkg.in/yaml.v3@v3.0.1/writerc.go | 48 - .../pkg/mod/gopkg.in/yaml.v3@v3.0.1/yaml.go | 698 ---- .../pkg/mod/gopkg.in/yaml.v3@v3.0.1/yamlh.go | 807 ----- .../gopkg.in/yaml.v3@v3.0.1/yamlprivateh.go | 198 -- .../state/go/pkg/sumdb/sum.golang.org/latest | 5 - .gitignore | 7 +- execute.go | 12 +- go.mod | 2 +- go.sum | 2 + issue-7_test.go | 37 + setting.go | 3 + 222 files changed, 59 insertions(+), 48862 deletions(-) delete mode 100644 .devenv/devenv.json delete mode 100644 .devenv/flake.json delete mode 120000 .devenv/gc/shell delete mode 120000 .devenv/gc/shell-3-link delete mode 100644 .devenv/imports.txt delete mode 120000 .devenv/profile delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/agnivade/levenshtein/@v/list delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/agnivade/levenshtein/@v/v1.1.1.mod delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/arbovm/levenshtein/@v/list delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/arbovm/levenshtein/@v/v0.0.0-20160628152529-48b4e1c0c4d0.mod delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/list delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.0.mod delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.1.info delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.1.lock delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.1.mod delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.1.zip delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.1.ziphash delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/dgryski/trifles/@v/list delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/dgryski/trifles/@v/v0.0.0-20200323201526-dd97f9abfb48.mod delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/list delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.0.info delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.0.lock delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.0.mod delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.0.zip delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.0.ziphash delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/stretchr/objx/@v/list delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/stretchr/objx/@v/v0.1.0.mod delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/stretchr/objx/@v/v0.4.0.mod delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/stretchr/objx/@v/v0.5.0.mod delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/list delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.7.1.mod delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.0.mod delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.2.info delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.2.lock delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.2.mod delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.2.zip delete mode 100644 .devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.2.ziphash delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/list delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.5.2.lock delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.5.2.mod delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.5.2.zip delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.5.2.ziphash delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.8.1.info delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.8.1.lock delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.8.1.mod delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.8.1.zip delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.8.1.ziphash delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gopkg.in/check.v1/@v/list delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gopkg.in/check.v1/@v/v0.0.0-20161208181325-20d25e280405.mod delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/list delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.0-20200313102051-9f266ea9e77c.mod delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.info delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.lock delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.mod delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.zip delete mode 100644 .devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.ziphash delete mode 100644 .devenv/state/go/pkg/mod/cache/download/sumdb/sum.golang.org/lookup/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1 delete mode 100644 .devenv/state/go/pkg/mod/cache/download/sumdb/sum.golang.org/tile/8/0/x076/690.p/73 delete mode 100644 .devenv/state/go/pkg/mod/cache/download/sumdb/sum.golang.org/tile/8/1/299.p/146 delete mode 100644 .devenv/state/go/pkg/mod/cache/download/sumdb/sum.golang.org/tile/8/2/001.p/43 delete mode 100644 .devenv/state/go/pkg/mod/cache/download/sumdb/sum.golang.org/tile/8/3/000.p/1 delete mode 100644 .devenv/state/go/pkg/mod/cache/lock delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/.gitignore delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/.travis.yml delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/LICENSE delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/README.md delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/cov_report.sh delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/bypass.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/bypasssafe.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/common.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/common_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/config.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/doc.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dumpcgo_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dumpnocgo_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/example_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/format.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/format_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/internal_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/internalunsafe_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/spew.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/spew_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/test_coverage.txt delete mode 100644 .devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/.travis.yml delete mode 100644 .devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/LICENSE delete mode 100644 .devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/README.md delete mode 100644 .devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/difflib/difflib.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/difflib/difflib_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.ci.gofmt.sh delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.ci.gogenerate.sh delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.ci.govet.sh delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.github/dependabot.yml delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.github/pull_request_template.md delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.github/workflows/main.yml delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.gitignore delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/CONTRIBUTING.md delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/LICENSE delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/MAINTAINERS.md delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/README.md delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare_can_convert.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare_go1.17_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare_legacy.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_format.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_format.go.tmpl delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_forward.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_forward.go.tmpl delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_order.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_order_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertions.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertions_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/doc.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/errors.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/forward_assertions.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/forward_assertions_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/http_assertions.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/http_assertions_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/doc.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/go.mod delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/go.sum delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/http/doc.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/http/test_response_writer.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/http/test_round_tripper.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/mock/doc.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/mock/mock.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/mock/mock_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/package_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/doc.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/forward_requirements.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/forward_requirements_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/require.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/require.go.tmpl delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/require_forward.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/require_forward.go.tmpl delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/requirements.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/requirements_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/doc.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/interfaces.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/stats.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/stats_test.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/suite.go delete mode 100644 .devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/suite_test.go delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/.chglog/CHANGELOG.tpl.md delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/.chglog/config.yml delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/.gitignore delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/CHANGELOG.md delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/LICENSE delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/Makefile delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/README.md delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/error.go delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/error_test.go delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/get.go delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/get_test.go delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/go.mod delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/go.sum delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/pathfinder.iml delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/release.json delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/set.go delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/set_test.go delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.chglog/CHANGELOG.tpl.md delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.chglog/config.yml delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.envrc delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.gitignore delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.gitlab-ci.yml delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/.gitignore delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/markdown.xml delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/misc.xml delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/modules.xml delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/pathfinder.iml delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/vcs.xml delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/LICENSE delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/README.md delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/Taskfile.yml delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/devenv.lock delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/devenv.nix delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/devenv.yaml delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/error.go delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/error_test.go delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/get.go delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/get_test.go delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/go.mod delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/go.sum delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/issue_2_test.go delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/issue_7_test.go delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/pathfinder.iml delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/release.json delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/set.go delete mode 100644 .devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/set_test.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/.github/workflows/go.yaml delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/LICENSE delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/NOTICE delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/README.md delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/apic.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/decode.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/decode_test.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/emitterc.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/encode.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/encode_test.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/example_embedded_test.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/go.mod delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/limit_test.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/node_test.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/parserc.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/readerc.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/resolve.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/scannerc.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/sorter.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/suite_test.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/writerc.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/yaml.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/yamlh.go delete mode 100644 .devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/yamlprivateh.go delete mode 100644 .devenv/state/go/pkg/sumdb/sum.golang.org/latest create mode 100644 issue-7_test.go diff --git a/.devenv/devenv.json b/.devenv/devenv.json deleted file mode 100644 index 7af2219..0000000 --- a/.devenv/devenv.json +++ /dev/null @@ -1 +0,0 @@ -{"inputs": {"nixpkgs": {"url": "github:nixos/nixpkgs/nixos-23.05"}, "version": {"url": "git+https://gitlab.schukai.com/oss/utilities/version.git", "flake": true}}, "allowUnfree": false} \ No newline at end of file diff --git a/.devenv/flake.json b/.devenv/flake.json deleted file mode 100644 index 5d482a5..0000000 --- a/.devenv/flake.json +++ /dev/null @@ -1 +0,0 @@ -{"nixpkgs": {"url": "github:nixos/nixpkgs/nixos-23.05"}, "version": {"url": "git+https://gitlab.schukai.com/oss/utilities/version.git", "flake": true}} \ No newline at end of file diff --git a/.devenv/gc/shell b/.devenv/gc/shell deleted file mode 120000 index f11c432..0000000 --- a/.devenv/gc/shell +++ /dev/null @@ -1 +0,0 @@ -shell-3-link \ No newline at end of file diff --git a/.devenv/gc/shell-3-link b/.devenv/gc/shell-3-link deleted file mode 120000 index c1733c7..0000000 --- a/.devenv/gc/shell-3-link +++ /dev/null @@ -1 +0,0 @@ -/nix/store/zj0y62aimrc2m5cn3pbd7hasvvr6ypjz-devenv-shell-env \ No newline at end of file diff --git a/.devenv/imports.txt b/.devenv/imports.txt deleted file mode 100644 index e69de29..0000000 diff --git a/.devenv/profile b/.devenv/profile deleted file mode 120000 index c21b37d..0000000 --- a/.devenv/profile +++ /dev/null @@ -1 +0,0 @@ -/nix/store/ishxkjwm6m1nq2dzailw41xw5rczf6hi-devenv-profile \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/agnivade/levenshtein/@v/list b/.devenv/state/go/pkg/mod/cache/download/github.com/agnivade/levenshtein/@v/list deleted file mode 100644 index 56130fb..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/agnivade/levenshtein/@v/list +++ /dev/null @@ -1 +0,0 @@ -v1.1.1 diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/agnivade/levenshtein/@v/v1.1.1.mod b/.devenv/state/go/pkg/mod/cache/download/github.com/agnivade/levenshtein/@v/v1.1.1.mod deleted file mode 100644 index 4fcfe43..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/agnivade/levenshtein/@v/v1.1.1.mod +++ /dev/null @@ -1,8 +0,0 @@ -module github.com/agnivade/levenshtein - -go 1.13 - -require ( - github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 - github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 -) diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/arbovm/levenshtein/@v/list b/.devenv/state/go/pkg/mod/cache/download/github.com/arbovm/levenshtein/@v/list deleted file mode 100644 index d2ece77..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/arbovm/levenshtein/@v/list +++ /dev/null @@ -1 +0,0 @@ -v0.0.0-20160628152529-48b4e1c0c4d0 diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/arbovm/levenshtein/@v/v0.0.0-20160628152529-48b4e1c0c4d0.mod b/.devenv/state/go/pkg/mod/cache/download/github.com/arbovm/levenshtein/@v/v0.0.0-20160628152529-48b4e1c0c4d0.mod deleted file mode 100644 index 0381ddb..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/arbovm/levenshtein/@v/v0.0.0-20160628152529-48b4e1c0c4d0.mod +++ /dev/null @@ -1 +0,0 @@ -module github.com/arbovm/levenshtein diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/list b/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/list deleted file mode 100644 index 1af0c48..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/list +++ /dev/null @@ -1,2 +0,0 @@ -v1.1.0 -v1.1.1 diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.0.mod b/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.0.mod deleted file mode 100644 index 5e4b0f5..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.0.mod +++ /dev/null @@ -1 +0,0 @@ -module github.com/davecgh/go-spew diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.1.info b/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.1.info deleted file mode 100644 index 0644503..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.1.info +++ /dev/null @@ -1 +0,0 @@ -{"Version":"v1.1.1","Time":"2018-02-21T23:26:28Z"} \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.1.lock b/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.1.lock deleted file mode 100644 index e69de29..0000000 diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.1.mod b/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.1.mod deleted file mode 100644 index 5e4b0f5..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.1.mod +++ /dev/null @@ -1 +0,0 @@ -module github.com/davecgh/go-spew diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.1.zip b/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.1.zip deleted file mode 100644 index 826238ef3eedd456c73cfdc4745f803b2ceadf1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60320 zcmWIWW@Zs#;9%fjKnFSu3=HX+B^jkjddc~@`YDNJsmbXX`sw+)#RaM54rPXVhI)qj zdg+-Zndy1?MX5G@j^0Nccv|286m8u5LP3!A=xU8P+c$wrd@gU9y>#vsPp!N4`lY4* zC%@k-uduG!n0YPGswThxP~+adN9H^FWlqiTZePEAl6tDl*3vz<<cs#+sN?PA5lZ!V z!nWbCxwQ34zTU0w8BR9azU=(u=xi}f>&4~`-%e>{dlYVcw7qz0TzH|!myaKQeEIv8 zvwnIGXM>B)4O!l@fA2aMK0G+f@7K~lhZ72C9W{SFJ$3F{HdPD$nVY7qZFbqj^@oLl z;s5^tZ+4FT%GYK0F)%RvVPIgu9WJ`Wg-c0MVp(RfUS)1hO^|Q*6$gR6&%;Fy%Y3=e z$^6J&q1{#NyOQ=J+bbnnbKBmnyAYZw{_(iC$>)bFW;=iS_3_^7Do-Z0?F$x*$%OY+ z%cq~ab$&%K_qo?wWU^0hl-w|(H2Cq26F&E~j_0y6Bs>V%zjFS$A8$qL%3JTpKRmqp zv*X{GlST#H%4`cysR!~robpyeMsr5dUM{vxR)sE^GVVb<cA8H&KXqy}j80HB`yJ`O z^UIcPE$7SQ<#+w9%Ky&aKmVQd@$8S!UR<7ksJ}n{o!y=C-JH$e=2V@USzLZ&Zqx*g z8SgjT-oHcAzT#lA!sc}h`}LAF)`mQ<==o*7Gb;b4(|>`k{^AAEb)M6L7uFc^v^an0 z+;v^>RodT*56n|IW;J>#TLqlcFP|>{Z?_NQ<cmTQuIdUFm(uFub`)Lvm^oo%jE1}1 z3g@RU-X1$M(_MbW?Ri_D20dIcr8;tr>csT=hK^M$3$q2<6w+Uo{rk^j;Iy;Cdv2Oe zT+i35=NVv;X(YvEUBt-1z{rd*GBt^cOdn5YSHED_kO}AWZd*tkd0*4z=(oG!+UzG6 zf&-^aw2NfPxTLyL!ct32R=B{$agpqgx7=F3v*UiS|4DmxTyR?pPqqD-c^i%Tu50d* z5&n1cfA{a(yMO<Gm;Zj>f>(NSsWx*D89dIuAN%L~o;Tsn-(T%F-1hZy_KfEO>`OX6 zzu|uKxI*`X)bD~FVlUeM{kK@iUp(v3XUobZ$ukU(J6F9{>vx`Wfj8W2-g3ipa`}p~ zg3D9;pSLuB=P>T8`*c2hkI&r+HSq~^9;trW=WbQT`SQg@+vDBozwiH-NaCuV|M|Y~ zar-6m{*Pbm=1g=bw@Q8U;JIk>I>m_C-LmE^i5pFS1%`w?Y>VcoW?rZDMDgA(H|dZ= z(<XKIvQ8JW&f^L9n~-Y#P)Z`IIQU@Z4!0Zr$5u_rRlQOb*m*XLYn9!~h1uH_gUw<r z|0ygf@b@mzouiZ;F2Lp0Eaz!?Lv40VQk8<oL3x#h*V+odvg}?OR1mp9sLd<fVMYIB zGmWjAzARRK$})Y$kGA#3O^(z4?b;N3c<$9N9&Bwn+Of;l_ug~Jn%#IYN-Lo7_~w%A z65Tnv8?sNBrWhH9_e}T8n7Z71?VN`*9WF+7nXa6)DM0_SpR{^O_D4O91HBt81Gno< zUo3t&NZa*&pZDFJ&DZqIqK&qiN$=Znt^WG{BztC9I`Ut%P4y!q1H(TieCbG=sB{$M z>geL@s+XIxCNj5J+I-SKpFdrETlc9xeb})iXZ^IPKTd7TIbMG9n7HNc(x*H86qdC& zOECK|@MunZ`@imLujHhvjk57`?K<W#?z*_%zr0!7oRc^2Ncl_u4)gnae(t-vtf5;Y zS^8ezDv8+}EG#d6)#9J(7TglEd-98?QSFnR)&;IzHM!4U?%L{)^VD)@Y0S0WziVf? zPx{_H6<qdNt!4>IyK656iD}yyW?p{s^yuZ2m$p<CTzd4xWoKG+m5WvTPrK6WFGa2K zLCzoTlJ_k+nI|v!bN1~2wJ(>3UM=6sBltI>L;R)fi(Q5hi+dSWL^^m)<dW|=J>J^; zVqu9~oP|cp6oEzgp*gl}9ehjl9HIjsY>HjGCH5(Uzr)U5A0rm>R`m)*$qL4B3Oe&_ zxVW+DW=U25e8;b97Z|19U)y!S$%Q?``Srv&Qx%8o&@1P>7C$y)-{H{Wz3Bh^d3OEb zA1AT)iXJ+px&7WpF*)hy$$T3wTR1#l#S|5tu*j&&^BHqd`Sv-E1q+m~6mfgEOyk%h zy3UdN;MO=r3xBTbFQ!gwWBDf=%Cl2I-}}a{Z|mh6*LElx8CFbb-KIUk`?}kTJ8Vg= zx4ggh@hnW~O^I6U&63H@vChr$+iHOj)n3QlhZt_Hn;WS<?PSrJFM8~0F0XGM6Pk8x zt;=JlH!K$d_bj|xE0J3;(|f(v-e&<zpHKc-@-3svs@7ocT)UbdAC}zrI#aYYSL;il z`<bb$e;3R?aq|7TuVUMUa~IDR$-SGgd)AseElio4_?JvB)H`xfaE|rWAPKJ`Q}v(R z<?pVjUsig0=ai_Qug$a<7q#{%zpr4=-gIeW)^wexy-zGWPwLIve(b>0Q;rX>sJ84d z^@#so^fqbDXA_M~O_OU<<`E5>-J+jpl;?`vYSZXdJRej1sfat*BVX`?mtv(U(`)WV zp|+S!0`aRG1^&N{67!t(AVS0L(JroInwe+B=7i2Dd3ofLNSKbH*qY`ASH1222`wsa zQ~ADjt4ehhzp&7!-47pK{Bp6R;-unji(KX0o4c+ZzO>tSflTpUI~|9oPAQ8fKf60W z;LQt;IJKL*e(cz@C+1W@=l%ny4st2`MEww&e)_ccvoG;$!`^e0)rvgw3{-jlVpaju zjpmCRQ@wIG_&@Ib{N6(|SG?vIx4Ko=L-BL6%bMe@7w9l>X20ATGfPAxAm~EmoeKvQ znRC1Eg-RaDZN7PL#f#Q$OFx%>N|6>gcYD{#2bBlq&mCs1z3q7-wP{<=tGD(`=cgW+ z|C#5Ljr{V|WwL_j{+!M}*1h|?8-Mrv2G1W8c1Lbn<?rK?pL!+R<Tj5<vSLn5HW$<K zNrxMc`kxAjy;yejD*H)OmsKq@Qp64hxLtcb=gf>Lf){U^M)|Jfm)4)nR@)H1W#^d( zm6vM|t`K@&oh@-y&*h@5!MO+b{+jlr1h(8eq|kjRnL{Gu>xy_){|nO3AKtt8H#`4m zV?Eyr@q)A5o~tezMCLkf@==@nR!rsChh-0smkZ3(i&!@A)4`^tFFpNtpJ(5jJ(+c# z<@eXDKTM|E>-x^Gd|tbnLFiwrcf}<Wx78wN&#zP2s^s+NLbx{fjC+C1j!TPfAC%tt z|C55yaTfo8g_#Yr1t)AcsCvToyG)$q6h_W9JGXcAF{>p`$xgm}j5%Q6nxx!M>5eDa z^exO@_UsdUs3nlnS?K-M#zMMC;RUZ~yT#)5o6~L|UCFoM^+bh5tJeHmy!2QD_cy8D zY>s)1Z=<TyUskh;U4OCrQ{0xCynE~+{WrE=3HxGTBE-OOcvIiuFTEu%_C@u?Y;9Mv ztry&Q%xS{50MBTNFN=8vD*th}9lN=Ko0<Rk-QV_6JcT^(XZ~0F&zRa+XL3&8ps&q; zZg0lpCttT6Ok_LU5w7B&+m?JU{#v1U>TI4i`xjR>rxfVd7@s-teE+{s$^X2Ly*iuo z@mt=k{QWb1>NY#?;NM<bE}%90qr|(zAIz<1+Q{`CJ?`hf>B$Q5`JulWP3!MPnM%#$ z*?dpv@!vlA(vFPzHy$zlm2y9P^yZfwt1}0(oO^!H*zcj}qrqceykMjB(T;Ox=35^> zzD;cXiQWjC<znfKi<9I2$Nl=4Q58DRc81?`i}}9Cm4!B$6m4zjYn`~-aDV0A!kG+t zSH%sow)XmdN&ayy>vP0`<ArJuZuSOe-Q1J-L~E&2#s80QA37VI&{+6cqV3$H0>;Hl zi_>^6Zr6CQ_=kpD{=G|)>3eE#{bf9pW-$Bk8<8~rgl__A{R!X9XUt_h^N-J%bF=Ch zkuzK~6wi3g@MpApa{d1U=kxhytTWCh*tP%EJR^VLkK!5mgMac3?3ri$mwhJm%zK9R z3~>YZ8Pf~A{_K;K`}_3X{=cOrcKhc0ewzHUPkwHhRr6)bnzQ%YZ~i%)d*1H3l-q;* zyT9Mr8glRVEQiHH8(PJDtQmG}k2|pa`0;-EE=I@vsuzF%B-rULn|%DYda2p7Uia*- z?#C%_+LIhIsy{sY{6**M>b)Lb)mNon?q0ZV{oXTNUR?ZnHcu8xS+SWs<<*tjKmX$Y zeCMZT-##AS>t@~RSNJc(s_y=)%}05zJi2yDG4s+y=H1f`0{bRSI`ZJzuX+2npZNOK z`pFNT?fxgORsUVNd1>5MyU?}srGIfa#niv`dXavXMTYh3xt!2fn|7X1;hObtqIBmR zB~O_xCXyb>3#9)o%2sRZI=YUBRZm|i?3nJ-#sfW1qOuO3eH!Jh<YQ_x_iFCak0wQ} zOP#Ln5HJx8@To{qyPooRp#m?r(YNBN2C3wyT?!xi!`7?%8^qqOX<uQvXWb8n$7YSU z%&u1XtGv39bI9~=-mH)Lw_bcx3A64GNSJb~B}C?^;hraKQ9MH5<V|KZ1ckQ$H7#+n znt!2Ef2~9b8&ei1k5dMR;PhyX4O7;3)?B@~qfOZ3-R)Q<sefYaI|Yt^n7qg8xLR1! zhsk>`l}0z`zE-U&(v&~DU4xaabz0Qj7YCMgH%U*|-6^r>U3$gq123YEJ14%_P%L}m zt$k^nWXbuLs~p}g653lnPuTiqdv%Z8N9*a&k|x}cx%7%5qcizq=Va@QpZ^6I=Ddx1 zeQ?>ORbFSOgmBH?(X8Ch^>voize~HN)@+_!w^DwC6QAb0pqS1^_r()$3U3zp)sd^a zwfL{fo%_FYOnlSyoK&xKT*_lSJ!#oL-_|2*X18p$eRIdj{$Kq!4vw{}9M~!z-Z`~E z!X{IyA}!pc#%lhC87tacOj=a$m%Hs$3JKhGCE`iah33k?^<~#4*G1jj`TE(RcLyAz zg2Rs)&NeF#SG=3^%*$|xDO+jhddW4Xu5Ea`;6kdWin+chr=;Nr)?0p8mT#Kq<zB1s z<loisPWD#~qN#ho#N|1&9n5guT&_F&z`~VUnYy#=757Tic-3T8ZO#3dK0C;XXWq>z z0&=0RnSXZ{%~O_5k+c-O*0)~LZn|311$C`Io06x#c+b;%PG)=3!$UuR%-_MARIqV# zlCE?``|S(ojZE|l4|90yaOO?-c(io)QKj~H<}Sv53zNped2bRVYuB#j3tZikd(6&r za~R(Te(_*WL1w@Ad=8UMcN{<C@wCT!5|7v86rPtWJ5QR#CTp>MnZO|&_eO84wY61! zyCk!Rf9H)QeHOyZe%8|$b?hu%<-K%{{;n)1$EO=jRwVuN&x|_rn{(skwd`v{wfAlj zoM?MNV&_t+y;ts<ezQ->*=v$h_?&x^&JycqPs4cD{aktQ>^c8GZx!C0Y?4&$WKniz z=~pocaE>xJ+<kaql7lXz*b<-mkCWETnmm8IfVTLC_}7M05~loFGKY7ULw~Epiz0EC zEq=<5;q5Dff0;VoTg~_B+(t*OeOcN^ULXE_!B*=&<CKez&HGCBJ=^_ZpX?)v$wy~N zO?H~1VaaT~;*J{cIm1%(xz#6aoY&2c;8|G4S~l@gsmiR`(|bR^cZe>OJ-74IJw-|J z$2;EdC~A0L&N=NXtIH0y+N{NwLK)=W<+T4PVEFTdg-zn=E4T04H+(o`D*EgHjs*7w zJ3@uBcKYrLTKDZ~;}y-h`wNds$GTsS4}8DgW}Wu*cTaZD-^*90v+MKn$>x9aqs#x_ zU}fLG;OV1!c-KHq@zu9O+zbrorSWwQ^oi;kB<GjK7o`^D7nSH0XS7Um%)eqF(0cwy z_#U&XTq+({<Q$_o3mN>LUf_0LZ(QhRG4H5czEr1t|D2qK3c4{m-gWtD`<`d6+r@lb zum6}yg@mQ@?j!E5C#O6-dXiJ?gNSCNYJ^5=>ttco*PNYwleWa3{o<|9c)5w$kuS?K zsDEZ@OJ9ql(}bCe+b3sk+E|}0#jx*NK*hC<GEwTm>GIF>)^4A>%#hbkJB@E)*s~c| z+Z<|T-#>f&clvk!`C6y4Qy7oN2syg1=6JMblS=`cyH1c$-l|<|PsqC!-8b;Km6p%T zzoSX-xcZFR>z7w{tFqjATfY6hmWzr0iQcBa@A$5tclQ3Ww_wqpN&om3@2$)Gp~X5m z_T0^eukjE6Jp7aI5&HK;SF~}#(%t=uj#`Df@Aj;jKm8!{p5kbQ=OW=BcyI6YzMvo5 zU$aDV_g&%G*f#U5+PL*wkM@7QyiIaFPpgmk+WKyGGen0jSWfY7BqIaEB)lCu1EOLL zG!mwtR9TQ%T&$O#e<UKl_|XZ$dbjzD&K`EVm7Mzf)wfBvqLwdWy&2XtQTgP(U0zRv zny)l*Cb^j!Hz~)}e-Am&VPF^k>fWcM3oCwKuU}SwH}~B6M4j7nA9XKf+|TpiclYUj z`F;C${1H^kX*QVVd$_gjyy)!*@h|)(xwaj%uYUgg-cQRri=&Fy?i5K-DUosyI8|oe zv~^9zUTH>Q(U2JFqtE9$8hEdBJbf!?rqhb0OloB;SISmRl}bE)R%pql`J0Rbl$ow? zaB2N4t0N-JwpwtDS6)S{=nPfkglQZ(dgdM;PZi}9dG#;uN_e}?J^lOoTVgYr^cqZg zGmEYy%10GSJI{*~k6*0Qrqcdfr`AX9BTHK#pQl|*hS^4^i_V3!(+oU6eKhfUSJbgA z_=i+#q>1(<3-vYYJqx)bYlKsUHG(wqCjVjmmSa;pLuIq{>KS+L`cJO-#KdqZ`_PW= z%^!13v=`~0G|{Zv^lbg)B(dj}94C3wG>`OuT+{GpT0vaJH`TUGq1u_p3g)J<h@P!$ z`eP@jezAmQvP$>yqa2fN{)?V<&|>b>kN4#tMNV`Hp5an{k=Jrk<kf!{*~+9vE2Zp@ zNv0J3GtkxOd9AazIdj(J=N~2<SDxYG>T>IQWYt`epB(${9XpykXX5>fXLgzBO)7EY zdR!8gBKXs=JAc_pUmNM;OJ+y4DxK|8sXbBMD(Dh9Y4XJ{3ttFNjk-~2HTx*vm9+Vv zK2C^U^4ns!-{##XnBwQ(b9*6pL`V0Lzro81t7ffQJ<V5ndyG!Py^qV9g1B-;9v^x! zQG4Ai^N_v1%t0pBGnA(k-TlO-&2&dEFk(Sa*tP|&CJU?-IfA%$Of0&n;F8O|F`^)` z^2wFNea+H0^#cEzZm&_=^N{_pn3T!t!X53&Q&n4vD-`+Xt-F4tp^ck|u}k&PhDWo` zO228js%~>wj3qd6^@bF-)$>f}vhAG`8yv}9tkM;JL}16n4UVoUmo8}OiAL_@sb^3s z%U{rBIc?45Bh_~%>KUx4h+XWIxFFH`rX<s1w*#$?p__$FbEfZ!IW%kS8l?}Vw;xEg zCbsR+&Mugj9$_9a%l%pjNA}8?Q__EqTK$;Y{r}DVsuDMw@=ROhqZe;_vbk|rO8$FL zsjD5H)3_k|PL*8z_8`d*dk+R!Iy>hZ+<C6^!6usd%fCM|a&JDS$eUe15cAJoVxL>M zp3e+Bqq|8bv-6Z)H@mO~MM_lnrglcXe}D02^WJQhJ&Ai1jTf3%q<-Vdx|Z=pCoDVU z-2dcI4v)*_k<86uw?cw%-t2laWiRitQ>ia_zh#B*eK}!X%G=-XpIbLK>Q@M}i0r$$ zm80~q*oDHxsKqw<hePJ`Tb&Pju;@{U-*JbNkB-GfoZYx`j(csLbM@q~`Pl&{R`DNM zdO`Y2!Iy`!9~Q3)+Mn1MI(3oCsatmQ9{hKVW_f;OR^%$FZB7?&Z`^P#D509M_OG<~ zRoTnh5vP_F{hU+0`0kgDrMI?zD>*7_AHD3%JuAix@jQ-BY140RyQXRJtY)6*w&WDA z>-oD+O^Uj??4q(0;|taKVsE<te>DB{t)14E7hXH~M+!$zH#y(A&z)`3pE>V4SLpKg z%Uxz|4+tnW4vAM;yJ5<z^9Q_6tW`L5cISpOR~D{i*tu)luka83^;wH|T{<w?JfJ9L z{n4f0e!e_;@6gss*+qR)?QiAfJwFLE#2k8l{zKstUXPcPtN%PcQ7zYaxhBK&p<C0# z+=_r-e|{?0Ebf>0H~nw&Y2N(U#z}wOuPrHEdokdjRp76K`#L!9#$Dxj!etjLo3;GL z)*09Sd1~6)vOhHCtiO5ohSXohM1JP{1KAdnwGT;c@%eB`e%_0NlLAkdz1eup<K<0h z4U@S-wQDW-_on}kXul?5q4~Gz)Njqw1J%vp3*9HmCH~>vV=u_@U@vQh)sKg_n-9FV zKDc-Dv+pabYWHw5{di}x*YSaE^z-`}H<pS>ha9^ablN2JS?07I20{`ZjeQxP=Zan~ zOVFLjHD&smjlmb*I4G{2x%8#GP+ow9)cWIXw>tM323Wp#&s6^~eO|k$u?~v|PtMY) z%vpOx<8?TWY!lp8JNKhs$ckCA;@s~q1ZU*FU3p(CbHf&q?dvmE=mjiDI%h1fqt#F5 z=&w0!ecAex6IBX|Z}@gj=?N3!oy)s6CTV9;@t2e+xvGRb5pnL2YwRIjTDNohoUfnw zTeIC@ty6ND$*owirK@%%beZqoe)&Y}Y2)R_(rel7PW4XsmD=^YEulN)yXw!^k3N`x zSY_fr`QsCfZJfe?Pe{f6WUTqk_D@a5c;Xx9Ps|nH`QAu=EwSg&QT%=DUc@2U8wL3y z8~>i@E1!KpdXIhO|98(<*KOEa_xbHBgNb_<Glu`N6u$H34r^ut_pw~z_dd({CciYe ze_B<zd*7j_`%X;!r+8^c+My4h3KsTVaX<C_<dY_8`yc<e8OD9ro49pC+En=iH`mW8 zn5@n5O=y4SbJuv~$$FksWw-5hovm8z`1K9%iqp~-ee)byo*k0DaK%78&wcyh2?>wC z%B<F5?N$52*1T7yT6LOq+`2NqbJ9FBSZltq&3=(uw03*u+u7kidrq9@{cXGGOxLXL z`^wpRZH>|GLV=5K>BpL$4Oune?;L%>XBpdW{O3+uzWer~UzP8@Z_U{jqx_+3SK7&0 z3!bmI>+<XBi+!`r_o!UIw_n9eWXJXRosnrT*T-#U*f)3HjP3^;E?YkPa>D+w;PcXy zJpJGD8x60Qt(g`3V$PRBub}6`lbUYck^cJZ>|SF>3G*G_?(cH^l%)3C?_(O<y(;%* zP2#JUa^HBkqvCyLx!U^U+dAdzE<F(0y{PWZH^XZtyZ^BZHU2hxux-QNb?)M-qJOek zw(|CO6h)lq;Bq-@_c1)6-7Bcy=9gP~nYZ%IeUmGhSA9u;pPMIlt>pNn>3?jttWjLc z_@5UxKJCVq_N$PCfgxK6UnA6n)aFcaVp^(RdVbCn$Nt;fgpZ!TxO~Qbf6jk>b6Ilv zU8ARHUo_)h`^4*uUeS`J8;^#mu}<2QE%Nu>(SUnr^DdoU$NTy3v$KzRrh9w5EhznU zgSF!Jo@Re}ySo4XF1PpFJ1jfLvGQ$ouFan-tBn77)z4}TRR5zIsW<tl(6$$Tx2kh_ zS-2M;w=^l+aqeMCbnT9Fjx)ug-Zo$UZK%-VSN-9efZi!ZnKjI*>sX}R%p>{>E-qw# z{ixoW%|fB++l7UP|BCkc&1`rp!<K%2*HJO2<xDMnj&I*ec3!dho}6=m*NuDQyAMa- zT=qZQaH`R4!LNB!r2am-HtSBoiqlhTQbgGU4{y_wcR6M}W22OdEpu4PM}gZXeIp&! zUYVpn+Q&BS`G*s$x<rFM%!=rD%3JU#J1kYfdxCV}{si&NeWzVE_Bj>qKg)VPj$uKJ z;NyAWFWW>X-R+Dyaem_;uM<tzzcRTnx^n($6c>8MTNr1t`|$+svgySUQ$-g>e3X2p z>(6@n`Gn4{<wbmpDt?88O_=6-w*LM{C$4GE$KKtX)e{m}^;=5%wn60dKaJr5AFHN& zXC;SD{XSv3sbzcY+2<1sPkQWKdur;0uQGDxF?kiP`yvH(mj+E?<-D|Mf~c}QYy9)1 zv)xlBZ|h--3=5jF`<L1b=G88~uBYejVGVW5i4tR-zre8eRC2icrD@@-H|<In+*4I6 z-Q6PKs`;~jLa#@#@8!}BwfXwDWD@OP?Q1<IB|qnq+K-<mG3<9QfB9w`aXCJ*|H6&S z3#xNCD_&l32}r(eaUsv7t>D^$Tep(?5417vu*?!J&zN-RA6K?@$&0$x&l6-9roC^r zs`~J%!B}af*}H>JK4;A5o#$urW3Sl`h6%EV)?AHyTP@>zMM!&vvSO5sjG0zKb@a50 z&F|mb*uF*M%IOyymmY2S@BhQT=FZ#<^Qgw~f*<!U*2UCJS82}r7vj!h|3KCAOXdc> z17{vCJg#<TlFBoV{K@90Ro^T!nQf7qlbiLd_JaBxrEs+aOE3GnA90g6sXAp=@<K!I z(1hfxCNKU5Ync1{$8pqz?OJZs{p4(TYJJ-SH=lb)EoV%*n)2Q8tBJsMNAp$h*QdPb z(fbjR9B?n0d;2-D%aOTFtgP3Lv}@Xh{?4|s?95vuk+7r5xk`QZg0&wFENm8Ynkb*Y z>oYCnw$+!5d3)Afd=NiHd)tLo3&a?ts}CCQvfMK5OQD_YH<4+k>kIEc6JGB6TeDvN znC+a4N8LY*?Xlyvoyoh{Sbw(qo!9^7FaLL2x?}s7r(%4IGyf^S-TwUgk@9%aAJ&z| zKO2fa`G3lXPl@&|(QZA-%)oG#4PQ|~LeD2TKQ}i&PcJ=xPgH)fw0Uv8Z(Ucf)y9)8 z%XHOCgO3+^drvu9nG&R`Sv{}tE7P9a!h*7m)eJJ4*B-yWca!y<yyhuCb^p&wj~<Hs zmfyYq=+B@2xj#7lO1GJQDtoy=xb)%E?#J=-_SO{s;W~Fj>S4(8l_6sHjwJQ|_x#`e z%WKVtT<MC>qO+!M3Cm*jbI#kyKJnZ(+lZGDYPaP$M4ffk8W&BpX4yVPY>nR?H;EP( zX@M;7o=taBZYkv~iEc9c6aJh}$Yp}qw2Xp{t<lO;4)0)}c`;iunI}(EW`}B1#0yiQ z<tw(hXR0fwh(_dvX-4lkWhBD3glXckEy0W4vR{5C?mWZy-1GTtmlb=`3QXtL$js$E z{~*Jl`QjT6w#UY5QZeWC)q*Xg&-&@JFXlIvh>1J2{9uWd#Ci9_k{^GW%!)ry@}thc zw)rQ^Gx5cdz2AR)`SdHtr0%@5yZkym_rsf|m}krp?&m-J^5xM48~Hubv3<|#(?336 z{IkMh_SZy{wvQ}r^6if;&**jd`))3G-XX(#FP86Njge|t^T+#%Wu`W=yn59IX0!PG zpW90GcE?ZFoa1+F^TYaB{^Or7J`g&`CeQZXbE0NGZ-35>qX~AidF=U?8_1qpr~f?V z*w2zrjC$(Emt@wZAC{ZL`;7Tkt?Ar3{m(Yb)$Ecur{5NQsoEfIs^9a)Cuf+=@jLeU zWy2Q<{`>KL_xO)5cfMu)koWV+61!P3=MS~X@hn>`$vHRXeDh+pGv7*#<oIoazuEnK zTy<>Dy0*)oPkuSvAUWTBvE#-1dwJ<fyM(uMm>u@rts6emjL+)rwTnrwFUW0;c0YOQ zqWsF2|Jf#sD93HM^<)1zm#DS<x9*nx{#iWZrKr=AsijVq-jeQ~vokg`&1EQFDy(uX z>X^fE*Sk$|iz63x{AMUVb$_afo3!_vjLnBLRz9&WT2d@NT_>Ec>D%9LQ4*J|guUF} zN4UM+FZ`p%xyjmn?&^aTB~?XNa<^|X*<L-x^wRuJk9WZ)9V&vBlOHF~d0~4|RcY(* z7E#&#=_^ky^mMtRvMw@E=)m;#v9|<YUiIoJoa_~PJLK()zuT3Jwt8=Lezvlt?bTdM zoqyiVD-^f7J*jkExoyYsHA=s|Tn<^8T)JoabyY{*C$(i!wvYB+SG}lXt?|xOWLG?A z^Q#H<-e<qB&{F!g`>yC#=Od4d&VICt<ytAnb#C)^8R?mPS8}`B=X`KGIfXO)QJwxJ z-a}J&v`ZLoXK7Z7O8Rr{c#`V7bno0dj-1+s=Y^Cq7ukqDQ&{N1+f~6`w$gmn#-*AI zwk=hfnxz{g`CcMgnU^L1b!J(6=~nGW=X+JM143QQWmruFwaN{?*QY2oPh7IEQo;CF ztKaX1t0V(nZE+73oO-QR;HKl;Fs0Qzca-lK8n~MNan}o~c33MSD!$JnrT>zvlCo9& z+36MaYWb?7MXy({zq~<6lB2_LlJ>+yQA;d~Jk_&0I`4=-$@<JGv)7{T=jrwTf4#b2 z_q%*!N0Lw9jCz%rEqfNN;`LtmNJRIc$^)xB+h>u6M=l0Vk?tsdCm!<8_9uIZw`}xz zE#KVzbDwCf+W0od;nhENW!YJBYZOg3{Byswi#z_7?o0+L=Joyu5?to4xcql+c%22K zYOqpfu1&k&)%aa+!?YuJ{;Nz|QskL_xp}etb$8oaH`l(sp{abg>~;3<)#bT&83fKf z)GEFseNt#!p-1k7#JgwAPlYbHwvY9hmfPgKrMsSn?L0eSx^bdr5O46ogtQAvUsIA+ z6i<IDQhzJq!n2ji7w-jbc)5MPz4|=m@MEe+S`?Pt+SDg8olAGyz2{3(91cZlZFAi) zfk(0K(6oXEoxa*{Eh|iIE_LesDOnY&l%MWr@#f&;iEn<~HPqSSXSw10{KM)jtrE=v z0bhMSeGpn~J)yH*{E7L_Q$aBstG!wsrJp^T+rRA5MfM#Rq+=$l-D_Oq-RPdM_-Ziw z_9EX2tSw1qQ`w>%TaIzM83o;q@^~uSD*T?aUXgjRP0<7opX6^l%?zt@=dguznh73? zirP70Wl6L_W!E<Tl)}8usiK@eb2_<}RA)J^Y4tg(bTsZ@>c*umihp&NHy9fg1!;4K zt<vZ*Xm#D_=6#rDO;H!y+ax;~``gcxzZ~9GuXSaG!REt(3&gLlIXiQUiv6>z(;TNu zv+`8kT6^t!+3u@RhdnRUyplb&@$H(QS2papy!6?_%+9<{5ru0fGdoH<B1@xQF*b+1 z-fgp4A+I&$TBW>>pxB`{o&|das!R)W_VpS%iyB9SCS0`Sik^S-jO4sajUSF55>`AI z`~LQ$2_H^`pEQtI7_+!hL&f81)cb34I;T}`r)4B=o^nx0={@uEgIwxseYQ=xfB(dd z=0k6To@buPi&+q^I4A05Wn`F_mUc1^TWCykrsBVeZ`&2(D-B&st3R>S-SA|JdQ>BM zWFzOwPZ@ta4>?O;tKA>)?8J$tlG5o@-u>t=JDs<rdzwPz@9SH3Ph0<&@8`@&cah4p z54-MW9i34yXVtn(%$K@Kx^n)9Xsd_z2|wliCK<P-LG8|)Yw@k~PT%^n^H%w;yKG16 z{;#+f`eJkS3zyp9fEzBxUe*!5xobb%_&@t&+=KYczu!4lMf*of`P9sQ_V1tHYm+TL z+)dFuT%rs3znV-gW_;Lt*6!5YwJDpJ-Cd%#YJ25hY>|GN;(3zSW6$gLs~b15X-8b~ z*g0!g*gdUzvt@&PH5hL@d-YAZeLYa?`>X5o*0%*&hLs=R`A}>@{kgewcdT)JwSB_s z>|L>^cNKN<{h5EEzwEvCjQ^RuGtVoEo)6Z2#pm;4<|?J|^9vI4xJ#0ads37P+luO5 z2<peLTgtlUyg`wijlMu#rRUC1udcV2>~${N#Pz#vlUhoq=F8t_zP`C}Z~1or>JM*r z97{U>E7&*U#lEz9kuW~#b5)@-o#Bgo54b5kU8fWNC`>Dn<DPVXiToy;j{IA4qE<5d z|Ezt!H1=(!LPN#GvPF5n3s`^gxzC(6d)A>Hc^*P8&o(H`Y-ri8{$Y`&mdJPSeU-KC z0Y7(KXllN*HF>?qwWP|%@8RdJIC-k87B6c%(7M#oSLAWb0ZvUWH*5d+JN94i7)<=$ zp7iXfiSsnkO<V?c=PqwKApf__`>A%(V*6cl&sa|q^Dm3NxkGB@sj{0N>^puRXyd#6 zadp9I4N?9j_J>bzaFF!;#*%z%t?RrAT-t@<EX&xB?=NNUQMi&*sh41LqI_1*smeb` zen0wl>Ha}$UQM-i_wxz`SLs;Sg{Js)t=fEIvYt)z<Ff88ipBTm{n+FxrvK^5<~@y* zvr7K0`E<4a%fDrJlcw8#e{!X6zU|{HRTY<ew<if4FP+V~;^MZV^Ot`wulClTx6NB* zrsKMbcltt2u{Xc(vu3>a<<~MVw@vyg3*>pzOfJm$Rg=24Q1sQK+07<brL#g-_DGnU zr&&L0eOho#^vb6xSMrTb@=tIo{<@U+GqvHoxo@7XyczfWd?$v^{ZA^Jp4H|a=n@Uu zvLmO`?roUJJFi#HnHxeLK1)6vp*mM&<sbPa%GbXz$M?9~%nB@z$ddZN(krq+I4P|- z`HODiJL@~2R=n5Le4X^rrSXQgIYaNuolANAkLs%0eO$TnB(snk%Y)QIZn|IF#Ej=Y zT{+(}V@XCAAA8O59ey8P_eEE4FkW9?{@6!xV+qf^E3%)C+VA0uQ!-nxxJmAvyOZG6 zo=NGqBX93h|Mln5vj65QANgJPXJp*EHrG(?3fsgariYmazjfc3-hNO2%a5F@cRV~V z3qH*>b-JrGWs&WU*bCD20{5PJHa+7$=sRssb^FC;_3pT>|2OaXX!Sm0amuM~?&e2* zb%uw#j?6#f+8Jkih}Su=cjEp{Ri9cKe(D@PdtamVU(oIH(pjzC8y3s|Pp!SOWs6-@ zs8smHUsCHBvK`sluiY%#C!VUhpdz?b{7OOCrIV(=ULW*W@k&Ere}q&|%&xZ|uU|dj zvFp~xg<g8eCN0q~wq!r9Nxf~!aAd8pUgxXjou@^4XWsp^Yva7-<x8?+-|IF1xxo69 zIednbaiYttq^#O+!u{S`wy{^pCqDDy5KUJ4G$m*24gK_pX~8|KT5Y6^;@<n2@pert z+W+;H|MB%w{rmUi*a+QNV{3PAc0g&brR}wymy75A-J0`h`Satf20^PfTYPW$@iF$_ zm73_UXJ#JnWINXJR_^5C=Etg9A5Q=C3VgbnRq9pVLyOk;Gwyt;;eGzw?D3(qg67R> zyt=zr6a=lFP%F!Af7Lr{x=Z;kmTpPW>Z>m%h^KFUaba`si352qX{)`}xgXw_Y>7@; znI!q~>ZAA-3Y=<te!F+x%}!m+{`9bXNMe@%*6>el-SMH<vaWyqDs*+V2UpqE<iDzh zf1=v;juz@Hjt~*vcW~M<vB?Q5be?cUBrNLPe|WP*rs(uHUi?OLqH?qqGk)o~o9x;B zIO@^o1?AGa%3S!xc85Q9{mNPD-16+_+FKu+A58U|{_CXDpMUA1!j9+X>g{Q4{r}Z} ztxl78lg0nf=f$NSUT2#A;dk^@_bIw_%0vJDkv{t3w$${kog43K2`lm{ua$95pL@XR za)Emb%fo2R(#ng^ivsii=-07x<}3V_eRAIZ_cr}&^U9Va?RoF9uPFM%twkH%erzgS z?lmLjV$8=M>RjL3RBvfEI2zBtZX2=Y`-Q`b=3+~~A6WVId8oyztP1{52QKQK&vE^A z+?n;m|A@agHmv$3dVF)>S-(|T-xkF4T|J$5*PD06w`GApo0gww=wB%NQNpQDVXN$a zZ*!)Iqu=e%$*S6XdURgU#Din2uAL2+_=A`O5!ogW&t<<?+Q)D3afi>(YR+H<3xU8T zy#BNNw*PgP%4{fIlk~3naQva1ybV9@a9rd3Z>#fTpV9l@$HnA3rPS8xsjRAQ7jvJt z=wfAsozk(IwcqwL!UnGH=J*&J@G&sdXyEIOni4;71?i2(m!uY#=%wesiO9`=<RSF0 zr`}cf(j0}?ii}GxYwlWej``dXD<;b~K3ir*uaydJ5Pkfubo<Ey!T*0l?ruBCr((TY z^6vDBN-w6bT7GZ!tU2=|3)q<F<+*N&(adPgeGyyo`+c?e-Tj9q<O;Ca^euKdbpLry z^Zy0?8zyfs{g>33w$FKE-;$mRrY>i-i)|B@M@wI;k<;B~wjqV@vxk=8S)<kkVG~(S ziofdQY+)5YFiDqj=}eEEE)`u@xOQB)Zxg)1p~d467wfrg8$@&hEw(F))(D?1<jXoL zvO<(;_D5c!pom+O3q)I2gkC7Rym!;l&{;~t0;&fd&9G3OGWX7w2gg|Ji)3vqg2ip* z-z}T$fA4~<)8&r`KhJ*9(?09OPX0W#V2P@K2~R4v+gU6Yw6VCn(wNWYy80S+{T+=f ze_x!*r#Qo*;PFrP8;=jZsC&_CpXK)cTi%nMhnX2>#0Vc-Yb|@n;_-o>4|?}J2-p30 zi~HER_vHtq4_7d~Q!kfksCTwtpH*9s_{37)O)tiO8Ozh2de;BvWGl{{Xj^Dr%HGI( zZ%2ghGJ_dCwcq2vzq9x-N04W3^mAoRqpNFvhDnz_X8CvI?-ReoSHHe5ZaA}Jo?l*~ z$w$xP9p7W6+x#8~e7{>#^p<rWFTZ(S!DBzq{PZ=UQY`mUe0Z8qTFkIoa{R_$i%)jD z9yfaL5k4#6v#im4=l5bZ={YN(Prh)nc7k=*qD1z|A8(j0xb^!<e|5a_-JO?TpZs#| z;(_Z|GXlPx*VRsas2r_yLS%kjxW?2}*Vj|HS#?)mj9C+UIm?7qFNx>tB#%WYH@B>D zE0$atYWBLNrgj~7+D@zZPv2Wg{N#OC=SDt%E|3=V(R4*_SBP~BgI%M7>Jq1o35reU zu0E+f^;M9A$MDvI7ZJ1iUwIkNXg&7ztI(oSsmD^ns-=}bSf9$xTBUzodQr+@=VdEQ zekg_a9^hh}B%(O+QpgL#xhcn^Qam|yBR6d=-nq7{j^%uq^MX?@OlO0Bs{NT0zdhyl zt=hTeeidqe_wQ^||M;ynjD4S__x~;B=e)kx2<~|C>YUqZxd3xs*6BhldI1SSLUTft zxTmg}A?&7fCP~f9No9|v7SG9JcWT-0f0!J$^3B1SVySPxiR|Tay&h0fEV?*FuG3Lv zSJ}=tGb;mfen-9a36g%k;Rp+B@RjwvtZl2VOk?nF)&6$HRR8F;t@=|nbTs(2ru?-{ z-S2mE{q1P3)49jK@;o<L&$YPZ-m74#ur_O9lN6H;3-32?Qi|q(FptH1zgW=cH;L!J zEWGM)BAm@G)l($s-ur`^*}|XHx*zMd=uGA~BM`R7ueYbIpiAkV(6uhr&l07MYd>@8 zTo6uudUC#4ySs7x{jDY1rX^>yj0;*HJZe?{<kt9X)0zjhSD)3bOn4KzDrSpgz3l4a zN25yrgt&A@ZJ8ByLv_z=bIt9c+_zhowdw!Tw=>AnSM)d2n8Lzlw2YlS{=nqALlRFb zmtFD^WMg;Zi!)|5>K2)ObeG;&ZcYB3VYR(Mn^d2@U81$_>yp;Ge`jUnqZA*0;+o~V z+Oc8c+Nlea4^C2TdRV<psyBmC@DG!C)#V8vK8Ic{T2y1czomSV&;Om-6K;hq-pJge zD)%AtmiOI#8Llc~f1mPA-Ff`PwrsJZ7VO2!4>Mb{TASuIa)!75<#sl??X=_2hrsR6 zTJs(-rHW}YJ$~kJ*?rQz(k*Lu-`lY?<772!6r0BW?F-+XlYDL{>0$ThZ>an;hw$(= z59_5KDq`Miterb~PRggPC|>yZ{p??Nr+*ZmyJNRf>C!b5_nG-?1y0$txH$aOx#?w^ z=HB<F#b`+^2w_(H*r4I1F`e<j=lq|iSA6a~DjCK5XHt^Ky!H1*wyiPn<GlFX>813| zMH@1n%X4g2oKoPnce(L{lS)y)x-_>q9*n#<!^&}XNaUhVU11A?=P%h}Cbe^&i?rSU zuy4K3=W-^t?kxJhXS0+mTh6zK=Qoxv;oq_Ti+@kby<78dZg@H6)Ye<Mlet~zd@GqE zpStd4k6x?f{Ruj6yJuauvJ!ZreaNgic(%2R&)xqiI&BkFLn4_<XUA`LXX)&`;u=)g zmn#r-Fg-^sKd~)M?L+Ioqb^rNZAzzf9CE+en0+^4X_9BehWx0#=Uk=hc4>v#FtYu< z_d9Zl%89ihJKi}g&`xa4zRb^GlNZ1ta&yn($IdIuDp{vG$Vd23n;uy{XWfpx*^~ah zY@HspQ{LN2IQHsA=cJ2SlkO+Vo-_@9`0CSr&ONs$^u9N%(g~^T?lSjXKkIcv=Mv7m zS)z?WyJl(1tXwO{#Pr><QF1Y-$CNK&7WVDxdUC1;na{q<Jg>}OeLZBapAVBfTg|2o zFC>dR7iMiryPb9B)7c)g#C;2I-no#^d3?@`uf>y1%a0yyKXo*x-f%@s%dbNzTh?to z+*EHiQU3FueH!1aIJQdF-MgvoUtTFx_rS)EcSGjOV|TVCUS5>9M*P_ei*Jg~y<3&8 zd0)v6s-CrWwf%2(*O|ZXDTX%I%kR}w=ob3AJ#78j%CpO=cf8#0?`7+B*ZNr0iXz$K zZ@V_m<xbA~clUkF95c)1FRx~DXVw`W_3xN{^FR(q|6^n6w4<qvFE|cvTR!#wo#lof z?rdL}?p(fn>Z$X)%q|rEU6bxyUw-L;)m`a|rFX<H`cJLUW(-p0b9TR-SNhvcO6K7U zS$2)X!Ij=`M6Wzu^C8Io?TTxKeD4z_JeBsjZhchjnQz{?syJr;EA6M2<-u>aRDbz0 zwV;Oiijl_F_AAlHerwwO72bX;=dPEZL|pv>QLlX#@8?<6AN`Zxw)cItw3z$n$(@;L zExC2;t$u!gu%l}Ig-gfJWwlgQT#0Wxe|5{QEAMl5fBC-j<F|8JbE@iZeV86_Yr!q| z=ii){gt;E8d&;4{;gm?d<)N490ZcQ`{GaF?pRN4nMS*?5v*`0bueX2xE?01W&-wYU zeC{t*-_u()=l_m1@^hCxYq5{}b?Z)k^zW9hd%5SkXvF<loW8Nu{m#5Rh9wvKU;PjK zdw=7re;nU5dxDMr$GBc^w|x6Q!S=sCthF?EYQ?wH91IM<<nXnY3`l7$<)vk&gBnUv z@%gtsCe@qSyB_R*6B+3`?=JH@#T}M&lumCf=zAjkl#{Lc_XVZyAmy`pdF8=fWd`^E z23+;+nxvzCGsW=p1aWn<n_u6D|DP3lU0=9@Q#ttUnwYh=F{!pcPV?9Q`yO8Z^Wpjb zjOIzr21Z_<Zy(qfZ#?*anfy(MZlV9$jCOw-woN(bx%i;;3fXUp##h(zFFl#M@pbbB z%O{sAwWn`&|B(Iiz|2GWt*#n9tP9IsR;<cRl{pml%T(g@|5>-38#yi=l+x8J->}K4 z`poZu$juWipFOyKs5xG_W9dzWz*AARTRs{&i#7fXt4^Hl9@=`S>59UXMU#c@Dy-VJ zL)zJDckCYdbH@!lA12!U&MY$C*LXUSYw{PNw#(9WnLl>yn0@wP+N8dB?UTzjdEUQ& z__x4L-cNjTq1Tps{$k|@^801a<tG?6AHA#c_QJfrck=mam$%mxe0uk=&S>9Dfrgv9 z7c0!?^}lPoeDuTFCv}^C%)EKuPwaBxEWQMz)|WiT?0c7Ud%W-PbKhj1ykkDk{X6{+ z%goe+4!=A<!LG-B^21vBJhjgsGcLBD-175&4&UONCbIwEKd#s{gXjIjv>$mtrm@WY zeDR02cA0t1lFc9eA6uR|{_^qPrYk$<p1*hSua4@;hlaA>AExb)xb(99=bN%k9=|{Q z%iFU<`n>16hf`dobk#O%%1WGF*8OwBlNo*Y@A=>BTfW$E?%a=!M|1YgI3sttVgdi* zpDL=$HXnC2xzcm8FYWS63xU+vlWpaKmwhpqcmLe8_ia8uz6tO;{kQVenpi8K%@Y35 z%rhlY^7TWlojYRQ+3Y&~<k2P#+rP@Ze@)&Qy;ME<)wHKa?}^seL&|G>-(J{Qp7!VY zEiV6i=~};z2kv>Y;f|qr*Ze~_f+~t4l%{%zYi?}r4KUrsc%W%f!y?B6UNe^lC~W=g zlzyYX=C`6;ippDF!*AC#7P;%a^Zn}ekWKWCk$(TQ$B&okX=`N7otWU{xnG*0$90=s zz=}loD@iO?8W-35zGL_wce*!Vh3!YxrQgp;oywaK6My;TQK^UW8NLC1!j97ey<?;& zSh>HwS-{*d-<LN!c(u%*b(3ZWWVwIYrnI5-h2y9HEIYhXJa)P?h@Woz98kF>s$!?( z*4Ky6U75h?`>jbcFMor;)=!RNN}HYdAFUCzh<^Hz=i|4a^&BfjChAU@y+%*^<w23< zIv$@r8aUk62=8D0p<(ssZRc$MOp1w#KiuN$lsEaLlbiTrnbqNjyvDIAf2^J{vng8$ zUG9t%nX@@m=f{PG+qW<n6>c(057}fKToklk#BH*Ed9N39gXcjrz8RW785f#7Ia<Au zi9>bi8;8~2a~E)@?fYY2@0k&naeYzIgY9Y`ia%N&c&e~7Bj@lnj~NfFKYnD>-k;Z` zcw@DQd}`$M1+R-bryWQPotfLG=RCLh%Do1+=Z5KCJ3lBn1>ROulTQ8p!CBr*WY)`e zkE?7`be76rC{#0?t9xvHqDpR<c4EIK)6}D<W^t`m(yltQ<DR8+-dUFBi6&_;=4{w~ z?Dfqg#aUTvFIaBNDiQ3PY~~T6bV5*jYxfb4!@_STbzdtA`kioE`sI<Jhr1=dREytP zH*t$v%a)G~*Je$K3UXswd8%p)E3;Zofx}AkXUxyutbOuH@7elIK@ml2k;#@GdVM?e zdIQ-X*+{7U^IWN+xX$pmfOWqO*MTMTrq7U)5i8g|?WR;un6*G;o9NPZtqti$V#ZUX zw;YLTzY`yQdRKrCJID9*KG|ePgCd;+lcK~|Y!zm0dhlVf#c2T!zpm276aQRWe=%`# z`%E!*m($7m!D2@0Y1y*1i`H1~oiOK(O>M+%-MkCmlpO*hANiUt%WlZYT@kDNTsY1u z@{Pxh1n1;vVK=3VJ?T%2vc-CIHXl(Ce!j`ni@Q&yr)AC=!&kePOPR_u@T@e8Dv{}x z5nOns$yHU-b(!-4%j;8CW;~4eG&|z9*V2dure6;_y=UlVGCse9ZAtc8Pp_4XU)`b> zpG=Ltz02-6Ys}oWjx1a5NjaY^jtDilroD1wX2Z`1s&jX@r0Q~7ZOqzheV_f<#Q*cV z`xECymt2`V$BiR(?+2sewQH{QG-}QWV4j)b!PB(5Eo||M&=22Z#8~HA`DF(+yFb6% zd7^rvUyEF)SIVW+`Xb_+zR3hX4%i;{CPseFB*|TNQ$idxu58|VLF($~TQ*aF&A+fh z`F-5<iHbY3=DcJ$_w!DQ;cDG@za*2Cj~WuM%x>f>uAXcDG;>brqQ)y6nO}F<h&oyF z6w00odHgKLc3X0Xtb1CDk|EdmPqtn8Mk`(8qj@*!7*0R5_*P+hqf&Z7Q_#j>POD-a zX*Jh9Gv<h$I(kRU$N%K>lPQrJ8=LMds5Xj96}-&+dUC6s$F5_QPLcOL4)*k&>e-n7 z%KOcI_LE0B_f$U#PX7D<!MfLbmacff{9jXHk4wR^pqH^pj<FYoP8#sAAN>BpAWF5w z*>UFuhrs*<@0CkG8@=AVy2xb4t#DJ*xZuah+U`fSu2kk#C(G?u3jCe&*6zxm%>ix| z;&rQQR<thcf7R-3GPj$FlYia1A5kvTs*fqk#%xu1qivsMR^Kl@&!banZoz+k#dAq+ z%$+*MX8n1OlmBOJ44Corpnu3tw#Kia`m+?oR)y;RSj@QVo72-h5nlTqtBC7*$v)7! zBgg3e>ziXhY2cy2HIpJ7zAxYO>2Gqv%ri!J<PMwa%rJa1hwYQ>57Vm`e)KFheX>Ao z!<mAkn`cZ`-o9y)`HfkJ7EYad^#9gk)~D02EiAk-C&r=sxn9N`Q$GF+qM4m@^uis# zeP~>Mmfx*fuWnhwT6V_{$4!D~&+^s1iOZ<tto@a}qvf>1w;3@jIIiDbD;nB5t++h! zmt&2X-M0vld#$H?H)!vR7c|-Qpr*|%#=mv3bU}{Ax9N9l*Kt*9X-wu_wj(!wQFM3z z`B<UNL4xzm6b1Jvn%q&8S;3!_|1hCr`vJYXDq)K~x?ZbPDTY3e^5N7?a$HuBo&0y! zp0?<eY0jFPmu}8mzW2uuE1A7FX1~<B@LoQ%RJBUIKI&T)=f>vMJaJ_gULIszxuQs( zg@>*ATFd@Fx0<!Lm}%Tud^*$TpFh`R$-R!R+smG=bICW5__FBmy|!PURX%O^&HeRu z!u@!GpO5)-)_##QJ#G{#^=t3Rh84!a!piIRX>M|f<@+DS&T(zmtvcCnyrL7*KFpi4 z*<WeB^IMD846%uJjelou$d{{g|Id9v|HPyFN~~L+?5g|lvgJc%UZKiU^*_!ppUb$s zJpW-r{sWo)f(yLrXE&%>-B(#6-FU9)TY=qt`x^h}^ZV_kU%$$pz%TNTbBXk|^T{=8 z`Svybx8u7$ZGU--&!g6NlHJ6YmG&0X=gZq!+tz<?*}HR}-J_}hmM71<Ip5W~c3G%@ z{qHc_nte%+H@&wn<otbINh0S%D1)2O@*hX5pDU*69`<)AQwv_cznSlMIn%A}Cl9o5 zndf=%{DPm6mFBhE4E^@6F;vUhFL$HG{-oiy{ptz(jTUZm*~fAC`K1@9pB!N6J$Y;W zZ`a>1UK|#B?VVfk+38YOvCW@J^9rLQ9ZmIvHMZPh&6z81C2po3bk;^IaiQnTztayG z*xumYEZ;Zb?b5IydA_(9%_)ZrF8e*Y9v$hWnq$n89l8I8gRtU9<<+t(CzI?mZ)|=V zxY{*ba_;uaTg0VzX!U-cFmsd8%=cd(9-VJip!(^~*2g!>!d(6TU$99%Se0n}_Ne^7 zk`L+s9-myXnq7L!X%*wAL0K0i(pQv!bT+juJ?p|BSHrX9zg(KOH_P?Aosr3(L>Sx~ z9X>AcWRf&f`4c>CqIRy%t`@nxRKG;;N6}|g&QF{bP+lO~zRM+D{7KQgy1d@M2R6SI zd%1*liR6kGF{blZ`?tOj%sH#(ClRvcqm*6S>-xtF_4YPcKDm_i?5bV})5`@an->-s z@qG3A$T<0yY4O|OrJ7&o^z3g`_VvCZSymQ0OEFvQcVySE8&AF*yzy*%(u6&G?1cZa zdnPfnKdcw%nya&5clsu~oLl{pmg^%w8ed=I7UuQFDdRZHp7yh||JKTGJDBp(Wa8oe zCLc*9?<pSl%7dq0eQ+n8A?g3he1`oh;;j3pe@(p2e(_|~9+huXj!fOK$i-jp@aDc3 z_m+KAe4KG7Xj8#oj^%&aBeZ<@${Kda_W#opd9q_oxI$^b^u3zL#9j9|_0R1P^-@(2 zyuI##r|g_{oClqRnEw^Y``pT#9a!-0wP&MJPnB<v%)EoY!}kbZO!1!RDVnzLtyfmh zlto|8N<Dn7va^D-utTD(rf5sV0@e1jidT#ubzAQJ`KByjv&fO<vtHzcwf!jJn3*P2 zF1yZbZlz2hr?L;<EeqXu%~xiwDweBYR&9-XeB5Aqwp+dK$H}oXny1c9ugG7b@XG&9 zgN<&e#F5GKC+^&Oas91S>4x47lWaOwt2cj^VE>zV=Gf+c37dAUG02-gu_F7=iHSe5 zT<(Qjy1j<$B9EKGmF`0e%WL<U9Xo0>VHO{IzU;EaCsp{QliyYqot~`HF+2U$%A1j) z`cuy=aM`td*AbBkNBvgrX7KpBaAC!UFbfZ%D)T2|H}7s+edB0EwIti}rmjOlRoZXX zO^)hmozh=DdCi6LRg8)9QC$Y_yL#{Ztnsvb)akc!c4&|E5<By)@6)Eg);PFNvg>T< zZua6yvfqW|)SZ;RcgCE!GcWh0*`Y(5`r>)n@?R}dSf0K0$Ky?UQmnI%>|fJe#wEM; z)s}|B_?}Yb`%7+Zy`Hw;s_=tTxN2+F)9VM7+V|Ex5&ATj<M$DN(+{SufyM7%RZTBA zmlE`2+5htAZ^|xQniN$3_x3~gwrxT4ZItA1*#DX6{rBoY>)N1+C%;wwF<RdlwBx4e zo_~UCE@*dsoT{88n^phx`#(1Oc~{~R!}mUUbiKCy-n>qRxj9eXIlhouQF^$x*5c;x z-s#i2&t=T6&)=pIf0+Nz?}xKazTPnXa&6I$yi2tYEAB7(y(W@B<KHm`xz*)Ytr@ml z-uma`o05OmpZtgKqzXNpFr|TyfkDd%U+-3z_}*<wello7PGoNJZMRAP&ioXuJ@>OO zBqM6coHgN7cl0gOm|ZHgQdM(zQ1$Ob4wDm_%*H3qG>GV(tl$4ij-lnAQ2wh`Ve%S6 z2fo-`Uhi)nH=o0zvGb(&>TTBicUQ14zWng!>WeQwRPUHj-O}k9yj1p&z-ilm;<YZ! zy2dr?4dV9~oSjm9D&qqiS9@)TPuw>}<BeXY>^x+h*UZ_T6<ooxKbUWh=O4$YmLm}p zcBwd4CKf*y;5+sHK*Ya%E`ClW4R-4-J2VrsmwuD@uDCsIeNxZC_e<FKJ5P|_>^@1v z^!deOt2rc@-p`glcy0S9nWd~t9hYgY4SB(K_2M=8<r|`6*4g(@51z61LE6qACc9_E z9q9hZm9|>kU|#$O=f}6d9zQCim$v%k)rzvcO&_m{*2w8kfBdt`EOz3W^P9iANBG(I zOc&n}ci`9KoU4;;=f~WQJM&Dw;^CWL&$7(+W^gtfRXw?5o}Rk=@y}m>{C$(P?O*5i z{d3knzkD@|VYB5Kaf81mbJr(+o%m$SguU|*UCsIPFN<q>w`!-<`TC}-XG@Hv<G(&k z+BV1UTJ4Opuk*WAeZ)Rr{gS`^^3N)>eNEjTzy4rmjQn)zmAd?!#}#{{eC&OvZ<w<# zZ~e8Bp3_esNv#vpcH-N<I#XWn*lWYJ`y%!9(qD(l+ttrmXYV(?rP?OlWAfJ=!{w}# zkJjv!5$^l><?z)vhfC~cUb@AqAE7_(_030Rp}H>)S6D`0T-JTNbm<D#?zuY8K4%J? zx}{!wXI;dlvn7=~BjWlaKRm6?p71rE`{OT{J11Ur-%;8j!@ppY%~77M<qC>!XB4-; zsO8)ldTViN_`d{&X>m=Tw{_GcUJMNI5N*Dsbj)|-U9G*c9ENT4xkYOkH@oi+uV9$W zBHx$%bm~Q;R+iKW2X2SIdso3~ze_XZRlKIIM8l<MkCY`rPepfCC)CVb%-m(>X@2R7 z%$=PAbA@*p^4Q+#xtP=>R@!3d?o%O>TvfCvCuGSbJFB>emxiCNu9|zLu*;C~+{I<8 z>-FZCORm`yTGjo{G%8!;nawR1x2YnN+nblGYV0+S*Elh??~+njm9`awoAbhtdgjx< zJqq61(jF{Vrgf|FqRJ98iR{-u_kQ=9RKi(#fi0pZVB)m-ZmjLHStphjFDcIbvN}uA z^QQOeCu+PW?oF3-jMDZ#zN&ELDt>A4$Ueg*uego&$lklCT4CCFB1O{nth?e&N6wUA zDupj%<;_$o^e;2XrmmB{*J@%N=bL71(0ZPmKlU0^vu@1NL)^Cx|1>%}PaxZCWzR8r zo+Da`udBT}ubs#U-#ss-KXJNJPsyv}b#gMVH1=;|`Mr$WGWM}zs8p=HlG)5(@s~t2 zWEX#%bmdOE^NSs_Y%-<`N|JJp@i%HOlHFPK^!k^IS!UNJ7v@~F+{6%I*`>)ewQuUt z6PL?_$`^T<WKT%w*LEp5IeWs4V~$R>3+G2`+gf!5O<5CZCCphI_bTF+#H2HqmsL(R z<CuBWCRM+B=ljE_^ItxmU2AadbpF1(!t=B?Ic8qsyK>QI(wtKwtg)?D$6Ul#wok9V zl-G4N$mqo3JAp4WYC`utxuI#}+3!5@$=_^#y)D|Gv{p1tO6)ItEM>cY4|hd<+Uq54 z+l*@>KAQU_Y3r|5uU~YkZ;#=T8Io^n0&bp@$>3bRXG@E2Rgl#C6HzMW(hO@RG&_bE z$>bQAvX|{yvZ1bhT2ODu%Ed7P8;Tw&S4_Ovc}vXfhX+Trxj<6xjciA=jgsGdx=eC+ zrrhSfxw&cLs|$I*;~!3t-OE4S@V~KG*q664B|lV3HqV|qe~Ik3#{d1l3?z7}uGYp~ zD^)vuKCE)fRp);BZ(`@_d2T)AohPPsY^D3^rQy{+r|nj-cm*FgD5AME(d(6{>FT$y zEhNJdH8meUnIv5C;b5}s!+>|6gFbCI@xnICRh5Zv+KS1g1<w5HwL8wN)_<WqO(*W% z!r79~U-MSUFkP5h_(tw{c7O8XU8gtRRldsAH~HGtZLv|Sv!AkC+!c2WeJ-N2J}#8Y zdimdYn~?JNE2pME?^zc2>)D*gTjQ$3{?=cfVIuQyUf_S0mgh%nOyvxBigR=eaPaHT zUXo<GPV>fWA)(gHGpem?WW(0%QMnfP%!1)m|DvZXwdeMTmVQ*LpZZ9y|K{<Hk3DWI zOH&T!s$A7xy)uZ)d1JWI6Mw798*8dc6pow`Hk)b1ytB|R@J<!;L|3sQ{yCSXG`$YF zYp|5(@3|v>56-vVIz44(LnYrUhKA4Kp>LEHFFsUcxo3KW%iM@rIi>ubIg6B5f96nM zcZQ|OB{KVf>GnsVB60rD)*QH!r8_scc2;4L&|JR+!?hV~Q!cKXyJvyb^o<K8<oPwM z=6bDksI*r-8eDsON@=1bLyw}lrLb+KkJgqKNB{p2XI}U5`lokH#ruWlp4+-7IC5g6 z-X`9tB9?n|J@b3?oP0HpN?&-PvDfAS4~ymmfu|1A9-+%>r2QX=oSLY#PCL8I>MHB; z7M-j=mIBsZe5Tj4ML(Vr&p58IVsC_{gRj!#=Vt3WKK<urTNNu>`F6{TRXs{){wfQ- zQrM`Leff;?@g<i-PG~)>e--jrIr)`MaeI<UP-jwGZ%pUOBM%e%nwF)^a4E6szw}wb zW%{Ej6GSo}EIneGdG_$KCLsZ<_wN?YJrUz}=dMhl-1@(pITk<mn&)WX{XSe|FaOLl z&I>!sg0g+)+cmr>+4qh^*g0B!$AyEfF3XLt9&FTcYkk_u;_emtXwm`4@6Wh7|J!aC zn(O!W&W4;6Rz`m-*QJw>$89va_TPNkl6#?x&-gt1!0OGOcf2O4`2kb-odl<yxy>yG zCI>$<<jE>NO6)e@Fxkaywn~RtaFpfxMRvF6<qF@L%6Q<;j|qodmmgLPOr5`A(z|0b zrc}&&?|g8+XO>E-^B3*!j`oc=zql+vY&<{Azaodd*{pMmZIGIJ{Kc0tl7%zeSnHEA zuf9wbk(3TUIm07+d9tCW;iqQ*D`7lMAM)1c9cSvwRjh1i&1tups`~cX(>AH^lcqTM z?)Qm&f9x2`xmL4h6L%Kb*cgegT<^am)=6tFdv}ZYisdJZ?$;lhv!%YT{et?{BNIX+ zXYOR#Z_M|)x^!Vk-)FJbNf-T&W^~%C^@?9)z9(iO(8PUl?c`{YB-b(xMWsg<COn<h zvFuc(*J9r`ZkMpOQ?eT0<co4XPS#YIoT|Woymv;ay?dXwawT(6^A_o+Yqu;7NE672 zcwpC1KIzVi_`{r5t8dwVTg{fB@begNn4Q~ind9QgAFNX!ulnK4F<bdX=w9xxK6iG8 z$!5hkr$w{h{%|k;rtz8|3XRG-5t9T=7eDO28t8nx{>`o#8y4z+YWrq7=TC;|InG0G z&p3X*GfigOY|o|a(~o_5Abv5^w@9zEWS;Z)7WoSO-1XH})A!UCS6Lmp_+iWSrN<RL zpMI0kQe1iG+mBPf5-QRhZhn{96{_~)Ab-@-_b%*puP?rR**w>1=KsGD)9Qb|m47R5 z`(oLOdKtDE7uFhi?WnreEbjKW`}2gpsy7d}^uPF{#&W)T*AgzKPusrVd85u^cPt>| zYjI=d&nq$>SBe!*9;~{+eDUSKzw%R`G^DXiJX3EY&AMj!Rrv!29ESyY&L{j}YrB8& zL$$;|*0y}cw))nEEf3k+1bLDrlz4<C<}&@U+VP)#zZp~ea)!l<J#Ge8%@?I5YS|aR zPy8Y-v6ofiuc(`lo3w<hL04jnf!Bi`mVdXq^Z)&QTK^|~d-<o_|5qP;eHp0mw%n{` zv)~`&`u%+F`!`Kf=XW!8TJw(ABh~hd=d46OiH9=mJ7hd&%G(&e6Fe8vZ*Tu4lfPzG z=J`Ud>Kx5$)*|jA?(ZgiVEJ@!N4xbVpJkf2zFqnDkHy2pdjB2sy){#R=U$Dqv9g&S z)U9W3RaVOW#dPh?AB(Ta?Av7eyi(}rXSdAA?f%KJVWnSZW(v!M%rd&4QJ$Bpy5;J5 z=S68sCJZxPrYT(GKiu8k6&RhXW94YhueFS8$xbyFtpbhRx=s5_%AYk{y|b5R$DHNo zn>WV4S|h>IeN67kr5|PGe?>a(J=o}ced(k%FK=YeZEx1`WS{w`>CW%ao6~3iIIeCT zCb;-@`t9E8)voKm-jizl5^W!Jc3R%uRHlYU8jYUww6{(#kBQbizA-;AZ1Fj@ts0Mo zgl4V`Ir$-N{mRMzXI1)^ZVQl^Kl{*@uJ7|3zOR|GzU`Js%B%nHZyddOvCD)v<fUgf z->gS<Usmio6hEU$qg-~8OS#iptL0JOi|YC8=gisj+ppwB%0u_qp8Gw1k1vP6@7up< zyKUWv*|wtZCkM>fCoF5_^ZL~L_2TC48i9ZNG`9qrYNi+_nuxaj&HZu8+Gn!Zuk!so zFF&*E&3s>HJ#UHS3CX^F_HX|Nt=RtDx#OJt-AsMn^yEu{i@CLTKP*sr@bK^BUs1x} z-`h7nE?;8Xytc4cfF=IuHMtL)4`{g@J-^H)PWEGQk=oJbMQI=0f)?9XwLj;55)_>6 z{!agpx8u64k*|*?lr~;(y`DAuQv}OSe|5#T;&zL)rk>@VzATw1;kBdM$t#5!DX*q$ z^~YTiGF*DEK6t;T>8`8WzQ5kIzV`1meKQH8ov!f_yg}0&U+!+SsMP&*%{u90J$w<@ zvA}DO<9Hbu{1x$a-1JE3xRvG>=%wdhsm=u*koO_|-1-+g<{kI8`f|fBXyuemUb4P{ zg4wF4yn_mJQ;Q=DmbD+r<T%495froj|L;(9gM5)x_2_c>N&H;tY=67l_AmVV%9TYw zVNG}Q#Miyebw&;A<M#jj^)!6_{TgoZq;`XAm3mWK?UyID|97mP6w#^sPk@nmzw_p) z*Syvq$kfo~Q@nUIkt2HUsW%2J3xhnCmb$I;YJXsMsp;y>+uY3)GMSxZIRXP`IYqbZ zEs?&^_J6%MyQGo_x3tL)s{^+<o*KwHC4TW+Hlyh_2YX(#LReLMi{{FwfwxYw%w$~_ zZE_}Teiu_K<4T7omX2Oq3I%d2O&gECefsHdhF#-Jrh8}e>u1IJ=smcZ!Fc(ovBX)u zii<DuDod@~yI&^N*v`7AlTcF2``-QY&x~zz{KQ&b|1GIx{d}^2@lRHr{KQJr*ewO; zk6kYpzkIWw$6{|~x$WGTEdmGLsy^H?^UU$^#W#z-lvUZr{_8y%?>Bw($t1zUC2X6c zXZ$glshe2nS`js8@7x1lOTK)oVw%3a*vWL(UtY2IYL8#OsNxX6{4-^b%%PI7zq{rh z{!zAV#-FcwM$vxm*9#1HN&fZdIU{Levne5b@zY0TpDw5HeLnf<U6p52%(?vh2fxZ3 z=N!J9WYp4qvB>4Z`)AvyUw)dz@qWG9>D4Fa{E$04W9i4DDr@D2k8g7<<pt$8pX|SW zSzdkf$CiYA$%IPlc)$GjVvGqKi+`3ly5zr~<`}rWr>w?$wy#alHM^IO^A66q=lg8> z_Rq5gmG`}Q$M*K$Y7H%yBK>O|+YZ!<oXlO=+gx|0dYhHSmh+458HaTGEsffL>jATE zdbIoh$+P}t#U&Y>HZ1)2TuPqnSL$5PEw@_d2d#a(IYYqJI+5f5>hJ)sr~9JixVBX@ zGJ2lL=MiJm)l$DI)e<ko>?6BYS9dP^S&t4DDfW|5&DJ6rKPxU3ZP@8^;nU6A51ga& zxK~~)ypsK5UU|p8wAz1H>TM-l<bGBtpQ#D@xLvO}kwL!0^gZVbpS)IYGY{>K_7r8G zGY4ej6kXdpAD>q$%y5uU<~x&{(8u@PtglKmFsZLZ^8S=-y<fLYu>AJ_<NS}^`;YJM z^SlzzdGr5o_oJ`pZYo-9@b|CHbjC}M6&W9xe7}0gzw@AnR$yPnuRR{3t;!cOqVMci zlsNeJmEA`9#G~qEi=BU)b370fdf%*3^_7d`<{{4ZlvREKJrlJqr)kR+>V`e}b8>xj z+!A8}9_C#RhqE7b7;G1aOh0wxVEc;g?Th~}>ANre@`B4=5$^3TYl8J&iAHI)AG?;n zebJAZGxX;CYz;rL^%7h9j|V?`7}jh#cYFPEE!U@qULTPw{E)OJRPFki%r6r|6>J?E z+n#KDXnA73%B>02igzbV+1$2#XYjmX+Kn5+Dn7eDaGms;>R{h0zBP!AF}vQOYNF(l zkIH@aE_?5FUVlEJ^G?#0*ODbm0|VbDU-5pt_j<~F*+iS;Os%i~|KYa%c6moywn2+Y z+A{WLh5VH#R{vA^G)YEs;g$`H)rIb!no=H_`8DXIOog?P<Gif>j;yWQ!qye_a9*CY zXy^7@YtG!9y7W-zgO^2>@siE5Y{GJE+n)<hTC2ga*2k<xS8$b)(+$qzgtf+MkHjx` zSud1Y=l6P-YGQr3bzq%biTvTbH;?vvO#Q}QaPP;ROjqW4_U-y*AFrHCdG~$&_U7Un zM<>f{|I7Hk{krm-rmoKE<>wB#tuXoSSEnuG&OO&L_sMGJnXM)>KB!w=R?yM#xe%4e zw|pu033=~tjj|_YwpX?D3O>~6k4{|oJ?EfjCeO{O+n=0yq5Jmm#OELTd}p=XopJEY zvB3Us-|Hk8&YwHTvDMAv@hp**Z8@{W{}jYU%I$x@bcXWnw5>H9-<wys-}?PR_GP>P z_lc#YZ_+-=1ewfO=r}du7RM8l8@>0O^<;t!xaE&Y8_n5Ve50%S&Hq2%AEcZsWdD3w z8Z(`(QAVmUzt!qTb53X6Ucoo3FDeA2?XlW2V?x&14ymiFOm0Z!#=l;%q-y=1O*2>i zb$cdZ;;pTH)M#6jOVGwiKbPu-dKI-K&zG4b(;pvpC#veZ)vLD?>fZd3d;6iqa<XOH z-<yfYXGkx4{=mm`-m>jR8t?u-Gug85kI}2IF0-VTwSKf-&u+zZ*Vp2COWe}G-)<`k zyg0BqV2SgE?=8zWw$Fe0TmSy$-_Or4^muqamN`pvQR0@gcTZ0z@9Q^o&Yd7An|Nw{ zS%mzf1vC7AGCq6M^3P9m!?TviN}shGe{pAa$H?5cx-~if&bLpy9KQNVgyf&R%Ri5Y z0la_j^QOeyD`giLITMrG=R|yC|JY>w;NODXIw!XtHM`2U-*KnA&S{=~4?Ywtu8nvq zk&`lI*%Xe2OV^$aEY(S7us`rx;NLuv8M@I`%2{*#kH1;<ccSS&vt!>bNv*s;_mIca zbsrk{WJ$f3_Wpb0;me73ecLxYUT?9au1ffA+^&|j)`DUSjTUd_3swC*G3t55d&c#- ze9q;iPorL4)l6G-=I+hFB0;X6gmsxdj!X9+J{VZ`(c_8QK3$Co_JR+c_Idrgc>K3S zgFu6R;(`#(StqRb-?6@XFj?W-0hg}i`nkXM$vCUMd3Mrgb=td?9F>iHXT!9XOlhmx zoA3RBaf@{9GtD&<PJ|xW%D6O^$KcdjIU~MJZu939{JYfpIl;N$nZPYW8J>t&b3RLX zO}3HCTqAuc-F2UB`&5s2mN$7gC#=i%@Z+De?v?NQB^Iv&Pwvt({-F4N_loJS3K=q) z+*Yms@UZF1^*zB)%NEU<cp@-GJbtm#eHG)3+Le8m&i!<q5@z=$p1<k!1AV!BSMyX} zZS|SGL?-;GzNjNt?Xr!Byi9x^uMmH8Yr4@#-cT>b`{!;l-pub8d1B@^{k8AjebI;i z^6dzFSR%D5Fxf&qZd&T*l|K}8XV)xWq|W><Cw0Q4%j|~^ls4;C)Tch1I*D`U?I>>R zawP%7<7aNJ4*wvxSFSZF-Sy`qt>bF!mPRty>KRgn7cmIva6IsOU)bJuc7qao=<C$= zSLeqt#GaOQ%Cy$B$YAA^^1FT4ZPnKEf0$iXepq;6%hAx-8J=f?wM-pmPdPV_ZHd67 z5C!YZr(Vx4$sU+u`MdA?iC=nCMJ4%aRh7z|o~eA9Fk6>rmzBt&Ni!F!I<7IEG`E{o zJ5=b_yr~H*-MpV$9mw-u7w5^kPpZqZ;P!-w!jzv$>5n%ClzLr|Kd}E_=-#Cg;mcX9 zxt}-Q-x;2v;U1OPE^zPTBmtevW*^QSyVt!}ZreHKoh9er$9~XS-ZSBhm({uzVG)cQ z>V>aeWAC$Az-yD7q`UBtdH-s!D;2piLa*Pm%~@VqR{f;*+~2JKi$0pI?OEa3x#x%c z;srmSCf`4CEVqBJi*i`*MC~`HN>4e?vpCggwNout=1^yjpLe(P{AsCYCWK3eTA1#8 ze*Wc#Hg&C@>AT{~KQtK{i0<EG^{YYYCd0EGOM`q?iCr%-Vh&MmxL&Y&)6aF;B6}yu z7g~O>_4rZz`tx^%{eLzYt&P3i>%IT#YNOwgL3MAWdv?dF26&5<+5dG+-mCs?hiBIM zS!SXOiY~FFKR$hXfoE7s>yzg7CLXfs&jq43g+|@Z$}suM(`D3Ge30S0>d|{MHhc|F z4Xb^xaQfsv-O$$a|JKd>xj+6?!;h!4j~jR^Z!g|?&w~HzyEP@B)=dbCPLFW)U9EQI ziD%}TJBf7-E!xpSGs}A3I#}gB`#VjRXJ(XCd6mr9GCn6&=LdhoMCv*7n+&%VS?|5u zCHby+<p#eFd!}b%{nJ-H4poVq%+-`KpF3KwZ0pYZ8OeXQ2EE8`=J;u_J<q#au3?Yq zvd|NXC40K~3a^E{uI8HXJ!t8as8?6(150lG{$=AjQMhW~x<?02SFT_^dBY`8B343E z=2`o$T%7|UzZs`E1hq&UI>vr*+3SOKC)n3sT98_^OzW}bmt~57eH%|qI9_3;T&pFy zH;G5#s^61MVXk*4+|D!PedBI>jZr>+zU&9VN7Lt4T}^&<Ets)>_oRxHrHxZ}?M>wN zS#o0L7fz>8cg5b-_tJ9b-<fCS_)u0fs$VNsBed^Y(+S?LF9F(9bqe=8HkZa$hU}lS z;9tq#A3OfohW@SFbSJxZORL8QO=kbAVRonAiF8=5DmA#`BBHcVrrp?~B~-KcdyrOC zu<nYrmyN`%BJW*#t@70WT7LKbXji5>*M>`xXN--?mR>zwzvyC&#uL@J#Zpx_Ha<vt z@Kqr0`qGTM9BZ>KWo>p3nZx_~c<XtdRmVTNX`J%$4_Lw7t@!5AMvaX5Rx|QlE*?4^ zebJ3|?Wre=^RI=)@3UyXKBs=GG+*-i@R!lNrqX-973;RSpXk4n(3kb;{?Ze<m+c>1 zI~Zbl-+aQU+TXtW4;e}vnteS~`r!`4PnLG`6P{@buW2eu-n;0>**$%(7axATZ_S*u zIJqmYPW<8?r(}&~roDmrZ`kK=xfb@C-zMi`Zb_En>DK%$Ufe4z4D0Sh?BeWp_TPN| z_=9fuyaI<?wjT`(OjeY}TF%}4`Gc{*gFDSk|LZt*AN>B+YQOZ<`p;F|Km9GdeZKsV zVcmAF=2PXul?)3PofNlR*uB6)VC}_^dt6t<uHx7zxOI7t6IaiwwC>~jk6v`Vie6i+ zbW+TL{~k-(pM~}kGVA9THQlVL`kedx<LmWS{rBrGSFX{#y3LKV>ovQy^`cUB>mx5V z`u5Jd{p4NBbUEAWESB!PBDMRfCOt`A*ZTX{YN?+2+7|x}Bo1AVpUd{=+wAiUb-&Ll zAJ}+L%+hX)!{OOnJF0Aa&1-5uUoGFy_>ZNs?0Wja!=<yY`<qGi?|S)G?$pW~1>a6= z-)E|H@bMobmG?DM9ga`y|I%Br<AI(1Ps{qG)#v{6Ux*AezRUGXcT@Do4=-D`U6sz6 zBOCnaceDB=&TmaRe%m>JTV&1E;#jev=YLd|pXIEW$5$49_S3Xr*XrJSivPhAG0lg( z_ZEKRzU1F86MK2t9DDbLzc0mn4Z557_<lCCeE-gx=V$gm-1BNqk#gCO-FL6|YB2du znwsA`yKZ&JN*@;WCt^V}3z_Ggs#wUdz17;_!27AYQ-9Yp9Ijh5`S$C(j}`aq5<D9J zA>nVfoP$Tso(sn=-WE8!#%!N&>Ti}8r|+um<S;k*UXh`f@J{;0<fSid<!a6^2(EY* zrMv6q>6a(lca?u}xmm5u75~#nvj4^8tNHJXzvhRp-|K(nK&kla`pdmjI)5u$TzX}+ zU>~yr_nt4kvHuLX`~N-eJk}O}=bcY!<jc1)VtJxAN|iaTp`y<>Rj6(IQJ;}2%G}SZ z)A5IW<9cg*!NBDLZ>7&0=w4j^Y1#3IC(BnIuFc#2C3~Kp_tZH@_Gd3+J!Jc7(&5AN z{%QDbJ;1nSf6wF9iwykEZ0x`Nt<z8N+o41EJf5#O7BjWZZ)x$(NsCvvWh&gMb=sD@ z&e&<KqO1q2jzVDAj{a40JNK81tjrJE_Rin3L1yd!O6kpOyY(ZVobmqs=KuS7t!uVN zRo1l3YguXBk~d#>wNx&X*$nZFSI-=FyxM3rJ+riV;_IzGe+v5Fi%P8Y=62nAD%I)5 zs;JZV<E#q%zn&3&xqViiXGPRG{{J^G+)48L)%o_!CEmpQKHqsA9b}G|27P*{tlf3z zz<Otaw7W<614RqIeETzp+2-}~%otXcvj-~{G1OU2v#&fNw02I&*;<C_^`(#B9sbAj z&DrCPq{=qyz#!Ad{l|paecQKL3BGa3+q}=<_2Pe*1kJCy#fR-pe3#s|^RLqLpXZmQ zYMt42XHij&dyux=w|yri7jVkjbsPy4+Ud9<>9p*R?xN_Hvng4B?{6sI^KR$;kBTc@ zj}*q7W!9PTJZnZk%e%_UtE-NbNQfW!B3OSX?d^sWCw}+u<Z`hyF@I1e@+{ZW@`3WS z`Rh-ud9-WR_2{XQ#hJc~_H_I(dNk!2cj6JT*PJHmAzD7Kq_3!?-|(|;S+d11|Ec{^ zt>Y_9eP6Z9xz6&c60%&fL+konzZJTZc{}G9SU%rS<iRrid7x>r@~gsGSvl)xeOdV| z#MqN1%J%yQeba~~8kZ~AeP6PdhqZjW<NFG}MOQmgo*&6}Q7XQ_YSsU}$4|YF*j9SA z=U=4A*SG__tIYbMpRTQxxIb5Y*NjW2J_^@<J8ynda#rb|PCwzqkDqrao#$7$>UTfc zie=@bJw8A6<Ql5ae`Pg&y{mPP?frwTGnV+?{Pl{--mzMpHBtO)&y<5KPy3!<^e+^3 z%WmDeByZ`}(+nOFC(0+Q8m2$dv9r}U9K8KbNcOQ*3*o>_iLGxP1DM`cO^Ylkd-0s{ zm1Y9dw`*2WJ<EfQJ}oK<bWvT&&$(3oAK#%0z7w;h=03k?v*OPxlW5larR&0#<lVL% zsC~nq#<RhpB~0VtqHTv}ziNqfo1x#GvG)4}qvmG4#Pg*I2iwB#n^~T17EDu}EBNd} z(S%zp=}${sOtqv7-}dlCof3C>eE89equTG=^!%z99^V&uyW(L`?5<<(|NI$X3-?#` z9nU)^#K7>#6yFG$F=-=Y@J)`j)y20hCjGeoX!(n$|0d0!qOplHpy<)9n^wKL{vpqA zSbE=Fxz?i8)qBF(O+Pg3ru^9R?_GF?fP%-wDRZ_ON#FOodP4EWU4~zcZsu}#s#6bW zTW}rPePZuE&jq%x8E$TWA-yS|_rZ-wLkq5H-q-sd>KCUU{nz~eOx3=}8}~~!oRE)v zva|3Fo1F^d62sSrbU5Dcdcay-UU;4L`253ndMBUQ>m|%~vRB$!MrYD`zat5PE)RZ` z&k2~}mMCES<CU7ZfXfea58(&{wmcqlouu&c0$IztL(gJ47AHJCcT;APw0h%{w#H)7 zH4@8Bg8zPOJ~G!Zhv}O1v)-xe4^6NX++k;NTJ?BI<ek&I%xdkMPX0Xk<@>{<9LI!z zR22T({_*1ri8BvbjtL95r61=o`D0RBU&na-@yUxX3;rZB9ljj=qqd^Z&}Md@yRhHu z?;pR|#`M%l$H^T2BD3uMapB%?H!r?i{`lj~{0@tMA3m1YSY6{d@RM`-$HbDtFLf1W zvj42?Wc~m5U7g>vJbm%WCG3xlEv(xw-giq6p0Ve7$(Ct<t(q=>{BZrU;G8+}1wn^5 z??3$H@rw)_o41EP{zxh@d3)%G&%f7ynEKA0S6lr5mx<NvzV_t>Hh&EM^qN0m3f%1e z=Em=bB}I0>ZogpCbDQkHJosMk<nGV>1yyzrb=&<X2a5N#UsgQ+ucENdXrAA$55Iq3 z{POoj)As6$Heah*edo_x9J=`P=9i=sw+qdFy)F53`^B4#BZcP$6RYYBW#`w=O5uo= zi0e_`bLq4H<(|Oj9^YR4d6T2kq4eF--p+TzrQ;Wmp8R>VT~WwR)2rFL{=C7rILTl! zbpub^^PTVbdN+T5`9i?2iDQQG?#7m*p5ihe?y9ylzE;<H)W7j{y#7ob!Bg@}!lMF( z3UW=?&6%MnnBe`)(4H}m|C|xuhAG-*3}^Z;cNE6*ONL+CDZMfB(ADcRT^(f>Us5Yq zydL?Ox29lU<7@T&-G8o2J&^bMaQ?tCd&vN;1($eq&OW%rV<0+VKik1cmUb$ES~(dH zb&}KeG<rVzQLH}eu+E1=s=v)Pd@TKzGI9GcX$iN9#q668_{&@`|C`;RI_b4~p(w-q z_6`3crPLdbv$LP~v^dWczfnKQ_}RJ*IhEnAYzM{8^@N5Ml}>-qeR5KCeduSg(+4~? z8mDgdS?#!g{le@NF5cK`ZRx6KdWz5VOZR=gcxC^&ds<d9N_(po+t(L3T?}eu-2O(- zEplhwp=ycO2HATL_FXI0Tpqe?u~Yzq;F%DIefNq!%2i7&-R$DfGV%4!&fP+P1oaCx zoZoRoll>%bcg6EdkwNTJOSPxpVyQf+bX9+?>^kOf$D(A04f%-zh1O5r`qzHlQE;;; z?zYOa*o~Iu-iv$><yf$pKfm!Y;@%Dab@N*|`8a-G_;z`zl!w)==ybdO2pQ)M4IP%= z5tb8Q$LLyaw)?qpbHd*Kp9g|m(|K1kDupk<+57l+&dSx&;nVi~Q2BaPLgk5s!wZ)_ z^(SxG1vaYm{;A*<SZKyr`O>J+*)HmtNoZu>lFj#e6Q8+lE_vxP;f{-ARV}k&^rv&W z5l8;a+#u2@#4TfYWu0QDU@7x7nda%`T@4@Emc?urP%Eh^7yJCPW%iMs%buE@to43z zCU0&wTj7a)|IFpz@*e)WqssAi#>|YL%Pty;#~u1#z;J#4v;RJUGnOT8Ig@R^({p{* z<^#76d*1wd_Fn0Sw%|LD?U!9N?AdEOV|iRh-I?B>Pk62toO=}cB+js)h1rW~M^a7R z5#9OPe@w$u4Od$E?G><@c8BHjyhgPp8fj8>`CDS-89v$FvzJ)AzHk1K4?n%lf^0>k zgb({pIOelseL|zCYQ(<M;4r@>6MwVXJfF7JzJ8)>><#h1<<CAR_p<Wc*`WG;X%pWp zX9=S@@<mI#ExTjveOjNMi+tmj!zb8%IrY%X!fz+DdR<?g{~~oO=8dKJE`=QzUVmkg zwwe=p;?v=Hk(t%k&ojvPOuMIgal<yPS4#a>bEa>4v~m84U60Lz?%xjH+%WHA)W@zL z`)`X`zL3zB=f1VRB5?WJ-KYC5a&3I`^i;;$w$GJE<i+AH&2E|aTD^PQPbHJx0_y}e z$vseYTC*WtO+8;~ZD^0bn59AQv~$Zs#m{W}Sv7T!nRUXxxTEXOdf$H|(&*GuHMOy@ zAg=n``5#+vM!Hwde3;>p*!K0=`r85@x=a5ZEuUU5nqZZ_mN8xTWJNabttm1*EY+Ql z)|;M?^kHe|Jf8K)Q1C);%rgV+ML%+QEf#k^Fxj^FO!g$h*&cb5rOJeFmMcm6nY2xe znkIa-c+m_$lXdxyNA<(w4p(|vJkLB<>2>SKCjK|uOA@%h1s|>RD*6_Du<lgg>>K{9 zCCa}o&va>h3qEwypY`|WV^dNcj3om!nWL1MwQf2r<ympeHcFd$Rf@w@o)v1%x+{J> zJ(Zneuwf_98y`02-GBQ8y!cPp$?kc3o1Ojd_TNqt+k}oCIM<rUop@u8+hl_r#=9Ck ze495-HDEInZ_{lFytryp$QvK6ZBx2pl|`eCj!g^NXj*q`YtY82Avvm|(UVV!h5RXc zY8v#==w-T*X0&TOr;@mHe8<A`7iS&0Abz1Y>4CxOeL~FQPW6*rzZl>9uKNDB>7Mte z-+>rX*MDu@^IrSjchUF1rQUB}@MyaB^@{bDiFU#3za3inuI=MO-(R(7`IlRl9m%{X zJh|?_WaXnRFS?E<S6_I4dEdM4%kocpE^jhFHq9nFe~#GQjTJe!pUnN6SKx5(Yia$Q ze+un$rr8$Vo0I-};^jr&V*R<V*XHu`<y8M~kbATL_4l=nSFg`4`qjLrD5~sqC~x() zI?JoF#`PMv-R-9zdly?A_2ul>Z6AATKCgG&5cB<PRZ{e>=c^SWwpBJhn^$?0Z?CcX zeCzbM@5Ud`P1?UBZh?$Rkwkadt9I3JWBne{e=2bi!FML7J_tFZrM@(jYvtaX$+N%d z+`g1P<7T&PR$-X)x)Y0d&$~?R<`M6krqRd$rswhd6Atr>)AY;jU!KvrRP3<H*1q#x zzU}8LJ&!$fOw4AqN6nbRHc52L(uF)$u@%lH&VdrvCZeJ4c{*<oN<S)_H+$m~?SrS{ zxR@kvyfu$uaxtGJlli@D^7W-N{eGW)P}*uRZ{ouTML%}kG+BSuTlkmH{vCBi`K65| zjdl`iuWEk2zSGux_lA_Z>Z=d`*cBbhnlMwCOCYnM=?~vp{n`K0HpLnJ7Z;9WE_-A; zV~^va2J@e$Gh}z{|FW>xwNqomuE@@dStpGy={jHZ{=e|l0{hGQ(YH$Yep+nSdr&() zHCyD=vA-g}O$$s4zVBo?WDzZ$J9}E^w3ks!izZE-9Aqi_bf(`b@$Yj=#4Qy6sPZq` zmZq!vu1<Y*o$!LGjFWsDTp02ggdNVZIa&SUSoyu|d-9T~x$jnb9Zis&rqi)zrohS# zijx-HogsU{ptVFG=-R~SNZG!vea>bN1zHbt`?SuG%znmH@w{i+?gLYQ&bwh%_~zKT ztCP<DjOZ-5fB*ZhbMdpTEscD`oN+*A`-P9*lT8jjw>_72)GvP4mrEjlYgc?KJoICG zNwL(2UCX)6ckEIsn!J7WvM1ptNslY0zTbXm%~FZBGY8U_`6O|Pt4x3Y-qI&rXGO`8 zWjoB?+Hl-SyS?n@0w?nZ&IQjD8_K?fWNqx+?Z5KX*MqjRxO_V#<S(?ja9*|5@imyc zLdb8+o1&MqE?(eT{P3$s_fxjD55;xVKg`VI-ec%`{><BH+gDz*w(m|U_!{OuRpOt| zTm3yP{Yk&?>#XMfeP5?(zes)VpSO?SGt~2c_?{b{u;;Kkd;R(k<!$?m|D^ud{a}Ae ze1gE5<^)-m*9sBr2dy}+Id0&abk%VKUsEZvct#leQ7es?k0xx}H2dvYx9ZKa-=2N< zqO<7aw!6zuRr+S_J*PLjXK$L(Hlvwm>~=hTlm4GELM(zshie*dnEV>X2=;`%tQ+n% zK5Zyvy~eY~GJ<Cf>x92O90%;Hj{bijKYd?~W=HgIh9gW)4FL*f6YM51PGDBZXFOr8 zz&Al#!C0YKf#(F%3b%j$)1S@%f4_VB|NVC>zwY|IZ2R{8Zu8$T2XJdNzWsmtW%Lty zQMG@Y*K1}t%H)ZzJ5ignb8%#Aar~xF)wdoWvwtyhd+Y{}_4XCNZoE4!KcW54IsyL5 zjdD*Fi?1DWJhysRLjLQB_twsP>#Z)W=KV4+Y5(ub>{b7lKiX5@X~4hF{FJt<UbJiF z(-%i4UG#RI5-$5OLvEwY)6f>1{>}<1rg^>}&ux3?SG*-y{*8%@-b&swv*T8=AMQSt zm;LbPLB(^<Lvxqt$BT3R^=@^vN{OGcFv#}$hZVmXLgnQCT3h_;d+@@&)$KoD&p%lS z)7))A?J8IEv}KMP9}W4v#;*RSqV(DgQn|}Tw|$e$-z2pBj+WA;M}?u16^|OtidPE+ zAM3yQaphgs{+-3^J7ssaKYhE;r2gO5Uym4#4BaEA$34t2oIY3h;Hruf{?>lm?3}BM zB&R+P<~{cH^GO$pp1P`N`((A9xAk(0?q^2)2+mKxZt|yDc-`x7$C5wVE-vM+JW`@9 zH)(xi<`$cO`R6(9xl`_l6jpPDiRb0>H`++7y`6gbMA_|^2ky!JaAewEQ{u_gk$;J0 zU9;+XJKoCL-sHz`b*JyW&hhx+kC%G(9Y13>?!9DKb*Qdee=6tW+tcS={3IoE+WCaq z)<**K0#+rt&Y9jBDpS8#=hmsX>2AsXy~nid9*K0#WO%aA?*Hke#m=1*js{n<EowTp zc3S<8Cr$Ck)sxJg9(__RRT=FUcIE1&E2oy;JMqeIo&Qgp#LaPOo91n}QKYzXOR~Ok zvc9pKzPY{r=6!l>D@zTQ9J^qf`CLf*OOf{a^{LV=ueAOqg>PB7gQHDsiLrY3q|deg z{0pkt<nvCQ^tb!8;!C<^=PSX?E3bN|DeP5k-*BjLg{67r?pmhH*=(OY?CzMD`tsVS z$X99|_@wBu!@U24m`Sgbi-UQeGt2LVy)Lh3p4Y#6Gob%O;i`A0nKiL;$2^V-I9@xu z+is!ck2e7iCvFYNaNQN!!^|5Uz30-kX~#`B?Kr>0K;){K!Qq2@^{3tr+LKfD@Z`(Z zaO1rno_skpc{7XuY>A4km%06Y^+l3iWM1yh1=Z}c+b1PWf5kTWmUhVx567=FJ&TWh z6`Q<LZmQbKv#Q)L??+d0Tw`v}F)N-m`={EhQ&%$cUYRb~xwCuAI`>NNS!d>Qy>KgD ze&h3<J70e+ob&YSi(4)&V(Cgx->h}lKGVEzHhb*%&#bQ(_|CIBy{F3P^Q)^Vakex6 zd`V%tdbwy>T<){0!85~KC90yHl}c;X?fjJXSHEnf-+%4A_D8eyh2HMl{bbhtIp_Br z4OyCg_|_Bi@T%Vi(GNb%%B(C~_l=ij>ap7ahHK-(%O>i5&55g@yy-U6uE3kQZ*s2c z>|XHf+pJl)cg_-5JpC&#{Kf9Q>)vzusLAQ?+*4G$ed)gIYs@Mloi0u0^jxo|`10hO z1?r!>=1ueZk|jK8o|lK#kqeiFCfyGBczUY&>za+;JI{$1XS`hV=|K3^)(qRlt(#BZ zxRjTeWm$2x|6*2b=V>;VTl2dOx4qLXy1;treRk&T8@Cd-sm<p)I_;$Q)LDsg_R&t- zu>l86Pg_pet@Gr72VVtG$<k9#4~6ZI-~97Yy3gO7efRx1=e}@yu9dLx%*TeM6D&Vj zseRvdXLrS&ua39V1SZSx+^ukIt>tUu)P-^?@xh|*MO$32u5nniYFb};QE%s3=dIce zPn<*6dAh9fS>_cqy`Z=$M$omisl92H;7*fMk>T6hAH?hb4Gr4EyWP^}?$XXVQJ=SV zdbMXdwtxO{En}<NuglGM)(Kp$-dJ!!l$+y7&4n_~BPHLXnN6lHZS7^eDxI-n*@E_` zTWh{d-zGNyVd<vnc0ODSZdta~aax?VTf4%dZ{woE&j(q%F2)vTKM`ubCSX$;!1Bi1 zLFusB#jfSb@mDW?>TFfNJtd$z>|x<<p;vrbIk%>LI3J^Q%Q&isTmIpD-#^0Yg4=nn zSu8y3cy!TzrB9|shpPWvSKN~loABp+^R_4J7pw~V8`-S8@m%nGt`l$lOu5QA*34Ah zC$_$2a^U9popT#r=U#jLO*<sc($_Uq?C+uDi;^F*#82mwHq1R5uxX|=mrcozN1KyG zJNCG$21L5r9oM`1g-86Cw|QQx=N7wYyUTj}ufD&_HF?F}{j)3c-2Od}oFLNfn)Qz1 zouuyc?}v=GL~phDe(8|up|{iXme(8)oAIaN>?*14M_D#79e!)GIdayzpBimGT+y%U z1B;5hebjawIxXAQe6*`hF1yl)XZzm3wUU?pa?^Uho<CdiYRRH_$)d+UM88eCU%swv z$A@&eJ1^1}=y9IB=jmK&^m#(d{N;%;1=$yV%vmdNZ_~D<7ka!7>3MTsDIYq&;MXtN zz?JsV*I&L}_k8-jg(aOk$_hhXoxe3#wu&XNG3W=^#3`zuCTIPBc3wea_Jb!Dk$<%` z&n*kTY0gk}`P{qb5l^M&x8BULy}3%@rkVWG3GbQ@={N9{{Oq{gYT=z$vY@t=^OoKQ zjYt341*3Aj1rG2i&)a@5q}?lrGs?sB;>3`q6`Oyrx!%V1Wac`qrwdY_R%}{w_VSY) zxw)Gzs*BvbZhwva!ST8|F3(&<7fh3!dr<r9Ou?<Ql)c|=z8tw%vSVW<`{I&$t`oP4 zg=eQ}&7Jt<r;wwKe`*M$<l1R$-^9};4b$t`Kl*;S`ut9qXHV$1{du!*T|4<Ep>{<c z_w8?SEh0%D-~TY`Et0sev~7cttw&O*%e(k>M>gJwlMr4f>*>>Fr`$Q)#z}~~|HG6z z)o|6E(yv(p+xBhQCw$E1<lGmPmN(mDE<43=Pg+n_l^e=-w`t9Rbr*a?&c!%)E?YEv zrQN2DyvsI9ACF#rzyI?d=_z|2IeWb_Dy%7g;^wvauH?njo^f#v%fIV~n>4>~HFP~% zp8i63s^SjgpfA(+EIBE1NAh}--*QQ>inGhV?A;lu(HEj`qj_w`t&dl}Uf;4sZ|Q3- z-50A;I@hfUX<oW(o7Odvp3|2OY&|&Z)iTwD?V0X-HMyd7B30IIJYm0Nx-|QQyJse5 zz5P)*StUrYvaY0NyV93C|BN$?{<v6(O||o%I`y5wk1N-5Tw{N(S@yTE!p!bh>wb~5 zuWh>dBQh^Zf1Fu8`Agm$37MU&3=6NTs^5EbdeWCI=Jqa4QMEfo46Q6%o-0}D&C@Yw zcq2V~spr+}pP#h<eO6F9y?)s`br$`Pw>dKo?(K<;nAFzf#Xmdr&n6kMsr!nXQ<wh! zx^YcSsioMu_?taPpK@nz+)#6HqQ()!B{5N@b%OCC{k5K4M|I0qg&*DO5*V}jf|6CR zk6L$}_~b&SJX^OTpFVx)Y)xG)BC?Ko?}-f6y_X+UT{P1VlFv7+Fcc3uE%t5d1#8*G zTOX8Z?~^)_t5ozSds(f?#N*S$UpDRkbo2VQ9sCckmuyT3Jf5+&K>Z{qdw%><ZpUTM zfBoos9J920o&Z;V_UTxKBb|@+Ztj^|yJkcCeN&OjzOYM&_4ID3t@=1W{)~R@4!%jw z6@rJk?=f%Z-gw4%$N$51&rjs`@~vNP%Khia*Wk1*6%KzEu$isAFMKEe%ltQbao4}x zd^F2kc6XV`5AN?(lPoxQKev#19Pn=9VYzc+*Y|Q7DcrW3S9|u;Ju8;WM!OyO4=za) zKcP6|NX-ig-EX=nn_JGds%tJv<^Ca3zI<z}{Y!@Vwjyy+x6BF)l~*vRh&FuU3t)6K z<@mcyfaOTF{pL&U-uBiUO!dE5Lz;JX6mfE@bsc7(CtdAlwA=E@=V{{F6&sBL{e-q2 zUV0!h?AZ*fkjKAH?#-N8;dW`sGsO>*9ESXjA{A<p%W}6|(h#|!UcG~F)@OD5-$fjf zyLa~=Q4yMKBR1K~=NG$yole2NiZY(ofIZ3FPXqV#WpB<n<bFc!Pu)Y4g?SVFgtHb` zWNo|fSNP10D|#m1O5JkYlr5zyS)|Th%;;0K`0ydQBxLs1h10~IO?LABs-(3gL|-X7 zBXi|6-l|pSV;s*Z%>KHWE44W;Y~i0B4<8-;aUVW_e<kUdc7iwq!`Ehf1Ndg74d5rI z=flSEr%e5rzt}?Tcs*bJQQ=FylXNF<QQWZn>bn;bPSQ(6svOd`?6T~QDG<6ZG@IF3 z|JL3Af4}g&T%vi$_cOENx9_!o|Jc=?%VArm(WiR*t!mF@&NJ)t&wT&<T3UMAl7$bt zY|{5M%{RVuVgEzrxkW__<hR`PnSJ&_<23fLP@jScOs~46CUiZ@IN+F)Q*F}lfyXH9 z<Rsf`lbY^q=F-|Y)qly74Wg<7buNn+>2U`JRwNbiFABN8XxfIQA`z_BQJ0P@zwtVx zdX`7S>*9u<G==XjO?QG7`WG#HF~#nEJNL<;RY3u-#qLkC^%Z4RRW;yKId3@WV%Du( z-N;IT_U$Lr)ju8Rf2hc1|I<64bC+<l{OboS-l|1rC$)MKULJpU>*M?6f@|47-ndK@ zR@o=M_<Fj1q~nvjmKTL42~3(QKfjXwUDf6<&DNqX?%S`a&96*jc&J--r+VV<qNXE1 zU#$Q8Bz)_iwewlxWc&~ED{vhA{e+eCi1ruD({C2DXW#$1<J$wXo(rcq>so&tEUrz@ zJ#eYt#@z4#zh8bLOP<7$d-u)bCj2-jHSOHq;`UA#tu4P-nr$nZWbwtWQqU!CPo(;e z-rE{`+Dj#ppKa*0WuE5uDB+8<$h}{lIR~CkoxWxd$LBJpsgq{^NNixtlTex1T*-3p z?ydcwnXVtc5x}aFIOWGfwRcQB1xohETo3zR64eUXmM6gym%VCL|JNHwPQ5(Xop<=f zy})DJ^)r1;w{RRf@|$y->Cxcc<=NVwVr&feH6Ne#RB}mE_$HN})2A}{uTOhgQT17d z<$V7K4@J@Trl%&(hnL$v{h;wg?$X=?%&}Kp6}>!-OKrY>pY%p+!j?%d{a$D&%(S}q z_LKF(XSW{LS|oU!vzW`Ivg2E$P@HDsEluqM|AJ<2aZB#G89XmYBik;Jb75@gg(<m` zCqFAs`EuWMt;$)yeJdYCZ(HrHv@t!Rm3Q7jWna(OK%QDAHSJmX7d3^q9NHITw&qQd z;0~D!ZAAy#?!9e18MaH^=CtOLEmK-PhSln1e4Qiu%!IY0<IZIv>A8<vCn~XAU2C~G zCM>ISvuNS`7UsYGOH|b@ckNUcQT?-e-4jjCHPcsxx^M9M{>9;;L*3$4GuQ=K^X5FM zP(2XpUZ>vEH+h+;%HQ5Mw}NUyTTIFv))`!L`}Iws)K~hYwc7Wuk4;3|XYO(=|9#VM z&+!>Es}d62R4#7qT$Y<XPszAkecIQB9tH<LveaF7d+YaYNsE(#UZ&+$H{L&AxaT}t zULLZ``r$jzpBJ=_3FjX9ZQ?lhx%e)pm-kF>t?-<yqy6#vH-+Vefkt}UlmF_s<~bN& zbUXW@<f6v%#DmsLGgQvKvbRb9de!w?d|~-6vn(ys+T!Hbw>na8t`vBDjG=Z-yy+*e z`46^xZK+<r?#oH>b^dW~B3e({H_tG8^0)mxSN-*)^Cd-|^W_^o*1z<B=H@@ntF6+# zPfe1U_~uSS+PufgvJGz*h+H)NZ2ENl>$xvaIdR4W@o)yIW_12J{O`HI<Vx<;Il=$B z`NA*gRk2zvS@OcIV5;^7^#zBgnn}IfU;nV+ZY@JyOhfL$ezkowiVrOO|MR5}!@mP_ zo?W)z_rYGD|HvNgmonL0KZ0UkK6hPPd9-X!n)p>y-VC2L>u!eM^%eiJ>D04=slK79 z#XC+dTeZnD;%V@#<yo_f>@;ex#RwV33mV>cI8vi6xOsZVO+iC{mow8&eE#s~=?~+T zaemy)vsjCwz7%#<Yv{IV>WVBqYOu6*(H4m%A#=U<zxcqzt#?x=Ze!$^jgs4gi|(Df zbLWQJ`4?Z$9@S`DeCt*4_o|4`aow-w7IpL8edJP7cr&@@^!~c3_g6%+nTQ2#uG-E0 z^pmt<_KX=zJ0cGs(Q!Q^^=`G9X>8}edhf{TH`avTSYy6r%GYbtHdRHRdc_c-&Ty@J z+NOEYr*<(k&p!QPTAK6q1-TB%${M@*LyB}lO8%E-@F#B;HLI4Gy>`RR!}V6Bsz(<- zy>w~w{^ohLp6Baa&(|^A{$Bg#O<Yx3`$@Zto8vERp8xWudR2WE;=U%suzmktvobKu z;Kx^;Sddno<mDq(C?S($`yZ=Gw61?0Us#s6YxOQq`**8WX(dnQoW!g-LGo?r(;F&| zr3Z{E7Oi+yzg}VH-J7#(ispUabG-ej&{X;LlWpfI*_F-zaN6Jgf7h;B(-nUVBE&yb z-`_XO{<8P>g10yS1nNvbTGY9A<~cK#*RqR_%lLGj>%T6Pe*gC2tuC*tzL*_3`R;j! zfWMi-59d8wCLcWLpK;f;@mQr)t-+2P6;1O$?Vhj9ckBS$oHHrk!ey3UbG<xWLj8YM z^=0LGw>m0}GQR)2suJ`)RrLAdw?5k@JnxG?yYH`Q-?F(0vbPdFys{5H+BYjMSYzWQ zeU~7E*0mz%*DN!Y>tG7zSJ-o|{e<88R+qCOR|U2OD)=^wE2%!56*x6Q-)FtzOW}#8 zTN>hwzxJJ7ofdBVZ%S*<=3I%j_Zbz!IyWxd6eYawq;mF*e{+tnpYbeYC94Fx_=59O zvR9No+Ee_^<D$W*8v$!td^8T(JLhH|^$1>+HYscu%j5j{EiS4%7S+GixZY#3;$)kR zs<M&y`}ogE*^8zwI3MB^v^BdVDp~a?TW`Qg%d)O%D>~IY_fAbZx<%{bre#&Wsh@l+ zwuNM>RS1PNWqVHI_nR;E&85<Ha#%{ESdj6?;BrS!rI}vNNB!<M3rR+Eo_onV>#~34 zn-I0!l`)(<6(#rl`j)BF)$+jU^8JAGYFn+gzJAbtFn*17lKt(4?$2X8g0o|Jp015y zw_fs%k9m*ux*O6Z|7>m@{K8pbDaoGv_@vK^KD*FcKRXQi7tdexGWe-{UC&!Xg;@f- z7uQ!<U;ei9xw*Xi{EU|#hvo-wWq*B!=|a3ugm`cFwcTYB>t5{LdETf{?sDmAHX)@0 zyLwJf-(<XQ?i&BE$N9JG+Ao<b|E{eoDQ9>6t;LQKXP>_Rk{u|Mc3rjo>c#7yE3b6^ z`Y8NQcVDz#VD<OfZ}XSmQ(LAzf5pLF=k|D?Ym3gyU-<Nhk!ot1fM1>5uRSO3)$BgH z=*RjW_OLY-ma|qy-eY25ILv}C50TI$ORY%EEyziQHOcOTCl=rGxb#owZ&%#C^6v+h zCwQwwws!}sH+O`#PUJu7nVT9L-E7jdlB3tlxM_#Xzu%$TS=f%BJ610L?$r+i597P% zFJHcU`LdOr(L)ZlO*?dt)+}5oTYkWDW3~Pq;oqh_H@glyq|H1by2tlM*MHge9kVy9 z)~7RR#(yl*oFZhzuDdYkPE&-~b}^k)rAyJ=5%V0Brsy4Ab4lillSY8i)$Fh$k5o>b z{jLiZX>qT#SkoHUpz|_5Oe*M{qejGsN$2wt<2J>7KGL*kiuS}0EMJ;3FL3kasD;Z+ zd~~<2Xr=3!lPr&P-}T<r6J<?T?U0F>ws6^lRkw3=cYRRcal7bV{;E;_&{dNk5BT>g zZn-1yX9MfI6c49&r6qzsi7(olH@=Q<d(e0M!^OFNcRim}D<;)`S<F47>iyl90*e?H zaogWHJdfwtb?5p|^F;ohUcK=>?{@|T3B_Ye&1GYDOg>@z{dnCM>5Kh;G9I-iivQvC zVftWKF`45K_mP{M-`r{5_<ml$tpsauOOg71$BL)CHRU-6FU+rMKEYJKsg`S*0f*Yc z@BP{NLO<V0w7pyUTaI_;q^!?g(z^>58+@><2%b^(@T<k4+@56zRePERblYEF*qrdf zO)o3nw|Sy`t60sR4~w|-yUKP88)XXoJjf!-c2H&3u8iYHs_nnsub$l4zKc=Q<)F!@ z=GPknHyoJzOK}q0^}xp~8WPwKraZd3;7RS5<E0)R;rB{JeDq_P<Ye8L7uV;^V(qry zY{?$_;j8>C?c7;Oktc$jZ<|ED4BGB<Ipb_=T*&4;o$1F*OrCW=-dWRVb=+dhnZC?d zx0?=YBo_<pG&>vdtjpn2&)McZkygx#rmNK#Z*|!#s?8Yh9NSg1?g7uVH9uM|nRhLF zS0+)LVd}4&-G0%>E&JxCGrgJ1Lgk#TRrm2-S@D+dN<=}rloD%d;~$>Cn`<BWzdU=t z;M+Nqo=LA)opGFb?AV=sOT6#$b_YGN%H6*1^ZA`I&zJDOoj=*{^r77Cm;Kmt72@Y? z7K&UQp`3Qeq}l7qt_x57QdFMK^O*Ws|3%fj9+vY$EC#&q6Sz)TDqY{>6M5#nnR)ej zj_Mj7!D$TtT6Md7oDWTx=$MqbE<y3S@7JcptvVkp5B?X`W}TfH^RVYq=bDo3-xh}- zUQn{T*-XezY>Uq1?2;E|jYj((NvhbKi#WMu!cL|&H9jk|P71GTs5-x4U#5)w%(jmT z**wY9&5u2vnf#{cxPjG*56VB2ZRR;1TWpykA${cUWgDY9mC4_VIUC=r*ICS$s+K#c z`Pg9fH&%Y*(-k(`d(u<IXZD*iPgZ!cOUvP;D*M$GsaZk6VXEQ2M}C?;h`l^xqmXUs zxl_B3J^ALDo-B3h*vpAi%8kRK?r(m$PPO>nt7bjzeK%*gd38z7-X34-liZd+KQC?j ztjF{G_ubgWsve)yeoU@cKeNX5akf<b(vMeGnclk~y|~aV*(cdadAZ@yi<T=*WgZoD z99HCOw}3L1KSbrXTU7D7_ghr;r3SV1_rLt{FGVV%W_O9j)Lh4`gKL7<vrpC2y1V@O zw{_df-GlP{4Q)<z{M&cOQoFoJ<c8gr*%L}1<mzoI|9b1#s{ec0J=hgn{z@FWyNvm5 z&-3(ew$8ilLe4s^XZD?O+gNimpX=_2i}#;3zr9Ggs-n$6G2qo@Ua7iWN9#BZwa-=Q zmp@TI%YR_o!LkGI8vhEt2~XJ1_B(uoKjRzo1mg|q3C9!E6N)zk7x*#kE90;KP%3}f zj<F!8K&GJT!5)_9q8959{uG@P%<!Dof@hATg`owfh0Gk0s*az*umAu1|2+QRrFSxa zuU1{OwX;0na%~>3E&IIBzq734-`jqlll`dcm2j+xlc?lw)@{3WUx`gq4AVNTdinOP zj@lI`j3<6hbL_6Et5|qt$8PP^fTCrV1|BJ`Ct8=ZINsZ}=V0b_6RpB7^*N6`KkCk! z8Lw5CC3W<jsQek{2N6>Wr*7P&7aXCqJ1thTT)X<IP-6$1z6yiIEv`Uk0p*ir&(;Yo zuia3%OZu?nAEE1Kwj6#dn7i$^lJM^jpI?37lghZaRIVeZusrCaviq)smDMF*-ii9& z$-aB@!?zc)w);Z4cb>bSJMXHbfy4<L(a!<KXZaUz+rEMOu4?W7fTiM<hl=l(Fc~e~ zX)8LRvg|hNEBR+L=WJYKHdkfUuFM1e3u0dVTJ7~=Nw$<$*o*w4OLDj7`sdVU{9PA4 zyH?zBsR6hArtX-`X~!kLi!vqkt`ZhoefeA3L5EclZx3y}bu{tn%J3C;*2!_6TID~( z=y~n$WqNk)GW^{0Kc?JOPTXy|>3qlCx+nAAd=OZh_h}y2J9+lMaVIP-gHJzlm5pw? zcdO}p%^_3anM{AI+)mzZ(l+6E&9JqWWy@=pZ~e>SPP-po^6Jy14wI*<%R=YIPEoa= zBdYPNCZ2EG$<Of@FHTT>a__zR##irD7jJrfrQ}`we$R8qXE(IxJ`DDCxSL^jk43^) zIN^`AZ^Oqgkrfx1CH%iK{I_0vc7N5Q{pFF$3AOR||2N%R&%>|x?te(G!|LhZ&CgGI z-RhHY@RQ16->cL49hWW&`E@({#fB!IA5|xU!%}yN<&?`!=~HLf<-G91?&(MR@6Qtn zP%1M%dwNdh#z!}G&;H3g+cb@}y~8*0#;X4rx{I#}cKzA#`#_w&%N~Ztytq#>+6iaF zb@flq=U%oTB|Bo{nnwxcv(K-7`}|w6_vLSFzUAf_yL5y5^=gARU8*Z)UG{gbp!DbY z@O{pYE*q%vaWF8P5yjWyAmRAswEUvn#1g&q{4-Jc#kb8S*X!1G^;&x_aanqK%jL>r zYps{xC|a{p_ovFvndw$@r8{E0EP@&M8J51dRP%jyY=elVw&&&9JD-0#B<Pt?zOlY; zH}``tt}OZwoW!k_r)#s{UBbRTzV`dy?I2P)ri=Gb>$&2UI)CPL@&1$k>zSl_?T0su z%}>6wQBm4knU*iya--cve7D`2QmxIg@-1G9Q?E(x)R1k8_T&yr&(r2{TE@$<RoTfk zlPgzn+oiP*(*NS8^BK8J5DUvF*x0;O@KoZh_CqgveGFN*3-R6Ia@6_4))^GE-aS)Y zI7M(q{zma_zd}Sbcsy8@&Sx%jk#1jlc740S?3lCnd6zj$oPCgI^)t7`a!<?TgFJ4V zg(Z6QD=$2#tFxVX=xIh-p|Ql>a|s2-%<tJQzf7=^=S_EceK(_y_wvKr2fqkC6P^*@ zpT>LZarf-sr!W4{^_RJO?`}`qbY3Qdok~*M55GM66?A)|<lUZU|5Lt&gKtkfY9MvE zg6Z)6w#Sxd)^++hZ!&k@A<2914$s3ZBh{ehkM@aW=6fV~^L`ar&f?R5Rx8oFI)1Wd zjL)&n5BJ{(-=4^($G*LJyUK|v%iG-JZhTF!o6S=%?U!gZ=kEP8nUdj`PwL+BNmH@B zbH1&1hs+svlizt(JEhL1*H)C<&WYz=uJS$Mj8g0w_sNF7J7)Aezsz{jP;TE|$-T0D z`fVoVhlHO^epzF(bABslt%Q%eagx=}`RuN~Gu|9cv5~7<w5Imb@xMKqcX^kGPk#Bf zfir&VTE}bly^EYw_>(#lxbL`4j1j+O@xpEH<fG>n+ICv0-@J9Po^7*?@W0Hto?C9U z%n#Ci>v^Sn(dFO`sg5iLdruv`G|3*c*>iz$na!vBDXKjlGEyfh0&LmEtWR9yYw{?Z zl975>@oce0<=3~T^B=TGrrlc8I@|K0z>{4k3VTmQKAXHYw&v*k&gmh1zG_ZWRH7^$ zAL>nAuCP_9D9Lf5$7bEhDjS*k)vpSbG`6uHXZS37NMd`nSma8fUu>NTN!%)PJUI2I zy>Mtar2D2lKinwt;*F{VEnYRf`;8kE&TM+JRX}y6hul=I$!4Z3trNSRdb!NIZBewF zDOzjexhb8^{DJAppM)0v3t#>C@bMLsBQyRfAN}}c#pI-iVQV7;mtU~iIcu}n(f3P3 z))hSC|ED+IOIqe}wYhqsSk&`C^~}u`g$qN~rq4U=zU|4PDV0^7Gc}5zPi0{fZa%bd z`*O1)&8a62GacL=*E_%Upv$dOeOj$+eeSNxOfYg$)RCN9_sJ--S#rPPb&+eg=X6dv zm9S{K*FST~!tey1g7rmPrs;a-pYY>Q^4&YL(@pQnCK2y9#v+^h!|FC(eYKPM&H}~B zlg}FTD*xiS%M)k9bKQDTUmpLiwM)OBSl4aTyt(*6M(^<*wZUnUv+^3%9G~91@H$SU zRD<!a`+ViTHtB^L&u&lrs`#oTg)MT<%^CMfmKMd%x|r-I`$%-Z@ui1bLSF25nS1W| ziqD2!e0FyCZTNFM?-egtZ#-?+?QSc!*vt@vlnwUm)|Ic1oOpWOq9MdHZrPXD+A$7K zqI9(<%XaJX6&zY`b3NK@vBq3AEzTt~78)w84_K?(&#P(ClCkRIq^r&A>{H(<uYR9* zLFd2}uK)GYacObqYcKF0X*#)QvH9J5{$Kh$u81@Vw}=S!&k>8AcklJpCt23pJnn_& z_fLF#t@zNX{RcM5#cj;hpBVCg>c40$qo4UaoB!=*Ws5x|tsTrJw)E<DuV>Xiwr+@B z*yI$gEpDl<uGDsFTHD=uU3P3zMkx!P8z1jFb&Yiq*BZmtGcQazwyK}6%bvh>SxMa5 z$JV;+*VJ_eJ#(9D?`Cayku>YrJ$>EOWouI8+e0h_mp%Ek@RZ&*{zDQQH`jtT>HmtV z(Ct#tbl)Bjda1S7z?v)EU$aB5<ci3@;Ek6ql$0|s)a(4Y^Lm|%{6xu|NAXL&cH3Im zuixMQs;c3SMmPVaYnCZW+g~t0KB*>mbK{xaiZW&ee6uTNJl++3-0`XK><4^tkF3)Z zR6}M}Gha(}VJj7jedC}t|7WD8c1-ZU@EHrX9(rT9v~||OWZ9YytL4iJUgq+>$(OW< zb?B2mqkSzUM)kABs|ng?Zc2o%G32uO|EyB~#rmj!o6|4UZj%4^e15@-opBe`6B*c- zP5SAeTfFA+CGAu0cVBAy6s|SjalO6Zim0xE`u8PsVx*c+HR`+GIDCE43hmV*vTA*r zs+Uw!^>|huJ|_1|?pI<`Z*64EX09F2+5b3sf49GRLi5>+4ZG#<wYRgqnmg~%`VQCC zyL>MOq&ZAY*cC6ZR7U=uwS39Wf{aJIChUp`445<baFk8L_wV*jhF9CeZO=dV((`V1 zaOLxj=id5x+Lj|b%H+-#`abP&{Ip7>SKMut>gAiOBbF+5)cjksQR8ZK=+zfNfnT0U zn4Aes3or;?J>6?nn9=@AOTBJ3);v(zt#bVE^r;)(WUgOyj_u{~W4E)K-5*U+(zub? z{MKO2%z4emszr;8H01V7{I(}<UyqgS#AR)ji8ar^9@uz$(?QGaC$-+1-T$_7kFl-3 z)5LedK}*lwfB9Q}&ZK#^%}TBFZ}(jZI1+auYDfNl+bO>%7+vX;bd|j%p})vYe*Fx6 z#yf_8WrGuRIlDj2xP9-pcE!Va&a<b<SIzO9IOSx;@|yMH#&h0$e0<Zm;uA*|{|9IB z74KRO)+XiGe7SmFgj-~t_8Mp9x6J%+t~1@dcW}x5{|hqj@*X>~{`P9&-wzL{To;Sp z1KI<s-M;4Q_viC3Z1~hZt?}X0%23H;;=4lLaXhx0v&Z7))o=N0_wvr`pB{LT&+ z@KV&TjjCHc<YsL4<Lh1YGq^2hN!RrAwM8caw=P=FzW=~#cgu$zz9*Y&R=i!fOLWdu zaqmSEGCLeMS#DeQYVM5cJ=rz>J13>RQU3K<{O#Q^Kkf%RB^JNgIaTjr#Pe?(i@G+S zUv|)-;=L*RVeJ)j*KWBf{(0ql_Vaz=I*M(ZEmr?xk8|8Cw{VXCk9}zs*PkUW?frUt za@}IXDGCKCk5$+tEZ3FfW}H|t`Op?8ne_ti)_mv8_GW$49HO~YYwr(#sqIfiT&Dzy zR9-z?9QG+FYC_+F8!rxdJT$m(n7@B+ih*YDROvOpU)fEJdZ}xEtyJ*9(N*gMc20R_ zG$UAY*_qSVQ#Ez>I83fzc;Q#b)Y7vd4y$@kJZ;p|Iq_BM@`jcbhpQIIh&-6p+!4R6 z;C8ST$IJr{HZKjCu=L#LZ3kSs=2Xf*3|V^ZRN{_lHcsFA9vy#NBP{B*UsS26S?TW8 zS1Jv6f@B}fv^(}a{XAdRnf(oX{Re;NCzOAAX*B<OrK9Pb<?YWzdM_@ElnLbBdr0;{ zwbsu+an^0Aho$a%EuZ!><gJL-#s{+V7PKEZHvQ72-O={DPASK3J2Tnc?t$XhkH-~) z)*n0K^*#Oh!}Np;s>^CWEZF|?ZwUXF50N)-GADYxWjr?{yET)&NbsM4R#w2RwM(Lo zF}&ZgSm(2d$nl3lvh!0LrfS_he%$Md+~dvy=IG9&?$U)N2fp@Rv)q^>v%J0Gk@UYy zZ@==X_e}ZizW?W!yZvjAzmMN8SN~_>*NDwhn&HKZ?(em$`Tk09bM?(fZvDPxU+z3{ zKkwW2C8l`Kblz!y3g$cyUDx{iU#V^X{MViTR$gy^A1^=u=VSi(SwA21_ov0ZD4qED z_pv)4md%T`m47a?ukQOV`TEuaf{bZ9eLm=f?0M_;t@v%)?rma~@50=spT4U2v(YfA z{F_AQJ&B1n3$haguRppI67Z%d=6=`r=`kPeEteOyAKLbcv99r2$8n+cM}MbHdvDTx zrcdj-^V6O$dw;6!b39tQLx0AO?q8fLe|Ua3+BeqxG;;ajxc5p*Hupr6El<3co}VJx zdq}A}I@;i)$I>7Bv~AhKBZ4%$q~|y%<Y|AsaDnGw`uqcb*&f*QRrB{S&VQ!Ovi6g# z#ZI?XR!k08FR1)ock5tV%qiC%^^13|aHs3Uzpj_(Kf0&*Sw2I?+$)v0-)Ad+2@`2l z*PXWg8PjIgqU{qn^tyGH7(M2?-Wbivx<l_ypL)&LL(+}kEmq~Ze$?+;!G5PTVwdRA z^*c7(&D$~8GsosKXd|d$nDp^y+hb?lc<%W7n$i|s{vEf=b@_ka{4f6SdxN!n`C5g` zmC5RV@-L?T{c$2qtlo0l_hq#**HaIj^qcxxyR%Y?$B?i8?!CevN9!l9&Y3g){PbD# z9b)%S_%He*Pe%S}PRyID3e}=>*W69~T=#nMrJcnh8nI&iN2QwcYtC8P)!pOOn)z=R zyGd@@k|-@32D`k|htH*NUsWsT{AcebrNbK<x9cy`3v+rqf1TG<ne+`e-~Vmhd)3nU z&9r|SzM+5lwnQ&n=~w<YmBCM;X3g{$B8l2MIlU!(q4Hu&@7FH7#3ZIvxq#2YJ^bx6 z=Zss??B5q=Pw3mlm2^s+<<gYht!dNW?=HKSZ&Rie)A*@1p!D17jg@a7Y1i+Qo%ViZ zYtc5TnipT@&klQjZ&mDvYVL<yu5qd7s(sviT|a5Y!-so0a~Et$lHA5JXTp^9e)GqP z4`<%JAN0cc@q#bTNA7v_&iyL3Z~Iy1dw(T+?iZSM7o1RQV$Z4BeN1KkoWq~b7T=#| z#`AII<|wum%f3nNI-PV+(BjQH%OijHo&0I}{MiK|JHAiH{2T&O7az%}`S+&MTlPul znt}=bCoaY9i!)f6CDrjgHf)CYS#LeR&kMJnOV#?ZPugkSbfb^%CSP_4y1klo{#<v_ z#M4V&O*+iDOqf4Ho=vSr@kspcm22*cESi1e+S-YBIkTomRI&g2)|kI_&fLSB+kV$P zFr9aB8Gom3^N~+?r~j=CuxPT}aq*JH`>ku{iU*#qU41x?(KB;yT)3Z`!lqv}5iV!X zZf(4OcT?)SUp+jh9$xzJwq3>Du~p~&WZB(o1+JPmYW==Z;H;S)wXtxTcBo$HW44Ls z4y<#XxA?wgx6QxEozr$2^y_)q+`Tegj>{)S?c$L@ljo0jG0PUP=3NkrTDnc?O9}Jc zt=ss7_UgGjs;aH{Rm2=SaoIMlQss%u*w(sw$M0XcZ&Sivy9{Rk{gpSXPR};F%J!|! zjJ<fui?2>vfiKenl=reTMyqMBs-M3vUCaMJ_qIt4vImO{-#jhT?&-UCL}}`~gQ{#2 znv)zp{Y$YpZWGY6{zQ(8{9jj5vHiPdY}n7pb~med^7r`>daqx+51Y;Y;d$NF)RtRv z(;lwL;uhPz*y+oOtldsQ`I|pWuH!4Xudw2IUVY@seG9|hA7AI0tFgwVOsH%AiZ9bw z^yyV?Ob+^|lW6a=npdmy%8M&}F*8*j{XM?s{ddLUqs#auq}}!XY{N{PH~m)4;P`mw z(DZb<m|q(ddH&3YFZpQn7W+GapMk+h2VZaBl=wM1NN*oDz3?WsI{)^LP5*EI6DdwH znV@}rt?KQ}-n)->t=w#yH|xo<cabt*M8r4w9zS$yQlHDtlct~U>U+F$+^b>PyE}3X z*OJZ?4-48Jota>7_vKfraNMDpZ}03r_Li-APfqi%Wy|*l-T%_|A@IJU#b)2j8*F~0 zE`5KYe&YXWvEKI=efM3^x_;trQ=9V}bPt&Qkb8CDQrSD}4O_#H{o2R8YirZghl$rC zen>FhlaQ<UCRKkumL>Z(>)l=IJu>%8bNCOIGv^;DdzpXx_y#u)9)7bEuHDr;N=vyH zhqB9DzbC1^g=x=4!w0-fwTbTq9&YLRvN0z|M^Lo!+Up~S+9La!OT>A&OD?OZ@;)hL zzWQvwn!#?X`Ty<q%{)-TcHKPu|D3uxH7uDn%`bhLK0bB#GWlopzoe8|e);Cj-5<Yv z<~b%V{^9qJXK6K-^Zn9VuD`$hQ+>zGKW6)Wa(vdFQ9tXP#l7k2;_-HV`t^%hm(O3X zzie{94D${vbsIbXymNNF`p+NpU+#YSCw|MX&oBQJ8O<(Dtm2#=Zt(N@lOn#&{w@6K zH`_U5e2&ZOsTI_fI!E;C|7YF&`sB@$nv0G7muH{6xrh1k=@08yOIz&THOKeg^V3g? z>}2B)9RK+IW4_A-=_r$mC0(^r=hMR{*Zbu?NHh9fWT>7s=YC9WTlZ?oi8A}nsLB4Y znAh+5^7ZW1pI_EoYrJpo`)t0Nxy!qcs-iD*?Dp<bVLi7_@40!h(($KHws*hGpL}{V zr)IS)_nGy1&n~al-@L$q{h0Y>$(3JTowmtXp?&Jxn^&KT4$Zi9P5tf1R5#05|GabS z^X&RHAAf#wTOt2{>E@rmQj7a+c#P|JU%mS~@bjlEJIRAP-!fgAE`8v{Vc81@jeH7n z4j($9+CMMx?ko+T#JTssiN^?S^UTlHE8!1RYw+3PD#n(?zw6~qlc^;+(i5Kk)KjXx z>$qg{Iv#Od!<YMhUD|5fUlvvKeuCZY8rJz=tqpYkY;*qip7*7`@6!EkwZF6#K1oiM zpYW4$uDrmno=?rWvpu#m?6%vyaBE)Gil1C*5!=Id?QUASx74S^{LSSz4^}SUm%FcN z<Lg)7H*C>eBRwtgZj-o}k<Oc^f&#WPzUtTV-;RDHv&~8^H!V8w^UjRU9$8=G_n&VB zY}&fdWyz$Oo;^1HU0X9>M+7G>pIvA7^6`_C8$3@GXU=#a$hA+jGk;57^PP@40YAFK z|9noro5-|L=mYz%?-{41#niegY<%4^R{2kSVz}O9zDENKXZGff6OUBWe}*_;k56)Y zxZ~Kh1IPNdnx0;;&N@Tu(9L7gPlTTSQPo?-b)_r*T+cSvBIUgnmOQdzX7@}OFU(Ee zePmU~pM9dX>v&Vvak)C(W{sMta5yE&&B06H@s}^UU9EqUB5oYKvgdw7&d;<bVz*+} z?TgxZ;`4#H=I#>VvR&CPxF?%j6F+_V`ig4V-JLdel1hy3m*!5BzPo9{$#U~ck&m7f z-%pZj-RmwbbNA}@H@4AcJ2-x?dz#9j87g`4n)$|u0{6u~_gs49RC8HcPKUSr<?LPD z6_0QId&_2%BJ}jy3D;|rBDu65Z8SPkn8s!JKO#u$%Zg{UM;83#dbT7#P|AIK&r)|c zcD8Si<{i78;<M+X?S;etEDK|;J%2pnlezoZ>1PHrYu`6l?+M$_rCI7lNu`JcPxyZ~ z;vsMDTb8G*8YVsYt3F$NhpG^dZ0*nXy6ywT7ry^jeYo<b$+ja+4tZuvj@r7-yOQJa zT32m9M`PmMN%pn3;+LjvR=g`!@mPPCclGaCeM<S}>+|1+w>-}NH2+GD`Rw)a$NzP? z#UEC7_R7lBexe(j+~|;=D13W^LyC*Lm%!nDs%qU2g=+2jD@$fy@mHy2+qNg)ETU>f z#^DVOf4bvt{abkR$GYen%s+nVDpZ}|dU^2JH`^mk8}}|t4)nRax^u_nyC#R@6IcIl ze6s$&&`a5h!?!%**Pgq4cFAG3nJH5?xK<=z7E?}+w)*7y<*8EAufFqpZg5q$b%(Xg z?zXwV<n7EUi*CpKzGf6Wb56!qKGVJ(N39M-t-1ZysL3od<JTd#{c74bHme^})c7i} zPiURu451>Uz0T4*eDAqwJic;>)6jP2wLiZ~O|)K_Nn0zi{EU9La{1e|!;3gSc~81B zP4{q)xip`z^-WXh-5;}_25sEF!@4-;@S*I;s)ru31!Yq<&3Mof^k&61p+tRCY3qKw zuUCRs-aKKl`b&~}X~Ol!x!3j1l$FU&sH^-L7vvJ6&KM~<*Y%{%;Trv?!kVf|ntOaU zExEuJxTLIbt5=X+WYC-i7gm3tdV2b)yIfDEb@)V_*dV%6VgDMp8lix2mF+=$jy7qt zd#p=wUH^qI%4?n!`~I$JN+JE*_uiWzF<&YoK3^mI)yoNz3#1|w@+D?3IF%Eiy3{3X zg;CZ*S)o~Tr6QB^J$wRFw|P7jh*<1Z*Ya(J8=K}LYfesYO<lK$tSL$-r?g}&@n7-r zwusoHCrkc1KDBZQm3u0+#fdjVKYZhiOzmrJ-!^-FQBQ0<rMkw4H&kcqCLynRVxsZB z-Y3If8m?clbc)95+iRBz?Y_#i`)Ww!+pqq=^S36>ms~F<xqjKPW2+4xU-bx__%W*| zDq~Me+H%)pt5+VWFiqRD(SV8j+KK)PO<PYixt6FaCTcD{%HgdWp)zxlKyQh#Zr#>H zPIKmLsm_S`zT(v4nC7q*jBo!)i5ce}y>&q^yz`%mPQcEVsVf(Dv4)2^oxHs0(dtai zpIWxhM5n$yCH-N8KhF+%i4Pm}_XmgiT8G}xIJ~|2-^-T|-b$yP{Ci?j``;UrexI52 zyQTfaq~ASJ87EuPuJ`Ly-cX-*Cw<x+<*5gj{C?t|ap~`gB?zbaMuDC7Wp>@4b*-%y zmYMZ0i~law>M!DrTF7=q>Q}^>Euz`Z)`_aWCU0<fDipS?O-n5{l2g^cyKDWjrB7CW znGt>^$ZN{e+*uJ{6gIplagcLKlac<|Ao;ODL|F1;Lm+qWj0<nrCJG7*%gG4zus?Cn z*x7ud2;l(TaIgbP`W^pxfgP}2qTuc#r~|fK=HCF0t+K7iv9%pbY&nL+^C-GK{j4Bb zJK^fV2IrN3ln;m02`vv|Z<boVs!(g<&alZbC%fWa%Kk~2bIPA7^i7}~AKR@4_f>!9 zvxNT4T+`(hlpMO_*s82GTIb6wH+0#as{I=K|L%v7TJr}Nwf?Ig46Tz|-*t55N3EF0 zp{8+DlaI(G9F==|?{-~%#jW@IEwB3B-y_Xab@*OG`<g%VTOxmEUeNO2Ahq?7X;$ds zu*zw&2g9By%Fbfns4FkO<J065p-VT!D2KBjRPr+A&3f|6-({Uw$<v0_{M&NXx{e<Z z-S2L5WS!Wy+*2xzhu3-B5?rW#$j)t@$6eEsQ0H)^>a}V+CyDO8Wc{P_LTE<gmjbtz zxIpP8p6;wGopy68Xhl8T+_+-OC9A1-=d;+^T8DUA`Y5RSFY0>xJ))(9+vEANwc@%< z&jhL099kh_b1G{4_4gl7YdIbhTpS$WEVEz+Pie<0=PUP>TvUB0Iof2UOg>zfF!}uz z#r+qAQsnBFs;=m`FD7&9^PZ&0pIJwZ`6@+CE6OGohOgiL<Sgg;8;SQ>y5}g!%oX4} zTrfeQ{b9w8cL%hmavu-uRAzg!qR&F*^x^PT7wgy*cShx`PA=M)c-`>lg&8vQZ}lH4 zI^@<~`%}~~Xlno2!iA69pYPDqb2`1gt?NeI>mM~UKCfTlC_DeZ)W@0kx+f+GxTk-- zE0eh7->O<;ojvbM9o{y46L8O%R(RyY8Lf`w&)4NvET~=GTr4~1zudu}n(vNvF8Ue% zcJ^b|@bEWF=Urj+RQ;cMiCO$&<*LWWzpTHt{e@m<UWk78d%ndS!VB3i&d>UzUdnzj zqd_FgtjBck{6(kVdHl?%_;tud`_U(j*hBp`Hdl8XTxnOJp|Dn>yuRXz!m53rE<8M5 zQn6~IbEC+jgUu^WY?iPU;ry}UVe^E@n{{3Xd!sJ0d5bMP>}~&TQm*34!+a`RZ~jf( zbgk}zS*#kjO#Nroc=<Q-FZ6tT_Rc&K!{NQ~YP<SO6QA#WuD_j|a%acqa<|qcFR$!5 z86L^Rs^QPN#7vPh*kslsxAV2XbY%AZx#K(EQD5V>@yaP(%T!V(ug+x;32L%S^G<XH zW#^T=lUH4M_$24Ih^WSm@0wblLZt1xUj=*;Ik`tJ@ul<jI<A?VU!JDve0jEqg_+NP zO+|maN%>E)CGWT9t-s%x7+!n3ao#Oio}Zm(wm)9~*R{0ZvZRu*Xs2h0f6lAUv-eYy zK8sAxIVL>Y>+`JnR%<oqT@9IkMPz5wVKp_U@&M*pnfC)KP4=&5JX<qW?sL~FUk{e> zSI2}Waebc17tuCz#*{x#EKdsicz#eg<7edM7uvAxKEGeYqUVenXWg8$+<m%jLTr0i zE;n52w`!MM{lZM1ufZ3e-aDfGQt!>LGrEQCSNExf`}LKEz0KZHCnOV^oFpdw?!4`6 zF_W~L7xk8gn5Zhwj(K}!(j=iThU)XRvMz9$t|(gvst7iEefj!u%cO;_3pd$(ayXpd z<a{nnO>BvCOXIyF-J=ms1-CzbY-p+IdGPV8_{<VsnGlV5t#V$ODdIL}1rzo>nax|x zon!iuvDbi0UBBe{x<BXo{>;CVaryC=tcN?c-Q{}f{d8UK_B{_a=1zAF_-AbP$MwNN z##5cUr}cGRu>Bl86`D(z+gi`@LFCdi-Q2PBOP4ETOs%`BDN~eJs?IRs<uMzsqTU79 z89D2>FBM#&vPV+w;q--kPB9XHC(U%{X*k*SNWkM#E_ZKL!~WaKQ=LK?gIqUdC<Qca zx@!0-*dW*6{qzrg$HtTgPyXp>9F|eY{ifBp#Uw{F)I|8`ojWdq^SvhSxSV5hDx)rl z`zhPED~lzhz1e?#Ddr5A*7;{9i(-!0ww9Peiw`c$9bLL1b_*87F4Wk})3@5{4u{rC z2hC$|_;TNHJ)Wul^GKWtpVB+MDD5ZVCNrz2S9Lx;!}RL0er}Nayx2QBkso^Q+UK&E zbcs83#_QkTBzd$`{qEMEDu=gxT6#3yX4dKz2RBQ9dHd?<MW*zSA9K%T^iH`UWd8cp zx*2^7j_dbxz3AT`F>8g)k6VkkUY1*O-7oaPb-!Tcvqy?FJbAC1S3m4}p|R6VOQz~t z_S~5Kb)Z_dYVGIs8?R~p`IKMKm|pZwe7DqTgQbC6#23#uS3dh|X0q<oXIG^wX4E}M zG<vx)c_UA;%k8Jqrvrp7&&>V8%r1OUbmx>R(P^(&g;q|<4%ot_U8ZSydV{K-YQAjP zo1l4VirbDXowDZ0w4GC$rzLsEcpcpuQ6E{eJ@_8`(cNd+=2leNzPr7TcW&K_tv54t zZX7px@uiU|CNBSeu)p;JKDIke6Ruk;@ra$Dv`6lv$VZP>xh#IO+NE{}9G5I{Dtd4u zPJZH*qZ(e<50yO2J+zTqm1|NHZ`>M}iQg;Nb^G-@9H^6cBg7P$y6E|#;8_=LmIVEn z++oFEFLcqKu_)w7+)1zbRl<iRu`h6RvP%_@eNuBHetXUy$GivnO6-e1@wM!jEcaFZ zi<#>)`xT;9ujYMMl&$)$*?+0x)kj9jb4xF5R?XTm-Q;Q3l?r#w-44ySgQQe8*e+eU zTju-3--)j_t~tP6xi|2T@WG@bf|-JX#SU2yrYNZ|Wz*~Y9+b7=y-9+*kS0$HyNP8= z{F8n2Y#CI(CA)G2bZW0=W9+;eIaA10V#1B3Pa7Om<8=91g{-$NZ*2716V1sN^6ViW zQ<K-7ITD<wN=q1BWaT%{Y-Pyl2rQm#?%dwmYd%GKS8<N`Vo}yfHQH4%(kEh$I_v2^ zG*mp)FuV6yPkj}KqlW+O&1<t|x3&6CtvGS=a$mnrAzzSp&Y|<}o0ugs<rS~Dun75Q zZD60jZudKr{=+lB-P4FHFgvBYsx3A2mqgVC5v8eVswa3QvlWwldA4VZ<lPTG7Ff9~ zWXim?4VtH1cvHNdS)M#o!zcAbbN1@wO>=_xCTvSPm~|-e!Mq=Q9W1-l_t`JxkqNeV zc;w*{j{Cvhd5tUDK5*`wvO2KkV<)p0-?8OWV^}7#f8soCBYG-aD99^dpOfI!n!QK# zz0a)Wd48H#D`U6AYSF0Hee+v5q{JC+KX@4}(!W~pqurD`{fqH(Wu3><E988CzI%0U z-apeO;VX<TbssMzxJ+$lQ);~L{&u+=_hSh`&Z83!m2fP)snh-QQ^icB2LA8+_tfm? zpZ$bU$e-V4mc$lb)AWD_O&Ol$k3VVnI`rp!RACJ6P1oAbqj2g9!(Mrw3zh$Da!>4O zuv)Q7e}&d+?&IB?^jGa(QxG*lN&WwuhhZDL^$$gRr}1262>;l#(5F-BNa&jf#RAtS zNjl3t(wb*z!~5u#`0npQM?xch1sn-Iu}13AucI3_G~Z?6&hy@zKkH#k<9~~d&9Ogy zUp+p;SJvOLkj>QNtJ$w9p3@)Cv{x$Eo1<y+#AKGH*(07AnkEnAj~N|ZrrluVy=I%% zB+YH%f)hMvD4b`m=GD98d*kIgN40{xX@?cQUC1tq*He4;@^WU}_gRwbYm#K@vuhLP z^EjQ+OcaT}HNWwJ?fJct=kqR4Et=urHP1!#_WQyekw)__=E;Bg<-92BQp_ajXOm|h z?<wl+dX*5)zT4^sXLGFD30c!)scSa#m6opfec9>mO}Fh`N^=qq6)lbyGg{ny;fdsn zR+YjBU3R;Lp0qA}dy*;Y#16jHQjOoyZJVTp_FDw=`2GFU_~gX1KFLiLzqPr-b~Ei+ zZ&GmO;3~eb(B`W<^L4qKL{A=S%Vmu|m0M5}et(m*&NN=VL;JE_pD(!Ss^A%R=ebR7 zw&wPJ3+H4}mxnsXXR#a$Ilc{C#Uw{p9-J?9ds3VCTC?LBnHkD4i?x27uMsM)>YUil z`+A#ozI^@jlwHU62c_uTU-!L-Im4BAUhJH^wh!|Tr;E&Xb&Fq-(|0q!R#>{P^T!I= zrG<G7XB<s`h_3i6nc{PcQU6BBHMUB}?UCgSJN15UjJ2}LFkma;H?lqFZ=UBW%_gaT zO7oF$(Z;*qK9&nl;}CeSaOR^fYxdPG&t<l;`o4&M^?7OL{YiH>s(#V6j6Q#4pKAW& znHRR(oZV);F<<j$Y1pG^zFWm=-*j6~eL6Aip<ZpUe$@Vl+m}kp=`d#<kiPyc-~54M zF|S^fvUsF-S+@G!^)iA*yQfY6VC2(xzN1yMy3D8adMwjyH<?5y!S_<!*-y_k{QdOF z_UF%|w{P5E`<=gYb3%+&y-1E^E^D&T1>K;^PS0h3A6@E<VpELWpvm1Xsxoi#p7x!o zLOK4$o}02n(l%S4627``?V-t&7oCs{pTCu}t@~u=?2LBNwd)luI+mrd&Td?F{$y8~ z@Y^CaUFL<Sea>%hOKP7vvq1FX^K<k4j`sN*G*(4F`nu}ef_rM)PFI~Ve5rS;YT454 z>bO&;8)u%I+kI{Cf%^&iUP0g0t*6S_zP2h^|CjUIl_y^~su!K)|90cabIs)e8&59^ z^4|IU{E9DsIyW7duKFkPQ%vN%?cL`lTh5dExhx>{m59uGaqG1%RUr#*W_)nHboIM@ zxU<(e$1|!078g&NA5!q@Ui$dtq<`88mNqS^UUM!V+VqpF=*$Y8oo_XtOj&*Cwz^pJ z^-U)d<;{%6t=}HG67ynP<l3a;u_mweKHj~$?5@-QxpTX_Vk^$|>^jo@+;`>CJ{#@e zPJR8E3e$gnZcaPV>UVcTSX=kB8+-cyRF|9-I%{ow=fq@b@2URbkH4_&-DZC?ld<;t zLia^}9J~*uE$fn3sy*MN;`-!Quj<PUE&VgP&Stm@KDtm@D8sf$Y+@1rZC769!uk78 zrezD2i}iD>oJ<g!w@ka!JSxwF^S03k7peJ+pB`hX;?Xs~r?NAZ<xID^eN=7K(HxUY zk1i}cni+NMYu3WoXSL^CRFz)Dw@zKR%B(1}bHc>TRUxX0N6wqbgcq6!UMOOoBi8za zYrV1bqq?p=ooU)!t?i7Sj{;^mOlny;;i?v2tE)nwr^cE#Ax`H+F)P9LLoy62R79RB zIy?%PF?FSi$g~HRsS7_SI6Ti~nzQqo?&1v1^1Am5Vw$o}Pa6{(8~6UWQ~5}(BFTIT z-_9a`+oxuC*jBp79DjPQdh@QNE3W(G;{DFoEoJY_OxwMDo*k#1g30<zp?71a9t~XT zq9WL&ux(EfgJZzHkatyq+xI+RoY2zYJ2ii;Pt0|_ruby#`!D2PJk%B5;&JUjq~2K{ zNz3V<gL&qz);BBL6=2+S>rgiL|LVveTi;bO>O>|y*ME1Qv-3vQ`uvC)_8eN@ua^HU zKOFq^?t-qL_omK#ADgr9jNSEv`)gkB5uSZ0_JdwV>QR*~SLZf#th^`mLhj6qjcdOB zTK;$Ytqt{2g~z>Kuan8oz5B62JG;faeEFfY1*t6?!Xt{+4_smi;n65`vbrYsI;Yq| zFG^}&V)WgZxY$zNQis>ye(iN+SNY`LSX;W4XK9qnt@9JUu}yL~@%|WB{)>4nLWS&_ zm5vG@3{(v}T<m;L@@Os$XLWksy>jgmz6-mbs|aoSwEE3)mjEBr2P>G2)GpR<654o| z_ovcd^*v`g|NJxm`})4nXVa7o2lD?gm9$T@bCY|qjPsk+2eymal{OKI`7foow=^BC z{o~8}YQnBF>8chdC3e`xJlth)Xy4%<hJnV?uBq2V;(MBU__yUgOPe!$+r0QEXYN_4 z?K*u{diT1z`Lmt(XU(1OJlo2A^#|q(6Z7ZN&WeZUScfhyJ7M|f{3jQ7&6&?EpZiB7 zKYjBxRh8@7*UYqcdnP@5!spg()atnAX3m3mt+l(SEtS5%D4wr=W71sbR}GyymN!q| zdYhK)%eFzbZ2z?v;RU6y#g<wr-!<9r;kwFwr~6Nj+PcMkZ{8oL{3t~FOV`@Z2WIR4 zF@1b3)u)O5@S-U#M-Ro9-;`FDGVL*4YH^)ccx{UQg8%EHZzTU-D7C{oI$76yW9Zhn zHB6fB9}YD~&;DEIC}JAKbiseMiPV_|z5ku}3*R#e=M`MMaf@zFgk6@I6#v;{%o|g8 zH8)*g-L3z~R;2t(NT9`*2^)`3+^Tp*@6Um&`y}&Tc^$ERQyMSO-m>>yto8DJ*@><C zmWPgqOYWSR?PRz({N7*lUEepIOWV0mHNSt~8{^wi(%X&KByUkq_2>+&(A20sdHQQ^ zz-pPA8xN!>=iFaBzv5+s8I$K^s|9@yK}*}qHaEVL*>WVq^|8I?Rq3w|vMU$#Zu#(7 z^Fx2U;v(g}%I{=+D!v(ZtbLeUy628V{+E322S@o{xEy}%(t7)etZ<_7Cb#&ih4*D% zv&PF@ULu$wtMrQFO3Rj)>-Pz)T+FUi_vHg~)r$7l4^>1u=cTMv-@4K-W|G^aEiRM1 zCe3rW-1PhVC7<B;zaAEzT_StWXQSlBvRmKfG9JI#%6?0!`s>04k{hn8Iwi07esV1C zJ9}LIewVyt-v1g|o(ui1t9pfA(~4hfw3m%(?~K`JYt?0P9H06#Xs!AD$y4g}o|;Kf zS1O%9BwuNM;J+yS!*l*U2N!<ewKMq--;uOrhSRI_(hLk$5Ae+xniD@`n3-3ST9lWV z1Di8k5*C|(dxuc1SpCtM_%GMWN}rl>zj3}Gvie4m&Vh-0Ce2xJBUUFPGevNsN8=J1 z3CDlGo2Jas-{RU>TbMHO`I$2_jfKxIV_9Y({x)z^?b5_K{tw<fULOCi{@cgP>o+W5 zZ`rvb`<Q5r-V4ThWBHxOGn?Z%B0jLC9-fla)GT&EvqVw+?Zs9%ku^5E94Z-EgQGUZ zE*C60Dxwkis#;6XOR@3OV#O@$n_R60=Sx_fZtY)mIY5aiIAGzCyMo^)74^1quN7er zOJLl!NUEgOq5M%pn`Zs0cJ8x9TQqO%cw4+_`QmM^T8)JZN^>XhOf{b}Z7q|><J7X( z>WnR#Ig@^<#jtQo{M2lD$?+#6QUB-d98vWR9G8FI;$I*9;d=Itual4TZ!+-Uy`DQ` ztpew|KPilnJU6v`;tSkAe=QSq3m21!%fFVmp~8{j<E4Ta_LDVF-DlQIt~>l@HSd0& z%^DuT{D(LeNi@w?IHeFPIZu3MEZYXYzo$zXPFom;)O``X<ZHnHcPn?d0q3)s+=(Ss zUBWYt2TJ|f$Gb@9%k>Q(*8kO>?2)waaCr2MQ|B*P?BEpgXe!x#&PVdJ%D%SJIkV0r z&Sulo`E$nng|CqQVV%;4Wuhso6$~qXPxQ^4*IJmu@Y&*&(ETTZtl_UeXmvbmJa|lO z!ckALW4B8fc05o|%xXGzJ4Zlk+m_E3T}|_@tjhm#W7)J!VU^PsJHP3E{8Vc0^F6)g z%rX_@X%|<ROj)x{EobEw1+Q%LtB-8AnCxF%&Ei?wdZ}XKe7j%L_0l$$v9}ZbtXmJ5 z6dZA4JX;)c%7^c<l<M-We=m7mT(qXY_KVEYWj)S*qFP1q8}~37+r(sKv<BsbE6Yf1 zb-bMyzIo4b?aaOf66ep}cqka6x@#9hAN!O5$=AjGGm`v&&g|h#^wnO{W?1O9d$F6T z(m9W$$mDfr7oY6>__xD{W9HcfFJ?X4kyEm2rCWk;baHcy_JV**)-9VZ#?@bY&u;yh zncbjnfvGmnd4Yqw7nZgM1jb$Id2h>bn{8Rc;)`9U9#8IBc5l-~|JV~N&uNFW<tnr_ zCkAgg9OPk=e{^nV_CzPMknAZ6Is2vhUnF<ua|K0}?QCOz6rsE4^g5luN$yUk`kou; zd9hv&pTMb;y-R-jGIrq`oPp9?T<&`Esm8?2X#V({|Gm0>+D(r$GjE1I=IoKYzV7L) zJqo{HIC*Bb+CSTw+Pbc;E7`1>XDVOy+e!NrYwahj_FJ^+kZA1XTXTP{Nzm(Bn7*Rn z({x#hU$@F1oxHhxUtK<r!`D~QpN(=k_CJi<yj}IuuKxS$E2q@1FFtiY`^LhrQeydR zM+AP&zVN#Ax8K!d-pdD9#-+I?7t}G%=O|1wj*yVt7rE4ZPV>$aAM5^{x+eVS&8|-+ zUoHg*KN5Mi_u{p0Zy)}XDT{sSwC>!)`r?D$+v-*P9?q10{4&u=CY53Lx-UVxlK1=7 zkL+9?Gkg2u^Ug`}ZbuSTHGZ6Dy>XcRk;N_UB_f+-`uAOZ^?#rCzb6~Sf63g_<Tm10 z7N5a=YOB85kxCW5-yar+C;fcV{Ql&|*QYiI-(3IJQ)ab${?dI#+*a)`ABKL^n{vvl z=$pr!ORpK#71!{k=ePd2ZuO^y>+g*vPTw?GdG|^`dvf#i`Q^v*ZvFYUfc;cfmf3c( zZ`=O58_u3P?dF3s>5o2cIQ8$x>#0k7+zj5TO0oTGw0Na^CdT;pGsJp~aQ@l#KUo+U zK5^nJU2RD(T}$(d6Vp;*W$d2N#QfVQ1pn&%>)P1Gt<tU@e<v<bqP*QmD0Smh&*@8q zWdgQDOmZ%o{Zwz`?kP%3{=Gk{qw4M#tDsx;-F49p<NSMjYK?d8YFhe=f0p^$)=10t z*YEHB`F0yb%7x{$ZwPTJ$b8V=_4Y&mmq0z0*B{i+@7~o^eMQ#1O`9|9V8Vs=ps(!m zR-qq%Jz$<J8geJ%Z1+K>8`Go>R&A?ZCYZIf@gy_j*XDOq9d8uhZo2d?npZ5#<pEpN zl?a&y7k#4E)V$bw>m!%;2HnjG(JWyrWQBr$Ug-^)HvNUhj$MD#H!WYh&wW{=cY;%Z zn)~L0-lww#Hl@tn&woi^5zo8JPhz)lg&Xi1b!^gP`FM(zmH(%jXQF88>0E)ksRB9M zKiGL(RyeoVKzYsgz<rG-dw4I2KH+>aTf_Qr-}Kw<p(6Kp9eMGtPP%oqF@wjomO}Am zr+o#UAH1C*{nUQ<r`H<&hjpSIM4ab1{Lt$uK4I2UeC$mw$8C*@-Moo&m#~N)v3D+$ z*IS(M`mmPQ;na7|BJ<}>5}D>Xr?tM4<FO6bwhdhGnxd5^?Yi>V|N0HJ6Ps0P#FtHI zyLs4bx!JYMBKF%V%FjMbXti6@WV7JSZ<9#(%4dgv`_9NeG^K)l<Kiu67OO04NfmmY z>0tBdLz(p5wvR?j?i^8l;yKIxq;r|i2Sty?JzZ-2KLb}BIjA?;g3mo*x!uc;6D*hf zHi%V!8T+8&`uY6iJ-;nZ9+r;a^_ZuYf7Od)>+?;GNe>n^1$ic$KE5PXza{J}Yh^e` zK#<G=2aV9{#f_qj@1m#htq7UAd2@)^7X?*EEza#;rc8=2syR{*FP*)}P_~Qt&Z>Q` zf0v)}6@KWuf9o2<goxhD!ZNGxSoE|=e?7A0^@;yY-Z2bMbPsKL)F#Tr{_+#&`AuyJ zT5n9Jok=R4GxK0W=2Zo)@P!UiAF>=J*Sr7du9x`V)RvJ_>)7${=w_z6#rJgTo>zuX zkMr}2G%1_Xtu`r>dsW#S-~Q?skv|(vIcD7yGxgnWQ`;k0zr5zXNLa#2w&nx69!E|w zXnUKqr98N_XqwLs`MqJbS%ng-r?1d`Eaa7Tq2l+n>ADxJ7O7RI^60Z1>N5`CBF}a3 zwBWil)uxA=mbkXHs}~luOGPa|d}#NcPxF2VCZB&CyM9aSO!Jvy?A>Xve3waOH!fZ3 z{^&@m@z-bPYEw_AG}k}dq_mT_$7o*Eq-okGTP$QA%N*wyS(BAe&=R{R`OwYlck{Y0 zZ0z47z00uZIp6Vp+O3Q0KPa1Di)@j8u6bngLJ#BHyPifFD{_U^NzAoz`qI4R*%O=O znQLaOTkuYYBQ9eZf8KfTJI%IVGVYvGTXRnLCENZF>k>9eMl^G;mrJQsJD$Tn{rs=b zj>@Zr%nQ6aEo(lhZC!A3$4|i*iDv^tHs8H7`@^r|H|qIDJ7pgKvplx6)4Y;JgzY?k z{NJ~4uKZSN<+yA3`Czrof4vJg8g_ZOH@W}47{PqySVeaG<m;;!zP{UY)vNqW)Rpw6 zc_n5Kru=)~QtNniGW$M(Z?30|xu?6^>lLYMs2kp|xcB50SC~t+!IrK6&Sr(omOjw` zr1X~1WZ6`^Zm(C8)4%a=e*e5Uzo=~E`ZBxHoPu}0T??1lbpD<xJ?-f2h3f*(@AY(j z@454gQTP0B<^eog`Iqi&4EI*ezGqW4Im=P--MP8ET?^w<!isO6d3G=5{F0^HgO4Zk z-S?ks$`kX4<6Y0X`+81mr>;xCJU#!b`TdaksTVY=neR(XcjFJ1-@$*ZT>sfQ!#`hN zufLWnb5Q;5K7r$}9<Dg6<k~!~s`A>)?%uk0pV@ygg@0Tgzx?Uf$s70I(*J)`;JUhd zi1T&XYjaEaW>gEOPc3Y73*K?HjCptZwhs%<&goq5zqcf==i~E3vHKU?`JdGr@3M4# z>G7}W)mJ`vYksabxE$W`<;7oZ*uMYOwN}^WvNABt;=xxBkZ{{*aY1UiUV8qU2*>=} z7Q(jf`;#V2j(rh)tL}hY*W0Af*?pWElftJ+i@5S{G1=64YKp_9!d`{{wT`F!-sHYf z@!O~?wo@hW#P=U*_s(>DyQ$3|=eRyE%*!X8&8kxT-oCoe|Nrl;{rk-P#b@o7xY$sq ztRH(Hg#TFncOv_w^B?*7Whz>-^tOm?WeGm)w3xs0?wXnz*IPBh?Fu3t6t@H>Z8G3U zQ!{z7%fx$~z^N$4>Dt~`bV7o&Tb3FaubBEfR-b1|hl0tOfQKop!AF-KJk;)XHGI(l zrZYX#2F5IQE7xBzdb<7NiCY~qb6Lvsiq*?DUokl$%E7s3l}^wCzH19potbnbQ>G_+ zH5f@OJ?VZ+z1D(PGN6nr@lN^dLxpBOK`(-@bvsoZROnIK!E@Q9$JlGe(_Kq$3Ir9& zEvr2tbfRraZsGC08F!X{+{t{YJJ7|mzMElE<I^1qnfVgOB7Zcxnf!jzCx1alt%ubi zxkFe%-g6G4bkscERCx{;lRpB25-KZ~ay|Ax;I_p5@QHRiUr+tdjmKv1pCnS{dFDiX zvQWB7&jR_lmgiv}uNJ&^7r$X}Cc?>Xl1R{@V}WUhC6=6Ib>ZB6D)CGQ|6c=c-Kr^S z%(D#T_1aaWCtZ2Pm#n^W`bCv(4RJ#0nHi-=p4cpUuJTT>+gC=x`%;fu@;0^~0?Ve{ zbe>$e%`fCpMzyER<Y`w@?>|dEBXhZ9Nwdmc4%v?h*Lh$6oB7<-=KrbX9J>xKeco9a ztj#R@{>hd(vxDD13AwU7?)v9*=NdFZS6{lO(Y|yO>(ZFm>BYipuHTXhJ<-ed<R{OL zS$fYjcnf$Ju_PvRa_L4N-g<1&TP8l%X*Ge85?8X$^*TncWD7l6%+i{+P({oj(y{0C zZCyqN(`l>jE{H9j^7<-Mj{2#UwlfZkt{1zp>hc|qSgtD#VZ{swE^yvjmiIVozK&;O zTelbcy_+-d&ble5EpBAK?QqWg^I55B+y3foxEdJx^-|JTFR6cTW4Ud2dWS84`aSkp z^V`eTd#dl(tKVIh&fhBg$I4IMg2l05_SV<4^-2O(nw`>%saDUO^+1lbQg?m8%mClg z_VQ+h7ggrxJ~=LKG5H?7FYfoxX{V3YG;zHWQqyjhn&u_Ze96~YFZ`Y4Z5xJDd*W^+ zZ}=g3ZoB1coqmH_X4XLV>1Il$>z`gqyV$<>+<nc817B==_eIuh{CjfSbhFp)=6`jM zmoeJdFv*4UTVImX=<$+U)#GKi$fPbJ^pA?V_Rk)%Z4cxx9a-D8H?Q|w|GSH)pVY1T zsFyldJ^J3Ez70EA<;=>@cgXGadGYv7?Xjsj?EmLf{^3__=T5k<A!l19w13KhJkF3$ zC*;;YxfmOF@^9@qzL*0y*B3E{uMnSFyhQiUwY~KhcbN(Mm*@5VzPICR`tjJ!*LKT) z$T}a8w*SoDpW=nDB@dTPe{f)nZNg(^Hy!JWyQ%)W-$e!gf7~Z$Y@I*R-{}2?BX^=0 z<~_e5@p|4mm%eYNTMXTIhhI?Zj+V|@GwXaTdzi-Zv}?b%X21O<qI2L%bl5GA_n(b3 z7T*=jWv%<S>G!@HHPuV^Meq9Nw@vK+;W_n3&z+OIf2wrL-F3HloWy>d-M;AI-RgiC zKfya2uirZ<b~}Chd+t5$vCpq;c|G^eou&W99^9>{XNMJ%>+DQIPqHvD1d8J;BuTh% z22@DGn#f0@a`SKRm|UM*+x0X1V(XMses3)NUT1d|%Pu#ZaKrL+=EjUJX5~P$z(^qv zt;};D%I$f+x~P_2JGk!#tCaVXGx>6sG83yS5)Lr(Jbu!-`Djqn)0-D8v*gXK-QUX1 znas|0*n%fg<-ufsxfk`1<=2Z&6#bjikhE`M&C!;GLKdU8kO1~Q7L`Q_qQ7-2iW*$( ze)xEtdl&5Ks5g^Akp0ud0xrihjV}HiQ<m6tvbMUbO&2KsD!p8Y$*YkwBFOLk{Dgy^ zDl6YR9D2<DELi@@B##N+Tu<!k7IZwB`psoyid?9c#!k<rIfheJrW7OyPB3usb92=; z&#kj$Dz7s9Z#Sbi;mx75Ilppi?5x;}9~`=2nrL7d?$Uhw=hG6l=gH+2rV{bH4R-8m zdf$9A$6#i^yIxYQ{CWLEvtL#-<{qx$`h0rh>O}vx@a@kZpA0{0v2Wi_ss3}O3^U>s zj(yEA+au%itXco@>W_c)RsSW~%<qZW&ia_sXPLn-vsq^j?sbvz-K?*?LyCW2Oz(pv zE9VslpXe9lyB+@c;8f%1k2xlDtPSRg_+OUfSuR}u#eVzZlQlLwnm!-=`aoODD0t1! z)kbfM49b@;&R;Bf#_iqPt1@SI%<x_RFzeN#X9chOWGv**u%D<ko*mcod>!+BefQ6& zFY<hq^O@px_-BQcW81?Lqxrl6{U=|%zWU>JhLMco`w+u3%Qye5sCxa3hmR*MS-jOR z|M||v%ecxc=K8ovuJ~m4>+!Wv5A(%0kCv3#1{@Ionvw8@pI2G&p8lo<3PQhr?4QJy zDUmbvNK8|z$(i5ko~@ZCXA)FDwjXWR@l)mgs2XN`;_#x@ObOoNgHMe1=2w1v6|i=} z(N6_}=7PTj{?BO3m1uAGy5=fXIph7x19$owf0|6vsc1T``gz)fCEpc4D|jgTCrKS| zJXQOo#p&q`<r@ZlOxp@nCyH<^Fq`p4aWPZM9iu0~PNt0$O?dSCT8#81c8S;R@>=!N zIANp8O`k&(cUAFhd2SG-Z?1Z>*X)&2+P9Fz9a3$plY1=sE6wZ{_KO?F3u<bbOF3Ew zuUf>Z?-Jg`y>aOUuM|y#&;Lz5FDzVom0!hY>TU+@c>!0o9)_G!59rZ}+S0>*$eS;` zNKBVy&cQAf`>u=gop{%4AOEKK|NNCjSAv3<E#A3#|5P8}t1p`V`R!WZCgJuswk2^& z@UGpaC8oUjC9JPg%x5*3@4BIzGWEt?vE93lzRT;rI}1$iIvVMeD>~QrX-Spbx7Q`V zrYu^Q%rs*LuT_lgA=XB*J5@(svFv>HRYF8%>hIU*)}MXO@ijqQBy`T*wNY7&E87?Q z31o<ze|y1cgCWnF^n_6F^KChrk!C5~?AP3ySrueD>K*^T`Pubb@XsIpIg!%6Y|D+F z3UVyoXxKG9L6v*1&S$e<qDT7!x1L*DzAx7*f@ST2ZGrRmNSxo8m38#S@<Wf`?9*9c z)K=XU>niYB^lPII$6={1Rm;^^IzmLUH!hBPy);VujMt6{HeXe4J>`75m-(q}@8JxV znep7kJ#Gt(48PC0m@six`otwR3UaaeJ;#(gRX(Mtly<Y~JPt{C7#)<l{Knx6v!-@@ zI~4HdP}Vd#Ii<Tbp00{)(T6O!=1*BSalYkTH>IZ~yERf4?AQE0V}aeGg#t1m3?9yh zK5)*qU9f+;is&TU0MWMPEnQ*@N^05Kr+!*$<t_A6@#{us7v3w|I-H8+wGU+ppSbh= zar(zKe@?ADzeBtBP1;NbCT}UVDdDqs^eCPWern>WG`~RpQHa_NhR+qOi~@`-7dL!m z5H#xFwkdV-!RSV&tvS+b<n1S3V(d~qevD^Q$<&w)2GWOJr)<?(TWOa!a~bn80bi3- zTdp=apZY(?@rYAxuB%RnLRKfM&Jy8Gi#j4YG9EUhO7qTVo8qh!WxT6PenqIj?Scx9 z$F3sD41vyvGmgjvJMUas-)3{O`=W;Y!bu4xOh>LS*ZOzr+BJh7)~ujuO?O^Ms_rw| zb!EjGXPu-=x=opy*Qfp!adQuvSi96l;M}8-h6O^^j2Dfh4hcUuQOMNj)@qG*wwvO( z;MO7G$v<YDN`1qv^5^r<RdM~wIe&g7G`&1vDg4B4iKVl=ivLSB_nnb@MW3mKEluFQ zW%{$$Pk84Y=G6*sovk0s9=jp1w1od&Q;Afnm5s5-r^ff6-&&LkPw3-voWC>0V^a9e zb`?dr$!i`33;uJnIQ(+W#nWC4>-=;?D}SF2^YjQene_9YOJ!)-<~a%z*B|IQAI{{t zOuOJ!;5UcL(-|J3x)Yrv(l$OwS)?{e+}O=Im%H=Hj44yHe>*uJaQxO*THCB(R2=8I zSFHBO<^_@YMa8u|@qEkQ7G@<!PrQG#ChUI!v)lX>i9?KsEGvsP8L5a!T{|M`S-`6i zT3X^8`7AYh;`tvFK5o01A#jfIf&1_Djj^U8T4EQI5|)0`zZ$f9;rvzo_a%7a*Bbd= z+2s=Fu5-si^xZ9$IkPQ-_%tk^9dqO~eX~{4{mPLub<-q&tF*033k_Rfe`VH(AjQX1 zvl!NX6KvaZ%i!D=UFN-8)}88LKI-1goOW$V&4ycZgKsllJ|r%EYwqRU8k--pE`C+% zb*}8Z)w?<0L^fAd^lBFzsQEs@P_BH9-|p&Le+%xs)_V8qt!amWmh1Z`_m}?i_5B=o z{nw3`GV=4w`ueKn{dO&1t}fpva%tMba0c$)pr^;ro$L&H_9SJxSl-j0Jxi~L&ht0E z{(YCVr0Mx;!?ff1tKT}f7jC~_KI5-c{L9}>rX0ylffn0jPncNL-LI8hY_OH>;_Il4 zB7es@d)^yXPiMTjoa@!c<IZ`tyVJk=`StmG@o%Z#CUv84LA|i(w<VEArPlJh<*S#^ z?dMuub(<|jGl=2KuCU+E+izRHE$jE|_wToxH)l(AF6-9Z8tE1L47~1dyLD>okKMDE z7i2#?7q|K|<IWG|yY;vF9J_mrQMkS=Xd07;#)OE!dG6OXZSE-AT>HdfbMca-Dg4{4 z<#P_qOnaUYeqj64?9IIaTq|$pz4N%a-}8oAT8^>z&1Z$h?&tQ++vv-aYkd0VGtbYF zm!|bz>F#Q`4&B!L&hgLkMgK}ZRK~N-+{0^kvoYSJ;PzGhD8?JJ*P1+eyXLlUm21$a zT`LxO)*O8K_<hyiOxL>ldk6Tx{@(oO=v|BIJ8urH5{h?>Tx78<H}h@-@9W(sTE4q2 zzG%=`S$pBdDL=<R#+p@Ca(<oLm;8Iao5QTH&B5Y*bLch^vk1lBbGIH$eDa3ZVAXqv z1@#@9Up0s3$8asVZuo9d@4mXOyqfBNky|g^I?ojId~MUD&C|~5Ipk<;3GXV)t>~*? ze(C+WJO0jV`lr3x@#})!riHaz+Vi%on|*CY=Buj?ub-;@ceuH!O6B~t!&3iq&34b& zvT5$;2==LVskif@U+?z#a?nac>P4^Ats6J(W$Qd9J-?v+se78`vjY>Gk1bfE_5RxV zphWpO-^65eU$04ebMA<O*oWDFdN_3t=Vve2zjFGc=_Z_qAI0drUeoPtCjV~!D(9(x zHY|RyT}9@Jxz5_1zg+6SUG1CivvzfbV8k<>UZp=xmCw_KeAu0&B2~BKu2wcq@cZ`h zvOTlkBG#*ZB^xyN`!mn!da-!vy85X2O9~6_9MhlXuC{mSqdeBG8_G@7Dz6`(a;nHT zW%-|LwNfdUqI8^MwcFkt*m`VX+rK{58;685d~P;g&E`nl!m89$#=TE7bg%yTDOt+{ zU+HjN3vke4Tiwva`z!CXX7FOg&y$Nz*L-KF-}Bk=tJq9gKDMr+r$5{dpANU&mor5x z^TMxlGnZWZ>z!IGe1B1%#9wc&-KnoS-ZbwE@b;bJbyeY0aIs>g>?*HS&m%l_Rem?K z?!L&BU47_n?_Bpx?Hyu$wG5xLB~;ET#~pb3@m6%`smf!?H%&RWdMl>zgnfEHZN7Sz zxZ6@!sSn;qT}vCk_;0<|)w4oxYMJhrs8WGns#o;-_Hs9CykGops_VD5SqfWbZ?1Q} zF8<VEig{^%grL55<BGh;_j-iiFjP4=<u$KeU%xP3{N2(;^J~M?cHjJLu|#lr+@6jb z{{#2$X}ajVc)`{MIaegJ|MLXI6zXQKSfMRfI`!Lp;}g4Bd>8zyPx$lk-2Uza!P9no zgd22zB&_lg@MGQLYO&4lzdWp;aW3cHDRv$PhLx)L`WaTl56YLM7MG+XmL%$@l;##B zr|0XX=g$ev&A)9S^snZZDD(Yx72COYv)^|;`qdPgYAN=>BhoW3;Ef(rl$7_KQ%k1l zpOkX_|2rweI!x&K(%1Z3JhJ9h&U<+HVg}2?H`ltZ_clKM#1gmn&-rYL&Dt#i+jPaH z?uEbMs$aBFhHKlQ{(Biudff{8vW{+j7Su2?!Sq+asl2y`y~1jCerxRH(puO1h&x-r z=dfwUPLu0CiaJY~)UL5yiM;CBTX5EwIcR5nCa;cQV|GTs!zA9VNrw`iIxl}Bx_$%G zWdr7AjtShAtt}z<JOnR&5Rzq`zWw&(ySb&ZMyxRm+0k83R<uWF9yMvQnJXghDCRil zaOJeRzT+1q*c|x^?HUv$cTaDsH1su=I9_SN{b;jH(@h?|CLQicN_|C#c6D@Xrd-UN z(7VuM;f!OI{MMZ5p9|;A*>&K@n;J3q$8roygb!JCZz_;das8k<@90tS>2*Tlo>QJX zcL;j~b=bLkGX9)WP<6)6)u6lCe=~<#rdxpHC)Q7&HF}z7@;|odK6I$v;->9V$(GDX z?)K*wFX?EO>}lToU`j`dUWs+-p=FK}mtTCY(X4ao`R1k+pG{wQ(lY(dB+hfU>uFY6 z@Zz)1+#{~<4j(nqS{CTGr};=ASGR?)hJw#zCGHM)p}FTCUDn`K?(&Uwn3(1|=iKMq z27X7e=Tl7Pir;ox%4g;?S>;y4u2;df&vrUn^>6Z=HJ6pIqUg6to1CLcrr=-sV`3+- zK3TUkC%W>iD=+uy+gx6nTLOEy7ys?uIc<;X_ief!7uO{=2Am2#9=(R+!!Acg?o26- zY|pl9+g>j*im<Ha`<ENB_TU1uR9*HjOsnVYHGi4?@|)SWxV0Kfo-(yFus+pGZCxOp zd7DdQ)3(_A6CNC53@N)hb?Y9LDT%tW(eodOU272aUfCmhCSiA5@Xm>fOBO~et~a03 zn*4xiD}Pj8h;ZO?|5fXKJhf$>*3O75Uy+&Fs3*7DHhtrht)XWw)IOOtt6lpllXseF z)4LB+J1*YPTR3TjtYT|@#JYlJUB^hqiq<88w{|h+nXNbT33<CrdVx_-x18kN#FH!C zoEv&(vWc1sI-Xszgt=_)f~Oii%J)utRD@KiG5j}K!IG_bM|N}5{k3M+K_SJLb{Dtn zNyjLzxe>1A-mHCSl5A$WZmG<V>(?T-e%WsJVNc)G_{hDEt7at5Gp~C1cXIcpt)hpj zbG7u&Z20+N;wG-?39Zkz9^g9Frm3;ktf(|Ivncak<-F*(f8#nfHS>S?boa09cEbfn znt$&O*c5;751agh+Y>E6J><x|V6x+-wp3kh<(I#6%V!HP+&JzW|K9mM3)73^&i`+p zKGj-To%yXsw?12r_uqZHA7xh=4%i(0dDiaR(G!ogcU?E&U|%<R&LYn2nK!oaN-sO7 zD$XXVVG_p4%hRH|d*ZRY-Q`CmcP5nk?<gyux#30Ij{IfC*Dgdy1<Lsq)G)oPKk4=7 zo9w>I|2I-v3N%ig`+aY5*^Fz(5_c~suKC?F@Axx@nGTxU_IbDNJgPhKt+=fDYImt9 zk-W7jb9Z~QXWAXOxYXLN@v)ri{2#j>J~4}a7Q8OG%Ic%$-De-Cwf(&IiG53lwfL6> zTGvzgII0)?Vo$l7{K2QPZ2kFfEVp)ZeQy79aPp&Hr^?=bIez46z4xqp-j{7Nf8Bc+ z_}rj8_3f{dlP6`Itu3wd2-1IP{B%cMS#g-j&H2-2-xUg7vzu#rgzY1r8+DEws!lBO zyCz)z{^un5C11`k&6pSNdw)&Z>udX&U?s5CS+hPVRtAPEc!$G@8|eWRzVXTVWvNAp z>8W}p6(wt?Irh)C5okOAX8nn$llR%?usL0rl)PIrYpI#5>)W}k&TFKkZ>rs#AJ3R+ zpp$u^f<I$PsNC5zzt8o^7wPn0eQlM<y5u9L>QBL<Zz^6TZO<l$x$ZnSGj;7NjY%6_ zUR!O_$$om{+pTT?qyN7D{or?hd8FiHSDoxzt9YYhq`y~4e=z5+T=+!m((MLw#>&-q z7;|^Gz73l%COAi7>hpI8?%sW_x<*4Hm&@*$iRugKN$%6S=1HvMU1!@JTIBOI{mV6x zl@ny-=WuS)TGG{J;cOq^7NAsrbjhpGmpdNp_+DwA;wvFKDZKN~xk5RU{{a`I3(`)` zj`dly?0LiEJLz{k^edh}>a<x}J0r>R#7Q=H=QHAAQ&{$X4X~c^d_%DA{0@of9qaci zDOL${3HKB(4qh*+_EIjj(DljEY}p@@^R^xo)qVV=Jli_;)4|>TGP6T`f?cY+@)8eS z(AM=ynkjR5#-k&b4qV`Q&iiaB=lb9Rr<l42J7;*WvCr+*N-0b7`mAZSoyqIUeHlHU z8K2iZzxX?Gj*G;tf6B=zg02Sl*6A*6mK1#xblc~~4EfON^G{1}wU;j5bZ}ZDXLVMC zLJ6l*)|aR$uH7f5DVJzTTInmSiTn52F#NpCg`b;*qrYct_@!C9FpBf5qWwpwQxCcV zlGnVDnJ%^AqU7HrmXBv@MiqSA<~i%(la4;V#d|KKtX+69$a(WrH@DQ@GpD2^r+r-z zS7v-7p@L)jfp1o8-mPF$UjM(cWv`q=Ouqku+UhCnHy&PN&JkMS{p>wcOasTX_%8`R zUHQLGT2cSu%lrL&FK)_JZ2SJ>!v}R(8ea6kH6xjcfx%7?)QVta5@8Tw;9%fj0D=9= z*JbxHFfjaKU|`Sz383Kg%#w`KB)#PPT>X^9vee}C4E^+cUC>~qLz$tTp`M|>UV3Ip zW_n(JQEGrUs>w!DT-HU53=E9S3=Fy`rb;j}Fc4vKNl{{1X0cvnZVtN9{)@J$eq>}| z_{YS+powDiQzl}J_VILf^$T`IH&#yZ)we_33=E(}X4)vm>ar4JY>=y?i?6F*ZVI}= z!E%asBN-VOCNVKE=%X0yAxMnD$@yjRMX3e(MJ0O08R&+)v8DYg<X~XP7Ghuk9gc}G z|DO;shJ#{LKdG`HvA9?-Js;ilz9rhNCz%--&ayEum>`U1U|={aO`_?bWgu8=xSQi+ zY{19BP@{qF{vYy0+mM`}o1349#q_yTE54oPU|{$q$G`wOOa$SDHa!wej|Y|CSgZ&= zoG_(<kAXqU2;Bo)%t^2!FD)}2i|NM#uRV_AWnl1EM9)T(+=w<kB|jO9(X0B7=N%Jb zV0dK8zyO-iMTCua2=PXj<`!Tv8~H{bQ0<5?J2#yqvvGww@*NMLQ|J*E=+%>C0n)7w z=!qZs415cO1q=)fwXG!Ck(ZChmPeNn=iZ|F<X{KUwxFG^kM0xX({@k`3FC=G+W|RY z2TNoxL0XxMn#mLwl4v@v=nm&cEKdV1@kPW&@Lr;=Kwt2S9!kh-A3!VJ5SDB_M6xBQ z>)z0<LY_fH&3ijf5N#Ex=*AKq$fE|RdGFp?lFY^x8OV)d(BK0ioZM~^Z2_n>MH`Ah n4<zJ<3#vy>+$Y8!kQFEm?f`FAHjrZ_7$g|}aWF9SJOc3mY43Q{ diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.1.ziphash b/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.1.ziphash deleted file mode 100644 index b36e08e..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.1.ziphash +++ /dev/null @@ -1 +0,0 @@ -h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/dgryski/trifles/@v/list b/.devenv/state/go/pkg/mod/cache/download/github.com/dgryski/trifles/@v/list deleted file mode 100644 index 262cda8..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/dgryski/trifles/@v/list +++ /dev/null @@ -1 +0,0 @@ -v0.0.0-20200323201526-dd97f9abfb48 diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/dgryski/trifles/@v/v0.0.0-20200323201526-dd97f9abfb48.mod b/.devenv/state/go/pkg/mod/cache/download/github.com/dgryski/trifles/@v/v0.0.0-20200323201526-dd97f9abfb48.mod deleted file mode 100644 index ac53d95..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/dgryski/trifles/@v/v0.0.0-20200323201526-dd97f9abfb48.mod +++ /dev/null @@ -1 +0,0 @@ -module github.com/dgryski/trifles diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/list b/.devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/list deleted file mode 100644 index 0ec25f7..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/list +++ /dev/null @@ -1 +0,0 @@ -v1.0.0 diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.0.info b/.devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.0.info deleted file mode 100644 index 79e89a9..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.0.info +++ /dev/null @@ -1 +0,0 @@ -{"Version":"v1.0.0","Time":"2016-01-10T10:55:54Z"} \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.0.lock b/.devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.0.lock deleted file mode 100644 index e69de29..0000000 diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.0.mod b/.devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.0.mod deleted file mode 100644 index a03051f..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.0.mod +++ /dev/null @@ -1 +0,0 @@ -module github.com/pmezard/go-difflib diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.0.zip b/.devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.0.zip deleted file mode 100644 index 5ad7d64ca4bbb8488f50c1f7c72a5a5f46473740..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12433 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 diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.0.ziphash b/.devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.0.ziphash deleted file mode 100644 index 6ae1402..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.0.ziphash +++ /dev/null @@ -1 +0,0 @@ -h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/objx/@v/list b/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/objx/@v/list deleted file mode 100644 index 008f082..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/objx/@v/list +++ /dev/null @@ -1,3 +0,0 @@ -v0.1.0 -v0.4.0 -v0.5.0 diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/objx/@v/v0.1.0.mod b/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/objx/@v/v0.1.0.mod deleted file mode 100644 index cbaa421..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/objx/@v/v0.1.0.mod +++ /dev/null @@ -1 +0,0 @@ -module github.com/stretchr/objx diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/objx/@v/v0.4.0.mod b/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/objx/@v/v0.4.0.mod deleted file mode 100644 index 45a55d2..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/objx/@v/v0.4.0.mod +++ /dev/null @@ -1,8 +0,0 @@ -module github.com/stretchr/objx - -go 1.12 - -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/stretchr/testify v1.7.1 -) diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/objx/@v/v0.5.0.mod b/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/objx/@v/v0.5.0.mod deleted file mode 100644 index eeb2cb3..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/objx/@v/v0.5.0.mod +++ /dev/null @@ -1,5 +0,0 @@ -module github.com/stretchr/objx - -go 1.12 - -require github.com/stretchr/testify v1.8.0 diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/list b/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/list deleted file mode 100644 index b7cdaf4..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/list +++ /dev/null @@ -1,3 +0,0 @@ -v1.7.1 -v1.8.0 -v1.8.2 diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.7.1.mod b/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.7.1.mod deleted file mode 100644 index ed0b50b..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.7.1.mod +++ /dev/null @@ -1,10 +0,0 @@ -module github.com/stretchr/testify - -go 1.13 - -require ( - github.com/davecgh/go-spew v1.1.0 - github.com/pmezard/go-difflib v1.0.0 - github.com/stretchr/objx v0.1.0 - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c -) diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.0.mod b/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.0.mod deleted file mode 100644 index c5d3e88..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.0.mod +++ /dev/null @@ -1,10 +0,0 @@ -module github.com/stretchr/testify - -go 1.13 - -require ( - github.com/davecgh/go-spew v1.1.1 - github.com/pmezard/go-difflib v1.0.0 - github.com/stretchr/objx v0.4.0 - gopkg.in/yaml.v3 v3.0.1 -) diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.2.info b/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.2.info deleted file mode 100644 index e1271a7..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.2.info +++ /dev/null @@ -1 +0,0 @@ -{"Version":"v1.8.2","Time":"2023-02-25T12:46:30Z","Origin":{"VCS":"git","URL":"https://github.com/stretchr/testify","Ref":"refs/tags/v1.8.2","Hash":"f36bfe3c337aa95c86f04c721acdbafb5ffb1611"}} \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.2.lock b/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.2.lock deleted file mode 100644 index e69de29..0000000 diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.2.mod b/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.2.mod deleted file mode 100644 index 3fe9bab..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.2.mod +++ /dev/null @@ -1,10 +0,0 @@ -module github.com/stretchr/testify - -go 1.13 - -require ( - github.com/davecgh/go-spew v1.1.1 - github.com/pmezard/go-difflib v1.0.0 - github.com/stretchr/objx v0.5.0 - gopkg.in/yaml.v3 v3.0.1 -) diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.2.zip b/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.2.zip deleted file mode 100644 index 3ac4e13886c8a3f35ac7849fdf8c5a47adcdd33a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114188 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⪻2N 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 WY@paQXE0~@Bg(+=YdIqW0|Nl}x8KSD diff --git a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.2.ziphash b/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.2.ziphash deleted file mode 100644 index c8b1155..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/github.com/stretchr/testify/@v/v1.8.2.ziphash +++ /dev/null @@ -1 +0,0 @@ -h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/list b/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/list deleted file mode 100644 index 4cf6351..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/list +++ /dev/null @@ -1,2 +0,0 @@ -v0.5.2 -v0.8.1 diff --git a/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.5.2.lock b/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.5.2.lock deleted file mode 100644 index e69de29..0000000 diff --git a/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.5.2.mod b/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.5.2.mod deleted file mode 100644 index 2d2e207..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.5.2.mod +++ /dev/null @@ -1,10 +0,0 @@ -module gitlab.schukai.com/oss/libraries/go/utilities/pathfinder - -go 1.19 - -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/testify v1.8.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.5.2.zip b/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.5.2.zip deleted file mode 100644 index b6a41fad614b0f44456f67c3204ee93445dc5722..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25981 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 S6pexmf(*<Y3=Ao;ARYjw*Y2+X diff --git a/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.5.2.ziphash b/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.5.2.ziphash deleted file mode 100644 index cb5dd94..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.5.2.ziphash +++ /dev/null @@ -1 +0,0 @@ -h1:R+dL2NJCM+AQNPK4DPDmfvx1eomi1Xb1dl0XKEFj7Ek= \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.8.1.info b/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.8.1.info deleted file mode 100644 index c8b194c..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.8.1.info +++ /dev/null @@ -1 +0,0 @@ -{"Version":"v0.8.1","Time":"2023-09-16T08:48:21Z","Origin":{"VCS":"git","URL":"https://gitlab.schukai.com/oss/libraries/go/utilities/pathfinder.git","Ref":"refs/tags/v0.8.1","Hash":"aa99843ec5a11ae8ac4af99f6ce2052ad410d716"}} \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.8.1.lock b/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.8.1.lock deleted file mode 100644 index e69de29..0000000 diff --git a/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.8.1.mod b/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.8.1.mod deleted file mode 100644 index f1f0841..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.8.1.mod +++ /dev/null @@ -1,11 +0,0 @@ -module gitlab.schukai.com/oss/libraries/go/utilities/pathfinder - -go 1.20 - -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/testify v1.8.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.8.1.zip b/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.8.1.zip deleted file mode 100644 index 50b322712529a1e100d1cacb90f35c6a41fc555b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39099 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 diff --git a/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.8.1.ziphash b/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.8.1.ziphash deleted file mode 100644 index 6eb6044..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/@v/v0.8.1.ziphash +++ /dev/null @@ -1 +0,0 @@ -h1:A3KvLvu4rV3OstgEn6xHulhQaXawVvzFzbafYHWHUfs= \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/cache/download/gopkg.in/check.v1/@v/list b/.devenv/state/go/pkg/mod/cache/download/gopkg.in/check.v1/@v/list deleted file mode 100644 index d4c3e43..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/gopkg.in/check.v1/@v/list +++ /dev/null @@ -1 +0,0 @@ -v0.0.0-20161208181325-20d25e280405 diff --git a/.devenv/state/go/pkg/mod/cache/download/gopkg.in/check.v1/@v/v0.0.0-20161208181325-20d25e280405.mod b/.devenv/state/go/pkg/mod/cache/download/gopkg.in/check.v1/@v/v0.0.0-20161208181325-20d25e280405.mod deleted file mode 100644 index 7cec6a0..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/gopkg.in/check.v1/@v/v0.0.0-20161208181325-20d25e280405.mod +++ /dev/null @@ -1 +0,0 @@ -module gopkg.in/check.v1 diff --git a/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/list b/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/list deleted file mode 100644 index 2c0cc33..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/list +++ /dev/null @@ -1,2 +0,0 @@ -v3.0.0-20200313102051-9f266ea9e77c -v3.0.1 diff --git a/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.0-20200313102051-9f266ea9e77c.mod b/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.0-20200313102051-9f266ea9e77c.mod deleted file mode 100644 index f407ea3..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.0-20200313102051-9f266ea9e77c.mod +++ /dev/null @@ -1,5 +0,0 @@ -module "gopkg.in/yaml.v3" - -require ( - "gopkg.in/check.v1" v0.0.0-20161208181325-20d25e280405 -) diff --git a/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.info b/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.info deleted file mode 100644 index 590bbd3..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.info +++ /dev/null @@ -1 +0,0 @@ -{"Version":"v3.0.1","Time":"2022-05-27T08:35:30Z"} \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.lock b/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.lock deleted file mode 100644 index e69de29..0000000 diff --git a/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.mod b/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.mod deleted file mode 100644 index f407ea3..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.mod +++ /dev/null @@ -1,5 +0,0 @@ -module "gopkg.in/yaml.v3" - -require ( - "gopkg.in/check.v1" v0.0.0-20161208181325-20d25e280405 -) diff --git a/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.zip b/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.zip deleted file mode 100644 index 14e5f8611f725d670dd1d408ced2c4f47e4869c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 104623 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 diff --git a/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.ziphash b/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.ziphash deleted file mode 100644 index 1220d15..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.ziphash +++ /dev/null @@ -1 +0,0 @@ -h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/cache/download/sumdb/sum.golang.org/lookup/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1 b/.devenv/state/go/pkg/mod/cache/download/sumdb/sum.golang.org/lookup/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1 deleted file mode 100644 index 66c1c22..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/sumdb/sum.golang.org/lookup/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1 +++ /dev/null @@ -1,9 +0,0 @@ -19632712 -gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.8.1 h1:A3KvLvu4rV3OstgEn6xHulhQaXawVvzFzbafYHWHUfs= -gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.8.1/go.mod h1:MqCBFv7DXKoBE2rZDc51LGvl2QI7Kz0D+XkQ0izj+ws= - -go.sum database tree -19632713 -+dFqIiCep9PFS2o8VBuGFtkBBGfUWWNR5ZdeHkgmu9k= - -— sum.golang.org Az3griAQL5WUYUZsThtGZu3lOLHLrxWK0YS6TDTBr7TJUTmogfpY1Hyrv21yIzVzvlSSsoq4A1vGmP1Se1EmBw8IcgQ= diff --git a/.devenv/state/go/pkg/mod/cache/download/sumdb/sum.golang.org/tile/8/0/x076/690.p/73 b/.devenv/state/go/pkg/mod/cache/download/sumdb/sum.golang.org/tile/8/0/x076/690.p/73 deleted file mode 100644 index d26c0100c2798b8ac5723cbd3c2e40773132972e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2336 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 Vb1Esp>iCvP&sXxFy}FDi902bMddUC) diff --git a/.devenv/state/go/pkg/mod/cache/download/sumdb/sum.golang.org/tile/8/1/299.p/146 b/.devenv/state/go/pkg/mod/cache/download/sumdb/sum.golang.org/tile/8/1/299.p/146 deleted file mode 100644 index fc9c844ae605cf14f394812ddfd08db01c537e8b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4672 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 diff --git a/.devenv/state/go/pkg/mod/cache/download/sumdb/sum.golang.org/tile/8/2/001.p/43 b/.devenv/state/go/pkg/mod/cache/download/sumdb/sum.golang.org/tile/8/2/001.p/43 deleted file mode 100644 index eb5d9393463e6672ac460bab415ac1fce97cfb05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1376 zcmcEA{B6@DxqmBLdzzLup6m(xTp3k$BBbt~lC47)--W%g+C1x1(_*&l`_Q^MbJ?Q5 zl@h)t&VpwQHmd|gE6=RRicL7U=8u4|-h_Y`+S^4{nB$VX*{}KRPkoy%zjS8^-wZXj zTb<TlRQK)Na_Lxr-R)cNS6|#;mzt$4QFDS>^Z%qg$>nE{mY%n~vOYuJfvxe(@9#TA z&OT<dl6uX!y?bHZ>+6vbDO)dS#-@8JoO%17vodb7^0t=^W+C6%GBVkkDs4LjZce>= z+qBE>#-3YCn~XhnT3bFYHL<r<|J%Oug86>iB|od)&(dP+ytLM{F0|#~s<plT7dEa_ z{v(lJ<`)zCuT-}}@E`XL&d6iGLfUoLq)0qE=knm1jP9&py*X8HuGCE2D!J%Pqb8Fx z!^ck>ZTV`~TQ=t=u3fY1BWIKEpTfFJe>#{xeUvcXUAa`GtmE>pEOCSD2Kl!;^ac2z z3U2gJ6m_xr9W~=>*ebU(I}fSsNxWkGTy@1E{)?8Ew)1Vj{%!;Nqmn)M?>%{SCH3{> z%}iHjKCn@o)P0YkDWG`IQ{Sy3O@eC{nOnd8Zn)=Tf9GxESzp{IJLa35{rP*>{dm3K zO42K*^D46?H{VcJuzR!7RcZFt_kMHtrdEC4v)t0#xN=|rruH?5m)L7Bi9GD|X8!Ht zm)swmdnUa1&h*$2>#{|SUv?dg6~1`y-LbOi+nn;+|9npHGpJi4yY5C#cksdro9Kx$ z><czl*nHc*)oJ$pqj$p3ZFn)4^Yf~k74eU@?3_4ho9v~?Lw}4OUv}wz`0<*?T%K8` z9ChB}mz$F`Yb!DYw3z;Q*@`;L2>g*PyAc<c$$a<gn&)4X0#(Ge`0kjHz#f))V(aBc z4DH(WB}cD5aY#BjQBOUod-AKG#v4{@rU#<VMfa$M{$*XvurVRyXY-vMQgzOv8DUp^ zR5s7de7VA*;NI$*o|6ttNyVbocWxZF<k=t8m~f`Fzx15^g1!4^pWL?mel&}tt`ZA# zP2dEPU8~x;?H>!DE4q3^!o*f`+x>MGx&f;K|6HuRxz{04?4J3AP`MnAz3Vg|RDI@k zaw?npdQy~#>iWf^B`g)fC$6=&o2$Q?f8p$nH@mFa&8+wBnH_ZGo%`i=(;lr;knl6U zvef@~g@@{j$1<1q>aG2{-qd4*#@DpRw>@5E&agS)dwq6i($S3bZ^e~wCOowd3BGlC zmN>WDe&fd{M4hrrY>IvSS6Ij~mQ54u=@n%AydZOaSgUBsv@NM^Gpr47`Q2E2e$R@+ zwX&Pvw;n$8tI);fxSjtajtx~Tb;mWtvXl)vg;zTK(atMKaekKS_eMnE;)~pcxr@a2 zDEzHA4A!^U(7<Xt{ZoSHR<^G*Oj7PgN5mSfzrJ>+NPK-5kFm0DM#}rgugv-lt{QkP zYVtnzWnF4chwQ)3r@{-E9tO*-SpP|iMYML8)#^gsV?n!R&;OBf5Ph~Ja*~(RLq*G_ z0z5NMZna)xyP{{!1l4?7iMjidBx<*_Kj3Pt|9nTyIho<;Z|hkf#816EKXuD?y(|9j zUP-yE**hbE>DHY4mzlPFlGI)5Q2V)Q`CS&4uI$~WU5iZ~*xBTsTj#AI5y9SM?{il2 z@8+c(B6<7<J`t?0HY>6MJ}TLSIMphDn%>a*-EP9)*(@#b9}_ps@fCGw*f@7H@89ii z2b4Sb=j`)Zy~KTndaQNy{_2@mjPI*IU-+h6aKoi#VXqY9Wg`xxF34!=KfK-kkYla# zjK_su25dQX+yCj?{QK$oURra{$={#0nOoiw&+idtXG@dc)RWYp6&ZQzW7gKK$~}7O zFFU`<zEv~Wn;WDyLqE<^V&UQH8_ScszA>G>vB>P+)=-%zF9p3zR{ZSVoY5OsIspLd Cqp11- diff --git a/.devenv/state/go/pkg/mod/cache/download/sumdb/sum.golang.org/tile/8/3/000.p/1 b/.devenv/state/go/pkg/mod/cache/download/sumdb/sum.golang.org/tile/8/3/000.p/1 deleted file mode 100644 index 1664933..0000000 --- a/.devenv/state/go/pkg/mod/cache/download/sumdb/sum.golang.org/tile/8/3/000.p/1 +++ /dev/null @@ -1,2 +0,0 @@ -o -�@m�%q��T`�ow!^�Z�{��ˍ��v \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/cache/lock b/.devenv/state/go/pkg/mod/cache/lock deleted file mode 100644 index e69de29..0000000 diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/.gitignore b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/.gitignore deleted file mode 100644 index 0026861..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/.gitignore +++ /dev/null @@ -1,22 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/.travis.yml b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/.travis.yml deleted file mode 100644 index 1f4cbf5..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/.travis.yml +++ /dev/null @@ -1,28 +0,0 @@ -language: go -go_import_path: github.com/davecgh/go-spew -go: - - 1.6.x - - 1.7.x - - 1.8.x - - 1.9.x - - 1.10.x - - tip -sudo: false -install: - - go get -v github.com/alecthomas/gometalinter - - gometalinter --install -script: - - export PATH=$PATH:$HOME/gopath/bin - - export GORACE="halt_on_error=1" - - test -z "$(gometalinter --disable-all - --enable=gofmt - --enable=golint - --enable=vet - --enable=gosimple - --enable=unconvert - --deadline=4m ./spew | tee /dev/stderr)" - - go test -v -race -tags safe ./spew - - go test -v -race -tags testcgo ./spew -covermode=atomic -coverprofile=profile.cov -after_success: - - go get -v github.com/mattn/goveralls - - goveralls -coverprofile=profile.cov -service=travis-ci diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/LICENSE b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/LICENSE deleted file mode 100644 index bc52e96..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -ISC License - -Copyright (c) 2012-2016 Dave Collins <dave@davec.name> - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/README.md b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/README.md deleted file mode 100644 index f6ed02c..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/README.md +++ /dev/null @@ -1,201 +0,0 @@ -go-spew -======= - -[](https://travis-ci.org/davecgh/go-spew) -[](http://copyfree.org) -[](https://coveralls.io/r/davecgh/go-spew?branch=master) - -Go-spew implements a deep pretty printer for Go data structures to aid in -debugging. A comprehensive suite of tests with 100% test coverage is provided -to ensure proper functionality. See `test_coverage.txt` for the gocov coverage -report. Go-spew is licensed under the liberal ISC license, so it may be used in -open source or commercial projects. - -If you're interested in reading about how this package came to life and some -of the challenges involved in providing a deep pretty printer, there is a blog -post about it -[here](https://web.archive.org/web/20160304013555/https://blog.cyphertite.com/go-spew-a-journey-into-dumping-go-data-structures/). - -## Documentation - -[](http://godoc.org/github.com/davecgh/go-spew/spew) - -Full `go doc` style documentation for the project can be viewed online without -installing this package by using the excellent GoDoc site here: -http://godoc.org/github.com/davecgh/go-spew/spew - -You can also view the documentation locally once the package is installed with -the `godoc` tool by running `godoc -http=":6060"` and pointing your browser to -http://localhost:6060/pkg/github.com/davecgh/go-spew/spew - -## Installation - -```bash -$ go get -u github.com/davecgh/go-spew/spew -``` - -## Quick Start - -Add this import line to the file you're working in: - -```Go -import "github.com/davecgh/go-spew/spew" -``` - -To dump a variable with full newlines, indentation, type, and pointer -information use Dump, Fdump, or Sdump: - -```Go -spew.Dump(myVar1, myVar2, ...) -spew.Fdump(someWriter, myVar1, myVar2, ...) -str := spew.Sdump(myVar1, myVar2, ...) -``` - -Alternatively, if you would prefer to use format strings with a compacted inline -printing style, use the convenience wrappers Printf, Fprintf, etc with %v (most -compact), %+v (adds pointer addresses), %#v (adds types), or %#+v (adds types -and pointer addresses): - -```Go -spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) -spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) -spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) -spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) -``` - -## Debugging a Web Application Example - -Here is an example of how you can use `spew.Sdump()` to help debug a web application. Please be sure to wrap your output using the `html.EscapeString()` function for safety reasons. You should also only use this debugging technique in a development environment, never in production. - -```Go -package main - -import ( - "fmt" - "html" - "net/http" - - "github.com/davecgh/go-spew/spew" -) - -func handler(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "text/html") - fmt.Fprintf(w, "Hi there, %s!", r.URL.Path[1:]) - fmt.Fprintf(w, "<!--\n" + html.EscapeString(spew.Sdump(w)) + "\n-->") -} - -func main() { - http.HandleFunc("/", handler) - http.ListenAndServe(":8080", nil) -} -``` - -## Sample Dump Output - -``` -(main.Foo) { - unexportedField: (*main.Bar)(0xf84002e210)({ - flag: (main.Flag) flagTwo, - data: (uintptr) <nil> - }), - ExportedField: (map[interface {}]interface {}) { - (string) "one": (bool) true - } -} -([]uint8) { - 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | - 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| - 00000020 31 32 |12| -} -``` - -## Sample Formatter Output - -Double pointer to a uint8: -``` - %v: <**>5 - %+v: <**>(0xf8400420d0->0xf8400420c8)5 - %#v: (**uint8)5 - %#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5 -``` - -Pointer to circular struct with a uint8 field and a pointer to itself: -``` - %v: <*>{1 <*><shown>} - %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)<shown>} - %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)<shown>} - %#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)<shown>} -``` - -## Configuration Options - -Configuration of spew is handled by fields in the ConfigState type. For -convenience, all of the top-level functions use a global state available via the -spew.Config global. - -It is also possible to create a ConfigState instance that provides methods -equivalent to the top-level functions. This allows concurrent configuration -options. See the ConfigState documentation for more details. - -``` -* Indent - String to use for each indentation level for Dump functions. - It is a single space by default. A popular alternative is "\t". - -* MaxDepth - Maximum number of levels to descend into nested data structures. - There is no limit by default. - -* DisableMethods - Disables invocation of error and Stringer interface methods. - Method invocation is enabled by default. - -* DisablePointerMethods - Disables invocation of error and Stringer interface methods on types - which only accept pointer receivers from non-pointer variables. This option - relies on access to the unsafe package, so it will not have any effect when - running in environments without access to the unsafe package such as Google - App Engine or with the "safe" build tag specified. - Pointer method invocation is enabled by default. - -* DisablePointerAddresses - DisablePointerAddresses specifies whether to disable the printing of - pointer addresses. This is useful when diffing data structures in tests. - -* DisableCapacities - DisableCapacities specifies whether to disable the printing of capacities - for arrays, slices, maps and channels. This is useful when diffing data - structures in tests. - -* ContinueOnMethod - Enables recursion into types after invoking error and Stringer interface - methods. Recursion after method invocation is disabled by default. - -* SortKeys - Specifies map keys should be sorted before being printed. Use - this to have a more deterministic, diffable output. Note that - only native types (bool, int, uint, floats, uintptr and string) - and types which implement error or Stringer interfaces are supported, - with other types sorted according to the reflect.Value.String() output - which guarantees display stability. Natural map order is used by - default. - -* SpewKeys - SpewKeys specifies that, as a last resort attempt, map keys should be - spewed to strings and sorted by those strings. This is only considered - if SortKeys is true. - -``` - -## Unsafe Package Dependency - -This package relies on the unsafe package to perform some of the more advanced -features, however it also supports a "limited" mode which allows it to work in -environments where the unsafe package is not available. By default, it will -operate in this mode on Google App Engine and when compiled with GopherJS. The -"safe" build tag may also be specified to force the package to build without -using the unsafe package. - -## License - -Go-spew is licensed under the [copyfree](http://copyfree.org) ISC License. diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/cov_report.sh b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/cov_report.sh deleted file mode 100644 index 9579497..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/cov_report.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -# This script uses gocov to generate a test coverage report. -# The gocov tool my be obtained with the following command: -# go get github.com/axw/gocov/gocov -# -# It will be installed to $GOPATH/bin, so ensure that location is in your $PATH. - -# Check for gocov. -if ! type gocov >/dev/null 2>&1; then - echo >&2 "This script requires the gocov tool." - echo >&2 "You may obtain it with the following command:" - echo >&2 "go get github.com/axw/gocov/gocov" - exit 1 -fi - -# Only run the cgo tests if gcc is installed. -if type gcc >/dev/null 2>&1; then - (cd spew && gocov test -tags testcgo | gocov report) -else - (cd spew && gocov test | gocov report) -fi diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/bypass.go b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/bypass.go deleted file mode 100644 index 7929947..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/bypass.go +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) 2015-2016 Dave Collins <dave@davec.name> -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -// NOTE: Due to the following build constraints, this file will only be compiled -// when the code is not running on Google App Engine, compiled by GopherJS, and -// "-tags safe" is not added to the go build command line. The "disableunsafe" -// tag is deprecated and thus should not be used. -// Go versions prior to 1.4 are disabled because they use a different layout -// for interfaces which make the implementation of unsafeReflectValue more complex. -// +build !js,!appengine,!safe,!disableunsafe,go1.4 - -package spew - -import ( - "reflect" - "unsafe" -) - -const ( - // UnsafeDisabled is a build-time constant which specifies whether or - // not access to the unsafe package is available. - UnsafeDisabled = false - - // ptrSize is the size of a pointer on the current arch. - ptrSize = unsafe.Sizeof((*byte)(nil)) -) - -type flag uintptr - -var ( - // flagRO indicates whether the value field of a reflect.Value - // is read-only. - flagRO flag - - // flagAddr indicates whether the address of the reflect.Value's - // value may be taken. - flagAddr flag -) - -// flagKindMask holds the bits that make up the kind -// part of the flags field. In all the supported versions, -// it is in the lower 5 bits. -const flagKindMask = flag(0x1f) - -// Different versions of Go have used different -// bit layouts for the flags type. This table -// records the known combinations. -var okFlags = []struct { - ro, addr flag -}{{ - // From Go 1.4 to 1.5 - ro: 1 << 5, - addr: 1 << 7, -}, { - // Up to Go tip. - ro: 1<<5 | 1<<6, - addr: 1 << 8, -}} - -var flagValOffset = func() uintptr { - field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") - if !ok { - panic("reflect.Value has no flag field") - } - return field.Offset -}() - -// flagField returns a pointer to the flag field of a reflect.Value. -func flagField(v *reflect.Value) *flag { - return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset)) -} - -// unsafeReflectValue converts the passed reflect.Value into a one that bypasses -// the typical safety restrictions preventing access to unaddressable and -// unexported data. It works by digging the raw pointer to the underlying -// value out of the protected value and generating a new unprotected (unsafe) -// reflect.Value to it. -// -// This allows us to check for implementations of the Stringer and error -// interfaces to be used for pretty printing ordinarily unaddressable and -// inaccessible values such as unexported struct fields. -func unsafeReflectValue(v reflect.Value) reflect.Value { - if !v.IsValid() || (v.CanInterface() && v.CanAddr()) { - return v - } - flagFieldPtr := flagField(&v) - *flagFieldPtr &^= flagRO - *flagFieldPtr |= flagAddr - return v -} - -// Sanity checks against future reflect package changes -// to the type or semantics of the Value.flag field. -func init() { - field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") - if !ok { - panic("reflect.Value has no flag field") - } - if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() { - panic("reflect.Value flag field has changed kind") - } - type t0 int - var t struct { - A t0 - // t0 will have flagEmbedRO set. - t0 - // a will have flagStickyRO set - a t0 - } - vA := reflect.ValueOf(t).FieldByName("A") - va := reflect.ValueOf(t).FieldByName("a") - vt0 := reflect.ValueOf(t).FieldByName("t0") - - // Infer flagRO from the difference between the flags - // for the (otherwise identical) fields in t. - flagPublic := *flagField(&vA) - flagWithRO := *flagField(&va) | *flagField(&vt0) - flagRO = flagPublic ^ flagWithRO - - // Infer flagAddr from the difference between a value - // taken from a pointer and not. - vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A") - flagNoPtr := *flagField(&vA) - flagPtr := *flagField(&vPtrA) - flagAddr = flagNoPtr ^ flagPtr - - // Check that the inferred flags tally with one of the known versions. - for _, f := range okFlags { - if flagRO == f.ro && flagAddr == f.addr { - return - } - } - panic("reflect.Value read-only flag has changed semantics") -} diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/bypasssafe.go b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/bypasssafe.go deleted file mode 100644 index 205c28d..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/bypasssafe.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2015-2016 Dave Collins <dave@davec.name> -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -// NOTE: Due to the following build constraints, this file will only be compiled -// when the code is running on Google App Engine, compiled by GopherJS, or -// "-tags safe" is added to the go build command line. The "disableunsafe" -// tag is deprecated and thus should not be used. -// +build js appengine safe disableunsafe !go1.4 - -package spew - -import "reflect" - -const ( - // UnsafeDisabled is a build-time constant which specifies whether or - // not access to the unsafe package is available. - UnsafeDisabled = true -) - -// unsafeReflectValue typically converts the passed reflect.Value into a one -// that bypasses the typical safety restrictions preventing access to -// unaddressable and unexported data. However, doing this relies on access to -// the unsafe package. This is a stub version which simply returns the passed -// reflect.Value when the unsafe package is not available. -func unsafeReflectValue(v reflect.Value) reflect.Value { - return v -} diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/common.go b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/common.go deleted file mode 100644 index 1be8ce9..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/common.go +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins <dave@davec.name> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew - -import ( - "bytes" - "fmt" - "io" - "reflect" - "sort" - "strconv" -) - -// Some constants in the form of bytes to avoid string overhead. This mirrors -// the technique used in the fmt package. -var ( - panicBytes = []byte("(PANIC=") - plusBytes = []byte("+") - iBytes = []byte("i") - trueBytes = []byte("true") - falseBytes = []byte("false") - interfaceBytes = []byte("(interface {})") - commaNewlineBytes = []byte(",\n") - newlineBytes = []byte("\n") - openBraceBytes = []byte("{") - openBraceNewlineBytes = []byte("{\n") - closeBraceBytes = []byte("}") - asteriskBytes = []byte("*") - colonBytes = []byte(":") - colonSpaceBytes = []byte(": ") - openParenBytes = []byte("(") - closeParenBytes = []byte(")") - spaceBytes = []byte(" ") - pointerChainBytes = []byte("->") - nilAngleBytes = []byte("<nil>") - maxNewlineBytes = []byte("<max depth reached>\n") - maxShortBytes = []byte("<max>") - circularBytes = []byte("<already shown>") - circularShortBytes = []byte("<shown>") - invalidAngleBytes = []byte("<invalid>") - openBracketBytes = []byte("[") - closeBracketBytes = []byte("]") - percentBytes = []byte("%") - precisionBytes = []byte(".") - openAngleBytes = []byte("<") - closeAngleBytes = []byte(">") - openMapBytes = []byte("map[") - closeMapBytes = []byte("]") - lenEqualsBytes = []byte("len=") - capEqualsBytes = []byte("cap=") -) - -// hexDigits is used to map a decimal value to a hex digit. -var hexDigits = "0123456789abcdef" - -// catchPanic handles any panics that might occur during the handleMethods -// calls. -func catchPanic(w io.Writer, v reflect.Value) { - if err := recover(); err != nil { - w.Write(panicBytes) - fmt.Fprintf(w, "%v", err) - w.Write(closeParenBytes) - } -} - -// handleMethods attempts to call the Error and String methods on the underlying -// type the passed reflect.Value represents and outputes the result to Writer w. -// -// It handles panics in any called methods by catching and displaying the error -// as the formatted value. -func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) { - // We need an interface to check if the type implements the error or - // Stringer interface. However, the reflect package won't give us an - // interface on certain things like unexported struct fields in order - // to enforce visibility rules. We use unsafe, when it's available, - // to bypass these restrictions since this package does not mutate the - // values. - if !v.CanInterface() { - if UnsafeDisabled { - return false - } - - v = unsafeReflectValue(v) - } - - // Choose whether or not to do error and Stringer interface lookups against - // the base type or a pointer to the base type depending on settings. - // Technically calling one of these methods with a pointer receiver can - // mutate the value, however, types which choose to satisify an error or - // Stringer interface with a pointer receiver should not be mutating their - // state inside these interface methods. - if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() { - v = unsafeReflectValue(v) - } - if v.CanAddr() { - v = v.Addr() - } - - // Is it an error or Stringer? - switch iface := v.Interface().(type) { - case error: - defer catchPanic(w, v) - if cs.ContinueOnMethod { - w.Write(openParenBytes) - w.Write([]byte(iface.Error())) - w.Write(closeParenBytes) - w.Write(spaceBytes) - return false - } - - w.Write([]byte(iface.Error())) - return true - - case fmt.Stringer: - defer catchPanic(w, v) - if cs.ContinueOnMethod { - w.Write(openParenBytes) - w.Write([]byte(iface.String())) - w.Write(closeParenBytes) - w.Write(spaceBytes) - return false - } - w.Write([]byte(iface.String())) - return true - } - return false -} - -// printBool outputs a boolean value as true or false to Writer w. -func printBool(w io.Writer, val bool) { - if val { - w.Write(trueBytes) - } else { - w.Write(falseBytes) - } -} - -// printInt outputs a signed integer value to Writer w. -func printInt(w io.Writer, val int64, base int) { - w.Write([]byte(strconv.FormatInt(val, base))) -} - -// printUint outputs an unsigned integer value to Writer w. -func printUint(w io.Writer, val uint64, base int) { - w.Write([]byte(strconv.FormatUint(val, base))) -} - -// printFloat outputs a floating point value using the specified precision, -// which is expected to be 32 or 64bit, to Writer w. -func printFloat(w io.Writer, val float64, precision int) { - w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision))) -} - -// printComplex outputs a complex value using the specified float precision -// for the real and imaginary parts to Writer w. -func printComplex(w io.Writer, c complex128, floatPrecision int) { - r := real(c) - w.Write(openParenBytes) - w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision))) - i := imag(c) - if i >= 0 { - w.Write(plusBytes) - } - w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision))) - w.Write(iBytes) - w.Write(closeParenBytes) -} - -// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x' -// prefix to Writer w. -func printHexPtr(w io.Writer, p uintptr) { - // Null pointer. - num := uint64(p) - if num == 0 { - w.Write(nilAngleBytes) - return - } - - // Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix - buf := make([]byte, 18) - - // It's simpler to construct the hex string right to left. - base := uint64(16) - i := len(buf) - 1 - for num >= base { - buf[i] = hexDigits[num%base] - num /= base - i-- - } - buf[i] = hexDigits[num] - - // Add '0x' prefix. - i-- - buf[i] = 'x' - i-- - buf[i] = '0' - - // Strip unused leading bytes. - buf = buf[i:] - w.Write(buf) -} - -// valuesSorter implements sort.Interface to allow a slice of reflect.Value -// elements to be sorted. -type valuesSorter struct { - values []reflect.Value - strings []string // either nil or same len and values - cs *ConfigState -} - -// newValuesSorter initializes a valuesSorter instance, which holds a set of -// surrogate keys on which the data should be sorted. It uses flags in -// ConfigState to decide if and how to populate those surrogate keys. -func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface { - vs := &valuesSorter{values: values, cs: cs} - if canSortSimply(vs.values[0].Kind()) { - return vs - } - if !cs.DisableMethods { - vs.strings = make([]string, len(values)) - for i := range vs.values { - b := bytes.Buffer{} - if !handleMethods(cs, &b, vs.values[i]) { - vs.strings = nil - break - } - vs.strings[i] = b.String() - } - } - if vs.strings == nil && cs.SpewKeys { - vs.strings = make([]string, len(values)) - for i := range vs.values { - vs.strings[i] = Sprintf("%#v", vs.values[i].Interface()) - } - } - return vs -} - -// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted -// directly, or whether it should be considered for sorting by surrogate keys -// (if the ConfigState allows it). -func canSortSimply(kind reflect.Kind) bool { - // This switch parallels valueSortLess, except for the default case. - switch kind { - case reflect.Bool: - return true - case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: - return true - case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: - return true - case reflect.Float32, reflect.Float64: - return true - case reflect.String: - return true - case reflect.Uintptr: - return true - case reflect.Array: - return true - } - return false -} - -// Len returns the number of values in the slice. It is part of the -// sort.Interface implementation. -func (s *valuesSorter) Len() int { - return len(s.values) -} - -// Swap swaps the values at the passed indices. It is part of the -// sort.Interface implementation. -func (s *valuesSorter) Swap(i, j int) { - s.values[i], s.values[j] = s.values[j], s.values[i] - if s.strings != nil { - s.strings[i], s.strings[j] = s.strings[j], s.strings[i] - } -} - -// valueSortLess returns whether the first value should sort before the second -// value. It is used by valueSorter.Less as part of the sort.Interface -// implementation. -func valueSortLess(a, b reflect.Value) bool { - switch a.Kind() { - case reflect.Bool: - return !a.Bool() && b.Bool() - case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: - return a.Int() < b.Int() - case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: - return a.Uint() < b.Uint() - case reflect.Float32, reflect.Float64: - return a.Float() < b.Float() - case reflect.String: - return a.String() < b.String() - case reflect.Uintptr: - return a.Uint() < b.Uint() - case reflect.Array: - // Compare the contents of both arrays. - l := a.Len() - for i := 0; i < l; i++ { - av := a.Index(i) - bv := b.Index(i) - if av.Interface() == bv.Interface() { - continue - } - return valueSortLess(av, bv) - } - } - return a.String() < b.String() -} - -// Less returns whether the value at index i should sort before the -// value at index j. It is part of the sort.Interface implementation. -func (s *valuesSorter) Less(i, j int) bool { - if s.strings == nil { - return valueSortLess(s.values[i], s.values[j]) - } - return s.strings[i] < s.strings[j] -} - -// sortValues is a sort function that handles both native types and any type that -// can be converted to error or Stringer. Other inputs are sorted according to -// their Value.String() value to ensure display stability. -func sortValues(values []reflect.Value, cs *ConfigState) { - if len(values) == 0 { - return - } - sort.Sort(newValuesSorter(values, cs)) -} diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/common_test.go b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/common_test.go deleted file mode 100644 index 0f5ce47..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/common_test.go +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins <dave@davec.name> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew_test - -import ( - "fmt" - "reflect" - "testing" - - "github.com/davecgh/go-spew/spew" -) - -// custom type to test Stinger interface on non-pointer receiver. -type stringer string - -// String implements the Stringer interface for testing invocation of custom -// stringers on types with non-pointer receivers. -func (s stringer) String() string { - return "stringer " + string(s) -} - -// custom type to test Stinger interface on pointer receiver. -type pstringer string - -// String implements the Stringer interface for testing invocation of custom -// stringers on types with only pointer receivers. -func (s *pstringer) String() string { - return "stringer " + string(*s) -} - -// xref1 and xref2 are cross referencing structs for testing circular reference -// detection. -type xref1 struct { - ps2 *xref2 -} -type xref2 struct { - ps1 *xref1 -} - -// indirCir1, indirCir2, and indirCir3 are used to generate an indirect circular -// reference for testing detection. -type indirCir1 struct { - ps2 *indirCir2 -} -type indirCir2 struct { - ps3 *indirCir3 -} -type indirCir3 struct { - ps1 *indirCir1 -} - -// embed is used to test embedded structures. -type embed struct { - a string -} - -// embedwrap is used to test embedded structures. -type embedwrap struct { - *embed - e *embed -} - -// panicer is used to intentionally cause a panic for testing spew properly -// handles them -type panicer int - -func (p panicer) String() string { - panic("test panic") -} - -// customError is used to test custom error interface invocation. -type customError int - -func (e customError) Error() string { - return fmt.Sprintf("error: %d", int(e)) -} - -// stringizeWants converts a slice of wanted test output into a format suitable -// for a test error message. -func stringizeWants(wants []string) string { - s := "" - for i, want := range wants { - if i > 0 { - s += fmt.Sprintf("want%d: %s", i+1, want) - } else { - s += "want: " + want - } - } - return s -} - -// testFailed returns whether or not a test failed by checking if the result -// of the test is in the slice of wanted strings. -func testFailed(result string, wants []string) bool { - for _, want := range wants { - if result == want { - return false - } - } - return true -} - -type sortableStruct struct { - x int -} - -func (ss sortableStruct) String() string { - return fmt.Sprintf("ss.%d", ss.x) -} - -type unsortableStruct struct { - x int -} - -type sortTestCase struct { - input []reflect.Value - expected []reflect.Value -} - -func helpTestSortValues(tests []sortTestCase, cs *spew.ConfigState, t *testing.T) { - getInterfaces := func(values []reflect.Value) []interface{} { - interfaces := []interface{}{} - for _, v := range values { - interfaces = append(interfaces, v.Interface()) - } - return interfaces - } - - for _, test := range tests { - spew.SortValues(test.input, cs) - // reflect.DeepEqual cannot really make sense of reflect.Value, - // probably because of all the pointer tricks. For instance, - // v(2.0) != v(2.0) on a 32-bits system. Turn them into interface{} - // instead. - input := getInterfaces(test.input) - expected := getInterfaces(test.expected) - if !reflect.DeepEqual(input, expected) { - t.Errorf("Sort mismatch:\n %v != %v", input, expected) - } - } -} - -// TestSortValues ensures the sort functionality for relect.Value based sorting -// works as intended. -func TestSortValues(t *testing.T) { - v := reflect.ValueOf - - a := v("a") - b := v("b") - c := v("c") - embedA := v(embed{"a"}) - embedB := v(embed{"b"}) - embedC := v(embed{"c"}) - tests := []sortTestCase{ - // No values. - { - []reflect.Value{}, - []reflect.Value{}, - }, - // Bools. - { - []reflect.Value{v(false), v(true), v(false)}, - []reflect.Value{v(false), v(false), v(true)}, - }, - // Ints. - { - []reflect.Value{v(2), v(1), v(3)}, - []reflect.Value{v(1), v(2), v(3)}, - }, - // Uints. - { - []reflect.Value{v(uint8(2)), v(uint8(1)), v(uint8(3))}, - []reflect.Value{v(uint8(1)), v(uint8(2)), v(uint8(3))}, - }, - // Floats. - { - []reflect.Value{v(2.0), v(1.0), v(3.0)}, - []reflect.Value{v(1.0), v(2.0), v(3.0)}, - }, - // Strings. - { - []reflect.Value{b, a, c}, - []reflect.Value{a, b, c}, - }, - // Array - { - []reflect.Value{v([3]int{3, 2, 1}), v([3]int{1, 3, 2}), v([3]int{1, 2, 3})}, - []reflect.Value{v([3]int{1, 2, 3}), v([3]int{1, 3, 2}), v([3]int{3, 2, 1})}, - }, - // Uintptrs. - { - []reflect.Value{v(uintptr(2)), v(uintptr(1)), v(uintptr(3))}, - []reflect.Value{v(uintptr(1)), v(uintptr(2)), v(uintptr(3))}, - }, - // SortableStructs. - { - // Note: not sorted - DisableMethods is set. - []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, - []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, - }, - // UnsortableStructs. - { - // Note: not sorted - SpewKeys is false. - []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, - []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, - }, - // Invalid. - { - []reflect.Value{embedB, embedA, embedC}, - []reflect.Value{embedB, embedA, embedC}, - }, - } - cs := spew.ConfigState{DisableMethods: true, SpewKeys: false} - helpTestSortValues(tests, &cs, t) -} - -// TestSortValuesWithMethods ensures the sort functionality for relect.Value -// based sorting works as intended when using string methods. -func TestSortValuesWithMethods(t *testing.T) { - v := reflect.ValueOf - - a := v("a") - b := v("b") - c := v("c") - tests := []sortTestCase{ - // Ints. - { - []reflect.Value{v(2), v(1), v(3)}, - []reflect.Value{v(1), v(2), v(3)}, - }, - // Strings. - { - []reflect.Value{b, a, c}, - []reflect.Value{a, b, c}, - }, - // SortableStructs. - { - []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, - []reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})}, - }, - // UnsortableStructs. - { - // Note: not sorted - SpewKeys is false. - []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, - []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, - }, - } - cs := spew.ConfigState{DisableMethods: false, SpewKeys: false} - helpTestSortValues(tests, &cs, t) -} - -// TestSortValuesWithSpew ensures the sort functionality for relect.Value -// based sorting works as intended when using spew to stringify keys. -func TestSortValuesWithSpew(t *testing.T) { - v := reflect.ValueOf - - a := v("a") - b := v("b") - c := v("c") - tests := []sortTestCase{ - // Ints. - { - []reflect.Value{v(2), v(1), v(3)}, - []reflect.Value{v(1), v(2), v(3)}, - }, - // Strings. - { - []reflect.Value{b, a, c}, - []reflect.Value{a, b, c}, - }, - // SortableStructs. - { - []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, - []reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})}, - }, - // UnsortableStructs. - { - []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, - []reflect.Value{v(unsortableStruct{1}), v(unsortableStruct{2}), v(unsortableStruct{3})}, - }, - } - cs := spew.ConfigState{DisableMethods: true, SpewKeys: true} - helpTestSortValues(tests, &cs, t) -} diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/config.go b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/config.go deleted file mode 100644 index 2e3d22f..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/config.go +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins <dave@davec.name> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew - -import ( - "bytes" - "fmt" - "io" - "os" -) - -// ConfigState houses the configuration options used by spew to format and -// display values. There is a global instance, Config, that is used to control -// all top-level Formatter and Dump functionality. Each ConfigState instance -// provides methods equivalent to the top-level functions. -// -// The zero value for ConfigState provides no indentation. You would typically -// want to set it to a space or a tab. -// -// Alternatively, you can use NewDefaultConfig to get a ConfigState instance -// with default settings. See the documentation of NewDefaultConfig for default -// values. -type ConfigState struct { - // Indent specifies the string to use for each indentation level. The - // global config instance that all top-level functions use set this to a - // single space by default. If you would like more indentation, you might - // set this to a tab with "\t" or perhaps two spaces with " ". - Indent string - - // MaxDepth controls the maximum number of levels to descend into nested - // data structures. The default, 0, means there is no limit. - // - // NOTE: Circular data structures are properly detected, so it is not - // necessary to set this value unless you specifically want to limit deeply - // nested data structures. - MaxDepth int - - // DisableMethods specifies whether or not error and Stringer interfaces are - // invoked for types that implement them. - DisableMethods bool - - // DisablePointerMethods specifies whether or not to check for and invoke - // error and Stringer interfaces on types which only accept a pointer - // receiver when the current type is not a pointer. - // - // NOTE: This might be an unsafe action since calling one of these methods - // with a pointer receiver could technically mutate the value, however, - // in practice, types which choose to satisify an error or Stringer - // interface with a pointer receiver should not be mutating their state - // inside these interface methods. As a result, this option relies on - // access to the unsafe package, so it will not have any effect when - // running in environments without access to the unsafe package such as - // Google App Engine or with the "safe" build tag specified. - DisablePointerMethods bool - - // DisablePointerAddresses specifies whether to disable the printing of - // pointer addresses. This is useful when diffing data structures in tests. - DisablePointerAddresses bool - - // DisableCapacities specifies whether to disable the printing of capacities - // for arrays, slices, maps and channels. This is useful when diffing - // data structures in tests. - DisableCapacities bool - - // ContinueOnMethod specifies whether or not recursion should continue once - // a custom error or Stringer interface is invoked. The default, false, - // means it will print the results of invoking the custom error or Stringer - // interface and return immediately instead of continuing to recurse into - // the internals of the data type. - // - // NOTE: This flag does not have any effect if method invocation is disabled - // via the DisableMethods or DisablePointerMethods options. - ContinueOnMethod bool - - // SortKeys specifies map keys should be sorted before being printed. Use - // this to have a more deterministic, diffable output. Note that only - // native types (bool, int, uint, floats, uintptr and string) and types - // that support the error or Stringer interfaces (if methods are - // enabled) are supported, with other types sorted according to the - // reflect.Value.String() output which guarantees display stability. - SortKeys bool - - // SpewKeys specifies that, as a last resort attempt, map keys should - // be spewed to strings and sorted by those strings. This is only - // considered if SortKeys is true. - SpewKeys bool -} - -// Config is the active configuration of the top-level functions. -// The configuration can be changed by modifying the contents of spew.Config. -var Config = ConfigState{Indent: " "} - -// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the formatted string as a value that satisfies error. See NewFormatter -// for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) { - return fmt.Errorf(format, c.convertArgs(a)...) -} - -// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) { - return fmt.Fprint(w, c.convertArgs(a)...) -} - -// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { - return fmt.Fprintf(w, format, c.convertArgs(a)...) -} - -// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it -// passed with a Formatter interface returned by c.NewFormatter. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { - return fmt.Fprintln(w, c.convertArgs(a)...) -} - -// Print is a wrapper for fmt.Print that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Print(c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Print(a ...interface{}) (n int, err error) { - return fmt.Print(c.convertArgs(a)...) -} - -// Printf is a wrapper for fmt.Printf that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) { - return fmt.Printf(format, c.convertArgs(a)...) -} - -// Println is a wrapper for fmt.Println that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Println(c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Println(a ...interface{}) (n int, err error) { - return fmt.Println(c.convertArgs(a)...) -} - -// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the resulting string. See NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Sprint(a ...interface{}) string { - return fmt.Sprint(c.convertArgs(a)...) -} - -// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the resulting string. See NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Sprintf(format string, a ...interface{}) string { - return fmt.Sprintf(format, c.convertArgs(a)...) -} - -// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it -// were passed with a Formatter interface returned by c.NewFormatter. It -// returns the resulting string. See NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Sprintln(a ...interface{}) string { - return fmt.Sprintln(c.convertArgs(a)...) -} - -/* -NewFormatter returns a custom formatter that satisfies the fmt.Formatter -interface. As a result, it integrates cleanly with standard fmt package -printing functions. The formatter is useful for inline printing of smaller data -types similar to the standard %v format specifier. - -The custom formatter only responds to the %v (most compact), %+v (adds pointer -addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb -combinations. Any other verbs such as %x and %q will be sent to the the -standard fmt package for formatting. In addition, the custom formatter ignores -the width and precision arguments (however they will still work on the format -specifiers not handled by the custom formatter). - -Typically this function shouldn't be called directly. It is much easier to make -use of the custom formatter by calling one of the convenience functions such as -c.Printf, c.Println, or c.Printf. -*/ -func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter { - return newFormatter(c, v) -} - -// Fdump formats and displays the passed arguments to io.Writer w. It formats -// exactly the same as Dump. -func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) { - fdump(c, w, a...) -} - -/* -Dump displays the passed parameters to standard out with newlines, customizable -indentation, and additional debug information such as complete types and all -pointer addresses used to indirect to the final value. It provides the -following features over the built-in printing facilities provided by the fmt -package: - - * Pointers are dereferenced and followed - * Circular data structures are detected and handled properly - * Custom Stringer/error interfaces are optionally invoked, including - on unexported types - * Custom types which only implement the Stringer/error interfaces via - a pointer receiver are optionally invoked when passing non-pointer - variables - * Byte arrays and slices are dumped like the hexdump -C command which - includes offsets, byte values in hex, and ASCII output - -The configuration options are controlled by modifying the public members -of c. See ConfigState for options documentation. - -See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to -get the formatted result as a string. -*/ -func (c *ConfigState) Dump(a ...interface{}) { - fdump(c, os.Stdout, a...) -} - -// Sdump returns a string with the passed arguments formatted exactly the same -// as Dump. -func (c *ConfigState) Sdump(a ...interface{}) string { - var buf bytes.Buffer - fdump(c, &buf, a...) - return buf.String() -} - -// convertArgs accepts a slice of arguments and returns a slice of the same -// length with each argument converted to a spew Formatter interface using -// the ConfigState associated with s. -func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) { - formatters = make([]interface{}, len(args)) - for index, arg := range args { - formatters[index] = newFormatter(c, arg) - } - return formatters -} - -// NewDefaultConfig returns a ConfigState with the following default settings. -// -// Indent: " " -// MaxDepth: 0 -// DisableMethods: false -// DisablePointerMethods: false -// ContinueOnMethod: false -// SortKeys: false -func NewDefaultConfig() *ConfigState { - return &ConfigState{Indent: " "} -} diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/doc.go b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/doc.go deleted file mode 100644 index aacaac6..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/doc.go +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins <dave@davec.name> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* -Package spew implements a deep pretty printer for Go data structures to aid in -debugging. - -A quick overview of the additional features spew provides over the built-in -printing facilities for Go data types are as follows: - - * Pointers are dereferenced and followed - * Circular data structures are detected and handled properly - * Custom Stringer/error interfaces are optionally invoked, including - on unexported types - * Custom types which only implement the Stringer/error interfaces via - a pointer receiver are optionally invoked when passing non-pointer - variables - * Byte arrays and slices are dumped like the hexdump -C command which - includes offsets, byte values in hex, and ASCII output (only when using - Dump style) - -There are two different approaches spew allows for dumping Go data structures: - - * Dump style which prints with newlines, customizable indentation, - and additional debug information such as types and all pointer addresses - used to indirect to the final value - * A custom Formatter interface that integrates cleanly with the standard fmt - package and replaces %v, %+v, %#v, and %#+v to provide inline printing - similar to the default %v while providing the additional functionality - outlined above and passing unsupported format verbs such as %x and %q - along to fmt - -Quick Start - -This section demonstrates how to quickly get started with spew. See the -sections below for further details on formatting and configuration options. - -To dump a variable with full newlines, indentation, type, and pointer -information use Dump, Fdump, or Sdump: - spew.Dump(myVar1, myVar2, ...) - spew.Fdump(someWriter, myVar1, myVar2, ...) - str := spew.Sdump(myVar1, myVar2, ...) - -Alternatively, if you would prefer to use format strings with a compacted inline -printing style, use the convenience wrappers Printf, Fprintf, etc with -%v (most compact), %+v (adds pointer addresses), %#v (adds types), or -%#+v (adds types and pointer addresses): - spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) - spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) - spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) - spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) - -Configuration Options - -Configuration of spew is handled by fields in the ConfigState type. For -convenience, all of the top-level functions use a global state available -via the spew.Config global. - -It is also possible to create a ConfigState instance that provides methods -equivalent to the top-level functions. This allows concurrent configuration -options. See the ConfigState documentation for more details. - -The following configuration options are available: - * Indent - String to use for each indentation level for Dump functions. - It is a single space by default. A popular alternative is "\t". - - * MaxDepth - Maximum number of levels to descend into nested data structures. - There is no limit by default. - - * DisableMethods - Disables invocation of error and Stringer interface methods. - Method invocation is enabled by default. - - * DisablePointerMethods - Disables invocation of error and Stringer interface methods on types - which only accept pointer receivers from non-pointer variables. - Pointer method invocation is enabled by default. - - * DisablePointerAddresses - DisablePointerAddresses specifies whether to disable the printing of - pointer addresses. This is useful when diffing data structures in tests. - - * DisableCapacities - DisableCapacities specifies whether to disable the printing of - capacities for arrays, slices, maps and channels. This is useful when - diffing data structures in tests. - - * ContinueOnMethod - Enables recursion into types after invoking error and Stringer interface - methods. Recursion after method invocation is disabled by default. - - * SortKeys - Specifies map keys should be sorted before being printed. Use - this to have a more deterministic, diffable output. Note that - only native types (bool, int, uint, floats, uintptr and string) - and types which implement error or Stringer interfaces are - supported with other types sorted according to the - reflect.Value.String() output which guarantees display - stability. Natural map order is used by default. - - * SpewKeys - Specifies that, as a last resort attempt, map keys should be - spewed to strings and sorted by those strings. This is only - considered if SortKeys is true. - -Dump Usage - -Simply call spew.Dump with a list of variables you want to dump: - - spew.Dump(myVar1, myVar2, ...) - -You may also call spew.Fdump if you would prefer to output to an arbitrary -io.Writer. For example, to dump to standard error: - - spew.Fdump(os.Stderr, myVar1, myVar2, ...) - -A third option is to call spew.Sdump to get the formatted output as a string: - - str := spew.Sdump(myVar1, myVar2, ...) - -Sample Dump Output - -See the Dump example for details on the setup of the types and variables being -shown here. - - (main.Foo) { - unexportedField: (*main.Bar)(0xf84002e210)({ - flag: (main.Flag) flagTwo, - data: (uintptr) <nil> - }), - ExportedField: (map[interface {}]interface {}) (len=1) { - (string) (len=3) "one": (bool) true - } - } - -Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C -command as shown. - ([]uint8) (len=32 cap=32) { - 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | - 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| - 00000020 31 32 |12| - } - -Custom Formatter - -Spew provides a custom formatter that implements the fmt.Formatter interface -so that it integrates cleanly with standard fmt package printing functions. The -formatter is useful for inline printing of smaller data types similar to the -standard %v format specifier. - -The custom formatter only responds to the %v (most compact), %+v (adds pointer -addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb -combinations. Any other verbs such as %x and %q will be sent to the the -standard fmt package for formatting. In addition, the custom formatter ignores -the width and precision arguments (however they will still work on the format -specifiers not handled by the custom formatter). - -Custom Formatter Usage - -The simplest way to make use of the spew custom formatter is to call one of the -convenience functions such as spew.Printf, spew.Println, or spew.Printf. The -functions have syntax you are most likely already familiar with: - - spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) - spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) - spew.Println(myVar, myVar2) - spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) - spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) - -See the Index for the full list convenience functions. - -Sample Formatter Output - -Double pointer to a uint8: - %v: <**>5 - %+v: <**>(0xf8400420d0->0xf8400420c8)5 - %#v: (**uint8)5 - %#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5 - -Pointer to circular struct with a uint8 field and a pointer to itself: - %v: <*>{1 <*><shown>} - %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)<shown>} - %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)<shown>} - %#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)<shown>} - -See the Printf example for details on the setup of variables being shown -here. - -Errors - -Since it is possible for custom Stringer/error interfaces to panic, spew -detects them and handles them internally by printing the panic information -inline with the output. Since spew is intended to provide deep pretty printing -capabilities on structures, it intentionally does not return any errors. -*/ -package spew diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go deleted file mode 100644 index f78d89f..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go +++ /dev/null @@ -1,509 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins <dave@davec.name> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew - -import ( - "bytes" - "encoding/hex" - "fmt" - "io" - "os" - "reflect" - "regexp" - "strconv" - "strings" -) - -var ( - // uint8Type is a reflect.Type representing a uint8. It is used to - // convert cgo types to uint8 slices for hexdumping. - uint8Type = reflect.TypeOf(uint8(0)) - - // cCharRE is a regular expression that matches a cgo char. - // It is used to detect character arrays to hexdump them. - cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`) - - // cUnsignedCharRE is a regular expression that matches a cgo unsigned - // char. It is used to detect unsigned character arrays to hexdump - // them. - cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`) - - // cUint8tCharRE is a regular expression that matches a cgo uint8_t. - // It is used to detect uint8_t arrays to hexdump them. - cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`) -) - -// dumpState contains information about the state of a dump operation. -type dumpState struct { - w io.Writer - depth int - pointers map[uintptr]int - ignoreNextType bool - ignoreNextIndent bool - cs *ConfigState -} - -// indent performs indentation according to the depth level and cs.Indent -// option. -func (d *dumpState) indent() { - if d.ignoreNextIndent { - d.ignoreNextIndent = false - return - } - d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth)) -} - -// unpackValue returns values inside of non-nil interfaces when possible. -// This is useful for data types like structs, arrays, slices, and maps which -// can contain varying types packed inside an interface. -func (d *dumpState) unpackValue(v reflect.Value) reflect.Value { - if v.Kind() == reflect.Interface && !v.IsNil() { - v = v.Elem() - } - return v -} - -// dumpPtr handles formatting of pointers by indirecting them as necessary. -func (d *dumpState) dumpPtr(v reflect.Value) { - // Remove pointers at or below the current depth from map used to detect - // circular refs. - for k, depth := range d.pointers { - if depth >= d.depth { - delete(d.pointers, k) - } - } - - // Keep list of all dereferenced pointers to show later. - pointerChain := make([]uintptr, 0) - - // Figure out how many levels of indirection there are by dereferencing - // pointers and unpacking interfaces down the chain while detecting circular - // references. - nilFound := false - cycleFound := false - indirects := 0 - ve := v - for ve.Kind() == reflect.Ptr { - if ve.IsNil() { - nilFound = true - break - } - indirects++ - addr := ve.Pointer() - pointerChain = append(pointerChain, addr) - if pd, ok := d.pointers[addr]; ok && pd < d.depth { - cycleFound = true - indirects-- - break - } - d.pointers[addr] = d.depth - - ve = ve.Elem() - if ve.Kind() == reflect.Interface { - if ve.IsNil() { - nilFound = true - break - } - ve = ve.Elem() - } - } - - // Display type information. - d.w.Write(openParenBytes) - d.w.Write(bytes.Repeat(asteriskBytes, indirects)) - d.w.Write([]byte(ve.Type().String())) - d.w.Write(closeParenBytes) - - // Display pointer information. - if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 { - d.w.Write(openParenBytes) - for i, addr := range pointerChain { - if i > 0 { - d.w.Write(pointerChainBytes) - } - printHexPtr(d.w, addr) - } - d.w.Write(closeParenBytes) - } - - // Display dereferenced value. - d.w.Write(openParenBytes) - switch { - case nilFound: - d.w.Write(nilAngleBytes) - - case cycleFound: - d.w.Write(circularBytes) - - default: - d.ignoreNextType = true - d.dump(ve) - } - d.w.Write(closeParenBytes) -} - -// dumpSlice handles formatting of arrays and slices. Byte (uint8 under -// reflection) arrays and slices are dumped in hexdump -C fashion. -func (d *dumpState) dumpSlice(v reflect.Value) { - // Determine whether this type should be hex dumped or not. Also, - // for types which should be hexdumped, try to use the underlying data - // first, then fall back to trying to convert them to a uint8 slice. - var buf []uint8 - doConvert := false - doHexDump := false - numEntries := v.Len() - if numEntries > 0 { - vt := v.Index(0).Type() - vts := vt.String() - switch { - // C types that need to be converted. - case cCharRE.MatchString(vts): - fallthrough - case cUnsignedCharRE.MatchString(vts): - fallthrough - case cUint8tCharRE.MatchString(vts): - doConvert = true - - // Try to use existing uint8 slices and fall back to converting - // and copying if that fails. - case vt.Kind() == reflect.Uint8: - // We need an addressable interface to convert the type - // to a byte slice. However, the reflect package won't - // give us an interface on certain things like - // unexported struct fields in order to enforce - // visibility rules. We use unsafe, when available, to - // bypass these restrictions since this package does not - // mutate the values. - vs := v - if !vs.CanInterface() || !vs.CanAddr() { - vs = unsafeReflectValue(vs) - } - if !UnsafeDisabled { - vs = vs.Slice(0, numEntries) - - // Use the existing uint8 slice if it can be - // type asserted. - iface := vs.Interface() - if slice, ok := iface.([]uint8); ok { - buf = slice - doHexDump = true - break - } - } - - // The underlying data needs to be converted if it can't - // be type asserted to a uint8 slice. - doConvert = true - } - - // Copy and convert the underlying type if needed. - if doConvert && vt.ConvertibleTo(uint8Type) { - // Convert and copy each element into a uint8 byte - // slice. - buf = make([]uint8, numEntries) - for i := 0; i < numEntries; i++ { - vv := v.Index(i) - buf[i] = uint8(vv.Convert(uint8Type).Uint()) - } - doHexDump = true - } - } - - // Hexdump the entire slice as needed. - if doHexDump { - indent := strings.Repeat(d.cs.Indent, d.depth) - str := indent + hex.Dump(buf) - str = strings.Replace(str, "\n", "\n"+indent, -1) - str = strings.TrimRight(str, d.cs.Indent) - d.w.Write([]byte(str)) - return - } - - // Recursively call dump for each item. - for i := 0; i < numEntries; i++ { - d.dump(d.unpackValue(v.Index(i))) - if i < (numEntries - 1) { - d.w.Write(commaNewlineBytes) - } else { - d.w.Write(newlineBytes) - } - } -} - -// dump is the main workhorse for dumping a value. It uses the passed reflect -// value to figure out what kind of object we are dealing with and formats it -// appropriately. It is a recursive function, however circular data structures -// are detected and handled properly. -func (d *dumpState) dump(v reflect.Value) { - // Handle invalid reflect values immediately. - kind := v.Kind() - if kind == reflect.Invalid { - d.w.Write(invalidAngleBytes) - return - } - - // Handle pointers specially. - if kind == reflect.Ptr { - d.indent() - d.dumpPtr(v) - return - } - - // Print type information unless already handled elsewhere. - if !d.ignoreNextType { - d.indent() - d.w.Write(openParenBytes) - d.w.Write([]byte(v.Type().String())) - d.w.Write(closeParenBytes) - d.w.Write(spaceBytes) - } - d.ignoreNextType = false - - // Display length and capacity if the built-in len and cap functions - // work with the value's kind and the len/cap itself is non-zero. - valueLen, valueCap := 0, 0 - switch v.Kind() { - case reflect.Array, reflect.Slice, reflect.Chan: - valueLen, valueCap = v.Len(), v.Cap() - case reflect.Map, reflect.String: - valueLen = v.Len() - } - if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 { - d.w.Write(openParenBytes) - if valueLen != 0 { - d.w.Write(lenEqualsBytes) - printInt(d.w, int64(valueLen), 10) - } - if !d.cs.DisableCapacities && valueCap != 0 { - if valueLen != 0 { - d.w.Write(spaceBytes) - } - d.w.Write(capEqualsBytes) - printInt(d.w, int64(valueCap), 10) - } - d.w.Write(closeParenBytes) - d.w.Write(spaceBytes) - } - - // Call Stringer/error interfaces if they exist and the handle methods flag - // is enabled - if !d.cs.DisableMethods { - if (kind != reflect.Invalid) && (kind != reflect.Interface) { - if handled := handleMethods(d.cs, d.w, v); handled { - return - } - } - } - - switch kind { - case reflect.Invalid: - // Do nothing. We should never get here since invalid has already - // been handled above. - - case reflect.Bool: - printBool(d.w, v.Bool()) - - case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: - printInt(d.w, v.Int(), 10) - - case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: - printUint(d.w, v.Uint(), 10) - - case reflect.Float32: - printFloat(d.w, v.Float(), 32) - - case reflect.Float64: - printFloat(d.w, v.Float(), 64) - - case reflect.Complex64: - printComplex(d.w, v.Complex(), 32) - - case reflect.Complex128: - printComplex(d.w, v.Complex(), 64) - - case reflect.Slice: - if v.IsNil() { - d.w.Write(nilAngleBytes) - break - } - fallthrough - - case reflect.Array: - d.w.Write(openBraceNewlineBytes) - d.depth++ - if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { - d.indent() - d.w.Write(maxNewlineBytes) - } else { - d.dumpSlice(v) - } - d.depth-- - d.indent() - d.w.Write(closeBraceBytes) - - case reflect.String: - d.w.Write([]byte(strconv.Quote(v.String()))) - - case reflect.Interface: - // The only time we should get here is for nil interfaces due to - // unpackValue calls. - if v.IsNil() { - d.w.Write(nilAngleBytes) - } - - case reflect.Ptr: - // Do nothing. We should never get here since pointers have already - // been handled above. - - case reflect.Map: - // nil maps should be indicated as different than empty maps - if v.IsNil() { - d.w.Write(nilAngleBytes) - break - } - - d.w.Write(openBraceNewlineBytes) - d.depth++ - if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { - d.indent() - d.w.Write(maxNewlineBytes) - } else { - numEntries := v.Len() - keys := v.MapKeys() - if d.cs.SortKeys { - sortValues(keys, d.cs) - } - for i, key := range keys { - d.dump(d.unpackValue(key)) - d.w.Write(colonSpaceBytes) - d.ignoreNextIndent = true - d.dump(d.unpackValue(v.MapIndex(key))) - if i < (numEntries - 1) { - d.w.Write(commaNewlineBytes) - } else { - d.w.Write(newlineBytes) - } - } - } - d.depth-- - d.indent() - d.w.Write(closeBraceBytes) - - case reflect.Struct: - d.w.Write(openBraceNewlineBytes) - d.depth++ - if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { - d.indent() - d.w.Write(maxNewlineBytes) - } else { - vt := v.Type() - numFields := v.NumField() - for i := 0; i < numFields; i++ { - d.indent() - vtf := vt.Field(i) - d.w.Write([]byte(vtf.Name)) - d.w.Write(colonSpaceBytes) - d.ignoreNextIndent = true - d.dump(d.unpackValue(v.Field(i))) - if i < (numFields - 1) { - d.w.Write(commaNewlineBytes) - } else { - d.w.Write(newlineBytes) - } - } - } - d.depth-- - d.indent() - d.w.Write(closeBraceBytes) - - case reflect.Uintptr: - printHexPtr(d.w, uintptr(v.Uint())) - - case reflect.UnsafePointer, reflect.Chan, reflect.Func: - printHexPtr(d.w, v.Pointer()) - - // There were not any other types at the time this code was written, but - // fall back to letting the default fmt package handle it in case any new - // types are added. - default: - if v.CanInterface() { - fmt.Fprintf(d.w, "%v", v.Interface()) - } else { - fmt.Fprintf(d.w, "%v", v.String()) - } - } -} - -// fdump is a helper function to consolidate the logic from the various public -// methods which take varying writers and config states. -func fdump(cs *ConfigState, w io.Writer, a ...interface{}) { - for _, arg := range a { - if arg == nil { - w.Write(interfaceBytes) - w.Write(spaceBytes) - w.Write(nilAngleBytes) - w.Write(newlineBytes) - continue - } - - d := dumpState{w: w, cs: cs} - d.pointers = make(map[uintptr]int) - d.dump(reflect.ValueOf(arg)) - d.w.Write(newlineBytes) - } -} - -// Fdump formats and displays the passed arguments to io.Writer w. It formats -// exactly the same as Dump. -func Fdump(w io.Writer, a ...interface{}) { - fdump(&Config, w, a...) -} - -// Sdump returns a string with the passed arguments formatted exactly the same -// as Dump. -func Sdump(a ...interface{}) string { - var buf bytes.Buffer - fdump(&Config, &buf, a...) - return buf.String() -} - -/* -Dump displays the passed parameters to standard out with newlines, customizable -indentation, and additional debug information such as complete types and all -pointer addresses used to indirect to the final value. It provides the -following features over the built-in printing facilities provided by the fmt -package: - - * Pointers are dereferenced and followed - * Circular data structures are detected and handled properly - * Custom Stringer/error interfaces are optionally invoked, including - on unexported types - * Custom types which only implement the Stringer/error interfaces via - a pointer receiver are optionally invoked when passing non-pointer - variables - * Byte arrays and slices are dumped like the hexdump -C command which - includes offsets, byte values in hex, and ASCII output - -The configuration options are controlled by an exported package global, -spew.Config. See ConfigState for options documentation. - -See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to -get the formatted result as a string. -*/ -func Dump(a ...interface{}) { - fdump(&Config, os.Stdout, a...) -} diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump_test.go b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump_test.go deleted file mode 100644 index 4a31a2e..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump_test.go +++ /dev/null @@ -1,1042 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins <dave@davec.name> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* -Test Summary: -NOTE: For each test, a nil pointer, a single pointer and double pointer to the -base test element are also tested to ensure proper indirection across all types. - -- Max int8, int16, int32, int64, int -- Max uint8, uint16, uint32, uint64, uint -- Boolean true and false -- Standard complex64 and complex128 -- Array containing standard ints -- Array containing type with custom formatter on pointer receiver only -- Array containing interfaces -- Array containing bytes -- Slice containing standard float32 values -- Slice containing type with custom formatter on pointer receiver only -- Slice containing interfaces -- Slice containing bytes -- Nil slice -- Standard string -- Nil interface -- Sub-interface -- Map with string keys and int vals -- Map with custom formatter type on pointer receiver only keys and vals -- Map with interface keys and values -- Map with nil interface value -- Struct with primitives -- Struct that contains another struct -- Struct that contains custom type with Stringer pointer interface via both - exported and unexported fields -- Struct that contains embedded struct and field to same struct -- Uintptr to 0 (null pointer) -- Uintptr address of real variable -- Unsafe.Pointer to 0 (null pointer) -- Unsafe.Pointer to address of real variable -- Nil channel -- Standard int channel -- Function with no params and no returns -- Function with param and no returns -- Function with multiple params and multiple returns -- Struct that is circular through self referencing -- Structs that are circular through cross referencing -- Structs that are indirectly circular -- Type that panics in its Stringer interface -*/ - -package spew_test - -import ( - "bytes" - "fmt" - "testing" - "unsafe" - - "github.com/davecgh/go-spew/spew" -) - -// dumpTest is used to describe a test to be performed against the Dump method. -type dumpTest struct { - in interface{} - wants []string -} - -// dumpTests houses all of the tests to be performed against the Dump method. -var dumpTests = make([]dumpTest, 0) - -// addDumpTest is a helper method to append the passed input and desired result -// to dumpTests -func addDumpTest(in interface{}, wants ...string) { - test := dumpTest{in, wants} - dumpTests = append(dumpTests, test) -} - -func addIntDumpTests() { - // Max int8. - v := int8(127) - nv := (*int8)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "int8" - vs := "127" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")(<nil>)\n") - - // Max int16. - v2 := int16(32767) - nv2 := (*int16)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "int16" - v2s := "32767" - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") - addDumpTest(nv2, "(*"+v2t+")(<nil>)\n") - - // Max int32. - v3 := int32(2147483647) - nv3 := (*int32)(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "int32" - v3s := "2147483647" - addDumpTest(v3, "("+v3t+") "+v3s+"\n") - addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") - addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") - addDumpTest(nv3, "(*"+v3t+")(<nil>)\n") - - // Max int64. - v4 := int64(9223372036854775807) - nv4 := (*int64)(nil) - pv4 := &v4 - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "int64" - v4s := "9223372036854775807" - addDumpTest(v4, "("+v4t+") "+v4s+"\n") - addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") - addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") - addDumpTest(nv4, "(*"+v4t+")(<nil>)\n") - - // Max int. - v5 := int(2147483647) - nv5 := (*int)(nil) - pv5 := &v5 - v5Addr := fmt.Sprintf("%p", pv5) - pv5Addr := fmt.Sprintf("%p", &pv5) - v5t := "int" - v5s := "2147483647" - addDumpTest(v5, "("+v5t+") "+v5s+"\n") - addDumpTest(pv5, "(*"+v5t+")("+v5Addr+")("+v5s+")\n") - addDumpTest(&pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")("+v5s+")\n") - addDumpTest(nv5, "(*"+v5t+")(<nil>)\n") -} - -func addUintDumpTests() { - // Max uint8. - v := uint8(255) - nv := (*uint8)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "uint8" - vs := "255" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")(<nil>)\n") - - // Max uint16. - v2 := uint16(65535) - nv2 := (*uint16)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "uint16" - v2s := "65535" - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") - addDumpTest(nv2, "(*"+v2t+")(<nil>)\n") - - // Max uint32. - v3 := uint32(4294967295) - nv3 := (*uint32)(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "uint32" - v3s := "4294967295" - addDumpTest(v3, "("+v3t+") "+v3s+"\n") - addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") - addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") - addDumpTest(nv3, "(*"+v3t+")(<nil>)\n") - - // Max uint64. - v4 := uint64(18446744073709551615) - nv4 := (*uint64)(nil) - pv4 := &v4 - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "uint64" - v4s := "18446744073709551615" - addDumpTest(v4, "("+v4t+") "+v4s+"\n") - addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") - addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") - addDumpTest(nv4, "(*"+v4t+")(<nil>)\n") - - // Max uint. - v5 := uint(4294967295) - nv5 := (*uint)(nil) - pv5 := &v5 - v5Addr := fmt.Sprintf("%p", pv5) - pv5Addr := fmt.Sprintf("%p", &pv5) - v5t := "uint" - v5s := "4294967295" - addDumpTest(v5, "("+v5t+") "+v5s+"\n") - addDumpTest(pv5, "(*"+v5t+")("+v5Addr+")("+v5s+")\n") - addDumpTest(&pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")("+v5s+")\n") - addDumpTest(nv5, "(*"+v5t+")(<nil>)\n") -} - -func addBoolDumpTests() { - // Boolean true. - v := bool(true) - nv := (*bool)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "bool" - vs := "true" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")(<nil>)\n") - - // Boolean false. - v2 := bool(false) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "bool" - v2s := "false" - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") -} - -func addFloatDumpTests() { - // Standard float32. - v := float32(3.1415) - nv := (*float32)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "float32" - vs := "3.1415" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")(<nil>)\n") - - // Standard float64. - v2 := float64(3.1415926) - nv2 := (*float64)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "float64" - v2s := "3.1415926" - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") - addDumpTest(nv2, "(*"+v2t+")(<nil>)\n") -} - -func addComplexDumpTests() { - // Standard complex64. - v := complex(float32(6), -2) - nv := (*complex64)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "complex64" - vs := "(6-2i)" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")(<nil>)\n") - - // Standard complex128. - v2 := complex(float64(-6), 2) - nv2 := (*complex128)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "complex128" - v2s := "(-6+2i)" - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") - addDumpTest(nv2, "(*"+v2t+")(<nil>)\n") -} - -func addArrayDumpTests() { - // Array containing standard ints. - v := [3]int{1, 2, 3} - vLen := fmt.Sprintf("%d", len(v)) - vCap := fmt.Sprintf("%d", cap(v)) - nv := (*[3]int)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "int" - vs := "(len=" + vLen + " cap=" + vCap + ") {\n (" + vt + ") 1,\n (" + - vt + ") 2,\n (" + vt + ") 3\n}" - addDumpTest(v, "([3]"+vt+") "+vs+"\n") - addDumpTest(pv, "(*[3]"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**[3]"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*[3]"+vt+")(<nil>)\n") - - // Array containing type with custom formatter on pointer receiver only. - v2i0 := pstringer("1") - v2i1 := pstringer("2") - v2i2 := pstringer("3") - v2 := [3]pstringer{v2i0, v2i1, v2i2} - v2i0Len := fmt.Sprintf("%d", len(v2i0)) - v2i1Len := fmt.Sprintf("%d", len(v2i1)) - v2i2Len := fmt.Sprintf("%d", len(v2i2)) - v2Len := fmt.Sprintf("%d", len(v2)) - v2Cap := fmt.Sprintf("%d", cap(v2)) - nv2 := (*[3]pstringer)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "spew_test.pstringer" - v2sp := "(len=" + v2Len + " cap=" + v2Cap + ") {\n (" + v2t + - ") (len=" + v2i0Len + ") stringer 1,\n (" + v2t + - ") (len=" + v2i1Len + ") stringer 2,\n (" + v2t + - ") (len=" + v2i2Len + ") " + "stringer 3\n}" - v2s := v2sp - if spew.UnsafeDisabled { - v2s = "(len=" + v2Len + " cap=" + v2Cap + ") {\n (" + v2t + - ") (len=" + v2i0Len + ") \"1\",\n (" + v2t + ") (len=" + - v2i1Len + ") \"2\",\n (" + v2t + ") (len=" + v2i2Len + - ") " + "\"3\"\n}" - } - addDumpTest(v2, "([3]"+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*[3]"+v2t+")("+v2Addr+")("+v2sp+")\n") - addDumpTest(&pv2, "(**[3]"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2sp+")\n") - addDumpTest(nv2, "(*[3]"+v2t+")(<nil>)\n") - - // Array containing interfaces. - v3i0 := "one" - v3 := [3]interface{}{v3i0, int(2), uint(3)} - v3i0Len := fmt.Sprintf("%d", len(v3i0)) - v3Len := fmt.Sprintf("%d", len(v3)) - v3Cap := fmt.Sprintf("%d", cap(v3)) - nv3 := (*[3]interface{})(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "[3]interface {}" - v3t2 := "string" - v3t3 := "int" - v3t4 := "uint" - v3s := "(len=" + v3Len + " cap=" + v3Cap + ") {\n (" + v3t2 + ") " + - "(len=" + v3i0Len + ") \"one\",\n (" + v3t3 + ") 2,\n (" + - v3t4 + ") 3\n}" - addDumpTest(v3, "("+v3t+") "+v3s+"\n") - addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") - addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") - addDumpTest(nv3, "(*"+v3t+")(<nil>)\n") - - // Array containing bytes. - v4 := [34]byte{ - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x31, 0x32, - } - v4Len := fmt.Sprintf("%d", len(v4)) - v4Cap := fmt.Sprintf("%d", cap(v4)) - nv4 := (*[34]byte)(nil) - pv4 := &v4 - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "[34]uint8" - v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " + - "{\n 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20" + - " |............... |\n" + - " 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30" + - " |!\"#$%&'()*+,-./0|\n" + - " 00000020 31 32 " + - " |12|\n}" - addDumpTest(v4, "("+v4t+") "+v4s+"\n") - addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") - addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") - addDumpTest(nv4, "(*"+v4t+")(<nil>)\n") -} - -func addSliceDumpTests() { - // Slice containing standard float32 values. - v := []float32{3.14, 6.28, 12.56} - vLen := fmt.Sprintf("%d", len(v)) - vCap := fmt.Sprintf("%d", cap(v)) - nv := (*[]float32)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "float32" - vs := "(len=" + vLen + " cap=" + vCap + ") {\n (" + vt + ") 3.14,\n (" + - vt + ") 6.28,\n (" + vt + ") 12.56\n}" - addDumpTest(v, "([]"+vt+") "+vs+"\n") - addDumpTest(pv, "(*[]"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**[]"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*[]"+vt+")(<nil>)\n") - - // Slice containing type with custom formatter on pointer receiver only. - v2i0 := pstringer("1") - v2i1 := pstringer("2") - v2i2 := pstringer("3") - v2 := []pstringer{v2i0, v2i1, v2i2} - v2i0Len := fmt.Sprintf("%d", len(v2i0)) - v2i1Len := fmt.Sprintf("%d", len(v2i1)) - v2i2Len := fmt.Sprintf("%d", len(v2i2)) - v2Len := fmt.Sprintf("%d", len(v2)) - v2Cap := fmt.Sprintf("%d", cap(v2)) - nv2 := (*[]pstringer)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "spew_test.pstringer" - v2s := "(len=" + v2Len + " cap=" + v2Cap + ") {\n (" + v2t + ") (len=" + - v2i0Len + ") stringer 1,\n (" + v2t + ") (len=" + v2i1Len + - ") stringer 2,\n (" + v2t + ") (len=" + v2i2Len + ") " + - "stringer 3\n}" - addDumpTest(v2, "([]"+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*[]"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**[]"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") - addDumpTest(nv2, "(*[]"+v2t+")(<nil>)\n") - - // Slice containing interfaces. - v3i0 := "one" - v3 := []interface{}{v3i0, int(2), uint(3), nil} - v3i0Len := fmt.Sprintf("%d", len(v3i0)) - v3Len := fmt.Sprintf("%d", len(v3)) - v3Cap := fmt.Sprintf("%d", cap(v3)) - nv3 := (*[]interface{})(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "[]interface {}" - v3t2 := "string" - v3t3 := "int" - v3t4 := "uint" - v3t5 := "interface {}" - v3s := "(len=" + v3Len + " cap=" + v3Cap + ") {\n (" + v3t2 + ") " + - "(len=" + v3i0Len + ") \"one\",\n (" + v3t3 + ") 2,\n (" + - v3t4 + ") 3,\n (" + v3t5 + ") <nil>\n}" - addDumpTest(v3, "("+v3t+") "+v3s+"\n") - addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") - addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") - addDumpTest(nv3, "(*"+v3t+")(<nil>)\n") - - // Slice containing bytes. - v4 := []byte{ - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x31, 0x32, - } - v4Len := fmt.Sprintf("%d", len(v4)) - v4Cap := fmt.Sprintf("%d", cap(v4)) - nv4 := (*[]byte)(nil) - pv4 := &v4 - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "[]uint8" - v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " + - "{\n 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20" + - " |............... |\n" + - " 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30" + - " |!\"#$%&'()*+,-./0|\n" + - " 00000020 31 32 " + - " |12|\n}" - addDumpTest(v4, "("+v4t+") "+v4s+"\n") - addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") - addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") - addDumpTest(nv4, "(*"+v4t+")(<nil>)\n") - - // Nil slice. - v5 := []int(nil) - nv5 := (*[]int)(nil) - pv5 := &v5 - v5Addr := fmt.Sprintf("%p", pv5) - pv5Addr := fmt.Sprintf("%p", &pv5) - v5t := "[]int" - v5s := "<nil>" - addDumpTest(v5, "("+v5t+") "+v5s+"\n") - addDumpTest(pv5, "(*"+v5t+")("+v5Addr+")("+v5s+")\n") - addDumpTest(&pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")("+v5s+")\n") - addDumpTest(nv5, "(*"+v5t+")(<nil>)\n") -} - -func addStringDumpTests() { - // Standard string. - v := "test" - vLen := fmt.Sprintf("%d", len(v)) - nv := (*string)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "string" - vs := "(len=" + vLen + ") \"test\"" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")(<nil>)\n") -} - -func addInterfaceDumpTests() { - // Nil interface. - var v interface{} - nv := (*interface{})(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "interface {}" - vs := "<nil>" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")(<nil>)\n") - - // Sub-interface. - v2 := interface{}(uint16(65535)) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "uint16" - v2s := "65535" - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") -} - -func addMapDumpTests() { - // Map with string keys and int vals. - k := "one" - kk := "two" - m := map[string]int{k: 1, kk: 2} - klen := fmt.Sprintf("%d", len(k)) // not kLen to shut golint up - kkLen := fmt.Sprintf("%d", len(kk)) - mLen := fmt.Sprintf("%d", len(m)) - nilMap := map[string]int(nil) - nm := (*map[string]int)(nil) - pm := &m - mAddr := fmt.Sprintf("%p", pm) - pmAddr := fmt.Sprintf("%p", &pm) - mt := "map[string]int" - mt1 := "string" - mt2 := "int" - ms := "(len=" + mLen + ") {\n (" + mt1 + ") (len=" + klen + ") " + - "\"one\": (" + mt2 + ") 1,\n (" + mt1 + ") (len=" + kkLen + - ") \"two\": (" + mt2 + ") 2\n}" - ms2 := "(len=" + mLen + ") {\n (" + mt1 + ") (len=" + kkLen + ") " + - "\"two\": (" + mt2 + ") 2,\n (" + mt1 + ") (len=" + klen + - ") \"one\": (" + mt2 + ") 1\n}" - addDumpTest(m, "("+mt+") "+ms+"\n", "("+mt+") "+ms2+"\n") - addDumpTest(pm, "(*"+mt+")("+mAddr+")("+ms+")\n", - "(*"+mt+")("+mAddr+")("+ms2+")\n") - addDumpTest(&pm, "(**"+mt+")("+pmAddr+"->"+mAddr+")("+ms+")\n", - "(**"+mt+")("+pmAddr+"->"+mAddr+")("+ms2+")\n") - addDumpTest(nm, "(*"+mt+")(<nil>)\n") - addDumpTest(nilMap, "("+mt+") <nil>\n") - - // Map with custom formatter type on pointer receiver only keys and vals. - k2 := pstringer("one") - v2 := pstringer("1") - m2 := map[pstringer]pstringer{k2: v2} - k2Len := fmt.Sprintf("%d", len(k2)) - v2Len := fmt.Sprintf("%d", len(v2)) - m2Len := fmt.Sprintf("%d", len(m2)) - nilMap2 := map[pstringer]pstringer(nil) - nm2 := (*map[pstringer]pstringer)(nil) - pm2 := &m2 - m2Addr := fmt.Sprintf("%p", pm2) - pm2Addr := fmt.Sprintf("%p", &pm2) - m2t := "map[spew_test.pstringer]spew_test.pstringer" - m2t1 := "spew_test.pstringer" - m2t2 := "spew_test.pstringer" - m2s := "(len=" + m2Len + ") {\n (" + m2t1 + ") (len=" + k2Len + ") " + - "stringer one: (" + m2t2 + ") (len=" + v2Len + ") stringer 1\n}" - if spew.UnsafeDisabled { - m2s = "(len=" + m2Len + ") {\n (" + m2t1 + ") (len=" + k2Len + - ") " + "\"one\": (" + m2t2 + ") (len=" + v2Len + - ") \"1\"\n}" - } - addDumpTest(m2, "("+m2t+") "+m2s+"\n") - addDumpTest(pm2, "(*"+m2t+")("+m2Addr+")("+m2s+")\n") - addDumpTest(&pm2, "(**"+m2t+")("+pm2Addr+"->"+m2Addr+")("+m2s+")\n") - addDumpTest(nm2, "(*"+m2t+")(<nil>)\n") - addDumpTest(nilMap2, "("+m2t+") <nil>\n") - - // Map with interface keys and values. - k3 := "one" - k3Len := fmt.Sprintf("%d", len(k3)) - m3 := map[interface{}]interface{}{k3: 1} - m3Len := fmt.Sprintf("%d", len(m3)) - nilMap3 := map[interface{}]interface{}(nil) - nm3 := (*map[interface{}]interface{})(nil) - pm3 := &m3 - m3Addr := fmt.Sprintf("%p", pm3) - pm3Addr := fmt.Sprintf("%p", &pm3) - m3t := "map[interface {}]interface {}" - m3t1 := "string" - m3t2 := "int" - m3s := "(len=" + m3Len + ") {\n (" + m3t1 + ") (len=" + k3Len + ") " + - "\"one\": (" + m3t2 + ") 1\n}" - addDumpTest(m3, "("+m3t+") "+m3s+"\n") - addDumpTest(pm3, "(*"+m3t+")("+m3Addr+")("+m3s+")\n") - addDumpTest(&pm3, "(**"+m3t+")("+pm3Addr+"->"+m3Addr+")("+m3s+")\n") - addDumpTest(nm3, "(*"+m3t+")(<nil>)\n") - addDumpTest(nilMap3, "("+m3t+") <nil>\n") - - // Map with nil interface value. - k4 := "nil" - k4Len := fmt.Sprintf("%d", len(k4)) - m4 := map[string]interface{}{k4: nil} - m4Len := fmt.Sprintf("%d", len(m4)) - nilMap4 := map[string]interface{}(nil) - nm4 := (*map[string]interface{})(nil) - pm4 := &m4 - m4Addr := fmt.Sprintf("%p", pm4) - pm4Addr := fmt.Sprintf("%p", &pm4) - m4t := "map[string]interface {}" - m4t1 := "string" - m4t2 := "interface {}" - m4s := "(len=" + m4Len + ") {\n (" + m4t1 + ") (len=" + k4Len + ")" + - " \"nil\": (" + m4t2 + ") <nil>\n}" - addDumpTest(m4, "("+m4t+") "+m4s+"\n") - addDumpTest(pm4, "(*"+m4t+")("+m4Addr+")("+m4s+")\n") - addDumpTest(&pm4, "(**"+m4t+")("+pm4Addr+"->"+m4Addr+")("+m4s+")\n") - addDumpTest(nm4, "(*"+m4t+")(<nil>)\n") - addDumpTest(nilMap4, "("+m4t+") <nil>\n") -} - -func addStructDumpTests() { - // Struct with primitives. - type s1 struct { - a int8 - b uint8 - } - v := s1{127, 255} - nv := (*s1)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "spew_test.s1" - vt2 := "int8" - vt3 := "uint8" - vs := "{\n a: (" + vt2 + ") 127,\n b: (" + vt3 + ") 255\n}" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")(<nil>)\n") - - // Struct that contains another struct. - type s2 struct { - s1 s1 - b bool - } - v2 := s2{s1{127, 255}, true} - nv2 := (*s2)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "spew_test.s2" - v2t2 := "spew_test.s1" - v2t3 := "int8" - v2t4 := "uint8" - v2t5 := "bool" - v2s := "{\n s1: (" + v2t2 + ") {\n a: (" + v2t3 + ") 127,\n b: (" + - v2t4 + ") 255\n },\n b: (" + v2t5 + ") true\n}" - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") - addDumpTest(nv2, "(*"+v2t+")(<nil>)\n") - - // Struct that contains custom type with Stringer pointer interface via both - // exported and unexported fields. - type s3 struct { - s pstringer - S pstringer - } - v3 := s3{"test", "test2"} - nv3 := (*s3)(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "spew_test.s3" - v3t2 := "spew_test.pstringer" - v3s := "{\n s: (" + v3t2 + ") (len=4) stringer test,\n S: (" + v3t2 + - ") (len=5) stringer test2\n}" - v3sp := v3s - if spew.UnsafeDisabled { - v3s = "{\n s: (" + v3t2 + ") (len=4) \"test\",\n S: (" + - v3t2 + ") (len=5) \"test2\"\n}" - v3sp = "{\n s: (" + v3t2 + ") (len=4) \"test\",\n S: (" + - v3t2 + ") (len=5) stringer test2\n}" - } - addDumpTest(v3, "("+v3t+") "+v3s+"\n") - addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3sp+")\n") - addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3sp+")\n") - addDumpTest(nv3, "(*"+v3t+")(<nil>)\n") - - // Struct that contains embedded struct and field to same struct. - e := embed{"embedstr"} - eLen := fmt.Sprintf("%d", len("embedstr")) - v4 := embedwrap{embed: &e, e: &e} - nv4 := (*embedwrap)(nil) - pv4 := &v4 - eAddr := fmt.Sprintf("%p", &e) - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "spew_test.embedwrap" - v4t2 := "spew_test.embed" - v4t3 := "string" - v4s := "{\n embed: (*" + v4t2 + ")(" + eAddr + ")({\n a: (" + v4t3 + - ") (len=" + eLen + ") \"embedstr\"\n }),\n e: (*" + v4t2 + - ")(" + eAddr + ")({\n a: (" + v4t3 + ") (len=" + eLen + ")" + - " \"embedstr\"\n })\n}" - addDumpTest(v4, "("+v4t+") "+v4s+"\n") - addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") - addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") - addDumpTest(nv4, "(*"+v4t+")(<nil>)\n") -} - -func addUintptrDumpTests() { - // Null pointer. - v := uintptr(0) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "uintptr" - vs := "<nil>" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - - // Address of real variable. - i := 1 - v2 := uintptr(unsafe.Pointer(&i)) - nv2 := (*uintptr)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "uintptr" - v2s := fmt.Sprintf("%p", &i) - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") - addDumpTest(nv2, "(*"+v2t+")(<nil>)\n") -} - -func addUnsafePointerDumpTests() { - // Null pointer. - v := unsafe.Pointer(nil) - nv := (*unsafe.Pointer)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "unsafe.Pointer" - vs := "<nil>" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")(<nil>)\n") - - // Address of real variable. - i := 1 - v2 := unsafe.Pointer(&i) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "unsafe.Pointer" - v2s := fmt.Sprintf("%p", &i) - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") - addDumpTest(nv, "(*"+vt+")(<nil>)\n") -} - -func addChanDumpTests() { - // Nil channel. - var v chan int - pv := &v - nv := (*chan int)(nil) - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "chan int" - vs := "<nil>" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")(<nil>)\n") - - // Real channel. - v2 := make(chan int) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "chan int" - v2s := fmt.Sprintf("%p", v2) - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") -} - -func addFuncDumpTests() { - // Function with no params and no returns. - v := addIntDumpTests - nv := (*func())(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "func()" - vs := fmt.Sprintf("%p", v) - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")(<nil>)\n") - - // Function with param and no returns. - v2 := TestDump - nv2 := (*func(*testing.T))(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "func(*testing.T)" - v2s := fmt.Sprintf("%p", v2) - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") - addDumpTest(nv2, "(*"+v2t+")(<nil>)\n") - - // Function with multiple params and multiple returns. - var v3 = func(i int, s string) (b bool, err error) { - return true, nil - } - nv3 := (*func(int, string) (bool, error))(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "func(int, string) (bool, error)" - v3s := fmt.Sprintf("%p", v3) - addDumpTest(v3, "("+v3t+") "+v3s+"\n") - addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") - addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") - addDumpTest(nv3, "(*"+v3t+")(<nil>)\n") -} - -func addCircularDumpTests() { - // Struct that is circular through self referencing. - type circular struct { - c *circular - } - v := circular{nil} - v.c = &v - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "spew_test.circular" - vs := "{\n c: (*" + vt + ")(" + vAddr + ")({\n c: (*" + vt + ")(" + - vAddr + ")(<already shown>)\n })\n}" - vs2 := "{\n c: (*" + vt + ")(" + vAddr + ")(<already shown>)\n}" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs2+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs2+")\n") - - // Structs that are circular through cross referencing. - v2 := xref1{nil} - ts2 := xref2{&v2} - v2.ps2 = &ts2 - pv2 := &v2 - ts2Addr := fmt.Sprintf("%p", &ts2) - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "spew_test.xref1" - v2t2 := "spew_test.xref2" - v2s := "{\n ps2: (*" + v2t2 + ")(" + ts2Addr + ")({\n ps1: (*" + v2t + - ")(" + v2Addr + ")({\n ps2: (*" + v2t2 + ")(" + ts2Addr + - ")(<already shown>)\n })\n })\n}" - v2s2 := "{\n ps2: (*" + v2t2 + ")(" + ts2Addr + ")({\n ps1: (*" + v2t + - ")(" + v2Addr + ")(<already shown>)\n })\n}" - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s2+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s2+")\n") - - // Structs that are indirectly circular. - v3 := indirCir1{nil} - tic2 := indirCir2{nil} - tic3 := indirCir3{&v3} - tic2.ps3 = &tic3 - v3.ps2 = &tic2 - pv3 := &v3 - tic2Addr := fmt.Sprintf("%p", &tic2) - tic3Addr := fmt.Sprintf("%p", &tic3) - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "spew_test.indirCir1" - v3t2 := "spew_test.indirCir2" - v3t3 := "spew_test.indirCir3" - v3s := "{\n ps2: (*" + v3t2 + ")(" + tic2Addr + ")({\n ps3: (*" + v3t3 + - ")(" + tic3Addr + ")({\n ps1: (*" + v3t + ")(" + v3Addr + - ")({\n ps2: (*" + v3t2 + ")(" + tic2Addr + - ")(<already shown>)\n })\n })\n })\n}" - v3s2 := "{\n ps2: (*" + v3t2 + ")(" + tic2Addr + ")({\n ps3: (*" + v3t3 + - ")(" + tic3Addr + ")({\n ps1: (*" + v3t + ")(" + v3Addr + - ")(<already shown>)\n })\n })\n}" - addDumpTest(v3, "("+v3t+") "+v3s+"\n") - addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s2+")\n") - addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s2+")\n") -} - -func addPanicDumpTests() { - // Type that panics in its Stringer interface. - v := panicer(127) - nv := (*panicer)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "spew_test.panicer" - vs := "(PANIC=test panic)127" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")(<nil>)\n") -} - -func addErrorDumpTests() { - // Type that has a custom Error interface. - v := customError(127) - nv := (*customError)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "spew_test.customError" - vs := "error: 127" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")(<nil>)\n") -} - -// TestDump executes all of the tests described by dumpTests. -func TestDump(t *testing.T) { - // Setup tests. - addIntDumpTests() - addUintDumpTests() - addBoolDumpTests() - addFloatDumpTests() - addComplexDumpTests() - addArrayDumpTests() - addSliceDumpTests() - addStringDumpTests() - addInterfaceDumpTests() - addMapDumpTests() - addStructDumpTests() - addUintptrDumpTests() - addUnsafePointerDumpTests() - addChanDumpTests() - addFuncDumpTests() - addCircularDumpTests() - addPanicDumpTests() - addErrorDumpTests() - addCgoDumpTests() - - t.Logf("Running %d tests", len(dumpTests)) - for i, test := range dumpTests { - buf := new(bytes.Buffer) - spew.Fdump(buf, test.in) - s := buf.String() - if testFailed(s, test.wants) { - t.Errorf("Dump #%d\n got: %s %s", i, s, stringizeWants(test.wants)) - continue - } - } -} - -func TestDumpSortedKeys(t *testing.T) { - cfg := spew.ConfigState{SortKeys: true} - s := cfg.Sdump(map[int]string{1: "1", 3: "3", 2: "2"}) - expected := "(map[int]string) (len=3) {\n(int) 1: (string) (len=1) " + - "\"1\",\n(int) 2: (string) (len=1) \"2\",\n(int) 3: (string) " + - "(len=1) \"3\"\n" + - "}\n" - if s != expected { - t.Errorf("Sorted keys mismatch:\n %v %v", s, expected) - } - - s = cfg.Sdump(map[stringer]int{"1": 1, "3": 3, "2": 2}) - expected = "(map[spew_test.stringer]int) (len=3) {\n" + - "(spew_test.stringer) (len=1) stringer 1: (int) 1,\n" + - "(spew_test.stringer) (len=1) stringer 2: (int) 2,\n" + - "(spew_test.stringer) (len=1) stringer 3: (int) 3\n" + - "}\n" - if s != expected { - t.Errorf("Sorted keys mismatch:\n %v %v", s, expected) - } - - s = cfg.Sdump(map[pstringer]int{pstringer("1"): 1, pstringer("3"): 3, pstringer("2"): 2}) - expected = "(map[spew_test.pstringer]int) (len=3) {\n" + - "(spew_test.pstringer) (len=1) stringer 1: (int) 1,\n" + - "(spew_test.pstringer) (len=1) stringer 2: (int) 2,\n" + - "(spew_test.pstringer) (len=1) stringer 3: (int) 3\n" + - "}\n" - if spew.UnsafeDisabled { - expected = "(map[spew_test.pstringer]int) (len=3) {\n" + - "(spew_test.pstringer) (len=1) \"1\": (int) 1,\n" + - "(spew_test.pstringer) (len=1) \"2\": (int) 2,\n" + - "(spew_test.pstringer) (len=1) \"3\": (int) 3\n" + - "}\n" - } - if s != expected { - t.Errorf("Sorted keys mismatch:\n %v %v", s, expected) - } - - s = cfg.Sdump(map[customError]int{customError(1): 1, customError(3): 3, customError(2): 2}) - expected = "(map[spew_test.customError]int) (len=3) {\n" + - "(spew_test.customError) error: 1: (int) 1,\n" + - "(spew_test.customError) error: 2: (int) 2,\n" + - "(spew_test.customError) error: 3: (int) 3\n" + - "}\n" - if s != expected { - t.Errorf("Sorted keys mismatch:\n %v %v", s, expected) - } - -} diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dumpcgo_test.go b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dumpcgo_test.go deleted file mode 100644 index 108baa5..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dumpcgo_test.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) 2013-2016 Dave Collins <dave@davec.name> -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -// NOTE: Due to the following build constraints, this file will only be compiled -// when both cgo is supported and "-tags testcgo" is added to the go test -// command line. This means the cgo tests are only added (and hence run) when -// specifially requested. This configuration is used because spew itself -// does not require cgo to run even though it does handle certain cgo types -// specially. Rather than forcing all clients to require cgo and an external -// C compiler just to run the tests, this scheme makes them optional. -// +build cgo,testcgo - -package spew_test - -import ( - "fmt" - - "github.com/davecgh/go-spew/spew/testdata" -) - -func addCgoDumpTests() { - // C char pointer. - v := testdata.GetCgoCharPointer() - nv := testdata.GetCgoNullCharPointer() - pv := &v - vcAddr := fmt.Sprintf("%p", v) - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "*testdata._Ctype_char" - vs := "116" - addDumpTest(v, "("+vt+")("+vcAddr+")("+vs+")\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+"->"+vcAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+"->"+vcAddr+")("+vs+")\n") - addDumpTest(nv, "("+vt+")(<nil>)\n") - - // C char array. - v2, v2l, v2c := testdata.GetCgoCharArray() - v2Len := fmt.Sprintf("%d", v2l) - v2Cap := fmt.Sprintf("%d", v2c) - v2t := "[6]testdata._Ctype_char" - v2s := "(len=" + v2Len + " cap=" + v2Cap + ") " + - "{\n 00000000 74 65 73 74 32 00 " + - " |test2.|\n}" - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - - // C unsigned char array. - v3, v3l, v3c := testdata.GetCgoUnsignedCharArray() - v3Len := fmt.Sprintf("%d", v3l) - v3Cap := fmt.Sprintf("%d", v3c) - v3t := "[6]testdata._Ctype_unsignedchar" - v3t2 := "[6]testdata._Ctype_uchar" - v3s := "(len=" + v3Len + " cap=" + v3Cap + ") " + - "{\n 00000000 74 65 73 74 33 00 " + - " |test3.|\n}" - addDumpTest(v3, "("+v3t+") "+v3s+"\n", "("+v3t2+") "+v3s+"\n") - - // C signed char array. - v4, v4l, v4c := testdata.GetCgoSignedCharArray() - v4Len := fmt.Sprintf("%d", v4l) - v4Cap := fmt.Sprintf("%d", v4c) - v4t := "[6]testdata._Ctype_schar" - v4t2 := "testdata._Ctype_schar" - v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " + - "{\n (" + v4t2 + ") 116,\n (" + v4t2 + ") 101,\n (" + v4t2 + - ") 115,\n (" + v4t2 + ") 116,\n (" + v4t2 + ") 52,\n (" + v4t2 + - ") 0\n}" - addDumpTest(v4, "("+v4t+") "+v4s+"\n") - - // C uint8_t array. - v5, v5l, v5c := testdata.GetCgoUint8tArray() - v5Len := fmt.Sprintf("%d", v5l) - v5Cap := fmt.Sprintf("%d", v5c) - v5t := "[6]testdata._Ctype_uint8_t" - v5t2 := "[6]testdata._Ctype_uchar" - v5s := "(len=" + v5Len + " cap=" + v5Cap + ") " + - "{\n 00000000 74 65 73 74 35 00 " + - " |test5.|\n}" - addDumpTest(v5, "("+v5t+") "+v5s+"\n", "("+v5t2+") "+v5s+"\n") - - // C typedefed unsigned char array. - v6, v6l, v6c := testdata.GetCgoTypdefedUnsignedCharArray() - v6Len := fmt.Sprintf("%d", v6l) - v6Cap := fmt.Sprintf("%d", v6c) - v6t := "[6]testdata._Ctype_custom_uchar_t" - v6t2 := "[6]testdata._Ctype_uchar" - v6s := "(len=" + v6Len + " cap=" + v6Cap + ") " + - "{\n 00000000 74 65 73 74 36 00 " + - " |test6.|\n}" - addDumpTest(v6, "("+v6t+") "+v6s+"\n", "("+v6t2+") "+v6s+"\n") -} diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dumpnocgo_test.go b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dumpnocgo_test.go deleted file mode 100644 index 52a0971..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dumpnocgo_test.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2013 Dave Collins <dave@davec.name> -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -// NOTE: Due to the following build constraints, this file will only be compiled -// when either cgo is not supported or "-tags testcgo" is not added to the go -// test command line. This file intentionally does not setup any cgo tests in -// this scenario. -// +build !cgo !testcgo - -package spew_test - -func addCgoDumpTests() { - // Don't add any tests for cgo since this file is only compiled when - // there should not be any cgo tests. -} diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/example_test.go b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/example_test.go deleted file mode 100644 index c6ec8c6..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/example_test.go +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins <dave@davec.name> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew_test - -import ( - "fmt" - - "github.com/davecgh/go-spew/spew" -) - -type Flag int - -const ( - flagOne Flag = iota - flagTwo -) - -var flagStrings = map[Flag]string{ - flagOne: "flagOne", - flagTwo: "flagTwo", -} - -func (f Flag) String() string { - if s, ok := flagStrings[f]; ok { - return s - } - return fmt.Sprintf("Unknown flag (%d)", int(f)) -} - -type Bar struct { - data uintptr -} - -type Foo struct { - unexportedField Bar - ExportedField map[interface{}]interface{} -} - -// This example demonstrates how to use Dump to dump variables to stdout. -func ExampleDump() { - // The following package level declarations are assumed for this example: - /* - type Flag int - - const ( - flagOne Flag = iota - flagTwo - ) - - var flagStrings = map[Flag]string{ - flagOne: "flagOne", - flagTwo: "flagTwo", - } - - func (f Flag) String() string { - if s, ok := flagStrings[f]; ok { - return s - } - return fmt.Sprintf("Unknown flag (%d)", int(f)) - } - - type Bar struct { - data uintptr - } - - type Foo struct { - unexportedField Bar - ExportedField map[interface{}]interface{} - } - */ - - // Setup some sample data structures for the example. - bar := Bar{uintptr(0)} - s1 := Foo{bar, map[interface{}]interface{}{"one": true}} - f := Flag(5) - b := []byte{ - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x31, 0x32, - } - - // Dump! - spew.Dump(s1, f, b) - - // Output: - // (spew_test.Foo) { - // unexportedField: (spew_test.Bar) { - // data: (uintptr) <nil> - // }, - // ExportedField: (map[interface {}]interface {}) (len=1) { - // (string) (len=3) "one": (bool) true - // } - // } - // (spew_test.Flag) Unknown flag (5) - // ([]uint8) (len=34 cap=34) { - // 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | - // 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| - // 00000020 31 32 |12| - // } - // -} - -// This example demonstrates how to use Printf to display a variable with a -// format string and inline formatting. -func ExamplePrintf() { - // Create a double pointer to a uint 8. - ui8 := uint8(5) - pui8 := &ui8 - ppui8 := &pui8 - - // Create a circular data type. - type circular struct { - ui8 uint8 - c *circular - } - c := circular{ui8: 1} - c.c = &c - - // Print! - spew.Printf("ppui8: %v\n", ppui8) - spew.Printf("circular: %v\n", c) - - // Output: - // ppui8: <**>5 - // circular: {1 <*>{1 <*><shown>}} -} - -// This example demonstrates how to use a ConfigState. -func ExampleConfigState() { - // Modify the indent level of the ConfigState only. The global - // configuration is not modified. - scs := spew.ConfigState{Indent: "\t"} - - // Output using the ConfigState instance. - v := map[string]int{"one": 1} - scs.Printf("v: %v\n", v) - scs.Dump(v) - - // Output: - // v: map[one:1] - // (map[string]int) (len=1) { - // (string) (len=3) "one": (int) 1 - // } -} - -// This example demonstrates how to use ConfigState.Dump to dump variables to -// stdout -func ExampleConfigState_Dump() { - // See the top-level Dump example for details on the types used in this - // example. - - // Create two ConfigState instances with different indentation. - scs := spew.ConfigState{Indent: "\t"} - scs2 := spew.ConfigState{Indent: " "} - - // Setup some sample data structures for the example. - bar := Bar{uintptr(0)} - s1 := Foo{bar, map[interface{}]interface{}{"one": true}} - - // Dump using the ConfigState instances. - scs.Dump(s1) - scs2.Dump(s1) - - // Output: - // (spew_test.Foo) { - // unexportedField: (spew_test.Bar) { - // data: (uintptr) <nil> - // }, - // ExportedField: (map[interface {}]interface {}) (len=1) { - // (string) (len=3) "one": (bool) true - // } - // } - // (spew_test.Foo) { - // unexportedField: (spew_test.Bar) { - // data: (uintptr) <nil> - // }, - // ExportedField: (map[interface {}]interface {}) (len=1) { - // (string) (len=3) "one": (bool) true - // } - // } - // -} - -// This example demonstrates how to use ConfigState.Printf to display a variable -// with a format string and inline formatting. -func ExampleConfigState_Printf() { - // See the top-level Dump example for details on the types used in this - // example. - - // Create two ConfigState instances and modify the method handling of the - // first ConfigState only. - scs := spew.NewDefaultConfig() - scs2 := spew.NewDefaultConfig() - scs.DisableMethods = true - - // Alternatively - // scs := spew.ConfigState{Indent: " ", DisableMethods: true} - // scs2 := spew.ConfigState{Indent: " "} - - // This is of type Flag which implements a Stringer and has raw value 1. - f := flagTwo - - // Dump using the ConfigState instances. - scs.Printf("f: %v\n", f) - scs2.Printf("f: %v\n", f) - - // Output: - // f: 1 - // f: flagTwo -} diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/format.go b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/format.go deleted file mode 100644 index b04edb7..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/format.go +++ /dev/null @@ -1,419 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins <dave@davec.name> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew - -import ( - "bytes" - "fmt" - "reflect" - "strconv" - "strings" -) - -// supportedFlags is a list of all the character flags supported by fmt package. -const supportedFlags = "0-+# " - -// formatState implements the fmt.Formatter interface and contains information -// about the state of a formatting operation. The NewFormatter function can -// be used to get a new Formatter which can be used directly as arguments -// in standard fmt package printing calls. -type formatState struct { - value interface{} - fs fmt.State - depth int - pointers map[uintptr]int - ignoreNextType bool - cs *ConfigState -} - -// buildDefaultFormat recreates the original format string without precision -// and width information to pass in to fmt.Sprintf in the case of an -// unrecognized type. Unless new types are added to the language, this -// function won't ever be called. -func (f *formatState) buildDefaultFormat() (format string) { - buf := bytes.NewBuffer(percentBytes) - - for _, flag := range supportedFlags { - if f.fs.Flag(int(flag)) { - buf.WriteRune(flag) - } - } - - buf.WriteRune('v') - - format = buf.String() - return format -} - -// constructOrigFormat recreates the original format string including precision -// and width information to pass along to the standard fmt package. This allows -// automatic deferral of all format strings this package doesn't support. -func (f *formatState) constructOrigFormat(verb rune) (format string) { - buf := bytes.NewBuffer(percentBytes) - - for _, flag := range supportedFlags { - if f.fs.Flag(int(flag)) { - buf.WriteRune(flag) - } - } - - if width, ok := f.fs.Width(); ok { - buf.WriteString(strconv.Itoa(width)) - } - - if precision, ok := f.fs.Precision(); ok { - buf.Write(precisionBytes) - buf.WriteString(strconv.Itoa(precision)) - } - - buf.WriteRune(verb) - - format = buf.String() - return format -} - -// unpackValue returns values inside of non-nil interfaces when possible and -// ensures that types for values which have been unpacked from an interface -// are displayed when the show types flag is also set. -// This is useful for data types like structs, arrays, slices, and maps which -// can contain varying types packed inside an interface. -func (f *formatState) unpackValue(v reflect.Value) reflect.Value { - if v.Kind() == reflect.Interface { - f.ignoreNextType = false - if !v.IsNil() { - v = v.Elem() - } - } - return v -} - -// formatPtr handles formatting of pointers by indirecting them as necessary. -func (f *formatState) formatPtr(v reflect.Value) { - // Display nil if top level pointer is nil. - showTypes := f.fs.Flag('#') - if v.IsNil() && (!showTypes || f.ignoreNextType) { - f.fs.Write(nilAngleBytes) - return - } - - // Remove pointers at or below the current depth from map used to detect - // circular refs. - for k, depth := range f.pointers { - if depth >= f.depth { - delete(f.pointers, k) - } - } - - // Keep list of all dereferenced pointers to possibly show later. - pointerChain := make([]uintptr, 0) - - // Figure out how many levels of indirection there are by derferencing - // pointers and unpacking interfaces down the chain while detecting circular - // references. - nilFound := false - cycleFound := false - indirects := 0 - ve := v - for ve.Kind() == reflect.Ptr { - if ve.IsNil() { - nilFound = true - break - } - indirects++ - addr := ve.Pointer() - pointerChain = append(pointerChain, addr) - if pd, ok := f.pointers[addr]; ok && pd < f.depth { - cycleFound = true - indirects-- - break - } - f.pointers[addr] = f.depth - - ve = ve.Elem() - if ve.Kind() == reflect.Interface { - if ve.IsNil() { - nilFound = true - break - } - ve = ve.Elem() - } - } - - // Display type or indirection level depending on flags. - if showTypes && !f.ignoreNextType { - f.fs.Write(openParenBytes) - f.fs.Write(bytes.Repeat(asteriskBytes, indirects)) - f.fs.Write([]byte(ve.Type().String())) - f.fs.Write(closeParenBytes) - } else { - if nilFound || cycleFound { - indirects += strings.Count(ve.Type().String(), "*") - } - f.fs.Write(openAngleBytes) - f.fs.Write([]byte(strings.Repeat("*", indirects))) - f.fs.Write(closeAngleBytes) - } - - // Display pointer information depending on flags. - if f.fs.Flag('+') && (len(pointerChain) > 0) { - f.fs.Write(openParenBytes) - for i, addr := range pointerChain { - if i > 0 { - f.fs.Write(pointerChainBytes) - } - printHexPtr(f.fs, addr) - } - f.fs.Write(closeParenBytes) - } - - // Display dereferenced value. - switch { - case nilFound: - f.fs.Write(nilAngleBytes) - - case cycleFound: - f.fs.Write(circularShortBytes) - - default: - f.ignoreNextType = true - f.format(ve) - } -} - -// format is the main workhorse for providing the Formatter interface. It -// uses the passed reflect value to figure out what kind of object we are -// dealing with and formats it appropriately. It is a recursive function, -// however circular data structures are detected and handled properly. -func (f *formatState) format(v reflect.Value) { - // Handle invalid reflect values immediately. - kind := v.Kind() - if kind == reflect.Invalid { - f.fs.Write(invalidAngleBytes) - return - } - - // Handle pointers specially. - if kind == reflect.Ptr { - f.formatPtr(v) - return - } - - // Print type information unless already handled elsewhere. - if !f.ignoreNextType && f.fs.Flag('#') { - f.fs.Write(openParenBytes) - f.fs.Write([]byte(v.Type().String())) - f.fs.Write(closeParenBytes) - } - f.ignoreNextType = false - - // Call Stringer/error interfaces if they exist and the handle methods - // flag is enabled. - if !f.cs.DisableMethods { - if (kind != reflect.Invalid) && (kind != reflect.Interface) { - if handled := handleMethods(f.cs, f.fs, v); handled { - return - } - } - } - - switch kind { - case reflect.Invalid: - // Do nothing. We should never get here since invalid has already - // been handled above. - - case reflect.Bool: - printBool(f.fs, v.Bool()) - - case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: - printInt(f.fs, v.Int(), 10) - - case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: - printUint(f.fs, v.Uint(), 10) - - case reflect.Float32: - printFloat(f.fs, v.Float(), 32) - - case reflect.Float64: - printFloat(f.fs, v.Float(), 64) - - case reflect.Complex64: - printComplex(f.fs, v.Complex(), 32) - - case reflect.Complex128: - printComplex(f.fs, v.Complex(), 64) - - case reflect.Slice: - if v.IsNil() { - f.fs.Write(nilAngleBytes) - break - } - fallthrough - - case reflect.Array: - f.fs.Write(openBracketBytes) - f.depth++ - if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { - f.fs.Write(maxShortBytes) - } else { - numEntries := v.Len() - for i := 0; i < numEntries; i++ { - if i > 0 { - f.fs.Write(spaceBytes) - } - f.ignoreNextType = true - f.format(f.unpackValue(v.Index(i))) - } - } - f.depth-- - f.fs.Write(closeBracketBytes) - - case reflect.String: - f.fs.Write([]byte(v.String())) - - case reflect.Interface: - // The only time we should get here is for nil interfaces due to - // unpackValue calls. - if v.IsNil() { - f.fs.Write(nilAngleBytes) - } - - case reflect.Ptr: - // Do nothing. We should never get here since pointers have already - // been handled above. - - case reflect.Map: - // nil maps should be indicated as different than empty maps - if v.IsNil() { - f.fs.Write(nilAngleBytes) - break - } - - f.fs.Write(openMapBytes) - f.depth++ - if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { - f.fs.Write(maxShortBytes) - } else { - keys := v.MapKeys() - if f.cs.SortKeys { - sortValues(keys, f.cs) - } - for i, key := range keys { - if i > 0 { - f.fs.Write(spaceBytes) - } - f.ignoreNextType = true - f.format(f.unpackValue(key)) - f.fs.Write(colonBytes) - f.ignoreNextType = true - f.format(f.unpackValue(v.MapIndex(key))) - } - } - f.depth-- - f.fs.Write(closeMapBytes) - - case reflect.Struct: - numFields := v.NumField() - f.fs.Write(openBraceBytes) - f.depth++ - if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { - f.fs.Write(maxShortBytes) - } else { - vt := v.Type() - for i := 0; i < numFields; i++ { - if i > 0 { - f.fs.Write(spaceBytes) - } - vtf := vt.Field(i) - if f.fs.Flag('+') || f.fs.Flag('#') { - f.fs.Write([]byte(vtf.Name)) - f.fs.Write(colonBytes) - } - f.format(f.unpackValue(v.Field(i))) - } - } - f.depth-- - f.fs.Write(closeBraceBytes) - - case reflect.Uintptr: - printHexPtr(f.fs, uintptr(v.Uint())) - - case reflect.UnsafePointer, reflect.Chan, reflect.Func: - printHexPtr(f.fs, v.Pointer()) - - // There were not any other types at the time this code was written, but - // fall back to letting the default fmt package handle it if any get added. - default: - format := f.buildDefaultFormat() - if v.CanInterface() { - fmt.Fprintf(f.fs, format, v.Interface()) - } else { - fmt.Fprintf(f.fs, format, v.String()) - } - } -} - -// Format satisfies the fmt.Formatter interface. See NewFormatter for usage -// details. -func (f *formatState) Format(fs fmt.State, verb rune) { - f.fs = fs - - // Use standard formatting for verbs that are not v. - if verb != 'v' { - format := f.constructOrigFormat(verb) - fmt.Fprintf(fs, format, f.value) - return - } - - if f.value == nil { - if fs.Flag('#') { - fs.Write(interfaceBytes) - } - fs.Write(nilAngleBytes) - return - } - - f.format(reflect.ValueOf(f.value)) -} - -// newFormatter is a helper function to consolidate the logic from the various -// public methods which take varying config states. -func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter { - fs := &formatState{value: v, cs: cs} - fs.pointers = make(map[uintptr]int) - return fs -} - -/* -NewFormatter returns a custom formatter that satisfies the fmt.Formatter -interface. As a result, it integrates cleanly with standard fmt package -printing functions. The formatter is useful for inline printing of smaller data -types similar to the standard %v format specifier. - -The custom formatter only responds to the %v (most compact), %+v (adds pointer -addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb -combinations. Any other verbs such as %x and %q will be sent to the the -standard fmt package for formatting. In addition, the custom formatter ignores -the width and precision arguments (however they will still work on the format -specifiers not handled by the custom formatter). - -Typically this function shouldn't be called directly. It is much easier to make -use of the custom formatter by calling one of the convenience functions such as -Printf, Println, or Fprintf. -*/ -func NewFormatter(v interface{}) fmt.Formatter { - return newFormatter(&Config, v) -} diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/format_test.go b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/format_test.go deleted file mode 100644 index 87ee965..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/format_test.go +++ /dev/null @@ -1,1558 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins <dave@davec.name> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* -Test Summary: -NOTE: For each test, a nil pointer, a single pointer and double pointer to the -base test element are also tested to ensure proper indirection across all types. - -- Max int8, int16, int32, int64, int -- Max uint8, uint16, uint32, uint64, uint -- Boolean true and false -- Standard complex64 and complex128 -- Array containing standard ints -- Array containing type with custom formatter on pointer receiver only -- Array containing interfaces -- Slice containing standard float32 values -- Slice containing type with custom formatter on pointer receiver only -- Slice containing interfaces -- Nil slice -- Standard string -- Nil interface -- Sub-interface -- Map with string keys and int vals -- Map with custom formatter type on pointer receiver only keys and vals -- Map with interface keys and values -- Map with nil interface value -- Struct with primitives -- Struct that contains another struct -- Struct that contains custom type with Stringer pointer interface via both - exported and unexported fields -- Struct that contains embedded struct and field to same struct -- Uintptr to 0 (null pointer) -- Uintptr address of real variable -- Unsafe.Pointer to 0 (null pointer) -- Unsafe.Pointer to address of real variable -- Nil channel -- Standard int channel -- Function with no params and no returns -- Function with param and no returns -- Function with multiple params and multiple returns -- Struct that is circular through self referencing -- Structs that are circular through cross referencing -- Structs that are indirectly circular -- Type that panics in its Stringer interface -- Type that has a custom Error interface -- %x passthrough with uint -- %#x passthrough with uint -- %f passthrough with precision -- %f passthrough with width and precision -- %d passthrough with width -- %q passthrough with string -*/ - -package spew_test - -import ( - "bytes" - "fmt" - "testing" - "unsafe" - - "github.com/davecgh/go-spew/spew" -) - -// formatterTest is used to describe a test to be performed against NewFormatter. -type formatterTest struct { - format string - in interface{} - wants []string -} - -// formatterTests houses all of the tests to be performed against NewFormatter. -var formatterTests = make([]formatterTest, 0) - -// addFormatterTest is a helper method to append the passed input and desired -// result to formatterTests. -func addFormatterTest(format string, in interface{}, wants ...string) { - test := formatterTest{format, in, wants} - formatterTests = append(formatterTests, test) -} - -func addIntFormatterTests() { - // Max int8. - v := int8(127) - nv := (*int8)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "int8" - vs := "127" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%v", nv, "<nil>") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>") - - // Max int16. - v2 := int16(32767) - nv2 := (*int16)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "int16" - v2s := "32767" - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%v", nv2, "<nil>") - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%+v", nv2, "<nil>") - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>") - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>") - - // Max int32. - v3 := int32(2147483647) - nv3 := (*int32)(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "int32" - v3s := "2147483647" - addFormatterTest("%v", v3, v3s) - addFormatterTest("%v", pv3, "<*>"+v3s) - addFormatterTest("%v", &pv3, "<**>"+v3s) - addFormatterTest("%v", nv3, "<nil>") - addFormatterTest("%+v", v3, v3s) - addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) - addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) - addFormatterTest("%+v", nv3, "<nil>") - addFormatterTest("%#v", v3, "("+v3t+")"+v3s) - addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s) - addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s) - addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>") - addFormatterTest("%#+v", v3, "("+v3t+")"+v3s) - addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s) - addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s) - addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>") - - // Max int64. - v4 := int64(9223372036854775807) - nv4 := (*int64)(nil) - pv4 := &v4 - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "int64" - v4s := "9223372036854775807" - addFormatterTest("%v", v4, v4s) - addFormatterTest("%v", pv4, "<*>"+v4s) - addFormatterTest("%v", &pv4, "<**>"+v4s) - addFormatterTest("%v", nv4, "<nil>") - addFormatterTest("%+v", v4, v4s) - addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s) - addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s) - addFormatterTest("%+v", nv4, "<nil>") - addFormatterTest("%#v", v4, "("+v4t+")"+v4s) - addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s) - addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s) - addFormatterTest("%#v", nv4, "(*"+v4t+")"+"<nil>") - addFormatterTest("%#+v", v4, "("+v4t+")"+v4s) - addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s) - addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s) - addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"<nil>") - - // Max int. - v5 := int(2147483647) - nv5 := (*int)(nil) - pv5 := &v5 - v5Addr := fmt.Sprintf("%p", pv5) - pv5Addr := fmt.Sprintf("%p", &pv5) - v5t := "int" - v5s := "2147483647" - addFormatterTest("%v", v5, v5s) - addFormatterTest("%v", pv5, "<*>"+v5s) - addFormatterTest("%v", &pv5, "<**>"+v5s) - addFormatterTest("%v", nv5, "<nil>") - addFormatterTest("%+v", v5, v5s) - addFormatterTest("%+v", pv5, "<*>("+v5Addr+")"+v5s) - addFormatterTest("%+v", &pv5, "<**>("+pv5Addr+"->"+v5Addr+")"+v5s) - addFormatterTest("%+v", nv5, "<nil>") - addFormatterTest("%#v", v5, "("+v5t+")"+v5s) - addFormatterTest("%#v", pv5, "(*"+v5t+")"+v5s) - addFormatterTest("%#v", &pv5, "(**"+v5t+")"+v5s) - addFormatterTest("%#v", nv5, "(*"+v5t+")"+"<nil>") - addFormatterTest("%#+v", v5, "("+v5t+")"+v5s) - addFormatterTest("%#+v", pv5, "(*"+v5t+")("+v5Addr+")"+v5s) - addFormatterTest("%#+v", &pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")"+v5s) - addFormatterTest("%#+v", nv5, "(*"+v5t+")"+"<nil>") -} - -func addUintFormatterTests() { - // Max uint8. - v := uint8(255) - nv := (*uint8)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "uint8" - vs := "255" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%v", nv, "<nil>") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>") - - // Max uint16. - v2 := uint16(65535) - nv2 := (*uint16)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "uint16" - v2s := "65535" - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%v", nv2, "<nil>") - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%+v", nv2, "<nil>") - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>") - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>") - - // Max uint32. - v3 := uint32(4294967295) - nv3 := (*uint32)(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "uint32" - v3s := "4294967295" - addFormatterTest("%v", v3, v3s) - addFormatterTest("%v", pv3, "<*>"+v3s) - addFormatterTest("%v", &pv3, "<**>"+v3s) - addFormatterTest("%v", nv3, "<nil>") - addFormatterTest("%+v", v3, v3s) - addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) - addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) - addFormatterTest("%+v", nv3, "<nil>") - addFormatterTest("%#v", v3, "("+v3t+")"+v3s) - addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s) - addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s) - addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>") - addFormatterTest("%#+v", v3, "("+v3t+")"+v3s) - addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s) - addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s) - addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>") - - // Max uint64. - v4 := uint64(18446744073709551615) - nv4 := (*uint64)(nil) - pv4 := &v4 - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "uint64" - v4s := "18446744073709551615" - addFormatterTest("%v", v4, v4s) - addFormatterTest("%v", pv4, "<*>"+v4s) - addFormatterTest("%v", &pv4, "<**>"+v4s) - addFormatterTest("%v", nv4, "<nil>") - addFormatterTest("%+v", v4, v4s) - addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s) - addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s) - addFormatterTest("%+v", nv4, "<nil>") - addFormatterTest("%#v", v4, "("+v4t+")"+v4s) - addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s) - addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s) - addFormatterTest("%#v", nv4, "(*"+v4t+")"+"<nil>") - addFormatterTest("%#+v", v4, "("+v4t+")"+v4s) - addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s) - addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s) - addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"<nil>") - - // Max uint. - v5 := uint(4294967295) - nv5 := (*uint)(nil) - pv5 := &v5 - v5Addr := fmt.Sprintf("%p", pv5) - pv5Addr := fmt.Sprintf("%p", &pv5) - v5t := "uint" - v5s := "4294967295" - addFormatterTest("%v", v5, v5s) - addFormatterTest("%v", pv5, "<*>"+v5s) - addFormatterTest("%v", &pv5, "<**>"+v5s) - addFormatterTest("%v", nv5, "<nil>") - addFormatterTest("%+v", v5, v5s) - addFormatterTest("%+v", pv5, "<*>("+v5Addr+")"+v5s) - addFormatterTest("%+v", &pv5, "<**>("+pv5Addr+"->"+v5Addr+")"+v5s) - addFormatterTest("%+v", nv5, "<nil>") - addFormatterTest("%#v", v5, "("+v5t+")"+v5s) - addFormatterTest("%#v", pv5, "(*"+v5t+")"+v5s) - addFormatterTest("%#v", &pv5, "(**"+v5t+")"+v5s) - addFormatterTest("%#v", nv5, "(*"+v5t+")"+"<nil>") - addFormatterTest("%#+v", v5, "("+v5t+")"+v5s) - addFormatterTest("%#+v", pv5, "(*"+v5t+")("+v5Addr+")"+v5s) - addFormatterTest("%#+v", &pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")"+v5s) - addFormatterTest("%#v", nv5, "(*"+v5t+")"+"<nil>") -} - -func addBoolFormatterTests() { - // Boolean true. - v := bool(true) - nv := (*bool)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "bool" - vs := "true" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%v", nv, "<nil>") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>") - - // Boolean false. - v2 := bool(false) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "bool" - v2s := "false" - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) -} - -func addFloatFormatterTests() { - // Standard float32. - v := float32(3.1415) - nv := (*float32)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "float32" - vs := "3.1415" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%v", nv, "<nil>") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>") - - // Standard float64. - v2 := float64(3.1415926) - nv2 := (*float64)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "float64" - v2s := "3.1415926" - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", nv2, "<nil>") - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%+v", nv2, "<nil>") - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>") - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>") -} - -func addComplexFormatterTests() { - // Standard complex64. - v := complex(float32(6), -2) - nv := (*complex64)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "complex64" - vs := "(6-2i)" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>") - - // Standard complex128. - v2 := complex(float64(-6), 2) - nv2 := (*complex128)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "complex128" - v2s := "(-6+2i)" - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", nv2, "<nil>") - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%+v", nv2, "<nil>") - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>") - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>") -} - -func addArrayFormatterTests() { - // Array containing standard ints. - v := [3]int{1, 2, 3} - nv := (*[3]int)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "[3]int" - vs := "[1 2 3]" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>") - - // Array containing type with custom formatter on pointer receiver only. - v2 := [3]pstringer{"1", "2", "3"} - nv2 := (*[3]pstringer)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "[3]spew_test.pstringer" - v2sp := "[stringer 1 stringer 2 stringer 3]" - v2s := v2sp - if spew.UnsafeDisabled { - v2s = "[1 2 3]" - } - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2sp) - addFormatterTest("%v", &pv2, "<**>"+v2sp) - addFormatterTest("%+v", nv2, "<nil>") - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2sp) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2sp) - addFormatterTest("%+v", nv2, "<nil>") - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2sp) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2sp) - addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>") - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2sp) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2sp) - addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>") - - // Array containing interfaces. - v3 := [3]interface{}{"one", int(2), uint(3)} - nv3 := (*[3]interface{})(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "[3]interface {}" - v3t2 := "string" - v3t3 := "int" - v3t4 := "uint" - v3s := "[one 2 3]" - v3s2 := "[(" + v3t2 + ")one (" + v3t3 + ")2 (" + v3t4 + ")3]" - addFormatterTest("%v", v3, v3s) - addFormatterTest("%v", pv3, "<*>"+v3s) - addFormatterTest("%v", &pv3, "<**>"+v3s) - addFormatterTest("%+v", nv3, "<nil>") - addFormatterTest("%+v", v3, v3s) - addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) - addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) - addFormatterTest("%+v", nv3, "<nil>") - addFormatterTest("%#v", v3, "("+v3t+")"+v3s2) - addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s2) - addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s2) - addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>") - addFormatterTest("%#+v", v3, "("+v3t+")"+v3s2) - addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s2) - addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s2) - addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"<nil>") -} - -func addSliceFormatterTests() { - // Slice containing standard float32 values. - v := []float32{3.14, 6.28, 12.56} - nv := (*[]float32)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "[]float32" - vs := "[3.14 6.28 12.56]" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>") - - // Slice containing type with custom formatter on pointer receiver only. - v2 := []pstringer{"1", "2", "3"} - nv2 := (*[]pstringer)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "[]spew_test.pstringer" - v2s := "[stringer 1 stringer 2 stringer 3]" - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", nv2, "<nil>") - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%+v", nv2, "<nil>") - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>") - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>") - - // Slice containing interfaces. - v3 := []interface{}{"one", int(2), uint(3), nil} - nv3 := (*[]interface{})(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "[]interface {}" - v3t2 := "string" - v3t3 := "int" - v3t4 := "uint" - v3t5 := "interface {}" - v3s := "[one 2 3 <nil>]" - v3s2 := "[(" + v3t2 + ")one (" + v3t3 + ")2 (" + v3t4 + ")3 (" + v3t5 + - ")<nil>]" - addFormatterTest("%v", v3, v3s) - addFormatterTest("%v", pv3, "<*>"+v3s) - addFormatterTest("%v", &pv3, "<**>"+v3s) - addFormatterTest("%+v", nv3, "<nil>") - addFormatterTest("%+v", v3, v3s) - addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) - addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) - addFormatterTest("%+v", nv3, "<nil>") - addFormatterTest("%#v", v3, "("+v3t+")"+v3s2) - addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s2) - addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s2) - addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>") - addFormatterTest("%#+v", v3, "("+v3t+")"+v3s2) - addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s2) - addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s2) - addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"<nil>") - - // Nil slice. - var v4 []int - nv4 := (*[]int)(nil) - pv4 := &v4 - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "[]int" - v4s := "<nil>" - addFormatterTest("%v", v4, v4s) - addFormatterTest("%v", pv4, "<*>"+v4s) - addFormatterTest("%v", &pv4, "<**>"+v4s) - addFormatterTest("%+v", nv4, "<nil>") - addFormatterTest("%+v", v4, v4s) - addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s) - addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s) - addFormatterTest("%+v", nv4, "<nil>") - addFormatterTest("%#v", v4, "("+v4t+")"+v4s) - addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s) - addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s) - addFormatterTest("%#v", nv4, "(*"+v4t+")"+"<nil>") - addFormatterTest("%#+v", v4, "("+v4t+")"+v4s) - addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s) - addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s) - addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"<nil>") -} - -func addStringFormatterTests() { - // Standard string. - v := "test" - nv := (*string)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "string" - vs := "test" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>") -} - -func addInterfaceFormatterTests() { - // Nil interface. - var v interface{} - nv := (*interface{})(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "interface {}" - vs := "<nil>" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>") - - // Sub-interface. - v2 := interface{}(uint16(65535)) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "uint16" - v2s := "65535" - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) -} - -func addMapFormatterTests() { - // Map with string keys and int vals. - v := map[string]int{"one": 1, "two": 2} - nilMap := map[string]int(nil) - nv := (*map[string]int)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "map[string]int" - vs := "map[one:1 two:2]" - vs2 := "map[two:2 one:1]" - addFormatterTest("%v", v, vs, vs2) - addFormatterTest("%v", pv, "<*>"+vs, "<*>"+vs2) - addFormatterTest("%v", &pv, "<**>"+vs, "<**>"+vs2) - addFormatterTest("%+v", nilMap, "<nil>") - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%+v", v, vs, vs2) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs, "<*>("+vAddr+")"+vs2) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs, - "<**>("+pvAddr+"->"+vAddr+")"+vs2) - addFormatterTest("%+v", nilMap, "<nil>") - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%#v", v, "("+vt+")"+vs, "("+vt+")"+vs2) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs, "(*"+vt+")"+vs2) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs, "(**"+vt+")"+vs2) - addFormatterTest("%#v", nilMap, "("+vt+")"+"<nil>") - addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>") - addFormatterTest("%#+v", v, "("+vt+")"+vs, "("+vt+")"+vs2) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs, - "(*"+vt+")("+vAddr+")"+vs2) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs, - "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs2) - addFormatterTest("%#+v", nilMap, "("+vt+")"+"<nil>") - addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>") - - // Map with custom formatter type on pointer receiver only keys and vals. - v2 := map[pstringer]pstringer{"one": "1"} - nv2 := (*map[pstringer]pstringer)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "map[spew_test.pstringer]spew_test.pstringer" - v2s := "map[stringer one:stringer 1]" - if spew.UnsafeDisabled { - v2s = "map[one:1]" - } - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", nv2, "<nil>") - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%+v", nv2, "<nil>") - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>") - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>") - - // Map with interface keys and values. - v3 := map[interface{}]interface{}{"one": 1} - nv3 := (*map[interface{}]interface{})(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "map[interface {}]interface {}" - v3t1 := "string" - v3t2 := "int" - v3s := "map[one:1]" - v3s2 := "map[(" + v3t1 + ")one:(" + v3t2 + ")1]" - addFormatterTest("%v", v3, v3s) - addFormatterTest("%v", pv3, "<*>"+v3s) - addFormatterTest("%v", &pv3, "<**>"+v3s) - addFormatterTest("%+v", nv3, "<nil>") - addFormatterTest("%+v", v3, v3s) - addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) - addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) - addFormatterTest("%+v", nv3, "<nil>") - addFormatterTest("%#v", v3, "("+v3t+")"+v3s2) - addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s2) - addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s2) - addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>") - addFormatterTest("%#+v", v3, "("+v3t+")"+v3s2) - addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s2) - addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s2) - addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"<nil>") - - // Map with nil interface value - v4 := map[string]interface{}{"nil": nil} - nv4 := (*map[string]interface{})(nil) - pv4 := &v4 - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "map[string]interface {}" - v4t1 := "interface {}" - v4s := "map[nil:<nil>]" - v4s2 := "map[nil:(" + v4t1 + ")<nil>]" - addFormatterTest("%v", v4, v4s) - addFormatterTest("%v", pv4, "<*>"+v4s) - addFormatterTest("%v", &pv4, "<**>"+v4s) - addFormatterTest("%+v", nv4, "<nil>") - addFormatterTest("%+v", v4, v4s) - addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s) - addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s) - addFormatterTest("%+v", nv4, "<nil>") - addFormatterTest("%#v", v4, "("+v4t+")"+v4s2) - addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s2) - addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s2) - addFormatterTest("%#v", nv4, "(*"+v4t+")"+"<nil>") - addFormatterTest("%#+v", v4, "("+v4t+")"+v4s2) - addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s2) - addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s2) - addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"<nil>") -} - -func addStructFormatterTests() { - // Struct with primitives. - type s1 struct { - a int8 - b uint8 - } - v := s1{127, 255} - nv := (*s1)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "spew_test.s1" - vt2 := "int8" - vt3 := "uint8" - vs := "{127 255}" - vs2 := "{a:127 b:255}" - vs3 := "{a:(" + vt2 + ")127 b:(" + vt3 + ")255}" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%+v", v, vs2) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs2) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs2) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%#v", v, "("+vt+")"+vs3) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs3) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs3) - addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>") - addFormatterTest("%#+v", v, "("+vt+")"+vs3) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs3) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs3) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>") - - // Struct that contains another struct. - type s2 struct { - s1 s1 - b bool - } - v2 := s2{s1{127, 255}, true} - nv2 := (*s2)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "spew_test.s2" - v2t2 := "spew_test.s1" - v2t3 := "int8" - v2t4 := "uint8" - v2t5 := "bool" - v2s := "{{127 255} true}" - v2s2 := "{s1:{a:127 b:255} b:true}" - v2s3 := "{s1:(" + v2t2 + "){a:(" + v2t3 + ")127 b:(" + v2t4 + ")255} b:(" + - v2t5 + ")true}" - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", nv2, "<nil>") - addFormatterTest("%+v", v2, v2s2) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s2) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s2) - addFormatterTest("%+v", nv2, "<nil>") - addFormatterTest("%#v", v2, "("+v2t+")"+v2s3) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s3) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s3) - addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>") - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s3) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s3) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s3) - addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>") - - // Struct that contains custom type with Stringer pointer interface via both - // exported and unexported fields. - type s3 struct { - s pstringer - S pstringer - } - v3 := s3{"test", "test2"} - nv3 := (*s3)(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "spew_test.s3" - v3t2 := "spew_test.pstringer" - v3s := "{stringer test stringer test2}" - v3sp := v3s - v3s2 := "{s:stringer test S:stringer test2}" - v3s2p := v3s2 - v3s3 := "{s:(" + v3t2 + ")stringer test S:(" + v3t2 + ")stringer test2}" - v3s3p := v3s3 - if spew.UnsafeDisabled { - v3s = "{test test2}" - v3sp = "{test stringer test2}" - v3s2 = "{s:test S:test2}" - v3s2p = "{s:test S:stringer test2}" - v3s3 = "{s:(" + v3t2 + ")test S:(" + v3t2 + ")test2}" - v3s3p = "{s:(" + v3t2 + ")test S:(" + v3t2 + ")stringer test2}" - } - addFormatterTest("%v", v3, v3s) - addFormatterTest("%v", pv3, "<*>"+v3sp) - addFormatterTest("%v", &pv3, "<**>"+v3sp) - addFormatterTest("%+v", nv3, "<nil>") - addFormatterTest("%+v", v3, v3s2) - addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s2p) - addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s2p) - addFormatterTest("%+v", nv3, "<nil>") - addFormatterTest("%#v", v3, "("+v3t+")"+v3s3) - addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s3p) - addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s3p) - addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>") - addFormatterTest("%#+v", v3, "("+v3t+")"+v3s3) - addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s3p) - addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s3p) - addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"<nil>") - - // Struct that contains embedded struct and field to same struct. - e := embed{"embedstr"} - v4 := embedwrap{embed: &e, e: &e} - nv4 := (*embedwrap)(nil) - pv4 := &v4 - eAddr := fmt.Sprintf("%p", &e) - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "spew_test.embedwrap" - v4t2 := "spew_test.embed" - v4t3 := "string" - v4s := "{<*>{embedstr} <*>{embedstr}}" - v4s2 := "{embed:<*>(" + eAddr + "){a:embedstr} e:<*>(" + eAddr + - "){a:embedstr}}" - v4s3 := "{embed:(*" + v4t2 + "){a:(" + v4t3 + ")embedstr} e:(*" + v4t2 + - "){a:(" + v4t3 + ")embedstr}}" - v4s4 := "{embed:(*" + v4t2 + ")(" + eAddr + "){a:(" + v4t3 + - ")embedstr} e:(*" + v4t2 + ")(" + eAddr + "){a:(" + v4t3 + ")embedstr}}" - addFormatterTest("%v", v4, v4s) - addFormatterTest("%v", pv4, "<*>"+v4s) - addFormatterTest("%v", &pv4, "<**>"+v4s) - addFormatterTest("%+v", nv4, "<nil>") - addFormatterTest("%+v", v4, v4s2) - addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s2) - addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s2) - addFormatterTest("%+v", nv4, "<nil>") - addFormatterTest("%#v", v4, "("+v4t+")"+v4s3) - addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s3) - addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s3) - addFormatterTest("%#v", nv4, "(*"+v4t+")"+"<nil>") - addFormatterTest("%#+v", v4, "("+v4t+")"+v4s4) - addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s4) - addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s4) - addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"<nil>") -} - -func addUintptrFormatterTests() { - // Null pointer. - v := uintptr(0) - nv := (*uintptr)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "uintptr" - vs := "<nil>" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>") - - // Address of real variable. - i := 1 - v2 := uintptr(unsafe.Pointer(&i)) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "uintptr" - v2s := fmt.Sprintf("%p", &i) - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) -} - -func addUnsafePointerFormatterTests() { - // Null pointer. - v := unsafe.Pointer(nil) - nv := (*unsafe.Pointer)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "unsafe.Pointer" - vs := "<nil>" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>") - - // Address of real variable. - i := 1 - v2 := unsafe.Pointer(&i) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "unsafe.Pointer" - v2s := fmt.Sprintf("%p", &i) - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) -} - -func addChanFormatterTests() { - // Nil channel. - var v chan int - pv := &v - nv := (*chan int)(nil) - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "chan int" - vs := "<nil>" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>") - - // Real channel. - v2 := make(chan int) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "chan int" - v2s := fmt.Sprintf("%p", v2) - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) -} - -func addFuncFormatterTests() { - // Function with no params and no returns. - v := addIntFormatterTests - nv := (*func())(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "func()" - vs := fmt.Sprintf("%p", v) - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>") - - // Function with param and no returns. - v2 := TestFormatter - nv2 := (*func(*testing.T))(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "func(*testing.T)" - v2s := fmt.Sprintf("%p", v2) - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", nv2, "<nil>") - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%+v", nv2, "<nil>") - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>") - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>") - - // Function with multiple params and multiple returns. - var v3 = func(i int, s string) (b bool, err error) { - return true, nil - } - nv3 := (*func(int, string) (bool, error))(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "func(int, string) (bool, error)" - v3s := fmt.Sprintf("%p", v3) - addFormatterTest("%v", v3, v3s) - addFormatterTest("%v", pv3, "<*>"+v3s) - addFormatterTest("%v", &pv3, "<**>"+v3s) - addFormatterTest("%+v", nv3, "<nil>") - addFormatterTest("%+v", v3, v3s) - addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) - addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) - addFormatterTest("%+v", nv3, "<nil>") - addFormatterTest("%#v", v3, "("+v3t+")"+v3s) - addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s) - addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s) - addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>") - addFormatterTest("%#+v", v3, "("+v3t+")"+v3s) - addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s) - addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s) - addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"<nil>") -} - -func addCircularFormatterTests() { - // Struct that is circular through self referencing. - type circular struct { - c *circular - } - v := circular{nil} - v.c = &v - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "spew_test.circular" - vs := "{<*>{<*><shown>}}" - vs2 := "{<*><shown>}" - vs3 := "{c:<*>(" + vAddr + "){c:<*>(" + vAddr + ")<shown>}}" - vs4 := "{c:<*>(" + vAddr + ")<shown>}" - vs5 := "{c:(*" + vt + "){c:(*" + vt + ")<shown>}}" - vs6 := "{c:(*" + vt + ")<shown>}" - vs7 := "{c:(*" + vt + ")(" + vAddr + "){c:(*" + vt + ")(" + vAddr + - ")<shown>}}" - vs8 := "{c:(*" + vt + ")(" + vAddr + ")<shown>}" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs2) - addFormatterTest("%v", &pv, "<**>"+vs2) - addFormatterTest("%+v", v, vs3) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs4) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs4) - addFormatterTest("%#v", v, "("+vt+")"+vs5) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs6) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs6) - addFormatterTest("%#+v", v, "("+vt+")"+vs7) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs8) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs8) - - // Structs that are circular through cross referencing. - v2 := xref1{nil} - ts2 := xref2{&v2} - v2.ps2 = &ts2 - pv2 := &v2 - ts2Addr := fmt.Sprintf("%p", &ts2) - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "spew_test.xref1" - v2t2 := "spew_test.xref2" - v2s := "{<*>{<*>{<*><shown>}}}" - v2s2 := "{<*>{<*><shown>}}" - v2s3 := "{ps2:<*>(" + ts2Addr + "){ps1:<*>(" + v2Addr + "){ps2:<*>(" + - ts2Addr + ")<shown>}}}" - v2s4 := "{ps2:<*>(" + ts2Addr + "){ps1:<*>(" + v2Addr + ")<shown>}}" - v2s5 := "{ps2:(*" + v2t2 + "){ps1:(*" + v2t + "){ps2:(*" + v2t2 + - ")<shown>}}}" - v2s6 := "{ps2:(*" + v2t2 + "){ps1:(*" + v2t + ")<shown>}}" - v2s7 := "{ps2:(*" + v2t2 + ")(" + ts2Addr + "){ps1:(*" + v2t + - ")(" + v2Addr + "){ps2:(*" + v2t2 + ")(" + ts2Addr + - ")<shown>}}}" - v2s8 := "{ps2:(*" + v2t2 + ")(" + ts2Addr + "){ps1:(*" + v2t + - ")(" + v2Addr + ")<shown>}}" - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s2) - addFormatterTest("%v", &pv2, "<**>"+v2s2) - addFormatterTest("%+v", v2, v2s3) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s4) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s4) - addFormatterTest("%#v", v2, "("+v2t+")"+v2s5) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s6) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s6) - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s7) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s8) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s8) - - // Structs that are indirectly circular. - v3 := indirCir1{nil} - tic2 := indirCir2{nil} - tic3 := indirCir3{&v3} - tic2.ps3 = &tic3 - v3.ps2 = &tic2 - pv3 := &v3 - tic2Addr := fmt.Sprintf("%p", &tic2) - tic3Addr := fmt.Sprintf("%p", &tic3) - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "spew_test.indirCir1" - v3t2 := "spew_test.indirCir2" - v3t3 := "spew_test.indirCir3" - v3s := "{<*>{<*>{<*>{<*><shown>}}}}" - v3s2 := "{<*>{<*>{<*><shown>}}}" - v3s3 := "{ps2:<*>(" + tic2Addr + "){ps3:<*>(" + tic3Addr + "){ps1:<*>(" + - v3Addr + "){ps2:<*>(" + tic2Addr + ")<shown>}}}}" - v3s4 := "{ps2:<*>(" + tic2Addr + "){ps3:<*>(" + tic3Addr + "){ps1:<*>(" + - v3Addr + ")<shown>}}}" - v3s5 := "{ps2:(*" + v3t2 + "){ps3:(*" + v3t3 + "){ps1:(*" + v3t + - "){ps2:(*" + v3t2 + ")<shown>}}}}" - v3s6 := "{ps2:(*" + v3t2 + "){ps3:(*" + v3t3 + "){ps1:(*" + v3t + - ")<shown>}}}" - v3s7 := "{ps2:(*" + v3t2 + ")(" + tic2Addr + "){ps3:(*" + v3t3 + ")(" + - tic3Addr + "){ps1:(*" + v3t + ")(" + v3Addr + "){ps2:(*" + v3t2 + - ")(" + tic2Addr + ")<shown>}}}}" - v3s8 := "{ps2:(*" + v3t2 + ")(" + tic2Addr + "){ps3:(*" + v3t3 + ")(" + - tic3Addr + "){ps1:(*" + v3t + ")(" + v3Addr + ")<shown>}}}" - addFormatterTest("%v", v3, v3s) - addFormatterTest("%v", pv3, "<*>"+v3s2) - addFormatterTest("%v", &pv3, "<**>"+v3s2) - addFormatterTest("%+v", v3, v3s3) - addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s4) - addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s4) - addFormatterTest("%#v", v3, "("+v3t+")"+v3s5) - addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s6) - addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s6) - addFormatterTest("%#+v", v3, "("+v3t+")"+v3s7) - addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s8) - addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s8) -} - -func addPanicFormatterTests() { - // Type that panics in its Stringer interface. - v := panicer(127) - nv := (*panicer)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "spew_test.panicer" - vs := "(PANIC=test panic)127" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%v", nv, "<nil>") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>") -} - -func addErrorFormatterTests() { - // Type that has a custom Error interface. - v := customError(127) - nv := (*customError)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "spew_test.customError" - vs := "error: 127" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%v", nv, "<nil>") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "<nil>") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>") -} - -func addPassthroughFormatterTests() { - // %x passthrough with uint. - v := uint(4294967295) - pv := &v - vAddr := fmt.Sprintf("%x", pv) - pvAddr := fmt.Sprintf("%x", &pv) - vs := "ffffffff" - addFormatterTest("%x", v, vs) - addFormatterTest("%x", pv, vAddr) - addFormatterTest("%x", &pv, pvAddr) - - // %#x passthrough with uint. - v2 := int(2147483647) - pv2 := &v2 - v2Addr := fmt.Sprintf("%#x", pv2) - pv2Addr := fmt.Sprintf("%#x", &pv2) - v2s := "0x7fffffff" - addFormatterTest("%#x", v2, v2s) - addFormatterTest("%#x", pv2, v2Addr) - addFormatterTest("%#x", &pv2, pv2Addr) - - // %f passthrough with precision. - addFormatterTest("%.2f", 3.1415, "3.14") - addFormatterTest("%.3f", 3.1415, "3.142") - addFormatterTest("%.4f", 3.1415, "3.1415") - - // %f passthrough with width and precision. - addFormatterTest("%5.2f", 3.1415, " 3.14") - addFormatterTest("%6.3f", 3.1415, " 3.142") - addFormatterTest("%7.4f", 3.1415, " 3.1415") - - // %d passthrough with width. - addFormatterTest("%3d", 127, "127") - addFormatterTest("%4d", 127, " 127") - addFormatterTest("%5d", 127, " 127") - - // %q passthrough with string. - addFormatterTest("%q", "test", "\"test\"") -} - -// TestFormatter executes all of the tests described by formatterTests. -func TestFormatter(t *testing.T) { - // Setup tests. - addIntFormatterTests() - addUintFormatterTests() - addBoolFormatterTests() - addFloatFormatterTests() - addComplexFormatterTests() - addArrayFormatterTests() - addSliceFormatterTests() - addStringFormatterTests() - addInterfaceFormatterTests() - addMapFormatterTests() - addStructFormatterTests() - addUintptrFormatterTests() - addUnsafePointerFormatterTests() - addChanFormatterTests() - addFuncFormatterTests() - addCircularFormatterTests() - addPanicFormatterTests() - addErrorFormatterTests() - addPassthroughFormatterTests() - - t.Logf("Running %d tests", len(formatterTests)) - for i, test := range formatterTests { - buf := new(bytes.Buffer) - spew.Fprintf(buf, test.format, test.in) - s := buf.String() - if testFailed(s, test.wants) { - t.Errorf("Formatter #%d format: %s got: %s %s", i, test.format, s, - stringizeWants(test.wants)) - continue - } - } -} - -type testStruct struct { - x int -} - -func (ts testStruct) String() string { - return fmt.Sprintf("ts.%d", ts.x) -} - -type testStructP struct { - x int -} - -func (ts *testStructP) String() string { - return fmt.Sprintf("ts.%d", ts.x) -} - -func TestPrintSortedKeys(t *testing.T) { - cfg := spew.ConfigState{SortKeys: true} - s := cfg.Sprint(map[int]string{1: "1", 3: "3", 2: "2"}) - expected := "map[1:1 2:2 3:3]" - if s != expected { - t.Errorf("Sorted keys mismatch 1:\n %v %v", s, expected) - } - - s = cfg.Sprint(map[stringer]int{"1": 1, "3": 3, "2": 2}) - expected = "map[stringer 1:1 stringer 2:2 stringer 3:3]" - if s != expected { - t.Errorf("Sorted keys mismatch 2:\n %v %v", s, expected) - } - - s = cfg.Sprint(map[pstringer]int{pstringer("1"): 1, pstringer("3"): 3, pstringer("2"): 2}) - expected = "map[stringer 1:1 stringer 2:2 stringer 3:3]" - if spew.UnsafeDisabled { - expected = "map[1:1 2:2 3:3]" - } - if s != expected { - t.Errorf("Sorted keys mismatch 3:\n %v %v", s, expected) - } - - s = cfg.Sprint(map[testStruct]int{{1}: 1, {3}: 3, {2}: 2}) - expected = "map[ts.1:1 ts.2:2 ts.3:3]" - if s != expected { - t.Errorf("Sorted keys mismatch 4:\n %v %v", s, expected) - } - - if !spew.UnsafeDisabled { - s = cfg.Sprint(map[testStructP]int{{1}: 1, {3}: 3, {2}: 2}) - expected = "map[ts.1:1 ts.2:2 ts.3:3]" - if s != expected { - t.Errorf("Sorted keys mismatch 5:\n %v %v", s, expected) - } - } - - s = cfg.Sprint(map[customError]int{customError(1): 1, customError(3): 3, customError(2): 2}) - expected = "map[error: 1:1 error: 2:2 error: 3:3]" - if s != expected { - t.Errorf("Sorted keys mismatch 6:\n %v %v", s, expected) - } -} diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/internal_test.go b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/internal_test.go deleted file mode 100644 index e312b4f..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/internal_test.go +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins <dave@davec.name> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* -This test file is part of the spew package rather than than the spew_test -package because it needs access to internals to properly test certain cases -which are not possible via the public interface since they should never happen. -*/ - -package spew - -import ( - "bytes" - "reflect" - "testing" -) - -// dummyFmtState implements a fake fmt.State to use for testing invalid -// reflect.Value handling. This is necessary because the fmt package catches -// invalid values before invoking the formatter on them. -type dummyFmtState struct { - bytes.Buffer -} - -func (dfs *dummyFmtState) Flag(f int) bool { - return f == int('+') -} - -func (dfs *dummyFmtState) Precision() (int, bool) { - return 0, false -} - -func (dfs *dummyFmtState) Width() (int, bool) { - return 0, false -} - -// TestInvalidReflectValue ensures the dump and formatter code handles an -// invalid reflect value properly. This needs access to internal state since it -// should never happen in real code and therefore can't be tested via the public -// API. -func TestInvalidReflectValue(t *testing.T) { - i := 1 - - // Dump invalid reflect value. - v := new(reflect.Value) - buf := new(bytes.Buffer) - d := dumpState{w: buf, cs: &Config} - d.dump(*v) - s := buf.String() - want := "<invalid>" - if s != want { - t.Errorf("InvalidReflectValue #%d\n got: %s want: %s", i, s, want) - } - i++ - - // Formatter invalid reflect value. - buf2 := new(dummyFmtState) - f := formatState{value: *v, cs: &Config, fs: buf2} - f.format(*v) - s = buf2.String() - want = "<invalid>" - if s != want { - t.Errorf("InvalidReflectValue #%d got: %s want: %s", i, s, want) - } -} - -// SortValues makes the internal sortValues function available to the test -// package. -func SortValues(values []reflect.Value, cs *ConfigState) { - sortValues(values, cs) -} diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/internalunsafe_test.go b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/internalunsafe_test.go deleted file mode 100644 index 80dc221..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/internalunsafe_test.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) 2013-2016 Dave Collins <dave@davec.name> - -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. - -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -// NOTE: Due to the following build constraints, this file will only be compiled -// when the code is not running on Google App Engine, compiled by GopherJS, and -// "-tags safe" is not added to the go build command line. The "disableunsafe" -// tag is deprecated and thus should not be used. -// +build !js,!appengine,!safe,!disableunsafe,go1.4 - -/* -This test file is part of the spew package rather than than the spew_test -package because it needs access to internals to properly test certain cases -which are not possible via the public interface since they should never happen. -*/ - -package spew - -import ( - "bytes" - "reflect" - "testing" -) - -// changeKind uses unsafe to intentionally change the kind of a reflect.Value to -// the maximum kind value which does not exist. This is needed to test the -// fallback code which punts to the standard fmt library for new types that -// might get added to the language. -func changeKind(v *reflect.Value, readOnly bool) { - flags := flagField(v) - if readOnly { - *flags |= flagRO - } else { - *flags &^= flagRO - } - *flags |= flagKindMask -} - -// TestAddedReflectValue tests functionaly of the dump and formatter code which -// falls back to the standard fmt library for new types that might get added to -// the language. -func TestAddedReflectValue(t *testing.T) { - i := 1 - - // Dump using a reflect.Value that is exported. - v := reflect.ValueOf(int8(5)) - changeKind(&v, false) - buf := new(bytes.Buffer) - d := dumpState{w: buf, cs: &Config} - d.dump(v) - s := buf.String() - want := "(int8) 5" - if s != want { - t.Errorf("TestAddedReflectValue #%d\n got: %s want: %s", i, s, want) - } - i++ - - // Dump using a reflect.Value that is not exported. - changeKind(&v, true) - buf.Reset() - d.dump(v) - s = buf.String() - want = "(int8) <int8 Value>" - if s != want { - t.Errorf("TestAddedReflectValue #%d\n got: %s want: %s", i, s, want) - } - i++ - - // Formatter using a reflect.Value that is exported. - changeKind(&v, false) - buf2 := new(dummyFmtState) - f := formatState{value: v, cs: &Config, fs: buf2} - f.format(v) - s = buf2.String() - want = "5" - if s != want { - t.Errorf("TestAddedReflectValue #%d got: %s want: %s", i, s, want) - } - i++ - - // Formatter using a reflect.Value that is not exported. - changeKind(&v, true) - buf2.Reset() - f = formatState{value: v, cs: &Config, fs: buf2} - f.format(v) - s = buf2.String() - want = "<int8 Value>" - if s != want { - t.Errorf("TestAddedReflectValue #%d got: %s want: %s", i, s, want) - } -} diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/spew.go b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/spew.go deleted file mode 100644 index 32c0e33..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/spew.go +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins <dave@davec.name> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew - -import ( - "fmt" - "io" -) - -// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the formatted string as a value that satisfies error. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b)) -func Errorf(format string, a ...interface{}) (err error) { - return fmt.Errorf(format, convertArgs(a)...) -} - -// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b)) -func Fprint(w io.Writer, a ...interface{}) (n int, err error) { - return fmt.Fprint(w, convertArgs(a)...) -} - -// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b)) -func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { - return fmt.Fprintf(w, format, convertArgs(a)...) -} - -// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it -// passed with a default Formatter interface returned by NewFormatter. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b)) -func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { - return fmt.Fprintln(w, convertArgs(a)...) -} - -// Print is a wrapper for fmt.Print that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b)) -func Print(a ...interface{}) (n int, err error) { - return fmt.Print(convertArgs(a)...) -} - -// Printf is a wrapper for fmt.Printf that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b)) -func Printf(format string, a ...interface{}) (n int, err error) { - return fmt.Printf(format, convertArgs(a)...) -} - -// Println is a wrapper for fmt.Println that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b)) -func Println(a ...interface{}) (n int, err error) { - return fmt.Println(convertArgs(a)...) -} - -// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the resulting string. See NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b)) -func Sprint(a ...interface{}) string { - return fmt.Sprint(convertArgs(a)...) -} - -// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the resulting string. See NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b)) -func Sprintf(format string, a ...interface{}) string { - return fmt.Sprintf(format, convertArgs(a)...) -} - -// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it -// were passed with a default Formatter interface returned by NewFormatter. It -// returns the resulting string. See NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b)) -func Sprintln(a ...interface{}) string { - return fmt.Sprintln(convertArgs(a)...) -} - -// convertArgs accepts a slice of arguments and returns a slice of the same -// length with each argument converted to a default spew Formatter interface. -func convertArgs(args []interface{}) (formatters []interface{}) { - formatters = make([]interface{}, len(args)) - for index, arg := range args { - formatters[index] = NewFormatter(arg) - } - return formatters -} diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/spew_test.go b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/spew_test.go deleted file mode 100644 index b70466c..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/spew_test.go +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins <dave@davec.name> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew_test - -import ( - "bytes" - "fmt" - "io/ioutil" - "os" - "testing" - - "github.com/davecgh/go-spew/spew" -) - -// spewFunc is used to identify which public function of the spew package or -// ConfigState a test applies to. -type spewFunc int - -const ( - fCSFdump spewFunc = iota - fCSFprint - fCSFprintf - fCSFprintln - fCSPrint - fCSPrintln - fCSSdump - fCSSprint - fCSSprintf - fCSSprintln - fCSErrorf - fCSNewFormatter - fErrorf - fFprint - fFprintln - fPrint - fPrintln - fSdump - fSprint - fSprintf - fSprintln -) - -// Map of spewFunc values to names for pretty printing. -var spewFuncStrings = map[spewFunc]string{ - fCSFdump: "ConfigState.Fdump", - fCSFprint: "ConfigState.Fprint", - fCSFprintf: "ConfigState.Fprintf", - fCSFprintln: "ConfigState.Fprintln", - fCSSdump: "ConfigState.Sdump", - fCSPrint: "ConfigState.Print", - fCSPrintln: "ConfigState.Println", - fCSSprint: "ConfigState.Sprint", - fCSSprintf: "ConfigState.Sprintf", - fCSSprintln: "ConfigState.Sprintln", - fCSErrorf: "ConfigState.Errorf", - fCSNewFormatter: "ConfigState.NewFormatter", - fErrorf: "spew.Errorf", - fFprint: "spew.Fprint", - fFprintln: "spew.Fprintln", - fPrint: "spew.Print", - fPrintln: "spew.Println", - fSdump: "spew.Sdump", - fSprint: "spew.Sprint", - fSprintf: "spew.Sprintf", - fSprintln: "spew.Sprintln", -} - -func (f spewFunc) String() string { - if s, ok := spewFuncStrings[f]; ok { - return s - } - return fmt.Sprintf("Unknown spewFunc (%d)", int(f)) -} - -// spewTest is used to describe a test to be performed against the public -// functions of the spew package or ConfigState. -type spewTest struct { - cs *spew.ConfigState - f spewFunc - format string - in interface{} - want string -} - -// spewTests houses the tests to be performed against the public functions of -// the spew package and ConfigState. -// -// These tests are only intended to ensure the public functions are exercised -// and are intentionally not exhaustive of types. The exhaustive type -// tests are handled in the dump and format tests. -var spewTests []spewTest - -// redirStdout is a helper function to return the standard output from f as a -// byte slice. -func redirStdout(f func()) ([]byte, error) { - tempFile, err := ioutil.TempFile("", "ss-test") - if err != nil { - return nil, err - } - fileName := tempFile.Name() - defer os.Remove(fileName) // Ignore error - - origStdout := os.Stdout - os.Stdout = tempFile - f() - os.Stdout = origStdout - tempFile.Close() - - return ioutil.ReadFile(fileName) -} - -func initSpewTests() { - // Config states with various settings. - scsDefault := spew.NewDefaultConfig() - scsNoMethods := &spew.ConfigState{Indent: " ", DisableMethods: true} - scsNoPmethods := &spew.ConfigState{Indent: " ", DisablePointerMethods: true} - scsMaxDepth := &spew.ConfigState{Indent: " ", MaxDepth: 1} - scsContinue := &spew.ConfigState{Indent: " ", ContinueOnMethod: true} - scsNoPtrAddr := &spew.ConfigState{DisablePointerAddresses: true} - scsNoCap := &spew.ConfigState{DisableCapacities: true} - - // Variables for tests on types which implement Stringer interface with and - // without a pointer receiver. - ts := stringer("test") - tps := pstringer("test") - - type ptrTester struct { - s *struct{} - } - tptr := &ptrTester{s: &struct{}{}} - - // depthTester is used to test max depth handling for structs, array, slices - // and maps. - type depthTester struct { - ic indirCir1 - arr [1]string - slice []string - m map[string]int - } - dt := depthTester{indirCir1{nil}, [1]string{"arr"}, []string{"slice"}, - map[string]int{"one": 1}} - - // Variable for tests on types which implement error interface. - te := customError(10) - - spewTests = []spewTest{ - {scsDefault, fCSFdump, "", int8(127), "(int8) 127\n"}, - {scsDefault, fCSFprint, "", int16(32767), "32767"}, - {scsDefault, fCSFprintf, "%v", int32(2147483647), "2147483647"}, - {scsDefault, fCSFprintln, "", int(2147483647), "2147483647\n"}, - {scsDefault, fCSPrint, "", int64(9223372036854775807), "9223372036854775807"}, - {scsDefault, fCSPrintln, "", uint8(255), "255\n"}, - {scsDefault, fCSSdump, "", uint8(64), "(uint8) 64\n"}, - {scsDefault, fCSSprint, "", complex(1, 2), "(1+2i)"}, - {scsDefault, fCSSprintf, "%v", complex(float32(3), 4), "(3+4i)"}, - {scsDefault, fCSSprintln, "", complex(float64(5), 6), "(5+6i)\n"}, - {scsDefault, fCSErrorf, "%#v", uint16(65535), "(uint16)65535"}, - {scsDefault, fCSNewFormatter, "%v", uint32(4294967295), "4294967295"}, - {scsDefault, fErrorf, "%v", uint64(18446744073709551615), "18446744073709551615"}, - {scsDefault, fFprint, "", float32(3.14), "3.14"}, - {scsDefault, fFprintln, "", float64(6.28), "6.28\n"}, - {scsDefault, fPrint, "", true, "true"}, - {scsDefault, fPrintln, "", false, "false\n"}, - {scsDefault, fSdump, "", complex(-10, -20), "(complex128) (-10-20i)\n"}, - {scsDefault, fSprint, "", complex(-1, -2), "(-1-2i)"}, - {scsDefault, fSprintf, "%v", complex(float32(-3), -4), "(-3-4i)"}, - {scsDefault, fSprintln, "", complex(float64(-5), -6), "(-5-6i)\n"}, - {scsNoMethods, fCSFprint, "", ts, "test"}, - {scsNoMethods, fCSFprint, "", &ts, "<*>test"}, - {scsNoMethods, fCSFprint, "", tps, "test"}, - {scsNoMethods, fCSFprint, "", &tps, "<*>test"}, - {scsNoPmethods, fCSFprint, "", ts, "stringer test"}, - {scsNoPmethods, fCSFprint, "", &ts, "<*>stringer test"}, - {scsNoPmethods, fCSFprint, "", tps, "test"}, - {scsNoPmethods, fCSFprint, "", &tps, "<*>stringer test"}, - {scsMaxDepth, fCSFprint, "", dt, "{{<max>} [<max>] [<max>] map[<max>]}"}, - {scsMaxDepth, fCSFdump, "", dt, "(spew_test.depthTester) {\n" + - " ic: (spew_test.indirCir1) {\n <max depth reached>\n },\n" + - " arr: ([1]string) (len=1 cap=1) {\n <max depth reached>\n },\n" + - " slice: ([]string) (len=1 cap=1) {\n <max depth reached>\n },\n" + - " m: (map[string]int) (len=1) {\n <max depth reached>\n }\n}\n"}, - {scsContinue, fCSFprint, "", ts, "(stringer test) test"}, - {scsContinue, fCSFdump, "", ts, "(spew_test.stringer) " + - "(len=4) (stringer test) \"test\"\n"}, - {scsContinue, fCSFprint, "", te, "(error: 10) 10"}, - {scsContinue, fCSFdump, "", te, "(spew_test.customError) " + - "(error: 10) 10\n"}, - {scsNoPtrAddr, fCSFprint, "", tptr, "<*>{<*>{}}"}, - {scsNoPtrAddr, fCSSdump, "", tptr, "(*spew_test.ptrTester)({\ns: (*struct {})({\n})\n})\n"}, - {scsNoCap, fCSSdump, "", make([]string, 0, 10), "([]string) {\n}\n"}, - {scsNoCap, fCSSdump, "", make([]string, 1, 10), "([]string) (len=1) {\n(string) \"\"\n}\n"}, - } -} - -// TestSpew executes all of the tests described by spewTests. -func TestSpew(t *testing.T) { - initSpewTests() - - t.Logf("Running %d tests", len(spewTests)) - for i, test := range spewTests { - buf := new(bytes.Buffer) - switch test.f { - case fCSFdump: - test.cs.Fdump(buf, test.in) - - case fCSFprint: - test.cs.Fprint(buf, test.in) - - case fCSFprintf: - test.cs.Fprintf(buf, test.format, test.in) - - case fCSFprintln: - test.cs.Fprintln(buf, test.in) - - case fCSPrint: - b, err := redirStdout(func() { test.cs.Print(test.in) }) - if err != nil { - t.Errorf("%v #%d %v", test.f, i, err) - continue - } - buf.Write(b) - - case fCSPrintln: - b, err := redirStdout(func() { test.cs.Println(test.in) }) - if err != nil { - t.Errorf("%v #%d %v", test.f, i, err) - continue - } - buf.Write(b) - - case fCSSdump: - str := test.cs.Sdump(test.in) - buf.WriteString(str) - - case fCSSprint: - str := test.cs.Sprint(test.in) - buf.WriteString(str) - - case fCSSprintf: - str := test.cs.Sprintf(test.format, test.in) - buf.WriteString(str) - - case fCSSprintln: - str := test.cs.Sprintln(test.in) - buf.WriteString(str) - - case fCSErrorf: - err := test.cs.Errorf(test.format, test.in) - buf.WriteString(err.Error()) - - case fCSNewFormatter: - fmt.Fprintf(buf, test.format, test.cs.NewFormatter(test.in)) - - case fErrorf: - err := spew.Errorf(test.format, test.in) - buf.WriteString(err.Error()) - - case fFprint: - spew.Fprint(buf, test.in) - - case fFprintln: - spew.Fprintln(buf, test.in) - - case fPrint: - b, err := redirStdout(func() { spew.Print(test.in) }) - if err != nil { - t.Errorf("%v #%d %v", test.f, i, err) - continue - } - buf.Write(b) - - case fPrintln: - b, err := redirStdout(func() { spew.Println(test.in) }) - if err != nil { - t.Errorf("%v #%d %v", test.f, i, err) - continue - } - buf.Write(b) - - case fSdump: - str := spew.Sdump(test.in) - buf.WriteString(str) - - case fSprint: - str := spew.Sprint(test.in) - buf.WriteString(str) - - case fSprintf: - str := spew.Sprintf(test.format, test.in) - buf.WriteString(str) - - case fSprintln: - str := spew.Sprintln(test.in) - buf.WriteString(str) - - default: - t.Errorf("%v #%d unrecognized function", test.f, i) - continue - } - s := buf.String() - if test.want != s { - t.Errorf("ConfigState #%d\n got: %s want: %s", i, s, test.want) - continue - } - } -} diff --git a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/test_coverage.txt b/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/test_coverage.txt deleted file mode 100644 index 2cd087a..0000000 --- a/.devenv/state/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/test_coverage.txt +++ /dev/null @@ -1,61 +0,0 @@ - -github.com/davecgh/go-spew/spew/dump.go dumpState.dump 100.00% (88/88) -github.com/davecgh/go-spew/spew/format.go formatState.format 100.00% (82/82) -github.com/davecgh/go-spew/spew/format.go formatState.formatPtr 100.00% (52/52) -github.com/davecgh/go-spew/spew/dump.go dumpState.dumpPtr 100.00% (44/44) -github.com/davecgh/go-spew/spew/dump.go dumpState.dumpSlice 100.00% (39/39) -github.com/davecgh/go-spew/spew/common.go handleMethods 100.00% (30/30) -github.com/davecgh/go-spew/spew/common.go printHexPtr 100.00% (18/18) -github.com/davecgh/go-spew/spew/common.go unsafeReflectValue 100.00% (13/13) -github.com/davecgh/go-spew/spew/format.go formatState.constructOrigFormat 100.00% (12/12) -github.com/davecgh/go-spew/spew/dump.go fdump 100.00% (11/11) -github.com/davecgh/go-spew/spew/format.go formatState.Format 100.00% (11/11) -github.com/davecgh/go-spew/spew/common.go init 100.00% (10/10) -github.com/davecgh/go-spew/spew/common.go printComplex 100.00% (9/9) -github.com/davecgh/go-spew/spew/common.go valuesSorter.Less 100.00% (8/8) -github.com/davecgh/go-spew/spew/format.go formatState.buildDefaultFormat 100.00% (7/7) -github.com/davecgh/go-spew/spew/format.go formatState.unpackValue 100.00% (5/5) -github.com/davecgh/go-spew/spew/dump.go dumpState.indent 100.00% (4/4) -github.com/davecgh/go-spew/spew/common.go catchPanic 100.00% (4/4) -github.com/davecgh/go-spew/spew/config.go ConfigState.convertArgs 100.00% (4/4) -github.com/davecgh/go-spew/spew/spew.go convertArgs 100.00% (4/4) -github.com/davecgh/go-spew/spew/format.go newFormatter 100.00% (3/3) -github.com/davecgh/go-spew/spew/dump.go Sdump 100.00% (3/3) -github.com/davecgh/go-spew/spew/common.go printBool 100.00% (3/3) -github.com/davecgh/go-spew/spew/common.go sortValues 100.00% (3/3) -github.com/davecgh/go-spew/spew/config.go ConfigState.Sdump 100.00% (3/3) -github.com/davecgh/go-spew/spew/dump.go dumpState.unpackValue 100.00% (3/3) -github.com/davecgh/go-spew/spew/spew.go Printf 100.00% (1/1) -github.com/davecgh/go-spew/spew/spew.go Println 100.00% (1/1) -github.com/davecgh/go-spew/spew/spew.go Sprint 100.00% (1/1) -github.com/davecgh/go-spew/spew/spew.go Sprintf 100.00% (1/1) -github.com/davecgh/go-spew/spew/spew.go Sprintln 100.00% (1/1) -github.com/davecgh/go-spew/spew/common.go printFloat 100.00% (1/1) -github.com/davecgh/go-spew/spew/config.go NewDefaultConfig 100.00% (1/1) -github.com/davecgh/go-spew/spew/common.go printInt 100.00% (1/1) -github.com/davecgh/go-spew/spew/common.go printUint 100.00% (1/1) -github.com/davecgh/go-spew/spew/common.go valuesSorter.Len 100.00% (1/1) -github.com/davecgh/go-spew/spew/common.go valuesSorter.Swap 100.00% (1/1) -github.com/davecgh/go-spew/spew/config.go ConfigState.Errorf 100.00% (1/1) -github.com/davecgh/go-spew/spew/config.go ConfigState.Fprint 100.00% (1/1) -github.com/davecgh/go-spew/spew/config.go ConfigState.Fprintf 100.00% (1/1) -github.com/davecgh/go-spew/spew/config.go ConfigState.Fprintln 100.00% (1/1) -github.com/davecgh/go-spew/spew/config.go ConfigState.Print 100.00% (1/1) -github.com/davecgh/go-spew/spew/config.go ConfigState.Printf 100.00% (1/1) -github.com/davecgh/go-spew/spew/config.go ConfigState.Println 100.00% (1/1) -github.com/davecgh/go-spew/spew/config.go ConfigState.Sprint 100.00% (1/1) -github.com/davecgh/go-spew/spew/config.go ConfigState.Sprintf 100.00% (1/1) -github.com/davecgh/go-spew/spew/config.go ConfigState.Sprintln 100.00% (1/1) -github.com/davecgh/go-spew/spew/config.go ConfigState.NewFormatter 100.00% (1/1) -github.com/davecgh/go-spew/spew/config.go ConfigState.Fdump 100.00% (1/1) -github.com/davecgh/go-spew/spew/config.go ConfigState.Dump 100.00% (1/1) -github.com/davecgh/go-spew/spew/dump.go Fdump 100.00% (1/1) -github.com/davecgh/go-spew/spew/dump.go Dump 100.00% (1/1) -github.com/davecgh/go-spew/spew/spew.go Fprintln 100.00% (1/1) -github.com/davecgh/go-spew/spew/format.go NewFormatter 100.00% (1/1) -github.com/davecgh/go-spew/spew/spew.go Errorf 100.00% (1/1) -github.com/davecgh/go-spew/spew/spew.go Fprint 100.00% (1/1) -github.com/davecgh/go-spew/spew/spew.go Fprintf 100.00% (1/1) -github.com/davecgh/go-spew/spew/spew.go Print 100.00% (1/1) -github.com/davecgh/go-spew/spew ------------------------------- 100.00% (505/505) - diff --git a/.devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/.travis.yml b/.devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/.travis.yml deleted file mode 100644 index 90c9c6f..0000000 --- a/.devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: go -go: - - 1.5 - - tip - diff --git a/.devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/LICENSE b/.devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/LICENSE deleted file mode 100644 index c67dad6..0000000 --- a/.devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2013, Patrick Mezard -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - The names of its contributors may not be used to endorse or promote -products derived from this software without specific prior written -permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/.devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/README.md b/.devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/README.md deleted file mode 100644 index e87f307..0000000 --- a/.devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/README.md +++ /dev/null @@ -1,50 +0,0 @@ -go-difflib -========== - -[](https://travis-ci.org/pmezard/go-difflib) -[](https://godoc.org/github.com/pmezard/go-difflib/difflib) - -Go-difflib is a partial port of python 3 difflib package. Its main goal -was to make unified and context diff available in pure Go, mostly for -testing purposes. - -The following class and functions (and related tests) have be ported: - -* `SequenceMatcher` -* `unified_diff()` -* `context_diff()` - -## Installation - -```bash -$ go get github.com/pmezard/go-difflib/difflib -``` - -### Quick Start - -Diffs are configured with Unified (or ContextDiff) structures, and can -be output to an io.Writer or returned as a string. - -```Go -diff := UnifiedDiff{ - A: difflib.SplitLines("foo\nbar\n"), - B: difflib.SplitLines("foo\nbaz\n"), - FromFile: "Original", - ToFile: "Current", - Context: 3, -} -text, _ := GetUnifiedDiffString(diff) -fmt.Printf(text) -``` - -would output: - -``` ---- Original -+++ Current -@@ -1,3 +1,3 @@ - foo --bar -+baz -``` - diff --git a/.devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/difflib/difflib.go b/.devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/difflib/difflib.go deleted file mode 100644 index 003e99f..0000000 --- a/.devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/difflib/difflib.go +++ /dev/null @@ -1,772 +0,0 @@ -// Package difflib is a partial port of Python difflib module. -// -// It provides tools to compare sequences of strings and generate textual diffs. -// -// The following class and functions have been ported: -// -// - SequenceMatcher -// -// - unified_diff -// -// - context_diff -// -// Getting unified diffs was the main goal of the port. Keep in mind this code -// is mostly suitable to output text differences in a human friendly way, there -// are no guarantees generated diffs are consumable by patch(1). -package difflib - -import ( - "bufio" - "bytes" - "fmt" - "io" - "strings" -) - -func min(a, b int) int { - if a < b { - return a - } - return b -} - -func max(a, b int) int { - if a > b { - return a - } - return b -} - -func calculateRatio(matches, length int) float64 { - if length > 0 { - return 2.0 * float64(matches) / float64(length) - } - return 1.0 -} - -type Match struct { - A int - B int - Size int -} - -type OpCode struct { - Tag byte - I1 int - I2 int - J1 int - J2 int -} - -// SequenceMatcher compares sequence of strings. The basic -// algorithm predates, and is a little fancier than, an algorithm -// published in the late 1980's by Ratcliff and Obershelp under the -// hyperbolic name "gestalt pattern matching". The basic idea is to find -// the longest contiguous matching subsequence that contains no "junk" -// elements (R-O doesn't address junk). The same idea is then applied -// recursively to the pieces of the sequences to the left and to the right -// of the matching subsequence. This does not yield minimal edit -// sequences, but does tend to yield matches that "look right" to people. -// -// SequenceMatcher tries to compute a "human-friendly diff" between two -// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the -// longest *contiguous* & junk-free matching subsequence. That's what -// catches peoples' eyes. The Windows(tm) windiff has another interesting -// notion, pairing up elements that appear uniquely in each sequence. -// That, and the method here, appear to yield more intuitive difference -// reports than does diff. This method appears to be the least vulnerable -// to synching up on blocks of "junk lines", though (like blank lines in -// ordinary text files, or maybe "<P>" lines in HTML files). That may be -// because this is the only method of the 3 that has a *concept* of -// "junk" <wink>. -// -// Timing: Basic R-O is cubic time worst case and quadratic time expected -// case. SequenceMatcher is quadratic time for the worst case and has -// expected-case behavior dependent in a complicated way on how many -// elements the sequences have in common; best case time is linear. -type SequenceMatcher struct { - a []string - b []string - b2j map[string][]int - IsJunk func(string) bool - autoJunk bool - bJunk map[string]struct{} - matchingBlocks []Match - fullBCount map[string]int - bPopular map[string]struct{} - opCodes []OpCode -} - -func NewMatcher(a, b []string) *SequenceMatcher { - m := SequenceMatcher{autoJunk: true} - m.SetSeqs(a, b) - return &m -} - -func NewMatcherWithJunk(a, b []string, autoJunk bool, - isJunk func(string) bool) *SequenceMatcher { - - m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk} - m.SetSeqs(a, b) - return &m -} - -// Set two sequences to be compared. -func (m *SequenceMatcher) SetSeqs(a, b []string) { - m.SetSeq1(a) - m.SetSeq2(b) -} - -// Set the first sequence to be compared. The second sequence to be compared is -// not changed. -// -// SequenceMatcher computes and caches detailed information about the second -// sequence, so if you want to compare one sequence S against many sequences, -// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other -// sequences. -// -// See also SetSeqs() and SetSeq2(). -func (m *SequenceMatcher) SetSeq1(a []string) { - if &a == &m.a { - return - } - m.a = a - m.matchingBlocks = nil - m.opCodes = nil -} - -// Set the second sequence to be compared. The first sequence to be compared is -// not changed. -func (m *SequenceMatcher) SetSeq2(b []string) { - if &b == &m.b { - return - } - m.b = b - m.matchingBlocks = nil - m.opCodes = nil - m.fullBCount = nil - m.chainB() -} - -func (m *SequenceMatcher) chainB() { - // Populate line -> index mapping - b2j := map[string][]int{} - for i, s := range m.b { - indices := b2j[s] - indices = append(indices, i) - b2j[s] = indices - } - - // Purge junk elements - m.bJunk = map[string]struct{}{} - if m.IsJunk != nil { - junk := m.bJunk - for s, _ := range b2j { - if m.IsJunk(s) { - junk[s] = struct{}{} - } - } - for s, _ := range junk { - delete(b2j, s) - } - } - - // Purge remaining popular elements - popular := map[string]struct{}{} - n := len(m.b) - if m.autoJunk && n >= 200 { - ntest := n/100 + 1 - for s, indices := range b2j { - if len(indices) > ntest { - popular[s] = struct{}{} - } - } - for s, _ := range popular { - delete(b2j, s) - } - } - m.bPopular = popular - m.b2j = b2j -} - -func (m *SequenceMatcher) isBJunk(s string) bool { - _, ok := m.bJunk[s] - return ok -} - -// Find longest matching block in a[alo:ahi] and b[blo:bhi]. -// -// If IsJunk is not defined: -// -// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where -// alo <= i <= i+k <= ahi -// blo <= j <= j+k <= bhi -// and for all (i',j',k') meeting those conditions, -// k >= k' -// i <= i' -// and if i == i', j <= j' -// -// In other words, of all maximal matching blocks, return one that -// starts earliest in a, and of all those maximal matching blocks that -// start earliest in a, return the one that starts earliest in b. -// -// If IsJunk is defined, first the longest matching block is -// determined as above, but with the additional restriction that no -// junk element appears in the block. Then that block is extended as -// far as possible by matching (only) junk elements on both sides. So -// the resulting block never matches on junk except as identical junk -// happens to be adjacent to an "interesting" match. -// -// If no blocks match, return (alo, blo, 0). -func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match { - // CAUTION: stripping common prefix or suffix would be incorrect. - // E.g., - // ab - // acab - // Longest matching block is "ab", but if common prefix is - // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so - // strip, so ends up claiming that ab is changed to acab by - // inserting "ca" in the middle. That's minimal but unintuitive: - // "it's obvious" that someone inserted "ac" at the front. - // Windiff ends up at the same place as diff, but by pairing up - // the unique 'b's and then matching the first two 'a's. - besti, bestj, bestsize := alo, blo, 0 - - // find longest junk-free match - // during an iteration of the loop, j2len[j] = length of longest - // junk-free match ending with a[i-1] and b[j] - j2len := map[int]int{} - for i := alo; i != ahi; i++ { - // look at all instances of a[i] in b; note that because - // b2j has no junk keys, the loop is skipped if a[i] is junk - newj2len := map[int]int{} - for _, j := range m.b2j[m.a[i]] { - // a[i] matches b[j] - if j < blo { - continue - } - if j >= bhi { - break - } - k := j2len[j-1] + 1 - newj2len[j] = k - if k > bestsize { - besti, bestj, bestsize = i-k+1, j-k+1, k - } - } - j2len = newj2len - } - - // Extend the best by non-junk elements on each end. In particular, - // "popular" non-junk elements aren't in b2j, which greatly speeds - // the inner loop above, but also means "the best" match so far - // doesn't contain any junk *or* popular non-junk elements. - for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) && - m.a[besti-1] == m.b[bestj-1] { - besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 - } - for besti+bestsize < ahi && bestj+bestsize < bhi && - !m.isBJunk(m.b[bestj+bestsize]) && - m.a[besti+bestsize] == m.b[bestj+bestsize] { - bestsize += 1 - } - - // Now that we have a wholly interesting match (albeit possibly - // empty!), we may as well suck up the matching junk on each - // side of it too. Can't think of a good reason not to, and it - // saves post-processing the (possibly considerable) expense of - // figuring out what to do with it. In the case of an empty - // interesting match, this is clearly the right thing to do, - // because no other kind of match is possible in the regions. - for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) && - m.a[besti-1] == m.b[bestj-1] { - besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 - } - for besti+bestsize < ahi && bestj+bestsize < bhi && - m.isBJunk(m.b[bestj+bestsize]) && - m.a[besti+bestsize] == m.b[bestj+bestsize] { - bestsize += 1 - } - - return Match{A: besti, B: bestj, Size: bestsize} -} - -// Return list of triples describing matching subsequences. -// -// Each triple is of the form (i, j, n), and means that -// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in -// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are -// adjacent triples in the list, and the second is not the last triple in the -// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe -// adjacent equal blocks. -// -// The last triple is a dummy, (len(a), len(b), 0), and is the only -// triple with n==0. -func (m *SequenceMatcher) GetMatchingBlocks() []Match { - if m.matchingBlocks != nil { - return m.matchingBlocks - } - - var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match - matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match { - match := m.findLongestMatch(alo, ahi, blo, bhi) - i, j, k := match.A, match.B, match.Size - if match.Size > 0 { - if alo < i && blo < j { - matched = matchBlocks(alo, i, blo, j, matched) - } - matched = append(matched, match) - if i+k < ahi && j+k < bhi { - matched = matchBlocks(i+k, ahi, j+k, bhi, matched) - } - } - return matched - } - matched := matchBlocks(0, len(m.a), 0, len(m.b), nil) - - // It's possible that we have adjacent equal blocks in the - // matching_blocks list now. - nonAdjacent := []Match{} - i1, j1, k1 := 0, 0, 0 - for _, b := range matched { - // Is this block adjacent to i1, j1, k1? - i2, j2, k2 := b.A, b.B, b.Size - if i1+k1 == i2 && j1+k1 == j2 { - // Yes, so collapse them -- this just increases the length of - // the first block by the length of the second, and the first - // block so lengthened remains the block to compare against. - k1 += k2 - } else { - // Not adjacent. Remember the first block (k1==0 means it's - // the dummy we started with), and make the second block the - // new block to compare against. - if k1 > 0 { - nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) - } - i1, j1, k1 = i2, j2, k2 - } - } - if k1 > 0 { - nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) - } - - nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0}) - m.matchingBlocks = nonAdjacent - return m.matchingBlocks -} - -// Return list of 5-tuples describing how to turn a into b. -// -// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple -// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the -// tuple preceding it, and likewise for j1 == the previous j2. -// -// The tags are characters, with these meanings: -// -// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2] -// -// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case. -// -// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case. -// -// 'e' (equal): a[i1:i2] == b[j1:j2] -func (m *SequenceMatcher) GetOpCodes() []OpCode { - if m.opCodes != nil { - return m.opCodes - } - i, j := 0, 0 - matching := m.GetMatchingBlocks() - opCodes := make([]OpCode, 0, len(matching)) - for _, m := range matching { - // invariant: we've pumped out correct diffs to change - // a[:i] into b[:j], and the next matching block is - // a[ai:ai+size] == b[bj:bj+size]. So we need to pump - // out a diff to change a[i:ai] into b[j:bj], pump out - // the matching block, and move (i,j) beyond the match - ai, bj, size := m.A, m.B, m.Size - tag := byte(0) - if i < ai && j < bj { - tag = 'r' - } else if i < ai { - tag = 'd' - } else if j < bj { - tag = 'i' - } - if tag > 0 { - opCodes = append(opCodes, OpCode{tag, i, ai, j, bj}) - } - i, j = ai+size, bj+size - // the list of matching blocks is terminated by a - // sentinel with size 0 - if size > 0 { - opCodes = append(opCodes, OpCode{'e', ai, i, bj, j}) - } - } - m.opCodes = opCodes - return m.opCodes -} - -// Isolate change clusters by eliminating ranges with no changes. -// -// Return a generator of groups with up to n lines of context. -// Each group is in the same format as returned by GetOpCodes(). -func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { - if n < 0 { - n = 3 - } - codes := m.GetOpCodes() - if len(codes) == 0 { - codes = []OpCode{OpCode{'e', 0, 1, 0, 1}} - } - // Fixup leading and trailing groups if they show no changes. - if codes[0].Tag == 'e' { - c := codes[0] - i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 - codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2} - } - if codes[len(codes)-1].Tag == 'e' { - c := codes[len(codes)-1] - i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 - codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)} - } - nn := n + n - groups := [][]OpCode{} - group := []OpCode{} - for _, c := range codes { - i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 - // End the current group and start a new one whenever - // there is a large range with no changes. - if c.Tag == 'e' && i2-i1 > nn { - group = append(group, OpCode{c.Tag, i1, min(i2, i1+n), - j1, min(j2, j1+n)}) - groups = append(groups, group) - group = []OpCode{} - i1, j1 = max(i1, i2-n), max(j1, j2-n) - } - group = append(group, OpCode{c.Tag, i1, i2, j1, j2}) - } - if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') { - groups = append(groups, group) - } - return groups -} - -// Return a measure of the sequences' similarity (float in [0,1]). -// -// Where T is the total number of elements in both sequences, and -// M is the number of matches, this is 2.0*M / T. -// Note that this is 1 if the sequences are identical, and 0 if -// they have nothing in common. -// -// .Ratio() is expensive to compute if you haven't already computed -// .GetMatchingBlocks() or .GetOpCodes(), in which case you may -// want to try .QuickRatio() or .RealQuickRation() first to get an -// upper bound. -func (m *SequenceMatcher) Ratio() float64 { - matches := 0 - for _, m := range m.GetMatchingBlocks() { - matches += m.Size - } - return calculateRatio(matches, len(m.a)+len(m.b)) -} - -// Return an upper bound on ratio() relatively quickly. -// -// This isn't defined beyond that it is an upper bound on .Ratio(), and -// is faster to compute. -func (m *SequenceMatcher) QuickRatio() float64 { - // viewing a and b as multisets, set matches to the cardinality - // of their intersection; this counts the number of matches - // without regard to order, so is clearly an upper bound - if m.fullBCount == nil { - m.fullBCount = map[string]int{} - for _, s := range m.b { - m.fullBCount[s] = m.fullBCount[s] + 1 - } - } - - // avail[x] is the number of times x appears in 'b' less the - // number of times we've seen it in 'a' so far ... kinda - avail := map[string]int{} - matches := 0 - for _, s := range m.a { - n, ok := avail[s] - if !ok { - n = m.fullBCount[s] - } - avail[s] = n - 1 - if n > 0 { - matches += 1 - } - } - return calculateRatio(matches, len(m.a)+len(m.b)) -} - -// Return an upper bound on ratio() very quickly. -// -// This isn't defined beyond that it is an upper bound on .Ratio(), and -// is faster to compute than either .Ratio() or .QuickRatio(). -func (m *SequenceMatcher) RealQuickRatio() float64 { - la, lb := len(m.a), len(m.b) - return calculateRatio(min(la, lb), la+lb) -} - -// Convert range to the "ed" format -func formatRangeUnified(start, stop int) string { - // Per the diff spec at http://www.unix.org/single_unix_specification/ - beginning := start + 1 // lines start numbering with one - length := stop - start - if length == 1 { - return fmt.Sprintf("%d", beginning) - } - if length == 0 { - beginning -= 1 // empty ranges begin at line just before the range - } - return fmt.Sprintf("%d,%d", beginning, length) -} - -// Unified diff parameters -type UnifiedDiff struct { - A []string // First sequence lines - FromFile string // First file name - FromDate string // First file time - B []string // Second sequence lines - ToFile string // Second file name - ToDate string // Second file time - Eol string // Headers end of line, defaults to LF - Context int // Number of context lines -} - -// Compare two sequences of lines; generate the delta as a unified diff. -// -// Unified diffs are a compact way of showing line changes and a few -// lines of context. The number of context lines is set by 'n' which -// defaults to three. -// -// By default, the diff control lines (those with ---, +++, or @@) are -// created with a trailing newline. This is helpful so that inputs -// created from file.readlines() result in diffs that are suitable for -// file.writelines() since both the inputs and outputs have trailing -// newlines. -// -// For inputs that do not have trailing newlines, set the lineterm -// argument to "" so that the output will be uniformly newline free. -// -// The unidiff format normally has a header for filenames and modification -// times. Any or all of these may be specified using strings for -// 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. -// The modification times are normally expressed in the ISO 8601 format. -func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { - buf := bufio.NewWriter(writer) - defer buf.Flush() - wf := func(format string, args ...interface{}) error { - _, err := buf.WriteString(fmt.Sprintf(format, args...)) - return err - } - ws := func(s string) error { - _, err := buf.WriteString(s) - return err - } - - if len(diff.Eol) == 0 { - diff.Eol = "\n" - } - - started := false - m := NewMatcher(diff.A, diff.B) - for _, g := range m.GetGroupedOpCodes(diff.Context) { - if !started { - started = true - fromDate := "" - if len(diff.FromDate) > 0 { - fromDate = "\t" + diff.FromDate - } - toDate := "" - if len(diff.ToDate) > 0 { - toDate = "\t" + diff.ToDate - } - if diff.FromFile != "" || diff.ToFile != "" { - err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol) - if err != nil { - return err - } - err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol) - if err != nil { - return err - } - } - } - first, last := g[0], g[len(g)-1] - range1 := formatRangeUnified(first.I1, last.I2) - range2 := formatRangeUnified(first.J1, last.J2) - if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil { - return err - } - for _, c := range g { - i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 - if c.Tag == 'e' { - for _, line := range diff.A[i1:i2] { - if err := ws(" " + line); err != nil { - return err - } - } - continue - } - if c.Tag == 'r' || c.Tag == 'd' { - for _, line := range diff.A[i1:i2] { - if err := ws("-" + line); err != nil { - return err - } - } - } - if c.Tag == 'r' || c.Tag == 'i' { - for _, line := range diff.B[j1:j2] { - if err := ws("+" + line); err != nil { - return err - } - } - } - } - } - return nil -} - -// Like WriteUnifiedDiff but returns the diff a string. -func GetUnifiedDiffString(diff UnifiedDiff) (string, error) { - w := &bytes.Buffer{} - err := WriteUnifiedDiff(w, diff) - return string(w.Bytes()), err -} - -// Convert range to the "ed" format. -func formatRangeContext(start, stop int) string { - // Per the diff spec at http://www.unix.org/single_unix_specification/ - beginning := start + 1 // lines start numbering with one - length := stop - start - if length == 0 { - beginning -= 1 // empty ranges begin at line just before the range - } - if length <= 1 { - return fmt.Sprintf("%d", beginning) - } - return fmt.Sprintf("%d,%d", beginning, beginning+length-1) -} - -type ContextDiff UnifiedDiff - -// Compare two sequences of lines; generate the delta as a context diff. -// -// Context diffs are a compact way of showing line changes and a few -// lines of context. The number of context lines is set by diff.Context -// which defaults to three. -// -// By default, the diff control lines (those with *** or ---) are -// created with a trailing newline. -// -// For inputs that do not have trailing newlines, set the diff.Eol -// argument to "" so that the output will be uniformly newline free. -// -// The context diff format normally has a header for filenames and -// modification times. Any or all of these may be specified using -// strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate. -// The modification times are normally expressed in the ISO 8601 format. -// If not specified, the strings default to blanks. -func WriteContextDiff(writer io.Writer, diff ContextDiff) error { - buf := bufio.NewWriter(writer) - defer buf.Flush() - var diffErr error - wf := func(format string, args ...interface{}) { - _, err := buf.WriteString(fmt.Sprintf(format, args...)) - if diffErr == nil && err != nil { - diffErr = err - } - } - ws := func(s string) { - _, err := buf.WriteString(s) - if diffErr == nil && err != nil { - diffErr = err - } - } - - if len(diff.Eol) == 0 { - diff.Eol = "\n" - } - - prefix := map[byte]string{ - 'i': "+ ", - 'd': "- ", - 'r': "! ", - 'e': " ", - } - - started := false - m := NewMatcher(diff.A, diff.B) - for _, g := range m.GetGroupedOpCodes(diff.Context) { - if !started { - started = true - fromDate := "" - if len(diff.FromDate) > 0 { - fromDate = "\t" + diff.FromDate - } - toDate := "" - if len(diff.ToDate) > 0 { - toDate = "\t" + diff.ToDate - } - if diff.FromFile != "" || diff.ToFile != "" { - wf("*** %s%s%s", diff.FromFile, fromDate, diff.Eol) - wf("--- %s%s%s", diff.ToFile, toDate, diff.Eol) - } - } - - first, last := g[0], g[len(g)-1] - ws("***************" + diff.Eol) - - range1 := formatRangeContext(first.I1, last.I2) - wf("*** %s ****%s", range1, diff.Eol) - for _, c := range g { - if c.Tag == 'r' || c.Tag == 'd' { - for _, cc := range g { - if cc.Tag == 'i' { - continue - } - for _, line := range diff.A[cc.I1:cc.I2] { - ws(prefix[cc.Tag] + line) - } - } - break - } - } - - range2 := formatRangeContext(first.J1, last.J2) - wf("--- %s ----%s", range2, diff.Eol) - for _, c := range g { - if c.Tag == 'r' || c.Tag == 'i' { - for _, cc := range g { - if cc.Tag == 'd' { - continue - } - for _, line := range diff.B[cc.J1:cc.J2] { - ws(prefix[cc.Tag] + line) - } - } - break - } - } - } - return diffErr -} - -// Like WriteContextDiff but returns the diff a string. -func GetContextDiffString(diff ContextDiff) (string, error) { - w := &bytes.Buffer{} - err := WriteContextDiff(w, diff) - return string(w.Bytes()), err -} - -// Split a string on "\n" while preserving them. The output can be used -// as input for UnifiedDiff and ContextDiff structures. -func SplitLines(s string) []string { - lines := strings.SplitAfter(s, "\n") - lines[len(lines)-1] += "\n" - return lines -} diff --git a/.devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/difflib/difflib_test.go b/.devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/difflib/difflib_test.go deleted file mode 100644 index d725119..0000000 --- a/.devenv/state/go/pkg/mod/github.com/pmezard/go-difflib@v1.0.0/difflib/difflib_test.go +++ /dev/null @@ -1,426 +0,0 @@ -package difflib - -import ( - "bytes" - "fmt" - "math" - "reflect" - "strings" - "testing" -) - -func assertAlmostEqual(t *testing.T, a, b float64, places int) { - if math.Abs(a-b) > math.Pow10(-places) { - t.Errorf("%.7f != %.7f", a, b) - } -} - -func assertEqual(t *testing.T, a, b interface{}) { - if !reflect.DeepEqual(a, b) { - t.Errorf("%v != %v", a, b) - } -} - -func splitChars(s string) []string { - chars := make([]string, 0, len(s)) - // Assume ASCII inputs - for i := 0; i != len(s); i++ { - chars = append(chars, string(s[i])) - } - return chars -} - -func TestSequenceMatcherRatio(t *testing.T) { - s := NewMatcher(splitChars("abcd"), splitChars("bcde")) - assertEqual(t, s.Ratio(), 0.75) - assertEqual(t, s.QuickRatio(), 0.75) - assertEqual(t, s.RealQuickRatio(), 1.0) -} - -func TestGetOptCodes(t *testing.T) { - a := "qabxcd" - b := "abycdf" - s := NewMatcher(splitChars(a), splitChars(b)) - w := &bytes.Buffer{} - for _, op := range s.GetOpCodes() { - fmt.Fprintf(w, "%s a[%d:%d], (%s) b[%d:%d] (%s)\n", string(op.Tag), - op.I1, op.I2, a[op.I1:op.I2], op.J1, op.J2, b[op.J1:op.J2]) - } - result := string(w.Bytes()) - expected := `d a[0:1], (q) b[0:0] () -e a[1:3], (ab) b[0:2] (ab) -r a[3:4], (x) b[2:3] (y) -e a[4:6], (cd) b[3:5] (cd) -i a[6:6], () b[5:6] (f) -` - if expected != result { - t.Errorf("unexpected op codes: \n%s", result) - } -} - -func TestGroupedOpCodes(t *testing.T) { - a := []string{} - for i := 0; i != 39; i++ { - a = append(a, fmt.Sprintf("%02d", i)) - } - b := []string{} - b = append(b, a[:8]...) - b = append(b, " i") - b = append(b, a[8:19]...) - b = append(b, " x") - b = append(b, a[20:22]...) - b = append(b, a[27:34]...) - b = append(b, " y") - b = append(b, a[35:]...) - s := NewMatcher(a, b) - w := &bytes.Buffer{} - for _, g := range s.GetGroupedOpCodes(-1) { - fmt.Fprintf(w, "group\n") - for _, op := range g { - fmt.Fprintf(w, " %s, %d, %d, %d, %d\n", string(op.Tag), - op.I1, op.I2, op.J1, op.J2) - } - } - result := string(w.Bytes()) - expected := `group - e, 5, 8, 5, 8 - i, 8, 8, 8, 9 - e, 8, 11, 9, 12 -group - e, 16, 19, 17, 20 - r, 19, 20, 20, 21 - e, 20, 22, 21, 23 - d, 22, 27, 23, 23 - e, 27, 30, 23, 26 -group - e, 31, 34, 27, 30 - r, 34, 35, 30, 31 - e, 35, 38, 31, 34 -` - if expected != result { - t.Errorf("unexpected op codes: \n%s", result) - } -} - -func ExampleGetUnifiedDiffCode() { - a := `one -two -three -four -fmt.Printf("%s,%T",a,b)` - b := `zero -one -three -four` - diff := UnifiedDiff{ - A: SplitLines(a), - B: SplitLines(b), - FromFile: "Original", - FromDate: "2005-01-26 23:30:50", - ToFile: "Current", - ToDate: "2010-04-02 10:20:52", - Context: 3, - } - result, _ := GetUnifiedDiffString(diff) - fmt.Println(strings.Replace(result, "\t", " ", -1)) - // Output: - // --- Original 2005-01-26 23:30:50 - // +++ Current 2010-04-02 10:20:52 - // @@ -1,5 +1,4 @@ - // +zero - // one - // -two - // three - // four - // -fmt.Printf("%s,%T",a,b) -} - -func ExampleGetContextDiffCode() { - a := `one -two -three -four -fmt.Printf("%s,%T",a,b)` - b := `zero -one -tree -four` - diff := ContextDiff{ - A: SplitLines(a), - B: SplitLines(b), - FromFile: "Original", - ToFile: "Current", - Context: 3, - Eol: "\n", - } - result, _ := GetContextDiffString(diff) - fmt.Print(strings.Replace(result, "\t", " ", -1)) - // Output: - // *** Original - // --- Current - // *************** - // *** 1,5 **** - // one - // ! two - // ! three - // four - // - fmt.Printf("%s,%T",a,b) - // --- 1,4 ---- - // + zero - // one - // ! tree - // four -} - -func ExampleGetContextDiffString() { - a := `one -two -three -four` - b := `zero -one -tree -four` - diff := ContextDiff{ - A: SplitLines(a), - B: SplitLines(b), - FromFile: "Original", - ToFile: "Current", - Context: 3, - Eol: "\n", - } - result, _ := GetContextDiffString(diff) - fmt.Printf(strings.Replace(result, "\t", " ", -1)) - // Output: - // *** Original - // --- Current - // *************** - // *** 1,4 **** - // one - // ! two - // ! three - // four - // --- 1,4 ---- - // + zero - // one - // ! tree - // four -} - -func rep(s string, count int) string { - return strings.Repeat(s, count) -} - -func TestWithAsciiOneInsert(t *testing.T) { - sm := NewMatcher(splitChars(rep("b", 100)), - splitChars("a"+rep("b", 100))) - assertAlmostEqual(t, sm.Ratio(), 0.995, 3) - assertEqual(t, sm.GetOpCodes(), - []OpCode{{'i', 0, 0, 0, 1}, {'e', 0, 100, 1, 101}}) - assertEqual(t, len(sm.bPopular), 0) - - sm = NewMatcher(splitChars(rep("b", 100)), - splitChars(rep("b", 50)+"a"+rep("b", 50))) - assertAlmostEqual(t, sm.Ratio(), 0.995, 3) - assertEqual(t, sm.GetOpCodes(), - []OpCode{{'e', 0, 50, 0, 50}, {'i', 50, 50, 50, 51}, {'e', 50, 100, 51, 101}}) - assertEqual(t, len(sm.bPopular), 0) -} - -func TestWithAsciiOnDelete(t *testing.T) { - sm := NewMatcher(splitChars(rep("a", 40)+"c"+rep("b", 40)), - splitChars(rep("a", 40)+rep("b", 40))) - assertAlmostEqual(t, sm.Ratio(), 0.994, 3) - assertEqual(t, sm.GetOpCodes(), - []OpCode{{'e', 0, 40, 0, 40}, {'d', 40, 41, 40, 40}, {'e', 41, 81, 40, 80}}) -} - -func TestWithAsciiBJunk(t *testing.T) { - isJunk := func(s string) bool { - return s == " " - } - sm := NewMatcherWithJunk(splitChars(rep("a", 40)+rep("b", 40)), - splitChars(rep("a", 44)+rep("b", 40)), true, isJunk) - assertEqual(t, sm.bJunk, map[string]struct{}{}) - - sm = NewMatcherWithJunk(splitChars(rep("a", 40)+rep("b", 40)), - splitChars(rep("a", 44)+rep("b", 40)+rep(" ", 20)), false, isJunk) - assertEqual(t, sm.bJunk, map[string]struct{}{" ": struct{}{}}) - - isJunk = func(s string) bool { - return s == " " || s == "b" - } - sm = NewMatcherWithJunk(splitChars(rep("a", 40)+rep("b", 40)), - splitChars(rep("a", 44)+rep("b", 40)+rep(" ", 20)), false, isJunk) - assertEqual(t, sm.bJunk, map[string]struct{}{" ": struct{}{}, "b": struct{}{}}) -} - -func TestSFBugsRatioForNullSeqn(t *testing.T) { - sm := NewMatcher(nil, nil) - assertEqual(t, sm.Ratio(), 1.0) - assertEqual(t, sm.QuickRatio(), 1.0) - assertEqual(t, sm.RealQuickRatio(), 1.0) -} - -func TestSFBugsComparingEmptyLists(t *testing.T) { - groups := NewMatcher(nil, nil).GetGroupedOpCodes(-1) - assertEqual(t, len(groups), 0) - diff := UnifiedDiff{ - FromFile: "Original", - ToFile: "Current", - Context: 3, - } - result, err := GetUnifiedDiffString(diff) - assertEqual(t, err, nil) - assertEqual(t, result, "") -} - -func TestOutputFormatRangeFormatUnified(t *testing.T) { - // Per the diff spec at http://www.unix.org/single_unix_specification/ - // - // Each <range> field shall be of the form: - // %1d", <beginning line number> if the range contains exactly one line, - // and: - // "%1d,%1d", <beginning line number>, <number of lines> otherwise. - // If a range is empty, its beginning line number shall be the number of - // the line just before the range, or 0 if the empty range starts the file. - fm := formatRangeUnified - assertEqual(t, fm(3, 3), "3,0") - assertEqual(t, fm(3, 4), "4") - assertEqual(t, fm(3, 5), "4,2") - assertEqual(t, fm(3, 6), "4,3") - assertEqual(t, fm(0, 0), "0,0") -} - -func TestOutputFormatRangeFormatContext(t *testing.T) { - // Per the diff spec at http://www.unix.org/single_unix_specification/ - // - // The range of lines in file1 shall be written in the following format - // if the range contains two or more lines: - // "*** %d,%d ****\n", <beginning line number>, <ending line number> - // and the following format otherwise: - // "*** %d ****\n", <ending line number> - // The ending line number of an empty range shall be the number of the preceding line, - // or 0 if the range is at the start of the file. - // - // Next, the range of lines in file2 shall be written in the following format - // if the range contains two or more lines: - // "--- %d,%d ----\n", <beginning line number>, <ending line number> - // and the following format otherwise: - // "--- %d ----\n", <ending line number> - fm := formatRangeContext - assertEqual(t, fm(3, 3), "3") - assertEqual(t, fm(3, 4), "4") - assertEqual(t, fm(3, 5), "4,5") - assertEqual(t, fm(3, 6), "4,6") - assertEqual(t, fm(0, 0), "0") -} - -func TestOutputFormatTabDelimiter(t *testing.T) { - diff := UnifiedDiff{ - A: splitChars("one"), - B: splitChars("two"), - FromFile: "Original", - FromDate: "2005-01-26 23:30:50", - ToFile: "Current", - ToDate: "2010-04-12 10:20:52", - Eol: "\n", - } - ud, err := GetUnifiedDiffString(diff) - assertEqual(t, err, nil) - assertEqual(t, SplitLines(ud)[:2], []string{ - "--- Original\t2005-01-26 23:30:50\n", - "+++ Current\t2010-04-12 10:20:52\n", - }) - cd, err := GetContextDiffString(ContextDiff(diff)) - assertEqual(t, err, nil) - assertEqual(t, SplitLines(cd)[:2], []string{ - "*** Original\t2005-01-26 23:30:50\n", - "--- Current\t2010-04-12 10:20:52\n", - }) -} - -func TestOutputFormatNoTrailingTabOnEmptyFiledate(t *testing.T) { - diff := UnifiedDiff{ - A: splitChars("one"), - B: splitChars("two"), - FromFile: "Original", - ToFile: "Current", - Eol: "\n", - } - ud, err := GetUnifiedDiffString(diff) - assertEqual(t, err, nil) - assertEqual(t, SplitLines(ud)[:2], []string{"--- Original\n", "+++ Current\n"}) - - cd, err := GetContextDiffString(ContextDiff(diff)) - assertEqual(t, err, nil) - assertEqual(t, SplitLines(cd)[:2], []string{"*** Original\n", "--- Current\n"}) -} - -func TestOmitFilenames(t *testing.T) { - diff := UnifiedDiff{ - A: SplitLines("o\nn\ne\n"), - B: SplitLines("t\nw\no\n"), - Eol: "\n", - } - ud, err := GetUnifiedDiffString(diff) - assertEqual(t, err, nil) - assertEqual(t, SplitLines(ud), []string{ - "@@ -0,0 +1,2 @@\n", - "+t\n", - "+w\n", - "@@ -2,2 +3,0 @@\n", - "-n\n", - "-e\n", - "\n", - }) - - cd, err := GetContextDiffString(ContextDiff(diff)) - assertEqual(t, err, nil) - assertEqual(t, SplitLines(cd), []string{ - "***************\n", - "*** 0 ****\n", - "--- 1,2 ----\n", - "+ t\n", - "+ w\n", - "***************\n", - "*** 2,3 ****\n", - "- n\n", - "- e\n", - "--- 3 ----\n", - "\n", - }) -} - -func TestSplitLines(t *testing.T) { - allTests := []struct { - input string - want []string - }{ - {"foo", []string{"foo\n"}}, - {"foo\nbar", []string{"foo\n", "bar\n"}}, - {"foo\nbar\n", []string{"foo\n", "bar\n", "\n"}}, - } - for _, test := range allTests { - assertEqual(t, SplitLines(test.input), test.want) - } -} - -func benchmarkSplitLines(b *testing.B, count int) { - str := strings.Repeat("foo\n", count) - - b.ResetTimer() - - n := 0 - for i := 0; i < b.N; i++ { - n += len(SplitLines(str)) - } -} - -func BenchmarkSplitLines100(b *testing.B) { - benchmarkSplitLines(b, 100) -} - -func BenchmarkSplitLines10000(b *testing.B) { - benchmarkSplitLines(b, 10000) -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.ci.gofmt.sh b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.ci.gofmt.sh deleted file mode 100644 index 3f2e5d3..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.ci.gofmt.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -if [ -n "$(gofmt -l .)" ]; then - echo "Go code is not formatted:" - gofmt -d . - exit 1 -fi - -go generate ./... -if [ -n "$(git status -s -uno)" ]; then - echo "Go generate output does not match commit." - echo "Did you forget to run go generate ./... ?" - exit 1 -fi diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.ci.gogenerate.sh b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.ci.gogenerate.sh deleted file mode 100644 index 3fc73fe..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.ci.gogenerate.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -# If GOMOD is defined we are running with Go Modules enabled, either -# automatically or via the GO111MODULE=on environment variable. Codegen only -# works with modules, so skip generation if modules is not in use. -if [[ -z "$(go env GOMOD)" ]]; then - echo "Skipping go generate because modules not enabled and required" - exit 0 -fi - -go generate ./... -if [ -n "$(git diff)" ]; then - echo "Go generate had not been run" - git diff - exit 1 -fi diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.ci.govet.sh b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.ci.govet.sh deleted file mode 100644 index 77aeb5c..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.ci.govet.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -set -e - -go vet ./... diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.github/dependabot.yml b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.github/dependabot.yml deleted file mode 100644 index bf6944e..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.github/dependabot.yml +++ /dev/null @@ -1,10 +0,0 @@ -version: 2 -updates: -- package-ecosystem: gomod - directory: / - schedule: - interval: daily -- package-ecosystem: github-actions - directory: / - schedule: - interval: daily diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.github/pull_request_template.md b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.github/pull_request_template.md deleted file mode 100644 index ba09b9b..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.github/pull_request_template.md +++ /dev/null @@ -1,15 +0,0 @@ -## Summary -<!-- High-level, one sentence summary of what this PR accomplishes --> - -## Changes -<!-- * Description of change 1 --> -<!-- * Description of change 2 --> -<!-- ... --> - -## Motivation -<!-- Why were the changes necessary. --> - -<!-- ## Example usage (if applicable) --> - -## Related issues -<!-- Put `Closes #XXXX` for each issue number this PR fixes/closes --> diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.github/workflows/main.yml b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.github/workflows/main.yml deleted file mode 100644 index 12a23ea..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.github/workflows/main.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: All builds -on: [push, pull_request] - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - go_version: ["1.18.1", "1.17.6", "1.16.5"] - steps: - - uses: actions/checkout@v3 - - name: Setup Go - uses: actions/setup-go@v3.2.0 - with: - go-version: ${{ matrix.go_version }} - - run: ./.ci.gogenerate.sh - - run: ./.ci.gofmt.sh - - run: ./.ci.govet.sh - - run: go test -v -race ./... diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.gitignore b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.gitignore deleted file mode 100644 index 5aacdb7..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe - -.DS_Store diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/CONTRIBUTING.md b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/CONTRIBUTING.md deleted file mode 100644 index a3a062c..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/CONTRIBUTING.md +++ /dev/null @@ -1,50 +0,0 @@ -# Contributing to Testify - -So you'd like to contribute to Testify? First of all, thank you! Testify is widely used, so each -contribution has a significant impact within the Golang community! Below you'll find everything you -need to know to get up to speed on the project. - -## Philosophy - -The Testify maintainers generally attempt to follow widely accepted practices within the Golang -community. That being said, the first priority is always to make sure that the package is useful to -the community. A few general guidelines are listed here: - -*Keep it simple (whenever practical)* - Try not to expand the API unless the new surface area -provides meaningful benefits. For example, don't add functions because they might be useful to -someone, someday. Add what is useful to specific users, today. - -*Ease of use is paramount* - This means good documentation and package organization. It also means -that we should try hard to use meaningful, descriptive function names, avoid breaking the API -unnecessarily, and try not to surprise the user. - -*Quality isn't an afterthought* - Testify is a testing library, so it seems reasonable that we -should have a decent test suite. This is doubly important because a bug in Testify doesn't just mean -a bug in our users' code, it means a bug in our users' tests, which means a potentially unnoticed -and hard-to-find bug in our users' code. - -## Pull Requests - -We welcome pull requests! Please include the following in the description: - - * Motivation, why your change is important or helpful - * Example usage (if applicable) - * Whether you intend to add / change behavior or fix a bug - -Please be aware that the maintainers may ask for changes. This isn't a commentary on the quality of -your idea or your code. Testify is the result of many contributions from many individuals, so we -need to enforce certain practices and patterns to keep the package easy for others to understand. -Essentially, we recognize that there are often many good ways to do a given thing, but we have to -pick one and stick with it. - -See `MAINTAINERS.md` for a list of users who can approve / merge your changes. - -## Issues - -If you find a bug or think of a useful feature you'd like to see added to Testify, the best thing -you can do is make the necessary changes and open a pull request (see above). If that isn't an -option, or if you'd like to discuss your change before you write the code, open an issue! - -Please provide enough context in the issue description that other members of the community can -easily understand what it is that you'd like to see. - diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/LICENSE b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/LICENSE deleted file mode 100644 index 4b0421c..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2012-2020 Mat Ryer, Tyler Bunnell and contributors. - -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. diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/MAINTAINERS.md b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/MAINTAINERS.md deleted file mode 100644 index b6c1dde..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/MAINTAINERS.md +++ /dev/null @@ -1,9 +0,0 @@ -# Testify Maintainers - -The individuals listed below are active in the project and have the ability to approve and merge -pull requests. - - * @glesica - * @boyan-soubachov - * @mvdkleijn - diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/README.md b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/README.md deleted file mode 100644 index ce6d3de..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/README.md +++ /dev/null @@ -1,371 +0,0 @@ -Testify - Thou Shalt Write Tests -================================ - -ℹ️ We are working on testify v2 and would love to hear what you'd like to see in it, have your say here: https://cutt.ly/testify - -[](https://travis-ci.org/stretchr/testify) [](https://goreportcard.com/report/github.com/stretchr/testify) [](https://pkg.go.dev/github.com/stretchr/testify) - -Go code (golang) set of packages that provide many tools for testifying that your code will behave as you intend. - -Features include: - - * [Easy assertions](#assert-package) - * [Mocking](#mock-package) - * [Testing suite interfaces and functions](#suite-package) - -Get started: - - * Install testify with [one line of code](#installation), or [update it with another](#staying-up-to-date) - * For an introduction to writing test code in Go, see http://golang.org/doc/code.html#Testing - * Check out the API Documentation http://godoc.org/github.com/stretchr/testify - * To make your testing life easier, check out our other project, [gorc](http://github.com/stretchr/gorc) - * A little about [Test-Driven Development (TDD)](http://en.wikipedia.org/wiki/Test-driven_development) - - - -[`assert`](http://godoc.org/github.com/stretchr/testify/assert "API documentation") package -------------------------------------------------------------------------------------------- - -The `assert` package provides some helpful methods that allow you to write better test code in Go. - - * Prints friendly, easy to read failure descriptions - * Allows for very readable code - * Optionally annotate each assertion with a message - -See it in action: - -```go -package yours - -import ( - "testing" - "github.com/stretchr/testify/assert" -) - -func TestSomething(t *testing.T) { - - // assert equality - assert.Equal(t, 123, 123, "they should be equal") - - // assert inequality - assert.NotEqual(t, 123, 456, "they should not be equal") - - // assert for nil (good for errors) - assert.Nil(t, object) - - // assert for not nil (good when you expect something) - if assert.NotNil(t, object) { - - // now we know that object isn't nil, we are safe to make - // further assertions without causing any errors - assert.Equal(t, "Something", object.Value) - - } - -} -``` - - * Every assert func takes the `testing.T` object as the first argument. This is how it writes the errors out through the normal `go test` capabilities. - * Every assert func returns a bool indicating whether the assertion was successful or not, this is useful for if you want to go on making further assertions under certain conditions. - -if you assert many times, use the below: - -```go -package yours - -import ( - "testing" - "github.com/stretchr/testify/assert" -) - -func TestSomething(t *testing.T) { - assert := assert.New(t) - - // assert equality - assert.Equal(123, 123, "they should be equal") - - // assert inequality - assert.NotEqual(123, 456, "they should not be equal") - - // assert for nil (good for errors) - assert.Nil(object) - - // assert for not nil (good when you expect something) - if assert.NotNil(object) { - - // now we know that object isn't nil, we are safe to make - // further assertions without causing any errors - assert.Equal("Something", object.Value) - } -} -``` - -[`require`](http://godoc.org/github.com/stretchr/testify/require "API documentation") package ---------------------------------------------------------------------------------------------- - -The `require` package provides same global functions as the `assert` package, but instead of returning a boolean result they terminate current test. - -See [t.FailNow](http://golang.org/pkg/testing/#T.FailNow) for details. - -[`mock`](http://godoc.org/github.com/stretchr/testify/mock "API documentation") package ----------------------------------------------------------------------------------------- - -The `mock` package provides a mechanism for easily writing mock objects that can be used in place of real objects when writing test code. - -An example test function that tests a piece of code that relies on an external object `testObj`, can setup expectations (testify) and assert that they indeed happened: - -```go -package yours - -import ( - "testing" - "github.com/stretchr/testify/mock" -) - -/* - Test objects -*/ - -// MyMockedObject is a mocked object that implements an interface -// that describes an object that the code I am testing relies on. -type MyMockedObject struct{ - mock.Mock -} - -// DoSomething is a method on MyMockedObject that implements some interface -// and just records the activity, and returns what the Mock object tells it to. -// -// In the real object, this method would do something useful, but since this -// is a mocked object - we're just going to stub it out. -// -// NOTE: This method is not being tested here, code that uses this object is. -func (m *MyMockedObject) DoSomething(number int) (bool, error) { - - args := m.Called(number) - return args.Bool(0), args.Error(1) - -} - -/* - Actual test functions -*/ - -// TestSomething is an example of how to use our test object to -// make assertions about some target code we are testing. -func TestSomething(t *testing.T) { - - // create an instance of our test object - testObj := new(MyMockedObject) - - // setup expectations - testObj.On("DoSomething", 123).Return(true, nil) - - // call the code we are testing - targetFuncThatDoesSomethingWithObj(testObj) - - // assert that the expectations were met - testObj.AssertExpectations(t) - - -} - -// TestSomethingWithPlaceholder is a second example of how to use our test object to -// make assertions about some target code we are testing. -// This time using a placeholder. Placeholders might be used when the -// data being passed in is normally dynamically generated and cannot be -// predicted beforehand (eg. containing hashes that are time sensitive) -func TestSomethingWithPlaceholder(t *testing.T) { - - // create an instance of our test object - testObj := new(MyMockedObject) - - // setup expectations with a placeholder in the argument list - testObj.On("DoSomething", mock.Anything).Return(true, nil) - - // call the code we are testing - targetFuncThatDoesSomethingWithObj(testObj) - - // assert that the expectations were met - testObj.AssertExpectations(t) - - -} - -// TestSomethingElse2 is a third example that shows how you can use -// the Unset method to cleanup handlers and then add new ones. -func TestSomethingElse2(t *testing.T) { - - // create an instance of our test object - testObj := new(MyMockedObject) - - // setup expectations with a placeholder in the argument list - mockCall := testObj.On("DoSomething", mock.Anything).Return(true, nil) - - // call the code we are testing - targetFuncThatDoesSomethingWithObj(testObj) - - // assert that the expectations were met - testObj.AssertExpectations(t) - - // remove the handler now so we can add another one that takes precedence - mockCall.Unset() - - // return false now instead of true - testObj.On("DoSomething", mock.Anything).Return(false, nil) - - testObj.AssertExpectations(t) -} -``` - -For more information on how to write mock code, check out the [API documentation for the `mock` package](http://godoc.org/github.com/stretchr/testify/mock). - -You can use the [mockery tool](http://github.com/vektra/mockery) to autogenerate the mock code against an interface as well, making using mocks much quicker. - -[`suite`](http://godoc.org/github.com/stretchr/testify/suite "API documentation") package ------------------------------------------------------------------------------------------ - -The `suite` package provides functionality that you might be used to from more common object oriented languages. With it, you can build a testing suite as a struct, build setup/teardown methods and testing methods on your struct, and run them with 'go test' as per normal. - -An example suite is shown below: - -```go -// Basic imports -import ( - "testing" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/suite" -) - -// Define the suite, and absorb the built-in basic suite -// functionality from testify - including a T() method which -// returns the current testing context -type ExampleTestSuite struct { - suite.Suite - VariableThatShouldStartAtFive int -} - -// Make sure that VariableThatShouldStartAtFive is set to five -// before each test -func (suite *ExampleTestSuite) SetupTest() { - suite.VariableThatShouldStartAtFive = 5 -} - -// All methods that begin with "Test" are run as tests within a -// suite. -func (suite *ExampleTestSuite) TestExample() { - assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive) -} - -// In order for 'go test' to run this suite, we need to create -// a normal test function and pass our suite to suite.Run -func TestExampleTestSuite(t *testing.T) { - suite.Run(t, new(ExampleTestSuite)) -} -``` - -For a more complete example, using all of the functionality provided by the suite package, look at our [example testing suite](https://github.com/stretchr/testify/blob/master/suite/suite_test.go) - -For more information on writing suites, check out the [API documentation for the `suite` package](http://godoc.org/github.com/stretchr/testify/suite). - -`Suite` object has assertion methods: - -```go -// Basic imports -import ( - "testing" - "github.com/stretchr/testify/suite" -) - -// Define the suite, and absorb the built-in basic suite -// functionality from testify - including assertion methods. -type ExampleTestSuite struct { - suite.Suite - VariableThatShouldStartAtFive int -} - -// Make sure that VariableThatShouldStartAtFive is set to five -// before each test -func (suite *ExampleTestSuite) SetupTest() { - suite.VariableThatShouldStartAtFive = 5 -} - -// All methods that begin with "Test" are run as tests within a -// suite. -func (suite *ExampleTestSuite) TestExample() { - suite.Equal(suite.VariableThatShouldStartAtFive, 5) -} - -// In order for 'go test' to run this suite, we need to create -// a normal test function and pass our suite to suite.Run -func TestExampleTestSuite(t *testing.T) { - suite.Run(t, new(ExampleTestSuite)) -} -``` - ------- - -Installation -============ - -To install Testify, use `go get`: - - go get github.com/stretchr/testify - -This will then make the following packages available to you: - - github.com/stretchr/testify/assert - github.com/stretchr/testify/require - github.com/stretchr/testify/mock - github.com/stretchr/testify/suite - github.com/stretchr/testify/http (deprecated) - -Import the `testify/assert` package into your code using this template: - -```go -package yours - -import ( - "testing" - "github.com/stretchr/testify/assert" -) - -func TestSomething(t *testing.T) { - - assert.True(t, true, "True is true!") - -} -``` - ------- - -Staying up to date -================== - -To update Testify to the latest version, use `go get -u github.com/stretchr/testify`. - ------- - -Supported go versions -================== - -We currently support the most recent major Go versions from 1.13 onward. - ------- - -Contributing -============ - -Please feel free to submit issues, fork the repository and send pull requests! - -When submitting an issue, we ask that you please include a complete test function that demonstrates the issue. Extra credit for those using Testify to write the test code that demonstrates it. - -Code generation is used. Look for `CODE GENERATED AUTOMATICALLY` at the top of some files. Run `go generate ./...` to update generated files. - -We also chat on the [Gophers Slack](https://gophers.slack.com) group in the `#testify` and `#testify-dev` channels. - ------- - -License -======= - -This project is licensed under the terms of the MIT license. diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare.go deleted file mode 100644 index 95d8e59..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare.go +++ /dev/null @@ -1,458 +0,0 @@ -package assert - -import ( - "bytes" - "fmt" - "reflect" - "time" -) - -type CompareType int - -const ( - compareLess CompareType = iota - 1 - compareEqual - compareGreater -) - -var ( - intType = reflect.TypeOf(int(1)) - int8Type = reflect.TypeOf(int8(1)) - int16Type = reflect.TypeOf(int16(1)) - int32Type = reflect.TypeOf(int32(1)) - int64Type = reflect.TypeOf(int64(1)) - - uintType = reflect.TypeOf(uint(1)) - uint8Type = reflect.TypeOf(uint8(1)) - uint16Type = reflect.TypeOf(uint16(1)) - uint32Type = reflect.TypeOf(uint32(1)) - uint64Type = reflect.TypeOf(uint64(1)) - - float32Type = reflect.TypeOf(float32(1)) - float64Type = reflect.TypeOf(float64(1)) - - stringType = reflect.TypeOf("") - - timeType = reflect.TypeOf(time.Time{}) - bytesType = reflect.TypeOf([]byte{}) -) - -func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { - obj1Value := reflect.ValueOf(obj1) - obj2Value := reflect.ValueOf(obj2) - - // throughout this switch we try and avoid calling .Convert() if possible, - // as this has a pretty big performance impact - switch kind { - case reflect.Int: - { - intobj1, ok := obj1.(int) - if !ok { - intobj1 = obj1Value.Convert(intType).Interface().(int) - } - intobj2, ok := obj2.(int) - if !ok { - intobj2 = obj2Value.Convert(intType).Interface().(int) - } - if intobj1 > intobj2 { - return compareGreater, true - } - if intobj1 == intobj2 { - return compareEqual, true - } - if intobj1 < intobj2 { - return compareLess, true - } - } - case reflect.Int8: - { - int8obj1, ok := obj1.(int8) - if !ok { - int8obj1 = obj1Value.Convert(int8Type).Interface().(int8) - } - int8obj2, ok := obj2.(int8) - if !ok { - int8obj2 = obj2Value.Convert(int8Type).Interface().(int8) - } - if int8obj1 > int8obj2 { - return compareGreater, true - } - if int8obj1 == int8obj2 { - return compareEqual, true - } - if int8obj1 < int8obj2 { - return compareLess, true - } - } - case reflect.Int16: - { - int16obj1, ok := obj1.(int16) - if !ok { - int16obj1 = obj1Value.Convert(int16Type).Interface().(int16) - } - int16obj2, ok := obj2.(int16) - if !ok { - int16obj2 = obj2Value.Convert(int16Type).Interface().(int16) - } - if int16obj1 > int16obj2 { - return compareGreater, true - } - if int16obj1 == int16obj2 { - return compareEqual, true - } - if int16obj1 < int16obj2 { - return compareLess, true - } - } - case reflect.Int32: - { - int32obj1, ok := obj1.(int32) - if !ok { - int32obj1 = obj1Value.Convert(int32Type).Interface().(int32) - } - int32obj2, ok := obj2.(int32) - if !ok { - int32obj2 = obj2Value.Convert(int32Type).Interface().(int32) - } - if int32obj1 > int32obj2 { - return compareGreater, true - } - if int32obj1 == int32obj2 { - return compareEqual, true - } - if int32obj1 < int32obj2 { - return compareLess, true - } - } - case reflect.Int64: - { - int64obj1, ok := obj1.(int64) - if !ok { - int64obj1 = obj1Value.Convert(int64Type).Interface().(int64) - } - int64obj2, ok := obj2.(int64) - if !ok { - int64obj2 = obj2Value.Convert(int64Type).Interface().(int64) - } - if int64obj1 > int64obj2 { - return compareGreater, true - } - if int64obj1 == int64obj2 { - return compareEqual, true - } - if int64obj1 < int64obj2 { - return compareLess, true - } - } - case reflect.Uint: - { - uintobj1, ok := obj1.(uint) - if !ok { - uintobj1 = obj1Value.Convert(uintType).Interface().(uint) - } - uintobj2, ok := obj2.(uint) - if !ok { - uintobj2 = obj2Value.Convert(uintType).Interface().(uint) - } - if uintobj1 > uintobj2 { - return compareGreater, true - } - if uintobj1 == uintobj2 { - return compareEqual, true - } - if uintobj1 < uintobj2 { - return compareLess, true - } - } - case reflect.Uint8: - { - uint8obj1, ok := obj1.(uint8) - if !ok { - uint8obj1 = obj1Value.Convert(uint8Type).Interface().(uint8) - } - uint8obj2, ok := obj2.(uint8) - if !ok { - uint8obj2 = obj2Value.Convert(uint8Type).Interface().(uint8) - } - if uint8obj1 > uint8obj2 { - return compareGreater, true - } - if uint8obj1 == uint8obj2 { - return compareEqual, true - } - if uint8obj1 < uint8obj2 { - return compareLess, true - } - } - case reflect.Uint16: - { - uint16obj1, ok := obj1.(uint16) - if !ok { - uint16obj1 = obj1Value.Convert(uint16Type).Interface().(uint16) - } - uint16obj2, ok := obj2.(uint16) - if !ok { - uint16obj2 = obj2Value.Convert(uint16Type).Interface().(uint16) - } - if uint16obj1 > uint16obj2 { - return compareGreater, true - } - if uint16obj1 == uint16obj2 { - return compareEqual, true - } - if uint16obj1 < uint16obj2 { - return compareLess, true - } - } - case reflect.Uint32: - { - uint32obj1, ok := obj1.(uint32) - if !ok { - uint32obj1 = obj1Value.Convert(uint32Type).Interface().(uint32) - } - uint32obj2, ok := obj2.(uint32) - if !ok { - uint32obj2 = obj2Value.Convert(uint32Type).Interface().(uint32) - } - if uint32obj1 > uint32obj2 { - return compareGreater, true - } - if uint32obj1 == uint32obj2 { - return compareEqual, true - } - if uint32obj1 < uint32obj2 { - return compareLess, true - } - } - case reflect.Uint64: - { - uint64obj1, ok := obj1.(uint64) - if !ok { - uint64obj1 = obj1Value.Convert(uint64Type).Interface().(uint64) - } - uint64obj2, ok := obj2.(uint64) - if !ok { - uint64obj2 = obj2Value.Convert(uint64Type).Interface().(uint64) - } - if uint64obj1 > uint64obj2 { - return compareGreater, true - } - if uint64obj1 == uint64obj2 { - return compareEqual, true - } - if uint64obj1 < uint64obj2 { - return compareLess, true - } - } - case reflect.Float32: - { - float32obj1, ok := obj1.(float32) - if !ok { - float32obj1 = obj1Value.Convert(float32Type).Interface().(float32) - } - float32obj2, ok := obj2.(float32) - if !ok { - float32obj2 = obj2Value.Convert(float32Type).Interface().(float32) - } - if float32obj1 > float32obj2 { - return compareGreater, true - } - if float32obj1 == float32obj2 { - return compareEqual, true - } - if float32obj1 < float32obj2 { - return compareLess, true - } - } - case reflect.Float64: - { - float64obj1, ok := obj1.(float64) - if !ok { - float64obj1 = obj1Value.Convert(float64Type).Interface().(float64) - } - float64obj2, ok := obj2.(float64) - if !ok { - float64obj2 = obj2Value.Convert(float64Type).Interface().(float64) - } - if float64obj1 > float64obj2 { - return compareGreater, true - } - if float64obj1 == float64obj2 { - return compareEqual, true - } - if float64obj1 < float64obj2 { - return compareLess, true - } - } - case reflect.String: - { - stringobj1, ok := obj1.(string) - if !ok { - stringobj1 = obj1Value.Convert(stringType).Interface().(string) - } - stringobj2, ok := obj2.(string) - if !ok { - stringobj2 = obj2Value.Convert(stringType).Interface().(string) - } - if stringobj1 > stringobj2 { - return compareGreater, true - } - if stringobj1 == stringobj2 { - return compareEqual, true - } - if stringobj1 < stringobj2 { - return compareLess, true - } - } - // Check for known struct types we can check for compare results. - case reflect.Struct: - { - // All structs enter here. We're not interested in most types. - if !canConvert(obj1Value, timeType) { - break - } - - // time.Time can compared! - timeObj1, ok := obj1.(time.Time) - if !ok { - timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time) - } - - timeObj2, ok := obj2.(time.Time) - if !ok { - timeObj2 = obj2Value.Convert(timeType).Interface().(time.Time) - } - - return compare(timeObj1.UnixNano(), timeObj2.UnixNano(), reflect.Int64) - } - case reflect.Slice: - { - // We only care about the []byte type. - if !canConvert(obj1Value, bytesType) { - break - } - - // []byte can be compared! - bytesObj1, ok := obj1.([]byte) - if !ok { - bytesObj1 = obj1Value.Convert(bytesType).Interface().([]byte) - - } - bytesObj2, ok := obj2.([]byte) - if !ok { - bytesObj2 = obj2Value.Convert(bytesType).Interface().([]byte) - } - - return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true - } - } - - return compareEqual, false -} - -// Greater asserts that the first element is greater than the second -// -// assert.Greater(t, 2, 1) -// assert.Greater(t, float64(2), float64(1)) -// assert.Greater(t, "b", "a") -func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...) -} - -// GreaterOrEqual asserts that the first element is greater than or equal to the second -// -// assert.GreaterOrEqual(t, 2, 1) -// assert.GreaterOrEqual(t, 2, 2) -// assert.GreaterOrEqual(t, "b", "a") -// assert.GreaterOrEqual(t, "b", "b") -func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...) -} - -// Less asserts that the first element is less than the second -// -// assert.Less(t, 1, 2) -// assert.Less(t, float64(1), float64(2)) -// assert.Less(t, "a", "b") -func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...) -} - -// LessOrEqual asserts that the first element is less than or equal to the second -// -// assert.LessOrEqual(t, 1, 2) -// assert.LessOrEqual(t, 2, 2) -// assert.LessOrEqual(t, "a", "b") -// assert.LessOrEqual(t, "b", "b") -func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...) -} - -// Positive asserts that the specified element is positive -// -// assert.Positive(t, 1) -// assert.Positive(t, 1.23) -func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - zero := reflect.Zero(reflect.TypeOf(e)) - return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs...) -} - -// Negative asserts that the specified element is negative -// -// assert.Negative(t, -1) -// assert.Negative(t, -1.23) -func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - zero := reflect.Zero(reflect.TypeOf(e)) - return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs...) -} - -func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - e1Kind := reflect.ValueOf(e1).Kind() - e2Kind := reflect.ValueOf(e2).Kind() - if e1Kind != e2Kind { - return Fail(t, "Elements should be the same type", msgAndArgs...) - } - - compareResult, isComparable := compare(e1, e2, e1Kind) - if !isComparable { - return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...) - } - - if !containsValue(allowedComparesResults, compareResult) { - return Fail(t, fmt.Sprintf(failMessage, e1, e2), msgAndArgs...) - } - - return true -} - -func containsValue(values []CompareType, value CompareType) bool { - for _, v := range values { - if v == value { - return true - } - } - - return false -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare_can_convert.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare_can_convert.go deleted file mode 100644 index da86790..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare_can_convert.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build go1.17 -// +build go1.17 - -// TODO: once support for Go 1.16 is dropped, this file can be -// merged/removed with assertion_compare_go1.17_test.go and -// assertion_compare_legacy.go - -package assert - -import "reflect" - -// Wrapper around reflect.Value.CanConvert, for compatibility -// reasons. -func canConvert(value reflect.Value, to reflect.Type) bool { - return value.CanConvert(to) -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare_go1.17_test.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare_go1.17_test.go deleted file mode 100644 index 53e01ed..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare_go1.17_test.go +++ /dev/null @@ -1,182 +0,0 @@ -//go:build go1.17 -// +build go1.17 - -// TODO: once support for Go 1.16 is dropped, this file can be -// merged/removed with assertion_compare_can_convert.go and -// assertion_compare_legacy.go - -package assert - -import ( - "bytes" - "reflect" - "testing" - "time" -) - -func TestCompare17(t *testing.T) { - type customTime time.Time - type customBytes []byte - for _, currCase := range []struct { - less interface{} - greater interface{} - cType string - }{ - {less: time.Now(), greater: time.Now().Add(time.Hour), cType: "time.Time"}, - {less: customTime(time.Now()), greater: customTime(time.Now().Add(time.Hour)), cType: "time.Time"}, - {less: []byte{1, 1}, greater: []byte{1, 2}, cType: "[]byte"}, - {less: customBytes([]byte{1, 1}), greater: customBytes([]byte{1, 2}), cType: "[]byte"}, - } { - resLess, isComparable := compare(currCase.less, currCase.greater, reflect.ValueOf(currCase.less).Kind()) - if !isComparable { - t.Error("object should be comparable for type " + currCase.cType) - } - - if resLess != compareLess { - t.Errorf("object less (%v) should be less than greater (%v) for type "+currCase.cType, - currCase.less, currCase.greater) - } - - resGreater, isComparable := compare(currCase.greater, currCase.less, reflect.ValueOf(currCase.less).Kind()) - if !isComparable { - t.Error("object are comparable for type " + currCase.cType) - } - - if resGreater != compareGreater { - t.Errorf("object greater should be greater than less for type " + currCase.cType) - } - - resEqual, isComparable := compare(currCase.less, currCase.less, reflect.ValueOf(currCase.less).Kind()) - if !isComparable { - t.Error("object are comparable for type " + currCase.cType) - } - - if resEqual != 0 { - t.Errorf("objects should be equal for type " + currCase.cType) - } - } -} - -func TestGreater17(t *testing.T) { - mockT := new(testing.T) - - if !Greater(mockT, 2, 1) { - t.Error("Greater should return true") - } - - if Greater(mockT, 1, 1) { - t.Error("Greater should return false") - } - - if Greater(mockT, 1, 2) { - t.Error("Greater should return false") - } - - // Check error report - for _, currCase := range []struct { - less interface{} - greater interface{} - msg string - }{ - {less: []byte{1, 1}, greater: []byte{1, 2}, msg: `"[1 1]" is not greater than "[1 2]"`}, - {less: time.Time{}, greater: time.Time{}.Add(time.Hour), msg: `"0001-01-01 00:00:00 +0000 UTC" is not greater than "0001-01-01 01:00:00 +0000 UTC"`}, - } { - out := &outputT{buf: bytes.NewBuffer(nil)} - False(t, Greater(out, currCase.less, currCase.greater)) - Contains(t, out.buf.String(), currCase.msg) - Contains(t, out.helpers, "github.com/stretchr/testify/assert.Greater") - } -} - -func TestGreaterOrEqual17(t *testing.T) { - mockT := new(testing.T) - - if !GreaterOrEqual(mockT, 2, 1) { - t.Error("GreaterOrEqual should return true") - } - - if !GreaterOrEqual(mockT, 1, 1) { - t.Error("GreaterOrEqual should return true") - } - - if GreaterOrEqual(mockT, 1, 2) { - t.Error("GreaterOrEqual should return false") - } - - // Check error report - for _, currCase := range []struct { - less interface{} - greater interface{} - msg string - }{ - {less: []byte{1, 1}, greater: []byte{1, 2}, msg: `"[1 1]" is not greater than or equal to "[1 2]"`}, - {less: time.Time{}, greater: time.Time{}.Add(time.Hour), msg: `"0001-01-01 00:00:00 +0000 UTC" is not greater than or equal to "0001-01-01 01:00:00 +0000 UTC"`}, - } { - out := &outputT{buf: bytes.NewBuffer(nil)} - False(t, GreaterOrEqual(out, currCase.less, currCase.greater)) - Contains(t, out.buf.String(), currCase.msg) - Contains(t, out.helpers, "github.com/stretchr/testify/assert.GreaterOrEqual") - } -} - -func TestLess17(t *testing.T) { - mockT := new(testing.T) - - if !Less(mockT, 1, 2) { - t.Error("Less should return true") - } - - if Less(mockT, 1, 1) { - t.Error("Less should return false") - } - - if Less(mockT, 2, 1) { - t.Error("Less should return false") - } - - // Check error report - for _, currCase := range []struct { - less interface{} - greater interface{} - msg string - }{ - {less: []byte{1, 1}, greater: []byte{1, 2}, msg: `"[1 2]" is not less than "[1 1]"`}, - {less: time.Time{}, greater: time.Time{}.Add(time.Hour), msg: `"0001-01-01 01:00:00 +0000 UTC" is not less than "0001-01-01 00:00:00 +0000 UTC"`}, - } { - out := &outputT{buf: bytes.NewBuffer(nil)} - False(t, Less(out, currCase.greater, currCase.less)) - Contains(t, out.buf.String(), currCase.msg) - Contains(t, out.helpers, "github.com/stretchr/testify/assert.Less") - } -} - -func TestLessOrEqual17(t *testing.T) { - mockT := new(testing.T) - - if !LessOrEqual(mockT, 1, 2) { - t.Error("LessOrEqual should return true") - } - - if !LessOrEqual(mockT, 1, 1) { - t.Error("LessOrEqual should return true") - } - - if LessOrEqual(mockT, 2, 1) { - t.Error("LessOrEqual should return false") - } - - // Check error report - for _, currCase := range []struct { - less interface{} - greater interface{} - msg string - }{ - {less: []byte{1, 1}, greater: []byte{1, 2}, msg: `"[1 2]" is not less than or equal to "[1 1]"`}, - {less: time.Time{}, greater: time.Time{}.Add(time.Hour), msg: `"0001-01-01 01:00:00 +0000 UTC" is not less than or equal to "0001-01-01 00:00:00 +0000 UTC"`}, - } { - out := &outputT{buf: bytes.NewBuffer(nil)} - False(t, LessOrEqual(out, currCase.greater, currCase.less)) - Contains(t, out.buf.String(), currCase.msg) - Contains(t, out.helpers, "github.com/stretchr/testify/assert.LessOrEqual") - } -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare_legacy.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare_legacy.go deleted file mode 100644 index 1701af2..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare_legacy.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build !go1.17 -// +build !go1.17 - -// TODO: once support for Go 1.16 is dropped, this file can be -// merged/removed with assertion_compare_go1.17_test.go and -// assertion_compare_can_convert.go - -package assert - -import "reflect" - -// Older versions of Go does not have the reflect.Value.CanConvert -// method. -func canConvert(value reflect.Value, to reflect.Type) bool { - return false -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare_test.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare_test.go deleted file mode 100644 index a38d880..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_compare_test.go +++ /dev/null @@ -1,449 +0,0 @@ -package assert - -import ( - "bytes" - "fmt" - "reflect" - "runtime" - "testing" -) - -func TestCompare(t *testing.T) { - type customInt int - type customInt8 int8 - type customInt16 int16 - type customInt32 int32 - type customInt64 int64 - type customUInt uint - type customUInt8 uint8 - type customUInt16 uint16 - type customUInt32 uint32 - type customUInt64 uint64 - type customFloat32 float32 - type customFloat64 float64 - type customString string - for _, currCase := range []struct { - less interface{} - greater interface{} - cType string - }{ - {less: customString("a"), greater: customString("b"), cType: "string"}, - {less: "a", greater: "b", cType: "string"}, - {less: customInt(1), greater: customInt(2), cType: "int"}, - {less: int(1), greater: int(2), cType: "int"}, - {less: customInt8(1), greater: customInt8(2), cType: "int8"}, - {less: int8(1), greater: int8(2), cType: "int8"}, - {less: customInt16(1), greater: customInt16(2), cType: "int16"}, - {less: int16(1), greater: int16(2), cType: "int16"}, - {less: customInt32(1), greater: customInt32(2), cType: "int32"}, - {less: int32(1), greater: int32(2), cType: "int32"}, - {less: customInt64(1), greater: customInt64(2), cType: "int64"}, - {less: int64(1), greater: int64(2), cType: "int64"}, - {less: customUInt(1), greater: customUInt(2), cType: "uint"}, - {less: uint8(1), greater: uint8(2), cType: "uint8"}, - {less: customUInt8(1), greater: customUInt8(2), cType: "uint8"}, - {less: uint16(1), greater: uint16(2), cType: "uint16"}, - {less: customUInt16(1), greater: customUInt16(2), cType: "uint16"}, - {less: uint32(1), greater: uint32(2), cType: "uint32"}, - {less: customUInt32(1), greater: customUInt32(2), cType: "uint32"}, - {less: uint64(1), greater: uint64(2), cType: "uint64"}, - {less: customUInt64(1), greater: customUInt64(2), cType: "uint64"}, - {less: float32(1.23), greater: float32(2.34), cType: "float32"}, - {less: customFloat32(1.23), greater: customFloat32(2.23), cType: "float32"}, - {less: float64(1.23), greater: float64(2.34), cType: "float64"}, - {less: customFloat64(1.23), greater: customFloat64(2.34), cType: "float64"}, - } { - resLess, isComparable := compare(currCase.less, currCase.greater, reflect.ValueOf(currCase.less).Kind()) - if !isComparable { - t.Error("object should be comparable for type " + currCase.cType) - } - - if resLess != compareLess { - t.Errorf("object less (%v) should be less than greater (%v) for type "+currCase.cType, - currCase.less, currCase.greater) - } - - resGreater, isComparable := compare(currCase.greater, currCase.less, reflect.ValueOf(currCase.less).Kind()) - if !isComparable { - t.Error("object are comparable for type " + currCase.cType) - } - - if resGreater != compareGreater { - t.Errorf("object greater should be greater than less for type " + currCase.cType) - } - - resEqual, isComparable := compare(currCase.less, currCase.less, reflect.ValueOf(currCase.less).Kind()) - if !isComparable { - t.Error("object are comparable for type " + currCase.cType) - } - - if resEqual != 0 { - t.Errorf("objects should be equal for type " + currCase.cType) - } - } -} - -type outputT struct { - buf *bytes.Buffer - helpers map[string]struct{} -} - -// Implements TestingT -func (t *outputT) Errorf(format string, args ...interface{}) { - s := fmt.Sprintf(format, args...) - t.buf.WriteString(s) -} - -func (t *outputT) Helper() { - if t.helpers == nil { - t.helpers = make(map[string]struct{}) - } - t.helpers[callerName(1)] = struct{}{} -} - -// callerName gives the function name (qualified with a package path) -// for the caller after skip frames (where 0 means the current function). -func callerName(skip int) string { - // Make room for the skip PC. - var pc [1]uintptr - n := runtime.Callers(skip+2, pc[:]) // skip + runtime.Callers + callerName - if n == 0 { - panic("testing: zero callers found") - } - frames := runtime.CallersFrames(pc[:n]) - frame, _ := frames.Next() - return frame.Function -} - -func TestGreater(t *testing.T) { - mockT := new(testing.T) - - if !Greater(mockT, 2, 1) { - t.Error("Greater should return true") - } - - if Greater(mockT, 1, 1) { - t.Error("Greater should return false") - } - - if Greater(mockT, 1, 2) { - t.Error("Greater should return false") - } - - // Check error report - for _, currCase := range []struct { - less interface{} - greater interface{} - msg string - }{ - {less: "a", greater: "b", msg: `"a" is not greater than "b"`}, - {less: int(1), greater: int(2), msg: `"1" is not greater than "2"`}, - {less: int8(1), greater: int8(2), msg: `"1" is not greater than "2"`}, - {less: int16(1), greater: int16(2), msg: `"1" is not greater than "2"`}, - {less: int32(1), greater: int32(2), msg: `"1" is not greater than "2"`}, - {less: int64(1), greater: int64(2), msg: `"1" is not greater than "2"`}, - {less: uint8(1), greater: uint8(2), msg: `"1" is not greater than "2"`}, - {less: uint16(1), greater: uint16(2), msg: `"1" is not greater than "2"`}, - {less: uint32(1), greater: uint32(2), msg: `"1" is not greater than "2"`}, - {less: uint64(1), greater: uint64(2), msg: `"1" is not greater than "2"`}, - {less: float32(1.23), greater: float32(2.34), msg: `"1.23" is not greater than "2.34"`}, - {less: float64(1.23), greater: float64(2.34), msg: `"1.23" is not greater than "2.34"`}, - } { - out := &outputT{buf: bytes.NewBuffer(nil)} - False(t, Greater(out, currCase.less, currCase.greater)) - Contains(t, out.buf.String(), currCase.msg) - Contains(t, out.helpers, "github.com/stretchr/testify/assert.Greater") - } -} - -func TestGreaterOrEqual(t *testing.T) { - mockT := new(testing.T) - - if !GreaterOrEqual(mockT, 2, 1) { - t.Error("GreaterOrEqual should return true") - } - - if !GreaterOrEqual(mockT, 1, 1) { - t.Error("GreaterOrEqual should return true") - } - - if GreaterOrEqual(mockT, 1, 2) { - t.Error("GreaterOrEqual should return false") - } - - // Check error report - for _, currCase := range []struct { - less interface{} - greater interface{} - msg string - }{ - {less: "a", greater: "b", msg: `"a" is not greater than or equal to "b"`}, - {less: int(1), greater: int(2), msg: `"1" is not greater than or equal to "2"`}, - {less: int8(1), greater: int8(2), msg: `"1" is not greater than or equal to "2"`}, - {less: int16(1), greater: int16(2), msg: `"1" is not greater than or equal to "2"`}, - {less: int32(1), greater: int32(2), msg: `"1" is not greater than or equal to "2"`}, - {less: int64(1), greater: int64(2), msg: `"1" is not greater than or equal to "2"`}, - {less: uint8(1), greater: uint8(2), msg: `"1" is not greater than or equal to "2"`}, - {less: uint16(1), greater: uint16(2), msg: `"1" is not greater than or equal to "2"`}, - {less: uint32(1), greater: uint32(2), msg: `"1" is not greater than or equal to "2"`}, - {less: uint64(1), greater: uint64(2), msg: `"1" is not greater than or equal to "2"`}, - {less: float32(1.23), greater: float32(2.34), msg: `"1.23" is not greater than or equal to "2.34"`}, - {less: float64(1.23), greater: float64(2.34), msg: `"1.23" is not greater than or equal to "2.34"`}, - } { - out := &outputT{buf: bytes.NewBuffer(nil)} - False(t, GreaterOrEqual(out, currCase.less, currCase.greater)) - Contains(t, out.buf.String(), currCase.msg) - Contains(t, out.helpers, "github.com/stretchr/testify/assert.GreaterOrEqual") - } -} - -func TestLess(t *testing.T) { - mockT := new(testing.T) - - if !Less(mockT, 1, 2) { - t.Error("Less should return true") - } - - if Less(mockT, 1, 1) { - t.Error("Less should return false") - } - - if Less(mockT, 2, 1) { - t.Error("Less should return false") - } - - // Check error report - for _, currCase := range []struct { - less interface{} - greater interface{} - msg string - }{ - {less: "a", greater: "b", msg: `"b" is not less than "a"`}, - {less: int(1), greater: int(2), msg: `"2" is not less than "1"`}, - {less: int8(1), greater: int8(2), msg: `"2" is not less than "1"`}, - {less: int16(1), greater: int16(2), msg: `"2" is not less than "1"`}, - {less: int32(1), greater: int32(2), msg: `"2" is not less than "1"`}, - {less: int64(1), greater: int64(2), msg: `"2" is not less than "1"`}, - {less: uint8(1), greater: uint8(2), msg: `"2" is not less than "1"`}, - {less: uint16(1), greater: uint16(2), msg: `"2" is not less than "1"`}, - {less: uint32(1), greater: uint32(2), msg: `"2" is not less than "1"`}, - {less: uint64(1), greater: uint64(2), msg: `"2" is not less than "1"`}, - {less: float32(1.23), greater: float32(2.34), msg: `"2.34" is not less than "1.23"`}, - {less: float64(1.23), greater: float64(2.34), msg: `"2.34" is not less than "1.23"`}, - } { - out := &outputT{buf: bytes.NewBuffer(nil)} - False(t, Less(out, currCase.greater, currCase.less)) - Contains(t, out.buf.String(), currCase.msg) - Contains(t, out.helpers, "github.com/stretchr/testify/assert.Less") - } -} - -func TestLessOrEqual(t *testing.T) { - mockT := new(testing.T) - - if !LessOrEqual(mockT, 1, 2) { - t.Error("LessOrEqual should return true") - } - - if !LessOrEqual(mockT, 1, 1) { - t.Error("LessOrEqual should return true") - } - - if LessOrEqual(mockT, 2, 1) { - t.Error("LessOrEqual should return false") - } - - // Check error report - for _, currCase := range []struct { - less interface{} - greater interface{} - msg string - }{ - {less: "a", greater: "b", msg: `"b" is not less than or equal to "a"`}, - {less: int(1), greater: int(2), msg: `"2" is not less than or equal to "1"`}, - {less: int8(1), greater: int8(2), msg: `"2" is not less than or equal to "1"`}, - {less: int16(1), greater: int16(2), msg: `"2" is not less than or equal to "1"`}, - {less: int32(1), greater: int32(2), msg: `"2" is not less than or equal to "1"`}, - {less: int64(1), greater: int64(2), msg: `"2" is not less than or equal to "1"`}, - {less: uint8(1), greater: uint8(2), msg: `"2" is not less than or equal to "1"`}, - {less: uint16(1), greater: uint16(2), msg: `"2" is not less than or equal to "1"`}, - {less: uint32(1), greater: uint32(2), msg: `"2" is not less than or equal to "1"`}, - {less: uint64(1), greater: uint64(2), msg: `"2" is not less than or equal to "1"`}, - {less: float32(1.23), greater: float32(2.34), msg: `"2.34" is not less than or equal to "1.23"`}, - {less: float64(1.23), greater: float64(2.34), msg: `"2.34" is not less than or equal to "1.23"`}, - } { - out := &outputT{buf: bytes.NewBuffer(nil)} - False(t, LessOrEqual(out, currCase.greater, currCase.less)) - Contains(t, out.buf.String(), currCase.msg) - Contains(t, out.helpers, "github.com/stretchr/testify/assert.LessOrEqual") - } -} - -func TestPositive(t *testing.T) { - mockT := new(testing.T) - - if !Positive(mockT, 1) { - t.Error("Positive should return true") - } - - if !Positive(mockT, 1.23) { - t.Error("Positive should return true") - } - - if Positive(mockT, -1) { - t.Error("Positive should return false") - } - - if Positive(mockT, -1.23) { - t.Error("Positive should return false") - } - - // Check error report - for _, currCase := range []struct { - e interface{} - msg string - }{ - {e: int(-1), msg: `"-1" is not positive`}, - {e: int8(-1), msg: `"-1" is not positive`}, - {e: int16(-1), msg: `"-1" is not positive`}, - {e: int32(-1), msg: `"-1" is not positive`}, - {e: int64(-1), msg: `"-1" is not positive`}, - {e: float32(-1.23), msg: `"-1.23" is not positive`}, - {e: float64(-1.23), msg: `"-1.23" is not positive`}, - } { - out := &outputT{buf: bytes.NewBuffer(nil)} - False(t, Positive(out, currCase.e)) - Contains(t, out.buf.String(), currCase.msg) - Contains(t, out.helpers, "github.com/stretchr/testify/assert.Positive") - } -} - -func TestNegative(t *testing.T) { - mockT := new(testing.T) - - if !Negative(mockT, -1) { - t.Error("Negative should return true") - } - - if !Negative(mockT, -1.23) { - t.Error("Negative should return true") - } - - if Negative(mockT, 1) { - t.Error("Negative should return false") - } - - if Negative(mockT, 1.23) { - t.Error("Negative should return false") - } - - // Check error report - for _, currCase := range []struct { - e interface{} - msg string - }{ - {e: int(1), msg: `"1" is not negative`}, - {e: int8(1), msg: `"1" is not negative`}, - {e: int16(1), msg: `"1" is not negative`}, - {e: int32(1), msg: `"1" is not negative`}, - {e: int64(1), msg: `"1" is not negative`}, - {e: float32(1.23), msg: `"1.23" is not negative`}, - {e: float64(1.23), msg: `"1.23" is not negative`}, - } { - out := &outputT{buf: bytes.NewBuffer(nil)} - False(t, Negative(out, currCase.e)) - Contains(t, out.buf.String(), currCase.msg) - Contains(t, out.helpers, "github.com/stretchr/testify/assert.Negative") - } -} - -func Test_compareTwoValuesDifferentValuesTypes(t *testing.T) { - mockT := new(testing.T) - - for _, currCase := range []struct { - v1 interface{} - v2 interface{} - compareResult bool - }{ - {v1: 123, v2: "abc"}, - {v1: "abc", v2: 123456}, - {v1: float64(12), v2: "123"}, - {v1: "float(12)", v2: float64(1)}, - } { - compareResult := compareTwoValues(mockT, currCase.v1, currCase.v2, []CompareType{compareLess, compareEqual, compareGreater}, "testFailMessage") - False(t, compareResult) - } -} - -func Test_compareTwoValuesNotComparableValues(t *testing.T) { - mockT := new(testing.T) - - type CompareStruct struct { - } - - for _, currCase := range []struct { - v1 interface{} - v2 interface{} - }{ - {v1: CompareStruct{}, v2: CompareStruct{}}, - {v1: map[string]int{}, v2: map[string]int{}}, - {v1: make([]int, 5), v2: make([]int, 5)}, - } { - compareResult := compareTwoValues(mockT, currCase.v1, currCase.v2, []CompareType{compareLess, compareEqual, compareGreater}, "testFailMessage") - False(t, compareResult) - } -} - -func Test_compareTwoValuesCorrectCompareResult(t *testing.T) { - mockT := new(testing.T) - - for _, currCase := range []struct { - v1 interface{} - v2 interface{} - compareTypes []CompareType - }{ - {v1: 1, v2: 2, compareTypes: []CompareType{compareLess}}, - {v1: 1, v2: 2, compareTypes: []CompareType{compareLess, compareEqual}}, - {v1: 2, v2: 2, compareTypes: []CompareType{compareGreater, compareEqual}}, - {v1: 2, v2: 2, compareTypes: []CompareType{compareEqual}}, - {v1: 2, v2: 1, compareTypes: []CompareType{compareEqual, compareGreater}}, - {v1: 2, v2: 1, compareTypes: []CompareType{compareGreater}}, - } { - compareResult := compareTwoValues(mockT, currCase.v1, currCase.v2, currCase.compareTypes, "testFailMessage") - True(t, compareResult) - } -} - -func Test_containsValue(t *testing.T) { - for _, currCase := range []struct { - values []CompareType - value CompareType - result bool - }{ - {values: []CompareType{compareGreater}, value: compareGreater, result: true}, - {values: []CompareType{compareGreater, compareLess}, value: compareGreater, result: true}, - {values: []CompareType{compareGreater, compareLess}, value: compareLess, result: true}, - {values: []CompareType{compareGreater, compareLess}, value: compareEqual, result: false}, - } { - compareResult := containsValue(currCase.values, currCase.value) - Equal(t, currCase.result, compareResult) - } -} - -func TestComparingMsgAndArgsForwarding(t *testing.T) { - msgAndArgs := []interface{}{"format %s %x", "this", 0xc001} - expectedOutput := "format this c001\n" - funcs := []func(t TestingT){ - func(t TestingT) { Greater(t, 1, 2, msgAndArgs...) }, - func(t TestingT) { GreaterOrEqual(t, 1, 2, msgAndArgs...) }, - func(t TestingT) { Less(t, 2, 1, msgAndArgs...) }, - func(t TestingT) { LessOrEqual(t, 2, 1, msgAndArgs...) }, - func(t TestingT) { Positive(t, 0, msgAndArgs...) }, - func(t TestingT) { Negative(t, 0, msgAndArgs...) }, - } - for _, f := range funcs { - out := &outputT{buf: bytes.NewBuffer(nil)} - f(out) - Contains(t, out.buf.String(), expectedOutput) - } -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_format.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_format.go deleted file mode 100644 index 7880b8f..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_format.go +++ /dev/null @@ -1,763 +0,0 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ - -package assert - -import ( - http "net/http" - url "net/url" - time "time" -) - -// Conditionf uses a Comparison to assert a complex condition. -func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Condition(t, comp, append([]interface{}{msg}, args...)...) -} - -// Containsf asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") -// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") -// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") -func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Contains(t, s, contains, append([]interface{}{msg}, args...)...) -} - -// DirExistsf checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return DirExists(t, path, append([]interface{}{msg}, args...)...) -} - -// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") -func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...) -} - -// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// assert.Emptyf(t, obj, "error message %s", "formatted") -func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Empty(t, object, append([]interface{}{msg}, args...)...) -} - -// Equalf asserts that two objects are equal. -// -// assert.Equalf(t, 123, 123, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Equal(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// EqualErrorf asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") -func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...) -} - -// EqualValuesf asserts that two objects are equal or convertable to the same types -// and equal. -// -// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") -func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// Errorf asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// if assert.Errorf(t, err, "error message %s", "formatted") { -// assert.Equal(t, expectedErrorf, err) -// } -func Errorf(t TestingT, err error, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Error(t, err, append([]interface{}{msg}, args...)...) -} - -// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return ErrorAs(t, err, target, append([]interface{}{msg}, args...)...) -} - -// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted") -func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return ErrorContains(t, theError, contains, append([]interface{}{msg}, args...)...) -} - -// ErrorIsf asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return ErrorIs(t, err, target, append([]interface{}{msg}, args...)...) -} - -// Eventuallyf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Eventually(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) -} - -// Exactlyf asserts that two objects are equal in value and type. -// -// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted") -func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// Failf reports a failure through -func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, failureMessage, append([]interface{}{msg}, args...)...) -} - -// FailNowf fails test -func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...) -} - -// Falsef asserts that the specified value is false. -// -// assert.Falsef(t, myBool, "error message %s", "formatted") -func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return False(t, value, append([]interface{}{msg}, args...)...) -} - -// FileExistsf checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return FileExists(t, path, append([]interface{}{msg}, args...)...) -} - -// Greaterf asserts that the first element is greater than the second -// -// assert.Greaterf(t, 2, 1, "error message %s", "formatted") -// assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted") -// assert.Greaterf(t, "b", "a", "error message %s", "formatted") -func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Greater(t, e1, e2, append([]interface{}{msg}, args...)...) -} - -// GreaterOrEqualf asserts that the first element is greater than or equal to the second -// -// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted") -// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted") -// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted") -// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted") -func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return GreaterOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...) -} - -// HTTPBodyContainsf asserts that a specified handler returns a -// body that contains a string. -// -// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) -} - -// HTTPBodyNotContainsf asserts that a specified handler returns a -// body that does not contain a string. -// -// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) -} - -// HTTPErrorf asserts that a specified handler returns an error status code. -// -// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return HTTPError(t, handler, method, url, values, append([]interface{}{msg}, args...)...) -} - -// HTTPRedirectf asserts that a specified handler returns a redirect status code. -// -// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...) -} - -// HTTPStatusCodef asserts that a specified handler returns a specified status code. -// -// assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return HTTPStatusCode(t, handler, method, url, values, statuscode, append([]interface{}{msg}, args...)...) -} - -// HTTPSuccessf asserts that a specified handler returns a success status code. -// -// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...) -} - -// Implementsf asserts that an object is implemented by the specified interface. -// -// assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) -} - -// InDeltaf asserts that the two numerals are within delta of each other. -// -// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted") -func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...) -} - -// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return InDeltaMapValues(t, expected, actual, delta, append([]interface{}{msg}, args...)...) -} - -// InDeltaSlicef is the same as InDelta, except it compares two slices. -func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...) -} - -// InEpsilonf asserts that expected and actual have a relative error less than epsilon -func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) -} - -// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. -func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) -} - -// IsDecreasingf asserts that the collection is decreasing -// -// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted") -// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted") -// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted") -func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return IsDecreasing(t, object, append([]interface{}{msg}, args...)...) -} - -// IsIncreasingf asserts that the collection is increasing -// -// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted") -// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted") -// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted") -func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return IsIncreasing(t, object, append([]interface{}{msg}, args...)...) -} - -// IsNonDecreasingf asserts that the collection is not decreasing -// -// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted") -// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted") -// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted") -func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return IsNonDecreasing(t, object, append([]interface{}{msg}, args...)...) -} - -// IsNonIncreasingf asserts that the collection is not increasing -// -// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted") -// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted") -// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted") -func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return IsNonIncreasing(t, object, append([]interface{}{msg}, args...)...) -} - -// IsTypef asserts that the specified objects are of the same type. -func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...) -} - -// JSONEqf asserts that two JSON strings are equivalent. -// -// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") -func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// Lenf asserts that the specified object has specific length. -// Lenf also fails if the object has a type that len() not accept. -// -// assert.Lenf(t, mySlice, 3, "error message %s", "formatted") -func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Len(t, object, length, append([]interface{}{msg}, args...)...) -} - -// Lessf asserts that the first element is less than the second -// -// assert.Lessf(t, 1, 2, "error message %s", "formatted") -// assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted") -// assert.Lessf(t, "a", "b", "error message %s", "formatted") -func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Less(t, e1, e2, append([]interface{}{msg}, args...)...) -} - -// LessOrEqualf asserts that the first element is less than or equal to the second -// -// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted") -// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted") -// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted") -// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted") -func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return LessOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...) -} - -// Negativef asserts that the specified element is negative -// -// assert.Negativef(t, -1, "error message %s", "formatted") -// assert.Negativef(t, -1.23, "error message %s", "formatted") -func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Negative(t, e, append([]interface{}{msg}, args...)...) -} - -// Neverf asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Never(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) -} - -// Nilf asserts that the specified object is nil. -// -// assert.Nilf(t, err, "error message %s", "formatted") -func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Nil(t, object, append([]interface{}{msg}, args...)...) -} - -// NoDirExistsf checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NoDirExists(t, path, append([]interface{}{msg}, args...)...) -} - -// NoErrorf asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if assert.NoErrorf(t, err, "error message %s", "formatted") { -// assert.Equal(t, expectedObj, actualObj) -// } -func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NoError(t, err, append([]interface{}{msg}, args...)...) -} - -// NoFileExistsf checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NoFileExists(t, path, append([]interface{}{msg}, args...)...) -} - -// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") -// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") -// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") -func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotContains(t, s, contains, append([]interface{}{msg}, args...)...) -} - -// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// if assert.NotEmptyf(t, obj, "error message %s", "formatted") { -// assert.Equal(t, "two", obj[1]) -// } -func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotEmpty(t, object, append([]interface{}{msg}, args...)...) -} - -// NotEqualf asserts that the specified values are NOT equal. -// -// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// NotEqualValuesf asserts that two objects are not equal even when converted to the same type -// -// assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted") -func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotEqualValues(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// NotErrorIsf asserts that at none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...) -} - -// NotNilf asserts that the specified object is not nil. -// -// assert.NotNilf(t, err, "error message %s", "formatted") -func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotNil(t, object, append([]interface{}{msg}, args...)...) -} - -// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") -func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotPanics(t, f, append([]interface{}{msg}, args...)...) -} - -// NotRegexpf asserts that a specified regexp does not match a string. -// -// assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") -// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") -func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...) -} - -// NotSamef asserts that two pointers do not reference the same object. -// -// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). -// -// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") -func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...) -} - -// NotZerof asserts that i is not the zero value for its type. -func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotZero(t, i, append([]interface{}{msg}, args...)...) -} - -// Panicsf asserts that the code inside the specified PanicTestFunc panics. -// -// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") -func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Panics(t, f, append([]interface{}{msg}, args...)...) -} - -// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func PanicsWithErrorf(t TestingT, errString string, f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return PanicsWithError(t, errString, f, append([]interface{}{msg}, args...)...) -} - -// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...) -} - -// Positivef asserts that the specified element is positive -// -// assert.Positivef(t, 1, "error message %s", "formatted") -// assert.Positivef(t, 1.23, "error message %s", "formatted") -func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Positive(t, e, append([]interface{}{msg}, args...)...) -} - -// Regexpf asserts that a specified regexp matches a string. -// -// assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") -// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") -func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Regexp(t, rx, str, append([]interface{}{msg}, args...)...) -} - -// Samef asserts that two pointers reference the same object. -// -// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func Samef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Same(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). -// -// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") -func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Subset(t, list, subset, append([]interface{}{msg}, args...)...) -} - -// Truef asserts that the specified value is true. -// -// assert.Truef(t, myBool, "error message %s", "formatted") -func Truef(t TestingT, value bool, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return True(t, value, append([]interface{}{msg}, args...)...) -} - -// WithinDurationf asserts that the two times are within duration delta of each other. -// -// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") -func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...) -} - -// WithinRangef asserts that a time is within a time range (inclusive). -// -// assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") -func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return WithinRange(t, actual, start, end, append([]interface{}{msg}, args...)...) -} - -// YAMLEqf asserts that two YAML strings are equivalent. -func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return YAMLEq(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// Zerof asserts that i is the zero value for its type. -func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Zero(t, i, append([]interface{}{msg}, args...)...) -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_format.go.tmpl b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_format.go.tmpl deleted file mode 100644 index d2bb0b8..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_format.go.tmpl +++ /dev/null @@ -1,5 +0,0 @@ -{{.CommentFormat}} -func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool { - if h, ok := t.(tHelper); ok { h.Helper() } - return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}}) -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_forward.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_forward.go deleted file mode 100644 index 339515b..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_forward.go +++ /dev/null @@ -1,1514 +0,0 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ - -package assert - -import ( - http "net/http" - url "net/url" - time "time" -) - -// Condition uses a Comparison to assert a complex condition. -func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Condition(a.t, comp, msgAndArgs...) -} - -// Conditionf uses a Comparison to assert a complex condition. -func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Conditionf(a.t, comp, msg, args...) -} - -// Contains asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// a.Contains("Hello World", "World") -// a.Contains(["Hello", "World"], "World") -// a.Contains({"Hello": "World"}, "Hello") -func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Contains(a.t, s, contains, msgAndArgs...) -} - -// Containsf asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// a.Containsf("Hello World", "World", "error message %s", "formatted") -// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") -// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") -func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Containsf(a.t, s, contains, msg, args...) -} - -// DirExists checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return DirExists(a.t, path, msgAndArgs...) -} - -// DirExistsf checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return DirExistsf(a.t, path, msg, args...) -} - -// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]) -func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ElementsMatch(a.t, listA, listB, msgAndArgs...) -} - -// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") -func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ElementsMatchf(a.t, listA, listB, msg, args...) -} - -// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// a.Empty(obj) -func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Empty(a.t, object, msgAndArgs...) -} - -// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// a.Emptyf(obj, "error message %s", "formatted") -func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Emptyf(a.t, object, msg, args...) -} - -// Equal asserts that two objects are equal. -// -// a.Equal(123, 123) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Equal(a.t, expected, actual, msgAndArgs...) -} - -// EqualError asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// a.EqualError(err, expectedErrorString) -func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EqualError(a.t, theError, errString, msgAndArgs...) -} - -// EqualErrorf asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") -func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EqualErrorf(a.t, theError, errString, msg, args...) -} - -// EqualValues asserts that two objects are equal or convertable to the same types -// and equal. -// -// a.EqualValues(uint32(123), int32(123)) -func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EqualValues(a.t, expected, actual, msgAndArgs...) -} - -// EqualValuesf asserts that two objects are equal or convertable to the same types -// and equal. -// -// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") -func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EqualValuesf(a.t, expected, actual, msg, args...) -} - -// Equalf asserts that two objects are equal. -// -// a.Equalf(123, 123, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Equalf(a.t, expected, actual, msg, args...) -} - -// Error asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// if a.Error(err) { -// assert.Equal(t, expectedError, err) -// } -func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Error(a.t, err, msgAndArgs...) -} - -// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ErrorAs(a.t, err, target, msgAndArgs...) -} - -// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ErrorAsf(a.t, err, target, msg, args...) -} - -// ErrorContains asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// a.ErrorContains(err, expectedErrorSubString) -func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ErrorContains(a.t, theError, contains, msgAndArgs...) -} - -// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted") -func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ErrorContainsf(a.t, theError, contains, msg, args...) -} - -// ErrorIs asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ErrorIs(a.t, err, target, msgAndArgs...) -} - -// ErrorIsf asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ErrorIsf(a.t, err, target, msg, args...) -} - -// Errorf asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// if a.Errorf(err, "error message %s", "formatted") { -// assert.Equal(t, expectedErrorf, err) -// } -func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Errorf(a.t, err, msg, args...) -} - -// Eventually asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond) -func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Eventually(a.t, condition, waitFor, tick, msgAndArgs...) -} - -// Eventuallyf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Eventuallyf(a.t, condition, waitFor, tick, msg, args...) -} - -// Exactly asserts that two objects are equal in value and type. -// -// a.Exactly(int32(123), int64(123)) -func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Exactly(a.t, expected, actual, msgAndArgs...) -} - -// Exactlyf asserts that two objects are equal in value and type. -// -// a.Exactlyf(int32(123), int64(123), "error message %s", "formatted") -func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Exactlyf(a.t, expected, actual, msg, args...) -} - -// Fail reports a failure through -func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Fail(a.t, failureMessage, msgAndArgs...) -} - -// FailNow fails test -func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return FailNow(a.t, failureMessage, msgAndArgs...) -} - -// FailNowf fails test -func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return FailNowf(a.t, failureMessage, msg, args...) -} - -// Failf reports a failure through -func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Failf(a.t, failureMessage, msg, args...) -} - -// False asserts that the specified value is false. -// -// a.False(myBool) -func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return False(a.t, value, msgAndArgs...) -} - -// Falsef asserts that the specified value is false. -// -// a.Falsef(myBool, "error message %s", "formatted") -func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Falsef(a.t, value, msg, args...) -} - -// FileExists checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return FileExists(a.t, path, msgAndArgs...) -} - -// FileExistsf checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return FileExistsf(a.t, path, msg, args...) -} - -// Greater asserts that the first element is greater than the second -// -// a.Greater(2, 1) -// a.Greater(float64(2), float64(1)) -// a.Greater("b", "a") -func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Greater(a.t, e1, e2, msgAndArgs...) -} - -// GreaterOrEqual asserts that the first element is greater than or equal to the second -// -// a.GreaterOrEqual(2, 1) -// a.GreaterOrEqual(2, 2) -// a.GreaterOrEqual("b", "a") -// a.GreaterOrEqual("b", "b") -func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return GreaterOrEqual(a.t, e1, e2, msgAndArgs...) -} - -// GreaterOrEqualf asserts that the first element is greater than or equal to the second -// -// a.GreaterOrEqualf(2, 1, "error message %s", "formatted") -// a.GreaterOrEqualf(2, 2, "error message %s", "formatted") -// a.GreaterOrEqualf("b", "a", "error message %s", "formatted") -// a.GreaterOrEqualf("b", "b", "error message %s", "formatted") -func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return GreaterOrEqualf(a.t, e1, e2, msg, args...) -} - -// Greaterf asserts that the first element is greater than the second -// -// a.Greaterf(2, 1, "error message %s", "formatted") -// a.Greaterf(float64(2), float64(1), "error message %s", "formatted") -// a.Greaterf("b", "a", "error message %s", "formatted") -func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Greaterf(a.t, e1, e2, msg, args...) -} - -// HTTPBodyContains asserts that a specified handler returns a -// body that contains a string. -// -// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) -} - -// HTTPBodyContainsf asserts that a specified handler returns a -// body that contains a string. -// -// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) -} - -// HTTPBodyNotContains asserts that a specified handler returns a -// body that does not contain a string. -// -// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) -} - -// HTTPBodyNotContainsf asserts that a specified handler returns a -// body that does not contain a string. -// -// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) -} - -// HTTPError asserts that a specified handler returns an error status code. -// -// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPError(a.t, handler, method, url, values, msgAndArgs...) -} - -// HTTPErrorf asserts that a specified handler returns an error status code. -// -// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPErrorf(a.t, handler, method, url, values, msg, args...) -} - -// HTTPRedirect asserts that a specified handler returns a redirect status code. -// -// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) -} - -// HTTPRedirectf asserts that a specified handler returns a redirect status code. -// -// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPRedirectf(a.t, handler, method, url, values, msg, args...) -} - -// HTTPStatusCode asserts that a specified handler returns a specified status code. -// -// a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501) -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPStatusCode(a.t, handler, method, url, values, statuscode, msgAndArgs...) -} - -// HTTPStatusCodef asserts that a specified handler returns a specified status code. -// -// a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPStatusCodef(a.t, handler, method, url, values, statuscode, msg, args...) -} - -// HTTPSuccess asserts that a specified handler returns a success status code. -// -// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) -} - -// HTTPSuccessf asserts that a specified handler returns a success status code. -// -// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPSuccessf(a.t, handler, method, url, values, msg, args...) -} - -// Implements asserts that an object is implemented by the specified interface. -// -// a.Implements((*MyInterface)(nil), new(MyObject)) -func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Implements(a.t, interfaceObject, object, msgAndArgs...) -} - -// Implementsf asserts that an object is implemented by the specified interface. -// -// a.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Implementsf(a.t, interfaceObject, object, msg, args...) -} - -// InDelta asserts that the two numerals are within delta of each other. -// -// a.InDelta(math.Pi, 22/7.0, 0.01) -func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InDelta(a.t, expected, actual, delta, msgAndArgs...) -} - -// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) -} - -// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) -} - -// InDeltaSlice is the same as InDelta, except it compares two slices. -func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) -} - -// InDeltaSlicef is the same as InDelta, except it compares two slices. -func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InDeltaSlicef(a.t, expected, actual, delta, msg, args...) -} - -// InDeltaf asserts that the two numerals are within delta of each other. -// -// a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted") -func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InDeltaf(a.t, expected, actual, delta, msg, args...) -} - -// InEpsilon asserts that expected and actual have a relative error less than epsilon -func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) -} - -// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. -func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) -} - -// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. -func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) -} - -// InEpsilonf asserts that expected and actual have a relative error less than epsilon -func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InEpsilonf(a.t, expected, actual, epsilon, msg, args...) -} - -// IsDecreasing asserts that the collection is decreasing -// -// a.IsDecreasing([]int{2, 1, 0}) -// a.IsDecreasing([]float{2, 1}) -// a.IsDecreasing([]string{"b", "a"}) -func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsDecreasing(a.t, object, msgAndArgs...) -} - -// IsDecreasingf asserts that the collection is decreasing -// -// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted") -// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted") -// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted") -func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsDecreasingf(a.t, object, msg, args...) -} - -// IsIncreasing asserts that the collection is increasing -// -// a.IsIncreasing([]int{1, 2, 3}) -// a.IsIncreasing([]float{1, 2}) -// a.IsIncreasing([]string{"a", "b"}) -func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsIncreasing(a.t, object, msgAndArgs...) -} - -// IsIncreasingf asserts that the collection is increasing -// -// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted") -// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted") -// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted") -func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsIncreasingf(a.t, object, msg, args...) -} - -// IsNonDecreasing asserts that the collection is not decreasing -// -// a.IsNonDecreasing([]int{1, 1, 2}) -// a.IsNonDecreasing([]float{1, 2}) -// a.IsNonDecreasing([]string{"a", "b"}) -func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsNonDecreasing(a.t, object, msgAndArgs...) -} - -// IsNonDecreasingf asserts that the collection is not decreasing -// -// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted") -// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted") -// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted") -func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsNonDecreasingf(a.t, object, msg, args...) -} - -// IsNonIncreasing asserts that the collection is not increasing -// -// a.IsNonIncreasing([]int{2, 1, 1}) -// a.IsNonIncreasing([]float{2, 1}) -// a.IsNonIncreasing([]string{"b", "a"}) -func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsNonIncreasing(a.t, object, msgAndArgs...) -} - -// IsNonIncreasingf asserts that the collection is not increasing -// -// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted") -// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted") -// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted") -func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsNonIncreasingf(a.t, object, msg, args...) -} - -// IsType asserts that the specified objects are of the same type. -func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsType(a.t, expectedType, object, msgAndArgs...) -} - -// IsTypef asserts that the specified objects are of the same type. -func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsTypef(a.t, expectedType, object, msg, args...) -} - -// JSONEq asserts that two JSON strings are equivalent. -// -// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) -func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return JSONEq(a.t, expected, actual, msgAndArgs...) -} - -// JSONEqf asserts that two JSON strings are equivalent. -// -// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") -func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return JSONEqf(a.t, expected, actual, msg, args...) -} - -// Len asserts that the specified object has specific length. -// Len also fails if the object has a type that len() not accept. -// -// a.Len(mySlice, 3) -func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Len(a.t, object, length, msgAndArgs...) -} - -// Lenf asserts that the specified object has specific length. -// Lenf also fails if the object has a type that len() not accept. -// -// a.Lenf(mySlice, 3, "error message %s", "formatted") -func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Lenf(a.t, object, length, msg, args...) -} - -// Less asserts that the first element is less than the second -// -// a.Less(1, 2) -// a.Less(float64(1), float64(2)) -// a.Less("a", "b") -func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Less(a.t, e1, e2, msgAndArgs...) -} - -// LessOrEqual asserts that the first element is less than or equal to the second -// -// a.LessOrEqual(1, 2) -// a.LessOrEqual(2, 2) -// a.LessOrEqual("a", "b") -// a.LessOrEqual("b", "b") -func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return LessOrEqual(a.t, e1, e2, msgAndArgs...) -} - -// LessOrEqualf asserts that the first element is less than or equal to the second -// -// a.LessOrEqualf(1, 2, "error message %s", "formatted") -// a.LessOrEqualf(2, 2, "error message %s", "formatted") -// a.LessOrEqualf("a", "b", "error message %s", "formatted") -// a.LessOrEqualf("b", "b", "error message %s", "formatted") -func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return LessOrEqualf(a.t, e1, e2, msg, args...) -} - -// Lessf asserts that the first element is less than the second -// -// a.Lessf(1, 2, "error message %s", "formatted") -// a.Lessf(float64(1), float64(2), "error message %s", "formatted") -// a.Lessf("a", "b", "error message %s", "formatted") -func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Lessf(a.t, e1, e2, msg, args...) -} - -// Negative asserts that the specified element is negative -// -// a.Negative(-1) -// a.Negative(-1.23) -func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Negative(a.t, e, msgAndArgs...) -} - -// Negativef asserts that the specified element is negative -// -// a.Negativef(-1, "error message %s", "formatted") -// a.Negativef(-1.23, "error message %s", "formatted") -func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Negativef(a.t, e, msg, args...) -} - -// Never asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond) -func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Never(a.t, condition, waitFor, tick, msgAndArgs...) -} - -// Neverf asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Neverf(a.t, condition, waitFor, tick, msg, args...) -} - -// Nil asserts that the specified object is nil. -// -// a.Nil(err) -func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Nil(a.t, object, msgAndArgs...) -} - -// Nilf asserts that the specified object is nil. -// -// a.Nilf(err, "error message %s", "formatted") -func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Nilf(a.t, object, msg, args...) -} - -// NoDirExists checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func (a *Assertions) NoDirExists(path string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NoDirExists(a.t, path, msgAndArgs...) -} - -// NoDirExistsf checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NoDirExistsf(a.t, path, msg, args...) -} - -// NoError asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if a.NoError(err) { -// assert.Equal(t, expectedObj, actualObj) -// } -func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NoError(a.t, err, msgAndArgs...) -} - -// NoErrorf asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if a.NoErrorf(err, "error message %s", "formatted") { -// assert.Equal(t, expectedObj, actualObj) -// } -func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NoErrorf(a.t, err, msg, args...) -} - -// NoFileExists checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func (a *Assertions) NoFileExists(path string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NoFileExists(a.t, path, msgAndArgs...) -} - -// NoFileExistsf checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func (a *Assertions) NoFileExistsf(path string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NoFileExistsf(a.t, path, msg, args...) -} - -// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// a.NotContains("Hello World", "Earth") -// a.NotContains(["Hello", "World"], "Earth") -// a.NotContains({"Hello": "World"}, "Earth") -func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotContains(a.t, s, contains, msgAndArgs...) -} - -// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") -// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") -// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") -func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotContainsf(a.t, s, contains, msg, args...) -} - -// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// if a.NotEmpty(obj) { -// assert.Equal(t, "two", obj[1]) -// } -func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotEmpty(a.t, object, msgAndArgs...) -} - -// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// if a.NotEmptyf(obj, "error message %s", "formatted") { -// assert.Equal(t, "two", obj[1]) -// } -func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotEmptyf(a.t, object, msg, args...) -} - -// NotEqual asserts that the specified values are NOT equal. -// -// a.NotEqual(obj1, obj2) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotEqual(a.t, expected, actual, msgAndArgs...) -} - -// NotEqualValues asserts that two objects are not equal even when converted to the same type -// -// a.NotEqualValues(obj1, obj2) -func (a *Assertions) NotEqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotEqualValues(a.t, expected, actual, msgAndArgs...) -} - -// NotEqualValuesf asserts that two objects are not equal even when converted to the same type -// -// a.NotEqualValuesf(obj1, obj2, "error message %s", "formatted") -func (a *Assertions) NotEqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotEqualValuesf(a.t, expected, actual, msg, args...) -} - -// NotEqualf asserts that the specified values are NOT equal. -// -// a.NotEqualf(obj1, obj2, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotEqualf(a.t, expected, actual, msg, args...) -} - -// NotErrorIs asserts that at none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotErrorIs(a.t, err, target, msgAndArgs...) -} - -// NotErrorIsf asserts that at none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotErrorIsf(a.t, err, target, msg, args...) -} - -// NotNil asserts that the specified object is not nil. -// -// a.NotNil(err) -func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotNil(a.t, object, msgAndArgs...) -} - -// NotNilf asserts that the specified object is not nil. -// -// a.NotNilf(err, "error message %s", "formatted") -func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotNilf(a.t, object, msg, args...) -} - -// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// a.NotPanics(func(){ RemainCalm() }) -func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotPanics(a.t, f, msgAndArgs...) -} - -// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") -func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotPanicsf(a.t, f, msg, args...) -} - -// NotRegexp asserts that a specified regexp does not match a string. -// -// a.NotRegexp(regexp.MustCompile("starts"), "it's starting") -// a.NotRegexp("^start", "it's not starting") -func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotRegexp(a.t, rx, str, msgAndArgs...) -} - -// NotRegexpf asserts that a specified regexp does not match a string. -// -// a.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") -// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") -func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotRegexpf(a.t, rx, str, msg, args...) -} - -// NotSame asserts that two pointers do not reference the same object. -// -// a.NotSame(ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) NotSame(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotSame(a.t, expected, actual, msgAndArgs...) -} - -// NotSamef asserts that two pointers do not reference the same object. -// -// a.NotSamef(ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotSamef(a.t, expected, actual, msg, args...) -} - -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). -// -// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") -func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotSubset(a.t, list, subset, msgAndArgs...) -} - -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). -// -// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") -func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotSubsetf(a.t, list, subset, msg, args...) -} - -// NotZero asserts that i is not the zero value for its type. -func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotZero(a.t, i, msgAndArgs...) -} - -// NotZerof asserts that i is not the zero value for its type. -func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotZerof(a.t, i, msg, args...) -} - -// Panics asserts that the code inside the specified PanicTestFunc panics. -// -// a.Panics(func(){ GoCrazy() }) -func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Panics(a.t, f, msgAndArgs...) -} - -// PanicsWithError asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// a.PanicsWithError("crazy error", func(){ GoCrazy() }) -func (a *Assertions) PanicsWithError(errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return PanicsWithError(a.t, errString, f, msgAndArgs...) -} - -// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func (a *Assertions) PanicsWithErrorf(errString string, f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return PanicsWithErrorf(a.t, errString, f, msg, args...) -} - -// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// a.PanicsWithValue("crazy error", func(){ GoCrazy() }) -func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return PanicsWithValue(a.t, expected, f, msgAndArgs...) -} - -// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return PanicsWithValuef(a.t, expected, f, msg, args...) -} - -// Panicsf asserts that the code inside the specified PanicTestFunc panics. -// -// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") -func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Panicsf(a.t, f, msg, args...) -} - -// Positive asserts that the specified element is positive -// -// a.Positive(1) -// a.Positive(1.23) -func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Positive(a.t, e, msgAndArgs...) -} - -// Positivef asserts that the specified element is positive -// -// a.Positivef(1, "error message %s", "formatted") -// a.Positivef(1.23, "error message %s", "formatted") -func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Positivef(a.t, e, msg, args...) -} - -// Regexp asserts that a specified regexp matches a string. -// -// a.Regexp(regexp.MustCompile("start"), "it's starting") -// a.Regexp("start...$", "it's not starting") -func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Regexp(a.t, rx, str, msgAndArgs...) -} - -// Regexpf asserts that a specified regexp matches a string. -// -// a.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") -// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") -func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Regexpf(a.t, rx, str, msg, args...) -} - -// Same asserts that two pointers reference the same object. -// -// a.Same(ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Same(a.t, expected, actual, msgAndArgs...) -} - -// Samef asserts that two pointers reference the same object. -// -// a.Samef(ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Samef(a.t, expected, actual, msg, args...) -} - -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). -// -// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") -func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Subset(a.t, list, subset, msgAndArgs...) -} - -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). -// -// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") -func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Subsetf(a.t, list, subset, msg, args...) -} - -// True asserts that the specified value is true. -// -// a.True(myBool) -func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return True(a.t, value, msgAndArgs...) -} - -// Truef asserts that the specified value is true. -// -// a.Truef(myBool, "error message %s", "formatted") -func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Truef(a.t, value, msg, args...) -} - -// WithinDuration asserts that the two times are within duration delta of each other. -// -// a.WithinDuration(time.Now(), time.Now(), 10*time.Second) -func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return WithinDuration(a.t, expected, actual, delta, msgAndArgs...) -} - -// WithinDurationf asserts that the two times are within duration delta of each other. -// -// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") -func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return WithinDurationf(a.t, expected, actual, delta, msg, args...) -} - -// WithinRange asserts that a time is within a time range (inclusive). -// -// a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) -func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return WithinRange(a.t, actual, start, end, msgAndArgs...) -} - -// WithinRangef asserts that a time is within a time range (inclusive). -// -// a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") -func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return WithinRangef(a.t, actual, start, end, msg, args...) -} - -// YAMLEq asserts that two YAML strings are equivalent. -func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return YAMLEq(a.t, expected, actual, msgAndArgs...) -} - -// YAMLEqf asserts that two YAML strings are equivalent. -func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return YAMLEqf(a.t, expected, actual, msg, args...) -} - -// Zero asserts that i is the zero value for its type. -func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Zero(a.t, i, msgAndArgs...) -} - -// Zerof asserts that i is the zero value for its type. -func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Zerof(a.t, i, msg, args...) -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_forward.go.tmpl b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_forward.go.tmpl deleted file mode 100644 index 188bb9e..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_forward.go.tmpl +++ /dev/null @@ -1,5 +0,0 @@ -{{.CommentWithoutT "a"}} -func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool { - if h, ok := a.t.(tHelper); ok { h.Helper() } - return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_order.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_order.go deleted file mode 100644 index 7594487..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_order.go +++ /dev/null @@ -1,81 +0,0 @@ -package assert - -import ( - "fmt" - "reflect" -) - -// isOrdered checks that collection contains orderable elements. -func isOrdered(t TestingT, object interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool { - objKind := reflect.TypeOf(object).Kind() - if objKind != reflect.Slice && objKind != reflect.Array { - return false - } - - objValue := reflect.ValueOf(object) - objLen := objValue.Len() - - if objLen <= 1 { - return true - } - - value := objValue.Index(0) - valueInterface := value.Interface() - firstValueKind := value.Kind() - - for i := 1; i < objLen; i++ { - prevValue := value - prevValueInterface := valueInterface - - value = objValue.Index(i) - valueInterface = value.Interface() - - compareResult, isComparable := compare(prevValueInterface, valueInterface, firstValueKind) - - if !isComparable { - return Fail(t, fmt.Sprintf("Can not compare type \"%s\" and \"%s\"", reflect.TypeOf(value), reflect.TypeOf(prevValue)), msgAndArgs...) - } - - if !containsValue(allowedComparesResults, compareResult) { - return Fail(t, fmt.Sprintf(failMessage, prevValue, value), msgAndArgs...) - } - } - - return true -} - -// IsIncreasing asserts that the collection is increasing -// -// assert.IsIncreasing(t, []int{1, 2, 3}) -// assert.IsIncreasing(t, []float{1, 2}) -// assert.IsIncreasing(t, []string{"a", "b"}) -func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - return isOrdered(t, object, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...) -} - -// IsNonIncreasing asserts that the collection is not increasing -// -// assert.IsNonIncreasing(t, []int{2, 1, 1}) -// assert.IsNonIncreasing(t, []float{2, 1}) -// assert.IsNonIncreasing(t, []string{"b", "a"}) -func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - return isOrdered(t, object, []CompareType{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...) -} - -// IsDecreasing asserts that the collection is decreasing -// -// assert.IsDecreasing(t, []int{2, 1, 0}) -// assert.IsDecreasing(t, []float{2, 1}) -// assert.IsDecreasing(t, []string{"b", "a"}) -func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - return isOrdered(t, object, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...) -} - -// IsNonDecreasing asserts that the collection is not decreasing -// -// assert.IsNonDecreasing(t, []int{1, 1, 2}) -// assert.IsNonDecreasing(t, []float{1, 2}) -// assert.IsNonDecreasing(t, []string{"a", "b"}) -func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - return isOrdered(t, object, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...) -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_order_test.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_order_test.go deleted file mode 100644 index eefe061..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertion_order_test.go +++ /dev/null @@ -1,203 +0,0 @@ -package assert - -import ( - "bytes" - "testing" -) - -func TestIsIncreasing(t *testing.T) { - mockT := new(testing.T) - - if !IsIncreasing(mockT, []int{1, 2}) { - t.Error("IsIncreasing should return true") - } - - if !IsIncreasing(mockT, []int{1, 2, 3, 4, 5}) { - t.Error("IsIncreasing should return true") - } - - if IsIncreasing(mockT, []int{1, 1}) { - t.Error("IsIncreasing should return false") - } - - if IsIncreasing(mockT, []int{2, 1}) { - t.Error("IsIncreasing should return false") - } - - // Check error report - for _, currCase := range []struct { - collection interface{} - msg string - }{ - {collection: []string{"b", "a"}, msg: `"b" is not less than "a"`}, - {collection: []int{2, 1}, msg: `"2" is not less than "1"`}, - {collection: []int{2, 1, 3, 4, 5, 6, 7}, msg: `"2" is not less than "1"`}, - {collection: []int{-1, 0, 2, 1}, msg: `"2" is not less than "1"`}, - {collection: []int8{2, 1}, msg: `"2" is not less than "1"`}, - {collection: []int16{2, 1}, msg: `"2" is not less than "1"`}, - {collection: []int32{2, 1}, msg: `"2" is not less than "1"`}, - {collection: []int64{2, 1}, msg: `"2" is not less than "1"`}, - {collection: []uint8{2, 1}, msg: `"2" is not less than "1"`}, - {collection: []uint16{2, 1}, msg: `"2" is not less than "1"`}, - {collection: []uint32{2, 1}, msg: `"2" is not less than "1"`}, - {collection: []uint64{2, 1}, msg: `"2" is not less than "1"`}, - {collection: []float32{2.34, 1.23}, msg: `"2.34" is not less than "1.23"`}, - {collection: []float64{2.34, 1.23}, msg: `"2.34" is not less than "1.23"`}, - } { - out := &outputT{buf: bytes.NewBuffer(nil)} - False(t, IsIncreasing(out, currCase.collection)) - Contains(t, out.buf.String(), currCase.msg) - } -} - -func TestIsNonIncreasing(t *testing.T) { - mockT := new(testing.T) - - if !IsNonIncreasing(mockT, []int{2, 1}) { - t.Error("IsNonIncreasing should return true") - } - - if !IsNonIncreasing(mockT, []int{5, 4, 4, 3, 2, 1}) { - t.Error("IsNonIncreasing should return true") - } - - if !IsNonIncreasing(mockT, []int{1, 1}) { - t.Error("IsNonIncreasing should return true") - } - - if IsNonIncreasing(mockT, []int{1, 2}) { - t.Error("IsNonIncreasing should return false") - } - - // Check error report - for _, currCase := range []struct { - collection interface{} - msg string - }{ - {collection: []string{"a", "b"}, msg: `"a" is not greater than or equal to "b"`}, - {collection: []int{1, 2}, msg: `"1" is not greater than or equal to "2"`}, - {collection: []int{1, 2, 7, 6, 5, 4, 3}, msg: `"1" is not greater than or equal to "2"`}, - {collection: []int{5, 4, 3, 1, 2}, msg: `"1" is not greater than or equal to "2"`}, - {collection: []int8{1, 2}, msg: `"1" is not greater than or equal to "2"`}, - {collection: []int16{1, 2}, msg: `"1" is not greater than or equal to "2"`}, - {collection: []int32{1, 2}, msg: `"1" is not greater than or equal to "2"`}, - {collection: []int64{1, 2}, msg: `"1" is not greater than or equal to "2"`}, - {collection: []uint8{1, 2}, msg: `"1" is not greater than or equal to "2"`}, - {collection: []uint16{1, 2}, msg: `"1" is not greater than or equal to "2"`}, - {collection: []uint32{1, 2}, msg: `"1" is not greater than or equal to "2"`}, - {collection: []uint64{1, 2}, msg: `"1" is not greater than or equal to "2"`}, - {collection: []float32{1.23, 2.34}, msg: `"1.23" is not greater than or equal to "2.34"`}, - {collection: []float64{1.23, 2.34}, msg: `"1.23" is not greater than or equal to "2.34"`}, - } { - out := &outputT{buf: bytes.NewBuffer(nil)} - False(t, IsNonIncreasing(out, currCase.collection)) - Contains(t, out.buf.String(), currCase.msg) - } -} - -func TestIsDecreasing(t *testing.T) { - mockT := new(testing.T) - - if !IsDecreasing(mockT, []int{2, 1}) { - t.Error("IsDecreasing should return true") - } - - if !IsDecreasing(mockT, []int{5, 4, 3, 2, 1}) { - t.Error("IsDecreasing should return true") - } - - if IsDecreasing(mockT, []int{1, 1}) { - t.Error("IsDecreasing should return false") - } - - if IsDecreasing(mockT, []int{1, 2}) { - t.Error("IsDecreasing should return false") - } - - // Check error report - for _, currCase := range []struct { - collection interface{} - msg string - }{ - {collection: []string{"a", "b"}, msg: `"a" is not greater than "b"`}, - {collection: []int{1, 2}, msg: `"1" is not greater than "2"`}, - {collection: []int{1, 2, 7, 6, 5, 4, 3}, msg: `"1" is not greater than "2"`}, - {collection: []int{5, 4, 3, 1, 2}, msg: `"1" is not greater than "2"`}, - {collection: []int8{1, 2}, msg: `"1" is not greater than "2"`}, - {collection: []int16{1, 2}, msg: `"1" is not greater than "2"`}, - {collection: []int32{1, 2}, msg: `"1" is not greater than "2"`}, - {collection: []int64{1, 2}, msg: `"1" is not greater than "2"`}, - {collection: []uint8{1, 2}, msg: `"1" is not greater than "2"`}, - {collection: []uint16{1, 2}, msg: `"1" is not greater than "2"`}, - {collection: []uint32{1, 2}, msg: `"1" is not greater than "2"`}, - {collection: []uint64{1, 2}, msg: `"1" is not greater than "2"`}, - {collection: []float32{1.23, 2.34}, msg: `"1.23" is not greater than "2.34"`}, - {collection: []float64{1.23, 2.34}, msg: `"1.23" is not greater than "2.34"`}, - } { - out := &outputT{buf: bytes.NewBuffer(nil)} - False(t, IsDecreasing(out, currCase.collection)) - Contains(t, out.buf.String(), currCase.msg) - } -} - -func TestIsNonDecreasing(t *testing.T) { - mockT := new(testing.T) - - if !IsNonDecreasing(mockT, []int{1, 2}) { - t.Error("IsNonDecreasing should return true") - } - - if !IsNonDecreasing(mockT, []int{1, 1, 2, 3, 4, 5}) { - t.Error("IsNonDecreasing should return true") - } - - if !IsNonDecreasing(mockT, []int{1, 1}) { - t.Error("IsNonDecreasing should return false") - } - - if IsNonDecreasing(mockT, []int{2, 1}) { - t.Error("IsNonDecreasing should return false") - } - - // Check error report - for _, currCase := range []struct { - collection interface{} - msg string - }{ - {collection: []string{"b", "a"}, msg: `"b" is not less than or equal to "a"`}, - {collection: []int{2, 1}, msg: `"2" is not less than or equal to "1"`}, - {collection: []int{2, 1, 3, 4, 5, 6, 7}, msg: `"2" is not less than or equal to "1"`}, - {collection: []int{-1, 0, 2, 1}, msg: `"2" is not less than or equal to "1"`}, - {collection: []int8{2, 1}, msg: `"2" is not less than or equal to "1"`}, - {collection: []int16{2, 1}, msg: `"2" is not less than or equal to "1"`}, - {collection: []int32{2, 1}, msg: `"2" is not less than or equal to "1"`}, - {collection: []int64{2, 1}, msg: `"2" is not less than or equal to "1"`}, - {collection: []uint8{2, 1}, msg: `"2" is not less than or equal to "1"`}, - {collection: []uint16{2, 1}, msg: `"2" is not less than or equal to "1"`}, - {collection: []uint32{2, 1}, msg: `"2" is not less than or equal to "1"`}, - {collection: []uint64{2, 1}, msg: `"2" is not less than or equal to "1"`}, - {collection: []float32{2.34, 1.23}, msg: `"2.34" is not less than or equal to "1.23"`}, - {collection: []float64{2.34, 1.23}, msg: `"2.34" is not less than or equal to "1.23"`}, - } { - out := &outputT{buf: bytes.NewBuffer(nil)} - False(t, IsNonDecreasing(out, currCase.collection)) - Contains(t, out.buf.String(), currCase.msg) - } -} - -func TestOrderingMsgAndArgsForwarding(t *testing.T) { - msgAndArgs := []interface{}{"format %s %x", "this", 0xc001} - expectedOutput := "format this c001\n" - collection := []int{1, 2, 1} - funcs := []func(t TestingT){ - func(t TestingT) { IsIncreasing(t, collection, msgAndArgs...) }, - func(t TestingT) { IsNonIncreasing(t, collection, msgAndArgs...) }, - func(t TestingT) { IsDecreasing(t, collection, msgAndArgs...) }, - func(t TestingT) { IsNonDecreasing(t, collection, msgAndArgs...) }, - } - for _, f := range funcs { - out := &outputT{buf: bytes.NewBuffer(nil)} - f(out) - Contains(t, out.buf.String(), expectedOutput) - } -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertions.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertions.go deleted file mode 100644 index 2924cf3..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertions.go +++ /dev/null @@ -1,1856 +0,0 @@ -package assert - -import ( - "bufio" - "bytes" - "encoding/json" - "errors" - "fmt" - "math" - "os" - "reflect" - "regexp" - "runtime" - "runtime/debug" - "strings" - "time" - "unicode" - "unicode/utf8" - - "github.com/davecgh/go-spew/spew" - "github.com/pmezard/go-difflib/difflib" - yaml "gopkg.in/yaml.v3" -) - -//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl" - -// TestingT is an interface wrapper around *testing.T -type TestingT interface { - Errorf(format string, args ...interface{}) -} - -// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful -// for table driven tests. -type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) bool - -// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful -// for table driven tests. -type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool - -// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful -// for table driven tests. -type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool - -// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful -// for table driven tests. -type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool - -// Comparison is a custom function that returns true on success and false on failure -type Comparison func() (success bool) - -/* - Helper functions -*/ - -// ObjectsAreEqual determines if two objects are considered equal. -// -// This function does no assertion of any kind. -func ObjectsAreEqual(expected, actual interface{}) bool { - if expected == nil || actual == nil { - return expected == actual - } - - exp, ok := expected.([]byte) - if !ok { - return reflect.DeepEqual(expected, actual) - } - - act, ok := actual.([]byte) - if !ok { - return false - } - if exp == nil || act == nil { - return exp == nil && act == nil - } - return bytes.Equal(exp, act) -} - -// ObjectsAreEqualValues gets whether two objects are equal, or if their -// values are equal. -func ObjectsAreEqualValues(expected, actual interface{}) bool { - if ObjectsAreEqual(expected, actual) { - return true - } - - actualType := reflect.TypeOf(actual) - if actualType == nil { - return false - } - expectedValue := reflect.ValueOf(expected) - if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) { - // Attempt comparison after type conversion - return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual) - } - - return false -} - -/* CallerInfo is necessary because the assert functions use the testing object -internally, causing it to print the file:line of the assert method, rather than where -the problem actually occurred in calling code.*/ - -// CallerInfo returns an array of strings containing the file and line number -// of each stack frame leading from the current test to the assert call that -// failed. -func CallerInfo() []string { - - var pc uintptr - var ok bool - var file string - var line int - var name string - - callers := []string{} - for i := 0; ; i++ { - pc, file, line, ok = runtime.Caller(i) - if !ok { - // The breaks below failed to terminate the loop, and we ran off the - // end of the call stack. - break - } - - // This is a huge edge case, but it will panic if this is the case, see #180 - if file == "<autogenerated>" { - break - } - - f := runtime.FuncForPC(pc) - if f == nil { - break - } - name = f.Name() - - // testing.tRunner is the standard library function that calls - // tests. Subtests are called directly by tRunner, without going through - // the Test/Benchmark/Example function that contains the t.Run calls, so - // with subtests we should break when we hit tRunner, without adding it - // to the list of callers. - if name == "testing.tRunner" { - break - } - - parts := strings.Split(file, "/") - if len(parts) > 1 { - filename := parts[len(parts)-1] - dir := parts[len(parts)-2] - if (dir != "assert" && dir != "mock" && dir != "require") || filename == "mock_test.go" { - callers = append(callers, fmt.Sprintf("%s:%d", file, line)) - } - } - - // Drop the package - segments := strings.Split(name, ".") - name = segments[len(segments)-1] - if isTest(name, "Test") || - isTest(name, "Benchmark") || - isTest(name, "Example") { - break - } - } - - return callers -} - -// Stolen from the `go test` tool. -// isTest tells whether name looks like a test (or benchmark, according to prefix). -// It is a Test (say) if there is a character after Test that is not a lower-case letter. -// We don't want TesticularCancer. -func isTest(name, prefix string) bool { - if !strings.HasPrefix(name, prefix) { - return false - } - if len(name) == len(prefix) { // "Test" is ok - return true - } - r, _ := utf8.DecodeRuneInString(name[len(prefix):]) - return !unicode.IsLower(r) -} - -func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { - if len(msgAndArgs) == 0 || msgAndArgs == nil { - return "" - } - if len(msgAndArgs) == 1 { - msg := msgAndArgs[0] - if msgAsStr, ok := msg.(string); ok { - return msgAsStr - } - return fmt.Sprintf("%+v", msg) - } - if len(msgAndArgs) > 1 { - return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) - } - return "" -} - -// Aligns the provided message so that all lines after the first line start at the same location as the first line. -// Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab). -// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the -// basis on which the alignment occurs). -func indentMessageLines(message string, longestLabelLen int) string { - outBuf := new(bytes.Buffer) - - for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ { - // no need to align first line because it starts at the correct location (after the label) - if i != 0 { - // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab - outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t") - } - outBuf.WriteString(scanner.Text()) - } - - return outBuf.String() -} - -type failNower interface { - FailNow() -} - -// FailNow fails test -func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - Fail(t, failureMessage, msgAndArgs...) - - // We cannot extend TestingT with FailNow() and - // maintain backwards compatibility, so we fallback - // to panicking when FailNow is not available in - // TestingT. - // See issue #263 - - if t, ok := t.(failNower); ok { - t.FailNow() - } else { - panic("test failed and t is missing `FailNow()`") - } - return false -} - -// Fail reports a failure through -func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - content := []labeledContent{ - {"Error Trace", strings.Join(CallerInfo(), "\n\t\t\t")}, - {"Error", failureMessage}, - } - - // Add test name if the Go version supports it - if n, ok := t.(interface { - Name() string - }); ok { - content = append(content, labeledContent{"Test", n.Name()}) - } - - message := messageFromMsgAndArgs(msgAndArgs...) - if len(message) > 0 { - content = append(content, labeledContent{"Messages", message}) - } - - t.Errorf("\n%s", ""+labeledOutput(content...)) - - return false -} - -type labeledContent struct { - label string - content string -} - -// labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner: -// -// \t{{label}}:{{align_spaces}}\t{{content}}\n -// -// The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label. -// If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this -// alignment is achieved, "\t{{content}}\n" is added for the output. -// -// If the content of the labeledOutput contains line breaks, the subsequent lines are aligned so that they start at the same location as the first line. -func labeledOutput(content ...labeledContent) string { - longestLabel := 0 - for _, v := range content { - if len(v.label) > longestLabel { - longestLabel = len(v.label) - } - } - var output string - for _, v := range content { - output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n" - } - return output -} - -// Implements asserts that an object is implemented by the specified interface. -// -// assert.Implements(t, (*MyInterface)(nil), new(MyObject)) -func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - interfaceType := reflect.TypeOf(interfaceObject).Elem() - - if object == nil { - return Fail(t, fmt.Sprintf("Cannot check if nil implements %v", interfaceType), msgAndArgs...) - } - if !reflect.TypeOf(object).Implements(interfaceType) { - return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...) - } - - return true -} - -// IsType asserts that the specified objects are of the same type. -func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) { - return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...) - } - - return true -} - -// Equal asserts that two objects are equal. -// -// assert.Equal(t, 123, 123) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if err := validateEqualArgs(expected, actual); err != nil { - return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)", - expected, actual, err), msgAndArgs...) - } - - if !ObjectsAreEqual(expected, actual) { - diff := diff(expected, actual) - expected, actual = formatUnequalValues(expected, actual) - return Fail(t, fmt.Sprintf("Not equal: \n"+ - "expected: %s\n"+ - "actual : %s%s", expected, actual, diff), msgAndArgs...) - } - - return true - -} - -// validateEqualArgs checks whether provided arguments can be safely used in the -// Equal/NotEqual functions. -func validateEqualArgs(expected, actual interface{}) error { - if expected == nil && actual == nil { - return nil - } - - if isFunction(expected) || isFunction(actual) { - return errors.New("cannot take func type as argument") - } - return nil -} - -// Same asserts that two pointers reference the same object. -// -// assert.Same(t, ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if !samePointers(expected, actual) { - return Fail(t, fmt.Sprintf("Not same: \n"+ - "expected: %p %#v\n"+ - "actual : %p %#v", expected, expected, actual, actual), msgAndArgs...) - } - - return true -} - -// NotSame asserts that two pointers do not reference the same object. -// -// assert.NotSame(t, ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if samePointers(expected, actual) { - return Fail(t, fmt.Sprintf( - "Expected and actual point to the same object: %p %#v", - expected, expected), msgAndArgs...) - } - return true -} - -// samePointers compares two generic interface objects and returns whether -// they point to the same object -func samePointers(first, second interface{}) bool { - firstPtr, secondPtr := reflect.ValueOf(first), reflect.ValueOf(second) - if firstPtr.Kind() != reflect.Ptr || secondPtr.Kind() != reflect.Ptr { - return false - } - - firstType, secondType := reflect.TypeOf(first), reflect.TypeOf(second) - if firstType != secondType { - return false - } - - // compare pointer addresses - return first == second -} - -// formatUnequalValues takes two values of arbitrary types and returns string -// representations appropriate to be presented to the user. -// -// If the values are not of like type, the returned strings will be prefixed -// with the type name, and the value will be enclosed in parenthesis similar -// to a type conversion in the Go grammar. -func formatUnequalValues(expected, actual interface{}) (e string, a string) { - if reflect.TypeOf(expected) != reflect.TypeOf(actual) { - return fmt.Sprintf("%T(%s)", expected, truncatingFormat(expected)), - fmt.Sprintf("%T(%s)", actual, truncatingFormat(actual)) - } - switch expected.(type) { - case time.Duration: - return fmt.Sprintf("%v", expected), fmt.Sprintf("%v", actual) - } - return truncatingFormat(expected), truncatingFormat(actual) -} - -// truncatingFormat formats the data and truncates it if it's too long. -// -// This helps keep formatted error messages lines from exceeding the -// bufio.MaxScanTokenSize max line length that the go testing framework imposes. -func truncatingFormat(data interface{}) string { - value := fmt.Sprintf("%#v", data) - max := bufio.MaxScanTokenSize - 100 // Give us some space the type info too if needed. - if len(value) > max { - value = value[0:max] + "<... truncated>" - } - return value -} - -// EqualValues asserts that two objects are equal or convertable to the same types -// and equal. -// -// assert.EqualValues(t, uint32(123), int32(123)) -func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if !ObjectsAreEqualValues(expected, actual) { - diff := diff(expected, actual) - expected, actual = formatUnequalValues(expected, actual) - return Fail(t, fmt.Sprintf("Not equal: \n"+ - "expected: %s\n"+ - "actual : %s%s", expected, actual, diff), msgAndArgs...) - } - - return true - -} - -// Exactly asserts that two objects are equal in value and type. -// -// assert.Exactly(t, int32(123), int64(123)) -func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - aType := reflect.TypeOf(expected) - bType := reflect.TypeOf(actual) - - if aType != bType { - return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) - } - - return Equal(t, expected, actual, msgAndArgs...) - -} - -// NotNil asserts that the specified object is not nil. -// -// assert.NotNil(t, err) -func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - if !isNil(object) { - return true - } - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, "Expected value not to be nil.", msgAndArgs...) -} - -// containsKind checks if a specified kind in the slice of kinds. -func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool { - for i := 0; i < len(kinds); i++ { - if kind == kinds[i] { - return true - } - } - - return false -} - -// isNil checks if a specified object is nil or not, without Failing. -func isNil(object interface{}) bool { - if object == nil { - return true - } - - value := reflect.ValueOf(object) - kind := value.Kind() - isNilableKind := containsKind( - []reflect.Kind{ - reflect.Chan, reflect.Func, - reflect.Interface, reflect.Map, - reflect.Ptr, reflect.Slice, reflect.UnsafePointer}, - kind) - - if isNilableKind && value.IsNil() { - return true - } - - return false -} - -// Nil asserts that the specified object is nil. -// -// assert.Nil(t, err) -func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - if isNil(object) { - return true - } - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...) -} - -// isEmpty gets whether the specified object is considered empty or not. -func isEmpty(object interface{}) bool { - - // get nil case out of the way - if object == nil { - return true - } - - objValue := reflect.ValueOf(object) - - switch objValue.Kind() { - // collection types are empty when they have no element - case reflect.Chan, reflect.Map, reflect.Slice: - return objValue.Len() == 0 - // pointers are empty if nil or if the value they point to is empty - case reflect.Ptr: - if objValue.IsNil() { - return true - } - deref := objValue.Elem().Interface() - return isEmpty(deref) - // for all other types, compare against the zero value - // array types are empty when they match their zero-initialized state - default: - zero := reflect.Zero(objValue.Type()) - return reflect.DeepEqual(object, zero.Interface()) - } -} - -// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// assert.Empty(t, obj) -func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - pass := isEmpty(object) - if !pass { - if h, ok := t.(tHelper); ok { - h.Helper() - } - Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...) - } - - return pass - -} - -// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// if assert.NotEmpty(t, obj) { -// assert.Equal(t, "two", obj[1]) -// } -func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - pass := !isEmpty(object) - if !pass { - if h, ok := t.(tHelper); ok { - h.Helper() - } - Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...) - } - - return pass - -} - -// getLen try to get length of object. -// return (false, 0) if impossible. -func getLen(x interface{}) (ok bool, length int) { - v := reflect.ValueOf(x) - defer func() { - if e := recover(); e != nil { - ok = false - } - }() - return true, v.Len() -} - -// Len asserts that the specified object has specific length. -// Len also fails if the object has a type that len() not accept. -// -// assert.Len(t, mySlice, 3) -func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - ok, l := getLen(object) - if !ok { - return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...) - } - - if l != length { - return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) - } - return true -} - -// True asserts that the specified value is true. -// -// assert.True(t, myBool) -func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { - if !value { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, "Should be true", msgAndArgs...) - } - - return true - -} - -// False asserts that the specified value is false. -// -// assert.False(t, myBool) -func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { - if value { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, "Should be false", msgAndArgs...) - } - - return true - -} - -// NotEqual asserts that the specified values are NOT equal. -// -// assert.NotEqual(t, obj1, obj2) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if err := validateEqualArgs(expected, actual); err != nil { - return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)", - expected, actual, err), msgAndArgs...) - } - - if ObjectsAreEqual(expected, actual) { - return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) - } - - return true - -} - -// NotEqualValues asserts that two objects are not equal even when converted to the same type -// -// assert.NotEqualValues(t, obj1, obj2) -func NotEqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if ObjectsAreEqualValues(expected, actual) { - return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) - } - - return true -} - -// containsElement try loop over the list check if the list includes the element. -// return (false, false) if impossible. -// return (true, false) if element was not found. -// return (true, true) if element was found. -func containsElement(list interface{}, element interface{}) (ok, found bool) { - - listValue := reflect.ValueOf(list) - listType := reflect.TypeOf(list) - if listType == nil { - return false, false - } - listKind := listType.Kind() - defer func() { - if e := recover(); e != nil { - ok = false - found = false - } - }() - - if listKind == reflect.String { - elementValue := reflect.ValueOf(element) - return true, strings.Contains(listValue.String(), elementValue.String()) - } - - if listKind == reflect.Map { - mapKeys := listValue.MapKeys() - for i := 0; i < len(mapKeys); i++ { - if ObjectsAreEqual(mapKeys[i].Interface(), element) { - return true, true - } - } - return true, false - } - - for i := 0; i < listValue.Len(); i++ { - if ObjectsAreEqual(listValue.Index(i).Interface(), element) { - return true, true - } - } - return true, false - -} - -// Contains asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// assert.Contains(t, "Hello World", "World") -// assert.Contains(t, ["Hello", "World"], "World") -// assert.Contains(t, {"Hello": "World"}, "Hello") -func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - ok, found := containsElement(s, contains) - if !ok { - return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...) - } - if !found { - return Fail(t, fmt.Sprintf("%#v does not contain %#v", s, contains), msgAndArgs...) - } - - return true - -} - -// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// assert.NotContains(t, "Hello World", "Earth") -// assert.NotContains(t, ["Hello", "World"], "Earth") -// assert.NotContains(t, {"Hello": "World"}, "Earth") -func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - ok, found := containsElement(s, contains) - if !ok { - return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) - } - if found { - return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...) - } - - return true - -} - -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). -// -// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") -func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if subset == nil { - return true // we consider nil to be equal to the nil set - } - - listKind := reflect.TypeOf(list).Kind() - if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map { - return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) - } - - subsetKind := reflect.TypeOf(subset).Kind() - if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map { - return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) - } - - if subsetKind == reflect.Map && listKind == reflect.Map { - subsetMap := reflect.ValueOf(subset) - actualMap := reflect.ValueOf(list) - - for _, k := range subsetMap.MapKeys() { - ev := subsetMap.MapIndex(k) - av := actualMap.MapIndex(k) - - if !av.IsValid() { - return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...) - } - if !ObjectsAreEqual(ev.Interface(), av.Interface()) { - return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...) - } - } - - return true - } - - subsetList := reflect.ValueOf(subset) - for i := 0; i < subsetList.Len(); i++ { - element := subsetList.Index(i).Interface() - ok, found := containsElement(list, element) - if !ok { - return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", list), msgAndArgs...) - } - if !found { - return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, element), msgAndArgs...) - } - } - - return true -} - -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). -// -// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") -func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if subset == nil { - return Fail(t, "nil is the empty set which is a subset of every set", msgAndArgs...) - } - - listKind := reflect.TypeOf(list).Kind() - if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map { - return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) - } - - subsetKind := reflect.TypeOf(subset).Kind() - if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map { - return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) - } - - if subsetKind == reflect.Map && listKind == reflect.Map { - subsetMap := reflect.ValueOf(subset) - actualMap := reflect.ValueOf(list) - - for _, k := range subsetMap.MapKeys() { - ev := subsetMap.MapIndex(k) - av := actualMap.MapIndex(k) - - if !av.IsValid() { - return true - } - if !ObjectsAreEqual(ev.Interface(), av.Interface()) { - return true - } - } - - return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...) - } - - subsetList := reflect.ValueOf(subset) - for i := 0; i < subsetList.Len(); i++ { - element := subsetList.Index(i).Interface() - ok, found := containsElement(list, element) - if !ok { - return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) - } - if !found { - return true - } - } - - return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...) -} - -// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) -func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if isEmpty(listA) && isEmpty(listB) { - return true - } - - if !isList(t, listA, msgAndArgs...) || !isList(t, listB, msgAndArgs...) { - return false - } - - extraA, extraB := diffLists(listA, listB) - - if len(extraA) == 0 && len(extraB) == 0 { - return true - } - - return Fail(t, formatListDiff(listA, listB, extraA, extraB), msgAndArgs...) -} - -// isList checks that the provided value is array or slice. -func isList(t TestingT, list interface{}, msgAndArgs ...interface{}) (ok bool) { - kind := reflect.TypeOf(list).Kind() - if kind != reflect.Array && kind != reflect.Slice { - return Fail(t, fmt.Sprintf("%q has an unsupported type %s, expecting array or slice", list, kind), - msgAndArgs...) - } - return true -} - -// diffLists diffs two arrays/slices and returns slices of elements that are only in A and only in B. -// If some element is present multiple times, each instance is counted separately (e.g. if something is 2x in A and -// 5x in B, it will be 0x in extraA and 3x in extraB). The order of items in both lists is ignored. -func diffLists(listA, listB interface{}) (extraA, extraB []interface{}) { - aValue := reflect.ValueOf(listA) - bValue := reflect.ValueOf(listB) - - aLen := aValue.Len() - bLen := bValue.Len() - - // Mark indexes in bValue that we already used - visited := make([]bool, bLen) - for i := 0; i < aLen; i++ { - element := aValue.Index(i).Interface() - found := false - for j := 0; j < bLen; j++ { - if visited[j] { - continue - } - if ObjectsAreEqual(bValue.Index(j).Interface(), element) { - visited[j] = true - found = true - break - } - } - if !found { - extraA = append(extraA, element) - } - } - - for j := 0; j < bLen; j++ { - if visited[j] { - continue - } - extraB = append(extraB, bValue.Index(j).Interface()) - } - - return -} - -func formatListDiff(listA, listB interface{}, extraA, extraB []interface{}) string { - var msg bytes.Buffer - - msg.WriteString("elements differ") - if len(extraA) > 0 { - msg.WriteString("\n\nextra elements in list A:\n") - msg.WriteString(spewConfig.Sdump(extraA)) - } - if len(extraB) > 0 { - msg.WriteString("\n\nextra elements in list B:\n") - msg.WriteString(spewConfig.Sdump(extraB)) - } - msg.WriteString("\n\nlistA:\n") - msg.WriteString(spewConfig.Sdump(listA)) - msg.WriteString("\n\nlistB:\n") - msg.WriteString(spewConfig.Sdump(listB)) - - return msg.String() -} - -// Condition uses a Comparison to assert a complex condition. -func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - result := comp() - if !result { - Fail(t, "Condition failed!", msgAndArgs...) - } - return result -} - -// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics -// methods, and represents a simple func that takes no arguments, and returns nothing. -type PanicTestFunc func() - -// didPanic returns true if the function passed to it panics. Otherwise, it returns false. -func didPanic(f PanicTestFunc) (didPanic bool, message interface{}, stack string) { - didPanic = true - - defer func() { - message = recover() - if didPanic { - stack = string(debug.Stack()) - } - }() - - // call the target function - f() - didPanic = false - - return -} - -// Panics asserts that the code inside the specified PanicTestFunc panics. -// -// assert.Panics(t, func(){ GoCrazy() }) -func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if funcDidPanic, panicValue, _ := didPanic(f); !funcDidPanic { - return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) - } - - return true -} - -// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) -func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - funcDidPanic, panicValue, panickedStack := didPanic(f) - if !funcDidPanic { - return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) - } - if panicValue != expected { - return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, expected, panicValue, panickedStack), msgAndArgs...) - } - - return true -} - -// PanicsWithError asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() }) -func PanicsWithError(t TestingT, errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - funcDidPanic, panicValue, panickedStack := didPanic(f) - if !funcDidPanic { - return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) - } - panicErr, ok := panicValue.(error) - if !ok || panicErr.Error() != errString { - return Fail(t, fmt.Sprintf("func %#v should panic with error message:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, errString, panicValue, panickedStack), msgAndArgs...) - } - - return true -} - -// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// assert.NotPanics(t, func(){ RemainCalm() }) -func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if funcDidPanic, panicValue, panickedStack := didPanic(f); funcDidPanic { - return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v\n\tPanic stack:\t%s", f, panicValue, panickedStack), msgAndArgs...) - } - - return true -} - -// WithinDuration asserts that the two times are within duration delta of each other. -// -// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) -func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - dt := expected.Sub(actual) - if dt < -delta || dt > delta { - return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) - } - - return true -} - -// WithinRange asserts that a time is within a time range (inclusive). -// -// assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) -func WithinRange(t TestingT, actual, start, end time.Time, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if end.Before(start) { - return Fail(t, "Start should be before end", msgAndArgs...) - } - - if actual.Before(start) { - return Fail(t, fmt.Sprintf("Time %v expected to be in time range %v to %v, but is before the range", actual, start, end), msgAndArgs...) - } else if actual.After(end) { - return Fail(t, fmt.Sprintf("Time %v expected to be in time range %v to %v, but is after the range", actual, start, end), msgAndArgs...) - } - - return true -} - -func toFloat(x interface{}) (float64, bool) { - var xf float64 - xok := true - - switch xn := x.(type) { - case uint: - xf = float64(xn) - case uint8: - xf = float64(xn) - case uint16: - xf = float64(xn) - case uint32: - xf = float64(xn) - case uint64: - xf = float64(xn) - case int: - xf = float64(xn) - case int8: - xf = float64(xn) - case int16: - xf = float64(xn) - case int32: - xf = float64(xn) - case int64: - xf = float64(xn) - case float32: - xf = float64(xn) - case float64: - xf = xn - case time.Duration: - xf = float64(xn) - default: - xok = false - } - - return xf, xok -} - -// InDelta asserts that the two numerals are within delta of each other. -// -// assert.InDelta(t, math.Pi, 22/7.0, 0.01) -func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - af, aok := toFloat(expected) - bf, bok := toFloat(actual) - - if !aok || !bok { - return Fail(t, "Parameters must be numerical", msgAndArgs...) - } - - if math.IsNaN(af) && math.IsNaN(bf) { - return true - } - - if math.IsNaN(af) { - return Fail(t, "Expected must not be NaN", msgAndArgs...) - } - - if math.IsNaN(bf) { - return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...) - } - - dt := af - bf - if dt < -delta || dt > delta { - return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) - } - - return true -} - -// InDeltaSlice is the same as InDelta, except it compares two slices. -func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if expected == nil || actual == nil || - reflect.TypeOf(actual).Kind() != reflect.Slice || - reflect.TypeOf(expected).Kind() != reflect.Slice { - return Fail(t, "Parameters must be slice", msgAndArgs...) - } - - actualSlice := reflect.ValueOf(actual) - expectedSlice := reflect.ValueOf(expected) - - for i := 0; i < actualSlice.Len(); i++ { - result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta, msgAndArgs...) - if !result { - return result - } - } - - return true -} - -// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if expected == nil || actual == nil || - reflect.TypeOf(actual).Kind() != reflect.Map || - reflect.TypeOf(expected).Kind() != reflect.Map { - return Fail(t, "Arguments must be maps", msgAndArgs...) - } - - expectedMap := reflect.ValueOf(expected) - actualMap := reflect.ValueOf(actual) - - if expectedMap.Len() != actualMap.Len() { - return Fail(t, "Arguments must have the same number of keys", msgAndArgs...) - } - - for _, k := range expectedMap.MapKeys() { - ev := expectedMap.MapIndex(k) - av := actualMap.MapIndex(k) - - if !ev.IsValid() { - return Fail(t, fmt.Sprintf("missing key %q in expected map", k), msgAndArgs...) - } - - if !av.IsValid() { - return Fail(t, fmt.Sprintf("missing key %q in actual map", k), msgAndArgs...) - } - - if !InDelta( - t, - ev.Interface(), - av.Interface(), - delta, - msgAndArgs..., - ) { - return false - } - } - - return true -} - -func calcRelativeError(expected, actual interface{}) (float64, error) { - af, aok := toFloat(expected) - bf, bok := toFloat(actual) - if !aok || !bok { - return 0, fmt.Errorf("Parameters must be numerical") - } - if math.IsNaN(af) && math.IsNaN(bf) { - return 0, nil - } - if math.IsNaN(af) { - return 0, errors.New("expected value must not be NaN") - } - if af == 0 { - return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error") - } - if math.IsNaN(bf) { - return 0, errors.New("actual value must not be NaN") - } - - return math.Abs(af-bf) / math.Abs(af), nil -} - -// InEpsilon asserts that expected and actual have a relative error less than epsilon -func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if math.IsNaN(epsilon) { - return Fail(t, "epsilon must not be NaN") - } - actualEpsilon, err := calcRelativeError(expected, actual) - if err != nil { - return Fail(t, err.Error(), msgAndArgs...) - } - if actualEpsilon > epsilon { - return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+ - " < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...) - } - - return true -} - -// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. -func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if expected == nil || actual == nil || - reflect.TypeOf(actual).Kind() != reflect.Slice || - reflect.TypeOf(expected).Kind() != reflect.Slice { - return Fail(t, "Parameters must be slice", msgAndArgs...) - } - - actualSlice := reflect.ValueOf(actual) - expectedSlice := reflect.ValueOf(expected) - - for i := 0; i < actualSlice.Len(); i++ { - result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon) - if !result { - return result - } - } - - return true -} - -/* - Errors -*/ - -// NoError asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if assert.NoError(t, err) { -// assert.Equal(t, expectedObj, actualObj) -// } -func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { - if err != nil { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...) - } - - return true -} - -// Error asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// if assert.Error(t, err) { -// assert.Equal(t, expectedError, err) -// } -func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { - if err == nil { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, "An error is expected but got nil.", msgAndArgs...) - } - - return true -} - -// EqualError asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// assert.EqualError(t, err, expectedErrorString) -func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if !Error(t, theError, msgAndArgs...) { - return false - } - expected := errString - actual := theError.Error() - // don't need to use deep equals here, we know they are both strings - if expected != actual { - return Fail(t, fmt.Sprintf("Error message not equal:\n"+ - "expected: %q\n"+ - "actual : %q", expected, actual), msgAndArgs...) - } - return true -} - -// ErrorContains asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// assert.ErrorContains(t, err, expectedErrorSubString) -func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if !Error(t, theError, msgAndArgs...) { - return false - } - - actual := theError.Error() - if !strings.Contains(actual, contains) { - return Fail(t, fmt.Sprintf("Error %#v does not contain %#v", actual, contains), msgAndArgs...) - } - - return true -} - -// matchRegexp return true if a specified regexp matches a string. -func matchRegexp(rx interface{}, str interface{}) bool { - - var r *regexp.Regexp - if rr, ok := rx.(*regexp.Regexp); ok { - r = rr - } else { - r = regexp.MustCompile(fmt.Sprint(rx)) - } - - return (r.FindStringIndex(fmt.Sprint(str)) != nil) - -} - -// Regexp asserts that a specified regexp matches a string. -// -// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") -// assert.Regexp(t, "start...$", "it's not starting") -func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - match := matchRegexp(rx, str) - - if !match { - Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...) - } - - return match -} - -// NotRegexp asserts that a specified regexp does not match a string. -// -// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") -// assert.NotRegexp(t, "^start", "it's not starting") -func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - match := matchRegexp(rx, str) - - if match { - Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...) - } - - return !match - -} - -// Zero asserts that i is the zero value for its type. -func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { - return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...) - } - return true -} - -// NotZero asserts that i is not the zero value for its type. -func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { - return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...) - } - return true -} - -// FileExists checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - info, err := os.Lstat(path) - if err != nil { - if os.IsNotExist(err) { - return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) - } - return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) - } - if info.IsDir() { - return Fail(t, fmt.Sprintf("%q is a directory", path), msgAndArgs...) - } - return true -} - -// NoFileExists checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func NoFileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - info, err := os.Lstat(path) - if err != nil { - return true - } - if info.IsDir() { - return true - } - return Fail(t, fmt.Sprintf("file %q exists", path), msgAndArgs...) -} - -// DirExists checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - info, err := os.Lstat(path) - if err != nil { - if os.IsNotExist(err) { - return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) - } - return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) - } - if !info.IsDir() { - return Fail(t, fmt.Sprintf("%q is a file", path), msgAndArgs...) - } - return true -} - -// NoDirExists checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - info, err := os.Lstat(path) - if err != nil { - if os.IsNotExist(err) { - return true - } - return true - } - if !info.IsDir() { - return true - } - return Fail(t, fmt.Sprintf("directory %q exists", path), msgAndArgs...) -} - -// JSONEq asserts that two JSON strings are equivalent. -// -// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) -func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - var expectedJSONAsInterface, actualJSONAsInterface interface{} - - if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil { - return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...) - } - - if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil { - return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...) - } - - return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...) -} - -// YAMLEq asserts that two YAML strings are equivalent. -func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - var expectedYAMLAsInterface, actualYAMLAsInterface interface{} - - if err := yaml.Unmarshal([]byte(expected), &expectedYAMLAsInterface); err != nil { - return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid yaml.\nYAML parsing error: '%s'", expected, err.Error()), msgAndArgs...) - } - - if err := yaml.Unmarshal([]byte(actual), &actualYAMLAsInterface); err != nil { - return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid yaml.\nYAML error: '%s'", actual, err.Error()), msgAndArgs...) - } - - return Equal(t, expectedYAMLAsInterface, actualYAMLAsInterface, msgAndArgs...) -} - -func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { - t := reflect.TypeOf(v) - k := t.Kind() - - if k == reflect.Ptr { - t = t.Elem() - k = t.Kind() - } - return t, k -} - -// diff returns a diff of both values as long as both are of the same type and -// are a struct, map, slice, array or string. Otherwise it returns an empty string. -func diff(expected interface{}, actual interface{}) string { - if expected == nil || actual == nil { - return "" - } - - et, ek := typeAndKind(expected) - at, _ := typeAndKind(actual) - - if et != at { - return "" - } - - if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String { - return "" - } - - var e, a string - - switch et { - case reflect.TypeOf(""): - e = reflect.ValueOf(expected).String() - a = reflect.ValueOf(actual).String() - case reflect.TypeOf(time.Time{}): - e = spewConfigStringerEnabled.Sdump(expected) - a = spewConfigStringerEnabled.Sdump(actual) - default: - e = spewConfig.Sdump(expected) - a = spewConfig.Sdump(actual) - } - - diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ - A: difflib.SplitLines(e), - B: difflib.SplitLines(a), - FromFile: "Expected", - FromDate: "", - ToFile: "Actual", - ToDate: "", - Context: 1, - }) - - return "\n\nDiff:\n" + diff -} - -func isFunction(arg interface{}) bool { - if arg == nil { - return false - } - return reflect.TypeOf(arg).Kind() == reflect.Func -} - -var spewConfig = spew.ConfigState{ - Indent: " ", - DisablePointerAddresses: true, - DisableCapacities: true, - SortKeys: true, - DisableMethods: true, - MaxDepth: 10, -} - -var spewConfigStringerEnabled = spew.ConfigState{ - Indent: " ", - DisablePointerAddresses: true, - DisableCapacities: true, - SortKeys: true, - MaxDepth: 10, -} - -type tHelper interface { - Helper() -} - -// Eventually asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond) -func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - ch := make(chan bool, 1) - - timer := time.NewTimer(waitFor) - defer timer.Stop() - - ticker := time.NewTicker(tick) - defer ticker.Stop() - - for tick := ticker.C; ; { - select { - case <-timer.C: - return Fail(t, "Condition never satisfied", msgAndArgs...) - case <-tick: - tick = nil - go func() { ch <- condition() }() - case v := <-ch: - if v { - return true - } - tick = ticker.C - } - } -} - -// Never asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond) -func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - ch := make(chan bool, 1) - - timer := time.NewTimer(waitFor) - defer timer.Stop() - - ticker := time.NewTicker(tick) - defer ticker.Stop() - - for tick := ticker.C; ; { - select { - case <-timer.C: - return true - case <-tick: - tick = nil - go func() { ch <- condition() }() - case v := <-ch: - if v { - return Fail(t, "Condition satisfied", msgAndArgs...) - } - tick = ticker.C - } - } -} - -// ErrorIs asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if errors.Is(err, target) { - return true - } - - var expectedText string - if target != nil { - expectedText = target.Error() - } - - chain := buildErrorChainString(err) - - return Fail(t, fmt.Sprintf("Target error should be in err chain:\n"+ - "expected: %q\n"+ - "in chain: %s", expectedText, chain, - ), msgAndArgs...) -} - -// NotErrorIs asserts that at none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if !errors.Is(err, target) { - return true - } - - var expectedText string - if target != nil { - expectedText = target.Error() - } - - chain := buildErrorChainString(err) - - return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+ - "found: %q\n"+ - "in chain: %s", expectedText, chain, - ), msgAndArgs...) -} - -// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if errors.As(err, target) { - return true - } - - chain := buildErrorChainString(err) - - return Fail(t, fmt.Sprintf("Should be in error chain:\n"+ - "expected: %q\n"+ - "in chain: %s", target, chain, - ), msgAndArgs...) -} - -func buildErrorChainString(err error) string { - if err == nil { - return "" - } - - e := errors.Unwrap(err) - chain := fmt.Sprintf("%q", err.Error()) - for e != nil { - chain += fmt.Sprintf("\n\t%q", e.Error()) - e = errors.Unwrap(e) - } - return chain -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertions_test.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertions_test.go deleted file mode 100644 index cae11f8..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/assertions_test.go +++ /dev/null @@ -1,2582 +0,0 @@ -package assert - -import ( - "bufio" - "bytes" - "encoding/json" - "errors" - "fmt" - "io" - "math" - "os" - "reflect" - "regexp" - "runtime" - "strings" - "testing" - "time" - "unsafe" -) - -var ( - i interface{} - zeros = []interface{}{ - false, - byte(0), - complex64(0), - complex128(0), - float32(0), - float64(0), - int(0), - int8(0), - int16(0), - int32(0), - int64(0), - rune(0), - uint(0), - uint8(0), - uint16(0), - uint32(0), - uint64(0), - uintptr(0), - "", - [0]interface{}{}, - []interface{}(nil), - struct{ x int }{}, - (*interface{})(nil), - (func())(nil), - nil, - interface{}(nil), - map[interface{}]interface{}(nil), - (chan interface{})(nil), - (<-chan interface{})(nil), - (chan<- interface{})(nil), - } - nonZeros = []interface{}{ - true, - byte(1), - complex64(1), - complex128(1), - float32(1), - float64(1), - int(1), - int8(1), - int16(1), - int32(1), - int64(1), - rune(1), - uint(1), - uint8(1), - uint16(1), - uint32(1), - uint64(1), - uintptr(1), - "s", - [1]interface{}{1}, - []interface{}{}, - struct{ x int }{1}, - (&i), - (func() {}), - interface{}(1), - map[interface{}]interface{}{}, - (make(chan interface{})), - (<-chan interface{})(make(chan interface{})), - (chan<- interface{})(make(chan interface{})), - } -) - -// AssertionTesterInterface defines an interface to be used for testing assertion methods -type AssertionTesterInterface interface { - TestMethod() -} - -// AssertionTesterConformingObject is an object that conforms to the AssertionTesterInterface interface -type AssertionTesterConformingObject struct { -} - -func (a *AssertionTesterConformingObject) TestMethod() { -} - -// AssertionTesterNonConformingObject is an object that does not conform to the AssertionTesterInterface interface -type AssertionTesterNonConformingObject struct { -} - -func TestObjectsAreEqual(t *testing.T) { - cases := []struct { - expected interface{} - actual interface{} - result bool - }{ - // cases that are expected to be equal - {"Hello World", "Hello World", true}, - {123, 123, true}, - {123.5, 123.5, true}, - {[]byte("Hello World"), []byte("Hello World"), true}, - {nil, nil, true}, - - // cases that are expected not to be equal - {map[int]int{5: 10}, map[int]int{10: 20}, false}, - {'x', "x", false}, - {"x", 'x', false}, - {0, 0.1, false}, - {0.1, 0, false}, - {time.Now, time.Now, false}, - {func() {}, func() {}, false}, - {uint32(10), int32(10), false}, - } - - for _, c := range cases { - t.Run(fmt.Sprintf("ObjectsAreEqual(%#v, %#v)", c.expected, c.actual), func(t *testing.T) { - res := ObjectsAreEqual(c.expected, c.actual) - - if res != c.result { - t.Errorf("ObjectsAreEqual(%#v, %#v) should return %#v", c.expected, c.actual, c.result) - } - - }) - } - - // Cases where type differ but values are equal - if !ObjectsAreEqualValues(uint32(10), int32(10)) { - t.Error("ObjectsAreEqualValues should return true") - } - if ObjectsAreEqualValues(0, nil) { - t.Fail() - } - if ObjectsAreEqualValues(nil, 0) { - t.Fail() - } - -} - -func TestImplements(t *testing.T) { - - mockT := new(testing.T) - - if !Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) { - t.Error("Implements method should return true: AssertionTesterConformingObject implements AssertionTesterInterface") - } - if Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) { - t.Error("Implements method should return false: AssertionTesterNonConformingObject does not implements AssertionTesterInterface") - } - if Implements(mockT, (*AssertionTesterInterface)(nil), nil) { - t.Error("Implements method should return false: nil does not implement AssertionTesterInterface") - } - -} - -func TestIsType(t *testing.T) { - - mockT := new(testing.T) - - if !IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) { - t.Error("IsType should return true: AssertionTesterConformingObject is the same type as AssertionTesterConformingObject") - } - if IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) { - t.Error("IsType should return false: AssertionTesterConformingObject is not the same type as AssertionTesterNonConformingObject") - } - -} - -func TestEqual(t *testing.T) { - type myType string - - mockT := new(testing.T) - var m map[string]interface{} - - cases := []struct { - expected interface{} - actual interface{} - result bool - remark string - }{ - {"Hello World", "Hello World", true, ""}, - {123, 123, true, ""}, - {123.5, 123.5, true, ""}, - {[]byte("Hello World"), []byte("Hello World"), true, ""}, - {nil, nil, true, ""}, - {int32(123), int32(123), true, ""}, - {uint64(123), uint64(123), true, ""}, - {myType("1"), myType("1"), true, ""}, - {&struct{}{}, &struct{}{}, true, "pointer equality is based on equality of underlying value"}, - - // Not expected to be equal - {m["bar"], "something", false, ""}, - {myType("1"), myType("2"), false, ""}, - - // A case that might be confusing, especially with numeric literals - {10, uint(10), false, ""}, - } - - for _, c := range cases { - t.Run(fmt.Sprintf("Equal(%#v, %#v)", c.expected, c.actual), func(t *testing.T) { - res := Equal(mockT, c.expected, c.actual) - - if res != c.result { - t.Errorf("Equal(%#v, %#v) should return %#v: %s", c.expected, c.actual, c.result, c.remark) - } - }) - } -} - -func ptr(i int) *int { - return &i -} - -func TestSame(t *testing.T) { - - mockT := new(testing.T) - - if Same(mockT, ptr(1), ptr(1)) { - t.Error("Same should return false") - } - if Same(mockT, 1, 1) { - t.Error("Same should return false") - } - p := ptr(2) - if Same(mockT, p, *p) { - t.Error("Same should return false") - } - if !Same(mockT, p, p) { - t.Error("Same should return true") - } -} - -func TestNotSame(t *testing.T) { - - mockT := new(testing.T) - - if !NotSame(mockT, ptr(1), ptr(1)) { - t.Error("NotSame should return true; different pointers") - } - if !NotSame(mockT, 1, 1) { - t.Error("NotSame should return true; constant inputs") - } - p := ptr(2) - if !NotSame(mockT, p, *p) { - t.Error("NotSame should return true; mixed-type inputs") - } - if NotSame(mockT, p, p) { - t.Error("NotSame should return false") - } -} - -func Test_samePointers(t *testing.T) { - p := ptr(2) - - type args struct { - first interface{} - second interface{} - } - tests := []struct { - name string - args args - assertion BoolAssertionFunc - }{ - { - name: "1 != 2", - args: args{first: 1, second: 2}, - assertion: False, - }, - { - name: "1 != 1 (not same ptr)", - args: args{first: 1, second: 1}, - assertion: False, - }, - { - name: "ptr(1) == ptr(1)", - args: args{first: p, second: p}, - assertion: True, - }, - { - name: "int(1) != float32(1)", - args: args{first: int(1), second: float32(1)}, - assertion: False, - }, - { - name: "array != slice", - args: args{first: [2]int{1, 2}, second: []int{1, 2}}, - assertion: False, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.assertion(t, samePointers(tt.args.first, tt.args.second)) - }) - } -} - -// bufferT implements TestingT. Its implementation of Errorf writes the output that would be produced by -// testing.T.Errorf to an internal bytes.Buffer. -type bufferT struct { - buf bytes.Buffer -} - -func (t *bufferT) Errorf(format string, args ...interface{}) { - // implementation of decorate is copied from testing.T - decorate := func(s string) string { - _, file, line, ok := runtime.Caller(3) // decorate + log + public function. - if ok { - // Truncate file name at last file name separator. - if index := strings.LastIndex(file, "/"); index >= 0 { - file = file[index+1:] - } else if index = strings.LastIndex(file, "\\"); index >= 0 { - file = file[index+1:] - } - } else { - file = "???" - line = 1 - } - buf := new(bytes.Buffer) - // Every line is indented at least one tab. - buf.WriteByte('\t') - fmt.Fprintf(buf, "%s:%d: ", file, line) - lines := strings.Split(s, "\n") - if l := len(lines); l > 1 && lines[l-1] == "" { - lines = lines[:l-1] - } - for i, line := range lines { - if i > 0 { - // Second and subsequent lines are indented an extra tab. - buf.WriteString("\n\t\t") - } - buf.WriteString(line) - } - buf.WriteByte('\n') - return buf.String() - } - t.buf.WriteString(decorate(fmt.Sprintf(format, args...))) -} - -func TestStringEqual(t *testing.T) { - for i, currCase := range []struct { - equalWant string - equalGot string - msgAndArgs []interface{} - want string - }{ - {equalWant: "hi, \nmy name is", equalGot: "what,\nmy name is", want: "\tassertions.go:\\d+: \n\t+Error Trace:\t\n\t+Error:\\s+Not equal:\\s+\n\\s+expected: \"hi, \\\\nmy name is\"\n\\s+actual\\s+: \"what,\\\\nmy name is\"\n\\s+Diff:\n\\s+-+ Expected\n\\s+\\++ Actual\n\\s+@@ -1,2 \\+1,2 @@\n\\s+-hi, \n\\s+\\+what,\n\\s+my name is"}, - } { - mockT := &bufferT{} - Equal(mockT, currCase.equalWant, currCase.equalGot, currCase.msgAndArgs...) - Regexp(t, regexp.MustCompile(currCase.want), mockT.buf.String(), "Case %d", i) - } -} - -func TestEqualFormatting(t *testing.T) { - for i, currCase := range []struct { - equalWant string - equalGot string - msgAndArgs []interface{} - want string - }{ - {equalWant: "want", equalGot: "got", want: "\tassertions.go:\\d+: \n\t+Error Trace:\t\n\t+Error:\\s+Not equal:\\s+\n\\s+expected: \"want\"\n\\s+actual\\s+: \"got\"\n\\s+Diff:\n\\s+-+ Expected\n\\s+\\++ Actual\n\\s+@@ -1 \\+1 @@\n\\s+-want\n\\s+\\+got\n"}, - {equalWant: "want", equalGot: "got", msgAndArgs: []interface{}{"hello, %v!", "world"}, want: "\tassertions.go:[0-9]+: \n\t+Error Trace:\t\n\t+Error:\\s+Not equal:\\s+\n\\s+expected: \"want\"\n\\s+actual\\s+: \"got\"\n\\s+Diff:\n\\s+-+ Expected\n\\s+\\++ Actual\n\\s+@@ -1 \\+1 @@\n\\s+-want\n\\s+\\+got\n\\s+Messages:\\s+hello, world!\n"}, - {equalWant: "want", equalGot: "got", msgAndArgs: []interface{}{123}, want: "\tassertions.go:[0-9]+: \n\t+Error Trace:\t\n\t+Error:\\s+Not equal:\\s+\n\\s+expected: \"want\"\n\\s+actual\\s+: \"got\"\n\\s+Diff:\n\\s+-+ Expected\n\\s+\\++ Actual\n\\s+@@ -1 \\+1 @@\n\\s+-want\n\\s+\\+got\n\\s+Messages:\\s+123\n"}, - {equalWant: "want", equalGot: "got", msgAndArgs: []interface{}{struct{ a string }{"hello"}}, want: "\tassertions.go:[0-9]+: \n\t+Error Trace:\t\n\t+Error:\\s+Not equal:\\s+\n\\s+expected: \"want\"\n\\s+actual\\s+: \"got\"\n\\s+Diff:\n\\s+-+ Expected\n\\s+\\++ Actual\n\\s+@@ -1 \\+1 @@\n\\s+-want\n\\s+\\+got\n\\s+Messages:\\s+{a:hello}\n"}, - } { - mockT := &bufferT{} - Equal(mockT, currCase.equalWant, currCase.equalGot, currCase.msgAndArgs...) - Regexp(t, regexp.MustCompile(currCase.want), mockT.buf.String(), "Case %d", i) - } -} - -func TestFormatUnequalValues(t *testing.T) { - expected, actual := formatUnequalValues("foo", "bar") - Equal(t, `"foo"`, expected, "value should not include type") - Equal(t, `"bar"`, actual, "value should not include type") - - expected, actual = formatUnequalValues(123, 123) - Equal(t, `123`, expected, "value should not include type") - Equal(t, `123`, actual, "value should not include type") - - expected, actual = formatUnequalValues(int64(123), int32(123)) - Equal(t, `int64(123)`, expected, "value should include type") - Equal(t, `int32(123)`, actual, "value should include type") - - expected, actual = formatUnequalValues(int64(123), nil) - Equal(t, `int64(123)`, expected, "value should include type") - Equal(t, `<nil>(<nil>)`, actual, "value should include type") - - type testStructType struct { - Val string - } - - expected, actual = formatUnequalValues(&testStructType{Val: "test"}, &testStructType{Val: "test"}) - Equal(t, `&assert.testStructType{Val:"test"}`, expected, "value should not include type annotation") - Equal(t, `&assert.testStructType{Val:"test"}`, actual, "value should not include type annotation") -} - -func TestNotNil(t *testing.T) { - - mockT := new(testing.T) - - if !NotNil(mockT, new(AssertionTesterConformingObject)) { - t.Error("NotNil should return true: object is not nil") - } - if NotNil(mockT, nil) { - t.Error("NotNil should return false: object is nil") - } - if NotNil(mockT, (*struct{})(nil)) { - t.Error("NotNil should return false: object is (*struct{})(nil)") - } - -} - -func TestNil(t *testing.T) { - - mockT := new(testing.T) - - if !Nil(mockT, nil) { - t.Error("Nil should return true: object is nil") - } - if !Nil(mockT, (*struct{})(nil)) { - t.Error("Nil should return true: object is (*struct{})(nil)") - } - if Nil(mockT, new(AssertionTesterConformingObject)) { - t.Error("Nil should return false: object is not nil") - } - -} - -func TestTrue(t *testing.T) { - - mockT := new(testing.T) - - if !True(mockT, true) { - t.Error("True should return true") - } - if True(mockT, false) { - t.Error("True should return false") - } - -} - -func TestFalse(t *testing.T) { - - mockT := new(testing.T) - - if !False(mockT, false) { - t.Error("False should return true") - } - if False(mockT, true) { - t.Error("False should return false") - } - -} - -func TestExactly(t *testing.T) { - - mockT := new(testing.T) - - a := float32(1) - b := float64(1) - c := float32(1) - d := float32(2) - cases := []struct { - expected interface{} - actual interface{} - result bool - }{ - {a, b, false}, - {a, d, false}, - {a, c, true}, - {nil, a, false}, - {a, nil, false}, - } - - for _, c := range cases { - t.Run(fmt.Sprintf("Exactly(%#v, %#v)", c.expected, c.actual), func(t *testing.T) { - res := Exactly(mockT, c.expected, c.actual) - - if res != c.result { - t.Errorf("Exactly(%#v, %#v) should return %#v", c.expected, c.actual, c.result) - } - }) - } -} - -func TestNotEqual(t *testing.T) { - - mockT := new(testing.T) - - cases := []struct { - expected interface{} - actual interface{} - result bool - }{ - // cases that are expected not to match - {"Hello World", "Hello World!", true}, - {123, 1234, true}, - {123.5, 123.55, true}, - {[]byte("Hello World"), []byte("Hello World!"), true}, - {nil, new(AssertionTesterConformingObject), true}, - - // cases that are expected to match - {nil, nil, false}, - {"Hello World", "Hello World", false}, - {123, 123, false}, - {123.5, 123.5, false}, - {[]byte("Hello World"), []byte("Hello World"), false}, - {new(AssertionTesterConformingObject), new(AssertionTesterConformingObject), false}, - {&struct{}{}, &struct{}{}, false}, - {func() int { return 23 }, func() int { return 24 }, false}, - // A case that might be confusing, especially with numeric literals - {int(10), uint(10), true}, - } - - for _, c := range cases { - t.Run(fmt.Sprintf("NotEqual(%#v, %#v)", c.expected, c.actual), func(t *testing.T) { - res := NotEqual(mockT, c.expected, c.actual) - - if res != c.result { - t.Errorf("NotEqual(%#v, %#v) should return %#v", c.expected, c.actual, c.result) - } - }) - } -} - -func TestNotEqualValues(t *testing.T) { - mockT := new(testing.T) - - cases := []struct { - expected interface{} - actual interface{} - result bool - }{ - // cases that are expected not to match - {"Hello World", "Hello World!", true}, - {123, 1234, true}, - {123.5, 123.55, true}, - {[]byte("Hello World"), []byte("Hello World!"), true}, - {nil, new(AssertionTesterConformingObject), true}, - - // cases that are expected to match - {nil, nil, false}, - {"Hello World", "Hello World", false}, - {123, 123, false}, - {123.5, 123.5, false}, - {[]byte("Hello World"), []byte("Hello World"), false}, - {new(AssertionTesterConformingObject), new(AssertionTesterConformingObject), false}, - {&struct{}{}, &struct{}{}, false}, - - // Different behaviour from NotEqual() - {func() int { return 23 }, func() int { return 24 }, true}, - {int(10), int(11), true}, - {int(10), uint(10), false}, - - {struct{}{}, struct{}{}, false}, - } - - for _, c := range cases { - t.Run(fmt.Sprintf("NotEqualValues(%#v, %#v)", c.expected, c.actual), func(t *testing.T) { - res := NotEqualValues(mockT, c.expected, c.actual) - - if res != c.result { - t.Errorf("NotEqualValues(%#v, %#v) should return %#v", c.expected, c.actual, c.result) - } - }) - } -} - -func TestContainsNotContains(t *testing.T) { - - type A struct { - Name, Value string - } - list := []string{"Foo", "Bar"} - - complexList := []*A{ - {"b", "c"}, - {"d", "e"}, - {"g", "h"}, - {"j", "k"}, - } - simpleMap := map[interface{}]interface{}{"Foo": "Bar"} - var zeroMap map[interface{}]interface{} - - cases := []struct { - expected interface{} - actual interface{} - result bool - }{ - {"Hello World", "Hello", true}, - {"Hello World", "Salut", false}, - {list, "Bar", true}, - {list, "Salut", false}, - {complexList, &A{"g", "h"}, true}, - {complexList, &A{"g", "e"}, false}, - {simpleMap, "Foo", true}, - {simpleMap, "Bar", false}, - {zeroMap, "Bar", false}, - } - - for _, c := range cases { - t.Run(fmt.Sprintf("Contains(%#v, %#v)", c.expected, c.actual), func(t *testing.T) { - mockT := new(testing.T) - res := Contains(mockT, c.expected, c.actual) - - if res != c.result { - if res { - t.Errorf("Contains(%#v, %#v) should return true:\n\t%#v contains %#v", c.expected, c.actual, c.expected, c.actual) - } else { - t.Errorf("Contains(%#v, %#v) should return false:\n\t%#v does not contain %#v", c.expected, c.actual, c.expected, c.actual) - } - } - }) - } - - for _, c := range cases { - t.Run(fmt.Sprintf("NotContains(%#v, %#v)", c.expected, c.actual), func(t *testing.T) { - mockT := new(testing.T) - res := NotContains(mockT, c.expected, c.actual) - - // NotContains should be inverse of Contains. If it's not, something is wrong - if res == Contains(mockT, c.expected, c.actual) { - if res { - t.Errorf("NotContains(%#v, %#v) should return true:\n\t%#v does not contains %#v", c.expected, c.actual, c.expected, c.actual) - } else { - t.Errorf("NotContains(%#v, %#v) should return false:\n\t%#v contains %#v", c.expected, c.actual, c.expected, c.actual) - } - } - }) - } -} - -func TestContainsFailMessage(t *testing.T) { - - mockT := new(mockTestingT) - - Contains(mockT, "Hello World", errors.New("Hello")) - expectedFail := "\"Hello World\" does not contain &errors.errorString{s:\"Hello\"}" - actualFail := mockT.errorString() - if !strings.Contains(actualFail, expectedFail) { - t.Errorf("Contains failure should include %q but was %q", expectedFail, actualFail) - } -} - -func TestContainsNotContainsOnNilValue(t *testing.T) { - mockT := new(mockTestingT) - - Contains(mockT, nil, "key") - expectedFail := "<nil> could not be applied builtin len()" - actualFail := mockT.errorString() - if !strings.Contains(actualFail, expectedFail) { - t.Errorf("Contains failure should include %q but was %q", expectedFail, actualFail) - } - - NotContains(mockT, nil, "key") - if !strings.Contains(actualFail, expectedFail) { - t.Errorf("Contains failure should include %q but was %q", expectedFail, actualFail) - } -} - -func TestSubsetNotSubset(t *testing.T) { - cases := []struct { - list interface{} - subset interface{} - result bool - message string - }{ - // cases that are expected to contain - {[]int{1, 2, 3}, nil, true, `nil is the empty set which is a subset of every set`}, - {[]int{1, 2, 3}, []int{}, true, `[] is a subset of ['\x01' '\x02' '\x03']`}, - {[]int{1, 2, 3}, []int{1, 2}, true, `['\x01' '\x02'] is a subset of ['\x01' '\x02' '\x03']`}, - {[]int{1, 2, 3}, []int{1, 2, 3}, true, `['\x01' '\x02' '\x03'] is a subset of ['\x01' '\x02' '\x03']`}, - {[]string{"hello", "world"}, []string{"hello"}, true, `["hello"] is a subset of ["hello" "world"]`}, - {map[string]string{ - "a": "x", - "c": "z", - "b": "y", - }, map[string]string{ - "a": "x", - "b": "y", - }, true, `map["a":"x" "b":"y"] is a subset of map["a":"x" "b":"y" "c":"z"]`}, - - // cases that are expected not to contain - {[]string{"hello", "world"}, []string{"hello", "testify"}, false, `[]string{"hello", "world"} does not contain "testify"`}, - {[]int{1, 2, 3}, []int{4, 5}, false, `[]int{1, 2, 3} does not contain 4`}, - {[]int{1, 2, 3}, []int{1, 5}, false, `[]int{1, 2, 3} does not contain 5`}, - {map[string]string{ - "a": "x", - "c": "z", - "b": "y", - }, map[string]string{ - "a": "x", - "b": "z", - }, false, `map[string]string{"a":"x", "b":"y", "c":"z"} does not contain map[string]string{"a":"x", "b":"z"}`}, - {map[string]string{ - "a": "x", - "b": "y", - }, map[string]string{ - "a": "x", - "b": "y", - "c": "z", - }, false, `map[string]string{"a":"x", "b":"y"} does not contain map[string]string{"a":"x", "b":"y", "c":"z"}`}, - } - - for _, c := range cases { - t.Run("SubSet: "+c.message, func(t *testing.T) { - - mockT := new(mockTestingT) - res := Subset(mockT, c.list, c.subset) - - if res != c.result { - t.Errorf("Subset should return %t: %s", c.result, c.message) - } - if !c.result { - expectedFail := c.message - actualFail := mockT.errorString() - if !strings.Contains(actualFail, expectedFail) { - t.Log(actualFail) - t.Errorf("Subset failure should contain %q but was %q", expectedFail, actualFail) - } - } - }) - } - for _, c := range cases { - t.Run("NotSubSet: "+c.message, func(t *testing.T) { - mockT := new(mockTestingT) - res := NotSubset(mockT, c.list, c.subset) - - // NotSubset should match the inverse of Subset. If it doesn't, something is wrong - if res == Subset(mockT, c.list, c.subset) { - t.Errorf("NotSubset should return %t: %s", !c.result, c.message) - } - if c.result { - expectedFail := c.message - actualFail := mockT.errorString() - if !strings.Contains(actualFail, expectedFail) { - t.Log(actualFail) - t.Errorf("NotSubset failure should contain %q but was %q", expectedFail, actualFail) - } - } - }) - } -} - -func TestNotSubsetNil(t *testing.T) { - mockT := new(testing.T) - NotSubset(mockT, []string{"foo"}, nil) - if !mockT.Failed() { - t.Error("NotSubset on nil set should have failed the test") - } -} - -func Test_containsElement(t *testing.T) { - - list1 := []string{"Foo", "Bar"} - list2 := []int{1, 2} - simpleMap := map[interface{}]interface{}{"Foo": "Bar"} - - ok, found := containsElement("Hello World", "World") - True(t, ok) - True(t, found) - - ok, found = containsElement(list1, "Foo") - True(t, ok) - True(t, found) - - ok, found = containsElement(list1, "Bar") - True(t, ok) - True(t, found) - - ok, found = containsElement(list2, 1) - True(t, ok) - True(t, found) - - ok, found = containsElement(list2, 2) - True(t, ok) - True(t, found) - - ok, found = containsElement(list1, "Foo!") - True(t, ok) - False(t, found) - - ok, found = containsElement(list2, 3) - True(t, ok) - False(t, found) - - ok, found = containsElement(list2, "1") - True(t, ok) - False(t, found) - - ok, found = containsElement(simpleMap, "Foo") - True(t, ok) - True(t, found) - - ok, found = containsElement(simpleMap, "Bar") - True(t, ok) - False(t, found) - - ok, found = containsElement(1433, "1") - False(t, ok) - False(t, found) -} - -func TestElementsMatch(t *testing.T) { - mockT := new(testing.T) - - cases := []struct { - expected interface{} - actual interface{} - result bool - }{ - // matching - {nil, nil, true}, - - {nil, nil, true}, - {[]int{}, []int{}, true}, - {[]int{1}, []int{1}, true}, - {[]int{1, 1}, []int{1, 1}, true}, - {[]int{1, 2}, []int{1, 2}, true}, - {[]int{1, 2}, []int{2, 1}, true}, - {[2]int{1, 2}, [2]int{2, 1}, true}, - {[]string{"hello", "world"}, []string{"world", "hello"}, true}, - {[]string{"hello", "hello"}, []string{"hello", "hello"}, true}, - {[]string{"hello", "hello", "world"}, []string{"hello", "world", "hello"}, true}, - {[3]string{"hello", "hello", "world"}, [3]string{"hello", "world", "hello"}, true}, - {[]int{}, nil, true}, - - // not matching - {[]int{1}, []int{1, 1}, false}, - {[]int{1, 2}, []int{2, 2}, false}, - {[]string{"hello", "hello"}, []string{"hello"}, false}, - } - - for _, c := range cases { - t.Run(fmt.Sprintf("ElementsMatch(%#v, %#v)", c.expected, c.actual), func(t *testing.T) { - res := ElementsMatch(mockT, c.actual, c.expected) - - if res != c.result { - t.Errorf("ElementsMatch(%#v, %#v) should return %v", c.actual, c.expected, c.result) - } - }) - } -} - -func TestDiffLists(t *testing.T) { - tests := []struct { - name string - listA interface{} - listB interface{} - extraA []interface{} - extraB []interface{} - }{ - { - name: "equal empty", - listA: []string{}, - listB: []string{}, - extraA: nil, - extraB: nil, - }, - { - name: "equal same order", - listA: []string{"hello", "world"}, - listB: []string{"hello", "world"}, - extraA: nil, - extraB: nil, - }, - { - name: "equal different order", - listA: []string{"hello", "world"}, - listB: []string{"world", "hello"}, - extraA: nil, - extraB: nil, - }, - { - name: "extra A", - listA: []string{"hello", "hello", "world"}, - listB: []string{"hello", "world"}, - extraA: []interface{}{"hello"}, - extraB: nil, - }, - { - name: "extra A twice", - listA: []string{"hello", "hello", "hello", "world"}, - listB: []string{"hello", "world"}, - extraA: []interface{}{"hello", "hello"}, - extraB: nil, - }, - { - name: "extra B", - listA: []string{"hello", "world"}, - listB: []string{"hello", "hello", "world"}, - extraA: nil, - extraB: []interface{}{"hello"}, - }, - { - name: "extra B twice", - listA: []string{"hello", "world"}, - listB: []string{"hello", "hello", "world", "hello"}, - extraA: nil, - extraB: []interface{}{"hello", "hello"}, - }, - { - name: "integers 1", - listA: []int{1, 2, 3, 4, 5}, - listB: []int{5, 4, 3, 2, 1}, - extraA: nil, - extraB: nil, - }, - { - name: "integers 2", - listA: []int{1, 2, 1, 2, 1}, - listB: []int{2, 1, 2, 1, 2}, - extraA: []interface{}{1}, - extraB: []interface{}{2}, - }, - } - for _, test := range tests { - test := test - t.Run(test.name, func(t *testing.T) { - actualExtraA, actualExtraB := diffLists(test.listA, test.listB) - Equal(t, test.extraA, actualExtraA, "extra A does not match for listA=%v listB=%v", - test.listA, test.listB) - Equal(t, test.extraB, actualExtraB, "extra B does not match for listA=%v listB=%v", - test.listA, test.listB) - }) - } -} - -func TestCondition(t *testing.T) { - mockT := new(testing.T) - - if !Condition(mockT, func() bool { return true }, "Truth") { - t.Error("Condition should return true") - } - - if Condition(mockT, func() bool { return false }, "Lie") { - t.Error("Condition should return false") - } - -} - -func TestDidPanic(t *testing.T) { - - const panicMsg = "Panic!" - - if funcDidPanic, msg, _ := didPanic(func() { - panic(panicMsg) - }); !funcDidPanic || msg != panicMsg { - t.Error("didPanic should return true, panicMsg") - } - - if funcDidPanic, msg, _ := didPanic(func() { - panic(nil) - }); !funcDidPanic || msg != nil { - t.Error("didPanic should return true, nil") - } - - if funcDidPanic, _, _ := didPanic(func() { - }); funcDidPanic { - t.Error("didPanic should return false") - } - -} - -func TestPanics(t *testing.T) { - - mockT := new(testing.T) - - if !Panics(mockT, func() { - panic("Panic!") - }) { - t.Error("Panics should return true") - } - - if Panics(mockT, func() { - }) { - t.Error("Panics should return false") - } - -} - -func TestPanicsWithValue(t *testing.T) { - - mockT := new(testing.T) - - if !PanicsWithValue(mockT, "Panic!", func() { - panic("Panic!") - }) { - t.Error("PanicsWithValue should return true") - } - - if !PanicsWithValue(mockT, nil, func() { - panic(nil) - }) { - t.Error("PanicsWithValue should return true") - } - - if PanicsWithValue(mockT, "Panic!", func() { - }) { - t.Error("PanicsWithValue should return false") - } - - if PanicsWithValue(mockT, "at the disco", func() { - panic("Panic!") - }) { - t.Error("PanicsWithValue should return false") - } -} - -func TestPanicsWithError(t *testing.T) { - - mockT := new(testing.T) - - if !PanicsWithError(mockT, "panic", func() { - panic(errors.New("panic")) - }) { - t.Error("PanicsWithError should return true") - } - - if PanicsWithError(mockT, "Panic!", func() { - }) { - t.Error("PanicsWithError should return false") - } - - if PanicsWithError(mockT, "at the disco", func() { - panic(errors.New("panic")) - }) { - t.Error("PanicsWithError should return false") - } - - if PanicsWithError(mockT, "Panic!", func() { - panic("panic") - }) { - t.Error("PanicsWithError should return false") - } -} - -func TestNotPanics(t *testing.T) { - - mockT := new(testing.T) - - if !NotPanics(mockT, func() { - }) { - t.Error("NotPanics should return true") - } - - if NotPanics(mockT, func() { - panic("Panic!") - }) { - t.Error("NotPanics should return false") - } - -} - -func TestNoError(t *testing.T) { - - mockT := new(testing.T) - - // start with a nil error - var err error - - True(t, NoError(mockT, err), "NoError should return True for nil arg") - - // now set an error - err = errors.New("some error") - - False(t, NoError(mockT, err), "NoError with error should return False") - - // returning an empty error interface - err = func() error { - var err *customError - return err - }() - - if err == nil { // err is not nil here! - t.Errorf("Error should be nil due to empty interface: %s", err) - } - - False(t, NoError(mockT, err), "NoError should fail with empty error interface") -} - -type customError struct{} - -func (*customError) Error() string { return "fail" } - -func TestError(t *testing.T) { - - mockT := new(testing.T) - - // start with a nil error - var err error - - False(t, Error(mockT, err), "Error should return False for nil arg") - - // now set an error - err = errors.New("some error") - - True(t, Error(mockT, err), "Error with error should return True") - - // go vet check - True(t, Errorf(mockT, err, "example with %s", "formatted message"), "Errorf with error should rturn True") - - // returning an empty error interface - err = func() error { - var err *customError - return err - }() - - if err == nil { // err is not nil here! - t.Errorf("Error should be nil due to empty interface: %s", err) - } - - True(t, Error(mockT, err), "Error should pass with empty error interface") -} - -func TestEqualError(t *testing.T) { - mockT := new(testing.T) - - // start with a nil error - var err error - False(t, EqualError(mockT, err, ""), - "EqualError should return false for nil arg") - - // now set an error - err = errors.New("some error") - False(t, EqualError(mockT, err, "Not some error"), - "EqualError should return false for different error string") - True(t, EqualError(mockT, err, "some error"), - "EqualError should return true") -} - -func TestErrorContains(t *testing.T) { - mockT := new(testing.T) - - // start with a nil error - var err error - False(t, ErrorContains(mockT, err, ""), - "ErrorContains should return false for nil arg") - - // now set an error - err = errors.New("some error: another error") - False(t, ErrorContains(mockT, err, "bad error"), - "ErrorContains should return false for different error string") - True(t, ErrorContains(mockT, err, "some error"), - "ErrorContains should return true") - True(t, ErrorContains(mockT, err, "another error"), - "ErrorContains should return true") -} - -func Test_isEmpty(t *testing.T) { - - chWithValue := make(chan struct{}, 1) - chWithValue <- struct{}{} - - True(t, isEmpty("")) - True(t, isEmpty(nil)) - True(t, isEmpty([]string{})) - True(t, isEmpty(0)) - True(t, isEmpty(int32(0))) - True(t, isEmpty(int64(0))) - True(t, isEmpty(false)) - True(t, isEmpty(map[string]string{})) - True(t, isEmpty(new(time.Time))) - True(t, isEmpty(time.Time{})) - True(t, isEmpty(make(chan struct{}))) - True(t, isEmpty([1]int{})) - False(t, isEmpty("something")) - False(t, isEmpty(errors.New("something"))) - False(t, isEmpty([]string{"something"})) - False(t, isEmpty(1)) - False(t, isEmpty(true)) - False(t, isEmpty(map[string]string{"Hello": "World"})) - False(t, isEmpty(chWithValue)) - False(t, isEmpty([1]int{42})) -} - -func TestEmpty(t *testing.T) { - - mockT := new(testing.T) - chWithValue := make(chan struct{}, 1) - chWithValue <- struct{}{} - var tiP *time.Time - var tiNP time.Time - var s *string - var f *os.File - sP := &s - x := 1 - xP := &x - - type TString string - type TStruct struct { - x int - } - - True(t, Empty(mockT, ""), "Empty string is empty") - True(t, Empty(mockT, nil), "Nil is empty") - True(t, Empty(mockT, []string{}), "Empty string array is empty") - True(t, Empty(mockT, 0), "Zero int value is empty") - True(t, Empty(mockT, false), "False value is empty") - True(t, Empty(mockT, make(chan struct{})), "Channel without values is empty") - True(t, Empty(mockT, s), "Nil string pointer is empty") - True(t, Empty(mockT, f), "Nil os.File pointer is empty") - True(t, Empty(mockT, tiP), "Nil time.Time pointer is empty") - True(t, Empty(mockT, tiNP), "time.Time is empty") - True(t, Empty(mockT, TStruct{}), "struct with zero values is empty") - True(t, Empty(mockT, TString("")), "empty aliased string is empty") - True(t, Empty(mockT, sP), "ptr to nil value is empty") - True(t, Empty(mockT, [1]int{}), "array is state") - - False(t, Empty(mockT, "something"), "Non Empty string is not empty") - False(t, Empty(mockT, errors.New("something")), "Non nil object is not empty") - False(t, Empty(mockT, []string{"something"}), "Non empty string array is not empty") - False(t, Empty(mockT, 1), "Non-zero int value is not empty") - False(t, Empty(mockT, true), "True value is not empty") - False(t, Empty(mockT, chWithValue), "Channel with values is not empty") - False(t, Empty(mockT, TStruct{x: 1}), "struct with initialized values is empty") - False(t, Empty(mockT, TString("abc")), "non-empty aliased string is empty") - False(t, Empty(mockT, xP), "ptr to non-nil value is not empty") - False(t, Empty(mockT, [1]int{42}), "array is not state") -} - -func TestNotEmpty(t *testing.T) { - - mockT := new(testing.T) - chWithValue := make(chan struct{}, 1) - chWithValue <- struct{}{} - - False(t, NotEmpty(mockT, ""), "Empty string is empty") - False(t, NotEmpty(mockT, nil), "Nil is empty") - False(t, NotEmpty(mockT, []string{}), "Empty string array is empty") - False(t, NotEmpty(mockT, 0), "Zero int value is empty") - False(t, NotEmpty(mockT, false), "False value is empty") - False(t, NotEmpty(mockT, make(chan struct{})), "Channel without values is empty") - False(t, NotEmpty(mockT, [1]int{}), "array is state") - - True(t, NotEmpty(mockT, "something"), "Non Empty string is not empty") - True(t, NotEmpty(mockT, errors.New("something")), "Non nil object is not empty") - True(t, NotEmpty(mockT, []string{"something"}), "Non empty string array is not empty") - True(t, NotEmpty(mockT, 1), "Non-zero int value is not empty") - True(t, NotEmpty(mockT, true), "True value is not empty") - True(t, NotEmpty(mockT, chWithValue), "Channel with values is not empty") - True(t, NotEmpty(mockT, [1]int{42}), "array is not state") -} - -func Test_getLen(t *testing.T) { - falseCases := []interface{}{ - nil, - 0, - true, - false, - 'A', - struct{}{}, - } - for _, v := range falseCases { - ok, l := getLen(v) - False(t, ok, "Expected getLen fail to get length of %#v", v) - Equal(t, 0, l, "getLen should return 0 for %#v", v) - } - - ch := make(chan int, 5) - ch <- 1 - ch <- 2 - ch <- 3 - trueCases := []struct { - v interface{} - l int - }{ - {[]int{1, 2, 3}, 3}, - {[...]int{1, 2, 3}, 3}, - {"ABC", 3}, - {map[int]int{1: 2, 2: 4, 3: 6}, 3}, - {ch, 3}, - - {[]int{}, 0}, - {map[int]int{}, 0}, - {make(chan int), 0}, - - {[]int(nil), 0}, - {map[int]int(nil), 0}, - {(chan int)(nil), 0}, - } - - for _, c := range trueCases { - ok, l := getLen(c.v) - True(t, ok, "Expected getLen success to get length of %#v", c.v) - Equal(t, c.l, l) - } -} - -func TestLen(t *testing.T) { - mockT := new(testing.T) - - False(t, Len(mockT, nil, 0), "nil does not have length") - False(t, Len(mockT, 0, 0), "int does not have length") - False(t, Len(mockT, true, 0), "true does not have length") - False(t, Len(mockT, false, 0), "false does not have length") - False(t, Len(mockT, 'A', 0), "Rune does not have length") - False(t, Len(mockT, struct{}{}, 0), "Struct does not have length") - - ch := make(chan int, 5) - ch <- 1 - ch <- 2 - ch <- 3 - - cases := []struct { - v interface{} - l int - }{ - {[]int{1, 2, 3}, 3}, - {[...]int{1, 2, 3}, 3}, - {"ABC", 3}, - {map[int]int{1: 2, 2: 4, 3: 6}, 3}, - {ch, 3}, - - {[]int{}, 0}, - {map[int]int{}, 0}, - {make(chan int), 0}, - - {[]int(nil), 0}, - {map[int]int(nil), 0}, - {(chan int)(nil), 0}, - } - - for _, c := range cases { - True(t, Len(mockT, c.v, c.l), "%#v have %d items", c.v, c.l) - } - - cases = []struct { - v interface{} - l int - }{ - {[]int{1, 2, 3}, 4}, - {[...]int{1, 2, 3}, 2}, - {"ABC", 2}, - {map[int]int{1: 2, 2: 4, 3: 6}, 4}, - {ch, 2}, - - {[]int{}, 1}, - {map[int]int{}, 1}, - {make(chan int), 1}, - - {[]int(nil), 1}, - {map[int]int(nil), 1}, - {(chan int)(nil), 1}, - } - - for _, c := range cases { - False(t, Len(mockT, c.v, c.l), "%#v have %d items", c.v, c.l) - } -} - -func TestWithinDuration(t *testing.T) { - - mockT := new(testing.T) - a := time.Now() - b := a.Add(10 * time.Second) - - True(t, WithinDuration(mockT, a, b, 10*time.Second), "A 10s difference is within a 10s time difference") - True(t, WithinDuration(mockT, b, a, 10*time.Second), "A 10s difference is within a 10s time difference") - - False(t, WithinDuration(mockT, a, b, 9*time.Second), "A 10s difference is not within a 9s time difference") - False(t, WithinDuration(mockT, b, a, 9*time.Second), "A 10s difference is not within a 9s time difference") - - False(t, WithinDuration(mockT, a, b, -9*time.Second), "A 10s difference is not within a 9s time difference") - False(t, WithinDuration(mockT, b, a, -9*time.Second), "A 10s difference is not within a 9s time difference") - - False(t, WithinDuration(mockT, a, b, -11*time.Second), "A 10s difference is not within a 9s time difference") - False(t, WithinDuration(mockT, b, a, -11*time.Second), "A 10s difference is not within a 9s time difference") -} - -func TestWithinRange(t *testing.T) { - - mockT := new(testing.T) - n := time.Now() - s := n.Add(-time.Second) - e := n.Add(time.Second) - - True(t, WithinRange(mockT, n, n, n), "Exact same actual, start, and end values return true") - - True(t, WithinRange(mockT, n, s, e), "Time in range is within the time range") - True(t, WithinRange(mockT, s, s, e), "The start time is within the time range") - True(t, WithinRange(mockT, e, s, e), "The end time is within the time range") - - False(t, WithinRange(mockT, s.Add(-time.Nanosecond), s, e, "Just before the start time is not within the time range")) - False(t, WithinRange(mockT, e.Add(time.Nanosecond), s, e, "Just after the end time is not within the time range")) - - False(t, WithinRange(mockT, n, e, s, "Just after the end time is not within the time range")) -} - -func TestInDelta(t *testing.T) { - mockT := new(testing.T) - - True(t, InDelta(mockT, 1.001, 1, 0.01), "|1.001 - 1| <= 0.01") - True(t, InDelta(mockT, 1, 1.001, 0.01), "|1 - 1.001| <= 0.01") - True(t, InDelta(mockT, 1, 2, 1), "|1 - 2| <= 1") - False(t, InDelta(mockT, 1, 2, 0.5), "Expected |1 - 2| <= 0.5 to fail") - False(t, InDelta(mockT, 2, 1, 0.5), "Expected |2 - 1| <= 0.5 to fail") - False(t, InDelta(mockT, "", nil, 1), "Expected non numerals to fail") - False(t, InDelta(mockT, 42, math.NaN(), 0.01), "Expected NaN for actual to fail") - False(t, InDelta(mockT, math.NaN(), 42, 0.01), "Expected NaN for expected to fail") - True(t, InDelta(mockT, math.NaN(), math.NaN(), 0.01), "Expected NaN for both to pass") - - cases := []struct { - a, b interface{} - delta float64 - }{ - {uint(2), uint(1), 1}, - {uint8(2), uint8(1), 1}, - {uint16(2), uint16(1), 1}, - {uint32(2), uint32(1), 1}, - {uint64(2), uint64(1), 1}, - - {int(2), int(1), 1}, - {int8(2), int8(1), 1}, - {int16(2), int16(1), 1}, - {int32(2), int32(1), 1}, - {int64(2), int64(1), 1}, - - {float32(2), float32(1), 1}, - {float64(2), float64(1), 1}, - } - - for _, tc := range cases { - True(t, InDelta(mockT, tc.a, tc.b, tc.delta), "Expected |%V - %V| <= %v", tc.a, tc.b, tc.delta) - } -} - -func TestInDeltaSlice(t *testing.T) { - mockT := new(testing.T) - - True(t, InDeltaSlice(mockT, - []float64{1.001, math.NaN(), 0.999}, - []float64{1, math.NaN(), 1}, - 0.1), "{1.001, NaN, 0.009} is element-wise close to {1, NaN, 1} in delta=0.1") - - True(t, InDeltaSlice(mockT, - []float64{1, math.NaN(), 2}, - []float64{0, math.NaN(), 3}, - 1), "{1, NaN, 2} is element-wise close to {0, NaN, 3} in delta=1") - - False(t, InDeltaSlice(mockT, - []float64{1, math.NaN(), 2}, - []float64{0, math.NaN(), 3}, - 0.1), "{1, NaN, 2} is not element-wise close to {0, NaN, 3} in delta=0.1") - - False(t, InDeltaSlice(mockT, "", nil, 1), "Expected non numeral slices to fail") -} - -func TestInDeltaMapValues(t *testing.T) { - mockT := new(testing.T) - - for _, tc := range []struct { - title string - expect interface{} - actual interface{} - f func(TestingT, bool, ...interface{}) bool - delta float64 - }{ - { - title: "Within delta", - expect: map[string]float64{ - "foo": 1.0, - "bar": 2.0, - "baz": math.NaN(), - }, - actual: map[string]float64{ - "foo": 1.01, - "bar": 1.99, - "baz": math.NaN(), - }, - delta: 0.1, - f: True, - }, - { - title: "Within delta", - expect: map[int]float64{ - 1: 1.0, - 2: 2.0, - }, - actual: map[int]float64{ - 1: 1.0, - 2: 1.99, - }, - delta: 0.1, - f: True, - }, - { - title: "Different number of keys", - expect: map[int]float64{ - 1: 1.0, - 2: 2.0, - }, - actual: map[int]float64{ - 1: 1.0, - }, - delta: 0.1, - f: False, - }, - { - title: "Within delta with zero value", - expect: map[string]float64{ - "zero": 0, - }, - actual: map[string]float64{ - "zero": 0, - }, - delta: 0.1, - f: True, - }, - { - title: "With missing key with zero value", - expect: map[string]float64{ - "zero": 0, - "foo": 0, - }, - actual: map[string]float64{ - "zero": 0, - "bar": 0, - }, - f: False, - }, - } { - tc.f(t, InDeltaMapValues(mockT, tc.expect, tc.actual, tc.delta), tc.title+"\n"+diff(tc.expect, tc.actual)) - } -} - -func TestInEpsilon(t *testing.T) { - mockT := new(testing.T) - - cases := []struct { - a, b interface{} - epsilon float64 - }{ - {uint8(2), uint16(2), .001}, - {2.1, 2.2, 0.1}, - {2.2, 2.1, 0.1}, - {-2.1, -2.2, 0.1}, - {-2.2, -2.1, 0.1}, - {uint64(100), uint8(101), 0.01}, - {0.1, -0.1, 2}, - {0.1, 0, 2}, - {math.NaN(), math.NaN(), 1}, - {time.Second, time.Second + time.Millisecond, 0.002}, - } - - for _, tc := range cases { - True(t, InEpsilon(t, tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon), "test: %q", tc) - } - - cases = []struct { - a, b interface{} - epsilon float64 - }{ - {uint8(2), int16(-2), .001}, - {uint64(100), uint8(102), 0.01}, - {2.1, 2.2, 0.001}, - {2.2, 2.1, 0.001}, - {2.1, -2.2, 1}, - {2.1, "bla-bla", 0}, - {0.1, -0.1, 1.99}, - {0, 0.1, 2}, // expected must be different to zero - {time.Second, time.Second + 10*time.Millisecond, 0.002}, - {math.NaN(), 0, 1}, - {0, math.NaN(), 1}, - {0, 0, math.NaN()}, - } - - for _, tc := range cases { - False(t, InEpsilon(mockT, tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon)) - } - -} - -func TestInEpsilonSlice(t *testing.T) { - mockT := new(testing.T) - - True(t, InEpsilonSlice(mockT, - []float64{2.2, math.NaN(), 2.0}, - []float64{2.1, math.NaN(), 2.1}, - 0.06), "{2.2, NaN, 2.0} is element-wise close to {2.1, NaN, 2.1} in espilon=0.06") - - False(t, InEpsilonSlice(mockT, - []float64{2.2, 2.0}, - []float64{2.1, 2.1}, - 0.04), "{2.2, 2.0} is not element-wise close to {2.1, 2.1} in espilon=0.04") - - False(t, InEpsilonSlice(mockT, "", nil, 1), "Expected non numeral slices to fail") -} - -func TestRegexp(t *testing.T) { - mockT := new(testing.T) - - cases := []struct { - rx, str string - }{ - {"^start", "start of the line"}, - {"end$", "in the end"}, - {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12.34"}, - } - - for _, tc := range cases { - True(t, Regexp(mockT, tc.rx, tc.str)) - True(t, Regexp(mockT, regexp.MustCompile(tc.rx), tc.str)) - False(t, NotRegexp(mockT, tc.rx, tc.str)) - False(t, NotRegexp(mockT, regexp.MustCompile(tc.rx), tc.str)) - } - - cases = []struct { - rx, str string - }{ - {"^asdfastart", "Not the start of the line"}, - {"end$", "in the end."}, - {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12a.34"}, - } - - for _, tc := range cases { - False(t, Regexp(mockT, tc.rx, tc.str), "Expected \"%s\" to not match \"%s\"", tc.rx, tc.str) - False(t, Regexp(mockT, regexp.MustCompile(tc.rx), tc.str)) - True(t, NotRegexp(mockT, tc.rx, tc.str)) - True(t, NotRegexp(mockT, regexp.MustCompile(tc.rx), tc.str)) - } -} - -func testAutogeneratedFunction() { - defer func() { - if err := recover(); err == nil { - panic("did not panic") - } - CallerInfo() - }() - t := struct { - io.Closer - }{} - c := t - c.Close() -} - -func TestCallerInfoWithAutogeneratedFunctions(t *testing.T) { - NotPanics(t, func() { - testAutogeneratedFunction() - }) -} - -func TestZero(t *testing.T) { - mockT := new(testing.T) - - for _, test := range zeros { - True(t, Zero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test))) - } - - for _, test := range nonZeros { - False(t, Zero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test))) - } -} - -func TestNotZero(t *testing.T) { - mockT := new(testing.T) - - for _, test := range zeros { - False(t, NotZero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test))) - } - - for _, test := range nonZeros { - True(t, NotZero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test))) - } -} - -func TestFileExists(t *testing.T) { - mockT := new(testing.T) - True(t, FileExists(mockT, "assertions.go")) - - mockT = new(testing.T) - False(t, FileExists(mockT, "random_file")) - - mockT = new(testing.T) - False(t, FileExists(mockT, "../_codegen")) - - var tempFiles []string - - link, err := getTempSymlinkPath("assertions.go") - if err != nil { - t.Fatal("could not create temp symlink, err:", err) - } - tempFiles = append(tempFiles, link) - mockT = new(testing.T) - True(t, FileExists(mockT, link)) - - link, err = getTempSymlinkPath("non_existent_file") - if err != nil { - t.Fatal("could not create temp symlink, err:", err) - } - tempFiles = append(tempFiles, link) - mockT = new(testing.T) - True(t, FileExists(mockT, link)) - - errs := cleanUpTempFiles(tempFiles) - if len(errs) > 0 { - t.Fatal("could not clean up temporary files") - } -} - -func TestNoFileExists(t *testing.T) { - mockT := new(testing.T) - False(t, NoFileExists(mockT, "assertions.go")) - - mockT = new(testing.T) - True(t, NoFileExists(mockT, "non_existent_file")) - - mockT = new(testing.T) - True(t, NoFileExists(mockT, "../_codegen")) - - var tempFiles []string - - link, err := getTempSymlinkPath("assertions.go") - if err != nil { - t.Fatal("could not create temp symlink, err:", err) - } - tempFiles = append(tempFiles, link) - mockT = new(testing.T) - False(t, NoFileExists(mockT, link)) - - link, err = getTempSymlinkPath("non_existent_file") - if err != nil { - t.Fatal("could not create temp symlink, err:", err) - } - tempFiles = append(tempFiles, link) - mockT = new(testing.T) - False(t, NoFileExists(mockT, link)) - - errs := cleanUpTempFiles(tempFiles) - if len(errs) > 0 { - t.Fatal("could not clean up temporary files") - } -} - -func getTempSymlinkPath(file string) (string, error) { - link := file + "_symlink" - err := os.Symlink(file, link) - return link, err -} - -func cleanUpTempFiles(paths []string) []error { - var res []error - for _, path := range paths { - err := os.Remove(path) - if err != nil { - res = append(res, err) - } - } - return res -} - -func TestDirExists(t *testing.T) { - mockT := new(testing.T) - False(t, DirExists(mockT, "assertions.go")) - - mockT = new(testing.T) - False(t, DirExists(mockT, "non_existent_dir")) - - mockT = new(testing.T) - True(t, DirExists(mockT, "../_codegen")) - - var tempFiles []string - - link, err := getTempSymlinkPath("assertions.go") - if err != nil { - t.Fatal("could not create temp symlink, err:", err) - } - tempFiles = append(tempFiles, link) - mockT = new(testing.T) - False(t, DirExists(mockT, link)) - - link, err = getTempSymlinkPath("non_existent_dir") - if err != nil { - t.Fatal("could not create temp symlink, err:", err) - } - tempFiles = append(tempFiles, link) - mockT = new(testing.T) - False(t, DirExists(mockT, link)) - - errs := cleanUpTempFiles(tempFiles) - if len(errs) > 0 { - t.Fatal("could not clean up temporary files") - } -} - -func TestNoDirExists(t *testing.T) { - mockT := new(testing.T) - True(t, NoDirExists(mockT, "assertions.go")) - - mockT = new(testing.T) - True(t, NoDirExists(mockT, "non_existent_dir")) - - mockT = new(testing.T) - False(t, NoDirExists(mockT, "../_codegen")) - - var tempFiles []string - - link, err := getTempSymlinkPath("assertions.go") - if err != nil { - t.Fatal("could not create temp symlink, err:", err) - } - tempFiles = append(tempFiles, link) - mockT = new(testing.T) - True(t, NoDirExists(mockT, link)) - - link, err = getTempSymlinkPath("non_existent_dir") - if err != nil { - t.Fatal("could not create temp symlink, err:", err) - } - tempFiles = append(tempFiles, link) - mockT = new(testing.T) - True(t, NoDirExists(mockT, link)) - - errs := cleanUpTempFiles(tempFiles) - if len(errs) > 0 { - t.Fatal("could not clean up temporary files") - } -} - -func TestJSONEq_EqualSONString(t *testing.T) { - mockT := new(testing.T) - True(t, JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`)) -} - -func TestJSONEq_EquivalentButNotEqual(t *testing.T) { - mockT := new(testing.T) - True(t, JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)) -} - -func TestJSONEq_HashOfArraysAndHashes(t *testing.T) { - mockT := new(testing.T) - True(t, JSONEq(mockT, "{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}", - "{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}")) -} - -func TestJSONEq_Array(t *testing.T) { - mockT := new(testing.T) - True(t, JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`)) -} - -func TestJSONEq_HashAndArrayNotEquivalent(t *testing.T) { - mockT := new(testing.T) - False(t, JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`)) -} - -func TestJSONEq_HashesNotEquivalent(t *testing.T) { - mockT := new(testing.T) - False(t, JSONEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)) -} - -func TestJSONEq_ActualIsNotJSON(t *testing.T) { - mockT := new(testing.T) - False(t, JSONEq(mockT, `{"foo": "bar"}`, "Not JSON")) -} - -func TestJSONEq_ExpectedIsNotJSON(t *testing.T) { - mockT := new(testing.T) - False(t, JSONEq(mockT, "Not JSON", `{"foo": "bar", "hello": "world"}`)) -} - -func TestJSONEq_ExpectedAndActualNotJSON(t *testing.T) { - mockT := new(testing.T) - False(t, JSONEq(mockT, "Not JSON", "Not JSON")) -} - -func TestJSONEq_ArraysOfDifferentOrder(t *testing.T) { - mockT := new(testing.T) - False(t, JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`)) -} - -func TestYAMLEq_EqualYAMLString(t *testing.T) { - mockT := new(testing.T) - True(t, YAMLEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`)) -} - -func TestYAMLEq_EquivalentButNotEqual(t *testing.T) { - mockT := new(testing.T) - True(t, YAMLEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)) -} - -func TestYAMLEq_HashOfArraysAndHashes(t *testing.T) { - mockT := new(testing.T) - expected := ` -numeric: 1.5 -array: - - foo: bar - - 1 - - "string" - - ["nested", "array", 5.5] -hash: - nested: hash - nested_slice: [this, is, nested] -string: "foo" -` - - actual := ` -numeric: 1.5 -hash: - nested: hash - nested_slice: [this, is, nested] -string: "foo" -array: - - foo: bar - - 1 - - "string" - - ["nested", "array", 5.5] -` - True(t, YAMLEq(mockT, expected, actual)) -} - -func TestYAMLEq_Array(t *testing.T) { - mockT := new(testing.T) - True(t, YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`)) -} - -func TestYAMLEq_HashAndArrayNotEquivalent(t *testing.T) { - mockT := new(testing.T) - False(t, YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`)) -} - -func TestYAMLEq_HashesNotEquivalent(t *testing.T) { - mockT := new(testing.T) - False(t, YAMLEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)) -} - -func TestYAMLEq_ActualIsSimpleString(t *testing.T) { - mockT := new(testing.T) - False(t, YAMLEq(mockT, `{"foo": "bar"}`, "Simple String")) -} - -func TestYAMLEq_ExpectedIsSimpleString(t *testing.T) { - mockT := new(testing.T) - False(t, YAMLEq(mockT, "Simple String", `{"foo": "bar", "hello": "world"}`)) -} - -func TestYAMLEq_ExpectedAndActualSimpleString(t *testing.T) { - mockT := new(testing.T) - True(t, YAMLEq(mockT, "Simple String", "Simple String")) -} - -func TestYAMLEq_ArraysOfDifferentOrder(t *testing.T) { - mockT := new(testing.T) - False(t, YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`)) -} - -type diffTestingStruct struct { - A string - B int -} - -func (d *diffTestingStruct) String() string { - return d.A -} - -func TestDiff(t *testing.T) { - expected := ` - -Diff: ---- Expected -+++ Actual -@@ -1,3 +1,3 @@ - (struct { foo string }) { -- foo: (string) (len=5) "hello" -+ foo: (string) (len=3) "bar" - } -` - actual := diff( - struct{ foo string }{"hello"}, - struct{ foo string }{"bar"}, - ) - Equal(t, expected, actual) - - expected = ` - -Diff: ---- Expected -+++ Actual -@@ -2,5 +2,5 @@ - (int) 1, -- (int) 2, - (int) 3, -- (int) 4 -+ (int) 5, -+ (int) 7 - } -` - actual = diff( - []int{1, 2, 3, 4}, - []int{1, 3, 5, 7}, - ) - Equal(t, expected, actual) - - expected = ` - -Diff: ---- Expected -+++ Actual -@@ -2,4 +2,4 @@ - (int) 1, -- (int) 2, -- (int) 3 -+ (int) 3, -+ (int) 5 - } -` - actual = diff( - []int{1, 2, 3, 4}[0:3], - []int{1, 3, 5, 7}[0:3], - ) - Equal(t, expected, actual) - - expected = ` - -Diff: ---- Expected -+++ Actual -@@ -1,6 +1,6 @@ - (map[string]int) (len=4) { -- (string) (len=4) "four": (int) 4, -+ (string) (len=4) "five": (int) 5, - (string) (len=3) "one": (int) 1, -- (string) (len=5) "three": (int) 3, -- (string) (len=3) "two": (int) 2 -+ (string) (len=5) "seven": (int) 7, -+ (string) (len=5) "three": (int) 3 - } -` - - actual = diff( - map[string]int{"one": 1, "two": 2, "three": 3, "four": 4}, - map[string]int{"one": 1, "three": 3, "five": 5, "seven": 7}, - ) - Equal(t, expected, actual) - - expected = ` - -Diff: ---- Expected -+++ Actual -@@ -1,3 +1,3 @@ - (*errors.errorString)({ -- s: (string) (len=19) "some expected error" -+ s: (string) (len=12) "actual error" - }) -` - - actual = diff( - errors.New("some expected error"), - errors.New("actual error"), - ) - Equal(t, expected, actual) - - expected = ` - -Diff: ---- Expected -+++ Actual -@@ -2,3 +2,3 @@ - A: (string) (len=11) "some string", -- B: (int) 10 -+ B: (int) 15 - } -` - - actual = diff( - diffTestingStruct{A: "some string", B: 10}, - diffTestingStruct{A: "some string", B: 15}, - ) - Equal(t, expected, actual) - - expected = ` - -Diff: ---- Expected -+++ Actual -@@ -1,2 +1,2 @@ --(time.Time) 2020-09-24 00:00:00 +0000 UTC -+(time.Time) 2020-09-25 00:00:00 +0000 UTC - -` - - actual = diff( - time.Date(2020, 9, 24, 0, 0, 0, 0, time.UTC), - time.Date(2020, 9, 25, 0, 0, 0, 0, time.UTC), - ) - Equal(t, expected, actual) -} - -func TestTimeEqualityErrorFormatting(t *testing.T) { - mockT := new(mockTestingT) - - Equal(mockT, time.Second*2, time.Millisecond) - - expectedErr := "\\s+Error Trace:\\s+Error:\\s+Not equal:\\s+\n\\s+expected: 2s\n\\s+actual\\s+: 1ms\n" - Regexp(t, regexp.MustCompile(expectedErr), mockT.errorString()) -} - -func TestDiffEmptyCases(t *testing.T) { - Equal(t, "", diff(nil, nil)) - Equal(t, "", diff(struct{ foo string }{}, nil)) - Equal(t, "", diff(nil, struct{ foo string }{})) - Equal(t, "", diff(1, 2)) - Equal(t, "", diff(1, 2)) - Equal(t, "", diff([]int{1}, []bool{true})) -} - -// Ensure there are no data races -func TestDiffRace(t *testing.T) { - t.Parallel() - - expected := map[string]string{ - "a": "A", - "b": "B", - "c": "C", - } - - actual := map[string]string{ - "d": "D", - "e": "E", - "f": "F", - } - - // run diffs in parallel simulating tests with t.Parallel() - numRoutines := 10 - rChans := make([]chan string, numRoutines) - for idx := range rChans { - rChans[idx] = make(chan string) - go func(ch chan string) { - defer close(ch) - ch <- diff(expected, actual) - }(rChans[idx]) - } - - for _, ch := range rChans { - for msg := range ch { - NotZero(t, msg) // dummy assert - } - } -} - -type mockTestingT struct { - errorFmt string - args []interface{} -} - -func (m *mockTestingT) errorString() string { - return fmt.Sprintf(m.errorFmt, m.args...) -} - -func (m *mockTestingT) Errorf(format string, args ...interface{}) { - m.errorFmt = format - m.args = args -} - -func TestFailNowWithPlainTestingT(t *testing.T) { - mockT := &mockTestingT{} - - Panics(t, func() { - FailNow(mockT, "failed") - }, "should panic since mockT is missing FailNow()") -} - -type mockFailNowTestingT struct { -} - -func (m *mockFailNowTestingT) Errorf(format string, args ...interface{}) {} - -func (m *mockFailNowTestingT) FailNow() {} - -func TestFailNowWithFullTestingT(t *testing.T) { - mockT := &mockFailNowTestingT{} - - NotPanics(t, func() { - FailNow(mockT, "failed") - }, "should call mockT.FailNow() rather than panicking") -} - -func TestBytesEqual(t *testing.T) { - var cases = []struct { - a, b []byte - }{ - {make([]byte, 2), make([]byte, 2)}, - {make([]byte, 2), make([]byte, 2, 3)}, - {nil, make([]byte, 0)}, - } - for i, c := range cases { - Equal(t, reflect.DeepEqual(c.a, c.b), ObjectsAreEqual(c.a, c.b), "case %d failed", i+1) - } -} - -func BenchmarkBytesEqual(b *testing.B) { - const size = 1024 * 8 - s := make([]byte, size) - for i := range s { - s[i] = byte(i % 255) - } - s2 := make([]byte, size) - copy(s2, s) - - mockT := &mockFailNowTestingT{} - b.ResetTimer() - for i := 0; i < b.N; i++ { - Equal(mockT, s, s2) - } -} - -func BenchmarkNotNil(b *testing.B) { - for i := 0; i < b.N; i++ { - NotNil(b, b) - } -} - -func ExampleComparisonAssertionFunc() { - t := &testing.T{} // provided by test - - adder := func(x, y int) int { - return x + y - } - - type args struct { - x int - y int - } - - tests := []struct { - name string - args args - expect int - assertion ComparisonAssertionFunc - }{ - {"2+2=4", args{2, 2}, 4, Equal}, - {"2+2!=5", args{2, 2}, 5, NotEqual}, - {"2+3==5", args{2, 3}, 5, Exactly}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.assertion(t, tt.expect, adder(tt.args.x, tt.args.y)) - }) - } -} - -func TestComparisonAssertionFunc(t *testing.T) { - type iface interface { - Name() string - } - - tests := []struct { - name string - expect interface{} - got interface{} - assertion ComparisonAssertionFunc - }{ - {"implements", (*iface)(nil), t, Implements}, - {"isType", (*testing.T)(nil), t, IsType}, - {"equal", t, t, Equal}, - {"equalValues", t, t, EqualValues}, - {"notEqualValues", t, nil, NotEqualValues}, - {"exactly", t, t, Exactly}, - {"notEqual", t, nil, NotEqual}, - {"notContains", []int{1, 2, 3}, 4, NotContains}, - {"subset", []int{1, 2, 3, 4}, []int{2, 3}, Subset}, - {"notSubset", []int{1, 2, 3, 4}, []int{0, 3}, NotSubset}, - {"elementsMatch", []byte("abc"), []byte("bac"), ElementsMatch}, - {"regexp", "^t.*y$", "testify", Regexp}, - {"notRegexp", "^t.*y$", "Testify", NotRegexp}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.assertion(t, tt.expect, tt.got) - }) - } -} - -func ExampleValueAssertionFunc() { - t := &testing.T{} // provided by test - - dumbParse := func(input string) interface{} { - var x interface{} - _ = json.Unmarshal([]byte(input), &x) - return x - } - - tests := []struct { - name string - arg string - assertion ValueAssertionFunc - }{ - {"true is not nil", "true", NotNil}, - {"empty string is nil", "", Nil}, - {"zero is not nil", "0", NotNil}, - {"zero is zero", "0", Zero}, - {"false is zero", "false", Zero}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.assertion(t, dumbParse(tt.arg)) - }) - } -} - -func TestValueAssertionFunc(t *testing.T) { - tests := []struct { - name string - value interface{} - assertion ValueAssertionFunc - }{ - {"notNil", true, NotNil}, - {"nil", nil, Nil}, - {"empty", []int{}, Empty}, - {"notEmpty", []int{1}, NotEmpty}, - {"zero", false, Zero}, - {"notZero", 42, NotZero}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.assertion(t, tt.value) - }) - } -} - -func ExampleBoolAssertionFunc() { - t := &testing.T{} // provided by test - - isOkay := func(x int) bool { - return x >= 42 - } - - tests := []struct { - name string - arg int - assertion BoolAssertionFunc - }{ - {"-1 is bad", -1, False}, - {"42 is good", 42, True}, - {"41 is bad", 41, False}, - {"45 is cool", 45, True}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.assertion(t, isOkay(tt.arg)) - }) - } -} - -func TestBoolAssertionFunc(t *testing.T) { - tests := []struct { - name string - value bool - assertion BoolAssertionFunc - }{ - {"true", true, True}, - {"false", false, False}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.assertion(t, tt.value) - }) - } -} - -func ExampleErrorAssertionFunc() { - t := &testing.T{} // provided by test - - dumbParseNum := func(input string, v interface{}) error { - return json.Unmarshal([]byte(input), v) - } - - tests := []struct { - name string - arg string - assertion ErrorAssertionFunc - }{ - {"1.2 is number", "1.2", NoError}, - {"1.2.3 not number", "1.2.3", Error}, - {"true is not number", "true", Error}, - {"3 is number", "3", NoError}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - var x float64 - tt.assertion(t, dumbParseNum(tt.arg, &x)) - }) - } -} - -func TestErrorAssertionFunc(t *testing.T) { - tests := []struct { - name string - err error - assertion ErrorAssertionFunc - }{ - {"noError", nil, NoError}, - {"error", errors.New("whoops"), Error}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.assertion(t, tt.err) - }) - } -} - -func TestEventuallyFalse(t *testing.T) { - mockT := new(testing.T) - - condition := func() bool { - return false - } - - False(t, Eventually(mockT, condition, 100*time.Millisecond, 20*time.Millisecond)) -} - -func TestEventuallyTrue(t *testing.T) { - state := 0 - condition := func() bool { - defer func() { - state += 1 - }() - return state == 2 - } - - True(t, Eventually(t, condition, 100*time.Millisecond, 20*time.Millisecond)) -} - -func TestNeverFalse(t *testing.T) { - condition := func() bool { - return false - } - - True(t, Never(t, condition, 100*time.Millisecond, 20*time.Millisecond)) -} - -func TestNeverTrue(t *testing.T) { - mockT := new(testing.T) - state := 0 - condition := func() bool { - defer func() { - state = state + 1 - }() - return state == 2 - } - - False(t, Never(mockT, condition, 100*time.Millisecond, 20*time.Millisecond)) -} - -func TestEventuallyIssue805(t *testing.T) { - mockT := new(testing.T) - - NotPanics(t, func() { - condition := func() bool { <-time.After(time.Millisecond); return true } - False(t, Eventually(mockT, condition, time.Millisecond, time.Microsecond)) - }) -} - -func Test_validateEqualArgs(t *testing.T) { - if validateEqualArgs(func() {}, func() {}) == nil { - t.Error("non-nil functions should error") - } - - if validateEqualArgs(func() {}, func() {}) == nil { - t.Error("non-nil functions should error") - } - - if validateEqualArgs(nil, nil) != nil { - t.Error("nil functions are equal") - } -} - -func Test_truncatingFormat(t *testing.T) { - - original := strings.Repeat("a", bufio.MaxScanTokenSize-102) - result := truncatingFormat(original) - Equal(t, fmt.Sprintf("%#v", original), result, "string should not be truncated") - - original = original + "x" - result = truncatingFormat(original) - NotEqual(t, fmt.Sprintf("%#v", original), result, "string should have been truncated.") - - if !strings.HasSuffix(result, "<... truncated>") { - t.Error("truncated string should have <... truncated> suffix") - } -} - -func TestErrorIs(t *testing.T) { - mockT := new(testing.T) - tests := []struct { - err error - target error - result bool - }{ - {io.EOF, io.EOF, true}, - {fmt.Errorf("wrap: %w", io.EOF), io.EOF, true}, - {io.EOF, io.ErrClosedPipe, false}, - {nil, io.EOF, false}, - {io.EOF, nil, false}, - {nil, nil, true}, - } - for _, tt := range tests { - tt := tt - t.Run(fmt.Sprintf("ErrorIs(%#v,%#v)", tt.err, tt.target), func(t *testing.T) { - res := ErrorIs(mockT, tt.err, tt.target) - if res != tt.result { - t.Errorf("ErrorIs(%#v,%#v) should return %t", tt.err, tt.target, tt.result) - } - }) - } -} - -func TestNotErrorIs(t *testing.T) { - mockT := new(testing.T) - tests := []struct { - err error - target error - result bool - }{ - {io.EOF, io.EOF, false}, - {fmt.Errorf("wrap: %w", io.EOF), io.EOF, false}, - {io.EOF, io.ErrClosedPipe, true}, - {nil, io.EOF, true}, - {io.EOF, nil, true}, - {nil, nil, false}, - } - for _, tt := range tests { - tt := tt - t.Run(fmt.Sprintf("NotErrorIs(%#v,%#v)", tt.err, tt.target), func(t *testing.T) { - res := NotErrorIs(mockT, tt.err, tt.target) - if res != tt.result { - t.Errorf("NotErrorIs(%#v,%#v) should return %t", tt.err, tt.target, tt.result) - } - }) - } -} - -func TestErrorAs(t *testing.T) { - mockT := new(testing.T) - tests := []struct { - err error - result bool - }{ - {fmt.Errorf("wrap: %w", &customError{}), true}, - {io.EOF, false}, - {nil, false}, - } - for _, tt := range tests { - tt := tt - var target *customError - t.Run(fmt.Sprintf("ErrorAs(%#v,%#v)", tt.err, target), func(t *testing.T) { - res := ErrorAs(mockT, tt.err, &target) - if res != tt.result { - t.Errorf("ErrorAs(%#v,%#v) should return %t)", tt.err, target, tt.result) - } - }) - } -} - -func TestIsNil(t *testing.T) { - var n unsafe.Pointer = nil - if !isNil(n) { - t.Fatal("fail") - } -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/doc.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/doc.go deleted file mode 100644 index c9dccc4..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/doc.go +++ /dev/null @@ -1,45 +0,0 @@ -// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. -// -// Example Usage -// -// The following is a complete example using assert in a standard test function: -// import ( -// "testing" -// "github.com/stretchr/testify/assert" -// ) -// -// func TestSomething(t *testing.T) { -// -// var a string = "Hello" -// var b string = "Hello" -// -// assert.Equal(t, a, b, "The two words should be the same.") -// -// } -// -// if you assert many times, use the format below: -// -// import ( -// "testing" -// "github.com/stretchr/testify/assert" -// ) -// -// func TestSomething(t *testing.T) { -// assert := assert.New(t) -// -// var a string = "Hello" -// var b string = "Hello" -// -// assert.Equal(a, b, "The two words should be the same.") -// } -// -// Assertions -// -// Assertions allow you to easily write test code, and are global funcs in the `assert` package. -// All assertion functions take, as the first argument, the `*testing.T` object provided by the -// testing framework. This allows the assertion funcs to write the failings and other details to -// the correct place. -// -// Every assertion function also takes an optional string message as the final argument, -// allowing custom error messages to be appended to the message the assertion method outputs. -package assert diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/errors.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/errors.go deleted file mode 100644 index ac9dc9d..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/errors.go +++ /dev/null @@ -1,10 +0,0 @@ -package assert - -import ( - "errors" -) - -// AnError is an error instance useful for testing. If the code does not care -// about error specifics, and only needs to return the error for example, this -// error should be used to make the test code more readable. -var AnError = errors.New("assert.AnError general error for testing") diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/forward_assertions.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/forward_assertions.go deleted file mode 100644 index df189d2..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/forward_assertions.go +++ /dev/null @@ -1,16 +0,0 @@ -package assert - -// Assertions provides assertion methods around the -// TestingT interface. -type Assertions struct { - t TestingT -} - -// New makes a new Assertions object for the specified TestingT. -func New(t TestingT) *Assertions { - return &Assertions{ - t: t, - } -} - -//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs" diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/forward_assertions_test.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/forward_assertions_test.go deleted file mode 100644 index 496d3c0..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/forward_assertions_test.go +++ /dev/null @@ -1,752 +0,0 @@ -package assert - -import ( - "errors" - "regexp" - "testing" - "time" -) - -func TestImplementsWrapper(t *testing.T) { - assert := New(new(testing.T)) - - if !assert.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) { - t.Error("Implements method should return true: AssertionTesterConformingObject implements AssertionTesterInterface") - } - if assert.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) { - t.Error("Implements method should return false: AssertionTesterNonConformingObject does not implements AssertionTesterInterface") - } -} - -func TestIsTypeWrapper(t *testing.T) { - assert := New(new(testing.T)) - - if !assert.IsType(new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) { - t.Error("IsType should return true: AssertionTesterConformingObject is the same type as AssertionTesterConformingObject") - } - if assert.IsType(new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) { - t.Error("IsType should return false: AssertionTesterConformingObject is not the same type as AssertionTesterNonConformingObject") - } - -} - -func TestEqualWrapper(t *testing.T) { - assert := New(new(testing.T)) - - if !assert.Equal("Hello World", "Hello World") { - t.Error("Equal should return true") - } - if !assert.Equal(123, 123) { - t.Error("Equal should return true") - } - if !assert.Equal(123.5, 123.5) { - t.Error("Equal should return true") - } - if !assert.Equal([]byte("Hello World"), []byte("Hello World")) { - t.Error("Equal should return true") - } - if !assert.Equal(nil, nil) { - t.Error("Equal should return true") - } -} - -func TestEqualValuesWrapper(t *testing.T) { - assert := New(new(testing.T)) - - if !assert.EqualValues(uint32(10), int32(10)) { - t.Error("EqualValues should return true") - } -} - -func TestNotNilWrapper(t *testing.T) { - assert := New(new(testing.T)) - - if !assert.NotNil(new(AssertionTesterConformingObject)) { - t.Error("NotNil should return true: object is not nil") - } - if assert.NotNil(nil) { - t.Error("NotNil should return false: object is nil") - } - -} - -func TestNilWrapper(t *testing.T) { - assert := New(new(testing.T)) - - if !assert.Nil(nil) { - t.Error("Nil should return true: object is nil") - } - if assert.Nil(new(AssertionTesterConformingObject)) { - t.Error("Nil should return false: object is not nil") - } - -} - -func TestTrueWrapper(t *testing.T) { - assert := New(new(testing.T)) - - if !assert.True(true) { - t.Error("True should return true") - } - if assert.True(false) { - t.Error("True should return false") - } - -} - -func TestFalseWrapper(t *testing.T) { - assert := New(new(testing.T)) - - if !assert.False(false) { - t.Error("False should return true") - } - if assert.False(true) { - t.Error("False should return false") - } - -} - -func TestExactlyWrapper(t *testing.T) { - assert := New(new(testing.T)) - - a := float32(1) - b := float64(1) - c := float32(1) - d := float32(2) - - if assert.Exactly(a, b) { - t.Error("Exactly should return false") - } - if assert.Exactly(a, d) { - t.Error("Exactly should return false") - } - if !assert.Exactly(a, c) { - t.Error("Exactly should return true") - } - - if assert.Exactly(nil, a) { - t.Error("Exactly should return false") - } - if assert.Exactly(a, nil) { - t.Error("Exactly should return false") - } - -} - -func TestNotEqualWrapper(t *testing.T) { - - assert := New(new(testing.T)) - - if !assert.NotEqual("Hello World", "Hello World!") { - t.Error("NotEqual should return true") - } - if !assert.NotEqual(123, 1234) { - t.Error("NotEqual should return true") - } - if !assert.NotEqual(123.5, 123.55) { - t.Error("NotEqual should return true") - } - if !assert.NotEqual([]byte("Hello World"), []byte("Hello World!")) { - t.Error("NotEqual should return true") - } - if !assert.NotEqual(nil, new(AssertionTesterConformingObject)) { - t.Error("NotEqual should return true") - } -} - -func TestNotEqualValuesWrapper(t *testing.T) { - - assert := New(new(testing.T)) - - if !assert.NotEqualValues("Hello World", "Hello World!") { - t.Error("NotEqualValues should return true") - } - if !assert.NotEqualValues(123, 1234) { - t.Error("NotEqualValues should return true") - } - if !assert.NotEqualValues(123.5, 123.55) { - t.Error("NotEqualValues should return true") - } - if !assert.NotEqualValues([]byte("Hello World"), []byte("Hello World!")) { - t.Error("NotEqualValues should return true") - } - if !assert.NotEqualValues(nil, new(AssertionTesterConformingObject)) { - t.Error("NotEqualValues should return true") - } - if assert.NotEqualValues(10, uint(10)) { - t.Error("NotEqualValues should return false") - } -} - -func TestContainsWrapper(t *testing.T) { - - assert := New(new(testing.T)) - list := []string{"Foo", "Bar"} - - if !assert.Contains("Hello World", "Hello") { - t.Error("Contains should return true: \"Hello World\" contains \"Hello\"") - } - if assert.Contains("Hello World", "Salut") { - t.Error("Contains should return false: \"Hello World\" does not contain \"Salut\"") - } - - if !assert.Contains(list, "Foo") { - t.Error("Contains should return true: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"") - } - if assert.Contains(list, "Salut") { - t.Error("Contains should return false: \"[\"Foo\", \"Bar\"]\" does not contain \"Salut\"") - } - -} - -func TestNotContainsWrapper(t *testing.T) { - - assert := New(new(testing.T)) - list := []string{"Foo", "Bar"} - - if !assert.NotContains("Hello World", "Hello!") { - t.Error("NotContains should return true: \"Hello World\" does not contain \"Hello!\"") - } - if assert.NotContains("Hello World", "Hello") { - t.Error("NotContains should return false: \"Hello World\" contains \"Hello\"") - } - - if !assert.NotContains(list, "Foo!") { - t.Error("NotContains should return true: \"[\"Foo\", \"Bar\"]\" does not contain \"Foo!\"") - } - if assert.NotContains(list, "Foo") { - t.Error("NotContains should return false: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"") - } - -} - -func TestConditionWrapper(t *testing.T) { - - assert := New(new(testing.T)) - - if !assert.Condition(func() bool { return true }, "Truth") { - t.Error("Condition should return true") - } - - if assert.Condition(func() bool { return false }, "Lie") { - t.Error("Condition should return false") - } - -} - -func TestDidPanicWrapper(t *testing.T) { - - if funcDidPanic, _, _ := didPanic(func() { - panic("Panic!") - }); !funcDidPanic { - t.Error("didPanic should return true") - } - - if funcDidPanic, _, _ := didPanic(func() { - }); funcDidPanic { - t.Error("didPanic should return false") - } - -} - -func TestPanicsWrapper(t *testing.T) { - - assert := New(new(testing.T)) - - if !assert.Panics(func() { - panic("Panic!") - }) { - t.Error("Panics should return true") - } - - if assert.Panics(func() { - }) { - t.Error("Panics should return false") - } - -} - -func TestNotPanicsWrapper(t *testing.T) { - - assert := New(new(testing.T)) - - if !assert.NotPanics(func() { - }) { - t.Error("NotPanics should return true") - } - - if assert.NotPanics(func() { - panic("Panic!") - }) { - t.Error("NotPanics should return false") - } - -} - -func TestNoErrorWrapper(t *testing.T) { - assert := New(t) - mockAssert := New(new(testing.T)) - - // start with a nil error - var err error - - assert.True(mockAssert.NoError(err), "NoError should return True for nil arg") - - // now set an error - err = errors.New("Some error") - - assert.False(mockAssert.NoError(err), "NoError with error should return False") - -} - -func TestErrorWrapper(t *testing.T) { - assert := New(t) - mockAssert := New(new(testing.T)) - - // start with a nil error - var err error - - assert.False(mockAssert.Error(err), "Error should return False for nil arg") - - // now set an error - err = errors.New("Some error") - - assert.True(mockAssert.Error(err), "Error with error should return True") - -} - -func TestErrorContainsWrapper(t *testing.T) { - assert := New(t) - mockAssert := New(new(testing.T)) - - // start with a nil error - var err error - assert.False(mockAssert.ErrorContains(err, ""), - "ErrorContains should return false for nil arg") - - // now set an error - err = errors.New("some error: another error") - assert.False(mockAssert.ErrorContains(err, "different error"), - "ErrorContains should return false for different error string") - assert.True(mockAssert.ErrorContains(err, "some error"), - "ErrorContains should return true") - assert.True(mockAssert.ErrorContains(err, "another error"), - "ErrorContains should return true") -} - -func TestEqualErrorWrapper(t *testing.T) { - assert := New(t) - mockAssert := New(new(testing.T)) - - // start with a nil error - var err error - assert.False(mockAssert.EqualError(err, ""), - "EqualError should return false for nil arg") - - // now set an error - err = errors.New("some error") - assert.False(mockAssert.EqualError(err, "Not some error"), - "EqualError should return false for different error string") - assert.True(mockAssert.EqualError(err, "some error"), - "EqualError should return true") -} - -func TestEmptyWrapper(t *testing.T) { - assert := New(t) - mockAssert := New(new(testing.T)) - - assert.True(mockAssert.Empty(""), "Empty string is empty") - assert.True(mockAssert.Empty(nil), "Nil is empty") - assert.True(mockAssert.Empty([]string{}), "Empty string array is empty") - assert.True(mockAssert.Empty(0), "Zero int value is empty") - assert.True(mockAssert.Empty(false), "False value is empty") - - assert.False(mockAssert.Empty("something"), "Non Empty string is not empty") - assert.False(mockAssert.Empty(errors.New("something")), "Non nil object is not empty") - assert.False(mockAssert.Empty([]string{"something"}), "Non empty string array is not empty") - assert.False(mockAssert.Empty(1), "Non-zero int value is not empty") - assert.False(mockAssert.Empty(true), "True value is not empty") - -} - -func TestNotEmptyWrapper(t *testing.T) { - assert := New(t) - mockAssert := New(new(testing.T)) - - assert.False(mockAssert.NotEmpty(""), "Empty string is empty") - assert.False(mockAssert.NotEmpty(nil), "Nil is empty") - assert.False(mockAssert.NotEmpty([]string{}), "Empty string array is empty") - assert.False(mockAssert.NotEmpty(0), "Zero int value is empty") - assert.False(mockAssert.NotEmpty(false), "False value is empty") - - assert.True(mockAssert.NotEmpty("something"), "Non Empty string is not empty") - assert.True(mockAssert.NotEmpty(errors.New("something")), "Non nil object is not empty") - assert.True(mockAssert.NotEmpty([]string{"something"}), "Non empty string array is not empty") - assert.True(mockAssert.NotEmpty(1), "Non-zero int value is not empty") - assert.True(mockAssert.NotEmpty(true), "True value is not empty") - -} - -func TestLenWrapper(t *testing.T) { - assert := New(t) - mockAssert := New(new(testing.T)) - - assert.False(mockAssert.Len(nil, 0), "nil does not have length") - assert.False(mockAssert.Len(0, 0), "int does not have length") - assert.False(mockAssert.Len(true, 0), "true does not have length") - assert.False(mockAssert.Len(false, 0), "false does not have length") - assert.False(mockAssert.Len('A', 0), "Rune does not have length") - assert.False(mockAssert.Len(struct{}{}, 0), "Struct does not have length") - - ch := make(chan int, 5) - ch <- 1 - ch <- 2 - ch <- 3 - - cases := []struct { - v interface{} - l int - }{ - {[]int{1, 2, 3}, 3}, - {[...]int{1, 2, 3}, 3}, - {"ABC", 3}, - {map[int]int{1: 2, 2: 4, 3: 6}, 3}, - {ch, 3}, - - {[]int{}, 0}, - {map[int]int{}, 0}, - {make(chan int), 0}, - - {[]int(nil), 0}, - {map[int]int(nil), 0}, - {(chan int)(nil), 0}, - } - - for _, c := range cases { - assert.True(mockAssert.Len(c.v, c.l), "%#v have %d items", c.v, c.l) - } -} - -func TestWithinDurationWrapper(t *testing.T) { - assert := New(t) - mockAssert := New(new(testing.T)) - a := time.Now() - b := a.Add(10 * time.Second) - - assert.True(mockAssert.WithinDuration(a, b, 10*time.Second), "A 10s difference is within a 10s time difference") - assert.True(mockAssert.WithinDuration(b, a, 10*time.Second), "A 10s difference is within a 10s time difference") - - assert.False(mockAssert.WithinDuration(a, b, 9*time.Second), "A 10s difference is not within a 9s time difference") - assert.False(mockAssert.WithinDuration(b, a, 9*time.Second), "A 10s difference is not within a 9s time difference") - - assert.False(mockAssert.WithinDuration(a, b, -9*time.Second), "A 10s difference is not within a 9s time difference") - assert.False(mockAssert.WithinDuration(b, a, -9*time.Second), "A 10s difference is not within a 9s time difference") - - assert.False(mockAssert.WithinDuration(a, b, -11*time.Second), "A 10s difference is not within a 9s time difference") - assert.False(mockAssert.WithinDuration(b, a, -11*time.Second), "A 10s difference is not within a 9s time difference") -} - -func TestInDeltaWrapper(t *testing.T) { - assert := New(new(testing.T)) - - True(t, assert.InDelta(1.001, 1, 0.01), "|1.001 - 1| <= 0.01") - True(t, assert.InDelta(1, 1.001, 0.01), "|1 - 1.001| <= 0.01") - True(t, assert.InDelta(1, 2, 1), "|1 - 2| <= 1") - False(t, assert.InDelta(1, 2, 0.5), "Expected |1 - 2| <= 0.5 to fail") - False(t, assert.InDelta(2, 1, 0.5), "Expected |2 - 1| <= 0.5 to fail") - False(t, assert.InDelta("", nil, 1), "Expected non numerals to fail") - - cases := []struct { - a, b interface{} - delta float64 - }{ - {uint8(2), uint8(1), 1}, - {uint16(2), uint16(1), 1}, - {uint32(2), uint32(1), 1}, - {uint64(2), uint64(1), 1}, - - {int(2), int(1), 1}, - {int8(2), int8(1), 1}, - {int16(2), int16(1), 1}, - {int32(2), int32(1), 1}, - {int64(2), int64(1), 1}, - - {float32(2), float32(1), 1}, - {float64(2), float64(1), 1}, - } - - for _, tc := range cases { - True(t, assert.InDelta(tc.a, tc.b, tc.delta), "Expected |%V - %V| <= %v", tc.a, tc.b, tc.delta) - } -} - -func TestInEpsilonWrapper(t *testing.T) { - assert := New(new(testing.T)) - - cases := []struct { - a, b interface{} - epsilon float64 - }{ - {uint8(2), uint16(2), .001}, - {2.1, 2.2, 0.1}, - {2.2, 2.1, 0.1}, - {-2.1, -2.2, 0.1}, - {-2.2, -2.1, 0.1}, - {uint64(100), uint8(101), 0.01}, - {0.1, -0.1, 2}, - } - - for _, tc := range cases { - True(t, assert.InEpsilon(tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon)) - } - - cases = []struct { - a, b interface{} - epsilon float64 - }{ - {uint8(2), int16(-2), .001}, - {uint64(100), uint8(102), 0.01}, - {2.1, 2.2, 0.001}, - {2.2, 2.1, 0.001}, - {2.1, -2.2, 1}, - {2.1, "bla-bla", 0}, - {0.1, -0.1, 1.99}, - } - - for _, tc := range cases { - False(t, assert.InEpsilon(tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon)) - } -} - -func TestRegexpWrapper(t *testing.T) { - - assert := New(new(testing.T)) - - cases := []struct { - rx, str string - }{ - {"^start", "start of the line"}, - {"end$", "in the end"}, - {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12.34"}, - } - - for _, tc := range cases { - True(t, assert.Regexp(tc.rx, tc.str)) - True(t, assert.Regexp(regexp.MustCompile(tc.rx), tc.str)) - False(t, assert.NotRegexp(tc.rx, tc.str)) - False(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str)) - } - - cases = []struct { - rx, str string - }{ - {"^asdfastart", "Not the start of the line"}, - {"end$", "in the end."}, - {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12a.34"}, - } - - for _, tc := range cases { - False(t, assert.Regexp(tc.rx, tc.str), "Expected \"%s\" to not match \"%s\"", tc.rx, tc.str) - False(t, assert.Regexp(regexp.MustCompile(tc.rx), tc.str)) - True(t, assert.NotRegexp(tc.rx, tc.str)) - True(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str)) - } -} - -func TestZeroWrapper(t *testing.T) { - assert := New(t) - mockAssert := New(new(testing.T)) - - for _, test := range zeros { - assert.True(mockAssert.Zero(test), "Zero should return true for %v", test) - } - - for _, test := range nonZeros { - assert.False(mockAssert.Zero(test), "Zero should return false for %v", test) - } -} - -func TestNotZeroWrapper(t *testing.T) { - assert := New(t) - mockAssert := New(new(testing.T)) - - for _, test := range zeros { - assert.False(mockAssert.NotZero(test), "Zero should return true for %v", test) - } - - for _, test := range nonZeros { - assert.True(mockAssert.NotZero(test), "Zero should return false for %v", test) - } -} - -func TestJSONEqWrapper_EqualSONString(t *testing.T) { - assert := New(new(testing.T)) - if !assert.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) { - t.Error("JSONEq should return true") - } - -} - -func TestJSONEqWrapper_EquivalentButNotEqual(t *testing.T) { - assert := New(new(testing.T)) - if !assert.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) { - t.Error("JSONEq should return true") - } - -} - -func TestJSONEqWrapper_HashOfArraysAndHashes(t *testing.T) { - assert := New(new(testing.T)) - if !assert.JSONEq("{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}", - "{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}") { - t.Error("JSONEq should return true") - } -} - -func TestJSONEqWrapper_Array(t *testing.T) { - assert := New(new(testing.T)) - if !assert.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) { - t.Error("JSONEq should return true") - } - -} - -func TestJSONEqWrapper_HashAndArrayNotEquivalent(t *testing.T) { - assert := New(new(testing.T)) - if assert.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) { - t.Error("JSONEq should return false") - } -} - -func TestJSONEqWrapper_HashesNotEquivalent(t *testing.T) { - assert := New(new(testing.T)) - if assert.JSONEq(`{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) { - t.Error("JSONEq should return false") - } -} - -func TestJSONEqWrapper_ActualIsNotJSON(t *testing.T) { - assert := New(new(testing.T)) - if assert.JSONEq(`{"foo": "bar"}`, "Not JSON") { - t.Error("JSONEq should return false") - } -} - -func TestJSONEqWrapper_ExpectedIsNotJSON(t *testing.T) { - assert := New(new(testing.T)) - if assert.JSONEq("Not JSON", `{"foo": "bar", "hello": "world"}`) { - t.Error("JSONEq should return false") - } -} - -func TestJSONEqWrapper_ExpectedAndActualNotJSON(t *testing.T) { - assert := New(new(testing.T)) - if assert.JSONEq("Not JSON", "Not JSON") { - t.Error("JSONEq should return false") - } -} - -func TestJSONEqWrapper_ArraysOfDifferentOrder(t *testing.T) { - assert := New(new(testing.T)) - if assert.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) { - t.Error("JSONEq should return false") - } -} - -func TestYAMLEqWrapper_EqualYAMLString(t *testing.T) { - assert := New(new(testing.T)) - if !assert.YAMLEq(`{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) { - t.Error("YAMLEq should return true") - } - -} - -func TestYAMLEqWrapper_EquivalentButNotEqual(t *testing.T) { - assert := New(new(testing.T)) - if !assert.YAMLEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) { - t.Error("YAMLEq should return true") - } - -} - -func TestYAMLEqWrapper_HashOfArraysAndHashes(t *testing.T) { - assert := New(new(testing.T)) - expected := ` -numeric: 1.5 -array: - - foo: bar - - 1 - - "string" - - ["nested", "array", 5.5] -hash: - nested: hash - nested_slice: [this, is, nested] -string: "foo" -` - - actual := ` -numeric: 1.5 -hash: - nested: hash - nested_slice: [this, is, nested] -string: "foo" -array: - - foo: bar - - 1 - - "string" - - ["nested", "array", 5.5] -` - if !assert.YAMLEq(expected, actual) { - t.Error("YAMLEq should return true") - } -} - -func TestYAMLEqWrapper_Array(t *testing.T) { - assert := New(new(testing.T)) - if !assert.YAMLEq(`["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) { - t.Error("YAMLEq should return true") - } - -} - -func TestYAMLEqWrapper_HashAndArrayNotEquivalent(t *testing.T) { - assert := New(new(testing.T)) - if assert.YAMLEq(`["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) { - t.Error("YAMLEq should return false") - } -} - -func TestYAMLEqWrapper_HashesNotEquivalent(t *testing.T) { - assert := New(new(testing.T)) - if assert.YAMLEq(`{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) { - t.Error("YAMLEq should return false") - } -} - -func TestYAMLEqWrapper_ActualIsSimpleString(t *testing.T) { - assert := New(new(testing.T)) - if assert.YAMLEq(`{"foo": "bar"}`, "Simple String") { - t.Error("YAMLEq should return false") - } -} - -func TestYAMLEqWrapper_ExpectedIsSimpleString(t *testing.T) { - assert := New(new(testing.T)) - if assert.YAMLEq("Simple String", `{"foo": "bar", "hello": "world"}`) { - t.Error("YAMLEq should return false") - } -} - -func TestYAMLEqWrapper_ExpectedAndActualSimpleString(t *testing.T) { - assert := New(new(testing.T)) - if !assert.YAMLEq("Simple String", "Simple String") { - t.Error("YAMLEq should return true") - } -} - -func TestYAMLEqWrapper_ArraysOfDifferentOrder(t *testing.T) { - assert := New(new(testing.T)) - if assert.YAMLEq(`["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) { - t.Error("YAMLEq should return false") - } -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/http_assertions.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/http_assertions.go deleted file mode 100644 index 4ed341d..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/http_assertions.go +++ /dev/null @@ -1,162 +0,0 @@ -package assert - -import ( - "fmt" - "net/http" - "net/http/httptest" - "net/url" - "strings" -) - -// httpCode is a helper that returns HTTP code of the response. It returns -1 and -// an error if building a new request fails. -func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) { - w := httptest.NewRecorder() - req, err := http.NewRequest(method, url, nil) - if err != nil { - return -1, err - } - req.URL.RawQuery = values.Encode() - handler(w, req) - return w.Code, nil -} - -// HTTPSuccess asserts that a specified handler returns a success status code. -// -// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - code, err := httpCode(handler, method, url, values) - if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) - } - - isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent - if !isSuccessCode { - Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code)) - } - - return isSuccessCode -} - -// HTTPRedirect asserts that a specified handler returns a redirect status code. -// -// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - code, err := httpCode(handler, method, url, values) - if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) - } - - isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect - if !isRedirectCode { - Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code)) - } - - return isRedirectCode -} - -// HTTPError asserts that a specified handler returns an error status code. -// -// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - code, err := httpCode(handler, method, url, values) - if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) - } - - isErrorCode := code >= http.StatusBadRequest - if !isErrorCode { - Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code)) - } - - return isErrorCode -} - -// HTTPStatusCode asserts that a specified handler returns a specified status code. -// -// assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501) -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - code, err := httpCode(handler, method, url, values) - if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) - } - - successful := code == statuscode - if !successful { - Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code)) - } - - return successful -} - -// HTTPBody is a helper that returns HTTP body of the response. It returns -// empty string if building a new request fails. -func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { - w := httptest.NewRecorder() - req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) - if err != nil { - return "" - } - handler(w, req) - return w.Body.String() -} - -// HTTPBodyContains asserts that a specified handler returns a -// body that contains a string. -// -// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - body := HTTPBody(handler, method, url, values) - - contains := strings.Contains(body, fmt.Sprint(str)) - if !contains { - Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) - } - - return contains -} - -// HTTPBodyNotContains asserts that a specified handler returns a -// body that does not contain a string. -// -// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - body := HTTPBody(handler, method, url, values) - - contains := strings.Contains(body, fmt.Sprint(str)) - if contains { - Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) - } - - return !contains -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/http_assertions_test.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/http_assertions_test.go deleted file mode 100644 index 413c971..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/assert/http_assertions_test.go +++ /dev/null @@ -1,182 +0,0 @@ -package assert - -import ( - "fmt" - "net/http" - "net/url" - "testing" -) - -func httpOK(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) -} - -func httpRedirect(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusTemporaryRedirect) -} - -func httpError(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusInternalServerError) -} - -func httpStatusCode(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusSwitchingProtocols) -} - -func TestHTTPSuccess(t *testing.T) { - assert := New(t) - - mockT1 := new(testing.T) - assert.Equal(HTTPSuccess(mockT1, httpOK, "GET", "/", nil), true) - assert.False(mockT1.Failed()) - - mockT2 := new(testing.T) - assert.Equal(HTTPSuccess(mockT2, httpRedirect, "GET", "/", nil), false) - assert.True(mockT2.Failed()) - - mockT3 := new(testing.T) - assert.Equal(HTTPSuccess(mockT3, httpError, "GET", "/", nil), false) - assert.True(mockT3.Failed()) - - mockT4 := new(testing.T) - assert.Equal(HTTPSuccess(mockT4, httpStatusCode, "GET", "/", nil), false) - assert.True(mockT4.Failed()) -} - -func TestHTTPRedirect(t *testing.T) { - assert := New(t) - - mockT1 := new(testing.T) - assert.Equal(HTTPRedirect(mockT1, httpOK, "GET", "/", nil), false) - assert.True(mockT1.Failed()) - - mockT2 := new(testing.T) - assert.Equal(HTTPRedirect(mockT2, httpRedirect, "GET", "/", nil), true) - assert.False(mockT2.Failed()) - - mockT3 := new(testing.T) - assert.Equal(HTTPRedirect(mockT3, httpError, "GET", "/", nil), false) - assert.True(mockT3.Failed()) - - mockT4 := new(testing.T) - assert.Equal(HTTPRedirect(mockT4, httpStatusCode, "GET", "/", nil), false) - assert.True(mockT4.Failed()) -} - -func TestHTTPError(t *testing.T) { - assert := New(t) - - mockT1 := new(testing.T) - assert.Equal(HTTPError(mockT1, httpOK, "GET", "/", nil), false) - assert.True(mockT1.Failed()) - - mockT2 := new(testing.T) - assert.Equal(HTTPError(mockT2, httpRedirect, "GET", "/", nil), false) - assert.True(mockT2.Failed()) - - mockT3 := new(testing.T) - assert.Equal(HTTPError(mockT3, httpError, "GET", "/", nil), true) - assert.False(mockT3.Failed()) - - mockT4 := new(testing.T) - assert.Equal(HTTPError(mockT4, httpStatusCode, "GET", "/", nil), false) - assert.True(mockT4.Failed()) -} - -func TestHTTPStatusCode(t *testing.T) { - assert := New(t) - - mockT1 := new(testing.T) - assert.Equal(HTTPStatusCode(mockT1, httpOK, "GET", "/", nil, http.StatusSwitchingProtocols), false) - assert.True(mockT1.Failed()) - - mockT2 := new(testing.T) - assert.Equal(HTTPStatusCode(mockT2, httpRedirect, "GET", "/", nil, http.StatusSwitchingProtocols), false) - assert.True(mockT2.Failed()) - - mockT3 := new(testing.T) - assert.Equal(HTTPStatusCode(mockT3, httpError, "GET", "/", nil, http.StatusSwitchingProtocols), false) - assert.True(mockT3.Failed()) - - mockT4 := new(testing.T) - assert.Equal(HTTPStatusCode(mockT4, httpStatusCode, "GET", "/", nil, http.StatusSwitchingProtocols), true) - assert.False(mockT4.Failed()) -} - -func TestHTTPStatusesWrapper(t *testing.T) { - assert := New(t) - mockAssert := New(new(testing.T)) - - assert.Equal(mockAssert.HTTPSuccess(httpOK, "GET", "/", nil), true) - assert.Equal(mockAssert.HTTPSuccess(httpRedirect, "GET", "/", nil), false) - assert.Equal(mockAssert.HTTPSuccess(httpError, "GET", "/", nil), false) - - assert.Equal(mockAssert.HTTPRedirect(httpOK, "GET", "/", nil), false) - assert.Equal(mockAssert.HTTPRedirect(httpRedirect, "GET", "/", nil), true) - assert.Equal(mockAssert.HTTPRedirect(httpError, "GET", "/", nil), false) - - assert.Equal(mockAssert.HTTPError(httpOK, "GET", "/", nil), false) - assert.Equal(mockAssert.HTTPError(httpRedirect, "GET", "/", nil), false) - assert.Equal(mockAssert.HTTPError(httpError, "GET", "/", nil), true) -} - -func httpHelloName(w http.ResponseWriter, r *http.Request) { - name := r.FormValue("name") - _, _ = w.Write([]byte(fmt.Sprintf("Hello, %s!", name))) -} - -func TestHTTPRequestWithNoParams(t *testing.T) { - var got *http.Request - handler := func(w http.ResponseWriter, r *http.Request) { - got = r - w.WriteHeader(http.StatusOK) - } - - True(t, HTTPSuccess(t, handler, "GET", "/url", nil)) - - Empty(t, got.URL.Query()) - Equal(t, "/url", got.URL.RequestURI()) -} - -func TestHTTPRequestWithParams(t *testing.T) { - var got *http.Request - handler := func(w http.ResponseWriter, r *http.Request) { - got = r - w.WriteHeader(http.StatusOK) - } - params := url.Values{} - params.Add("id", "12345") - - True(t, HTTPSuccess(t, handler, "GET", "/url", params)) - - Equal(t, url.Values{"id": []string{"12345"}}, got.URL.Query()) - Equal(t, "/url?id=12345", got.URL.String()) - Equal(t, "/url?id=12345", got.URL.RequestURI()) -} - -func TestHttpBody(t *testing.T) { - assert := New(t) - mockT := new(testing.T) - - assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) - assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) - assert.False(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) - - assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) - assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) - assert.True(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) -} - -func TestHttpBodyWrappers(t *testing.T) { - assert := New(t) - mockAssert := New(new(testing.T)) - - assert.True(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) - assert.True(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) - assert.False(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) - - assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) - assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) - assert.True(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) - -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/doc.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/doc.go deleted file mode 100644 index 3460b46..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/doc.go +++ /dev/null @@ -1,23 +0,0 @@ -// ** We are working on testify v2 and would love to hear what you'd like to see in it, have your say here: https://cutt.ly/testify ** -// Package testify is a set of packages that provide many tools for testifying that your code will behave as you intend. -// -// testify contains the following packages: -// -// The assert package provides a comprehensive set of assertion functions that tie in to the Go testing system. -// -// The http package contains tools to make it easier to test http activity using the Go testing system. -// -// The mock package provides a system by which it is possible to mock your objects and verify calls are happening as expected. -// -// The suite package provides a basic structure for using structs as testing suites, and methods on those structs as tests. It includes setup/teardown functionality in the way of interfaces. -package testify - -// blank imports help docs. -import ( - // assert package - _ "github.com/stretchr/testify/assert" - // http package - _ "github.com/stretchr/testify/http" - // mock package - _ "github.com/stretchr/testify/mock" -) diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/go.mod b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/go.mod deleted file mode 100644 index 3fe9bab..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/go.mod +++ /dev/null @@ -1,10 +0,0 @@ -module github.com/stretchr/testify - -go 1.13 - -require ( - github.com/davecgh/go-spew v1.1.1 - github.com/pmezard/go-difflib v1.0.0 - github.com/stretchr/objx v0.5.0 - gopkg.in/yaml.v3 v3.0.1 -) diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/go.sum b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/go.sum deleted file mode 100644 index 4f3ced6..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/go.sum +++ /dev/null @@ -1,16 +0,0 @@ -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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/http/doc.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/http/doc.go deleted file mode 100644 index 695167c..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/http/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package http DEPRECATED USE net/http/httptest -package http diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/http/test_response_writer.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/http/test_response_writer.go deleted file mode 100644 index 300a63b..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/http/test_response_writer.go +++ /dev/null @@ -1,49 +0,0 @@ -package http - -import ( - "net/http" -) - -// TestResponseWriter DEPRECATED: We recommend you use http://golang.org/pkg/net/http/httptest instead. -type TestResponseWriter struct { - - // StatusCode is the last int written by the call to WriteHeader(int) - StatusCode int - - // Output is a string containing the written bytes using the Write([]byte) func. - Output string - - // header is the internal storage of the http.Header object - header http.Header -} - -// Header DEPRECATED: We recommend you use http://golang.org/pkg/net/http/httptest instead. -func (rw *TestResponseWriter) Header() http.Header { - - if rw.header == nil { - rw.header = make(http.Header) - } - - return rw.header -} - -// Write DEPRECATED: We recommend you use http://golang.org/pkg/net/http/httptest instead. -func (rw *TestResponseWriter) Write(bytes []byte) (int, error) { - - // assume 200 success if no header has been set - if rw.StatusCode == 0 { - rw.WriteHeader(200) - } - - // add these bytes to the output string - rw.Output += string(bytes) - - // return normal values - return 0, nil - -} - -// WriteHeader DEPRECATED: We recommend you use http://golang.org/pkg/net/http/httptest instead. -func (rw *TestResponseWriter) WriteHeader(i int) { - rw.StatusCode = i -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/http/test_round_tripper.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/http/test_round_tripper.go deleted file mode 100644 index 11a024e..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/http/test_round_tripper.go +++ /dev/null @@ -1,18 +0,0 @@ -package http - -import ( - "net/http" - - "github.com/stretchr/testify/mock" -) - -// TestRoundTripper DEPRECATED USE net/http/httptest -type TestRoundTripper struct { - mock.Mock -} - -// RoundTrip DEPRECATED USE net/http/httptest -func (t *TestRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - args := t.Called(req) - return args.Get(0).(*http.Response), args.Error(1) -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/mock/doc.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/mock/doc.go deleted file mode 100644 index 7324128..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/mock/doc.go +++ /dev/null @@ -1,44 +0,0 @@ -// Package mock provides a system by which it is possible to mock your objects -// and verify calls are happening as expected. -// -// Example Usage -// -// The mock package provides an object, Mock, that tracks activity on another object. It is usually -// embedded into a test object as shown below: -// -// type MyTestObject struct { -// // add a Mock object instance -// mock.Mock -// -// // other fields go here as normal -// } -// -// When implementing the methods of an interface, you wire your functions up -// to call the Mock.Called(args...) method, and return the appropriate values. -// -// For example, to mock a method that saves the name and age of a person and returns -// the year of their birth or an error, you might write this: -// -// func (o *MyTestObject) SavePersonDetails(firstname, lastname string, age int) (int, error) { -// args := o.Called(firstname, lastname, age) -// return args.Int(0), args.Error(1) -// } -// -// The Int, Error and Bool methods are examples of strongly typed getters that take the argument -// index position. Given this argument list: -// -// (12, true, "Something") -// -// You could read them out strongly typed like this: -// -// args.Int(0) -// args.Bool(1) -// args.String(2) -// -// For objects of your own type, use the generic Arguments.Get(index) method and make a type assertion: -// -// return args.Get(0).(*MyObject), args.Get(1).(*AnotherObjectOfMine) -// -// This may cause a panic if the object you are getting is nil (the type assertion will fail), in those -// cases you should check for nil first. -package mock diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/mock/mock.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/mock/mock.go deleted file mode 100644 index e6ff8df..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/mock/mock.go +++ /dev/null @@ -1,1104 +0,0 @@ -package mock - -import ( - "errors" - "fmt" - "reflect" - "regexp" - "runtime" - "strings" - "sync" - "time" - - "github.com/davecgh/go-spew/spew" - "github.com/pmezard/go-difflib/difflib" - "github.com/stretchr/objx" - "github.com/stretchr/testify/assert" -) - -// TestingT is an interface wrapper around *testing.T -type TestingT interface { - Logf(format string, args ...interface{}) - Errorf(format string, args ...interface{}) - FailNow() -} - -/* - Call -*/ - -// Call represents a method call and is used for setting expectations, -// as well as recording activity. -type Call struct { - Parent *Mock - - // The name of the method that was or will be called. - Method string - - // Holds the arguments of the method. - Arguments Arguments - - // Holds the arguments that should be returned when - // this method is called. - ReturnArguments Arguments - - // Holds the caller info for the On() call - callerInfo []string - - // The number of times to return the return arguments when setting - // expectations. 0 means to always return the value. - Repeatability int - - // Amount of times this call has been called - totalCalls int - - // Call to this method can be optional - optional bool - - // Holds a channel that will be used to block the Return until it either - // receives a message or is closed. nil means it returns immediately. - WaitFor <-chan time.Time - - waitTime time.Duration - - // Holds a handler used to manipulate arguments content that are passed by - // reference. It's useful when mocking methods such as unmarshalers or - // decoders. - RunFn func(Arguments) - - // PanicMsg holds msg to be used to mock panic on the function call - // if the PanicMsg is set to a non nil string the function call will panic - // irrespective of other settings - PanicMsg *string - - // Calls which must be satisfied before this call can be - requires []*Call -} - -func newCall(parent *Mock, methodName string, callerInfo []string, methodArguments ...interface{}) *Call { - return &Call{ - Parent: parent, - Method: methodName, - Arguments: methodArguments, - ReturnArguments: make([]interface{}, 0), - callerInfo: callerInfo, - Repeatability: 0, - WaitFor: nil, - RunFn: nil, - PanicMsg: nil, - } -} - -func (c *Call) lock() { - c.Parent.mutex.Lock() -} - -func (c *Call) unlock() { - c.Parent.mutex.Unlock() -} - -// Return specifies the return arguments for the expectation. -// -// Mock.On("DoSomething").Return(errors.New("failed")) -func (c *Call) Return(returnArguments ...interface{}) *Call { - c.lock() - defer c.unlock() - - c.ReturnArguments = returnArguments - - return c -} - -// Panic specifies if the functon call should fail and the panic message -// -// Mock.On("DoSomething").Panic("test panic") -func (c *Call) Panic(msg string) *Call { - c.lock() - defer c.unlock() - - c.PanicMsg = &msg - - return c -} - -// Once indicates that that the mock should only return the value once. -// -// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Once() -func (c *Call) Once() *Call { - return c.Times(1) -} - -// Twice indicates that that the mock should only return the value twice. -// -// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Twice() -func (c *Call) Twice() *Call { - return c.Times(2) -} - -// Times indicates that that the mock should only return the indicated number -// of times. -// -// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5) -func (c *Call) Times(i int) *Call { - c.lock() - defer c.unlock() - c.Repeatability = i - return c -} - -// WaitUntil sets the channel that will block the mock's return until its closed -// or a message is received. -// -// Mock.On("MyMethod", arg1, arg2).WaitUntil(time.After(time.Second)) -func (c *Call) WaitUntil(w <-chan time.Time) *Call { - c.lock() - defer c.unlock() - c.WaitFor = w - return c -} - -// After sets how long to block until the call returns -// -// Mock.On("MyMethod", arg1, arg2).After(time.Second) -func (c *Call) After(d time.Duration) *Call { - c.lock() - defer c.unlock() - c.waitTime = d - return c -} - -// Run sets a handler to be called before returning. It can be used when -// mocking a method (such as an unmarshaler) that takes a pointer to a struct and -// sets properties in such struct -// -// Mock.On("Unmarshal", AnythingOfType("*map[string]interface{}")).Return().Run(func(args Arguments) { -// arg := args.Get(0).(*map[string]interface{}) -// arg["foo"] = "bar" -// }) -func (c *Call) Run(fn func(args Arguments)) *Call { - c.lock() - defer c.unlock() - c.RunFn = fn - return c -} - -// Maybe allows the method call to be optional. Not calling an optional method -// will not cause an error while asserting expectations -func (c *Call) Maybe() *Call { - c.lock() - defer c.unlock() - c.optional = true - return c -} - -// On chains a new expectation description onto the mocked interface. This -// allows syntax like. -// -// Mock. -// On("MyMethod", 1).Return(nil). -// On("MyOtherMethod", 'a', 'b', 'c').Return(errors.New("Some Error")) -//go:noinline -func (c *Call) On(methodName string, arguments ...interface{}) *Call { - return c.Parent.On(methodName, arguments...) -} - -// Unset removes a mock handler from being called. -// test.On("func", mock.Anything).Unset() -func (c *Call) Unset() *Call { - var unlockOnce sync.Once - - for _, arg := range c.Arguments { - if v := reflect.ValueOf(arg); v.Kind() == reflect.Func { - panic(fmt.Sprintf("cannot use Func in expectations. Use mock.AnythingOfType(\"%T\")", arg)) - } - } - - c.lock() - defer unlockOnce.Do(c.unlock) - - foundMatchingCall := false - - // in-place filter slice for calls to be removed - iterate from 0'th to last skipping unnecessary ones - var index int // write index - for _, call := range c.Parent.ExpectedCalls { - if call.Method == c.Method { - _, diffCount := call.Arguments.Diff(c.Arguments) - if diffCount == 0 { - foundMatchingCall = true - // Remove from ExpectedCalls - just skip it - continue - } - } - c.Parent.ExpectedCalls[index] = call - index++ - } - // trim slice up to last copied index - c.Parent.ExpectedCalls = c.Parent.ExpectedCalls[:index] - - if !foundMatchingCall { - unlockOnce.Do(c.unlock) - c.Parent.fail("\n\nmock: Could not find expected call\n-----------------------------\n\n%s\n\n", - callString(c.Method, c.Arguments, true), - ) - } - - return c -} - -// NotBefore indicates that the mock should only be called after the referenced -// calls have been called as expected. The referenced calls may be from the -// same mock instance and/or other mock instances. -// -// Mock.On("Do").Return(nil).Notbefore( -// Mock.On("Init").Return(nil) -// ) -func (c *Call) NotBefore(calls ...*Call) *Call { - c.lock() - defer c.unlock() - - for _, call := range calls { - if call.Parent == nil { - panic("not before calls must be created with Mock.On()") - } - } - - c.requires = append(c.requires, calls...) - return c -} - -// Mock is the workhorse used to track activity on another object. -// For an example of its usage, refer to the "Example Usage" section at the top -// of this document. -type Mock struct { - // Represents the calls that are expected of - // an object. - ExpectedCalls []*Call - - // Holds the calls that were made to this mocked object. - Calls []Call - - // test is An optional variable that holds the test struct, to be used when an - // invalid mock call was made. - test TestingT - - // TestData holds any data that might be useful for testing. Testify ignores - // this data completely allowing you to do whatever you like with it. - testData objx.Map - - mutex sync.Mutex -} - -// String provides a %v format string for Mock. -// Note: this is used implicitly by Arguments.Diff if a Mock is passed. -// It exists because go's default %v formatting traverses the struct -// without acquiring the mutex, which is detected by go test -race. -func (m *Mock) String() string { - return fmt.Sprintf("%[1]T<%[1]p>", m) -} - -// TestData holds any data that might be useful for testing. Testify ignores -// this data completely allowing you to do whatever you like with it. -func (m *Mock) TestData() objx.Map { - if m.testData == nil { - m.testData = make(objx.Map) - } - - return m.testData -} - -/* - Setting expectations -*/ - -// Test sets the test struct variable of the mock object -func (m *Mock) Test(t TestingT) { - m.mutex.Lock() - defer m.mutex.Unlock() - m.test = t -} - -// fail fails the current test with the given formatted format and args. -// In case that a test was defined, it uses the test APIs for failing a test, -// otherwise it uses panic. -func (m *Mock) fail(format string, args ...interface{}) { - m.mutex.Lock() - defer m.mutex.Unlock() - - if m.test == nil { - panic(fmt.Sprintf(format, args...)) - } - m.test.Errorf(format, args...) - m.test.FailNow() -} - -// On starts a description of an expectation of the specified method -// being called. -// -// Mock.On("MyMethod", arg1, arg2) -func (m *Mock) On(methodName string, arguments ...interface{}) *Call { - for _, arg := range arguments { - if v := reflect.ValueOf(arg); v.Kind() == reflect.Func { - panic(fmt.Sprintf("cannot use Func in expectations. Use mock.AnythingOfType(\"%T\")", arg)) - } - } - - m.mutex.Lock() - defer m.mutex.Unlock() - c := newCall(m, methodName, assert.CallerInfo(), arguments...) - m.ExpectedCalls = append(m.ExpectedCalls, c) - return c -} - -// /* -// Recording and responding to activity -// */ - -func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *Call) { - var expectedCall *Call - - for i, call := range m.ExpectedCalls { - if call.Method == method { - _, diffCount := call.Arguments.Diff(arguments) - if diffCount == 0 { - expectedCall = call - if call.Repeatability > -1 { - return i, call - } - } - } - } - - return -1, expectedCall -} - -type matchCandidate struct { - call *Call - mismatch string - diffCount int -} - -func (c matchCandidate) isBetterMatchThan(other matchCandidate) bool { - if c.call == nil { - return false - } - if other.call == nil { - return true - } - - if c.diffCount > other.diffCount { - return false - } - if c.diffCount < other.diffCount { - return true - } - - if c.call.Repeatability > 0 && other.call.Repeatability <= 0 { - return true - } - return false -} - -func (m *Mock) findClosestCall(method string, arguments ...interface{}) (*Call, string) { - var bestMatch matchCandidate - - for _, call := range m.expectedCalls() { - if call.Method == method { - - errInfo, tempDiffCount := call.Arguments.Diff(arguments) - tempCandidate := matchCandidate{ - call: call, - mismatch: errInfo, - diffCount: tempDiffCount, - } - if tempCandidate.isBetterMatchThan(bestMatch) { - bestMatch = tempCandidate - } - } - } - - return bestMatch.call, bestMatch.mismatch -} - -func callString(method string, arguments Arguments, includeArgumentValues bool) string { - var argValsString string - if includeArgumentValues { - var argVals []string - for argIndex, arg := range arguments { - argVals = append(argVals, fmt.Sprintf("%d: %#v", argIndex, arg)) - } - argValsString = fmt.Sprintf("\n\t\t%s", strings.Join(argVals, "\n\t\t")) - } - - return fmt.Sprintf("%s(%s)%s", method, arguments.String(), argValsString) -} - -// Called tells the mock object that a method has been called, and gets an array -// of arguments to return. Panics if the call is unexpected (i.e. not preceded by -// appropriate .On .Return() calls) -// If Call.WaitFor is set, blocks until the channel is closed or receives a message. -func (m *Mock) Called(arguments ...interface{}) Arguments { - // get the calling function's name - pc, _, _, ok := runtime.Caller(1) - if !ok { - panic("Couldn't get the caller information") - } - functionPath := runtime.FuncForPC(pc).Name() - // Next four lines are required to use GCCGO function naming conventions. - // For Ex: github_com_docker_libkv_store_mock.WatchTree.pN39_github_com_docker_libkv_store_mock.Mock - // uses interface information unlike golang github.com/docker/libkv/store/mock.(*Mock).WatchTree - // With GCCGO we need to remove interface information starting from pN<dd>. - re := regexp.MustCompile("\\.pN\\d+_") - if re.MatchString(functionPath) { - functionPath = re.Split(functionPath, -1)[0] - } - parts := strings.Split(functionPath, ".") - functionName := parts[len(parts)-1] - return m.MethodCalled(functionName, arguments...) -} - -// MethodCalled tells the mock object that the given method has been called, and gets -// an array of arguments to return. Panics if the call is unexpected (i.e. not preceded -// by appropriate .On .Return() calls) -// If Call.WaitFor is set, blocks until the channel is closed or receives a message. -func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Arguments { - m.mutex.Lock() - // TODO: could combine expected and closes in single loop - found, call := m.findExpectedCall(methodName, arguments...) - - if found < 0 { - // expected call found but it has already been called with repeatable times - if call != nil { - m.mutex.Unlock() - m.fail("\nassert: mock: The method has been called over %d times.\n\tEither do one more Mock.On(\"%s\").Return(...), or remove extra call.\n\tThis call was unexpected:\n\t\t%s\n\tat: %s", call.totalCalls, methodName, callString(methodName, arguments, true), assert.CallerInfo()) - } - // we have to fail here - because we don't know what to do - // as the return arguments. This is because: - // - // a) this is a totally unexpected call to this method, - // b) the arguments are not what was expected, or - // c) the developer has forgotten to add an accompanying On...Return pair. - closestCall, mismatch := m.findClosestCall(methodName, arguments...) - m.mutex.Unlock() - - if closestCall != nil { - m.fail("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n\n%s\nDiff: %s", - callString(methodName, arguments, true), - callString(methodName, closestCall.Arguments, true), - diffArguments(closestCall.Arguments, arguments), - strings.TrimSpace(mismatch), - ) - } else { - m.fail("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", methodName, methodName, callString(methodName, arguments, true), assert.CallerInfo()) - } - } - - for _, requirement := range call.requires { - if satisfied, _ := requirement.Parent.checkExpectation(requirement); !satisfied { - m.mutex.Unlock() - m.fail("mock: Unexpected Method Call\n-----------------------------\n\n%s\n\nMust not be called before%s:\n\n%s", - callString(call.Method, call.Arguments, true), - func() (s string) { - if requirement.totalCalls > 0 { - s = " another call of" - } - if call.Parent != requirement.Parent { - s += " method from another mock instance" - } - return - }(), - callString(requirement.Method, requirement.Arguments, true), - ) - } - } - - if call.Repeatability == 1 { - call.Repeatability = -1 - } else if call.Repeatability > 1 { - call.Repeatability-- - } - call.totalCalls++ - - // add the call - m.Calls = append(m.Calls, *newCall(m, methodName, assert.CallerInfo(), arguments...)) - m.mutex.Unlock() - - // block if specified - if call.WaitFor != nil { - <-call.WaitFor - } else { - time.Sleep(call.waitTime) - } - - m.mutex.Lock() - panicMsg := call.PanicMsg - m.mutex.Unlock() - if panicMsg != nil { - panic(*panicMsg) - } - - m.mutex.Lock() - runFn := call.RunFn - m.mutex.Unlock() - - if runFn != nil { - runFn(arguments) - } - - m.mutex.Lock() - returnArgs := call.ReturnArguments - m.mutex.Unlock() - - return returnArgs -} - -/* - Assertions -*/ - -type assertExpectationser interface { - AssertExpectations(TestingT) bool -} - -// AssertExpectationsForObjects asserts that everything specified with On and Return -// of the specified objects was in fact called as expected. -// -// Calls may have occurred in any order. -func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - for _, obj := range testObjects { - if m, ok := obj.(*Mock); ok { - t.Logf("Deprecated mock.AssertExpectationsForObjects(myMock.Mock) use mock.AssertExpectationsForObjects(myMock)") - obj = m - } - m := obj.(assertExpectationser) - if !m.AssertExpectations(t) { - t.Logf("Expectations didn't match for Mock: %+v", reflect.TypeOf(m)) - return false - } - } - return true -} - -// AssertExpectations asserts that everything specified with On and Return was -// in fact called as expected. Calls may have occurred in any order. -func (m *Mock) AssertExpectations(t TestingT) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - m.mutex.Lock() - defer m.mutex.Unlock() - var failedExpectations int - - // iterate through each expectation - expectedCalls := m.expectedCalls() - for _, expectedCall := range expectedCalls { - satisfied, reason := m.checkExpectation(expectedCall) - if !satisfied { - failedExpectations++ - } - t.Logf(reason) - } - - if failedExpectations != 0 { - t.Errorf("FAIL: %d out of %d expectation(s) were met.\n\tThe code you are testing needs to make %d more call(s).\n\tat: %s", len(expectedCalls)-failedExpectations, len(expectedCalls), failedExpectations, assert.CallerInfo()) - } - - return failedExpectations == 0 -} - -func (m *Mock) checkExpectation(call *Call) (bool, string) { - if !call.optional && !m.methodWasCalled(call.Method, call.Arguments) && call.totalCalls == 0 { - return false, fmt.Sprintf("FAIL:\t%s(%s)\n\t\tat: %s", call.Method, call.Arguments.String(), call.callerInfo) - } - if call.Repeatability > 0 { - return false, fmt.Sprintf("FAIL:\t%s(%s)\n\t\tat: %s", call.Method, call.Arguments.String(), call.callerInfo) - } - return true, fmt.Sprintf("PASS:\t%s(%s)", call.Method, call.Arguments.String()) -} - -// AssertNumberOfCalls asserts that the method was called expectedCalls times. -func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls int) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - m.mutex.Lock() - defer m.mutex.Unlock() - var actualCalls int - for _, call := range m.calls() { - if call.Method == methodName { - actualCalls++ - } - } - return assert.Equal(t, expectedCalls, actualCalls, fmt.Sprintf("Expected number of calls (%d) does not match the actual number of calls (%d).", expectedCalls, actualCalls)) -} - -// AssertCalled asserts that the method was called. -// It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method. -func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - m.mutex.Lock() - defer m.mutex.Unlock() - if !m.methodWasCalled(methodName, arguments) { - var calledWithArgs []string - for _, call := range m.calls() { - calledWithArgs = append(calledWithArgs, fmt.Sprintf("%v", call.Arguments)) - } - if len(calledWithArgs) == 0 { - return assert.Fail(t, "Should have called with given arguments", - fmt.Sprintf("Expected %q to have been called with:\n%v\nbut no actual calls happened", methodName, arguments)) - } - return assert.Fail(t, "Should have called with given arguments", - fmt.Sprintf("Expected %q to have been called with:\n%v\nbut actual calls were:\n %v", methodName, arguments, strings.Join(calledWithArgs, "\n"))) - } - return true -} - -// AssertNotCalled asserts that the method was not called. -// It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method. -func (m *Mock) AssertNotCalled(t TestingT, methodName string, arguments ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - m.mutex.Lock() - defer m.mutex.Unlock() - if m.methodWasCalled(methodName, arguments) { - return assert.Fail(t, "Should not have called with given arguments", - fmt.Sprintf("Expected %q to not have been called with:\n%v\nbut actually it was.", methodName, arguments)) - } - return true -} - -// IsMethodCallable checking that the method can be called -// If the method was called more than `Repeatability` return false -func (m *Mock) IsMethodCallable(t TestingT, methodName string, arguments ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - m.mutex.Lock() - defer m.mutex.Unlock() - - for _, v := range m.ExpectedCalls { - if v.Method != methodName { - continue - } - if len(arguments) != len(v.Arguments) { - continue - } - if v.Repeatability < v.totalCalls { - continue - } - if isArgsEqual(v.Arguments, arguments) { - return true - } - } - return false -} - -// isArgsEqual compares arguments -func isArgsEqual(expected Arguments, args []interface{}) bool { - if len(expected) != len(args) { - return false - } - for i, v := range args { - if !reflect.DeepEqual(expected[i], v) { - return false - } - } - return true -} - -func (m *Mock) methodWasCalled(methodName string, expected []interface{}) bool { - for _, call := range m.calls() { - if call.Method == methodName { - - _, differences := Arguments(expected).Diff(call.Arguments) - - if differences == 0 { - // found the expected call - return true - } - - } - } - // we didn't find the expected call - return false -} - -func (m *Mock) expectedCalls() []*Call { - return append([]*Call{}, m.ExpectedCalls...) -} - -func (m *Mock) calls() []Call { - return append([]Call{}, m.Calls...) -} - -/* - Arguments -*/ - -// Arguments holds an array of method arguments or return values. -type Arguments []interface{} - -const ( - // Anything is used in Diff and Assert when the argument being tested - // shouldn't be taken into consideration. - Anything = "mock.Anything" -) - -// AnythingOfTypeArgument is a string that contains the type of an argument -// for use when type checking. Used in Diff and Assert. -type AnythingOfTypeArgument string - -// AnythingOfType returns an AnythingOfTypeArgument object containing the -// name of the type to check for. Used in Diff and Assert. -// -// For example: -// Assert(t, AnythingOfType("string"), AnythingOfType("int")) -func AnythingOfType(t string) AnythingOfTypeArgument { - return AnythingOfTypeArgument(t) -} - -// IsTypeArgument is a struct that contains the type of an argument -// for use when type checking. This is an alternative to AnythingOfType. -// Used in Diff and Assert. -type IsTypeArgument struct { - t interface{} -} - -// IsType returns an IsTypeArgument object containing the type to check for. -// You can provide a zero-value of the type to check. This is an -// alternative to AnythingOfType. Used in Diff and Assert. -// -// For example: -// Assert(t, IsType(""), IsType(0)) -func IsType(t interface{}) *IsTypeArgument { - return &IsTypeArgument{t: t} -} - -// argumentMatcher performs custom argument matching, returning whether or -// not the argument is matched by the expectation fixture function. -type argumentMatcher struct { - // fn is a function which accepts one argument, and returns a bool. - fn reflect.Value -} - -func (f argumentMatcher) Matches(argument interface{}) bool { - expectType := f.fn.Type().In(0) - expectTypeNilSupported := false - switch expectType.Kind() { - case reflect.Interface, reflect.Chan, reflect.Func, reflect.Map, reflect.Slice, reflect.Ptr: - expectTypeNilSupported = true - } - - argType := reflect.TypeOf(argument) - var arg reflect.Value - if argType == nil { - arg = reflect.New(expectType).Elem() - } else { - arg = reflect.ValueOf(argument) - } - - if argType == nil && !expectTypeNilSupported { - panic(errors.New("attempting to call matcher with nil for non-nil expected type")) - } - if argType == nil || argType.AssignableTo(expectType) { - result := f.fn.Call([]reflect.Value{arg}) - return result[0].Bool() - } - return false -} - -func (f argumentMatcher) String() string { - return fmt.Sprintf("func(%s) bool", f.fn.Type().In(0).String()) -} - -// MatchedBy can be used to match a mock call based on only certain properties -// from a complex struct or some calculation. It takes a function that will be -// evaluated with the called argument and will return true when there's a match -// and false otherwise. -// -// Example: -// m.On("Do", MatchedBy(func(req *http.Request) bool { return req.Host == "example.com" })) -// -// |fn|, must be a function accepting a single argument (of the expected type) -// which returns a bool. If |fn| doesn't match the required signature, -// MatchedBy() panics. -func MatchedBy(fn interface{}) argumentMatcher { - fnType := reflect.TypeOf(fn) - - if fnType.Kind() != reflect.Func { - panic(fmt.Sprintf("assert: arguments: %s is not a func", fn)) - } - if fnType.NumIn() != 1 { - panic(fmt.Sprintf("assert: arguments: %s does not take exactly one argument", fn)) - } - if fnType.NumOut() != 1 || fnType.Out(0).Kind() != reflect.Bool { - panic(fmt.Sprintf("assert: arguments: %s does not return a bool", fn)) - } - - return argumentMatcher{fn: reflect.ValueOf(fn)} -} - -// Get Returns the argument at the specified index. -func (args Arguments) Get(index int) interface{} { - if index+1 > len(args) { - panic(fmt.Sprintf("assert: arguments: Cannot call Get(%d) because there are %d argument(s).", index, len(args))) - } - return args[index] -} - -// Is gets whether the objects match the arguments specified. -func (args Arguments) Is(objects ...interface{}) bool { - for i, obj := range args { - if obj != objects[i] { - return false - } - } - return true -} - -// Diff gets a string describing the differences between the arguments -// and the specified objects. -// -// Returns the diff string and number of differences found. -func (args Arguments) Diff(objects []interface{}) (string, int) { - // TODO: could return string as error and nil for No difference - - output := "\n" - var differences int - - maxArgCount := len(args) - if len(objects) > maxArgCount { - maxArgCount = len(objects) - } - - for i := 0; i < maxArgCount; i++ { - var actual, expected interface{} - var actualFmt, expectedFmt string - - if len(objects) <= i { - actual = "(Missing)" - actualFmt = "(Missing)" - } else { - actual = objects[i] - actualFmt = fmt.Sprintf("(%[1]T=%[1]v)", actual) - } - - if len(args) <= i { - expected = "(Missing)" - expectedFmt = "(Missing)" - } else { - expected = args[i] - expectedFmt = fmt.Sprintf("(%[1]T=%[1]v)", expected) - } - - if matcher, ok := expected.(argumentMatcher); ok { - var matches bool - func() { - defer func() { - if r := recover(); r != nil { - actualFmt = fmt.Sprintf("panic in argument matcher: %v", r) - } - }() - matches = matcher.Matches(actual) - }() - if matches { - output = fmt.Sprintf("%s\t%d: PASS: %s matched by %s\n", output, i, actualFmt, matcher) - } else { - differences++ - output = fmt.Sprintf("%s\t%d: FAIL: %s not matched by %s\n", output, i, actualFmt, matcher) - } - } else if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() { - // type checking - if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) { - // not match - differences++ - output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt) - } - } else if reflect.TypeOf(expected) == reflect.TypeOf((*IsTypeArgument)(nil)) { - t := expected.(*IsTypeArgument).t - if reflect.TypeOf(t) != reflect.TypeOf(actual) { - differences++ - output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, reflect.TypeOf(t).Name(), reflect.TypeOf(actual).Name(), actualFmt) - } - } else { - // normal checking - - if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) { - // match - output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt) - } else { - // not match - differences++ - output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt) - } - } - - } - - if differences == 0 { - return "No differences.", differences - } - - return output, differences -} - -// Assert compares the arguments with the specified objects and fails if -// they do not exactly match. -func (args Arguments) Assert(t TestingT, objects ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - // get the differences - diff, diffCount := args.Diff(objects) - - if diffCount == 0 { - return true - } - - // there are differences... report them... - t.Logf(diff) - t.Errorf("%sArguments do not match.", assert.CallerInfo()) - - return false -} - -// String gets the argument at the specified index. Panics if there is no argument, or -// if the argument is of the wrong type. -// -// If no index is provided, String() returns a complete string representation -// of the arguments. -func (args Arguments) String(indexOrNil ...int) string { - if len(indexOrNil) == 0 { - // normal String() method - return a string representation of the args - var argsStr []string - for _, arg := range args { - argsStr = append(argsStr, fmt.Sprintf("%T", arg)) // handles nil nicely - } - return strings.Join(argsStr, ",") - } else if len(indexOrNil) == 1 { - // Index has been specified - get the argument at that index - index := indexOrNil[0] - var s string - var ok bool - if s, ok = args.Get(index).(string); !ok { - panic(fmt.Sprintf("assert: arguments: String(%d) failed because object wasn't correct type: %s", index, args.Get(index))) - } - return s - } - - panic(fmt.Sprintf("assert: arguments: Wrong number of arguments passed to String. Must be 0 or 1, not %d", len(indexOrNil))) -} - -// Int gets the argument at the specified index. Panics if there is no argument, or -// if the argument is of the wrong type. -func (args Arguments) Int(index int) int { - var s int - var ok bool - if s, ok = args.Get(index).(int); !ok { - panic(fmt.Sprintf("assert: arguments: Int(%d) failed because object wasn't correct type: %v", index, args.Get(index))) - } - return s -} - -// Error gets the argument at the specified index. Panics if there is no argument, or -// if the argument is of the wrong type. -func (args Arguments) Error(index int) error { - obj := args.Get(index) - var s error - var ok bool - if obj == nil { - return nil - } - if s, ok = obj.(error); !ok { - panic(fmt.Sprintf("assert: arguments: Error(%d) failed because object wasn't correct type: %v", index, args.Get(index))) - } - return s -} - -// Bool gets the argument at the specified index. Panics if there is no argument, or -// if the argument is of the wrong type. -func (args Arguments) Bool(index int) bool { - var s bool - var ok bool - if s, ok = args.Get(index).(bool); !ok { - panic(fmt.Sprintf("assert: arguments: Bool(%d) failed because object wasn't correct type: %v", index, args.Get(index))) - } - return s -} - -func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { - t := reflect.TypeOf(v) - k := t.Kind() - - if k == reflect.Ptr { - t = t.Elem() - k = t.Kind() - } - return t, k -} - -func diffArguments(expected Arguments, actual Arguments) string { - if len(expected) != len(actual) { - return fmt.Sprintf("Provided %v arguments, mocked for %v arguments", len(expected), len(actual)) - } - - for x := range expected { - if diffString := diff(expected[x], actual[x]); diffString != "" { - return fmt.Sprintf("Difference found in argument %v:\n\n%s", x, diffString) - } - } - - return "" -} - -// diff returns a diff of both values as long as both are of the same type and -// are a struct, map, slice or array. Otherwise it returns an empty string. -func diff(expected interface{}, actual interface{}) string { - if expected == nil || actual == nil { - return "" - } - - et, ek := typeAndKind(expected) - at, _ := typeAndKind(actual) - - if et != at { - return "" - } - - if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array { - return "" - } - - e := spewConfig.Sdump(expected) - a := spewConfig.Sdump(actual) - - diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ - A: difflib.SplitLines(e), - B: difflib.SplitLines(a), - FromFile: "Expected", - FromDate: "", - ToFile: "Actual", - ToDate: "", - Context: 1, - }) - - return diff -} - -var spewConfig = spew.ConfigState{ - Indent: " ", - DisablePointerAddresses: true, - DisableCapacities: true, - SortKeys: true, -} - -type tHelper interface { - Helper() -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/mock/mock_test.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/mock/mock_test.go deleted file mode 100644 index 260bb9c..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/mock/mock_test.go +++ /dev/null @@ -1,2084 +0,0 @@ -package mock - -import ( - "errors" - "fmt" - "regexp" - "runtime" - "sync" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -/* - Test objects -*/ - -// ExampleInterface represents an example interface. -type ExampleInterface interface { - TheExampleMethod(a, b, c int) (int, error) -} - -// TestExampleImplementation is a test implementation of ExampleInterface -type TestExampleImplementation struct { - Mock -} - -func (i *TestExampleImplementation) TheExampleMethod(a, b, c int) (int, error) { - args := i.Called(a, b, c) - return args.Int(0), errors.New("Whoops") -} - -//go:noinline -func (i *TestExampleImplementation) TheExampleMethod2(yesorno bool) { - i.Called(yesorno) -} - -type ExampleType struct { - ran bool -} - -func (i *TestExampleImplementation) TheExampleMethod3(et *ExampleType) error { - args := i.Called(et) - return args.Error(0) -} - -func (i *TestExampleImplementation) TheExampleMethod4(v ExampleInterface) error { - args := i.Called(v) - return args.Error(0) -} - -func (i *TestExampleImplementation) TheExampleMethod5(ch chan struct{}) error { - args := i.Called(ch) - return args.Error(0) -} - -func (i *TestExampleImplementation) TheExampleMethod6(m map[string]bool) error { - args := i.Called(m) - return args.Error(0) -} - -func (i *TestExampleImplementation) TheExampleMethod7(slice []bool) error { - args := i.Called(slice) - return args.Error(0) -} - -func (i *TestExampleImplementation) TheExampleMethodFunc(fn func(string) error) error { - args := i.Called(fn) - return args.Error(0) -} - -func (i *TestExampleImplementation) TheExampleMethodVariadic(a ...int) error { - args := i.Called(a) - return args.Error(0) -} - -func (i *TestExampleImplementation) TheExampleMethodVariadicInterface(a ...interface{}) error { - args := i.Called(a) - return args.Error(0) -} - -func (i *TestExampleImplementation) TheExampleMethodMixedVariadic(a int, b ...int) error { - args := i.Called(a, b) - return args.Error(0) -} - -type ExampleFuncType func(string) error - -func (i *TestExampleImplementation) TheExampleMethodFuncType(fn ExampleFuncType) error { - args := i.Called(fn) - return args.Error(0) -} - -// MockTestingT mocks a test struct -type MockTestingT struct { - logfCount, errorfCount, failNowCount int -} - -const mockTestingTFailNowCalled = "FailNow was called" - -func (m *MockTestingT) Logf(string, ...interface{}) { - m.logfCount++ -} - -func (m *MockTestingT) Errorf(string, ...interface{}) { - m.errorfCount++ -} - -// FailNow mocks the FailNow call. -// It panics in order to mimic the FailNow behavior in the sense that -// the execution stops. -// When expecting this method, the call that invokes it should use the following code: -// -// assert.PanicsWithValue(t, mockTestingTFailNowCalled, func() {...}) -func (m *MockTestingT) FailNow() { - m.failNowCount++ - - // this function should panic now to stop the execution as expected - panic(mockTestingTFailNowCalled) -} - -/* - Mock -*/ - -func Test_Mock_TestData(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - if assert.NotNil(t, mockedService.TestData()) { - - mockedService.TestData().Set("something", 123) - assert.Equal(t, 123, mockedService.TestData().Get("something").Data()) - } -} - -func Test_Mock_On(t *testing.T) { - - // make a test impl object - var mockedService = new(TestExampleImplementation) - - c := mockedService.On("TheExampleMethod") - assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls) - assert.Equal(t, "TheExampleMethod", c.Method) -} - -func Test_Mock_Chained_On(t *testing.T) { - // make a test impl object - var mockedService = new(TestExampleImplementation) - - // determine our current line number so we can assert the expected calls callerInfo properly - _, filename, line, _ := runtime.Caller(0) - mockedService. - On("TheExampleMethod", 1, 2, 3). - Return(0). - On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")). - Return(nil) - - expectedCalls := []*Call{ - { - Parent: &mockedService.Mock, - Method: "TheExampleMethod", - Arguments: []interface{}{1, 2, 3}, - ReturnArguments: []interface{}{0}, - callerInfo: []string{fmt.Sprintf("%s:%d", filename, line+2)}, - }, - { - Parent: &mockedService.Mock, - Method: "TheExampleMethod3", - Arguments: []interface{}{AnythingOfType("*mock.ExampleType")}, - ReturnArguments: []interface{}{nil}, - callerInfo: []string{fmt.Sprintf("%s:%d", filename, line+4)}, - }, - } - assert.Equal(t, expectedCalls, mockedService.ExpectedCalls) -} - -func Test_Mock_On_WithArgs(t *testing.T) { - - // make a test impl object - var mockedService = new(TestExampleImplementation) - - c := mockedService.On("TheExampleMethod", 1, 2, 3, 4) - - assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls) - assert.Equal(t, "TheExampleMethod", c.Method) - assert.Equal(t, Arguments{1, 2, 3, 4}, c.Arguments) -} - -func Test_Mock_On_WithFuncArg(t *testing.T) { - - // make a test impl object - var mockedService = new(TestExampleImplementation) - - c := mockedService. - On("TheExampleMethodFunc", AnythingOfType("func(string) error")). - Return(nil) - - assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls) - assert.Equal(t, "TheExampleMethodFunc", c.Method) - assert.Equal(t, 1, len(c.Arguments)) - assert.Equal(t, AnythingOfType("func(string) error"), c.Arguments[0]) - - fn := func(string) error { return nil } - - assert.NotPanics(t, func() { - mockedService.TheExampleMethodFunc(fn) - }) -} - -func Test_Mock_On_WithIntArgMatcher(t *testing.T) { - var mockedService TestExampleImplementation - - mockedService.On("TheExampleMethod", - MatchedBy(func(a int) bool { - return a == 1 - }), MatchedBy(func(b int) bool { - return b == 2 - }), MatchedBy(func(c int) bool { - return c == 3 - })).Return(0, nil) - - assert.Panics(t, func() { - mockedService.TheExampleMethod(1, 2, 4) - }) - assert.Panics(t, func() { - mockedService.TheExampleMethod(2, 2, 3) - }) - assert.NotPanics(t, func() { - mockedService.TheExampleMethod(1, 2, 3) - }) -} - -func Test_Mock_On_WithArgMatcherThatPanics(t *testing.T) { - var mockedService TestExampleImplementation - - mockedService.On("TheExampleMethod2", MatchedBy(func(_ interface{}) bool { - panic("try to lock mockedService") - })).Return() - - defer func() { - assertedExpectations := make(chan struct{}) - go func() { - tt := new(testing.T) - mockedService.AssertExpectations(tt) - close(assertedExpectations) - }() - select { - case <-assertedExpectations: - case <-time.After(time.Second): - t.Fatal("AssertExpectations() deadlocked, did the panic leave mockedService locked?") - } - }() - - assert.Panics(t, func() { - mockedService.TheExampleMethod2(false) - }) -} - -func TestMock_WithTest(t *testing.T) { - var ( - mockedService TestExampleImplementation - mockedTest MockTestingT - ) - - mockedService.Test(&mockedTest) - mockedService.On("TheExampleMethod", 1, 2, 3).Return(0, nil) - - // Test that on an expected call, the test was not failed - - mockedService.TheExampleMethod(1, 2, 3) - - // Assert that Errorf and FailNow were not called - assert.Equal(t, 0, mockedTest.errorfCount) - assert.Equal(t, 0, mockedTest.failNowCount) - - // Test that on unexpected call, the mocked test was called to fail the test - - assert.PanicsWithValue(t, mockTestingTFailNowCalled, func() { - mockedService.TheExampleMethod(1, 1, 1) - }) - - // Assert that Errorf and FailNow were called once - assert.Equal(t, 1, mockedTest.errorfCount) - assert.Equal(t, 1, mockedTest.failNowCount) -} - -func Test_Mock_On_WithPtrArgMatcher(t *testing.T) { - var mockedService TestExampleImplementation - - mockedService.On("TheExampleMethod3", - MatchedBy(func(a *ExampleType) bool { return a != nil && a.ran == true }), - ).Return(nil) - - mockedService.On("TheExampleMethod3", - MatchedBy(func(a *ExampleType) bool { return a != nil && a.ran == false }), - ).Return(errors.New("error")) - - mockedService.On("TheExampleMethod3", - MatchedBy(func(a *ExampleType) bool { return a == nil }), - ).Return(errors.New("error2")) - - assert.Equal(t, mockedService.TheExampleMethod3(&ExampleType{true}), nil) - assert.EqualError(t, mockedService.TheExampleMethod3(&ExampleType{false}), "error") - assert.EqualError(t, mockedService.TheExampleMethod3(nil), "error2") -} - -func Test_Mock_On_WithFuncArgMatcher(t *testing.T) { - var mockedService TestExampleImplementation - - fixture1, fixture2 := errors.New("fixture1"), errors.New("fixture2") - - mockedService.On("TheExampleMethodFunc", - MatchedBy(func(a func(string) error) bool { return a != nil && a("string") == fixture1 }), - ).Return(errors.New("fixture1")) - - mockedService.On("TheExampleMethodFunc", - MatchedBy(func(a func(string) error) bool { return a != nil && a("string") == fixture2 }), - ).Return(errors.New("fixture2")) - - mockedService.On("TheExampleMethodFunc", - MatchedBy(func(a func(string) error) bool { return a == nil }), - ).Return(errors.New("fixture3")) - - assert.EqualError(t, mockedService.TheExampleMethodFunc( - func(string) error { return fixture1 }), "fixture1") - assert.EqualError(t, mockedService.TheExampleMethodFunc( - func(string) error { return fixture2 }), "fixture2") - assert.EqualError(t, mockedService.TheExampleMethodFunc(nil), "fixture3") -} - -func Test_Mock_On_WithInterfaceArgMatcher(t *testing.T) { - var mockedService TestExampleImplementation - - mockedService.On("TheExampleMethod4", - MatchedBy(func(a ExampleInterface) bool { return a == nil }), - ).Return(errors.New("fixture1")) - - assert.EqualError(t, mockedService.TheExampleMethod4(nil), "fixture1") -} - -func Test_Mock_On_WithChannelArgMatcher(t *testing.T) { - var mockedService TestExampleImplementation - - mockedService.On("TheExampleMethod5", - MatchedBy(func(ch chan struct{}) bool { return ch == nil }), - ).Return(errors.New("fixture1")) - - assert.EqualError(t, mockedService.TheExampleMethod5(nil), "fixture1") -} - -func Test_Mock_On_WithMapArgMatcher(t *testing.T) { - var mockedService TestExampleImplementation - - mockedService.On("TheExampleMethod6", - MatchedBy(func(m map[string]bool) bool { return m == nil }), - ).Return(errors.New("fixture1")) - - assert.EqualError(t, mockedService.TheExampleMethod6(nil), "fixture1") -} - -func Test_Mock_On_WithSliceArgMatcher(t *testing.T) { - var mockedService TestExampleImplementation - - mockedService.On("TheExampleMethod7", - MatchedBy(func(slice []bool) bool { return slice == nil }), - ).Return(errors.New("fixture1")) - - assert.EqualError(t, mockedService.TheExampleMethod7(nil), "fixture1") -} - -func Test_Mock_On_WithVariadicFunc(t *testing.T) { - - // make a test impl object - var mockedService = new(TestExampleImplementation) - - c := mockedService. - On("TheExampleMethodVariadic", []int{1, 2, 3}). - Return(nil) - - assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls) - assert.Equal(t, 1, len(c.Arguments)) - assert.Equal(t, []int{1, 2, 3}, c.Arguments[0]) - - assert.NotPanics(t, func() { - mockedService.TheExampleMethodVariadic(1, 2, 3) - }) - assert.Panics(t, func() { - mockedService.TheExampleMethodVariadic(1, 2) - }) - -} - -func Test_Mock_On_WithMixedVariadicFunc(t *testing.T) { - - // make a test impl object - var mockedService = new(TestExampleImplementation) - - c := mockedService. - On("TheExampleMethodMixedVariadic", 1, []int{2, 3, 4}). - Return(nil) - - assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls) - assert.Equal(t, 2, len(c.Arguments)) - assert.Equal(t, 1, c.Arguments[0]) - assert.Equal(t, []int{2, 3, 4}, c.Arguments[1]) - - assert.NotPanics(t, func() { - mockedService.TheExampleMethodMixedVariadic(1, 2, 3, 4) - }) - assert.Panics(t, func() { - mockedService.TheExampleMethodMixedVariadic(1, 2, 3, 5) - }) - -} - -func Test_Mock_On_WithVariadicFuncWithInterface(t *testing.T) { - - // make a test impl object - var mockedService = new(TestExampleImplementation) - - c := mockedService.On("TheExampleMethodVariadicInterface", []interface{}{1, 2, 3}). - Return(nil) - - assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls) - assert.Equal(t, 1, len(c.Arguments)) - assert.Equal(t, []interface{}{1, 2, 3}, c.Arguments[0]) - - assert.NotPanics(t, func() { - mockedService.TheExampleMethodVariadicInterface(1, 2, 3) - }) - assert.Panics(t, func() { - mockedService.TheExampleMethodVariadicInterface(1, 2) - }) - -} - -func Test_Mock_On_WithVariadicFuncWithEmptyInterfaceArray(t *testing.T) { - - // make a test impl object - var mockedService = new(TestExampleImplementation) - - var expected []interface{} - c := mockedService. - On("TheExampleMethodVariadicInterface", expected). - Return(nil) - - assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls) - assert.Equal(t, 1, len(c.Arguments)) - assert.Equal(t, expected, c.Arguments[0]) - - assert.NotPanics(t, func() { - mockedService.TheExampleMethodVariadicInterface() - }) - assert.Panics(t, func() { - mockedService.TheExampleMethodVariadicInterface(1, 2) - }) - -} - -func Test_Mock_On_WithFuncPanics(t *testing.T) { - // make a test impl object - var mockedService = new(TestExampleImplementation) - - assert.Panics(t, func() { - mockedService.On("TheExampleMethodFunc", func(string) error { return nil }) - }) -} - -func Test_Mock_On_WithFuncTypeArg(t *testing.T) { - - // make a test impl object - var mockedService = new(TestExampleImplementation) - - c := mockedService. - On("TheExampleMethodFuncType", AnythingOfType("mock.ExampleFuncType")). - Return(nil) - - assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls) - assert.Equal(t, 1, len(c.Arguments)) - assert.Equal(t, AnythingOfType("mock.ExampleFuncType"), c.Arguments[0]) - - fn := func(string) error { return nil } - assert.NotPanics(t, func() { - mockedService.TheExampleMethodFuncType(fn) - }) -} - -func Test_Mock_Unset(t *testing.T) { - // make a test impl object - var mockedService = new(TestExampleImplementation) - - call := mockedService. - On("TheExampleMethodFuncType", "argA"). - Return("blah") - - found, foundCall := mockedService.findExpectedCall("TheExampleMethodFuncType", "argA") - require.NotEqual(t, -1, found) - require.Equal(t, foundCall, call) - - call.Unset() - - found, foundCall = mockedService.findExpectedCall("TheExampleMethodFuncType", "argA") - require.Equal(t, -1, found) - - var expectedCall *Call - require.Equal(t, expectedCall, foundCall) - - fn := func(string) error { return nil } - assert.Panics(t, func() { - mockedService.TheExampleMethodFuncType(fn) - }) -} - -// Since every time you call On it creates a new object -// the last time you call Unset it will only unset the last call -func Test_Mock_Chained_UnsetOnlyUnsetsLastCall(t *testing.T) { - // make a test impl object - var mockedService = new(TestExampleImplementation) - - // determine our current line number so we can assert the expected calls callerInfo properly - _, filename, line, _ := runtime.Caller(0) - mockedService. - On("TheExampleMethod1", 1, 1). - Return(0). - On("TheExampleMethod2", 2, 2). - On("TheExampleMethod3", 3, 3, 3). - Return(nil). - Unset() - - expectedCalls := []*Call{ - { - Parent: &mockedService.Mock, - Method: "TheExampleMethod1", - Arguments: []interface{}{1, 1}, - ReturnArguments: []interface{}{0}, - callerInfo: []string{fmt.Sprintf("%s:%d", filename, line+2)}, - }, - { - Parent: &mockedService.Mock, - Method: "TheExampleMethod2", - Arguments: []interface{}{2, 2}, - ReturnArguments: []interface{}{}, - callerInfo: []string{fmt.Sprintf("%s:%d", filename, line+4)}, - }, - } - assert.Equal(t, 2, len(expectedCalls)) - assert.Equal(t, expectedCalls, mockedService.ExpectedCalls) -} - -func Test_Mock_UnsetIfAlreadyUnsetFails(t *testing.T) { - // make a test impl object - var mockedService = new(TestExampleImplementation) - - mock1 := mockedService. - On("TheExampleMethod1", 1, 1). - Return(1) - - assert.Equal(t, 1, len(mockedService.ExpectedCalls)) - mock1.Unset() - assert.Equal(t, 0, len(mockedService.ExpectedCalls)) - - assert.Panics(t, func() { - mock1.Unset() - }) - - assert.Equal(t, 0, len(mockedService.ExpectedCalls)) -} - -func Test_Mock_UnsetByOnMethodSpec(t *testing.T) { - // make a test impl object - var mockedService = new(TestExampleImplementation) - - mock1 := mockedService. - On("TheExampleMethod", 1, 2, 3). - Return(0, nil) - - assert.Equal(t, 1, len(mockedService.ExpectedCalls)) - mock1.On("TheExampleMethod", 1, 2, 3). - Return(0, nil).Unset() - - assert.Equal(t, 0, len(mockedService.ExpectedCalls)) - - assert.Panics(t, func() { - mock1.Unset() - }) - - assert.Equal(t, 0, len(mockedService.ExpectedCalls)) -} - -func Test_Mock_UnsetByOnMethodSpecAmongOthers(t *testing.T) { - // make a test impl object - var mockedService = new(TestExampleImplementation) - - _, filename, line, _ := runtime.Caller(0) - mock1 := mockedService. - On("TheExampleMethod", 1, 2, 3). - Return(0, nil). - On("TheExampleMethodVariadic", 1, 2, 3, 4, 5).Once(). - Return(nil) - mock1. - On("TheExampleMethodFuncType", Anything). - Return(nil) - - assert.Equal(t, 3, len(mockedService.ExpectedCalls)) - mock1.On("TheExampleMethod", 1, 2, 3). - Return(0, nil).Unset() - - assert.Equal(t, 2, len(mockedService.ExpectedCalls)) - - expectedCalls := []*Call{ - { - Parent: &mockedService.Mock, - Method: "TheExampleMethodVariadic", - Repeatability: 1, - Arguments: []interface{}{1, 2, 3, 4, 5}, - ReturnArguments: []interface{}{nil}, - callerInfo: []string{fmt.Sprintf("%s:%d", filename, line+4)}, - }, - { - Parent: &mockedService.Mock, - Method: "TheExampleMethodFuncType", - Arguments: []interface{}{Anything}, - ReturnArguments: []interface{}{nil}, - callerInfo: []string{fmt.Sprintf("%s:%d", filename, line+7)}, - }, - } - - assert.Equal(t, 2, len(mockedService.ExpectedCalls)) - assert.Equal(t, expectedCalls, mockedService.ExpectedCalls) -} - -func Test_Mock_Unset_WithFuncPanics(t *testing.T) { - // make a test impl object - var mockedService = new(TestExampleImplementation) - mock1 := mockedService.On("TheExampleMethod", 1) - mock1.Arguments = append(mock1.Arguments, func(string) error { return nil }) - - assert.Panics(t, func() { - mock1.Unset() - }) -} - -func Test_Mock_Return(t *testing.T) { - - // make a test impl object - var mockedService = new(TestExampleImplementation) - - c := mockedService. - On("TheExampleMethod", "A", "B", true). - Return(1, "two", true) - - require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) - - call := mockedService.ExpectedCalls[0] - - assert.Equal(t, "TheExampleMethod", call.Method) - assert.Equal(t, "A", call.Arguments[0]) - assert.Equal(t, "B", call.Arguments[1]) - assert.Equal(t, true, call.Arguments[2]) - assert.Equal(t, 1, call.ReturnArguments[0]) - assert.Equal(t, "two", call.ReturnArguments[1]) - assert.Equal(t, true, call.ReturnArguments[2]) - assert.Equal(t, 0, call.Repeatability) - assert.Nil(t, call.WaitFor) -} - -func Test_Mock_Panic(t *testing.T) { - - // make a test impl object - var mockedService = new(TestExampleImplementation) - - c := mockedService. - On("TheExampleMethod", "A", "B", true). - Panic("panic message for example method") - - require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) - - call := mockedService.ExpectedCalls[0] - - assert.Equal(t, "TheExampleMethod", call.Method) - assert.Equal(t, "A", call.Arguments[0]) - assert.Equal(t, "B", call.Arguments[1]) - assert.Equal(t, true, call.Arguments[2]) - assert.Equal(t, 0, call.Repeatability) - assert.Equal(t, 0, call.Repeatability) - assert.Equal(t, "panic message for example method", *call.PanicMsg) - assert.Nil(t, call.WaitFor) -} - -func Test_Mock_Return_WaitUntil(t *testing.T) { - - // make a test impl object - var mockedService = new(TestExampleImplementation) - ch := time.After(time.Second) - - c := mockedService.Mock. - On("TheExampleMethod", "A", "B", true). - WaitUntil(ch). - Return(1, "two", true) - - // assert that the call was created - require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) - - call := mockedService.ExpectedCalls[0] - - assert.Equal(t, "TheExampleMethod", call.Method) - assert.Equal(t, "A", call.Arguments[0]) - assert.Equal(t, "B", call.Arguments[1]) - assert.Equal(t, true, call.Arguments[2]) - assert.Equal(t, 1, call.ReturnArguments[0]) - assert.Equal(t, "two", call.ReturnArguments[1]) - assert.Equal(t, true, call.ReturnArguments[2]) - assert.Equal(t, 0, call.Repeatability) - assert.Equal(t, ch, call.WaitFor) -} - -func Test_Mock_Return_After(t *testing.T) { - - // make a test impl object - var mockedService = new(TestExampleImplementation) - - c := mockedService.Mock. - On("TheExampleMethod", "A", "B", true). - Return(1, "two", true). - After(time.Second) - - require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) - - call := mockedService.Mock.ExpectedCalls[0] - - assert.Equal(t, "TheExampleMethod", call.Method) - assert.Equal(t, "A", call.Arguments[0]) - assert.Equal(t, "B", call.Arguments[1]) - assert.Equal(t, true, call.Arguments[2]) - assert.Equal(t, 1, call.ReturnArguments[0]) - assert.Equal(t, "two", call.ReturnArguments[1]) - assert.Equal(t, true, call.ReturnArguments[2]) - assert.Equal(t, 0, call.Repeatability) - assert.NotEqual(t, nil, call.WaitFor) - -} - -func Test_Mock_Return_Run(t *testing.T) { - - // make a test impl object - var mockedService = new(TestExampleImplementation) - - fn := func(args Arguments) { - arg := args.Get(0).(*ExampleType) - arg.ran = true - } - - c := mockedService.Mock. - On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")). - Return(nil). - Run(fn) - - require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) - - call := mockedService.Mock.ExpectedCalls[0] - - assert.Equal(t, "TheExampleMethod3", call.Method) - assert.Equal(t, AnythingOfType("*mock.ExampleType"), call.Arguments[0]) - assert.Equal(t, nil, call.ReturnArguments[0]) - assert.Equal(t, 0, call.Repeatability) - assert.NotEqual(t, nil, call.WaitFor) - assert.NotNil(t, call.Run) - - et := ExampleType{} - assert.Equal(t, false, et.ran) - mockedService.TheExampleMethod3(&et) - assert.Equal(t, true, et.ran) -} - -func Test_Mock_Return_Run_Out_Of_Order(t *testing.T) { - // make a test impl object - var mockedService = new(TestExampleImplementation) - f := func(args Arguments) { - arg := args.Get(0).(*ExampleType) - arg.ran = true - } - - c := mockedService.Mock. - On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")). - Run(f). - Return(nil) - - require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) - - call := mockedService.Mock.ExpectedCalls[0] - - assert.Equal(t, "TheExampleMethod3", call.Method) - assert.Equal(t, AnythingOfType("*mock.ExampleType"), call.Arguments[0]) - assert.Equal(t, nil, call.ReturnArguments[0]) - assert.Equal(t, 0, call.Repeatability) - assert.NotEqual(t, nil, call.WaitFor) - assert.NotNil(t, call.Run) -} - -func Test_Mock_Return_Once(t *testing.T) { - - // make a test impl object - var mockedService = new(TestExampleImplementation) - - c := mockedService.On("TheExampleMethod", "A", "B", true). - Return(1, "two", true). - Once() - - require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) - - call := mockedService.ExpectedCalls[0] - - assert.Equal(t, "TheExampleMethod", call.Method) - assert.Equal(t, "A", call.Arguments[0]) - assert.Equal(t, "B", call.Arguments[1]) - assert.Equal(t, true, call.Arguments[2]) - assert.Equal(t, 1, call.ReturnArguments[0]) - assert.Equal(t, "two", call.ReturnArguments[1]) - assert.Equal(t, true, call.ReturnArguments[2]) - assert.Equal(t, 1, call.Repeatability) - assert.Nil(t, call.WaitFor) -} - -func Test_Mock_Return_Twice(t *testing.T) { - - // make a test impl object - var mockedService = new(TestExampleImplementation) - - c := mockedService. - On("TheExampleMethod", "A", "B", true). - Return(1, "two", true). - Twice() - - require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) - - call := mockedService.ExpectedCalls[0] - - assert.Equal(t, "TheExampleMethod", call.Method) - assert.Equal(t, "A", call.Arguments[0]) - assert.Equal(t, "B", call.Arguments[1]) - assert.Equal(t, true, call.Arguments[2]) - assert.Equal(t, 1, call.ReturnArguments[0]) - assert.Equal(t, "two", call.ReturnArguments[1]) - assert.Equal(t, true, call.ReturnArguments[2]) - assert.Equal(t, 2, call.Repeatability) - assert.Nil(t, call.WaitFor) -} - -func Test_Mock_Return_Times(t *testing.T) { - - // make a test impl object - var mockedService = new(TestExampleImplementation) - - c := mockedService. - On("TheExampleMethod", "A", "B", true). - Return(1, "two", true). - Times(5) - - require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) - - call := mockedService.ExpectedCalls[0] - - assert.Equal(t, "TheExampleMethod", call.Method) - assert.Equal(t, "A", call.Arguments[0]) - assert.Equal(t, "B", call.Arguments[1]) - assert.Equal(t, true, call.Arguments[2]) - assert.Equal(t, 1, call.ReturnArguments[0]) - assert.Equal(t, "two", call.ReturnArguments[1]) - assert.Equal(t, true, call.ReturnArguments[2]) - assert.Equal(t, 5, call.Repeatability) - assert.Nil(t, call.WaitFor) -} - -func Test_Mock_Return_Nothing(t *testing.T) { - - // make a test impl object - var mockedService = new(TestExampleImplementation) - - c := mockedService. - On("TheExampleMethod", "A", "B", true). - Return() - - require.Equal(t, []*Call{c}, mockedService.ExpectedCalls) - - call := mockedService.ExpectedCalls[0] - - assert.Equal(t, "TheExampleMethod", call.Method) - assert.Equal(t, "A", call.Arguments[0]) - assert.Equal(t, "B", call.Arguments[1]) - assert.Equal(t, true, call.Arguments[2]) - assert.Equal(t, 0, len(call.ReturnArguments)) -} - -func Test_Mock_Return_NotBefore_In_Order(t *testing.T) { - var mockedService = new(TestExampleImplementation) - - b := mockedService. - On("TheExampleMethod", 1, 2, 3). - Return(4, nil) - c := mockedService. - On("TheExampleMethod2", true). - Return(). - NotBefore(b) - - require.Equal(t, []*Call{b, c}, mockedService.ExpectedCalls) - require.NotPanics(t, func() { - mockedService.TheExampleMethod(1, 2, 3) - }) - require.NotPanics(t, func() { - mockedService.TheExampleMethod2(true) - }) -} - -func Test_Mock_Return_NotBefore_Out_Of_Order(t *testing.T) { - var mockedService = new(TestExampleImplementation) - - b := mockedService. - On("TheExampleMethod", 1, 2, 3). - Return(4, nil).Twice() - c := mockedService. - On("TheExampleMethod2", true). - Return(). - NotBefore(b) - - require.Equal(t, []*Call{b, c}, mockedService.ExpectedCalls) - - expectedPanicString := `mock: Unexpected Method Call ------------------------------ - -TheExampleMethod2(bool) - 0: true - -Must not be called before: - -TheExampleMethod(int,int,int) - 0: 1 - 1: 2 - 2: 3` - require.PanicsWithValue(t, expectedPanicString, func() { - mockedService.TheExampleMethod2(true) - }) -} - -func Test_Mock_Return_NotBefore_Not_Enough_Times(t *testing.T) { - var mockedService = new(TestExampleImplementation) - - b := mockedService. - On("TheExampleMethod", 1, 2, 3). - Return(4, nil).Twice() - c := mockedService. - On("TheExampleMethod2", true). - Return(). - NotBefore(b) - - require.Equal(t, []*Call{b, c}, mockedService.ExpectedCalls) - - require.NotPanics(t, func() { - mockedService.TheExampleMethod(1, 2, 3) - }) - expectedPanicString := `mock: Unexpected Method Call ------------------------------ - -TheExampleMethod2(bool) - 0: true - -Must not be called before another call of: - -TheExampleMethod(int,int,int) - 0: 1 - 1: 2 - 2: 3` - require.PanicsWithValue(t, expectedPanicString, func() { - mockedService.TheExampleMethod2(true) - }) -} - -func Test_Mock_Return_NotBefore_Different_Mock_In_Order(t *testing.T) { - var ( - mockedService1 = new(TestExampleImplementation) - mockedService2 = new(TestExampleImplementation) - ) - - b := mockedService1. - On("TheExampleMethod", 1, 2, 3). - Return(4, nil) - c := mockedService2. - On("TheExampleMethod2", true). - Return(). - NotBefore(b) - - require.Equal(t, []*Call{c}, mockedService2.ExpectedCalls) - require.NotPanics(t, func() { - mockedService1.TheExampleMethod(1, 2, 3) - }) - require.NotPanics(t, func() { - mockedService2.TheExampleMethod2(true) - }) -} -func Test_Mock_Return_NotBefore_Different_Mock_Out_Of_Order(t *testing.T) { - var ( - mockedService1 = new(TestExampleImplementation) - mockedService2 = new(TestExampleImplementation) - ) - - b := mockedService1. - On("TheExampleMethod", 1, 2, 3). - Return(4, nil) - c := mockedService2. - On("TheExampleMethod2", true). - Return(). - NotBefore(b) - - require.Equal(t, []*Call{c}, mockedService2.ExpectedCalls) - - expectedPanicString := `mock: Unexpected Method Call ------------------------------ - -TheExampleMethod2(bool) - 0: true - -Must not be called before method from another mock instance: - -TheExampleMethod(int,int,int) - 0: 1 - 1: 2 - 2: 3` - require.PanicsWithValue(t, expectedPanicString, func() { - mockedService2.TheExampleMethod2(true) - }) -} - -func Test_Mock_Return_NotBefore_In_Order_With_Non_Dependant(t *testing.T) { - var mockedService = new(TestExampleImplementation) - - a := mockedService. - On("TheExampleMethod", 1, 2, 3). - Return(4, nil) - b := mockedService. - On("TheExampleMethod", 4, 5, 6). - Return(4, nil) - c := mockedService. - On("TheExampleMethod2", true). - Return(). - NotBefore(a, b) - d := mockedService. - On("TheExampleMethod7", []bool{}).Return(nil) - - require.Equal(t, []*Call{a, b, c, d}, mockedService.ExpectedCalls) - require.NotPanics(t, func() { - mockedService.TheExampleMethod7([]bool{}) - }) - require.NotPanics(t, func() { - mockedService.TheExampleMethod(1, 2, 3) - }) - require.NotPanics(t, func() { - mockedService.TheExampleMethod7([]bool{}) - }) - require.NotPanics(t, func() { - mockedService.TheExampleMethod(4, 5, 6) - }) - require.NotPanics(t, func() { - mockedService.TheExampleMethod7([]bool{}) - }) - require.NotPanics(t, func() { - mockedService.TheExampleMethod2(true) - }) - require.NotPanics(t, func() { - mockedService.TheExampleMethod7([]bool{}) - }) -} - -func Test_Mock_Return_NotBefore_Orphan_Call(t *testing.T) { - var mockedService = new(TestExampleImplementation) - - require.PanicsWithValue(t, "not before calls must be created with Mock.On()", func() { - mockedService. - On("TheExampleMethod2", true). - Return(). - NotBefore(&Call{Method: "Not", Arguments: Arguments{"how", "it's"}, ReturnArguments: Arguments{"done"}}) - }) -} - -func Test_Mock_findExpectedCall(t *testing.T) { - - m := new(Mock) - m.On("One", 1).Return("one") - m.On("Two", 2).Return("two") - m.On("Two", 3).Return("three") - - f, c := m.findExpectedCall("Two", 3) - - if assert.Equal(t, 2, f) { - if assert.NotNil(t, c) { - assert.Equal(t, "Two", c.Method) - assert.Equal(t, 3, c.Arguments[0]) - assert.Equal(t, "three", c.ReturnArguments[0]) - } - } - -} - -func Test_Mock_findExpectedCall_For_Unknown_Method(t *testing.T) { - - m := new(Mock) - m.On("One", 1).Return("one") - m.On("Two", 2).Return("two") - m.On("Two", 3).Return("three") - - f, _ := m.findExpectedCall("Two") - - assert.Equal(t, -1, f) - -} - -func Test_Mock_findExpectedCall_Respects_Repeatability(t *testing.T) { - - m := new(Mock) - m.On("One", 1).Return("one") - m.On("Two", 2).Return("two").Once() - m.On("Two", 3).Return("three").Twice() - m.On("Two", 3).Return("three").Times(8) - - f, c := m.findExpectedCall("Two", 3) - - if assert.Equal(t, 2, f) { - if assert.NotNil(t, c) { - assert.Equal(t, "Two", c.Method) - assert.Equal(t, 3, c.Arguments[0]) - assert.Equal(t, "three", c.ReturnArguments[0]) - } - } - - c = m.On("Once", 1).Return("one").Once() - c.Repeatability = -1 - f, c = m.findExpectedCall("Once", 1) - if assert.Equal(t, -1, f) { - if assert.NotNil(t, c) { - assert.Equal(t, "Once", c.Method) - assert.Equal(t, 1, c.Arguments[0]) - assert.Equal(t, "one", c.ReturnArguments[0]) - } - } -} - -func Test_callString(t *testing.T) { - - assert.Equal(t, `Method(int,bool,string)`, callString("Method", []interface{}{1, true, "something"}, false)) - assert.Equal(t, `Method(<nil>)`, callString("Method", []interface{}{nil}, false)) - -} - -func Test_Mock_Called(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - mockedService.On("Test_Mock_Called", 1, 2, 3).Return(5, "6", true) - - returnArguments := mockedService.Called(1, 2, 3) - - if assert.Equal(t, 1, len(mockedService.Calls)) { - assert.Equal(t, "Test_Mock_Called", mockedService.Calls[0].Method) - assert.Equal(t, 1, mockedService.Calls[0].Arguments[0]) - assert.Equal(t, 2, mockedService.Calls[0].Arguments[1]) - assert.Equal(t, 3, mockedService.Calls[0].Arguments[2]) - } - - if assert.Equal(t, 3, len(returnArguments)) { - assert.Equal(t, 5, returnArguments[0]) - assert.Equal(t, "6", returnArguments[1]) - assert.Equal(t, true, returnArguments[2]) - } - -} - -func asyncCall(m *Mock, ch chan Arguments) { - ch <- m.Called(1, 2, 3) -} - -func Test_Mock_Called_blocks(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - mockedService.Mock.On("asyncCall", 1, 2, 3).Return(5, "6", true).After(2 * time.Millisecond) - - ch := make(chan Arguments) - - go asyncCall(&mockedService.Mock, ch) - - select { - case <-ch: - t.Fatal("should have waited") - case <-time.After(1 * time.Millisecond): - } - - returnArguments := <-ch - - if assert.Equal(t, 1, len(mockedService.Mock.Calls)) { - assert.Equal(t, "asyncCall", mockedService.Mock.Calls[0].Method) - assert.Equal(t, 1, mockedService.Mock.Calls[0].Arguments[0]) - assert.Equal(t, 2, mockedService.Mock.Calls[0].Arguments[1]) - assert.Equal(t, 3, mockedService.Mock.Calls[0].Arguments[2]) - } - - if assert.Equal(t, 3, len(returnArguments)) { - assert.Equal(t, 5, returnArguments[0]) - assert.Equal(t, "6", returnArguments[1]) - assert.Equal(t, true, returnArguments[2]) - } - -} - -func Test_Mock_Called_For_Bounded_Repeatability(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - mockedService. - On("Test_Mock_Called_For_Bounded_Repeatability", 1, 2, 3). - Return(5, "6", true). - Once() - mockedService. - On("Test_Mock_Called_For_Bounded_Repeatability", 1, 2, 3). - Return(-1, "hi", false) - - returnArguments1 := mockedService.Called(1, 2, 3) - returnArguments2 := mockedService.Called(1, 2, 3) - - if assert.Equal(t, 2, len(mockedService.Calls)) { - assert.Equal(t, "Test_Mock_Called_For_Bounded_Repeatability", mockedService.Calls[0].Method) - assert.Equal(t, 1, mockedService.Calls[0].Arguments[0]) - assert.Equal(t, 2, mockedService.Calls[0].Arguments[1]) - assert.Equal(t, 3, mockedService.Calls[0].Arguments[2]) - - assert.Equal(t, "Test_Mock_Called_For_Bounded_Repeatability", mockedService.Calls[1].Method) - assert.Equal(t, 1, mockedService.Calls[1].Arguments[0]) - assert.Equal(t, 2, mockedService.Calls[1].Arguments[1]) - assert.Equal(t, 3, mockedService.Calls[1].Arguments[2]) - } - - if assert.Equal(t, 3, len(returnArguments1)) { - assert.Equal(t, 5, returnArguments1[0]) - assert.Equal(t, "6", returnArguments1[1]) - assert.Equal(t, true, returnArguments1[2]) - } - - if assert.Equal(t, 3, len(returnArguments2)) { - assert.Equal(t, -1, returnArguments2[0]) - assert.Equal(t, "hi", returnArguments2[1]) - assert.Equal(t, false, returnArguments2[2]) - } - -} - -func Test_Mock_Called_For_SetTime_Expectation(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - mockedService.On("TheExampleMethod", 1, 2, 3).Return(5, "6", true).Times(4) - - mockedService.TheExampleMethod(1, 2, 3) - mockedService.TheExampleMethod(1, 2, 3) - mockedService.TheExampleMethod(1, 2, 3) - mockedService.TheExampleMethod(1, 2, 3) - assert.Panics(t, func() { - mockedService.TheExampleMethod(1, 2, 3) - }) - -} - -func Test_Mock_Called_Unexpected(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - // make sure it panics if no expectation was made - assert.Panics(t, func() { - mockedService.Called(1, 2, 3) - }, "Calling unexpected method should panic") - -} - -func Test_AssertExpectationsForObjects_Helper(t *testing.T) { - - var mockedService1 = new(TestExampleImplementation) - var mockedService2 = new(TestExampleImplementation) - var mockedService3 = new(TestExampleImplementation) - var mockedService4 = new(TestExampleImplementation) // No expectations does not cause a panic - - mockedService1.On("Test_AssertExpectationsForObjects_Helper", 1).Return() - mockedService2.On("Test_AssertExpectationsForObjects_Helper", 2).Return() - mockedService3.On("Test_AssertExpectationsForObjects_Helper", 3).Return() - - mockedService1.Called(1) - mockedService2.Called(2) - mockedService3.Called(3) - - assert.True(t, AssertExpectationsForObjects(t, &mockedService1.Mock, &mockedService2.Mock, &mockedService3.Mock, &mockedService4.Mock)) - assert.True(t, AssertExpectationsForObjects(t, mockedService1, mockedService2, mockedService3, mockedService4)) - -} - -func Test_AssertExpectationsForObjects_Helper_Failed(t *testing.T) { - - var mockedService1 = new(TestExampleImplementation) - var mockedService2 = new(TestExampleImplementation) - var mockedService3 = new(TestExampleImplementation) - - mockedService1.On("Test_AssertExpectationsForObjects_Helper_Failed", 1).Return() - mockedService2.On("Test_AssertExpectationsForObjects_Helper_Failed", 2).Return() - mockedService3.On("Test_AssertExpectationsForObjects_Helper_Failed", 3).Return() - - mockedService1.Called(1) - mockedService3.Called(3) - - tt := new(testing.T) - assert.False(t, AssertExpectationsForObjects(tt, &mockedService1.Mock, &mockedService2.Mock, &mockedService3.Mock)) - assert.False(t, AssertExpectationsForObjects(tt, mockedService1, mockedService2, mockedService3)) - -} - -func Test_Mock_AssertExpectations(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - mockedService.On("Test_Mock_AssertExpectations", 1, 2, 3).Return(5, 6, 7) - - tt := new(testing.T) - assert.False(t, mockedService.AssertExpectations(tt)) - - // make the call now - mockedService.Called(1, 2, 3) - - // now assert expectations - assert.True(t, mockedService.AssertExpectations(tt)) - -} - -func Test_Mock_AssertExpectations_Placeholder_NoArgs(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - mockedService.On("Test_Mock_AssertExpectations_Placeholder_NoArgs").Return(5, 6, 7).Once() - mockedService.On("Test_Mock_AssertExpectations_Placeholder_NoArgs").Return(7, 6, 5) - - tt := new(testing.T) - assert.False(t, mockedService.AssertExpectations(tt)) - - // make the call now - mockedService.Called() - - // now assert expectations - assert.True(t, mockedService.AssertExpectations(tt)) - -} - -func Test_Mock_AssertExpectations_Placeholder(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - mockedService.On("Test_Mock_AssertExpectations_Placeholder", 1, 2, 3).Return(5, 6, 7).Once() - mockedService.On("Test_Mock_AssertExpectations_Placeholder", 3, 2, 1).Return(7, 6, 5) - - tt := new(testing.T) - assert.False(t, mockedService.AssertExpectations(tt)) - - // make the call now - mockedService.Called(1, 2, 3) - - // now assert expectations - assert.False(t, mockedService.AssertExpectations(tt)) - - // make call to the second expectation - mockedService.Called(3, 2, 1) - - // now assert expectations again - assert.True(t, mockedService.AssertExpectations(tt)) -} - -func Test_Mock_AssertExpectations_With_Pointers(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - mockedService.On("Test_Mock_AssertExpectations_With_Pointers", &struct{ Foo int }{1}).Return(1) - mockedService.On("Test_Mock_AssertExpectations_With_Pointers", &struct{ Foo int }{2}).Return(2) - - tt := new(testing.T) - assert.False(t, mockedService.AssertExpectations(tt)) - - s := struct{ Foo int }{1} - // make the calls now - mockedService.Called(&s) - s.Foo = 2 - mockedService.Called(&s) - - // now assert expectations - assert.True(t, mockedService.AssertExpectations(tt)) - -} - -func Test_Mock_AssertExpectationsCustomType(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - mockedService.On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).Return(nil).Once() - - tt := new(testing.T) - assert.False(t, mockedService.AssertExpectations(tt)) - - // make the call now - mockedService.TheExampleMethod3(&ExampleType{}) - - // now assert expectations - assert.True(t, mockedService.AssertExpectations(tt)) - -} - -func Test_Mock_AssertExpectations_With_Repeatability(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - mockedService.On("Test_Mock_AssertExpectations_With_Repeatability", 1, 2, 3).Return(5, 6, 7).Twice() - - tt := new(testing.T) - assert.False(t, mockedService.AssertExpectations(tt)) - - // make the call now - mockedService.Called(1, 2, 3) - - assert.False(t, mockedService.AssertExpectations(tt)) - - mockedService.Called(1, 2, 3) - - // now assert expectations - assert.True(t, mockedService.AssertExpectations(tt)) - -} - -func Test_Mock_TwoCallsWithDifferentArguments(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - mockedService.On("Test_Mock_TwoCallsWithDifferentArguments", 1, 2, 3).Return(5, 6, 7) - mockedService.On("Test_Mock_TwoCallsWithDifferentArguments", 4, 5, 6).Return(5, 6, 7) - - args1 := mockedService.Called(1, 2, 3) - assert.Equal(t, 5, args1.Int(0)) - assert.Equal(t, 6, args1.Int(1)) - assert.Equal(t, 7, args1.Int(2)) - - args2 := mockedService.Called(4, 5, 6) - assert.Equal(t, 5, args2.Int(0)) - assert.Equal(t, 6, args2.Int(1)) - assert.Equal(t, 7, args2.Int(2)) - -} - -func Test_Mock_AssertNumberOfCalls(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - mockedService.On("Test_Mock_AssertNumberOfCalls", 1, 2, 3).Return(5, 6, 7) - - mockedService.Called(1, 2, 3) - assert.True(t, mockedService.AssertNumberOfCalls(t, "Test_Mock_AssertNumberOfCalls", 1)) - - mockedService.Called(1, 2, 3) - assert.True(t, mockedService.AssertNumberOfCalls(t, "Test_Mock_AssertNumberOfCalls", 2)) - -} - -func Test_Mock_AssertCalled(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - mockedService.On("Test_Mock_AssertCalled", 1, 2, 3).Return(5, 6, 7) - - mockedService.Called(1, 2, 3) - - assert.True(t, mockedService.AssertCalled(t, "Test_Mock_AssertCalled", 1, 2, 3)) - -} - -func Test_Mock_AssertCalled_WithAnythingOfTypeArgument(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - mockedService. - On("Test_Mock_AssertCalled_WithAnythingOfTypeArgument", Anything, Anything, Anything). - Return() - - mockedService.Called(1, "two", []uint8("three")) - - assert.True(t, mockedService.AssertCalled(t, "Test_Mock_AssertCalled_WithAnythingOfTypeArgument", AnythingOfType("int"), AnythingOfType("string"), AnythingOfType("[]uint8"))) - -} - -func Test_Mock_AssertCalled_WithArguments(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - mockedService.On("Test_Mock_AssertCalled_WithArguments", 1, 2, 3).Return(5, 6, 7) - - mockedService.Called(1, 2, 3) - - tt := new(testing.T) - assert.True(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments", 1, 2, 3)) - assert.False(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments", 2, 3, 4)) - -} - -func Test_Mock_AssertCalled_WithArguments_With_Repeatability(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - mockedService.On("Test_Mock_AssertCalled_WithArguments_With_Repeatability", 1, 2, 3).Return(5, 6, 7).Once() - mockedService.On("Test_Mock_AssertCalled_WithArguments_With_Repeatability", 2, 3, 4).Return(5, 6, 7).Once() - - mockedService.Called(1, 2, 3) - mockedService.Called(2, 3, 4) - - tt := new(testing.T) - assert.True(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments_With_Repeatability", 1, 2, 3)) - assert.True(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments_With_Repeatability", 2, 3, 4)) - assert.False(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments_With_Repeatability", 3, 4, 5)) - -} - -func Test_Mock_AssertNotCalled(t *testing.T) { - - var mockedService = new(TestExampleImplementation) - - mockedService.On("Test_Mock_AssertNotCalled", 1, 2, 3).Return(5, 6, 7) - - mockedService.Called(1, 2, 3) - - assert.True(t, mockedService.AssertNotCalled(t, "Test_Mock_NotCalled")) - -} - -func Test_Mock_IsMethodCallable(t *testing.T) { - var mockedService = new(TestExampleImplementation) - - arg := []Call{{Repeatability: 1}, {Repeatability: 2}} - arg2 := []Call{{Repeatability: 1}, {Repeatability: 1}} - arg3 := []Call{{Repeatability: 1}, {Repeatability: 1}} - - mockedService.On("Test_Mock_IsMethodCallable", arg2).Return(true).Twice() - - assert.False(t, mockedService.IsMethodCallable(t, "Test_Mock_IsMethodCallable", arg)) - assert.True(t, mockedService.IsMethodCallable(t, "Test_Mock_IsMethodCallable", arg2)) - assert.True(t, mockedService.IsMethodCallable(t, "Test_Mock_IsMethodCallable", arg3)) - - mockedService.MethodCalled("Test_Mock_IsMethodCallable", arg2) - mockedService.MethodCalled("Test_Mock_IsMethodCallable", arg2) - - assert.False(t, mockedService.IsMethodCallable(t, "Test_Mock_IsMethodCallable", arg2)) -} - -func TestIsArgsEqual(t *testing.T) { - var expected = Arguments{5, 3, 4, 6, 7, 2} - var args = make([]interface{}, 5) - for i := 1; i < len(expected); i++ { - args[i-1] = expected[i] - } - args[2] = expected[1] - assert.False(t, isArgsEqual(expected, args)) - - var arr = make([]interface{}, 6) - for i := 0; i < len(expected); i++ { - arr[i] = expected[i] - } - assert.True(t, isArgsEqual(expected, arr)) -} - -func Test_Mock_AssertOptional(t *testing.T) { - // Optional called - var ms1 = new(TestExampleImplementation) - ms1.On("TheExampleMethod", 1, 2, 3).Maybe().Return(4, nil) - ms1.TheExampleMethod(1, 2, 3) - - tt1 := new(testing.T) - assert.Equal(t, true, ms1.AssertExpectations(tt1)) - - // Optional not called - var ms2 = new(TestExampleImplementation) - ms2.On("TheExampleMethod", 1, 2, 3).Maybe().Return(4, nil) - - tt2 := new(testing.T) - assert.Equal(t, true, ms2.AssertExpectations(tt2)) - - // Non-optional called - var ms3 = new(TestExampleImplementation) - ms3.On("TheExampleMethod", 1, 2, 3).Return(4, nil) - ms3.TheExampleMethod(1, 2, 3) - - tt3 := new(testing.T) - assert.Equal(t, true, ms3.AssertExpectations(tt3)) -} - -/* - Arguments helper methods -*/ -func Test_Arguments_Get(t *testing.T) { - - var args = Arguments([]interface{}{"string", 123, true}) - - assert.Equal(t, "string", args.Get(0).(string)) - assert.Equal(t, 123, args.Get(1).(int)) - assert.Equal(t, true, args.Get(2).(bool)) - -} - -func Test_Arguments_Is(t *testing.T) { - - var args = Arguments([]interface{}{"string", 123, true}) - - assert.True(t, args.Is("string", 123, true)) - assert.False(t, args.Is("wrong", 456, false)) - -} - -func Test_Arguments_Diff(t *testing.T) { - - var args = Arguments([]interface{}{"Hello World", 123, true}) - var diff string - var count int - diff, count = args.Diff([]interface{}{"Hello World", 456, "false"}) - - assert.Equal(t, 2, count) - assert.Contains(t, diff, `(int=456) != (int=123)`) - assert.Contains(t, diff, `(string=false) != (bool=true)`) - -} - -func Test_Arguments_Diff_DifferentNumberOfArgs(t *testing.T) { - - var args = Arguments([]interface{}{"string", 123, true}) - var diff string - var count int - diff, count = args.Diff([]interface{}{"string", 456, "false", "extra"}) - - assert.Equal(t, 3, count) - assert.Contains(t, diff, `(string=extra) != (Missing)`) - -} - -func Test_Arguments_Diff_WithAnythingArgument(t *testing.T) { - - var args = Arguments([]interface{}{"string", 123, true}) - var count int - _, count = args.Diff([]interface{}{"string", Anything, true}) - - assert.Equal(t, 0, count) - -} - -func Test_Arguments_Diff_WithAnythingArgument_InActualToo(t *testing.T) { - - var args = Arguments([]interface{}{"string", Anything, true}) - var count int - _, count = args.Diff([]interface{}{"string", 123, true}) - - assert.Equal(t, 0, count) - -} - -func Test_Arguments_Diff_WithAnythingOfTypeArgument(t *testing.T) { - - var args = Arguments([]interface{}{"string", AnythingOfType("int"), true}) - var count int - _, count = args.Diff([]interface{}{"string", 123, true}) - - assert.Equal(t, 0, count) - -} - -func Test_Arguments_Diff_WithAnythingOfTypeArgument_Failing(t *testing.T) { - - var args = Arguments([]interface{}{"string", AnythingOfType("string"), true}) - var count int - var diff string - diff, count = args.Diff([]interface{}{"string", 123, true}) - - assert.Equal(t, 1, count) - assert.Contains(t, diff, `string != type int - (int=123)`) - -} - -func Test_Arguments_Diff_WithIsTypeArgument(t *testing.T) { - var args = Arguments([]interface{}{"string", IsType(0), true}) - var count int - _, count = args.Diff([]interface{}{"string", 123, true}) - - assert.Equal(t, 0, count) -} - -func Test_Arguments_Diff_WithIsTypeArgument_Failing(t *testing.T) { - var args = Arguments([]interface{}{"string", IsType(""), true}) - var count int - var diff string - diff, count = args.Diff([]interface{}{"string", 123, true}) - - assert.Equal(t, 1, count) - assert.Contains(t, diff, `string != type int - (int=123)`) -} - -func Test_Arguments_Diff_WithArgMatcher(t *testing.T) { - matchFn := func(a int) bool { - return a == 123 - } - var args = Arguments([]interface{}{"string", MatchedBy(matchFn), true}) - - diff, count := args.Diff([]interface{}{"string", 124, true}) - assert.Equal(t, 1, count) - assert.Contains(t, diff, `(int=124) not matched by func(int) bool`) - - diff, count = args.Diff([]interface{}{"string", false, true}) - assert.Equal(t, 1, count) - assert.Contains(t, diff, `(bool=false) not matched by func(int) bool`) - - diff, count = args.Diff([]interface{}{"string", 123, false}) - assert.Equal(t, 1, count) - assert.Contains(t, diff, `(int=123) matched by func(int) bool`) - - diff, count = args.Diff([]interface{}{"string", 123, true}) - assert.Equal(t, 0, count) - assert.Contains(t, diff, `No differences.`) -} - -func Test_Arguments_Assert(t *testing.T) { - - var args = Arguments([]interface{}{"string", 123, true}) - - assert.True(t, args.Assert(t, "string", 123, true)) - -} - -func Test_Arguments_String_Representation(t *testing.T) { - - var args = Arguments([]interface{}{"string", 123, true}) - assert.Equal(t, `string,int,bool`, args.String()) - -} - -func Test_Arguments_String(t *testing.T) { - - var args = Arguments([]interface{}{"string", 123, true}) - assert.Equal(t, "string", args.String(0)) - -} - -func Test_Arguments_Error(t *testing.T) { - - var err = errors.New("An Error") - var args = Arguments([]interface{}{"string", 123, true, err}) - assert.Equal(t, err, args.Error(3)) - -} - -func Test_Arguments_Error_Nil(t *testing.T) { - - var args = Arguments([]interface{}{"string", 123, true, nil}) - assert.Equal(t, nil, args.Error(3)) - -} - -func Test_Arguments_Int(t *testing.T) { - - var args = Arguments([]interface{}{"string", 123, true}) - assert.Equal(t, 123, args.Int(1)) - -} - -func Test_Arguments_Bool(t *testing.T) { - - var args = Arguments([]interface{}{"string", 123, true}) - assert.Equal(t, true, args.Bool(2)) - -} - -func Test_WaitUntil_Parallel(t *testing.T) { - - // make a test impl object - var mockedService = new(TestExampleImplementation) - - ch1 := make(chan time.Time) - ch2 := make(chan time.Time) - - mockedService.Mock.On("TheExampleMethod2", true).Return().WaitUntil(ch2).Run(func(args Arguments) { - ch1 <- time.Now() - }) - - mockedService.Mock.On("TheExampleMethod2", false).Return().WaitUntil(ch1) - - // Lock both goroutines on the .WaitUntil method - go func() { - mockedService.TheExampleMethod2(false) - }() - go func() { - mockedService.TheExampleMethod2(true) - }() - - // Allow the first call to execute, so the second one executes afterwards - ch2 <- time.Now() -} - -func Test_MockMethodCalled(t *testing.T) { - m := new(Mock) - m.On("foo", "hello").Return("world") - - retArgs := m.MethodCalled("foo", "hello") - require.True(t, len(retArgs) == 1) - require.Equal(t, "world", retArgs[0]) - m.AssertExpectations(t) -} - -func Test_MockMethodCalled_Panic(t *testing.T) { - m := new(Mock) - m.On("foo", "hello").Panic("world panics") - - require.PanicsWithValue(t, "world panics", func() { m.MethodCalled("foo", "hello") }) - m.AssertExpectations(t) -} - -// Test to validate fix for racy concurrent call access in MethodCalled() -func Test_MockReturnAndCalledConcurrent(t *testing.T) { - iterations := 1000 - m := &Mock{} - call := m.On("ConcurrencyTestMethod") - - wg := sync.WaitGroup{} - wg.Add(2) - - go func() { - for i := 0; i < iterations; i++ { - call.Return(10) - } - wg.Done() - }() - go func() { - for i := 0; i < iterations; i++ { - ConcurrencyTestMethod(m) - } - wg.Done() - }() - wg.Wait() -} - -type timer struct{ Mock } - -func (s *timer) GetTime(i int) string { - return s.Called(i).Get(0).(string) -} - -func (s *timer) GetTimes(times []int) string { - return s.Called(times).Get(0).(string) -} - -type tCustomLogger struct { - *testing.T - logs []string - errs []string -} - -func (tc *tCustomLogger) Logf(format string, args ...interface{}) { - tc.T.Logf(format, args...) - tc.logs = append(tc.logs, fmt.Sprintf(format, args...)) -} - -func (tc *tCustomLogger) Errorf(format string, args ...interface{}) { - tc.errs = append(tc.errs, fmt.Sprintf(format, args...)) -} - -func (tc *tCustomLogger) FailNow() {} - -func TestLoggingAssertExpectations(t *testing.T) { - m := new(timer) - m.On("GetTime", 0).Return("") - tcl := &tCustomLogger{t, []string{}, []string{}} - - AssertExpectationsForObjects(tcl, m, new(TestExampleImplementation)) - - require.Equal(t, 1, len(tcl.errs)) - assert.Regexp(t, regexp.MustCompile("(?s)FAIL: 0 out of 1 expectation\\(s\\) were met.*The code you are testing needs to make 1 more call\\(s\\).*"), tcl.errs[0]) - require.Equal(t, 2, len(tcl.logs)) - assert.Regexp(t, regexp.MustCompile("(?s)FAIL:\tGetTime\\(int\\).*"), tcl.logs[0]) - require.Equal(t, "Expectations didn't match for Mock: *mock.timer", tcl.logs[1]) -} - -func TestAfterTotalWaitTimeWhileExecution(t *testing.T) { - waitDuration := 1 - total, waitMs := 5, time.Millisecond*time.Duration(waitDuration) - aTimer := new(timer) - for i := 0; i < total; i++ { - aTimer.On("GetTime", i).After(waitMs).Return(fmt.Sprintf("Time%d", i)).Once() - } - time.Sleep(waitMs) - start := time.Now() - var results []string - - for i := 0; i < total; i++ { - results = append(results, aTimer.GetTime(i)) - } - - end := time.Now() - elapsedTime := end.Sub(start) - assert.True(t, elapsedTime > waitMs, fmt.Sprintf("Total elapsed time:%v should be atleast greater than %v", elapsedTime, waitMs)) - assert.Equal(t, total, len(results)) - for i := range results { - assert.Equal(t, fmt.Sprintf("Time%d", i), results[i], "Return value of method should be same") - } -} - -func TestArgumentMatcherToPrintMismatch(t *testing.T) { - defer func() { - if r := recover(); r != nil { - matchingExp := regexp.MustCompile( - `\s+mock: Unexpected Method Call\s+-*\s+GetTime\(int\)\s+0: 1\s+The closest call I have is:\s+GetTime\(mock.argumentMatcher\)\s+0: mock.argumentMatcher\{.*?\}\s+Diff:.*\(int=1\) not matched by func\(int\) bool`) - assert.Regexp(t, matchingExp, r) - } - }() - - m := new(timer) - m.On("GetTime", MatchedBy(func(i int) bool { return false })).Return("SomeTime").Once() - - res := m.GetTime(1) - require.Equal(t, "SomeTime", res) - m.AssertExpectations(t) -} - -func TestArgumentMatcherToPrintMismatchWithReferenceType(t *testing.T) { - defer func() { - if r := recover(); r != nil { - matchingExp := regexp.MustCompile( - `\s+mock: Unexpected Method Call\s+-*\s+GetTimes\(\[\]int\)\s+0: \[\]int\{1\}\s+The closest call I have is:\s+GetTimes\(mock.argumentMatcher\)\s+0: mock.argumentMatcher\{.*?\}\s+Diff:.*\(\[\]int=\[1\]\) not matched by func\(\[\]int\) bool`) - assert.Regexp(t, matchingExp, r) - } - }() - - m := new(timer) - m.On("GetTimes", MatchedBy(func(_ []int) bool { return false })).Return("SomeTime").Once() - - res := m.GetTimes([]int{1}) - require.Equal(t, "SomeTime", res) - m.AssertExpectations(t) -} - -func TestClosestCallMismatchedArgumentInformationShowsTheClosest(t *testing.T) { - defer func() { - if r := recover(); r != nil { - matchingExp := regexp.MustCompile(unexpectedCallRegex(`TheExampleMethod(int,int,int)`, `0: 1\s+1: 1\s+2: 2`, `0: 1\s+1: 1\s+2: 1`, `Diff: 0: PASS: \(int=1\) == \(int=1\)\s+1: PASS: \(int=1\) == \(int=1\)\s+2: FAIL: \(int=2\) != \(int=1\)`)) - assert.Regexp(t, matchingExp, r) - } - }() - - m := new(TestExampleImplementation) - m.On("TheExampleMethod", 1, 1, 1).Return(1, nil).Once() - m.On("TheExampleMethod", 2, 2, 2).Return(2, nil).Once() - - m.TheExampleMethod(1, 1, 2) -} - -func TestClosestCallFavorsFirstMock(t *testing.T) { - defer func() { - if r := recover(); r != nil { - diffRegExp := `Difference found in argument 0:\s+--- Expected\s+\+\+\+ Actual\s+@@ -2,4 \+2,4 @@\s+\(bool\) true,\s+- \(bool\) true,\s+- \(bool\) true\s+\+ \(bool\) false,\s+\+ \(bool\) false\s+}\s+` - matchingExp := regexp.MustCompile(unexpectedCallRegex(`TheExampleMethod7([]bool)`, `0: \[\]bool{true, false, false}`, `0: \[\]bool{true, true, true}`, diffRegExp)) - assert.Regexp(t, matchingExp, r) - } - }() - - m := new(TestExampleImplementation) - m.On("TheExampleMethod7", []bool{true, true, true}).Return(nil).Once() - m.On("TheExampleMethod7", []bool{false, false, false}).Return(nil).Once() - - m.TheExampleMethod7([]bool{true, false, false}) -} - -func TestClosestCallUsesRepeatabilityToFindClosest(t *testing.T) { - defer func() { - if r := recover(); r != nil { - diffRegExp := `Difference found in argument 0:\s+--- Expected\s+\+\+\+ Actual\s+@@ -1,4 \+1,4 @@\s+\(\[\]bool\) \(len=3\) {\s+- \(bool\) false,\s+- \(bool\) false,\s+\+ \(bool\) true,\s+\+ \(bool\) true,\s+\(bool\) false\s+` - matchingExp := regexp.MustCompile(unexpectedCallRegex(`TheExampleMethod7([]bool)`, `0: \[\]bool{true, true, false}`, `0: \[\]bool{false, false, false}`, diffRegExp)) - assert.Regexp(t, matchingExp, r) - } - }() - - m := new(TestExampleImplementation) - m.On("TheExampleMethod7", []bool{true, true, true}).Return(nil).Once() - m.On("TheExampleMethod7", []bool{false, false, false}).Return(nil).Once() - - m.TheExampleMethod7([]bool{true, true, true}) - - // Since the first mocked call has already been used, it now has no repeatability, - // thus the second mock should be shown as the closest match - m.TheExampleMethod7([]bool{true, true, false}) -} - -func TestClosestCallMismatchedArgumentValueInformation(t *testing.T) { - defer func() { - if r := recover(); r != nil { - matchingExp := regexp.MustCompile(unexpectedCallRegex(`GetTime(int)`, "0: 1", "0: 999", `Diff: 0: FAIL: \(int=1\) != \(int=999\)`)) - assert.Regexp(t, matchingExp, r) - } - }() - - m := new(timer) - m.On("GetTime", 999).Return("SomeTime").Once() - - _ = m.GetTime(1) -} - -func Test_isBetterMatchThanReturnsFalseIfCandidateCallIsNil(t *testing.T) { - assert.False(t, matchCandidate{}.isBetterMatchThan(matchCandidate{})) -} - -func Test_isBetterMatchThanReturnsTrueIfOtherCandidateCallIsNil(t *testing.T) { - assert.True(t, matchCandidate{call: &Call{}}.isBetterMatchThan(matchCandidate{})) -} - -func Test_isBetterMatchThanReturnsFalseIfDiffCountIsGreaterThanOther(t *testing.T) { - assert.False(t, matchCandidate{call: &Call{}, diffCount: 2}.isBetterMatchThan(matchCandidate{call: &Call{}, diffCount: 1})) -} - -func Test_isBetterMatchThanReturnsTrueIfDiffCountIsLessThanOther(t *testing.T) { - assert.True(t, matchCandidate{call: &Call{}, diffCount: 1}.isBetterMatchThan(matchCandidate{call: &Call{}, diffCount: 2})) -} - -func Test_isBetterMatchThanReturnsTrueIfRepeatabilityIsGreaterThanOther(t *testing.T) { - assert.True(t, matchCandidate{call: &Call{Repeatability: 1}, diffCount: 1}.isBetterMatchThan(matchCandidate{call: &Call{Repeatability: -1}, diffCount: 1})) -} - -func Test_isBetterMatchThanReturnsFalseIfRepeatabilityIsLessThanOrEqualToOther(t *testing.T) { - assert.False(t, matchCandidate{call: &Call{Repeatability: 1}, diffCount: 1}.isBetterMatchThan(matchCandidate{call: &Call{Repeatability: 1}, diffCount: 1})) -} - -func unexpectedCallRegex(method, calledArg, expectedArg, diff string) string { - rMethod := regexp.QuoteMeta(method) - return fmt.Sprintf(`\s+mock: Unexpected Method Call\s+-*\s+%s\s+%s\s+The closest call I have is:\s+%s\s+%s\s+%s`, - rMethod, calledArg, rMethod, expectedArg, diff) -} - -//go:noinline -func ConcurrencyTestMethod(m *Mock) { - m.Called() -} - -func TestConcurrentArgumentRead(t *testing.T) { - methodUnderTest := func(c caller, u user) { - go u.Use(c) - c.Call() - } - - c := &mockCaller{} - defer c.AssertExpectations(t) - - u := &mockUser{} - defer u.AssertExpectations(t) - - done := make(chan struct{}) - - c.On("Call").Return().Once() - u.On("Use", c).Return().Once().Run(func(args Arguments) { close(done) }) - - methodUnderTest(c, u) - <-done // wait until Use is called or assertions will fail -} - -type caller interface { - Call() -} - -type mockCaller struct{ Mock } - -func (m *mockCaller) Call() { m.Called() } - -type user interface { - Use(caller) -} - -type mockUser struct{ Mock } - -func (m *mockUser) Use(c caller) { m.Called(c) } diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/package_test.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/package_test.go deleted file mode 100644 index f17ff15..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/package_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package testify - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestImports(t *testing.T) { - if assert.Equal(t, 1, 1) != true { - t.Error("Something is wrong.") - } -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/doc.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/doc.go deleted file mode 100644 index 169de39..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/doc.go +++ /dev/null @@ -1,28 +0,0 @@ -// Package require implements the same assertions as the `assert` package but -// stops test execution when a test fails. -// -// Example Usage -// -// The following is a complete example using require in a standard test function: -// import ( -// "testing" -// "github.com/stretchr/testify/require" -// ) -// -// func TestSomething(t *testing.T) { -// -// var a string = "Hello" -// var b string = "Hello" -// -// require.Equal(t, a, b, "The two words should be the same.") -// -// } -// -// Assertions -// -// The `require` package have same global functions as in the `assert` package, -// but instead of returning a boolean result they call `t.FailNow()`. -// -// Every assertion function also takes an optional string message as the final argument, -// allowing custom error messages to be appended to the message the assertion method outputs. -package require diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/forward_requirements.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/forward_requirements.go deleted file mode 100644 index 1dcb233..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/forward_requirements.go +++ /dev/null @@ -1,16 +0,0 @@ -package require - -// Assertions provides assertion methods around the -// TestingT interface. -type Assertions struct { - t TestingT -} - -// New makes a new Assertions object for the specified TestingT. -func New(t TestingT) *Assertions { - return &Assertions{ - t: t, - } -} - -//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require_forward.go.tmpl -include-format-funcs" diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/forward_requirements_test.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/forward_requirements_test.go deleted file mode 100644 index 8fbcc15..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/forward_requirements_test.go +++ /dev/null @@ -1,523 +0,0 @@ -package require - -import ( - "errors" - "testing" - "time" -) - -func TestImplementsWrapper(t *testing.T) { - require := New(t) - - require.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestIsTypeWrapper(t *testing.T) { - require := New(t) - require.IsType(new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.IsType(new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestEqualWrapper(t *testing.T) { - require := New(t) - require.Equal(1, 1) - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.Equal(1, 2) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestNotEqualWrapper(t *testing.T) { - require := New(t) - require.NotEqual(1, 2) - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.NotEqual(2, 2) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestExactlyWrapper(t *testing.T) { - require := New(t) - - a := float32(1) - b := float32(1) - c := float64(1) - - require.Exactly(a, b) - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.Exactly(a, c) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestNotNilWrapper(t *testing.T) { - require := New(t) - require.NotNil(t, new(AssertionTesterConformingObject)) - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.NotNil(nil) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestNilWrapper(t *testing.T) { - require := New(t) - require.Nil(nil) - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.Nil(new(AssertionTesterConformingObject)) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestTrueWrapper(t *testing.T) { - require := New(t) - require.True(true) - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.True(false) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestFalseWrapper(t *testing.T) { - require := New(t) - require.False(false) - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.False(true) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestContainsWrapper(t *testing.T) { - require := New(t) - require.Contains("Hello World", "Hello") - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.Contains("Hello World", "Salut") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestNotContainsWrapper(t *testing.T) { - require := New(t) - require.NotContains("Hello World", "Hello!") - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.NotContains("Hello World", "Hello") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestPanicsWrapper(t *testing.T) { - require := New(t) - require.Panics(func() { - panic("Panic!") - }) - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.Panics(func() {}) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestNotPanicsWrapper(t *testing.T) { - require := New(t) - require.NotPanics(func() {}) - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.NotPanics(func() { - panic("Panic!") - }) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestNoErrorWrapper(t *testing.T) { - require := New(t) - require.NoError(nil) - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.NoError(errors.New("some error")) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestErrorWrapper(t *testing.T) { - require := New(t) - require.Error(errors.New("some error")) - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.Error(nil) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestErrorContainsWrapper(t *testing.T) { - require := New(t) - require.ErrorContains(errors.New("some error: another error"), "some error") - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.ErrorContains(errors.New("some error: another error"), "different error") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestEqualErrorWrapper(t *testing.T) { - require := New(t) - require.EqualError(errors.New("some error"), "some error") - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.EqualError(errors.New("some error"), "Not some error") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestEmptyWrapper(t *testing.T) { - require := New(t) - require.Empty("") - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.Empty("x") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestNotEmptyWrapper(t *testing.T) { - require := New(t) - require.NotEmpty("x") - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.NotEmpty("") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestWithinDurationWrapper(t *testing.T) { - require := New(t) - a := time.Now() - b := a.Add(10 * time.Second) - - require.WithinDuration(a, b, 15*time.Second) - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.WithinDuration(a, b, 5*time.Second) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestInDeltaWrapper(t *testing.T) { - require := New(t) - require.InDelta(1.001, 1, 0.01) - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.InDelta(1, 2, 0.5) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestZeroWrapper(t *testing.T) { - require := New(t) - require.Zero(0) - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.Zero(1) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestNotZeroWrapper(t *testing.T) { - require := New(t) - require.NotZero(1) - - mockT := new(MockT) - mockRequire := New(mockT) - mockRequire.NotZero(0) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestJSONEqWrapper_EqualSONString(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) - if mockT.Failed { - t.Error("Check should pass") - } -} - -func TestJSONEqWrapper_EquivalentButNotEqual(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) - if mockT.Failed { - t.Error("Check should pass") - } -} - -func TestJSONEqWrapper_HashOfArraysAndHashes(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.JSONEq("{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}", - "{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}") - if mockT.Failed { - t.Error("Check should pass") - } -} - -func TestJSONEqWrapper_Array(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) - if mockT.Failed { - t.Error("Check should pass") - } -} - -func TestJSONEqWrapper_HashAndArrayNotEquivalent(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestJSONEqWrapper_HashesNotEquivalent(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.JSONEq(`{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestJSONEqWrapper_ActualIsNotJSON(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.JSONEq(`{"foo": "bar"}`, "Not JSON") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestJSONEqWrapper_ExpectedIsNotJSON(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.JSONEq("Not JSON", `{"foo": "bar", "hello": "world"}`) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestJSONEqWrapper_ExpectedAndActualNotJSON(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.JSONEq("Not JSON", "Not JSON") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestJSONEqWrapper_ArraysOfDifferentOrder(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestYAMLEqWrapper_EqualYAMLString(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.YAMLEq(`{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) - if mockT.Failed { - t.Error("Check should pass") - } -} - -func TestYAMLEqWrapper_EquivalentButNotEqual(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.YAMLEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) - if mockT.Failed { - t.Error("Check should pass") - } -} - -func TestYAMLEqWrapper_HashOfArraysAndHashes(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - expected := ` -numeric: 1.5 -array: - - foo: bar - - 1 - - "string" - - ["nested", "array", 5.5] -hash: - nested: hash - nested_slice: [this, is, nested] -string: "foo" -` - - actual := ` -numeric: 1.5 -hash: - nested: hash - nested_slice: [this, is, nested] -string: "foo" -array: - - foo: bar - - 1 - - "string" - - ["nested", "array", 5.5] -` - - mockRequire.YAMLEq(expected, actual) - if mockT.Failed { - t.Error("Check should pass") - } -} - -func TestYAMLEqWrapper_Array(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.YAMLEq(`["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) - if mockT.Failed { - t.Error("Check should pass") - } -} - -func TestYAMLEqWrapper_HashAndArrayNotEquivalent(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.YAMLEq(`["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestYAMLEqWrapper_HashesNotEquivalent(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.YAMLEq(`{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestYAMLEqWrapper_ActualIsSimpleString(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.YAMLEq(`{"foo": "bar"}`, "Simple String") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestYAMLEqWrapper_ExpectedIsSimpleString(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.YAMLEq("Simple String", `{"foo": "bar", "hello": "world"}`) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestYAMLEqWrapper_ExpectedAndActualSimpleString(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.YAMLEq("Simple String", "Simple String") - if mockT.Failed { - t.Error("Check should pass") - } -} - -func TestYAMLEqWrapper_ArraysOfDifferentOrder(t *testing.T) { - mockT := new(MockT) - mockRequire := New(mockT) - - mockRequire.YAMLEq(`["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) - if !mockT.Failed { - t.Error("Check should fail") - } -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/require.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/require.go deleted file mode 100644 index 880853f..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/require.go +++ /dev/null @@ -1,1935 +0,0 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ - -package require - -import ( - assert "github.com/stretchr/testify/assert" - http "net/http" - url "net/url" - time "time" -) - -// Condition uses a Comparison to assert a complex condition. -func Condition(t TestingT, comp assert.Comparison, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Condition(t, comp, msgAndArgs...) { - return - } - t.FailNow() -} - -// Conditionf uses a Comparison to assert a complex condition. -func Conditionf(t TestingT, comp assert.Comparison, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Conditionf(t, comp, msg, args...) { - return - } - t.FailNow() -} - -// Contains asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// assert.Contains(t, "Hello World", "World") -// assert.Contains(t, ["Hello", "World"], "World") -// assert.Contains(t, {"Hello": "World"}, "Hello") -func Contains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Contains(t, s, contains, msgAndArgs...) { - return - } - t.FailNow() -} - -// Containsf asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") -// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") -// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") -func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Containsf(t, s, contains, msg, args...) { - return - } - t.FailNow() -} - -// DirExists checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func DirExists(t TestingT, path string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.DirExists(t, path, msgAndArgs...) { - return - } - t.FailNow() -} - -// DirExistsf checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func DirExistsf(t TestingT, path string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.DirExistsf(t, path, msg, args...) { - return - } - t.FailNow() -} - -// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) -func ElementsMatch(t TestingT, listA interface{}, listB interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ElementsMatch(t, listA, listB, msgAndArgs...) { - return - } - t.FailNow() -} - -// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") -func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ElementsMatchf(t, listA, listB, msg, args...) { - return - } - t.FailNow() -} - -// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// assert.Empty(t, obj) -func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Empty(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// assert.Emptyf(t, obj, "error message %s", "formatted") -func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Emptyf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// Equal asserts that two objects are equal. -// -// assert.Equal(t, 123, 123) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func Equal(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Equal(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// EqualError asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// assert.EqualError(t, err, expectedErrorString) -func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EqualError(t, theError, errString, msgAndArgs...) { - return - } - t.FailNow() -} - -// EqualErrorf asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") -func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EqualErrorf(t, theError, errString, msg, args...) { - return - } - t.FailNow() -} - -// EqualValues asserts that two objects are equal or convertable to the same types -// and equal. -// -// assert.EqualValues(t, uint32(123), int32(123)) -func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EqualValues(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// EqualValuesf asserts that two objects are equal or convertable to the same types -// and equal. -// -// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") -func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EqualValuesf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// Equalf asserts that two objects are equal. -// -// assert.Equalf(t, 123, 123, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Equalf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// Error asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// if assert.Error(t, err) { -// assert.Equal(t, expectedError, err) -// } -func Error(t TestingT, err error, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Error(t, err, msgAndArgs...) { - return - } - t.FailNow() -} - -// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ErrorAs(t, err, target, msgAndArgs...) { - return - } - t.FailNow() -} - -// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ErrorAsf(t, err, target, msg, args...) { - return - } - t.FailNow() -} - -// ErrorContains asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// assert.ErrorContains(t, err, expectedErrorSubString) -func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ErrorContains(t, theError, contains, msgAndArgs...) { - return - } - t.FailNow() -} - -// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted") -func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ErrorContainsf(t, theError, contains, msg, args...) { - return - } - t.FailNow() -} - -// ErrorIs asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func ErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ErrorIs(t, err, target, msgAndArgs...) { - return - } - t.FailNow() -} - -// ErrorIsf asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ErrorIsf(t, err, target, msg, args...) { - return - } - t.FailNow() -} - -// Errorf asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// if assert.Errorf(t, err, "error message %s", "formatted") { -// assert.Equal(t, expectedErrorf, err) -// } -func Errorf(t TestingT, err error, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Errorf(t, err, msg, args...) { - return - } - t.FailNow() -} - -// Eventually asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond) -func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Eventually(t, condition, waitFor, tick, msgAndArgs...) { - return - } - t.FailNow() -} - -// Eventuallyf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Eventuallyf(t, condition, waitFor, tick, msg, args...) { - return - } - t.FailNow() -} - -// Exactly asserts that two objects are equal in value and type. -// -// assert.Exactly(t, int32(123), int64(123)) -func Exactly(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Exactly(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// Exactlyf asserts that two objects are equal in value and type. -// -// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted") -func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Exactlyf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// Fail reports a failure through -func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Fail(t, failureMessage, msgAndArgs...) { - return - } - t.FailNow() -} - -// FailNow fails test -func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.FailNow(t, failureMessage, msgAndArgs...) { - return - } - t.FailNow() -} - -// FailNowf fails test -func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.FailNowf(t, failureMessage, msg, args...) { - return - } - t.FailNow() -} - -// Failf reports a failure through -func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Failf(t, failureMessage, msg, args...) { - return - } - t.FailNow() -} - -// False asserts that the specified value is false. -// -// assert.False(t, myBool) -func False(t TestingT, value bool, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.False(t, value, msgAndArgs...) { - return - } - t.FailNow() -} - -// Falsef asserts that the specified value is false. -// -// assert.Falsef(t, myBool, "error message %s", "formatted") -func Falsef(t TestingT, value bool, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Falsef(t, value, msg, args...) { - return - } - t.FailNow() -} - -// FileExists checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func FileExists(t TestingT, path string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.FileExists(t, path, msgAndArgs...) { - return - } - t.FailNow() -} - -// FileExistsf checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func FileExistsf(t TestingT, path string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.FileExistsf(t, path, msg, args...) { - return - } - t.FailNow() -} - -// Greater asserts that the first element is greater than the second -// -// assert.Greater(t, 2, 1) -// assert.Greater(t, float64(2), float64(1)) -// assert.Greater(t, "b", "a") -func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Greater(t, e1, e2, msgAndArgs...) { - return - } - t.FailNow() -} - -// GreaterOrEqual asserts that the first element is greater than or equal to the second -// -// assert.GreaterOrEqual(t, 2, 1) -// assert.GreaterOrEqual(t, 2, 2) -// assert.GreaterOrEqual(t, "b", "a") -// assert.GreaterOrEqual(t, "b", "b") -func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.GreaterOrEqual(t, e1, e2, msgAndArgs...) { - return - } - t.FailNow() -} - -// GreaterOrEqualf asserts that the first element is greater than or equal to the second -// -// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted") -// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted") -// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted") -// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted") -func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.GreaterOrEqualf(t, e1, e2, msg, args...) { - return - } - t.FailNow() -} - -// Greaterf asserts that the first element is greater than the second -// -// assert.Greaterf(t, 2, 1, "error message %s", "formatted") -// assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted") -// assert.Greaterf(t, "b", "a", "error message %s", "formatted") -func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Greaterf(t, e1, e2, msg, args...) { - return - } - t.FailNow() -} - -// HTTPBodyContains asserts that a specified handler returns a -// body that contains a string. -// -// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPBodyContains(t, handler, method, url, values, str, msgAndArgs...) { - return - } - t.FailNow() -} - -// HTTPBodyContainsf asserts that a specified handler returns a -// body that contains a string. -// -// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPBodyContainsf(t, handler, method, url, values, str, msg, args...) { - return - } - t.FailNow() -} - -// HTTPBodyNotContains asserts that a specified handler returns a -// body that does not contain a string. -// -// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPBodyNotContains(t, handler, method, url, values, str, msgAndArgs...) { - return - } - t.FailNow() -} - -// HTTPBodyNotContainsf asserts that a specified handler returns a -// body that does not contain a string. -// -// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPBodyNotContainsf(t, handler, method, url, values, str, msg, args...) { - return - } - t.FailNow() -} - -// HTTPError asserts that a specified handler returns an error status code. -// -// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPError(t, handler, method, url, values, msgAndArgs...) { - return - } - t.FailNow() -} - -// HTTPErrorf asserts that a specified handler returns an error status code. -// -// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPErrorf(t, handler, method, url, values, msg, args...) { - return - } - t.FailNow() -} - -// HTTPRedirect asserts that a specified handler returns a redirect status code. -// -// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPRedirect(t, handler, method, url, values, msgAndArgs...) { - return - } - t.FailNow() -} - -// HTTPRedirectf asserts that a specified handler returns a redirect status code. -// -// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPRedirectf(t, handler, method, url, values, msg, args...) { - return - } - t.FailNow() -} - -// HTTPStatusCode asserts that a specified handler returns a specified status code. -// -// assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501) -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPStatusCode(t, handler, method, url, values, statuscode, msgAndArgs...) { - return - } - t.FailNow() -} - -// HTTPStatusCodef asserts that a specified handler returns a specified status code. -// -// assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPStatusCodef(t, handler, method, url, values, statuscode, msg, args...) { - return - } - t.FailNow() -} - -// HTTPSuccess asserts that a specified handler returns a success status code. -// -// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPSuccess(t, handler, method, url, values, msgAndArgs...) { - return - } - t.FailNow() -} - -// HTTPSuccessf asserts that a specified handler returns a success status code. -// -// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPSuccessf(t, handler, method, url, values, msg, args...) { - return - } - t.FailNow() -} - -// Implements asserts that an object is implemented by the specified interface. -// -// assert.Implements(t, (*MyInterface)(nil), new(MyObject)) -func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Implements(t, interfaceObject, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// Implementsf asserts that an object is implemented by the specified interface. -// -// assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Implementsf(t, interfaceObject, object, msg, args...) { - return - } - t.FailNow() -} - -// InDelta asserts that the two numerals are within delta of each other. -// -// assert.InDelta(t, math.Pi, 22/7.0, 0.01) -func InDelta(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InDelta(t, expected, actual, delta, msgAndArgs...) { - return - } - t.FailNow() -} - -// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func InDeltaMapValues(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InDeltaMapValues(t, expected, actual, delta, msgAndArgs...) { - return - } - t.FailNow() -} - -// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InDeltaMapValuesf(t, expected, actual, delta, msg, args...) { - return - } - t.FailNow() -} - -// InDeltaSlice is the same as InDelta, except it compares two slices. -func InDeltaSlice(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InDeltaSlice(t, expected, actual, delta, msgAndArgs...) { - return - } - t.FailNow() -} - -// InDeltaSlicef is the same as InDelta, except it compares two slices. -func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InDeltaSlicef(t, expected, actual, delta, msg, args...) { - return - } - t.FailNow() -} - -// InDeltaf asserts that the two numerals are within delta of each other. -// -// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted") -func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InDeltaf(t, expected, actual, delta, msg, args...) { - return - } - t.FailNow() -} - -// InEpsilon asserts that expected and actual have a relative error less than epsilon -func InEpsilon(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InEpsilon(t, expected, actual, epsilon, msgAndArgs...) { - return - } - t.FailNow() -} - -// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. -func InEpsilonSlice(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InEpsilonSlice(t, expected, actual, epsilon, msgAndArgs...) { - return - } - t.FailNow() -} - -// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. -func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InEpsilonSlicef(t, expected, actual, epsilon, msg, args...) { - return - } - t.FailNow() -} - -// InEpsilonf asserts that expected and actual have a relative error less than epsilon -func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InEpsilonf(t, expected, actual, epsilon, msg, args...) { - return - } - t.FailNow() -} - -// IsDecreasing asserts that the collection is decreasing -// -// assert.IsDecreasing(t, []int{2, 1, 0}) -// assert.IsDecreasing(t, []float{2, 1}) -// assert.IsDecreasing(t, []string{"b", "a"}) -func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsDecreasing(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// IsDecreasingf asserts that the collection is decreasing -// -// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted") -// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted") -// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted") -func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsDecreasingf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// IsIncreasing asserts that the collection is increasing -// -// assert.IsIncreasing(t, []int{1, 2, 3}) -// assert.IsIncreasing(t, []float{1, 2}) -// assert.IsIncreasing(t, []string{"a", "b"}) -func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsIncreasing(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// IsIncreasingf asserts that the collection is increasing -// -// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted") -// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted") -// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted") -func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsIncreasingf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// IsNonDecreasing asserts that the collection is not decreasing -// -// assert.IsNonDecreasing(t, []int{1, 1, 2}) -// assert.IsNonDecreasing(t, []float{1, 2}) -// assert.IsNonDecreasing(t, []string{"a", "b"}) -func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsNonDecreasing(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// IsNonDecreasingf asserts that the collection is not decreasing -// -// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted") -// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted") -// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted") -func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsNonDecreasingf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// IsNonIncreasing asserts that the collection is not increasing -// -// assert.IsNonIncreasing(t, []int{2, 1, 1}) -// assert.IsNonIncreasing(t, []float{2, 1}) -// assert.IsNonIncreasing(t, []string{"b", "a"}) -func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsNonIncreasing(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// IsNonIncreasingf asserts that the collection is not increasing -// -// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted") -// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted") -// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted") -func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsNonIncreasingf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// IsType asserts that the specified objects are of the same type. -func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsType(t, expectedType, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// IsTypef asserts that the specified objects are of the same type. -func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsTypef(t, expectedType, object, msg, args...) { - return - } - t.FailNow() -} - -// JSONEq asserts that two JSON strings are equivalent. -// -// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) -func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.JSONEq(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// JSONEqf asserts that two JSON strings are equivalent. -// -// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") -func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.JSONEqf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// Len asserts that the specified object has specific length. -// Len also fails if the object has a type that len() not accept. -// -// assert.Len(t, mySlice, 3) -func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Len(t, object, length, msgAndArgs...) { - return - } - t.FailNow() -} - -// Lenf asserts that the specified object has specific length. -// Lenf also fails if the object has a type that len() not accept. -// -// assert.Lenf(t, mySlice, 3, "error message %s", "formatted") -func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Lenf(t, object, length, msg, args...) { - return - } - t.FailNow() -} - -// Less asserts that the first element is less than the second -// -// assert.Less(t, 1, 2) -// assert.Less(t, float64(1), float64(2)) -// assert.Less(t, "a", "b") -func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Less(t, e1, e2, msgAndArgs...) { - return - } - t.FailNow() -} - -// LessOrEqual asserts that the first element is less than or equal to the second -// -// assert.LessOrEqual(t, 1, 2) -// assert.LessOrEqual(t, 2, 2) -// assert.LessOrEqual(t, "a", "b") -// assert.LessOrEqual(t, "b", "b") -func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.LessOrEqual(t, e1, e2, msgAndArgs...) { - return - } - t.FailNow() -} - -// LessOrEqualf asserts that the first element is less than or equal to the second -// -// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted") -// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted") -// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted") -// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted") -func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.LessOrEqualf(t, e1, e2, msg, args...) { - return - } - t.FailNow() -} - -// Lessf asserts that the first element is less than the second -// -// assert.Lessf(t, 1, 2, "error message %s", "formatted") -// assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted") -// assert.Lessf(t, "a", "b", "error message %s", "formatted") -func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Lessf(t, e1, e2, msg, args...) { - return - } - t.FailNow() -} - -// Negative asserts that the specified element is negative -// -// assert.Negative(t, -1) -// assert.Negative(t, -1.23) -func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Negative(t, e, msgAndArgs...) { - return - } - t.FailNow() -} - -// Negativef asserts that the specified element is negative -// -// assert.Negativef(t, -1, "error message %s", "formatted") -// assert.Negativef(t, -1.23, "error message %s", "formatted") -func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Negativef(t, e, msg, args...) { - return - } - t.FailNow() -} - -// Never asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond) -func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Never(t, condition, waitFor, tick, msgAndArgs...) { - return - } - t.FailNow() -} - -// Neverf asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Neverf(t, condition, waitFor, tick, msg, args...) { - return - } - t.FailNow() -} - -// Nil asserts that the specified object is nil. -// -// assert.Nil(t, err) -func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Nil(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// Nilf asserts that the specified object is nil. -// -// assert.Nilf(t, err, "error message %s", "formatted") -func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Nilf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// NoDirExists checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NoDirExists(t, path, msgAndArgs...) { - return - } - t.FailNow() -} - -// NoDirExistsf checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NoDirExistsf(t, path, msg, args...) { - return - } - t.FailNow() -} - -// NoError asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if assert.NoError(t, err) { -// assert.Equal(t, expectedObj, actualObj) -// } -func NoError(t TestingT, err error, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NoError(t, err, msgAndArgs...) { - return - } - t.FailNow() -} - -// NoErrorf asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if assert.NoErrorf(t, err, "error message %s", "formatted") { -// assert.Equal(t, expectedObj, actualObj) -// } -func NoErrorf(t TestingT, err error, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NoErrorf(t, err, msg, args...) { - return - } - t.FailNow() -} - -// NoFileExists checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func NoFileExists(t TestingT, path string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NoFileExists(t, path, msgAndArgs...) { - return - } - t.FailNow() -} - -// NoFileExistsf checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NoFileExistsf(t, path, msg, args...) { - return - } - t.FailNow() -} - -// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// assert.NotContains(t, "Hello World", "Earth") -// assert.NotContains(t, ["Hello", "World"], "Earth") -// assert.NotContains(t, {"Hello": "World"}, "Earth") -func NotContains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotContains(t, s, contains, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") -// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") -// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") -func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotContainsf(t, s, contains, msg, args...) { - return - } - t.FailNow() -} - -// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// if assert.NotEmpty(t, obj) { -// assert.Equal(t, "two", obj[1]) -// } -func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotEmpty(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// if assert.NotEmptyf(t, obj, "error message %s", "formatted") { -// assert.Equal(t, "two", obj[1]) -// } -func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotEmptyf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// NotEqual asserts that the specified values are NOT equal. -// -// assert.NotEqual(t, obj1, obj2) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func NotEqual(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotEqual(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotEqualValues asserts that two objects are not equal even when converted to the same type -// -// assert.NotEqualValues(t, obj1, obj2) -func NotEqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotEqualValues(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotEqualValuesf asserts that two objects are not equal even when converted to the same type -// -// assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted") -func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotEqualValuesf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// NotEqualf asserts that the specified values are NOT equal. -// -// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotEqualf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// NotErrorIs asserts that at none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func NotErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotErrorIs(t, err, target, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotErrorIsf asserts that at none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotErrorIsf(t, err, target, msg, args...) { - return - } - t.FailNow() -} - -// NotNil asserts that the specified object is not nil. -// -// assert.NotNil(t, err) -func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotNil(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotNilf asserts that the specified object is not nil. -// -// assert.NotNilf(t, err, "error message %s", "formatted") -func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotNilf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// assert.NotPanics(t, func(){ RemainCalm() }) -func NotPanics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotPanics(t, f, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") -func NotPanicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotPanicsf(t, f, msg, args...) { - return - } - t.FailNow() -} - -// NotRegexp asserts that a specified regexp does not match a string. -// -// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") -// assert.NotRegexp(t, "^start", "it's not starting") -func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotRegexp(t, rx, str, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotRegexpf asserts that a specified regexp does not match a string. -// -// assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") -// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") -func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotRegexpf(t, rx, str, msg, args...) { - return - } - t.FailNow() -} - -// NotSame asserts that two pointers do not reference the same object. -// -// assert.NotSame(t, ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func NotSame(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotSame(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotSamef asserts that two pointers do not reference the same object. -// -// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotSamef(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). -// -// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") -func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotSubset(t, list, subset, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). -// -// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") -func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotSubsetf(t, list, subset, msg, args...) { - return - } - t.FailNow() -} - -// NotZero asserts that i is not the zero value for its type. -func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotZero(t, i, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotZerof asserts that i is not the zero value for its type. -func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotZerof(t, i, msg, args...) { - return - } - t.FailNow() -} - -// Panics asserts that the code inside the specified PanicTestFunc panics. -// -// assert.Panics(t, func(){ GoCrazy() }) -func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Panics(t, f, msgAndArgs...) { - return - } - t.FailNow() -} - -// PanicsWithError asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() }) -func PanicsWithError(t TestingT, errString string, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.PanicsWithError(t, errString, f, msgAndArgs...) { - return - } - t.FailNow() -} - -// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func PanicsWithErrorf(t TestingT, errString string, f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.PanicsWithErrorf(t, errString, f, msg, args...) { - return - } - t.FailNow() -} - -// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) -func PanicsWithValue(t TestingT, expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.PanicsWithValue(t, expected, f, msgAndArgs...) { - return - } - t.FailNow() -} - -// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func PanicsWithValuef(t TestingT, expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.PanicsWithValuef(t, expected, f, msg, args...) { - return - } - t.FailNow() -} - -// Panicsf asserts that the code inside the specified PanicTestFunc panics. -// -// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") -func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Panicsf(t, f, msg, args...) { - return - } - t.FailNow() -} - -// Positive asserts that the specified element is positive -// -// assert.Positive(t, 1) -// assert.Positive(t, 1.23) -func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Positive(t, e, msgAndArgs...) { - return - } - t.FailNow() -} - -// Positivef asserts that the specified element is positive -// -// assert.Positivef(t, 1, "error message %s", "formatted") -// assert.Positivef(t, 1.23, "error message %s", "formatted") -func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Positivef(t, e, msg, args...) { - return - } - t.FailNow() -} - -// Regexp asserts that a specified regexp matches a string. -// -// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") -// assert.Regexp(t, "start...$", "it's not starting") -func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Regexp(t, rx, str, msgAndArgs...) { - return - } - t.FailNow() -} - -// Regexpf asserts that a specified regexp matches a string. -// -// assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") -// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") -func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Regexpf(t, rx, str, msg, args...) { - return - } - t.FailNow() -} - -// Same asserts that two pointers reference the same object. -// -// assert.Same(t, ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func Same(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Same(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// Samef asserts that two pointers reference the same object. -// -// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func Samef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Samef(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). -// -// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") -func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Subset(t, list, subset, msgAndArgs...) { - return - } - t.FailNow() -} - -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). -// -// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") -func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Subsetf(t, list, subset, msg, args...) { - return - } - t.FailNow() -} - -// True asserts that the specified value is true. -// -// assert.True(t, myBool) -func True(t TestingT, value bool, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.True(t, value, msgAndArgs...) { - return - } - t.FailNow() -} - -// Truef asserts that the specified value is true. -// -// assert.Truef(t, myBool, "error message %s", "formatted") -func Truef(t TestingT, value bool, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Truef(t, value, msg, args...) { - return - } - t.FailNow() -} - -// WithinDuration asserts that the two times are within duration delta of each other. -// -// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) -func WithinDuration(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.WithinDuration(t, expected, actual, delta, msgAndArgs...) { - return - } - t.FailNow() -} - -// WithinDurationf asserts that the two times are within duration delta of each other. -// -// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") -func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.WithinDurationf(t, expected, actual, delta, msg, args...) { - return - } - t.FailNow() -} - -// WithinRange asserts that a time is within a time range (inclusive). -// -// assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) -func WithinRange(t TestingT, actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.WithinRange(t, actual, start, end, msgAndArgs...) { - return - } - t.FailNow() -} - -// WithinRangef asserts that a time is within a time range (inclusive). -// -// assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") -func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.WithinRangef(t, actual, start, end, msg, args...) { - return - } - t.FailNow() -} - -// YAMLEq asserts that two YAML strings are equivalent. -func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.YAMLEq(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// YAMLEqf asserts that two YAML strings are equivalent. -func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.YAMLEqf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// Zero asserts that i is the zero value for its type. -func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Zero(t, i, msgAndArgs...) { - return - } - t.FailNow() -} - -// Zerof asserts that i is the zero value for its type. -func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Zerof(t, i, msg, args...) { - return - } - t.FailNow() -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/require.go.tmpl b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/require.go.tmpl deleted file mode 100644 index 55e42dd..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/require.go.tmpl +++ /dev/null @@ -1,6 +0,0 @@ -{{.Comment}} -func {{.DocInfo.Name}}(t TestingT, {{.Params}}) { - if h, ok := t.(tHelper); ok { h.Helper() } - if assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { return } - t.FailNow() -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/require_forward.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/require_forward.go deleted file mode 100644 index 960bf6f..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/require_forward.go +++ /dev/null @@ -1,1515 +0,0 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ - -package require - -import ( - assert "github.com/stretchr/testify/assert" - http "net/http" - url "net/url" - time "time" -) - -// Condition uses a Comparison to assert a complex condition. -func (a *Assertions) Condition(comp assert.Comparison, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Condition(a.t, comp, msgAndArgs...) -} - -// Conditionf uses a Comparison to assert a complex condition. -func (a *Assertions) Conditionf(comp assert.Comparison, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Conditionf(a.t, comp, msg, args...) -} - -// Contains asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// a.Contains("Hello World", "World") -// a.Contains(["Hello", "World"], "World") -// a.Contains({"Hello": "World"}, "Hello") -func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Contains(a.t, s, contains, msgAndArgs...) -} - -// Containsf asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// a.Containsf("Hello World", "World", "error message %s", "formatted") -// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") -// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") -func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Containsf(a.t, s, contains, msg, args...) -} - -// DirExists checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - DirExists(a.t, path, msgAndArgs...) -} - -// DirExistsf checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - DirExistsf(a.t, path, msg, args...) -} - -// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]) -func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ElementsMatch(a.t, listA, listB, msgAndArgs...) -} - -// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") -func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ElementsMatchf(a.t, listA, listB, msg, args...) -} - -// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// a.Empty(obj) -func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Empty(a.t, object, msgAndArgs...) -} - -// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// a.Emptyf(obj, "error message %s", "formatted") -func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Emptyf(a.t, object, msg, args...) -} - -// Equal asserts that two objects are equal. -// -// a.Equal(123, 123) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Equal(a.t, expected, actual, msgAndArgs...) -} - -// EqualError asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// a.EqualError(err, expectedErrorString) -func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EqualError(a.t, theError, errString, msgAndArgs...) -} - -// EqualErrorf asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") -func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EqualErrorf(a.t, theError, errString, msg, args...) -} - -// EqualValues asserts that two objects are equal or convertable to the same types -// and equal. -// -// a.EqualValues(uint32(123), int32(123)) -func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EqualValues(a.t, expected, actual, msgAndArgs...) -} - -// EqualValuesf asserts that two objects are equal or convertable to the same types -// and equal. -// -// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") -func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EqualValuesf(a.t, expected, actual, msg, args...) -} - -// Equalf asserts that two objects are equal. -// -// a.Equalf(123, 123, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Equalf(a.t, expected, actual, msg, args...) -} - -// Error asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// if a.Error(err) { -// assert.Equal(t, expectedError, err) -// } -func (a *Assertions) Error(err error, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Error(a.t, err, msgAndArgs...) -} - -// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ErrorAs(a.t, err, target, msgAndArgs...) -} - -// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ErrorAsf(a.t, err, target, msg, args...) -} - -// ErrorContains asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// a.ErrorContains(err, expectedErrorSubString) -func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ErrorContains(a.t, theError, contains, msgAndArgs...) -} - -// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted") -func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ErrorContainsf(a.t, theError, contains, msg, args...) -} - -// ErrorIs asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ErrorIs(a.t, err, target, msgAndArgs...) -} - -// ErrorIsf asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ErrorIsf(a.t, err, target, msg, args...) -} - -// Errorf asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// if a.Errorf(err, "error message %s", "formatted") { -// assert.Equal(t, expectedErrorf, err) -// } -func (a *Assertions) Errorf(err error, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Errorf(a.t, err, msg, args...) -} - -// Eventually asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond) -func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Eventually(a.t, condition, waitFor, tick, msgAndArgs...) -} - -// Eventuallyf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Eventuallyf(a.t, condition, waitFor, tick, msg, args...) -} - -// Exactly asserts that two objects are equal in value and type. -// -// a.Exactly(int32(123), int64(123)) -func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Exactly(a.t, expected, actual, msgAndArgs...) -} - -// Exactlyf asserts that two objects are equal in value and type. -// -// a.Exactlyf(int32(123), int64(123), "error message %s", "formatted") -func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Exactlyf(a.t, expected, actual, msg, args...) -} - -// Fail reports a failure through -func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Fail(a.t, failureMessage, msgAndArgs...) -} - -// FailNow fails test -func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - FailNow(a.t, failureMessage, msgAndArgs...) -} - -// FailNowf fails test -func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - FailNowf(a.t, failureMessage, msg, args...) -} - -// Failf reports a failure through -func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Failf(a.t, failureMessage, msg, args...) -} - -// False asserts that the specified value is false. -// -// a.False(myBool) -func (a *Assertions) False(value bool, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - False(a.t, value, msgAndArgs...) -} - -// Falsef asserts that the specified value is false. -// -// a.Falsef(myBool, "error message %s", "formatted") -func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Falsef(a.t, value, msg, args...) -} - -// FileExists checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - FileExists(a.t, path, msgAndArgs...) -} - -// FileExistsf checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - FileExistsf(a.t, path, msg, args...) -} - -// Greater asserts that the first element is greater than the second -// -// a.Greater(2, 1) -// a.Greater(float64(2), float64(1)) -// a.Greater("b", "a") -func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Greater(a.t, e1, e2, msgAndArgs...) -} - -// GreaterOrEqual asserts that the first element is greater than or equal to the second -// -// a.GreaterOrEqual(2, 1) -// a.GreaterOrEqual(2, 2) -// a.GreaterOrEqual("b", "a") -// a.GreaterOrEqual("b", "b") -func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - GreaterOrEqual(a.t, e1, e2, msgAndArgs...) -} - -// GreaterOrEqualf asserts that the first element is greater than or equal to the second -// -// a.GreaterOrEqualf(2, 1, "error message %s", "formatted") -// a.GreaterOrEqualf(2, 2, "error message %s", "formatted") -// a.GreaterOrEqualf("b", "a", "error message %s", "formatted") -// a.GreaterOrEqualf("b", "b", "error message %s", "formatted") -func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - GreaterOrEqualf(a.t, e1, e2, msg, args...) -} - -// Greaterf asserts that the first element is greater than the second -// -// a.Greaterf(2, 1, "error message %s", "formatted") -// a.Greaterf(float64(2), float64(1), "error message %s", "formatted") -// a.Greaterf("b", "a", "error message %s", "formatted") -func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Greaterf(a.t, e1, e2, msg, args...) -} - -// HTTPBodyContains asserts that a specified handler returns a -// body that contains a string. -// -// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) -} - -// HTTPBodyContainsf asserts that a specified handler returns a -// body that contains a string. -// -// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) -} - -// HTTPBodyNotContains asserts that a specified handler returns a -// body that does not contain a string. -// -// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) -} - -// HTTPBodyNotContainsf asserts that a specified handler returns a -// body that does not contain a string. -// -// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) -} - -// HTTPError asserts that a specified handler returns an error status code. -// -// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPError(a.t, handler, method, url, values, msgAndArgs...) -} - -// HTTPErrorf asserts that a specified handler returns an error status code. -// -// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPErrorf(a.t, handler, method, url, values, msg, args...) -} - -// HTTPRedirect asserts that a specified handler returns a redirect status code. -// -// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) -} - -// HTTPRedirectf asserts that a specified handler returns a redirect status code. -// -// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPRedirectf(a.t, handler, method, url, values, msg, args...) -} - -// HTTPStatusCode asserts that a specified handler returns a specified status code. -// -// a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501) -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPStatusCode(a.t, handler, method, url, values, statuscode, msgAndArgs...) -} - -// HTTPStatusCodef asserts that a specified handler returns a specified status code. -// -// a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPStatusCodef(a.t, handler, method, url, values, statuscode, msg, args...) -} - -// HTTPSuccess asserts that a specified handler returns a success status code. -// -// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) -} - -// HTTPSuccessf asserts that a specified handler returns a success status code. -// -// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPSuccessf(a.t, handler, method, url, values, msg, args...) -} - -// Implements asserts that an object is implemented by the specified interface. -// -// a.Implements((*MyInterface)(nil), new(MyObject)) -func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Implements(a.t, interfaceObject, object, msgAndArgs...) -} - -// Implementsf asserts that an object is implemented by the specified interface. -// -// a.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Implementsf(a.t, interfaceObject, object, msg, args...) -} - -// InDelta asserts that the two numerals are within delta of each other. -// -// a.InDelta(math.Pi, 22/7.0, 0.01) -func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InDelta(a.t, expected, actual, delta, msgAndArgs...) -} - -// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) -} - -// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) -} - -// InDeltaSlice is the same as InDelta, except it compares two slices. -func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) -} - -// InDeltaSlicef is the same as InDelta, except it compares two slices. -func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InDeltaSlicef(a.t, expected, actual, delta, msg, args...) -} - -// InDeltaf asserts that the two numerals are within delta of each other. -// -// a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted") -func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InDeltaf(a.t, expected, actual, delta, msg, args...) -} - -// InEpsilon asserts that expected and actual have a relative error less than epsilon -func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) -} - -// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. -func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) -} - -// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. -func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) -} - -// InEpsilonf asserts that expected and actual have a relative error less than epsilon -func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InEpsilonf(a.t, expected, actual, epsilon, msg, args...) -} - -// IsDecreasing asserts that the collection is decreasing -// -// a.IsDecreasing([]int{2, 1, 0}) -// a.IsDecreasing([]float{2, 1}) -// a.IsDecreasing([]string{"b", "a"}) -func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsDecreasing(a.t, object, msgAndArgs...) -} - -// IsDecreasingf asserts that the collection is decreasing -// -// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted") -// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted") -// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted") -func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsDecreasingf(a.t, object, msg, args...) -} - -// IsIncreasing asserts that the collection is increasing -// -// a.IsIncreasing([]int{1, 2, 3}) -// a.IsIncreasing([]float{1, 2}) -// a.IsIncreasing([]string{"a", "b"}) -func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsIncreasing(a.t, object, msgAndArgs...) -} - -// IsIncreasingf asserts that the collection is increasing -// -// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted") -// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted") -// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted") -func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsIncreasingf(a.t, object, msg, args...) -} - -// IsNonDecreasing asserts that the collection is not decreasing -// -// a.IsNonDecreasing([]int{1, 1, 2}) -// a.IsNonDecreasing([]float{1, 2}) -// a.IsNonDecreasing([]string{"a", "b"}) -func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsNonDecreasing(a.t, object, msgAndArgs...) -} - -// IsNonDecreasingf asserts that the collection is not decreasing -// -// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted") -// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted") -// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted") -func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsNonDecreasingf(a.t, object, msg, args...) -} - -// IsNonIncreasing asserts that the collection is not increasing -// -// a.IsNonIncreasing([]int{2, 1, 1}) -// a.IsNonIncreasing([]float{2, 1}) -// a.IsNonIncreasing([]string{"b", "a"}) -func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsNonIncreasing(a.t, object, msgAndArgs...) -} - -// IsNonIncreasingf asserts that the collection is not increasing -// -// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted") -// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted") -// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted") -func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsNonIncreasingf(a.t, object, msg, args...) -} - -// IsType asserts that the specified objects are of the same type. -func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsType(a.t, expectedType, object, msgAndArgs...) -} - -// IsTypef asserts that the specified objects are of the same type. -func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsTypef(a.t, expectedType, object, msg, args...) -} - -// JSONEq asserts that two JSON strings are equivalent. -// -// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) -func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - JSONEq(a.t, expected, actual, msgAndArgs...) -} - -// JSONEqf asserts that two JSON strings are equivalent. -// -// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") -func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - JSONEqf(a.t, expected, actual, msg, args...) -} - -// Len asserts that the specified object has specific length. -// Len also fails if the object has a type that len() not accept. -// -// a.Len(mySlice, 3) -func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Len(a.t, object, length, msgAndArgs...) -} - -// Lenf asserts that the specified object has specific length. -// Lenf also fails if the object has a type that len() not accept. -// -// a.Lenf(mySlice, 3, "error message %s", "formatted") -func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Lenf(a.t, object, length, msg, args...) -} - -// Less asserts that the first element is less than the second -// -// a.Less(1, 2) -// a.Less(float64(1), float64(2)) -// a.Less("a", "b") -func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Less(a.t, e1, e2, msgAndArgs...) -} - -// LessOrEqual asserts that the first element is less than or equal to the second -// -// a.LessOrEqual(1, 2) -// a.LessOrEqual(2, 2) -// a.LessOrEqual("a", "b") -// a.LessOrEqual("b", "b") -func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - LessOrEqual(a.t, e1, e2, msgAndArgs...) -} - -// LessOrEqualf asserts that the first element is less than or equal to the second -// -// a.LessOrEqualf(1, 2, "error message %s", "formatted") -// a.LessOrEqualf(2, 2, "error message %s", "formatted") -// a.LessOrEqualf("a", "b", "error message %s", "formatted") -// a.LessOrEqualf("b", "b", "error message %s", "formatted") -func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - LessOrEqualf(a.t, e1, e2, msg, args...) -} - -// Lessf asserts that the first element is less than the second -// -// a.Lessf(1, 2, "error message %s", "formatted") -// a.Lessf(float64(1), float64(2), "error message %s", "formatted") -// a.Lessf("a", "b", "error message %s", "formatted") -func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Lessf(a.t, e1, e2, msg, args...) -} - -// Negative asserts that the specified element is negative -// -// a.Negative(-1) -// a.Negative(-1.23) -func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Negative(a.t, e, msgAndArgs...) -} - -// Negativef asserts that the specified element is negative -// -// a.Negativef(-1, "error message %s", "formatted") -// a.Negativef(-1.23, "error message %s", "formatted") -func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Negativef(a.t, e, msg, args...) -} - -// Never asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond) -func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Never(a.t, condition, waitFor, tick, msgAndArgs...) -} - -// Neverf asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Neverf(a.t, condition, waitFor, tick, msg, args...) -} - -// Nil asserts that the specified object is nil. -// -// a.Nil(err) -func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Nil(a.t, object, msgAndArgs...) -} - -// Nilf asserts that the specified object is nil. -// -// a.Nilf(err, "error message %s", "formatted") -func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Nilf(a.t, object, msg, args...) -} - -// NoDirExists checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func (a *Assertions) NoDirExists(path string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NoDirExists(a.t, path, msgAndArgs...) -} - -// NoDirExistsf checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NoDirExistsf(a.t, path, msg, args...) -} - -// NoError asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if a.NoError(err) { -// assert.Equal(t, expectedObj, actualObj) -// } -func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NoError(a.t, err, msgAndArgs...) -} - -// NoErrorf asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if a.NoErrorf(err, "error message %s", "formatted") { -// assert.Equal(t, expectedObj, actualObj) -// } -func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NoErrorf(a.t, err, msg, args...) -} - -// NoFileExists checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func (a *Assertions) NoFileExists(path string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NoFileExists(a.t, path, msgAndArgs...) -} - -// NoFileExistsf checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func (a *Assertions) NoFileExistsf(path string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NoFileExistsf(a.t, path, msg, args...) -} - -// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// a.NotContains("Hello World", "Earth") -// a.NotContains(["Hello", "World"], "Earth") -// a.NotContains({"Hello": "World"}, "Earth") -func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotContains(a.t, s, contains, msgAndArgs...) -} - -// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") -// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") -// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") -func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotContainsf(a.t, s, contains, msg, args...) -} - -// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// if a.NotEmpty(obj) { -// assert.Equal(t, "two", obj[1]) -// } -func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotEmpty(a.t, object, msgAndArgs...) -} - -// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// if a.NotEmptyf(obj, "error message %s", "formatted") { -// assert.Equal(t, "two", obj[1]) -// } -func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotEmptyf(a.t, object, msg, args...) -} - -// NotEqual asserts that the specified values are NOT equal. -// -// a.NotEqual(obj1, obj2) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotEqual(a.t, expected, actual, msgAndArgs...) -} - -// NotEqualValues asserts that two objects are not equal even when converted to the same type -// -// a.NotEqualValues(obj1, obj2) -func (a *Assertions) NotEqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotEqualValues(a.t, expected, actual, msgAndArgs...) -} - -// NotEqualValuesf asserts that two objects are not equal even when converted to the same type -// -// a.NotEqualValuesf(obj1, obj2, "error message %s", "formatted") -func (a *Assertions) NotEqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotEqualValuesf(a.t, expected, actual, msg, args...) -} - -// NotEqualf asserts that the specified values are NOT equal. -// -// a.NotEqualf(obj1, obj2, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotEqualf(a.t, expected, actual, msg, args...) -} - -// NotErrorIs asserts that at none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotErrorIs(a.t, err, target, msgAndArgs...) -} - -// NotErrorIsf asserts that at none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotErrorIsf(a.t, err, target, msg, args...) -} - -// NotNil asserts that the specified object is not nil. -// -// a.NotNil(err) -func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotNil(a.t, object, msgAndArgs...) -} - -// NotNilf asserts that the specified object is not nil. -// -// a.NotNilf(err, "error message %s", "formatted") -func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotNilf(a.t, object, msg, args...) -} - -// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// a.NotPanics(func(){ RemainCalm() }) -func (a *Assertions) NotPanics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotPanics(a.t, f, msgAndArgs...) -} - -// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") -func (a *Assertions) NotPanicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotPanicsf(a.t, f, msg, args...) -} - -// NotRegexp asserts that a specified regexp does not match a string. -// -// a.NotRegexp(regexp.MustCompile("starts"), "it's starting") -// a.NotRegexp("^start", "it's not starting") -func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotRegexp(a.t, rx, str, msgAndArgs...) -} - -// NotRegexpf asserts that a specified regexp does not match a string. -// -// a.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") -// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") -func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotRegexpf(a.t, rx, str, msg, args...) -} - -// NotSame asserts that two pointers do not reference the same object. -// -// a.NotSame(ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) NotSame(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotSame(a.t, expected, actual, msgAndArgs...) -} - -// NotSamef asserts that two pointers do not reference the same object. -// -// a.NotSamef(ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotSamef(a.t, expected, actual, msg, args...) -} - -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). -// -// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") -func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotSubset(a.t, list, subset, msgAndArgs...) -} - -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). -// -// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") -func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotSubsetf(a.t, list, subset, msg, args...) -} - -// NotZero asserts that i is not the zero value for its type. -func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotZero(a.t, i, msgAndArgs...) -} - -// NotZerof asserts that i is not the zero value for its type. -func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotZerof(a.t, i, msg, args...) -} - -// Panics asserts that the code inside the specified PanicTestFunc panics. -// -// a.Panics(func(){ GoCrazy() }) -func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Panics(a.t, f, msgAndArgs...) -} - -// PanicsWithError asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// a.PanicsWithError("crazy error", func(){ GoCrazy() }) -func (a *Assertions) PanicsWithError(errString string, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - PanicsWithError(a.t, errString, f, msgAndArgs...) -} - -// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func (a *Assertions) PanicsWithErrorf(errString string, f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - PanicsWithErrorf(a.t, errString, f, msg, args...) -} - -// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// a.PanicsWithValue("crazy error", func(){ GoCrazy() }) -func (a *Assertions) PanicsWithValue(expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - PanicsWithValue(a.t, expected, f, msgAndArgs...) -} - -// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func (a *Assertions) PanicsWithValuef(expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - PanicsWithValuef(a.t, expected, f, msg, args...) -} - -// Panicsf asserts that the code inside the specified PanicTestFunc panics. -// -// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") -func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Panicsf(a.t, f, msg, args...) -} - -// Positive asserts that the specified element is positive -// -// a.Positive(1) -// a.Positive(1.23) -func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Positive(a.t, e, msgAndArgs...) -} - -// Positivef asserts that the specified element is positive -// -// a.Positivef(1, "error message %s", "formatted") -// a.Positivef(1.23, "error message %s", "formatted") -func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Positivef(a.t, e, msg, args...) -} - -// Regexp asserts that a specified regexp matches a string. -// -// a.Regexp(regexp.MustCompile("start"), "it's starting") -// a.Regexp("start...$", "it's not starting") -func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Regexp(a.t, rx, str, msgAndArgs...) -} - -// Regexpf asserts that a specified regexp matches a string. -// -// a.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") -// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") -func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Regexpf(a.t, rx, str, msg, args...) -} - -// Same asserts that two pointers reference the same object. -// -// a.Same(ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Same(a.t, expected, actual, msgAndArgs...) -} - -// Samef asserts that two pointers reference the same object. -// -// a.Samef(ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Samef(a.t, expected, actual, msg, args...) -} - -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). -// -// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") -func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Subset(a.t, list, subset, msgAndArgs...) -} - -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). -// -// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") -func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Subsetf(a.t, list, subset, msg, args...) -} - -// True asserts that the specified value is true. -// -// a.True(myBool) -func (a *Assertions) True(value bool, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - True(a.t, value, msgAndArgs...) -} - -// Truef asserts that the specified value is true. -// -// a.Truef(myBool, "error message %s", "formatted") -func (a *Assertions) Truef(value bool, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Truef(a.t, value, msg, args...) -} - -// WithinDuration asserts that the two times are within duration delta of each other. -// -// a.WithinDuration(time.Now(), time.Now(), 10*time.Second) -func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - WithinDuration(a.t, expected, actual, delta, msgAndArgs...) -} - -// WithinDurationf asserts that the two times are within duration delta of each other. -// -// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") -func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - WithinDurationf(a.t, expected, actual, delta, msg, args...) -} - -// WithinRange asserts that a time is within a time range (inclusive). -// -// a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) -func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - WithinRange(a.t, actual, start, end, msgAndArgs...) -} - -// WithinRangef asserts that a time is within a time range (inclusive). -// -// a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") -func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - WithinRangef(a.t, actual, start, end, msg, args...) -} - -// YAMLEq asserts that two YAML strings are equivalent. -func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - YAMLEq(a.t, expected, actual, msgAndArgs...) -} - -// YAMLEqf asserts that two YAML strings are equivalent. -func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - YAMLEqf(a.t, expected, actual, msg, args...) -} - -// Zero asserts that i is the zero value for its type. -func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Zero(a.t, i, msgAndArgs...) -} - -// Zerof asserts that i is the zero value for its type. -func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Zerof(a.t, i, msg, args...) -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/require_forward.go.tmpl b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/require_forward.go.tmpl deleted file mode 100644 index 54124df..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/require_forward.go.tmpl +++ /dev/null @@ -1,5 +0,0 @@ -{{.CommentWithoutT "a"}} -func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) { - if h, ok := a.t.(tHelper); ok { h.Helper() } - {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/requirements.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/requirements.go deleted file mode 100644 index 91772df..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/requirements.go +++ /dev/null @@ -1,29 +0,0 @@ -package require - -// TestingT is an interface wrapper around *testing.T -type TestingT interface { - Errorf(format string, args ...interface{}) - FailNow() -} - -type tHelper interface { - Helper() -} - -// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful -// for table driven tests. -type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) - -// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful -// for table driven tests. -type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) - -// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful -// for table driven tests. -type BoolAssertionFunc func(TestingT, bool, ...interface{}) - -// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful -// for table driven tests. -type ErrorAssertionFunc func(TestingT, error, ...interface{}) - -//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require.go.tmpl -include-format-funcs" diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/requirements_test.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/requirements_test.go deleted file mode 100644 index febf0c1..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/require/requirements_test.go +++ /dev/null @@ -1,683 +0,0 @@ -package require - -import ( - "encoding/json" - "errors" - "testing" - "time" -) - -// AssertionTesterInterface defines an interface to be used for testing assertion methods -type AssertionTesterInterface interface { - TestMethod() -} - -// AssertionTesterConformingObject is an object that conforms to the AssertionTesterInterface interface -type AssertionTesterConformingObject struct { -} - -func (a *AssertionTesterConformingObject) TestMethod() { -} - -// AssertionTesterNonConformingObject is an object that does not conform to the AssertionTesterInterface interface -type AssertionTesterNonConformingObject struct { -} - -type MockT struct { - Failed bool -} - -func (t *MockT) FailNow() { - t.Failed = true -} - -func (t *MockT) Errorf(format string, args ...interface{}) { - _, _ = format, args -} - -func TestImplements(t *testing.T) { - - Implements(t, (*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) - - mockT := new(MockT) - Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestIsType(t *testing.T) { - - IsType(t, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) - - mockT := new(MockT) - IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestEqual(t *testing.T) { - - Equal(t, 1, 1) - - mockT := new(MockT) - Equal(mockT, 1, 2) - if !mockT.Failed { - t.Error("Check should fail") - } - -} - -func TestNotEqual(t *testing.T) { - - NotEqual(t, 1, 2) - mockT := new(MockT) - NotEqual(mockT, 2, 2) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestExactly(t *testing.T) { - - a := float32(1) - b := float32(1) - c := float64(1) - - Exactly(t, a, b) - - mockT := new(MockT) - Exactly(mockT, a, c) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestNotNil(t *testing.T) { - - NotNil(t, new(AssertionTesterConformingObject)) - - mockT := new(MockT) - NotNil(mockT, nil) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestNil(t *testing.T) { - - Nil(t, nil) - - mockT := new(MockT) - Nil(mockT, new(AssertionTesterConformingObject)) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestTrue(t *testing.T) { - - True(t, true) - - mockT := new(MockT) - True(mockT, false) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestFalse(t *testing.T) { - - False(t, false) - - mockT := new(MockT) - False(mockT, true) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestContains(t *testing.T) { - - Contains(t, "Hello World", "Hello") - - mockT := new(MockT) - Contains(mockT, "Hello World", "Salut") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestNotContains(t *testing.T) { - - NotContains(t, "Hello World", "Hello!") - - mockT := new(MockT) - NotContains(mockT, "Hello World", "Hello") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestPanics(t *testing.T) { - - Panics(t, func() { - panic("Panic!") - }) - - mockT := new(MockT) - Panics(mockT, func() {}) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestNotPanics(t *testing.T) { - - NotPanics(t, func() {}) - - mockT := new(MockT) - NotPanics(mockT, func() { - panic("Panic!") - }) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestNoError(t *testing.T) { - - NoError(t, nil) - - mockT := new(MockT) - NoError(mockT, errors.New("some error")) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestError(t *testing.T) { - - Error(t, errors.New("some error")) - - mockT := new(MockT) - Error(mockT, nil) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestErrorContains(t *testing.T) { - - ErrorContains(t, errors.New("some error: another error"), "some error") - - mockT := new(MockT) - ErrorContains(mockT, errors.New("some error"), "different error") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestEqualError(t *testing.T) { - - EqualError(t, errors.New("some error"), "some error") - - mockT := new(MockT) - EqualError(mockT, errors.New("some error"), "Not some error") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestEmpty(t *testing.T) { - - Empty(t, "") - - mockT := new(MockT) - Empty(mockT, "x") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestNotEmpty(t *testing.T) { - - NotEmpty(t, "x") - - mockT := new(MockT) - NotEmpty(mockT, "") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestWithinDuration(t *testing.T) { - - a := time.Now() - b := a.Add(10 * time.Second) - - WithinDuration(t, a, b, 15*time.Second) - - mockT := new(MockT) - WithinDuration(mockT, a, b, 5*time.Second) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestInDelta(t *testing.T) { - - InDelta(t, 1.001, 1, 0.01) - - mockT := new(MockT) - InDelta(mockT, 1, 2, 0.5) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestZero(t *testing.T) { - - Zero(t, "") - - mockT := new(MockT) - Zero(mockT, "x") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestNotZero(t *testing.T) { - - NotZero(t, "x") - - mockT := new(MockT) - NotZero(mockT, "") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestJSONEq_EqualSONString(t *testing.T) { - mockT := new(MockT) - JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) - if mockT.Failed { - t.Error("Check should pass") - } -} - -func TestJSONEq_EquivalentButNotEqual(t *testing.T) { - mockT := new(MockT) - JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) - if mockT.Failed { - t.Error("Check should pass") - } -} - -func TestJSONEq_HashOfArraysAndHashes(t *testing.T) { - mockT := new(MockT) - JSONEq(mockT, "{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}", - "{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}") - if mockT.Failed { - t.Error("Check should pass") - } -} - -func TestJSONEq_Array(t *testing.T) { - mockT := new(MockT) - JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) - if mockT.Failed { - t.Error("Check should pass") - } -} - -func TestJSONEq_HashAndArrayNotEquivalent(t *testing.T) { - mockT := new(MockT) - JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestJSONEq_HashesNotEquivalent(t *testing.T) { - mockT := new(MockT) - JSONEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestJSONEq_ActualIsNotJSON(t *testing.T) { - mockT := new(MockT) - JSONEq(mockT, `{"foo": "bar"}`, "Not JSON") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestJSONEq_ExpectedIsNotJSON(t *testing.T) { - mockT := new(MockT) - JSONEq(mockT, "Not JSON", `{"foo": "bar", "hello": "world"}`) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestJSONEq_ExpectedAndActualNotJSON(t *testing.T) { - mockT := new(MockT) - JSONEq(mockT, "Not JSON", "Not JSON") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestJSONEq_ArraysOfDifferentOrder(t *testing.T) { - mockT := new(MockT) - JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestYAMLEq_EqualYAMLString(t *testing.T) { - mockT := new(MockT) - YAMLEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) - if mockT.Failed { - t.Error("Check should pass") - } -} - -func TestYAMLEq_EquivalentButNotEqual(t *testing.T) { - mockT := new(MockT) - YAMLEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) - if mockT.Failed { - t.Error("Check should pass") - } -} - -func TestYAMLEq_HashOfArraysAndHashes(t *testing.T) { - mockT := new(MockT) - expected := ` -numeric: 1.5 -array: - - foo: bar - - 1 - - "string" - - ["nested", "array", 5.5] -hash: - nested: hash - nested_slice: [this, is, nested] -string: "foo" -` - - actual := ` -numeric: 1.5 -hash: - nested: hash - nested_slice: [this, is, nested] -string: "foo" -array: - - foo: bar - - 1 - - "string" - - ["nested", "array", 5.5] -` - YAMLEq(mockT, expected, actual) - if mockT.Failed { - t.Error("Check should pass") - } -} - -func TestYAMLEq_Array(t *testing.T) { - mockT := new(MockT) - YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) - if mockT.Failed { - t.Error("Check should pass") - } -} - -func TestYAMLEq_HashAndArrayNotEquivalent(t *testing.T) { - mockT := new(MockT) - YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestYAMLEq_HashesNotEquivalent(t *testing.T) { - mockT := new(MockT) - YAMLEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestYAMLEq_ActualIsSimpleString(t *testing.T) { - mockT := new(MockT) - YAMLEq(mockT, `{"foo": "bar"}`, "Simple String") - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestYAMLEq_ExpectedIsSimpleString(t *testing.T) { - mockT := new(MockT) - YAMLEq(mockT, "Simple String", `{"foo": "bar", "hello": "world"}`) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func TestYAMLEq_ExpectedAndActualSimpleString(t *testing.T) { - mockT := new(MockT) - YAMLEq(mockT, "Simple String", "Simple String") - if mockT.Failed { - t.Error("Check should pass") - } -} - -func TestYAMLEq_ArraysOfDifferentOrder(t *testing.T) { - mockT := new(MockT) - YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) - if !mockT.Failed { - t.Error("Check should fail") - } -} - -func ExampleComparisonAssertionFunc() { - t := &testing.T{} // provided by test - - adder := func(x, y int) int { - return x + y - } - - type args struct { - x int - y int - } - - tests := []struct { - name string - args args - expect int - assertion ComparisonAssertionFunc - }{ - {"2+2=4", args{2, 2}, 4, Equal}, - {"2+2!=5", args{2, 2}, 5, NotEqual}, - {"2+3==5", args{2, 3}, 5, Exactly}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.assertion(t, tt.expect, adder(tt.args.x, tt.args.y)) - }) - } -} - -func TestComparisonAssertionFunc(t *testing.T) { - type iface interface { - Name() string - } - - tests := []struct { - name string - expect interface{} - got interface{} - assertion ComparisonAssertionFunc - }{ - {"implements", (*iface)(nil), t, Implements}, - {"isType", (*testing.T)(nil), t, IsType}, - {"equal", t, t, Equal}, - {"equalValues", t, t, EqualValues}, - {"exactly", t, t, Exactly}, - {"notEqual", t, nil, NotEqual}, - {"NotEqualValues", t, nil, NotEqualValues}, - {"notContains", []int{1, 2, 3}, 4, NotContains}, - {"subset", []int{1, 2, 3, 4}, []int{2, 3}, Subset}, - {"notSubset", []int{1, 2, 3, 4}, []int{0, 3}, NotSubset}, - {"elementsMatch", []byte("abc"), []byte("bac"), ElementsMatch}, - {"regexp", "^t.*y$", "testify", Regexp}, - {"notRegexp", "^t.*y$", "Testify", NotRegexp}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.assertion(t, tt.expect, tt.got) - }) - } -} - -func ExampleValueAssertionFunc() { - t := &testing.T{} // provided by test - - dumbParse := func(input string) interface{} { - var x interface{} - json.Unmarshal([]byte(input), &x) - return x - } - - tests := []struct { - name string - arg string - assertion ValueAssertionFunc - }{ - {"true is not nil", "true", NotNil}, - {"empty string is nil", "", Nil}, - {"zero is not nil", "0", NotNil}, - {"zero is zero", "0", Zero}, - {"false is zero", "false", Zero}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.assertion(t, dumbParse(tt.arg)) - }) - } -} - -func TestValueAssertionFunc(t *testing.T) { - tests := []struct { - name string - value interface{} - assertion ValueAssertionFunc - }{ - {"notNil", true, NotNil}, - {"nil", nil, Nil}, - {"empty", []int{}, Empty}, - {"notEmpty", []int{1}, NotEmpty}, - {"zero", false, Zero}, - {"notZero", 42, NotZero}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.assertion(t, tt.value) - }) - } -} - -func ExampleBoolAssertionFunc() { - t := &testing.T{} // provided by test - - isOkay := func(x int) bool { - return x >= 42 - } - - tests := []struct { - name string - arg int - assertion BoolAssertionFunc - }{ - {"-1 is bad", -1, False}, - {"42 is good", 42, True}, - {"41 is bad", 41, False}, - {"45 is cool", 45, True}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.assertion(t, isOkay(tt.arg)) - }) - } -} - -func TestBoolAssertionFunc(t *testing.T) { - tests := []struct { - name string - value bool - assertion BoolAssertionFunc - }{ - {"true", true, True}, - {"false", false, False}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.assertion(t, tt.value) - }) - } -} - -func ExampleErrorAssertionFunc() { - t := &testing.T{} // provided by test - - dumbParseNum := func(input string, v interface{}) error { - return json.Unmarshal([]byte(input), v) - } - - tests := []struct { - name string - arg string - assertion ErrorAssertionFunc - }{ - {"1.2 is number", "1.2", NoError}, - {"1.2.3 not number", "1.2.3", Error}, - {"true is not number", "true", Error}, - {"3 is number", "3", NoError}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - var x float64 - tt.assertion(t, dumbParseNum(tt.arg, &x)) - }) - } -} - -func TestErrorAssertionFunc(t *testing.T) { - tests := []struct { - name string - err error - assertion ErrorAssertionFunc - }{ - {"noError", nil, NoError}, - {"error", errors.New("whoops"), Error}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.assertion(t, tt.err) - }) - } -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/doc.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/doc.go deleted file mode 100644 index f91a245..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/doc.go +++ /dev/null @@ -1,65 +0,0 @@ -// Package suite contains logic for creating testing suite structs -// and running the methods on those structs as tests. The most useful -// piece of this package is that you can create setup/teardown methods -// on your testing suites, which will run before/after the whole suite -// or individual tests (depending on which interface(s) you -// implement). -// -// A testing suite is usually built by first extending the built-in -// suite functionality from suite.Suite in testify. Alternatively, -// you could reproduce that logic on your own if you wanted (you -// just need to implement the TestingSuite interface from -// suite/interfaces.go). -// -// After that, you can implement any of the interfaces in -// suite/interfaces.go to add setup/teardown functionality to your -// suite, and add any methods that start with "Test" to add tests. -// Methods that do not match any suite interfaces and do not begin -// with "Test" will not be run by testify, and can safely be used as -// helper methods. -// -// Once you've built your testing suite, you need to run the suite -// (using suite.Run from testify) inside any function that matches the -// identity that "go test" is already looking for (i.e. -// func(*testing.T)). -// -// Regular expression to select test suites specified command-line -// argument "-run". Regular expression to select the methods -// of test suites specified command-line argument "-m". -// Suite object has assertion methods. -// -// A crude example: -// // Basic imports -// import ( -// "testing" -// "github.com/stretchr/testify/assert" -// "github.com/stretchr/testify/suite" -// ) -// -// // Define the suite, and absorb the built-in basic suite -// // functionality from testify - including a T() method which -// // returns the current testing context -// type ExampleTestSuite struct { -// suite.Suite -// VariableThatShouldStartAtFive int -// } -// -// // Make sure that VariableThatShouldStartAtFive is set to five -// // before each test -// func (suite *ExampleTestSuite) SetupTest() { -// suite.VariableThatShouldStartAtFive = 5 -// } -// -// // All methods that begin with "Test" are run as tests within a -// // suite. -// func (suite *ExampleTestSuite) TestExample() { -// assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive) -// suite.Equal(5, suite.VariableThatShouldStartAtFive) -// } -// -// // In order for 'go test' to run this suite, we need to create -// // a normal test function and pass our suite to suite.Run -// func TestExampleTestSuite(t *testing.T) { -// suite.Run(t, new(ExampleTestSuite)) -// } -package suite diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/interfaces.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/interfaces.go deleted file mode 100644 index fed037d..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/interfaces.go +++ /dev/null @@ -1,66 +0,0 @@ -package suite - -import "testing" - -// TestingSuite can store and return the current *testing.T context -// generated by 'go test'. -type TestingSuite interface { - T() *testing.T - SetT(*testing.T) - SetS(suite TestingSuite) -} - -// SetupAllSuite has a SetupSuite method, which will run before the -// tests in the suite are run. -type SetupAllSuite interface { - SetupSuite() -} - -// SetupTestSuite has a SetupTest method, which will run before each -// test in the suite. -type SetupTestSuite interface { - SetupTest() -} - -// TearDownAllSuite has a TearDownSuite method, which will run after -// all the tests in the suite have been run. -type TearDownAllSuite interface { - TearDownSuite() -} - -// TearDownTestSuite has a TearDownTest method, which will run after -// each test in the suite. -type TearDownTestSuite interface { - TearDownTest() -} - -// BeforeTest has a function to be executed right before the test -// starts and receives the suite and test names as input -type BeforeTest interface { - BeforeTest(suiteName, testName string) -} - -// AfterTest has a function to be executed right after the test -// finishes and receives the suite and test names as input -type AfterTest interface { - AfterTest(suiteName, testName string) -} - -// WithStats implements HandleStats, a function that will be executed -// when a test suite is finished. The stats contain information about -// the execution of that suite and its tests. -type WithStats interface { - HandleStats(suiteName string, stats *SuiteInformation) -} - -// SetupSubTest has a SetupSubTest method, which will run before each -// subtest in the suite. -type SetupSubTest interface { - SetupSubTest() -} - -// TearDownSubTest has a TearDownSubTest method, which will run after -// each subtest in the suite have been run. -type TearDownSubTest interface { - TearDownSubTest() -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/stats.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/stats.go deleted file mode 100644 index 261da37..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/stats.go +++ /dev/null @@ -1,46 +0,0 @@ -package suite - -import "time" - -// SuiteInformation stats stores stats for the whole suite execution. -type SuiteInformation struct { - Start, End time.Time - TestStats map[string]*TestInformation -} - -// TestInformation stores information about the execution of each test. -type TestInformation struct { - TestName string - Start, End time.Time - Passed bool -} - -func newSuiteInformation() *SuiteInformation { - testStats := make(map[string]*TestInformation) - - return &SuiteInformation{ - TestStats: testStats, - } -} - -func (s SuiteInformation) start(testName string) { - s.TestStats[testName] = &TestInformation{ - TestName: testName, - Start: time.Now(), - } -} - -func (s SuiteInformation) end(testName string, passed bool) { - s.TestStats[testName].End = time.Now() - s.TestStats[testName].Passed = passed -} - -func (s SuiteInformation) Passed() bool { - for _, stats := range s.TestStats { - if !stats.Passed { - return false - } - } - - return true -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/stats_test.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/stats_test.go deleted file mode 100644 index 4446a6d..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/stats_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package suite - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestPassedReturnsTrueWhenAllTestsPass(t *testing.T) { - sinfo := newSuiteInformation() - sinfo.TestStats = map[string]*TestInformation{ - "Test1": {TestName: "Test1", Passed: true}, - "Test2": {TestName: "Test2", Passed: true}, - "Test3": {TestName: "Test3", Passed: true}, - } - - assert.True(t, sinfo.Passed()) -} - -func TestPassedReturnsFalseWhenSomeTestFails(t *testing.T) { - sinfo := newSuiteInformation() - sinfo.TestStats = map[string]*TestInformation{ - "Test1": {TestName: "Test1", Passed: true}, - "Test2": {TestName: "Test2", Passed: false}, - "Test3": {TestName: "Test3", Passed: true}, - } - - assert.False(t, sinfo.Passed()) -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/suite.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/suite.go deleted file mode 100644 index 8b4202d..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/suite.go +++ /dev/null @@ -1,248 +0,0 @@ -package suite - -import ( - "flag" - "fmt" - "os" - "reflect" - "regexp" - "runtime/debug" - "sync" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -var allTestsFilter = func(_, _ string) (bool, error) { return true, nil } -var matchMethod = flag.String("testify.m", "", "regular expression to select tests of the testify suite to run") - -// Suite is a basic testing suite with methods for storing and -// retrieving the current *testing.T context. -type Suite struct { - *assert.Assertions - - mu sync.RWMutex - require *require.Assertions - t *testing.T - - // Parent suite to have access to the implemented methods of parent struct - s TestingSuite -} - -// T retrieves the current *testing.T context. -func (suite *Suite) T() *testing.T { - suite.mu.RLock() - defer suite.mu.RUnlock() - return suite.t -} - -// SetT sets the current *testing.T context. -func (suite *Suite) SetT(t *testing.T) { - suite.mu.Lock() - defer suite.mu.Unlock() - suite.t = t - suite.Assertions = assert.New(t) - suite.require = require.New(t) -} - -// SetS needs to set the current test suite as parent -// to get access to the parent methods -func (suite *Suite) SetS(s TestingSuite) { - suite.s = s -} - -// Require returns a require context for suite. -func (suite *Suite) Require() *require.Assertions { - suite.mu.Lock() - defer suite.mu.Unlock() - if suite.require == nil { - suite.require = require.New(suite.T()) - } - return suite.require -} - -// Assert returns an assert context for suite. Normally, you can call -// `suite.NoError(expected, actual)`, but for situations where the embedded -// methods are overridden (for example, you might want to override -// assert.Assertions with require.Assertions), this method is provided so you -// can call `suite.Assert().NoError()`. -func (suite *Suite) Assert() *assert.Assertions { - suite.mu.Lock() - defer suite.mu.Unlock() - if suite.Assertions == nil { - suite.Assertions = assert.New(suite.T()) - } - return suite.Assertions -} - -func recoverAndFailOnPanic(t *testing.T) { - r := recover() - failOnPanic(t, r) -} - -func failOnPanic(t *testing.T, r interface{}) { - if r != nil { - t.Errorf("test panicked: %v\n%s", r, debug.Stack()) - t.FailNow() - } -} - -// Run provides suite functionality around golang subtests. It should be -// called in place of t.Run(name, func(t *testing.T)) in test suite code. -// The passed-in func will be executed as a subtest with a fresh instance of t. -// Provides compatibility with go test pkg -run TestSuite/TestName/SubTestName. -func (suite *Suite) Run(name string, subtest func()) bool { - oldT := suite.T() - - if setupSubTest, ok := suite.s.(SetupSubTest); ok { - setupSubTest.SetupSubTest() - } - - defer func() { - suite.SetT(oldT) - if tearDownSubTest, ok := suite.s.(TearDownSubTest); ok { - tearDownSubTest.TearDownSubTest() - } - }() - - return oldT.Run(name, func(t *testing.T) { - suite.SetT(t) - subtest() - }) -} - -// Run takes a testing suite and runs all of the tests attached -// to it. -func Run(t *testing.T, suite TestingSuite) { - defer recoverAndFailOnPanic(t) - - suite.SetT(t) - suite.SetS(suite) - - var suiteSetupDone bool - - var stats *SuiteInformation - if _, ok := suite.(WithStats); ok { - stats = newSuiteInformation() - } - - tests := []testing.InternalTest{} - methodFinder := reflect.TypeOf(suite) - suiteName := methodFinder.Elem().Name() - - for i := 0; i < methodFinder.NumMethod(); i++ { - method := methodFinder.Method(i) - - ok, err := methodFilter(method.Name) - if err != nil { - fmt.Fprintf(os.Stderr, "testify: invalid regexp for -m: %s\n", err) - os.Exit(1) - } - - if !ok { - continue - } - - if !suiteSetupDone { - if stats != nil { - stats.Start = time.Now() - } - - if setupAllSuite, ok := suite.(SetupAllSuite); ok { - setupAllSuite.SetupSuite() - } - - suiteSetupDone = true - } - - test := testing.InternalTest{ - Name: method.Name, - F: func(t *testing.T) { - parentT := suite.T() - suite.SetT(t) - defer recoverAndFailOnPanic(t) - defer func() { - r := recover() - - if stats != nil { - passed := !t.Failed() && r == nil - stats.end(method.Name, passed) - } - - if afterTestSuite, ok := suite.(AfterTest); ok { - afterTestSuite.AfterTest(suiteName, method.Name) - } - - if tearDownTestSuite, ok := suite.(TearDownTestSuite); ok { - tearDownTestSuite.TearDownTest() - } - - suite.SetT(parentT) - failOnPanic(t, r) - }() - - if setupTestSuite, ok := suite.(SetupTestSuite); ok { - setupTestSuite.SetupTest() - } - if beforeTestSuite, ok := suite.(BeforeTest); ok { - beforeTestSuite.BeforeTest(methodFinder.Elem().Name(), method.Name) - } - - if stats != nil { - stats.start(method.Name) - } - - method.Func.Call([]reflect.Value{reflect.ValueOf(suite)}) - }, - } - tests = append(tests, test) - } - if suiteSetupDone { - defer func() { - if tearDownAllSuite, ok := suite.(TearDownAllSuite); ok { - tearDownAllSuite.TearDownSuite() - } - - if suiteWithStats, measureStats := suite.(WithStats); measureStats { - stats.End = time.Now() - suiteWithStats.HandleStats(suiteName, stats) - } - }() - } - - runTests(t, tests) -} - -// Filtering method according to set regular expression -// specified command-line argument -m -func methodFilter(name string) (bool, error) { - if ok, _ := regexp.MatchString("^Test", name); !ok { - return false, nil - } - return regexp.MatchString(*matchMethod, name) -} - -func runTests(t testing.TB, tests []testing.InternalTest) { - if len(tests) == 0 { - t.Log("warning: no tests to run") - return - } - - r, ok := t.(runner) - if !ok { // backwards compatibility with Go 1.6 and below - if !testing.RunTests(allTestsFilter, tests) { - t.Fail() - } - return - } - - for _, test := range tests { - r.Run(test.Name, test.F) - } -} - -type runner interface { - Run(name string, f func(t *testing.T)) bool -} diff --git a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/suite_test.go b/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/suite_test.go deleted file mode 100644 index d684f52..0000000 --- a/.devenv/state/go/pkg/mod/github.com/stretchr/testify@v1.8.2/suite/suite_test.go +++ /dev/null @@ -1,619 +0,0 @@ -package suite - -import ( - "bytes" - "errors" - "flag" - "io/ioutil" - "math/rand" - "os" - "os/exec" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -// SuiteRequireTwice is intended to test the usage of suite.Require in two -// different tests -type SuiteRequireTwice struct{ Suite } - -// TestSuiteRequireTwice checks for regressions of issue #149 where -// suite.requirements was not initialised in suite.SetT() -// A regression would result on these tests panicking rather than failing. -func TestSuiteRequireTwice(t *testing.T) { - ok := testing.RunTests( - allTestsFilter, - []testing.InternalTest{{ - Name: "TestSuiteRequireTwice", - F: func(t *testing.T) { - suite := new(SuiteRequireTwice) - Run(t, suite) - }, - }}, - ) - assert.Equal(t, false, ok) -} - -func (s *SuiteRequireTwice) TestRequireOne() { - r := s.Require() - r.Equal(1, 2) -} - -func (s *SuiteRequireTwice) TestRequireTwo() { - r := s.Require() - r.Equal(1, 2) -} - -type panickingSuite struct { - Suite - panicInSetupSuite bool - panicInSetupTest bool - panicInBeforeTest bool - panicInTest bool - panicInAfterTest bool - panicInTearDownTest bool - panicInTearDownSuite bool -} - -func (s *panickingSuite) SetupSuite() { - if s.panicInSetupSuite { - panic("oops in setup suite") - } -} - -func (s *panickingSuite) SetupTest() { - if s.panicInSetupTest { - panic("oops in setup test") - } -} - -func (s *panickingSuite) BeforeTest(_, _ string) { - if s.panicInBeforeTest { - panic("oops in before test") - } -} - -func (s *panickingSuite) Test() { - if s.panicInTest { - panic("oops in test") - } -} - -func (s *panickingSuite) AfterTest(_, _ string) { - if s.panicInAfterTest { - panic("oops in after test") - } -} - -func (s *panickingSuite) TearDownTest() { - if s.panicInTearDownTest { - panic("oops in tear down test") - } -} - -func (s *panickingSuite) TearDownSuite() { - if s.panicInTearDownSuite { - panic("oops in tear down suite") - } -} - -func TestSuiteRecoverPanic(t *testing.T) { - ok := true - panickingTests := []testing.InternalTest{ - { - Name: "TestPanicInSetupSuite", - F: func(t *testing.T) { Run(t, &panickingSuite{panicInSetupSuite: true}) }, - }, - { - Name: "TestPanicInSetupTest", - F: func(t *testing.T) { Run(t, &panickingSuite{panicInSetupTest: true}) }, - }, - { - Name: "TestPanicInBeforeTest", - F: func(t *testing.T) { Run(t, &panickingSuite{panicInBeforeTest: true}) }, - }, - { - Name: "TestPanicInTest", - F: func(t *testing.T) { Run(t, &panickingSuite{panicInTest: true}) }, - }, - { - Name: "TestPanicInAfterTest", - F: func(t *testing.T) { Run(t, &panickingSuite{panicInAfterTest: true}) }, - }, - { - Name: "TestPanicInTearDownTest", - F: func(t *testing.T) { Run(t, &panickingSuite{panicInTearDownTest: true}) }, - }, - { - Name: "TestPanicInTearDownSuite", - F: func(t *testing.T) { Run(t, &panickingSuite{panicInTearDownSuite: true}) }, - }, - } - - require.NotPanics(t, func() { - ok = testing.RunTests(allTestsFilter, panickingTests) - }) - - assert.False(t, ok) -} - -// This suite is intended to store values to make sure that only -// testing-suite-related methods are run. It's also a fully -// functional example of a testing suite, using setup/teardown methods -// and a helper method that is ignored by testify. To make this look -// more like a real world example, all tests in the suite perform some -// type of assertion. -type SuiteTester struct { - // Include our basic suite logic. - Suite - - // Keep counts of how many times each method is run. - SetupSuiteRunCount int - TearDownSuiteRunCount int - SetupTestRunCount int - TearDownTestRunCount int - TestOneRunCount int - TestTwoRunCount int - TestSubtestRunCount int - NonTestMethodRunCount int - SetupSubTestRunCount int - TearDownSubTestRunCount int - - SuiteNameBefore []string - TestNameBefore []string - - SuiteNameAfter []string - TestNameAfter []string - - TimeBefore []time.Time - TimeAfter []time.Time -} - -// The SetupSuite method will be run by testify once, at the very -// start of the testing suite, before any tests are run. -func (suite *SuiteTester) SetupSuite() { - suite.SetupSuiteRunCount++ -} - -func (suite *SuiteTester) BeforeTest(suiteName, testName string) { - suite.SuiteNameBefore = append(suite.SuiteNameBefore, suiteName) - suite.TestNameBefore = append(suite.TestNameBefore, testName) - suite.TimeBefore = append(suite.TimeBefore, time.Now()) -} - -func (suite *SuiteTester) AfterTest(suiteName, testName string) { - suite.SuiteNameAfter = append(suite.SuiteNameAfter, suiteName) - suite.TestNameAfter = append(suite.TestNameAfter, testName) - suite.TimeAfter = append(suite.TimeAfter, time.Now()) -} - -// The TearDownSuite method will be run by testify once, at the very -// end of the testing suite, after all tests have been run. -func (suite *SuiteTester) TearDownSuite() { - suite.TearDownSuiteRunCount++ -} - -// The SetupTest method will be run before every test in the suite. -func (suite *SuiteTester) SetupTest() { - suite.SetupTestRunCount++ -} - -// The TearDownTest method will be run after every test in the suite. -func (suite *SuiteTester) TearDownTest() { - suite.TearDownTestRunCount++ -} - -// Every method in a testing suite that begins with "Test" will be run -// as a test. TestOne is an example of a test. For the purposes of -// this example, we've included assertions in the tests, since most -// tests will issue assertions. -func (suite *SuiteTester) TestOne() { - beforeCount := suite.TestOneRunCount - suite.TestOneRunCount++ - assert.Equal(suite.T(), suite.TestOneRunCount, beforeCount+1) - suite.Equal(suite.TestOneRunCount, beforeCount+1) -} - -// TestTwo is another example of a test. -func (suite *SuiteTester) TestTwo() { - beforeCount := suite.TestTwoRunCount - suite.TestTwoRunCount++ - assert.NotEqual(suite.T(), suite.TestTwoRunCount, beforeCount) - suite.NotEqual(suite.TestTwoRunCount, beforeCount) -} - -func (suite *SuiteTester) TestSkip() { - suite.T().Skip() -} - -// NonTestMethod does not begin with "Test", so it will not be run by -// testify as a test in the suite. This is useful for creating helper -// methods for your tests. -func (suite *SuiteTester) NonTestMethod() { - suite.NonTestMethodRunCount++ -} - -func (suite *SuiteTester) TestSubtest() { - suite.TestSubtestRunCount++ - - for _, t := range []struct { - testName string - }{ - {"first"}, - {"second"}, - } { - suiteT := suite.T() - suite.Run(t.testName, func() { - // We should get a different *testing.T for subtests, so that - // go test recognizes them as proper subtests for output formatting - // and running individual subtests - subTestT := suite.T() - suite.NotEqual(subTestT, suiteT) - }) - suite.Equal(suiteT, suite.T()) - } -} - -func (suite *SuiteTester) TearDownSubTest() { - suite.TearDownSubTestRunCount++ -} - -func (suite *SuiteTester) SetupSubTest() { - suite.SetupSubTestRunCount++ -} - -type SuiteSkipTester struct { - // Include our basic suite logic. - Suite - - // Keep counts of how many times each method is run. - SetupSuiteRunCount int - TearDownSuiteRunCount int -} - -func (suite *SuiteSkipTester) SetupSuite() { - suite.SetupSuiteRunCount++ - suite.T().Skip() -} - -func (suite *SuiteSkipTester) TestNothing() { - // SetupSuite is only called when at least one test satisfies - // test filter. For this suite to be set up (and then tore down) - // it is necessary to add at least one test method. -} - -func (suite *SuiteSkipTester) TearDownSuite() { - suite.TearDownSuiteRunCount++ -} - -// TestRunSuite will be run by the 'go test' command, so within it, we -// can run our suite using the Run(*testing.T, TestingSuite) function. -func TestRunSuite(t *testing.T) { - suiteTester := new(SuiteTester) - Run(t, suiteTester) - - // Normally, the test would end here. The following are simply - // some assertions to ensure that the Run function is working as - // intended - they are not part of the example. - - // The suite was only run once, so the SetupSuite and TearDownSuite - // methods should have each been run only once. - assert.Equal(t, suiteTester.SetupSuiteRunCount, 1) - assert.Equal(t, suiteTester.TearDownSuiteRunCount, 1) - - assert.Equal(t, len(suiteTester.SuiteNameAfter), 4) - assert.Equal(t, len(suiteTester.SuiteNameBefore), 4) - assert.Equal(t, len(suiteTester.TestNameAfter), 4) - assert.Equal(t, len(suiteTester.TestNameBefore), 4) - - assert.Contains(t, suiteTester.TestNameAfter, "TestOne") - assert.Contains(t, suiteTester.TestNameAfter, "TestTwo") - assert.Contains(t, suiteTester.TestNameAfter, "TestSkip") - assert.Contains(t, suiteTester.TestNameAfter, "TestSubtest") - - assert.Contains(t, suiteTester.TestNameBefore, "TestOne") - assert.Contains(t, suiteTester.TestNameBefore, "TestTwo") - assert.Contains(t, suiteTester.TestNameBefore, "TestSkip") - assert.Contains(t, suiteTester.TestNameBefore, "TestSubtest") - - for _, suiteName := range suiteTester.SuiteNameAfter { - assert.Equal(t, "SuiteTester", suiteName) - } - - for _, suiteName := range suiteTester.SuiteNameBefore { - assert.Equal(t, "SuiteTester", suiteName) - } - - for _, when := range suiteTester.TimeAfter { - assert.False(t, when.IsZero()) - } - - for _, when := range suiteTester.TimeBefore { - assert.False(t, when.IsZero()) - } - - // There are four test methods (TestOne, TestTwo, TestSkip, and TestSubtest), so - // the SetupTest and TearDownTest methods (which should be run once for - // each test) should have been run four times. - assert.Equal(t, suiteTester.SetupTestRunCount, 4) - assert.Equal(t, suiteTester.TearDownTestRunCount, 4) - - // Each test should have been run once. - assert.Equal(t, suiteTester.TestOneRunCount, 1) - assert.Equal(t, suiteTester.TestTwoRunCount, 1) - assert.Equal(t, suiteTester.TestSubtestRunCount, 1) - - assert.Equal(t, suiteTester.TearDownSubTestRunCount, 2) - assert.Equal(t, suiteTester.SetupSubTestRunCount, 2) - - // Methods that don't match the test method identifier shouldn't - // have been run at all. - assert.Equal(t, suiteTester.NonTestMethodRunCount, 0) - - suiteSkipTester := new(SuiteSkipTester) - Run(t, suiteSkipTester) - - // The suite was only run once, so the SetupSuite and TearDownSuite - // methods should have each been run only once, even though SetupSuite - // called Skip() - assert.Equal(t, suiteSkipTester.SetupSuiteRunCount, 1) - assert.Equal(t, suiteSkipTester.TearDownSuiteRunCount, 1) - -} - -// This suite has no Test... methods. It's setup and teardown must be skipped. -type SuiteSetupSkipTester struct { - Suite - - setUp bool - toreDown bool -} - -func (s *SuiteSetupSkipTester) SetupSuite() { - s.setUp = true -} - -func (s *SuiteSetupSkipTester) NonTestMethod() { - -} - -func (s *SuiteSetupSkipTester) TearDownSuite() { - s.toreDown = true -} - -func TestSkippingSuiteSetup(t *testing.T) { - suiteTester := new(SuiteSetupSkipTester) - Run(t, suiteTester) - assert.False(t, suiteTester.setUp) - assert.False(t, suiteTester.toreDown) -} - -func TestSuiteGetters(t *testing.T) { - suite := new(SuiteTester) - suite.SetT(t) - assert.NotNil(t, suite.Assert()) - assert.Equal(t, suite.Assertions, suite.Assert()) - assert.NotNil(t, suite.Require()) - assert.Equal(t, suite.require, suite.Require()) -} - -type SuiteLoggingTester struct { - Suite -} - -func (s *SuiteLoggingTester) TestLoggingPass() { - s.T().Log("TESTLOGPASS") -} - -func (s *SuiteLoggingTester) TestLoggingFail() { - s.T().Log("TESTLOGFAIL") - assert.NotNil(s.T(), nil) // expected to fail -} - -type StdoutCapture struct { - oldStdout *os.File - readPipe *os.File -} - -func (sc *StdoutCapture) StartCapture() { - sc.oldStdout = os.Stdout - sc.readPipe, os.Stdout, _ = os.Pipe() -} - -func (sc *StdoutCapture) StopCapture() (string, error) { - if sc.oldStdout == nil || sc.readPipe == nil { - return "", errors.New("StartCapture not called before StopCapture") - } - os.Stdout.Close() - os.Stdout = sc.oldStdout - bytes, err := ioutil.ReadAll(sc.readPipe) - if err != nil { - return "", err - } - return string(bytes), nil -} - -func TestSuiteLogging(t *testing.T) { - suiteLoggingTester := new(SuiteLoggingTester) - capture := StdoutCapture{} - internalTest := testing.InternalTest{ - Name: "SomeTest", - F: func(subT *testing.T) { - Run(subT, suiteLoggingTester) - }, - } - capture.StartCapture() - testing.RunTests(allTestsFilter, []testing.InternalTest{internalTest}) - output, err := capture.StopCapture() - require.NoError(t, err, "Got an error trying to capture stdout and stderr!") - require.NotEmpty(t, output, "output content must not be empty") - - // Failed tests' output is always printed - assert.Contains(t, output, "TESTLOGFAIL") - - if testing.Verbose() { - // In verbose mode, output from successful tests is also printed - assert.Contains(t, output, "TESTLOGPASS") - } else { - assert.NotContains(t, output, "TESTLOGPASS") - } -} - -type CallOrderSuite struct { - Suite - callOrder []string -} - -func (s *CallOrderSuite) call(method string) { - time.Sleep(time.Duration(rand.Intn(300)) * time.Millisecond) - s.callOrder = append(s.callOrder, method) -} - -func TestSuiteCallOrder(t *testing.T) { - Run(t, new(CallOrderSuite)) -} -func (s *CallOrderSuite) SetupSuite() { - s.call("SetupSuite") -} - -func (s *CallOrderSuite) TearDownSuite() { - s.call("TearDownSuite") - assert.Equal(s.T(), "SetupSuite;SetupTest;Test A;TearDownTest;SetupTest;Test B;TearDownTest;TearDownSuite", strings.Join(s.callOrder, ";")) -} -func (s *CallOrderSuite) SetupTest() { - s.call("SetupTest") -} - -func (s *CallOrderSuite) TearDownTest() { - s.call("TearDownTest") -} - -func (s *CallOrderSuite) Test_A() { - s.call("Test A") -} - -func (s *CallOrderSuite) Test_B() { - s.call("Test B") -} - -type suiteWithStats struct { - Suite - wasCalled bool - stats *SuiteInformation -} - -func (s *suiteWithStats) HandleStats(suiteName string, stats *SuiteInformation) { - s.wasCalled = true - s.stats = stats -} - -func (s *suiteWithStats) TestSomething() { - s.Equal(1, 1) -} - -func (s *suiteWithStats) TestPanic() { - panic("oops") -} - -func TestSuiteWithStats(t *testing.T) { - suiteWithStats := new(suiteWithStats) - - testing.RunTests(allTestsFilter, []testing.InternalTest{ - { - Name: "WithStats", - F: func(t *testing.T) { - Run(t, suiteWithStats) - }, - }, - }) - - assert.True(t, suiteWithStats.wasCalled) - assert.NotZero(t, suiteWithStats.stats.Start) - assert.NotZero(t, suiteWithStats.stats.End) - assert.False(t, suiteWithStats.stats.Passed()) - - testStats := suiteWithStats.stats.TestStats - - assert.NotZero(t, testStats["TestSomething"].Start) - assert.NotZero(t, testStats["TestSomething"].End) - assert.True(t, testStats["TestSomething"].Passed) - - assert.NotZero(t, testStats["TestPanic"].Start) - assert.NotZero(t, testStats["TestPanic"].End) - assert.False(t, testStats["TestPanic"].Passed) -} - -// FailfastSuite will test the behavior when running with the failfast flag -// It logs calls in the callOrder slice which we then use to assert the correct calls were made -type FailfastSuite struct { - Suite - callOrder []string -} - -func (s *FailfastSuite) call(method string) { - s.callOrder = append(s.callOrder, method) -} - -func TestFailfastSuite(t *testing.T) { - // This test suite is run twice. Once normally and once with the -failfast flag by TestFailfastSuiteFailFastOn - // If you need to debug it run this test directly with the failfast flag set on/off as you need - failFast := flag.Lookup("test.failfast").Value.(flag.Getter).Get().(bool) - s := new(FailfastSuite) - ok := testing.RunTests( - allTestsFilter, - []testing.InternalTest{{ - Name: "TestFailfastSuite", - F: func(t *testing.T) { - Run(t, s) - }, - }}, - ) - assert.Equal(t, false, ok) - if failFast { - // Test A Fails and because we are running with failfast Test B never runs and we proceed straight to TearDownSuite - assert.Equal(t, "SetupSuite;SetupTest;Test A Fails;TearDownTest;TearDownSuite", strings.Join(s.callOrder, ";")) - } else { - // Test A Fails and because we are running without failfast we continue and run Test B and then proceed to TearDownSuite - assert.Equal(t, "SetupSuite;SetupTest;Test A Fails;TearDownTest;SetupTest;Test B Passes;TearDownTest;TearDownSuite", strings.Join(s.callOrder, ";")) - } -} -func TestFailfastSuiteFailFastOn(t *testing.T) { - // To test this with failfast on (and isolated from other intended test failures in our test suite) we launch it in its own process - cmd := exec.Command("go", "test", "-v", "-race", "-run", "TestFailfastSuite", "-failfast") - var out bytes.Buffer - cmd.Stdout = &out - t.Log("Running go test -v -race -run TestFailfastSuite -failfast") - err := cmd.Run() - t.Log(out.String()) - if err != nil { - t.Log(err) - t.Fail() - } -} -func (s *FailfastSuite) SetupSuite() { - s.call("SetupSuite") -} - -func (s *FailfastSuite) TearDownSuite() { - s.call("TearDownSuite") -} -func (s *FailfastSuite) SetupTest() { - s.call("SetupTest") -} - -func (s *FailfastSuite) TearDownTest() { - s.call("TearDownTest") -} - -func (s *FailfastSuite) Test_A_Fails() { - s.call("Test A Fails") - s.T().Error("Test A meant to fail") -} - -func (s *FailfastSuite) Test_B_Passes() { - s.call("Test B Passes") - s.Require().True(true) -} diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/.chglog/CHANGELOG.tpl.md b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/.chglog/CHANGELOG.tpl.md deleted file mode 100644 index 8e98c0b..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/.chglog/CHANGELOG.tpl.md +++ /dev/null @@ -1,27 +0,0 @@ -{{ range .Versions }} -<a name="{{ .Tag.Name }}"></a> -## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }} -{{ range .CommitGroups -}} -### {{ .Title }} -{{ range .Commits -}} -- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }} -{{ end }} -{{ end -}} - -{{- if .NoteGroups -}} -{{ range .NoteGroups -}} -### {{ .Title }} -{{ range .Notes }} -{{ .Body }} -{{ end }} -{{ end -}} -{{ end -}} -{{ end -}} - -{{- if .Versions }} -{{ range .Versions -}} -{{ if .Tag.Previous -}} -[{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }} -{{ end -}} -{{ end -}} -{{ end -}} \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/.chglog/config.yml b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/.chglog/config.yml deleted file mode 100644 index 237f6bc..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/.chglog/config.yml +++ /dev/null @@ -1,57 +0,0 @@ -style: gitlab -template: CHANGELOG.tpl.md -info: - title: CHANGELOG - repository_url: https://gitlab.schukai.com/oss/libraries/go/utilities/pathfinder -options: - commits: - filters: - Type: - - feat - - fix - - doc - - refactor - - perf - - test - - chore - ## deprecated types and typos - - docs - - documentation - - feat - - added - - add - - bugfix - - revert - - update - - updates - - change - - changed - commit_groups: - title_maps: - feat: Add Features - fix: Bug Fixes - doc: Documentation - refactor: Code Refactoring - perf: Performance Improvements - test: Tests - ## Chore is used for all other changes that don't fit in the other categories - chore: Changes - ## deprecated types and typos - docs: Documentation - documentation: Documentation - added: Add Features - add: Add Features - bugfix: Bug Fixes - revert: Reverts - update: Changes - updates: Changes - change: Changes - changed: Changes - header: - pattern: "^((\\w+)\\s.*)$" - pattern_maps: - - Subject - - Type - notes: - keywords: - - BREAKING CHANGE diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/.gitignore b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/.gitignore deleted file mode 100644 index c55f7d0..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/.gitignore +++ /dev/null @@ -1,149 +0,0 @@ -# Created by https://www.toptal.com/developers/gitignore/api/intellij,go -# Edit at https://www.toptal.com/developers/gitignore?templates=intellij,go - -### Go ### -# If you prefer the allow list template instead of the deny list, see community template: -# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore -# -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib - -# Test binary, built with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -testdata/ - -# Dependency directories (remove the comment below to include it) -# vendor/ - -# Go workspace file -go.work - -# Go Fuzz build -testdata/ - -### Go Patch ### -/vendor/ -/Godeps/ - -### Intellij ### -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/**/usage.statistics.xml -.idea/**/dictionaries -.idea/**/shelf - -# AWS User-specific -.idea/**/aws.xml - -# Generated files -.idea/**/contentModel.xml - -# Sensitive or high-churn files -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml -.idea/**/dbnavigator.xml - -# Gradle -.idea/**/gradle.xml -.idea/**/libraries - -# Gradle and Maven with auto-import -# When using Gradle or Maven with auto-import, you should exclude module files, -# since they will be recreated, and may cause churn. Uncomment if using -# auto-import. -# .idea/artifacts -# .idea/compiler.xml -# .idea/jarRepositories.xml -# .idea/modules.xml -# .idea/*.iml -# .idea/modules -# *.iml -# *.ipr - -# CMake -cmake-build-*/ - -# Mongo Explorer plugin -.idea/**/mongoSettings.xml - -# File-based project format -*.iws - -# IntelliJ -out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# SonarLint plugin -.idea/sonarlint/ - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties - -# Editor-based Rest Client -.idea/httpRequests - -# Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser - -### Intellij Patch ### -# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 - -# *.iml -# modules.xml -# .idea/misc.xml -# *.ipr - -# Sonarlint plugin -# https://plugins.jetbrains.com/plugin/7973-sonarlint -.idea/**/sonarlint/ - -# SonarQube Plugin -# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin -.idea/**/sonarIssues.xml - -# Markdown Navigator plugin -# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced -.idea/**/markdown-navigator.xml -.idea/**/markdown-navigator-enh.xml -.idea/**/markdown-navigator/ - -# Cache file creation bug -# See https://youtrack.jetbrains.com/issue/JBR-2257 -.idea/$CACHE_FILE$ - -# CodeStream plugin -# https://plugins.jetbrains.com/plugin/12206-codestream -.idea/codestream.xml - -# Azure Toolkit for IntelliJ plugin -# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij -.idea/**/azureSettings.xml - -# End of https://www.toptal.com/developers/gitignore/api/intellij,go \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/CHANGELOG.md b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/CHANGELOG.md deleted file mode 100644 index 859750c..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/CHANGELOG.md +++ /dev/null @@ -1,37 +0,0 @@ - -<a name="v0.5.2"></a> -## [v0.5.2] - 2022-12-23 - -<a name="v0.5.1"></a> -## [v0.5.1] - 2022-12-23 - -<a name="v0.5.0"></a> -## [v0.5.0] - 2022-12-18 - -<a name="v0.4.0"></a> -## [v0.4.0] - 2022-12-17 - -<a name="v0.3.1"></a> -## [v0.3.1] - 2022-10-16 -### Bug Fixes -- fix secure access to structure with a constraint - - -<a name="v0.3.0"></a> -## [v0.3.0] - 2022-10-15 -### Code Refactoring -- refactor change function signatur - - -<a name="v0.2.0"></a> -## v0.2.0 - 2022-10-15 -### Add Features -- feat takeover from other project - - -[v0.5.2]: https://gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/compare/v0.5.1...v0.5.2 -[v0.5.1]: https://gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/compare/v0.5.0...v0.5.1 -[v0.5.0]: https://gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/compare/v0.4.0...v0.5.0 -[v0.4.0]: https://gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/compare/v0.3.1...v0.4.0 -[v0.3.1]: https://gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/compare/v0.3.0...v0.3.1 -[v0.3.0]: https://gitlab.schukai.com/oss/libraries/go/utilities/pathfinder/compare/v0.2.0...v0.3.0 diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/LICENSE b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/LICENSE deleted file mode 100644 index 22686f9..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/LICENSE +++ /dev/null @@ -1,662 +0,0 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - AGPL-3.0 - - Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <https://www.gnu.org/licenses/>. - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -<https://www.gnu.org/licenses/>. \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/Makefile b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/Makefile deleted file mode 100644 index c149982..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/Makefile +++ /dev/null @@ -1,157 +0,0 @@ -## Copyright 2022 schukai GmbH. All rights reserved. -## Use of this source code is governed by a AGPL-3.0 -## license that can be found in the LICENSE file. - -PROJECT_ROOT:=$(dir $(realpath $(lastword $(MAKEFILE_LIST)))) -THIS_MAKEFILE:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) -THIS_MAKEFILE_PATH:=$(PROJECT_ROOT)$(THIS_MAKEFILE) - -# @see .PHONY https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html#Phony-Targets -.DEFAULT_GOAL := help - -.PHONY: print -## Print Path -print: - @echo "THIS_MAKEFILE: $(THIS_MAKEFILE)" - @echo "THIS_MAKEFILE_PATH: $(THIS_MAKEFILE_PATH)" - @echo "PROJECT_ROOT: $(PROJECT_ROOT)" - -# Add a comment to the public targets so that it appears -# in this help Use two # characters for a help comment -.PHONY: help -help: - @printf "${COMMENT}Usage:${RESET}\n" - @printf " make [target] [arg=\"val\"...]\n\n" - @printf "${COMMENT}Available targets:${RESET}\n" - @awk '/^[a-zA-Z\-\\_0-9\.@]+:/ { \ - helpMessage = match(lastLine, /^## (.*)/); \ - if (helpMessage) { \ - helpCommand = substr($$1, 0, index($$1, ":")); \ - helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \ - printf " ${INFO}%-22s${RESET} %s\n", helpCommand, helpMessage; \ - } \ - } \ - { lastLine = $$0 }' $(MAKEFILE_LIST) - @printf "\n${COMMENT}Available arguments:${RESET}\n\n" - @awk '/^(([a-zA-Z\-\\_0-9\.@]+)\s[?:]?=)/ { \ - helpMessage = match(lastLine, /^## (.*)/); \ - if (helpMessage) { \ - helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \ - printf " ${INFO}%-22s${RESET} %s (Default: %s)\n", $$1, helpMessage, $$3; \ - } \ - } \ - { lastLine = $$0 }' $(MAKEFILE_LIST) - - -## run tests -test: - echo "Running tests" - go test -cover -v ./... - -## run tests with fuzzing -test-fuzz: - echo "Running fuzz tests" - go test -v -fuzztime=30s -fuzz=Fuzz ./... - -#### VERSION -BIN_DIR ?= $(shell echo $$HOME)/.local/bin/ -VERSION_NAME := version -EXECUTABLES = $(EXECUTABLES:-) $(VERSION_NAME) -VERSION_BIN_PATH := $(BIN_DIR)$(VERSION_NAME) - -VERSION_BIN := $(shell command -v $(VERSION_NAME) 2> /dev/null) - -ifndef VERSION_BIN - $(shell curl -o $(VERSION_BIN_PATH) http://download.schukai.com/tools/version/version-$(shell uname -s | tr [:upper:] [:lower:])-$(shell echo `uname -m | sed s/aarch64/arm64/ | sed s/x86_64/amd64/`)) - $(shell chmod +x $(VERSION_BIN_PATH)) -endif - -GIT_CHGLOG_BIN := $(shell command -v git-chglog 2> /dev/null) - -ifeq ($(GIT_CHGLOG_BIN),) - $(shell go install github.com/git-chglog/git-chglog/cmd/git-chglog@latest) -endif - -RELEASE_FILE ?= $(PROJECT_ROOT)release.json -CHANGELOG_FILE ?= $(PROJECT_ROOT)CHANGELOG.md - -ifeq ("$(wildcard $(RELEASE_FILE))","") - $(shell echo '{"version":"0.1.0"}' > $(RELEASE_FILE)) -endif - -PROJECT_VERSION ?= $(shell cat $(RELEASE_FILE) | jq -r .version) -PROJECT_BUILD_DATE ?= $(shell $(VERSION_BIN) date) - -.PHONY: next-patch-version -next-patch-version: check-clean-repo - echo "Creating next version" - $(VERSION_BIN) patch --path $(RELEASE_FILE) --selector "version" - git add $(RELEASE_FILE) && git commit -m "Bump version to $$(cat $(RELEASE_FILE) | jq -r .version)" - -.PHONY: next-minor-version -next-minor-version: check-clean-repo - echo "Creating next minor version" - $(VERSION_BIN) minor --path $(RELEASE_FILE) --selector "version" - git add $(RELEASE_FILE) && git commit -m "Bump version to $$( cat $(RELEASE_FILE) | jq -r .version)" - -.PHONY: next-major-version -next-major-version: check-clean-repo - echo "Creating next minor version" - $(VERSION_BIN) major --path $(RELEASE_FILE) --selector "version" - git add $(RELEASE_FILE) && git commit -m "Bump version to $$(cat $(RELEASE_FILE) | jq -r .version)" - -.PHONY: check-clean-repo -check-clean-repo: - git diff-index --quiet HEAD || (echo "There are uncommitted changes after running make. Please commit or stash them before running make."; exit 1) - -## tag repository with next patch version -tag-patch-version: next-patch-version - echo "Tagging patch version" - $(eval PROJECT_VERSION := $(shell cat $(RELEASE_FILE) | jq -r .version)) - git-chglog --next-tag v$(PROJECT_VERSION) -o $(CHANGELOG_FILE) - git add $(CHANGELOG_FILE) && git commit -m "Update changelog" - git tag -a v$(PROJECT_VERSION) -m "Version $(PROJECT_VERSION)" - -## tag repository with next minor version -tag-minor-version: next-minor-version - echo "Tagging minor version" - $(eval PROJECT_VERSION := $(shell cat $(RELEASE_FILE) | jq -r .version)) - git-chglog --next-tag v$(PROJECT_VERSION) -o $(CHANGELOG_FILE) - git add $(CHANGELOG_FILE) && git commit -m "Update changelog" - git tag -a v$(PROJECT_VERSION) -m "Version $(PROJECT_VERSION)" - -## tag repository with next major version -tag-major-version: next-major-version - echo "Tagging major version" - $(eval PROJECT_VERSION := $(shell cat $(RELEASE_FILE) | jq -r .version)) - git-chglog --next-tag v$(PROJECT_VERSION) -o $(CHANGELOG_FILE) - git add $(CHANGELOG_FILE) && git commit -m "Update changelog" - git tag -a v$(PROJECT_VERSION) -m "Version $(PROJECT_VERSION)" - -GO_MOD_FILE := $(SOURCE_PATH)go.mod - -ifeq ($(shell test -e $(GO_MOD_FILE) && echo -n yes),yes) - GO_CURRENT_MODULE := $(shell cat $(GO_MOD_FILE) | head -n1 | cut -d" " -f2) - # go install github.com/google/go-licenses@latest - EXECUTABLES = $(EXECUTABLES:-) go-licenses; -endif - -.PHONY: fetch-licenses -## Fetch licenses for all modules -fetch-licenses: - go-licenses save $(GO_CURRENT_MODULE) --ignore gitlab.schukai.com --force --save_path $(PROJECT_ROOT)licenses/ - -# https://spdx.github.io/spdx-spec/v2.3/SPDX-license-list/ -ADDLICENSE_BIN ?= addlicense -ifeq ($(shell command -v $(ADDLICENSE_BIN) 2> /dev/null),) - $(shell go install github.com/google/addlicense@latest) - EXECUTABLES = $(EXECUTABLES:-) $(ADDLICENSE_BIN); -endif - -.PHONY: add-licenses -## Add license headers to all go files -add-licenses: - addlicense -c "schukai GmbH" -s -l "AGPL-3.0" ./*.go - - - diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/README.md b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/README.md deleted file mode 100644 index 4d1522c..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/README.md +++ /dev/null @@ -1,69 +0,0 @@ -## Pathfinder - -## What does this library? - -This library provides a simple way to get and set values in a nested structure. - -It supports: - -* [X] Set values in a nested structure -* [X] Get values from a nested structure - -## Installation - -```shell -go get gitlab.schukai.com/oss/libraries/go/utilities/pathfinder -``` - -**Note:** This library uses [Go Modules](https://github.com/golang/go/wiki/Modules) to manage dependencies. - -## Usage - -### Set values - -```go -s := &StructA{} -err := GetValue[*StructA](s, "my.key") -``` - -### Get values - -```go -s := &StructA{} -err := SetValue[*StructA](s, "my.key", "value") -``` - -## Contributing - -Merge requests are welcome. For major changes, please open an issue first to discuss what -you would like to change. **Please make sure to update tests as appropriate.** - -Versioning is done with [SemVer](https://semver.org/). -Changelog is generated with [git-chglog](https://github.com/git-chglog/git-chglog#git-chglog) - -Commit messages should follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification. -Messages are started with a type, which is one of the following: - -- **feat**: A new feature -- **fix**: A bug fix -- **doc**: Documentation only changes -- **refactor**: A code change that neither fixes a bug nor adds a feature -- **perf**: A code change that improves performance -- **test**: Adding missing or correcting existing tests -- **chore**: Other changes that don't modify src or test files - -The footer would be used for a reference to an issue or a breaking change. - -A commit that has a footer `BREAKING CHANGE:`, or appends a ! after the type/scope, -introduces a breaking API change (correlating with MAJOR in semantic versioning). -A BREAKING CHANGE can be part of commits of any type. - -the following is an example of a commit message: - -```text -feat: add 'extras' field -``` - -## License - -[AGPL-3.0](https://choosealicense.com/licenses/agpl-3.0/) diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/error.go b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/error.go deleted file mode 100644 index 614b13e..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/error.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2022 schukai GmbH -// SPDX-License-Identifier: AGPL-3.0 - -package pathfinder - -import ( - "errors" - "reflect" -) - -type InvalidPathError error - -func newInvalidPathError(path string) InvalidPathError { - return InvalidPathError(errors.New("invalid path " + path)) -} - -type UnsupportedTypeAtTopOfPathError error - -func newUnsupportedTypeAtTopOfPathError(path string, t reflect.Type) UnsupportedTypeAtTopOfPathError { - return UnsupportedTypeAtTopOfPathError(errors.New("unsupported type " + t.String() + " at top of path " + path)) -} - -type UnsupportedTypePathError error - -func newUnsupportedTypePathError(path string, t reflect.Type) UnsupportedTypePathError { - return UnsupportedTypePathError(errors.New("unsupported type " + t.String() + " at path " + path)) -} - -type CannotSetError error - -func newCannotSetError(name string) CannotSetError { - return CannotSetError(errors.New("cannot set " + name)) -} - -type InvalidTypeForPathError error - -func newInvalidTypeForPathError(path string, pt string, nt string) InvalidTypeForPathError { - return InvalidTypeForPathError(errors.New("invalid type for path " + path + ": expected " + pt + ", got " + nt)) -} diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/error_test.go b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/error_test.go deleted file mode 100644 index e245946..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/error_test.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2022 schukai GmbH -// SPDX-License-Identifier: AGPL-3.0 - -package pathfinder - -import ( - "github.com/stretchr/testify/assert" - "reflect" - "testing" -) - -func TestInvalidPathError(t *testing.T) { - err := newInvalidPathError("test") - _, ok := err.(InvalidPathError) - assert.True(t, ok) -} - -func TestUnsupportedTypeAtTopOfPathError(t *testing.T) { - err := newUnsupportedTypeAtTopOfPathError("test", reflect.TypeOf(1)) - _, ok := err.(UnsupportedTypeAtTopOfPathError) - assert.True(t, ok) -} - -func TestUnsupportedTypePathError(t *testing.T) { - err := newUnsupportedTypePathError("test", reflect.TypeOf(1)) - _, ok := err.(UnsupportedTypePathError) - assert.True(t, ok) -} - -func TestCannotSetError(t *testing.T) { - err := newCannotSetError("test") - _, ok := err.(CannotSetError) - assert.True(t, ok) -} - -func TestInvalidTypeForPathError(t *testing.T) { - err := newInvalidTypeForPathError("test", "test", "test") - _, ok := err.(InvalidTypeForPathError) - assert.True(t, ok) -} diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/get.go b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/get.go deleted file mode 100644 index 79789c4..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/get.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2022 schukai GmbH -// SPDX-License-Identifier: AGPL-3.0 - -package pathfinder - -import ( - "reflect" - "strconv" - "strings" -) - -// This function returns the value of a field in a struct, given a path to the field. -func GetValue[D any](obj D, keyWithDots string) (any, error) { - keySlice := strings.Split(keyWithDots, ".") - v := reflect.ValueOf(obj) - - for _, key := range keySlice[0:len(keySlice)] { - - switch v.Kind() { - case reflect.Ptr, reflect.Slice, reflect.Array, reflect.Interface: - v = v.Elem() - } - - switch v.Kind() { - case reflect.Map: - v = v.MapIndex(reflect.ValueOf(key)) - if !v.IsValid() { - return nil, newInvalidPathError(keyWithDots) - } - - case reflect.Slice, reflect.Array: - index, err := strconv.Atoi(key) - if err != nil { - return nil, newInvalidPathError(keyWithDots) - } - v = v.Index(index) - case reflect.Struct: - v = v.FieldByName(key) - if !v.IsValid() { - return nil, newInvalidPathError(keyWithDots) - } - default: - return nil, newInvalidPathError(keyWithDots) - } - - } - - if v.Kind() == reflect.Invalid { - return nil, newInvalidPathError(keyWithDots) - } - - for v.Kind() == reflect.Ptr { - v = v.Elem() - } - - return v.Interface(), nil - -} diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/get_test.go b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/get_test.go deleted file mode 100644 index 2340260..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/get_test.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2022 schukai GmbH -// SPDX-License-Identifier: AGPL-3.0 - -package pathfinder - -import ( - "github.com/stretchr/testify/assert" - "testing" -) - -func TestGetIndexFromArray(t *testing.T) { - m := map[string]any{ - "A": "true", - "B": []string{ - "1", - "2", - "3", - }, - } - - v, err := GetValue[map[string]any](m, "B.1") - if err != nil { - t.Error(err) - } - - assert.Equal(t, "2", v) - -} - -func TestGetValueFrom(t *testing.T) { - - m := map[string]string{ - "KeyA": "true", - "KeyB": "2", - "KeyC": "3", - "KeyD": "4.0", - } - - v, err := GetValue[map[string]string](m, "KeyA") - if err != nil { - t.Error(err) - } - - assert.Equal(t, v, "true") - -} - -func TestPathGetValueFromX(t *testing.T) { - m := map[string]any{ - "A": "true", - "B": map[string]any{ - "C": 2, - "D": map[string]any{ - "E": "3", - }, - }, - "X": "3", - "Y": "4.0", - } - - v, err := GetValue[map[string]any](m, "B.D.E") - if err != nil { - t.Error(err) - } - - assert.Equal(t, "3", v) - - v, err = GetValue[map[string]any](m, "B.C") - if err != nil { - t.Error(err) - } - - assert.Equal(t, 2, v) - -} - -func TestPathGetValueFrom(t *testing.T) { - - type PathfindTestStruct1 struct { - A bool - Sub1 struct { - B int - Sub2 struct { - C bool - } - D int - } - } - - var testData PathfindTestStruct1 - testData.A = true - testData.Sub1.B = 2 - testData.Sub1.Sub2.C = true - testData.Sub1.D = 4 - - GetValue[PathfindTestStruct1](testData, "Sub1.B") - GetValue[PathfindTestStruct1](testData, "Sub1.Sub2.C") - GetValue[PathfindTestStruct1](testData, "Sub1.D") - -} diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/go.mod b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/go.mod deleted file mode 100644 index 2d2e207..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/go.mod +++ /dev/null @@ -1,10 +0,0 @@ -module gitlab.schukai.com/oss/libraries/go/utilities/pathfinder - -go 1.19 - -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/testify v1.8.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/go.sum b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/go.sum deleted file mode 100644 index b410979..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/go.sum +++ /dev/null @@ -1,14 +0,0 @@ -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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/pathfinder.iml b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/pathfinder.iml deleted file mode 100644 index 49df094..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/pathfinder.iml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="WEB_MODULE" version="4"> - <component name="Go" enabled="true" /> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$" /> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - </component> -</module> \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/release.json b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/release.json deleted file mode 100644 index ccd00c2..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/release.json +++ /dev/null @@ -1 +0,0 @@ -{"version":"0.5.2"} diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/set.go b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/set.go deleted file mode 100644 index f5ca2f4..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/set.go +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2022 schukai GmbH -// SPDX-License-Identifier: AGPL-3.0 - -package pathfinder - -import ( - "fmt" - "reflect" - "strconv" - "strings" -) - -// This function sets the value of a field in a struct, given a path to the field. -func SetValue[D any](obj D, keyWithDots string, newValue any) error { - - keySlice := strings.Split(keyWithDots, ".") - v := reflect.ValueOf(obj) - - for _, key := range keySlice[0 : len(keySlice)-1] { - for v.Kind() != reflect.Ptr { - if v.Kind() == reflect.Invalid { - return newInvalidPathError(keyWithDots) - } - v = v.Addr() - } - - if v.Kind() != reflect.Ptr { - return newUnsupportedTypePathError(keyWithDots, v.Type()) - } - - elem := v.Elem() - if elem.Kind() != reflect.Struct { - return newUnsupportedTypePathError(keyWithDots, v.Type()) - } - - v = elem.FieldByName(key) - - } - - if v.Kind() == reflect.Invalid { - return newInvalidPathError(keyWithDots) - } - - for v.Kind() == reflect.Ptr { - v = v.Elem() - } - - // non-supporter type at the top of the path - if v.Kind() != reflect.Struct { - return newUnsupportedTypeAtTopOfPathError(keyWithDots, v.Type()) - } - - v = v.FieldByName(keySlice[len(keySlice)-1]) - if !v.IsValid() { - return newInvalidPathError(keyWithDots) - } - - if !v.CanSet() { - return newCannotSetError(keyWithDots) - } - - switch v.Kind() { - case reflect.Ptr: - if newValue == nil { - v.Set(reflect.Zero(v.Type())) - } else { - v.Set(reflect.ValueOf(&newValue)) - } - return nil - } - - newValueType := reflect.TypeOf(newValue) - if newValueType == nil { - return newUnsupportedTypePathError(keyWithDots, v.Type()) - } - - newValueKind := reflect.TypeOf(newValue).Kind() - - switch v.Kind() { - case reflect.String: - if newValueKind == reflect.String { - v.SetString(newValue.(string)) - } else { - v.SetString(fmt.Sprintf("%v", newValue)) - } - - case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: - - if newValueKind == reflect.Int { - v.SetInt(int64(newValue.(int))) - } else { - s, err := strconv.ParseInt(fmt.Sprintf("%v", newValue), 10, 64) - if err != nil { - return err - } - v.SetInt(s) - } - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - - if newValueKind == reflect.Int { - v.SetUint(uint64(newValue.(int))) - } else { - s, err := strconv.ParseInt(fmt.Sprintf("%v", newValue), 10, 64) - if err != nil { - return err - } - v.SetUint(uint64(s)) - } - - case reflect.Bool: - - if newValueKind == reflect.Bool { - v.SetBool(newValue.(bool)) - } else { - b, err := strconv.ParseBool(fmt.Sprintf("%v", newValue)) - if err != nil { - return err - } - - v.SetBool(b) - } - - case reflect.Float64, reflect.Float32: - - if newValueKind == reflect.Float64 { - v.SetFloat(newValue.(float64)) - } else { - s, err := strconv.ParseFloat(fmt.Sprintf("%v", newValue), 64) - if err != nil { - return err - } - - v.SetFloat(s) - } - - case reflect.Slice, reflect.Array: - - if newValueKind == reflect.Ptr { - newValue = reflect.ValueOf(newValue).Elem().Interface() - v.Set(reflect.ValueOf(newValue)) - } else if newValueKind == reflect.Slice { - v.Set(reflect.ValueOf(newValue)) - } else { - return newUnsupportedTypePathError(keyWithDots, v.Type()) - } - - default: - return newInvalidTypeForPathError(keyWithDots, v.Type().String(), newValueKind.String()) - } - - return nil - -} diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/set_test.go b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/set_test.go deleted file mode 100644 index 37adcb7..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.5.2/set_test.go +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright 2022 schukai GmbH -// SPDX-License-Identifier: AGPL-3.0 - -package pathfinder - -import "testing" - -type PathfindTestStruct1 struct { - A bool - Sub1 struct { - B bool - Bi int - Bs string - Bf float64 - Sub2 struct { - C bool - Ci int - Cs string - Cf float64 - - Sub3 struct { - D bool - Di int - Ds string - Df float64 - } - } - } -} - -func TestPathFindError(t *testing.T) { - - s := PathfindTestStruct1{} - - _, err := GetValue[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.XX") - if err == nil { - t.Error("err == nil") - } - -} - -func TestPathFindSetValueString(t *testing.T) { - - testData := map[string]string{ - "Sub1.B": "true", - "Sub1.Bi": "2", - "Sub1.Bs": "3", - "Sub1.Bf": "4.0", - "Sub1.Sub2.C": "true", - "Sub1.Sub2.Ci": "2", - "Sub1.Sub2.Cs": "3", - "Sub1.Sub2.Cf": "4.0", - "Sub1.Sub2.Sub3.D": "true", - "Sub1.Sub2.Sub3.Di": "2", - "Sub1.Sub2.Sub3.Ds": "3", - "Sub1.Sub2.Sub3.Df": "4.0", - } - - for k, v := range testData { - s := &PathfindTestStruct1{} - err := SetValue[*PathfindTestStruct1](s, k, v) - if err != nil { - t.Error(err) - } - } -} - -func TestPathFindGetValueFrom(t *testing.T) { - - s := PathfindTestStruct1{} - - s.Sub1.B = true - s.Sub1.Bi = 2 - s.Sub1.Bs = "3" - s.Sub1.Bf = 4.0 - - v, err := GetValue[PathfindTestStruct1](s, "Sub1.B") - if err != nil { - t.Error(err) - } - - if v != true { - t.Error("v != true") - } - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Bi") - if err != nil { - t.Error(err) - } - - if v != 2 { - t.Error("v != 2") - } - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Bs") - if err != nil { - t.Error(err) - } - - if v != "3" { - t.Error("v != 3") - } - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Bf") - if err != nil { - t.Error(err) - } - - if v != 4.0 { - t.Error("v != 4.0") - } - - s.Sub1.Sub2.C = true - s.Sub1.Sub2.Ci = 2 - s.Sub1.Sub2.Cs = "3" - s.Sub1.Sub2.Cf = 4.0 - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Sub2.C") - if err != nil { - t.Error(err) - } - - if v != true { - t.Error("v != true") - } - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Sub2.Ci") - if err != nil { - t.Error(err) - } - - if v != 2 { - t.Error("v != 2") - } - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Sub2.Cs") - if err != nil { - t.Error(err) - } - - if v != "3" { - t.Error("v != 3") - } - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Sub2.Cf") - if err != nil { - t.Error(err) - } - - if v != 4.0 { - t.Error("v != 4.0") - } - - s.Sub1.Sub2.Sub3.D = true - s.Sub1.Sub2.Sub3.Di = 2 - s.Sub1.Sub2.Sub3.Ds = "3" - s.Sub1.Sub2.Sub3.Df = 4.0 - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.D") - if err != nil { - t.Error(err) - - } - - if v != true { - t.Error("v != true") - } - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Di") - if err != nil { - t.Error(err) - } - - if v != 2 { - t.Error("v != 2") - } - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Ds") - if err != nil { - t.Error(err) - } - - if v != "3" { - t.Error("v != 3") - } - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Df") - if err != nil { - t.Error(err) - } - - if v != 4.0 { - t.Error("v != 4.0") - } - -} - -func TestPathFindSetValueFrom(t *testing.T) { - s := &PathfindTestStruct1{} - - SetValue[*PathfindTestStruct1](s, "Sub1.B", "true") - SetValue[*PathfindTestStruct1](s, "Sub1.Bi", "2") - SetValue[*PathfindTestStruct1](s, "Sub1.Bs", "3") - SetValue[*PathfindTestStruct1](s, "Sub1.Bf", "4.0") - - if s.Sub1.B != true { - t.Error("s.Sub1.B != true") - } - - if s.Sub1.Bi != 2 { - t.Error("s.Sub1.Bi != 2") - - } - - if s.Sub1.Bs != "3" { - t.Error("s.Sub1.Bs != 3") - } - - if s.Sub1.Bf != 4.0 { - t.Error("s.Sub1.Bf != 4.0") - } - - SetValue[*PathfindTestStruct1](s, "Sub1.Sub2.C", "true") - SetValue[*PathfindTestStruct1](s, "Sub1.Sub2.Ci", "2") - SetValue[*PathfindTestStruct1](s, "Sub1.Sub2.Cs", "3") - SetValue[*PathfindTestStruct1](s, "Sub1.Sub2.Cf", "4.0") - - if s.Sub1.Sub2.C != true { - t.Error("s.Sub1.Sub2.C != true") - - } - - if s.Sub1.Sub2.Ci != 2 { - t.Error("s.Sub1.Sub2.Ci != 2") - - } - - if s.Sub1.Sub2.Cs != "3" { - t.Error("s.Sub1.Sub2.Cs != 3") - - } - - if s.Sub1.Sub2.Cf != 4.0 { - t.Error("s.Sub1.Sub2.Cf != 4.0") - - } - - if s.Sub1.Sub2.Sub3.D != false { - t.Error("s.Sub1.Sub2.Sub3.D != false") - - } - - SetValue[*PathfindTestStruct1](s, "Sub1.Sub2.Sub3.D", "true") - SetValue[*PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Di", "2") - SetValue[*PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Ds", "3") - SetValue[*PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Df", "4.0") - - if s.Sub1.Sub2.Sub3.D != true { - t.Error("s.Sub1.Sub2.Sub3.D != true") - - } - - if s.Sub1.Sub2.Sub3.Di != 2 { - t.Error("s.Sub1.Sub2.Sub3.Di != 2") - - } - - if s.Sub1.Sub2.Sub3.Ds != "3" { - t.Error("s.Sub1.Sub2.Sub3.Ds != 3") - - } - - if s.Sub1.Sub2.Sub3.Df != 4.0 { - t.Error("s.Sub1.Sub2.Sub3.Df != 4.0") - - } - -} diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.chglog/CHANGELOG.tpl.md b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.chglog/CHANGELOG.tpl.md deleted file mode 100644 index 8e98c0b..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.chglog/CHANGELOG.tpl.md +++ /dev/null @@ -1,27 +0,0 @@ -{{ range .Versions }} -<a name="{{ .Tag.Name }}"></a> -## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }} -{{ range .CommitGroups -}} -### {{ .Title }} -{{ range .Commits -}} -- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }} -{{ end }} -{{ end -}} - -{{- if .NoteGroups -}} -{{ range .NoteGroups -}} -### {{ .Title }} -{{ range .Notes }} -{{ .Body }} -{{ end }} -{{ end -}} -{{ end -}} -{{ end -}} - -{{- if .Versions }} -{{ range .Versions -}} -{{ if .Tag.Previous -}} -[{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }} -{{ end -}} -{{ end -}} -{{ end -}} \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.chglog/config.yml b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.chglog/config.yml deleted file mode 100644 index 237f6bc..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.chglog/config.yml +++ /dev/null @@ -1,57 +0,0 @@ -style: gitlab -template: CHANGELOG.tpl.md -info: - title: CHANGELOG - repository_url: https://gitlab.schukai.com/oss/libraries/go/utilities/pathfinder -options: - commits: - filters: - Type: - - feat - - fix - - doc - - refactor - - perf - - test - - chore - ## deprecated types and typos - - docs - - documentation - - feat - - added - - add - - bugfix - - revert - - update - - updates - - change - - changed - commit_groups: - title_maps: - feat: Add Features - fix: Bug Fixes - doc: Documentation - refactor: Code Refactoring - perf: Performance Improvements - test: Tests - ## Chore is used for all other changes that don't fit in the other categories - chore: Changes - ## deprecated types and typos - docs: Documentation - documentation: Documentation - added: Add Features - add: Add Features - bugfix: Bug Fixes - revert: Reverts - update: Changes - updates: Changes - change: Changes - changed: Changes - header: - pattern: "^((\\w+)\\s.*)$" - pattern_maps: - - Subject - - Type - notes: - keywords: - - BREAKING CHANGE diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.envrc b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.envrc deleted file mode 100644 index 6de8a8a..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.envrc +++ /dev/null @@ -1,3 +0,0 @@ -source_url "https://raw.githubusercontent.com/cachix/devenv/d1f7b48e35e6dee421cfd0f51481d17f77586997/direnvrc" "sha256-YBzqskFZxmNb3kYVoKD9ZixoPXJh1C9ZvTLGFRkauZ0=" - -use devenv \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.gitignore b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.gitignore deleted file mode 100644 index 13bb7b5..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.gitignore +++ /dev/null @@ -1,155 +0,0 @@ -# Created by https://www.toptal.com/developers/gitignore/api/intellij,go -# Edit at https://www.toptal.com/developers/gitignore?templates=intellij,go - -### Go ### -# If you prefer the allow list template instead of the deny list, see community template: -# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore -# -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib - -# Test binary, built with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -# Dependency directories (remove the comment below to include it) -# vendor/ - -# Go workspace file -go.work - -### Go Patch ### -/vendor/ -/Godeps/ - -### Intellij ### -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/**/usage.statistics.xml -.idea/**/dictionaries -.idea/**/shelf - -# AWS User-specific -.idea/**/aws.xml - -# Generated files -.idea/**/contentModel.xml - -# Sensitive or high-churn files -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml -.idea/**/dbnavigator.xml - -# Gradle -.idea/**/gradle.xml -.idea/**/libraries - -# Gradle and Maven with auto-import -# When using Gradle or Maven with auto-import, you should exclude module files, -# since they will be recreated, and may cause churn. Uncomment if using -# auto-import. -# .idea/artifacts -# .idea/compiler.xml -# .idea/jarRepositories.xml -# .idea/modules.xml -# .idea/*.iml -# .idea/modules -# *.iml -# *.ipr - -# CMake -cmake-build-*/ - -# Mongo Explorer plugin -.idea/**/mongoSettings.xml - -# File-based project format -*.iws - -# IntelliJ -out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# SonarLint plugin -.idea/sonarlint/ - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties - -# Editor-based Rest Client -.idea/httpRequests - -# Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser - -### Intellij Patch ### -# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 - -# *.iml -# modules.xml -# .idea/misc.xml -# *.ipr - -# Sonarlint plugin -# https://plugins.jetbrains.com/plugin/7973-sonarlint -.idea/**/sonarlint/ - -# SonarQube Plugin -# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin -.idea/**/sonarIssues.xml - -# Markdown Navigator plugin -# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced -.idea/**/markdown-navigator.xml -.idea/**/markdown-navigator-enh.xml -.idea/**/markdown-navigator/ - -# Cache file creation bug -# See https://youtrack.jetbrains.com/issue/JBR-2257 -.idea/$CACHE_FILE$ - -# CodeStream plugin -# https://plugins.jetbrains.com/plugin/12206-codestream -.idea/codestream.xml - -# Azure Toolkit for IntelliJ plugin -# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij -.idea/**/azureSettings.xml - -# End of https://www.toptal.com/developers/gitignore/api/intellij,go -# Devenv -.devenv* -devenv.local.nix - -# direnv -.direnv - -# pre-commit -.pre-commit-config.yaml - -/Session.vim diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.gitlab-ci.yml b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.gitlab-ci.yml deleted file mode 100644 index 4339280..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.gitlab-ci.yml +++ /dev/null @@ -1,69 +0,0 @@ - -# THIS FILE IS AUTOGENERATED BY THE DEVENVSHELL -# DO NOT EDIT THIS FILE MANUALLY -# INSTEAD EDIT THE DEVENVSHELL CONFIGURATION FILE devenv.nix -# AND OPEN A SHELL WITH THE COMMAND devenv shell -# - -image: docker-registry.schukai.com:443/nixos-ci-devenv:latest - -services: - - docker:dind - -variables: - # The repo name as used in - # https://github.com/nix-community/NUR/blob/master/repos.json - NIXOS_VERSION: "23.05" - NIXPKGS_ALLOW_UNFREE: "1" - NIXPKGS_ALLOW_INSECURE: "1" - DOCKER_DRIVER: overlay2 - GIT_DEPTH: 10 - -stages: - - test - - deploy - -before_script: - - nix shell nixpkgs#coreutils-full -c mkdir -p /certs/client/ - - nix shell nixpkgs#coreutils-full -c ln -fs /etc/ssl/certs/ca-bundle.crt /certs/client/ca.pem - - echo > .env-gitlab-ci - - variables=("HOME=$HOME" "CI_COMMIT_REF_NAME=$CI_COMMIT_REF_NAME" "CI_REPOSITORY_URL=$CI_REPOSITORY_URL" "GITLAB_TOKEN=$GITLAB_TOKEN" "CI_JOB_TOKEN=$CI_JOB_TOKEN" "GITLAB_USER_EMAIL=$GITLAB_USER_EMAIL" "GITLAB_USER_NAME=\"$GITLAB_USER_NAME\"" "CI_REGISTRY_USER=$CI_REGISTRY_USER" "CI_PROJECT_ID=$CI_PROJECT_ID" "CI_PROJECT_DIR=$CI_PROJECT_DIR" "CI_API_V4_URL=$CI_API_V4_URL" "CI_PROJECT_NAME=$CI_PROJECT_NAME" "CI_COMMIT_SHORT_SHA=$CI_COMMIT_SHORT_SHA"); for var in "${variables[@]}"; do echo "$var" >> .env-gitlab-ci; done - - cat .env-gitlab-ci - -after_script: - - if [ -f .env-gitlab-ci ]; then rm .env-gitlab-ci; fi - -test: - stage: test - tags: - - nixos - script: - - devenv shell test-lib - - cache: - - key: nixos - paths: - - /nix/store - - artifacts: - paths: - - dist - -deploy: - stage: deploy - tags: - - nixos - script: - - devenv shell -c deploy-lib - - when: on_success - - cache: - - key: nixos - paths: - - /nix/store - - - artifacts: - paths: - - dist diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/.gitignore b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/.gitignore deleted file mode 100644 index 13566b8..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/markdown.xml b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/markdown.xml deleted file mode 100644 index ec0b30f..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/markdown.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project version="4"> - <component name="MarkdownSettings"> - <enabledExtensions> - <entry key="MermaidLanguageExtension" value="false" /> - <entry key="PlantUMLLanguageExtension" value="true" /> - </enabledExtensions> - </component> -</project> \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/misc.xml b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/misc.xml deleted file mode 100644 index 639900d..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/misc.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project version="4"> - <component name="ProjectRootManager"> - <output url="file://$PROJECT_DIR$/out" /> - </component> -</project> \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/modules.xml b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/modules.xml deleted file mode 100644 index 921c18f..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project version="4"> - <component name="ProjectModuleManager"> - <modules> - <module fileurl="file://$PROJECT_DIR$/.idea/pathfinder.iml" filepath="$PROJECT_DIR$/.idea/pathfinder.iml" /> - </modules> - </component> -</project> \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/pathfinder.iml b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/pathfinder.iml deleted file mode 100644 index 25ed3f6..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/pathfinder.iml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="JAVA_MODULE" version="4"> - <component name="Go" enabled="true" /> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$" /> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - </component> -</module> \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/vcs.xml b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project version="4"> - <component name="VcsDirectoryMappings"> - <mapping directory="" vcs="Git" /> - </component> -</project> \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/LICENSE b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/LICENSE deleted file mode 100644 index 22686f9..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/LICENSE +++ /dev/null @@ -1,662 +0,0 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - AGPL-3.0 - - Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <https://www.gnu.org/licenses/>. - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -<https://www.gnu.org/licenses/>. \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/README.md b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/README.md deleted file mode 100644 index 4d1522c..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/README.md +++ /dev/null @@ -1,69 +0,0 @@ -## Pathfinder - -## What does this library? - -This library provides a simple way to get and set values in a nested structure. - -It supports: - -* [X] Set values in a nested structure -* [X] Get values from a nested structure - -## Installation - -```shell -go get gitlab.schukai.com/oss/libraries/go/utilities/pathfinder -``` - -**Note:** This library uses [Go Modules](https://github.com/golang/go/wiki/Modules) to manage dependencies. - -## Usage - -### Set values - -```go -s := &StructA{} -err := GetValue[*StructA](s, "my.key") -``` - -### Get values - -```go -s := &StructA{} -err := SetValue[*StructA](s, "my.key", "value") -``` - -## Contributing - -Merge requests are welcome. For major changes, please open an issue first to discuss what -you would like to change. **Please make sure to update tests as appropriate.** - -Versioning is done with [SemVer](https://semver.org/). -Changelog is generated with [git-chglog](https://github.com/git-chglog/git-chglog#git-chglog) - -Commit messages should follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification. -Messages are started with a type, which is one of the following: - -- **feat**: A new feature -- **fix**: A bug fix -- **doc**: Documentation only changes -- **refactor**: A code change that neither fixes a bug nor adds a feature -- **perf**: A code change that improves performance -- **test**: Adding missing or correcting existing tests -- **chore**: Other changes that don't modify src or test files - -The footer would be used for a reference to an issue or a breaking change. - -A commit that has a footer `BREAKING CHANGE:`, or appends a ! after the type/scope, -introduces a breaking API change (correlating with MAJOR in semantic versioning). -A BREAKING CHANGE can be part of commits of any type. - -the following is an example of a commit message: - -```text -feat: add 'extras' field -``` - -## License - -[AGPL-3.0](https://choosealicense.com/licenses/agpl-3.0/) diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/Taskfile.yml b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/Taskfile.yml deleted file mode 100644 index 7095ba5..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/Taskfile.yml +++ /dev/null @@ -1,59 +0,0 @@ - -# THIS FILE IS AUTOGENERATED BY THE DEVENVSHELL -# DO NOT EDIT THIS FILE MANUALLY -# INSTEAD EDIT THE DEVENVSHELL CONFIGURATION FILE devenv.nix -# AND OPEN A SHELL WITH THE COMMAND devenv shell -# -# Information about the task runner can be found here: -# https://taskfile.dev - -version: '3' - -tasks: - default: - cmds: - - task --list - silent: true - - test: - desc: Execute unit tests in Go. - cmds: - - echo "Execute unit tests in Go." - - go test -cover -v ./... - - go test -bench . - - go test -race . - - test-fuzz: - desc: Conduct fuzzing tests.# - cmds: - - echo "Conduct fuzzing tests." - - go test -v -fuzztime=30s -fuzz=Fuzz ./... - - add-licenses: - desc: Attach license headers to Go files. - cmds: - - echo "Attach license headers to Go files." - - go install github.com/google/addlicense@latest - - addlicense -c "schukai GmbH" -s -l "AGPL-3.0" ./*.go - silent: true - - check-licenses: - desc: Check license headers of Go files. - silent: true - cmds: - - go-licenses save "$(get-go-default-packages)" --ignore "gitlab.schukai.com" --force --save_path ${DEVENV_ROOT}/licenses/ - - check: - desc: Confirm repository status. - cmds: - - git diff-index --quiet HEAD || (echo "There are uncommitted changes after running make. Please commit or stash them before running make."; exit 1) - silent: true - - commit: - desc: Commit changes to the repository. - aliases: - - c - - ci - - git-commit - cmds: - - do-git-commit diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/devenv.lock b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/devenv.lock deleted file mode 100644 index 8993ca8..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/devenv.lock +++ /dev/null @@ -1,190 +0,0 @@ -{ - "nodes": { - "devenv": { - "locked": { - "dir": "src/modules", - "lastModified": 1692003204, - "narHash": "sha256-gO2DXwXuArjpywgtRTDb3aKscWMbnI7YwFaqvV46yv0=", - "owner": "cachix", - "repo": "devenv", - "rev": "ade3ae522baf366296598e232b7b063d81740bbb", - "type": "github" - }, - "original": { - "dir": "src/modules", - "owner": "cachix", - "repo": "devenv", - "type": "github" - } - }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1685518550, - "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "pre-commit-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1660459072, - "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1691950488, - "narHash": "sha256-iUNEeudc4dGjx+HsHccnGiuZUVE/nhjXuQ1DVCsHIUY=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "720e61ed8de116eec48d6baea1d54469b536b985", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-23.05", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-stable": { - "locked": { - "lastModified": 1685801374, - "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-23.05", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1691950488, - "narHash": "sha256-iUNEeudc4dGjx+HsHccnGiuZUVE/nhjXuQ1DVCsHIUY=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "720e61ed8de116eec48d6baea1d54469b536b985", - "type": "github" - }, - "original": { - "id": "nixpkgs", - "ref": "nixos-23.05", - "type": "indirect" - } - }, - "pre-commit-hooks": { - "inputs": { - "flake-compat": "flake-compat", - "flake-utils": "flake-utils", - "gitignore": "gitignore", - "nixpkgs": [ - "nixpkgs" - ], - "nixpkgs-stable": "nixpkgs-stable" - }, - "locked": { - "lastModified": 1691747570, - "narHash": "sha256-J3fnIwJtHVQ0tK2JMBv4oAmII+1mCdXdpeCxtIsrL2A=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "c5ac3aa3324bd8aebe8622a3fc92eeb3975d317a", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "type": "github" - } - }, - "root": { - "inputs": { - "devenv": "devenv", - "nixpkgs": "nixpkgs", - "pre-commit-hooks": "pre-commit-hooks", - "version": "version" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "version": { - "inputs": { - "nixpkgs": "nixpkgs_2" - }, - "locked": { - "lastModified": 1690668568, - "narHash": "sha256-jzixQKFFW4oxO0S4GYqbkFCXzhBd6com6Z9+MtVKakU=", - "ref": "refs/heads/master", - "rev": "3838f03165b726e47d586c04a1821749375e1001", - "revCount": 37, - "type": "git", - "url": "https://gitlab.schukai.com/oss/utilities/version.git" - }, - "original": { - "type": "git", - "url": "https://gitlab.schukai.com/oss/utilities/version.git" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/devenv.nix b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/devenv.nix deleted file mode 100644 index 9a8bbe4..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/devenv.nix +++ /dev/null @@ -1,638 +0,0 @@ -{ pkgs, inputs, phps, lib, config, modulesPath,... }: - -{ - # https://devenv.sh/packages/ - packages = with pkgs; [ - inputs.version.defaultPackage."${builtins.currentSystem}" - appimage-run - blackbox - blackbox-terminal - coreutils-full - dbeaver - delve - dialog - drill - exa - fd - fd - gcc12 - gdlv - git - glab - gnugrep - gnumake - gnused - go-licenses - go-task - gum - httpie - hurl - jq - libffi - logrotate - meld - memcached - netcat - nixfmt - procps - ranger - unixtools.xxd - unzip - util-linux - wget - zlib - ]; - - - # https://devenv.sh/languages/ - # languages.nix.enable = true; - languages = { - go = { enable = true; }; - }; - - difftastic.enable = true; - - scripts.get-go-default-packages.exec = '' -#!${pkgs.bash}/bin/bash -echo $(awk -F ' ' '/^module / { print $2 }' go.mod) -''; - - # This script is executed when the app is built - # You can use it to build the app - scripts.test-lib.exec = '' -#!${pkgs.bash}/bin/bash -#set -euo pipefail -set -x - -PATH="''${PATH}":${pkgs.coreutils}/bin -PATH="''${PATH}":${pkgs.findutils}/bin -PATH="''${PATH}":${pkgs.jq}/bin/ -PATH="''${PATH}":${pkgs.rsync}/bin/ -PATH="''${PATH}":${pkgs.bash}/bin/ -PATH="''${PATH}":${pkgs.curl}/bin/ -PATH="''${PATH}":${pkgs.moreutils}/bin/ -PATH="''${PATH}":${pkgs.gnutar}/bin -PATH="''${PATH}":${pkgs.gzip}/bin/ -PATH="''${PATH}":${pkgs.procps}/bin/ -PATH="''${PATH}":${pkgs.exa}/bin/ -PATH="''${PATH}":${pkgs.git}/bin/ -PATH="''${PATH}":${pkgs.gnugrep}/bin/ -PATH="''${PATH}":${inputs.version.defaultPackage."${builtins.currentSystem}"}/bin/ - -export PATH - -task test - -''; - - # This scritp is used to deploy the app to the gitlab registry - # It is used by the gitlab-ci.yml file - # The environment variables are set in the gitlab project settings - scripts.deploy-lib.exec = '' -#!${pkgs.bash}/bin/bash - -PATH="''${PATH}":${pkgs.coreutils}/bin -PATH="''${PATH}":${pkgs.jq}/bin/ -PATH="''${PATH}":${pkgs.curl}/bin/ -PATH="''${PATH}":${pkgs.moreutils}/bin/ -PATH="''${PATH}":${pkgs.gnutar}/bin -PATH="''${PATH}":${pkgs.gzip}/bin/ -PATH="''${PATH}":${pkgs.exa}/bin/ -PATH="''${PATH}":${pkgs.git}/bin/ -PATH="''${PATH}":${inputs.version.defaultPackage."${builtins.currentSystem}"}/bin/ - -export PATH - -if [[ -f .env-gitlab-ci ]]; then - source .env-gitlab-ci - rm .env-gitlab-ci -fi - -set -x -## if $HOME not set, set it to current directory -if [[ -z "''${HOME}" ]]; then - HOME=$(pwd) -fi - -export HOME - -git config user.email "''${GITLAB_USER_EMAIL}" -git config user.name "''${GITLAB_USER_NAME:-"Gitlab CI"}" -git config pull.rebase true -git config http.sslVerify "false" -git remote set-url origin https://pad:''${GITLAB_TOKEN}@''${CI_REPOSITORY_URL#*@} - -git fetch --all --tags --unshallow -git reset --hard origin/master -git checkout $CI_COMMIT_REF_NAME -git pull origin $CI_COMMIT_REF_NAME - -if [ ! -z "''${CI_PROJECT_DIR}" ]; then - echo "CI_PROJECT_DIR is set, using it as project root." - project_root=$(realpath "''${CI_PROJECT_DIR}")/ -elif [ ! -z "''${DEVENV_ROOT}" ]; then - echo "DEVENV_ROOT is set, using it as project root." - project_root=$(realpath "''${DEVENV_ROOT}")/ -else - echo "Error: DEVENV_ROOT or CI_PROJECT_DIR environment variables are not set." - exit 1 -fi - -if [ ! -d "''${project_root}" ]; then - echo "Error: Project root directory does not seem to be valid." - echo "Check the DEVENV_ROOT or CI_PROJECT_DIR environment variables." - exit 1 -fi - -if [ -z "'CI_JOB_TOKEN" ]; then - echo "Error: CI_JOB_TOKEN variable is not set." - exit 1 -fi - -git --no-pager log --decorate=short --pretty=oneline -gitVersion=v$(version predict) -git tag -a $gitVersion -m"chore: bump version" -git --no-pager log --decorate=short --pretty=oneline -git push -o ci.skip origin ''${CI_COMMIT_REF_NAME} --tags - -echo "done" - -''; - - enterShell = '' - -cat <<'EOF' > Taskfile.yml - -# THIS FILE IS AUTOGENERATED BY THE DEVENVSHELL -# DO NOT EDIT THIS FILE MANUALLY -# INSTEAD EDIT THE DEVENVSHELL CONFIGURATION FILE devenv.nix -# AND OPEN A SHELL WITH THE COMMAND devenv shell -# -# Information about the task runner can be found here: -# https://taskfile.dev - -version: '3' - -tasks: - default: - cmds: - - task --list - silent: true - - test: - desc: Execute unit tests in Go. - cmds: - - echo "Execute unit tests in Go." - - go test -cover -v ./... - - go test -bench . - - go test -race . - - test-fuzz: - desc: Conduct fuzzing tests.# - cmds: - - echo "Conduct fuzzing tests." - - go test -v -fuzztime=30s -fuzz=Fuzz ./... - - add-licenses: - desc: Attach license headers to Go files. - cmds: - - echo "Attach license headers to Go files." - - go install github.com/google/addlicense@latest - - addlicense -c "schukai GmbH" -s -l "AGPL-3.0" ./*.go - silent: true - - check-licenses: - desc: Check license headers of Go files. - silent: true - cmds: - - go-licenses save "$(get-go-default-packages)" --ignore "gitlab.schukai.com" --force --save_path ''${DEVENV_ROOT}/licenses/ - - check: - desc: Confirm repository status. - cmds: - - git diff-index --quiet HEAD || (echo "There are uncommitted changes after running make. Please commit or stash them before running make."; exit 1) - silent: true - - commit: - desc: Commit changes to the repository. - aliases: - - c - - ci - - git-commit - cmds: - - do-git-commit -EOF - -cat <<'EOF' > .gitlab-ci.yml - -# THIS FILE IS AUTOGENERATED BY THE DEVENVSHELL -# DO NOT EDIT THIS FILE MANUALLY -# INSTEAD EDIT THE DEVENVSHELL CONFIGURATION FILE devenv.nix -# AND OPEN A SHELL WITH THE COMMAND devenv shell -# - -image: docker-registry.schukai.com:443/nixos-ci-devenv:latest - -services: - - docker:dind - -variables: - # The repo name as used in - # https://github.com/nix-community/NUR/blob/master/repos.json - NIXOS_VERSION: "23.05" - NIXPKGS_ALLOW_UNFREE: "1" - NIXPKGS_ALLOW_INSECURE: "1" - DOCKER_DRIVER: overlay2 - GIT_DEPTH: 10 - -stages: - - test - - deploy - -before_script: - - nix shell nixpkgs#coreutils-full -c mkdir -p /certs/client/ - - nix shell nixpkgs#coreutils-full -c ln -fs /etc/ssl/certs/ca-bundle.crt /certs/client/ca.pem - - echo > .env-gitlab-ci - - variables=("HOME=''$HOME" "CI_COMMIT_REF_NAME=''$CI_COMMIT_REF_NAME" "CI_REPOSITORY_URL=''$CI_REPOSITORY_URL" "GITLAB_TOKEN=''$GITLAB_TOKEN" "CI_JOB_TOKEN=''$CI_JOB_TOKEN" "GITLAB_USER_EMAIL=''$GITLAB_USER_EMAIL" "GITLAB_USER_NAME=\"''$GITLAB_USER_NAME\"" "CI_REGISTRY_USER=''$CI_REGISTRY_USER" "CI_PROJECT_ID=''$CI_PROJECT_ID" "CI_PROJECT_DIR=''$CI_PROJECT_DIR" "CI_API_V4_URL=''$CI_API_V4_URL" "CI_PROJECT_NAME=''$CI_PROJECT_NAME" "CI_COMMIT_SHORT_SHA=''$CI_COMMIT_SHORT_SHA"); for var in "''${variables[@]}"; do echo "''$var" >> .env-gitlab-ci; done - - cat .env-gitlab-ci - -after_script: - - if [ -f .env-gitlab-ci ]; then rm .env-gitlab-ci; fi - -test: - stage: test - tags: - - nixos - script: - - devenv shell test-lib - - cache: - - key: nixos - paths: - - /nix/store - - artifacts: - paths: - - dist - -deploy: - stage: deploy - tags: - - nixos - script: - - devenv shell -c deploy-lib - - when: on_success - - cache: - - key: nixos - paths: - - /nix/store - - - artifacts: - paths: - - dist -EOF - - - - ''; - - scripts.do-git-commit.exec = '' -#!/usr/bin/env bash - -# Define colors if the terminal supports it -if [ -t 1 ]; then - RED='\033[0;31m' - GREEN='\033[0;32m' - RESET='\033[0m' - BOLD='\033[1m' -else - RED="" - GREEN="" - RESET="" -fi - -step=1 - -reset -clear - -# create random log file -LOGFILE="''$(mktemp)" -if [ $? -ne 0 ]; then - echo -e "''${RED}✖ Could not create temporary log file. Exiting.''${RESET}" - exit 1 -fi - -log_and_display() { - echo -e "''${GREEN}==> $step. $1''${RESET}" | tee -a $LOGFILE - step=$((step + 1)) -} - -log_error_and_display() { - echo -e "''${RED}==> $step. $1''${RESET}" | tee -a $LOGFILE -} - -printLogfileAndExit() { - exit_code=$1 - echo -e "\n\n========================================\n\n\n" - - echo -e "\n\n''${BOLD}Git and GitLab Automation Script''${RESET}\n\nI have performed the following actions:\n\n" - cat "$LOGFILE" - - # Optional: Remove log file - rm -f "$LOGFILE" - - if [ $exit_code -eq 0 ]; then - echo -e "\n''${GREEN}✔''${RESET} All actions were successful" | tee -a $LOGFILE - elif [ $exit_code -eq -1 ]; then - echo -e "\n''${RED}✖''${RESET} The script was manually cancelled" | tee -a $LOGFILE - exit_code=0 - else - echo -e "\n''${RED}✖''${RESET} Some actions failed" | tee -a $LOGFILE - fi - - exit $exit_code -} - -print_headline() { - local title=$1 - local underline=$(printf '─%.0s' $(seq 1 ''${#title})) - echo -e "\n\n''${BOLD}''${title}\n''${underline}''${RESET}\n" -} - -do_cancel() { - echo -e "''${RED}==> ✖ Cancelled.''${RESET}" | tee -a $LOGFILE - printLogfileAndExit -1 -} - -# Function for unified logging and display -log_action() { - if [ $? -eq 0 ]; then - echo -e " ''${GREEN}✔''${RESET} $1: Successful" | tee -a $LOGFILE - else - echo -e " ''${RED}✖''${RESET} $1: Failed" | tee -a $LOGFILE - printLogfileAndExit 1 - fi -} - -print_what_to_do() { - echo -e "\n\nWhat do you want to do?\n" -} - -git_status=$(git status --porcelain) -if [[ -z "$git_status" ]]; then - log_error_and_display "No changes to commit. Exiting." - printLogfileAndExit 0 -fi - -print_headline "Choose commit type" -selection=$(gum choose "feat: (new feature for the user, not a new feature for build script)" "fix: (bug fix for the user, not a fix to a build script)" "chore: (updating grunt tasks etc.; no production code change)" "docs: (changes to the documentation)" "style: (formatting, missing semi colons, etc; no production code change)" "refactor: (refactoring production code, eg. renaming a variable)" "test: (adding missing tests, refactoring tests; no production code change)" "Cancel") - -commit_type=$(echo "$selection" | awk -F':' '{print $1}') - -if [[ "$commit_type" == "Cancel" ]]; then - do_cancel -fi - -log_and_display "You chose the commit type: $commit_type" - -# NEXT STEP ISSUE HANDLING ############################################################################################################ -#log_and_display "Issue handling" - -gitlabIssues=() -while IFS= read -r line; do - if [[ $line =~ ^# ]]; then - id=$(echo "$line" | awk '{print substr($1, 2)}') - title=$(echo "$line" | awk -F'about' '{print $1}' | awk '{$1=$2=""; print substr($0, 3)}') - gitlabIssues+=("$id > $title") - fi -done < <(gum spin --spinner dot --show-output --title "Ask gitlab ..." -- glab issue list --output-format=details) - -## if issues are available, ask if user wants to use an existing issue or create a new one -createOption="Create new issue" -existingOption="Use existing issue" -cancelOption="Cancel" - -print_headline "Choose issue handling" -if [ ''${#gitlabIssues[@]} -eq 0 ]; then - log_and_display "There are no issues available." - - print_what_to_do - choice=$(gum choose "$createOption" "$cancelOption") - -else - log_and_display "There are ''${#gitlabIssues[@]} issues available." - print_what_to_do - choice=$(gum choose "$createOption" "$existingOption" "$cancelOption") -fi - -if [[ "$choice" == "$cancelOption" ]]; then - do_cancel -fi - -## array of issue ids -work_on_issue_ids=() - -issue_text="" - -if [[ "$choice" == "$createOption" ]]; then - print_headline "Create new issue" - issue_text=$(gum input --placeholder "Enter issue title") - echo -e "Enter issue description. ''${RED}End with Ctrl+D''${RESET}\n" - issue_description=$(gum write --placeholder "Enter issue description. End with Ctrl+D") - - if [[ -z "$issue_text" ]]; then - log_error_and_display "Issue title is empty. Exiting." - printLogfileAndExit 1 - fi - - log_and_display "You entered the issue title: $issue_text" - log_and_display "You entered the issue description: $issue_description" - echo -e "\n" - - gum confirm "Do you want to create this issue?" - # gum confirm exits with status 0 if confirmed and status 1 if cancelled. - if [ $? -eq 1 ]; then - do_cancel - fi - - issue_output=$(glab issue create -t"$issue_text" --no-editor --description "$issue_description") - issue_id=$(echo "$issue_output" | grep -oP '(?<=/issues/)\d+') - - work_on_issue_ids+=("$issue_id") - - log_action "glab issue with id $issue_id created" - -else - - print_headline "Use existing issue" - echo -e "Select issue with arrow keys and press tab or space to select. Press enter to confirm.\n" - issue_ids=$(gum choose --no-limit "''${gitlabIssues[@]}") - - # assign issue_ids to work_on_issue_ids. iterate over lines and take integer from beginning of line - while IFS= read -r line; do - work_on_issue_ids+=($(echo "$line" | grep -oP '^\d+')) - done <<<"$issue_ids" - -fi - -if [ ''${#work_on_issue_ids[@]} -eq 0 ]; then - log_and_display "No issue selected. Exiting." - printLogfileAndExit 0 -fi - -# NEXT STEP COMMIT MESSAGE ############################################################################################################ -# print work_on_issue_ids -work_on_issue_ids_string="" -for i in "''${work_on_issue_ids[@]}"; do - work_on_issue_ids_string+="#$i " -done - -log_and_display "You chose to work on the following issues: ''${work_on_issue_ids_string}" - - -print_headline "Check for changes to commit" - -# ' ' = unmodified -# M = modified -# T = file type changed (regular file, symbolic link or submodule) -# A = added -# D = deleted -# R = renamed -# C = copied (if config option status.renames is set to "copies") -# U = updated but unmerged -# https://man.freebsd.org/cgi/man.cgi?query=git-status&sektion=1&manpath=freebsd-release-ports - -count_all_changes=$(echo "$git_status" | wc -l) -count_staged_changes=$(echo "$git_status" | grep -c '^M') -count_new_staged_files=$(echo "$git_status" | grep -c '^A') -count_staged_changes=$((count_staged_changes + count_new_staged_files)) - - - -git_options_all="All $count_all_changes changes" -git_options_staged="Only the $count_staged_changes staged changes" -git_options_select_files="Select files" -git_options_cancel="Cancel" - -git_options_array=() -if [[ $count_all_changes -gt 0 ]]; then - git_options_array+=("$git_options_all") -fi - -if [[ $count_staged_changes -gt 0 ]]; then - git_options_array+=("$git_options_staged") -fi - -git_options_array+=( "$git_options_select_files" ) -git_options_array+=( "$git_options_cancel" ) - - -selection=$(gum choose "''${git_options_array[@]}") -if [[ "$selection" == "$git_options_cancel" ]]; then - do_cancel -fi - -if [[ "$selection" == "$git_options_all" ]]; then - git add -A - echo "1" -elif [[ "$selection" == "$git_options_select_files" ]]; then - - files=() - while IFS= read -r line; do - files+=("$line") - done <<<"$git_status" - - selected_files=$(gum choose --no-limit "''${files[@]}") - - # no files selected - if [[ -z "$selected_files" ]]; then - log_and_display "No files selected. Exiting." - printLogfileAndExit 0 - fi - - # add selected files - while IFS= read -r line; do - ## git proclimne could have letter, ? or ! at the beginning of the line - file=$(echo "$line" | awk '{print $2}') - if [[ -z "$file" || ! -f "$file" ]]; then - log_and_display "No file found in line: $line" - continue - fi - - git add "$file" - done <<<"$selected_files" - -fi - -## count staged changes again and print -count_staged_changes=$(echo "$git_status" | grep -c '^M') -count_new_staged_files=$(echo "$git_status" | grep -c '^A') -count_staged_changes=$((count_staged_changes + count_new_staged_files)) - -log_and_display "You have $count_staged_changes staged changes to commit." - -# NEXT STEP COMMIT MESSAGE ############################################################################################################ - -print_headline "Enter commit message" -commit_message=$(gum input --placeholder "Enter commit message" --value "$commit_type: $issue_text $work_on_issue_ids_string") - -if [[ -z "$commit_message" ]]; then - log_error_and_display "Commit message is empty. Exiting." - printLogfileAndExit 1 -fi - -log_and_display "You entered the commit message: $commit_message" - -gum confirm "Do you want to commit with this message?" -if [ $? -eq 1 ]; then - do_cancel -fi - -# NEXT STEP COMMIT #################################################################################################################### -print_headline "Committing changes" - -if ! git commit -m "$commit_message" ; then - log_error_and_display "Commit failed. Exiting." - printLogfileAndExit 1 -fi - -log_and_display "Commit successful." - -# NEXT STEP PUSH ###################################################################################################################### - -print_headline "Pushing changes" - -if ! git push ; then - log_error_and_display "Push failed. Exiting." - printLogfileAndExit 1 -fi - -log_and_display "Push successful." - -# Close issue ###################################################################################################################### - -print_headline "Closing issues" - -for issue_id in "''${work_on_issue_ids[@]}"; do - - gum confirm "Do you want to close issue #$issue_id?" - if [ $? -eq 1 ]; then - continue - fi - - if ! glab issue close "$issue_id" ; then - log_error_and_display "Closing issue $issue_id failed. Exiting." - else - log_and_display "Closing issue $issue_id successful." - fi -done - -printLogfileAndExit 0 -''; - - -} diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/devenv.yaml b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/devenv.yaml deleted file mode 100644 index 525a6f0..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/devenv.yaml +++ /dev/null @@ -1,7 +0,0 @@ -inputs: - nixpkgs: - url: github:nixos/nixpkgs/nixos-23.05 - - version: - url: git+https://gitlab.schukai.com/oss/utilities/version.git - flake: true diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/error.go b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/error.go deleted file mode 100644 index 614b13e..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/error.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2022 schukai GmbH -// SPDX-License-Identifier: AGPL-3.0 - -package pathfinder - -import ( - "errors" - "reflect" -) - -type InvalidPathError error - -func newInvalidPathError(path string) InvalidPathError { - return InvalidPathError(errors.New("invalid path " + path)) -} - -type UnsupportedTypeAtTopOfPathError error - -func newUnsupportedTypeAtTopOfPathError(path string, t reflect.Type) UnsupportedTypeAtTopOfPathError { - return UnsupportedTypeAtTopOfPathError(errors.New("unsupported type " + t.String() + " at top of path " + path)) -} - -type UnsupportedTypePathError error - -func newUnsupportedTypePathError(path string, t reflect.Type) UnsupportedTypePathError { - return UnsupportedTypePathError(errors.New("unsupported type " + t.String() + " at path " + path)) -} - -type CannotSetError error - -func newCannotSetError(name string) CannotSetError { - return CannotSetError(errors.New("cannot set " + name)) -} - -type InvalidTypeForPathError error - -func newInvalidTypeForPathError(path string, pt string, nt string) InvalidTypeForPathError { - return InvalidTypeForPathError(errors.New("invalid type for path " + path + ": expected " + pt + ", got " + nt)) -} diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/error_test.go b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/error_test.go deleted file mode 100644 index e245946..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/error_test.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2022 schukai GmbH -// SPDX-License-Identifier: AGPL-3.0 - -package pathfinder - -import ( - "github.com/stretchr/testify/assert" - "reflect" - "testing" -) - -func TestInvalidPathError(t *testing.T) { - err := newInvalidPathError("test") - _, ok := err.(InvalidPathError) - assert.True(t, ok) -} - -func TestUnsupportedTypeAtTopOfPathError(t *testing.T) { - err := newUnsupportedTypeAtTopOfPathError("test", reflect.TypeOf(1)) - _, ok := err.(UnsupportedTypeAtTopOfPathError) - assert.True(t, ok) -} - -func TestUnsupportedTypePathError(t *testing.T) { - err := newUnsupportedTypePathError("test", reflect.TypeOf(1)) - _, ok := err.(UnsupportedTypePathError) - assert.True(t, ok) -} - -func TestCannotSetError(t *testing.T) { - err := newCannotSetError("test") - _, ok := err.(CannotSetError) - assert.True(t, ok) -} - -func TestInvalidTypeForPathError(t *testing.T) { - err := newInvalidTypeForPathError("test", "test", "test") - _, ok := err.(InvalidTypeForPathError) - assert.True(t, ok) -} diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/get.go b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/get.go deleted file mode 100644 index 90c2b1c..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/get.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2022 schukai GmbH -// SPDX-License-Identifier: AGPL-3.0 - -package pathfinder - -import ( - "reflect" - "strconv" - "strings" -) - -// GetValue returns the value of a field in a struct, given a path to the field. -// The path can contain dots to access nested fields. -// The object must be a pointer to a struct, a struct, a map, a slice or an array, -// otherwise an error is returned. -func GetValue[D any](obj D, keyWithDots string) (any, error) { - keySlice := strings.Split(keyWithDots, ".") - v := reflect.ValueOf(obj) - - for _, key := range keySlice[0:len(keySlice)] { - - if !v.IsValid() { - return nil, newInvalidPathError(keyWithDots) - } - - switch v.Kind() { - case reflect.Ptr, reflect.Interface: - v = v.Elem() - } - - switch v.Kind() { - case reflect.Map: - v = v.MapIndex(reflect.ValueOf(key)) - if !v.IsValid() { - return nil, newInvalidPathError(keyWithDots) - } - - case reflect.Slice, reflect.Array: - index, err := strconv.Atoi(key) - if err != nil { - return nil, newInvalidPathError(keyWithDots) - } - // check if index is in range - if index >= v.Len() { - return nil, newInvalidPathError(keyWithDots) - } - v = v.Index(index) - case reflect.Struct: - v = v.FieldByName(key) - if !v.IsValid() { - return nil, newInvalidPathError(keyWithDots) - } - default: - return nil, newInvalidPathError(keyWithDots) - } - - } - - if v.Kind() == reflect.Invalid { - return nil, newInvalidPathError(keyWithDots) - } - - for v.Kind() == reflect.Ptr { - v = v.Elem() - } - - // check if v can interface - if !v.CanInterface() { - return nil, newInvalidPathError(keyWithDots) - } - - return v.Interface(), nil - -} diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/get_test.go b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/get_test.go deleted file mode 100644 index 2340260..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/get_test.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2022 schukai GmbH -// SPDX-License-Identifier: AGPL-3.0 - -package pathfinder - -import ( - "github.com/stretchr/testify/assert" - "testing" -) - -func TestGetIndexFromArray(t *testing.T) { - m := map[string]any{ - "A": "true", - "B": []string{ - "1", - "2", - "3", - }, - } - - v, err := GetValue[map[string]any](m, "B.1") - if err != nil { - t.Error(err) - } - - assert.Equal(t, "2", v) - -} - -func TestGetValueFrom(t *testing.T) { - - m := map[string]string{ - "KeyA": "true", - "KeyB": "2", - "KeyC": "3", - "KeyD": "4.0", - } - - v, err := GetValue[map[string]string](m, "KeyA") - if err != nil { - t.Error(err) - } - - assert.Equal(t, v, "true") - -} - -func TestPathGetValueFromX(t *testing.T) { - m := map[string]any{ - "A": "true", - "B": map[string]any{ - "C": 2, - "D": map[string]any{ - "E": "3", - }, - }, - "X": "3", - "Y": "4.0", - } - - v, err := GetValue[map[string]any](m, "B.D.E") - if err != nil { - t.Error(err) - } - - assert.Equal(t, "3", v) - - v, err = GetValue[map[string]any](m, "B.C") - if err != nil { - t.Error(err) - } - - assert.Equal(t, 2, v) - -} - -func TestPathGetValueFrom(t *testing.T) { - - type PathfindTestStruct1 struct { - A bool - Sub1 struct { - B int - Sub2 struct { - C bool - } - D int - } - } - - var testData PathfindTestStruct1 - testData.A = true - testData.Sub1.B = 2 - testData.Sub1.Sub2.C = true - testData.Sub1.D = 4 - - GetValue[PathfindTestStruct1](testData, "Sub1.B") - GetValue[PathfindTestStruct1](testData, "Sub1.Sub2.C") - GetValue[PathfindTestStruct1](testData, "Sub1.D") - -} diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/go.mod b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/go.mod deleted file mode 100644 index f1f0841..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/go.mod +++ /dev/null @@ -1,11 +0,0 @@ -module gitlab.schukai.com/oss/libraries/go/utilities/pathfinder - -go 1.20 - -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/testify v1.8.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/go.sum b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/go.sum deleted file mode 100644 index 0a45411..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/go.sum +++ /dev/null @@ -1,16 +0,0 @@ -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/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/issue_2_test.go b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/issue_2_test.go deleted file mode 100644 index f9d652f..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/issue_2_test.go +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2023 schukai GmbH -// SPDX-License-Identifier: AGPL-3.0 - -package pathfinder - -import ( - "fmt" - "github.com/google/gofuzz" - "github.com/stretchr/testify/assert" - "testing" -) - -type Issue2SubSubStruct struct { - Issue2SubSubField []string -} - -type Issue2SubStruct struct { - Issue2SubField Issue2SubSubStruct -} - -type Issue2Struct struct { - Issue1Sub1 Issue2SubStruct -} - -func TestGetValueWithArray(t *testing.T) { - testStructForGet := Issue2Struct{ - Issue1Sub1: Issue2SubStruct{ - Issue2SubField: Issue2SubSubStruct{ - Issue2SubSubField: []string{"test0", "test1", "test2"}, - }, - }, - } - - // iterate from 0 to 2 - for i := 0; i < 2; i++ { - result, err := GetValue(testStructForGet, "Issue1Sub1.Issue2SubField.Issue2SubSubField."+fmt.Sprintf("%d", i)) - - assert.Nil(t, err) - assert.Equal(t, result, "test"+fmt.Sprintf("%d", i)) - } - - i := 3 - result, err := GetValue(testStructForGet, "Issue1Sub1.Issue2SubField.Issue2SubSubField."+fmt.Sprintf("%d", i)) - - assert.NotNil(t, err) - assert.Nil(t, result) - -} - -func TestGetValueWithArrayFuzz(t *testing.T) { - f := fuzz.New() - - testStructForGet := Issue2Struct{ - Issue1Sub1: Issue2SubStruct{ - Issue2SubField: Issue2SubSubStruct{ - Issue2SubSubField: []string{"test0", "test1", "test2"}, - }, - }, - } - - for i := 0; i < 100; i++ { - var randomIndex int - f.Fuzz(&randomIndex) - randomIndex = randomIndex % len(testStructForGet.Issue1Sub1.Issue2SubField.Issue2SubSubField) - if randomIndex < 0 { - randomIndex = -randomIndex - } - - result, err := GetValue(testStructForGet, "Issue1Sub1.Issue2SubField.Issue2SubSubField."+fmt.Sprintf("%d", randomIndex)) - - if randomIndex < 3 { - assert.Nil(t, err) - assert.Equal(t, result, "test"+fmt.Sprintf("%d", randomIndex)) - } else { - assert.NotNil(t, err) - assert.Nil(t, result) - } - } -} - -func TestSetValueWithArray(t *testing.T) { - testStructForSet := Issue2Struct{ - Issue1Sub1: Issue2SubStruct{ - Issue2SubField: Issue2SubSubStruct{ - Issue2SubSubField: []string{"test0", "test1", "test2"}, - }, - }, - } - - // iterate from 0 to 2 - for i := 0; i < 2; i++ { - - newValue := "test~~" + fmt.Sprintf("%d", i) - k := "Issue1Sub1.Issue2SubField.Issue2SubSubField." + fmt.Sprintf("%d", i) - err := SetValue(&testStructForSet, k, newValue) - - assert.Nil(t, err) - - result, err := GetValue(testStructForSet, k) - assert.Equal(t, result, newValue) - } - - i := 3 - k := "Issue1Sub1.Issue2SubField.Issue2SubSubField." + fmt.Sprintf("%d", i) - err := SetValue(testStructForSet, k, "test3") - assert.NotNil(t, err) - -} - -type PathValue string - -type SubTestSubPaths struct { - Template PathValue - Definitions []PathValue -} - -type SubTest2Def struct { - Paths SubTestSubPaths -} - -type SubTestStruct1 map[string]SubTest2Def -type MainTestStruct struct { - Sub SubTestStruct1 -} - -func TestReplacePathForConfig(t *testing.T) { - config := MainTestStruct{ - Sub: SubTestStruct1{ - "Default": SubTest2Def{ - Paths: SubTestSubPaths{ - Template: "../../../default.html", - Definitions: []PathValue{"../../../legacy.yaml"}, - }, - }, - }, - } - - nn, err2 := GetValue[MainTestStruct](config, "Sub.Default.Paths.Template") - assert.Nil(t, err2) - - assert.Equal(t, nn, PathValue("../../../default.html")) - - err := SetValue[*MainTestStruct](&config, "Sub.Default.Paths.Template", "test") - assert.Nil(t, err) - - nn, err3 := GetValue[MainTestStruct](config, "Sub.Default.Paths.Template") - assert.Nil(t, err3) - - assert.Equal(t, nn, PathValue("test")) - -} diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/issue_7_test.go b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/issue_7_test.go deleted file mode 100644 index 5033b28..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/issue_7_test.go +++ /dev/null @@ -1,126 +0,0 @@ -package pathfinder - -import ( - "github.com/stretchr/testify/assert" - "testing" -) - -// Test für SetValue -func TestSetValue(t *testing.T) { - type Inner struct { - Field PathValue - } - type Outer struct { - InnerField *Inner - } - - obj := &Outer{ - InnerField: &Inner{ - Field: "oldValue", - }, - } - - v, err := GetValue[Outer](*obj, "InnerField.Field") - if err != nil { - t.Error(err) - } - - assert.Equal(t, PathValue("oldValue"), v) - - nv := PathValue("newValue") - err = SetValue[*Outer](obj, "InnerField.Field", nv) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - if obj.InnerField.Field != "newValue" { - t.Fatalf("expected newValue, got: %s", obj.InnerField.Field) - } - - v, err = GetValue[Outer](*obj, "InnerField.Field") - if err != nil { - t.Error(err) - } - - assert.Equal(t, v, nv) - -} - -type Issue7Routing struct { - P PathValue `json:"p" yaml:"p"` - X string `json:"x" yaml:"x"` -} - -type Issue7Server struct { - Routing []Issue7Routing `json:"routing" yaml:"routing"` -} - -type Issue7Config struct { - Server Issue7Server `json:"server" yaml:"server"` -} - -func TestPathRewrite(t *testing.T) { - - obj := Issue7Config{ - Server: Issue7Server{ - Routing: []Issue7Routing{ - { - P: "./test", - X: "testX", - }, - }, - }, - } - - v, err := GetValue[*Issue7Config](&obj, "Server.Routing.0.P") - assert.Nil(t, err) - - assert.Equal(t, PathValue("./test"), v) - - nv := PathValue("newValue") - err = SetValue[*Issue7Config](&obj, "Server.Routing.0.P", nv) - assert.Nil(t, err) - - if obj.Server.Routing[0].P != "newValue" { - t.Fatalf("expected newValue, got: %s", obj.Server.Routing[0].P) - } - - v, err = GetValue[*Issue7Config](&obj, "Server.Routing.0.P") - assert.Nil(t, err) - assert.Equal(t, v, nv) - -} - -// Test data structs -type Issue7TestStruct2 struct { - D map[string]PathValue -} - -func TestPathRewrite2(t *testing.T) { - // Test case 2 - ts2 := Issue7TestStruct2{ - D: map[string]PathValue{ - "key1": "yyy", - "key2": "zzz", - }, - } - - v, err := GetValue[Issue7TestStruct2](ts2, "D.key1") - assert.Nil(t, err) - assert.Equal(t, PathValue("yyy"), v) - - v, err = GetValue[Issue7TestStruct2](ts2, "D.key2") - assert.Nil(t, err) - assert.Equal(t, PathValue("zzz"), v) - - err = SetValue[*Issue7TestStruct2](&ts2, "D.key1", "xxx") - assert.Nil(t, err) - - v, err = GetValue[Issue7TestStruct2](ts2, "D.key1") - assert.Nil(t, err) - assert.Equal(t, PathValue("xxx"), v) - - v, err = GetValue[Issue7TestStruct2](ts2, "D.key2") - assert.Nil(t, err) - assert.Equal(t, PathValue("zzz"), v) -} diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/pathfinder.iml b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/pathfinder.iml deleted file mode 100644 index 49df094..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/pathfinder.iml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="WEB_MODULE" version="4"> - <component name="Go" enabled="true" /> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$" /> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - </component> -</module> \ No newline at end of file diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/release.json b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/release.json deleted file mode 100644 index ccd00c2..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/release.json +++ /dev/null @@ -1 +0,0 @@ -{"version":"0.5.2"} diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/set.go b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/set.go deleted file mode 100644 index 92b6509..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/set.go +++ /dev/null @@ -1,332 +0,0 @@ -// Copyright 2022 schukai GmbH -// SPDX-License-Identifier: AGPL-3.0 - -package pathfinder - -import ( - "bytes" - "encoding/gob" - "fmt" - "reflect" - "strconv" - "strings" -) - -func deepCopy(src, dst interface{}) error { - var buf bytes.Buffer - enc := gob.NewEncoder(&buf) - dec := gob.NewDecoder(&buf) - - if err := enc.Encode(src); err != nil { - return err - } - - return dec.Decode(dst) -} - -// SetValue sets the value of a field in a struct, given a path to the field. -// The object must be a pointer to a struct, otherwise an error is returned. -func SetValue[D any](obj D, keyWithDots string, newValue any) error { - - keySlice := strings.Split(keyWithDots, ".") - reflectionOfObject := reflect.ValueOf(obj) - - for keyIndex, key := range keySlice[0 : len(keySlice)-1] { - - if reflectionOfObject.Kind() == reflect.Map { - - if reflectionOfObject.IsNil() { - return newInvalidPathError(keyWithDots) - } - - currentValue := reflectionOfObject.MapIndex(reflect.ValueOf(key)).Interface() - newValueCopy := reflect.New(reflect.TypeOf(currentValue)).Interface() - if err := deepCopy(currentValue, newValueCopy); err != nil { - return err - } - - newValueCopyPtr := &newValueCopy - newValueCopyReflect := reflect.ValueOf(newValueCopyPtr).Elem() - if !newValueCopyReflect.CanAddr() { - return newCannotSetError("Wert ist nicht adressierbar") - } - newKey := strings.Join(keySlice[keyIndex+1:], ".") - err := SetValue(newValueCopyPtr, newKey, newValue) - if err != nil { - return err - } - - reflectionOfObject.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(newValueCopy).Elem()) - return nil - - } - - if reflectionOfObject.Kind() == reflect.Ptr && reflectionOfObject.Elem().Kind() == reflect.Interface { - reflectionOfObject = reflectionOfObject.Elem().Elem() - } - - for reflectionOfObject.Kind() != reflect.Ptr { - if reflectionOfObject.Kind() == reflect.Invalid { - return newInvalidPathError(keyWithDots) - } - - if reflectionOfObject.CanAddr() { - reflectionOfObject = reflectionOfObject.Addr() - } else { - return newCannotSetError(keyWithDots) - } - - } - - if reflectionOfObject.Kind() != reflect.Ptr { - return newUnsupportedTypePathError(keyWithDots, reflectionOfObject.Type()) - } - - switch reflectionOfObject.Elem().Kind() { - case reflect.Struct: - reflectionOfObject = reflectionOfObject.Elem().FieldByName(key) - - case reflect.Slice: - // index is a number and get reflectionOfObject from slice with index - index, err := strconv.Atoi(key) - if err != nil { - return newInvalidPathError(keyWithDots) - } - - if index >= reflectionOfObject.Elem().Len() { - return newInvalidPathError(keyWithDots) - } - - reflectionOfObject = reflectionOfObject.Elem().Index(index) - default: - return newUnsupportedTypePathError(keyWithDots, reflectionOfObject.Type()) - } - - } - - if reflectionOfObject.Kind() == reflect.Invalid { - return newInvalidPathError(keyWithDots) - } - - for reflectionOfObject.Kind() == reflect.Ptr { - reflectionOfObject = reflectionOfObject.Elem() - } - - // non-supporter type at the top of the path - switch reflectionOfObject.Kind() { - case reflect.Struct: - - reflectionOfObject = reflectionOfObject.FieldByName(keySlice[len(keySlice)-1]) - if !reflectionOfObject.IsValid() { - return newInvalidPathError(keyWithDots) - } - - if !reflectionOfObject.CanSet() { - return newCannotSetError(keyWithDots) - } - - case reflect.Map: - - key := keySlice[len(keySlice)-1] - m := reflectionOfObject - - keyVal := reflect.ValueOf(key) - newVal := reflect.ValueOf(newValue) - - if !keyVal.Type().ConvertibleTo(m.Type().Key()) { - return fmt.Errorf("key type mismatch") - } - - if !newVal.Type().ConvertibleTo(m.Type().Elem()) { - return fmt.Errorf("value type mismatch") - } - - keyValConverted := keyVal.Convert(m.Type().Key()) - newValConverted := newVal.Convert(m.Type().Elem()) - m.SetMapIndex(keyValConverted, newValConverted) - return nil - - //currentValue := reflectionOfObject.MapIndex(reflect.ValueOf(key)).Interface() - //newValueCopy := reflect.New(reflect.TypeOf(currentValue)).Interface() - //if err := deepCopy(currentValue, newValueCopy); err != nil { - // return err - //} - //newValueCopyPtr := &newValueCopy - //newValueCopyReflect := reflect.ValueOf(newValueCopyPtr).Elem() - //if !newValueCopyReflect.CanAddr() { - // return newCannotSetError("Wert ist nicht adressierbar") - //} - ////newKey := strings.Join(keySlice[keyIndex+1:], ".") - ////err := SetValue(newValueCopyPtr, newKey, newValue) - ////if err != nil { - //// return err - ////} - // - //reflectionOfObject.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(newValueCopy).Elem()) - //return nil - - //if reflectionOfObject.IsNil() { - // return newInvalidPathError(keyWithDots) - //} - // - //index := keySlice[len(keySlice)-1] - //reflectedIndex := reflect.ValueOf(index) - // - //if !reflectedIndex.Type().AssignableTo(reflectionOfObject.Type().Key()) { - // return newInvalidPathError(keyWithDots) - //} - // - //currentValue := reflectionOfObject.MapIndex(reflectedIndex).Interface() - //newValueCopy := reflect.New(reflect.TypeOf(currentValue)).Interface() - //if err := deepCopy(currentValue, newValueCopy); err != nil { - // return err - //} - // - //if !reflect.ValueOf(newValueCopy).Elem().Type().AssignableTo(reflectionOfObject.Type().Elem()) { - // return newInvalidPathError(keyWithDots) - //} - // - //newValueCopyX := reflect.ValueOf(newValueCopy).Elem() - //reflectionOfObject.SetMapIndex(reflectedIndex, newValueCopyX) - - case reflect.Slice: - - // index is a number and get reflectionOfObject from slice with index - index, err := strconv.Atoi(keySlice[len(keySlice)-1]) - if err != nil { - return newInvalidPathError(keyWithDots) - } - - // index out of range - if index >= reflectionOfObject.Len() { - return newInvalidPathError(keyWithDots) - } - - reflectionOfObject = reflectionOfObject.Index(index) - - case reflect.Array: - return newUnsupportedTypeAtTopOfPathError(keyWithDots, reflectionOfObject.Type()) - case reflect.Ptr: - if newValue == nil { - reflectionOfObject.Set(reflect.Zero(reflectionOfObject.Type())) - } else { - reflectionOfObject.Set(reflect.ValueOf(&newValue)) - } - return nil - case reflect.Interface: - return newUnsupportedTypeAtTopOfPathError(keyWithDots, reflectionOfObject.Type()) - case reflect.Chan: - return newUnsupportedTypeAtTopOfPathError(keyWithDots, reflectionOfObject.Type()) - case reflect.Func: - return newUnsupportedTypeAtTopOfPathError(keyWithDots, reflectionOfObject.Type()) - case reflect.UnsafePointer: - return newUnsupportedTypeAtTopOfPathError(keyWithDots, reflectionOfObject.Type()) - case reflect.Uintptr: - return newUnsupportedTypeAtTopOfPathError(keyWithDots, reflectionOfObject.Type()) - case reflect.Complex64: - return newUnsupportedTypeAtTopOfPathError(keyWithDots, reflectionOfObject.Type()) - case reflect.Complex128: - return newUnsupportedTypeAtTopOfPathError(keyWithDots, reflectionOfObject.Type()) - case reflect.Invalid: - return newUnsupportedTypeAtTopOfPathError(keyWithDots, reflectionOfObject.Type()) - default: - return newUnsupportedTypeAtTopOfPathError(keyWithDots, reflectionOfObject.Type()) - } - - newValueType := reflect.TypeOf(newValue) - if newValueType == nil { - return newUnsupportedTypePathError(keyWithDots, reflectionOfObject.Type()) - } - - newValueKind := reflect.TypeOf(newValue).Kind() - - switch reflectionOfObject.Kind() { - case reflect.String: - if reflectionOfObject.Kind() == reflect.Ptr || reflectionOfObject.Kind() == reflect.Interface { - if reflectionOfObject.Elem().CanSet() && reflectionOfObject.Elem().Kind() == reflect.String { - if newValueKind == reflect.String { - reflectionOfObject.Elem().SetString(newValue.(string)) - } else { - reflectionOfObject.Elem().SetString(fmt.Sprintf("%v", newValue)) - } - } - } else if newValueKind == reflect.String { - - if reflect.TypeOf(newValue).ConvertibleTo(reflect.TypeOf("")) { - newValueString := reflect.ValueOf(newValue).Convert(reflect.TypeOf("")).Interface().(string) - reflectionOfObject.SetString(newValueString) - } else { - return newUnsupportedTypePathError(keyWithDots, reflectionOfObject.Type()) - } - } else { - reflectionOfObject.SetString(fmt.Sprintf("%v", newValue)) - } - - case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: - - if newValueKind == reflect.Int { - reflectionOfObject.SetInt(int64(newValue.(int))) - } else { - s, err := strconv.ParseInt(fmt.Sprintf("%v", newValue), 10, 64) - if err != nil { - return err - } - reflectionOfObject.SetInt(s) - } - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - - if newValueKind == reflect.Int { - reflectionOfObject.SetUint(uint64(newValue.(int))) - } else { - s, err := strconv.ParseInt(fmt.Sprintf("%v", newValue), 10, 64) - if err != nil { - return err - } - reflectionOfObject.SetUint(uint64(s)) - } - - case reflect.Bool: - - if newValueKind == reflect.Bool { - reflectionOfObject.SetBool(newValue.(bool)) - } else { - b, err := strconv.ParseBool(fmt.Sprintf("%v", newValue)) - if err != nil { - return err - } - - reflectionOfObject.SetBool(b) - } - - case reflect.Float64, reflect.Float32: - - if newValueKind == reflect.Float64 { - reflectionOfObject.SetFloat(newValue.(float64)) - } else { - s, err := strconv.ParseFloat(fmt.Sprintf("%v", newValue), 64) - if err != nil { - return err - } - - reflectionOfObject.SetFloat(s) - } - - case reflect.Slice, reflect.Array: - - if newValueKind == reflect.Ptr { - newValue = reflect.ValueOf(newValue).Elem().Interface() - reflectionOfObject.Set(reflect.ValueOf(newValue)) - } else if newValueKind == reflect.Slice { - reflectionOfObject.Set(reflect.ValueOf(newValue)) - } else { - return newUnsupportedTypePathError(keyWithDots, reflectionOfObject.Type()) - } - - default: - return newInvalidTypeForPathError(keyWithDots, reflectionOfObject.Type().String(), newValueKind.String()) - } - - return nil - -} diff --git a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/set_test.go b/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/set_test.go deleted file mode 100644 index 37adcb7..0000000 --- a/.devenv/state/go/pkg/mod/gitlab.schukai.com/oss/libraries/go/utilities/pathfinder@v0.8.1/set_test.go +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright 2022 schukai GmbH -// SPDX-License-Identifier: AGPL-3.0 - -package pathfinder - -import "testing" - -type PathfindTestStruct1 struct { - A bool - Sub1 struct { - B bool - Bi int - Bs string - Bf float64 - Sub2 struct { - C bool - Ci int - Cs string - Cf float64 - - Sub3 struct { - D bool - Di int - Ds string - Df float64 - } - } - } -} - -func TestPathFindError(t *testing.T) { - - s := PathfindTestStruct1{} - - _, err := GetValue[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.XX") - if err == nil { - t.Error("err == nil") - } - -} - -func TestPathFindSetValueString(t *testing.T) { - - testData := map[string]string{ - "Sub1.B": "true", - "Sub1.Bi": "2", - "Sub1.Bs": "3", - "Sub1.Bf": "4.0", - "Sub1.Sub2.C": "true", - "Sub1.Sub2.Ci": "2", - "Sub1.Sub2.Cs": "3", - "Sub1.Sub2.Cf": "4.0", - "Sub1.Sub2.Sub3.D": "true", - "Sub1.Sub2.Sub3.Di": "2", - "Sub1.Sub2.Sub3.Ds": "3", - "Sub1.Sub2.Sub3.Df": "4.0", - } - - for k, v := range testData { - s := &PathfindTestStruct1{} - err := SetValue[*PathfindTestStruct1](s, k, v) - if err != nil { - t.Error(err) - } - } -} - -func TestPathFindGetValueFrom(t *testing.T) { - - s := PathfindTestStruct1{} - - s.Sub1.B = true - s.Sub1.Bi = 2 - s.Sub1.Bs = "3" - s.Sub1.Bf = 4.0 - - v, err := GetValue[PathfindTestStruct1](s, "Sub1.B") - if err != nil { - t.Error(err) - } - - if v != true { - t.Error("v != true") - } - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Bi") - if err != nil { - t.Error(err) - } - - if v != 2 { - t.Error("v != 2") - } - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Bs") - if err != nil { - t.Error(err) - } - - if v != "3" { - t.Error("v != 3") - } - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Bf") - if err != nil { - t.Error(err) - } - - if v != 4.0 { - t.Error("v != 4.0") - } - - s.Sub1.Sub2.C = true - s.Sub1.Sub2.Ci = 2 - s.Sub1.Sub2.Cs = "3" - s.Sub1.Sub2.Cf = 4.0 - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Sub2.C") - if err != nil { - t.Error(err) - } - - if v != true { - t.Error("v != true") - } - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Sub2.Ci") - if err != nil { - t.Error(err) - } - - if v != 2 { - t.Error("v != 2") - } - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Sub2.Cs") - if err != nil { - t.Error(err) - } - - if v != "3" { - t.Error("v != 3") - } - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Sub2.Cf") - if err != nil { - t.Error(err) - } - - if v != 4.0 { - t.Error("v != 4.0") - } - - s.Sub1.Sub2.Sub3.D = true - s.Sub1.Sub2.Sub3.Di = 2 - s.Sub1.Sub2.Sub3.Ds = "3" - s.Sub1.Sub2.Sub3.Df = 4.0 - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.D") - if err != nil { - t.Error(err) - - } - - if v != true { - t.Error("v != true") - } - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Di") - if err != nil { - t.Error(err) - } - - if v != 2 { - t.Error("v != 2") - } - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Ds") - if err != nil { - t.Error(err) - } - - if v != "3" { - t.Error("v != 3") - } - - v, err = GetValue[PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Df") - if err != nil { - t.Error(err) - } - - if v != 4.0 { - t.Error("v != 4.0") - } - -} - -func TestPathFindSetValueFrom(t *testing.T) { - s := &PathfindTestStruct1{} - - SetValue[*PathfindTestStruct1](s, "Sub1.B", "true") - SetValue[*PathfindTestStruct1](s, "Sub1.Bi", "2") - SetValue[*PathfindTestStruct1](s, "Sub1.Bs", "3") - SetValue[*PathfindTestStruct1](s, "Sub1.Bf", "4.0") - - if s.Sub1.B != true { - t.Error("s.Sub1.B != true") - } - - if s.Sub1.Bi != 2 { - t.Error("s.Sub1.Bi != 2") - - } - - if s.Sub1.Bs != "3" { - t.Error("s.Sub1.Bs != 3") - } - - if s.Sub1.Bf != 4.0 { - t.Error("s.Sub1.Bf != 4.0") - } - - SetValue[*PathfindTestStruct1](s, "Sub1.Sub2.C", "true") - SetValue[*PathfindTestStruct1](s, "Sub1.Sub2.Ci", "2") - SetValue[*PathfindTestStruct1](s, "Sub1.Sub2.Cs", "3") - SetValue[*PathfindTestStruct1](s, "Sub1.Sub2.Cf", "4.0") - - if s.Sub1.Sub2.C != true { - t.Error("s.Sub1.Sub2.C != true") - - } - - if s.Sub1.Sub2.Ci != 2 { - t.Error("s.Sub1.Sub2.Ci != 2") - - } - - if s.Sub1.Sub2.Cs != "3" { - t.Error("s.Sub1.Sub2.Cs != 3") - - } - - if s.Sub1.Sub2.Cf != 4.0 { - t.Error("s.Sub1.Sub2.Cf != 4.0") - - } - - if s.Sub1.Sub2.Sub3.D != false { - t.Error("s.Sub1.Sub2.Sub3.D != false") - - } - - SetValue[*PathfindTestStruct1](s, "Sub1.Sub2.Sub3.D", "true") - SetValue[*PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Di", "2") - SetValue[*PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Ds", "3") - SetValue[*PathfindTestStruct1](s, "Sub1.Sub2.Sub3.Df", "4.0") - - if s.Sub1.Sub2.Sub3.D != true { - t.Error("s.Sub1.Sub2.Sub3.D != true") - - } - - if s.Sub1.Sub2.Sub3.Di != 2 { - t.Error("s.Sub1.Sub2.Sub3.Di != 2") - - } - - if s.Sub1.Sub2.Sub3.Ds != "3" { - t.Error("s.Sub1.Sub2.Sub3.Ds != 3") - - } - - if s.Sub1.Sub2.Sub3.Df != 4.0 { - t.Error("s.Sub1.Sub2.Sub3.Df != 4.0") - - } - -} diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/.github/workflows/go.yaml b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/.github/workflows/go.yaml deleted file mode 100644 index d2bb00b..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/.github/workflows/go.yaml +++ /dev/null @@ -1,61 +0,0 @@ ---- -name: Go -on: [push, pull_request] -jobs: - test: - name: Test - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - go: - - "1.5" - - "1.6" - - "1.7" - - "1.8" - - "1.9" - - "1.10" - - "1.11" - - "1.12" - - "1.13" - - "1.14" - - "1.15" - - "1.16.0-beta1" - - "tip" - env: - GOPATH: ${{ github.workspace }}/go - steps: - - name: Check out code into the Go module directory - uses: actions/checkout@v2 - with: - path: ${{ github.workspace }}/go/src/gopkg.in/yaml.v3 - - name: Set up Go ${{ matrix.go }} - if: matrix.go != 'tip' - uses: actions/setup-go@v2 - with: - go-version: ${{ matrix.go }} - stable: false - - name: Set up Go ${{ matrix.go }} - if: matrix.go == 'tip' - run: | - export GOROOT_BOOTSTRAP=`go env GOROOT` - export GOROOT=$HOME/gotip - mkdir $HOME/gotip - cd $HOME/gotip - - curl -s 'https://go.googlesource.com/go/+/refs/heads/master?format=JSON' | awk '/"commit"/{print substr($2,2,40);exit}' >HEAD - awk '{printf("gotip-%s",substr($0,0,7))}' <HEAD >VERSION - - curl -s -o go.tar.gz https://go.googlesource.com/go/+archive/`cat HEAD`.tar.gz - tar xfz go.tar.gz - - cd src - bash make.bash - - echo "GOROOT=$GOROOT" >> $GITHUB_ENV - echo "$GOROOT/bin" >> $GITHUB_PATH - - run: go version - - run: go get -t ./... - working-directory: ${{ github.workspace }}/go/src/gopkg.in/yaml.v3 - - run: go test . - working-directory: ${{ github.workspace }}/go/src/gopkg.in/yaml.v3 diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/LICENSE b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/LICENSE deleted file mode 100644 index 2683e4b..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/LICENSE +++ /dev/null @@ -1,50 +0,0 @@ - -This project is covered by two different licenses: MIT and Apache. - -#### MIT License #### - -The following files were ported to Go from C files of libyaml, and thus -are still covered by their original MIT license, with the additional -copyright staring in 2011 when the project was ported over: - - apic.go emitterc.go parserc.go readerc.go scannerc.go - writerc.go yamlh.go yamlprivateh.go - -Copyright (c) 2006-2010 Kirill Simonov -Copyright (c) 2006-2011 Kirill Simonov - -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. - -### Apache License ### - -All the remaining project files are covered by the Apache license: - -Copyright (c) 2011-2019 Canonical Ltd - -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. diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/NOTICE b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/NOTICE deleted file mode 100644 index 866d74a..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/NOTICE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2011-2016 Canonical Ltd. - -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. diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/README.md b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/README.md deleted file mode 100644 index 08eb1ba..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/README.md +++ /dev/null @@ -1,150 +0,0 @@ -# YAML support for the Go language - -Introduction ------------- - -The yaml package enables Go programs to comfortably encode and decode YAML -values. It was developed within [Canonical](https://www.canonical.com) as -part of the [juju](https://juju.ubuntu.com) project, and is based on a -pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) -C library to parse and generate YAML data quickly and reliably. - -Compatibility -------------- - -The yaml package supports most of YAML 1.2, but preserves some behavior -from 1.1 for backwards compatibility. - -Specifically, as of v3 of the yaml package: - - - YAML 1.1 bools (_yes/no, on/off_) are supported as long as they are being - decoded into a typed bool value. Otherwise they behave as a string. Booleans - in YAML 1.2 are _true/false_ only. - - Octals encode and decode as _0777_ per YAML 1.1, rather than _0o777_ - as specified in YAML 1.2, because most parsers still use the old format. - Octals in the _0o777_ format are supported though, so new files work. - - Does not support base-60 floats. These are gone from YAML 1.2, and were - actually never supported by this package as it's clearly a poor choice. - -and offers backwards -compatibility with YAML 1.1 in some cases. -1.2, including support for -anchors, tags, map merging, etc. Multi-document unmarshalling is not yet -implemented, and base-60 floats from YAML 1.1 are purposefully not -supported since they're a poor design and are gone in YAML 1.2. - -Installation and usage ----------------------- - -The import path for the package is *gopkg.in/yaml.v3*. - -To install it, run: - - go get gopkg.in/yaml.v3 - -API documentation ------------------ - -If opened in a browser, the import path itself leads to the API documentation: - - - [https://gopkg.in/yaml.v3](https://gopkg.in/yaml.v3) - -API stability -------------- - -The package API for yaml v3 will remain stable as described in [gopkg.in](https://gopkg.in). - - -License -------- - -The yaml package is licensed under the MIT and Apache License 2.0 licenses. -Please see the LICENSE file for details. - - -Example -------- - -```Go -package main - -import ( - "fmt" - "log" - - "gopkg.in/yaml.v3" -) - -var data = ` -a: Easy! -b: - c: 2 - d: [3, 4] -` - -// Note: struct fields must be public in order for unmarshal to -// correctly populate the data. -type T struct { - A string - B struct { - RenamedC int `yaml:"c"` - D []int `yaml:",flow"` - } -} - -func main() { - t := T{} - - err := yaml.Unmarshal([]byte(data), &t) - if err != nil { - log.Fatalf("error: %v", err) - } - fmt.Printf("--- t:\n%v\n\n", t) - - d, err := yaml.Marshal(&t) - if err != nil { - log.Fatalf("error: %v", err) - } - fmt.Printf("--- t dump:\n%s\n\n", string(d)) - - m := make(map[interface{}]interface{}) - - err = yaml.Unmarshal([]byte(data), &m) - if err != nil { - log.Fatalf("error: %v", err) - } - fmt.Printf("--- m:\n%v\n\n", m) - - d, err = yaml.Marshal(&m) - if err != nil { - log.Fatalf("error: %v", err) - } - fmt.Printf("--- m dump:\n%s\n\n", string(d)) -} -``` - -This example will generate the following output: - -``` ---- t: -{Easy! {2 [3 4]}} - ---- t dump: -a: Easy! -b: - c: 2 - d: [3, 4] - - ---- m: -map[a:Easy! b:map[c:2 d:[3 4]]] - ---- m dump: -a: Easy! -b: - c: 2 - d: - - 3 - - 4 -``` - diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/apic.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/apic.go deleted file mode 100644 index ae7d049..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/apic.go +++ /dev/null @@ -1,747 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// 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. - -package yaml - -import ( - "io" -) - -func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) { - //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens)) - - // Check if we can move the queue at the beginning of the buffer. - if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) { - if parser.tokens_head != len(parser.tokens) { - copy(parser.tokens, parser.tokens[parser.tokens_head:]) - } - parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head] - parser.tokens_head = 0 - } - parser.tokens = append(parser.tokens, *token) - if pos < 0 { - return - } - copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:]) - parser.tokens[parser.tokens_head+pos] = *token -} - -// Create a new parser object. -func yaml_parser_initialize(parser *yaml_parser_t) bool { - *parser = yaml_parser_t{ - raw_buffer: make([]byte, 0, input_raw_buffer_size), - buffer: make([]byte, 0, input_buffer_size), - } - return true -} - -// Destroy a parser object. -func yaml_parser_delete(parser *yaml_parser_t) { - *parser = yaml_parser_t{} -} - -// String read handler. -func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { - if parser.input_pos == len(parser.input) { - return 0, io.EOF - } - n = copy(buffer, parser.input[parser.input_pos:]) - parser.input_pos += n - return n, nil -} - -// Reader read handler. -func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { - return parser.input_reader.Read(buffer) -} - -// Set a string input. -func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) { - if parser.read_handler != nil { - panic("must set the input source only once") - } - parser.read_handler = yaml_string_read_handler - parser.input = input - parser.input_pos = 0 -} - -// Set a file input. -func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) { - if parser.read_handler != nil { - panic("must set the input source only once") - } - parser.read_handler = yaml_reader_read_handler - parser.input_reader = r -} - -// Set the source encoding. -func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) { - if parser.encoding != yaml_ANY_ENCODING { - panic("must set the encoding only once") - } - parser.encoding = encoding -} - -// Create a new emitter object. -func yaml_emitter_initialize(emitter *yaml_emitter_t) { - *emitter = yaml_emitter_t{ - buffer: make([]byte, output_buffer_size), - raw_buffer: make([]byte, 0, output_raw_buffer_size), - states: make([]yaml_emitter_state_t, 0, initial_stack_size), - events: make([]yaml_event_t, 0, initial_queue_size), - best_width: -1, - } -} - -// Destroy an emitter object. -func yaml_emitter_delete(emitter *yaml_emitter_t) { - *emitter = yaml_emitter_t{} -} - -// String write handler. -func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error { - *emitter.output_buffer = append(*emitter.output_buffer, buffer...) - return nil -} - -// yaml_writer_write_handler uses emitter.output_writer to write the -// emitted text. -func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error { - _, err := emitter.output_writer.Write(buffer) - return err -} - -// Set a string output. -func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) { - if emitter.write_handler != nil { - panic("must set the output target only once") - } - emitter.write_handler = yaml_string_write_handler - emitter.output_buffer = output_buffer -} - -// Set a file output. -func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) { - if emitter.write_handler != nil { - panic("must set the output target only once") - } - emitter.write_handler = yaml_writer_write_handler - emitter.output_writer = w -} - -// Set the output encoding. -func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) { - if emitter.encoding != yaml_ANY_ENCODING { - panic("must set the output encoding only once") - } - emitter.encoding = encoding -} - -// Set the canonical output style. -func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) { - emitter.canonical = canonical -} - -// Set the indentation increment. -func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) { - if indent < 2 || indent > 9 { - indent = 2 - } - emitter.best_indent = indent -} - -// Set the preferred line width. -func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) { - if width < 0 { - width = -1 - } - emitter.best_width = width -} - -// Set if unescaped non-ASCII characters are allowed. -func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) { - emitter.unicode = unicode -} - -// Set the preferred line break character. -func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) { - emitter.line_break = line_break -} - -///* -// * Destroy a token object. -// */ -// -//YAML_DECLARE(void) -//yaml_token_delete(yaml_token_t *token) -//{ -// assert(token); // Non-NULL token object expected. -// -// switch (token.type) -// { -// case YAML_TAG_DIRECTIVE_TOKEN: -// yaml_free(token.data.tag_directive.handle); -// yaml_free(token.data.tag_directive.prefix); -// break; -// -// case YAML_ALIAS_TOKEN: -// yaml_free(token.data.alias.value); -// break; -// -// case YAML_ANCHOR_TOKEN: -// yaml_free(token.data.anchor.value); -// break; -// -// case YAML_TAG_TOKEN: -// yaml_free(token.data.tag.handle); -// yaml_free(token.data.tag.suffix); -// break; -// -// case YAML_SCALAR_TOKEN: -// yaml_free(token.data.scalar.value); -// break; -// -// default: -// break; -// } -// -// memset(token, 0, sizeof(yaml_token_t)); -//} -// -///* -// * Check if a string is a valid UTF-8 sequence. -// * -// * Check 'reader.c' for more details on UTF-8 encoding. -// */ -// -//static int -//yaml_check_utf8(yaml_char_t *start, size_t length) -//{ -// yaml_char_t *end = start+length; -// yaml_char_t *pointer = start; -// -// while (pointer < end) { -// unsigned char octet; -// unsigned int width; -// unsigned int value; -// size_t k; -// -// octet = pointer[0]; -// width = (octet & 0x80) == 0x00 ? 1 : -// (octet & 0xE0) == 0xC0 ? 2 : -// (octet & 0xF0) == 0xE0 ? 3 : -// (octet & 0xF8) == 0xF0 ? 4 : 0; -// value = (octet & 0x80) == 0x00 ? octet & 0x7F : -// (octet & 0xE0) == 0xC0 ? octet & 0x1F : -// (octet & 0xF0) == 0xE0 ? octet & 0x0F : -// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; -// if (!width) return 0; -// if (pointer+width > end) return 0; -// for (k = 1; k < width; k ++) { -// octet = pointer[k]; -// if ((octet & 0xC0) != 0x80) return 0; -// value = (value << 6) + (octet & 0x3F); -// } -// if (!((width == 1) || -// (width == 2 && value >= 0x80) || -// (width == 3 && value >= 0x800) || -// (width == 4 && value >= 0x10000))) return 0; -// -// pointer += width; -// } -// -// return 1; -//} -// - -// Create STREAM-START. -func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) { - *event = yaml_event_t{ - typ: yaml_STREAM_START_EVENT, - encoding: encoding, - } -} - -// Create STREAM-END. -func yaml_stream_end_event_initialize(event *yaml_event_t) { - *event = yaml_event_t{ - typ: yaml_STREAM_END_EVENT, - } -} - -// Create DOCUMENT-START. -func yaml_document_start_event_initialize( - event *yaml_event_t, - version_directive *yaml_version_directive_t, - tag_directives []yaml_tag_directive_t, - implicit bool, -) { - *event = yaml_event_t{ - typ: yaml_DOCUMENT_START_EVENT, - version_directive: version_directive, - tag_directives: tag_directives, - implicit: implicit, - } -} - -// Create DOCUMENT-END. -func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) { - *event = yaml_event_t{ - typ: yaml_DOCUMENT_END_EVENT, - implicit: implicit, - } -} - -// Create ALIAS. -func yaml_alias_event_initialize(event *yaml_event_t, anchor []byte) bool { - *event = yaml_event_t{ - typ: yaml_ALIAS_EVENT, - anchor: anchor, - } - return true -} - -// Create SCALAR. -func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool { - *event = yaml_event_t{ - typ: yaml_SCALAR_EVENT, - anchor: anchor, - tag: tag, - value: value, - implicit: plain_implicit, - quoted_implicit: quoted_implicit, - style: yaml_style_t(style), - } - return true -} - -// Create SEQUENCE-START. -func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool { - *event = yaml_event_t{ - typ: yaml_SEQUENCE_START_EVENT, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(style), - } - return true -} - -// Create SEQUENCE-END. -func yaml_sequence_end_event_initialize(event *yaml_event_t) bool { - *event = yaml_event_t{ - typ: yaml_SEQUENCE_END_EVENT, - } - return true -} - -// Create MAPPING-START. -func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) { - *event = yaml_event_t{ - typ: yaml_MAPPING_START_EVENT, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(style), - } -} - -// Create MAPPING-END. -func yaml_mapping_end_event_initialize(event *yaml_event_t) { - *event = yaml_event_t{ - typ: yaml_MAPPING_END_EVENT, - } -} - -// Destroy an event object. -func yaml_event_delete(event *yaml_event_t) { - *event = yaml_event_t{} -} - -///* -// * Create a document object. -// */ -// -//YAML_DECLARE(int) -//yaml_document_initialize(document *yaml_document_t, -// version_directive *yaml_version_directive_t, -// tag_directives_start *yaml_tag_directive_t, -// tag_directives_end *yaml_tag_directive_t, -// start_implicit int, end_implicit int) -//{ -// struct { -// error yaml_error_type_t -// } context -// struct { -// start *yaml_node_t -// end *yaml_node_t -// top *yaml_node_t -// } nodes = { NULL, NULL, NULL } -// version_directive_copy *yaml_version_directive_t = NULL -// struct { -// start *yaml_tag_directive_t -// end *yaml_tag_directive_t -// top *yaml_tag_directive_t -// } tag_directives_copy = { NULL, NULL, NULL } -// value yaml_tag_directive_t = { NULL, NULL } -// mark yaml_mark_t = { 0, 0, 0 } -// -// assert(document) // Non-NULL document object is expected. -// assert((tag_directives_start && tag_directives_end) || -// (tag_directives_start == tag_directives_end)) -// // Valid tag directives are expected. -// -// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error -// -// if (version_directive) { -// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t)) -// if (!version_directive_copy) goto error -// version_directive_copy.major = version_directive.major -// version_directive_copy.minor = version_directive.minor -// } -// -// if (tag_directives_start != tag_directives_end) { -// tag_directive *yaml_tag_directive_t -// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE)) -// goto error -// for (tag_directive = tag_directives_start -// tag_directive != tag_directives_end; tag_directive ++) { -// assert(tag_directive.handle) -// assert(tag_directive.prefix) -// if (!yaml_check_utf8(tag_directive.handle, -// strlen((char *)tag_directive.handle))) -// goto error -// if (!yaml_check_utf8(tag_directive.prefix, -// strlen((char *)tag_directive.prefix))) -// goto error -// value.handle = yaml_strdup(tag_directive.handle) -// value.prefix = yaml_strdup(tag_directive.prefix) -// if (!value.handle || !value.prefix) goto error -// if (!PUSH(&context, tag_directives_copy, value)) -// goto error -// value.handle = NULL -// value.prefix = NULL -// } -// } -// -// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy, -// tag_directives_copy.start, tag_directives_copy.top, -// start_implicit, end_implicit, mark, mark) -// -// return 1 -// -//error: -// STACK_DEL(&context, nodes) -// yaml_free(version_directive_copy) -// while (!STACK_EMPTY(&context, tag_directives_copy)) { -// value yaml_tag_directive_t = POP(&context, tag_directives_copy) -// yaml_free(value.handle) -// yaml_free(value.prefix) -// } -// STACK_DEL(&context, tag_directives_copy) -// yaml_free(value.handle) -// yaml_free(value.prefix) -// -// return 0 -//} -// -///* -// * Destroy a document object. -// */ -// -//YAML_DECLARE(void) -//yaml_document_delete(document *yaml_document_t) -//{ -// struct { -// error yaml_error_type_t -// } context -// tag_directive *yaml_tag_directive_t -// -// context.error = YAML_NO_ERROR // Eliminate a compiler warning. -// -// assert(document) // Non-NULL document object is expected. -// -// while (!STACK_EMPTY(&context, document.nodes)) { -// node yaml_node_t = POP(&context, document.nodes) -// yaml_free(node.tag) -// switch (node.type) { -// case YAML_SCALAR_NODE: -// yaml_free(node.data.scalar.value) -// break -// case YAML_SEQUENCE_NODE: -// STACK_DEL(&context, node.data.sequence.items) -// break -// case YAML_MAPPING_NODE: -// STACK_DEL(&context, node.data.mapping.pairs) -// break -// default: -// assert(0) // Should not happen. -// } -// } -// STACK_DEL(&context, document.nodes) -// -// yaml_free(document.version_directive) -// for (tag_directive = document.tag_directives.start -// tag_directive != document.tag_directives.end -// tag_directive++) { -// yaml_free(tag_directive.handle) -// yaml_free(tag_directive.prefix) -// } -// yaml_free(document.tag_directives.start) -// -// memset(document, 0, sizeof(yaml_document_t)) -//} -// -///** -// * Get a document node. -// */ -// -//YAML_DECLARE(yaml_node_t *) -//yaml_document_get_node(document *yaml_document_t, index int) -//{ -// assert(document) // Non-NULL document object is expected. -// -// if (index > 0 && document.nodes.start + index <= document.nodes.top) { -// return document.nodes.start + index - 1 -// } -// return NULL -//} -// -///** -// * Get the root object. -// */ -// -//YAML_DECLARE(yaml_node_t *) -//yaml_document_get_root_node(document *yaml_document_t) -//{ -// assert(document) // Non-NULL document object is expected. -// -// if (document.nodes.top != document.nodes.start) { -// return document.nodes.start -// } -// return NULL -//} -// -///* -// * Add a scalar node to a document. -// */ -// -//YAML_DECLARE(int) -//yaml_document_add_scalar(document *yaml_document_t, -// tag *yaml_char_t, value *yaml_char_t, length int, -// style yaml_scalar_style_t) -//{ -// struct { -// error yaml_error_type_t -// } context -// mark yaml_mark_t = { 0, 0, 0 } -// tag_copy *yaml_char_t = NULL -// value_copy *yaml_char_t = NULL -// node yaml_node_t -// -// assert(document) // Non-NULL document object is expected. -// assert(value) // Non-NULL value is expected. -// -// if (!tag) { -// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG -// } -// -// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error -// tag_copy = yaml_strdup(tag) -// if (!tag_copy) goto error -// -// if (length < 0) { -// length = strlen((char *)value) -// } -// -// if (!yaml_check_utf8(value, length)) goto error -// value_copy = yaml_malloc(length+1) -// if (!value_copy) goto error -// memcpy(value_copy, value, length) -// value_copy[length] = '\0' -// -// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark) -// if (!PUSH(&context, document.nodes, node)) goto error -// -// return document.nodes.top - document.nodes.start -// -//error: -// yaml_free(tag_copy) -// yaml_free(value_copy) -// -// return 0 -//} -// -///* -// * Add a sequence node to a document. -// */ -// -//YAML_DECLARE(int) -//yaml_document_add_sequence(document *yaml_document_t, -// tag *yaml_char_t, style yaml_sequence_style_t) -//{ -// struct { -// error yaml_error_type_t -// } context -// mark yaml_mark_t = { 0, 0, 0 } -// tag_copy *yaml_char_t = NULL -// struct { -// start *yaml_node_item_t -// end *yaml_node_item_t -// top *yaml_node_item_t -// } items = { NULL, NULL, NULL } -// node yaml_node_t -// -// assert(document) // Non-NULL document object is expected. -// -// if (!tag) { -// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG -// } -// -// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error -// tag_copy = yaml_strdup(tag) -// if (!tag_copy) goto error -// -// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error -// -// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end, -// style, mark, mark) -// if (!PUSH(&context, document.nodes, node)) goto error -// -// return document.nodes.top - document.nodes.start -// -//error: -// STACK_DEL(&context, items) -// yaml_free(tag_copy) -// -// return 0 -//} -// -///* -// * Add a mapping node to a document. -// */ -// -//YAML_DECLARE(int) -//yaml_document_add_mapping(document *yaml_document_t, -// tag *yaml_char_t, style yaml_mapping_style_t) -//{ -// struct { -// error yaml_error_type_t -// } context -// mark yaml_mark_t = { 0, 0, 0 } -// tag_copy *yaml_char_t = NULL -// struct { -// start *yaml_node_pair_t -// end *yaml_node_pair_t -// top *yaml_node_pair_t -// } pairs = { NULL, NULL, NULL } -// node yaml_node_t -// -// assert(document) // Non-NULL document object is expected. -// -// if (!tag) { -// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG -// } -// -// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error -// tag_copy = yaml_strdup(tag) -// if (!tag_copy) goto error -// -// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error -// -// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end, -// style, mark, mark) -// if (!PUSH(&context, document.nodes, node)) goto error -// -// return document.nodes.top - document.nodes.start -// -//error: -// STACK_DEL(&context, pairs) -// yaml_free(tag_copy) -// -// return 0 -//} -// -///* -// * Append an item to a sequence node. -// */ -// -//YAML_DECLARE(int) -//yaml_document_append_sequence_item(document *yaml_document_t, -// sequence int, item int) -//{ -// struct { -// error yaml_error_type_t -// } context -// -// assert(document) // Non-NULL document is required. -// assert(sequence > 0 -// && document.nodes.start + sequence <= document.nodes.top) -// // Valid sequence id is required. -// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE) -// // A sequence node is required. -// assert(item > 0 && document.nodes.start + item <= document.nodes.top) -// // Valid item id is required. -// -// if (!PUSH(&context, -// document.nodes.start[sequence-1].data.sequence.items, item)) -// return 0 -// -// return 1 -//} -// -///* -// * Append a pair of a key and a value to a mapping node. -// */ -// -//YAML_DECLARE(int) -//yaml_document_append_mapping_pair(document *yaml_document_t, -// mapping int, key int, value int) -//{ -// struct { -// error yaml_error_type_t -// } context -// -// pair yaml_node_pair_t -// -// assert(document) // Non-NULL document is required. -// assert(mapping > 0 -// && document.nodes.start + mapping <= document.nodes.top) -// // Valid mapping id is required. -// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE) -// // A mapping node is required. -// assert(key > 0 && document.nodes.start + key <= document.nodes.top) -// // Valid key id is required. -// assert(value > 0 && document.nodes.start + value <= document.nodes.top) -// // Valid value id is required. -// -// pair.key = key -// pair.value = value -// -// if (!PUSH(&context, -// document.nodes.start[mapping-1].data.mapping.pairs, pair)) -// return 0 -// -// return 1 -//} -// -// diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/decode.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/decode.go deleted file mode 100644 index 0173b69..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/decode.go +++ /dev/null @@ -1,1000 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yaml - -import ( - "encoding" - "encoding/base64" - "fmt" - "io" - "math" - "reflect" - "strconv" - "time" -) - -// ---------------------------------------------------------------------------- -// Parser, produces a node tree out of a libyaml event stream. - -type parser struct { - parser yaml_parser_t - event yaml_event_t - doc *Node - anchors map[string]*Node - doneInit bool - textless bool -} - -func newParser(b []byte) *parser { - p := parser{} - if !yaml_parser_initialize(&p.parser) { - panic("failed to initialize YAML emitter") - } - if len(b) == 0 { - b = []byte{'\n'} - } - yaml_parser_set_input_string(&p.parser, b) - return &p -} - -func newParserFromReader(r io.Reader) *parser { - p := parser{} - if !yaml_parser_initialize(&p.parser) { - panic("failed to initialize YAML emitter") - } - yaml_parser_set_input_reader(&p.parser, r) - return &p -} - -func (p *parser) init() { - if p.doneInit { - return - } - p.anchors = make(map[string]*Node) - p.expect(yaml_STREAM_START_EVENT) - p.doneInit = true -} - -func (p *parser) destroy() { - if p.event.typ != yaml_NO_EVENT { - yaml_event_delete(&p.event) - } - yaml_parser_delete(&p.parser) -} - -// expect consumes an event from the event stream and -// checks that it's of the expected type. -func (p *parser) expect(e yaml_event_type_t) { - if p.event.typ == yaml_NO_EVENT { - if !yaml_parser_parse(&p.parser, &p.event) { - p.fail() - } - } - if p.event.typ == yaml_STREAM_END_EVENT { - failf("attempted to go past the end of stream; corrupted value?") - } - if p.event.typ != e { - p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ) - p.fail() - } - yaml_event_delete(&p.event) - p.event.typ = yaml_NO_EVENT -} - -// peek peeks at the next event in the event stream, -// puts the results into p.event and returns the event type. -func (p *parser) peek() yaml_event_type_t { - if p.event.typ != yaml_NO_EVENT { - return p.event.typ - } - // It's curious choice from the underlying API to generally return a - // positive result on success, but on this case return true in an error - // scenario. This was the source of bugs in the past (issue #666). - if !yaml_parser_parse(&p.parser, &p.event) || p.parser.error != yaml_NO_ERROR { - p.fail() - } - return p.event.typ -} - -func (p *parser) fail() { - var where string - var line int - if p.parser.context_mark.line != 0 { - line = p.parser.context_mark.line - // Scanner errors don't iterate line before returning error - if p.parser.error == yaml_SCANNER_ERROR { - line++ - } - } else if p.parser.problem_mark.line != 0 { - line = p.parser.problem_mark.line - // Scanner errors don't iterate line before returning error - if p.parser.error == yaml_SCANNER_ERROR { - line++ - } - } - if line != 0 { - where = "line " + strconv.Itoa(line) + ": " - } - var msg string - if len(p.parser.problem) > 0 { - msg = p.parser.problem - } else { - msg = "unknown problem parsing YAML content" - } - failf("%s%s", where, msg) -} - -func (p *parser) anchor(n *Node, anchor []byte) { - if anchor != nil { - n.Anchor = string(anchor) - p.anchors[n.Anchor] = n - } -} - -func (p *parser) parse() *Node { - p.init() - switch p.peek() { - case yaml_SCALAR_EVENT: - return p.scalar() - case yaml_ALIAS_EVENT: - return p.alias() - case yaml_MAPPING_START_EVENT: - return p.mapping() - case yaml_SEQUENCE_START_EVENT: - return p.sequence() - case yaml_DOCUMENT_START_EVENT: - return p.document() - case yaml_STREAM_END_EVENT: - // Happens when attempting to decode an empty buffer. - return nil - case yaml_TAIL_COMMENT_EVENT: - panic("internal error: unexpected tail comment event (please report)") - default: - panic("internal error: attempted to parse unknown event (please report): " + p.event.typ.String()) - } -} - -func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node { - var style Style - if tag != "" && tag != "!" { - tag = shortTag(tag) - style = TaggedStyle - } else if defaultTag != "" { - tag = defaultTag - } else if kind == ScalarNode { - tag, _ = resolve("", value) - } - n := &Node{ - Kind: kind, - Tag: tag, - Value: value, - Style: style, - } - if !p.textless { - n.Line = p.event.start_mark.line + 1 - n.Column = p.event.start_mark.column + 1 - n.HeadComment = string(p.event.head_comment) - n.LineComment = string(p.event.line_comment) - n.FootComment = string(p.event.foot_comment) - } - return n -} - -func (p *parser) parseChild(parent *Node) *Node { - child := p.parse() - parent.Content = append(parent.Content, child) - return child -} - -func (p *parser) document() *Node { - n := p.node(DocumentNode, "", "", "") - p.doc = n - p.expect(yaml_DOCUMENT_START_EVENT) - p.parseChild(n) - if p.peek() == yaml_DOCUMENT_END_EVENT { - n.FootComment = string(p.event.foot_comment) - } - p.expect(yaml_DOCUMENT_END_EVENT) - return n -} - -func (p *parser) alias() *Node { - n := p.node(AliasNode, "", "", string(p.event.anchor)) - n.Alias = p.anchors[n.Value] - if n.Alias == nil { - failf("unknown anchor '%s' referenced", n.Value) - } - p.expect(yaml_ALIAS_EVENT) - return n -} - -func (p *parser) scalar() *Node { - var parsedStyle = p.event.scalar_style() - var nodeStyle Style - switch { - case parsedStyle&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0: - nodeStyle = DoubleQuotedStyle - case parsedStyle&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0: - nodeStyle = SingleQuotedStyle - case parsedStyle&yaml_LITERAL_SCALAR_STYLE != 0: - nodeStyle = LiteralStyle - case parsedStyle&yaml_FOLDED_SCALAR_STYLE != 0: - nodeStyle = FoldedStyle - } - var nodeValue = string(p.event.value) - var nodeTag = string(p.event.tag) - var defaultTag string - if nodeStyle == 0 { - if nodeValue == "<<" { - defaultTag = mergeTag - } - } else { - defaultTag = strTag - } - n := p.node(ScalarNode, defaultTag, nodeTag, nodeValue) - n.Style |= nodeStyle - p.anchor(n, p.event.anchor) - p.expect(yaml_SCALAR_EVENT) - return n -} - -func (p *parser) sequence() *Node { - n := p.node(SequenceNode, seqTag, string(p.event.tag), "") - if p.event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 { - n.Style |= FlowStyle - } - p.anchor(n, p.event.anchor) - p.expect(yaml_SEQUENCE_START_EVENT) - for p.peek() != yaml_SEQUENCE_END_EVENT { - p.parseChild(n) - } - n.LineComment = string(p.event.line_comment) - n.FootComment = string(p.event.foot_comment) - p.expect(yaml_SEQUENCE_END_EVENT) - return n -} - -func (p *parser) mapping() *Node { - n := p.node(MappingNode, mapTag, string(p.event.tag), "") - block := true - if p.event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 { - block = false - n.Style |= FlowStyle - } - p.anchor(n, p.event.anchor) - p.expect(yaml_MAPPING_START_EVENT) - for p.peek() != yaml_MAPPING_END_EVENT { - k := p.parseChild(n) - if block && k.FootComment != "" { - // Must be a foot comment for the prior value when being dedented. - if len(n.Content) > 2 { - n.Content[len(n.Content)-3].FootComment = k.FootComment - k.FootComment = "" - } - } - v := p.parseChild(n) - if k.FootComment == "" && v.FootComment != "" { - k.FootComment = v.FootComment - v.FootComment = "" - } - if p.peek() == yaml_TAIL_COMMENT_EVENT { - if k.FootComment == "" { - k.FootComment = string(p.event.foot_comment) - } - p.expect(yaml_TAIL_COMMENT_EVENT) - } - } - n.LineComment = string(p.event.line_comment) - n.FootComment = string(p.event.foot_comment) - if n.Style&FlowStyle == 0 && n.FootComment != "" && len(n.Content) > 1 { - n.Content[len(n.Content)-2].FootComment = n.FootComment - n.FootComment = "" - } - p.expect(yaml_MAPPING_END_EVENT) - return n -} - -// ---------------------------------------------------------------------------- -// Decoder, unmarshals a node into a provided value. - -type decoder struct { - doc *Node - aliases map[*Node]bool - terrors []string - - stringMapType reflect.Type - generalMapType reflect.Type - - knownFields bool - uniqueKeys bool - decodeCount int - aliasCount int - aliasDepth int - - mergedFields map[interface{}]bool -} - -var ( - nodeType = reflect.TypeOf(Node{}) - durationType = reflect.TypeOf(time.Duration(0)) - stringMapType = reflect.TypeOf(map[string]interface{}{}) - generalMapType = reflect.TypeOf(map[interface{}]interface{}{}) - ifaceType = generalMapType.Elem() - timeType = reflect.TypeOf(time.Time{}) - ptrTimeType = reflect.TypeOf(&time.Time{}) -) - -func newDecoder() *decoder { - d := &decoder{ - stringMapType: stringMapType, - generalMapType: generalMapType, - uniqueKeys: true, - } - d.aliases = make(map[*Node]bool) - return d -} - -func (d *decoder) terror(n *Node, tag string, out reflect.Value) { - if n.Tag != "" { - tag = n.Tag - } - value := n.Value - if tag != seqTag && tag != mapTag { - if len(value) > 10 { - value = " `" + value[:7] + "...`" - } else { - value = " `" + value + "`" - } - } - d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.Line, shortTag(tag), value, out.Type())) -} - -func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) { - err := u.UnmarshalYAML(n) - if e, ok := err.(*TypeError); ok { - d.terrors = append(d.terrors, e.Errors...) - return false - } - if err != nil { - fail(err) - } - return true -} - -func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good bool) { - terrlen := len(d.terrors) - err := u.UnmarshalYAML(func(v interface{}) (err error) { - defer handleErr(&err) - d.unmarshal(n, reflect.ValueOf(v)) - if len(d.terrors) > terrlen { - issues := d.terrors[terrlen:] - d.terrors = d.terrors[:terrlen] - return &TypeError{issues} - } - return nil - }) - if e, ok := err.(*TypeError); ok { - d.terrors = append(d.terrors, e.Errors...) - return false - } - if err != nil { - fail(err) - } - return true -} - -// d.prepare initializes and dereferences pointers and calls UnmarshalYAML -// if a value is found to implement it. -// It returns the initialized and dereferenced out value, whether -// unmarshalling was already done by UnmarshalYAML, and if so whether -// its types unmarshalled appropriately. -// -// If n holds a null value, prepare returns before doing anything. -func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) { - if n.ShortTag() == nullTag { - return out, false, false - } - again := true - for again { - again = false - if out.Kind() == reflect.Ptr { - if out.IsNil() { - out.Set(reflect.New(out.Type().Elem())) - } - out = out.Elem() - again = true - } - if out.CanAddr() { - outi := out.Addr().Interface() - if u, ok := outi.(Unmarshaler); ok { - good = d.callUnmarshaler(n, u) - return out, true, good - } - if u, ok := outi.(obsoleteUnmarshaler); ok { - good = d.callObsoleteUnmarshaler(n, u) - return out, true, good - } - } - } - return out, false, false -} - -func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field reflect.Value) { - if n.ShortTag() == nullTag { - return reflect.Value{} - } - for _, num := range index { - for { - if v.Kind() == reflect.Ptr { - if v.IsNil() { - v.Set(reflect.New(v.Type().Elem())) - } - v = v.Elem() - continue - } - break - } - v = v.Field(num) - } - return v -} - -const ( - // 400,000 decode operations is ~500kb of dense object declarations, or - // ~5kb of dense object declarations with 10000% alias expansion - alias_ratio_range_low = 400000 - - // 4,000,000 decode operations is ~5MB of dense object declarations, or - // ~4.5MB of dense object declarations with 10% alias expansion - alias_ratio_range_high = 4000000 - - // alias_ratio_range is the range over which we scale allowed alias ratios - alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low) -) - -func allowedAliasRatio(decodeCount int) float64 { - switch { - case decodeCount <= alias_ratio_range_low: - // allow 99% to come from alias expansion for small-to-medium documents - return 0.99 - case decodeCount >= alias_ratio_range_high: - // allow 10% to come from alias expansion for very large documents - return 0.10 - default: - // scale smoothly from 99% down to 10% over the range. - // this maps to 396,000 - 400,000 allowed alias-driven decodes over the range. - // 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps). - return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range) - } -} - -func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) { - d.decodeCount++ - if d.aliasDepth > 0 { - d.aliasCount++ - } - if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) { - failf("document contains excessive aliasing") - } - if out.Type() == nodeType { - out.Set(reflect.ValueOf(n).Elem()) - return true - } - switch n.Kind { - case DocumentNode: - return d.document(n, out) - case AliasNode: - return d.alias(n, out) - } - out, unmarshaled, good := d.prepare(n, out) - if unmarshaled { - return good - } - switch n.Kind { - case ScalarNode: - good = d.scalar(n, out) - case MappingNode: - good = d.mapping(n, out) - case SequenceNode: - good = d.sequence(n, out) - case 0: - if n.IsZero() { - return d.null(out) - } - fallthrough - default: - failf("cannot decode node with unknown kind %d", n.Kind) - } - return good -} - -func (d *decoder) document(n *Node, out reflect.Value) (good bool) { - if len(n.Content) == 1 { - d.doc = n - d.unmarshal(n.Content[0], out) - return true - } - return false -} - -func (d *decoder) alias(n *Node, out reflect.Value) (good bool) { - if d.aliases[n] { - // TODO this could actually be allowed in some circumstances. - failf("anchor '%s' value contains itself", n.Value) - } - d.aliases[n] = true - d.aliasDepth++ - good = d.unmarshal(n.Alias, out) - d.aliasDepth-- - delete(d.aliases, n) - return good -} - -var zeroValue reflect.Value - -func resetMap(out reflect.Value) { - for _, k := range out.MapKeys() { - out.SetMapIndex(k, zeroValue) - } -} - -func (d *decoder) null(out reflect.Value) bool { - if out.CanAddr() { - switch out.Kind() { - case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: - out.Set(reflect.Zero(out.Type())) - return true - } - } - return false -} - -func (d *decoder) scalar(n *Node, out reflect.Value) bool { - var tag string - var resolved interface{} - if n.indicatedString() { - tag = strTag - resolved = n.Value - } else { - tag, resolved = resolve(n.Tag, n.Value) - if tag == binaryTag { - data, err := base64.StdEncoding.DecodeString(resolved.(string)) - if err != nil { - failf("!!binary value contains invalid base64 data") - } - resolved = string(data) - } - } - if resolved == nil { - return d.null(out) - } - if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { - // We've resolved to exactly the type we want, so use that. - out.Set(resolvedv) - return true - } - // Perhaps we can use the value as a TextUnmarshaler to - // set its value. - if out.CanAddr() { - u, ok := out.Addr().Interface().(encoding.TextUnmarshaler) - if ok { - var text []byte - if tag == binaryTag { - text = []byte(resolved.(string)) - } else { - // We let any value be unmarshaled into TextUnmarshaler. - // That might be more lax than we'd like, but the - // TextUnmarshaler itself should bowl out any dubious values. - text = []byte(n.Value) - } - err := u.UnmarshalText(text) - if err != nil { - fail(err) - } - return true - } - } - switch out.Kind() { - case reflect.String: - if tag == binaryTag { - out.SetString(resolved.(string)) - return true - } - out.SetString(n.Value) - return true - case reflect.Interface: - out.Set(reflect.ValueOf(resolved)) - return true - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - // This used to work in v2, but it's very unfriendly. - isDuration := out.Type() == durationType - - switch resolved := resolved.(type) { - case int: - if !isDuration && !out.OverflowInt(int64(resolved)) { - out.SetInt(int64(resolved)) - return true - } - case int64: - if !isDuration && !out.OverflowInt(resolved) { - out.SetInt(resolved) - return true - } - case uint64: - if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { - out.SetInt(int64(resolved)) - return true - } - case float64: - if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { - out.SetInt(int64(resolved)) - return true - } - case string: - if out.Type() == durationType { - d, err := time.ParseDuration(resolved) - if err == nil { - out.SetInt(int64(d)) - return true - } - } - } - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - switch resolved := resolved.(type) { - case int: - if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { - out.SetUint(uint64(resolved)) - return true - } - case int64: - if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { - out.SetUint(uint64(resolved)) - return true - } - case uint64: - if !out.OverflowUint(uint64(resolved)) { - out.SetUint(uint64(resolved)) - return true - } - case float64: - if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) { - out.SetUint(uint64(resolved)) - return true - } - } - case reflect.Bool: - switch resolved := resolved.(type) { - case bool: - out.SetBool(resolved) - return true - case string: - // This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html). - // It only works if explicitly attempting to unmarshal into a typed bool value. - switch resolved { - case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON": - out.SetBool(true) - return true - case "n", "N", "no", "No", "NO", "off", "Off", "OFF": - out.SetBool(false) - return true - } - } - case reflect.Float32, reflect.Float64: - switch resolved := resolved.(type) { - case int: - out.SetFloat(float64(resolved)) - return true - case int64: - out.SetFloat(float64(resolved)) - return true - case uint64: - out.SetFloat(float64(resolved)) - return true - case float64: - out.SetFloat(resolved) - return true - } - case reflect.Struct: - if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { - out.Set(resolvedv) - return true - } - case reflect.Ptr: - panic("yaml internal error: please report the issue") - } - d.terror(n, tag, out) - return false -} - -func settableValueOf(i interface{}) reflect.Value { - v := reflect.ValueOf(i) - sv := reflect.New(v.Type()).Elem() - sv.Set(v) - return sv -} - -func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) { - l := len(n.Content) - - var iface reflect.Value - switch out.Kind() { - case reflect.Slice: - out.Set(reflect.MakeSlice(out.Type(), l, l)) - case reflect.Array: - if l != out.Len() { - failf("invalid array: want %d elements but got %d", out.Len(), l) - } - case reflect.Interface: - // No type hints. Will have to use a generic sequence. - iface = out - out = settableValueOf(make([]interface{}, l)) - default: - d.terror(n, seqTag, out) - return false - } - et := out.Type().Elem() - - j := 0 - for i := 0; i < l; i++ { - e := reflect.New(et).Elem() - if ok := d.unmarshal(n.Content[i], e); ok { - out.Index(j).Set(e) - j++ - } - } - if out.Kind() != reflect.Array { - out.Set(out.Slice(0, j)) - } - if iface.IsValid() { - iface.Set(out) - } - return true -} - -func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) { - l := len(n.Content) - if d.uniqueKeys { - nerrs := len(d.terrors) - for i := 0; i < l; i += 2 { - ni := n.Content[i] - for j := i + 2; j < l; j += 2 { - nj := n.Content[j] - if ni.Kind == nj.Kind && ni.Value == nj.Value { - d.terrors = append(d.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line)) - } - } - } - if len(d.terrors) > nerrs { - return false - } - } - switch out.Kind() { - case reflect.Struct: - return d.mappingStruct(n, out) - case reflect.Map: - // okay - case reflect.Interface: - iface := out - if isStringMap(n) { - out = reflect.MakeMap(d.stringMapType) - } else { - out = reflect.MakeMap(d.generalMapType) - } - iface.Set(out) - default: - d.terror(n, mapTag, out) - return false - } - - outt := out.Type() - kt := outt.Key() - et := outt.Elem() - - stringMapType := d.stringMapType - generalMapType := d.generalMapType - if outt.Elem() == ifaceType { - if outt.Key().Kind() == reflect.String { - d.stringMapType = outt - } else if outt.Key() == ifaceType { - d.generalMapType = outt - } - } - - mergedFields := d.mergedFields - d.mergedFields = nil - - var mergeNode *Node - - mapIsNew := false - if out.IsNil() { - out.Set(reflect.MakeMap(outt)) - mapIsNew = true - } - for i := 0; i < l; i += 2 { - if isMerge(n.Content[i]) { - mergeNode = n.Content[i+1] - continue - } - k := reflect.New(kt).Elem() - if d.unmarshal(n.Content[i], k) { - if mergedFields != nil { - ki := k.Interface() - if mergedFields[ki] { - continue - } - mergedFields[ki] = true - } - kkind := k.Kind() - if kkind == reflect.Interface { - kkind = k.Elem().Kind() - } - if kkind == reflect.Map || kkind == reflect.Slice { - failf("invalid map key: %#v", k.Interface()) - } - e := reflect.New(et).Elem() - if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) { - out.SetMapIndex(k, e) - } - } - } - - d.mergedFields = mergedFields - if mergeNode != nil { - d.merge(n, mergeNode, out) - } - - d.stringMapType = stringMapType - d.generalMapType = generalMapType - return true -} - -func isStringMap(n *Node) bool { - if n.Kind != MappingNode { - return false - } - l := len(n.Content) - for i := 0; i < l; i += 2 { - shortTag := n.Content[i].ShortTag() - if shortTag != strTag && shortTag != mergeTag { - return false - } - } - return true -} - -func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) { - sinfo, err := getStructInfo(out.Type()) - if err != nil { - panic(err) - } - - var inlineMap reflect.Value - var elemType reflect.Type - if sinfo.InlineMap != -1 { - inlineMap = out.Field(sinfo.InlineMap) - elemType = inlineMap.Type().Elem() - } - - for _, index := range sinfo.InlineUnmarshalers { - field := d.fieldByIndex(n, out, index) - d.prepare(n, field) - } - - mergedFields := d.mergedFields - d.mergedFields = nil - var mergeNode *Node - var doneFields []bool - if d.uniqueKeys { - doneFields = make([]bool, len(sinfo.FieldsList)) - } - name := settableValueOf("") - l := len(n.Content) - for i := 0; i < l; i += 2 { - ni := n.Content[i] - if isMerge(ni) { - mergeNode = n.Content[i+1] - continue - } - if !d.unmarshal(ni, name) { - continue - } - sname := name.String() - if mergedFields != nil { - if mergedFields[sname] { - continue - } - mergedFields[sname] = true - } - if info, ok := sinfo.FieldsMap[sname]; ok { - if d.uniqueKeys { - if doneFields[info.Id] { - d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type())) - continue - } - doneFields[info.Id] = true - } - var field reflect.Value - if info.Inline == nil { - field = out.Field(info.Num) - } else { - field = d.fieldByIndex(n, out, info.Inline) - } - d.unmarshal(n.Content[i+1], field) - } else if sinfo.InlineMap != -1 { - if inlineMap.IsNil() { - inlineMap.Set(reflect.MakeMap(inlineMap.Type())) - } - value := reflect.New(elemType).Elem() - d.unmarshal(n.Content[i+1], value) - inlineMap.SetMapIndex(name, value) - } else if d.knownFields { - d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type())) - } - } - - d.mergedFields = mergedFields - if mergeNode != nil { - d.merge(n, mergeNode, out) - } - return true -} - -func failWantMap() { - failf("map merge requires map or sequence of maps as the value") -} - -func (d *decoder) merge(parent *Node, merge *Node, out reflect.Value) { - mergedFields := d.mergedFields - if mergedFields == nil { - d.mergedFields = make(map[interface{}]bool) - for i := 0; i < len(parent.Content); i += 2 { - k := reflect.New(ifaceType).Elem() - if d.unmarshal(parent.Content[i], k) { - d.mergedFields[k.Interface()] = true - } - } - } - - switch merge.Kind { - case MappingNode: - d.unmarshal(merge, out) - case AliasNode: - if merge.Alias != nil && merge.Alias.Kind != MappingNode { - failWantMap() - } - d.unmarshal(merge, out) - case SequenceNode: - for i := 0; i < len(merge.Content); i++ { - ni := merge.Content[i] - if ni.Kind == AliasNode { - if ni.Alias != nil && ni.Alias.Kind != MappingNode { - failWantMap() - } - } else if ni.Kind != MappingNode { - failWantMap() - } - d.unmarshal(ni, out) - } - default: - failWantMap() - } - - d.mergedFields = mergedFields -} - -func isMerge(n *Node) bool { - return n.Kind == ScalarNode && n.Value == "<<" && (n.Tag == "" || n.Tag == "!" || shortTag(n.Tag) == mergeTag) -} diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/decode_test.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/decode_test.go deleted file mode 100644 index 0364b0b..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/decode_test.go +++ /dev/null @@ -1,1771 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yaml_test - -import ( - "bytes" - "errors" - "fmt" - "io" - "math" - "reflect" - "strings" - "time" - - . "gopkg.in/check.v1" - "gopkg.in/yaml.v3" -) - -var unmarshalIntTest = 123 - -var unmarshalTests = []struct { - data string - value interface{} -}{ - { - "", - (*struct{})(nil), - }, - { - "{}", &struct{}{}, - }, { - "v: hi", - map[string]string{"v": "hi"}, - }, { - "v: hi", map[string]interface{}{"v": "hi"}, - }, { - "v: true", - map[string]string{"v": "true"}, - }, { - "v: true", - map[string]interface{}{"v": true}, - }, { - "v: 10", - map[string]interface{}{"v": 10}, - }, { - "v: 0b10", - map[string]interface{}{"v": 2}, - }, { - "v: 0xA", - map[string]interface{}{"v": 10}, - }, { - "v: 4294967296", - map[string]int64{"v": 4294967296}, - }, { - "v: 0.1", - map[string]interface{}{"v": 0.1}, - }, { - "v: .1", - map[string]interface{}{"v": 0.1}, - }, { - "v: .Inf", - map[string]interface{}{"v": math.Inf(+1)}, - }, { - "v: -.Inf", - map[string]interface{}{"v": math.Inf(-1)}, - }, { - "v: -10", - map[string]interface{}{"v": -10}, - }, { - "v: -.1", - map[string]interface{}{"v": -0.1}, - }, - - // Simple values. - { - "123", - &unmarshalIntTest, - }, - - // Floats from spec - { - "canonical: 6.8523e+5", - map[string]interface{}{"canonical": 6.8523e+5}, - }, { - "expo: 685.230_15e+03", - map[string]interface{}{"expo": 685.23015e+03}, - }, { - "fixed: 685_230.15", - map[string]interface{}{"fixed": 685230.15}, - }, { - "neginf: -.inf", - map[string]interface{}{"neginf": math.Inf(-1)}, - }, { - "fixed: 685_230.15", - map[string]float64{"fixed": 685230.15}, - }, - //{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported - //{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails. - - // Bools are per 1.2 spec. - { - "canonical: true", - map[string]interface{}{"canonical": true}, - }, { - "canonical: false", - map[string]interface{}{"canonical": false}, - }, { - "bool: True", - map[string]interface{}{"bool": true}, - }, { - "bool: False", - map[string]interface{}{"bool": false}, - }, { - "bool: TRUE", - map[string]interface{}{"bool": true}, - }, { - "bool: FALSE", - map[string]interface{}{"bool": false}, - }, - // For backwards compatibility with 1.1, decoding old strings into typed values still works. - { - "option: on", - map[string]bool{"option": true}, - }, { - "option: y", - map[string]bool{"option": true}, - }, { - "option: Off", - map[string]bool{"option": false}, - }, { - "option: No", - map[string]bool{"option": false}, - }, { - "option: other", - map[string]bool{}, - }, - // Ints from spec - { - "canonical: 685230", - map[string]interface{}{"canonical": 685230}, - }, { - "decimal: +685_230", - map[string]interface{}{"decimal": 685230}, - }, { - "octal: 02472256", - map[string]interface{}{"octal": 685230}, - }, { - "octal: -02472256", - map[string]interface{}{"octal": -685230}, - }, { - "octal: 0o2472256", - map[string]interface{}{"octal": 685230}, - }, { - "octal: -0o2472256", - map[string]interface{}{"octal": -685230}, - }, { - "hexa: 0x_0A_74_AE", - map[string]interface{}{"hexa": 685230}, - }, { - "bin: 0b1010_0111_0100_1010_1110", - map[string]interface{}{"bin": 685230}, - }, { - "bin: -0b101010", - map[string]interface{}{"bin": -42}, - }, { - "bin: -0b1000000000000000000000000000000000000000000000000000000000000000", - map[string]interface{}{"bin": -9223372036854775808}, - }, { - "decimal: +685_230", - map[string]int{"decimal": 685230}, - }, - - //{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported - - // Nulls from spec - { - "empty:", - map[string]interface{}{"empty": nil}, - }, { - "canonical: ~", - map[string]interface{}{"canonical": nil}, - }, { - "english: null", - map[string]interface{}{"english": nil}, - }, { - "~: null key", - map[interface{}]string{nil: "null key"}, - }, { - "empty:", - map[string]*bool{"empty": nil}, - }, - - // Flow sequence - { - "seq: [A,B]", - map[string]interface{}{"seq": []interface{}{"A", "B"}}, - }, { - "seq: [A,B,C,]", - map[string][]string{"seq": []string{"A", "B", "C"}}, - }, { - "seq: [A,1,C]", - map[string][]string{"seq": []string{"A", "1", "C"}}, - }, { - "seq: [A,1,C]", - map[string][]int{"seq": []int{1}}, - }, { - "seq: [A,1,C]", - map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, - }, - // Block sequence - { - "seq:\n - A\n - B", - map[string]interface{}{"seq": []interface{}{"A", "B"}}, - }, { - "seq:\n - A\n - B\n - C", - map[string][]string{"seq": []string{"A", "B", "C"}}, - }, { - "seq:\n - A\n - 1\n - C", - map[string][]string{"seq": []string{"A", "1", "C"}}, - }, { - "seq:\n - A\n - 1\n - C", - map[string][]int{"seq": []int{1}}, - }, { - "seq:\n - A\n - 1\n - C", - map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, - }, - - // Literal block scalar - { - "scalar: | # Comment\n\n literal\n\n \ttext\n\n", - map[string]string{"scalar": "\nliteral\n\n\ttext\n"}, - }, - - // Folded block scalar - { - "scalar: > # Comment\n\n folded\n line\n \n next\n line\n * one\n * two\n\n last\n line\n\n", - map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"}, - }, - - // Map inside interface with no type hints. - { - "a: {b: c}", - map[interface{}]interface{}{"a": map[string]interface{}{"b": "c"}}, - }, - // Non-string map inside interface with no type hints. - { - "a: {b: c, 1: d}", - map[interface{}]interface{}{"a": map[interface{}]interface{}{"b": "c", 1: "d"}}, - }, - - // Structs and type conversions. - { - "hello: world", - &struct{ Hello string }{"world"}, - }, { - "a: {b: c}", - &struct{ A struct{ B string } }{struct{ B string }{"c"}}, - }, { - "a: {b: c}", - &struct{ A *struct{ B string } }{&struct{ B string }{"c"}}, - }, { - "a: 'null'", - &struct{ A *unmarshalerType }{&unmarshalerType{"null"}}, - }, { - "a: {b: c}", - &struct{ A map[string]string }{map[string]string{"b": "c"}}, - }, { - "a: {b: c}", - &struct{ A *map[string]string }{&map[string]string{"b": "c"}}, - }, { - "a:", - &struct{ A map[string]string }{}, - }, { - "a: 1", - &struct{ A int }{1}, - }, { - "a: 1", - &struct{ A float64 }{1}, - }, { - "a: 1.0", - &struct{ A int }{1}, - }, { - "a: 1.0", - &struct{ A uint }{1}, - }, { - "a: [1, 2]", - &struct{ A []int }{[]int{1, 2}}, - }, { - "a: [1, 2]", - &struct{ A [2]int }{[2]int{1, 2}}, - }, { - "a: 1", - &struct{ B int }{0}, - }, { - "a: 1", - &struct { - B int "a" - }{1}, - }, { - // Some limited backwards compatibility with the 1.1 spec. - "a: YES", - &struct{ A bool }{true}, - }, - - // Some cross type conversions - { - "v: 42", - map[string]uint{"v": 42}, - }, { - "v: -42", - map[string]uint{}, - }, { - "v: 4294967296", - map[string]uint64{"v": 4294967296}, - }, { - "v: -4294967296", - map[string]uint64{}, - }, - - // int - { - "int_max: 2147483647", - map[string]int{"int_max": math.MaxInt32}, - }, - { - "int_min: -2147483648", - map[string]int{"int_min": math.MinInt32}, - }, - { - "int_overflow: 9223372036854775808", // math.MaxInt64 + 1 - map[string]int{}, - }, - - // int64 - { - "int64_max: 9223372036854775807", - map[string]int64{"int64_max": math.MaxInt64}, - }, - { - "int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111", - map[string]int64{"int64_max_base2": math.MaxInt64}, - }, - { - "int64_min: -9223372036854775808", - map[string]int64{"int64_min": math.MinInt64}, - }, - { - "int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111", - map[string]int64{"int64_neg_base2": -math.MaxInt64}, - }, - { - "int64_overflow: 9223372036854775808", // math.MaxInt64 + 1 - map[string]int64{}, - }, - - // uint - { - "uint_min: 0", - map[string]uint{"uint_min": 0}, - }, - { - "uint_max: 4294967295", - map[string]uint{"uint_max": math.MaxUint32}, - }, - { - "uint_underflow: -1", - map[string]uint{}, - }, - - // uint64 - { - "uint64_min: 0", - map[string]uint{"uint64_min": 0}, - }, - { - "uint64_max: 18446744073709551615", - map[string]uint64{"uint64_max": math.MaxUint64}, - }, - { - "uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111", - map[string]uint64{"uint64_max_base2": math.MaxUint64}, - }, - { - "uint64_maxint64: 9223372036854775807", - map[string]uint64{"uint64_maxint64": math.MaxInt64}, - }, - { - "uint64_underflow: -1", - map[string]uint64{}, - }, - - // float32 - { - "float32_max: 3.40282346638528859811704183484516925440e+38", - map[string]float32{"float32_max": math.MaxFloat32}, - }, - { - "float32_nonzero: 1.401298464324817070923729583289916131280e-45", - map[string]float32{"float32_nonzero": math.SmallestNonzeroFloat32}, - }, - { - "float32_maxuint64: 18446744073709551615", - map[string]float32{"float32_maxuint64": float32(math.MaxUint64)}, - }, - { - "float32_maxuint64+1: 18446744073709551616", - map[string]float32{"float32_maxuint64+1": float32(math.MaxUint64 + 1)}, - }, - - // float64 - { - "float64_max: 1.797693134862315708145274237317043567981e+308", - map[string]float64{"float64_max": math.MaxFloat64}, - }, - { - "float64_nonzero: 4.940656458412465441765687928682213723651e-324", - map[string]float64{"float64_nonzero": math.SmallestNonzeroFloat64}, - }, - { - "float64_maxuint64: 18446744073709551615", - map[string]float64{"float64_maxuint64": float64(math.MaxUint64)}, - }, - { - "float64_maxuint64+1: 18446744073709551616", - map[string]float64{"float64_maxuint64+1": float64(math.MaxUint64 + 1)}, - }, - - // Overflow cases. - { - "v: 4294967297", - map[string]int32{}, - }, { - "v: 128", - map[string]int8{}, - }, - - // Quoted values. - { - "'1': '\"2\"'", - map[interface{}]interface{}{"1": "\"2\""}, - }, { - "v:\n- A\n- 'B\n\n C'\n", - map[string][]string{"v": []string{"A", "B\nC"}}, - }, - - // Explicit tags. - { - "v: !!float '1.1'", - map[string]interface{}{"v": 1.1}, - }, { - "v: !!float 0", - map[string]interface{}{"v": float64(0)}, - }, { - "v: !!float -1", - map[string]interface{}{"v": float64(-1)}, - }, { - "v: !!null ''", - map[string]interface{}{"v": nil}, - }, { - "%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'", - map[string]interface{}{"v": 1}, - }, - - // Non-specific tag (Issue #75) - { - "v: ! test", - map[string]interface{}{"v": "test"}, - }, - - // Anchors and aliases. - { - "a: &x 1\nb: &y 2\nc: *x\nd: *y\n", - &struct{ A, B, C, D int }{1, 2, 1, 2}, - }, { - "a: &a {c: 1}\nb: *a", - &struct { - A, B struct { - C int - } - }{struct{ C int }{1}, struct{ C int }{1}}, - }, { - "a: &a [1, 2]\nb: *a", - &struct{ B []int }{[]int{1, 2}}, - }, - - // Bug #1133337 - { - "foo: ''", - map[string]*string{"foo": new(string)}, - }, { - "foo: null", - map[string]*string{"foo": nil}, - }, { - "foo: null", - map[string]string{"foo": ""}, - }, { - "foo: null", - map[string]interface{}{"foo": nil}, - }, - - // Support for ~ - { - "foo: ~", - map[string]*string{"foo": nil}, - }, { - "foo: ~", - map[string]string{"foo": ""}, - }, { - "foo: ~", - map[string]interface{}{"foo": nil}, - }, - - // Ignored field - { - "a: 1\nb: 2\n", - &struct { - A int - B int "-" - }{1, 0}, - }, - - // Bug #1191981 - { - "" + - "%YAML 1.1\n" + - "--- !!str\n" + - `"Generic line break (no glyph)\n\` + "\n" + - ` Generic line break (glyphed)\n\` + "\n" + - ` Line separator\u2028\` + "\n" + - ` Paragraph separator\u2029"` + "\n", - "" + - "Generic line break (no glyph)\n" + - "Generic line break (glyphed)\n" + - "Line separator\u2028Paragraph separator\u2029", - }, - - // Struct inlining - { - "a: 1\nb: 2\nc: 3\n", - &struct { - A int - C inlineB `yaml:",inline"` - }{1, inlineB{2, inlineC{3}}}, - }, - - // Struct inlining as a pointer. - { - "a: 1\nb: 2\nc: 3\n", - &struct { - A int - C *inlineB `yaml:",inline"` - }{1, &inlineB{2, inlineC{3}}}, - }, { - "a: 1\n", - &struct { - A int - C *inlineB `yaml:",inline"` - }{1, nil}, - }, { - "a: 1\nc: 3\nd: 4\n", - &struct { - A int - C *inlineD `yaml:",inline"` - }{1, &inlineD{&inlineC{3}, 4}}, - }, - - // Map inlining - { - "a: 1\nb: 2\nc: 3\n", - &struct { - A int - C map[string]int `yaml:",inline"` - }{1, map[string]int{"b": 2, "c": 3}}, - }, - - // bug 1243827 - { - "a: -b_c", - map[string]interface{}{"a": "-b_c"}, - }, - { - "a: +b_c", - map[string]interface{}{"a": "+b_c"}, - }, - { - "a: 50cent_of_dollar", - map[string]interface{}{"a": "50cent_of_dollar"}, - }, - - // issue #295 (allow scalars with colons in flow mappings and sequences) - { - "a: {b: https://github.com/go-yaml/yaml}", - map[string]interface{}{"a": map[string]interface{}{ - "b": "https://github.com/go-yaml/yaml", - }}, - }, - { - "a: [https://github.com/go-yaml/yaml]", - map[string]interface{}{"a": []interface{}{"https://github.com/go-yaml/yaml"}}, - }, - - // Duration - { - "a: 3s", - map[string]time.Duration{"a": 3 * time.Second}, - }, - - // Issue #24. - { - "a: <foo>", - map[string]string{"a": "<foo>"}, - }, - - // Base 60 floats are obsolete and unsupported. - { - "a: 1:1\n", - map[string]string{"a": "1:1"}, - }, - - // Binary data. - { - "a: !!binary gIGC\n", - map[string]string{"a": "\x80\x81\x82"}, - }, { - "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n", - map[string]string{"a": strings.Repeat("\x90", 54)}, - }, { - "a: !!binary |\n " + strings.Repeat("A", 70) + "\n ==\n", - map[string]string{"a": strings.Repeat("\x00", 52)}, - }, - - // Issue #39. - { - "a:\n b:\n c: d\n", - map[string]struct{ B interface{} }{"a": {map[string]interface{}{"c": "d"}}}, - }, - - // Custom map type. - { - "a: {b: c}", - M{"a": M{"b": "c"}}, - }, - - // Support encoding.TextUnmarshaler. - { - "a: 1.2.3.4\n", - map[string]textUnmarshaler{"a": textUnmarshaler{S: "1.2.3.4"}}, - }, - { - "a: 2015-02-24T18:19:39Z\n", - map[string]textUnmarshaler{"a": textUnmarshaler{"2015-02-24T18:19:39Z"}}, - }, - - // Timestamps - { - // Date only. - "a: 2015-01-01\n", - map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, - }, - { - // RFC3339 - "a: 2015-02-24T18:19:39.12Z\n", - map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, .12e9, time.UTC)}, - }, - { - // RFC3339 with short dates. - "a: 2015-2-3T3:4:5Z", - map[string]time.Time{"a": time.Date(2015, 2, 3, 3, 4, 5, 0, time.UTC)}, - }, - { - // ISO8601 lower case t - "a: 2015-02-24t18:19:39Z\n", - map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)}, - }, - { - // space separate, no time zone - "a: 2015-02-24 18:19:39\n", - map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)}, - }, - // Some cases not currently handled. Uncomment these when - // the code is fixed. - // { - // // space separated with time zone - // "a: 2001-12-14 21:59:43.10 -5", - // map[string]interface{}{"a": time.Date(2001, 12, 14, 21, 59, 43, .1e9, time.UTC)}, - // }, - // { - // // arbitrary whitespace between fields - // "a: 2001-12-14 \t\t \t21:59:43.10 \t Z", - // map[string]interface{}{"a": time.Date(2001, 12, 14, 21, 59, 43, .1e9, time.UTC)}, - // }, - { - // explicit string tag - "a: !!str 2015-01-01", - map[string]interface{}{"a": "2015-01-01"}, - }, - { - // explicit timestamp tag on quoted string - "a: !!timestamp \"2015-01-01\"", - map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, - }, - { - // explicit timestamp tag on unquoted string - "a: !!timestamp 2015-01-01", - map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, - }, - { - // quoted string that's a valid timestamp - "a: \"2015-01-01\"", - map[string]interface{}{"a": "2015-01-01"}, - }, - { - // explicit timestamp tag into interface. - "a: !!timestamp \"2015-01-01\"", - map[string]interface{}{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, - }, - { - // implicit timestamp tag into interface. - "a: 2015-01-01", - map[string]interface{}{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, - }, - - // Encode empty lists as zero-length slices. - { - "a: []", - &struct{ A []int }{[]int{}}, - }, - - // UTF-16-LE - { - "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n\x00", - M{"ñoño": "very yes"}, - }, - // UTF-16-LE with surrogate. - { - "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \x00=\xd8\xd4\xdf\n\x00", - M{"ñoño": "very yes 🟔"}, - }, - - // UTF-16-BE - { - "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n", - M{"ñoño": "very yes"}, - }, - // UTF-16-BE with surrogate. - { - "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \xd8=\xdf\xd4\x00\n", - M{"ñoño": "very yes 🟔"}, - }, - - // This *is* in fact a float number, per the spec. #171 was a mistake. - { - "a: 123456e1\n", - M{"a": 123456e1}, - }, { - "a: 123456E1\n", - M{"a": 123456e1}, - }, - // yaml-test-suite 3GZX: Spec Example 7.1. Alias Nodes - { - "First occurrence: &anchor Foo\nSecond occurrence: *anchor\nOverride anchor: &anchor Bar\nReuse anchor: *anchor\n", - map[string]interface{}{ - "First occurrence": "Foo", - "Second occurrence": "Foo", - "Override anchor": "Bar", - "Reuse anchor": "Bar", - }, - }, - // Single document with garbage following it. - { - "---\nhello\n...\n}not yaml", - "hello", - }, - - // Comment scan exhausting the input buffer (issue #469). - { - "true\n#" + strings.Repeat(" ", 512*3), - "true", - }, { - "true #" + strings.Repeat(" ", 512*3), - "true", - }, - - // CRLF - { - "a: b\r\nc:\r\n- d\r\n- e\r\n", - map[string]interface{}{ - "a": "b", - "c": []interface{}{"d", "e"}, - }, - }, -} - -type M map[string]interface{} - -type inlineB struct { - B int - inlineC `yaml:",inline"` -} - -type inlineC struct { - C int -} - -type inlineD struct { - C *inlineC `yaml:",inline"` - D int -} - -func (s *S) TestUnmarshal(c *C) { - for i, item := range unmarshalTests { - c.Logf("test %d: %q", i, item.data) - t := reflect.ValueOf(item.value).Type() - value := reflect.New(t) - err := yaml.Unmarshal([]byte(item.data), value.Interface()) - if _, ok := err.(*yaml.TypeError); !ok { - c.Assert(err, IsNil) - } - c.Assert(value.Elem().Interface(), DeepEquals, item.value, Commentf("error: %v", err)) - } -} - -func (s *S) TestUnmarshalFullTimestamp(c *C) { - // Full timestamp in same format as encoded. This is confirmed to be - // properly decoded by Python as a timestamp as well. - var str = "2015-02-24T18:19:39.123456789-03:00" - var t interface{} - err := yaml.Unmarshal([]byte(str), &t) - c.Assert(err, IsNil) - c.Assert(t, Equals, time.Date(2015, 2, 24, 18, 19, 39, 123456789, t.(time.Time).Location())) - c.Assert(t.(time.Time).In(time.UTC), Equals, time.Date(2015, 2, 24, 21, 19, 39, 123456789, time.UTC)) -} - -func (s *S) TestDecoderSingleDocument(c *C) { - // Test that Decoder.Decode works as expected on - // all the unmarshal tests. - for i, item := range unmarshalTests { - c.Logf("test %d: %q", i, item.data) - if item.data == "" { - // Behaviour differs when there's no YAML. - continue - } - t := reflect.ValueOf(item.value).Type() - value := reflect.New(t) - err := yaml.NewDecoder(strings.NewReader(item.data)).Decode(value.Interface()) - if _, ok := err.(*yaml.TypeError); !ok { - c.Assert(err, IsNil) - } - c.Assert(value.Elem().Interface(), DeepEquals, item.value) - } -} - -var decoderTests = []struct { - data string - values []interface{} -}{{ - "", - nil, -}, { - "a: b", - []interface{}{ - map[string]interface{}{"a": "b"}, - }, -}, { - "---\na: b\n...\n", - []interface{}{ - map[string]interface{}{"a": "b"}, - }, -}, { - "---\n'hello'\n...\n---\ngoodbye\n...\n", - []interface{}{ - "hello", - "goodbye", - }, -}} - -func (s *S) TestDecoder(c *C) { - for i, item := range decoderTests { - c.Logf("test %d: %q", i, item.data) - var values []interface{} - dec := yaml.NewDecoder(strings.NewReader(item.data)) - for { - var value interface{} - err := dec.Decode(&value) - if err == io.EOF { - break - } - c.Assert(err, IsNil) - values = append(values, value) - } - c.Assert(values, DeepEquals, item.values) - } -} - -type errReader struct{} - -func (errReader) Read([]byte) (int, error) { - return 0, errors.New("some read error") -} - -func (s *S) TestDecoderReadError(c *C) { - err := yaml.NewDecoder(errReader{}).Decode(&struct{}{}) - c.Assert(err, ErrorMatches, `yaml: input error: some read error`) -} - -func (s *S) TestUnmarshalNaN(c *C) { - value := map[string]interface{}{} - err := yaml.Unmarshal([]byte("notanum: .NaN"), &value) - c.Assert(err, IsNil) - c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true) -} - -func (s *S) TestUnmarshalDurationInt(c *C) { - // Don't accept plain ints as durations as it's unclear (issue #200). - var d time.Duration - err := yaml.Unmarshal([]byte("123"), &d) - c.Assert(err, ErrorMatches, "(?s).* line 1: cannot unmarshal !!int `123` into time.Duration") -} - -var unmarshalErrorTests = []struct { - data, error string -}{ - {"v: !!float 'error'", "yaml: cannot decode !!str `error` as a !!float"}, - {"v: [A,", "yaml: line 1: did not find expected node content"}, - {"v:\n- [A,", "yaml: line 2: did not find expected node content"}, - {"a:\n- b: *,", "yaml: line 2: did not find expected alphabetic or numeric character"}, - {"a: *b\n", "yaml: unknown anchor 'b' referenced"}, - {"a: &a\n b: *a\n", "yaml: anchor 'a' value contains itself"}, - {"value: -", "yaml: block sequence entries are not allowed in this context"}, - {"a: !!binary ==", "yaml: !!binary value contains invalid base64 data"}, - {"{[.]}", `yaml: invalid map key: \[\]interface \{\}\{"\."\}`}, - {"{{.}}", `yaml: invalid map key: map\[string]interface \{\}\{".":interface \{\}\(nil\)\}`}, - {"b: *a\na: &a {c: 1}", `yaml: unknown anchor 'a' referenced`}, - {"%TAG !%79! tag:yaml.org,2002:\n---\nv: !%79!int '1'", "yaml: did not find expected whitespace"}, - {"a:\n 1:\nb\n 2:", ".*could not find expected ':'"}, - {"a: 1\nb: 2\nc 2\nd: 3\n", "^yaml: line 3: could not find expected ':'$"}, - {"#\n-\n{", "yaml: line 3: could not find expected ':'"}, // Issue #665 - {"0: [:!00 \xef", "yaml: incomplete UTF-8 octet sequence"}, // Issue #666 - { - "a: &a [00,00,00,00,00,00,00,00,00]\n" + - "b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]\n" + - "c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]\n" + - "d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]\n" + - "e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]\n" + - "f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]\n" + - "g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]\n" + - "h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]\n" + - "i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]\n", - "yaml: document contains excessive aliasing", - }, -} - -func (s *S) TestUnmarshalErrors(c *C) { - for i, item := range unmarshalErrorTests { - c.Logf("test %d: %q", i, item.data) - var value interface{} - err := yaml.Unmarshal([]byte(item.data), &value) - c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value)) - } -} - -func (s *S) TestDecoderErrors(c *C) { - for _, item := range unmarshalErrorTests { - var value interface{} - err := yaml.NewDecoder(strings.NewReader(item.data)).Decode(&value) - c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value)) - } -} - -var unmarshalerTests = []struct { - data, tag string - value interface{} -}{ - {"_: {hi: there}", "!!map", map[string]interface{}{"hi": "there"}}, - {"_: [1,A]", "!!seq", []interface{}{1, "A"}}, - {"_: 10", "!!int", 10}, - {"_: null", "!!null", nil}, - {`_: BAR!`, "!!str", "BAR!"}, - {`_: "BAR!"`, "!!str", "BAR!"}, - {"_: !!foo 'BAR!'", "!!foo", "BAR!"}, - {`_: ""`, "!!str", ""}, -} - -var unmarshalerResult = map[int]error{} - -type unmarshalerType struct { - value interface{} -} - -func (o *unmarshalerType) UnmarshalYAML(value *yaml.Node) error { - if err := value.Decode(&o.value); err != nil { - return err - } - if i, ok := o.value.(int); ok { - if result, ok := unmarshalerResult[i]; ok { - return result - } - } - return nil -} - -type unmarshalerPointer struct { - Field *unmarshalerType "_" -} - -type unmarshalerValue struct { - Field unmarshalerType "_" -} - -type unmarshalerInlined struct { - Field *unmarshalerType "_" - Inlined unmarshalerType `yaml:",inline"` -} - -type unmarshalerInlinedTwice struct { - InlinedTwice unmarshalerInlined `yaml:",inline"` -} - -type obsoleteUnmarshalerType struct { - value interface{} -} - -func (o *obsoleteUnmarshalerType) UnmarshalYAML(unmarshal func(v interface{}) error) error { - if err := unmarshal(&o.value); err != nil { - return err - } - if i, ok := o.value.(int); ok { - if result, ok := unmarshalerResult[i]; ok { - return result - } - } - return nil -} - -type obsoleteUnmarshalerPointer struct { - Field *obsoleteUnmarshalerType "_" -} - -type obsoleteUnmarshalerValue struct { - Field obsoleteUnmarshalerType "_" -} - -func (s *S) TestUnmarshalerPointerField(c *C) { - for _, item := range unmarshalerTests { - obj := &unmarshalerPointer{} - err := yaml.Unmarshal([]byte(item.data), obj) - c.Assert(err, IsNil) - if item.value == nil { - c.Assert(obj.Field, IsNil) - } else { - c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) - c.Assert(obj.Field.value, DeepEquals, item.value) - } - } - for _, item := range unmarshalerTests { - obj := &obsoleteUnmarshalerPointer{} - err := yaml.Unmarshal([]byte(item.data), obj) - c.Assert(err, IsNil) - if item.value == nil { - c.Assert(obj.Field, IsNil) - } else { - c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) - c.Assert(obj.Field.value, DeepEquals, item.value) - } - } -} - -func (s *S) TestUnmarshalerValueField(c *C) { - for _, item := range unmarshalerTests { - obj := &obsoleteUnmarshalerValue{} - err := yaml.Unmarshal([]byte(item.data), obj) - c.Assert(err, IsNil) - c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) - c.Assert(obj.Field.value, DeepEquals, item.value) - } -} - -func (s *S) TestUnmarshalerInlinedField(c *C) { - obj := &unmarshalerInlined{} - err := yaml.Unmarshal([]byte("_: a\ninlined: b\n"), obj) - c.Assert(err, IsNil) - c.Assert(obj.Field, DeepEquals, &unmarshalerType{"a"}) - c.Assert(obj.Inlined, DeepEquals, unmarshalerType{map[string]interface{}{"_": "a", "inlined": "b"}}) - - twc := &unmarshalerInlinedTwice{} - err = yaml.Unmarshal([]byte("_: a\ninlined: b\n"), twc) - c.Assert(err, IsNil) - c.Assert(twc.InlinedTwice.Field, DeepEquals, &unmarshalerType{"a"}) - c.Assert(twc.InlinedTwice.Inlined, DeepEquals, unmarshalerType{map[string]interface{}{"_": "a", "inlined": "b"}}) -} - -func (s *S) TestUnmarshalerWholeDocument(c *C) { - obj := &obsoleteUnmarshalerType{} - err := yaml.Unmarshal([]byte(unmarshalerTests[0].data), obj) - c.Assert(err, IsNil) - value, ok := obj.value.(map[string]interface{}) - c.Assert(ok, Equals, true, Commentf("value: %#v", obj.value)) - c.Assert(value["_"], DeepEquals, unmarshalerTests[0].value) -} - -func (s *S) TestUnmarshalerTypeError(c *C) { - unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}} - unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}} - defer func() { - delete(unmarshalerResult, 2) - delete(unmarshalerResult, 4) - }() - - type T struct { - Before int - After int - M map[string]*unmarshalerType - } - var v T - data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}` - err := yaml.Unmarshal([]byte(data), &v) - c.Assert(err, ErrorMatches, ""+ - "yaml: unmarshal errors:\n"+ - " line 1: cannot unmarshal !!str `A` into int\n"+ - " foo\n"+ - " bar\n"+ - " line 1: cannot unmarshal !!str `B` into int") - c.Assert(v.M["abc"], NotNil) - c.Assert(v.M["def"], IsNil) - c.Assert(v.M["ghi"], NotNil) - c.Assert(v.M["jkl"], IsNil) - - c.Assert(v.M["abc"].value, Equals, 1) - c.Assert(v.M["ghi"].value, Equals, 3) -} - -func (s *S) TestObsoleteUnmarshalerTypeError(c *C) { - unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}} - unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}} - defer func() { - delete(unmarshalerResult, 2) - delete(unmarshalerResult, 4) - }() - - type T struct { - Before int - After int - M map[string]*obsoleteUnmarshalerType - } - var v T - data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}` - err := yaml.Unmarshal([]byte(data), &v) - c.Assert(err, ErrorMatches, ""+ - "yaml: unmarshal errors:\n"+ - " line 1: cannot unmarshal !!str `A` into int\n"+ - " foo\n"+ - " bar\n"+ - " line 1: cannot unmarshal !!str `B` into int") - c.Assert(v.M["abc"], NotNil) - c.Assert(v.M["def"], IsNil) - c.Assert(v.M["ghi"], NotNil) - c.Assert(v.M["jkl"], IsNil) - - c.Assert(v.M["abc"].value, Equals, 1) - c.Assert(v.M["ghi"].value, Equals, 3) -} - -type proxyTypeError struct{} - -func (v *proxyTypeError) UnmarshalYAML(node *yaml.Node) error { - var s string - var a int32 - var b int64 - if err := node.Decode(&s); err != nil { - panic(err) - } - if s == "a" { - if err := node.Decode(&b); err == nil { - panic("should have failed") - } - return node.Decode(&a) - } - if err := node.Decode(&a); err == nil { - panic("should have failed") - } - return node.Decode(&b) -} - -func (s *S) TestUnmarshalerTypeErrorProxying(c *C) { - type T struct { - Before int - After int - M map[string]*proxyTypeError - } - var v T - data := `{before: A, m: {abc: a, def: b}, after: B}` - err := yaml.Unmarshal([]byte(data), &v) - c.Assert(err, ErrorMatches, ""+ - "yaml: unmarshal errors:\n"+ - " line 1: cannot unmarshal !!str `A` into int\n"+ - " line 1: cannot unmarshal !!str `a` into int32\n"+ - " line 1: cannot unmarshal !!str `b` into int64\n"+ - " line 1: cannot unmarshal !!str `B` into int") -} - -type obsoleteProxyTypeError struct{} - -func (v *obsoleteProxyTypeError) UnmarshalYAML(unmarshal func(interface{}) error) error { - var s string - var a int32 - var b int64 - if err := unmarshal(&s); err != nil { - panic(err) - } - if s == "a" { - if err := unmarshal(&b); err == nil { - panic("should have failed") - } - return unmarshal(&a) - } - if err := unmarshal(&a); err == nil { - panic("should have failed") - } - return unmarshal(&b) -} - -func (s *S) TestObsoleteUnmarshalerTypeErrorProxying(c *C) { - type T struct { - Before int - After int - M map[string]*obsoleteProxyTypeError - } - var v T - data := `{before: A, m: {abc: a, def: b}, after: B}` - err := yaml.Unmarshal([]byte(data), &v) - c.Assert(err, ErrorMatches, ""+ - "yaml: unmarshal errors:\n"+ - " line 1: cannot unmarshal !!str `A` into int\n"+ - " line 1: cannot unmarshal !!str `a` into int32\n"+ - " line 1: cannot unmarshal !!str `b` into int64\n"+ - " line 1: cannot unmarshal !!str `B` into int") -} - -var failingErr = errors.New("failingErr") - -type failingUnmarshaler struct{} - -func (ft *failingUnmarshaler) UnmarshalYAML(node *yaml.Node) error { - return failingErr -} - -func (s *S) TestUnmarshalerError(c *C) { - err := yaml.Unmarshal([]byte("a: b"), &failingUnmarshaler{}) - c.Assert(err, Equals, failingErr) -} - -type obsoleteFailingUnmarshaler struct{} - -func (ft *obsoleteFailingUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error { - return failingErr -} - -func (s *S) TestObsoleteUnmarshalerError(c *C) { - err := yaml.Unmarshal([]byte("a: b"), &obsoleteFailingUnmarshaler{}) - c.Assert(err, Equals, failingErr) -} - -type sliceUnmarshaler []int - -func (su *sliceUnmarshaler) UnmarshalYAML(node *yaml.Node) error { - var slice []int - err := node.Decode(&slice) - if err == nil { - *su = slice - return nil - } - - var intVal int - err = node.Decode(&intVal) - if err == nil { - *su = []int{intVal} - return nil - } - - return err -} - -func (s *S) TestUnmarshalerRetry(c *C) { - var su sliceUnmarshaler - err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su) - c.Assert(err, IsNil) - c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1, 2, 3})) - - err = yaml.Unmarshal([]byte("1"), &su) - c.Assert(err, IsNil) - c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1})) -} - -type obsoleteSliceUnmarshaler []int - -func (su *obsoleteSliceUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error { - var slice []int - err := unmarshal(&slice) - if err == nil { - *su = slice - return nil - } - - var intVal int - err = unmarshal(&intVal) - if err == nil { - *su = []int{intVal} - return nil - } - - return err -} - -func (s *S) TestObsoleteUnmarshalerRetry(c *C) { - var su obsoleteSliceUnmarshaler - err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su) - c.Assert(err, IsNil) - c.Assert(su, DeepEquals, obsoleteSliceUnmarshaler([]int{1, 2, 3})) - - err = yaml.Unmarshal([]byte("1"), &su) - c.Assert(err, IsNil) - c.Assert(su, DeepEquals, obsoleteSliceUnmarshaler([]int{1})) -} - -// From http://yaml.org/type/merge.html -var mergeTests = ` -anchors: - list: - - &CENTER { "x": 1, "y": 2 } - - &LEFT { "x": 0, "y": 2 } - - &BIG { "r": 10 } - - &SMALL { "r": 1 } - -# All the following maps are equal: - -plain: - # Explicit keys - "x": 1 - "y": 2 - "r": 10 - label: center/big - -mergeOne: - # Merge one map - << : *CENTER - "r": 10 - label: center/big - -mergeMultiple: - # Merge multiple maps - << : [ *CENTER, *BIG ] - label: center/big - -override: - # Override - << : [ *BIG, *LEFT, *SMALL ] - "x": 1 - label: center/big - -shortTag: - # Explicit short merge tag - !!merge "<<" : [ *CENTER, *BIG ] - label: center/big - -longTag: - # Explicit merge long tag - !<tag:yaml.org,2002:merge> "<<" : [ *CENTER, *BIG ] - label: center/big - -inlineMap: - # Inlined map - << : {"x": 1, "y": 2, "r": 10} - label: center/big - -inlineSequenceMap: - # Inlined map in sequence - << : [ *CENTER, {"r": 10} ] - label: center/big -` - -func (s *S) TestMerge(c *C) { - var want = map[string]interface{}{ - "x": 1, - "y": 2, - "r": 10, - "label": "center/big", - } - - wantStringMap := make(map[string]interface{}) - for k, v := range want { - wantStringMap[fmt.Sprintf("%v", k)] = v - } - - var m map[interface{}]interface{} - err := yaml.Unmarshal([]byte(mergeTests), &m) - c.Assert(err, IsNil) - for name, test := range m { - if name == "anchors" { - continue - } - if name == "plain" { - c.Assert(test, DeepEquals, wantStringMap, Commentf("test %q failed", name)) - continue - } - c.Assert(test, DeepEquals, want, Commentf("test %q failed", name)) - } -} - -func (s *S) TestMergeStruct(c *C) { - type Data struct { - X, Y, R int - Label string - } - want := Data{1, 2, 10, "center/big"} - - var m map[string]Data - err := yaml.Unmarshal([]byte(mergeTests), &m) - c.Assert(err, IsNil) - for name, test := range m { - if name == "anchors" { - continue - } - c.Assert(test, Equals, want, Commentf("test %q failed", name)) - } -} - -var mergeTestsNested = ` -mergeouter1: &mergeouter1 - d: 40 - e: 50 - -mergeouter2: &mergeouter2 - e: 5 - f: 6 - g: 70 - -mergeinner1: &mergeinner1 - <<: *mergeouter1 - inner: - a: 1 - b: 2 - -mergeinner2: &mergeinner2 - <<: *mergeouter2 - inner: - a: -1 - b: -2 - -outer: - <<: [*mergeinner1, *mergeinner2] - f: 60 - inner: - a: 10 -` - -func (s *S) TestMergeNestedStruct(c *C) { - // Issue #818: Merging used to just unmarshal twice on the target - // value, which worked for maps as these were replaced by the new map, - // but not on struct values as these are preserved. This resulted in - // the nested data from the merged map to be mixed up with the data - // from the map being merged into. - // - // This test also prevents two potential bugs from showing up: - // - // 1) A simple implementation might just zero out the nested value - // before unmarshaling the second time, but this would clobber previous - // data that is usually respected ({C: 30} below). - // - // 2) A simple implementation might attempt to handle the key skipping - // directly by iterating over the merging map without recursion, but - // there are more complex cases that require recursion. - // - // Quick summary of the fields: - // - // - A must come from outer and not overriden - // - B must not be set as its in the ignored merge - // - C should still be set as it's preset in the value - // - D should be set from the recursive merge - // - E should be set from the first recursive merge, ignored on the second - // - F should be set in the inlined map from outer, ignored later - // - G should be set in the inlined map from the second recursive merge - // - - type Inner struct { - A, B, C int - } - type Outer struct { - D, E int - Inner Inner - Inline map[string]int `yaml:",inline"` - } - type Data struct { - Outer Outer - } - - test := Data{Outer{0, 0, Inner{C: 30}, nil}} - want := Data{Outer{40, 50, Inner{A: 10, C: 30}, map[string]int{"f": 60, "g": 70}}} - - err := yaml.Unmarshal([]byte(mergeTestsNested), &test) - c.Assert(err, IsNil) - c.Assert(test, DeepEquals, want) - - // Repeat test with a map. - - var testm map[string]interface{} - var wantm = map[string]interface {} { - "f": 60, - "inner": map[string]interface{}{ - "a": 10, - }, - "d": 40, - "e": 50, - "g": 70, - } - err = yaml.Unmarshal([]byte(mergeTestsNested), &testm) - c.Assert(err, IsNil) - c.Assert(testm["outer"], DeepEquals, wantm) -} - -var unmarshalNullTests = []struct { - input string - pristine, expected func() interface{} -}{{ - "null", - func() interface{} { var v interface{}; v = "v"; return &v }, - func() interface{} { var v interface{}; v = nil; return &v }, -}, { - "null", - func() interface{} { var s = "s"; return &s }, - func() interface{} { var s = "s"; return &s }, -}, { - "null", - func() interface{} { var s = "s"; sptr := &s; return &sptr }, - func() interface{} { var sptr *string; return &sptr }, -}, { - "null", - func() interface{} { var i = 1; return &i }, - func() interface{} { var i = 1; return &i }, -}, { - "null", - func() interface{} { var i = 1; iptr := &i; return &iptr }, - func() interface{} { var iptr *int; return &iptr }, -}, { - "null", - func() interface{} { var m = map[string]int{"s": 1}; return &m }, - func() interface{} { var m map[string]int; return &m }, -}, { - "null", - func() interface{} { var m = map[string]int{"s": 1}; return m }, - func() interface{} { var m = map[string]int{"s": 1}; return m }, -}, { - "s2: null\ns3: null", - func() interface{} { var m = map[string]int{"s1": 1, "s2": 2}; return m }, - func() interface{} { var m = map[string]int{"s1": 1, "s2": 2, "s3": 0}; return m }, -}, { - "s2: null\ns3: null", - func() interface{} { var m = map[string]interface{}{"s1": 1, "s2": 2}; return m }, - func() interface{} { var m = map[string]interface{}{"s1": 1, "s2": nil, "s3": nil}; return m }, -}} - -func (s *S) TestUnmarshalNull(c *C) { - for _, test := range unmarshalNullTests { - pristine := test.pristine() - expected := test.expected() - err := yaml.Unmarshal([]byte(test.input), pristine) - c.Assert(err, IsNil) - c.Assert(pristine, DeepEquals, expected) - } -} - -func (s *S) TestUnmarshalPreservesData(c *C) { - var v struct { - A, B int - C int `yaml:"-"` - } - v.A = 42 - v.C = 88 - err := yaml.Unmarshal([]byte("---"), &v) - c.Assert(err, IsNil) - c.Assert(v.A, Equals, 42) - c.Assert(v.B, Equals, 0) - c.Assert(v.C, Equals, 88) - - err = yaml.Unmarshal([]byte("b: 21\nc: 99"), &v) - c.Assert(err, IsNil) - c.Assert(v.A, Equals, 42) - c.Assert(v.B, Equals, 21) - c.Assert(v.C, Equals, 88) -} - -func (s *S) TestUnmarshalSliceOnPreset(c *C) { - // Issue #48. - v := struct{ A []int }{[]int{1}} - yaml.Unmarshal([]byte("a: [2]"), &v) - c.Assert(v.A, DeepEquals, []int{2}) -} - -var unmarshalStrictTests = []struct { - known bool - unique bool - data string - value interface{} - error string -}{{ - known: true, - data: "a: 1\nc: 2\n", - value: struct{ A, B int }{A: 1}, - error: `yaml: unmarshal errors:\n line 2: field c not found in type struct { A int; B int }`, -}, { - unique: true, - data: "a: 1\nb: 2\na: 3\n", - value: struct{ A, B int }{A: 3, B: 2}, - error: `yaml: unmarshal errors:\n line 3: mapping key "a" already defined at line 1`, -}, { - unique: true, - data: "c: 3\na: 1\nb: 2\nc: 4\n", - value: struct { - A int - inlineB `yaml:",inline"` - }{ - A: 1, - inlineB: inlineB{ - B: 2, - inlineC: inlineC{ - C: 4, - }, - }, - }, - error: `yaml: unmarshal errors:\n line 4: mapping key "c" already defined at line 1`, -}, { - unique: true, - data: "c: 0\na: 1\nb: 2\nc: 1\n", - value: struct { - A int - inlineB `yaml:",inline"` - }{ - A: 1, - inlineB: inlineB{ - B: 2, - inlineC: inlineC{ - C: 1, - }, - }, - }, - error: `yaml: unmarshal errors:\n line 4: mapping key "c" already defined at line 1`, -}, { - unique: true, - data: "c: 1\na: 1\nb: 2\nc: 3\n", - value: struct { - A int - M map[string]interface{} `yaml:",inline"` - }{ - A: 1, - M: map[string]interface{}{ - "b": 2, - "c": 3, - }, - }, - error: `yaml: unmarshal errors:\n line 4: mapping key "c" already defined at line 1`, -}, { - unique: true, - data: "a: 1\n9: 2\nnull: 3\n9: 4", - value: map[interface{}]interface{}{ - "a": 1, - nil: 3, - 9: 4, - }, - error: `yaml: unmarshal errors:\n line 4: mapping key "9" already defined at line 2`, -}} - -func (s *S) TestUnmarshalKnownFields(c *C) { - for i, item := range unmarshalStrictTests { - c.Logf("test %d: %q", i, item.data) - // First test that normal Unmarshal unmarshals to the expected value. - if !item.unique { - t := reflect.ValueOf(item.value).Type() - value := reflect.New(t) - err := yaml.Unmarshal([]byte(item.data), value.Interface()) - c.Assert(err, Equals, nil) - c.Assert(value.Elem().Interface(), DeepEquals, item.value) - } - - // Then test that it fails on the same thing with KnownFields on. - t := reflect.ValueOf(item.value).Type() - value := reflect.New(t) - dec := yaml.NewDecoder(bytes.NewBuffer([]byte(item.data))) - dec.KnownFields(item.known) - err := dec.Decode(value.Interface()) - c.Assert(err, ErrorMatches, item.error) - } -} - -type textUnmarshaler struct { - S string -} - -func (t *textUnmarshaler) UnmarshalText(s []byte) error { - t.S = string(s) - return nil -} - -func (s *S) TestFuzzCrashers(c *C) { - cases := []string{ - // runtime error: index out of range - "\"\\0\\\r\n", - - // should not happen - " 0: [\n] 0", - "? ? \"\n\" 0", - " - {\n000}0", - "0:\n 0: [0\n] 0", - " - \"\n000\"0", - " - \"\n000\"\"", - "0:\n - {\n000}0", - "0:\n - \"\n000\"0", - "0:\n - \"\n000\"\"", - - // runtime error: index out of range - " \ufeff\n", - "? \ufeff\n", - "? \ufeff:\n", - "0: \ufeff\n", - "? \ufeff: \ufeff\n", - } - for _, data := range cases { - var v interface{} - _ = yaml.Unmarshal([]byte(data), &v) - } -} - -//var data []byte -//func init() { -// var err error -// data, err = ioutil.ReadFile("/tmp/file.yaml") -// if err != nil { -// panic(err) -// } -//} -// -//func (s *S) BenchmarkUnmarshal(c *C) { -// var err error -// for i := 0; i < c.N; i++ { -// var v map[string]interface{} -// err = yaml.Unmarshal(data, &v) -// } -// if err != nil { -// panic(err) -// } -//} -// -//func (s *S) BenchmarkMarshal(c *C) { -// var v map[string]interface{} -// yaml.Unmarshal(data, &v) -// c.ResetTimer() -// for i := 0; i < c.N; i++ { -// yaml.Marshal(&v) -// } -//} diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/emitterc.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/emitterc.go deleted file mode 100644 index 0f47c9c..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/emitterc.go +++ /dev/null @@ -1,2020 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// 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. - -package yaml - -import ( - "bytes" - "fmt" -) - -// Flush the buffer if needed. -func flush(emitter *yaml_emitter_t) bool { - if emitter.buffer_pos+5 >= len(emitter.buffer) { - return yaml_emitter_flush(emitter) - } - return true -} - -// Put a character to the output buffer. -func put(emitter *yaml_emitter_t, value byte) bool { - if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { - return false - } - emitter.buffer[emitter.buffer_pos] = value - emitter.buffer_pos++ - emitter.column++ - return true -} - -// Put a line break to the output buffer. -func put_break(emitter *yaml_emitter_t) bool { - if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { - return false - } - switch emitter.line_break { - case yaml_CR_BREAK: - emitter.buffer[emitter.buffer_pos] = '\r' - emitter.buffer_pos += 1 - case yaml_LN_BREAK: - emitter.buffer[emitter.buffer_pos] = '\n' - emitter.buffer_pos += 1 - case yaml_CRLN_BREAK: - emitter.buffer[emitter.buffer_pos+0] = '\r' - emitter.buffer[emitter.buffer_pos+1] = '\n' - emitter.buffer_pos += 2 - default: - panic("unknown line break setting") - } - if emitter.column == 0 { - emitter.space_above = true - } - emitter.column = 0 - emitter.line++ - // [Go] Do this here and below and drop from everywhere else (see commented lines). - emitter.indention = true - return true -} - -// Copy a character from a string into buffer. -func write(emitter *yaml_emitter_t, s []byte, i *int) bool { - if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { - return false - } - p := emitter.buffer_pos - w := width(s[*i]) - switch w { - case 4: - emitter.buffer[p+3] = s[*i+3] - fallthrough - case 3: - emitter.buffer[p+2] = s[*i+2] - fallthrough - case 2: - emitter.buffer[p+1] = s[*i+1] - fallthrough - case 1: - emitter.buffer[p+0] = s[*i+0] - default: - panic("unknown character width") - } - emitter.column++ - emitter.buffer_pos += w - *i += w - return true -} - -// Write a whole string into buffer. -func write_all(emitter *yaml_emitter_t, s []byte) bool { - for i := 0; i < len(s); { - if !write(emitter, s, &i) { - return false - } - } - return true -} - -// Copy a line break character from a string into buffer. -func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool { - if s[*i] == '\n' { - if !put_break(emitter) { - return false - } - *i++ - } else { - if !write(emitter, s, i) { - return false - } - if emitter.column == 0 { - emitter.space_above = true - } - emitter.column = 0 - emitter.line++ - // [Go] Do this here and above and drop from everywhere else (see commented lines). - emitter.indention = true - } - return true -} - -// Set an emitter error and return false. -func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool { - emitter.error = yaml_EMITTER_ERROR - emitter.problem = problem - return false -} - -// Emit an event. -func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool { - emitter.events = append(emitter.events, *event) - for !yaml_emitter_need_more_events(emitter) { - event := &emitter.events[emitter.events_head] - if !yaml_emitter_analyze_event(emitter, event) { - return false - } - if !yaml_emitter_state_machine(emitter, event) { - return false - } - yaml_event_delete(event) - emitter.events_head++ - } - return true -} - -// Check if we need to accumulate more events before emitting. -// -// We accumulate extra -// - 1 event for DOCUMENT-START -// - 2 events for SEQUENCE-START -// - 3 events for MAPPING-START -// -func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool { - if emitter.events_head == len(emitter.events) { - return true - } - var accumulate int - switch emitter.events[emitter.events_head].typ { - case yaml_DOCUMENT_START_EVENT: - accumulate = 1 - break - case yaml_SEQUENCE_START_EVENT: - accumulate = 2 - break - case yaml_MAPPING_START_EVENT: - accumulate = 3 - break - default: - return false - } - if len(emitter.events)-emitter.events_head > accumulate { - return false - } - var level int - for i := emitter.events_head; i < len(emitter.events); i++ { - switch emitter.events[i].typ { - case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT: - level++ - case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT: - level-- - } - if level == 0 { - return false - } - } - return true -} - -// Append a directive to the directives stack. -func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool { - for i := 0; i < len(emitter.tag_directives); i++ { - if bytes.Equal(value.handle, emitter.tag_directives[i].handle) { - if allow_duplicates { - return true - } - return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive") - } - } - - // [Go] Do we actually need to copy this given garbage collection - // and the lack of deallocating destructors? - tag_copy := yaml_tag_directive_t{ - handle: make([]byte, len(value.handle)), - prefix: make([]byte, len(value.prefix)), - } - copy(tag_copy.handle, value.handle) - copy(tag_copy.prefix, value.prefix) - emitter.tag_directives = append(emitter.tag_directives, tag_copy) - return true -} - -// Increase the indentation level. -func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool { - emitter.indents = append(emitter.indents, emitter.indent) - if emitter.indent < 0 { - if flow { - emitter.indent = emitter.best_indent - } else { - emitter.indent = 0 - } - } else if !indentless { - // [Go] This was changed so that indentations are more regular. - if emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE { - // The first indent inside a sequence will just skip the "- " indicator. - emitter.indent += 2 - } else { - // Everything else aligns to the chosen indentation. - emitter.indent = emitter.best_indent*((emitter.indent+emitter.best_indent)/emitter.best_indent) - } - } - return true -} - -// State dispatcher. -func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool { - switch emitter.state { - default: - case yaml_EMIT_STREAM_START_STATE: - return yaml_emitter_emit_stream_start(emitter, event) - - case yaml_EMIT_FIRST_DOCUMENT_START_STATE: - return yaml_emitter_emit_document_start(emitter, event, true) - - case yaml_EMIT_DOCUMENT_START_STATE: - return yaml_emitter_emit_document_start(emitter, event, false) - - case yaml_EMIT_DOCUMENT_CONTENT_STATE: - return yaml_emitter_emit_document_content(emitter, event) - - case yaml_EMIT_DOCUMENT_END_STATE: - return yaml_emitter_emit_document_end(emitter, event) - - case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE: - return yaml_emitter_emit_flow_sequence_item(emitter, event, true, false) - - case yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE: - return yaml_emitter_emit_flow_sequence_item(emitter, event, false, true) - - case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE: - return yaml_emitter_emit_flow_sequence_item(emitter, event, false, false) - - case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE: - return yaml_emitter_emit_flow_mapping_key(emitter, event, true, false) - - case yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE: - return yaml_emitter_emit_flow_mapping_key(emitter, event, false, true) - - case yaml_EMIT_FLOW_MAPPING_KEY_STATE: - return yaml_emitter_emit_flow_mapping_key(emitter, event, false, false) - - case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE: - return yaml_emitter_emit_flow_mapping_value(emitter, event, true) - - case yaml_EMIT_FLOW_MAPPING_VALUE_STATE: - return yaml_emitter_emit_flow_mapping_value(emitter, event, false) - - case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE: - return yaml_emitter_emit_block_sequence_item(emitter, event, true) - - case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE: - return yaml_emitter_emit_block_sequence_item(emitter, event, false) - - case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE: - return yaml_emitter_emit_block_mapping_key(emitter, event, true) - - case yaml_EMIT_BLOCK_MAPPING_KEY_STATE: - return yaml_emitter_emit_block_mapping_key(emitter, event, false) - - case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE: - return yaml_emitter_emit_block_mapping_value(emitter, event, true) - - case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE: - return yaml_emitter_emit_block_mapping_value(emitter, event, false) - - case yaml_EMIT_END_STATE: - return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END") - } - panic("invalid emitter state") -} - -// Expect STREAM-START. -func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if event.typ != yaml_STREAM_START_EVENT { - return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START") - } - if emitter.encoding == yaml_ANY_ENCODING { - emitter.encoding = event.encoding - if emitter.encoding == yaml_ANY_ENCODING { - emitter.encoding = yaml_UTF8_ENCODING - } - } - if emitter.best_indent < 2 || emitter.best_indent > 9 { - emitter.best_indent = 2 - } - if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 { - emitter.best_width = 80 - } - if emitter.best_width < 0 { - emitter.best_width = 1<<31 - 1 - } - if emitter.line_break == yaml_ANY_BREAK { - emitter.line_break = yaml_LN_BREAK - } - - emitter.indent = -1 - emitter.line = 0 - emitter.column = 0 - emitter.whitespace = true - emitter.indention = true - emitter.space_above = true - emitter.foot_indent = -1 - - if emitter.encoding != yaml_UTF8_ENCODING { - if !yaml_emitter_write_bom(emitter) { - return false - } - } - emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE - return true -} - -// Expect DOCUMENT-START or STREAM-END. -func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { - - if event.typ == yaml_DOCUMENT_START_EVENT { - - if event.version_directive != nil { - if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) { - return false - } - } - - for i := 0; i < len(event.tag_directives); i++ { - tag_directive := &event.tag_directives[i] - if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) { - return false - } - if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) { - return false - } - } - - for i := 0; i < len(default_tag_directives); i++ { - tag_directive := &default_tag_directives[i] - if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) { - return false - } - } - - implicit := event.implicit - if !first || emitter.canonical { - implicit = false - } - - if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) { - if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - - if event.version_directive != nil { - implicit = false - if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - - if len(event.tag_directives) > 0 { - implicit = false - for i := 0; i < len(event.tag_directives); i++ { - tag_directive := &event.tag_directives[i] - if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) { - return false - } - if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) { - return false - } - if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - } - - if yaml_emitter_check_empty_document(emitter) { - implicit = false - } - if !implicit { - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) { - return false - } - if emitter.canonical || true { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - } - - if len(emitter.head_comment) > 0 { - if !yaml_emitter_process_head_comment(emitter) { - return false - } - if !put_break(emitter) { - return false - } - } - - emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE - return true - } - - if event.typ == yaml_STREAM_END_EVENT { - if emitter.open_ended { - if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_flush(emitter) { - return false - } - emitter.state = yaml_EMIT_END_STATE - return true - } - - return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END") -} - -// Expect the root node. -func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool { - emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE) - - if !yaml_emitter_process_head_comment(emitter) { - return false - } - if !yaml_emitter_emit_node(emitter, event, true, false, false, false) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - return true -} - -// Expect DOCUMENT-END. -func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if event.typ != yaml_DOCUMENT_END_EVENT { - return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END") - } - // [Go] Force document foot separation. - emitter.foot_indent = 0 - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - emitter.foot_indent = -1 - if !yaml_emitter_write_indent(emitter) { - return false - } - if !event.implicit { - // [Go] Allocate the slice elsewhere. - if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_flush(emitter) { - return false - } - emitter.state = yaml_EMIT_DOCUMENT_START_STATE - emitter.tag_directives = emitter.tag_directives[:0] - return true -} - -// Expect a flow item node. -func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool { - if first { - if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) { - return false - } - if !yaml_emitter_increase_indent(emitter, true, false) { - return false - } - emitter.flow_level++ - } - - if event.typ == yaml_SEQUENCE_END_EVENT { - if emitter.canonical && !first && !trail { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - emitter.flow_level-- - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - if emitter.column == 0 || emitter.canonical && !first { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - - return true - } - - if !first && !trail { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - - if !yaml_emitter_process_head_comment(emitter) { - return false - } - if emitter.column == 0 { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - - if emitter.canonical || emitter.column > emitter.best_width { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { - emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE) - } else { - emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE) - } - if !yaml_emitter_emit_node(emitter, event, false, true, false, false) { - return false - } - if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - return true -} - -// Expect a flow key node. -func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool { - if first { - if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) { - return false - } - if !yaml_emitter_increase_indent(emitter, true, false) { - return false - } - emitter.flow_level++ - } - - if event.typ == yaml_MAPPING_END_EVENT { - if (emitter.canonical || len(emitter.head_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0) && !first && !trail { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - if !yaml_emitter_process_head_comment(emitter) { - return false - } - emitter.flow_level-- - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - if emitter.canonical && !first { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true - } - - if !first && !trail { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - - if !yaml_emitter_process_head_comment(emitter) { - return false - } - - if emitter.column == 0 { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - - if emitter.canonical || emitter.column > emitter.best_width { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - - if !emitter.canonical && yaml_emitter_check_simple_key(emitter) { - emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE) - return yaml_emitter_emit_node(emitter, event, false, false, true, true) - } - if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) { - return false - } - emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE) - return yaml_emitter_emit_node(emitter, event, false, false, true, false) -} - -// Expect a flow value node. -func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { - if simple { - if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { - return false - } - } else { - if emitter.canonical || emitter.column > emitter.best_width { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) { - return false - } - } - if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { - emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE) - } else { - emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE) - } - if !yaml_emitter_emit_node(emitter, event, false, false, true, false) { - return false - } - if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - return true -} - -// Expect a block item node. -func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { - if first { - if !yaml_emitter_increase_indent(emitter, false, false) { - return false - } - } - if event.typ == yaml_SEQUENCE_END_EVENT { - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true - } - if !yaml_emitter_process_head_comment(emitter) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) { - return false - } - emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE) - if !yaml_emitter_emit_node(emitter, event, false, true, false, false) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - return true -} - -// Expect a block key node. -func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { - if first { - if !yaml_emitter_increase_indent(emitter, false, false) { - return false - } - } - if !yaml_emitter_process_head_comment(emitter) { - return false - } - if event.typ == yaml_MAPPING_END_EVENT { - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true - } - if !yaml_emitter_write_indent(emitter) { - return false - } - if len(emitter.line_comment) > 0 { - // [Go] A line comment was provided for the key. That's unusual as the - // scanner associates line comments with the value. Either way, - // save the line comment and render it appropriately later. - emitter.key_line_comment = emitter.line_comment - emitter.line_comment = nil - } - if yaml_emitter_check_simple_key(emitter) { - emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE) - return yaml_emitter_emit_node(emitter, event, false, false, true, true) - } - if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) { - return false - } - emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE) - return yaml_emitter_emit_node(emitter, event, false, false, true, false) -} - -// Expect a block value node. -func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { - if simple { - if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { - return false - } - } else { - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) { - return false - } - } - if len(emitter.key_line_comment) > 0 { - // [Go] Line comments are generally associated with the value, but when there's - // no value on the same line as a mapping key they end up attached to the - // key itself. - if event.typ == yaml_SCALAR_EVENT { - if len(emitter.line_comment) == 0 { - // A scalar is coming and it has no line comments by itself yet, - // so just let it handle the line comment as usual. If it has a - // line comment, we can't have both so the one from the key is lost. - emitter.line_comment = emitter.key_line_comment - emitter.key_line_comment = nil - } - } else if event.sequence_style() != yaml_FLOW_SEQUENCE_STYLE && (event.typ == yaml_MAPPING_START_EVENT || event.typ == yaml_SEQUENCE_START_EVENT) { - // An indented block follows, so write the comment right now. - emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment - if !yaml_emitter_process_line_comment(emitter) { - return false - } - emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment - } - } - emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE) - if !yaml_emitter_emit_node(emitter, event, false, false, true, false) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - return true -} - -func yaml_emitter_silent_nil_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { - return event.typ == yaml_SCALAR_EVENT && event.implicit && !emitter.canonical && len(emitter.scalar_data.value) == 0 -} - -// Expect a node. -func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t, - root bool, sequence bool, mapping bool, simple_key bool) bool { - - emitter.root_context = root - emitter.sequence_context = sequence - emitter.mapping_context = mapping - emitter.simple_key_context = simple_key - - switch event.typ { - case yaml_ALIAS_EVENT: - return yaml_emitter_emit_alias(emitter, event) - case yaml_SCALAR_EVENT: - return yaml_emitter_emit_scalar(emitter, event) - case yaml_SEQUENCE_START_EVENT: - return yaml_emitter_emit_sequence_start(emitter, event) - case yaml_MAPPING_START_EVENT: - return yaml_emitter_emit_mapping_start(emitter, event) - default: - return yaml_emitter_set_emitter_error(emitter, - fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ)) - } -} - -// Expect ALIAS. -func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if !yaml_emitter_process_anchor(emitter) { - return false - } - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true -} - -// Expect SCALAR. -func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if !yaml_emitter_select_scalar_style(emitter, event) { - return false - } - if !yaml_emitter_process_anchor(emitter) { - return false - } - if !yaml_emitter_process_tag(emitter) { - return false - } - if !yaml_emitter_increase_indent(emitter, true, false) { - return false - } - if !yaml_emitter_process_scalar(emitter) { - return false - } - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true -} - -// Expect SEQUENCE-START. -func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if !yaml_emitter_process_anchor(emitter) { - return false - } - if !yaml_emitter_process_tag(emitter) { - return false - } - if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE || - yaml_emitter_check_empty_sequence(emitter) { - emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE - } else { - emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE - } - return true -} - -// Expect MAPPING-START. -func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if !yaml_emitter_process_anchor(emitter) { - return false - } - if !yaml_emitter_process_tag(emitter) { - return false - } - if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE || - yaml_emitter_check_empty_mapping(emitter) { - emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE - } else { - emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE - } - return true -} - -// Check if the document content is an empty scalar. -func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool { - return false // [Go] Huh? -} - -// Check if the next events represent an empty sequence. -func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool { - if len(emitter.events)-emitter.events_head < 2 { - return false - } - return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT && - emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT -} - -// Check if the next events represent an empty mapping. -func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool { - if len(emitter.events)-emitter.events_head < 2 { - return false - } - return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT && - emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT -} - -// Check if the next node can be expressed as a simple key. -func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool { - length := 0 - switch emitter.events[emitter.events_head].typ { - case yaml_ALIAS_EVENT: - length += len(emitter.anchor_data.anchor) - case yaml_SCALAR_EVENT: - if emitter.scalar_data.multiline { - return false - } - length += len(emitter.anchor_data.anchor) + - len(emitter.tag_data.handle) + - len(emitter.tag_data.suffix) + - len(emitter.scalar_data.value) - case yaml_SEQUENCE_START_EVENT: - if !yaml_emitter_check_empty_sequence(emitter) { - return false - } - length += len(emitter.anchor_data.anchor) + - len(emitter.tag_data.handle) + - len(emitter.tag_data.suffix) - case yaml_MAPPING_START_EVENT: - if !yaml_emitter_check_empty_mapping(emitter) { - return false - } - length += len(emitter.anchor_data.anchor) + - len(emitter.tag_data.handle) + - len(emitter.tag_data.suffix) - default: - return false - } - return length <= 128 -} - -// Determine an acceptable scalar style. -func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool { - - no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 - if no_tag && !event.implicit && !event.quoted_implicit { - return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified") - } - - style := event.scalar_style() - if style == yaml_ANY_SCALAR_STYLE { - style = yaml_PLAIN_SCALAR_STYLE - } - if emitter.canonical { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - if emitter.simple_key_context && emitter.scalar_data.multiline { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - - if style == yaml_PLAIN_SCALAR_STYLE { - if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed || - emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed { - style = yaml_SINGLE_QUOTED_SCALAR_STYLE - } - if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) { - style = yaml_SINGLE_QUOTED_SCALAR_STYLE - } - if no_tag && !event.implicit { - style = yaml_SINGLE_QUOTED_SCALAR_STYLE - } - } - if style == yaml_SINGLE_QUOTED_SCALAR_STYLE { - if !emitter.scalar_data.single_quoted_allowed { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - } - if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE { - if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - } - - if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE { - emitter.tag_data.handle = []byte{'!'} - } - emitter.scalar_data.style = style - return true -} - -// Write an anchor. -func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool { - if emitter.anchor_data.anchor == nil { - return true - } - c := []byte{'&'} - if emitter.anchor_data.alias { - c[0] = '*' - } - if !yaml_emitter_write_indicator(emitter, c, true, false, false) { - return false - } - return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor) -} - -// Write a tag. -func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool { - if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 { - return true - } - if len(emitter.tag_data.handle) > 0 { - if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) { - return false - } - if len(emitter.tag_data.suffix) > 0 { - if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { - return false - } - } - } else { - // [Go] Allocate these slices elsewhere. - if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) { - return false - } - if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) { - return false - } - } - return true -} - -// Write a scalar. -func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool { - switch emitter.scalar_data.style { - case yaml_PLAIN_SCALAR_STYLE: - return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) - - case yaml_SINGLE_QUOTED_SCALAR_STYLE: - return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) - - case yaml_DOUBLE_QUOTED_SCALAR_STYLE: - return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) - - case yaml_LITERAL_SCALAR_STYLE: - return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value) - - case yaml_FOLDED_SCALAR_STYLE: - return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value) - } - panic("unknown scalar style") -} - -// Write a head comment. -func yaml_emitter_process_head_comment(emitter *yaml_emitter_t) bool { - if len(emitter.tail_comment) > 0 { - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_comment(emitter, emitter.tail_comment) { - return false - } - emitter.tail_comment = emitter.tail_comment[:0] - emitter.foot_indent = emitter.indent - if emitter.foot_indent < 0 { - emitter.foot_indent = 0 - } - } - - if len(emitter.head_comment) == 0 { - return true - } - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_comment(emitter, emitter.head_comment) { - return false - } - emitter.head_comment = emitter.head_comment[:0] - return true -} - -// Write an line comment. -func yaml_emitter_process_line_comment(emitter *yaml_emitter_t) bool { - if len(emitter.line_comment) == 0 { - return true - } - if !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - if !yaml_emitter_write_comment(emitter, emitter.line_comment) { - return false - } - emitter.line_comment = emitter.line_comment[:0] - return true -} - -// Write a foot comment. -func yaml_emitter_process_foot_comment(emitter *yaml_emitter_t) bool { - if len(emitter.foot_comment) == 0 { - return true - } - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_comment(emitter, emitter.foot_comment) { - return false - } - emitter.foot_comment = emitter.foot_comment[:0] - emitter.foot_indent = emitter.indent - if emitter.foot_indent < 0 { - emitter.foot_indent = 0 - } - return true -} - -// Check if a %YAML directive is valid. -func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool { - if version_directive.major != 1 || version_directive.minor != 1 { - return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive") - } - return true -} - -// Check if a %TAG directive is valid. -func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool { - handle := tag_directive.handle - prefix := tag_directive.prefix - if len(handle) == 0 { - return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty") - } - if handle[0] != '!' { - return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'") - } - if handle[len(handle)-1] != '!' { - return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'") - } - for i := 1; i < len(handle)-1; i += width(handle[i]) { - if !is_alpha(handle, i) { - return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only") - } - } - if len(prefix) == 0 { - return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty") - } - return true -} - -// Check if an anchor is valid. -func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool { - if len(anchor) == 0 { - problem := "anchor value must not be empty" - if alias { - problem = "alias value must not be empty" - } - return yaml_emitter_set_emitter_error(emitter, problem) - } - for i := 0; i < len(anchor); i += width(anchor[i]) { - if !is_alpha(anchor, i) { - problem := "anchor value must contain alphanumerical characters only" - if alias { - problem = "alias value must contain alphanumerical characters only" - } - return yaml_emitter_set_emitter_error(emitter, problem) - } - } - emitter.anchor_data.anchor = anchor - emitter.anchor_data.alias = alias - return true -} - -// Check if a tag is valid. -func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool { - if len(tag) == 0 { - return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty") - } - for i := 0; i < len(emitter.tag_directives); i++ { - tag_directive := &emitter.tag_directives[i] - if bytes.HasPrefix(tag, tag_directive.prefix) { - emitter.tag_data.handle = tag_directive.handle - emitter.tag_data.suffix = tag[len(tag_directive.prefix):] - return true - } - } - emitter.tag_data.suffix = tag - return true -} - -// Check if a scalar is valid. -func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool { - var ( - block_indicators = false - flow_indicators = false - line_breaks = false - special_characters = false - tab_characters = false - - leading_space = false - leading_break = false - trailing_space = false - trailing_break = false - break_space = false - space_break = false - - preceded_by_whitespace = false - followed_by_whitespace = false - previous_space = false - previous_break = false - ) - - emitter.scalar_data.value = value - - if len(value) == 0 { - emitter.scalar_data.multiline = false - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = true - emitter.scalar_data.single_quoted_allowed = true - emitter.scalar_data.block_allowed = false - return true - } - - if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) { - block_indicators = true - flow_indicators = true - } - - preceded_by_whitespace = true - for i, w := 0, 0; i < len(value); i += w { - w = width(value[i]) - followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w) - - if i == 0 { - switch value[i] { - case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`': - flow_indicators = true - block_indicators = true - case '?', ':': - flow_indicators = true - if followed_by_whitespace { - block_indicators = true - } - case '-': - if followed_by_whitespace { - flow_indicators = true - block_indicators = true - } - } - } else { - switch value[i] { - case ',', '?', '[', ']', '{', '}': - flow_indicators = true - case ':': - flow_indicators = true - if followed_by_whitespace { - block_indicators = true - } - case '#': - if preceded_by_whitespace { - flow_indicators = true - block_indicators = true - } - } - } - - if value[i] == '\t' { - tab_characters = true - } else if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode { - special_characters = true - } - if is_space(value, i) { - if i == 0 { - leading_space = true - } - if i+width(value[i]) == len(value) { - trailing_space = true - } - if previous_break { - break_space = true - } - previous_space = true - previous_break = false - } else if is_break(value, i) { - line_breaks = true - if i == 0 { - leading_break = true - } - if i+width(value[i]) == len(value) { - trailing_break = true - } - if previous_space { - space_break = true - } - previous_space = false - previous_break = true - } else { - previous_space = false - previous_break = false - } - - // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition. - preceded_by_whitespace = is_blankz(value, i) - } - - emitter.scalar_data.multiline = line_breaks - emitter.scalar_data.flow_plain_allowed = true - emitter.scalar_data.block_plain_allowed = true - emitter.scalar_data.single_quoted_allowed = true - emitter.scalar_data.block_allowed = true - - if leading_space || leading_break || trailing_space || trailing_break { - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = false - } - if trailing_space { - emitter.scalar_data.block_allowed = false - } - if break_space { - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = false - emitter.scalar_data.single_quoted_allowed = false - } - if space_break || tab_characters || special_characters { - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = false - emitter.scalar_data.single_quoted_allowed = false - } - if space_break || special_characters { - emitter.scalar_data.block_allowed = false - } - if line_breaks { - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = false - } - if flow_indicators { - emitter.scalar_data.flow_plain_allowed = false - } - if block_indicators { - emitter.scalar_data.block_plain_allowed = false - } - return true -} - -// Check if the event data is valid. -func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { - - emitter.anchor_data.anchor = nil - emitter.tag_data.handle = nil - emitter.tag_data.suffix = nil - emitter.scalar_data.value = nil - - if len(event.head_comment) > 0 { - emitter.head_comment = event.head_comment - } - if len(event.line_comment) > 0 { - emitter.line_comment = event.line_comment - } - if len(event.foot_comment) > 0 { - emitter.foot_comment = event.foot_comment - } - if len(event.tail_comment) > 0 { - emitter.tail_comment = event.tail_comment - } - - switch event.typ { - case yaml_ALIAS_EVENT: - if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) { - return false - } - - case yaml_SCALAR_EVENT: - if len(event.anchor) > 0 { - if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { - return false - } - } - if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) { - if !yaml_emitter_analyze_tag(emitter, event.tag) { - return false - } - } - if !yaml_emitter_analyze_scalar(emitter, event.value) { - return false - } - - case yaml_SEQUENCE_START_EVENT: - if len(event.anchor) > 0 { - if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { - return false - } - } - if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { - if !yaml_emitter_analyze_tag(emitter, event.tag) { - return false - } - } - - case yaml_MAPPING_START_EVENT: - if len(event.anchor) > 0 { - if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { - return false - } - } - if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { - if !yaml_emitter_analyze_tag(emitter, event.tag) { - return false - } - } - } - return true -} - -// Write the BOM character. -func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool { - if !flush(emitter) { - return false - } - pos := emitter.buffer_pos - emitter.buffer[pos+0] = '\xEF' - emitter.buffer[pos+1] = '\xBB' - emitter.buffer[pos+2] = '\xBF' - emitter.buffer_pos += 3 - return true -} - -func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool { - indent := emitter.indent - if indent < 0 { - indent = 0 - } - if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) { - if !put_break(emitter) { - return false - } - } - if emitter.foot_indent == indent { - if !put_break(emitter) { - return false - } - } - for emitter.column < indent { - if !put(emitter, ' ') { - return false - } - } - emitter.whitespace = true - //emitter.indention = true - emitter.space_above = false - emitter.foot_indent = -1 - return true -} - -func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool { - if need_whitespace && !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - if !write_all(emitter, indicator) { - return false - } - emitter.whitespace = is_whitespace - emitter.indention = (emitter.indention && is_indention) - emitter.open_ended = false - return true -} - -func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool { - if !write_all(emitter, value) { - return false - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool { - if !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - if !write_all(emitter, value) { - return false - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool { - if need_whitespace && !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - for i := 0; i < len(value); { - var must_write bool - switch value[i] { - case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']': - must_write = true - default: - must_write = is_alpha(value, i) - } - if must_write { - if !write(emitter, value, &i) { - return false - } - } else { - w := width(value[i]) - for k := 0; k < w; k++ { - octet := value[i] - i++ - if !put(emitter, '%') { - return false - } - - c := octet >> 4 - if c < 10 { - c += '0' - } else { - c += 'A' - 10 - } - if !put(emitter, c) { - return false - } - - c = octet & 0x0f - if c < 10 { - c += '0' - } else { - c += 'A' - 10 - } - if !put(emitter, c) { - return false - } - } - } - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { - if len(value) > 0 && !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - - spaces := false - breaks := false - for i := 0; i < len(value); { - if is_space(value, i) { - if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) { - if !yaml_emitter_write_indent(emitter) { - return false - } - i += width(value[i]) - } else { - if !write(emitter, value, &i) { - return false - } - } - spaces = true - } else if is_break(value, i) { - if !breaks && value[i] == '\n' { - if !put_break(emitter) { - return false - } - } - if !write_break(emitter, value, &i) { - return false - } - //emitter.indention = true - breaks = true - } else { - if breaks { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !write(emitter, value, &i) { - return false - } - emitter.indention = false - spaces = false - breaks = false - } - } - - if len(value) > 0 { - emitter.whitespace = false - } - emitter.indention = false - if emitter.root_context { - emitter.open_ended = true - } - - return true -} - -func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { - - if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) { - return false - } - - spaces := false - breaks := false - for i := 0; i < len(value); { - if is_space(value, i) { - if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) { - if !yaml_emitter_write_indent(emitter) { - return false - } - i += width(value[i]) - } else { - if !write(emitter, value, &i) { - return false - } - } - spaces = true - } else if is_break(value, i) { - if !breaks && value[i] == '\n' { - if !put_break(emitter) { - return false - } - } - if !write_break(emitter, value, &i) { - return false - } - //emitter.indention = true - breaks = true - } else { - if breaks { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if value[i] == '\'' { - if !put(emitter, '\'') { - return false - } - } - if !write(emitter, value, &i) { - return false - } - emitter.indention = false - spaces = false - breaks = false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) { - return false - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { - spaces := false - if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) { - return false - } - - for i := 0; i < len(value); { - if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) || - is_bom(value, i) || is_break(value, i) || - value[i] == '"' || value[i] == '\\' { - - octet := value[i] - - var w int - var v rune - switch { - case octet&0x80 == 0x00: - w, v = 1, rune(octet&0x7F) - case octet&0xE0 == 0xC0: - w, v = 2, rune(octet&0x1F) - case octet&0xF0 == 0xE0: - w, v = 3, rune(octet&0x0F) - case octet&0xF8 == 0xF0: - w, v = 4, rune(octet&0x07) - } - for k := 1; k < w; k++ { - octet = value[i+k] - v = (v << 6) + (rune(octet) & 0x3F) - } - i += w - - if !put(emitter, '\\') { - return false - } - - var ok bool - switch v { - case 0x00: - ok = put(emitter, '0') - case 0x07: - ok = put(emitter, 'a') - case 0x08: - ok = put(emitter, 'b') - case 0x09: - ok = put(emitter, 't') - case 0x0A: - ok = put(emitter, 'n') - case 0x0b: - ok = put(emitter, 'v') - case 0x0c: - ok = put(emitter, 'f') - case 0x0d: - ok = put(emitter, 'r') - case 0x1b: - ok = put(emitter, 'e') - case 0x22: - ok = put(emitter, '"') - case 0x5c: - ok = put(emitter, '\\') - case 0x85: - ok = put(emitter, 'N') - case 0xA0: - ok = put(emitter, '_') - case 0x2028: - ok = put(emitter, 'L') - case 0x2029: - ok = put(emitter, 'P') - default: - if v <= 0xFF { - ok = put(emitter, 'x') - w = 2 - } else if v <= 0xFFFF { - ok = put(emitter, 'u') - w = 4 - } else { - ok = put(emitter, 'U') - w = 8 - } - for k := (w - 1) * 4; ok && k >= 0; k -= 4 { - digit := byte((v >> uint(k)) & 0x0F) - if digit < 10 { - ok = put(emitter, digit+'0') - } else { - ok = put(emitter, digit+'A'-10) - } - } - } - if !ok { - return false - } - spaces = false - } else if is_space(value, i) { - if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 { - if !yaml_emitter_write_indent(emitter) { - return false - } - if is_space(value, i+1) { - if !put(emitter, '\\') { - return false - } - } - i += width(value[i]) - } else if !write(emitter, value, &i) { - return false - } - spaces = true - } else { - if !write(emitter, value, &i) { - return false - } - spaces = false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) { - return false - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool { - if is_space(value, 0) || is_break(value, 0) { - indent_hint := []byte{'0' + byte(emitter.best_indent)} - if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) { - return false - } - } - - emitter.open_ended = false - - var chomp_hint [1]byte - if len(value) == 0 { - chomp_hint[0] = '-' - } else { - i := len(value) - 1 - for value[i]&0xC0 == 0x80 { - i-- - } - if !is_break(value, i) { - chomp_hint[0] = '-' - } else if i == 0 { - chomp_hint[0] = '+' - emitter.open_ended = true - } else { - i-- - for value[i]&0xC0 == 0x80 { - i-- - } - if is_break(value, i) { - chomp_hint[0] = '+' - emitter.open_ended = true - } - } - } - if chomp_hint[0] != 0 { - if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) { - return false - } - } - return true -} - -func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool { - if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) { - return false - } - if !yaml_emitter_write_block_scalar_hints(emitter, value) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - //emitter.indention = true - emitter.whitespace = true - breaks := true - for i := 0; i < len(value); { - if is_break(value, i) { - if !write_break(emitter, value, &i) { - return false - } - //emitter.indention = true - breaks = true - } else { - if breaks { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !write(emitter, value, &i) { - return false - } - emitter.indention = false - breaks = false - } - } - - return true -} - -func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool { - if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) { - return false - } - if !yaml_emitter_write_block_scalar_hints(emitter, value) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - - //emitter.indention = true - emitter.whitespace = true - - breaks := true - leading_spaces := true - for i := 0; i < len(value); { - if is_break(value, i) { - if !breaks && !leading_spaces && value[i] == '\n' { - k := 0 - for is_break(value, k) { - k += width(value[k]) - } - if !is_blankz(value, k) { - if !put_break(emitter) { - return false - } - } - } - if !write_break(emitter, value, &i) { - return false - } - //emitter.indention = true - breaks = true - } else { - if breaks { - if !yaml_emitter_write_indent(emitter) { - return false - } - leading_spaces = is_blank(value, i) - } - if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width { - if !yaml_emitter_write_indent(emitter) { - return false - } - i += width(value[i]) - } else { - if !write(emitter, value, &i) { - return false - } - } - emitter.indention = false - breaks = false - } - } - return true -} - -func yaml_emitter_write_comment(emitter *yaml_emitter_t, comment []byte) bool { - breaks := false - pound := false - for i := 0; i < len(comment); { - if is_break(comment, i) { - if !write_break(emitter, comment, &i) { - return false - } - //emitter.indention = true - breaks = true - pound = false - } else { - if breaks && !yaml_emitter_write_indent(emitter) { - return false - } - if !pound { - if comment[i] != '#' && (!put(emitter, '#') || !put(emitter, ' ')) { - return false - } - pound = true - } - if !write(emitter, comment, &i) { - return false - } - emitter.indention = false - breaks = false - } - } - if !breaks && !put_break(emitter) { - return false - } - - emitter.whitespace = true - //emitter.indention = true - return true -} diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/encode.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/encode.go deleted file mode 100644 index de9e72a..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/encode.go +++ /dev/null @@ -1,577 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yaml - -import ( - "encoding" - "fmt" - "io" - "reflect" - "regexp" - "sort" - "strconv" - "strings" - "time" - "unicode/utf8" -) - -type encoder struct { - emitter yaml_emitter_t - event yaml_event_t - out []byte - flow bool - indent int - doneInit bool -} - -func newEncoder() *encoder { - e := &encoder{} - yaml_emitter_initialize(&e.emitter) - yaml_emitter_set_output_string(&e.emitter, &e.out) - yaml_emitter_set_unicode(&e.emitter, true) - return e -} - -func newEncoderWithWriter(w io.Writer) *encoder { - e := &encoder{} - yaml_emitter_initialize(&e.emitter) - yaml_emitter_set_output_writer(&e.emitter, w) - yaml_emitter_set_unicode(&e.emitter, true) - return e -} - -func (e *encoder) init() { - if e.doneInit { - return - } - if e.indent == 0 { - e.indent = 4 - } - e.emitter.best_indent = e.indent - yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING) - e.emit() - e.doneInit = true -} - -func (e *encoder) finish() { - e.emitter.open_ended = false - yaml_stream_end_event_initialize(&e.event) - e.emit() -} - -func (e *encoder) destroy() { - yaml_emitter_delete(&e.emitter) -} - -func (e *encoder) emit() { - // This will internally delete the e.event value. - e.must(yaml_emitter_emit(&e.emitter, &e.event)) -} - -func (e *encoder) must(ok bool) { - if !ok { - msg := e.emitter.problem - if msg == "" { - msg = "unknown problem generating YAML content" - } - failf("%s", msg) - } -} - -func (e *encoder) marshalDoc(tag string, in reflect.Value) { - e.init() - var node *Node - if in.IsValid() { - node, _ = in.Interface().(*Node) - } - if node != nil && node.Kind == DocumentNode { - e.nodev(in) - } else { - yaml_document_start_event_initialize(&e.event, nil, nil, true) - e.emit() - e.marshal(tag, in) - yaml_document_end_event_initialize(&e.event, true) - e.emit() - } -} - -func (e *encoder) marshal(tag string, in reflect.Value) { - tag = shortTag(tag) - if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() { - e.nilv() - return - } - iface := in.Interface() - switch value := iface.(type) { - case *Node: - e.nodev(in) - return - case Node: - if !in.CanAddr() { - var n = reflect.New(in.Type()).Elem() - n.Set(in) - in = n - } - e.nodev(in.Addr()) - return - case time.Time: - e.timev(tag, in) - return - case *time.Time: - e.timev(tag, in.Elem()) - return - case time.Duration: - e.stringv(tag, reflect.ValueOf(value.String())) - return - case Marshaler: - v, err := value.MarshalYAML() - if err != nil { - fail(err) - } - if v == nil { - e.nilv() - return - } - e.marshal(tag, reflect.ValueOf(v)) - return - case encoding.TextMarshaler: - text, err := value.MarshalText() - if err != nil { - fail(err) - } - in = reflect.ValueOf(string(text)) - case nil: - e.nilv() - return - } - switch in.Kind() { - case reflect.Interface: - e.marshal(tag, in.Elem()) - case reflect.Map: - e.mapv(tag, in) - case reflect.Ptr: - e.marshal(tag, in.Elem()) - case reflect.Struct: - e.structv(tag, in) - case reflect.Slice, reflect.Array: - e.slicev(tag, in) - case reflect.String: - e.stringv(tag, in) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - e.intv(tag, in) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - e.uintv(tag, in) - case reflect.Float32, reflect.Float64: - e.floatv(tag, in) - case reflect.Bool: - e.boolv(tag, in) - default: - panic("cannot marshal type: " + in.Type().String()) - } -} - -func (e *encoder) mapv(tag string, in reflect.Value) { - e.mappingv(tag, func() { - keys := keyList(in.MapKeys()) - sort.Sort(keys) - for _, k := range keys { - e.marshal("", k) - e.marshal("", in.MapIndex(k)) - } - }) -} - -func (e *encoder) fieldByIndex(v reflect.Value, index []int) (field reflect.Value) { - for _, num := range index { - for { - if v.Kind() == reflect.Ptr { - if v.IsNil() { - return reflect.Value{} - } - v = v.Elem() - continue - } - break - } - v = v.Field(num) - } - return v -} - -func (e *encoder) structv(tag string, in reflect.Value) { - sinfo, err := getStructInfo(in.Type()) - if err != nil { - panic(err) - } - e.mappingv(tag, func() { - for _, info := range sinfo.FieldsList { - var value reflect.Value - if info.Inline == nil { - value = in.Field(info.Num) - } else { - value = e.fieldByIndex(in, info.Inline) - if !value.IsValid() { - continue - } - } - if info.OmitEmpty && isZero(value) { - continue - } - e.marshal("", reflect.ValueOf(info.Key)) - e.flow = info.Flow - e.marshal("", value) - } - if sinfo.InlineMap >= 0 { - m := in.Field(sinfo.InlineMap) - if m.Len() > 0 { - e.flow = false - keys := keyList(m.MapKeys()) - sort.Sort(keys) - for _, k := range keys { - if _, found := sinfo.FieldsMap[k.String()]; found { - panic(fmt.Sprintf("cannot have key %q in inlined map: conflicts with struct field", k.String())) - } - e.marshal("", k) - e.flow = false - e.marshal("", m.MapIndex(k)) - } - } - } - }) -} - -func (e *encoder) mappingv(tag string, f func()) { - implicit := tag == "" - style := yaml_BLOCK_MAPPING_STYLE - if e.flow { - e.flow = false - style = yaml_FLOW_MAPPING_STYLE - } - yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style) - e.emit() - f() - yaml_mapping_end_event_initialize(&e.event) - e.emit() -} - -func (e *encoder) slicev(tag string, in reflect.Value) { - implicit := tag == "" - style := yaml_BLOCK_SEQUENCE_STYLE - if e.flow { - e.flow = false - style = yaml_FLOW_SEQUENCE_STYLE - } - e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) - e.emit() - n := in.Len() - for i := 0; i < n; i++ { - e.marshal("", in.Index(i)) - } - e.must(yaml_sequence_end_event_initialize(&e.event)) - e.emit() -} - -// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. -// -// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported -// in YAML 1.2 and by this package, but these should be marshalled quoted for -// the time being for compatibility with other parsers. -func isBase60Float(s string) (result bool) { - // Fast path. - if s == "" { - return false - } - c := s[0] - if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { - return false - } - // Do the full match. - return base60float.MatchString(s) -} - -// From http://yaml.org/type/float.html, except the regular expression there -// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. -var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) - -// isOldBool returns whether s is bool notation as defined in YAML 1.1. -// -// We continue to force strings that YAML 1.1 would interpret as booleans to be -// rendered as quotes strings so that the marshalled output valid for YAML 1.1 -// parsing. -func isOldBool(s string) (result bool) { - switch s { - case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON", - "n", "N", "no", "No", "NO", "off", "Off", "OFF": - return true - default: - return false - } -} - -func (e *encoder) stringv(tag string, in reflect.Value) { - var style yaml_scalar_style_t - s := in.String() - canUsePlain := true - switch { - case !utf8.ValidString(s): - if tag == binaryTag { - failf("explicitly tagged !!binary data must be base64-encoded") - } - if tag != "" { - failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag)) - } - // It can't be encoded directly as YAML so use a binary tag - // and encode it as base64. - tag = binaryTag - s = encodeBase64(s) - case tag == "": - // Check to see if it would resolve to a specific - // tag when encoded unquoted. If it doesn't, - // there's no need to quote it. - rtag, _ := resolve("", s) - canUsePlain = rtag == strTag && !(isBase60Float(s) || isOldBool(s)) - } - // Note: it's possible for user code to emit invalid YAML - // if they explicitly specify a tag and a string containing - // text that's incompatible with that tag. - switch { - case strings.Contains(s, "\n"): - if e.flow { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } else { - style = yaml_LITERAL_SCALAR_STYLE - } - case canUsePlain: - style = yaml_PLAIN_SCALAR_STYLE - default: - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - e.emitScalar(s, "", tag, style, nil, nil, nil, nil) -} - -func (e *encoder) boolv(tag string, in reflect.Value) { - var s string - if in.Bool() { - s = "true" - } else { - s = "false" - } - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) -} - -func (e *encoder) intv(tag string, in reflect.Value) { - s := strconv.FormatInt(in.Int(), 10) - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) -} - -func (e *encoder) uintv(tag string, in reflect.Value) { - s := strconv.FormatUint(in.Uint(), 10) - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) -} - -func (e *encoder) timev(tag string, in reflect.Value) { - t := in.Interface().(time.Time) - s := t.Format(time.RFC3339Nano) - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) -} - -func (e *encoder) floatv(tag string, in reflect.Value) { - // Issue #352: When formatting, use the precision of the underlying value - precision := 64 - if in.Kind() == reflect.Float32 { - precision = 32 - } - - s := strconv.FormatFloat(in.Float(), 'g', -1, precision) - switch s { - case "+Inf": - s = ".inf" - case "-Inf": - s = "-.inf" - case "NaN": - s = ".nan" - } - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) -} - -func (e *encoder) nilv() { - e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) -} - -func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t, head, line, foot, tail []byte) { - // TODO Kill this function. Replace all initialize calls by their underlining Go literals. - implicit := tag == "" - if !implicit { - tag = longTag(tag) - } - e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) - e.event.head_comment = head - e.event.line_comment = line - e.event.foot_comment = foot - e.event.tail_comment = tail - e.emit() -} - -func (e *encoder) nodev(in reflect.Value) { - e.node(in.Interface().(*Node), "") -} - -func (e *encoder) node(node *Node, tail string) { - // Zero nodes behave as nil. - if node.Kind == 0 && node.IsZero() { - e.nilv() - return - } - - // If the tag was not explicitly requested, and dropping it won't change the - // implicit tag of the value, don't include it in the presentation. - var tag = node.Tag - var stag = shortTag(tag) - var forceQuoting bool - if tag != "" && node.Style&TaggedStyle == 0 { - if node.Kind == ScalarNode { - if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 { - tag = "" - } else { - rtag, _ := resolve("", node.Value) - if rtag == stag { - tag = "" - } else if stag == strTag { - tag = "" - forceQuoting = true - } - } - } else { - var rtag string - switch node.Kind { - case MappingNode: - rtag = mapTag - case SequenceNode: - rtag = seqTag - } - if rtag == stag { - tag = "" - } - } - } - - switch node.Kind { - case DocumentNode: - yaml_document_start_event_initialize(&e.event, nil, nil, true) - e.event.head_comment = []byte(node.HeadComment) - e.emit() - for _, node := range node.Content { - e.node(node, "") - } - yaml_document_end_event_initialize(&e.event, true) - e.event.foot_comment = []byte(node.FootComment) - e.emit() - - case SequenceNode: - style := yaml_BLOCK_SEQUENCE_STYLE - if node.Style&FlowStyle != 0 { - style = yaml_FLOW_SEQUENCE_STYLE - } - e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style)) - e.event.head_comment = []byte(node.HeadComment) - e.emit() - for _, node := range node.Content { - e.node(node, "") - } - e.must(yaml_sequence_end_event_initialize(&e.event)) - e.event.line_comment = []byte(node.LineComment) - e.event.foot_comment = []byte(node.FootComment) - e.emit() - - case MappingNode: - style := yaml_BLOCK_MAPPING_STYLE - if node.Style&FlowStyle != 0 { - style = yaml_FLOW_MAPPING_STYLE - } - yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style) - e.event.tail_comment = []byte(tail) - e.event.head_comment = []byte(node.HeadComment) - e.emit() - - // The tail logic below moves the foot comment of prior keys to the following key, - // since the value for each key may be a nested structure and the foot needs to be - // processed only the entirety of the value is streamed. The last tail is processed - // with the mapping end event. - var tail string - for i := 0; i+1 < len(node.Content); i += 2 { - k := node.Content[i] - foot := k.FootComment - if foot != "" { - kopy := *k - kopy.FootComment = "" - k = &kopy - } - e.node(k, tail) - tail = foot - - v := node.Content[i+1] - e.node(v, "") - } - - yaml_mapping_end_event_initialize(&e.event) - e.event.tail_comment = []byte(tail) - e.event.line_comment = []byte(node.LineComment) - e.event.foot_comment = []byte(node.FootComment) - e.emit() - - case AliasNode: - yaml_alias_event_initialize(&e.event, []byte(node.Value)) - e.event.head_comment = []byte(node.HeadComment) - e.event.line_comment = []byte(node.LineComment) - e.event.foot_comment = []byte(node.FootComment) - e.emit() - - case ScalarNode: - value := node.Value - if !utf8.ValidString(value) { - if stag == binaryTag { - failf("explicitly tagged !!binary data must be base64-encoded") - } - if stag != "" { - failf("cannot marshal invalid UTF-8 data as %s", stag) - } - // It can't be encoded directly as YAML so use a binary tag - // and encode it as base64. - tag = binaryTag - value = encodeBase64(value) - } - - style := yaml_PLAIN_SCALAR_STYLE - switch { - case node.Style&DoubleQuotedStyle != 0: - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - case node.Style&SingleQuotedStyle != 0: - style = yaml_SINGLE_QUOTED_SCALAR_STYLE - case node.Style&LiteralStyle != 0: - style = yaml_LITERAL_SCALAR_STYLE - case node.Style&FoldedStyle != 0: - style = yaml_FOLDED_SCALAR_STYLE - case strings.Contains(value, "\n"): - style = yaml_LITERAL_SCALAR_STYLE - case forceQuoting: - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - - e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail)) - default: - failf("cannot encode node with unknown kind %d", node.Kind) - } -} diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/encode_test.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/encode_test.go deleted file mode 100644 index 4a8bf2e..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/encode_test.go +++ /dev/null @@ -1,736 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yaml_test - -import ( - "bytes" - "fmt" - "math" - "strconv" - "strings" - "time" - - "net" - "os" - - . "gopkg.in/check.v1" - "gopkg.in/yaml.v3" -) - -var marshalIntTest = 123 - -var marshalTests = []struct { - value interface{} - data string -}{ - { - nil, - "null\n", - }, { - (*marshalerType)(nil), - "null\n", - }, { - &struct{}{}, - "{}\n", - }, { - map[string]string{"v": "hi"}, - "v: hi\n", - }, { - map[string]interface{}{"v": "hi"}, - "v: hi\n", - }, { - map[string]string{"v": "true"}, - "v: \"true\"\n", - }, { - map[string]string{"v": "false"}, - "v: \"false\"\n", - }, { - map[string]interface{}{"v": true}, - "v: true\n", - }, { - map[string]interface{}{"v": false}, - "v: false\n", - }, { - map[string]interface{}{"v": 10}, - "v: 10\n", - }, { - map[string]interface{}{"v": -10}, - "v: -10\n", - }, { - map[string]uint{"v": 42}, - "v: 42\n", - }, { - map[string]interface{}{"v": int64(4294967296)}, - "v: 4294967296\n", - }, { - map[string]int64{"v": int64(4294967296)}, - "v: 4294967296\n", - }, { - map[string]uint64{"v": 4294967296}, - "v: 4294967296\n", - }, { - map[string]interface{}{"v": "10"}, - "v: \"10\"\n", - }, { - map[string]interface{}{"v": 0.1}, - "v: 0.1\n", - }, { - map[string]interface{}{"v": float64(0.1)}, - "v: 0.1\n", - }, { - map[string]interface{}{"v": float32(0.99)}, - "v: 0.99\n", - }, { - map[string]interface{}{"v": -0.1}, - "v: -0.1\n", - }, { - map[string]interface{}{"v": math.Inf(+1)}, - "v: .inf\n", - }, { - map[string]interface{}{"v": math.Inf(-1)}, - "v: -.inf\n", - }, { - map[string]interface{}{"v": math.NaN()}, - "v: .nan\n", - }, { - map[string]interface{}{"v": nil}, - "v: null\n", - }, { - map[string]interface{}{"v": ""}, - "v: \"\"\n", - }, { - map[string][]string{"v": []string{"A", "B"}}, - "v:\n - A\n - B\n", - }, { - map[string][]string{"v": []string{"A", "B\nC"}}, - "v:\n - A\n - |-\n B\n C\n", - }, { - map[string][]interface{}{"v": []interface{}{"A", 1, map[string][]int{"B": []int{2, 3}}}}, - "v:\n - A\n - 1\n - B:\n - 2\n - 3\n", - }, { - map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}}, - "a:\n b: c\n", - }, { - map[string]interface{}{"a": "-"}, - "a: '-'\n", - }, - - // Simple values. - { - &marshalIntTest, - "123\n", - }, - - // Structures - { - &struct{ Hello string }{"world"}, - "hello: world\n", - }, { - &struct { - A struct { - B string - } - }{struct{ B string }{"c"}}, - "a:\n b: c\n", - }, { - &struct { - A *struct { - B string - } - }{&struct{ B string }{"c"}}, - "a:\n b: c\n", - }, { - &struct { - A *struct { - B string - } - }{}, - "a: null\n", - }, { - &struct{ A int }{1}, - "a: 1\n", - }, { - &struct{ A []int }{[]int{1, 2}}, - "a:\n - 1\n - 2\n", - }, { - &struct{ A [2]int }{[2]int{1, 2}}, - "a:\n - 1\n - 2\n", - }, { - &struct { - B int "a" - }{1}, - "a: 1\n", - }, { - &struct{ A bool }{true}, - "a: true\n", - }, { - &struct{ A string }{"true"}, - "a: \"true\"\n", - }, { - &struct{ A string }{"off"}, - "a: \"off\"\n", - }, - - // Conditional flag - { - &struct { - A int "a,omitempty" - B int "b,omitempty" - }{1, 0}, - "a: 1\n", - }, { - &struct { - A int "a,omitempty" - B int "b,omitempty" - }{0, 0}, - "{}\n", - }, { - &struct { - A *struct{ X, y int } "a,omitempty,flow" - }{&struct{ X, y int }{1, 2}}, - "a: {x: 1}\n", - }, { - &struct { - A *struct{ X, y int } "a,omitempty,flow" - }{nil}, - "{}\n", - }, { - &struct { - A *struct{ X, y int } "a,omitempty,flow" - }{&struct{ X, y int }{}}, - "a: {x: 0}\n", - }, { - &struct { - A struct{ X, y int } "a,omitempty,flow" - }{struct{ X, y int }{1, 2}}, - "a: {x: 1}\n", - }, { - &struct { - A struct{ X, y int } "a,omitempty,flow" - }{struct{ X, y int }{0, 1}}, - "{}\n", - }, { - &struct { - A float64 "a,omitempty" - B float64 "b,omitempty" - }{1, 0}, - "a: 1\n", - }, - { - &struct { - T1 time.Time "t1,omitempty" - T2 time.Time "t2,omitempty" - T3 *time.Time "t3,omitempty" - T4 *time.Time "t4,omitempty" - }{ - T2: time.Date(2018, 1, 9, 10, 40, 47, 0, time.UTC), - T4: newTime(time.Date(2098, 1, 9, 10, 40, 47, 0, time.UTC)), - }, - "t2: 2018-01-09T10:40:47Z\nt4: 2098-01-09T10:40:47Z\n", - }, - // Nil interface that implements Marshaler. - { - map[string]yaml.Marshaler{ - "a": nil, - }, - "a: null\n", - }, - - // Flow flag - { - &struct { - A []int "a,flow" - }{[]int{1, 2}}, - "a: [1, 2]\n", - }, { - &struct { - A map[string]string "a,flow" - }{map[string]string{"b": "c", "d": "e"}}, - "a: {b: c, d: e}\n", - }, { - &struct { - A struct { - B, D string - } "a,flow" - }{struct{ B, D string }{"c", "e"}}, - "a: {b: c, d: e}\n", - }, { - &struct { - A string "a,flow" - }{"b\nc"}, - "a: \"b\\nc\"\n", - }, - - // Unexported field - { - &struct { - u int - A int - }{0, 1}, - "a: 1\n", - }, - - // Ignored field - { - &struct { - A int - B int "-" - }{1, 2}, - "a: 1\n", - }, - - // Struct inlining - { - &struct { - A int - C inlineB `yaml:",inline"` - }{1, inlineB{2, inlineC{3}}}, - "a: 1\nb: 2\nc: 3\n", - }, - // Struct inlining as a pointer - { - &struct { - A int - C *inlineB `yaml:",inline"` - }{1, &inlineB{2, inlineC{3}}}, - "a: 1\nb: 2\nc: 3\n", - }, { - &struct { - A int - C *inlineB `yaml:",inline"` - }{1, nil}, - "a: 1\n", - }, { - &struct { - A int - D *inlineD `yaml:",inline"` - }{1, &inlineD{&inlineC{3}, 4}}, - "a: 1\nc: 3\nd: 4\n", - }, - - // Map inlining - { - &struct { - A int - C map[string]int `yaml:",inline"` - }{1, map[string]int{"b": 2, "c": 3}}, - "a: 1\nb: 2\nc: 3\n", - }, - - // Duration - { - map[string]time.Duration{"a": 3 * time.Second}, - "a: 3s\n", - }, - - // Issue #24: bug in map merging logic. - { - map[string]string{"a": "<foo>"}, - "a: <foo>\n", - }, - - // Issue #34: marshal unsupported base 60 floats quoted for compatibility - // with old YAML 1.1 parsers. - { - map[string]string{"a": "1:1"}, - "a: \"1:1\"\n", - }, - - // Binary data. - { - map[string]string{"a": "\x00"}, - "a: \"\\0\"\n", - }, { - map[string]string{"a": "\x80\x81\x82"}, - "a: !!binary gIGC\n", - }, { - map[string]string{"a": strings.Repeat("\x90", 54)}, - "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n", - }, - - // Encode unicode as utf-8 rather than in escaped form. - { - map[string]string{"a": "你好"}, - "a: 你好\n", - }, - - // Support encoding.TextMarshaler. - { - map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)}, - "a: 1.2.3.4\n", - }, - // time.Time gets a timestamp tag. - { - map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)}, - "a: 2015-02-24T18:19:39Z\n", - }, - { - map[string]*time.Time{"a": newTime(time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC))}, - "a: 2015-02-24T18:19:39Z\n", - }, - { - // This is confirmed to be properly decoded in Python (libyaml) without a timestamp tag. - map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 123456789, time.FixedZone("FOO", -3*60*60))}, - "a: 2015-02-24T18:19:39.123456789-03:00\n", - }, - // Ensure timestamp-like strings are quoted. - { - map[string]string{"a": "2015-02-24T18:19:39Z"}, - "a: \"2015-02-24T18:19:39Z\"\n", - }, - - // Ensure strings containing ": " are quoted (reported as PR #43, but not reproducible). - { - map[string]string{"a": "b: c"}, - "a: 'b: c'\n", - }, - - // Containing hash mark ('#') in string should be quoted - { - map[string]string{"a": "Hello #comment"}, - "a: 'Hello #comment'\n", - }, - { - map[string]string{"a": "你好 #comment"}, - "a: '你好 #comment'\n", - }, - - // Ensure MarshalYAML also gets called on the result of MarshalYAML itself. - { - &marshalerType{marshalerType{true}}, - "true\n", - }, { - &marshalerType{&marshalerType{true}}, - "true\n", - }, - - // Check indentation of maps inside sequences inside maps. - { - map[string]interface{}{"a": map[string]interface{}{"b": []map[string]int{{"c": 1, "d": 2}}}}, - "a:\n b:\n - c: 1\n d: 2\n", - }, - - // Strings with tabs were disallowed as literals (issue #471). - { - map[string]string{"a": "\tB\n\tC\n"}, - "a: |\n \tB\n \tC\n", - }, - - // Ensure that strings do not wrap - { - map[string]string{"a": "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 "}, - "a: 'abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 '\n", - }, - - // yaml.Node - { - &struct { - Value yaml.Node - }{ - yaml.Node{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "foo", - Style: yaml.SingleQuotedStyle, - }, - }, - "value: 'foo'\n", - }, { - yaml.Node{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "foo", - Style: yaml.SingleQuotedStyle, - }, - "'foo'\n", - }, - - // Enforced tagging with shorthand notation (issue #616). - { - &struct { - Value yaml.Node - }{ - yaml.Node{ - Kind: yaml.ScalarNode, - Style: yaml.TaggedStyle, - Value: "foo", - Tag: "!!str", - }, - }, - "value: !!str foo\n", - }, { - &struct { - Value yaml.Node - }{ - yaml.Node{ - Kind: yaml.MappingNode, - Style: yaml.TaggedStyle, - Tag: "!!map", - }, - }, - "value: !!map {}\n", - }, { - &struct { - Value yaml.Node - }{ - yaml.Node{ - Kind: yaml.SequenceNode, - Style: yaml.TaggedStyle, - Tag: "!!seq", - }, - }, - "value: !!seq []\n", - }, -} - -func (s *S) TestMarshal(c *C) { - defer os.Setenv("TZ", os.Getenv("TZ")) - os.Setenv("TZ", "UTC") - for i, item := range marshalTests { - c.Logf("test %d: %q", i, item.data) - data, err := yaml.Marshal(item.value) - c.Assert(err, IsNil) - c.Assert(string(data), Equals, item.data) - } -} - -func (s *S) TestEncoderSingleDocument(c *C) { - for i, item := range marshalTests { - c.Logf("test %d. %q", i, item.data) - var buf bytes.Buffer - enc := yaml.NewEncoder(&buf) - err := enc.Encode(item.value) - c.Assert(err, Equals, nil) - err = enc.Close() - c.Assert(err, Equals, nil) - c.Assert(buf.String(), Equals, item.data) - } -} - -func (s *S) TestEncoderMultipleDocuments(c *C) { - var buf bytes.Buffer - enc := yaml.NewEncoder(&buf) - err := enc.Encode(map[string]string{"a": "b"}) - c.Assert(err, Equals, nil) - err = enc.Encode(map[string]string{"c": "d"}) - c.Assert(err, Equals, nil) - err = enc.Close() - c.Assert(err, Equals, nil) - c.Assert(buf.String(), Equals, "a: b\n---\nc: d\n") -} - -func (s *S) TestEncoderWriteError(c *C) { - enc := yaml.NewEncoder(errorWriter{}) - err := enc.Encode(map[string]string{"a": "b"}) - c.Assert(err, ErrorMatches, `yaml: write error: some write error`) // Data not flushed yet -} - -type errorWriter struct{} - -func (errorWriter) Write([]byte) (int, error) { - return 0, fmt.Errorf("some write error") -} - -var marshalErrorTests = []struct { - value interface{} - error string - panic string -}{{ - value: &struct { - B int - inlineB ",inline" - }{1, inlineB{2, inlineC{3}}}, - panic: `duplicated key 'b' in struct struct \{ B int; .*`, -}, { - value: &struct { - A int - B map[string]int ",inline" - }{1, map[string]int{"a": 2}}, - panic: `cannot have key "a" in inlined map: conflicts with struct field`, -}} - -func (s *S) TestMarshalErrors(c *C) { - for _, item := range marshalErrorTests { - if item.panic != "" { - c.Assert(func() { yaml.Marshal(item.value) }, PanicMatches, item.panic) - } else { - _, err := yaml.Marshal(item.value) - c.Assert(err, ErrorMatches, item.error) - } - } -} - -func (s *S) TestMarshalTypeCache(c *C) { - var data []byte - var err error - func() { - type T struct{ A int } - data, err = yaml.Marshal(&T{}) - c.Assert(err, IsNil) - }() - func() { - type T struct{ B int } - data, err = yaml.Marshal(&T{}) - c.Assert(err, IsNil) - }() - c.Assert(string(data), Equals, "b: 0\n") -} - -var marshalerTests = []struct { - data string - value interface{} -}{ - {"_:\n hi: there\n", map[interface{}]interface{}{"hi": "there"}}, - {"_:\n - 1\n - A\n", []interface{}{1, "A"}}, - {"_: 10\n", 10}, - {"_: null\n", nil}, - {"_: BAR!\n", "BAR!"}, -} - -type marshalerType struct { - value interface{} -} - -func (o marshalerType) MarshalText() ([]byte, error) { - panic("MarshalText called on type with MarshalYAML") -} - -func (o marshalerType) MarshalYAML() (interface{}, error) { - return o.value, nil -} - -type marshalerValue struct { - Field marshalerType "_" -} - -func (s *S) TestMarshaler(c *C) { - for _, item := range marshalerTests { - obj := &marshalerValue{} - obj.Field.value = item.value - data, err := yaml.Marshal(obj) - c.Assert(err, IsNil) - c.Assert(string(data), Equals, string(item.data)) - } -} - -func (s *S) TestMarshalerWholeDocument(c *C) { - obj := &marshalerType{} - obj.value = map[string]string{"hello": "world!"} - data, err := yaml.Marshal(obj) - c.Assert(err, IsNil) - c.Assert(string(data), Equals, "hello: world!\n") -} - -type failingMarshaler struct{} - -func (ft *failingMarshaler) MarshalYAML() (interface{}, error) { - return nil, failingErr -} - -func (s *S) TestMarshalerError(c *C) { - _, err := yaml.Marshal(&failingMarshaler{}) - c.Assert(err, Equals, failingErr) -} - -func (s *S) TestSetIndent(c *C) { - var buf bytes.Buffer - enc := yaml.NewEncoder(&buf) - enc.SetIndent(8) - err := enc.Encode(map[string]interface{}{"a": map[string]interface{}{"b": map[string]string{"c": "d"}}}) - c.Assert(err, Equals, nil) - err = enc.Close() - c.Assert(err, Equals, nil) - c.Assert(buf.String(), Equals, "a:\n b:\n c: d\n") -} - -func (s *S) TestSortedOutput(c *C) { - order := []interface{}{ - false, - true, - 1, - uint(1), - 1.0, - 1.1, - 1.2, - 2, - uint(2), - 2.0, - 2.1, - "", - ".1", - ".2", - ".a", - "1", - "2", - "a!10", - "a/0001", - "a/002", - "a/3", - "a/10", - "a/11", - "a/0012", - "a/100", - "a~10", - "ab/1", - "b/1", - "b/01", - "b/2", - "b/02", - "b/3", - "b/03", - "b1", - "b01", - "b3", - "c2.10", - "c10.2", - "d1", - "d7", - "d7abc", - "d12", - "d12a", - "e2b", - "e4b", - "e21a", - } - m := make(map[interface{}]int) - for _, k := range order { - m[k] = 1 - } - data, err := yaml.Marshal(m) - c.Assert(err, IsNil) - out := "\n" + string(data) - last := 0 - for i, k := range order { - repr := fmt.Sprint(k) - if s, ok := k.(string); ok { - if _, err = strconv.ParseFloat(repr, 32); s == "" || err == nil { - repr = `"` + repr + `"` - } - } - index := strings.Index(out, "\n"+repr+":") - if index == -1 { - c.Fatalf("%#v is not in the output: %#v", k, out) - } - if index < last { - c.Fatalf("%#v was generated before %#v: %q", k, order[i-1], out) - } - last = index - } -} - -func newTime(t time.Time) *time.Time { - return &t -} diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/example_embedded_test.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/example_embedded_test.go deleted file mode 100644 index 9d17398..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/example_embedded_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yaml_test - -import ( - "fmt" - "log" - - "gopkg.in/yaml.v3" -) - -// An example showing how to unmarshal embedded -// structs from YAML. - -type StructA struct { - A string `yaml:"a"` -} - -type StructB struct { - // Embedded structs are not treated as embedded in YAML by default. To do that, - // add the ",inline" annotation below - StructA `yaml:",inline"` - B string `yaml:"b"` -} - -var data = ` -a: a string from struct A -b: a string from struct B -` - -func ExampleUnmarshal_embedded() { - var b StructB - - err := yaml.Unmarshal([]byte(data), &b) - if err != nil { - log.Fatalf("cannot unmarshal data: %v", err) - } - fmt.Println(b.A) - fmt.Println(b.B) - // Output: - // a string from struct A - // a string from struct B -} diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/go.mod b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/go.mod deleted file mode 100644 index f407ea3..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module "gopkg.in/yaml.v3" - -require ( - "gopkg.in/check.v1" v0.0.0-20161208181325-20d25e280405 -) diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/limit_test.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/limit_test.go deleted file mode 100644 index 07a3cbd..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/limit_test.go +++ /dev/null @@ -1,128 +0,0 @@ -package yaml_test - -import ( - "strings" - "testing" - - . "gopkg.in/check.v1" - "gopkg.in/yaml.v3" -) - -var limitTests = []struct { - name string - data []byte - error string -}{ - { - name: "1000kb of maps with 100 aliases", - data: []byte(`{a: &a [{a}` + strings.Repeat(`,{a}`, 1000*1024/4-100) + `], b: &b [*a` + strings.Repeat(`,*a`, 99) + `]}`), - error: "yaml: document contains excessive aliasing", - }, { - name: "1000kb of deeply nested slices", - data: []byte(strings.Repeat(`[`, 1000*1024)), - error: "yaml: exceeded max depth of 10000", - }, { - name: "1000kb of deeply nested maps", - data: []byte("x: " + strings.Repeat(`{`, 1000*1024)), - error: "yaml: exceeded max depth of 10000", - }, { - name: "1000kb of deeply nested indents", - data: []byte(strings.Repeat(`- `, 1000*1024)), - error: "yaml: exceeded max depth of 10000", - }, { - name: "1000kb of 1000-indent lines", - data: []byte(strings.Repeat(strings.Repeat(`- `, 1000)+"\n", 1024/2)), - }, - {name: "1kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 1*1024/4-1) + `]`)}, - {name: "10kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 10*1024/4-1) + `]`)}, - {name: "100kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 100*1024/4-1) + `]`)}, - {name: "1000kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 1000*1024/4-1) + `]`)}, - {name: "1000kb slice nested at max-depth", data: []byte(strings.Repeat(`[`, 10000) + `1` + strings.Repeat(`,1`, 1000*1024/2-20000-1) + strings.Repeat(`]`, 10000))}, - {name: "1000kb slice nested in maps at max-depth", data: []byte("{a,b:\n" + strings.Repeat(" {a,b:", 10000-2) + ` [1` + strings.Repeat(",1", 1000*1024/2-6*10000-1) + `]` + strings.Repeat(`}`, 10000-1))}, - {name: "1000kb of 10000-nested lines", data: []byte(strings.Repeat(`- `+strings.Repeat(`[`, 10000)+strings.Repeat(`]`, 10000)+"\n", 1000*1024/20000))}, -} - -func (s *S) TestLimits(c *C) { - if testing.Short() { - return - } - for _, tc := range limitTests { - var v interface{} - err := yaml.Unmarshal(tc.data, &v) - if len(tc.error) > 0 { - c.Assert(err, ErrorMatches, tc.error, Commentf("testcase: %s", tc.name)) - } else { - c.Assert(err, IsNil, Commentf("testcase: %s", tc.name)) - } - } -} - -func Benchmark1000KB100Aliases(b *testing.B) { - benchmark(b, "1000kb of maps with 100 aliases") -} -func Benchmark1000KBDeeplyNestedSlices(b *testing.B) { - benchmark(b, "1000kb of deeply nested slices") -} -func Benchmark1000KBDeeplyNestedMaps(b *testing.B) { - benchmark(b, "1000kb of deeply nested maps") -} -func Benchmark1000KBDeeplyNestedIndents(b *testing.B) { - benchmark(b, "1000kb of deeply nested indents") -} -func Benchmark1000KB1000IndentLines(b *testing.B) { - benchmark(b, "1000kb of 1000-indent lines") -} -func Benchmark1KBMaps(b *testing.B) { - benchmark(b, "1kb of maps") -} -func Benchmark10KBMaps(b *testing.B) { - benchmark(b, "10kb of maps") -} -func Benchmark100KBMaps(b *testing.B) { - benchmark(b, "100kb of maps") -} -func Benchmark1000KBMaps(b *testing.B) { - benchmark(b, "1000kb of maps") -} - -func BenchmarkDeepSlice(b *testing.B) { - benchmark(b, "1000kb slice nested at max-depth") -} - -func BenchmarkDeepFlow(b *testing.B) { - benchmark(b, "1000kb slice nested in maps at max-depth") -} - -func Benchmark1000KBMaxDepthNested(b *testing.B) { - benchmark(b, "1000kb of 10000-nested lines") -} - -func benchmark(b *testing.B, name string) { - for _, t := range limitTests { - if t.name != name { - continue - } - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - var v interface{} - err := yaml.Unmarshal(t.data, &v) - if len(t.error) > 0 { - if err == nil { - b.Errorf("expected error, got none") - } else if err.Error() != t.error { - b.Errorf("expected error '%s', got '%s'", t.error, err.Error()) - } - } else { - if err != nil { - b.Errorf("unexpected error: %v", err) - } - } - } - - return - } - - b.Errorf("testcase %q not found", name) -} diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/node_test.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/node_test.go deleted file mode 100644 index b7d0c9a..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/node_test.go +++ /dev/null @@ -1,2886 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yaml_test - -import ( - "bytes" - "fmt" - "os" - - . "gopkg.in/check.v1" - "gopkg.in/yaml.v3" - "io" - "strings" -) - -var nodeTests = []struct { - yaml string - node yaml.Node -}{ - { - "null\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "null", - Tag: "!!null", - Line: 1, - Column: 1, - }}, - }, - }, { - "[encode]null\n", - yaml.Node{}, - }, { - "foo\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "foo", - Tag: "!!str", - Line: 1, - Column: 1, - }}, - }, - }, { - "\"foo\"\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Style: yaml.DoubleQuotedStyle, - Value: "foo", - Tag: "!!str", - Line: 1, - Column: 1, - }}, - }, - }, { - "'foo'\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Style: yaml.SingleQuotedStyle, - Value: "foo", - Tag: "!!str", - Line: 1, - Column: 1, - }}, - }, - }, { - "!!str 123\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Style: yaml.TaggedStyle, - Value: "123", - Tag: "!!str", - Line: 1, - Column: 1, - }}, - }, - }, { - // Although the node isn't TaggedStyle, dropping the tag would change the value. - "[encode]!!binary gIGC\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "gIGC", - Tag: "!!binary", - Line: 1, - Column: 1, - }}, - }, - }, { - // Item doesn't have a tag, but needs to be binary encoded due to its content. - "[encode]!!binary gIGC\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "\x80\x81\x82", - Line: 1, - Column: 1, - }}, - }, - }, { - // Same, but with strings we can just quote them. - "[encode]\"123\"\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "123", - Tag: "!!str", - Line: 1, - Column: 1, - }}, - }, - }, { - "!tag:something 123\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Style: yaml.TaggedStyle, - Value: "123", - Tag: "!tag:something", - Line: 1, - Column: 1, - }}, - }, - }, { - "[encode]!tag:something 123\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "123", - Tag: "!tag:something", - Line: 1, - Column: 1, - }}, - }, - }, { - "!tag:something {}\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Style: yaml.TaggedStyle | yaml.FlowStyle, - Tag: "!tag:something", - Line: 1, - Column: 1, - }}, - }, - }, { - "[encode]!tag:something {}\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Style: yaml.FlowStyle, - Tag: "!tag:something", - Line: 1, - Column: 1, - }}, - }, - }, { - "!tag:something []\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Style: yaml.TaggedStyle | yaml.FlowStyle, - Tag: "!tag:something", - Line: 1, - Column: 1, - }}, - }, - }, { - "[encode]!tag:something []\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Style: yaml.FlowStyle, - Tag: "!tag:something", - Line: 1, - Column: 1, - }}, - }, - }, { - "''\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Style: yaml.SingleQuotedStyle, - Value: "", - Tag: "!!str", - Line: 1, - Column: 1, - }}, - }, - }, { - "|\n foo\n bar\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Style: yaml.LiteralStyle, - Value: "foo\nbar\n", - Tag: "!!str", - Line: 1, - Column: 1, - }}, - }, - }, { - "true\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "true", - Tag: "!!bool", - Line: 1, - Column: 1, - }}, - }, - }, { - "-10\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "-10", - Tag: "!!int", - Line: 1, - Column: 1, - }}, - }, - }, { - "4294967296\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "4294967296", - Tag: "!!int", - Line: 1, - Column: 1, - }}, - }, - }, { - "0.1000\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "0.1000", - Tag: "!!float", - Line: 1, - Column: 1, - }}, - }, - }, { - "-.inf\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "-.inf", - Tag: "!!float", - Line: 1, - Column: 1, - }}, - }, - }, { - ".nan\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: ".nan", - Tag: "!!float", - Line: 1, - Column: 1, - }}, - }, - }, { - "{}\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Style: yaml.FlowStyle, - Value: "", - Tag: "!!map", - Line: 1, - Column: 1, - }}, - }, - }, { - "a: b c\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Value: "", - Tag: "!!map", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "a", - Tag: "!!str", - Line: 1, - Column: 1, - }, { - Kind: yaml.ScalarNode, - Value: "b c", - Tag: "!!str", - Line: 1, - Column: 4, - }}, - }}, - }, - }, { - "a:\n b: c\n d: e\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "a", - Tag: "!!str", - Line: 1, - Column: 1, - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 2, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "b", - Tag: "!!str", - Line: 2, - Column: 3, - }, { - Kind: yaml.ScalarNode, - Value: "c", - Tag: "!!str", - Line: 2, - Column: 6, - }, { - Kind: yaml.ScalarNode, - Value: "d", - Tag: "!!str", - Line: 3, - Column: 3, - }, { - Kind: yaml.ScalarNode, - Value: "e", - Tag: "!!str", - Line: 3, - Column: 6, - }}, - }}, - }}, - }, - }, { - "a:\n - b: c\n d: e\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "a", - Tag: "!!str", - Line: 1, - Column: 1, - }, { - Kind: yaml.SequenceNode, - Tag: "!!seq", - Line: 2, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 2, - Column: 5, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "b", - Tag: "!!str", - Line: 2, - Column: 5, - }, { - Kind: yaml.ScalarNode, - Value: "c", - Tag: "!!str", - Line: 2, - Column: 8, - }, { - Kind: yaml.ScalarNode, - Value: "d", - Tag: "!!str", - Line: 3, - Column: 5, - }, { - Kind: yaml.ScalarNode, - Value: "e", - Tag: "!!str", - Line: 3, - Column: 8, - }}, - }}, - }}, - }}, - }, - }, { - "a: # AI\n - b\nc:\n - d\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "a", - LineComment: "# AI", - Line: 1, - Column: 1, - }, { - Kind: yaml.SequenceNode, - Tag: "!!seq", - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "b", - Line: 2, - Column: 5, - }}, - Line: 2, - Column: 3, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "c", - Line: 3, - Column: 1, - }, { - Kind: yaml.SequenceNode, - Tag: "!!seq", - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "d", - Line: 4, - Column: 5, - }}, - Line: 4, - Column: 3, - }}, - }}, - }, - }, { - "[decode]a:\n # HM\n - # HB1\n # HB2\n b: # IB\n c # IC\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Style: 0x0, - Tag: "!!str", - Value: "a", - Line: 1, - Column: 1, - }, { - Kind: yaml.SequenceNode, - Tag: "!!seq", - Line: 3, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - HeadComment: "# HM", - Line: 5, - Column: 5, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "b", - HeadComment: "# HB1\n# HB2", - LineComment: "# IB", - Line: 5, - Column: 5, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "c", - LineComment: "# IC", - Line: 6, - Column: 7, - }}, - }}, - }}, - }}, - }, - }, { - // When encoding the value above, it loses b's inline comment. - "[encode]a:\n # HM\n - # HB1\n # HB2\n b: c # IC\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Style: 0x0, - Tag: "!!str", - Value: "a", - Line: 1, - Column: 1, - }, { - Kind: yaml.SequenceNode, - Tag: "!!seq", - Line: 3, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - HeadComment: "# HM", - Line: 5, - Column: 5, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "b", - HeadComment: "# HB1\n# HB2", - LineComment: "# IB", - Line: 5, - Column: 5, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "c", - LineComment: "# IC", - Line: 6, - Column: 7, - }}, - }}, - }}, - }}, - }, - }, { - // Multiple cases of comment inlining next to mapping keys. - "a: | # IA\n str\nb: >- # IB\n str\nc: # IC\n - str\nd: # ID\n str:\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "a", - Line: 1, - Column: 1, - }, { - Kind: yaml.ScalarNode, - Style: yaml.LiteralStyle, - Tag: "!!str", - Value: "str\n", - LineComment: "# IA", - Line: 1, - Column: 4, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "b", - Line: 3, - Column: 1, - }, { - Kind: yaml.ScalarNode, - Style: yaml.FoldedStyle, - Tag: "!!str", - Value: "str", - LineComment: "# IB", - Line: 3, - Column: 4, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "c", - LineComment: "# IC", - Line: 5, - Column: 1, - }, { - Kind: yaml.SequenceNode, - Tag: "!!seq", - Line: 6, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "str", - Line: 6, - Column: 5, - }}, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "d", - LineComment: "# ID", - Line: 7, - Column: 1, - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 8, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "str", - Line: 8, - Column: 3, - }, { - Kind: yaml.ScalarNode, - Tag: "!!null", - Line: 8, - Column: 7, - }}, - }}, - }}, - }, - }, { - // Indentless sequence. - "[decode]a:\n# HM\n- # HB1\n # HB2\n b: # IB\n c # IC\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "a", - Line: 1, - Column: 1, - }, { - Kind: yaml.SequenceNode, - Tag: "!!seq", - Line: 3, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - HeadComment: "# HM", - Line: 5, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "b", - HeadComment: "# HB1\n# HB2", - LineComment: "# IB", - Line: 5, - Column: 3, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "c", - LineComment: "# IC", - Line: 6, - Column: 5, - }}, - }}, - }}, - }}, - }, - }, { - "- a\n- b\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Value: "", - Tag: "!!seq", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "a", - Tag: "!!str", - Line: 1, - Column: 3, - }, { - Kind: yaml.ScalarNode, - Value: "b", - Tag: "!!str", - Line: 2, - Column: 3, - }}, - }}, - }, - }, { - "- a\n- - b\n - c\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Tag: "!!seq", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "a", - Tag: "!!str", - Line: 1, - Column: 3, - }, { - Kind: yaml.SequenceNode, - Tag: "!!seq", - Line: 2, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "b", - Tag: "!!str", - Line: 2, - Column: 5, - }, { - Kind: yaml.ScalarNode, - Value: "c", - Tag: "!!str", - Line: 3, - Column: 5, - }}, - }}, - }}, - }, - }, { - "[a, b]\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Style: yaml.FlowStyle, - Value: "", - Tag: "!!seq", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "a", - Tag: "!!str", - Line: 1, - Column: 2, - }, { - Kind: yaml.ScalarNode, - Value: "b", - Tag: "!!str", - Line: 1, - Column: 5, - }}, - }}, - }, - }, { - "- a\n- [b, c]\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Tag: "!!seq", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "a", - Tag: "!!str", - Line: 1, - Column: 3, - }, { - Kind: yaml.SequenceNode, - Tag: "!!seq", - Style: yaml.FlowStyle, - Line: 2, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "b", - Tag: "!!str", - Line: 2, - Column: 4, - }, { - Kind: yaml.ScalarNode, - Value: "c", - Tag: "!!str", - Line: 2, - Column: 7, - }}, - }}, - }}, - }, - }, { - "a: &x 1\nb: &y 2\nc: *x\nd: *y\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Line: 1, - Column: 1, - Tag: "!!map", - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "a", - Tag: "!!str", - Line: 1, - Column: 1, - }, - saveNode("x", &yaml.Node{ - Kind: yaml.ScalarNode, - Value: "1", - Tag: "!!int", - Anchor: "x", - Line: 1, - Column: 4, - }), - { - Kind: yaml.ScalarNode, - Value: "b", - Tag: "!!str", - Line: 2, - Column: 1, - }, - saveNode("y", &yaml.Node{ - Kind: yaml.ScalarNode, - Value: "2", - Tag: "!!int", - Anchor: "y", - Line: 2, - Column: 4, - }), - { - Kind: yaml.ScalarNode, - Value: "c", - Tag: "!!str", - Line: 3, - Column: 1, - }, { - Kind: yaml.AliasNode, - Value: "x", - Alias: dropNode("x"), - Line: 3, - Column: 4, - }, { - Kind: yaml.ScalarNode, - Value: "d", - Tag: "!!str", - Line: 4, - Column: 1, - }, { - Kind: yaml.AliasNode, - Value: "y", - Tag: "", - Alias: dropNode("y"), - Line: 4, - Column: 4, - }}, - }}, - }, - }, { - - "# One\n# Two\ntrue # Three\n# Four\n# Five\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 3, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "true", - Tag: "!!bool", - Line: 3, - Column: 1, - HeadComment: "# One\n# Two", - LineComment: "# Three", - FootComment: "# Four\n# Five", - }}, - }, - }, { - - "# š\ntrue # š\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 2, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "true", - Tag: "!!bool", - Line: 2, - Column: 1, - HeadComment: "# š", - LineComment: "# š", - }}, - }, - }, { - - "[decode]\n# One\n\n# Two\n\n# Three\ntrue # Four\n# Five\n\n# Six\n\n# Seven\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 7, - Column: 1, - HeadComment: "# One\n\n# Two", - FootComment: "# Six\n\n# Seven", - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "true", - Tag: "!!bool", - Line: 7, - Column: 1, - HeadComment: "# Three", - LineComment: "# Four", - FootComment: "# Five", - }}, - }, - }, { - // Write out the pound character if missing from comments. - "[encode]# One\n# Two\ntrue # Three\n# Four\n# Five\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 3, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "true", - Tag: "!!bool", - Line: 3, - Column: 1, - HeadComment: "One\nTwo\n", - LineComment: "Three\n", - FootComment: "Four\nFive\n", - }}, - }, - }, { - "[encode]# One\n# Two\ntrue # Three\n# Four\n# Five\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 3, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "true", - Tag: "!!bool", - Line: 3, - Column: 1, - HeadComment: " One\n Two", - LineComment: " Three", - FootComment: " Four\n Five", - }}, - }, - }, { - "# DH1\n\n# DH2\n\n# H1\n# H2\ntrue # I\n# F1\n# F2\n\n# DF1\n\n# DF2\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 7, - Column: 1, - HeadComment: "# DH1\n\n# DH2", - FootComment: "# DF1\n\n# DF2", - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "true", - Tag: "!!bool", - Line: 7, - Column: 1, - HeadComment: "# H1\n# H2", - LineComment: "# I", - FootComment: "# F1\n# F2", - }}, - }, - }, { - "# DH1\n\n# DH2\n\n# HA1\n# HA2\nka: va # IA\n# FA1\n# FA2\n\n# HB1\n# HB2\nkb: vb # IB\n# FB1\n# FB2\n\n# DF1\n\n# DF2\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 7, - Column: 1, - HeadComment: "# DH1\n\n# DH2", - FootComment: "# DF1\n\n# DF2", - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 7, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Line: 7, - Column: 1, - Tag: "!!str", - Value: "ka", - HeadComment: "# HA1\n# HA2", - FootComment: "# FA1\n# FA2", - }, { - Kind: yaml.ScalarNode, - Line: 7, - Column: 5, - Tag: "!!str", - Value: "va", - LineComment: "# IA", - }, { - Kind: yaml.ScalarNode, - Line: 13, - Column: 1, - Tag: "!!str", - Value: "kb", - HeadComment: "# HB1\n# HB2", - FootComment: "# FB1\n# FB2", - }, { - Kind: yaml.ScalarNode, - Line: 13, - Column: 5, - Tag: "!!str", - Value: "vb", - LineComment: "# IB", - }}, - }}, - }, - }, { - "# DH1\n\n# DH2\n\n# HA1\n# HA2\n- la # IA\n# FA1\n# FA2\n\n# HB1\n# HB2\n- lb # IB\n# FB1\n# FB2\n\n# DF1\n\n# DF2\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 7, - Column: 1, - HeadComment: "# DH1\n\n# DH2", - FootComment: "# DF1\n\n# DF2", - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Tag: "!!seq", - Line: 7, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 7, - Column: 3, - Value: "la", - HeadComment: "# HA1\n# HA2", - LineComment: "# IA", - FootComment: "# FA1\n# FA2", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 13, - Column: 3, - Value: "lb", - HeadComment: "# HB1\n# HB2", - LineComment: "# IB", - FootComment: "# FB1\n# FB2", - }}, - }}, - }, - }, { - "# DH1\n\n- la # IA\n# HB1\n- lb\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 3, - Column: 1, - HeadComment: "# DH1", - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Tag: "!!seq", - Line: 3, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 3, - Column: 3, - Value: "la", - LineComment: "# IA", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 5, - Column: 3, - Value: "lb", - HeadComment: "# HB1", - }}, - }}, - }, - }, { - "- la # IA\n- lb # IB\n- lc # IC\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Tag: "!!seq", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 1, - Column: 3, - Value: "la", - LineComment: "# IA", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 2, - Column: 3, - Value: "lb", - LineComment: "# IB", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 3, - Column: 3, - Value: "lc", - LineComment: "# IC", - }}, - }}, - }, - }, { - "# DH1\n\n# HL1\n- - la\n # HB1\n - lb\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 4, - Column: 1, - HeadComment: "# DH1", - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Tag: "!!seq", - Line: 4, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Tag: "!!seq", - Line: 4, - Column: 3, - HeadComment: "# HL1", - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 4, - Column: 5, - Value: "la", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 6, - Column: 5, - Value: "lb", - HeadComment: "# HB1", - }}, - }}, - }}, - }, - }, { - "# DH1\n\n# HL1\n- # HA1\n - la\n # HB1\n - lb\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 4, - Column: 1, - HeadComment: "# DH1", - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Tag: "!!seq", - Line: 4, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Tag: "!!seq", - Line: 5, - Column: 3, - HeadComment: "# HL1", - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 5, - Column: 5, - Value: "la", - HeadComment: "# HA1", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 7, - Column: 5, - Value: "lb", - HeadComment: "# HB1", - }}, - }}, - }}, - }, - }, { - "[decode]# DH1\n\n# HL1\n- # HA1\n\n - la\n # HB1\n - lb\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 4, - Column: 1, - HeadComment: "# DH1", - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Tag: "!!seq", - Line: 4, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Tag: "!!seq", - Line: 6, - Column: 3, - HeadComment: "# HL1", - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 6, - Column: 5, - Value: "la", - HeadComment: "# HA1\n", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 8, - Column: 5, - Value: "lb", - HeadComment: "# HB1", - }}, - }}, - }}, - }, - }, { - "# DH1\n\n# HA1\nka:\n # HB1\n kb:\n # HC1\n # HC2\n - lc # IC\n # FC1\n # FC2\n\n # HD1\n - ld # ID\n # FD1\n\n# DF1\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 4, - Column: 1, - HeadComment: "# DH1", - FootComment: "# DF1", - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 4, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 4, - Column: 1, - Value: "ka", - HeadComment: "# HA1", - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 6, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 6, - Column: 3, - Value: "kb", - HeadComment: "# HB1", - }, { - Kind: yaml.SequenceNode, - Line: 9, - Column: 5, - Tag: "!!seq", - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 9, - Column: 7, - Value: "lc", - HeadComment: "# HC1\n# HC2", - LineComment: "# IC", - FootComment: "# FC1\n# FC2", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 14, - Column: 7, - Value: "ld", - HeadComment: "# HD1", - - LineComment: "# ID", - FootComment: "# FD1", - }}, - }}, - }}, - }}, - }, - }, { - "# DH1\n\n# HA1\nka:\n # HB1\n kb:\n # HC1\n # HC2\n - lc # IC\n # FC1\n # FC2\n\n # HD1\n - ld # ID\n # FD1\nke: ve\n\n# DF1\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 4, - Column: 1, - HeadComment: "# DH1", - FootComment: "# DF1", - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 4, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 4, - Column: 1, - Value: "ka", - HeadComment: "# HA1", - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 6, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 6, - Column: 3, - Value: "kb", - HeadComment: "# HB1", - }, { - Kind: yaml.SequenceNode, - Line: 9, - Column: 5, - Tag: "!!seq", - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 9, - Column: 7, - Value: "lc", - HeadComment: "# HC1\n# HC2", - LineComment: "# IC", - FootComment: "# FC1\n# FC2", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 14, - Column: 7, - Value: "ld", - HeadComment: "# HD1", - LineComment: "# ID", - FootComment: "# FD1", - }}, - }}, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 16, - Column: 1, - Value: "ke", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 16, - Column: 5, - Value: "ve", - }}, - }}, - }, - }, { - "# DH1\n\n# DH2\n\n# HA1\n# HA2\nka:\n # HB1\n # HB2\n kb:\n" + - " # HC1\n # HC2\n kc:\n # HD1\n # HD2\n kd: vd\n # FD1\n # FD2\n" + - " # FC1\n # FC2\n # FB1\n # FB2\n# FA1\n# FA2\n\n# HE1\n# HE2\nke: ve\n# FE1\n# FE2\n\n# DF1\n\n# DF2\n", - yaml.Node{ - Kind: yaml.DocumentNode, - HeadComment: "# DH1\n\n# DH2", - FootComment: "# DF1\n\n# DF2", - Line: 7, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 7, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ka", - HeadComment: "# HA1\n# HA2", - FootComment: "# FA1\n# FA2", - Line: 7, - Column: 1, - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 10, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kb", - HeadComment: "# HB1\n# HB2", - FootComment: "# FB1\n# FB2", - Line: 10, - Column: 3, - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 13, - Column: 5, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kc", - HeadComment: "# HC1\n# HC2", - FootComment: "# FC1\n# FC2", - Line: 13, - Column: 5, - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 16, - Column: 7, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kd", - HeadComment: "# HD1\n# HD2", - FootComment: "# FD1\n# FD2", - Line: 16, - Column: 7, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vd", - Line: 16, - Column: 11, - }}, - }}, - }}, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ke", - HeadComment: "# HE1\n# HE2", - FootComment: "# FE1\n# FE2", - Line: 28, - Column: 1, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ve", - Line: 28, - Column: 5, - }}, - }}, - }, - }, { - // Same as above but indenting ke in so it's also part of ka's value. - "# DH1\n\n# DH2\n\n# HA1\n# HA2\nka:\n # HB1\n # HB2\n kb:\n" + - " # HC1\n # HC2\n kc:\n # HD1\n # HD2\n kd: vd\n # FD1\n # FD2\n" + - " # FC1\n # FC2\n # FB1\n # FB2\n\n # HE1\n # HE2\n ke: ve\n # FE1\n # FE2\n# FA1\n# FA2\n\n# DF1\n\n# DF2\n", - yaml.Node{ - Kind: yaml.DocumentNode, - HeadComment: "# DH1\n\n# DH2", - FootComment: "# DF1\n\n# DF2", - Line: 7, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 7, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ka", - HeadComment: "# HA1\n# HA2", - FootComment: "# FA1\n# FA2", - Line: 7, - Column: 1, - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 10, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kb", - HeadComment: "# HB1\n# HB2", - FootComment: "# FB1\n# FB2", - Line: 10, - Column: 3, - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 13, - Column: 5, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kc", - HeadComment: "# HC1\n# HC2", - FootComment: "# FC1\n# FC2", - Line: 13, - Column: 5, - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 16, - Column: 7, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kd", - HeadComment: "# HD1\n# HD2", - FootComment: "# FD1\n# FD2", - Line: 16, - Column: 7, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vd", - Line: 16, - Column: 11, - }}, - }}, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ke", - HeadComment: "# HE1\n# HE2", - FootComment: "# FE1\n# FE2", - Line: 26, - Column: 3, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ve", - Line: 26, - Column: 7, - }}, - }}, - }}, - }, - }, { - // Decode only due to lack of newline at the end. - "[decode]# HA1\nka:\n # HB1\n kb: vb\n # FB1\n# FA1", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 2, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 2, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ka", - HeadComment: "# HA1", - FootComment: "# FA1", - Line: 2, - Column: 1, - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 4, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kb", - HeadComment: "# HB1", - FootComment: "# FB1", - Line: 4, - Column: 3, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vb", - Line: 4, - Column: 7, - }}, - }}, - }}, - }, - }, { - // Same as above, but with newline at the end. - "# HA1\nka:\n # HB1\n kb: vb\n # FB1\n# FA1\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 2, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 2, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ka", - HeadComment: "# HA1", - FootComment: "# FA1", - Line: 2, - Column: 1, - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 4, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kb", - HeadComment: "# HB1", - FootComment: "# FB1", - Line: 4, - Column: 3, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vb", - Line: 4, - Column: 7, - }}, - }}, - }}, - }, - }, { - // Same as above, but without FB1. - "# HA1\nka:\n # HB1\n kb: vb\n# FA1\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 2, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 2, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ka", - HeadComment: "# HA1", - FootComment: "# FA1", - Line: 2, - Column: 1, - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 4, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kb", - HeadComment: "# HB1", - Line: 4, - Column: 3, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vb", - Line: 4, - Column: 7, - }}, - }}, - }}, - }, - }, { - // Same as above, but with two newlines at the end. Decode-only for that. - "[decode]# HA1\nka:\n # HB1\n kb: vb\n # FB1\n# FA1\n\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 2, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 2, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ka", - HeadComment: "# HA1", - FootComment: "# FA1", - Line: 2, - Column: 1, - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 4, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kb", - HeadComment: "# HB1", - FootComment: "# FB1", - Line: 4, - Column: 3, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vb", - Line: 4, - Column: 7, - }}, - }}, - }}, - }, - }, { - // Similar to above, but make HB1 look more like a footer of ka. - "[decode]# HA1\nka:\n# HB1\n\n kb: vb\n# FA1\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 2, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 2, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ka", - HeadComment: "# HA1", - FootComment: "# FA1", - Line: 2, - Column: 1, - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 5, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kb", - HeadComment: "# HB1\n", - Line: 5, - Column: 3, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vb", - Line: 5, - Column: 7, - }}, - }}, - }}, - }, - }, { - "ka:\n kb: vb\n# FA1\n\nkc: vc\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ka", - Line: 1, - Column: 1, - FootComment: "# FA1", - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 2, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kb", - Line: 2, - Column: 3, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vb", - Line: 2, - Column: 7, - }}, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kc", - Line: 5, - Column: 1, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vc", - Line: 5, - Column: 5, - }}, - }}, - }, - }, { - "ka:\n kb: vb\n# HC1\nkc: vc\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ka", - Line: 1, - Column: 1, - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 2, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kb", - Line: 2, - Column: 3, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vb", - Line: 2, - Column: 7, - }}, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kc", - HeadComment: "# HC1", - Line: 4, - Column: 1, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vc", - Line: 4, - Column: 5, - }}, - }}, - }, - }, { - // Decode only due to empty line before HC1. - "[decode]ka:\n kb: vb\n\n# HC1\nkc: vc\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ka", - Line: 1, - Column: 1, - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 2, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kb", - Line: 2, - Column: 3, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vb", - Line: 2, - Column: 7, - }}, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kc", - HeadComment: "# HC1", - Line: 5, - Column: 1, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vc", - Line: 5, - Column: 5, - }}, - }}, - }, - }, { - // Decode-only due to empty lines around HC1. - "[decode]ka:\n kb: vb\n\n# HC1\n\nkc: vc\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ka", - Line: 1, - Column: 1, - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 2, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kb", - Line: 2, - Column: 3, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vb", - Line: 2, - Column: 7, - }}, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kc", - HeadComment: "# HC1\n", - Line: 6, - Column: 1, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vc", - Line: 6, - Column: 5, - }}, - }}, - }, - }, { - "ka: # IA\n kb: # IB\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ka", - Line: 1, - Column: 1, - LineComment: "# IA", - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 2, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kb", - Line: 2, - Column: 3, - LineComment: "# IB", - }, { - Kind: yaml.ScalarNode, - Tag: "!!null", - Line: 2, - Column: 6, - }}, - }}, - }}, - }, - }, { - "# HA1\nka:\n # HB1\n kb: vb\n # FB1\n# HC1\n# HC2\nkc: vc\n# FC1\n# FC2\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 2, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 2, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ka", - HeadComment: "# HA1", - Line: 2, - Column: 1, - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 4, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kb", - HeadComment: "# HB1", - FootComment: "# FB1", - Line: 4, - Column: 3, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vb", - Line: 4, - Column: 7, - }}, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kc", - HeadComment: "# HC1\n# HC2", - FootComment: "# FC1\n# FC2", - Line: 8, - Column: 1, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vc", - Line: 8, - Column: 5, - }}, - }}, - }, - }, { - // Same as above, but decode only due to empty line between ka's value and kc's headers. - "[decode]# HA1\nka:\n # HB1\n kb: vb\n # FB1\n\n# HC1\n# HC2\nkc: vc\n# FC1\n# FC2\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 2, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 2, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ka", - HeadComment: "# HA1", - Line: 2, - Column: 1, - }, { - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 4, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kb", - HeadComment: "# HB1", - FootComment: "# FB1", - Line: 4, - Column: 3, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vb", - Line: 4, - Column: 7, - }}, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kc", - HeadComment: "# HC1\n# HC2", - FootComment: "# FC1\n# FC2", - Line: 9, - Column: 1, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "vc", - Line: 9, - Column: 5, - }}, - }}, - }, - }, { - "# H1\n[la, lb] # I\n# F1\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 2, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Tag: "!!seq", - Style: yaml.FlowStyle, - Line: 2, - Column: 1, - HeadComment: "# H1", - LineComment: "# I", - FootComment: "# F1", - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 2, - Column: 2, - Value: "la", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 2, - Column: 6, - Value: "lb", - }}, - }}, - }, - }, { - "# DH1\n\n# SH1\n[\n # HA1\n la, # IA\n # FA1\n\n # HB1\n lb, # IB\n # FB1\n]\n# SF1\n\n# DF1\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 4, - Column: 1, - HeadComment: "# DH1", - FootComment: "# DF1", - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Tag: "!!seq", - Style: yaml.FlowStyle, - Line: 4, - Column: 1, - HeadComment: "# SH1", - FootComment: "# SF1", - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 6, - Column: 3, - Value: "la", - HeadComment: "# HA1", - LineComment: "# IA", - FootComment: "# FA1", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 10, - Column: 3, - Value: "lb", - HeadComment: "# HB1", - LineComment: "# IB", - FootComment: "# FB1", - }}, - }}, - }, - }, { - // Same as above, but with extra newlines before FB1 and FB2 - "[decode]# DH1\n\n# SH1\n[\n # HA1\n la, # IA\n # FA1\n\n # HB1\n lb, # IB\n\n\n # FB1\n\n# FB2\n]\n# SF1\n\n# DF1\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 4, - Column: 1, - HeadComment: "# DH1", - FootComment: "# DF1", - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Tag: "!!seq", - Style: yaml.FlowStyle, - Line: 4, - Column: 1, - HeadComment: "# SH1", - FootComment: "# SF1", - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 6, - Column: 3, - Value: "la", - HeadComment: "# HA1", - LineComment: "# IA", - FootComment: "# FA1", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 10, - Column: 3, - Value: "lb", - HeadComment: "# HB1", - LineComment: "# IB", - FootComment: "# FB1\n\n# FB2", - }}, - }}, - }, - }, { - "# DH1\n\n# SH1\n[\n # HA1\n la,\n # FA1\n\n # HB1\n lb,\n # FB1\n]\n# SF1\n\n# DF1\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 4, - Column: 1, - HeadComment: "# DH1", - FootComment: "# DF1", - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Tag: "!!seq", - Style: yaml.FlowStyle, - Line: 4, - Column: 1, - HeadComment: "# SH1", - FootComment: "# SF1", - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 6, - Column: 3, - Value: "la", - HeadComment: "# HA1", - FootComment: "# FA1", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 10, - Column: 3, - Value: "lb", - HeadComment: "# HB1", - FootComment: "# FB1", - }}, - }}, - }, - }, { - "ka:\n kb: [\n # HA1\n la,\n # FA1\n\n # HB1\n lb,\n # FB1\n ]\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Line: 1, - Column: 1, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "ka", - Line: 1, - Column: 1, - }, { - Kind: 0x4, - Tag: "!!map", - Line: 2, - Column: 3, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "kb", - Line: 2, - Column: 3, - }, { - Kind: yaml.SequenceNode, - Style: 0x20, - Tag: "!!seq", - Line: 2, - Column: 7, - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "la", - HeadComment: "# HA1", - FootComment: "# FA1", - Line: 4, - Column: 5, - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Value: "lb", - HeadComment: "# HB1", - FootComment: "# FB1", - Line: 8, - Column: 5, - }}, - }}, - }}, - }}, - }, - }, { - "# DH1\n\n# MH1\n{\n # HA1\n ka: va, # IA\n # FA1\n\n # HB1\n kb: vb, # IB\n # FB1\n}\n# MF1\n\n# DF1\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 4, - Column: 1, - HeadComment: "# DH1", - FootComment: "# DF1", - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Style: yaml.FlowStyle, - Line: 4, - Column: 1, - HeadComment: "# MH1", - FootComment: "# MF1", - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 6, - Column: 3, - Value: "ka", - HeadComment: "# HA1", - FootComment: "# FA1", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 6, - Column: 7, - Value: "va", - LineComment: "# IA", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 10, - Column: 3, - Value: "kb", - HeadComment: "# HB1", - FootComment: "# FB1", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 10, - Column: 7, - Value: "vb", - LineComment: "# IB", - }}, - }}, - }, - }, { - "# DH1\n\n# MH1\n{\n # HA1\n ka: va,\n # FA1\n\n # HB1\n kb: vb,\n # FB1\n}\n# MF1\n\n# DF1\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 4, - Column: 1, - HeadComment: "# DH1", - FootComment: "# DF1", - Content: []*yaml.Node{{ - Kind: yaml.MappingNode, - Tag: "!!map", - Style: yaml.FlowStyle, - Line: 4, - Column: 1, - HeadComment: "# MH1", - FootComment: "# MF1", - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 6, - Column: 3, - Value: "ka", - HeadComment: "# HA1", - FootComment: "# FA1", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 6, - Column: 7, - Value: "va", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 10, - Column: 3, - Value: "kb", - HeadComment: "# HB1", - FootComment: "# FB1", - }, { - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 10, - Column: 7, - Value: "vb", - }}, - }}, - }, - }, { - "# DH1\n\n# DH2\n\n# HA1\n# HA2\n- &x la # IA\n# FA1\n# FA2\n\n# HB1\n# HB2\n- *x # IB\n# FB1\n# FB2\n\n# DF1\n\n# DF2\n", - yaml.Node{ - Kind: yaml.DocumentNode, - Line: 7, - Column: 1, - HeadComment: "# DH1\n\n# DH2", - FootComment: "# DF1\n\n# DF2", - Content: []*yaml.Node{{ - Kind: yaml.SequenceNode, - Tag: "!!seq", - Line: 7, - Column: 1, - Content: []*yaml.Node{ - saveNode("x", &yaml.Node{ - Kind: yaml.ScalarNode, - Tag: "!!str", - Line: 7, - Column: 3, - Value: "la", - HeadComment: "# HA1\n# HA2", - LineComment: "# IA", - FootComment: "# FA1\n# FA2", - Anchor: "x", - }), { - Kind: yaml.AliasNode, - Line: 13, - Column: 3, - Value: "x", - Alias: dropNode("x"), - HeadComment: "# HB1\n# HB2", - LineComment: "# IB", - FootComment: "# FB1\n# FB2", - }, - }, - }}, - }, - }, -} - -func (s *S) TestNodeRoundtrip(c *C) { - defer os.Setenv("TZ", os.Getenv("TZ")) - os.Setenv("TZ", "UTC") - for i, item := range nodeTests { - c.Logf("test %d: %q", i, item.yaml) - - if strings.Contains(item.yaml, "#") { - var buf bytes.Buffer - fprintComments(&buf, &item.node, " ") - c.Logf(" expected comments:\n%s", buf.Bytes()) - } - - decode := true - encode := true - - testYaml := item.yaml - if s := strings.TrimPrefix(testYaml, "[decode]"); s != testYaml { - encode = false - testYaml = s - } - if s := strings.TrimPrefix(testYaml, "[encode]"); s != testYaml { - decode = false - testYaml = s - } - - if decode { - var node yaml.Node - err := yaml.Unmarshal([]byte(testYaml), &node) - c.Assert(err, IsNil) - if strings.Contains(item.yaml, "#") { - var buf bytes.Buffer - fprintComments(&buf, &node, " ") - c.Logf(" obtained comments:\n%s", buf.Bytes()) - } - c.Assert(&node, DeepEquals, &item.node) - } - if encode { - node := deepCopyNode(&item.node, nil) - buf := bytes.Buffer{} - enc := yaml.NewEncoder(&buf) - enc.SetIndent(2) - err := enc.Encode(node) - c.Assert(err, IsNil) - err = enc.Close() - c.Assert(err, IsNil) - c.Assert(buf.String(), Equals, testYaml) - - // Ensure there were no mutations to the tree. - c.Assert(node, DeepEquals, &item.node) - } - } -} - -func deepCopyNode(node *yaml.Node, cache map[*yaml.Node]*yaml.Node) *yaml.Node { - if n, ok := cache[node]; ok { - return n - } - if cache == nil { - cache = make(map[*yaml.Node]*yaml.Node) - } - copy := *node - cache[node] = © - copy.Content = nil - for _, elem := range node.Content { - copy.Content = append(copy.Content, deepCopyNode(elem, cache)) - } - if node.Alias != nil { - copy.Alias = deepCopyNode(node.Alias, cache) - } - return © -} - -var savedNodes = make(map[string]*yaml.Node) - -func saveNode(name string, node *yaml.Node) *yaml.Node { - savedNodes[name] = node - return node -} - -func peekNode(name string) *yaml.Node { - return savedNodes[name] -} - -func dropNode(name string) *yaml.Node { - node := savedNodes[name] - delete(savedNodes, name) - return node -} - -var setStringTests = []struct { - str string - yaml string - node yaml.Node -}{ - { - "something simple", - "something simple\n", - yaml.Node{ - Kind: yaml.ScalarNode, - Value: "something simple", - Tag: "!!str", - }, - }, { - `"quoted value"`, - "'\"quoted value\"'\n", - yaml.Node{ - Kind: yaml.ScalarNode, - Value: `"quoted value"`, - Tag: "!!str", - }, - }, { - "multi\nline", - "|-\n multi\n line\n", - yaml.Node{ - Kind: yaml.ScalarNode, - Value: "multi\nline", - Tag: "!!str", - Style: yaml.LiteralStyle, - }, - }, { - "123", - "\"123\"\n", - yaml.Node{ - Kind: yaml.ScalarNode, - Value: "123", - Tag: "!!str", - }, - }, { - "multi\nline\n", - "|\n multi\n line\n", - yaml.Node{ - Kind: yaml.ScalarNode, - Value: "multi\nline\n", - Tag: "!!str", - Style: yaml.LiteralStyle, - }, - }, { - "\x80\x81\x82", - "!!binary gIGC\n", - yaml.Node{ - Kind: yaml.ScalarNode, - Value: "gIGC", - Tag: "!!binary", - }, - }, -} - -func (s *S) TestSetString(c *C) { - defer os.Setenv("TZ", os.Getenv("TZ")) - os.Setenv("TZ", "UTC") - for i, item := range setStringTests { - c.Logf("test %d: %q", i, item.str) - - var node yaml.Node - - node.SetString(item.str) - - c.Assert(node, DeepEquals, item.node) - - buf := bytes.Buffer{} - enc := yaml.NewEncoder(&buf) - enc.SetIndent(2) - err := enc.Encode(&item.node) - c.Assert(err, IsNil) - err = enc.Close() - c.Assert(err, IsNil) - c.Assert(buf.String(), Equals, item.yaml) - - var doc yaml.Node - err = yaml.Unmarshal([]byte(item.yaml), &doc) - c.Assert(err, IsNil) - - var str string - err = node.Decode(&str) - c.Assert(err, IsNil) - c.Assert(str, Equals, item.str) - } -} - -var nodeEncodeDecodeTests = []struct { - value interface{} - yaml string - node yaml.Node -}{{ - "something simple", - "something simple\n", - yaml.Node{ - Kind: yaml.ScalarNode, - Value: "something simple", - Tag: "!!str", - }, -}, { - `"quoted value"`, - "'\"quoted value\"'\n", - yaml.Node{ - Kind: yaml.ScalarNode, - Style: yaml.SingleQuotedStyle, - Value: `"quoted value"`, - Tag: "!!str", - }, -}, { - 123, - "123", - yaml.Node{ - Kind: yaml.ScalarNode, - Value: `123`, - Tag: "!!int", - }, -}, { - []interface{}{1, 2}, - "[1, 2]", - yaml.Node{ - Kind: yaml.SequenceNode, - Tag: "!!seq", - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "1", - Tag: "!!int", - }, { - Kind: yaml.ScalarNode, - Value: "2", - Tag: "!!int", - }}, - }, -}, { - map[string]interface{}{"a": "b"}, - "a: b", - yaml.Node{ - Kind: yaml.MappingNode, - Tag: "!!map", - Content: []*yaml.Node{{ - Kind: yaml.ScalarNode, - Value: "a", - Tag: "!!str", - }, { - Kind: yaml.ScalarNode, - Value: "b", - Tag: "!!str", - }}, - }, -}} - -func (s *S) TestNodeEncodeDecode(c *C) { - for i, item := range nodeEncodeDecodeTests { - c.Logf("Encode/Decode test value #%d: %#v", i, item.value) - - var v interface{} - err := item.node.Decode(&v) - c.Assert(err, IsNil) - c.Assert(v, DeepEquals, item.value) - - var n yaml.Node - err = n.Encode(item.value) - c.Assert(err, IsNil) - c.Assert(n, DeepEquals, item.node) - } -} - -func (s *S) TestNodeZeroEncodeDecode(c *C) { - // Zero node value behaves as nil when encoding... - var n yaml.Node - data, err := yaml.Marshal(&n) - c.Assert(err, IsNil) - c.Assert(string(data), Equals, "null\n") - - // ... and decoding. - var v *struct{} = &struct{}{} - c.Assert(n.Decode(&v), IsNil) - c.Assert(v, IsNil) - - // ... and even when looking for its tag. - c.Assert(n.ShortTag(), Equals, "!!null") - - // Kind zero is still unknown, though. - n.Line = 1 - _, err = yaml.Marshal(&n) - c.Assert(err, ErrorMatches, "yaml: cannot encode node with unknown kind 0") - c.Assert(n.Decode(&v), ErrorMatches, "yaml: cannot decode node with unknown kind 0") -} - -func (s *S) TestNodeOmitEmpty(c *C) { - var v struct { - A int - B yaml.Node ",omitempty" - } - v.A = 1 - data, err := yaml.Marshal(&v) - c.Assert(err, IsNil) - c.Assert(string(data), Equals, "a: 1\n") - - v.B.Line = 1 - _, err = yaml.Marshal(&v) - c.Assert(err, ErrorMatches, "yaml: cannot encode node with unknown kind 0") -} - -func fprintComments(out io.Writer, node *yaml.Node, indent string) { - switch node.Kind { - case yaml.ScalarNode: - fmt.Fprintf(out, "%s<%s> ", indent, node.Value) - fprintCommentSet(out, node) - fmt.Fprintf(out, "\n") - case yaml.DocumentNode: - fmt.Fprintf(out, "%s<DOC> ", indent) - fprintCommentSet(out, node) - fmt.Fprintf(out, "\n") - for i := 0; i < len(node.Content); i++ { - fprintComments(out, node.Content[i], indent+" ") - } - case yaml.MappingNode: - fmt.Fprintf(out, "%s<MAP> ", indent) - fprintCommentSet(out, node) - fmt.Fprintf(out, "\n") - for i := 0; i < len(node.Content); i += 2 { - fprintComments(out, node.Content[i], indent+" ") - fprintComments(out, node.Content[i+1], indent+" ") - } - case yaml.SequenceNode: - fmt.Fprintf(out, "%s<SEQ> ", indent) - fprintCommentSet(out, node) - fmt.Fprintf(out, "\n") - for i := 0; i < len(node.Content); i++ { - fprintComments(out, node.Content[i], indent+" ") - } - } -} - -func fprintCommentSet(out io.Writer, node *yaml.Node) { - if len(node.HeadComment)+len(node.LineComment)+len(node.FootComment) > 0 { - fmt.Fprintf(out, "%q / %q / %q", node.HeadComment, node.LineComment, node.FootComment) - } -} diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/parserc.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/parserc.go deleted file mode 100644 index 268558a..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/parserc.go +++ /dev/null @@ -1,1258 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// 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. - -package yaml - -import ( - "bytes" -) - -// The parser implements the following grammar: -// -// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END -// implicit_document ::= block_node DOCUMENT-END* -// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* -// block_node_or_indentless_sequence ::= -// ALIAS -// | properties (block_content | indentless_block_sequence)? -// | block_content -// | indentless_block_sequence -// block_node ::= ALIAS -// | properties block_content? -// | block_content -// flow_node ::= ALIAS -// | properties flow_content? -// | flow_content -// properties ::= TAG ANCHOR? | ANCHOR TAG? -// block_content ::= block_collection | flow_collection | SCALAR -// flow_content ::= flow_collection | SCALAR -// block_collection ::= block_sequence | block_mapping -// flow_collection ::= flow_sequence | flow_mapping -// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END -// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ -// block_mapping ::= BLOCK-MAPPING_START -// ((KEY block_node_or_indentless_sequence?)? -// (VALUE block_node_or_indentless_sequence?)?)* -// BLOCK-END -// flow_sequence ::= FLOW-SEQUENCE-START -// (flow_sequence_entry FLOW-ENTRY)* -// flow_sequence_entry? -// FLOW-SEQUENCE-END -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// flow_mapping ::= FLOW-MAPPING-START -// (flow_mapping_entry FLOW-ENTRY)* -// flow_mapping_entry? -// FLOW-MAPPING-END -// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? - -// Peek the next token in the token queue. -func peek_token(parser *yaml_parser_t) *yaml_token_t { - if parser.token_available || yaml_parser_fetch_more_tokens(parser) { - token := &parser.tokens[parser.tokens_head] - yaml_parser_unfold_comments(parser, token) - return token - } - return nil -} - -// yaml_parser_unfold_comments walks through the comments queue and joins all -// comments behind the position of the provided token into the respective -// top-level comment slices in the parser. -func yaml_parser_unfold_comments(parser *yaml_parser_t, token *yaml_token_t) { - for parser.comments_head < len(parser.comments) && token.start_mark.index >= parser.comments[parser.comments_head].token_mark.index { - comment := &parser.comments[parser.comments_head] - if len(comment.head) > 0 { - if token.typ == yaml_BLOCK_END_TOKEN { - // No heads on ends, so keep comment.head for a follow up token. - break - } - if len(parser.head_comment) > 0 { - parser.head_comment = append(parser.head_comment, '\n') - } - parser.head_comment = append(parser.head_comment, comment.head...) - } - if len(comment.foot) > 0 { - if len(parser.foot_comment) > 0 { - parser.foot_comment = append(parser.foot_comment, '\n') - } - parser.foot_comment = append(parser.foot_comment, comment.foot...) - } - if len(comment.line) > 0 { - if len(parser.line_comment) > 0 { - parser.line_comment = append(parser.line_comment, '\n') - } - parser.line_comment = append(parser.line_comment, comment.line...) - } - *comment = yaml_comment_t{} - parser.comments_head++ - } -} - -// Remove the next token from the queue (must be called after peek_token). -func skip_token(parser *yaml_parser_t) { - parser.token_available = false - parser.tokens_parsed++ - parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN - parser.tokens_head++ -} - -// Get the next event. -func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool { - // Erase the event object. - *event = yaml_event_t{} - - // No events after the end of the stream or error. - if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE { - return true - } - - // Generate the next event. - return yaml_parser_state_machine(parser, event) -} - -// Set parser error. -func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool { - parser.error = yaml_PARSER_ERROR - parser.problem = problem - parser.problem_mark = problem_mark - return false -} - -func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool { - parser.error = yaml_PARSER_ERROR - parser.context = context - parser.context_mark = context_mark - parser.problem = problem - parser.problem_mark = problem_mark - return false -} - -// State dispatcher. -func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool { - //trace("yaml_parser_state_machine", "state:", parser.state.String()) - - switch parser.state { - case yaml_PARSE_STREAM_START_STATE: - return yaml_parser_parse_stream_start(parser, event) - - case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: - return yaml_parser_parse_document_start(parser, event, true) - - case yaml_PARSE_DOCUMENT_START_STATE: - return yaml_parser_parse_document_start(parser, event, false) - - case yaml_PARSE_DOCUMENT_CONTENT_STATE: - return yaml_parser_parse_document_content(parser, event) - - case yaml_PARSE_DOCUMENT_END_STATE: - return yaml_parser_parse_document_end(parser, event) - - case yaml_PARSE_BLOCK_NODE_STATE: - return yaml_parser_parse_node(parser, event, true, false) - - case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: - return yaml_parser_parse_node(parser, event, true, true) - - case yaml_PARSE_FLOW_NODE_STATE: - return yaml_parser_parse_node(parser, event, false, false) - - case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: - return yaml_parser_parse_block_sequence_entry(parser, event, true) - - case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: - return yaml_parser_parse_block_sequence_entry(parser, event, false) - - case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: - return yaml_parser_parse_indentless_sequence_entry(parser, event) - - case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: - return yaml_parser_parse_block_mapping_key(parser, event, true) - - case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: - return yaml_parser_parse_block_mapping_key(parser, event, false) - - case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: - return yaml_parser_parse_block_mapping_value(parser, event) - - case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: - return yaml_parser_parse_flow_sequence_entry(parser, event, true) - - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: - return yaml_parser_parse_flow_sequence_entry(parser, event, false) - - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: - return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event) - - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: - return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event) - - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: - return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event) - - case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: - return yaml_parser_parse_flow_mapping_key(parser, event, true) - - case yaml_PARSE_FLOW_MAPPING_KEY_STATE: - return yaml_parser_parse_flow_mapping_key(parser, event, false) - - case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: - return yaml_parser_parse_flow_mapping_value(parser, event, false) - - case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: - return yaml_parser_parse_flow_mapping_value(parser, event, true) - - default: - panic("invalid parser state") - } -} - -// Parse the production: -// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END -// ************ -func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_STREAM_START_TOKEN { - return yaml_parser_set_parser_error(parser, "did not find expected <stream-start>", token.start_mark) - } - parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE - *event = yaml_event_t{ - typ: yaml_STREAM_START_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - encoding: token.encoding, - } - skip_token(parser) - return true -} - -// Parse the productions: -// implicit_document ::= block_node DOCUMENT-END* -// * -// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* -// ************************* -func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool { - - token := peek_token(parser) - if token == nil { - return false - } - - // Parse extra document end indicators. - if !implicit { - for token.typ == yaml_DOCUMENT_END_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } - } - - if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN && - token.typ != yaml_TAG_DIRECTIVE_TOKEN && - token.typ != yaml_DOCUMENT_START_TOKEN && - token.typ != yaml_STREAM_END_TOKEN { - // Parse an implicit document. - if !yaml_parser_process_directives(parser, nil, nil) { - return false - } - parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) - parser.state = yaml_PARSE_BLOCK_NODE_STATE - - var head_comment []byte - if len(parser.head_comment) > 0 { - // [Go] Scan the header comment backwards, and if an empty line is found, break - // the header so the part before the last empty line goes into the - // document header, while the bottom of it goes into a follow up event. - for i := len(parser.head_comment) - 1; i > 0; i-- { - if parser.head_comment[i] == '\n' { - if i == len(parser.head_comment)-1 { - head_comment = parser.head_comment[:i] - parser.head_comment = parser.head_comment[i+1:] - break - } else if parser.head_comment[i-1] == '\n' { - head_comment = parser.head_comment[:i-1] - parser.head_comment = parser.head_comment[i+1:] - break - } - } - } - } - - *event = yaml_event_t{ - typ: yaml_DOCUMENT_START_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - - head_comment: head_comment, - } - - } else if token.typ != yaml_STREAM_END_TOKEN { - // Parse an explicit document. - var version_directive *yaml_version_directive_t - var tag_directives []yaml_tag_directive_t - start_mark := token.start_mark - if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) { - return false - } - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_DOCUMENT_START_TOKEN { - yaml_parser_set_parser_error(parser, - "did not find expected <document start>", token.start_mark) - return false - } - parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) - parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE - end_mark := token.end_mark - - *event = yaml_event_t{ - typ: yaml_DOCUMENT_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - version_directive: version_directive, - tag_directives: tag_directives, - implicit: false, - } - skip_token(parser) - - } else { - // Parse the stream end. - parser.state = yaml_PARSE_END_STATE - *event = yaml_event_t{ - typ: yaml_STREAM_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - skip_token(parser) - } - - return true -} - -// Parse the productions: -// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* -// *********** -// -func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ == yaml_VERSION_DIRECTIVE_TOKEN || - token.typ == yaml_TAG_DIRECTIVE_TOKEN || - token.typ == yaml_DOCUMENT_START_TOKEN || - token.typ == yaml_DOCUMENT_END_TOKEN || - token.typ == yaml_STREAM_END_TOKEN { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - return yaml_parser_process_empty_scalar(parser, event, - token.start_mark) - } - return yaml_parser_parse_node(parser, event, true, false) -} - -// Parse the productions: -// implicit_document ::= block_node DOCUMENT-END* -// ************* -// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* -// -func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - - start_mark := token.start_mark - end_mark := token.start_mark - - implicit := true - if token.typ == yaml_DOCUMENT_END_TOKEN { - end_mark = token.end_mark - skip_token(parser) - implicit = false - } - - parser.tag_directives = parser.tag_directives[:0] - - parser.state = yaml_PARSE_DOCUMENT_START_STATE - *event = yaml_event_t{ - typ: yaml_DOCUMENT_END_EVENT, - start_mark: start_mark, - end_mark: end_mark, - implicit: implicit, - } - yaml_parser_set_event_comments(parser, event) - if len(event.head_comment) > 0 && len(event.foot_comment) == 0 { - event.foot_comment = event.head_comment - event.head_comment = nil - } - return true -} - -func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t) { - event.head_comment = parser.head_comment - event.line_comment = parser.line_comment - event.foot_comment = parser.foot_comment - parser.head_comment = nil - parser.line_comment = nil - parser.foot_comment = nil - parser.tail_comment = nil - parser.stem_comment = nil -} - -// Parse the productions: -// block_node_or_indentless_sequence ::= -// ALIAS -// ***** -// | properties (block_content | indentless_block_sequence)? -// ********** * -// | block_content | indentless_block_sequence -// * -// block_node ::= ALIAS -// ***** -// | properties block_content? -// ********** * -// | block_content -// * -// flow_node ::= ALIAS -// ***** -// | properties flow_content? -// ********** * -// | flow_content -// * -// properties ::= TAG ANCHOR? | ANCHOR TAG? -// ************************* -// block_content ::= block_collection | flow_collection | SCALAR -// ****** -// flow_content ::= flow_collection | SCALAR -// ****** -func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool { - //defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)() - - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ == yaml_ALIAS_TOKEN { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - *event = yaml_event_t{ - typ: yaml_ALIAS_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - anchor: token.value, - } - yaml_parser_set_event_comments(parser, event) - skip_token(parser) - return true - } - - start_mark := token.start_mark - end_mark := token.start_mark - - var tag_token bool - var tag_handle, tag_suffix, anchor []byte - var tag_mark yaml_mark_t - if token.typ == yaml_ANCHOR_TOKEN { - anchor = token.value - start_mark = token.start_mark - end_mark = token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ == yaml_TAG_TOKEN { - tag_token = true - tag_handle = token.value - tag_suffix = token.suffix - tag_mark = token.start_mark - end_mark = token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } - } else if token.typ == yaml_TAG_TOKEN { - tag_token = true - tag_handle = token.value - tag_suffix = token.suffix - start_mark = token.start_mark - tag_mark = token.start_mark - end_mark = token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ == yaml_ANCHOR_TOKEN { - anchor = token.value - end_mark = token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } - } - - var tag []byte - if tag_token { - if len(tag_handle) == 0 { - tag = tag_suffix - tag_suffix = nil - } else { - for i := range parser.tag_directives { - if bytes.Equal(parser.tag_directives[i].handle, tag_handle) { - tag = append([]byte(nil), parser.tag_directives[i].prefix...) - tag = append(tag, tag_suffix...) - break - } - } - if len(tag) == 0 { - yaml_parser_set_parser_error_context(parser, - "while parsing a node", start_mark, - "found undefined tag handle", tag_mark) - return false - } - } - } - - implicit := len(tag) == 0 - if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN { - end_mark = token.end_mark - parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE - *event = yaml_event_t{ - typ: yaml_SEQUENCE_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), - } - return true - } - if token.typ == yaml_SCALAR_TOKEN { - var plain_implicit, quoted_implicit bool - end_mark = token.end_mark - if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') { - plain_implicit = true - } else if len(tag) == 0 { - quoted_implicit = true - } - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - - *event = yaml_event_t{ - typ: yaml_SCALAR_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - value: token.value, - implicit: plain_implicit, - quoted_implicit: quoted_implicit, - style: yaml_style_t(token.style), - } - yaml_parser_set_event_comments(parser, event) - skip_token(parser) - return true - } - if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN { - // [Go] Some of the events below can be merged as they differ only on style. - end_mark = token.end_mark - parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE - *event = yaml_event_t{ - typ: yaml_SEQUENCE_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE), - } - yaml_parser_set_event_comments(parser, event) - return true - } - if token.typ == yaml_FLOW_MAPPING_START_TOKEN { - end_mark = token.end_mark - parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE - *event = yaml_event_t{ - typ: yaml_MAPPING_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), - } - yaml_parser_set_event_comments(parser, event) - return true - } - if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN { - end_mark = token.end_mark - parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE - *event = yaml_event_t{ - typ: yaml_SEQUENCE_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), - } - if parser.stem_comment != nil { - event.head_comment = parser.stem_comment - parser.stem_comment = nil - } - return true - } - if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN { - end_mark = token.end_mark - parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE - *event = yaml_event_t{ - typ: yaml_MAPPING_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE), - } - if parser.stem_comment != nil { - event.head_comment = parser.stem_comment - parser.stem_comment = nil - } - return true - } - if len(anchor) > 0 || len(tag) > 0 { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - - *event = yaml_event_t{ - typ: yaml_SCALAR_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - quoted_implicit: false, - style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), - } - return true - } - - context := "while parsing a flow node" - if block { - context = "while parsing a block node" - } - yaml_parser_set_parser_error_context(parser, context, start_mark, - "did not find expected node content", token.start_mark) - return false -} - -// Parse the productions: -// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END -// ******************** *********** * ********* -// -func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { - if first { - token := peek_token(parser) - if token == nil { - return false - } - parser.marks = append(parser.marks, token.start_mark) - skip_token(parser) - } - - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ == yaml_BLOCK_ENTRY_TOKEN { - mark := token.end_mark - prior_head_len := len(parser.head_comment) - skip_token(parser) - yaml_parser_split_stem_comment(parser, prior_head_len) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE) - return yaml_parser_parse_node(parser, event, true, false) - } else { - parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) - } - } - if token.typ == yaml_BLOCK_END_TOKEN { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - - *event = yaml_event_t{ - typ: yaml_SEQUENCE_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - - skip_token(parser) - return true - } - - context_mark := parser.marks[len(parser.marks)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - return yaml_parser_set_parser_error_context(parser, - "while parsing a block collection", context_mark, - "did not find expected '-' indicator", token.start_mark) -} - -// Parse the productions: -// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ -// *********** * -func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ == yaml_BLOCK_ENTRY_TOKEN { - mark := token.end_mark - prior_head_len := len(parser.head_comment) - skip_token(parser) - yaml_parser_split_stem_comment(parser, prior_head_len) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_BLOCK_ENTRY_TOKEN && - token.typ != yaml_KEY_TOKEN && - token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_BLOCK_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE) - return yaml_parser_parse_node(parser, event, true, false) - } - parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) - } - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - - *event = yaml_event_t{ - typ: yaml_SEQUENCE_END_EVENT, - start_mark: token.start_mark, - end_mark: token.start_mark, // [Go] Shouldn't this be token.end_mark? - } - return true -} - -// Split stem comment from head comment. -// -// When a sequence or map is found under a sequence entry, the former head comment -// is assigned to the underlying sequence or map as a whole, not the individual -// sequence or map entry as would be expected otherwise. To handle this case the -// previous head comment is moved aside as the stem comment. -func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) { - if stem_len == 0 { - return - } - - token := peek_token(parser) - if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN { - return - } - - parser.stem_comment = parser.head_comment[:stem_len] - if len(parser.head_comment) == stem_len { - parser.head_comment = nil - } else { - // Copy suffix to prevent very strange bugs if someone ever appends - // further bytes to the prefix in the stem_comment slice above. - parser.head_comment = append([]byte(nil), parser.head_comment[stem_len+1:]...) - } -} - -// Parse the productions: -// block_mapping ::= BLOCK-MAPPING_START -// ******************* -// ((KEY block_node_or_indentless_sequence?)? -// *** * -// (VALUE block_node_or_indentless_sequence?)?)* -// -// BLOCK-END -// ********* -// -func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { - if first { - token := peek_token(parser) - if token == nil { - return false - } - parser.marks = append(parser.marks, token.start_mark) - skip_token(parser) - } - - token := peek_token(parser) - if token == nil { - return false - } - - // [Go] A tail comment was left from the prior mapping value processed. Emit an event - // as it needs to be processed with that value and not the following key. - if len(parser.tail_comment) > 0 { - *event = yaml_event_t{ - typ: yaml_TAIL_COMMENT_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - foot_comment: parser.tail_comment, - } - parser.tail_comment = nil - return true - } - - if token.typ == yaml_KEY_TOKEN { - mark := token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_KEY_TOKEN && - token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_BLOCK_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE) - return yaml_parser_parse_node(parser, event, true, true) - } else { - parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) - } - } else if token.typ == yaml_BLOCK_END_TOKEN { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - *event = yaml_event_t{ - typ: yaml_MAPPING_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - yaml_parser_set_event_comments(parser, event) - skip_token(parser) - return true - } - - context_mark := parser.marks[len(parser.marks)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - return yaml_parser_set_parser_error_context(parser, - "while parsing a block mapping", context_mark, - "did not find expected key", token.start_mark) -} - -// Parse the productions: -// block_mapping ::= BLOCK-MAPPING_START -// -// ((KEY block_node_or_indentless_sequence?)? -// -// (VALUE block_node_or_indentless_sequence?)?)* -// ***** * -// BLOCK-END -// -// -func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - if token.typ == yaml_VALUE_TOKEN { - mark := token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_KEY_TOKEN && - token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_BLOCK_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE) - return yaml_parser_parse_node(parser, event, true, true) - } - parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) - } - parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) -} - -// Parse the productions: -// flow_sequence ::= FLOW-SEQUENCE-START -// ******************* -// (flow_sequence_entry FLOW-ENTRY)* -// * ********** -// flow_sequence_entry? -// * -// FLOW-SEQUENCE-END -// ***************** -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// * -// -func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { - if first { - token := peek_token(parser) - if token == nil { - return false - } - parser.marks = append(parser.marks, token.start_mark) - skip_token(parser) - } - token := peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { - if !first { - if token.typ == yaml_FLOW_ENTRY_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } else { - context_mark := parser.marks[len(parser.marks)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - return yaml_parser_set_parser_error_context(parser, - "while parsing a flow sequence", context_mark, - "did not find expected ',' or ']'", token.start_mark) - } - } - - if token.typ == yaml_KEY_TOKEN { - parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE - *event = yaml_event_t{ - typ: yaml_MAPPING_START_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - implicit: true, - style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), - } - skip_token(parser) - return true - } else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - } - - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - - *event = yaml_event_t{ - typ: yaml_SEQUENCE_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - yaml_parser_set_event_comments(parser, event) - - skip_token(parser) - return true -} - -// -// Parse the productions: -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// *** * -// -func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_FLOW_ENTRY_TOKEN && - token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - mark := token.end_mark - skip_token(parser) - parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) -} - -// Parse the productions: -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// ***** * -// -func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - if token.typ == yaml_VALUE_TOKEN { - skip_token(parser) - token := peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - } - parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) -} - -// Parse the productions: -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// * -// -func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE - *event = yaml_event_t{ - typ: yaml_MAPPING_END_EVENT, - start_mark: token.start_mark, - end_mark: token.start_mark, // [Go] Shouldn't this be end_mark? - } - return true -} - -// Parse the productions: -// flow_mapping ::= FLOW-MAPPING-START -// ****************** -// (flow_mapping_entry FLOW-ENTRY)* -// * ********** -// flow_mapping_entry? -// ****************** -// FLOW-MAPPING-END -// **************** -// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// * *** * -// -func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { - if first { - token := peek_token(parser) - parser.marks = append(parser.marks, token.start_mark) - skip_token(parser) - } - - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ != yaml_FLOW_MAPPING_END_TOKEN { - if !first { - if token.typ == yaml_FLOW_ENTRY_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } else { - context_mark := parser.marks[len(parser.marks)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - return yaml_parser_set_parser_error_context(parser, - "while parsing a flow mapping", context_mark, - "did not find expected ',' or '}'", token.start_mark) - } - } - - if token.typ == yaml_KEY_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_FLOW_ENTRY_TOKEN && - token.typ != yaml_FLOW_MAPPING_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } else { - parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) - } - } else if token.typ != yaml_FLOW_MAPPING_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - } - - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - *event = yaml_event_t{ - typ: yaml_MAPPING_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - yaml_parser_set_event_comments(parser, event) - skip_token(parser) - return true -} - -// Parse the productions: -// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// * ***** * -// -func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool { - token := peek_token(parser) - if token == nil { - return false - } - if empty { - parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) - } - if token.typ == yaml_VALUE_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - } - parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) -} - -// Generate an empty scalar event. -func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool { - *event = yaml_event_t{ - typ: yaml_SCALAR_EVENT, - start_mark: mark, - end_mark: mark, - value: nil, // Empty - implicit: true, - style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), - } - return true -} - -var default_tag_directives = []yaml_tag_directive_t{ - {[]byte("!"), []byte("!")}, - {[]byte("!!"), []byte("tag:yaml.org,2002:")}, -} - -// Parse directives. -func yaml_parser_process_directives(parser *yaml_parser_t, - version_directive_ref **yaml_version_directive_t, - tag_directives_ref *[]yaml_tag_directive_t) bool { - - var version_directive *yaml_version_directive_t - var tag_directives []yaml_tag_directive_t - - token := peek_token(parser) - if token == nil { - return false - } - - for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN { - if token.typ == yaml_VERSION_DIRECTIVE_TOKEN { - if version_directive != nil { - yaml_parser_set_parser_error(parser, - "found duplicate %YAML directive", token.start_mark) - return false - } - if token.major != 1 || token.minor != 1 { - yaml_parser_set_parser_error(parser, - "found incompatible YAML document", token.start_mark) - return false - } - version_directive = &yaml_version_directive_t{ - major: token.major, - minor: token.minor, - } - } else if token.typ == yaml_TAG_DIRECTIVE_TOKEN { - value := yaml_tag_directive_t{ - handle: token.value, - prefix: token.prefix, - } - if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) { - return false - } - tag_directives = append(tag_directives, value) - } - - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } - - for i := range default_tag_directives { - if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) { - return false - } - } - - if version_directive_ref != nil { - *version_directive_ref = version_directive - } - if tag_directives_ref != nil { - *tag_directives_ref = tag_directives - } - return true -} - -// Append a tag directive to the directives stack. -func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool { - for i := range parser.tag_directives { - if bytes.Equal(value.handle, parser.tag_directives[i].handle) { - if allow_duplicates { - return true - } - return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark) - } - } - - // [Go] I suspect the copy is unnecessary. This was likely done - // because there was no way to track ownership of the data. - value_copy := yaml_tag_directive_t{ - handle: make([]byte, len(value.handle)), - prefix: make([]byte, len(value.prefix)), - } - copy(value_copy.handle, value.handle) - copy(value_copy.prefix, value.prefix) - parser.tag_directives = append(parser.tag_directives, value_copy) - return true -} diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/readerc.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/readerc.go deleted file mode 100644 index b7de0a8..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/readerc.go +++ /dev/null @@ -1,434 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// 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. - -package yaml - -import ( - "io" -) - -// Set the reader error and return 0. -func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool { - parser.error = yaml_READER_ERROR - parser.problem = problem - parser.problem_offset = offset - parser.problem_value = value - return false -} - -// Byte order marks. -const ( - bom_UTF8 = "\xef\xbb\xbf" - bom_UTF16LE = "\xff\xfe" - bom_UTF16BE = "\xfe\xff" -) - -// Determine the input stream encoding by checking the BOM symbol. If no BOM is -// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure. -func yaml_parser_determine_encoding(parser *yaml_parser_t) bool { - // Ensure that we had enough bytes in the raw buffer. - for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 { - if !yaml_parser_update_raw_buffer(parser) { - return false - } - } - - // Determine the encoding. - buf := parser.raw_buffer - pos := parser.raw_buffer_pos - avail := len(buf) - pos - if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] { - parser.encoding = yaml_UTF16LE_ENCODING - parser.raw_buffer_pos += 2 - parser.offset += 2 - } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] { - parser.encoding = yaml_UTF16BE_ENCODING - parser.raw_buffer_pos += 2 - parser.offset += 2 - } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] { - parser.encoding = yaml_UTF8_ENCODING - parser.raw_buffer_pos += 3 - parser.offset += 3 - } else { - parser.encoding = yaml_UTF8_ENCODING - } - return true -} - -// Update the raw buffer. -func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool { - size_read := 0 - - // Return if the raw buffer is full. - if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) { - return true - } - - // Return on EOF. - if parser.eof { - return true - } - - // Move the remaining bytes in the raw buffer to the beginning. - if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) { - copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:]) - } - parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos] - parser.raw_buffer_pos = 0 - - // Call the read handler to fill the buffer. - size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)]) - parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read] - if err == io.EOF { - parser.eof = true - } else if err != nil { - return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1) - } - return true -} - -// Ensure that the buffer contains at least `length` characters. -// Return true on success, false on failure. -// -// The length is supposed to be significantly less that the buffer size. -func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool { - if parser.read_handler == nil { - panic("read handler must be set") - } - - // [Go] This function was changed to guarantee the requested length size at EOF. - // The fact we need to do this is pretty awful, but the description above implies - // for that to be the case, and there are tests - - // If the EOF flag is set and the raw buffer is empty, do nothing. - if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { - // [Go] ACTUALLY! Read the documentation of this function above. - // This is just broken. To return true, we need to have the - // given length in the buffer. Not doing that means every single - // check that calls this function to make sure the buffer has a - // given length is Go) panicking; or C) accessing invalid memory. - //return true - } - - // Return if the buffer contains enough characters. - if parser.unread >= length { - return true - } - - // Determine the input encoding if it is not known yet. - if parser.encoding == yaml_ANY_ENCODING { - if !yaml_parser_determine_encoding(parser) { - return false - } - } - - // Move the unread characters to the beginning of the buffer. - buffer_len := len(parser.buffer) - if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len { - copy(parser.buffer, parser.buffer[parser.buffer_pos:]) - buffer_len -= parser.buffer_pos - parser.buffer_pos = 0 - } else if parser.buffer_pos == buffer_len { - buffer_len = 0 - parser.buffer_pos = 0 - } - - // Open the whole buffer for writing, and cut it before returning. - parser.buffer = parser.buffer[:cap(parser.buffer)] - - // Fill the buffer until it has enough characters. - first := true - for parser.unread < length { - - // Fill the raw buffer if necessary. - if !first || parser.raw_buffer_pos == len(parser.raw_buffer) { - if !yaml_parser_update_raw_buffer(parser) { - parser.buffer = parser.buffer[:buffer_len] - return false - } - } - first = false - - // Decode the raw buffer. - inner: - for parser.raw_buffer_pos != len(parser.raw_buffer) { - var value rune - var width int - - raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos - - // Decode the next character. - switch parser.encoding { - case yaml_UTF8_ENCODING: - // Decode a UTF-8 character. Check RFC 3629 - // (http://www.ietf.org/rfc/rfc3629.txt) for more details. - // - // The following table (taken from the RFC) is used for - // decoding. - // - // Char. number range | UTF-8 octet sequence - // (hexadecimal) | (binary) - // --------------------+------------------------------------ - // 0000 0000-0000 007F | 0xxxxxxx - // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx - // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx - // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - // - // Additionally, the characters in the range 0xD800-0xDFFF - // are prohibited as they are reserved for use with UTF-16 - // surrogate pairs. - - // Determine the length of the UTF-8 sequence. - octet := parser.raw_buffer[parser.raw_buffer_pos] - switch { - case octet&0x80 == 0x00: - width = 1 - case octet&0xE0 == 0xC0: - width = 2 - case octet&0xF0 == 0xE0: - width = 3 - case octet&0xF8 == 0xF0: - width = 4 - default: - // The leading octet is invalid. - return yaml_parser_set_reader_error(parser, - "invalid leading UTF-8 octet", - parser.offset, int(octet)) - } - - // Check if the raw buffer contains an incomplete character. - if width > raw_unread { - if parser.eof { - return yaml_parser_set_reader_error(parser, - "incomplete UTF-8 octet sequence", - parser.offset, -1) - } - break inner - } - - // Decode the leading octet. - switch { - case octet&0x80 == 0x00: - value = rune(octet & 0x7F) - case octet&0xE0 == 0xC0: - value = rune(octet & 0x1F) - case octet&0xF0 == 0xE0: - value = rune(octet & 0x0F) - case octet&0xF8 == 0xF0: - value = rune(octet & 0x07) - default: - value = 0 - } - - // Check and decode the trailing octets. - for k := 1; k < width; k++ { - octet = parser.raw_buffer[parser.raw_buffer_pos+k] - - // Check if the octet is valid. - if (octet & 0xC0) != 0x80 { - return yaml_parser_set_reader_error(parser, - "invalid trailing UTF-8 octet", - parser.offset+k, int(octet)) - } - - // Decode the octet. - value = (value << 6) + rune(octet&0x3F) - } - - // Check the length of the sequence against the value. - switch { - case width == 1: - case width == 2 && value >= 0x80: - case width == 3 && value >= 0x800: - case width == 4 && value >= 0x10000: - default: - return yaml_parser_set_reader_error(parser, - "invalid length of a UTF-8 sequence", - parser.offset, -1) - } - - // Check the range of the value. - if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF { - return yaml_parser_set_reader_error(parser, - "invalid Unicode character", - parser.offset, int(value)) - } - - case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING: - var low, high int - if parser.encoding == yaml_UTF16LE_ENCODING { - low, high = 0, 1 - } else { - low, high = 1, 0 - } - - // The UTF-16 encoding is not as simple as one might - // naively think. Check RFC 2781 - // (http://www.ietf.org/rfc/rfc2781.txt). - // - // Normally, two subsequent bytes describe a Unicode - // character. However a special technique (called a - // surrogate pair) is used for specifying character - // values larger than 0xFFFF. - // - // A surrogate pair consists of two pseudo-characters: - // high surrogate area (0xD800-0xDBFF) - // low surrogate area (0xDC00-0xDFFF) - // - // The following formulas are used for decoding - // and encoding characters using surrogate pairs: - // - // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF) - // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF) - // W1 = 110110yyyyyyyyyy - // W2 = 110111xxxxxxxxxx - // - // where U is the character value, W1 is the high surrogate - // area, W2 is the low surrogate area. - - // Check for incomplete UTF-16 character. - if raw_unread < 2 { - if parser.eof { - return yaml_parser_set_reader_error(parser, - "incomplete UTF-16 character", - parser.offset, -1) - } - break inner - } - - // Get the character. - value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) + - (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8) - - // Check for unexpected low surrogate area. - if value&0xFC00 == 0xDC00 { - return yaml_parser_set_reader_error(parser, - "unexpected low surrogate area", - parser.offset, int(value)) - } - - // Check for a high surrogate area. - if value&0xFC00 == 0xD800 { - width = 4 - - // Check for incomplete surrogate pair. - if raw_unread < 4 { - if parser.eof { - return yaml_parser_set_reader_error(parser, - "incomplete UTF-16 surrogate pair", - parser.offset, -1) - } - break inner - } - - // Get the next character. - value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) + - (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8) - - // Check for a low surrogate area. - if value2&0xFC00 != 0xDC00 { - return yaml_parser_set_reader_error(parser, - "expected low surrogate area", - parser.offset+2, int(value2)) - } - - // Generate the value of the surrogate pair. - value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF) - } else { - width = 2 - } - - default: - panic("impossible") - } - - // Check if the character is in the allowed range: - // #x9 | #xA | #xD | [#x20-#x7E] (8 bit) - // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit) - // | [#x10000-#x10FFFF] (32 bit) - switch { - case value == 0x09: - case value == 0x0A: - case value == 0x0D: - case value >= 0x20 && value <= 0x7E: - case value == 0x85: - case value >= 0xA0 && value <= 0xD7FF: - case value >= 0xE000 && value <= 0xFFFD: - case value >= 0x10000 && value <= 0x10FFFF: - default: - return yaml_parser_set_reader_error(parser, - "control characters are not allowed", - parser.offset, int(value)) - } - - // Move the raw pointers. - parser.raw_buffer_pos += width - parser.offset += width - - // Finally put the character into the buffer. - if value <= 0x7F { - // 0000 0000-0000 007F . 0xxxxxxx - parser.buffer[buffer_len+0] = byte(value) - buffer_len += 1 - } else if value <= 0x7FF { - // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx - parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6)) - parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F)) - buffer_len += 2 - } else if value <= 0xFFFF { - // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx - parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12)) - parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F)) - parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F)) - buffer_len += 3 - } else { - // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18)) - parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F)) - parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F)) - parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F)) - buffer_len += 4 - } - - parser.unread++ - } - - // On EOF, put NUL into the buffer and return. - if parser.eof { - parser.buffer[buffer_len] = 0 - buffer_len++ - parser.unread++ - break - } - } - // [Go] Read the documentation of this function above. To return true, - // we need to have the given length in the buffer. Not doing that means - // every single check that calls this function to make sure the buffer - // has a given length is Go) panicking; or C) accessing invalid memory. - // This happens here due to the EOF above breaking early. - for buffer_len < length { - parser.buffer[buffer_len] = 0 - buffer_len++ - } - parser.buffer = parser.buffer[:buffer_len] - return true -} diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/resolve.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/resolve.go deleted file mode 100644 index 64ae888..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/resolve.go +++ /dev/null @@ -1,326 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yaml - -import ( - "encoding/base64" - "math" - "regexp" - "strconv" - "strings" - "time" -) - -type resolveMapItem struct { - value interface{} - tag string -} - -var resolveTable = make([]byte, 256) -var resolveMap = make(map[string]resolveMapItem) - -func init() { - t := resolveTable - t[int('+')] = 'S' // Sign - t[int('-')] = 'S' - for _, c := range "0123456789" { - t[int(c)] = 'D' // Digit - } - for _, c := range "yYnNtTfFoO~" { - t[int(c)] = 'M' // In map - } - t[int('.')] = '.' // Float (potentially in map) - - var resolveMapList = []struct { - v interface{} - tag string - l []string - }{ - {true, boolTag, []string{"true", "True", "TRUE"}}, - {false, boolTag, []string{"false", "False", "FALSE"}}, - {nil, nullTag, []string{"", "~", "null", "Null", "NULL"}}, - {math.NaN(), floatTag, []string{".nan", ".NaN", ".NAN"}}, - {math.Inf(+1), floatTag, []string{".inf", ".Inf", ".INF"}}, - {math.Inf(+1), floatTag, []string{"+.inf", "+.Inf", "+.INF"}}, - {math.Inf(-1), floatTag, []string{"-.inf", "-.Inf", "-.INF"}}, - {"<<", mergeTag, []string{"<<"}}, - } - - m := resolveMap - for _, item := range resolveMapList { - for _, s := range item.l { - m[s] = resolveMapItem{item.v, item.tag} - } - } -} - -const ( - nullTag = "!!null" - boolTag = "!!bool" - strTag = "!!str" - intTag = "!!int" - floatTag = "!!float" - timestampTag = "!!timestamp" - seqTag = "!!seq" - mapTag = "!!map" - binaryTag = "!!binary" - mergeTag = "!!merge" -) - -var longTags = make(map[string]string) -var shortTags = make(map[string]string) - -func init() { - for _, stag := range []string{nullTag, boolTag, strTag, intTag, floatTag, timestampTag, seqTag, mapTag, binaryTag, mergeTag} { - ltag := longTag(stag) - longTags[stag] = ltag - shortTags[ltag] = stag - } -} - -const longTagPrefix = "tag:yaml.org,2002:" - -func shortTag(tag string) string { - if strings.HasPrefix(tag, longTagPrefix) { - if stag, ok := shortTags[tag]; ok { - return stag - } - return "!!" + tag[len(longTagPrefix):] - } - return tag -} - -func longTag(tag string) string { - if strings.HasPrefix(tag, "!!") { - if ltag, ok := longTags[tag]; ok { - return ltag - } - return longTagPrefix + tag[2:] - } - return tag -} - -func resolvableTag(tag string) bool { - switch tag { - case "", strTag, boolTag, intTag, floatTag, nullTag, timestampTag: - return true - } - return false -} - -var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`) - -func resolve(tag string, in string) (rtag string, out interface{}) { - tag = shortTag(tag) - if !resolvableTag(tag) { - return tag, in - } - - defer func() { - switch tag { - case "", rtag, strTag, binaryTag: - return - case floatTag: - if rtag == intTag { - switch v := out.(type) { - case int64: - rtag = floatTag - out = float64(v) - return - case int: - rtag = floatTag - out = float64(v) - return - } - } - } - failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) - }() - - // Any data is accepted as a !!str or !!binary. - // Otherwise, the prefix is enough of a hint about what it might be. - hint := byte('N') - if in != "" { - hint = resolveTable[in[0]] - } - if hint != 0 && tag != strTag && tag != binaryTag { - // Handle things we can lookup in a map. - if item, ok := resolveMap[in]; ok { - return item.tag, item.value - } - - // Base 60 floats are a bad idea, were dropped in YAML 1.2, and - // are purposefully unsupported here. They're still quoted on - // the way out for compatibility with other parser, though. - - switch hint { - case 'M': - // We've already checked the map above. - - case '.': - // Not in the map, so maybe a normal float. - floatv, err := strconv.ParseFloat(in, 64) - if err == nil { - return floatTag, floatv - } - - case 'D', 'S': - // Int, float, or timestamp. - // Only try values as a timestamp if the value is unquoted or there's an explicit - // !!timestamp tag. - if tag == "" || tag == timestampTag { - t, ok := parseTimestamp(in) - if ok { - return timestampTag, t - } - } - - plain := strings.Replace(in, "_", "", -1) - intv, err := strconv.ParseInt(plain, 0, 64) - if err == nil { - if intv == int64(int(intv)) { - return intTag, int(intv) - } else { - return intTag, intv - } - } - uintv, err := strconv.ParseUint(plain, 0, 64) - if err == nil { - return intTag, uintv - } - if yamlStyleFloat.MatchString(plain) { - floatv, err := strconv.ParseFloat(plain, 64) - if err == nil { - return floatTag, floatv - } - } - if strings.HasPrefix(plain, "0b") { - intv, err := strconv.ParseInt(plain[2:], 2, 64) - if err == nil { - if intv == int64(int(intv)) { - return intTag, int(intv) - } else { - return intTag, intv - } - } - uintv, err := strconv.ParseUint(plain[2:], 2, 64) - if err == nil { - return intTag, uintv - } - } else if strings.HasPrefix(plain, "-0b") { - intv, err := strconv.ParseInt("-"+plain[3:], 2, 64) - if err == nil { - if true || intv == int64(int(intv)) { - return intTag, int(intv) - } else { - return intTag, intv - } - } - } - // Octals as introduced in version 1.2 of the spec. - // Octals from the 1.1 spec, spelled as 0777, are still - // decoded by default in v3 as well for compatibility. - // May be dropped in v4 depending on how usage evolves. - if strings.HasPrefix(plain, "0o") { - intv, err := strconv.ParseInt(plain[2:], 8, 64) - if err == nil { - if intv == int64(int(intv)) { - return intTag, int(intv) - } else { - return intTag, intv - } - } - uintv, err := strconv.ParseUint(plain[2:], 8, 64) - if err == nil { - return intTag, uintv - } - } else if strings.HasPrefix(plain, "-0o") { - intv, err := strconv.ParseInt("-"+plain[3:], 8, 64) - if err == nil { - if true || intv == int64(int(intv)) { - return intTag, int(intv) - } else { - return intTag, intv - } - } - } - default: - panic("internal error: missing handler for resolver table: " + string(rune(hint)) + " (with " + in + ")") - } - } - return strTag, in -} - -// encodeBase64 encodes s as base64 that is broken up into multiple lines -// as appropriate for the resulting length. -func encodeBase64(s string) string { - const lineLen = 70 - encLen := base64.StdEncoding.EncodedLen(len(s)) - lines := encLen/lineLen + 1 - buf := make([]byte, encLen*2+lines) - in := buf[0:encLen] - out := buf[encLen:] - base64.StdEncoding.Encode(in, []byte(s)) - k := 0 - for i := 0; i < len(in); i += lineLen { - j := i + lineLen - if j > len(in) { - j = len(in) - } - k += copy(out[k:], in[i:j]) - if lines > 1 { - out[k] = '\n' - k++ - } - } - return string(out[:k]) -} - -// This is a subset of the formats allowed by the regular expression -// defined at http://yaml.org/type/timestamp.html. -var allowedTimestampFormats = []string{ - "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields. - "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t". - "2006-1-2 15:4:5.999999999", // space separated with no time zone - "2006-1-2", // date only - // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5" - // from the set of examples. -} - -// parseTimestamp parses s as a timestamp string and -// returns the timestamp and reports whether it succeeded. -// Timestamp formats are defined at http://yaml.org/type/timestamp.html -func parseTimestamp(s string) (time.Time, bool) { - // TODO write code to check all the formats supported by - // http://yaml.org/type/timestamp.html instead of using time.Parse. - - // Quick check: all date formats start with YYYY-. - i := 0 - for ; i < len(s); i++ { - if c := s[i]; c < '0' || c > '9' { - break - } - } - if i != 4 || i == len(s) || s[i] != '-' { - return time.Time{}, false - } - for _, format := range allowedTimestampFormats { - if t, err := time.Parse(format, s); err == nil { - return t, true - } - } - return time.Time{}, false -} diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/scannerc.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/scannerc.go deleted file mode 100644 index ca00701..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/scannerc.go +++ /dev/null @@ -1,3038 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// 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. - -package yaml - -import ( - "bytes" - "fmt" -) - -// Introduction -// ************ -// -// The following notes assume that you are familiar with the YAML specification -// (http://yaml.org/spec/1.2/spec.html). We mostly follow it, although in -// some cases we are less restrictive that it requires. -// -// The process of transforming a YAML stream into a sequence of events is -// divided on two steps: Scanning and Parsing. -// -// The Scanner transforms the input stream into a sequence of tokens, while the -// parser transform the sequence of tokens produced by the Scanner into a -// sequence of parsing events. -// -// The Scanner is rather clever and complicated. The Parser, on the contrary, -// is a straightforward implementation of a recursive-descendant parser (or, -// LL(1) parser, as it is usually called). -// -// Actually there are two issues of Scanning that might be called "clever", the -// rest is quite straightforward. The issues are "block collection start" and -// "simple keys". Both issues are explained below in details. -// -// Here the Scanning step is explained and implemented. We start with the list -// of all the tokens produced by the Scanner together with short descriptions. -// -// Now, tokens: -// -// STREAM-START(encoding) # The stream start. -// STREAM-END # The stream end. -// VERSION-DIRECTIVE(major,minor) # The '%YAML' directive. -// TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive. -// DOCUMENT-START # '---' -// DOCUMENT-END # '...' -// BLOCK-SEQUENCE-START # Indentation increase denoting a block -// BLOCK-MAPPING-START # sequence or a block mapping. -// BLOCK-END # Indentation decrease. -// FLOW-SEQUENCE-START # '[' -// FLOW-SEQUENCE-END # ']' -// BLOCK-SEQUENCE-START # '{' -// BLOCK-SEQUENCE-END # '}' -// BLOCK-ENTRY # '-' -// FLOW-ENTRY # ',' -// KEY # '?' or nothing (simple keys). -// VALUE # ':' -// ALIAS(anchor) # '*anchor' -// ANCHOR(anchor) # '&anchor' -// TAG(handle,suffix) # '!handle!suffix' -// SCALAR(value,style) # A scalar. -// -// The following two tokens are "virtual" tokens denoting the beginning and the -// end of the stream: -// -// STREAM-START(encoding) -// STREAM-END -// -// We pass the information about the input stream encoding with the -// STREAM-START token. -// -// The next two tokens are responsible for tags: -// -// VERSION-DIRECTIVE(major,minor) -// TAG-DIRECTIVE(handle,prefix) -// -// Example: -// -// %YAML 1.1 -// %TAG ! !foo -// %TAG !yaml! tag:yaml.org,2002: -// --- -// -// The correspoding sequence of tokens: -// -// STREAM-START(utf-8) -// VERSION-DIRECTIVE(1,1) -// TAG-DIRECTIVE("!","!foo") -// TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:") -// DOCUMENT-START -// STREAM-END -// -// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole -// line. -// -// The document start and end indicators are represented by: -// -// DOCUMENT-START -// DOCUMENT-END -// -// Note that if a YAML stream contains an implicit document (without '---' -// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be -// produced. -// -// In the following examples, we present whole documents together with the -// produced tokens. -// -// 1. An implicit document: -// -// 'a scalar' -// -// Tokens: -// -// STREAM-START(utf-8) -// SCALAR("a scalar",single-quoted) -// STREAM-END -// -// 2. An explicit document: -// -// --- -// 'a scalar' -// ... -// -// Tokens: -// -// STREAM-START(utf-8) -// DOCUMENT-START -// SCALAR("a scalar",single-quoted) -// DOCUMENT-END -// STREAM-END -// -// 3. Several documents in a stream: -// -// 'a scalar' -// --- -// 'another scalar' -// --- -// 'yet another scalar' -// -// Tokens: -// -// STREAM-START(utf-8) -// SCALAR("a scalar",single-quoted) -// DOCUMENT-START -// SCALAR("another scalar",single-quoted) -// DOCUMENT-START -// SCALAR("yet another scalar",single-quoted) -// STREAM-END -// -// We have already introduced the SCALAR token above. The following tokens are -// used to describe aliases, anchors, tag, and scalars: -// -// ALIAS(anchor) -// ANCHOR(anchor) -// TAG(handle,suffix) -// SCALAR(value,style) -// -// The following series of examples illustrate the usage of these tokens: -// -// 1. A recursive sequence: -// -// &A [ *A ] -// -// Tokens: -// -// STREAM-START(utf-8) -// ANCHOR("A") -// FLOW-SEQUENCE-START -// ALIAS("A") -// FLOW-SEQUENCE-END -// STREAM-END -// -// 2. A tagged scalar: -// -// !!float "3.14" # A good approximation. -// -// Tokens: -// -// STREAM-START(utf-8) -// TAG("!!","float") -// SCALAR("3.14",double-quoted) -// STREAM-END -// -// 3. Various scalar styles: -// -// --- # Implicit empty plain scalars do not produce tokens. -// --- a plain scalar -// --- 'a single-quoted scalar' -// --- "a double-quoted scalar" -// --- |- -// a literal scalar -// --- >- -// a folded -// scalar -// -// Tokens: -// -// STREAM-START(utf-8) -// DOCUMENT-START -// DOCUMENT-START -// SCALAR("a plain scalar",plain) -// DOCUMENT-START -// SCALAR("a single-quoted scalar",single-quoted) -// DOCUMENT-START -// SCALAR("a double-quoted scalar",double-quoted) -// DOCUMENT-START -// SCALAR("a literal scalar",literal) -// DOCUMENT-START -// SCALAR("a folded scalar",folded) -// STREAM-END -// -// Now it's time to review collection-related tokens. We will start with -// flow collections: -// -// FLOW-SEQUENCE-START -// FLOW-SEQUENCE-END -// FLOW-MAPPING-START -// FLOW-MAPPING-END -// FLOW-ENTRY -// KEY -// VALUE -// -// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and -// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}' -// correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the -// indicators '?' and ':', which are used for denoting mapping keys and values, -// are represented by the KEY and VALUE tokens. -// -// The following examples show flow collections: -// -// 1. A flow sequence: -// -// [item 1, item 2, item 3] -// -// Tokens: -// -// STREAM-START(utf-8) -// FLOW-SEQUENCE-START -// SCALAR("item 1",plain) -// FLOW-ENTRY -// SCALAR("item 2",plain) -// FLOW-ENTRY -// SCALAR("item 3",plain) -// FLOW-SEQUENCE-END -// STREAM-END -// -// 2. A flow mapping: -// -// { -// a simple key: a value, # Note that the KEY token is produced. -// ? a complex key: another value, -// } -// -// Tokens: -// -// STREAM-START(utf-8) -// FLOW-MAPPING-START -// KEY -// SCALAR("a simple key",plain) -// VALUE -// SCALAR("a value",plain) -// FLOW-ENTRY -// KEY -// SCALAR("a complex key",plain) -// VALUE -// SCALAR("another value",plain) -// FLOW-ENTRY -// FLOW-MAPPING-END -// STREAM-END -// -// A simple key is a key which is not denoted by the '?' indicator. Note that -// the Scanner still produce the KEY token whenever it encounters a simple key. -// -// For scanning block collections, the following tokens are used (note that we -// repeat KEY and VALUE here): -// -// BLOCK-SEQUENCE-START -// BLOCK-MAPPING-START -// BLOCK-END -// BLOCK-ENTRY -// KEY -// VALUE -// -// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation -// increase that precedes a block collection (cf. the INDENT token in Python). -// The token BLOCK-END denote indentation decrease that ends a block collection -// (cf. the DEDENT token in Python). However YAML has some syntax pecularities -// that makes detections of these tokens more complex. -// -// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators -// '-', '?', and ':' correspondingly. -// -// The following examples show how the tokens BLOCK-SEQUENCE-START, -// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner: -// -// 1. Block sequences: -// -// - item 1 -// - item 2 -// - -// - item 3.1 -// - item 3.2 -// - -// key 1: value 1 -// key 2: value 2 -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-ENTRY -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 3.1",plain) -// BLOCK-ENTRY -// SCALAR("item 3.2",plain) -// BLOCK-END -// BLOCK-ENTRY -// BLOCK-MAPPING-START -// KEY -// SCALAR("key 1",plain) -// VALUE -// SCALAR("value 1",plain) -// KEY -// SCALAR("key 2",plain) -// VALUE -// SCALAR("value 2",plain) -// BLOCK-END -// BLOCK-END -// STREAM-END -// -// 2. Block mappings: -// -// a simple key: a value # The KEY token is produced here. -// ? a complex key -// : another value -// a mapping: -// key 1: value 1 -// key 2: value 2 -// a sequence: -// - item 1 -// - item 2 -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-MAPPING-START -// KEY -// SCALAR("a simple key",plain) -// VALUE -// SCALAR("a value",plain) -// KEY -// SCALAR("a complex key",plain) -// VALUE -// SCALAR("another value",plain) -// KEY -// SCALAR("a mapping",plain) -// BLOCK-MAPPING-START -// KEY -// SCALAR("key 1",plain) -// VALUE -// SCALAR("value 1",plain) -// KEY -// SCALAR("key 2",plain) -// VALUE -// SCALAR("value 2",plain) -// BLOCK-END -// KEY -// SCALAR("a sequence",plain) -// VALUE -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-END -// BLOCK-END -// STREAM-END -// -// YAML does not always require to start a new block collection from a new -// line. If the current line contains only '-', '?', and ':' indicators, a new -// block collection may start at the current line. The following examples -// illustrate this case: -// -// 1. Collections in a sequence: -// -// - - item 1 -// - item 2 -// - key 1: value 1 -// key 2: value 2 -// - ? complex key -// : complex value -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-END -// BLOCK-ENTRY -// BLOCK-MAPPING-START -// KEY -// SCALAR("key 1",plain) -// VALUE -// SCALAR("value 1",plain) -// KEY -// SCALAR("key 2",plain) -// VALUE -// SCALAR("value 2",plain) -// BLOCK-END -// BLOCK-ENTRY -// BLOCK-MAPPING-START -// KEY -// SCALAR("complex key") -// VALUE -// SCALAR("complex value") -// BLOCK-END -// BLOCK-END -// STREAM-END -// -// 2. Collections in a mapping: -// -// ? a sequence -// : - item 1 -// - item 2 -// ? a mapping -// : key 1: value 1 -// key 2: value 2 -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-MAPPING-START -// KEY -// SCALAR("a sequence",plain) -// VALUE -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-END -// KEY -// SCALAR("a mapping",plain) -// VALUE -// BLOCK-MAPPING-START -// KEY -// SCALAR("key 1",plain) -// VALUE -// SCALAR("value 1",plain) -// KEY -// SCALAR("key 2",plain) -// VALUE -// SCALAR("value 2",plain) -// BLOCK-END -// BLOCK-END -// STREAM-END -// -// YAML also permits non-indented sequences if they are included into a block -// mapping. In this case, the token BLOCK-SEQUENCE-START is not produced: -// -// key: -// - item 1 # BLOCK-SEQUENCE-START is NOT produced here. -// - item 2 -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-MAPPING-START -// KEY -// SCALAR("key",plain) -// VALUE -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-END -// - -// Ensure that the buffer contains the required number of characters. -// Return true on success, false on failure (reader error or memory error). -func cache(parser *yaml_parser_t, length int) bool { - // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B) - return parser.unread >= length || yaml_parser_update_buffer(parser, length) -} - -// Advance the buffer pointer. -func skip(parser *yaml_parser_t) { - if !is_blank(parser.buffer, parser.buffer_pos) { - parser.newlines = 0 - } - parser.mark.index++ - parser.mark.column++ - parser.unread-- - parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) -} - -func skip_line(parser *yaml_parser_t) { - if is_crlf(parser.buffer, parser.buffer_pos) { - parser.mark.index += 2 - parser.mark.column = 0 - parser.mark.line++ - parser.unread -= 2 - parser.buffer_pos += 2 - parser.newlines++ - } else if is_break(parser.buffer, parser.buffer_pos) { - parser.mark.index++ - parser.mark.column = 0 - parser.mark.line++ - parser.unread-- - parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) - parser.newlines++ - } -} - -// Copy a character to a string buffer and advance pointers. -func read(parser *yaml_parser_t, s []byte) []byte { - if !is_blank(parser.buffer, parser.buffer_pos) { - parser.newlines = 0 - } - w := width(parser.buffer[parser.buffer_pos]) - if w == 0 { - panic("invalid character sequence") - } - if len(s) == 0 { - s = make([]byte, 0, 32) - } - if w == 1 && len(s)+w <= cap(s) { - s = s[:len(s)+1] - s[len(s)-1] = parser.buffer[parser.buffer_pos] - parser.buffer_pos++ - } else { - s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...) - parser.buffer_pos += w - } - parser.mark.index++ - parser.mark.column++ - parser.unread-- - return s -} - -// Copy a line break character to a string buffer and advance pointers. -func read_line(parser *yaml_parser_t, s []byte) []byte { - buf := parser.buffer - pos := parser.buffer_pos - switch { - case buf[pos] == '\r' && buf[pos+1] == '\n': - // CR LF . LF - s = append(s, '\n') - parser.buffer_pos += 2 - parser.mark.index++ - parser.unread-- - case buf[pos] == '\r' || buf[pos] == '\n': - // CR|LF . LF - s = append(s, '\n') - parser.buffer_pos += 1 - case buf[pos] == '\xC2' && buf[pos+1] == '\x85': - // NEL . LF - s = append(s, '\n') - parser.buffer_pos += 2 - case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'): - // LS|PS . LS|PS - s = append(s, buf[parser.buffer_pos:pos+3]...) - parser.buffer_pos += 3 - default: - return s - } - parser.mark.index++ - parser.mark.column = 0 - parser.mark.line++ - parser.unread-- - parser.newlines++ - return s -} - -// Get the next token. -func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool { - // Erase the token object. - *token = yaml_token_t{} // [Go] Is this necessary? - - // No tokens after STREAM-END or error. - if parser.stream_end_produced || parser.error != yaml_NO_ERROR { - return true - } - - // Ensure that the tokens queue contains enough tokens. - if !parser.token_available { - if !yaml_parser_fetch_more_tokens(parser) { - return false - } - } - - // Fetch the next token from the queue. - *token = parser.tokens[parser.tokens_head] - parser.tokens_head++ - parser.tokens_parsed++ - parser.token_available = false - - if token.typ == yaml_STREAM_END_TOKEN { - parser.stream_end_produced = true - } - return true -} - -// Set the scanner error and return false. -func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool { - parser.error = yaml_SCANNER_ERROR - parser.context = context - parser.context_mark = context_mark - parser.problem = problem - parser.problem_mark = parser.mark - return false -} - -func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool { - context := "while parsing a tag" - if directive { - context = "while parsing a %TAG directive" - } - return yaml_parser_set_scanner_error(parser, context, context_mark, problem) -} - -func trace(args ...interface{}) func() { - pargs := append([]interface{}{"+++"}, args...) - fmt.Println(pargs...) - pargs = append([]interface{}{"---"}, args...) - return func() { fmt.Println(pargs...) } -} - -// Ensure that the tokens queue contains at least one token which can be -// returned to the Parser. -func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool { - // While we need more tokens to fetch, do it. - for { - // [Go] The comment parsing logic requires a lookahead of two tokens - // so that foot comments may be parsed in time of associating them - // with the tokens that are parsed before them, and also for line - // comments to be transformed into head comments in some edge cases. - if parser.tokens_head < len(parser.tokens)-2 { - // If a potential simple key is at the head position, we need to fetch - // the next token to disambiguate it. - head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed] - if !ok { - break - } else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok { - return false - } else if !valid { - break - } - } - // Fetch the next token. - if !yaml_parser_fetch_next_token(parser) { - return false - } - } - - parser.token_available = true - return true -} - -// The dispatcher for token fetchers. -func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) { - // Ensure that the buffer is initialized. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - // Check if we just started scanning. Fetch STREAM-START then. - if !parser.stream_start_produced { - return yaml_parser_fetch_stream_start(parser) - } - - scan_mark := parser.mark - - // Eat whitespaces and comments until we reach the next token. - if !yaml_parser_scan_to_next_token(parser) { - return false - } - - // [Go] While unrolling indents, transform the head comments of prior - // indentation levels observed after scan_start into foot comments at - // the respective indexes. - - // Check the indentation level against the current column. - if !yaml_parser_unroll_indent(parser, parser.mark.column, scan_mark) { - return false - } - - // Ensure that the buffer contains at least 4 characters. 4 is the length - // of the longest indicators ('--- ' and '... '). - if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { - return false - } - - // Is it the end of the stream? - if is_z(parser.buffer, parser.buffer_pos) { - return yaml_parser_fetch_stream_end(parser) - } - - // Is it a directive? - if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' { - return yaml_parser_fetch_directive(parser) - } - - buf := parser.buffer - pos := parser.buffer_pos - - // Is it the document start indicator? - if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) { - return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN) - } - - // Is it the document end indicator? - if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) { - return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN) - } - - comment_mark := parser.mark - if len(parser.tokens) > 0 && (parser.flow_level == 0 && buf[pos] == ':' || parser.flow_level > 0 && buf[pos] == ',') { - // Associate any following comments with the prior token. - comment_mark = parser.tokens[len(parser.tokens)-1].start_mark - } - defer func() { - if !ok { - return - } - if len(parser.tokens) > 0 && parser.tokens[len(parser.tokens)-1].typ == yaml_BLOCK_ENTRY_TOKEN { - // Sequence indicators alone have no line comments. It becomes - // a head comment for whatever follows. - return - } - if !yaml_parser_scan_line_comment(parser, comment_mark) { - ok = false - return - } - }() - - // Is it the flow sequence start indicator? - if buf[pos] == '[' { - return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN) - } - - // Is it the flow mapping start indicator? - if parser.buffer[parser.buffer_pos] == '{' { - return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN) - } - - // Is it the flow sequence end indicator? - if parser.buffer[parser.buffer_pos] == ']' { - return yaml_parser_fetch_flow_collection_end(parser, - yaml_FLOW_SEQUENCE_END_TOKEN) - } - - // Is it the flow mapping end indicator? - if parser.buffer[parser.buffer_pos] == '}' { - return yaml_parser_fetch_flow_collection_end(parser, - yaml_FLOW_MAPPING_END_TOKEN) - } - - // Is it the flow entry indicator? - if parser.buffer[parser.buffer_pos] == ',' { - return yaml_parser_fetch_flow_entry(parser) - } - - // Is it the block entry indicator? - if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) { - return yaml_parser_fetch_block_entry(parser) - } - - // Is it the key indicator? - if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { - return yaml_parser_fetch_key(parser) - } - - // Is it the value indicator? - if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { - return yaml_parser_fetch_value(parser) - } - - // Is it an alias? - if parser.buffer[parser.buffer_pos] == '*' { - return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN) - } - - // Is it an anchor? - if parser.buffer[parser.buffer_pos] == '&' { - return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN) - } - - // Is it a tag? - if parser.buffer[parser.buffer_pos] == '!' { - return yaml_parser_fetch_tag(parser) - } - - // Is it a literal scalar? - if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 { - return yaml_parser_fetch_block_scalar(parser, true) - } - - // Is it a folded scalar? - if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 { - return yaml_parser_fetch_block_scalar(parser, false) - } - - // Is it a single-quoted scalar? - if parser.buffer[parser.buffer_pos] == '\'' { - return yaml_parser_fetch_flow_scalar(parser, true) - } - - // Is it a double-quoted scalar? - if parser.buffer[parser.buffer_pos] == '"' { - return yaml_parser_fetch_flow_scalar(parser, false) - } - - // Is it a plain scalar? - // - // A plain scalar may start with any non-blank characters except - // - // '-', '?', ':', ',', '[', ']', '{', '}', - // '#', '&', '*', '!', '|', '>', '\'', '\"', - // '%', '@', '`'. - // - // In the block context (and, for the '-' indicator, in the flow context - // too), it may also start with the characters - // - // '-', '?', ':' - // - // if it is followed by a non-space character. - // - // The last rule is more restrictive than the specification requires. - // [Go] TODO Make this logic more reasonable. - //switch parser.buffer[parser.buffer_pos] { - //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`': - //} - if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' || - parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' || - parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' || - parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || - parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' || - parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' || - parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' || - parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' || - parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' || - parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') || - (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) || - (parser.flow_level == 0 && - (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') && - !is_blankz(parser.buffer, parser.buffer_pos+1)) { - return yaml_parser_fetch_plain_scalar(parser) - } - - // If we don't determine the token type so far, it is an error. - return yaml_parser_set_scanner_error(parser, - "while scanning for the next token", parser.mark, - "found character that cannot start any token") -} - -func yaml_simple_key_is_valid(parser *yaml_parser_t, simple_key *yaml_simple_key_t) (valid, ok bool) { - if !simple_key.possible { - return false, true - } - - // The 1.2 specification says: - // - // "If the ? indicator is omitted, parsing needs to see past the - // implicit key to recognize it as such. To limit the amount of - // lookahead required, the “:” indicator must appear at most 1024 - // Unicode characters beyond the start of the key. In addition, the key - // is restricted to a single line." - // - if simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index { - // Check if the potential simple key to be removed is required. - if simple_key.required { - return false, yaml_parser_set_scanner_error(parser, - "while scanning a simple key", simple_key.mark, - "could not find expected ':'") - } - simple_key.possible = false - return false, true - } - return true, true -} - -// Check if a simple key may start at the current position and add it if -// needed. -func yaml_parser_save_simple_key(parser *yaml_parser_t) bool { - // A simple key is required at the current position if the scanner is in - // the block context and the current column coincides with the indentation - // level. - - required := parser.flow_level == 0 && parser.indent == parser.mark.column - - // - // If the current position may start a simple key, save it. - // - if parser.simple_key_allowed { - simple_key := yaml_simple_key_t{ - possible: true, - required: required, - token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), - mark: parser.mark, - } - - if !yaml_parser_remove_simple_key(parser) { - return false - } - parser.simple_keys[len(parser.simple_keys)-1] = simple_key - parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1 - } - return true -} - -// Remove a potential simple key at the current flow level. -func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool { - i := len(parser.simple_keys) - 1 - if parser.simple_keys[i].possible { - // If the key is required, it is an error. - if parser.simple_keys[i].required { - return yaml_parser_set_scanner_error(parser, - "while scanning a simple key", parser.simple_keys[i].mark, - "could not find expected ':'") - } - // Remove the key from the stack. - parser.simple_keys[i].possible = false - delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number) - } - return true -} - -// max_flow_level limits the flow_level -const max_flow_level = 10000 - -// Increase the flow level and resize the simple key list if needed. -func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { - // Reset the simple key on the next level. - parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{ - possible: false, - required: false, - token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), - mark: parser.mark, - }) - - // Increase the flow level. - parser.flow_level++ - if parser.flow_level > max_flow_level { - return yaml_parser_set_scanner_error(parser, - "while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark, - fmt.Sprintf("exceeded max depth of %d", max_flow_level)) - } - return true -} - -// Decrease the flow level. -func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool { - if parser.flow_level > 0 { - parser.flow_level-- - last := len(parser.simple_keys) - 1 - delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number) - parser.simple_keys = parser.simple_keys[:last] - } - return true -} - -// max_indents limits the indents stack size -const max_indents = 10000 - -// Push the current indentation level to the stack and set the new level -// the current column is greater than the indentation level. In this case, -// append or insert the specified token into the token queue. -func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool { - // In the flow context, do nothing. - if parser.flow_level > 0 { - return true - } - - if parser.indent < column { - // Push the current indentation level to the stack and set the new - // indentation level. - parser.indents = append(parser.indents, parser.indent) - parser.indent = column - if len(parser.indents) > max_indents { - return yaml_parser_set_scanner_error(parser, - "while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark, - fmt.Sprintf("exceeded max depth of %d", max_indents)) - } - - // Create a token and insert it into the queue. - token := yaml_token_t{ - typ: typ, - start_mark: mark, - end_mark: mark, - } - if number > -1 { - number -= parser.tokens_parsed - } - yaml_insert_token(parser, number, &token) - } - return true -} - -// Pop indentation levels from the indents stack until the current level -// becomes less or equal to the column. For each indentation level, append -// the BLOCK-END token. -func yaml_parser_unroll_indent(parser *yaml_parser_t, column int, scan_mark yaml_mark_t) bool { - // In the flow context, do nothing. - if parser.flow_level > 0 { - return true - } - - block_mark := scan_mark - block_mark.index-- - - // Loop through the indentation levels in the stack. - for parser.indent > column { - - // [Go] Reposition the end token before potential following - // foot comments of parent blocks. For that, search - // backwards for recent comments that were at the same - // indent as the block that is ending now. - stop_index := block_mark.index - for i := len(parser.comments) - 1; i >= 0; i-- { - comment := &parser.comments[i] - - if comment.end_mark.index < stop_index { - // Don't go back beyond the start of the comment/whitespace scan, unless column < 0. - // If requested indent column is < 0, then the document is over and everything else - // is a foot anyway. - break - } - if comment.start_mark.column == parser.indent+1 { - // This is a good match. But maybe there's a former comment - // at that same indent level, so keep searching. - block_mark = comment.start_mark - } - - // While the end of the former comment matches with - // the start of the following one, we know there's - // nothing in between and scanning is still safe. - stop_index = comment.scan_mark.index - } - - // Create a token and append it to the queue. - token := yaml_token_t{ - typ: yaml_BLOCK_END_TOKEN, - start_mark: block_mark, - end_mark: block_mark, - } - yaml_insert_token(parser, -1, &token) - - // Pop the indentation level. - parser.indent = parser.indents[len(parser.indents)-1] - parser.indents = parser.indents[:len(parser.indents)-1] - } - return true -} - -// Initialize the scanner and produce the STREAM-START token. -func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool { - - // Set the initial indentation. - parser.indent = -1 - - // Initialize the simple key stack. - parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) - - parser.simple_keys_by_tok = make(map[int]int) - - // A simple key is allowed at the beginning of the stream. - parser.simple_key_allowed = true - - // We have started. - parser.stream_start_produced = true - - // Create the STREAM-START token and append it to the queue. - token := yaml_token_t{ - typ: yaml_STREAM_START_TOKEN, - start_mark: parser.mark, - end_mark: parser.mark, - encoding: parser.encoding, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the STREAM-END token and shut down the scanner. -func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool { - - // Force new line. - if parser.mark.column != 0 { - parser.mark.column = 0 - parser.mark.line++ - } - - // Reset the indentation level. - if !yaml_parser_unroll_indent(parser, -1, parser.mark) { - return false - } - - // Reset simple keys. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - parser.simple_key_allowed = false - - // Create the STREAM-END token and append it to the queue. - token := yaml_token_t{ - typ: yaml_STREAM_END_TOKEN, - start_mark: parser.mark, - end_mark: parser.mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token. -func yaml_parser_fetch_directive(parser *yaml_parser_t) bool { - // Reset the indentation level. - if !yaml_parser_unroll_indent(parser, -1, parser.mark) { - return false - } - - // Reset simple keys. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - parser.simple_key_allowed = false - - // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. - token := yaml_token_t{} - if !yaml_parser_scan_directive(parser, &token) { - return false - } - // Append the token to the queue. - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the DOCUMENT-START or DOCUMENT-END token. -func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool { - // Reset the indentation level. - if !yaml_parser_unroll_indent(parser, -1, parser.mark) { - return false - } - - // Reset simple keys. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - parser.simple_key_allowed = false - - // Consume the token. - start_mark := parser.mark - - skip(parser) - skip(parser) - skip(parser) - - end_mark := parser.mark - - // Create the DOCUMENT-START or DOCUMENT-END token. - token := yaml_token_t{ - typ: typ, - start_mark: start_mark, - end_mark: end_mark, - } - // Append the token to the queue. - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token. -func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool { - - // The indicators '[' and '{' may start a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // Increase the flow level. - if !yaml_parser_increase_flow_level(parser) { - return false - } - - // A simple key may follow the indicators '[' and '{'. - parser.simple_key_allowed = true - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. - token := yaml_token_t{ - typ: typ, - start_mark: start_mark, - end_mark: end_mark, - } - // Append the token to the queue. - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token. -func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool { - // Reset any potential simple key on the current flow level. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // Decrease the flow level. - if !yaml_parser_decrease_flow_level(parser) { - return false - } - - // No simple keys after the indicators ']' and '}'. - parser.simple_key_allowed = false - - // Consume the token. - - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. - token := yaml_token_t{ - typ: typ, - start_mark: start_mark, - end_mark: end_mark, - } - // Append the token to the queue. - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the FLOW-ENTRY token. -func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool { - // Reset any potential simple keys on the current flow level. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // Simple keys are allowed after ','. - parser.simple_key_allowed = true - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the FLOW-ENTRY token and append it to the queue. - token := yaml_token_t{ - typ: yaml_FLOW_ENTRY_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the BLOCK-ENTRY token. -func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool { - // Check if the scanner is in the block context. - if parser.flow_level == 0 { - // Check if we are allowed to start a new entry. - if !parser.simple_key_allowed { - return yaml_parser_set_scanner_error(parser, "", parser.mark, - "block sequence entries are not allowed in this context") - } - // Add the BLOCK-SEQUENCE-START token if needed. - if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) { - return false - } - } else { - // It is an error for the '-' indicator to occur in the flow context, - // but we let the Parser detect and report about it because the Parser - // is able to point to the context. - } - - // Reset any potential simple keys on the current flow level. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // Simple keys are allowed after '-'. - parser.simple_key_allowed = true - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the BLOCK-ENTRY token and append it to the queue. - token := yaml_token_t{ - typ: yaml_BLOCK_ENTRY_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the KEY token. -func yaml_parser_fetch_key(parser *yaml_parser_t) bool { - - // In the block context, additional checks are required. - if parser.flow_level == 0 { - // Check if we are allowed to start a new key (not nessesary simple). - if !parser.simple_key_allowed { - return yaml_parser_set_scanner_error(parser, "", parser.mark, - "mapping keys are not allowed in this context") - } - // Add the BLOCK-MAPPING-START token if needed. - if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { - return false - } - } - - // Reset any potential simple keys on the current flow level. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // Simple keys are allowed after '?' in the block context. - parser.simple_key_allowed = parser.flow_level == 0 - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the KEY token and append it to the queue. - token := yaml_token_t{ - typ: yaml_KEY_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the VALUE token. -func yaml_parser_fetch_value(parser *yaml_parser_t) bool { - - simple_key := &parser.simple_keys[len(parser.simple_keys)-1] - - // Have we found a simple key? - if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok { - return false - - } else if valid { - - // Create the KEY token and insert it into the queue. - token := yaml_token_t{ - typ: yaml_KEY_TOKEN, - start_mark: simple_key.mark, - end_mark: simple_key.mark, - } - yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token) - - // In the block context, we may need to add the BLOCK-MAPPING-START token. - if !yaml_parser_roll_indent(parser, simple_key.mark.column, - simple_key.token_number, - yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) { - return false - } - - // Remove the simple key. - simple_key.possible = false - delete(parser.simple_keys_by_tok, simple_key.token_number) - - // A simple key cannot follow another simple key. - parser.simple_key_allowed = false - - } else { - // The ':' indicator follows a complex key. - - // In the block context, extra checks are required. - if parser.flow_level == 0 { - - // Check if we are allowed to start a complex value. - if !parser.simple_key_allowed { - return yaml_parser_set_scanner_error(parser, "", parser.mark, - "mapping values are not allowed in this context") - } - - // Add the BLOCK-MAPPING-START token if needed. - if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { - return false - } - } - - // Simple keys after ':' are allowed in the block context. - parser.simple_key_allowed = parser.flow_level == 0 - } - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the VALUE token and append it to the queue. - token := yaml_token_t{ - typ: yaml_VALUE_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the ALIAS or ANCHOR token. -func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool { - // An anchor or an alias could be a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // A simple key cannot follow an anchor or an alias. - parser.simple_key_allowed = false - - // Create the ALIAS or ANCHOR token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_anchor(parser, &token, typ) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the TAG token. -func yaml_parser_fetch_tag(parser *yaml_parser_t) bool { - // A tag could be a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // A simple key cannot follow a tag. - parser.simple_key_allowed = false - - // Create the TAG token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_tag(parser, &token) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens. -func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool { - // Remove any potential simple keys. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // A simple key may follow a block scalar. - parser.simple_key_allowed = true - - // Create the SCALAR token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_block_scalar(parser, &token, literal) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens. -func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool { - // A plain scalar could be a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // A simple key cannot follow a flow scalar. - parser.simple_key_allowed = false - - // Create the SCALAR token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_flow_scalar(parser, &token, single) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the SCALAR(...,plain) token. -func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool { - // A plain scalar could be a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // A simple key cannot follow a flow scalar. - parser.simple_key_allowed = false - - // Create the SCALAR token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_plain_scalar(parser, &token) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Eat whitespaces and comments until the next token is found. -func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool { - - scan_mark := parser.mark - - // Until the next token is not found. - for { - // Allow the BOM mark to start a line. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) { - skip(parser) - } - - // Eat whitespaces. - // Tabs are allowed: - // - in the flow context - // - in the block context, but not at the beginning of the line or - // after '-', '?', or ':' (complex value). - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check if we just had a line comment under a sequence entry that - // looks more like a header to the following content. Similar to this: - // - // - # The comment - // - Some data - // - // If so, transform the line comment to a head comment and reposition. - if len(parser.comments) > 0 && len(parser.tokens) > 1 { - tokenA := parser.tokens[len(parser.tokens)-2] - tokenB := parser.tokens[len(parser.tokens)-1] - comment := &parser.comments[len(parser.comments)-1] - if tokenA.typ == yaml_BLOCK_SEQUENCE_START_TOKEN && tokenB.typ == yaml_BLOCK_ENTRY_TOKEN && len(comment.line) > 0 && !is_break(parser.buffer, parser.buffer_pos) { - // If it was in the prior line, reposition so it becomes a - // header of the follow up token. Otherwise, keep it in place - // so it becomes a header of the former. - comment.head = comment.line - comment.line = nil - if comment.start_mark.line == parser.mark.line-1 { - comment.token_mark = parser.mark - } - } - } - - // Eat a comment until a line break. - if parser.buffer[parser.buffer_pos] == '#' { - if !yaml_parser_scan_comments(parser, scan_mark) { - return false - } - } - - // If it is a line break, eat it. - if is_break(parser.buffer, parser.buffer_pos) { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - skip_line(parser) - - // In the block context, a new line may start a simple key. - if parser.flow_level == 0 { - parser.simple_key_allowed = true - } - } else { - break // We have found a token. - } - } - - return true -} - -// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token. -// -// Scope: -// %YAML 1.1 # a comment \n -// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -// %TAG !yaml! tag:yaml.org,2002: \n -// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -// -func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool { - // Eat '%'. - start_mark := parser.mark - skip(parser) - - // Scan the directive name. - var name []byte - if !yaml_parser_scan_directive_name(parser, start_mark, &name) { - return false - } - - // Is it a YAML directive? - if bytes.Equal(name, []byte("YAML")) { - // Scan the VERSION directive value. - var major, minor int8 - if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) { - return false - } - end_mark := parser.mark - - // Create a VERSION-DIRECTIVE token. - *token = yaml_token_t{ - typ: yaml_VERSION_DIRECTIVE_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - major: major, - minor: minor, - } - - // Is it a TAG directive? - } else if bytes.Equal(name, []byte("TAG")) { - // Scan the TAG directive value. - var handle, prefix []byte - if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) { - return false - } - end_mark := parser.mark - - // Create a TAG-DIRECTIVE token. - *token = yaml_token_t{ - typ: yaml_TAG_DIRECTIVE_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: handle, - prefix: prefix, - } - - // Unknown directive. - } else { - yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "found unknown directive name") - return false - } - - // Eat the rest of the line including any comments. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - if parser.buffer[parser.buffer_pos] == '#' { - // [Go] Discard this inline comment for the time being. - //if !yaml_parser_scan_line_comment(parser, start_mark) { - // return false - //} - for !is_breakz(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - } - - // Check if we are at the end of the line. - if !is_breakz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "did not find expected comment or line break") - return false - } - - // Eat a line break. - if is_break(parser.buffer, parser.buffer_pos) { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - skip_line(parser) - } - - return true -} - -// Scan the directive name. -// -// Scope: -// %YAML 1.1 # a comment \n -// ^^^^ -// %TAG !yaml! tag:yaml.org,2002: \n -// ^^^ -// -func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool { - // Consume the directive name. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - var s []byte - for is_alpha(parser.buffer, parser.buffer_pos) { - s = read(parser, s) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check if the name is empty. - if len(s) == 0 { - yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "could not find expected directive name") - return false - } - - // Check for an blank character after the name. - if !is_blankz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "found unexpected non-alphabetical character") - return false - } - *name = s - return true -} - -// Scan the value of VERSION-DIRECTIVE. -// -// Scope: -// %YAML 1.1 # a comment \n -// ^^^^^^ -func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool { - // Eat whitespaces. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Consume the major version number. - if !yaml_parser_scan_version_directive_number(parser, start_mark, major) { - return false - } - - // Eat '.'. - if parser.buffer[parser.buffer_pos] != '.' { - return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", - start_mark, "did not find expected digit or '.' character") - } - - skip(parser) - - // Consume the minor version number. - if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) { - return false - } - return true -} - -const max_number_length = 2 - -// Scan the version number of VERSION-DIRECTIVE. -// -// Scope: -// %YAML 1.1 # a comment \n -// ^ -// %YAML 1.1 # a comment \n -// ^ -func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool { - - // Repeat while the next character is digit. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - var value, length int8 - for is_digit(parser.buffer, parser.buffer_pos) { - // Check if the number is too long. - length++ - if length > max_number_length { - return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", - start_mark, "found extremely long version number") - } - value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos)) - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check if the number was present. - if length == 0 { - return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", - start_mark, "did not find expected version number") - } - *number = value - return true -} - -// Scan the value of a TAG-DIRECTIVE token. -// -// Scope: -// %TAG !yaml! tag:yaml.org,2002: \n -// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -// -func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool { - var handle_value, prefix_value []byte - - // Eat whitespaces. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Scan a handle. - if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) { - return false - } - - // Expect a whitespace. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if !is_blank(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", - start_mark, "did not find expected whitespace") - return false - } - - // Eat whitespaces. - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Scan a prefix. - if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) { - return false - } - - // Expect a whitespace or line break. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if !is_blankz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", - start_mark, "did not find expected whitespace or line break") - return false - } - - *handle = handle_value - *prefix = prefix_value - return true -} - -func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool { - var s []byte - - // Eat the indicator character. - start_mark := parser.mark - skip(parser) - - // Consume the value. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for is_alpha(parser.buffer, parser.buffer_pos) { - s = read(parser, s) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - end_mark := parser.mark - - /* - * Check if length of the anchor is greater than 0 and it is followed by - * a whitespace character or one of the indicators: - * - * '?', ':', ',', ']', '}', '%', '@', '`'. - */ - - if len(s) == 0 || - !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' || - parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' || - parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' || - parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' || - parser.buffer[parser.buffer_pos] == '`') { - context := "while scanning an alias" - if typ == yaml_ANCHOR_TOKEN { - context = "while scanning an anchor" - } - yaml_parser_set_scanner_error(parser, context, start_mark, - "did not find expected alphabetic or numeric character") - return false - } - - // Create a token. - *token = yaml_token_t{ - typ: typ, - start_mark: start_mark, - end_mark: end_mark, - value: s, - } - - return true -} - -/* - * Scan a TAG token. - */ - -func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool { - var handle, suffix []byte - - start_mark := parser.mark - - // Check if the tag is in the canonical form. - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - - if parser.buffer[parser.buffer_pos+1] == '<' { - // Keep the handle as '' - - // Eat '!<' - skip(parser) - skip(parser) - - // Consume the tag value. - if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { - return false - } - - // Check for '>' and eat it. - if parser.buffer[parser.buffer_pos] != '>' { - yaml_parser_set_scanner_error(parser, "while scanning a tag", - start_mark, "did not find the expected '>'") - return false - } - - skip(parser) - } else { - // The tag has either the '!suffix' or the '!handle!suffix' form. - - // First, try to scan a handle. - if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) { - return false - } - - // Check if it is, indeed, handle. - if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' { - // Scan the suffix now. - if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { - return false - } - } else { - // It wasn't a handle after all. Scan the rest of the tag. - if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) { - return false - } - - // Set the handle to '!'. - handle = []byte{'!'} - - // A special case: the '!' tag. Set the handle to '' and the - // suffix to '!'. - if len(suffix) == 0 { - handle, suffix = suffix, handle - } - } - } - - // Check the character which ends the tag. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if !is_blankz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a tag", - start_mark, "did not find expected whitespace or line break") - return false - } - - end_mark := parser.mark - - // Create a token. - *token = yaml_token_t{ - typ: yaml_TAG_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: handle, - suffix: suffix, - } - return true -} - -// Scan a tag handle. -func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool { - // Check the initial '!' character. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if parser.buffer[parser.buffer_pos] != '!' { - yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "did not find expected '!'") - return false - } - - var s []byte - - // Copy the '!' character. - s = read(parser, s) - - // Copy all subsequent alphabetical and numerical characters. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - for is_alpha(parser.buffer, parser.buffer_pos) { - s = read(parser, s) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check if the trailing character is '!' and copy it. - if parser.buffer[parser.buffer_pos] == '!' { - s = read(parser, s) - } else { - // It's either the '!' tag or not really a tag handle. If it's a %TAG - // directive, it's an error. If it's a tag token, it must be a part of URI. - if directive && string(s) != "!" { - yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "did not find expected '!'") - return false - } - } - - *handle = s - return true -} - -// Scan a tag. -func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool { - //size_t length = head ? strlen((char *)head) : 0 - var s []byte - hasTag := len(head) > 0 - - // Copy the head if needed. - // - // Note that we don't copy the leading '!' character. - if len(head) > 1 { - s = append(s, head[1:]...) - } - - // Scan the tag. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - // The set of characters that may appear in URI is as follows: - // - // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&', - // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']', - // '%'. - // [Go] TODO Convert this into more reasonable logic. - for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' || - parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' || - parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' || - parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' || - parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' || - parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' || - parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' || - parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' || - parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' || - parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' || - parser.buffer[parser.buffer_pos] == '%' { - // Check if it is a URI-escape sequence. - if parser.buffer[parser.buffer_pos] == '%' { - if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) { - return false - } - } else { - s = read(parser, s) - } - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - hasTag = true - } - - if !hasTag { - yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "did not find expected tag URI") - return false - } - *uri = s - return true -} - -// Decode an URI-escape sequence corresponding to a single UTF-8 character. -func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool { - - // Decode the required number of characters. - w := 1024 - for w > 0 { - // Check for a URI-escaped octet. - if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { - return false - } - - if !(parser.buffer[parser.buffer_pos] == '%' && - is_hex(parser.buffer, parser.buffer_pos+1) && - is_hex(parser.buffer, parser.buffer_pos+2)) { - return yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "did not find URI escaped octet") - } - - // Get the octet. - octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2)) - - // If it is the leading octet, determine the length of the UTF-8 sequence. - if w == 1024 { - w = width(octet) - if w == 0 { - return yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "found an incorrect leading UTF-8 octet") - } - } else { - // Check if the trailing octet is correct. - if octet&0xC0 != 0x80 { - return yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "found an incorrect trailing UTF-8 octet") - } - } - - // Copy the octet and move the pointers. - *s = append(*s, octet) - skip(parser) - skip(parser) - skip(parser) - w-- - } - return true -} - -// Scan a block scalar. -func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool { - // Eat the indicator '|' or '>'. - start_mark := parser.mark - skip(parser) - - // Scan the additional block scalar indicators. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - // Check for a chomping indicator. - var chomping, increment int - if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { - // Set the chomping method and eat the indicator. - if parser.buffer[parser.buffer_pos] == '+' { - chomping = +1 - } else { - chomping = -1 - } - skip(parser) - - // Check for an indentation indicator. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if is_digit(parser.buffer, parser.buffer_pos) { - // Check that the indentation is greater than 0. - if parser.buffer[parser.buffer_pos] == '0' { - yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "found an indentation indicator equal to 0") - return false - } - - // Get the indentation level and eat the indicator. - increment = as_digit(parser.buffer, parser.buffer_pos) - skip(parser) - } - - } else if is_digit(parser.buffer, parser.buffer_pos) { - // Do the same as above, but in the opposite order. - - if parser.buffer[parser.buffer_pos] == '0' { - yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "found an indentation indicator equal to 0") - return false - } - increment = as_digit(parser.buffer, parser.buffer_pos) - skip(parser) - - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { - if parser.buffer[parser.buffer_pos] == '+' { - chomping = +1 - } else { - chomping = -1 - } - skip(parser) - } - } - - // Eat whitespaces and comments to the end of the line. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - if parser.buffer[parser.buffer_pos] == '#' { - if !yaml_parser_scan_line_comment(parser, start_mark) { - return false - } - for !is_breakz(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - } - - // Check if we are at the end of the line. - if !is_breakz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "did not find expected comment or line break") - return false - } - - // Eat a line break. - if is_break(parser.buffer, parser.buffer_pos) { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - skip_line(parser) - } - - end_mark := parser.mark - - // Set the indentation level if it was specified. - var indent int - if increment > 0 { - if parser.indent >= 0 { - indent = parser.indent + increment - } else { - indent = increment - } - } - - // Scan the leading line breaks and determine the indentation level if needed. - var s, leading_break, trailing_breaks []byte - if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { - return false - } - - // Scan the block scalar content. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - var leading_blank, trailing_blank bool - for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) { - // We are at the beginning of a non-empty line. - - // Is it a trailing whitespace? - trailing_blank = is_blank(parser.buffer, parser.buffer_pos) - - // Check if we need to fold the leading line break. - if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' { - // Do we need to join the lines by space? - if len(trailing_breaks) == 0 { - s = append(s, ' ') - } - } else { - s = append(s, leading_break...) - } - leading_break = leading_break[:0] - - // Append the remaining line breaks. - s = append(s, trailing_breaks...) - trailing_breaks = trailing_breaks[:0] - - // Is it a leading whitespace? - leading_blank = is_blank(parser.buffer, parser.buffer_pos) - - // Consume the current line. - for !is_breakz(parser.buffer, parser.buffer_pos) { - s = read(parser, s) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Consume the line break. - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - - leading_break = read_line(parser, leading_break) - - // Eat the following indentation spaces and line breaks. - if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { - return false - } - } - - // Chomp the tail. - if chomping != -1 { - s = append(s, leading_break...) - } - if chomping == 1 { - s = append(s, trailing_breaks...) - } - - // Create a token. - *token = yaml_token_t{ - typ: yaml_SCALAR_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: s, - style: yaml_LITERAL_SCALAR_STYLE, - } - if !literal { - token.style = yaml_FOLDED_SCALAR_STYLE - } - return true -} - -// Scan indentation spaces and line breaks for a block scalar. Determine the -// indentation level if needed. -func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool { - *end_mark = parser.mark - - // Eat the indentation spaces and line breaks. - max_indent := 0 - for { - // Eat the indentation spaces. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - if parser.mark.column > max_indent { - max_indent = parser.mark.column - } - - // Check for a tab character messing the indentation. - if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) { - return yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "found a tab character where an indentation space is expected") - } - - // Have we found a non-empty line? - if !is_break(parser.buffer, parser.buffer_pos) { - break - } - - // Consume the line break. - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - // [Go] Should really be returning breaks instead. - *breaks = read_line(parser, *breaks) - *end_mark = parser.mark - } - - // Determine the indentation level if needed. - if *indent == 0 { - *indent = max_indent - if *indent < parser.indent+1 { - *indent = parser.indent + 1 - } - if *indent < 1 { - *indent = 1 - } - } - return true -} - -// Scan a quoted scalar. -func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool { - // Eat the left quote. - start_mark := parser.mark - skip(parser) - - // Consume the content of the quoted scalar. - var s, leading_break, trailing_breaks, whitespaces []byte - for { - // Check that there are no document indicators at the beginning of the line. - if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { - return false - } - - if parser.mark.column == 0 && - ((parser.buffer[parser.buffer_pos+0] == '-' && - parser.buffer[parser.buffer_pos+1] == '-' && - parser.buffer[parser.buffer_pos+2] == '-') || - (parser.buffer[parser.buffer_pos+0] == '.' && - parser.buffer[parser.buffer_pos+1] == '.' && - parser.buffer[parser.buffer_pos+2] == '.')) && - is_blankz(parser.buffer, parser.buffer_pos+3) { - yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", - start_mark, "found unexpected document indicator") - return false - } - - // Check for EOF. - if is_z(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", - start_mark, "found unexpected end of stream") - return false - } - - // Consume non-blank characters. - leading_blanks := false - for !is_blankz(parser.buffer, parser.buffer_pos) { - if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' { - // Is is an escaped single quote. - s = append(s, '\'') - skip(parser) - skip(parser) - - } else if single && parser.buffer[parser.buffer_pos] == '\'' { - // It is a right single quote. - break - } else if !single && parser.buffer[parser.buffer_pos] == '"' { - // It is a right double quote. - break - - } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) { - // It is an escaped line break. - if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { - return false - } - skip(parser) - skip_line(parser) - leading_blanks = true - break - - } else if !single && parser.buffer[parser.buffer_pos] == '\\' { - // It is an escape sequence. - code_length := 0 - - // Check the escape character. - switch parser.buffer[parser.buffer_pos+1] { - case '0': - s = append(s, 0) - case 'a': - s = append(s, '\x07') - case 'b': - s = append(s, '\x08') - case 't', '\t': - s = append(s, '\x09') - case 'n': - s = append(s, '\x0A') - case 'v': - s = append(s, '\x0B') - case 'f': - s = append(s, '\x0C') - case 'r': - s = append(s, '\x0D') - case 'e': - s = append(s, '\x1B') - case ' ': - s = append(s, '\x20') - case '"': - s = append(s, '"') - case '\'': - s = append(s, '\'') - case '\\': - s = append(s, '\\') - case 'N': // NEL (#x85) - s = append(s, '\xC2') - s = append(s, '\x85') - case '_': // #xA0 - s = append(s, '\xC2') - s = append(s, '\xA0') - case 'L': // LS (#x2028) - s = append(s, '\xE2') - s = append(s, '\x80') - s = append(s, '\xA8') - case 'P': // PS (#x2029) - s = append(s, '\xE2') - s = append(s, '\x80') - s = append(s, '\xA9') - case 'x': - code_length = 2 - case 'u': - code_length = 4 - case 'U': - code_length = 8 - default: - yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", - start_mark, "found unknown escape character") - return false - } - - skip(parser) - skip(parser) - - // Consume an arbitrary escape code. - if code_length > 0 { - var value int - - // Scan the character value. - if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) { - return false - } - for k := 0; k < code_length; k++ { - if !is_hex(parser.buffer, parser.buffer_pos+k) { - yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", - start_mark, "did not find expected hexdecimal number") - return false - } - value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k) - } - - // Check the value and write the character. - if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF { - yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", - start_mark, "found invalid Unicode character escape code") - return false - } - if value <= 0x7F { - s = append(s, byte(value)) - } else if value <= 0x7FF { - s = append(s, byte(0xC0+(value>>6))) - s = append(s, byte(0x80+(value&0x3F))) - } else if value <= 0xFFFF { - s = append(s, byte(0xE0+(value>>12))) - s = append(s, byte(0x80+((value>>6)&0x3F))) - s = append(s, byte(0x80+(value&0x3F))) - } else { - s = append(s, byte(0xF0+(value>>18))) - s = append(s, byte(0x80+((value>>12)&0x3F))) - s = append(s, byte(0x80+((value>>6)&0x3F))) - s = append(s, byte(0x80+(value&0x3F))) - } - - // Advance the pointer. - for k := 0; k < code_length; k++ { - skip(parser) - } - } - } else { - // It is a non-escaped non-blank character. - s = read(parser, s) - } - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - } - - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - // Check if we are at the end of the scalar. - if single { - if parser.buffer[parser.buffer_pos] == '\'' { - break - } - } else { - if parser.buffer[parser.buffer_pos] == '"' { - break - } - } - - // Consume blank characters. - for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { - if is_blank(parser.buffer, parser.buffer_pos) { - // Consume a space or a tab character. - if !leading_blanks { - whitespaces = read(parser, whitespaces) - } else { - skip(parser) - } - } else { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - - // Check if it is a first line break. - if !leading_blanks { - whitespaces = whitespaces[:0] - leading_break = read_line(parser, leading_break) - leading_blanks = true - } else { - trailing_breaks = read_line(parser, trailing_breaks) - } - } - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Join the whitespaces or fold line breaks. - if leading_blanks { - // Do we need to fold line breaks? - if len(leading_break) > 0 && leading_break[0] == '\n' { - if len(trailing_breaks) == 0 { - s = append(s, ' ') - } else { - s = append(s, trailing_breaks...) - } - } else { - s = append(s, leading_break...) - s = append(s, trailing_breaks...) - } - trailing_breaks = trailing_breaks[:0] - leading_break = leading_break[:0] - } else { - s = append(s, whitespaces...) - whitespaces = whitespaces[:0] - } - } - - // Eat the right quote. - skip(parser) - end_mark := parser.mark - - // Create a token. - *token = yaml_token_t{ - typ: yaml_SCALAR_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: s, - style: yaml_SINGLE_QUOTED_SCALAR_STYLE, - } - if !single { - token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - return true -} - -// Scan a plain scalar. -func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool { - - var s, leading_break, trailing_breaks, whitespaces []byte - var leading_blanks bool - var indent = parser.indent + 1 - - start_mark := parser.mark - end_mark := parser.mark - - // Consume the content of the plain scalar. - for { - // Check for a document indicator. - if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { - return false - } - if parser.mark.column == 0 && - ((parser.buffer[parser.buffer_pos+0] == '-' && - parser.buffer[parser.buffer_pos+1] == '-' && - parser.buffer[parser.buffer_pos+2] == '-') || - (parser.buffer[parser.buffer_pos+0] == '.' && - parser.buffer[parser.buffer_pos+1] == '.' && - parser.buffer[parser.buffer_pos+2] == '.')) && - is_blankz(parser.buffer, parser.buffer_pos+3) { - break - } - - // Check for a comment. - if parser.buffer[parser.buffer_pos] == '#' { - break - } - - // Consume non-blank characters. - for !is_blankz(parser.buffer, parser.buffer_pos) { - - // Check for indicators that may end a plain scalar. - if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) || - (parser.flow_level > 0 && - (parser.buffer[parser.buffer_pos] == ',' || - parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' || - parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || - parser.buffer[parser.buffer_pos] == '}')) { - break - } - - // Check if we need to join whitespaces and breaks. - if leading_blanks || len(whitespaces) > 0 { - if leading_blanks { - // Do we need to fold line breaks? - if leading_break[0] == '\n' { - if len(trailing_breaks) == 0 { - s = append(s, ' ') - } else { - s = append(s, trailing_breaks...) - } - } else { - s = append(s, leading_break...) - s = append(s, trailing_breaks...) - } - trailing_breaks = trailing_breaks[:0] - leading_break = leading_break[:0] - leading_blanks = false - } else { - s = append(s, whitespaces...) - whitespaces = whitespaces[:0] - } - } - - // Copy the character. - s = read(parser, s) - - end_mark = parser.mark - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - } - - // Is it the end? - if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) { - break - } - - // Consume blank characters. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { - if is_blank(parser.buffer, parser.buffer_pos) { - - // Check for tab characters that abuse indentation. - if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", - start_mark, "found a tab character that violates indentation") - return false - } - - // Consume a space or a tab character. - if !leading_blanks { - whitespaces = read(parser, whitespaces) - } else { - skip(parser) - } - } else { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - - // Check if it is a first line break. - if !leading_blanks { - whitespaces = whitespaces[:0] - leading_break = read_line(parser, leading_break) - leading_blanks = true - } else { - trailing_breaks = read_line(parser, trailing_breaks) - } - } - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check indentation level. - if parser.flow_level == 0 && parser.mark.column < indent { - break - } - } - - // Create a token. - *token = yaml_token_t{ - typ: yaml_SCALAR_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: s, - style: yaml_PLAIN_SCALAR_STYLE, - } - - // Note that we change the 'simple_key_allowed' flag. - if leading_blanks { - parser.simple_key_allowed = true - } - return true -} - -func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t) bool { - if parser.newlines > 0 { - return true - } - - var start_mark yaml_mark_t - var text []byte - - for peek := 0; peek < 512; peek++ { - if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) { - break - } - if is_blank(parser.buffer, parser.buffer_pos+peek) { - continue - } - if parser.buffer[parser.buffer_pos+peek] == '#' { - seen := parser.mark.index+peek - for { - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if is_breakz(parser.buffer, parser.buffer_pos) { - if parser.mark.index >= seen { - break - } - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - skip_line(parser) - } else if parser.mark.index >= seen { - if len(text) == 0 { - start_mark = parser.mark - } - text = read(parser, text) - } else { - skip(parser) - } - } - } - break - } - if len(text) > 0 { - parser.comments = append(parser.comments, yaml_comment_t{ - token_mark: token_mark, - start_mark: start_mark, - line: text, - }) - } - return true -} - -func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) bool { - token := parser.tokens[len(parser.tokens)-1] - - if token.typ == yaml_FLOW_ENTRY_TOKEN && len(parser.tokens) > 1 { - token = parser.tokens[len(parser.tokens)-2] - } - - var token_mark = token.start_mark - var start_mark yaml_mark_t - var next_indent = parser.indent - if next_indent < 0 { - next_indent = 0 - } - - var recent_empty = false - var first_empty = parser.newlines <= 1 - - var line = parser.mark.line - var column = parser.mark.column - - var text []byte - - // The foot line is the place where a comment must start to - // still be considered as a foot of the prior content. - // If there's some content in the currently parsed line, then - // the foot is the line below it. - var foot_line = -1 - if scan_mark.line > 0 { - foot_line = parser.mark.line-parser.newlines+1 - if parser.newlines == 0 && parser.mark.column > 1 { - foot_line++ - } - } - - var peek = 0 - for ; peek < 512; peek++ { - if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) { - break - } - column++ - if is_blank(parser.buffer, parser.buffer_pos+peek) { - continue - } - c := parser.buffer[parser.buffer_pos+peek] - var close_flow = parser.flow_level > 0 && (c == ']' || c == '}') - if close_flow || is_breakz(parser.buffer, parser.buffer_pos+peek) { - // Got line break or terminator. - if close_flow || !recent_empty { - if close_flow || first_empty && (start_mark.line == foot_line && token.typ != yaml_VALUE_TOKEN || start_mark.column-1 < next_indent) { - // This is the first empty line and there were no empty lines before, - // so this initial part of the comment is a foot of the prior token - // instead of being a head for the following one. Split it up. - // Alternatively, this might also be the last comment inside a flow - // scope, so it must be a footer. - if len(text) > 0 { - if start_mark.column-1 < next_indent { - // If dedented it's unrelated to the prior token. - token_mark = start_mark - } - parser.comments = append(parser.comments, yaml_comment_t{ - scan_mark: scan_mark, - token_mark: token_mark, - start_mark: start_mark, - end_mark: yaml_mark_t{parser.mark.index + peek, line, column}, - foot: text, - }) - scan_mark = yaml_mark_t{parser.mark.index + peek, line, column} - token_mark = scan_mark - text = nil - } - } else { - if len(text) > 0 && parser.buffer[parser.buffer_pos+peek] != 0 { - text = append(text, '\n') - } - } - } - if !is_break(parser.buffer, parser.buffer_pos+peek) { - break - } - first_empty = false - recent_empty = true - column = 0 - line++ - continue - } - - if len(text) > 0 && (close_flow || column-1 < next_indent && column != start_mark.column) { - // The comment at the different indentation is a foot of the - // preceding data rather than a head of the upcoming one. - parser.comments = append(parser.comments, yaml_comment_t{ - scan_mark: scan_mark, - token_mark: token_mark, - start_mark: start_mark, - end_mark: yaml_mark_t{parser.mark.index + peek, line, column}, - foot: text, - }) - scan_mark = yaml_mark_t{parser.mark.index + peek, line, column} - token_mark = scan_mark - text = nil - } - - if parser.buffer[parser.buffer_pos+peek] != '#' { - break - } - - if len(text) == 0 { - start_mark = yaml_mark_t{parser.mark.index + peek, line, column} - } else { - text = append(text, '\n') - } - - recent_empty = false - - // Consume until after the consumed comment line. - seen := parser.mark.index+peek - for { - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if is_breakz(parser.buffer, parser.buffer_pos) { - if parser.mark.index >= seen { - break - } - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - skip_line(parser) - } else if parser.mark.index >= seen { - text = read(parser, text) - } else { - skip(parser) - } - } - - peek = 0 - column = 0 - line = parser.mark.line - next_indent = parser.indent - if next_indent < 0 { - next_indent = 0 - } - } - - if len(text) > 0 { - parser.comments = append(parser.comments, yaml_comment_t{ - scan_mark: scan_mark, - token_mark: start_mark, - start_mark: start_mark, - end_mark: yaml_mark_t{parser.mark.index + peek - 1, line, column}, - head: text, - }) - } - return true -} diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/sorter.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/sorter.go deleted file mode 100644 index 9210ece..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/sorter.go +++ /dev/null @@ -1,134 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yaml - -import ( - "reflect" - "unicode" -) - -type keyList []reflect.Value - -func (l keyList) Len() int { return len(l) } -func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } -func (l keyList) Less(i, j int) bool { - a := l[i] - b := l[j] - ak := a.Kind() - bk := b.Kind() - for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { - a = a.Elem() - ak = a.Kind() - } - for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { - b = b.Elem() - bk = b.Kind() - } - af, aok := keyFloat(a) - bf, bok := keyFloat(b) - if aok && bok { - if af != bf { - return af < bf - } - if ak != bk { - return ak < bk - } - return numLess(a, b) - } - if ak != reflect.String || bk != reflect.String { - return ak < bk - } - ar, br := []rune(a.String()), []rune(b.String()) - digits := false - for i := 0; i < len(ar) && i < len(br); i++ { - if ar[i] == br[i] { - digits = unicode.IsDigit(ar[i]) - continue - } - al := unicode.IsLetter(ar[i]) - bl := unicode.IsLetter(br[i]) - if al && bl { - return ar[i] < br[i] - } - if al || bl { - if digits { - return al - } else { - return bl - } - } - var ai, bi int - var an, bn int64 - if ar[i] == '0' || br[i] == '0' { - for j := i - 1; j >= 0 && unicode.IsDigit(ar[j]); j-- { - if ar[j] != '0' { - an = 1 - bn = 1 - break - } - } - } - for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { - an = an*10 + int64(ar[ai]-'0') - } - for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { - bn = bn*10 + int64(br[bi]-'0') - } - if an != bn { - return an < bn - } - if ai != bi { - return ai < bi - } - return ar[i] < br[i] - } - return len(ar) < len(br) -} - -// keyFloat returns a float value for v if it is a number/bool -// and whether it is a number/bool or not. -func keyFloat(v reflect.Value) (f float64, ok bool) { - switch v.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return float64(v.Int()), true - case reflect.Float32, reflect.Float64: - return v.Float(), true - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return float64(v.Uint()), true - case reflect.Bool: - if v.Bool() { - return 1, true - } - return 0, true - } - return 0, false -} - -// numLess returns whether a < b. -// a and b must necessarily have the same kind. -func numLess(a, b reflect.Value) bool { - switch a.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return a.Int() < b.Int() - case reflect.Float32, reflect.Float64: - return a.Float() < b.Float() - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return a.Uint() < b.Uint() - case reflect.Bool: - return !a.Bool() && b.Bool() - } - panic("not a number") -} diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/suite_test.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/suite_test.go deleted file mode 100644 index 4630b5f..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/suite_test.go +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yaml_test - -import ( - . "gopkg.in/check.v1" - "testing" -) - -func Test(t *testing.T) { TestingT(t) } - -type S struct{} - -var _ = Suite(&S{}) diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/writerc.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/writerc.go deleted file mode 100644 index b8a116b..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/writerc.go +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// 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. - -package yaml - -// Set the writer error and return false. -func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { - emitter.error = yaml_WRITER_ERROR - emitter.problem = problem - return false -} - -// Flush the output buffer. -func yaml_emitter_flush(emitter *yaml_emitter_t) bool { - if emitter.write_handler == nil { - panic("write handler not set") - } - - // Check if the buffer is empty. - if emitter.buffer_pos == 0 { - return true - } - - if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { - return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) - } - emitter.buffer_pos = 0 - return true -} diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/yaml.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/yaml.go deleted file mode 100644 index 8cec6da..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/yaml.go +++ /dev/null @@ -1,698 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package yaml implements YAML support for the Go language. -// -// Source code and other details for the project are available at GitHub: -// -// https://github.com/go-yaml/yaml -// -package yaml - -import ( - "errors" - "fmt" - "io" - "reflect" - "strings" - "sync" - "unicode/utf8" -) - -// The Unmarshaler interface may be implemented by types to customize their -// behavior when being unmarshaled from a YAML document. -type Unmarshaler interface { - UnmarshalYAML(value *Node) error -} - -type obsoleteUnmarshaler interface { - UnmarshalYAML(unmarshal func(interface{}) error) error -} - -// The Marshaler interface may be implemented by types to customize their -// behavior when being marshaled into a YAML document. The returned value -// is marshaled in place of the original value implementing Marshaler. -// -// If an error is returned by MarshalYAML, the marshaling procedure stops -// and returns with the provided error. -type Marshaler interface { - MarshalYAML() (interface{}, error) -} - -// Unmarshal decodes the first document found within the in byte slice -// and assigns decoded values into the out value. -// -// Maps and pointers (to a struct, string, int, etc) are accepted as out -// values. If an internal pointer within a struct is not initialized, -// the yaml package will initialize it if necessary for unmarshalling -// the provided data. The out parameter must not be nil. -// -// The type of the decoded values should be compatible with the respective -// values in out. If one or more values cannot be decoded due to a type -// mismatches, decoding continues partially until the end of the YAML -// content, and a *yaml.TypeError is returned with details for all -// missed values. -// -// Struct fields are only unmarshalled if they are exported (have an -// upper case first letter), and are unmarshalled using the field name -// lowercased as the default key. Custom keys may be defined via the -// "yaml" name in the field tag: the content preceding the first comma -// is used as the key, and the following comma-separated options are -// used to tweak the marshalling process (see Marshal). -// Conflicting names result in a runtime error. -// -// For example: -// -// type T struct { -// F int `yaml:"a,omitempty"` -// B int -// } -// var t T -// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t) -// -// See the documentation of Marshal for the format of tags and a list of -// supported tag options. -// -func Unmarshal(in []byte, out interface{}) (err error) { - return unmarshal(in, out, false) -} - -// A Decoder reads and decodes YAML values from an input stream. -type Decoder struct { - parser *parser - knownFields bool -} - -// NewDecoder returns a new decoder that reads from r. -// -// The decoder introduces its own buffering and may read -// data from r beyond the YAML values requested. -func NewDecoder(r io.Reader) *Decoder { - return &Decoder{ - parser: newParserFromReader(r), - } -} - -// KnownFields ensures that the keys in decoded mappings to -// exist as fields in the struct being decoded into. -func (dec *Decoder) KnownFields(enable bool) { - dec.knownFields = enable -} - -// Decode reads the next YAML-encoded value from its input -// and stores it in the value pointed to by v. -// -// See the documentation for Unmarshal for details about the -// conversion of YAML into a Go value. -func (dec *Decoder) Decode(v interface{}) (err error) { - d := newDecoder() - d.knownFields = dec.knownFields - defer handleErr(&err) - node := dec.parser.parse() - if node == nil { - return io.EOF - } - out := reflect.ValueOf(v) - if out.Kind() == reflect.Ptr && !out.IsNil() { - out = out.Elem() - } - d.unmarshal(node, out) - if len(d.terrors) > 0 { - return &TypeError{d.terrors} - } - return nil -} - -// Decode decodes the node and stores its data into the value pointed to by v. -// -// See the documentation for Unmarshal for details about the -// conversion of YAML into a Go value. -func (n *Node) Decode(v interface{}) (err error) { - d := newDecoder() - defer handleErr(&err) - out := reflect.ValueOf(v) - if out.Kind() == reflect.Ptr && !out.IsNil() { - out = out.Elem() - } - d.unmarshal(n, out) - if len(d.terrors) > 0 { - return &TypeError{d.terrors} - } - return nil -} - -func unmarshal(in []byte, out interface{}, strict bool) (err error) { - defer handleErr(&err) - d := newDecoder() - p := newParser(in) - defer p.destroy() - node := p.parse() - if node != nil { - v := reflect.ValueOf(out) - if v.Kind() == reflect.Ptr && !v.IsNil() { - v = v.Elem() - } - d.unmarshal(node, v) - } - if len(d.terrors) > 0 { - return &TypeError{d.terrors} - } - return nil -} - -// Marshal serializes the value provided into a YAML document. The structure -// of the generated document will reflect the structure of the value itself. -// Maps and pointers (to struct, string, int, etc) are accepted as the in value. -// -// Struct fields are only marshalled if they are exported (have an upper case -// first letter), and are marshalled using the field name lowercased as the -// default key. Custom keys may be defined via the "yaml" name in the field -// tag: the content preceding the first comma is used as the key, and the -// following comma-separated options are used to tweak the marshalling process. -// Conflicting names result in a runtime error. -// -// The field tag format accepted is: -// -// `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)` -// -// The following flags are currently supported: -// -// omitempty Only include the field if it's not set to the zero -// value for the type or to empty slices or maps. -// Zero valued structs will be omitted if all their public -// fields are zero, unless they implement an IsZero -// method (see the IsZeroer interface type), in which -// case the field will be excluded if IsZero returns true. -// -// flow Marshal using a flow style (useful for structs, -// sequences and maps). -// -// inline Inline the field, which must be a struct or a map, -// causing all of its fields or keys to be processed as if -// they were part of the outer struct. For maps, keys must -// not conflict with the yaml keys of other struct fields. -// -// In addition, if the key is "-", the field is ignored. -// -// For example: -// -// type T struct { -// F int `yaml:"a,omitempty"` -// B int -// } -// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n" -// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n" -// -func Marshal(in interface{}) (out []byte, err error) { - defer handleErr(&err) - e := newEncoder() - defer e.destroy() - e.marshalDoc("", reflect.ValueOf(in)) - e.finish() - out = e.out - return -} - -// An Encoder writes YAML values to an output stream. -type Encoder struct { - encoder *encoder -} - -// NewEncoder returns a new encoder that writes to w. -// The Encoder should be closed after use to flush all data -// to w. -func NewEncoder(w io.Writer) *Encoder { - return &Encoder{ - encoder: newEncoderWithWriter(w), - } -} - -// Encode writes the YAML encoding of v to the stream. -// If multiple items are encoded to the stream, the -// second and subsequent document will be preceded -// with a "---" document separator, but the first will not. -// -// See the documentation for Marshal for details about the conversion of Go -// values to YAML. -func (e *Encoder) Encode(v interface{}) (err error) { - defer handleErr(&err) - e.encoder.marshalDoc("", reflect.ValueOf(v)) - return nil -} - -// Encode encodes value v and stores its representation in n. -// -// See the documentation for Marshal for details about the -// conversion of Go values into YAML. -func (n *Node) Encode(v interface{}) (err error) { - defer handleErr(&err) - e := newEncoder() - defer e.destroy() - e.marshalDoc("", reflect.ValueOf(v)) - e.finish() - p := newParser(e.out) - p.textless = true - defer p.destroy() - doc := p.parse() - *n = *doc.Content[0] - return nil -} - -// SetIndent changes the used indentation used when encoding. -func (e *Encoder) SetIndent(spaces int) { - if spaces < 0 { - panic("yaml: cannot indent to a negative number of spaces") - } - e.encoder.indent = spaces -} - -// Close closes the encoder by writing any remaining data. -// It does not write a stream terminating string "...". -func (e *Encoder) Close() (err error) { - defer handleErr(&err) - e.encoder.finish() - return nil -} - -func handleErr(err *error) { - if v := recover(); v != nil { - if e, ok := v.(yamlError); ok { - *err = e.err - } else { - panic(v) - } - } -} - -type yamlError struct { - err error -} - -func fail(err error) { - panic(yamlError{err}) -} - -func failf(format string, args ...interface{}) { - panic(yamlError{fmt.Errorf("yaml: "+format, args...)}) -} - -// A TypeError is returned by Unmarshal when one or more fields in -// the YAML document cannot be properly decoded into the requested -// types. When this error is returned, the value is still -// unmarshaled partially. -type TypeError struct { - Errors []string -} - -func (e *TypeError) Error() string { - return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n ")) -} - -type Kind uint32 - -const ( - DocumentNode Kind = 1 << iota - SequenceNode - MappingNode - ScalarNode - AliasNode -) - -type Style uint32 - -const ( - TaggedStyle Style = 1 << iota - DoubleQuotedStyle - SingleQuotedStyle - LiteralStyle - FoldedStyle - FlowStyle -) - -// Node represents an element in the YAML document hierarchy. While documents -// are typically encoded and decoded into higher level types, such as structs -// and maps, Node is an intermediate representation that allows detailed -// control over the content being decoded or encoded. -// -// It's worth noting that although Node offers access into details such as -// line numbers, colums, and comments, the content when re-encoded will not -// have its original textual representation preserved. An effort is made to -// render the data plesantly, and to preserve comments near the data they -// describe, though. -// -// Values that make use of the Node type interact with the yaml package in the -// same way any other type would do, by encoding and decoding yaml data -// directly or indirectly into them. -// -// For example: -// -// var person struct { -// Name string -// Address yaml.Node -// } -// err := yaml.Unmarshal(data, &person) -// -// Or by itself: -// -// var person Node -// err := yaml.Unmarshal(data, &person) -// -type Node struct { - // Kind defines whether the node is a document, a mapping, a sequence, - // a scalar value, or an alias to another node. The specific data type of - // scalar nodes may be obtained via the ShortTag and LongTag methods. - Kind Kind - - // Style allows customizing the apperance of the node in the tree. - Style Style - - // Tag holds the YAML tag defining the data type for the value. - // When decoding, this field will always be set to the resolved tag, - // even when it wasn't explicitly provided in the YAML content. - // When encoding, if this field is unset the value type will be - // implied from the node properties, and if it is set, it will only - // be serialized into the representation if TaggedStyle is used or - // the implicit tag diverges from the provided one. - Tag string - - // Value holds the unescaped and unquoted represenation of the value. - Value string - - // Anchor holds the anchor name for this node, which allows aliases to point to it. - Anchor string - - // Alias holds the node that this alias points to. Only valid when Kind is AliasNode. - Alias *Node - - // Content holds contained nodes for documents, mappings, and sequences. - Content []*Node - - // HeadComment holds any comments in the lines preceding the node and - // not separated by an empty line. - HeadComment string - - // LineComment holds any comments at the end of the line where the node is in. - LineComment string - - // FootComment holds any comments following the node and before empty lines. - FootComment string - - // Line and Column hold the node position in the decoded YAML text. - // These fields are not respected when encoding the node. - Line int - Column int -} - -// IsZero returns whether the node has all of its fields unset. -func (n *Node) IsZero() bool { - return n.Kind == 0 && n.Style == 0 && n.Tag == "" && n.Value == "" && n.Anchor == "" && n.Alias == nil && n.Content == nil && - n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0 -} - - -// LongTag returns the long form of the tag that indicates the data type for -// the node. If the Tag field isn't explicitly defined, one will be computed -// based on the node properties. -func (n *Node) LongTag() string { - return longTag(n.ShortTag()) -} - -// ShortTag returns the short form of the YAML tag that indicates data type for -// the node. If the Tag field isn't explicitly defined, one will be computed -// based on the node properties. -func (n *Node) ShortTag() string { - if n.indicatedString() { - return strTag - } - if n.Tag == "" || n.Tag == "!" { - switch n.Kind { - case MappingNode: - return mapTag - case SequenceNode: - return seqTag - case AliasNode: - if n.Alias != nil { - return n.Alias.ShortTag() - } - case ScalarNode: - tag, _ := resolve("", n.Value) - return tag - case 0: - // Special case to make the zero value convenient. - if n.IsZero() { - return nullTag - } - } - return "" - } - return shortTag(n.Tag) -} - -func (n *Node) indicatedString() bool { - return n.Kind == ScalarNode && - (shortTag(n.Tag) == strTag || - (n.Tag == "" || n.Tag == "!") && n.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0) -} - -// SetString is a convenience function that sets the node to a string value -// and defines its style in a pleasant way depending on its content. -func (n *Node) SetString(s string) { - n.Kind = ScalarNode - if utf8.ValidString(s) { - n.Value = s - n.Tag = strTag - } else { - n.Value = encodeBase64(s) - n.Tag = binaryTag - } - if strings.Contains(n.Value, "\n") { - n.Style = LiteralStyle - } -} - -// -------------------------------------------------------------------------- -// Maintain a mapping of keys to structure field indexes - -// The code in this section was copied from mgo/bson. - -// structInfo holds details for the serialization of fields of -// a given struct. -type structInfo struct { - FieldsMap map[string]fieldInfo - FieldsList []fieldInfo - - // InlineMap is the number of the field in the struct that - // contains an ,inline map, or -1 if there's none. - InlineMap int - - // InlineUnmarshalers holds indexes to inlined fields that - // contain unmarshaler values. - InlineUnmarshalers [][]int -} - -type fieldInfo struct { - Key string - Num int - OmitEmpty bool - Flow bool - // Id holds the unique field identifier, so we can cheaply - // check for field duplicates without maintaining an extra map. - Id int - - // Inline holds the field index if the field is part of an inlined struct. - Inline []int -} - -var structMap = make(map[reflect.Type]*structInfo) -var fieldMapMutex sync.RWMutex -var unmarshalerType reflect.Type - -func init() { - var v Unmarshaler - unmarshalerType = reflect.ValueOf(&v).Elem().Type() -} - -func getStructInfo(st reflect.Type) (*structInfo, error) { - fieldMapMutex.RLock() - sinfo, found := structMap[st] - fieldMapMutex.RUnlock() - if found { - return sinfo, nil - } - - n := st.NumField() - fieldsMap := make(map[string]fieldInfo) - fieldsList := make([]fieldInfo, 0, n) - inlineMap := -1 - inlineUnmarshalers := [][]int(nil) - for i := 0; i != n; i++ { - field := st.Field(i) - if field.PkgPath != "" && !field.Anonymous { - continue // Private field - } - - info := fieldInfo{Num: i} - - tag := field.Tag.Get("yaml") - if tag == "" && strings.Index(string(field.Tag), ":") < 0 { - tag = string(field.Tag) - } - if tag == "-" { - continue - } - - inline := false - fields := strings.Split(tag, ",") - if len(fields) > 1 { - for _, flag := range fields[1:] { - switch flag { - case "omitempty": - info.OmitEmpty = true - case "flow": - info.Flow = true - case "inline": - inline = true - default: - return nil, errors.New(fmt.Sprintf("unsupported flag %q in tag %q of type %s", flag, tag, st)) - } - } - tag = fields[0] - } - - if inline { - switch field.Type.Kind() { - case reflect.Map: - if inlineMap >= 0 { - return nil, errors.New("multiple ,inline maps in struct " + st.String()) - } - if field.Type.Key() != reflect.TypeOf("") { - return nil, errors.New("option ,inline needs a map with string keys in struct " + st.String()) - } - inlineMap = info.Num - case reflect.Struct, reflect.Ptr: - ftype := field.Type - for ftype.Kind() == reflect.Ptr { - ftype = ftype.Elem() - } - if ftype.Kind() != reflect.Struct { - return nil, errors.New("option ,inline may only be used on a struct or map field") - } - if reflect.PtrTo(ftype).Implements(unmarshalerType) { - inlineUnmarshalers = append(inlineUnmarshalers, []int{i}) - } else { - sinfo, err := getStructInfo(ftype) - if err != nil { - return nil, err - } - for _, index := range sinfo.InlineUnmarshalers { - inlineUnmarshalers = append(inlineUnmarshalers, append([]int{i}, index...)) - } - for _, finfo := range sinfo.FieldsList { - if _, found := fieldsMap[finfo.Key]; found { - msg := "duplicated key '" + finfo.Key + "' in struct " + st.String() - return nil, errors.New(msg) - } - if finfo.Inline == nil { - finfo.Inline = []int{i, finfo.Num} - } else { - finfo.Inline = append([]int{i}, finfo.Inline...) - } - finfo.Id = len(fieldsList) - fieldsMap[finfo.Key] = finfo - fieldsList = append(fieldsList, finfo) - } - } - default: - return nil, errors.New("option ,inline may only be used on a struct or map field") - } - continue - } - - if tag != "" { - info.Key = tag - } else { - info.Key = strings.ToLower(field.Name) - } - - if _, found = fieldsMap[info.Key]; found { - msg := "duplicated key '" + info.Key + "' in struct " + st.String() - return nil, errors.New(msg) - } - - info.Id = len(fieldsList) - fieldsList = append(fieldsList, info) - fieldsMap[info.Key] = info - } - - sinfo = &structInfo{ - FieldsMap: fieldsMap, - FieldsList: fieldsList, - InlineMap: inlineMap, - InlineUnmarshalers: inlineUnmarshalers, - } - - fieldMapMutex.Lock() - structMap[st] = sinfo - fieldMapMutex.Unlock() - return sinfo, nil -} - -// IsZeroer is used to check whether an object is zero to -// determine whether it should be omitted when marshaling -// with the omitempty flag. One notable implementation -// is time.Time. -type IsZeroer interface { - IsZero() bool -} - -func isZero(v reflect.Value) bool { - kind := v.Kind() - if z, ok := v.Interface().(IsZeroer); ok { - if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() { - return true - } - return z.IsZero() - } - switch kind { - case reflect.String: - return len(v.String()) == 0 - case reflect.Interface, reflect.Ptr: - return v.IsNil() - case reflect.Slice: - return v.Len() == 0 - case reflect.Map: - return v.Len() == 0 - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Float32, reflect.Float64: - return v.Float() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - case reflect.Bool: - return !v.Bool() - case reflect.Struct: - vt := v.Type() - for i := v.NumField() - 1; i >= 0; i-- { - if vt.Field(i).PkgPath != "" { - continue // Private field - } - if !isZero(v.Field(i)) { - return false - } - } - return true - } - return false -} diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/yamlh.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/yamlh.go deleted file mode 100644 index 7c6d007..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/yamlh.go +++ /dev/null @@ -1,807 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// 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. - -package yaml - -import ( - "fmt" - "io" -) - -// The version directive data. -type yaml_version_directive_t struct { - major int8 // The major version number. - minor int8 // The minor version number. -} - -// The tag directive data. -type yaml_tag_directive_t struct { - handle []byte // The tag handle. - prefix []byte // The tag prefix. -} - -type yaml_encoding_t int - -// The stream encoding. -const ( - // Let the parser choose the encoding. - yaml_ANY_ENCODING yaml_encoding_t = iota - - yaml_UTF8_ENCODING // The default UTF-8 encoding. - yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM. - yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM. -) - -type yaml_break_t int - -// Line break types. -const ( - // Let the parser choose the break type. - yaml_ANY_BREAK yaml_break_t = iota - - yaml_CR_BREAK // Use CR for line breaks (Mac style). - yaml_LN_BREAK // Use LN for line breaks (Unix style). - yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style). -) - -type yaml_error_type_t int - -// Many bad things could happen with the parser and emitter. -const ( - // No error is produced. - yaml_NO_ERROR yaml_error_type_t = iota - - yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory. - yaml_READER_ERROR // Cannot read or decode the input stream. - yaml_SCANNER_ERROR // Cannot scan the input stream. - yaml_PARSER_ERROR // Cannot parse the input stream. - yaml_COMPOSER_ERROR // Cannot compose a YAML document. - yaml_WRITER_ERROR // Cannot write to the output stream. - yaml_EMITTER_ERROR // Cannot emit a YAML stream. -) - -// The pointer position. -type yaml_mark_t struct { - index int // The position index. - line int // The position line. - column int // The position column. -} - -// Node Styles - -type yaml_style_t int8 - -type yaml_scalar_style_t yaml_style_t - -// Scalar styles. -const ( - // Let the emitter choose the style. - yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = 0 - - yaml_PLAIN_SCALAR_STYLE yaml_scalar_style_t = 1 << iota // The plain scalar style. - yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style. - yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style. - yaml_LITERAL_SCALAR_STYLE // The literal scalar style. - yaml_FOLDED_SCALAR_STYLE // The folded scalar style. -) - -type yaml_sequence_style_t yaml_style_t - -// Sequence styles. -const ( - // Let the emitter choose the style. - yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota - - yaml_BLOCK_SEQUENCE_STYLE // The block sequence style. - yaml_FLOW_SEQUENCE_STYLE // The flow sequence style. -) - -type yaml_mapping_style_t yaml_style_t - -// Mapping styles. -const ( - // Let the emitter choose the style. - yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota - - yaml_BLOCK_MAPPING_STYLE // The block mapping style. - yaml_FLOW_MAPPING_STYLE // The flow mapping style. -) - -// Tokens - -type yaml_token_type_t int - -// Token types. -const ( - // An empty token. - yaml_NO_TOKEN yaml_token_type_t = iota - - yaml_STREAM_START_TOKEN // A STREAM-START token. - yaml_STREAM_END_TOKEN // A STREAM-END token. - - yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token. - yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token. - yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token. - yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token. - - yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token. - yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token. - yaml_BLOCK_END_TOKEN // A BLOCK-END token. - - yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token. - yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token. - yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token. - yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token. - - yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token. - yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token. - yaml_KEY_TOKEN // A KEY token. - yaml_VALUE_TOKEN // A VALUE token. - - yaml_ALIAS_TOKEN // An ALIAS token. - yaml_ANCHOR_TOKEN // An ANCHOR token. - yaml_TAG_TOKEN // A TAG token. - yaml_SCALAR_TOKEN // A SCALAR token. -) - -func (tt yaml_token_type_t) String() string { - switch tt { - case yaml_NO_TOKEN: - return "yaml_NO_TOKEN" - case yaml_STREAM_START_TOKEN: - return "yaml_STREAM_START_TOKEN" - case yaml_STREAM_END_TOKEN: - return "yaml_STREAM_END_TOKEN" - case yaml_VERSION_DIRECTIVE_TOKEN: - return "yaml_VERSION_DIRECTIVE_TOKEN" - case yaml_TAG_DIRECTIVE_TOKEN: - return "yaml_TAG_DIRECTIVE_TOKEN" - case yaml_DOCUMENT_START_TOKEN: - return "yaml_DOCUMENT_START_TOKEN" - case yaml_DOCUMENT_END_TOKEN: - return "yaml_DOCUMENT_END_TOKEN" - case yaml_BLOCK_SEQUENCE_START_TOKEN: - return "yaml_BLOCK_SEQUENCE_START_TOKEN" - case yaml_BLOCK_MAPPING_START_TOKEN: - return "yaml_BLOCK_MAPPING_START_TOKEN" - case yaml_BLOCK_END_TOKEN: - return "yaml_BLOCK_END_TOKEN" - case yaml_FLOW_SEQUENCE_START_TOKEN: - return "yaml_FLOW_SEQUENCE_START_TOKEN" - case yaml_FLOW_SEQUENCE_END_TOKEN: - return "yaml_FLOW_SEQUENCE_END_TOKEN" - case yaml_FLOW_MAPPING_START_TOKEN: - return "yaml_FLOW_MAPPING_START_TOKEN" - case yaml_FLOW_MAPPING_END_TOKEN: - return "yaml_FLOW_MAPPING_END_TOKEN" - case yaml_BLOCK_ENTRY_TOKEN: - return "yaml_BLOCK_ENTRY_TOKEN" - case yaml_FLOW_ENTRY_TOKEN: - return "yaml_FLOW_ENTRY_TOKEN" - case yaml_KEY_TOKEN: - return "yaml_KEY_TOKEN" - case yaml_VALUE_TOKEN: - return "yaml_VALUE_TOKEN" - case yaml_ALIAS_TOKEN: - return "yaml_ALIAS_TOKEN" - case yaml_ANCHOR_TOKEN: - return "yaml_ANCHOR_TOKEN" - case yaml_TAG_TOKEN: - return "yaml_TAG_TOKEN" - case yaml_SCALAR_TOKEN: - return "yaml_SCALAR_TOKEN" - } - return "<unknown token>" -} - -// The token structure. -type yaml_token_t struct { - // The token type. - typ yaml_token_type_t - - // The start/end of the token. - start_mark, end_mark yaml_mark_t - - // The stream encoding (for yaml_STREAM_START_TOKEN). - encoding yaml_encoding_t - - // The alias/anchor/scalar value or tag/tag directive handle - // (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN). - value []byte - - // The tag suffix (for yaml_TAG_TOKEN). - suffix []byte - - // The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN). - prefix []byte - - // The scalar style (for yaml_SCALAR_TOKEN). - style yaml_scalar_style_t - - // The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN). - major, minor int8 -} - -// Events - -type yaml_event_type_t int8 - -// Event types. -const ( - // An empty event. - yaml_NO_EVENT yaml_event_type_t = iota - - yaml_STREAM_START_EVENT // A STREAM-START event. - yaml_STREAM_END_EVENT // A STREAM-END event. - yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event. - yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event. - yaml_ALIAS_EVENT // An ALIAS event. - yaml_SCALAR_EVENT // A SCALAR event. - yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event. - yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event. - yaml_MAPPING_START_EVENT // A MAPPING-START event. - yaml_MAPPING_END_EVENT // A MAPPING-END event. - yaml_TAIL_COMMENT_EVENT -) - -var eventStrings = []string{ - yaml_NO_EVENT: "none", - yaml_STREAM_START_EVENT: "stream start", - yaml_STREAM_END_EVENT: "stream end", - yaml_DOCUMENT_START_EVENT: "document start", - yaml_DOCUMENT_END_EVENT: "document end", - yaml_ALIAS_EVENT: "alias", - yaml_SCALAR_EVENT: "scalar", - yaml_SEQUENCE_START_EVENT: "sequence start", - yaml_SEQUENCE_END_EVENT: "sequence end", - yaml_MAPPING_START_EVENT: "mapping start", - yaml_MAPPING_END_EVENT: "mapping end", - yaml_TAIL_COMMENT_EVENT: "tail comment", -} - -func (e yaml_event_type_t) String() string { - if e < 0 || int(e) >= len(eventStrings) { - return fmt.Sprintf("unknown event %d", e) - } - return eventStrings[e] -} - -// The event structure. -type yaml_event_t struct { - - // The event type. - typ yaml_event_type_t - - // The start and end of the event. - start_mark, end_mark yaml_mark_t - - // The document encoding (for yaml_STREAM_START_EVENT). - encoding yaml_encoding_t - - // The version directive (for yaml_DOCUMENT_START_EVENT). - version_directive *yaml_version_directive_t - - // The list of tag directives (for yaml_DOCUMENT_START_EVENT). - tag_directives []yaml_tag_directive_t - - // The comments - head_comment []byte - line_comment []byte - foot_comment []byte - tail_comment []byte - - // The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT). - anchor []byte - - // The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). - tag []byte - - // The scalar value (for yaml_SCALAR_EVENT). - value []byte - - // Is the document start/end indicator implicit, or the tag optional? - // (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT). - implicit bool - - // Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT). - quoted_implicit bool - - // The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). - style yaml_style_t -} - -func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) } -func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) } -func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) } - -// Nodes - -const ( - yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null. - yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false. - yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values. - yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values. - yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values. - yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values. - - yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences. - yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping. - - // Not in original libyaml. - yaml_BINARY_TAG = "tag:yaml.org,2002:binary" - yaml_MERGE_TAG = "tag:yaml.org,2002:merge" - - yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str. - yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq. - yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map. -) - -type yaml_node_type_t int - -// Node types. -const ( - // An empty node. - yaml_NO_NODE yaml_node_type_t = iota - - yaml_SCALAR_NODE // A scalar node. - yaml_SEQUENCE_NODE // A sequence node. - yaml_MAPPING_NODE // A mapping node. -) - -// An element of a sequence node. -type yaml_node_item_t int - -// An element of a mapping node. -type yaml_node_pair_t struct { - key int // The key of the element. - value int // The value of the element. -} - -// The node structure. -type yaml_node_t struct { - typ yaml_node_type_t // The node type. - tag []byte // The node tag. - - // The node data. - - // The scalar parameters (for yaml_SCALAR_NODE). - scalar struct { - value []byte // The scalar value. - length int // The length of the scalar value. - style yaml_scalar_style_t // The scalar style. - } - - // The sequence parameters (for YAML_SEQUENCE_NODE). - sequence struct { - items_data []yaml_node_item_t // The stack of sequence items. - style yaml_sequence_style_t // The sequence style. - } - - // The mapping parameters (for yaml_MAPPING_NODE). - mapping struct { - pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value). - pairs_start *yaml_node_pair_t // The beginning of the stack. - pairs_end *yaml_node_pair_t // The end of the stack. - pairs_top *yaml_node_pair_t // The top of the stack. - style yaml_mapping_style_t // The mapping style. - } - - start_mark yaml_mark_t // The beginning of the node. - end_mark yaml_mark_t // The end of the node. - -} - -// The document structure. -type yaml_document_t struct { - - // The document nodes. - nodes []yaml_node_t - - // The version directive. - version_directive *yaml_version_directive_t - - // The list of tag directives. - tag_directives_data []yaml_tag_directive_t - tag_directives_start int // The beginning of the tag directives list. - tag_directives_end int // The end of the tag directives list. - - start_implicit int // Is the document start indicator implicit? - end_implicit int // Is the document end indicator implicit? - - // The start/end of the document. - start_mark, end_mark yaml_mark_t -} - -// The prototype of a read handler. -// -// The read handler is called when the parser needs to read more bytes from the -// source. The handler should write not more than size bytes to the buffer. -// The number of written bytes should be set to the size_read variable. -// -// [in,out] data A pointer to an application data specified by -// yaml_parser_set_input(). -// [out] buffer The buffer to write the data from the source. -// [in] size The size of the buffer. -// [out] size_read The actual number of bytes read from the source. -// -// On success, the handler should return 1. If the handler failed, -// the returned value should be 0. On EOF, the handler should set the -// size_read to 0 and return 1. -type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error) - -// This structure holds information about a potential simple key. -type yaml_simple_key_t struct { - possible bool // Is a simple key possible? - required bool // Is a simple key required? - token_number int // The number of the token. - mark yaml_mark_t // The position mark. -} - -// The states of the parser. -type yaml_parser_state_t int - -const ( - yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota - - yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document. - yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START. - yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document. - yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END. - yaml_PARSE_BLOCK_NODE_STATE // Expect a block node. - yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence. - yaml_PARSE_FLOW_NODE_STATE // Expect a flow node. - yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence. - yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence. - yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence. - yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. - yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key. - yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value. - yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence. - yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence. - yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping. - yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping. - yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry. - yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. - yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. - yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. - yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping. - yaml_PARSE_END_STATE // Expect nothing. -) - -func (ps yaml_parser_state_t) String() string { - switch ps { - case yaml_PARSE_STREAM_START_STATE: - return "yaml_PARSE_STREAM_START_STATE" - case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: - return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE" - case yaml_PARSE_DOCUMENT_START_STATE: - return "yaml_PARSE_DOCUMENT_START_STATE" - case yaml_PARSE_DOCUMENT_CONTENT_STATE: - return "yaml_PARSE_DOCUMENT_CONTENT_STATE" - case yaml_PARSE_DOCUMENT_END_STATE: - return "yaml_PARSE_DOCUMENT_END_STATE" - case yaml_PARSE_BLOCK_NODE_STATE: - return "yaml_PARSE_BLOCK_NODE_STATE" - case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: - return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE" - case yaml_PARSE_FLOW_NODE_STATE: - return "yaml_PARSE_FLOW_NODE_STATE" - case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: - return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE" - case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: - return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE" - case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: - return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE" - case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: - return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE" - case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: - return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE" - case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: - return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE" - case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE" - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE" - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE" - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE" - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE" - case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: - return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE" - case yaml_PARSE_FLOW_MAPPING_KEY_STATE: - return "yaml_PARSE_FLOW_MAPPING_KEY_STATE" - case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: - return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE" - case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: - return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE" - case yaml_PARSE_END_STATE: - return "yaml_PARSE_END_STATE" - } - return "<unknown parser state>" -} - -// This structure holds aliases data. -type yaml_alias_data_t struct { - anchor []byte // The anchor. - index int // The node id. - mark yaml_mark_t // The anchor mark. -} - -// The parser structure. -// -// All members are internal. Manage the structure using the -// yaml_parser_ family of functions. -type yaml_parser_t struct { - - // Error handling - - error yaml_error_type_t // Error type. - - problem string // Error description. - - // The byte about which the problem occurred. - problem_offset int - problem_value int - problem_mark yaml_mark_t - - // The error context. - context string - context_mark yaml_mark_t - - // Reader stuff - - read_handler yaml_read_handler_t // Read handler. - - input_reader io.Reader // File input data. - input []byte // String input data. - input_pos int - - eof bool // EOF flag - - buffer []byte // The working buffer. - buffer_pos int // The current position of the buffer. - - unread int // The number of unread characters in the buffer. - - newlines int // The number of line breaks since last non-break/non-blank character - - raw_buffer []byte // The raw buffer. - raw_buffer_pos int // The current position of the buffer. - - encoding yaml_encoding_t // The input encoding. - - offset int // The offset of the current position (in bytes). - mark yaml_mark_t // The mark of the current position. - - // Comments - - head_comment []byte // The current head comments - line_comment []byte // The current line comments - foot_comment []byte // The current foot comments - tail_comment []byte // Foot comment that happens at the end of a block. - stem_comment []byte // Comment in item preceding a nested structure (list inside list item, etc) - - comments []yaml_comment_t // The folded comments for all parsed tokens - comments_head int - - // Scanner stuff - - stream_start_produced bool // Have we started to scan the input stream? - stream_end_produced bool // Have we reached the end of the input stream? - - flow_level int // The number of unclosed '[' and '{' indicators. - - tokens []yaml_token_t // The tokens queue. - tokens_head int // The head of the tokens queue. - tokens_parsed int // The number of tokens fetched from the queue. - token_available bool // Does the tokens queue contain a token ready for dequeueing. - - indent int // The current indentation level. - indents []int // The indentation levels stack. - - simple_key_allowed bool // May a simple key occur at the current position? - simple_keys []yaml_simple_key_t // The stack of simple keys. - simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number - - // Parser stuff - - state yaml_parser_state_t // The current parser state. - states []yaml_parser_state_t // The parser states stack. - marks []yaml_mark_t // The stack of marks. - tag_directives []yaml_tag_directive_t // The list of TAG directives. - - // Dumper stuff - - aliases []yaml_alias_data_t // The alias data. - - document *yaml_document_t // The currently parsed document. -} - -type yaml_comment_t struct { - - scan_mark yaml_mark_t // Position where scanning for comments started - token_mark yaml_mark_t // Position after which tokens will be associated with this comment - start_mark yaml_mark_t // Position of '#' comment mark - end_mark yaml_mark_t // Position where comment terminated - - head []byte - line []byte - foot []byte -} - -// Emitter Definitions - -// The prototype of a write handler. -// -// The write handler is called when the emitter needs to flush the accumulated -// characters to the output. The handler should write @a size bytes of the -// @a buffer to the output. -// -// @param[in,out] data A pointer to an application data specified by -// yaml_emitter_set_output(). -// @param[in] buffer The buffer with bytes to be written. -// @param[in] size The size of the buffer. -// -// @returns On success, the handler should return @c 1. If the handler failed, -// the returned value should be @c 0. -// -type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error - -type yaml_emitter_state_t int - -// The emitter states. -const ( - // Expect STREAM-START. - yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota - - yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END. - yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END. - yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document. - yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END. - yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence. - yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE // Expect the next item of a flow sequence, with the comma already written out - yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence. - yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. - yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE // Expect the next key of a flow mapping, with the comma already written out - yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. - yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping. - yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. - yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence. - yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence. - yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. - yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping. - yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping. - yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping. - yaml_EMIT_END_STATE // Expect nothing. -) - -// The emitter structure. -// -// All members are internal. Manage the structure using the @c yaml_emitter_ -// family of functions. -type yaml_emitter_t struct { - - // Error handling - - error yaml_error_type_t // Error type. - problem string // Error description. - - // Writer stuff - - write_handler yaml_write_handler_t // Write handler. - - output_buffer *[]byte // String output data. - output_writer io.Writer // File output data. - - buffer []byte // The working buffer. - buffer_pos int // The current position of the buffer. - - raw_buffer []byte // The raw buffer. - raw_buffer_pos int // The current position of the buffer. - - encoding yaml_encoding_t // The stream encoding. - - // Emitter stuff - - canonical bool // If the output is in the canonical style? - best_indent int // The number of indentation spaces. - best_width int // The preferred width of the output lines. - unicode bool // Allow unescaped non-ASCII characters? - line_break yaml_break_t // The preferred line break. - - state yaml_emitter_state_t // The current emitter state. - states []yaml_emitter_state_t // The stack of states. - - events []yaml_event_t // The event queue. - events_head int // The head of the event queue. - - indents []int // The stack of indentation levels. - - tag_directives []yaml_tag_directive_t // The list of tag directives. - - indent int // The current indentation level. - - flow_level int // The current flow level. - - root_context bool // Is it the document root context? - sequence_context bool // Is it a sequence context? - mapping_context bool // Is it a mapping context? - simple_key_context bool // Is it a simple mapping key context? - - line int // The current line. - column int // The current column. - whitespace bool // If the last character was a whitespace? - indention bool // If the last character was an indentation character (' ', '-', '?', ':')? - open_ended bool // If an explicit document end is required? - - space_above bool // Is there's an empty line above? - foot_indent int // The indent used to write the foot comment above, or -1 if none. - - // Anchor analysis. - anchor_data struct { - anchor []byte // The anchor value. - alias bool // Is it an alias? - } - - // Tag analysis. - tag_data struct { - handle []byte // The tag handle. - suffix []byte // The tag suffix. - } - - // Scalar analysis. - scalar_data struct { - value []byte // The scalar value. - multiline bool // Does the scalar contain line breaks? - flow_plain_allowed bool // Can the scalar be expessed in the flow plain style? - block_plain_allowed bool // Can the scalar be expressed in the block plain style? - single_quoted_allowed bool // Can the scalar be expressed in the single quoted style? - block_allowed bool // Can the scalar be expressed in the literal or folded styles? - style yaml_scalar_style_t // The output style. - } - - // Comments - head_comment []byte - line_comment []byte - foot_comment []byte - tail_comment []byte - - key_line_comment []byte - - // Dumper stuff - - opened bool // If the stream was already opened? - closed bool // If the stream was already closed? - - // The information associated with the document nodes. - anchors *struct { - references int // The number of references. - anchor int // The anchor id. - serialized bool // If the node has been emitted? - } - - last_anchor_id int // The last assigned anchor id. - - document *yaml_document_t // The currently emitted document. -} diff --git a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/yamlprivateh.go b/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/yamlprivateh.go deleted file mode 100644 index e88f9c5..0000000 --- a/.devenv/state/go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/yamlprivateh.go +++ /dev/null @@ -1,198 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// 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. - -package yaml - -const ( - // The size of the input raw buffer. - input_raw_buffer_size = 512 - - // The size of the input buffer. - // It should be possible to decode the whole raw buffer. - input_buffer_size = input_raw_buffer_size * 3 - - // The size of the output buffer. - output_buffer_size = 128 - - // The size of the output raw buffer. - // It should be possible to encode the whole output buffer. - output_raw_buffer_size = (output_buffer_size*2 + 2) - - // The size of other stacks and queues. - initial_stack_size = 16 - initial_queue_size = 16 - initial_string_size = 16 -) - -// Check if the character at the specified position is an alphabetical -// character, a digit, '_', or '-'. -func is_alpha(b []byte, i int) bool { - return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-' -} - -// Check if the character at the specified position is a digit. -func is_digit(b []byte, i int) bool { - return b[i] >= '0' && b[i] <= '9' -} - -// Get the value of a digit. -func as_digit(b []byte, i int) int { - return int(b[i]) - '0' -} - -// Check if the character at the specified position is a hex-digit. -func is_hex(b []byte, i int) bool { - return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f' -} - -// Get the value of a hex-digit. -func as_hex(b []byte, i int) int { - bi := b[i] - if bi >= 'A' && bi <= 'F' { - return int(bi) - 'A' + 10 - } - if bi >= 'a' && bi <= 'f' { - return int(bi) - 'a' + 10 - } - return int(bi) - '0' -} - -// Check if the character is ASCII. -func is_ascii(b []byte, i int) bool { - return b[i] <= 0x7F -} - -// Check if the character at the start of the buffer can be printed unescaped. -func is_printable(b []byte, i int) bool { - return ((b[i] == 0x0A) || // . == #x0A - (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E - (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF - (b[i] > 0xC2 && b[i] < 0xED) || - (b[i] == 0xED && b[i+1] < 0xA0) || - (b[i] == 0xEE) || - (b[i] == 0xEF && // #xE000 <= . <= #xFFFD - !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF - !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF)))) -} - -// Check if the character at the specified position is NUL. -func is_z(b []byte, i int) bool { - return b[i] == 0x00 -} - -// Check if the beginning of the buffer is a BOM. -func is_bom(b []byte, i int) bool { - return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF -} - -// Check if the character at the specified position is space. -func is_space(b []byte, i int) bool { - return b[i] == ' ' -} - -// Check if the character at the specified position is tab. -func is_tab(b []byte, i int) bool { - return b[i] == '\t' -} - -// Check if the character at the specified position is blank (space or tab). -func is_blank(b []byte, i int) bool { - //return is_space(b, i) || is_tab(b, i) - return b[i] == ' ' || b[i] == '\t' -} - -// Check if the character at the specified position is a line break. -func is_break(b []byte, i int) bool { - return (b[i] == '\r' || // CR (#xD) - b[i] == '\n' || // LF (#xA) - b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029) -} - -func is_crlf(b []byte, i int) bool { - return b[i] == '\r' && b[i+1] == '\n' -} - -// Check if the character is a line break or NUL. -func is_breakz(b []byte, i int) bool { - //return is_break(b, i) || is_z(b, i) - return ( - // is_break: - b[i] == '\r' || // CR (#xD) - b[i] == '\n' || // LF (#xA) - b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) - // is_z: - b[i] == 0) -} - -// Check if the character is a line break, space, or NUL. -func is_spacez(b []byte, i int) bool { - //return is_space(b, i) || is_breakz(b, i) - return ( - // is_space: - b[i] == ' ' || - // is_breakz: - b[i] == '\r' || // CR (#xD) - b[i] == '\n' || // LF (#xA) - b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) - b[i] == 0) -} - -// Check if the character is a line break, space, tab, or NUL. -func is_blankz(b []byte, i int) bool { - //return is_blank(b, i) || is_breakz(b, i) - return ( - // is_blank: - b[i] == ' ' || b[i] == '\t' || - // is_breakz: - b[i] == '\r' || // CR (#xD) - b[i] == '\n' || // LF (#xA) - b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) - b[i] == 0) -} - -// Determine the width of the character. -func width(b byte) int { - // Don't replace these by a switch without first - // confirming that it is being inlined. - if b&0x80 == 0x00 { - return 1 - } - if b&0xE0 == 0xC0 { - return 2 - } - if b&0xF0 == 0xE0 { - return 3 - } - if b&0xF8 == 0xF0 { - return 4 - } - return 0 - -} diff --git a/.devenv/state/go/pkg/sumdb/sum.golang.org/latest b/.devenv/state/go/pkg/sumdb/sum.golang.org/latest deleted file mode 100644 index eb4b0d7..0000000 --- a/.devenv/state/go/pkg/sumdb/sum.golang.org/latest +++ /dev/null @@ -1,5 +0,0 @@ -go.sum database tree -19632713 -+dFqIiCep9PFS2o8VBuGFtkBBGfUWWNR5ZdeHkgmu9k= - -— sum.golang.org Az3griAQL5WUYUZsThtGZu3lOLHLrxWK0YS6TDTBr7TJUTmogfpY1Hyrv21yIzVzvlSSsoq4A1vGmP1Se1EmBw8IcgQ= diff --git a/.gitignore b/.gitignore index c55f7d0..ddb7cef 100644 --- a/.gitignore +++ b/.gitignore @@ -61,7 +61,7 @@ testdata/ # Gradle .idea/**/gradle.xml -.idea/**/libraries +g.idea/**/libraries # Gradle and Maven with auto-import # When using Gradle or Maven with auto-import, you should exclude module files, @@ -146,4 +146,7 @@ fabric.properties # https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij .idea/**/azureSettings.xml -# End of https://www.toptal.com/developers/gitignore/api/intellij,go \ No newline at end of file +# End of https://www.toptal.com/developers/gitignore/api/intellij,go +/.attach_pid* +.devenv* +devenv.local.nix diff --git a/execute.go b/execute.go index 68a06c6..b8569b1 100644 --- a/execute.go +++ b/execute.go @@ -11,6 +11,9 @@ import ( ) func (s *Settings[C]) Execute() *Settings[C] { + s.mu.Lock() + defer s.mu.Unlock() + if len(s.errors) > 0 { return s } @@ -89,6 +92,8 @@ func callCmdFunctions[C any](settings *Settings[C], commands []*cmd[C]) bool { // HelpRequested indicates if the help flag was set. func (s *Settings[C]) HelpRequested() bool { + s.mu.Lock() + defer s.mu.Unlock() for _, err := range s.errors { if err == flag.ErrHelp { @@ -99,8 +104,10 @@ func (s *Settings[C]) HelpRequested() bool { return false } -// MissingCommandError is returned if no command was found. +// MissingCommand returns true if the command was not found func (s *Settings[C]) MissingCommand() bool { + s.mu.Lock() + defer s.mu.Unlock() for _, err := range s.errors { if err == MissingCommandError { @@ -113,5 +120,8 @@ func (s *Settings[C]) MissingCommand() bool { // WasExecuted returns true if the call function was executed func (s *Settings[C]) WasExecuted() bool { + s.mu.Lock() + defer s.mu.Unlock() + return s.wasExecuted } diff --git a/go.mod b/go.mod index b725f36..578f6bc 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( github.com/stretchr/testify v1.8.2 - gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.8.1 + gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.9.1 ) require ( diff --git a/go.sum b/go.sum index 83ee2b1..9ee6019 100644 --- a/go.sum +++ b/go.sum @@ -26,6 +26,8 @@ gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.5.2 h1:R+dL2NJCM+AQN gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.5.2/go.mod h1:UvdD4NAf3gLKYafabJD7e9ZCOetzM9JZ9y4GkZukPVU= gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.8.1 h1:A3KvLvu4rV3OstgEn6xHulhQaXawVvzFzbafYHWHUfs= gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.8.1/go.mod h1:MqCBFv7DXKoBE2rZDc51LGvl2QI7Kz0D+XkQ0izj+ws= +gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.9.1 h1:WpM6PcFqQZWPBGDEuMILWHq98dPVBLAxi8ae9QMWWbM= +gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.9.1/go.mod h1:MqCBFv7DXKoBE2rZDc51LGvl2QI7Kz0D+XkQ0izj+ws= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/issue-7_test.go b/issue-7_test.go new file mode 100644 index 0000000..7593351 --- /dev/null +++ b/issue-7_test.go @@ -0,0 +1,37 @@ +package xflags + +import ( + "sync" + "testing" +) + +type testI7 struct { +} + +func TestRaceCondition(t *testing.T) { + var wg sync.WaitGroup + settings := &Settings[testI7]{} + + for i := 0; i < 100; i++ { + wg.Add(4) // 4 Methoden werden in jeder Iteration aufgerufen + + go func() { + settings.Execute() + wg.Done() + }() + go func() { + _ = settings.HelpRequested() + wg.Done() + }() + go func() { + _ = settings.MissingCommand() + wg.Done() + }() + go func() { + _ = settings.WasExecuted() + wg.Done() + }() + } + + wg.Wait() +} diff --git a/setting.go b/setting.go index 78e1acd..6697cbf 100644 --- a/setting.go +++ b/setting.go @@ -6,6 +6,7 @@ package xflags import ( "flag" "io" + "sync" ) func (s *Settings[C]) initCommands(name string) { @@ -19,6 +20,8 @@ type config struct { // Settings[C] is the main struct for the xflags package. type Settings[C any] struct { + mu sync.Mutex + definitions C command *cmd[C] -- GitLab