From 4f93bc4ab54e0f51ad1f67d54d753acd8684261a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 07:49:50 +0000 Subject: [PATCH] Bump github.com/go-redis/redis/v8 from 8.11.3 to 8.11.5 Bumps [github.com/go-redis/redis/v8](https://github.com/go-redis/redis) from 8.11.3 to 8.11.5. - [Release notes](https://github.com/go-redis/redis/releases) - [Changelog](https://github.com/redis/go-redis/blob/v8.11.5/CHANGELOG.md) - [Commits](https://github.com/go-redis/redis/compare/v8.11.3...v8.11.5) --- updated-dependencies: - dependency-name: github.com/go-redis/redis/v8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 6 +- go.sum | 18 +- .../github.com/cespare/xxhash/v2/.travis.yml | 8 - vendor/github.com/cespare/xxhash/v2/README.md | 6 +- vendor/github.com/cespare/xxhash/v2/xxhash.go | 1 - .../cespare/xxhash/v2/xxhash_amd64.s | 62 ++-- .../cespare/xxhash/v2/xxhash_unsafe.go | 53 +-- .../go-redis/redis/v8/.golangci.yml | 22 -- .../redis/v8/{.prettierrc => .prettierrc.yml} | 0 .../github.com/go-redis/redis/v8/CHANGELOG.md | 40 ++- vendor/github.com/go-redis/redis/v8/Makefile | 19 +- vendor/github.com/go-redis/redis/v8/README.md | 39 ++- .../github.com/go-redis/redis/v8/RELEASING.md | 10 +- .../github.com/go-redis/redis/v8/cluster.go | 20 +- .../github.com/go-redis/redis/v8/command.go | 311 +++++++++++++++++- .../github.com/go-redis/redis/v8/commands.go | 92 +++++- vendor/github.com/go-redis/redis/v8/error.go | 26 +- .../redis/v8/internal/hscan/structmap.go | 6 +- .../go-redis/redis/v8/internal/pool/pool.go | 36 +- .../redis/v8/internal/proto/reader.go | 2 +- .../go-redis/redis/v8/internal/proto/scan.go | 8 + .../redis/v8/internal/proto/writer.go | 2 + .../go-redis/redis/v8/internal/safe.go | 1 + .../go-redis/redis/v8/internal/unsafe.go | 1 + .../go-redis/redis/v8/internal/util/safe.go | 1 + .../go-redis/redis/v8/internal/util/unsafe.go | 1 + .../github.com/go-redis/redis/v8/options.go | 151 ++++++++- .../github.com/go-redis/redis/v8/package.json | 8 + .../github.com/go-redis/redis/v8/pipeline.go | 10 + vendor/github.com/go-redis/redis/v8/pubsub.go | 12 +- vendor/github.com/go-redis/redis/v8/redis.go | 26 +- vendor/github.com/go-redis/redis/v8/ring.go | 5 +- .../github.com/go-redis/redis/v8/sentinel.go | 9 +- vendor/github.com/go-redis/redis/v8/tx.go | 3 +- .../github.com/go-redis/redis/v8/universal.go | 2 + .../github.com/go-redis/redis/v8/version.go | 2 +- vendor/github.com/onsi/gomega/.travis.yml | 18 - vendor/github.com/onsi/gomega/CHANGELOG.md | 42 +++ vendor/github.com/onsi/gomega/Dockerfile | 1 - vendor/github.com/onsi/gomega/Makefile | 33 -- .../onsi/gomega/docker-compose.yaml | 10 - vendor/github.com/onsi/gomega/gomega_dsl.go | 17 +- .../onsi/gomega/internal/assertion.go | 81 +++-- .../onsi/gomega/internal/async_assertion.go | 19 +- .../github.com/onsi/gomega/internal/gomega.go | 8 +- .../onsi/gomega/internal/gutil/post_ioutil.go | 48 +++ .../gomega/internal/gutil/using_ioutil.go | 47 +++ vendor/github.com/onsi/gomega/matchers.go | 76 ++++- .../onsi/gomega/matchers/have_field.go | 87 +++++ .../gomega/matchers/have_http_body_matcher.go | 101 ++++++ .../have_http_header_with_value_matcher.go | 81 +++++ .../matchers/have_http_status_matcher.go | 72 +++- .../onsi/gomega/matchers/have_value.go | 54 +++ .../onsi/gomega/matchers/with_transform.go | 16 +- vendor/github.com/onsi/gomega/tools | 8 + vendor/github.com/onsi/gomega/types/types.go | 8 + vendor/modules.txt | 11 +- 57 files changed, 1525 insertions(+), 332 deletions(-) delete mode 100644 vendor/github.com/cespare/xxhash/v2/.travis.yml rename vendor/github.com/go-redis/redis/v8/{.prettierrc => .prettierrc.yml} (100%) create mode 100644 vendor/github.com/go-redis/redis/v8/package.json delete mode 100644 vendor/github.com/onsi/gomega/.travis.yml delete mode 100644 vendor/github.com/onsi/gomega/Dockerfile delete mode 100644 vendor/github.com/onsi/gomega/Makefile delete mode 100644 vendor/github.com/onsi/gomega/docker-compose.yaml create mode 100644 vendor/github.com/onsi/gomega/internal/gutil/post_ioutil.go create mode 100644 vendor/github.com/onsi/gomega/internal/gutil/using_ioutil.go create mode 100644 vendor/github.com/onsi/gomega/matchers/have_field.go create mode 100644 vendor/github.com/onsi/gomega/matchers/have_http_body_matcher.go create mode 100644 vendor/github.com/onsi/gomega/matchers/have_http_header_with_value_matcher.go create mode 100644 vendor/github.com/onsi/gomega/matchers/have_value.go create mode 100644 vendor/github.com/onsi/gomega/tools diff --git a/go.mod b/go.mod index 0183199e..40197407 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/fsnotify/fsnotify v1.7.0 github.com/getlantern/httptest v0.0.0-20161025015934-4b40f4c7e590 github.com/go-openapi/spec v0.19.7 - github.com/go-redis/redis/v8 v8.11.3 + github.com/go-redis/redis/v8 v8.11.5 github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.2 github.com/gorilla/mux v1.8.1 @@ -18,7 +18,7 @@ require ( github.com/jhump/protoreflect v1.9.0 github.com/mitchellh/go-server-timing v1.0.2-0.20201108055052-feb680ab92c2 github.com/motemen/go-loghttp v0.0.0-20170804080138-974ac5ceac27 - github.com/onsi/gomega v1.15.0 + github.com/onsi/gomega v1.18.1 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.11.0 github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b @@ -71,7 +71,7 @@ require ( github.com/alessio/shellescape v1.4.1 // indirect github.com/aokoli/goutils v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cyphar/filepath-securejoin v0.2.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect diff --git a/go.sum b/go.sum index d347b92c..243f308f 100644 --- a/go.sum +++ b/go.sum @@ -169,8 +169,9 @@ github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6 github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -387,8 +388,8 @@ github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85n github.com/go-openapi/validate v0.19.7/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= github.com/go-redis/redis/v8 v8.3.3/go.mod h1:jszGxBCez8QA1HWSmQxJO9Y82kNibbUmeYhKWrBejTU= -github.com/go-redis/redis/v8 v8.11.3 h1:GCjoYp8c+yQTJfc0n69iwSiHjvuAdruxl7elnZCxgt8= -github.com/go-redis/redis/v8 v8.11.3/go.mod h1:xNJ9xDG09FsIPwh3bWdk+0oDWHbtF9rPN0F/oD9XeKc= +github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= +github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -516,6 +517,7 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= @@ -782,8 +784,11 @@ github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.0.0 h1:CcuG/HvWNkkaqCUpJifQY8z7qEMBJya6aLPx6ftGyjQ= +github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -793,8 +798,10 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= -github.com/onsi/gomega v1.15.0 h1:WjP/FQ/sk43MRmnEcT+MlDw2TFvkrXlprrPST/IudjU= github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= +github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/oracle/oci-go-sdk v24.3.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= @@ -1306,6 +1313,7 @@ golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= diff --git a/vendor/github.com/cespare/xxhash/v2/.travis.yml b/vendor/github.com/cespare/xxhash/v2/.travis.yml deleted file mode 100644 index c516ea88..00000000 --- a/vendor/github.com/cespare/xxhash/v2/.travis.yml +++ /dev/null @@ -1,8 +0,0 @@ -language: go -go: - - "1.x" - - master -env: - - TAGS="" - - TAGS="-tags purego" -script: go test $TAGS -v ./... diff --git a/vendor/github.com/cespare/xxhash/v2/README.md b/vendor/github.com/cespare/xxhash/v2/README.md index 2fd8693c..792b4a60 100644 --- a/vendor/github.com/cespare/xxhash/v2/README.md +++ b/vendor/github.com/cespare/xxhash/v2/README.md @@ -1,7 +1,7 @@ # xxhash -[![GoDoc](https://godoc.org/github.com/cespare/xxhash?status.svg)](https://godoc.org/github.com/cespare/xxhash) -[![Build Status](https://travis-ci.org/cespare/xxhash.svg?branch=master)](https://travis-ci.org/cespare/xxhash) +[![Go Reference](https://pkg.go.dev/badge/github.com/cespare/xxhash/v2.svg)](https://pkg.go.dev/github.com/cespare/xxhash/v2) +[![Test](https://github.com/cespare/xxhash/actions/workflows/test.yml/badge.svg)](https://github.com/cespare/xxhash/actions/workflows/test.yml) xxhash is a Go implementation of the 64-bit [xxHash](http://cyan4973.github.io/xxHash/) algorithm, XXH64. This is a @@ -64,4 +64,6 @@ $ go test -benchtime 10s -bench '/xxhash,direct,bytes' - [InfluxDB](https://github.com/influxdata/influxdb) - [Prometheus](https://github.com/prometheus/prometheus) +- [VictoriaMetrics](https://github.com/VictoriaMetrics/VictoriaMetrics) - [FreeCache](https://github.com/coocood/freecache) +- [FastCache](https://github.com/VictoriaMetrics/fastcache) diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash.go b/vendor/github.com/cespare/xxhash/v2/xxhash.go index db0b35fb..15c835d5 100644 --- a/vendor/github.com/cespare/xxhash/v2/xxhash.go +++ b/vendor/github.com/cespare/xxhash/v2/xxhash.go @@ -193,7 +193,6 @@ func (d *Digest) UnmarshalBinary(b []byte) error { b, d.v4 = consumeUint64(b) b, d.total = consumeUint64(b) copy(d.mem[:], b) - b = b[len(d.mem):] d.n = int(d.total % uint64(len(d.mem))) return nil } diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s b/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s index d580e32a..be8db5bf 100644 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s +++ b/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s @@ -6,7 +6,7 @@ // Register allocation: // AX h -// CX pointer to advance through b +// SI pointer to advance through b // DX n // BX loop end // R8 v1, k1 @@ -16,39 +16,39 @@ // R12 tmp // R13 prime1v // R14 prime2v -// R15 prime4v +// DI prime4v -// round reads from and advances the buffer pointer in CX. +// round reads from and advances the buffer pointer in SI. // It assumes that R13 has prime1v and R14 has prime2v. #define round(r) \ - MOVQ (CX), R12 \ - ADDQ $8, CX \ + MOVQ (SI), R12 \ + ADDQ $8, SI \ IMULQ R14, R12 \ ADDQ R12, r \ ROLQ $31, r \ IMULQ R13, r // mergeRound applies a merge round on the two registers acc and val. -// It assumes that R13 has prime1v, R14 has prime2v, and R15 has prime4v. +// It assumes that R13 has prime1v, R14 has prime2v, and DI has prime4v. #define mergeRound(acc, val) \ IMULQ R14, val \ ROLQ $31, val \ IMULQ R13, val \ XORQ val, acc \ IMULQ R13, acc \ - ADDQ R15, acc + ADDQ DI, acc // func Sum64(b []byte) uint64 TEXT ·Sum64(SB), NOSPLIT, $0-32 // Load fixed primes. MOVQ ·prime1v(SB), R13 MOVQ ·prime2v(SB), R14 - MOVQ ·prime4v(SB), R15 + MOVQ ·prime4v(SB), DI // Load slice. - MOVQ b_base+0(FP), CX + MOVQ b_base+0(FP), SI MOVQ b_len+8(FP), DX - LEAQ (CX)(DX*1), BX + LEAQ (SI)(DX*1), BX // The first loop limit will be len(b)-32. SUBQ $32, BX @@ -65,14 +65,14 @@ TEXT ·Sum64(SB), NOSPLIT, $0-32 XORQ R11, R11 SUBQ R13, R11 - // Loop until CX > BX. + // Loop until SI > BX. blockLoop: round(R8) round(R9) round(R10) round(R11) - CMPQ CX, BX + CMPQ SI, BX JLE blockLoop MOVQ R8, AX @@ -100,16 +100,16 @@ noBlocks: afterBlocks: ADDQ DX, AX - // Right now BX has len(b)-32, and we want to loop until CX > len(b)-8. + // Right now BX has len(b)-32, and we want to loop until SI > len(b)-8. ADDQ $24, BX - CMPQ CX, BX + CMPQ SI, BX JG fourByte wordLoop: // Calculate k1. - MOVQ (CX), R8 - ADDQ $8, CX + MOVQ (SI), R8 + ADDQ $8, SI IMULQ R14, R8 ROLQ $31, R8 IMULQ R13, R8 @@ -117,18 +117,18 @@ wordLoop: XORQ R8, AX ROLQ $27, AX IMULQ R13, AX - ADDQ R15, AX + ADDQ DI, AX - CMPQ CX, BX + CMPQ SI, BX JLE wordLoop fourByte: ADDQ $4, BX - CMPQ CX, BX + CMPQ SI, BX JG singles - MOVL (CX), R8 - ADDQ $4, CX + MOVL (SI), R8 + ADDQ $4, SI IMULQ R13, R8 XORQ R8, AX @@ -138,19 +138,19 @@ fourByte: singles: ADDQ $4, BX - CMPQ CX, BX + CMPQ SI, BX JGE finalize singlesLoop: - MOVBQZX (CX), R12 - ADDQ $1, CX + MOVBQZX (SI), R12 + ADDQ $1, SI IMULQ ·prime5v(SB), R12 XORQ R12, AX ROLQ $11, AX IMULQ R13, AX - CMPQ CX, BX + CMPQ SI, BX JL singlesLoop finalize: @@ -179,9 +179,9 @@ TEXT ·writeBlocks(SB), NOSPLIT, $0-40 MOVQ ·prime2v(SB), R14 // Load slice. - MOVQ b_base+8(FP), CX + MOVQ b_base+8(FP), SI MOVQ b_len+16(FP), DX - LEAQ (CX)(DX*1), BX + LEAQ (SI)(DX*1), BX SUBQ $32, BX // Load vN from d. @@ -199,7 +199,7 @@ blockLoop: round(R10) round(R11) - CMPQ CX, BX + CMPQ SI, BX JLE blockLoop // Copy vN back to d. @@ -208,8 +208,8 @@ blockLoop: MOVQ R10, 16(AX) MOVQ R11, 24(AX) - // The number of bytes written is CX minus the old base pointer. - SUBQ b_base+8(FP), CX - MOVQ CX, ret+32(FP) + // The number of bytes written is SI minus the old base pointer. + SUBQ b_base+8(FP), SI + MOVQ SI, ret+32(FP) RET diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go b/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go index 53bf76ef..376e0ca2 100644 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go +++ b/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go @@ -6,41 +6,52 @@ package xxhash import ( - "reflect" "unsafe" ) -// Notes: +// In the future it's possible that compiler optimizations will make these +// XxxString functions unnecessary by realizing that calls such as +// Sum64([]byte(s)) don't need to copy s. See https://golang.org/issue/2205. +// If that happens, even if we keep these functions they can be replaced with +// the trivial safe code. + +// NOTE: The usual way of doing an unsafe string-to-[]byte conversion is: // -// See https://groups.google.com/d/msg/golang-nuts/dcjzJy-bSpw/tcZYBzQqAQAJ -// for some discussion about these unsafe conversions. +// var b []byte +// bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) +// bh.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data +// bh.Len = len(s) +// bh.Cap = len(s) // -// In the future it's possible that compiler optimizations will make these -// unsafe operations unnecessary: https://golang.org/issue/2205. +// Unfortunately, as of Go 1.15.3 the inliner's cost model assigns a high enough +// weight to this sequence of expressions that any function that uses it will +// not be inlined. Instead, the functions below use a different unsafe +// conversion designed to minimize the inliner weight and allow both to be +// inlined. There is also a test (TestInlining) which verifies that these are +// inlined. // -// Both of these wrapper functions still incur function call overhead since they -// will not be inlined. We could write Go/asm copies of Sum64 and Digest.Write -// for strings to squeeze out a bit more speed. Mid-stack inlining should -// eventually fix this. +// See https://github.com/golang/go/issues/42739 for discussion. // Sum64String computes the 64-bit xxHash digest of s. // It may be faster than Sum64([]byte(s)) by avoiding a copy. func Sum64String(s string) uint64 { - var b []byte - bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) - bh.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data - bh.Len = len(s) - bh.Cap = len(s) + b := *(*[]byte)(unsafe.Pointer(&sliceHeader{s, len(s)})) return Sum64(b) } // WriteString adds more data to d. It always returns len(s), nil. // It may be faster than Write([]byte(s)) by avoiding a copy. func (d *Digest) WriteString(s string) (n int, err error) { - var b []byte - bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) - bh.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data - bh.Len = len(s) - bh.Cap = len(s) - return d.Write(b) + d.Write(*(*[]byte)(unsafe.Pointer(&sliceHeader{s, len(s)}))) + // d.Write always returns len(s), nil. + // Ignoring the return output and returning these fixed values buys a + // savings of 6 in the inliner's cost model. + return len(s), nil +} + +// sliceHeader is similar to reflect.SliceHeader, but it assumes that the layout +// of the first two words is the same as the layout of a string. +type sliceHeader struct { + s string + cap int } diff --git a/vendor/github.com/go-redis/redis/v8/.golangci.yml b/vendor/github.com/go-redis/redis/v8/.golangci.yml index d15b5ac5..de514554 100644 --- a/vendor/github.com/go-redis/redis/v8/.golangci.yml +++ b/vendor/github.com/go-redis/redis/v8/.golangci.yml @@ -2,25 +2,3 @@ run: concurrency: 8 deadline: 5m tests: false -linters: - enable-all: true - disable: - - funlen - - gochecknoglobals - - gochecknoinits - - gocognit - - goconst - - godox - - gosec - - maligned - - wsl - - gomnd - - goerr113 - - exhaustive - - nestif - - nlreturn - - exhaustivestruct - - wrapcheck - - errorlint - - cyclop - - forcetypeassert diff --git a/vendor/github.com/go-redis/redis/v8/.prettierrc b/vendor/github.com/go-redis/redis/v8/.prettierrc.yml similarity index 100% rename from vendor/github.com/go-redis/redis/v8/.prettierrc rename to vendor/github.com/go-redis/redis/v8/.prettierrc.yml diff --git a/vendor/github.com/go-redis/redis/v8/CHANGELOG.md b/vendor/github.com/go-redis/redis/v8/CHANGELOG.md index 63aabd3d..195e5193 100644 --- a/vendor/github.com/go-redis/redis/v8/CHANGELOG.md +++ b/vendor/github.com/go-redis/redis/v8/CHANGELOG.md @@ -1,7 +1,41 @@ -# Changelog +## [8.11.5](https://github.com/go-redis/redis/compare/v8.11.4...v8.11.5) (2022-03-17) + + +### Bug Fixes + +* add missing Expire methods to Cmdable ([17e3b43](https://github.com/go-redis/redis/commit/17e3b43879d516437ada71cf9c0deac6a382ed9a)) +* add whitespace for avoid unlikely colisions ([7f7c181](https://github.com/go-redis/redis/commit/7f7c1817617cfec909efb13d14ad22ef05a6ad4c)) +* example/otel compile error ([#2028](https://github.com/go-redis/redis/issues/2028)) ([187c07c](https://github.com/go-redis/redis/commit/187c07c41bf68dc3ab280bc3a925e960bbef6475)) +* **extra/redisotel:** set span.kind attribute to client ([065b200](https://github.com/go-redis/redis/commit/065b200070b41e6e949710b4f9e01b50ccc60ab2)) +* format ([96f53a0](https://github.com/go-redis/redis/commit/96f53a0159a28affa94beec1543a62234e7f8b32)) +* invalid type assert in stringArg ([de6c131](https://github.com/go-redis/redis/commit/de6c131865b8263400c8491777b295035f2408e4)) +* rename Golang to Go ([#2030](https://github.com/go-redis/redis/issues/2030)) ([b82a2d9](https://github.com/go-redis/redis/commit/b82a2d9d4d2de7b7cbe8fcd4895be62dbcacacbc)) +* set timeout for WAIT command. Fixes [#1963](https://github.com/go-redis/redis/issues/1963) ([333fee1](https://github.com/go-redis/redis/commit/333fee1a8fd98a2fbff1ab187c1b03246a7eb01f)) +* update some argument counts in pre-allocs ([f6974eb](https://github.com/go-redis/redis/commit/f6974ebb5c40a8adf90d2cacab6dc297f4eba4c2)) + + +### Features + +* Add redis v7's NX, XX, GT, LT expire variants ([e19bbb2](https://github.com/go-redis/redis/commit/e19bbb26e2e395c6e077b48d80d79e99f729a8b8)) +* add support for acl sentinel auth in universal client ([ab0ccc4](https://github.com/go-redis/redis/commit/ab0ccc47413f9b2a6eabc852fed5005a3ee1af6e)) +* add support for COPY command ([#2016](https://github.com/go-redis/redis/issues/2016)) ([730afbc](https://github.com/go-redis/redis/commit/730afbcffb93760e8a36cc06cfe55ab102b693a7)) +* add support for passing extra attributes added to spans ([39faaa1](https://github.com/go-redis/redis/commit/39faaa171523834ba527c9789710c4fde87f5a2e)) +* add support for time.Duration write and scan ([2f1b74e](https://github.com/go-redis/redis/commit/2f1b74e20cdd7719b2aecf0768d3e3ae7c3e781b)) +* **redisotel:** ability to override TracerProvider ([#1998](https://github.com/go-redis/redis/issues/1998)) ([bf8d4aa](https://github.com/go-redis/redis/commit/bf8d4aa60c00366cda2e98c3ddddc8cf68507417)) +* set net.peer.name and net.peer.port in otel example ([69bf454](https://github.com/go-redis/redis/commit/69bf454f706204211cd34835f76b2e8192d3766d)) + + + +## [8.11.4](https://github.com/go-redis/redis/compare/v8.11.3...v8.11.4) (2021-10-04) + + +### Features + +* add acl auth support for sentinels ([f66582f](https://github.com/go-redis/redis/commit/f66582f44f3dc3a4705a5260f982043fde4aa634)) +* add Cmd.{String,Int,Float,Bool}Slice helpers and an example ([5d3d293](https://github.com/go-redis/redis/commit/5d3d293cc9c60b90871e2420602001463708ce24)) +* add SetVal method for each command ([168981d](https://github.com/go-redis/redis/commit/168981da2d84ee9e07d15d3e74d738c162e264c4)) + -> :heart: -> [**Uptrace.dev** - All-in-one tool to optimize performance and monitor errors & logs](https://uptrace.dev) ## v8.11 diff --git a/vendor/github.com/go-redis/redis/v8/Makefile b/vendor/github.com/go-redis/redis/v8/Makefile index b16709c8..a4cfe057 100644 --- a/vendor/github.com/go-redis/redis/v8/Makefile +++ b/vendor/github.com/go-redis/redis/v8/Makefile @@ -1,3 +1,5 @@ +PACKAGE_DIRS := $(shell find . -mindepth 2 -type f -name 'go.mod' -exec dirname {} \; | sort) + test: testdeps go test ./... go test ./... -short -race @@ -19,8 +21,15 @@ testdata/redis: testdata/redis/src/redis-server: testdata/redis cd $< && make all -tag: - git tag $(VERSION) - git tag extra/rediscmd/$(VERSION) - git tag extra/redisotel/$(VERSION) - git tag extra/rediscensus/$(VERSION) +fmt: + gofmt -w -s ./ + goimports -w -local github.com/go-redis/redis ./ + +go_mod_tidy: + go get -u && go mod tidy + set -e; for dir in $(PACKAGE_DIRS); do \ + echo "go mod tidy in $${dir}"; \ + (cd "$${dir}" && \ + go get -u && \ + go mod tidy); \ + done diff --git a/vendor/github.com/go-redis/redis/v8/README.md b/vendor/github.com/go-redis/redis/v8/README.md index 2c36f786..f3b6a018 100644 --- a/vendor/github.com/go-redis/redis/v8/README.md +++ b/vendor/github.com/go-redis/redis/v8/README.md @@ -1,34 +1,32 @@ -

- - All-in-one tool to optimize performance and monitor errors & logs - -

- -# Redis client for Golang +# Redis client for Go ![build workflow](https://github.com/go-redis/redis/actions/workflows/build.yml/badge.svg) [![PkgGoDev](https://pkg.go.dev/badge/github.com/go-redis/redis/v8)](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc) [![Documentation](https://img.shields.io/badge/redis-documentation-informational)](https://redis.uptrace.dev/) -[![Chat](https://discordapp.com/api/guilds/752070105847955518/widget.png)](https://discord.gg/rWtp5Aj) -- Join [Discord](https://discord.gg/rWtp5Aj) to ask questions. +go-redis is brought to you by :star: [**uptrace/uptrace**](https://github.com/uptrace/uptrace). +Uptrace is an open source and blazingly fast **distributed tracing** backend powered by +OpenTelemetry and ClickHouse. Give it a star as well! + +## Resources + +- [Discussions](https://github.com/go-redis/redis/discussions) - [Documentation](https://redis.uptrace.dev) - [Reference](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc) - [Examples](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#pkg-examples) - [RealWorld example app](https://github.com/uptrace/go-treemux-realworld-example-app) -My other projects: +Other projects you may like: - [Bun](https://bun.uptrace.dev) - fast and simple SQL client for PostgreSQL, MySQL, and SQLite. -- [treemux](https://github.com/vmihailenco/treemux) - high-speed, flexible, tree-based HTTP router - for Go. +- [BunRouter](https://bunrouter.uptrace.dev/) - fast and flexible HTTP router for Go. ## Ecosystem -- [Redis Mock](https://github.com/go-redis/redismock). -- [Distributed Locks](https://github.com/bsm/redislock). -- [Redis Cache](https://github.com/go-redis/cache). -- [Rate limiting](https://github.com/go-redis/redis_rate). +- [Redis Mock](https://github.com/go-redis/redismock) +- [Distributed Locks](https://github.com/bsm/redislock) +- [Redis Cache](https://github.com/go-redis/cache) +- [Rate limiting](https://github.com/go-redis/redis_rate) ## Features @@ -37,16 +35,16 @@ My other projects: [circuit breaker](https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern) support. - [Pub/Sub](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#PubSub). - [Transactions](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#example-Client-TxPipeline). -- [Pipeline](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#example-Client-Pipeline) and - [TxPipeline](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#example-Client-TxPipeline). +- [Pipeline](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#example-Client.Pipeline) and + [TxPipeline](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#example-Client.TxPipeline). - [Scripting](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#Script). - [Timeouts](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#Options). - [Redis Sentinel](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#NewFailoverClient). - [Redis Cluster](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#NewClusterClient). -- [Cluster of Redis Servers](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#example-NewClusterClient--ManualSetup) +- [Cluster of Redis Servers](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#example-NewClusterClient-ManualSetup) without using cluster mode and Redis Sentinel. - [Ring](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#NewRing). -- [Instrumentation](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#ex-package--Instrumentation). +- [Instrumentation](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#example-package-Instrumentation). ## Installation @@ -70,6 +68,7 @@ go get github.com/go-redis/redis/v8 import ( "context" "github.com/go-redis/redis/v8" + "fmt" ) var ctx = context.Background() diff --git a/vendor/github.com/go-redis/redis/v8/RELEASING.md b/vendor/github.com/go-redis/redis/v8/RELEASING.md index 9e50c106..1115db4e 100644 --- a/vendor/github.com/go-redis/redis/v8/RELEASING.md +++ b/vendor/github.com/go-redis/redis/v8/RELEASING.md @@ -3,7 +3,7 @@ 1. Run `release.sh` script which updates versions in go.mod files and pushes a new branch to GitHub: ```shell -./scripts/release.sh -t v1.0.0 +TAG=v1.0.0 ./scripts/release.sh ``` 2. Open a pull request and wait for the build to finish. @@ -11,11 +11,5 @@ 3. Merge the pull request and run `tag.sh` to create tags for packages: ```shell -./scripts/tag.sh -t v1.0.0 -``` - -4. Push the tags: - -```shell -git push origin --tags +TAG=v1.0.0 ./scripts/tag.sh ``` diff --git a/vendor/github.com/go-redis/redis/v8/cluster.go b/vendor/github.com/go-redis/redis/v8/cluster.go index 8d93b369..a54f2f37 100644 --- a/vendor/github.com/go-redis/redis/v8/cluster.go +++ b/vendor/github.com/go-redis/redis/v8/cluster.go @@ -352,7 +352,7 @@ func (c *clusterNodes) GC(generation uint32) { } } -func (c *clusterNodes) Get(addr string) (*clusterNode, error) { +func (c *clusterNodes) GetOrCreate(addr string) (*clusterNode, error) { node, err := c.get(addr) if err != nil { return nil, err @@ -416,7 +416,7 @@ func (c *clusterNodes) Random() (*clusterNode, error) { } n := rand.Intn(len(addrs)) - return c.Get(addrs[n]) + return c.GetOrCreate(addrs[n]) } //------------------------------------------------------------------------------ @@ -474,7 +474,7 @@ func newClusterState( addr = replaceLoopbackHost(addr, originHost) } - node, err := c.nodes.Get(addr) + node, err := c.nodes.GetOrCreate(addr) if err != nil { return nil, err } @@ -824,8 +824,10 @@ func (c *ClusterClient) process(ctx context.Context, cmd Cmder) error { var addr string moved, ask, addr = isMovedError(lastErr) if moved || ask { + c.state.LazyReload() + var err error - node, err = c.nodes.Get(addr) + node, err = c.nodes.GetOrCreate(addr) if err != nil { return err } @@ -1022,7 +1024,7 @@ func (c *ClusterClient) loadState(ctx context.Context) (*clusterState, error) { for _, idx := range rand.Perm(len(addrs)) { addr := addrs[idx] - node, err := c.nodes.Get(addr) + node, err := c.nodes.GetOrCreate(addr) if err != nil { if firstErr == nil { firstErr = err @@ -1236,7 +1238,7 @@ func (c *ClusterClient) checkMovedErr( return false } - node, err := c.nodes.Get(addr) + node, err := c.nodes.GetOrCreate(addr) if err != nil { return false } @@ -1422,7 +1424,7 @@ func (c *ClusterClient) cmdsMoved( addr string, failedCmds *cmdsMap, ) error { - node, err := c.nodes.Get(addr) + node, err := c.nodes.GetOrCreate(addr) if err != nil { return err } @@ -1477,7 +1479,7 @@ func (c *ClusterClient) Watch(ctx context.Context, fn func(*Tx) error, keys ...s moved, ask, addr := isMovedError(err) if moved || ask { - node, err = c.nodes.Get(addr) + node, err = c.nodes.GetOrCreate(addr) if err != nil { return err } @@ -1589,7 +1591,7 @@ func (c *ClusterClient) cmdsInfo(ctx context.Context) (map[string]*CommandInfo, for _, idx := range perm { addr := addrs[idx] - node, err := c.nodes.Get(addr) + node, err := c.nodes.GetOrCreate(addr) if err != nil { if firstErr == nil { firstErr = err diff --git a/vendor/github.com/go-redis/redis/v8/command.go b/vendor/github.com/go-redis/redis/v8/command.go index 6f77258b..4bb12a85 100644 --- a/vendor/github.com/go-redis/redis/v8/command.go +++ b/vendor/github.com/go-redis/redis/v8/command.go @@ -20,7 +20,7 @@ type Cmder interface { String() string stringArg(int) string firstKeyPos() int8 - setFirstKeyPos(int8) + SetFirstKeyPos(int8) readTimeout() *time.Duration readReply(rd *proto.Reader) error @@ -151,15 +151,21 @@ func (cmd *baseCmd) stringArg(pos int) string { if pos < 0 || pos >= len(cmd.args) { return "" } - s, _ := cmd.args[pos].(string) - return s + arg := cmd.args[pos] + switch v := arg.(type) { + case string: + return v + default: + // TODO: consider using appendArg + return fmt.Sprint(v) + } } func (cmd *baseCmd) firstKeyPos() int8 { return cmd.keyPos } -func (cmd *baseCmd) setFirstKeyPos(keyPos int8) { +func (cmd *baseCmd) SetFirstKeyPos(keyPos int8) { cmd.keyPos = keyPos } @@ -200,6 +206,10 @@ func (cmd *Cmd) String() string { return cmdString(cmd, cmd.val) } +func (cmd *Cmd) SetVal(val interface{}) { + cmd.val = val +} + func (cmd *Cmd) Val() interface{} { return cmd.val } @@ -212,7 +222,11 @@ func (cmd *Cmd) Text() (string, error) { if cmd.err != nil { return "", cmd.err } - switch val := cmd.val.(type) { + return toString(cmd.val) +} + +func toString(val interface{}) (string, error) { + switch val := val.(type) { case string: return val, nil default: @@ -240,7 +254,11 @@ func (cmd *Cmd) Int64() (int64, error) { if cmd.err != nil { return 0, cmd.err } - switch val := cmd.val.(type) { + return toInt64(cmd.val) +} + +func toInt64(val interface{}) (int64, error) { + switch val := val.(type) { case int64: return val, nil case string: @@ -255,7 +273,11 @@ func (cmd *Cmd) Uint64() (uint64, error) { if cmd.err != nil { return 0, cmd.err } - switch val := cmd.val.(type) { + return toUint64(cmd.val) +} + +func toUint64(val interface{}) (uint64, error) { + switch val := val.(type) { case int64: return uint64(val), nil case string: @@ -270,7 +292,11 @@ func (cmd *Cmd) Float32() (float32, error) { if cmd.err != nil { return 0, cmd.err } - switch val := cmd.val.(type) { + return toFloat32(cmd.val) +} + +func toFloat32(val interface{}) (float32, error) { + switch val := val.(type) { case int64: return float32(val), nil case string: @@ -289,7 +315,11 @@ func (cmd *Cmd) Float64() (float64, error) { if cmd.err != nil { return 0, cmd.err } - switch val := cmd.val.(type) { + return toFloat64(cmd.val) +} + +func toFloat64(val interface{}) (float64, error) { + switch val := val.(type) { case int64: return float64(val), nil case string: @@ -304,7 +334,11 @@ func (cmd *Cmd) Bool() (bool, error) { if cmd.err != nil { return false, cmd.err } - switch val := cmd.val.(type) { + return toBool(cmd.val) +} + +func toBool(val interface{}) (bool, error) { + switch val := val.(type) { case int64: return val != 0, nil case string: @@ -315,6 +349,120 @@ func (cmd *Cmd) Bool() (bool, error) { } } +func (cmd *Cmd) Slice() ([]interface{}, error) { + if cmd.err != nil { + return nil, cmd.err + } + switch val := cmd.val.(type) { + case []interface{}: + return val, nil + default: + return nil, fmt.Errorf("redis: unexpected type=%T for Slice", val) + } +} + +func (cmd *Cmd) StringSlice() ([]string, error) { + slice, err := cmd.Slice() + if err != nil { + return nil, err + } + + ss := make([]string, len(slice)) + for i, iface := range slice { + val, err := toString(iface) + if err != nil { + return nil, err + } + ss[i] = val + } + return ss, nil +} + +func (cmd *Cmd) Int64Slice() ([]int64, error) { + slice, err := cmd.Slice() + if err != nil { + return nil, err + } + + nums := make([]int64, len(slice)) + for i, iface := range slice { + val, err := toInt64(iface) + if err != nil { + return nil, err + } + nums[i] = val + } + return nums, nil +} + +func (cmd *Cmd) Uint64Slice() ([]uint64, error) { + slice, err := cmd.Slice() + if err != nil { + return nil, err + } + + nums := make([]uint64, len(slice)) + for i, iface := range slice { + val, err := toUint64(iface) + if err != nil { + return nil, err + } + nums[i] = val + } + return nums, nil +} + +func (cmd *Cmd) Float32Slice() ([]float32, error) { + slice, err := cmd.Slice() + if err != nil { + return nil, err + } + + floats := make([]float32, len(slice)) + for i, iface := range slice { + val, err := toFloat32(iface) + if err != nil { + return nil, err + } + floats[i] = val + } + return floats, nil +} + +func (cmd *Cmd) Float64Slice() ([]float64, error) { + slice, err := cmd.Slice() + if err != nil { + return nil, err + } + + floats := make([]float64, len(slice)) + for i, iface := range slice { + val, err := toFloat64(iface) + if err != nil { + return nil, err + } + floats[i] = val + } + return floats, nil +} + +func (cmd *Cmd) BoolSlice() ([]bool, error) { + slice, err := cmd.Slice() + if err != nil { + return nil, err + } + + bools := make([]bool, len(slice)) + for i, iface := range slice { + val, err := toBool(iface) + if err != nil { + return nil, err + } + bools[i] = val + } + return bools, nil +} + func (cmd *Cmd) readReply(rd *proto.Reader) (err error) { cmd.val, err = rd.ReadReply(sliceParser) return err @@ -360,6 +508,10 @@ func NewSliceCmd(ctx context.Context, args ...interface{}) *SliceCmd { } } +func (cmd *SliceCmd) SetVal(val []interface{}) { + cmd.val = val +} + func (cmd *SliceCmd) Val() []interface{} { return cmd.val } @@ -420,6 +572,10 @@ func NewStatusCmd(ctx context.Context, args ...interface{}) *StatusCmd { } } +func (cmd *StatusCmd) SetVal(val string) { + cmd.val = val +} + func (cmd *StatusCmd) Val() string { return cmd.val } @@ -456,6 +612,10 @@ func NewIntCmd(ctx context.Context, args ...interface{}) *IntCmd { } } +func (cmd *IntCmd) SetVal(val int64) { + cmd.val = val +} + func (cmd *IntCmd) Val() int64 { return cmd.val } @@ -496,6 +656,10 @@ func NewIntSliceCmd(ctx context.Context, args ...interface{}) *IntSliceCmd { } } +func (cmd *IntSliceCmd) SetVal(val []int64) { + cmd.val = val +} + func (cmd *IntSliceCmd) Val() []int64 { return cmd.val } @@ -544,6 +708,10 @@ func NewDurationCmd(ctx context.Context, precision time.Duration, args ...interf } } +func (cmd *DurationCmd) SetVal(val time.Duration) { + cmd.val = val +} + func (cmd *DurationCmd) Val() time.Duration { return cmd.val } @@ -591,6 +759,10 @@ func NewTimeCmd(ctx context.Context, args ...interface{}) *TimeCmd { } } +func (cmd *TimeCmd) SetVal(val time.Time) { + cmd.val = val +} + func (cmd *TimeCmd) Val() time.Time { return cmd.val } @@ -644,6 +816,10 @@ func NewBoolCmd(ctx context.Context, args ...interface{}) *BoolCmd { } } +func (cmd *BoolCmd) SetVal(val bool) { + cmd.val = val +} + func (cmd *BoolCmd) Val() bool { return cmd.val } @@ -698,6 +874,10 @@ func NewStringCmd(ctx context.Context, args ...interface{}) *StringCmd { } } +func (cmd *StringCmd) SetVal(val string) { + cmd.val = val +} + func (cmd *StringCmd) Val() string { return cmd.val } @@ -798,6 +978,10 @@ func NewFloatCmd(ctx context.Context, args ...interface{}) *FloatCmd { } } +func (cmd *FloatCmd) SetVal(val float64) { + cmd.val = val +} + func (cmd *FloatCmd) Val() float64 { return cmd.val } @@ -834,6 +1018,10 @@ func NewFloatSliceCmd(ctx context.Context, args ...interface{}) *FloatSliceCmd { } } +func (cmd *FloatSliceCmd) SetVal(val []float64) { + cmd.val = val +} + func (cmd *FloatSliceCmd) Val() []float64 { return cmd.val } @@ -883,6 +1071,10 @@ func NewStringSliceCmd(ctx context.Context, args ...interface{}) *StringSliceCmd } } +func (cmd *StringSliceCmd) SetVal(val []string) { + cmd.val = val +} + func (cmd *StringSliceCmd) Val() []string { return cmd.val } @@ -936,6 +1128,10 @@ func NewBoolSliceCmd(ctx context.Context, args ...interface{}) *BoolSliceCmd { } } +func (cmd *BoolSliceCmd) SetVal(val []bool) { + cmd.val = val +} + func (cmd *BoolSliceCmd) Val() []bool { return cmd.val } @@ -982,6 +1178,10 @@ func NewStringStringMapCmd(ctx context.Context, args ...interface{}) *StringStri } } +func (cmd *StringStringMapCmd) SetVal(val map[string]string) { + cmd.val = val +} + func (cmd *StringStringMapCmd) Val() map[string]string { return cmd.val } @@ -996,12 +1196,12 @@ func (cmd *StringStringMapCmd) String() string { // Scan scans the results from the map into a destination struct. The map keys // are matched in the Redis struct fields by the `redis:"field"` tag. -func (cmd *StringStringMapCmd) Scan(dst interface{}) error { +func (cmd *StringStringMapCmd) Scan(dest interface{}) error { if cmd.err != nil { return cmd.err } - strct, err := hscan.Struct(dst) + strct, err := hscan.Struct(dest) if err != nil { return err } @@ -1055,6 +1255,10 @@ func NewStringIntMapCmd(ctx context.Context, args ...interface{}) *StringIntMapC } } +func (cmd *StringIntMapCmd) SetVal(val map[string]int64) { + cmd.val = val +} + func (cmd *StringIntMapCmd) Val() map[string]int64 { return cmd.val } @@ -1107,6 +1311,10 @@ func NewStringStructMapCmd(ctx context.Context, args ...interface{}) *StringStru } } +func (cmd *StringStructMapCmd) SetVal(val map[string]struct{}) { + cmd.val = val +} + func (cmd *StringStructMapCmd) Val() map[string]struct{} { return cmd.val } @@ -1158,6 +1366,10 @@ func NewXMessageSliceCmd(ctx context.Context, args ...interface{}) *XMessageSlic } } +func (cmd *XMessageSliceCmd) SetVal(val []XMessage) { + cmd.val = val +} + func (cmd *XMessageSliceCmd) Val() []XMessage { return cmd.val } @@ -1267,6 +1479,10 @@ func NewXStreamSliceCmd(ctx context.Context, args ...interface{}) *XStreamSliceC } } +func (cmd *XStreamSliceCmd) SetVal(val []XStream) { + cmd.val = val +} + func (cmd *XStreamSliceCmd) Val() []XStream { return cmd.val } @@ -1339,6 +1555,10 @@ func NewXPendingCmd(ctx context.Context, args ...interface{}) *XPendingCmd { } } +func (cmd *XPendingCmd) SetVal(val *XPending) { + cmd.val = val +} + func (cmd *XPendingCmd) Val() *XPending { return cmd.val } @@ -1441,6 +1661,10 @@ func NewXPendingExtCmd(ctx context.Context, args ...interface{}) *XPendingExtCmd } } +func (cmd *XPendingExtCmd) SetVal(val []XPendingExt) { + cmd.val = val +} + func (cmd *XPendingExtCmd) Val() []XPendingExt { return cmd.val } @@ -1519,6 +1743,11 @@ func NewXAutoClaimCmd(ctx context.Context, args ...interface{}) *XAutoClaimCmd { } } +func (cmd *XAutoClaimCmd) SetVal(val []XMessage, start string) { + cmd.val = val + cmd.start = start +} + func (cmd *XAutoClaimCmd) Val() (messages []XMessage, start string) { return cmd.val, cmd.start } @@ -1573,6 +1802,11 @@ func NewXAutoClaimJustIDCmd(ctx context.Context, args ...interface{}) *XAutoClai } } +func (cmd *XAutoClaimJustIDCmd) SetVal(val []string, start string) { + cmd.val = val + cmd.start = start +} + func (cmd *XAutoClaimJustIDCmd) Val() (ids []string, start string) { return cmd.val, cmd.start } @@ -1639,6 +1873,10 @@ func NewXInfoConsumersCmd(ctx context.Context, stream string, group string) *XIn } } +func (cmd *XInfoConsumersCmd) SetVal(val []XInfoConsumer) { + cmd.val = val +} + func (cmd *XInfoConsumersCmd) Val() []XInfoConsumer { return cmd.val } @@ -1737,6 +1975,10 @@ func NewXInfoGroupsCmd(ctx context.Context, stream string) *XInfoGroupsCmd { } } +func (cmd *XInfoGroupsCmd) SetVal(val []XInfoGroup) { + cmd.val = val +} + func (cmd *XInfoGroupsCmd) Val() []XInfoGroup { return cmd.val } @@ -1840,6 +2082,10 @@ func NewXInfoStreamCmd(ctx context.Context, stream string) *XInfoStreamCmd { } } +func (cmd *XInfoStreamCmd) SetVal(val *XInfoStream) { + cmd.val = val +} + func (cmd *XInfoStreamCmd) Val() *XInfoStream { return cmd.val } @@ -1959,6 +2205,10 @@ func NewXInfoStreamFullCmd(ctx context.Context, args ...interface{}) *XInfoStrea } } +func (cmd *XInfoStreamFullCmd) SetVal(val *XInfoStreamFull) { + cmd.val = val +} + func (cmd *XInfoStreamFullCmd) Val() *XInfoStreamFull { return cmd.val } @@ -2219,6 +2469,10 @@ func NewZSliceCmd(ctx context.Context, args ...interface{}) *ZSliceCmd { } } +func (cmd *ZSliceCmd) SetVal(val []Z) { + cmd.val = val +} + func (cmd *ZSliceCmd) Val() []Z { return cmd.val } @@ -2274,6 +2528,10 @@ func NewZWithKeyCmd(ctx context.Context, args ...interface{}) *ZWithKeyCmd { } } +func (cmd *ZWithKeyCmd) SetVal(val *ZWithKey) { + cmd.val = val +} + func (cmd *ZWithKeyCmd) Val() *ZWithKey { return cmd.val } @@ -2338,6 +2596,11 @@ func NewScanCmd(ctx context.Context, process cmdable, args ...interface{}) *Scan } } +func (cmd *ScanCmd) SetVal(page []string, cursor uint64) { + cmd.page = page + cmd.cursor = cursor +} + func (cmd *ScanCmd) Val() (keys []string, cursor uint64) { return cmd.page, cmd.cursor } @@ -2392,6 +2655,10 @@ func NewClusterSlotsCmd(ctx context.Context, args ...interface{}) *ClusterSlotsC } } +func (cmd *ClusterSlotsCmd) SetVal(val []ClusterSlot) { + cmd.val = val +} + func (cmd *ClusterSlotsCmd) Val() []ClusterSlot { return cmd.val } @@ -2546,6 +2813,10 @@ func geoLocationArgs(q *GeoRadiusQuery, args ...interface{}) []interface{} { return args } +func (cmd *GeoLocationCmd) SetVal(locations []GeoLocation) { + cmd.locations = locations +} + func (cmd *GeoLocationCmd) Val() []GeoLocation { return cmd.locations } @@ -2749,6 +3020,10 @@ func NewGeoSearchLocationCmd( } } +func (cmd *GeoSearchLocationCmd) SetVal(val []GeoLocation) { + cmd.val = val +} + func (cmd *GeoSearchLocationCmd) Val() []GeoLocation { return cmd.val } @@ -2840,6 +3115,10 @@ func NewGeoPosCmd(ctx context.Context, args ...interface{}) *GeoPosCmd { } } +func (cmd *GeoPosCmd) SetVal(val []*GeoPos) { + cmd.val = val +} + func (cmd *GeoPosCmd) Val() []*GeoPos { return cmd.val } @@ -2917,6 +3196,10 @@ func NewCommandsInfoCmd(ctx context.Context, args ...interface{}) *CommandsInfoC } } +func (cmd *CommandsInfoCmd) SetVal(val map[string]*CommandInfo) { + cmd.val = val +} + func (cmd *CommandsInfoCmd) Val() map[string]*CommandInfo { return cmd.val } @@ -3104,6 +3387,10 @@ func NewSlowLogCmd(ctx context.Context, args ...interface{}) *SlowLogCmd { } } +func (cmd *SlowLogCmd) SetVal(val []SlowLog) { + cmd.val = val +} + func (cmd *SlowLogCmd) Val() []SlowLog { return cmd.val } diff --git a/vendor/github.com/go-redis/redis/v8/commands.go b/vendor/github.com/go-redis/redis/v8/commands.go index 80b2bab9..bbfe089d 100644 --- a/vendor/github.com/go-redis/redis/v8/commands.go +++ b/vendor/github.com/go-redis/redis/v8/commands.go @@ -96,6 +96,10 @@ type Cmdable interface { Exists(ctx context.Context, keys ...string) *IntCmd Expire(ctx context.Context, key string, expiration time.Duration) *BoolCmd ExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd + ExpireNX(ctx context.Context, key string, expiration time.Duration) *BoolCmd + ExpireXX(ctx context.Context, key string, expiration time.Duration) *BoolCmd + ExpireGT(ctx context.Context, key string, expiration time.Duration) *BoolCmd + ExpireLT(ctx context.Context, key string, expiration time.Duration) *BoolCmd Keys(ctx context.Context, pattern string) *StringSliceCmd Migrate(ctx context.Context, host, port, key string, db int, timeout time.Duration) *StatusCmd Move(ctx context.Context, key string, db int) *BoolCmd @@ -139,6 +143,7 @@ type Cmdable interface { SetXX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd SetRange(ctx context.Context, key string, offset int64, value string) *IntCmd StrLen(ctx context.Context, key string) *IntCmd + Copy(ctx context.Context, sourceKey string, destKey string, db int, replace bool) *IntCmd GetBit(ctx context.Context, key string, offset int64) *IntCmd SetBit(ctx context.Context, key string, offset int64, value int) *IntCmd @@ -195,6 +200,7 @@ type Cmdable interface { RPush(ctx context.Context, key string, values ...interface{}) *IntCmd RPushX(ctx context.Context, key string, values ...interface{}) *IntCmd LMove(ctx context.Context, source, destination, srcpos, destpos string) *StringCmd + BLMove(ctx context.Context, source, destination, srcpos, destpos string, timeout time.Duration) *StringCmd SAdd(ctx context.Context, key string, members ...interface{}) *IntCmd SCard(ctx context.Context, key string) *IntCmd @@ -430,6 +436,7 @@ func (c statefulCmdable) AuthACL(ctx context.Context, username, password string) func (c cmdable) Wait(ctx context.Context, numSlaves int, timeout time.Duration) *IntCmd { cmd := NewIntCmd(ctx, "wait", numSlaves, int(timeout/time.Millisecond)) + cmd.setReadTimeout(timeout) _ = c(ctx, cmd) return cmd } @@ -524,7 +531,37 @@ func (c cmdable) Exists(ctx context.Context, keys ...string) *IntCmd { } func (c cmdable) Expire(ctx context.Context, key string, expiration time.Duration) *BoolCmd { - cmd := NewBoolCmd(ctx, "expire", key, formatSec(ctx, expiration)) + return c.expire(ctx, key, expiration, "") +} + +func (c cmdable) ExpireNX(ctx context.Context, key string, expiration time.Duration) *BoolCmd { + return c.expire(ctx, key, expiration, "NX") +} + +func (c cmdable) ExpireXX(ctx context.Context, key string, expiration time.Duration) *BoolCmd { + return c.expire(ctx, key, expiration, "XX") +} + +func (c cmdable) ExpireGT(ctx context.Context, key string, expiration time.Duration) *BoolCmd { + return c.expire(ctx, key, expiration, "GT") +} + +func (c cmdable) ExpireLT(ctx context.Context, key string, expiration time.Duration) *BoolCmd { + return c.expire(ctx, key, expiration, "LT") +} + +func (c cmdable) expire( + ctx context.Context, key string, expiration time.Duration, mode string, +) *BoolCmd { + args := make([]interface{}, 3, 4) + args[0] = "expire" + args[1] = key + args[2] = formatSec(ctx, expiration) + if mode != "" { + args = append(args, mode) + } + + cmd := NewBoolCmd(ctx, args...) _ = c(ctx, cmd) return cmd } @@ -989,6 +1026,16 @@ func (c cmdable) StrLen(ctx context.Context, key string) *IntCmd { return cmd } +func (c cmdable) Copy(ctx context.Context, sourceKey, destKey string, db int, replace bool) *IntCmd { + args := []interface{}{"copy", sourceKey, destKey, "DB", db} + if replace { + args = append(args, "REPLACE") + } + cmd := NewIntCmd(ctx, args...) + _ = c(ctx, cmd) + return cmd +} + //------------------------------------------------------------------------------ func (c cmdable) GetBit(ctx context.Context, key string, offset int64) *IntCmd { @@ -1494,6 +1541,15 @@ func (c cmdable) LMove(ctx context.Context, source, destination, srcpos, destpos return cmd } +func (c cmdable) BLMove( + ctx context.Context, source, destination, srcpos, destpos string, timeout time.Duration, +) *StringCmd { + cmd := NewStringCmd(ctx, "blmove", source, destination, srcpos, destpos, formatSec(ctx, timeout)) + cmd.setReadTimeout(timeout) + _ = c(ctx, cmd) + return cmd +} + //------------------------------------------------------------------------------ func (c cmdable) SAdd(ctx context.Context, key string, members ...interface{}) *IntCmd { @@ -1768,7 +1824,7 @@ type XReadArgs struct { } func (c cmdable) XRead(ctx context.Context, a *XReadArgs) *XStreamSliceCmd { - args := make([]interface{}, 0, 5+len(a.Streams)) + args := make([]interface{}, 0, 6+len(a.Streams)) args = append(args, "xread") keyPos := int8(1) @@ -1792,7 +1848,7 @@ func (c cmdable) XRead(ctx context.Context, a *XReadArgs) *XStreamSliceCmd { if a.Block >= 0 { cmd.setReadTimeout(a.Block) } - cmd.setFirstKeyPos(keyPos) + cmd.SetFirstKeyPos(keyPos) _ = c(ctx, cmd) return cmd } @@ -1850,7 +1906,7 @@ type XReadGroupArgs struct { } func (c cmdable) XReadGroup(ctx context.Context, a *XReadGroupArgs) *XStreamSliceCmd { - args := make([]interface{}, 0, 8+len(a.Streams)) + args := make([]interface{}, 0, 10+len(a.Streams)) args = append(args, "xreadgroup", "group", a.Group, a.Consumer) keyPos := int8(4) @@ -1876,7 +1932,7 @@ func (c cmdable) XReadGroup(ctx context.Context, a *XReadGroupArgs) *XStreamSlic if a.Block >= 0 { cmd.setReadTimeout(a.Block) } - cmd.setFirstKeyPos(keyPos) + cmd.SetFirstKeyPos(keyPos) _ = c(ctx, cmd) return cmd } @@ -1947,7 +2003,7 @@ func (c cmdable) XAutoClaimJustID(ctx context.Context, a *XAutoClaimArgs) *XAuto } func xAutoClaimArgs(ctx context.Context, a *XAutoClaimArgs) []interface{} { - args := make([]interface{}, 0, 9) + args := make([]interface{}, 0, 8) args = append(args, "xautoclaim", a.Stream, a.Group, a.Consumer, formatMs(ctx, a.MinIdle), a.Start) if a.Count > 0 { args = append(args, "count", a.Count) @@ -1979,7 +2035,7 @@ func (c cmdable) XClaimJustID(ctx context.Context, a *XClaimArgs) *StringSliceCm } func xClaimArgs(a *XClaimArgs) []interface{} { - args := make([]interface{}, 0, 4+len(a.Messages)) + args := make([]interface{}, 0, 5+len(a.Messages)) args = append(args, "xclaim", a.Stream, @@ -2352,7 +2408,7 @@ func (c cmdable) ZInterStore(ctx context.Context, destination string, store *ZSt args = append(args, "zinterstore", destination, len(store.Keys)) args = store.appendArgs(args) cmd := NewIntCmd(ctx, args...) - cmd.setFirstKeyPos(3) + cmd.SetFirstKeyPos(3) _ = c(ctx, cmd) return cmd } @@ -2362,7 +2418,7 @@ func (c cmdable) ZInter(ctx context.Context, store *ZStore) *StringSliceCmd { args = append(args, "zinter", len(store.Keys)) args = store.appendArgs(args) cmd := NewStringSliceCmd(ctx, args...) - cmd.setFirstKeyPos(2) + cmd.SetFirstKeyPos(2) _ = c(ctx, cmd) return cmd } @@ -2373,7 +2429,7 @@ func (c cmdable) ZInterWithScores(ctx context.Context, store *ZStore) *ZSliceCmd args = store.appendArgs(args) args = append(args, "withscores") cmd := NewZSliceCmd(ctx, args...) - cmd.setFirstKeyPos(2) + cmd.SetFirstKeyPos(2) _ = c(ctx, cmd) return cmd } @@ -2700,7 +2756,7 @@ func (c cmdable) ZUnion(ctx context.Context, store ZStore) *StringSliceCmd { args = append(args, "zunion", len(store.Keys)) args = store.appendArgs(args) cmd := NewStringSliceCmd(ctx, args...) - cmd.setFirstKeyPos(2) + cmd.SetFirstKeyPos(2) _ = c(ctx, cmd) return cmd } @@ -2711,7 +2767,7 @@ func (c cmdable) ZUnionWithScores(ctx context.Context, store ZStore) *ZSliceCmd args = store.appendArgs(args) args = append(args, "withscores") cmd := NewZSliceCmd(ctx, args...) - cmd.setFirstKeyPos(2) + cmd.SetFirstKeyPos(2) _ = c(ctx, cmd) return cmd } @@ -2721,7 +2777,7 @@ func (c cmdable) ZUnionStore(ctx context.Context, dest string, store *ZStore) *I args = append(args, "zunionstore", dest, len(store.Keys)) args = store.appendArgs(args) cmd := NewIntCmd(ctx, args...) - cmd.setFirstKeyPos(3) + cmd.SetFirstKeyPos(3) _ = c(ctx, cmd) return cmd } @@ -2751,7 +2807,7 @@ func (c cmdable) ZDiff(ctx context.Context, keys ...string) *StringSliceCmd { } cmd := NewStringSliceCmd(ctx, args...) - cmd.setFirstKeyPos(2) + cmd.SetFirstKeyPos(2) _ = c(ctx, cmd) return cmd } @@ -2767,7 +2823,7 @@ func (c cmdable) ZDiffWithScores(ctx context.Context, keys ...string) *ZSliceCmd args[len(keys)+2] = "withscores" cmd := NewZSliceCmd(ctx, args...) - cmd.setFirstKeyPos(2) + cmd.SetFirstKeyPos(2) _ = c(ctx, cmd) return cmd } @@ -3043,7 +3099,7 @@ func (c cmdable) MemoryUsage(ctx context.Context, key string, samples ...int) *I args = append(args, "SAMPLES", samples[0]) } cmd := NewIntCmd(ctx, args...) - cmd.setFirstKeyPos(2) + cmd.SetFirstKeyPos(2) _ = c(ctx, cmd) return cmd } @@ -3060,7 +3116,7 @@ func (c cmdable) Eval(ctx context.Context, script string, keys []string, args .. } cmdArgs = appendArgs(cmdArgs, args) cmd := NewCmd(ctx, cmdArgs...) - cmd.setFirstKeyPos(3) + cmd.SetFirstKeyPos(3) _ = c(ctx, cmd) return cmd } @@ -3075,7 +3131,7 @@ func (c cmdable) EvalSha(ctx context.Context, sha1 string, keys []string, args . } cmdArgs = appendArgs(cmdArgs, args) cmd := NewCmd(ctx, cmdArgs...) - cmd.setFirstKeyPos(3) + cmd.SetFirstKeyPos(3) _ = c(ctx, cmd) return cmd } diff --git a/vendor/github.com/go-redis/redis/v8/error.go b/vendor/github.com/go-redis/redis/v8/error.go index ad9e173e..521594bb 100644 --- a/vendor/github.com/go-redis/redis/v8/error.go +++ b/vendor/github.com/go-redis/redis/v8/error.go @@ -65,7 +65,7 @@ func isRedisError(err error) bool { return ok } -func isBadConn(err error, allowTimeout bool) bool { +func isBadConn(err error, allowTimeout bool, addr string) bool { switch err { case nil: return false @@ -74,9 +74,19 @@ func isBadConn(err error, allowTimeout bool) bool { } if isRedisError(err) { - // Close connections in read only state in case domain addr is used - // and domain resolves to a different Redis Server. See #790. - return isReadOnlyError(err) + switch { + case isReadOnlyError(err): + // Close connections in read only state in case domain addr is used + // and domain resolves to a different Redis Server. See #790. + return true + case isMovedSameConnAddr(err, addr): + // Close connections when we are asked to move to the same addr + // of the connection. Force a DNS resolution when all connections + // of the pool are recycled + return true + default: + return false + } } if allowTimeout { @@ -119,6 +129,14 @@ func isReadOnlyError(err error) bool { return strings.HasPrefix(err.Error(), "READONLY ") } +func isMovedSameConnAddr(err error, addr string) bool { + redisError := err.Error() + if !strings.HasPrefix(redisError, "MOVED ") { + return false + } + return strings.HasSuffix(redisError, " "+addr) +} + //------------------------------------------------------------------------------ type timeoutError interface { diff --git a/vendor/github.com/go-redis/redis/v8/internal/hscan/structmap.go b/vendor/github.com/go-redis/redis/v8/internal/hscan/structmap.go index 1b233258..6839412b 100644 --- a/vendor/github.com/go-redis/redis/v8/internal/hscan/structmap.go +++ b/vendor/github.com/go-redis/redis/v8/internal/hscan/structmap.go @@ -39,12 +39,12 @@ func (s *structSpec) set(tag string, sf *structField) { } func newStructSpec(t reflect.Type, fieldTag string) *structSpec { + numField := t.NumField() out := &structSpec{ - m: make(map[string]*structField), + m: make(map[string]*structField, numField), } - num := t.NumField() - for i := 0; i < num; i++ { + for i := 0; i < numField; i++ { f := t.Field(i) tag := f.Tag.Get(fieldTag) diff --git a/vendor/github.com/go-redis/redis/v8/internal/pool/pool.go b/vendor/github.com/go-redis/redis/v8/internal/pool/pool.go index 91b55e46..44a4e779 100644 --- a/vendor/github.com/go-redis/redis/v8/internal/pool/pool.go +++ b/vendor/github.com/go-redis/redis/v8/internal/pool/pool.go @@ -121,9 +121,10 @@ func (p *ConnPool) checkMinIdleConns() { for p.poolSize < p.opt.PoolSize && p.idleConnsLen < p.opt.MinIdleConns { p.poolSize++ p.idleConnsLen++ + go func() { err := p.addIdleConn() - if err != nil { + if err != nil && err != ErrClosed { p.connsMu.Lock() p.poolSize-- p.idleConnsLen-- @@ -140,9 +141,16 @@ func (p *ConnPool) addIdleConn() error { } p.connsMu.Lock() + defer p.connsMu.Unlock() + + // It is not allowed to add new connections to the closed connection pool. + if p.closed() { + _ = cn.Close() + return ErrClosed + } + p.conns = append(p.conns, cn) p.idleConns = append(p.idleConns, cn) - p.connsMu.Unlock() return nil } @@ -157,6 +165,14 @@ func (p *ConnPool) newConn(ctx context.Context, pooled bool) (*Conn, error) { } p.connsMu.Lock() + defer p.connsMu.Unlock() + + // It is not allowed to add new connections to the closed connection pool. + if p.closed() { + _ = cn.Close() + return nil, ErrClosed + } + p.conns = append(p.conns, cn) if pooled { // If pool is full remove the cn on next Put. @@ -166,7 +182,6 @@ func (p *ConnPool) newConn(ctx context.Context, pooled bool) (*Conn, error) { p.poolSize++ } } - p.connsMu.Unlock() return cn, nil } @@ -237,9 +252,13 @@ func (p *ConnPool) Get(ctx context.Context) (*Conn, error) { for { p.connsMu.Lock() - cn := p.popIdle() + cn, err := p.popIdle() p.connsMu.Unlock() + if err != nil { + return nil, err + } + if cn == nil { break } @@ -308,10 +327,13 @@ func (p *ConnPool) freeTurn() { <-p.queue } -func (p *ConnPool) popIdle() *Conn { +func (p *ConnPool) popIdle() (*Conn, error) { + if p.closed() { + return nil, ErrClosed + } n := len(p.idleConns) if n == 0 { - return nil + return nil, nil } var cn *Conn @@ -326,7 +348,7 @@ func (p *ConnPool) popIdle() *Conn { } p.idleConnsLen-- p.checkMinIdleConns() - return cn + return cn, nil } func (p *ConnPool) Put(ctx context.Context, cn *Conn) { diff --git a/vendor/github.com/go-redis/redis/v8/internal/proto/reader.go b/vendor/github.com/go-redis/redis/v8/internal/proto/reader.go index 10d1b423..0e6ca779 100644 --- a/vendor/github.com/go-redis/redis/v8/internal/proto/reader.go +++ b/vendor/github.com/go-redis/redis/v8/internal/proto/reader.go @@ -19,7 +19,7 @@ const ( //------------------------------------------------------------------------------ -const Nil = RedisError("redis: nil") +const Nil = RedisError("redis: nil") // nolint:errname type RedisError string diff --git a/vendor/github.com/go-redis/redis/v8/internal/proto/scan.go b/vendor/github.com/go-redis/redis/v8/internal/proto/scan.go index 7d7183c3..0e994765 100644 --- a/vendor/github.com/go-redis/redis/v8/internal/proto/scan.go +++ b/vendor/github.com/go-redis/redis/v8/internal/proto/scan.go @@ -10,6 +10,7 @@ import ( ) // Scan parses bytes `b` to `v` with appropriate type. +//nolint:gocyclo func Scan(b []byte, v interface{}) error { switch v := v.(type) { case nil: @@ -105,6 +106,13 @@ func Scan(b []byte, v interface{}) error { var err error *v, err = time.Parse(time.RFC3339Nano, util.BytesToString(b)) return err + case *time.Duration: + n, err := util.ParseInt(b, 10, 64) + if err != nil { + return err + } + *v = time.Duration(n) + return nil case encoding.BinaryUnmarshaler: return v.UnmarshalBinary(b) default: diff --git a/vendor/github.com/go-redis/redis/v8/internal/proto/writer.go b/vendor/github.com/go-redis/redis/v8/internal/proto/writer.go index 81b09b8e..c4260981 100644 --- a/vendor/github.com/go-redis/redis/v8/internal/proto/writer.go +++ b/vendor/github.com/go-redis/redis/v8/internal/proto/writer.go @@ -98,6 +98,8 @@ func (w *Writer) WriteArg(v interface{}) error { case time.Time: w.numBuf = v.AppendFormat(w.numBuf[:0], time.RFC3339Nano) return w.bytes(w.numBuf) + case time.Duration: + return w.int(v.Nanoseconds()) case encoding.BinaryMarshaler: b, err := v.MarshalBinary() if err != nil { diff --git a/vendor/github.com/go-redis/redis/v8/internal/safe.go b/vendor/github.com/go-redis/redis/v8/internal/safe.go index 862ff0eb..fd2f4340 100644 --- a/vendor/github.com/go-redis/redis/v8/internal/safe.go +++ b/vendor/github.com/go-redis/redis/v8/internal/safe.go @@ -1,3 +1,4 @@ +//go:build appengine // +build appengine package internal diff --git a/vendor/github.com/go-redis/redis/v8/internal/unsafe.go b/vendor/github.com/go-redis/redis/v8/internal/unsafe.go index 4bc79701..9f2e418f 100644 --- a/vendor/github.com/go-redis/redis/v8/internal/unsafe.go +++ b/vendor/github.com/go-redis/redis/v8/internal/unsafe.go @@ -1,3 +1,4 @@ +//go:build !appengine // +build !appengine package internal diff --git a/vendor/github.com/go-redis/redis/v8/internal/util/safe.go b/vendor/github.com/go-redis/redis/v8/internal/util/safe.go index 1b3060eb..21307110 100644 --- a/vendor/github.com/go-redis/redis/v8/internal/util/safe.go +++ b/vendor/github.com/go-redis/redis/v8/internal/util/safe.go @@ -1,3 +1,4 @@ +//go:build appengine // +build appengine package util diff --git a/vendor/github.com/go-redis/redis/v8/internal/util/unsafe.go b/vendor/github.com/go-redis/redis/v8/internal/util/unsafe.go index c9868aac..daa8d769 100644 --- a/vendor/github.com/go-redis/redis/v8/internal/util/unsafe.go +++ b/vendor/github.com/go-redis/redis/v8/internal/util/unsafe.go @@ -1,3 +1,4 @@ +//go:build !appengine // +build !appengine package util diff --git a/vendor/github.com/go-redis/redis/v8/options.go b/vendor/github.com/go-redis/redis/v8/options.go index 5d39bf04..a4abe32c 100644 --- a/vendor/github.com/go-redis/redis/v8/options.go +++ b/vendor/github.com/go-redis/redis/v8/options.go @@ -8,6 +8,7 @@ import ( "net" "net/url" "runtime" + "sort" "strconv" "strings" "time" @@ -192,9 +193,32 @@ func (opt *Options) clone() *Options { // Scheme is required. // There are two connection types: by tcp socket and by unix socket. // Tcp connection: -// redis://:@:/ +// redis://:@:/ // Unix connection: // unix://:@?db= +// Most Option fields can be set using query parameters, with the following restrictions: +// - field names are mapped using snake-case conversion: to set MaxRetries, use max_retries +// - only scalar type fields are supported (bool, int, time.Duration) +// - for time.Duration fields, values must be a valid input for time.ParseDuration(); +// additionally a plain integer as value (i.e. without unit) is intepreted as seconds +// - to disable a duration field, use value less than or equal to 0; to use the default +// value, leave the value blank or remove the parameter +// - only the last value is interpreted if a parameter is given multiple times +// - fields "network", "addr", "username" and "password" can only be set using other +// URL attributes (scheme, host, userinfo, resp.), query paremeters using these +// names will be treated as unknown parameters +// - unknown parameter names will result in an error +// Examples: +// redis://user:password@localhost:6789/3?dial_timeout=3&db=1&read_timeout=6s&max_retries=2 +// is equivalent to: +// &Options{ +// Network: "tcp", +// Addr: "localhost:6789", +// DB: 1, // path "/3" was overridden by "&db=1" +// DialTimeout: 3 * time.Second, // no time unit = seconds +// ReadTimeout: 6 * time.Second, +// MaxRetries: 2, +// } func ParseURL(redisURL string) (*Options, error) { u, err := url.Parse(redisURL) if err != nil { @@ -216,10 +240,6 @@ func setupTCPConn(u *url.URL) (*Options, error) { o.Username, o.Password = getUserPassword(u) - if len(u.Query()) > 0 { - return nil, errors.New("redis: no options supported") - } - h, p, err := net.SplitHostPort(u.Host) if err != nil { h = u.Host @@ -250,7 +270,7 @@ func setupTCPConn(u *url.URL) (*Options, error) { o.TLSConfig = &tls.Config{ServerName: h} } - return o, nil + return setupConnParams(u, o) } func setupUnixConn(u *url.URL) (*Options, error) { @@ -262,19 +282,122 @@ func setupUnixConn(u *url.URL) (*Options, error) { return nil, errors.New("redis: empty unix socket path") } o.Addr = u.Path - o.Username, o.Password = getUserPassword(u) + return setupConnParams(u, o) +} - dbStr := u.Query().Get("db") - if dbStr == "" { - return o, nil // if database is not set, connect to 0 db. +type queryOptions struct { + q url.Values + err error +} + +func (o *queryOptions) string(name string) string { + vs := o.q[name] + if len(vs) == 0 { + return "" } + delete(o.q, name) // enable detection of unknown parameters + return vs[len(vs)-1] +} - db, err := strconv.Atoi(dbStr) - if err != nil { - return nil, fmt.Errorf("redis: invalid database number: %w", err) +func (o *queryOptions) int(name string) int { + s := o.string(name) + if s == "" { + return 0 + } + i, err := strconv.Atoi(s) + if err == nil { + return i + } + if o.err == nil { + o.err = fmt.Errorf("redis: invalid %s number: %s", name, err) + } + return 0 +} + +func (o *queryOptions) duration(name string) time.Duration { + s := o.string(name) + if s == "" { + return 0 + } + // try plain number first + if i, err := strconv.Atoi(s); err == nil { + if i <= 0 { + // disable timeouts + return -1 + } + return time.Duration(i) * time.Second + } + dur, err := time.ParseDuration(s) + if err == nil { + return dur + } + if o.err == nil { + o.err = fmt.Errorf("redis: invalid %s duration: %w", name, err) + } + return 0 +} + +func (o *queryOptions) bool(name string) bool { + switch s := o.string(name); s { + case "true", "1": + return true + case "false", "0", "": + return false + default: + if o.err == nil { + o.err = fmt.Errorf("redis: invalid %s boolean: expected true/false/1/0 or an empty string, got %q", name, s) + } + return false + } +} + +func (o *queryOptions) remaining() []string { + if len(o.q) == 0 { + return nil + } + keys := make([]string, 0, len(o.q)) + for k := range o.q { + keys = append(keys, k) + } + sort.Strings(keys) + return keys +} + +// setupConnParams converts query parameters in u to option value in o. +func setupConnParams(u *url.URL, o *Options) (*Options, error) { + q := queryOptions{q: u.Query()} + + // compat: a future major release may use q.int("db") + if tmp := q.string("db"); tmp != "" { + db, err := strconv.Atoi(tmp) + if err != nil { + return nil, fmt.Errorf("redis: invalid database number: %w", err) + } + o.DB = db + } + + o.MaxRetries = q.int("max_retries") + o.MinRetryBackoff = q.duration("min_retry_backoff") + o.MaxRetryBackoff = q.duration("max_retry_backoff") + o.DialTimeout = q.duration("dial_timeout") + o.ReadTimeout = q.duration("read_timeout") + o.WriteTimeout = q.duration("write_timeout") + o.PoolFIFO = q.bool("pool_fifo") + o.PoolSize = q.int("pool_size") + o.MinIdleConns = q.int("min_idle_conns") + o.MaxConnAge = q.duration("max_conn_age") + o.PoolTimeout = q.duration("pool_timeout") + o.IdleTimeout = q.duration("idle_timeout") + o.IdleCheckFrequency = q.duration("idle_check_frequency") + if q.err != nil { + return nil, q.err + } + + // any parameters left? + if r := q.remaining(); len(r) > 0 { + return nil, fmt.Errorf("redis: unexpected option: %s", strings.Join(r, ", ")) } - o.DB = db return o, nil } diff --git a/vendor/github.com/go-redis/redis/v8/package.json b/vendor/github.com/go-redis/redis/v8/package.json new file mode 100644 index 00000000..e4ea4bb0 --- /dev/null +++ b/vendor/github.com/go-redis/redis/v8/package.json @@ -0,0 +1,8 @@ +{ + "name": "redis", + "version": "8.11.5", + "main": "index.js", + "repository": "git@github.com:go-redis/redis.git", + "author": "Vladimir Mihailenco ", + "license": "BSD-2-clause" +} diff --git a/vendor/github.com/go-redis/redis/v8/pipeline.go b/vendor/github.com/go-redis/redis/v8/pipeline.go index c6ec3409..31bab971 100644 --- a/vendor/github.com/go-redis/redis/v8/pipeline.go +++ b/vendor/github.com/go-redis/redis/v8/pipeline.go @@ -24,6 +24,7 @@ type pipelineExecer func(context.Context, []Cmder) error // depends of your batch size and/or use TxPipeline. type Pipeliner interface { StatefulCmdable + Len() int Do(ctx context.Context, args ...interface{}) *Cmd Process(ctx context.Context, cmd Cmder) error Close() error @@ -53,6 +54,15 @@ func (c *Pipeline) init() { c.statefulCmdable = c.Process } +// Len returns the number of queued commands. +func (c *Pipeline) Len() int { + c.mu.Lock() + ln := len(c.cmds) + c.mu.Unlock() + return ln +} + +// Do queues the custom command for later execution. func (c *Pipeline) Do(ctx context.Context, args ...interface{}) *Cmd { cmd := NewCmd(ctx, args...) _ = c.Process(ctx, cmd) diff --git a/vendor/github.com/go-redis/redis/v8/pubsub.go b/vendor/github.com/go-redis/redis/v8/pubsub.go index c6ffb256..efc2354a 100644 --- a/vendor/github.com/go-redis/redis/v8/pubsub.go +++ b/vendor/github.com/go-redis/redis/v8/pubsub.go @@ -141,7 +141,7 @@ func (c *PubSub) releaseConn(ctx context.Context, cn *pool.Conn, err error, allo if c.cn != cn { return } - if isBadConn(err, allowTimeout) { + if isBadConn(err, allowTimeout, c.opt.Addr) { c.reconnect(ctx, err) } } @@ -252,13 +252,16 @@ func (c *PubSub) Ping(ctx context.Context, payload ...string) error { } cmd := NewCmd(ctx, args...) - cn, err := c.connWithLock(ctx) + c.mu.Lock() + defer c.mu.Unlock() + + cn, err := c.conn(ctx, nil) if err != nil { return err } err = c.writeCmd(ctx, cn, cmd) - c.releaseConnWithLock(ctx, cn, err, false) + c.releaseConn(ctx, cn, err, false) return err } @@ -361,6 +364,8 @@ func (c *PubSub) ReceiveTimeout(ctx context.Context, timeout time.Duration) (int c.cmd = NewCmd(ctx) } + // Don't hold the lock to allow subscriptions and pings. + cn, err := c.connWithLock(ctx) if err != nil { return nil, err @@ -371,6 +376,7 @@ func (c *PubSub) ReceiveTimeout(ctx context.Context, timeout time.Duration) (int }) c.releaseConnWithLock(ctx, cn, err, timeout > 0) + if err != nil { return nil, err } diff --git a/vendor/github.com/go-redis/redis/v8/redis.go b/vendor/github.com/go-redis/redis/v8/redis.go index 98d60349..bcf8a2a9 100644 --- a/vendor/github.com/go-redis/redis/v8/redis.go +++ b/vendor/github.com/go-redis/redis/v8/redis.go @@ -51,9 +51,7 @@ func (hs hooks) process( ctx context.Context, cmd Cmder, fn func(context.Context, Cmder) error, ) error { if len(hs.hooks) == 0 { - err := hs.withContext(ctx, func() error { - return fn(ctx, cmd) - }) + err := fn(ctx, cmd) cmd.SetErr(err) return err } @@ -69,9 +67,7 @@ func (hs hooks) process( } if retErr == nil { - retErr = hs.withContext(ctx, func() error { - return fn(ctx, cmd) - }) + retErr = fn(ctx, cmd) cmd.SetErr(retErr) } @@ -89,9 +85,7 @@ func (hs hooks) processPipeline( ctx context.Context, cmds []Cmder, fn func(context.Context, []Cmder) error, ) error { if len(hs.hooks) == 0 { - err := hs.withContext(ctx, func() error { - return fn(ctx, cmds) - }) + err := fn(ctx, cmds) return err } @@ -106,9 +100,7 @@ func (hs hooks) processPipeline( } if retErr == nil { - retErr = hs.withContext(ctx, func() error { - return fn(ctx, cmds) - }) + retErr = fn(ctx, cmds) } for hookIndex--; hookIndex >= 0; hookIndex-- { @@ -128,10 +120,6 @@ func (hs hooks) processTxPipeline( return hs.processPipeline(ctx, cmds, fn) } -func (hs hooks) withContext(ctx context.Context, fn func() error) error { - return fn() -} - //------------------------------------------------------------------------------ type baseClient struct { @@ -273,7 +261,7 @@ func (c *baseClient) releaseConn(ctx context.Context, cn *pool.Conn, err error) c.opt.Limiter.ReportResult(err) } - if isBadConn(err, false) { + if isBadConn(err, false, c.opt.Addr) { c.connPool.Remove(ctx, cn, err) } else { c.connPool.Put(ctx, cn) @@ -722,7 +710,9 @@ type conn struct { hooks // TODO: inherit hooks } -// Conn is like Client, but its pool contains single connection. +// Conn represents a single Redis connection rather than a pool of connections. +// Prefer running commands from Client unless there is a specific need +// for a continuous single Redis connection. type Conn struct { *conn ctx context.Context diff --git a/vendor/github.com/go-redis/redis/v8/ring.go b/vendor/github.com/go-redis/redis/v8/ring.go index 5e35b6bb..4df00fc8 100644 --- a/vendor/github.com/go-redis/redis/v8/ring.go +++ b/vendor/github.com/go-redis/redis/v8/ring.go @@ -12,7 +12,8 @@ import ( "time" "github.com/cespare/xxhash/v2" - "github.com/dgryski/go-rendezvous" + rendezvous "github.com/dgryski/go-rendezvous" //nolint + "github.com/go-redis/redis/v8/internal" "github.com/go-redis/redis/v8/internal/hashtag" "github.com/go-redis/redis/v8/internal/pool" @@ -575,7 +576,7 @@ func (c *Ring) cmdInfo(ctx context.Context, name string) *CommandInfo { } info := cmdsInfo[name] if info == nil { - internal.Logger.Printf(c.Context(), "info for cmd=%s not found", name) + internal.Logger.Printf(ctx, "info for cmd=%s not found", name) } return info } diff --git a/vendor/github.com/go-redis/redis/v8/sentinel.go b/vendor/github.com/go-redis/redis/v8/sentinel.go index 7b53fd4f..ec6221dc 100644 --- a/vendor/github.com/go-redis/redis/v8/sentinel.go +++ b/vendor/github.com/go-redis/redis/v8/sentinel.go @@ -23,7 +23,13 @@ type FailoverOptions struct { MasterName string // A seed list of host:port addresses of sentinel nodes. SentinelAddrs []string - // Sentinel password from "requirepass " (if enabled) in Sentinel configuration + + // If specified with SentinelPassword, enables ACL-based authentication (via + // AUTH ). + SentinelUsername string + // Sentinel password from "requirepass " (if enabled) in Sentinel + // configuration, or, if SentinelUsername is also supplied, used for ACL-based + // authentication. SentinelPassword string // Allows routing read-only commands to the closest master or slave node. @@ -109,6 +115,7 @@ func (opt *FailoverOptions) sentinelOptions(addr string) *Options { OnConnect: opt.OnConnect, DB: 0, + Username: opt.SentinelUsername, Password: opt.SentinelPassword, MaxRetries: opt.MaxRetries, diff --git a/vendor/github.com/go-redis/redis/v8/tx.go b/vendor/github.com/go-redis/redis/v8/tx.go index 08d381a9..8c9d8720 100644 --- a/vendor/github.com/go-redis/redis/v8/tx.go +++ b/vendor/github.com/go-redis/redis/v8/tx.go @@ -13,7 +13,8 @@ const TxFailedErr = proto.RedisError("redis: transaction failed") // Tx implements Redis transactions as described in // http://redis.io/topics/transactions. It's NOT safe for concurrent use // by multiple goroutines, because Exec resets list of watched keys. -// If you don't need WATCH it is better to use Pipeline. +// +// If you don't need WATCH, use Pipeline instead. type Tx struct { baseClient cmdable diff --git a/vendor/github.com/go-redis/redis/v8/universal.go b/vendor/github.com/go-redis/redis/v8/universal.go index 1e962ab3..c89b3e5d 100644 --- a/vendor/github.com/go-redis/redis/v8/universal.go +++ b/vendor/github.com/go-redis/redis/v8/universal.go @@ -25,6 +25,7 @@ type UniversalOptions struct { Username string Password string + SentinelUsername string SentinelPassword string MaxRetries int @@ -114,6 +115,7 @@ func (o *UniversalOptions) Failover() *FailoverOptions { DB: o.DB, Username: o.Username, Password: o.Password, + SentinelUsername: o.SentinelUsername, SentinelPassword: o.SentinelPassword, MaxRetries: o.MaxRetries, diff --git a/vendor/github.com/go-redis/redis/v8/version.go b/vendor/github.com/go-redis/redis/v8/version.go index 80601587..112c9a2d 100644 --- a/vendor/github.com/go-redis/redis/v8/version.go +++ b/vendor/github.com/go-redis/redis/v8/version.go @@ -2,5 +2,5 @@ package redis // Version is the current release version. func Version() string { - return "8.11.3" + return "8.11.5" } diff --git a/vendor/github.com/onsi/gomega/.travis.yml b/vendor/github.com/onsi/gomega/.travis.yml deleted file mode 100644 index 6543dc55..00000000 --- a/vendor/github.com/onsi/gomega/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: go -arch: - - amd64 - - ppc64le - -go: - - gotip - - 1.16.x - - 1.15.x - -env: - - GO111MODULE=on - -install: skip - -script: - - go mod tidy && git diff --exit-code go.mod go.sum - - make test diff --git a/vendor/github.com/onsi/gomega/CHANGELOG.md b/vendor/github.com/onsi/gomega/CHANGELOG.md index 3486f358..e3b43798 100644 --- a/vendor/github.com/onsi/gomega/CHANGELOG.md +++ b/vendor/github.com/onsi/gomega/CHANGELOG.md @@ -1,3 +1,45 @@ +## 1.18.1 + +## Fixes +- Add pointer support to HaveField matcher (#495) [79e41a3] + +## 1.18.0 + +## Features +- Docs now live on the master branch in the docs folder which will make for easier PRs. The docs also use Ginkgo 2.0's new docs html/css/js. [2570272] +- New HaveValue matcher can handle actuals that are either values (in which case they are passed on unscathed) or pointers (in which case they are indirected). [Docs here.](https://onsi.github.io/gomega/#working-with-values) (#485) [bdc087c] +- Gmeasure has been declared GA [360db9d] + +## Fixes +- Gomega now uses ioutil for Go 1.15 and lower (#492) - official support is only for the most recent two major versions of Go but this will unblock users who need to stay on older unsupported versions of Go. [c29c1c0] + +## Maintenace +- Remove Travis workflow (#491) [72e6040] +- Upgrade to Ginkgo 2.0.0 GA [f383637] +- chore: fix description of HaveField matcher (#487) [2b4b2c0] +- use tools.go to ensure Ginkgo cli dependencies are included [f58a52b] +- remove dockerfile and simplify github actions to match ginkgo's actions [3f8160d] + +## 1.17.0 + +### Features +- Add HaveField matcher [3a26311] +- add Error() assertions on the final error value of multi-return values (#480) [2f96943] +- separate out offsets and timeouts (#478) [18a4723] +- fix transformation error reporting (#479) [e001fab] +- allow transform functions to report errors (#472) [bf93408] + +### Fixes +Stop using deprecated ioutil package (#467) [07f405d] + +## 1.16.0 + +### Features +- feat: HaveHTTPStatus multiple expected values (#465) [aa69f1b] +- feat: HaveHTTPHeaderWithValue() matcher (#463) [dd83a96] +- feat: HaveHTTPBody matcher (#462) [504e1f2] +- feat: formatter for HTTP responses (#461) [e5b3157] + ## 1.15.0 ### Fixes diff --git a/vendor/github.com/onsi/gomega/Dockerfile b/vendor/github.com/onsi/gomega/Dockerfile deleted file mode 100644 index 11c7e63e..00000000 --- a/vendor/github.com/onsi/gomega/Dockerfile +++ /dev/null @@ -1 +0,0 @@ -FROM golang:1.15 diff --git a/vendor/github.com/onsi/gomega/Makefile b/vendor/github.com/onsi/gomega/Makefile deleted file mode 100644 index 1c6d107e..00000000 --- a/vendor/github.com/onsi/gomega/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -###### Help ################################################################### - -.DEFAULT_GOAL = help - -.PHONY: help - -help: ## list Makefile targets - @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' - -###### Targets ################################################################ - -test: version download fmt vet ginkgo ## Runs all build, static analysis, and test steps - -download: ## Download dependencies - go mod download - -vet: ## Run static code analysis - go vet ./... - -ginkgo: ## Run tests using Ginkgo - go run github.com/onsi/ginkgo/ginkgo -p -r --randomizeAllSpecs --failOnPending --randomizeSuites --race - -fmt: ## Checks that the code is formatted correcty - @@if [ -n "$$(gofmt -s -e -l -d .)" ]; then \ - echo "gofmt check failed: run 'gofmt -s -e -l -w .'"; \ - exit 1; \ - fi - -docker_test: ## Run tests in a container via docker-compose - docker-compose build test && docker-compose run --rm test make test - -version: ## Display the version of Go - @@go version diff --git a/vendor/github.com/onsi/gomega/docker-compose.yaml b/vendor/github.com/onsi/gomega/docker-compose.yaml deleted file mode 100644 index f3749614..00000000 --- a/vendor/github.com/onsi/gomega/docker-compose.yaml +++ /dev/null @@ -1,10 +0,0 @@ -version: '3.0' - -services: - test: - build: - dockerfile: Dockerfile - context: . - working_dir: /app - volumes: - - ${PWD}:/app diff --git a/vendor/github.com/onsi/gomega/gomega_dsl.go b/vendor/github.com/onsi/gomega/gomega_dsl.go index 6c7f1d9b..6936e241 100644 --- a/vendor/github.com/onsi/gomega/gomega_dsl.go +++ b/vendor/github.com/onsi/gomega/gomega_dsl.go @@ -22,7 +22,7 @@ import ( "github.com/onsi/gomega/types" ) -const GOMEGA_VERSION = "1.15.0" +const GOMEGA_VERSION = "1.18.1" const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler. If you're using Ginkgo then you probably forgot to put your assertion in an It(). @@ -204,7 +204,8 @@ func Expect(actual interface{}, extra ...interface{}) Assertion { // ExpectWithOffset(1, "foo").To(Equal("foo")) // // Unlike `Expect` and `Ω`, `ExpectWithOffset` takes an additional integer argument -// that is used to modify the call-stack offset when computing line numbers. +// that is used to modify the call-stack offset when computing line numbers. It is +// the same as `Expect(...).WithOffset`. // // This is most useful in helper functions that make assertions. If you want Gomega's // error message to refer to the calling line in the test (as opposed to the line in the helper function) @@ -300,6 +301,9 @@ For example: }).Should(Succeed()) will rerun the function until all assertions pass. + +`Eventually` specifying a timeout interval (and an optional polling interval) are +the same as `Eventually(...).WithTimeout` or `Eventually(...).WithTimeout(...).WithPolling`. */ func Eventually(actual interface{}, intervals ...interface{}) AsyncAssertion { ensureDefaultGomegaIsConfigured() @@ -309,6 +313,12 @@ func Eventually(actual interface{}, intervals ...interface{}) AsyncAssertion { // EventuallyWithOffset operates like Eventually but takes an additional // initial argument to indicate an offset in the call stack. This is useful when building helper // functions that contain matchers. To learn more, read about `ExpectWithOffset`. +// +// `EventuallyWithOffset` is the same as `Eventually(...).WithOffset`. +// +// `EventuallyWithOffset` specifying a timeout interval (and an optional polling interval) are +// the same as `Eventually(...).WithOffset(...).WithTimeout` or +// `Eventually(...).WithOffset(...).WithTimeout(...).WithPolling`. func EventuallyWithOffset(offset int, actual interface{}, intervals ...interface{}) AsyncAssertion { ensureDefaultGomegaIsConfigured() return Default.EventuallyWithOffset(offset, actual, intervals...) @@ -337,6 +347,9 @@ func Consistently(actual interface{}, intervals ...interface{}) AsyncAssertion { // ConsistentlyWithOffset operates like Consistently but takes an additional // initial argument to indicate an offset in the call stack. This is useful when building helper // functions that contain matchers. To learn more, read about `ExpectWithOffset`. +// +// `ConsistentlyWithOffset` is the same as `Consistently(...).WithOffset` and +// optional `WithTimeout` and `WithPolling`. func ConsistentlyWithOffset(offset int, actual interface{}, intervals ...interface{}) AsyncAssertion { ensureDefaultGomegaIsConfigured() return Default.ConsistentlyWithOffset(offset, actual, intervals...) diff --git a/vendor/github.com/onsi/gomega/internal/assertion.go b/vendor/github.com/onsi/gomega/internal/assertion.go index 36b0e834..b3c26889 100644 --- a/vendor/github.com/onsi/gomega/internal/assertion.go +++ b/vendor/github.com/onsi/gomega/internal/assertion.go @@ -8,44 +8,64 @@ import ( ) type Assertion struct { - actualInput interface{} + actuals []interface{} // actual value plus all extra values + actualIndex int // value to pass to the matcher + vet vetinari // the vet to call before calling Gomega matcher offset int - extra []interface{} g *Gomega } +// ...obligatory discworld reference, as "vetineer" doesn't sound ... quite right. +type vetinari func(assertion *Assertion, optionalDescription ...interface{}) bool + func NewAssertion(actualInput interface{}, g *Gomega, offset int, extra ...interface{}) *Assertion { return &Assertion{ - actualInput: actualInput, + actuals: append([]interface{}{actualInput}, extra...), + actualIndex: 0, + vet: (*Assertion).vetActuals, offset: offset, - extra: extra, g: g, } } +func (assertion *Assertion) WithOffset(offset int) types.Assertion { + assertion.offset = offset + return assertion +} + +func (assertion *Assertion) Error() types.Assertion { + return &Assertion{ + actuals: assertion.actuals, + actualIndex: len(assertion.actuals) - 1, + vet: (*Assertion).vetError, + offset: assertion.offset, + g: assertion.g, + } +} + func (assertion *Assertion) Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool { assertion.g.THelper() - return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, true, optionalDescription...) + return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, true, optionalDescription...) } func (assertion *Assertion) ShouldNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool { assertion.g.THelper() - return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, false, optionalDescription...) + return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, false, optionalDescription...) } func (assertion *Assertion) To(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool { assertion.g.THelper() - return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, true, optionalDescription...) + return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, true, optionalDescription...) } func (assertion *Assertion) ToNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool { assertion.g.THelper() - return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, false, optionalDescription...) + return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, false, optionalDescription...) } func (assertion *Assertion) NotTo(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool { assertion.g.THelper() - return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, false, optionalDescription...) + return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, false, optionalDescription...) } func (assertion *Assertion) buildDescription(optionalDescription ...interface{}) string { @@ -61,7 +81,8 @@ func (assertion *Assertion) buildDescription(optionalDescription ...interface{}) } func (assertion *Assertion) match(matcher types.GomegaMatcher, desiredMatch bool, optionalDescription ...interface{}) bool { - matches, err := matcher.Match(assertion.actualInput) + actualInput := assertion.actuals[assertion.actualIndex] + matches, err := matcher.Match(actualInput) assertion.g.THelper() if err != nil { description := assertion.buildDescription(optionalDescription...) @@ -71,9 +92,9 @@ func (assertion *Assertion) match(matcher types.GomegaMatcher, desiredMatch bool if matches != desiredMatch { var message string if desiredMatch { - message = matcher.FailureMessage(assertion.actualInput) + message = matcher.FailureMessage(actualInput) } else { - message = matcher.NegatedFailureMessage(assertion.actualInput) + message = matcher.NegatedFailureMessage(actualInput) } description := assertion.buildDescription(optionalDescription...) assertion.g.Fail(description+message, 2+assertion.offset) @@ -83,8 +104,11 @@ func (assertion *Assertion) match(matcher types.GomegaMatcher, desiredMatch bool return true } -func (assertion *Assertion) vetExtras(optionalDescription ...interface{}) bool { - success, message := vetExtras(assertion.extra) +// vetActuals vets the actual values, with the (optional) exception of a +// specific value, such as the first value in case non-error assertions, or the +// last value in case of Error()-based assertions. +func (assertion *Assertion) vetActuals(optionalDescription ...interface{}) bool { + success, message := vetActuals(assertion.actuals, assertion.actualIndex) if success { return true } @@ -95,12 +119,29 @@ func (assertion *Assertion) vetExtras(optionalDescription ...interface{}) bool { return false } -func vetExtras(extras []interface{}) (bool, string) { - for i, extra := range extras { - if extra != nil { - zeroValue := reflect.Zero(reflect.TypeOf(extra)).Interface() - if !reflect.DeepEqual(zeroValue, extra) { - message := fmt.Sprintf("Unexpected non-nil/non-zero extra argument at index %d:\n\t<%T>: %#v", i+1, extra, extra) +// vetError vets the actual values, except for the final error value, in case +// the final error value is non-zero. Otherwise, it doesn't vet the actual +// values, as these are allowed to take on any values unless there is a non-zero +// error value. +func (assertion *Assertion) vetError(optionalDescription ...interface{}) bool { + if err := assertion.actuals[assertion.actualIndex]; err != nil { + // Go error result idiom: all other actual values must be zero values. + return assertion.vetActuals(optionalDescription...) + } + return true +} + +// vetActuals vets a slice of actual values, optionally skipping a particular +// value slice element, such as the first or last value slice element. +func vetActuals(actuals []interface{}, skipIndex int) (bool, string) { + for i, actual := range actuals { + if i == skipIndex { + continue + } + if actual != nil { + zeroValue := reflect.Zero(reflect.TypeOf(actual)).Interface() + if !reflect.DeepEqual(zeroValue, actual) { + message := fmt.Sprintf("Unexpected non-nil/non-zero argument at index %d:\n\t<%T>: %#v", i, actual, actual) return false, message } } diff --git a/vendor/github.com/onsi/gomega/internal/async_assertion.go b/vendor/github.com/onsi/gomega/internal/async_assertion.go index ae20c14b..99f4ebcf 100644 --- a/vendor/github.com/onsi/gomega/internal/async_assertion.go +++ b/vendor/github.com/onsi/gomega/internal/async_assertion.go @@ -87,6 +87,21 @@ func NewAsyncAssertion(asyncType AsyncAssertionType, actualInput interface{}, g return out } +func (assertion *AsyncAssertion) WithOffset(offset int) types.AsyncAssertion { + assertion.offset = offset + return assertion +} + +func (assertion *AsyncAssertion) WithTimeout(interval time.Duration) types.AsyncAssertion { + assertion.timeoutInterval = interval + return assertion +} + +func (assertion *AsyncAssertion) WithPolling(interval time.Duration) types.AsyncAssertion { + assertion.pollingInterval = interval + return assertion +} + func (assertion *AsyncAssertion) Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool { assertion.g.THelper() return assertion.match(matcher, true, optionalDescription...) @@ -118,11 +133,11 @@ func (assertion *AsyncAssertion) pollActual() (interface{}, error) { if err != nil { return nil, err } - extras := []interface{}{} + extras := []interface{}{nil} for _, value := range values[1:] { extras = append(extras, value.Interface()) } - success, message := vetExtras(extras) + success, message := vetActuals(extras, 0) if !success { return nil, errors.New(message) } diff --git a/vendor/github.com/onsi/gomega/internal/gomega.go b/vendor/github.com/onsi/gomega/internal/gomega.go index f5b5c6b7..d26a6748 100644 --- a/vendor/github.com/onsi/gomega/internal/gomega.go +++ b/vendor/github.com/onsi/gomega/internal/gomega.go @@ -39,12 +39,12 @@ func (g *Gomega) ConfigureWithT(t types.GomegaTestingT) *Gomega { return g } -func (g *Gomega) Ω(atual interface{}, extra ...interface{}) types.Assertion { - return g.ExpectWithOffset(0, atual, extra...) +func (g *Gomega) Ω(actual interface{}, extra ...interface{}) types.Assertion { + return g.ExpectWithOffset(0, actual, extra...) } -func (g *Gomega) Expect(atual interface{}, extra ...interface{}) types.Assertion { - return g.ExpectWithOffset(0, atual, extra...) +func (g *Gomega) Expect(actual interface{}, extra ...interface{}) types.Assertion { + return g.ExpectWithOffset(0, actual, extra...) } func (g *Gomega) ExpectWithOffset(offset int, actual interface{}, extra ...interface{}) types.Assertion { diff --git a/vendor/github.com/onsi/gomega/internal/gutil/post_ioutil.go b/vendor/github.com/onsi/gomega/internal/gutil/post_ioutil.go new file mode 100644 index 00000000..6864055a --- /dev/null +++ b/vendor/github.com/onsi/gomega/internal/gutil/post_ioutil.go @@ -0,0 +1,48 @@ +//go:build go1.16 +// +build go1.16 + +// Package gutil is a replacement for ioutil, which should not be used in new +// code as of Go 1.16. With Go 1.16 and higher, this implementation +// uses the ioutil replacement functions in "io" and "os" with some +// Gomega specifics. This means that we should not get deprecation warnings +// for ioutil when they are added. +package gutil + +import ( + "io" + "os" +) + +func NopCloser(r io.Reader) io.ReadCloser { + return io.NopCloser(r) +} + +func ReadAll(r io.Reader) ([]byte, error) { + return io.ReadAll(r) +} + +func ReadDir(dirname string) ([]string, error) { + entries, err := os.ReadDir(dirname) + if err != nil { + return nil, err + } + + var names []string + for _, entry := range entries { + names = append(names, entry.Name()) + } + + return names, nil +} + +func ReadFile(filename string) ([]byte, error) { + return os.ReadFile(filename) +} + +func MkdirTemp(dir, pattern string) (string, error) { + return os.MkdirTemp(dir, pattern) +} + +func WriteFile(filename string, data []byte) error { + return os.WriteFile(filename, data, 0644) +} diff --git a/vendor/github.com/onsi/gomega/internal/gutil/using_ioutil.go b/vendor/github.com/onsi/gomega/internal/gutil/using_ioutil.go new file mode 100644 index 00000000..5c0ce1ee --- /dev/null +++ b/vendor/github.com/onsi/gomega/internal/gutil/using_ioutil.go @@ -0,0 +1,47 @@ +//go:build !go1.16 +// +build !go1.16 + +// Package gutil is a replacement for ioutil, which should not be used in new +// code as of Go 1.16. With Go 1.15 and lower, this implementation +// uses the ioutil functions, meaning that although Gomega is not officially +// supported on these versions, it is still likely to work. +package gutil + +import ( + "io" + "io/ioutil" +) + +func NopCloser(r io.Reader) io.ReadCloser { + return ioutil.NopCloser(r) +} + +func ReadAll(r io.Reader) ([]byte, error) { + return ioutil.ReadAll(r) +} + +func ReadDir(dirname string) ([]string, error) { + files, err := ioutil.ReadDir(dirname) + if err != nil { + return nil, err + } + + var names []string + for _, file := range files { + names = append(names, file.Name()) + } + + return names, nil +} + +func ReadFile(filename string) ([]byte, error) { + return ioutil.ReadFile(filename) +} + +func MkdirTemp(dir, pattern string) (string, error) { + return ioutil.TempDir(dir, pattern) +} + +func WriteFile(filename string, data []byte) error { + return ioutil.WriteFile(filename, data, 0644) +} diff --git a/vendor/github.com/onsi/gomega/matchers.go b/vendor/github.com/onsi/gomega/matchers.go index 667160ad..b46e461a 100644 --- a/vendor/github.com/onsi/gomega/matchers.go +++ b/vendor/github.com/onsi/gomega/matchers.go @@ -342,6 +342,54 @@ func HaveKeyWithValue(key interface{}, value interface{}) types.GomegaMatcher { } } +//HaveField succeeds if actual is a struct and the value at the passed in field +//matches the passed in matcher. By default HaveField used Equal() to perform the match, +//however a matcher can be passed in in stead. +// +//The field must be a string that resolves to the name of a field in the struct. Structs can be traversed +//using the '.' delimiter. If the field ends with '()' a method named field is assumed to exist on the struct and is invoked. +//Such methods must take no arguments and return a single value: +// +// type Book struct { +// Title string +// Author Person +// } +// type Person struct { +// FirstName string +// LastName string +// DOB time.Time +// } +// Expect(book).To(HaveField("Title", "Les Miserables")) +// Expect(book).To(HaveField("Title", ContainSubstring("Les")) +// Expect(book).To(HaveField("Author.FirstName", Equal("Victor")) +// Expect(book).To(HaveField("Author.DOB.Year()", BeNumerically("<", 1900)) +func HaveField(field string, expected interface{}) types.GomegaMatcher { + return &matchers.HaveFieldMatcher{ + Field: field, + Expected: expected, + } +} + +// HaveValue applies the given matcher to the value of actual, optionally and +// repeatedly dereferencing pointers or taking the concrete value of interfaces. +// Thus, the matcher will always be applied to non-pointer and non-interface +// values only. HaveValue will fail with an error if a pointer or interface is +// nil. It will also fail for more than 31 pointer or interface dereferences to +// guard against mistakenly applying it to arbitrarily deep linked pointers. +// +// HaveValue differs from gstruct.PointTo in that it does not expect actual to +// be a pointer (as gstruct.PointTo does) but instead also accepts non-pointer +// and even interface values. +// +// actual := 42 +// Expect(actual).To(HaveValue(42)) +// Expect(&actual).To(HaveValue(42)) +func HaveValue(matcher types.GomegaMatcher) types.GomegaMatcher { + return &matchers.HaveValueMatcher{ + Matcher: matcher, + } +} + //BeNumerically performs numerical assertions in a type-agnostic way. //Actual and expected should be numbers, though the specific type of //number is irrelevant (float32, float64, uint8, etc...). @@ -423,10 +471,29 @@ func BeADirectory() types.GomegaMatcher { //Expected must be either an int or a string. // Expect(resp).Should(HaveHTTPStatus(http.StatusOK)) // asserts that resp.StatusCode == 200 // Expect(resp).Should(HaveHTTPStatus("404 Not Found")) // asserts that resp.Status == "404 Not Found" -func HaveHTTPStatus(expected interface{}) types.GomegaMatcher { +// Expect(resp).Should(HaveHTTPStatus(http.StatusOK, http.StatusNoContent)) // asserts that resp.StatusCode == 200 || resp.StatusCode == 204 +func HaveHTTPStatus(expected ...interface{}) types.GomegaMatcher { return &matchers.HaveHTTPStatusMatcher{Expected: expected} } +// HaveHTTPHeaderWithValue succeeds if the header is found and the value matches. +// Actual must be either a *http.Response or *httptest.ResponseRecorder. +// Expected must be a string header name, followed by a header value which +// can be a string, or another matcher. +func HaveHTTPHeaderWithValue(header string, value interface{}) types.GomegaMatcher { + return &matchers.HaveHTTPHeaderWithValueMatcher{ + Header: header, + Value: value, + } +} + +// HaveHTTPBody matches if the body matches. +// Actual must be either a *http.Response or *httptest.ResponseRecorder. +// Expected must be either a string, []byte, or other matcher +func HaveHTTPBody(expected interface{}) types.GomegaMatcher { + return &matchers.HaveHTTPBodyMatcher{Expected: expected} +} + //And succeeds only if all of the given matchers succeed. //The matchers are tried in order, and will fail-fast if one doesn't succeed. // Expect("hi").To(And(HaveLen(2), Equal("hi")) @@ -466,10 +533,15 @@ func Not(matcher types.GomegaMatcher) types.GomegaMatcher { } //WithTransform applies the `transform` to the actual value and matches it against `matcher`. -//The given transform must be a function of one parameter that returns one value. +//The given transform must be either a function of one parameter that returns one value or a +// function of one parameter that returns two values, where the second value must be of the +// error type. // var plus1 = func(i int) int { return i + 1 } // Expect(1).To(WithTransform(plus1, Equal(2)) // +// var failingplus1 = func(i int) (int, error) { return 42, "this does not compute" } +// Expect(1).To(WithTransform(failingplus1, Equal(2))) +// //And(), Or(), Not() and WithTransform() allow matchers to be composed into complex expressions. func WithTransform(transform interface{}, matcher types.GomegaMatcher) types.GomegaMatcher { return matchers.NewWithTransformMatcher(transform, matcher) diff --git a/vendor/github.com/onsi/gomega/matchers/have_field.go b/vendor/github.com/onsi/gomega/matchers/have_field.go new file mode 100644 index 00000000..e1fe934d --- /dev/null +++ b/vendor/github.com/onsi/gomega/matchers/have_field.go @@ -0,0 +1,87 @@ +package matchers + +import ( + "fmt" + "reflect" + "strings" + + "github.com/onsi/gomega/format" +) + +func extractField(actual interface{}, field string) (interface{}, error) { + fields := strings.SplitN(field, ".", 2) + actualValue := reflect.ValueOf(actual) + + if actualValue.Kind() == reflect.Ptr { + actualValue = actualValue.Elem() + } + if actualValue == (reflect.Value{}) { + return nil, fmt.Errorf("HaveField encountered nil while dereferencing a pointer of type %T.", actual) + } + + if actualValue.Kind() != reflect.Struct { + return nil, fmt.Errorf("HaveField encountered:\n%s\nWhich is not a struct.", format.Object(actual, 1)) + } + + var extractedValue reflect.Value + + if strings.HasSuffix(fields[0], "()") { + extractedValue = actualValue.MethodByName(strings.TrimSuffix(fields[0], "()")) + if extractedValue == (reflect.Value{}) { + return nil, fmt.Errorf("HaveField could not find method named '%s' in struct of type %T.", fields[0], actual) + } + t := extractedValue.Type() + if t.NumIn() != 0 || t.NumOut() != 1 { + return nil, fmt.Errorf("HaveField found an invalid method named '%s' in struct of type %T.\nMethods must take no arguments and return exactly one value.", fields[0], actual) + } + extractedValue = extractedValue.Call([]reflect.Value{})[0] + } else { + extractedValue = actualValue.FieldByName(fields[0]) + if extractedValue == (reflect.Value{}) { + return nil, fmt.Errorf("HaveField could not find field named '%s' in struct:\n%s", fields[0], format.Object(actual, 1)) + } + } + + if len(fields) == 1 { + return extractedValue.Interface(), nil + } else { + return extractField(extractedValue.Interface(), fields[1]) + } +} + +type HaveFieldMatcher struct { + Field string + Expected interface{} + + extractedField interface{} + expectedMatcher omegaMatcher +} + +func (matcher *HaveFieldMatcher) Match(actual interface{}) (success bool, err error) { + matcher.extractedField, err = extractField(actual, matcher.Field) + if err != nil { + return false, err + } + + var isMatcher bool + matcher.expectedMatcher, isMatcher = matcher.Expected.(omegaMatcher) + if !isMatcher { + matcher.expectedMatcher = &EqualMatcher{Expected: matcher.Expected} + } + + return matcher.expectedMatcher.Match(matcher.extractedField) +} + +func (matcher *HaveFieldMatcher) FailureMessage(actual interface{}) (message string) { + message = fmt.Sprintf("Value for field '%s' failed to satisfy matcher.\n", matcher.Field) + message += matcher.expectedMatcher.FailureMessage(matcher.extractedField) + + return message +} + +func (matcher *HaveFieldMatcher) NegatedFailureMessage(actual interface{}) (message string) { + message = fmt.Sprintf("Value for field '%s' satisfied matcher, but should not have.\n", matcher.Field) + message += matcher.expectedMatcher.NegatedFailureMessage(matcher.extractedField) + + return message +} diff --git a/vendor/github.com/onsi/gomega/matchers/have_http_body_matcher.go b/vendor/github.com/onsi/gomega/matchers/have_http_body_matcher.go new file mode 100644 index 00000000..6a3dcdc3 --- /dev/null +++ b/vendor/github.com/onsi/gomega/matchers/have_http_body_matcher.go @@ -0,0 +1,101 @@ +package matchers + +import ( + "fmt" + "net/http" + "net/http/httptest" + + "github.com/onsi/gomega/format" + "github.com/onsi/gomega/internal/gutil" + "github.com/onsi/gomega/types" +) + +type HaveHTTPBodyMatcher struct { + Expected interface{} + cachedBody []byte +} + +func (matcher *HaveHTTPBodyMatcher) Match(actual interface{}) (bool, error) { + body, err := matcher.body(actual) + if err != nil { + return false, err + } + + switch e := matcher.Expected.(type) { + case string: + return (&EqualMatcher{Expected: e}).Match(string(body)) + case []byte: + return (&EqualMatcher{Expected: e}).Match(body) + case types.GomegaMatcher: + return e.Match(body) + default: + return false, fmt.Errorf("HaveHTTPBody matcher expects string, []byte, or GomegaMatcher. Got:\n%s", format.Object(matcher.Expected, 1)) + } +} + +func (matcher *HaveHTTPBodyMatcher) FailureMessage(actual interface{}) (message string) { + body, err := matcher.body(actual) + if err != nil { + return fmt.Sprintf("failed to read body: %s", err) + } + + switch e := matcher.Expected.(type) { + case string: + return (&EqualMatcher{Expected: e}).FailureMessage(string(body)) + case []byte: + return (&EqualMatcher{Expected: e}).FailureMessage(body) + case types.GomegaMatcher: + return e.FailureMessage(body) + default: + return fmt.Sprintf("HaveHTTPBody matcher expects string, []byte, or GomegaMatcher. Got:\n%s", format.Object(matcher.Expected, 1)) + } +} + +func (matcher *HaveHTTPBodyMatcher) NegatedFailureMessage(actual interface{}) (message string) { + body, err := matcher.body(actual) + if err != nil { + return fmt.Sprintf("failed to read body: %s", err) + } + + switch e := matcher.Expected.(type) { + case string: + return (&EqualMatcher{Expected: e}).NegatedFailureMessage(string(body)) + case []byte: + return (&EqualMatcher{Expected: e}).NegatedFailureMessage(body) + case types.GomegaMatcher: + return e.NegatedFailureMessage(body) + default: + return fmt.Sprintf("HaveHTTPBody matcher expects string, []byte, or GomegaMatcher. Got:\n%s", format.Object(matcher.Expected, 1)) + } +} + +// body returns the body. It is cached because once we read it in Match() +// the Reader is closed and it is not readable again in FailureMessage() +// or NegatedFailureMessage() +func (matcher *HaveHTTPBodyMatcher) body(actual interface{}) ([]byte, error) { + if matcher.cachedBody != nil { + return matcher.cachedBody, nil + } + + body := func(a *http.Response) ([]byte, error) { + if a.Body != nil { + defer a.Body.Close() + var err error + matcher.cachedBody, err = gutil.ReadAll(a.Body) + if err != nil { + return nil, fmt.Errorf("error reading response body: %w", err) + } + } + return matcher.cachedBody, nil + } + + switch a := actual.(type) { + case *http.Response: + return body(a) + case *httptest.ResponseRecorder: + return body(a.Result()) + default: + return nil, fmt.Errorf("HaveHTTPBody matcher expects *http.Response or *httptest.ResponseRecorder. Got:\n%s", format.Object(actual, 1)) + } + +} diff --git a/vendor/github.com/onsi/gomega/matchers/have_http_header_with_value_matcher.go b/vendor/github.com/onsi/gomega/matchers/have_http_header_with_value_matcher.go new file mode 100644 index 00000000..c256f452 --- /dev/null +++ b/vendor/github.com/onsi/gomega/matchers/have_http_header_with_value_matcher.go @@ -0,0 +1,81 @@ +package matchers + +import ( + "fmt" + "net/http" + "net/http/httptest" + + "github.com/onsi/gomega/format" + "github.com/onsi/gomega/types" +) + +type HaveHTTPHeaderWithValueMatcher struct { + Header string + Value interface{} +} + +func (matcher *HaveHTTPHeaderWithValueMatcher) Match(actual interface{}) (success bool, err error) { + headerValue, err := matcher.extractHeader(actual) + if err != nil { + return false, err + } + + headerMatcher, err := matcher.getSubMatcher() + if err != nil { + return false, err + } + + return headerMatcher.Match(headerValue) +} + +func (matcher *HaveHTTPHeaderWithValueMatcher) FailureMessage(actual interface{}) string { + headerValue, err := matcher.extractHeader(actual) + if err != nil { + panic(err) // protected by Match() + } + + headerMatcher, err := matcher.getSubMatcher() + if err != nil { + panic(err) // protected by Match() + } + + diff := format.IndentString(headerMatcher.FailureMessage(headerValue), 1) + return fmt.Sprintf("HTTP header %q:\n%s", matcher.Header, diff) +} + +func (matcher *HaveHTTPHeaderWithValueMatcher) NegatedFailureMessage(actual interface{}) (message string) { + headerValue, err := matcher.extractHeader(actual) + if err != nil { + panic(err) // protected by Match() + } + + headerMatcher, err := matcher.getSubMatcher() + if err != nil { + panic(err) // protected by Match() + } + + diff := format.IndentString(headerMatcher.NegatedFailureMessage(headerValue), 1) + return fmt.Sprintf("HTTP header %q:\n%s", matcher.Header, diff) +} + +func (matcher *HaveHTTPHeaderWithValueMatcher) getSubMatcher() (types.GomegaMatcher, error) { + switch m := matcher.Value.(type) { + case string: + return &EqualMatcher{Expected: matcher.Value}, nil + case types.GomegaMatcher: + return m, nil + default: + return nil, fmt.Errorf("HaveHTTPHeaderWithValue matcher must be passed a string or a GomegaMatcher. Got:\n%s", format.Object(matcher.Value, 1)) + } +} + +func (matcher *HaveHTTPHeaderWithValueMatcher) extractHeader(actual interface{}) (string, error) { + switch r := actual.(type) { + case *http.Response: + return r.Header.Get(matcher.Header), nil + case *httptest.ResponseRecorder: + return r.Result().Header.Get(matcher.Header), nil + default: + return "", fmt.Errorf("HaveHTTPHeaderWithValue matcher expects *http.Response or *httptest.ResponseRecorder. Got:\n%s", format.Object(actual, 1)) + } +} diff --git a/vendor/github.com/onsi/gomega/matchers/have_http_status_matcher.go b/vendor/github.com/onsi/gomega/matchers/have_http_status_matcher.go index 3ce4800b..0f66e46e 100644 --- a/vendor/github.com/onsi/gomega/matchers/have_http_status_matcher.go +++ b/vendor/github.com/onsi/gomega/matchers/have_http_status_matcher.go @@ -4,12 +4,15 @@ import ( "fmt" "net/http" "net/http/httptest" + "reflect" + "strings" "github.com/onsi/gomega/format" + "github.com/onsi/gomega/internal/gutil" ) type HaveHTTPStatusMatcher struct { - Expected interface{} + Expected []interface{} } func (matcher *HaveHTTPStatusMatcher) Match(actual interface{}) (success bool, err error) { @@ -23,20 +26,71 @@ func (matcher *HaveHTTPStatusMatcher) Match(actual interface{}) (success bool, e return false, fmt.Errorf("HaveHTTPStatus matcher expects *http.Response or *httptest.ResponseRecorder. Got:\n%s", format.Object(actual, 1)) } - switch e := matcher.Expected.(type) { - case int: - return resp.StatusCode == e, nil - case string: - return resp.Status == e, nil + if len(matcher.Expected) == 0 { + return false, fmt.Errorf("HaveHTTPStatus matcher must be passed an int or a string. Got nothing") } - return false, fmt.Errorf("HaveHTTPStatus matcher must be passed an int or a string. Got:\n%s", format.Object(matcher.Expected, 1)) + for _, expected := range matcher.Expected { + switch e := expected.(type) { + case int: + if resp.StatusCode == e { + return true, nil + } + case string: + if resp.Status == e { + return true, nil + } + default: + return false, fmt.Errorf("HaveHTTPStatus matcher must be passed int or string types. Got:\n%s", format.Object(expected, 1)) + } + } + + return false, nil } func (matcher *HaveHTTPStatusMatcher) FailureMessage(actual interface{}) (message string) { - return format.Message(actual, "to have HTTP status", matcher.Expected) + return fmt.Sprintf("Expected\n%s\n%s\n%s", formatHttpResponse(actual), "to have HTTP status", matcher.expectedString()) } func (matcher *HaveHTTPStatusMatcher) NegatedFailureMessage(actual interface{}) (message string) { - return format.Message(actual, "not to have HTTP status", matcher.Expected) + return fmt.Sprintf("Expected\n%s\n%s\n%s", formatHttpResponse(actual), "not to have HTTP status", matcher.expectedString()) +} + +func (matcher *HaveHTTPStatusMatcher) expectedString() string { + var lines []string + for _, expected := range matcher.Expected { + lines = append(lines, format.Object(expected, 1)) + } + return strings.Join(lines, "\n") +} + +func formatHttpResponse(input interface{}) string { + var resp *http.Response + switch r := input.(type) { + case *http.Response: + resp = r + case *httptest.ResponseRecorder: + resp = r.Result() + default: + return "cannot format invalid HTTP response" + } + + body := "" + if resp.Body != nil { + defer resp.Body.Close() + data, err := gutil.ReadAll(resp.Body) + if err != nil { + data = []byte("") + } + body = format.Object(string(data), 0) + } + + var s strings.Builder + s.WriteString(fmt.Sprintf("%s<%s>: {\n", format.Indent, reflect.TypeOf(input))) + s.WriteString(fmt.Sprintf("%s%sStatus: %s\n", format.Indent, format.Indent, format.Object(resp.Status, 0))) + s.WriteString(fmt.Sprintf("%s%sStatusCode: %s\n", format.Indent, format.Indent, format.Object(resp.StatusCode, 0))) + s.WriteString(fmt.Sprintf("%s%sBody: %s\n", format.Indent, format.Indent, body)) + s.WriteString(fmt.Sprintf("%s}", format.Indent)) + + return s.String() } diff --git a/vendor/github.com/onsi/gomega/matchers/have_value.go b/vendor/github.com/onsi/gomega/matchers/have_value.go new file mode 100644 index 00000000..f6725283 --- /dev/null +++ b/vendor/github.com/onsi/gomega/matchers/have_value.go @@ -0,0 +1,54 @@ +package matchers + +import ( + "errors" + "reflect" + + "github.com/onsi/gomega/format" + "github.com/onsi/gomega/types" +) + +const maxIndirections = 31 + +type HaveValueMatcher struct { + Matcher types.GomegaMatcher // the matcher to apply to the "resolved" actual value. + resolvedActual interface{} // the ("resolved") value. +} + +func (m *HaveValueMatcher) Match(actual interface{}) (bool, error) { + val := reflect.ValueOf(actual) + for allowedIndirs := maxIndirections; allowedIndirs > 0; allowedIndirs-- { + // return an error if value isn't valid. Please note that we cannot + // check for nil here, as we might not deal with a pointer or interface + // at this point. + if !val.IsValid() { + return false, errors.New(format.Message( + actual, "not to be ")) + } + switch val.Kind() { + case reflect.Ptr, reflect.Interface: + // resolve pointers and interfaces to their values, then rinse and + // repeat. + if val.IsNil() { + return false, errors.New(format.Message( + actual, "not to be ")) + } + val = val.Elem() + continue + default: + // forward the final value to the specified matcher. + m.resolvedActual = val.Interface() + return m.Matcher.Match(m.resolvedActual) + } + } + // too many indirections: extreme star gazing, indeed...? + return false, errors.New(format.Message(actual, "too many indirections")) +} + +func (m *HaveValueMatcher) FailureMessage(_ interface{}) (message string) { + return m.Matcher.FailureMessage(m.resolvedActual) +} + +func (m *HaveValueMatcher) NegatedFailureMessage(_ interface{}) (message string) { + return m.Matcher.NegatedFailureMessage(m.resolvedActual) +} diff --git a/vendor/github.com/onsi/gomega/matchers/with_transform.go b/vendor/github.com/onsi/gomega/matchers/with_transform.go index 8a06bd38..6f743b1b 100644 --- a/vendor/github.com/onsi/gomega/matchers/with_transform.go +++ b/vendor/github.com/onsi/gomega/matchers/with_transform.go @@ -9,7 +9,7 @@ import ( type WithTransformMatcher struct { // input - Transform interface{} // must be a function of one parameter that returns one value + Transform interface{} // must be a function of one parameter that returns one value and an optional error Matcher types.GomegaMatcher // cached value @@ -19,6 +19,9 @@ type WithTransformMatcher struct { transformedValue interface{} } +// reflect.Type for error +var errorT = reflect.TypeOf((*error)(nil)).Elem() + func NewWithTransformMatcher(transform interface{}, matcher types.GomegaMatcher) *WithTransformMatcher { if transform == nil { panic("transform function cannot be nil") @@ -27,8 +30,10 @@ func NewWithTransformMatcher(transform interface{}, matcher types.GomegaMatcher) if txType.NumIn() != 1 { panic("transform function must have 1 argument") } - if txType.NumOut() != 1 { - panic("transform function must have 1 return value") + if numout := txType.NumOut(); numout != 1 { + if numout != 2 || !txType.Out(1).AssignableTo(errorT) { + panic("transform function must either have 1 return value, or 1 return value plus 1 error value") + } } return &WithTransformMatcher{ @@ -57,6 +62,11 @@ func (m *WithTransformMatcher) Match(actual interface{}) (bool, error) { // call the Transform function with `actual` fn := reflect.ValueOf(m.Transform) result := fn.Call([]reflect.Value{param}) + if len(result) == 2 { + if !result[1].IsNil() { + return false, fmt.Errorf("Transform function failed: %s", result[1].Interface().(error).Error()) + } + } m.transformedValue = result[0].Interface() // expect exactly one value return m.Matcher.Match(m.transformedValue) diff --git a/vendor/github.com/onsi/gomega/tools b/vendor/github.com/onsi/gomega/tools new file mode 100644 index 00000000..e4195cf3 --- /dev/null +++ b/vendor/github.com/onsi/gomega/tools @@ -0,0 +1,8 @@ +//go:build tools +// +build tools + +package main + +import ( + _ "github.com/onsi/ginkgo/v2/ginkgo" +) diff --git a/vendor/github.com/onsi/gomega/types/types.go b/vendor/github.com/onsi/gomega/types/types.go index c75fcb3c..c315ef06 100644 --- a/vendor/github.com/onsi/gomega/types/types.go +++ b/vendor/github.com/onsi/gomega/types/types.go @@ -66,6 +66,10 @@ func MatchMayChangeInTheFuture(matcher GomegaMatcher, value interface{}) bool { type AsyncAssertion interface { Should(matcher GomegaMatcher, optionalDescription ...interface{}) bool ShouldNot(matcher GomegaMatcher, optionalDescription ...interface{}) bool + + WithOffset(offset int) AsyncAssertion + WithTimeout(interval time.Duration) AsyncAssertion + WithPolling(interval time.Duration) AsyncAssertion } // Assertions are returned by Ω and Expect and enable assertions against Gomega matchers @@ -76,4 +80,8 @@ type Assertion interface { To(matcher GomegaMatcher, optionalDescription ...interface{}) bool ToNot(matcher GomegaMatcher, optionalDescription ...interface{}) bool NotTo(matcher GomegaMatcher, optionalDescription ...interface{}) bool + + WithOffset(offset int) Assertion + + Error() Assertion } diff --git a/vendor/modules.txt b/vendor/modules.txt index 94f8d072..ca564e96 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -51,7 +51,7 @@ github.com/beorn7/perks/quantile # github.com/cenkalti/backoff v2.2.1+incompatible ## explicit github.com/cenkalti/backoff -# github.com/cespare/xxhash/v2 v2.1.1 +# github.com/cespare/xxhash/v2 v2.1.2 ## explicit; go 1.11 github.com/cespare/xxhash/v2 # github.com/coreos/go-oidc v2.2.1+incompatible @@ -126,8 +126,8 @@ github.com/go-openapi/spec # github.com/go-openapi/swag v0.19.14 ## explicit; go 1.11 github.com/go-openapi/swag -# github.com/go-redis/redis/v8 v8.11.3 -## explicit; go 1.13 +# github.com/go-redis/redis/v8 v8.11.5 +## explicit; go 1.17 github.com/go-redis/redis/v8 github.com/go-redis/redis/v8/internal github.com/go-redis/redis/v8/internal/hashtag @@ -272,11 +272,12 @@ github.com/motemen/go-loghttp # github.com/motemen/go-nuts v0.0.0-20210915132349-615a782f2c69 ## explicit; go 1.16 github.com/motemen/go-nuts/roundtime -# github.com/onsi/gomega v1.15.0 -## explicit; go 1.14 +# github.com/onsi/gomega v1.18.1 +## explicit; go 1.16 github.com/onsi/gomega github.com/onsi/gomega/format github.com/onsi/gomega/internal +github.com/onsi/gomega/internal/gutil github.com/onsi/gomega/matchers github.com/onsi/gomega/matchers/support/goraph/bipartitegraph github.com/onsi/gomega/matchers/support/goraph/edge