diff --git a/Dockerfile b/Dockerfile index 073a1ab5e..e336f3cbc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM openshift/origin-release:golang-1.10 +FROM openshift/origin-release:golang-1.12 COPY . /go/src/github.com/openshift/telemeter RUN cd /go/src/github.com/openshift/telemeter && \ go build ./cmd/telemeter-client && \ @@ -8,4 +8,4 @@ RUN cd /go/src/github.com/openshift/telemeter && \ FROM centos:7 COPY --from=0 /go/src/github.com/openshift/telemeter/telemeter-client /usr/bin/ COPY --from=0 /go/src/github.com/openshift/telemeter/telemeter-server /usr/bin/ -COPY --from=0 /go/src/github.com/openshift/telemeter/authorization-server /usr/bin/ \ No newline at end of file +COPY --from=0 /go/src/github.com/openshift/telemeter/authorization-server /usr/bin/ diff --git a/Makefile b/Makefile index 2839330f2..27d0a45cd 100644 --- a/Makefile +++ b/Makefile @@ -20,12 +20,12 @@ JSONNET_VENDOR=jsonnet/jsonnetfile.lock.json jsonnet/vendor DOCS=$(shell grep -rlF [embedmd] docs) GO_BUILD_RECIPE=GOOS=linux CGO_ENABLED=0 go build -# TODO(paulfantom): add '-e GO111MODULE=on' when moving to go 1.12 CONTAINER_CMD:=docker run --rm \ -u="$(shell id -u):$(shell id -g)" \ -v "$(shell go env GOCACHE):/.cache/go-build" \ -v "$(PWD):/go/src/$(GO_PKG):Z" \ -w "/go/src/$(GO_PKG)" \ + -e GO111MODULE=on \ quay.io/coreos/jsonnet-ci @@ -67,7 +67,9 @@ image: .hack-operator-image ############## vendor: - glide update -v --skip-test + go mod vendor + go mod tidy + go mod verify .PHONY: generate generate: $(DOCS) manifests @@ -181,6 +183,6 @@ $(GOJSONTOYAML_BIN): go get -u github.com/brancz/gojsontoyaml $(GOLANGCI_LINT_BIN): - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(FIRST_GOPATH)/bin v1.10.2 + curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(FIRST_GOPATH)/bin v1.16.0 diff --git a/cmd/telemeter-benchmark/main.go b/cmd/telemeter-benchmark/main.go index 4b00647cc..91af8ec87 100644 --- a/cmd/telemeter-benchmark/main.go +++ b/cmd/telemeter-benchmark/main.go @@ -102,11 +102,9 @@ func runCmd() error { u.Path = path.Join(to.Path, "authorize") toAuthorize = &u } - if toUpload == nil { - u := *to - u.Path = path.Join(to.Path, "upload") - toUpload = &u - } + u := *to + u.Path = path.Join(to.Path, "upload") + toUpload = &u } if toUpload == nil || toAuthorize == nil { diff --git a/cmd/telemeter-client/main.go b/cmd/telemeter-client/main.go index 25a452b0c..b10d5358a 100644 --- a/cmd/telemeter-client/main.go +++ b/cmd/telemeter-client/main.go @@ -175,11 +175,9 @@ func (o *Options) Run() error { } toAuthorize = &u } - if toUpload == nil { - u := *to - u.Path = path.Join(to.Path, "upload") - toUpload = &u - } + u := *to + u.Path = path.Join(to.Path, "upload") + toUpload = &u } if toUpload == nil || toAuthorize == nil { diff --git a/glide.lock b/glide.lock deleted file mode 100644 index e81c3b611..000000000 --- a/glide.lock +++ /dev/null @@ -1,172 +0,0 @@ -hash: 32f5b627e5eae9b1f575f2f5406a2b3e659e135f1249b1db71ace559274a7d3e -updated: 2019-03-05T11:14:23.311087899+01:00 -imports: -- name: github.com/alecthomas/units - version: 2efee857e7cfd4f3d0138cc3cbb1b4966962b93a -- name: github.com/armon/go-metrics - version: 3c58d8115a78a6879e5df75ae900846768d36895 -- name: github.com/beorn7/perks - version: 3ac7bf7a47d159a033b107610db8a1b6575507a4 - subpackages: - - quantile -- name: github.com/cespare/xxhash - version: 3767db7a7e183c0ad3395680d460d0b61534ae7b -- name: github.com/coreos/go-oidc - version: 1180514eaf4d9f38d0d19eef639a1d695e066e72 -- name: github.com/go-kit/kit - version: 102522abed87468226354b1a1c8c588c81313822 - subpackages: - - log - - log/level -- name: github.com/go-logfmt/logfmt - version: 07c9b44f60d7ffdfb7d8efe1ad539965737836dc -- name: github.com/golang/protobuf - version: aa810b61a9c79d51363740d207bb46cf8e620ed5 - subpackages: - - proto -- name: github.com/golang/snappy - version: 2e65f85255dbc3072edf28d6b5b8efc472979f5a -- name: github.com/hashicorp/errwrap - version: 7554cd9344cec97297fa6649b055a8c98c2a1e55 -- name: github.com/hashicorp/go-immutable-radix - version: 27df80928bb34bb1b0d6d0e01b9e679902e7a6b5 -- name: github.com/hashicorp/go-msgpack - version: fa3f63826f7c23912c15263591e65d54d080b458 - subpackages: - - codec -- name: github.com/hashicorp/go-multierror - version: b7773ae218740a7be65057fc60b366a49b538a44 -- name: github.com/hashicorp/go-sockaddr - version: 6d291a969b86c4b633730bfc6b8b9d64c3aafed9 -- name: github.com/hashicorp/golang-lru - version: a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4 - subpackages: - - simplelru -- name: github.com/hashicorp/memberlist - version: b195c8e4fcc6284fff1583fd6ab09e68ca207551 -- name: github.com/inconshreveable/mousetrap - version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 -- name: github.com/kr/logfmt - version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 -- name: github.com/matttproud/golang_protobuf_extensions - version: c12348ce28de40eed0136aa2b644d0ee0650e56c - subpackages: - - pbutil -- name: github.com/miekg/dns - version: e875a31a5cfbcd646131e625f24818cbae228913 -- name: github.com/oklog/run - version: 6934b124db28979da51d3470dadfa34d73d72652 -- name: github.com/oklog/ulid - version: 1fe95fa015d44afc8cd427914daadb0317481b71 -- name: github.com/opentracing/opentracing-go - version: 25a84ff92183e2f8ac018ba1db54f8a07b3c0e04 - subpackages: - - log -- name: github.com/pkg/errors - version: 645ef00459ed84a119197bfb8d8205042c6df63d -- name: github.com/pquerna/cachecontrol - version: 1555304b9b35fdd2b425bccf1a5613677705e7d0 - subpackages: - - cacheobject -- name: github.com/prometheus/client_golang - version: 1cafe34db7fdec6022e17e00e1c1ea501022f3e4 - subpackages: - - prometheus - - prometheus/internal - - prometheus/promauto - - prometheus/promhttp -- name: github.com/prometheus/client_model - version: 5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f - subpackages: - - go -- name: github.com/prometheus/common - version: cfeb6f9992ffa54aaa4f2170ade4067ee478b250 - subpackages: - - expfmt - - internal/bitbucket.org/ww/goautoneg - - model -- name: github.com/prometheus/procfs - version: 65c1f6f8f0fc1e2185eb9863a3bc751496404259 - subpackages: - - xfs -- name: github.com/prometheus/prometheus - version: 62e591f928ddf6b3468308b7ac1de1c63aa7fcf3 - subpackages: - - pkg/gate - - pkg/labels - - pkg/textparse - - pkg/timestamp - - pkg/value - - promql - - storage - - storage/tsdb - - util/stats - - util/strutil - - util/testutil -- name: github.com/prometheus/tsdb - version: 08af7bbf906a44b8dedd3c0ebfae347d9deb1183 - subpackages: - - chunkenc - - chunks - - encoding - - fileutil - - index - - labels - - wal -- name: github.com/satori/go.uuid - version: b2ce2384e17bbe0c6d34077efa39dbab3e09123b -- name: github.com/sean-/seed - version: e2103e2c35297fb7e17febb81e49b312087a2372 -- name: github.com/serialx/hashring - version: 49a4782e9908fe098c907022a1bd7519c79803d6 -- name: github.com/spf13/cobra - version: ef82de70bb3f60c65fb8eebacbb2d122ef517385 -- name: github.com/spf13/pflag - version: 9a97c102cda95a86cec2345a6f09f55a939babf5 -- name: golang.org/x/crypto - version: de0752318171da717af4ce24d0a2e8626afaeb11 - subpackages: - - ed25519 - - ed25519/internal/edwards25519 -- name: golang.org/x/net - version: 0ed95abb35c445290478a5348a7b38bb154135fd - subpackages: - - bpf - - context - - internal/iana - - internal/socket - - ipv4 - - ipv6 -- name: golang.org/x/oauth2 - version: a6bd8cefa1811bd24b86f8902872e4e8225f74c4 - subpackages: - - internal -- name: golang.org/x/sync - version: 1d60e4601c6fd243af51cc01ddf169918a5407ca - subpackages: - - errgroup -- name: golang.org/x/sys - version: b90733256f2e882e81d52f9126de08df5615afd9 - subpackages: - - unix -- name: golang.org/x/time - version: f51c12702a4d776e4c1fa9b0fabab841babae631 - subpackages: - - rate -- name: google.golang.org/appengine - version: 12d5545dc1cfa6047a286d5e853841b6471f4c19 - subpackages: - - internal - - internal/base - - internal/datastore - - internal/log - - internal/remote_api - - internal/urlfetch - - urlfetch -- name: gopkg.in/square/go-jose.v2 - version: 89060dee6a84df9a4dae49f676f0c755037834f1 - subpackages: - - cipher - - json - - jwt -testImports: [] diff --git a/glide.yaml b/glide.yaml deleted file mode 100644 index 6acb76ea1..000000000 --- a/glide.yaml +++ /dev/null @@ -1,30 +0,0 @@ -package: github.com/openshift/telemeter -import: -- package: github.com/prometheus/prometheus - version: v2.7.1 - subpackages: - - pkg/labels - - promql -- package: github.com/prometheus/client_golang - version: 0.9.0 - subpackages: - - prometheus -- package: github.com/prometheus/client_model - version: 5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f -- package: github.com/prometheus/common - version: v0.2.0 -- package: github.com/spf13/cobra - version: 0.0.3 -- package: github.com/spf13/pflag - version: 1.0.2 -- package: github.com/golang/protobuf - version: v1.2.0 - subpackages: - - proto -- package: github.com/coreos/go-oidc - version: v2.0.0 -- package: golang.org/x/oauth2 - subpackages: - - internal -- package: golang.org/x/time -- package: github.com/oklog/run diff --git a/go.mod b/go.mod new file mode 100644 index 000000000..6d295b01a --- /dev/null +++ b/go.mod @@ -0,0 +1,26 @@ +module github.com/openshift/telemeter + +go 1.12 + +require ( + github.com/coreos/go-oidc v2.0.0+incompatible + github.com/go-logfmt/logfmt v0.4.0 // indirect + github.com/golang/protobuf v1.2.0 + github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db + github.com/hashicorp/go-msgpack v0.5.3 + github.com/hashicorp/memberlist v0.1.4 + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/oklog/run v0.0.0-20180308005104-6934b124db28 + github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect + github.com/prometheus/client_golang v0.9.1 + github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 + github.com/prometheus/common v0.2.0 + github.com/prometheus/prometheus v2.7.1+incompatible + github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b + github.com/serialx/hashring v0.0.0-20180504054112-49a4782e9908 + github.com/spf13/cobra v0.0.3 + golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be + golang.org/x/sys v0.0.0-20190124100055-b90733256f2e // indirect + golang.org/x/time v0.0.0-20170424234030-8be79e1e0910 + gopkg.in/square/go-jose.v2 v2.0.0-20180411045311-89060dee6a84 +) diff --git a/go.sum b/go.sum new file mode 100644 index 000000000..0422909fa --- /dev/null +++ b/go.sum @@ -0,0 +1,254 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/Azure/azure-sdk-for-go v0.0.0-20161028183111-bd73d950fa44/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/StackExchange/wmi v0.0.0-20180725035823-b12b22c5341f/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/aws/aws-sdk-go v0.0.0-20180507225419-00862f899353/go.mod h1:ZRmQr0FajVIyZ4ZzBYKG5P3ZqPz9IHG41ZoMu1ADI3k= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/biogo/store v0.0.0-20160505134755-913427a1d5e8/go.mod h1:Iev9Q3MErcn+w3UOJD/DkEzllvugfdx7bGcMOFhvr/4= +github.com/cenk/backoff v2.0.0+incompatible/go.mod h1:7FtoeaSnHoZnmZzz47cM35Y9nSW7tNyaidugnHTaFDE= +github.com/certifi/gocertifi v0.0.0-20180905225744-ee1a9a0726d2/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/cockroachdb/cmux v0.0.0-20170110192607-30d10be49292/go.mod h1:qRiX68mZX1lGBkTWyp3CLcenw9I94W2dLeRvMzcn9N4= +github.com/cockroachdb/cockroach v0.0.0-20170608034007-84bc9597164f/go.mod h1:xeT/CQ0qZHangbYbWShlCGAx31aV4AjGswDUjhKS6HQ= +github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-oidc v2.0.0+incompatible h1:+RStIopZ8wooMx+Vs5Bt8zMXxV1ABl5LbakNExNmZIg= +github.com/coreos/go-oidc v2.0.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v0.0.0-20161101193935-9ed569b5d1ac/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/elastic/gosigar v0.9.0/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= +github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= +github.com/evanphx/json-patch v4.1.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a/go.mod h1:7Ga40egUymuWXxAe151lTNnCv97MddSOVsjpPPkityA= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/getsentry/raven-go v0.1.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-ini/ini v1.21.1/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +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= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0 h1:xU6/SpYbvkNYiptHJYEDRseDLvYE7wSqhYYNy0QSUzI= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20180924190550-6f2cf27854a4/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.0-20160529050041-d9eb7a3d35ec/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/gofuzz v0.0.0-20150304233714-bbcb9da2d746/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/pprof v0.0.0-20180605153948-8b03ce837f34/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/googleapis/gnostic v0.0.0-20180520015035-48a0ecefe2e4/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/gophercloud/gophercloud v0.0.0-20181206160319-9d88c34913a9/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/grpc-gateway v1.6.3/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= +github.com/hashicorp/consul v0.0.0-20180615161029-bed22a81e9fd/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.0.0-20160407174126-ad28ea4487f0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.0.0-20150518234257-fa3f63826f7c h1:BTAbnbegUIMB6xmQCwWE8yRzbA4XSpnZY5hvRJC188I= +github.com/hashicorp/go-msgpack v0.0.0-20150518234257-fa3f63826f7c/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90/go.mod h1:o4zcYY1e0GEZI6eSEr+43QDYmuGglw1qSO6qdHUHCgg= +github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86 h1:7YOlAIO2YWnJZkQp7B5eFykaIY7C9JndqAFQyVV5BhM= +github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCSnM= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/memberlist v0.1.0 h1:qSsCiC0WYD39lbSitKNt40e30uorm2Ss/d4JGU1hzH8= +github.com/hashicorp/memberlist v0.1.0/go.mod h1:ncdBp14cuox2iFOq3kDiquKU6fqsTBc3W6JvZwjxxsE= +github.com/hashicorp/memberlist v0.1.4 h1:gkyML/r71w3FL8gUi74Vk76avkj/9lYAY9lvg0OcoGs= +github.com/hashicorp/memberlist v0.1.4/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.0.0-20161007004122-1d4fa605f6ff/go.mod h1:h/Ru6tmZazX7WO/GDmwdpS975F019L4t5ng5IgwbNrE= +github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb v0.0.0-20170331210902-15e594fc09f1/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= +github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= +github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= +github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v0.0.0-20150905172533-109e267447e9/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/knz/strtime v0.0.0-20181018220328-af2256ee352c/go.mod h1:4ZxfWkxwtc7dBeifERVVWRy9F9rTU9p0yCDgeCtlius= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lightstep/lightstep-tracer-go v0.15.6/go.mod h1:6AMpwZpsyCFwSovxzM78e+AsYxE8sGwiM6C3TytaWeI= +github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.4 h1:Ec3LTJwwzqT1++63P12fhtdEbQhtPE7TBdD6rlhqrMM= +github.com/miekg/dns v1.0.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/go-homedir v0.0.0-20180523094522-3864e76763d9/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/montanaflynn/stats v0.0.0-20180911141734-db72e6cae808/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/oklog/oklog v0.0.0-20170918173356-f857583a70c3/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v0.0.0-20180308005104-6934b124db28 h1:Hbr3fbVPXea52oPQeP7KLSxP52g6SFaNY1IqAmUyEW0= +github.com/oklog/run v0.0.0-20180308005104-6934b124db28/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20180912035003-be2c049b30cc/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/opentracing-contrib/go-stdlib v0.0.0-20170113013457-1de4cc2120e7/go.mod h1:PLldrQSroqzH70Xl+1DQcGnefIbqsKR7UDaiux3zV+w= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.1 h1:IYN/cK5AaULfeMAlgFZSIBLSpsZ5MRHDy1fKBEqqJfQ= +github.com/opentracing/opentracing-go v1.0.1/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/peterbourgon/diskv v0.0.0-20180312054125-0646ccaebea1/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/peterbourgon/g2s v0.0.0-20170223122336-d4e7ad98afea/go.mod h1:1VcHEd3ro4QMoHfiNl/j7Jkln9+KQuorp0PItHMJYNg= +github.com/petermattis/goid v0.0.0-20170504144140-0ded85884ba5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= +github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU= +github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/prometheus/client_golang v0.9.1 h1:K47Rk0v/fkEfwfQet2KWhscE0cJzjgCCDBG2KHZoVno= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181119215939-b36ad289a3ea/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d h1:GoAlyOgbOEIFdaDqxJVlbOQ1DtGmZWs/Qau0hIlk+WQ= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/prometheus v2.7.1+incompatible h1:7bmH9kGNqg1/VYDDJZLC/xiLEhklrP99Tv7upJEmF5o= +github.com/prometheus/prometheus v2.7.1+incompatible/go.mod h1:aNuqjQW47j/yc/kN0cNZ8cOTBlBU8VbspEvNDfxe1To= +github.com/prometheus/tsdb v0.4.0 h1:pXJyEi/5p6UBmOrnzsZmYxLrZjxnRlEB78/qj3+a8Gk= +github.com/prometheus/tsdb v0.4.0/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rlmcpherson/s3gof3r v0.5.0/go.mod h1:s7vv7SMDPInkitQMuZzH615G7yWHdrU2r/Go7Bo71Rs= +github.com/rubyist/circuitbreaker v2.2.1+incompatible/go.mod h1:Ycs3JgJADPuzJDwffe12k6BZT8hxVi6lFK+gWYJLN4A= +github.com/samuel/go-zookeeper v0.0.0-20161028232340-1d7be4effb13/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sasha-s/go-deadlock v0.0.0-20161201235124-341000892f3d/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b h1:gQZ0qzfKHQIybLANtM3mBXNUtOfsCFXeTsnBqCsx1KM= +github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/serialx/hashring v0.0.0-20180504054112-49a4782e9908 h1:RRpyb4kheanCQVyYfOhkZoD/cwClvn12RzHex2ZmHxw= +github.com/serialx/hashring v0.0.0-20180504054112-49a4782e9908/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc= +github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/vfsgen v0.0.0-20180711163814-62bca832be04/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3 h1:KYQXGkl6vs02hK7pK4eIbw0NpNPedieTSTEiJ//bwGs= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a h1:gOpx8G595UYyvj8UK4+OFyY4rx037g3fmfhe5SasG3U= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190124100055-b90733256f2e h1:3GIlrlVLfkoipSReOMNAgApI0ajnalyLa/EZHHca/XI= +golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/time v0.0.0-20170424234030-8be79e1e0910 h1:bCMaBn7ph495H+x72gEvgcv+mDRd9dElbzo/mVCMxX4= +golang.org/x/time v0.0.0-20170424234030-8be79e1e0910/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181023010539-40a48ad93fbe/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +google.golang.org/api v0.0.0-20180506000402-20530fd5d65a/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/fsnotify/fsnotify.v1 v1.3.0/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE= +gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/square/go-jose.v2 v2.0.0-20180411045311-89060dee6a84 h1:ELQJ5WuT+ydETLCpWvAuw8iGBQRGoJq+A3RAbbAcZUY= +gopkg.in/square/go-jose.v2 v2.0.0-20180411045311-89060dee6a84/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/vmihailenco/msgpack.v2 v2.9.1/go.mod h1:/3Dn1Npt9+MYyLpYYXjInO/5jvMLamn+AEGwNEOatn8= +gopkg.in/yaml.v2 v2.2.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +k8s.io/api v0.0.0-20181213150558-05914d821849/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +k8s.io/apimachinery v0.0.0-20181127025237-2b1284ed4c93/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +k8s.io/client-go v2.0.0-alpha.0.0.20181121191925-a47917edff34+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +k8s.io/klog v0.1.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/kube-openapi v0.0.0-20180629012420-d83b052f768a/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +labix.org/v2/mgo v0.0.0-20140701140051-000000000287/go.mod h1:Lg7AYkt1uXJoR9oeSZ3W/8IXLdvOfIITgZnommstyz4= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/vendor/github.com/alecthomas/units/bytes_test.go b/vendor/github.com/alecthomas/units/bytes_test.go deleted file mode 100644 index 6cbc79de4..000000000 --- a/vendor/github.com/alecthomas/units/bytes_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package units - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestBase2BytesString(t *testing.T) { - assert.Equal(t, Base2Bytes(0).String(), "0B") - assert.Equal(t, Base2Bytes(1025).String(), "1KiB1B") - assert.Equal(t, Base2Bytes(1048577).String(), "1MiB1B") -} - -func TestParseBase2Bytes(t *testing.T) { - n, err := ParseBase2Bytes("0B") - assert.NoError(t, err) - assert.Equal(t, 0, int(n)) - n, err = ParseBase2Bytes("1KB") - assert.NoError(t, err) - assert.Equal(t, 1024, int(n)) - n, err = ParseBase2Bytes("1MB1KB25B") - assert.NoError(t, err) - assert.Equal(t, 1049625, int(n)) - n, err = ParseBase2Bytes("1.5MB") - assert.NoError(t, err) - assert.Equal(t, 1572864, int(n)) -} - -func TestMetricBytesString(t *testing.T) { - assert.Equal(t, MetricBytes(0).String(), "0B") - assert.Equal(t, MetricBytes(1001).String(), "1KB1B") - assert.Equal(t, MetricBytes(1001025).String(), "1MB1KB25B") -} - -func TestParseMetricBytes(t *testing.T) { - n, err := ParseMetricBytes("0B") - assert.NoError(t, err) - assert.Equal(t, 0, int(n)) - n, err = ParseMetricBytes("1KB1B") - assert.NoError(t, err) - assert.Equal(t, 1001, int(n)) - n, err = ParseMetricBytes("1MB1KB25B") - assert.NoError(t, err) - assert.Equal(t, 1001025, int(n)) - n, err = ParseMetricBytes("1.5MB") - assert.NoError(t, err) - assert.Equal(t, 1500000, int(n)) -} diff --git a/vendor/github.com/armon/go-metrics/inmem_endpoint_test.go b/vendor/github.com/armon/go-metrics/inmem_endpoint_test.go deleted file mode 100644 index f9c6793b6..000000000 --- a/vendor/github.com/armon/go-metrics/inmem_endpoint_test.go +++ /dev/null @@ -1,133 +0,0 @@ -package metrics - -import ( - "testing" - "time" - - "github.com/pascaldekloe/goe/verify" -) - -func TestDisplayMetrics(t *testing.T) { - interval := 10 * time.Millisecond - inm := NewInmemSink(interval, 50*time.Millisecond) - - // Add data points - inm.SetGauge([]string{"foo", "bar"}, 42) - inm.SetGaugeWithLabels([]string{"foo", "bar"}, 23, []Label{{"a", "b"}}) - inm.EmitKey([]string{"foo", "bar"}, 42) - inm.IncrCounter([]string{"foo", "bar"}, 20) - inm.IncrCounter([]string{"foo", "bar"}, 22) - inm.IncrCounterWithLabels([]string{"foo", "bar"}, 20, []Label{{"a", "b"}}) - inm.IncrCounterWithLabels([]string{"foo", "bar"}, 40, []Label{{"a", "b"}}) - inm.AddSample([]string{"foo", "bar"}, 20) - inm.AddSample([]string{"foo", "bar"}, 24) - inm.AddSampleWithLabels([]string{"foo", "bar"}, 23, []Label{{"a", "b"}}) - inm.AddSampleWithLabels([]string{"foo", "bar"}, 33, []Label{{"a", "b"}}) - - data := inm.Data() - if len(data) != 1 { - t.Fatalf("bad: %v", data) - } - - expected := MetricsSummary{ - Timestamp: data[0].Interval.Round(time.Second).UTC().String(), - Gauges: []GaugeValue{ - { - Name: "foo.bar", - Hash: "foo.bar", - Value: float32(42), - DisplayLabels: map[string]string{}, - }, - { - Name: "foo.bar", - Hash: "foo.bar;a=b", - Value: float32(23), - DisplayLabels: map[string]string{"a": "b"}, - }, - }, - Points: []PointValue{ - { - Name: "foo.bar", - Points: []float32{42}, - }, - }, - Counters: []SampledValue{ - { - Name: "foo.bar", - Hash: "foo.bar", - AggregateSample: &AggregateSample{ - Count: 2, - Min: 20, - Max: 22, - Sum: 42, - SumSq: 884, - Rate: 4200, - }, - Mean: 21, - Stddev: 1.4142135623730951, - }, - { - Name: "foo.bar", - Hash: "foo.bar;a=b", - AggregateSample: &AggregateSample{ - Count: 2, - Min: 20, - Max: 40, - Sum: 60, - SumSq: 2000, - Rate: 6000, - }, - Mean: 30, - Stddev: 14.142135623730951, - DisplayLabels: map[string]string{"a": "b"}, - }, - }, - Samples: []SampledValue{ - { - Name: "foo.bar", - Hash: "foo.bar", - AggregateSample: &AggregateSample{ - Count: 2, - Min: 20, - Max: 24, - Sum: 44, - SumSq: 976, - Rate: 4400, - }, - Mean: 22, - Stddev: 2.8284271247461903, - }, - { - Name: "foo.bar", - Hash: "foo.bar;a=b", - AggregateSample: &AggregateSample{ - Count: 2, - Min: 23, - Max: 33, - Sum: 56, - SumSq: 1618, - Rate: 5600, - }, - Mean: 28, - Stddev: 7.0710678118654755, - DisplayLabels: map[string]string{"a": "b"}, - }, - }, - } - - raw, err := inm.DisplayMetrics(nil, nil) - if err != nil { - t.Fatalf("err: %v", err) - } - result := raw.(MetricsSummary) - - // Ignore the LastUpdated field, we don't export that anyway - for i, got := range result.Counters { - expected.Counters[i].LastUpdated = got.LastUpdated - } - for i, got := range result.Samples { - expected.Samples[i].LastUpdated = got.LastUpdated - } - - verify.Values(t, "all", result, expected) -} diff --git a/vendor/github.com/armon/go-metrics/inmem_signal_test.go b/vendor/github.com/armon/go-metrics/inmem_signal_test.go deleted file mode 100644 index c992d6bce..000000000 --- a/vendor/github.com/armon/go-metrics/inmem_signal_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package metrics - -import ( - "bytes" - "os" - "strings" - "syscall" - "testing" - "time" -) - -func TestInmemSignal(t *testing.T) { - buf := bytes.NewBuffer(nil) - inm := NewInmemSink(10*time.Millisecond, 50*time.Millisecond) - sig := NewInmemSignal(inm, syscall.SIGUSR1, buf) - defer sig.Stop() - - inm.SetGauge([]string{"foo"}, 42) - inm.EmitKey([]string{"bar"}, 42) - inm.IncrCounter([]string{"baz"}, 42) - inm.AddSample([]string{"wow"}, 42) - inm.SetGaugeWithLabels([]string{"asdf"}, 42, []Label{{"a", "b"}}) - inm.IncrCounterWithLabels([]string{"qwer"}, 42, []Label{{"a", "b"}}) - inm.AddSampleWithLabels([]string{"zxcv"}, 42, []Label{{"a", "b"}}) - - // Wait for period to end - time.Sleep(15 * time.Millisecond) - - // Send signal! - syscall.Kill(os.Getpid(), syscall.SIGUSR1) - - // Wait for flush - time.Sleep(10 * time.Millisecond) - - // Check the output - out := string(buf.Bytes()) - if !strings.Contains(out, "[G] 'foo': 42") { - t.Fatalf("bad: %v", out) - } - if !strings.Contains(out, "[P] 'bar': 42") { - t.Fatalf("bad: %v", out) - } - if !strings.Contains(out, "[C] 'baz': Count: 1 Sum: 42") { - t.Fatalf("bad: %v", out) - } - if !strings.Contains(out, "[S] 'wow': Count: 1 Sum: 42") { - t.Fatalf("bad: %v", out) - } - if !strings.Contains(out, "[G] 'asdf.b': 42") { - t.Fatalf("bad: %v", out) - } - if !strings.Contains(out, "[C] 'qwer.b': Count: 1 Sum: 42") { - t.Fatalf("bad: %v", out) - } - if !strings.Contains(out, "[S] 'zxcv.b': Count: 1 Sum: 42") { - t.Fatalf("bad: %v", out) - } -} diff --git a/vendor/github.com/armon/go-metrics/inmem_test.go b/vendor/github.com/armon/go-metrics/inmem_test.go deleted file mode 100644 index 3b037c70d..000000000 --- a/vendor/github.com/armon/go-metrics/inmem_test.go +++ /dev/null @@ -1,190 +0,0 @@ -package metrics - -import ( - "math" - "net/url" - "strings" - "testing" - "time" -) - -func TestInmemSink(t *testing.T) { - inm := NewInmemSink(10*time.Millisecond, 50*time.Millisecond) - - data := inm.Data() - if len(data) != 1 { - t.Fatalf("bad: %v", data) - } - - // Add data points - inm.SetGauge([]string{"foo", "bar"}, 42) - inm.SetGaugeWithLabels([]string{"foo", "bar"}, 23, []Label{{"a", "b"}}) - inm.EmitKey([]string{"foo", "bar"}, 42) - inm.IncrCounter([]string{"foo", "bar"}, 20) - inm.IncrCounter([]string{"foo", "bar"}, 22) - inm.IncrCounterWithLabels([]string{"foo", "bar"}, 20, []Label{{"a", "b"}}) - inm.IncrCounterWithLabels([]string{"foo", "bar"}, 22, []Label{{"a", "b"}}) - inm.AddSample([]string{"foo", "bar"}, 20) - inm.AddSample([]string{"foo", "bar"}, 22) - inm.AddSampleWithLabels([]string{"foo", "bar"}, 23, []Label{{"a", "b"}}) - - data = inm.Data() - if len(data) != 1 { - t.Fatalf("bad: %v", data) - } - - intvM := data[0] - intvM.RLock() - - if time.Now().Sub(intvM.Interval) > 10*time.Millisecond { - t.Fatalf("interval too old") - } - if intvM.Gauges["foo.bar"].Value != 42 { - t.Fatalf("bad val: %v", intvM.Gauges) - } - if intvM.Gauges["foo.bar;a=b"].Value != 23 { - t.Fatalf("bad val: %v", intvM.Gauges) - } - if intvM.Points["foo.bar"][0] != 42 { - t.Fatalf("bad val: %v", intvM.Points) - } - - for _, agg := range []SampledValue{intvM.Counters["foo.bar"], intvM.Counters["foo.bar;a=b"]} { - if agg.Count != 2 { - t.Fatalf("bad val: %v", agg) - } - if agg.Rate != 4200 { - t.Fatalf("bad val: %v", agg.Rate) - } - if agg.Sum != 42 { - t.Fatalf("bad val: %v", agg) - } - if agg.SumSq != 884 { - t.Fatalf("bad val: %v", agg) - } - if agg.Min != 20 { - t.Fatalf("bad val: %v", agg) - } - if agg.Max != 22 { - t.Fatalf("bad val: %v", agg) - } - if agg.AggregateSample.Mean() != 21 { - t.Fatalf("bad val: %v", agg) - } - if agg.AggregateSample.Stddev() != math.Sqrt(2) { - t.Fatalf("bad val: %v", agg) - } - - if agg.LastUpdated.IsZero() { - t.Fatalf("agg.LastUpdated is not set: %v", agg) - } - - diff := time.Now().Sub(agg.LastUpdated).Seconds() - if diff > 1 { - t.Fatalf("time diff too great: %f", diff) - } - } - - if _, ok := intvM.Samples["foo.bar"]; !ok { - t.Fatalf("missing sample") - } - - if _, ok := intvM.Samples["foo.bar;a=b"]; !ok { - t.Fatalf("missing sample") - } - - intvM.RUnlock() - - for i := 1; i < 10; i++ { - time.Sleep(10 * time.Millisecond) - inm.SetGauge([]string{"foo", "bar"}, 42) - data = inm.Data() - if len(data) != min(i+1, 5) { - t.Fatalf("bad: %v", data) - } - } - - // Should not exceed 5 intervals! - time.Sleep(10 * time.Millisecond) - inm.SetGauge([]string{"foo", "bar"}, 42) - data = inm.Data() - if len(data) != 5 { - t.Fatalf("bad: %v", data) - } -} - -func TestNewInmemSinkFromURL(t *testing.T) { - for _, tc := range []struct { - desc string - input string - expectErr string - expectInterval time.Duration - expectRetain time.Duration - }{ - { - desc: "interval and duration are set via query params", - input: "inmem://?interval=11s&retain=22s", - expectInterval: duration(t, "11s"), - expectRetain: duration(t, "22s"), - }, - { - desc: "interval is required", - input: "inmem://?retain=22s", - expectErr: "Bad 'interval' param", - }, - { - desc: "interval must be a duration", - input: "inmem://?retain=30s&interval=HIYA", - expectErr: "Bad 'interval' param", - }, - { - desc: "retain is required", - input: "inmem://?interval=30s", - expectErr: "Bad 'retain' param", - }, - { - desc: "retain must be a valid duration", - input: "inmem://?interval=30s&retain=HELLO", - expectErr: "Bad 'retain' param", - }, - } { - t.Run(tc.desc, func(t *testing.T) { - u, err := url.Parse(tc.input) - if err != nil { - t.Fatalf("error parsing URL: %s", err) - } - ms, err := NewInmemSinkFromURL(u) - if tc.expectErr != "" { - if !strings.Contains(err.Error(), tc.expectErr) { - t.Fatalf("expected err: %q, to contain: %q", err, tc.expectErr) - } - } else { - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - is := ms.(*InmemSink) - if is.interval != tc.expectInterval { - t.Fatalf("expected interval %s, got: %s", tc.expectInterval, is.interval) - } - if is.retain != tc.expectRetain { - t.Fatalf("expected retain %s, got: %s", tc.expectRetain, is.retain) - } - } - }) - } -} - -func min(a, b int) int { - if a < b { - return a - } - return b -} - -func duration(t *testing.T, s string) time.Duration { - dur, err := time.ParseDuration(s) - if err != nil { - t.Fatalf("error parsing duration: %s", err) - } - return dur -} diff --git a/vendor/github.com/armon/go-metrics/metrics_test.go b/vendor/github.com/armon/go-metrics/metrics_test.go deleted file mode 100644 index 3fed72978..000000000 --- a/vendor/github.com/armon/go-metrics/metrics_test.go +++ /dev/null @@ -1,493 +0,0 @@ -package metrics - -import ( - "reflect" - "runtime" - "testing" - "time" -) - -func mockMetric() (*MockSink, *Metrics) { - m := &MockSink{} - met := &Metrics{Config: Config{FilterDefault: true}, sink: m} - return m, met -} - -func TestMetrics_SetGauge(t *testing.T) { - m, met := mockMetric() - met.SetGauge([]string{"key"}, float32(1)) - if m.keys[0][0] != "key" { - t.Fatalf("") - } - if m.vals[0] != 1 { - t.Fatalf("") - } - - m, met = mockMetric() - labels := []Label{{"a", "b"}} - met.SetGaugeWithLabels([]string{"key"}, float32(1), labels) - if m.keys[0][0] != "key" { - t.Fatalf("") - } - if m.vals[0] != 1 { - t.Fatalf("") - } - if !reflect.DeepEqual(m.labels[0], labels) { - t.Fatalf("") - } - - m, met = mockMetric() - met.HostName = "test" - met.EnableHostname = true - met.SetGauge([]string{"key"}, float32(1)) - if m.keys[0][0] != "test" || m.keys[0][1] != "key" { - t.Fatalf("") - } - if m.vals[0] != 1 { - t.Fatalf("") - } - - m, met = mockMetric() - met.EnableTypePrefix = true - met.SetGauge([]string{"key"}, float32(1)) - if m.keys[0][0] != "gauge" || m.keys[0][1] != "key" { - t.Fatalf("") - } - if m.vals[0] != 1 { - t.Fatalf("") - } - - m, met = mockMetric() - met.ServiceName = "service" - met.SetGauge([]string{"key"}, float32(1)) - if m.keys[0][0] != "service" || m.keys[0][1] != "key" { - t.Fatalf("") - } - if m.vals[0] != 1 { - t.Fatalf("") - } -} - -func TestMetrics_EmitKey(t *testing.T) { - m, met := mockMetric() - met.EmitKey([]string{"key"}, float32(1)) - if m.keys[0][0] != "key" { - t.Fatalf("") - } - if m.vals[0] != 1 { - t.Fatalf("") - } - - m, met = mockMetric() - met.EnableTypePrefix = true - met.EmitKey([]string{"key"}, float32(1)) - if m.keys[0][0] != "kv" || m.keys[0][1] != "key" { - t.Fatalf("") - } - if m.vals[0] != 1 { - t.Fatalf("") - } - - m, met = mockMetric() - met.ServiceName = "service" - met.EmitKey([]string{"key"}, float32(1)) - if m.keys[0][0] != "service" || m.keys[0][1] != "key" { - t.Fatalf("") - } - if m.vals[0] != 1 { - t.Fatalf("") - } -} - -func TestMetrics_IncrCounter(t *testing.T) { - m, met := mockMetric() - met.IncrCounter([]string{"key"}, float32(1)) - if m.keys[0][0] != "key" { - t.Fatalf("") - } - if m.vals[0] != 1 { - t.Fatalf("") - } - - m, met = mockMetric() - labels := []Label{{"a", "b"}} - met.IncrCounterWithLabels([]string{"key"}, float32(1), labels) - if m.keys[0][0] != "key" { - t.Fatalf("") - } - if m.vals[0] != 1 { - t.Fatalf("") - } - if !reflect.DeepEqual(m.labels[0], labels) { - t.Fatalf("") - } - - m, met = mockMetric() - met.EnableTypePrefix = true - met.IncrCounter([]string{"key"}, float32(1)) - if m.keys[0][0] != "counter" || m.keys[0][1] != "key" { - t.Fatalf("") - } - if m.vals[0] != 1 { - t.Fatalf("") - } - - m, met = mockMetric() - met.ServiceName = "service" - met.IncrCounter([]string{"key"}, float32(1)) - if m.keys[0][0] != "service" || m.keys[0][1] != "key" { - t.Fatalf("") - } - if m.vals[0] != 1 { - t.Fatalf("") - } -} - -func TestMetrics_AddSample(t *testing.T) { - m, met := mockMetric() - met.AddSample([]string{"key"}, float32(1)) - if m.keys[0][0] != "key" { - t.Fatalf("") - } - if m.vals[0] != 1 { - t.Fatalf("") - } - - m, met = mockMetric() - labels := []Label{{"a", "b"}} - met.AddSampleWithLabels([]string{"key"}, float32(1), labels) - if m.keys[0][0] != "key" { - t.Fatalf("") - } - if m.vals[0] != 1 { - t.Fatalf("") - } - if !reflect.DeepEqual(m.labels[0], labels) { - t.Fatalf("") - } - - m, met = mockMetric() - met.EnableTypePrefix = true - met.AddSample([]string{"key"}, float32(1)) - if m.keys[0][0] != "sample" || m.keys[0][1] != "key" { - t.Fatalf("") - } - if m.vals[0] != 1 { - t.Fatalf("") - } - - m, met = mockMetric() - met.ServiceName = "service" - met.AddSample([]string{"key"}, float32(1)) - if m.keys[0][0] != "service" || m.keys[0][1] != "key" { - t.Fatalf("") - } - if m.vals[0] != 1 { - t.Fatalf("") - } -} - -func TestMetrics_MeasureSince(t *testing.T) { - m, met := mockMetric() - met.TimerGranularity = time.Millisecond - n := time.Now() - met.MeasureSince([]string{"key"}, n) - if m.keys[0][0] != "key" { - t.Fatalf("") - } - if m.vals[0] > 0.1 { - t.Fatalf("") - } - - m, met = mockMetric() - met.TimerGranularity = time.Millisecond - labels := []Label{{"a", "b"}} - met.MeasureSinceWithLabels([]string{"key"}, n, labels) - if m.keys[0][0] != "key" { - t.Fatalf("") - } - if m.vals[0] > 0.1 { - t.Fatalf("") - } - if !reflect.DeepEqual(m.labels[0], labels) { - t.Fatalf("") - } - - m, met = mockMetric() - met.TimerGranularity = time.Millisecond - met.EnableTypePrefix = true - met.MeasureSince([]string{"key"}, n) - if m.keys[0][0] != "timer" || m.keys[0][1] != "key" { - t.Fatalf("") - } - if m.vals[0] > 0.1 { - t.Fatalf("") - } - - m, met = mockMetric() - met.TimerGranularity = time.Millisecond - met.ServiceName = "service" - met.MeasureSince([]string{"key"}, n) - if m.keys[0][0] != "service" || m.keys[0][1] != "key" { - t.Fatalf("") - } - if m.vals[0] > 0.1 { - t.Fatalf("") - } -} - -func TestMetrics_EmitRuntimeStats(t *testing.T) { - runtime.GC() - m, met := mockMetric() - met.emitRuntimeStats() - - if m.keys[0][0] != "runtime" || m.keys[0][1] != "num_goroutines" { - t.Fatalf("bad key %v", m.keys) - } - if m.vals[0] <= 1 { - t.Fatalf("bad val: %v", m.vals) - } - - if m.keys[1][0] != "runtime" || m.keys[1][1] != "alloc_bytes" { - t.Fatalf("bad key %v", m.keys) - } - if m.vals[1] <= 40000 { - t.Fatalf("bad val: %v", m.vals) - } - - if m.keys[2][0] != "runtime" || m.keys[2][1] != "sys_bytes" { - t.Fatalf("bad key %v", m.keys) - } - if m.vals[2] <= 100000 { - t.Fatalf("bad val: %v", m.vals) - } - - if m.keys[3][0] != "runtime" || m.keys[3][1] != "malloc_count" { - t.Fatalf("bad key %v", m.keys) - } - if m.vals[3] <= 100 { - t.Fatalf("bad val: %v", m.vals) - } - - if m.keys[4][0] != "runtime" || m.keys[4][1] != "free_count" { - t.Fatalf("bad key %v", m.keys) - } - if m.vals[4] <= 100 { - t.Fatalf("bad val: %v", m.vals) - } - - if m.keys[5][0] != "runtime" || m.keys[5][1] != "heap_objects" { - t.Fatalf("bad key %v", m.keys) - } - if m.vals[5] <= 100 { - t.Fatalf("bad val: %v", m.vals) - } - - if m.keys[6][0] != "runtime" || m.keys[6][1] != "total_gc_pause_ns" { - t.Fatalf("bad key %v", m.keys) - } - if m.vals[6] <= 100000 { - t.Fatalf("bad val: %v", m.vals) - } - - if m.keys[7][0] != "runtime" || m.keys[7][1] != "total_gc_runs" { - t.Fatalf("bad key %v", m.keys) - } - if m.vals[7] < 1 { - t.Fatalf("bad val: %v", m.vals) - } - - if m.keys[8][0] != "runtime" || m.keys[8][1] != "gc_pause_ns" { - t.Fatalf("bad key %v", m.keys) - } - if m.vals[8] <= 1000 { - t.Fatalf("bad val: %v", m.vals) - } -} - -func TestInsert(t *testing.T) { - k := []string{"hi", "bob"} - exp := []string{"hi", "there", "bob"} - out := insert(1, "there", k) - if !reflect.DeepEqual(exp, out) { - t.Fatalf("bad insert %v %v", exp, out) - } -} - -func TestMetrics_Filter_Blacklist(t *testing.T) { - m := &MockSink{} - conf := DefaultConfig("") - conf.AllowedPrefixes = []string{"service", "debug.thing"} - conf.BlockedPrefixes = []string{"debug"} - conf.EnableHostname = false - met, err := New(conf, m) - if err != nil { - t.Fatal(err) - } - - // Allowed by default - key := []string{"thing"} - met.SetGauge(key, 1) - if !reflect.DeepEqual(m.keys[0], key) { - t.Fatalf("key doesn't exist %v, %v", m.keys[0], key) - } - if m.vals[0] != 1 { - t.Fatalf("bad val: %v", m.vals[0]) - } - - // Allowed by filter - key = []string{"service", "thing"} - met.SetGauge(key, 2) - if !reflect.DeepEqual(m.keys[1], key) { - t.Fatalf("key doesn't exist") - } - if m.vals[1] != 2 { - t.Fatalf("bad val: %v", m.vals[1]) - } - - // Allowed by filter, subtree of a blocked entry - key = []string{"debug", "thing"} - met.SetGauge(key, 3) - if !reflect.DeepEqual(m.keys[2], key) { - t.Fatalf("key doesn't exist") - } - if m.vals[2] != 3 { - t.Fatalf("bad val: %v", m.vals[2]) - } - - // Blocked by filter - key = []string{"debug", "other-thing"} - met.SetGauge(key, 4) - if len(m.keys) != 3 { - t.Fatalf("key shouldn't exist") - } -} - -func HasElem(s interface{}, elem interface{}) bool { - arrV := reflect.ValueOf(s) - - if arrV.Kind() == reflect.Slice { - for i := 0; i < arrV.Len(); i++ { - if arrV.Index(i).Interface() == elem { - return true - } - } - } - - return false -} - -func TestMetrics_Filter_Whitelist(t *testing.T) { - m := &MockSink{} - conf := DefaultConfig("") - conf.AllowedPrefixes = []string{"service", "debug.thing"} - conf.BlockedPrefixes = []string{"debug"} - conf.FilterDefault = false - conf.EnableHostname = false - conf.BlockedLabels = []string{"bad_label"} - met, err := New(conf, m) - if err != nil { - t.Fatal(err) - } - - // Blocked by default - key := []string{"thing"} - met.SetGauge(key, 1) - if len(m.keys) != 0 { - t.Fatalf("key should not exist") - } - - // Allowed by filter - key = []string{"service", "thing"} - met.SetGauge(key, 2) - if !reflect.DeepEqual(m.keys[0], key) { - t.Fatalf("key doesn't exist") - } - if m.vals[0] != 2 { - t.Fatalf("bad val: %v", m.vals[0]) - } - - // Allowed by filter, subtree of a blocked entry - key = []string{"debug", "thing"} - met.SetGauge(key, 3) - if !reflect.DeepEqual(m.keys[1], key) { - t.Fatalf("key doesn't exist") - } - if m.vals[1] != 3 { - t.Fatalf("bad val: %v", m.vals[1]) - } - - // Blocked by filter - key = []string{"debug", "other-thing"} - met.SetGauge(key, 4) - if len(m.keys) != 2 { - t.Fatalf("key shouldn't exist") - } - // Test blacklisting of labels - key = []string{"debug", "thing"} - goodLabel := Label{Name: "good", Value: "should be present"} - badLabel := Label{Name: "bad_label", Value: "should not be there"} - labels := []Label{badLabel, goodLabel} - met.SetGaugeWithLabels(key, 3, labels) - if !reflect.DeepEqual(m.keys[1], key) { - t.Fatalf("key doesn't exist") - } - if m.vals[2] != 3 { - t.Fatalf("bad val: %v", m.vals[1]) - } - if HasElem(m.labels[2], badLabel) { - t.Fatalf("bad_label should not be present in %v", m.labels[2]) - } - if !HasElem(m.labels[2], goodLabel) { - t.Fatalf("good label is not present in %v", m.labels[2]) - } -} - -func TestMetrics_Filter_Labels_Whitelist(t *testing.T) { - m := &MockSink{} - conf := DefaultConfig("") - conf.AllowedPrefixes = []string{"service", "debug.thing"} - conf.BlockedPrefixes = []string{"debug"} - conf.FilterDefault = false - conf.EnableHostname = false - conf.AllowedLabels = []string{"good_label"} - conf.BlockedLabels = []string{"bad_label"} - met, err := New(conf, m) - if err != nil { - t.Fatal(err) - } - - // Blocked by default - key := []string{"thing"} - key = []string{"debug", "thing"} - goodLabel := Label{Name: "good_label", Value: "should be present"} - notReallyGoodLabel := Label{Name: "not_really_good_label", Value: "not whitelisted, but not blacklisted"} - badLabel := Label{Name: "bad_label", Value: "should not be there"} - labels := []Label{badLabel, notReallyGoodLabel, goodLabel} - met.SetGaugeWithLabels(key, 1, labels) - - if HasElem(m.labels[0], badLabel) { - t.Fatalf("bad_label should not be present in %v", m.labels[0]) - } - if HasElem(m.labels[0], notReallyGoodLabel) { - t.Fatalf("not_really_good_label should not be present in %v", m.labels[0]) - } - if !HasElem(m.labels[0], goodLabel) { - t.Fatalf("good label is not present in %v", m.labels[0]) - } - - conf.AllowedLabels = nil - met.UpdateFilterAndLabels(conf.AllowedPrefixes, conf.BlockedLabels, conf.AllowedLabels, conf.BlockedLabels) - met.SetGaugeWithLabels(key, 1, labels) - - if HasElem(m.labels[1], badLabel) { - t.Fatalf("bad_label should not be present in %v", m.labels[1]) - } - // Since no whitelist, not_really_good_label should be there - if !HasElem(m.labels[1], notReallyGoodLabel) { - t.Fatalf("not_really_good_label is not present in %v", m.labels[1]) - } - if !HasElem(m.labels[1], goodLabel) { - t.Fatalf("good label is not present in %v", m.labels[1]) - } -} diff --git a/vendor/github.com/armon/go-metrics/sink_test.go b/vendor/github.com/armon/go-metrics/sink_test.go deleted file mode 100644 index 714f99b81..000000000 --- a/vendor/github.com/armon/go-metrics/sink_test.go +++ /dev/null @@ -1,272 +0,0 @@ -package metrics - -import ( - "reflect" - "strings" - "testing" -) - -type MockSink struct { - keys [][]string - vals []float32 - labels [][]Label -} - -func (m *MockSink) SetGauge(key []string, val float32) { - m.SetGaugeWithLabels(key, val, nil) -} -func (m *MockSink) SetGaugeWithLabels(key []string, val float32, labels []Label) { - m.keys = append(m.keys, key) - m.vals = append(m.vals, val) - m.labels = append(m.labels, labels) -} -func (m *MockSink) EmitKey(key []string, val float32) { - m.keys = append(m.keys, key) - m.vals = append(m.vals, val) - m.labels = append(m.labels, nil) -} -func (m *MockSink) IncrCounter(key []string, val float32) { - m.IncrCounterWithLabels(key, val, nil) -} -func (m *MockSink) IncrCounterWithLabels(key []string, val float32, labels []Label) { - m.keys = append(m.keys, key) - m.vals = append(m.vals, val) - m.labels = append(m.labels, labels) -} -func (m *MockSink) AddSample(key []string, val float32) { - m.AddSampleWithLabels(key, val, nil) -} -func (m *MockSink) AddSampleWithLabels(key []string, val float32, labels []Label) { - m.keys = append(m.keys, key) - m.vals = append(m.vals, val) - m.labels = append(m.labels, labels) -} - -func TestFanoutSink_Gauge(t *testing.T) { - m1 := &MockSink{} - m2 := &MockSink{} - fh := &FanoutSink{m1, m2} - - k := []string{"test"} - v := float32(42.0) - fh.SetGauge(k, v) - - if !reflect.DeepEqual(m1.keys[0], k) { - t.Fatalf("key not equal") - } - if !reflect.DeepEqual(m2.keys[0], k) { - t.Fatalf("key not equal") - } - if !reflect.DeepEqual(m1.vals[0], v) { - t.Fatalf("val not equal") - } - if !reflect.DeepEqual(m2.vals[0], v) { - t.Fatalf("val not equal") - } -} - -func TestFanoutSink_Gauge_Labels(t *testing.T) { - m1 := &MockSink{} - m2 := &MockSink{} - fh := &FanoutSink{m1, m2} - - k := []string{"test"} - v := float32(42.0) - l := []Label{{"a", "b"}} - fh.SetGaugeWithLabels(k, v, l) - - if !reflect.DeepEqual(m1.keys[0], k) { - t.Fatalf("key not equal") - } - if !reflect.DeepEqual(m2.keys[0], k) { - t.Fatalf("key not equal") - } - if !reflect.DeepEqual(m1.vals[0], v) { - t.Fatalf("val not equal") - } - if !reflect.DeepEqual(m2.vals[0], v) { - t.Fatalf("val not equal") - } - if !reflect.DeepEqual(m1.labels[0], l) { - t.Fatalf("labels not equal") - } - if !reflect.DeepEqual(m2.labels[0], l) { - t.Fatalf("labels not equal") - } -} - -func TestFanoutSink_Key(t *testing.T) { - m1 := &MockSink{} - m2 := &MockSink{} - fh := &FanoutSink{m1, m2} - - k := []string{"test"} - v := float32(42.0) - fh.EmitKey(k, v) - - if !reflect.DeepEqual(m1.keys[0], k) { - t.Fatalf("key not equal") - } - if !reflect.DeepEqual(m2.keys[0], k) { - t.Fatalf("key not equal") - } - if !reflect.DeepEqual(m1.vals[0], v) { - t.Fatalf("val not equal") - } - if !reflect.DeepEqual(m2.vals[0], v) { - t.Fatalf("val not equal") - } -} - -func TestFanoutSink_Counter(t *testing.T) { - m1 := &MockSink{} - m2 := &MockSink{} - fh := &FanoutSink{m1, m2} - - k := []string{"test"} - v := float32(42.0) - fh.IncrCounter(k, v) - - if !reflect.DeepEqual(m1.keys[0], k) { - t.Fatalf("key not equal") - } - if !reflect.DeepEqual(m2.keys[0], k) { - t.Fatalf("key not equal") - } - if !reflect.DeepEqual(m1.vals[0], v) { - t.Fatalf("val not equal") - } - if !reflect.DeepEqual(m2.vals[0], v) { - t.Fatalf("val not equal") - } -} - -func TestFanoutSink_Counter_Labels(t *testing.T) { - m1 := &MockSink{} - m2 := &MockSink{} - fh := &FanoutSink{m1, m2} - - k := []string{"test"} - v := float32(42.0) - l := []Label{{"a", "b"}} - fh.IncrCounterWithLabels(k, v, l) - - if !reflect.DeepEqual(m1.keys[0], k) { - t.Fatalf("key not equal") - } - if !reflect.DeepEqual(m2.keys[0], k) { - t.Fatalf("key not equal") - } - if !reflect.DeepEqual(m1.vals[0], v) { - t.Fatalf("val not equal") - } - if !reflect.DeepEqual(m2.vals[0], v) { - t.Fatalf("val not equal") - } - if !reflect.DeepEqual(m1.labels[0], l) { - t.Fatalf("labels not equal") - } - if !reflect.DeepEqual(m2.labels[0], l) { - t.Fatalf("labels not equal") - } -} - -func TestFanoutSink_Sample(t *testing.T) { - m1 := &MockSink{} - m2 := &MockSink{} - fh := &FanoutSink{m1, m2} - - k := []string{"test"} - v := float32(42.0) - fh.AddSample(k, v) - - if !reflect.DeepEqual(m1.keys[0], k) { - t.Fatalf("key not equal") - } - if !reflect.DeepEqual(m2.keys[0], k) { - t.Fatalf("key not equal") - } - if !reflect.DeepEqual(m1.vals[0], v) { - t.Fatalf("val not equal") - } - if !reflect.DeepEqual(m2.vals[0], v) { - t.Fatalf("val not equal") - } -} - -func TestFanoutSink_Sample_Labels(t *testing.T) { - m1 := &MockSink{} - m2 := &MockSink{} - fh := &FanoutSink{m1, m2} - - k := []string{"test"} - v := float32(42.0) - l := []Label{{"a", "b"}} - fh.AddSampleWithLabels(k, v, l) - - if !reflect.DeepEqual(m1.keys[0], k) { - t.Fatalf("key not equal") - } - if !reflect.DeepEqual(m2.keys[0], k) { - t.Fatalf("key not equal") - } - if !reflect.DeepEqual(m1.vals[0], v) { - t.Fatalf("val not equal") - } - if !reflect.DeepEqual(m2.vals[0], v) { - t.Fatalf("val not equal") - } - if !reflect.DeepEqual(m1.labels[0], l) { - t.Fatalf("labels not equal") - } - if !reflect.DeepEqual(m2.labels[0], l) { - t.Fatalf("labels not equal") - } -} - -func TestNewMetricSinkFromURL(t *testing.T) { - for _, tc := range []struct { - desc string - input string - expect reflect.Type - expectErr string - }{ - { - desc: "statsd scheme yields a StatsdSink", - input: "statsd://someserver:123", - expect: reflect.TypeOf(&StatsdSink{}), - }, - { - desc: "statsite scheme yields a StatsiteSink", - input: "statsite://someserver:123", - expect: reflect.TypeOf(&StatsiteSink{}), - }, - { - desc: "inmem scheme yields an InmemSink", - input: "inmem://?interval=30s&retain=30s", - expect: reflect.TypeOf(&InmemSink{}), - }, - { - desc: "unknown scheme yields an error", - input: "notasink://whatever", - expectErr: "unrecognized sink name: \"notasink\"", - }, - } { - t.Run(tc.desc, func(t *testing.T) { - ms, err := NewMetricSinkFromURL(tc.input) - if tc.expectErr != "" { - if !strings.Contains(err.Error(), tc.expectErr) { - t.Fatalf("expected err: %q to contain: %q", err, tc.expectErr) - } - } else { - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - got := reflect.TypeOf(ms) - if got != tc.expect { - t.Fatalf("expected return type to be %v, got: %v", tc.expect, got) - } - } - }) - } -} diff --git a/vendor/github.com/armon/go-metrics/start_test.go b/vendor/github.com/armon/go-metrics/start_test.go deleted file mode 100644 index 872d358ea..000000000 --- a/vendor/github.com/armon/go-metrics/start_test.go +++ /dev/null @@ -1,216 +0,0 @@ -package metrics - -import ( - "io/ioutil" - "log" - "reflect" - "sync/atomic" - "testing" - "time" -) - -func TestDefaultConfig(t *testing.T) { - conf := DefaultConfig("service") - if conf.ServiceName != "service" { - t.Fatalf("Bad name") - } - if conf.HostName == "" { - t.Fatalf("missing hostname") - } - if !conf.EnableHostname || !conf.EnableRuntimeMetrics { - t.Fatalf("expect true") - } - if conf.EnableTypePrefix { - t.Fatalf("expect false") - } - if conf.TimerGranularity != time.Millisecond { - t.Fatalf("bad granularity") - } - if conf.ProfileInterval != time.Second { - t.Fatalf("bad interval") - } -} - -func Test_GlobalMetrics(t *testing.T) { - var tests = []struct { - desc string - key []string - val float32 - fn func([]string, float32) - }{ - {"SetGauge", []string{"test"}, 42, SetGauge}, - {"EmitKey", []string{"test"}, 42, EmitKey}, - {"IncrCounter", []string{"test"}, 42, IncrCounter}, - {"AddSample", []string{"test"}, 42, AddSample}, - } - - for _, tt := range tests { - t.Run(tt.desc, func(t *testing.T) { - s := &MockSink{} - globalMetrics.Store(&Metrics{Config: Config{FilterDefault: true}, sink: s}) - tt.fn(tt.key, tt.val) - if got, want := s.keys[0], tt.key; !reflect.DeepEqual(got, want) { - t.Fatalf("got key %s want %s", got, want) - } - if got, want := s.vals[0], tt.val; !reflect.DeepEqual(got, want) { - t.Fatalf("got val %s want %s", got, want) - } - }) - } -} - -func Test_GlobalMetrics_Labels(t *testing.T) { - labels := []Label{{"a", "b"}} - var tests = []struct { - desc string - key []string - val float32 - fn func([]string, float32, []Label) - labels []Label - }{ - {"SetGaugeWithLabels", []string{"test"}, 42, SetGaugeWithLabels, labels}, - {"IncrCounterWithLabels", []string{"test"}, 42, IncrCounterWithLabels, labels}, - {"AddSampleWithLabels", []string{"test"}, 42, AddSampleWithLabels, labels}, - } - - for _, tt := range tests { - t.Run(tt.desc, func(t *testing.T) { - s := &MockSink{} - globalMetrics.Store(&Metrics{Config: Config{FilterDefault: true}, sink: s}) - tt.fn(tt.key, tt.val, tt.labels) - if got, want := s.keys[0], tt.key; !reflect.DeepEqual(got, want) { - t.Fatalf("got key %s want %s", got, want) - } - if got, want := s.vals[0], tt.val; !reflect.DeepEqual(got, want) { - t.Fatalf("got val %s want %s", got, want) - } - if got, want := s.labels[0], tt.labels; !reflect.DeepEqual(got, want) { - t.Fatalf("got val %s want %s", got, want) - } - }) - } -} - -func Test_GlobalMetrics_DefaultLabels(t *testing.T) { - config := Config{ - HostName: "host1", - ServiceName: "redis", - EnableHostnameLabel: true, - EnableServiceLabel: true, - FilterDefault: true, - } - labels := []Label{ - {"host", config.HostName}, - {"service", config.ServiceName}, - } - var tests = []struct { - desc string - key []string - val float32 - fn func([]string, float32, []Label) - labels []Label - }{ - {"SetGaugeWithLabels", []string{"test"}, 42, SetGaugeWithLabels, labels}, - {"IncrCounterWithLabels", []string{"test"}, 42, IncrCounterWithLabels, labels}, - {"AddSampleWithLabels", []string{"test"}, 42, AddSampleWithLabels, labels}, - } - - for _, tt := range tests { - t.Run(tt.desc, func(t *testing.T) { - s := &MockSink{} - globalMetrics.Store(&Metrics{Config: config, sink: s}) - tt.fn(tt.key, tt.val, nil) - if got, want := s.keys[0], tt.key; !reflect.DeepEqual(got, want) { - t.Fatalf("got key %s want %s", got, want) - } - if got, want := s.vals[0], tt.val; !reflect.DeepEqual(got, want) { - t.Fatalf("got val %s want %s", got, want) - } - if got, want := s.labels[0], tt.labels; !reflect.DeepEqual(got, want) { - t.Fatalf("got val %s want %s", got, want) - } - }) - } -} - -func Test_GlobalMetrics_MeasureSince(t *testing.T) { - s := &MockSink{} - m := &Metrics{sink: s, Config: Config{TimerGranularity: time.Millisecond, FilterDefault: true}} - globalMetrics.Store(m) - - k := []string{"test"} - now := time.Now() - MeasureSince(k, now) - - if !reflect.DeepEqual(s.keys[0], k) { - t.Fatalf("key not equal") - } - if s.vals[0] > 0.1 { - t.Fatalf("val too large %v", s.vals[0]) - } - - labels := []Label{{"a", "b"}} - MeasureSinceWithLabels(k, now, labels) - if got, want := s.keys[1], k; !reflect.DeepEqual(got, want) { - t.Fatalf("got key %s want %s", got, want) - } - if s.vals[1] > 0.1 { - t.Fatalf("val too large %v", s.vals[0]) - } - if got, want := s.labels[1], labels; !reflect.DeepEqual(got, want) { - t.Fatalf("got val %s want %s", got, want) - } -} - -func Test_GlobalMetrics_UpdateFilter(t *testing.T) { - globalMetrics.Store(&Metrics{Config: Config{ - AllowedPrefixes: []string{"a"}, - BlockedPrefixes: []string{"b"}, - AllowedLabels: []string{"1"}, - BlockedLabels: []string{"2"}, - }}) - UpdateFilterAndLabels([]string{"c"}, []string{"d"}, []string{"3"}, []string{"4"}) - - m := globalMetrics.Load().(*Metrics) - if m.AllowedPrefixes[0] != "c" { - t.Fatalf("bad: %v", m.AllowedPrefixes) - } - if m.BlockedPrefixes[0] != "d" { - t.Fatalf("bad: %v", m.BlockedPrefixes) - } - if m.AllowedLabels[0] != "3" { - t.Fatalf("bad: %v", m.AllowedPrefixes) - } - if m.BlockedLabels[0] != "4" { - t.Fatalf("bad: %v", m.AllowedPrefixes) - } - if _, ok := m.allowedLabels["3"]; !ok { - t.Fatalf("bad: %v", m.allowedLabels) - } - if _, ok := m.blockedLabels["4"]; !ok { - t.Fatalf("bad: %v", m.blockedLabels) - } -} - -// Benchmark_GlobalMetrics_Direct/direct-8 5000000 278 ns/op -// Benchmark_GlobalMetrics_Direct/atomic.Value-8 5000000 235 ns/op -func Benchmark_GlobalMetrics_Direct(b *testing.B) { - log.SetOutput(ioutil.Discard) - s := &MockSink{} - m := &Metrics{sink: s} - var v atomic.Value - v.Store(m) - k := []string{"test"} - b.Run("direct", func(b *testing.B) { - for i := 0; i < b.N; i++ { - m.IncrCounter(k, 1) - } - }) - b.Run("atomic.Value", func(b *testing.B) { - for i := 0; i < b.N; i++ { - v.Load().(*Metrics).IncrCounter(k, 1) - } - }) - // do something with m so that the compiler does not optimize this away - b.Logf("%d", m.lastNumGC) -} diff --git a/vendor/github.com/armon/go-metrics/statsd_test.go b/vendor/github.com/armon/go-metrics/statsd_test.go deleted file mode 100644 index bdf36cc00..000000000 --- a/vendor/github.com/armon/go-metrics/statsd_test.go +++ /dev/null @@ -1,175 +0,0 @@ -package metrics - -import ( - "bufio" - "bytes" - "net" - "net/url" - "strings" - "testing" - "time" -) - -func TestStatsd_Flatten(t *testing.T) { - s := &StatsdSink{} - flat := s.flattenKey([]string{"a", "b", "c", "d"}) - if flat != "a.b.c.d" { - t.Fatalf("Bad flat") - } -} - -func TestStatsd_PushFullQueue(t *testing.T) { - q := make(chan string, 1) - q <- "full" - - s := &StatsdSink{metricQueue: q} - s.pushMetric("omit") - - out := <-q - if out != "full" { - t.Fatalf("bad val %v", out) - } - - select { - case v := <-q: - t.Fatalf("bad val %v", v) - default: - } -} - -func TestStatsd_Conn(t *testing.T) { - addr := "127.0.0.1:7524" - done := make(chan bool) - go func() { - list, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 7524}) - if err != nil { - panic(err) - } - defer list.Close() - buf := make([]byte, 1500) - n, err := list.Read(buf) - if err != nil { - panic(err) - } - buf = buf[:n] - reader := bufio.NewReader(bytes.NewReader(buf)) - - line, err := reader.ReadString('\n') - if err != nil { - t.Fatalf("unexpected err %s", err) - } - if line != "gauge.val:1.000000|g\n" { - t.Fatalf("bad line %s", line) - } - - line, err = reader.ReadString('\n') - if err != nil { - t.Fatalf("unexpected err %s", err) - } - if line != "gauge_labels.val.label:2.000000|g\n" { - t.Fatalf("bad line %s", line) - } - - line, err = reader.ReadString('\n') - if err != nil { - t.Fatalf("unexpected err %s", err) - } - if line != "key.other:3.000000|kv\n" { - t.Fatalf("bad line %s", line) - } - - line, err = reader.ReadString('\n') - if err != nil { - t.Fatalf("unexpected err %s", err) - } - if line != "counter.me:4.000000|c\n" { - t.Fatalf("bad line %s", line) - } - - line, err = reader.ReadString('\n') - if err != nil { - t.Fatalf("unexpected err %s", err) - } - if line != "counter_labels.me.label:5.000000|c\n" { - t.Fatalf("bad line %s", line) - } - - line, err = reader.ReadString('\n') - if err != nil { - t.Fatalf("unexpected err %s", err) - } - if line != "sample.slow_thingy:6.000000|ms\n" { - t.Fatalf("bad line %s", line) - } - - line, err = reader.ReadString('\n') - if err != nil { - t.Fatalf("unexpected err %s", err) - } - if line != "sample_labels.slow_thingy.label:7.000000|ms\n" { - t.Fatalf("bad line %s", line) - } - - done <- true - }() - s, err := NewStatsdSink(addr) - if err != nil { - t.Fatalf("bad error") - } - - s.SetGauge([]string{"gauge", "val"}, float32(1)) - s.SetGaugeWithLabels([]string{"gauge_labels", "val"}, float32(2), []Label{{"a", "label"}}) - s.EmitKey([]string{"key", "other"}, float32(3)) - s.IncrCounter([]string{"counter", "me"}, float32(4)) - s.IncrCounterWithLabels([]string{"counter_labels", "me"}, float32(5), []Label{{"a", "label"}}) - s.AddSample([]string{"sample", "slow thingy"}, float32(6)) - s.AddSampleWithLabels([]string{"sample_labels", "slow thingy"}, float32(7), []Label{{"a", "label"}}) - - select { - case <-done: - s.Shutdown() - case <-time.After(3 * time.Second): - t.Fatalf("timeout") - } -} - -func TestNewStatsdSinkFromURL(t *testing.T) { - for _, tc := range []struct { - desc string - input string - expectErr string - expectAddr string - }{ - { - desc: "address is populated", - input: "statsd://statsd.service.consul", - expectAddr: "statsd.service.consul", - }, - { - desc: "address includes port", - input: "statsd://statsd.service.consul:1234", - expectAddr: "statsd.service.consul:1234", - }, - } { - t.Run(tc.desc, func(t *testing.T) { - u, err := url.Parse(tc.input) - if err != nil { - t.Fatalf("error parsing URL: %s", err) - } - ms, err := NewStatsdSinkFromURL(u) - if tc.expectErr != "" { - if !strings.Contains(err.Error(), tc.expectErr) { - t.Fatalf("expected err: %q, to contain: %q", err, tc.expectErr) - } - } else { - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - is := ms.(*StatsdSink) - if is.addr != tc.expectAddr { - t.Fatalf("expected addr %s, got: %s", tc.expectAddr, is.addr) - } - } - }) - } -} diff --git a/vendor/github.com/armon/go-metrics/statsite_test.go b/vendor/github.com/armon/go-metrics/statsite_test.go deleted file mode 100644 index 92687889b..000000000 --- a/vendor/github.com/armon/go-metrics/statsite_test.go +++ /dev/null @@ -1,171 +0,0 @@ -package metrics - -import ( - "bufio" - "net" - "net/url" - "strings" - "testing" - "time" -) - -func acceptConn(addr string) net.Conn { - ln, _ := net.Listen("tcp", addr) - conn, _ := ln.Accept() - return conn -} - -func TestStatsite_Flatten(t *testing.T) { - s := &StatsiteSink{} - flat := s.flattenKey([]string{"a", "b", "c", "d"}) - if flat != "a.b.c.d" { - t.Fatalf("Bad flat") - } -} - -func TestStatsite_PushFullQueue(t *testing.T) { - q := make(chan string, 1) - q <- "full" - - s := &StatsiteSink{metricQueue: q} - s.pushMetric("omit") - - out := <-q - if out != "full" { - t.Fatalf("bad val %v", out) - } - - select { - case v := <-q: - t.Fatalf("bad val %v", v) - default: - } -} - -func TestStatsite_Conn(t *testing.T) { - addr := "localhost:7523" - done := make(chan bool) - go func() { - conn := acceptConn(addr) - reader := bufio.NewReader(conn) - - line, err := reader.ReadString('\n') - if err != nil { - t.Fatalf("unexpected err %s", err) - } - if line != "gauge.val:1.000000|g\n" { - t.Fatalf("bad line %s", line) - } - - line, err = reader.ReadString('\n') - if err != nil { - t.Fatalf("unexpected err %s", err) - } - if line != "gauge_labels.val.label:2.000000|g\n" { - t.Fatalf("bad line %s", line) - } - - line, err = reader.ReadString('\n') - if err != nil { - t.Fatalf("unexpected err %s", err) - } - if line != "key.other:3.000000|kv\n" { - t.Fatalf("bad line %s", line) - } - - line, err = reader.ReadString('\n') - if err != nil { - t.Fatalf("unexpected err %s", err) - } - if line != "counter.me:4.000000|c\n" { - t.Fatalf("bad line %s", line) - } - - line, err = reader.ReadString('\n') - if err != nil { - t.Fatalf("unexpected err %s", err) - } - if line != "counter_labels.me.label:5.000000|c\n" { - t.Fatalf("bad line %s", line) - } - - line, err = reader.ReadString('\n') - if err != nil { - t.Fatalf("unexpected err %s", err) - } - if line != "sample.slow_thingy:6.000000|ms\n" { - t.Fatalf("bad line %s", line) - } - - line, err = reader.ReadString('\n') - if err != nil { - t.Fatalf("unexpected err %s", err) - } - if line != "sample_labels.slow_thingy.label:7.000000|ms\n" { - t.Fatalf("bad line %s", line) - } - - conn.Close() - done <- true - }() - s, err := NewStatsiteSink(addr) - if err != nil { - t.Fatalf("bad error") - } - - s.SetGauge([]string{"gauge", "val"}, float32(1)) - s.SetGaugeWithLabels([]string{"gauge_labels", "val"}, float32(2), []Label{{"a", "label"}}) - s.EmitKey([]string{"key", "other"}, float32(3)) - s.IncrCounter([]string{"counter", "me"}, float32(4)) - s.IncrCounterWithLabels([]string{"counter_labels", "me"}, float32(5), []Label{{"a", "label"}}) - s.AddSample([]string{"sample", "slow thingy"}, float32(6)) - s.AddSampleWithLabels([]string{"sample_labels", "slow thingy"}, float32(7), []Label{{"a", "label"}}) - - select { - case <-done: - s.Shutdown() - case <-time.After(3 * time.Second): - t.Fatalf("timeout") - } -} - -func TestNewStatsiteSinkFromURL(t *testing.T) { - for _, tc := range []struct { - desc string - input string - expectErr string - expectAddr string - }{ - { - desc: "address is populated", - input: "statsd://statsd.service.consul", - expectAddr: "statsd.service.consul", - }, - { - desc: "address includes port", - input: "statsd://statsd.service.consul:1234", - expectAddr: "statsd.service.consul:1234", - }, - } { - t.Run(tc.desc, func(t *testing.T) { - u, err := url.Parse(tc.input) - if err != nil { - t.Fatalf("error parsing URL: %s", err) - } - ms, err := NewStatsiteSinkFromURL(u) - if tc.expectErr != "" { - if !strings.Contains(err.Error(), tc.expectErr) { - t.Fatalf("expected err: %q, to contain: %q", err, tc.expectErr) - } - } else { - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - is := ms.(*StatsiteSink) - if is.addr != tc.expectAddr { - t.Fatalf("expected addr %s, got: %s", tc.expectAddr, is.addr) - } - } - }) - } -} diff --git a/vendor/github.com/beorn7/perks/quantile/bench_test.go b/vendor/github.com/beorn7/perks/quantile/bench_test.go deleted file mode 100644 index 0bd0e4e77..000000000 --- a/vendor/github.com/beorn7/perks/quantile/bench_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package quantile - -import ( - "testing" -) - -func BenchmarkInsertTargeted(b *testing.B) { - b.ReportAllocs() - - s := NewTargeted(Targets) - b.ResetTimer() - for i := float64(0); i < float64(b.N); i++ { - s.Insert(i) - } -} - -func BenchmarkInsertTargetedSmallEpsilon(b *testing.B) { - s := NewTargeted(TargetsSmallEpsilon) - b.ResetTimer() - for i := float64(0); i < float64(b.N); i++ { - s.Insert(i) - } -} - -func BenchmarkInsertBiased(b *testing.B) { - s := NewLowBiased(0.01) - b.ResetTimer() - for i := float64(0); i < float64(b.N); i++ { - s.Insert(i) - } -} - -func BenchmarkInsertBiasedSmallEpsilon(b *testing.B) { - s := NewLowBiased(0.0001) - b.ResetTimer() - for i := float64(0); i < float64(b.N); i++ { - s.Insert(i) - } -} - -func BenchmarkQuery(b *testing.B) { - s := NewTargeted(Targets) - for i := float64(0); i < 1e6; i++ { - s.Insert(i) - } - b.ResetTimer() - n := float64(b.N) - for i := float64(0); i < n; i++ { - s.Query(i / n) - } -} - -func BenchmarkQuerySmallEpsilon(b *testing.B) { - s := NewTargeted(TargetsSmallEpsilon) - for i := float64(0); i < 1e6; i++ { - s.Insert(i) - } - b.ResetTimer() - n := float64(b.N) - for i := float64(0); i < n; i++ { - s.Query(i / n) - } -} diff --git a/vendor/github.com/beorn7/perks/quantile/example_test.go b/vendor/github.com/beorn7/perks/quantile/example_test.go deleted file mode 100644 index ab3293aaf..000000000 --- a/vendor/github.com/beorn7/perks/quantile/example_test.go +++ /dev/null @@ -1,121 +0,0 @@ -// +build go1.1 - -package quantile_test - -import ( - "bufio" - "fmt" - "log" - "os" - "strconv" - "time" - - "github.com/beorn7/perks/quantile" -) - -func Example_simple() { - ch := make(chan float64) - go sendFloats(ch) - - // Compute the 50th, 90th, and 99th percentile. - q := quantile.NewTargeted(map[float64]float64{ - 0.50: 0.005, - 0.90: 0.001, - 0.99: 0.0001, - }) - for v := range ch { - q.Insert(v) - } - - fmt.Println("perc50:", q.Query(0.50)) - fmt.Println("perc90:", q.Query(0.90)) - fmt.Println("perc99:", q.Query(0.99)) - fmt.Println("count:", q.Count()) - // Output: - // perc50: 5 - // perc90: 16 - // perc99: 223 - // count: 2388 -} - -func Example_mergeMultipleStreams() { - // Scenario: - // We have multiple database shards. On each shard, there is a process - // collecting query response times from the database logs and inserting - // them into a Stream (created via NewTargeted(0.90)), much like the - // Simple example. These processes expose a network interface for us to - // ask them to serialize and send us the results of their - // Stream.Samples so we may Merge and Query them. - // - // NOTES: - // * These sample sets are small, allowing us to get them - // across the network much faster than sending the entire list of data - // points. - // - // * For this to work correctly, we must supply the same quantiles - // a priori the process collecting the samples supplied to NewTargeted, - // even if we do not plan to query them all here. - ch := make(chan quantile.Samples) - getDBQuerySamples(ch) - q := quantile.NewTargeted(map[float64]float64{0.90: 0.001}) - for samples := range ch { - q.Merge(samples) - } - fmt.Println("perc90:", q.Query(0.90)) -} - -func Example_window() { - // Scenario: We want the 90th, 95th, and 99th percentiles for each - // minute. - - ch := make(chan float64) - go sendStreamValues(ch) - - tick := time.NewTicker(1 * time.Minute) - q := quantile.NewTargeted(map[float64]float64{ - 0.90: 0.001, - 0.95: 0.0005, - 0.99: 0.0001, - }) - for { - select { - case t := <-tick.C: - flushToDB(t, q.Samples()) - q.Reset() - case v := <-ch: - q.Insert(v) - } - } -} - -func sendStreamValues(ch chan float64) { - // Use your imagination -} - -func flushToDB(t time.Time, samples quantile.Samples) { - // Use your imagination -} - -// This is a stub for the above example. In reality this would hit the remote -// servers via http or something like it. -func getDBQuerySamples(ch chan quantile.Samples) {} - -func sendFloats(ch chan<- float64) { - f, err := os.Open("exampledata.txt") - if err != nil { - log.Fatal(err) - } - sc := bufio.NewScanner(f) - for sc.Scan() { - b := sc.Bytes() - v, err := strconv.ParseFloat(string(b), 64) - if err != nil { - log.Fatal(err) - } - ch <- v - } - if sc.Err() != nil { - log.Fatal(sc.Err()) - } - close(ch) -} diff --git a/vendor/github.com/beorn7/perks/quantile/stream.go b/vendor/github.com/beorn7/perks/quantile/stream.go index 587b1fc5b..d7d14f8eb 100644 --- a/vendor/github.com/beorn7/perks/quantile/stream.go +++ b/vendor/github.com/beorn7/perks/quantile/stream.go @@ -77,15 +77,20 @@ func NewHighBiased(epsilon float64) *Stream { // is guaranteed to be within (Quantile±Epsilon). // // See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error properties. -func NewTargeted(targets map[float64]float64) *Stream { +func NewTargeted(targetMap map[float64]float64) *Stream { + // Convert map to slice to avoid slow iterations on a map. + // ƒ is called on the hot path, so converting the map to a slice + // beforehand results in significant CPU savings. + targets := targetMapToSlice(targetMap) + ƒ := func(s *stream, r float64) float64 { var m = math.MaxFloat64 var f float64 - for quantile, epsilon := range targets { - if quantile*s.n <= r { - f = (2 * epsilon * r) / quantile + for _, t := range targets { + if t.quantile*s.n <= r { + f = (2 * t.epsilon * r) / t.quantile } else { - f = (2 * epsilon * (s.n - r)) / (1 - quantile) + f = (2 * t.epsilon * (s.n - r)) / (1 - t.quantile) } if f < m { m = f @@ -96,6 +101,25 @@ func NewTargeted(targets map[float64]float64) *Stream { return newStream(ƒ) } +type target struct { + quantile float64 + epsilon float64 +} + +func targetMapToSlice(targetMap map[float64]float64) []target { + targets := make([]target, 0, len(targetMap)) + + for quantile, epsilon := range targetMap { + t := target{ + quantile: quantile, + epsilon: epsilon, + } + targets = append(targets, t) + } + + return targets +} + // Stream computes quantiles for a stream of float64s. It is not thread-safe by // design. Take care when using across multiple goroutines. type Stream struct { @@ -133,7 +157,7 @@ func (s *Stream) Query(q float64) float64 { if l == 0 { return 0 } - i := int(float64(l) * q) + i := int(math.Ceil(float64(l) * q)) if i > 0 { i -= 1 } diff --git a/vendor/github.com/beorn7/perks/quantile/stream_test.go b/vendor/github.com/beorn7/perks/quantile/stream_test.go deleted file mode 100644 index 4dba05449..000000000 --- a/vendor/github.com/beorn7/perks/quantile/stream_test.go +++ /dev/null @@ -1,188 +0,0 @@ -package quantile - -import ( - "math" - "math/rand" - "sort" - "testing" -) - -var ( - Targets = map[float64]float64{ - 0.01: 0.001, - 0.10: 0.01, - 0.50: 0.05, - 0.90: 0.01, - 0.99: 0.001, - } - TargetsSmallEpsilon = map[float64]float64{ - 0.01: 0.0001, - 0.10: 0.001, - 0.50: 0.005, - 0.90: 0.001, - 0.99: 0.0001, - } - LowQuantiles = []float64{0.01, 0.1, 0.5} - HighQuantiles = []float64{0.99, 0.9, 0.5} -) - -const RelativeEpsilon = 0.01 - -func verifyPercsWithAbsoluteEpsilon(t *testing.T, a []float64, s *Stream) { - sort.Float64s(a) - for quantile, epsilon := range Targets { - n := float64(len(a)) - k := int(quantile * n) - lower := int((quantile - epsilon) * n) - if lower < 1 { - lower = 1 - } - upper := int(math.Ceil((quantile + epsilon) * n)) - if upper > len(a) { - upper = len(a) - } - w, min, max := a[k-1], a[lower-1], a[upper-1] - if g := s.Query(quantile); g < min || g > max { - t.Errorf("q=%f: want %v [%f,%f], got %v", quantile, w, min, max, g) - } - } -} - -func verifyLowPercsWithRelativeEpsilon(t *testing.T, a []float64, s *Stream) { - sort.Float64s(a) - for _, qu := range LowQuantiles { - n := float64(len(a)) - k := int(qu * n) - - lowerRank := int((1 - RelativeEpsilon) * qu * n) - upperRank := int(math.Ceil((1 + RelativeEpsilon) * qu * n)) - w, min, max := a[k-1], a[lowerRank-1], a[upperRank-1] - if g := s.Query(qu); g < min || g > max { - t.Errorf("q=%f: want %v [%f,%f], got %v", qu, w, min, max, g) - } - } -} - -func verifyHighPercsWithRelativeEpsilon(t *testing.T, a []float64, s *Stream) { - sort.Float64s(a) - for _, qu := range HighQuantiles { - n := float64(len(a)) - k := int(qu * n) - - lowerRank := int((1 - (1+RelativeEpsilon)*(1-qu)) * n) - upperRank := int(math.Ceil((1 - (1-RelativeEpsilon)*(1-qu)) * n)) - w, min, max := a[k-1], a[lowerRank-1], a[upperRank-1] - if g := s.Query(qu); g < min || g > max { - t.Errorf("q=%f: want %v [%f,%f], got %v", qu, w, min, max, g) - } - } -} - -func populateStream(s *Stream) []float64 { - a := make([]float64, 0, 1e5+100) - for i := 0; i < cap(a); i++ { - v := rand.NormFloat64() - // Add 5% asymmetric outliers. - if i%20 == 0 { - v = v*v + 1 - } - s.Insert(v) - a = append(a, v) - } - return a -} - -func TestTargetedQuery(t *testing.T) { - rand.Seed(42) - s := NewTargeted(Targets) - a := populateStream(s) - verifyPercsWithAbsoluteEpsilon(t, a, s) -} - -func TestLowBiasedQuery(t *testing.T) { - rand.Seed(42) - s := NewLowBiased(RelativeEpsilon) - a := populateStream(s) - verifyLowPercsWithRelativeEpsilon(t, a, s) -} - -func TestHighBiasedQuery(t *testing.T) { - rand.Seed(42) - s := NewHighBiased(RelativeEpsilon) - a := populateStream(s) - verifyHighPercsWithRelativeEpsilon(t, a, s) -} - -// BrokenTestTargetedMerge is broken, see Merge doc comment. -func BrokenTestTargetedMerge(t *testing.T) { - rand.Seed(42) - s1 := NewTargeted(Targets) - s2 := NewTargeted(Targets) - a := populateStream(s1) - a = append(a, populateStream(s2)...) - s1.Merge(s2.Samples()) - verifyPercsWithAbsoluteEpsilon(t, a, s1) -} - -// BrokenTestLowBiasedMerge is broken, see Merge doc comment. -func BrokenTestLowBiasedMerge(t *testing.T) { - rand.Seed(42) - s1 := NewLowBiased(RelativeEpsilon) - s2 := NewLowBiased(RelativeEpsilon) - a := populateStream(s1) - a = append(a, populateStream(s2)...) - s1.Merge(s2.Samples()) - verifyLowPercsWithRelativeEpsilon(t, a, s2) -} - -// BrokenTestHighBiasedMerge is broken, see Merge doc comment. -func BrokenTestHighBiasedMerge(t *testing.T) { - rand.Seed(42) - s1 := NewHighBiased(RelativeEpsilon) - s2 := NewHighBiased(RelativeEpsilon) - a := populateStream(s1) - a = append(a, populateStream(s2)...) - s1.Merge(s2.Samples()) - verifyHighPercsWithRelativeEpsilon(t, a, s2) -} - -func TestUncompressed(t *testing.T) { - q := NewTargeted(Targets) - for i := 100; i > 0; i-- { - q.Insert(float64(i)) - } - if g := q.Count(); g != 100 { - t.Errorf("want count 100, got %d", g) - } - // Before compression, Query should have 100% accuracy. - for quantile := range Targets { - w := quantile * 100 - if g := q.Query(quantile); g != w { - t.Errorf("want %f, got %f", w, g) - } - } -} - -func TestUncompressedSamples(t *testing.T) { - q := NewTargeted(map[float64]float64{0.99: 0.001}) - for i := 1; i <= 100; i++ { - q.Insert(float64(i)) - } - if g := q.Samples().Len(); g != 100 { - t.Errorf("want count 100, got %d", g) - } -} - -func TestUncompressedOne(t *testing.T) { - q := NewTargeted(map[float64]float64{0.99: 0.01}) - q.Insert(3.14) - if g := q.Query(0.90); g != 3.14 { - t.Error("want PI, got", g) - } -} - -func TestDefaults(t *testing.T) { - if g := NewTargeted(map[float64]float64{0.99: 0.001}).Query(0.99); g != 0 { - t.Errorf("want 0, got %f", g) - } -} diff --git a/vendor/github.com/cespare/xxhash/.travis.yml b/vendor/github.com/cespare/xxhash/.travis.yml deleted file mode 100644 index c516ea88d..000000000 --- a/vendor/github.com/cespare/xxhash/.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/README.md b/vendor/github.com/cespare/xxhash/README.md index cbcc6ea5e..0982fd25e 100644 --- a/vendor/github.com/cespare/xxhash/README.md +++ b/vendor/github.com/cespare/xxhash/README.md @@ -1,29 +1,24 @@ # 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) xxhash is a Go implementation of the 64-bit [xxHash](http://cyan4973.github.io/xxHash/) algorithm, XXH64. This is a high-quality hashing algorithm that is much faster than anything in the Go standard library. -This package provides a straightforward API: +The API is very small, taking its cue from the other hashing packages in the +standard library: -``` -func Sum64(b []byte) uint64 -func Sum64String(s string) uint64 -type Digest struct{ ... } - func New() *Digest -``` + $ go doc github.com/cespare/xxhash ! + package xxhash // import "github.com/cespare/xxhash" -The `Digest` type implements hash.Hash64. Its key methods are: + Package xxhash implements the 64-bit variant of xxHash (XXH64) as described + at http://cyan4973.github.io/xxHash/. -``` -func (*Digest) Write([]byte) (int, error) -func (*Digest) WriteString(string) (int, error) -func (*Digest) Sum64() uint64 -``` + func New() hash.Hash64 + func Sum64(b []byte) uint64 + func Sum64String(s string) uint64 This implementation provides a fast pure-Go implementation and an even faster assembly implementation for amd64. @@ -31,25 +26,25 @@ assembly implementation for amd64. ## Benchmarks Here are some quick benchmarks comparing the pure-Go and assembly -implementations of Sum64. +implementations of Sum64 against another popular Go XXH64 implementation, +[github.com/OneOfOne/xxhash](https://github.com/OneOfOne/xxhash): -| input size | purego | asm | -| --- | --- | --- | -| 5 B | 979.66 MB/s | 1291.17 MB/s | -| 100 B | 7475.26 MB/s | 7973.40 MB/s | -| 4 KB | 17573.46 MB/s | 17602.65 MB/s | -| 10 MB | 17131.46 MB/s | 17142.16 MB/s | +| input size | OneOfOne | cespare (purego) | cespare | +| --- | --- | --- | --- | +| 5 B | 416 MB/s | 720 MB/s | 872 MB/s | +| 100 B | 3980 MB/s | 5013 MB/s | 5252 MB/s | +| 4 KB | 12727 MB/s | 12999 MB/s | 13026 MB/s | +| 10 MB | 9879 MB/s | 10775 MB/s | 10913 MB/s | -These numbers were generated on Ubuntu 18.04 with an Intel i7-8700K CPU using -the following commands under Go 1.11.2: +These numbers were generated with: ``` -$ go test -tags purego -benchtime 10s -bench '/xxhash,direct,bytes' -$ go test -benchtime 10s -bench '/xxhash,direct,bytes' +$ go test -benchtime 10s -bench '/OneOfOne,' +$ go test -tags purego -benchtime 10s -bench '/xxhash,' +$ go test -benchtime 10s -bench '/xxhash,' ``` ## Projects using this package - [InfluxDB](https://github.com/influxdata/influxdb) - [Prometheus](https://github.com/prometheus/prometheus) -- [FreeCache](https://github.com/coocood/freecache) diff --git a/vendor/github.com/cespare/xxhash/go.mod b/vendor/github.com/cespare/xxhash/go.mod index b83ab6ac3..10605a6a5 100644 --- a/vendor/github.com/cespare/xxhash/go.mod +++ b/vendor/github.com/cespare/xxhash/go.mod @@ -1,7 +1,6 @@ -module github.com/cespare/xxhash/v2 +module github.com/cespare/xxhash require ( github.com/OneOfOne/xxhash v1.2.2 - github.com/cespare/xxhash v1.1.0 // indirect github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 ) diff --git a/vendor/github.com/cespare/xxhash/go.sum b/vendor/github.com/cespare/xxhash/go.sum index a7f183224..f6b554261 100644 --- a/vendor/github.com/cespare/xxhash/go.sum +++ b/vendor/github.com/cespare/xxhash/go.sum @@ -1,6 +1,4 @@ github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= diff --git a/vendor/github.com/cespare/xxhash/rotate.go b/vendor/github.com/cespare/xxhash/rotate.go new file mode 100644 index 000000000..f3eac5ebc --- /dev/null +++ b/vendor/github.com/cespare/xxhash/rotate.go @@ -0,0 +1,14 @@ +// +build !go1.9 + +package xxhash + +// TODO(caleb): After Go 1.10 comes out, remove this fallback code. + +func rol1(x uint64) uint64 { return (x << 1) | (x >> (64 - 1)) } +func rol7(x uint64) uint64 { return (x << 7) | (x >> (64 - 7)) } +func rol11(x uint64) uint64 { return (x << 11) | (x >> (64 - 11)) } +func rol12(x uint64) uint64 { return (x << 12) | (x >> (64 - 12)) } +func rol18(x uint64) uint64 { return (x << 18) | (x >> (64 - 18)) } +func rol23(x uint64) uint64 { return (x << 23) | (x >> (64 - 23)) } +func rol27(x uint64) uint64 { return (x << 27) | (x >> (64 - 27)) } +func rol31(x uint64) uint64 { return (x << 31) | (x >> (64 - 31)) } diff --git a/vendor/github.com/cespare/xxhash/rotate19.go b/vendor/github.com/cespare/xxhash/rotate19.go new file mode 100644 index 000000000..b99612bab --- /dev/null +++ b/vendor/github.com/cespare/xxhash/rotate19.go @@ -0,0 +1,14 @@ +// +build go1.9 + +package xxhash + +import "math/bits" + +func rol1(x uint64) uint64 { return bits.RotateLeft64(x, 1) } +func rol7(x uint64) uint64 { return bits.RotateLeft64(x, 7) } +func rol11(x uint64) uint64 { return bits.RotateLeft64(x, 11) } +func rol12(x uint64) uint64 { return bits.RotateLeft64(x, 12) } +func rol18(x uint64) uint64 { return bits.RotateLeft64(x, 18) } +func rol23(x uint64) uint64 { return bits.RotateLeft64(x, 23) } +func rol27(x uint64) uint64 { return bits.RotateLeft64(x, 27) } +func rol31(x uint64) uint64 { return bits.RotateLeft64(x, 31) } diff --git a/vendor/github.com/cespare/xxhash/xxhash.go b/vendor/github.com/cespare/xxhash/xxhash.go index db0b35fbe..f896bd28f 100644 --- a/vendor/github.com/cespare/xxhash/xxhash.go +++ b/vendor/github.com/cespare/xxhash/xxhash.go @@ -4,8 +4,7 @@ package xxhash import ( "encoding/binary" - "errors" - "math/bits" + "hash" ) const ( @@ -30,79 +29,72 @@ var ( prime5v = prime5 ) -// Digest implements hash.Hash64. -type Digest struct { +type xxh struct { v1 uint64 v2 uint64 v3 uint64 v4 uint64 - total uint64 + total int mem [32]byte n int // how much of mem is used } -// New creates a new Digest that computes the 64-bit xxHash algorithm. -func New() *Digest { - var d Digest - d.Reset() - return &d +// New creates a new hash.Hash64 that implements the 64-bit xxHash algorithm. +func New() hash.Hash64 { + var x xxh + x.Reset() + return &x } -// Reset clears the Digest's state so that it can be reused. -func (d *Digest) Reset() { - d.v1 = prime1v + prime2 - d.v2 = prime2 - d.v3 = 0 - d.v4 = -prime1v - d.total = 0 - d.n = 0 +func (x *xxh) Reset() { + x.n = 0 + x.total = 0 + x.v1 = prime1v + prime2 + x.v2 = prime2 + x.v3 = 0 + x.v4 = -prime1v } -// Size always returns 8 bytes. -func (d *Digest) Size() int { return 8 } +func (x *xxh) Size() int { return 8 } +func (x *xxh) BlockSize() int { return 32 } -// BlockSize always returns 32 bytes. -func (d *Digest) BlockSize() int { return 32 } - -// Write adds more data to d. It always returns len(b), nil. -func (d *Digest) Write(b []byte) (n int, err error) { +// Write adds more data to x. It always returns len(b), nil. +func (x *xxh) Write(b []byte) (n int, err error) { n = len(b) - d.total += uint64(n) + x.total += len(b) - if d.n+n < 32 { + if x.n+len(b) < 32 { // This new data doesn't even fill the current block. - copy(d.mem[d.n:], b) - d.n += n + copy(x.mem[x.n:], b) + x.n += len(b) return } - if d.n > 0 { + if x.n > 0 { // Finish off the partial block. - copy(d.mem[d.n:], b) - d.v1 = round(d.v1, u64(d.mem[0:8])) - d.v2 = round(d.v2, u64(d.mem[8:16])) - d.v3 = round(d.v3, u64(d.mem[16:24])) - d.v4 = round(d.v4, u64(d.mem[24:32])) - b = b[32-d.n:] - d.n = 0 + copy(x.mem[x.n:], b) + x.v1 = round(x.v1, u64(x.mem[0:8])) + x.v2 = round(x.v2, u64(x.mem[8:16])) + x.v3 = round(x.v3, u64(x.mem[16:24])) + x.v4 = round(x.v4, u64(x.mem[24:32])) + b = b[32-x.n:] + x.n = 0 } if len(b) >= 32 { // One or more full blocks left. - nw := writeBlocks(d, b) - b = b[nw:] + b = writeBlocks(x, b) } // Store any remaining partial block. - copy(d.mem[:], b) - d.n = len(b) + copy(x.mem[:], b) + x.n = len(b) return } -// Sum appends the current hash to b and returns the resulting slice. -func (d *Digest) Sum(b []byte) []byte { - s := d.Sum64() +func (x *xxh) Sum(b []byte) []byte { + s := x.Sum64() return append( b, byte(s>>56), @@ -116,36 +108,35 @@ func (d *Digest) Sum(b []byte) []byte { ) } -// Sum64 returns the current hash. -func (d *Digest) Sum64() uint64 { +func (x *xxh) Sum64() uint64 { var h uint64 - if d.total >= 32 { - v1, v2, v3, v4 := d.v1, d.v2, d.v3, d.v4 + if x.total >= 32 { + v1, v2, v3, v4 := x.v1, x.v2, x.v3, x.v4 h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4) h = mergeRound(h, v1) h = mergeRound(h, v2) h = mergeRound(h, v3) h = mergeRound(h, v4) } else { - h = d.v3 + prime5 + h = x.v3 + prime5 } - h += d.total + h += uint64(x.total) - i, end := 0, d.n + i, end := 0, x.n for ; i+8 <= end; i += 8 { - k1 := round(0, u64(d.mem[i:i+8])) + k1 := round(0, u64(x.mem[i:i+8])) h ^= k1 h = rol27(h)*prime1 + prime4 } if i+4 <= end { - h ^= uint64(u32(d.mem[i:i+4])) * prime1 + h ^= uint64(u32(x.mem[i:i+4])) * prime1 h = rol23(h)*prime2 + prime3 i += 4 } for i < end { - h ^= uint64(d.mem[i]) * prime5 + h ^= uint64(x.mem[i]) * prime5 h = rol11(h) * prime1 i++ } @@ -159,56 +150,6 @@ func (d *Digest) Sum64() uint64 { return h } -const ( - magic = "xxh\x06" - marshaledSize = len(magic) + 8*5 + 32 -) - -// MarshalBinary implements the encoding.BinaryMarshaler interface. -func (d *Digest) MarshalBinary() ([]byte, error) { - b := make([]byte, 0, marshaledSize) - b = append(b, magic...) - b = appendUint64(b, d.v1) - b = appendUint64(b, d.v2) - b = appendUint64(b, d.v3) - b = appendUint64(b, d.v4) - b = appendUint64(b, d.total) - b = append(b, d.mem[:d.n]...) - b = b[:len(b)+len(d.mem)-d.n] - return b, nil -} - -// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. -func (d *Digest) UnmarshalBinary(b []byte) error { - if len(b) < len(magic) || string(b[:len(magic)]) != magic { - return errors.New("xxhash: invalid hash state identifier") - } - if len(b) != marshaledSize { - return errors.New("xxhash: invalid hash state size") - } - b = b[len(magic):] - b, d.v1 = consumeUint64(b) - b, d.v2 = consumeUint64(b) - b, d.v3 = consumeUint64(b) - 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 -} - -func appendUint64(b []byte, x uint64) []byte { - var a [8]byte - binary.LittleEndian.PutUint64(a[:], x) - return append(b, a[:]...) -} - -func consumeUint64(b []byte) ([]byte, uint64) { - x := u64(b) - return b[8:], x -} - func u64(b []byte) uint64 { return binary.LittleEndian.Uint64(b) } func u32(b []byte) uint32 { return binary.LittleEndian.Uint32(b) } @@ -225,12 +166,3 @@ func mergeRound(acc, val uint64) uint64 { acc = acc*prime1 + prime4 return acc } - -func rol1(x uint64) uint64 { return bits.RotateLeft64(x, 1) } -func rol7(x uint64) uint64 { return bits.RotateLeft64(x, 7) } -func rol11(x uint64) uint64 { return bits.RotateLeft64(x, 11) } -func rol12(x uint64) uint64 { return bits.RotateLeft64(x, 12) } -func rol18(x uint64) uint64 { return bits.RotateLeft64(x, 18) } -func rol23(x uint64) uint64 { return bits.RotateLeft64(x, 23) } -func rol27(x uint64) uint64 { return bits.RotateLeft64(x, 27) } -func rol31(x uint64) uint64 { return bits.RotateLeft64(x, 31) } diff --git a/vendor/github.com/cespare/xxhash/xxhash_amd64.go b/vendor/github.com/cespare/xxhash/xxhash_amd64.go index 35318d7c4..d61765268 100644 --- a/vendor/github.com/cespare/xxhash/xxhash_amd64.go +++ b/vendor/github.com/cespare/xxhash/xxhash_amd64.go @@ -9,5 +9,4 @@ package xxhash //go:noescape func Sum64(b []byte) uint64 -//go:noescape -func writeBlocks(*Digest, []byte) int +func writeBlocks(x *xxh, b []byte) []byte diff --git a/vendor/github.com/cespare/xxhash/xxhash_amd64.s b/vendor/github.com/cespare/xxhash/xxhash_amd64.s index d580e32ae..757f2011f 100644 --- a/vendor/github.com/cespare/xxhash/xxhash_amd64.s +++ b/vendor/github.com/cespare/xxhash/xxhash_amd64.s @@ -170,22 +170,23 @@ finalize: RET // writeBlocks uses the same registers as above except that it uses AX to store -// the d pointer. +// the x pointer. -// func writeBlocks(d *Digest, b []byte) int -TEXT ·writeBlocks(SB), NOSPLIT, $0-40 +// func writeBlocks(x *xxh, b []byte) []byte +TEXT ·writeBlocks(SB), NOSPLIT, $0-56 // Load fixed primes needed for round. MOVQ ·prime1v(SB), R13 MOVQ ·prime2v(SB), R14 // Load slice. MOVQ b_base+8(FP), CX + MOVQ CX, ret_base+32(FP) // initialize return base pointer; see NOTE below MOVQ b_len+16(FP), DX LEAQ (CX)(DX*1), BX SUBQ $32, BX - // Load vN from d. - MOVQ d+0(FP), AX + // Load vN from x. + MOVQ x+0(FP), AX MOVQ 0(AX), R8 // v1 MOVQ 8(AX), R9 // v2 MOVQ 16(AX), R10 // v3 @@ -202,14 +203,31 @@ blockLoop: CMPQ CX, BX JLE blockLoop - // Copy vN back to d. + // Copy vN back to x. MOVQ R8, 0(AX) MOVQ R9, 8(AX) 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) + // Construct return slice. + // NOTE: It's important that we don't construct a slice that has a base + // pointer off the end of the original slice, as in Go 1.7+ this will + // cause runtime crashes. (See discussion in, for example, + // https://github.com/golang/go/issues/16772.) + // Therefore, we calculate the length/cap first, and if they're zero, we + // keep the old base. This is what the compiler does as well if you + // write code like + // b = b[len(b):] + + // New length is 32 - (CX - BX) -> BX+32 - CX. + ADDQ $32, BX + SUBQ CX, BX + JZ afterSetBase + + MOVQ CX, ret_base+32(FP) + +afterSetBase: + MOVQ BX, ret_len+40(FP) + MOVQ BX, ret_cap+48(FP) // set cap == len RET diff --git a/vendor/github.com/cespare/xxhash/xxhash_other.go b/vendor/github.com/cespare/xxhash/xxhash_other.go index 4a5a82160..c68d13f89 100644 --- a/vendor/github.com/cespare/xxhash/xxhash_other.go +++ b/vendor/github.com/cespare/xxhash/xxhash_other.go @@ -5,9 +5,9 @@ package xxhash // Sum64 computes the 64-bit xxHash digest of b. func Sum64(b []byte) uint64 { // A simpler version would be - // d := New() - // d.Write(b) - // return d.Sum64() + // x := New() + // x.Write(b) + // return x.Sum64() // but this is faster, particularly for small inputs. n := len(b) @@ -61,9 +61,8 @@ func Sum64(b []byte) uint64 { return h } -func writeBlocks(d *Digest, b []byte) int { - v1, v2, v3, v4 := d.v1, d.v2, d.v3, d.v4 - n := len(b) +func writeBlocks(x *xxh, b []byte) []byte { + v1, v2, v3, v4 := x.v1, x.v2, x.v3, x.v4 for len(b) >= 32 { v1 = round(v1, u64(b[0:8:len(b)])) v2 = round(v2, u64(b[8:16:len(b)])) @@ -71,6 +70,6 @@ func writeBlocks(d *Digest, b []byte) int { v4 = round(v4, u64(b[24:32:len(b)])) b = b[32:len(b):len(b)] } - d.v1, d.v2, d.v3, d.v4 = v1, v2, v3, v4 - return n - len(b) + x.v1, x.v2, x.v3, x.v4 = v1, v2, v3, v4 + return b } diff --git a/vendor/github.com/cespare/xxhash/xxhash_safe.go b/vendor/github.com/cespare/xxhash/xxhash_safe.go index fc9bea7a3..dfa15ab7e 100644 --- a/vendor/github.com/cespare/xxhash/xxhash_safe.go +++ b/vendor/github.com/cespare/xxhash/xxhash_safe.go @@ -8,8 +8,3 @@ package xxhash func Sum64String(s string) uint64 { return Sum64([]byte(s)) } - -// WriteString adds more data to d. It always returns len(s), nil. -func (d *Digest) WriteString(s string) (n int, err error) { - return d.Write([]byte(s)) -} diff --git a/vendor/github.com/cespare/xxhash/xxhash_test.go b/vendor/github.com/cespare/xxhash/xxhash_test.go deleted file mode 100644 index 58f358489..000000000 --- a/vendor/github.com/cespare/xxhash/xxhash_test.go +++ /dev/null @@ -1,313 +0,0 @@ -package xxhash - -import ( - "bytes" - "encoding/binary" - "fmt" - "hash/crc32" - "hash/fnv" - "strings" - "testing" - - OneOfOne "github.com/OneOfOne/xxhash" - "github.com/spaolacci/murmur3" -) - -func TestAll(t *testing.T) { - for _, tt := range []struct { - name string - input string - want uint64 - }{ - {"empty", "", 0xef46db3751d8e999}, - {"a", "a", 0xd24ec4f1a98c6e5b}, - {"as", "as", 0x1c330fb2d66be179}, - {"asd", "asd", 0x631c37ce72a97393}, - {"asdf", "asdf", 0x415872f599cea71e}, - { - "len=63", - // Exactly 63 characters, which exercises all code paths. - "Call me Ishmael. Some years ago--never mind how long precisely-", - 0x02a2e85470d6fd96, - }, - } { - for chunkSize := 1; chunkSize <= len(tt.input); chunkSize++ { - name := fmt.Sprintf("%s,chunkSize=%d", tt.name, chunkSize) - t.Run(name, func(t *testing.T) { - testDigest(t, tt.input, chunkSize, tt.want) - }) - } - t.Run(tt.name, func(t *testing.T) { testSum(t, tt.input, tt.want) }) - } -} - -func testDigest(t *testing.T, input string, chunkSize int, want uint64) { - d := New() - ds := New() // uses WriteString - for i := 0; i < len(input); i += chunkSize { - chunk := input[i:] - if len(chunk) > chunkSize { - chunk = chunk[:chunkSize] - } - n, err := d.Write([]byte(chunk)) - if err != nil || n != len(chunk) { - t.Fatalf("Digest.Write: got (%d, %v); want (%d, nil)", n, err, len(chunk)) - } - n, err = ds.WriteString(chunk) - if err != nil || n != len(chunk) { - t.Fatalf("Digest.WriteString: got (%d, %v); want (%d, nil)", n, err, len(chunk)) - } - } - if got := d.Sum64(); got != want { - t.Fatalf("Digest.Sum64: got 0x%x; want 0x%x", got, want) - } - if got := ds.Sum64(); got != want { - t.Fatalf("Digest.Sum64 (WriteString): got 0x%x; want 0x%x", got, want) - } - var b [8]byte - binary.BigEndian.PutUint64(b[:], want) - if got := d.Sum(nil); !bytes.Equal(got, b[:]) { - t.Fatalf("Sum: got %v; want %v", got, b[:]) - } -} - -func testSum(t *testing.T, input string, want uint64) { - if got := Sum64([]byte(input)); got != want { - t.Fatalf("Sum64: got 0x%x; want 0x%x", got, want) - } - if got := Sum64String(input); got != want { - t.Fatalf("Sum64String: got 0x%x; want 0x%x", got, want) - } -} - -func TestReset(t *testing.T) { - parts := []string{"The quic", "k br", "o", "wn fox jumps", " ov", "er the lazy ", "dog."} - d := New() - for _, part := range parts { - d.Write([]byte(part)) - } - h0 := d.Sum64() - - d.Reset() - d.Write([]byte(strings.Join(parts, ""))) - h1 := d.Sum64() - - if h0 != h1 { - t.Errorf("0x%x != 0x%x", h0, h1) - } -} - -func TestBinaryMarshaling(t *testing.T) { - d := New() - d.WriteString("abc") - b, err := d.MarshalBinary() - if err != nil { - t.Fatal(err) - } - d = New() - d.WriteString("junk") - if err := d.UnmarshalBinary(b); err != nil { - t.Fatal(err) - } - d.WriteString("def") - if got, want := d.Sum64(), Sum64String("abcdef"); got != want { - t.Fatalf("after MarshalBinary+UnmarshalBinary, got 0x%x; want 0x%x", got, want) - } - - d0 := New() - d1 := New() - for i := 0; i < 64; i++ { - b, err := d0.MarshalBinary() - if err != nil { - t.Fatal(err) - } - d0 = new(Digest) - if err := d0.UnmarshalBinary(b); err != nil { - t.Fatal(err) - } - if got, want := d0.Sum64(), d1.Sum64(); got != want { - t.Fatalf("after %d Writes, unmarshaled Digest gave sum 0x%x; want 0x%x", i, got, want) - } - - d0.Write([]byte{'a'}) - d1.Write([]byte{'a'}) - } -} - -func TestAllocs(t *testing.T) { - const shortStr = "abcdefghijklmnop" - // Sum64([]byte(shortString)) shouldn't allocate because the - // intermediate []byte ought not to escape. - // (See https://github.com/cespare/xxhash/pull/2.) - t.Run("Sum64", func(t *testing.T) { - testAllocs(t, func() { - sink = Sum64([]byte(shortStr)) - }) - }) - // Creating and using a Digest shouldn't allocate because its methods - // shouldn't make it escape. (A previous version of New returned a - // hash.Hash64 which forces an allocation.) - t.Run("Digest", func(t *testing.T) { - b := []byte("asdf") - testAllocs(t, func() { - d := New() - d.Write(b) - sink = d.Sum64() - }) - }) -} - -func testAllocs(t *testing.T, fn func()) { - t.Helper() - if allocs := int(testing.AllocsPerRun(10, fn)); allocs > 0 { - t.Fatalf("got %d allocation(s) (want zero)", allocs) - } -} - -var sink uint64 - -var benchmarks = []struct { - name string - directBytes func([]byte) uint64 - directString func(string) uint64 - digestBytes func([]byte) uint64 - digestString func(string) uint64 -}{ - { - name: "xxhash", - directBytes: Sum64, - directString: Sum64String, - digestBytes: func(b []byte) uint64 { - h := New() - h.Write(b) - return h.Sum64() - }, - digestString: func(s string) uint64 { - h := New() - h.WriteString(s) - return h.Sum64() - }, - }, - { - name: "OneOfOne", - directBytes: OneOfOne.Checksum64, - directString: OneOfOne.ChecksumString64, - digestBytes: func(b []byte) uint64 { - h := OneOfOne.New64() - h.Write(b) - return h.Sum64() - }, - digestString: func(s string) uint64 { - h := OneOfOne.New64() - h.WriteString(s) - return h.Sum64() - }, - }, - { - name: "murmur3", - directBytes: murmur3.Sum64, - directString: func(s string) uint64 { - return murmur3.Sum64([]byte(s)) - }, - digestBytes: func(b []byte) uint64 { - h := murmur3.New64() - h.Write(b) - return h.Sum64() - }, - digestString: func(s string) uint64 { - h := murmur3.New64() - h.Write([]byte(s)) - return h.Sum64() - }, - }, - { - name: "CRC-32", - directBytes: func(b []byte) uint64 { - return uint64(crc32.ChecksumIEEE(b)) - }, - directString: func(s string) uint64 { - return uint64(crc32.ChecksumIEEE([]byte(s))) - }, - digestBytes: func(b []byte) uint64 { - h := crc32.NewIEEE() - h.Write(b) - return uint64(h.Sum32()) - }, - digestString: func(s string) uint64 { - h := crc32.NewIEEE() - h.Write([]byte(s)) - return uint64(h.Sum32()) - }, - }, - { - name: "FNV-1a", - digestBytes: func(b []byte) uint64 { - h := fnv.New64() - h.Write(b) - return uint64(h.Sum64()) - }, - digestString: func(s string) uint64 { - h := fnv.New64a() - h.Write([]byte(s)) - return uint64(h.Sum64()) - }, - }, -} - -func BenchmarkHashes(b *testing.B) { - for _, bb := range benchmarks { - for _, benchSize := range []struct { - name string - n int - }{ - {"5B", 5}, - {"100B", 100}, - {"4KB", 4e3}, - {"10MB", 10e6}, - } { - input := make([]byte, benchSize.n) - for i := range input { - input[i] = byte(i) - } - inputString := string(input) - if bb.directBytes != nil { - name := fmt.Sprintf("%s,direct,bytes,n=%s", bb.name, benchSize.name) - b.Run(name, func(b *testing.B) { - benchmarkHashBytes(b, input, bb.directBytes) - }) - } - if bb.directString != nil { - name := fmt.Sprintf("%s,direct,string,n=%s", bb.name, benchSize.name) - b.Run(name, func(b *testing.B) { - benchmarkHashString(b, inputString, bb.directString) - }) - } - if bb.digestBytes != nil { - name := fmt.Sprintf("%s,digest,bytes,n=%s", bb.name, benchSize.name) - b.Run(name, func(b *testing.B) { - benchmarkHashBytes(b, input, bb.digestBytes) - }) - } - if bb.digestString != nil { - name := fmt.Sprintf("%s,digest,string,n=%s", bb.name, benchSize.name) - b.Run(name, func(b *testing.B) { - benchmarkHashString(b, inputString, bb.digestString) - }) - } - } - } -} - -func benchmarkHashBytes(b *testing.B, input []byte, fn func([]byte) uint64) { - b.SetBytes(int64(len(input))) - for i := 0; i < b.N; i++ { - sink = fn(input) - } -} - -func benchmarkHashString(b *testing.B, input string, fn func(string) uint64) { - b.SetBytes(int64(len(input))) - for i := 0; i < b.N; i++ { - sink = fn(input) - } -} diff --git a/vendor/github.com/cespare/xxhash/xxhash_unsafe.go b/vendor/github.com/cespare/xxhash/xxhash_unsafe.go index 53bf76efb..d2b64e8bb 100644 --- a/vendor/github.com/cespare/xxhash/xxhash_unsafe.go +++ b/vendor/github.com/cespare/xxhash/xxhash_unsafe.go @@ -10,22 +10,17 @@ import ( "unsafe" ) -// Notes: -// -// See https://groups.google.com/d/msg/golang-nuts/dcjzJy-bSpw/tcZYBzQqAQAJ -// for some discussion about these unsafe conversions. -// -// In the future it's possible that compiler optimizations will make these -// unsafe operations unnecessary: https://golang.org/issue/2205. -// -// 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. - // Sum64String computes the 64-bit xxHash digest of s. // It may be faster than Sum64([]byte(s)) by avoiding a copy. +// +// TODO(caleb): Consider removing this if an optimization is ever added to make +// it unnecessary: https://golang.org/issue/2205. +// +// TODO(caleb): We still have a function call; we could instead write Go/asm +// copies of Sum64 for strings to squeeze out a bit more speed. func Sum64String(s string) uint64 { + // See https://groups.google.com/d/msg/golang-nuts/dcjzJy-bSpw/tcZYBzQqAQAJ + // for some discussion about this unsafe conversion. var b []byte bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) bh.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data @@ -33,14 +28,3 @@ func Sum64String(s string) uint64 { bh.Cap = 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) -} diff --git a/vendor/github.com/cespare/xxhash/xxhash_unsafe_test.go b/vendor/github.com/cespare/xxhash/xxhash_unsafe_test.go deleted file mode 100644 index 4d3f96461..000000000 --- a/vendor/github.com/cespare/xxhash/xxhash_unsafe_test.go +++ /dev/null @@ -1,24 +0,0 @@ -// +build !appengine - -package xxhash - -import ( - "strings" - "testing" -) - -func TestStringAllocs(t *testing.T) { - longStr := strings.Repeat("a", 1000) - t.Run("Sum64String", func(t *testing.T) { - testAllocs(t, func() { - sink = Sum64String(longStr) - }) - }) - t.Run("Digest.WriteString", func(t *testing.T) { - testAllocs(t, func() { - d := New() - d.WriteString(longStr) - sink = d.Sum64() - }) - }) -} diff --git a/vendor/github.com/coreos/go-oidc/jwks_test.go b/vendor/github.com/coreos/go-oidc/jwks_test.go deleted file mode 100644 index 6226117a9..000000000 --- a/vendor/github.com/coreos/go-oidc/jwks_test.go +++ /dev/null @@ -1,250 +0,0 @@ -package oidc - -import ( - "bytes" - "context" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "crypto/rsa" - "encoding/json" - "net/http" - "net/http/httptest" - "strconv" - "testing" - "time" - - jose "gopkg.in/square/go-jose.v2" -) - -type keyServer struct { - keys jose.JSONWebKeySet - setHeaders func(h http.Header) -} - -func (k *keyServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if k.setHeaders != nil { - k.setHeaders(w.Header()) - } - if err := json.NewEncoder(w).Encode(k.keys); err != nil { - panic(err) - } -} - -type signingKey struct { - keyID string // optional - priv interface{} - pub interface{} - alg jose.SignatureAlgorithm -} - -// sign creates a JWS using the private key from the provided payload. -func (s *signingKey) sign(t *testing.T, payload []byte) string { - privKey := &jose.JSONWebKey{Key: s.priv, Algorithm: string(s.alg), KeyID: s.keyID} - - signer, err := jose.NewSigner(jose.SigningKey{Algorithm: s.alg, Key: privKey}, nil) - if err != nil { - t.Fatal(err) - } - jws, err := signer.Sign(payload) - if err != nil { - t.Fatal(err) - } - - data, err := jws.CompactSerialize() - if err != nil { - t.Fatal(err) - } - return data -} - -// jwk returns the public part of the signing key. -func (s *signingKey) jwk() jose.JSONWebKey { - return jose.JSONWebKey{Key: s.pub, Use: "sig", Algorithm: string(s.alg), KeyID: s.keyID} -} - -func newRSAKey(t *testing.T) *signingKey { - priv, err := rsa.GenerateKey(rand.Reader, 1028) - if err != nil { - t.Fatal(err) - } - return &signingKey{"", priv, priv.Public(), jose.RS256} -} - -func newECDSAKey(t *testing.T) *signingKey { - priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - t.Fatal(err) - } - return &signingKey{"", priv, priv.Public(), jose.ES256} -} - -func TestRSAVerify(t *testing.T) { - good := newRSAKey(t) - bad := newRSAKey(t) - - testKeyVerify(t, good, bad, good) -} - -func TestECDSAVerify(t *testing.T) { - good := newECDSAKey(t) - bad := newECDSAKey(t) - testKeyVerify(t, good, bad, good) -} - -func TestMultipleKeysVerify(t *testing.T) { - key1 := newRSAKey(t) - key2 := newRSAKey(t) - bad := newECDSAKey(t) - - key1.keyID = "key1" - key2.keyID = "key2" - bad.keyID = "key3" - - testKeyVerify(t, key2, bad, key1, key2) -} - -func TestMismatchedKeyID(t *testing.T) { - key1 := newRSAKey(t) - key2 := newRSAKey(t) - - // shallow copy - bad := new(signingKey) - *bad = *key1 - - // The bad key is a valid key this time, but has a different Key ID. - // It shouldn't match key1 because of the mismatched ID, even though - // it would confirm the signature just fine. - bad.keyID = "key3" - - key1.keyID = "key1" - key2.keyID = "key2" - - testKeyVerify(t, key2, bad, key1, key2) -} - -func testKeyVerify(t *testing.T, good, bad *signingKey, verification ...*signingKey) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - keySet := jose.JSONWebKeySet{} - for _, v := range verification { - keySet.Keys = append(keySet.Keys, v.jwk()) - } - - payload := []byte("a secret") - - jws, err := jose.ParseSigned(good.sign(t, payload)) - if err != nil { - t.Fatal(err) - } - badJWS, err := jose.ParseSigned(bad.sign(t, payload)) - if err != nil { - t.Fatal(err) - } - - s := httptest.NewServer(&keyServer{keys: keySet}) - defer s.Close() - - rks := newRemoteKeySet(ctx, s.URL, nil) - - // Ensure the token verifies. - gotPayload, err := rks.verify(ctx, jws) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(gotPayload, payload) { - t.Errorf("expected payload %s got %s", payload, gotPayload) - } - - // Ensure the token verifies from the cache. - gotPayload, err = rks.verify(ctx, jws) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(gotPayload, payload) { - t.Errorf("expected payload %s got %s", payload, gotPayload) - } - - // Ensure item signed by wrong token doesn't verify. - if _, err := rks.verify(context.Background(), badJWS); err == nil { - t.Errorf("incorrectly verified signature") - } -} - -func TestCacheControl(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - key1 := newRSAKey(t) - key2 := newRSAKey(t) - - key1.keyID = "key1" - key2.keyID = "key2" - - payload := []byte("a secret") - jws1, err := jose.ParseSigned(key1.sign(t, payload)) - if err != nil { - t.Fatal(err) - } - jws2, err := jose.ParseSigned(key2.sign(t, payload)) - if err != nil { - t.Fatal(err) - } - - cacheForSeconds := 1200 - now := time.Now() - - server := &keyServer{ - keys: jose.JSONWebKeySet{ - Keys: []jose.JSONWebKey{key1.jwk()}, - }, - setHeaders: func(h http.Header) { - h.Set("Cache-Control", "max-age="+strconv.Itoa(cacheForSeconds)) - }, - } - s := httptest.NewServer(server) - defer s.Close() - - rks := newRemoteKeySet(ctx, s.URL, func() time.Time { return now }) - - if _, err := rks.verify(ctx, jws1); err != nil { - t.Errorf("failed to verify valid signature: %v", err) - } - if _, err := rks.verify(ctx, jws2); err == nil { - t.Errorf("incorrectly verified signature") - } - - // Add second key to public list. - server.keys = jose.JSONWebKeySet{ - Keys: []jose.JSONWebKey{key1.jwk(), key2.jwk()}, - } - - if _, err := rks.verify(ctx, jws1); err != nil { - t.Errorf("failed to verify valid signature: %v", err) - } - if _, err := rks.verify(ctx, jws2); err == nil { - t.Errorf("incorrectly verified signature, still within cache limit") - } - - // Move time forward. Remote key set should not query the remote server. - now = now.Add(time.Duration(cacheForSeconds) * time.Second) - - if _, err := rks.verify(ctx, jws1); err != nil { - t.Errorf("failed to verify valid signature: %v", err) - } - if _, err := rks.verify(ctx, jws2); err != nil { - t.Errorf("failed to verify valid signature: %v", err) - } - - // Kill server and move time forward again. Keys should still verify. - s.Close() - now = now.Add(time.Duration(cacheForSeconds) * time.Second) - - if _, err := rks.verify(ctx, jws1); err != nil { - t.Errorf("failed to verify valid signature: %v", err) - } - if _, err := rks.verify(ctx, jws2); err != nil { - t.Errorf("failed to verify valid signature: %v", err) - } -} diff --git a/vendor/github.com/coreos/go-oidc/oidc_test.go b/vendor/github.com/coreos/go-oidc/oidc_test.go deleted file mode 100644 index 1a2f07ac8..000000000 --- a/vendor/github.com/coreos/go-oidc/oidc_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package oidc - -import ( - "fmt" - "testing" -) - -const ( - // at_hash value and access_token returned by Google. - googleAccessTokenHash = "piwt8oCH-K2D9pXlaS1Y-w" - googleAccessToken = "ya29.CjHSA1l5WUn8xZ6HanHFzzdHdbXm-14rxnC7JHch9eFIsZkQEGoWzaYG4o7k5f6BnPLj" - googleSigningAlg = RS256 - // following values computed by own algo for regression testing - computed384TokenHash = "_ILKVQjbEzFKNJjUKC2kz9eReYi0A9Of" - computed512TokenHash = "Spa_APgwBrarSeQbxI-rbragXho6dqFpH5x9PqaPfUI" -) - -type accessTokenTest struct { - name string - tok *IDToken - accessToken string - verifier func(err error) error -} - -func (a accessTokenTest) run(t *testing.T) { - err := a.tok.VerifyAccessToken(a.accessToken) - result := a.verifier(err) - if result != nil { - t.Error(result) - } -} - -func TestAccessTokenVerification(t *testing.T) { - newToken := func(alg, atHash string) *IDToken { - return &IDToken{sigAlgorithm: alg, AccessTokenHash: atHash} - } - assertNil := func(err error) error { - if err != nil { - return fmt.Errorf("want nil error, got %v", err) - } - return nil - } - assertMsg := func(msg string) func(err error) error { - return func(err error) error { - if err == nil { - return fmt.Errorf("expected error, got success") - } - if err.Error() != msg { - return fmt.Errorf("bad error message, %q, (want %q)", err.Error(), msg) - } - return nil - } - } - tests := []accessTokenTest{ - { - "goodRS256", - newToken(googleSigningAlg, googleAccessTokenHash), - googleAccessToken, - assertNil, - }, - { - "goodES384", - newToken("ES384", computed384TokenHash), - googleAccessToken, - assertNil, - }, - { - "goodPS512", - newToken("PS512", computed512TokenHash), - googleAccessToken, - assertNil, - }, - { - "badRS256", - newToken("RS256", computed512TokenHash), - googleAccessToken, - assertMsg("access token hash does not match value in ID token"), - }, - { - "nohash", - newToken("RS256", ""), - googleAccessToken, - assertMsg("id token did not have an access token hash"), - }, - { - "badSignAlgo", - newToken("none", "xxx"), - googleAccessToken, - assertMsg(`oidc: unsupported signing algorithm "none"`), - }, - } - for _, test := range tests { - t.Run(test.name, test.run) - } -} diff --git a/vendor/github.com/coreos/go-oidc/test b/vendor/github.com/coreos/go-oidc/test old mode 100755 new mode 100644 diff --git a/vendor/github.com/coreos/go-oidc/verify_test.go b/vendor/github.com/coreos/go-oidc/verify_test.go deleted file mode 100644 index ff821af95..000000000 --- a/vendor/github.com/coreos/go-oidc/verify_test.go +++ /dev/null @@ -1,272 +0,0 @@ -package oidc - -import ( - "context" - "fmt" - "strconv" - "testing" - "time" - - jose "gopkg.in/square/go-jose.v2" -) - -type testVerifier struct { - jwk jose.JSONWebKey -} - -func (t *testVerifier) VerifySignature(ctx context.Context, jwt string) ([]byte, error) { - jws, err := jose.ParseSigned(jwt) - if err != nil { - return nil, fmt.Errorf("oidc: malformed jwt: %v", err) - } - return jws.Verify(&t.jwk) -} - -func TestVerify(t *testing.T) { - tests := []verificationTest{ - { - name: "good token", - idToken: `{"iss":"https://foo"}`, - config: Config{ - SkipClientIDCheck: true, - SkipExpiryCheck: true, - }, - signKey: newRSAKey(t), - }, - { - name: "invalid issuer", - issuer: "https://bar", - idToken: `{"iss":"https://foo"}`, - config: Config{ - SkipClientIDCheck: true, - SkipExpiryCheck: true, - }, - signKey: newRSAKey(t), - wantErr: true, - }, - { - name: "invalid sig", - idToken: `{"iss":"https://foo"}`, - config: Config{ - SkipClientIDCheck: true, - SkipExpiryCheck: true, - }, - signKey: newRSAKey(t), - verificationKey: newRSAKey(t), - wantErr: true, - }, - { - name: "google accounts without scheme", - issuer: "https://accounts.google.com", - idToken: `{"iss":"accounts.google.com"}`, - config: Config{ - SkipClientIDCheck: true, - SkipExpiryCheck: true, - }, - signKey: newRSAKey(t), - }, - { - name: "expired token", - idToken: `{"iss":"https://foo","exp":` + strconv.FormatInt(time.Now().Add(-time.Hour).Unix(), 10) + `}`, - config: Config{ - SkipClientIDCheck: true, - }, - signKey: newRSAKey(t), - wantErr: true, - }, - { - name: "unexpired token", - idToken: `{"iss":"https://foo","exp":` + strconv.FormatInt(time.Now().Add(time.Hour).Unix(), 10) + `}`, - config: Config{ - SkipClientIDCheck: true, - }, - signKey: newRSAKey(t), - }, - { - name: "expiry as float", - idToken: `{"iss":"https://foo","exp":` + - strconv.FormatFloat(float64(time.Now().Add(time.Hour).Unix()), 'E', -1, 64) + - `}`, - config: Config{ - SkipClientIDCheck: true, - }, - signKey: newRSAKey(t), - }, - } - for _, test := range tests { - t.Run(test.name, test.run) - } -} - -func TestVerifyAudience(t *testing.T) { - tests := []verificationTest{ - { - name: "good audience", - idToken: `{"iss":"https://foo","aud":"client1"}`, - config: Config{ - ClientID: "client1", - SkipExpiryCheck: true, - }, - signKey: newRSAKey(t), - }, - { - name: "mismatched audience", - idToken: `{"iss":"https://foo","aud":"client2"}`, - config: Config{ - ClientID: "client1", - SkipExpiryCheck: true, - }, - signKey: newRSAKey(t), - wantErr: true, - }, - { - name: "multiple audiences, one matches", - idToken: `{"iss":"https://foo","aud":["client1","client2"]}`, - config: Config{ - ClientID: "client2", - SkipExpiryCheck: true, - }, - signKey: newRSAKey(t), - }, - } - for _, test := range tests { - t.Run(test.name, test.run) - } -} - -func TestVerifySigningAlg(t *testing.T) { - tests := []verificationTest{ - { - name: "default signing alg", - idToken: `{"iss":"https://foo"}`, - config: Config{ - SkipClientIDCheck: true, - SkipExpiryCheck: true, - }, - signKey: newRSAKey(t), - }, - { - name: "bad signing alg", - idToken: `{"iss":"https://foo"}`, - config: Config{ - SkipClientIDCheck: true, - SkipExpiryCheck: true, - }, - signKey: newECDSAKey(t), - wantErr: true, - }, - { - name: "ecdsa signing", - idToken: `{"iss":"https://foo"}`, - config: Config{ - SupportedSigningAlgs: []string{ES256}, - SkipClientIDCheck: true, - SkipExpiryCheck: true, - }, - signKey: newECDSAKey(t), - }, - { - name: "one of many supported", - idToken: `{"iss":"https://foo"}`, - config: Config{ - SkipClientIDCheck: true, - SkipExpiryCheck: true, - SupportedSigningAlgs: []string{RS256, ES256}, - }, - signKey: newECDSAKey(t), - }, - { - name: "not in requiredAlgs", - idToken: `{"iss":"https://foo"}`, - config: Config{ - SupportedSigningAlgs: []string{RS256, ES512}, - SkipClientIDCheck: true, - SkipExpiryCheck: true, - }, - signKey: newECDSAKey(t), - wantErr: true, - }, - } - for _, test := range tests { - t.Run(test.name, test.run) - } -} - -func TestAccessTokenHash(t *testing.T) { - atHash := "piwt8oCH-K2D9pXlaS1Y-w" - vt := verificationTest{ - name: "preserves token hash and sig algo", - idToken: `{"iss":"https://foo","aud":"client1", "at_hash": "` + atHash + `"}`, - config: Config{ - ClientID: "client1", - SkipExpiryCheck: true, - }, - signKey: newRSAKey(t), - } - t.Run("at_hash", func(t *testing.T) { - tok := vt.runGetToken(t) - if tok != nil { - if tok.AccessTokenHash != atHash { - t.Errorf("access token hash not preserved correctly, want %q got %q", atHash, tok.AccessTokenHash) - } - if tok.sigAlgorithm != RS256 { - t.Errorf("invalid signature algo, want %q got %q", RS256, tok.sigAlgorithm) - } - } - }) -} - -type verificationTest struct { - // Name of the subtest. - name string - - // If not provided defaults to "https://foo" - issuer string - - // JWT payload (just the claims). - idToken string - - // Key to sign the ID Token with. - signKey *signingKey - // If not provided defaults to signKey. Only useful when - // testing invalid signatures. - verificationKey *signingKey - - config Config - wantErr bool -} - -func (v verificationTest) runGetToken(t *testing.T) *IDToken { - token := v.signKey.sign(t, []byte(v.idToken)) - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - issuer := "https://foo" - if v.issuer != "" { - issuer = v.issuer - } - var ks KeySet - if v.verificationKey == nil { - ks = &testVerifier{v.signKey.jwk()} - } else { - ks = &testVerifier{v.verificationKey.jwk()} - } - verifier := NewVerifier(issuer, ks, &v.config) - - idToken, err := verifier.Verify(ctx, token) - if err != nil { - if !v.wantErr { - t.Errorf("%s: verify %v", v.name, err) - } - } else { - if v.wantErr { - t.Errorf("%s: expected error", v.name) - } - } - return idToken -} - -func (v verificationTest) run(t *testing.T) { - v.runGetToken(t) -} diff --git a/vendor/github.com/go-kit/kit/log/benchmark_test.go b/vendor/github.com/go-kit/kit/log/benchmark_test.go deleted file mode 100644 index 126bfa5ae..000000000 --- a/vendor/github.com/go-kit/kit/log/benchmark_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package log_test - -import ( - "testing" - - "github.com/go-kit/kit/log" -) - -func benchmarkRunner(b *testing.B, logger log.Logger, f func(log.Logger)) { - lc := log.With(logger, "common_key", "common_value") - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - f(lc) - } -} - -var ( - baseMessage = func(logger log.Logger) { logger.Log("foo_key", "foo_value") } - withMessage = func(logger log.Logger) { log.With(logger, "a", "b").Log("c", "d") } -) diff --git a/vendor/github.com/go-kit/kit/log/concurrency_test.go b/vendor/github.com/go-kit/kit/log/concurrency_test.go deleted file mode 100644 index 95a749e77..000000000 --- a/vendor/github.com/go-kit/kit/log/concurrency_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package log_test - -import ( - "math" - "testing" - - "github.com/go-kit/kit/log" -) - -// These test are designed to be run with the race detector. - -func testConcurrency(t *testing.T, logger log.Logger, total int) { - n := int(math.Sqrt(float64(total))) - share := total / n - - errC := make(chan error, n) - - for i := 0; i < n; i++ { - go func() { - errC <- spam(logger, share) - }() - } - - for i := 0; i < n; i++ { - err := <-errC - if err != nil { - t.Fatalf("concurrent logging error: %v", err) - } - } -} - -func spam(logger log.Logger, count int) error { - for i := 0; i < count; i++ { - err := logger.Log("key", i) - if err != nil { - return err - } - } - return nil -} diff --git a/vendor/github.com/go-kit/kit/log/example_test.go b/vendor/github.com/go-kit/kit/log/example_test.go deleted file mode 100644 index 976677489..000000000 --- a/vendor/github.com/go-kit/kit/log/example_test.go +++ /dev/null @@ -1,137 +0,0 @@ -package log_test - -import ( - "math/rand" - "os" - "sync" - "time" - - "github.com/go-kit/kit/log" -) - -func Example_basic() { - logger := log.NewLogfmtLogger(os.Stdout) - - type Task struct { - ID int - } - - RunTask := func(task Task, logger log.Logger) { - logger.Log("taskID", task.ID, "event", "starting task") - - logger.Log("taskID", task.ID, "event", "task complete") - } - - RunTask(Task{ID: 1}, logger) - - // Output: - // taskID=1 event="starting task" - // taskID=1 event="task complete" -} - -func Example_contextual() { - logger := log.NewLogfmtLogger(os.Stdout) - - type Task struct { - ID int - Cmd string - } - - taskHelper := func(cmd string, logger log.Logger) { - // execute(cmd) - logger.Log("cmd", cmd, "dur", 42*time.Millisecond) - } - - RunTask := func(task Task, logger log.Logger) { - logger = log.With(logger, "taskID", task.ID) - logger.Log("event", "starting task") - - taskHelper(task.Cmd, logger) - - logger.Log("event", "task complete") - } - - RunTask(Task{ID: 1, Cmd: "echo Hello, world!"}, logger) - - // Output: - // taskID=1 event="starting task" - // taskID=1 cmd="echo Hello, world!" dur=42ms - // taskID=1 event="task complete" -} - -func Example_valuer() { - logger := log.NewLogfmtLogger(os.Stdout) - - count := 0 - counter := func() interface{} { - count++ - return count - } - - logger = log.With(logger, "count", log.Valuer(counter)) - - logger.Log("call", "first") - logger.Log("call", "second") - - // Output: - // count=1 call=first - // count=2 call=second -} - -func Example_debugInfo() { - logger := log.NewLogfmtLogger(os.Stdout) - - // make time predictable for this test - baseTime := time.Date(2015, time.February, 3, 10, 0, 0, 0, time.UTC) - mockTime := func() time.Time { - baseTime = baseTime.Add(time.Second) - return baseTime - } - - logger = log.With(logger, "time", log.Timestamp(mockTime), "caller", log.DefaultCaller) - - logger.Log("call", "first") - logger.Log("call", "second") - - // ... - - logger.Log("call", "third") - - // Output: - // time=2015-02-03T10:00:01Z caller=example_test.go:93 call=first - // time=2015-02-03T10:00:02Z caller=example_test.go:94 call=second - // time=2015-02-03T10:00:03Z caller=example_test.go:98 call=third -} - -func Example_syncWriter() { - w := log.NewSyncWriter(os.Stdout) - logger := log.NewLogfmtLogger(w) - - type Task struct { - ID int - } - - var wg sync.WaitGroup - - RunTask := func(task Task, logger log.Logger) { - logger.Log("taskID", task.ID, "event", "starting task") - - time.Sleep(time.Duration(rand.Intn(200)) * time.Millisecond) - - logger.Log("taskID", task.ID, "event", "task complete") - wg.Done() - } - - wg.Add(2) - - go RunTask(Task{ID: 1}, logger) - go RunTask(Task{ID: 2}, logger) - - wg.Wait() - - // Unordered output: - // taskID=1 event="starting task" - // taskID=2 event="starting task" - // taskID=1 event="task complete" - // taskID=2 event="task complete" -} diff --git a/vendor/github.com/go-kit/kit/log/json_logger_test.go b/vendor/github.com/go-kit/kit/log/json_logger_test.go deleted file mode 100644 index e3e309090..000000000 --- a/vendor/github.com/go-kit/kit/log/json_logger_test.go +++ /dev/null @@ -1,162 +0,0 @@ -package log_test - -import ( - "bytes" - "errors" - "io/ioutil" - "testing" - - "github.com/go-kit/kit/log" -) - -func TestJSONLoggerCaller(t *testing.T) { - t.Parallel() - buf := &bytes.Buffer{} - logger := log.NewJSONLogger(buf) - logger = log.With(logger, "caller", log.DefaultCaller) - - if err := logger.Log(); err != nil { - t.Fatal(err) - } - if want, have := `{"caller":"json_logger_test.go:18"}`+"\n", buf.String(); want != have { - t.Errorf("\nwant %#v\nhave %#v", want, have) - } -} - -func TestJSONLogger(t *testing.T) { - t.Parallel() - buf := &bytes.Buffer{} - logger := log.NewJSONLogger(buf) - if err := logger.Log("err", errors.New("err"), "m", map[string]int{"0": 0}, "a", []int{1, 2, 3}); err != nil { - t.Fatal(err) - } - if want, have := `{"a":[1,2,3],"err":"err","m":{"0":0}}`+"\n", buf.String(); want != have { - t.Errorf("\nwant %#v\nhave %#v", want, have) - } -} - -func TestJSONLoggerMissingValue(t *testing.T) { - t.Parallel() - buf := &bytes.Buffer{} - logger := log.NewJSONLogger(buf) - if err := logger.Log("k"); err != nil { - t.Fatal(err) - } - if want, have := `{"k":"(MISSING)"}`+"\n", buf.String(); want != have { - t.Errorf("\nwant %#v\nhave %#v", want, have) - } -} - -func TestJSONLoggerNilStringerKey(t *testing.T) { - t.Parallel() - - buf := &bytes.Buffer{} - logger := log.NewJSONLogger(buf) - if err := logger.Log((*stringer)(nil), "v"); err != nil { - t.Fatal(err) - } - if want, have := `{"NULL":"v"}`+"\n", buf.String(); want != have { - t.Errorf("\nwant %#v\nhave %#v", want, have) - } -} - -func TestJSONLoggerNilErrorValue(t *testing.T) { - t.Parallel() - - buf := &bytes.Buffer{} - logger := log.NewJSONLogger(buf) - if err := logger.Log("err", (*stringError)(nil)); err != nil { - t.Fatal(err) - } - if want, have := `{"err":null}`+"\n", buf.String(); want != have { - t.Errorf("\nwant %#v\nhave %#v", want, have) - } -} - -// aller implements json.Marshaler, encoding.TextMarshaler, and fmt.Stringer. -type aller struct{} - -func (aller) MarshalJSON() ([]byte, error) { - return []byte("\"json\""), nil -} - -func (aller) MarshalText() ([]byte, error) { - return []byte("text"), nil -} - -func (aller) String() string { - return "string" -} - -func (aller) Error() string { - return "error" -} - -// textstringer implements encoding.TextMarshaler and fmt.Stringer. -type textstringer struct{} - -func (textstringer) MarshalText() ([]byte, error) { - return []byte("text"), nil -} - -func (textstringer) String() string { - return "string" -} - -func TestJSONLoggerStringValue(t *testing.T) { - t.Parallel() - tests := []struct { - v interface{} - expected string - }{ - { - v: aller{}, - expected: `{"v":"json"}`, - }, - { - v: textstringer{}, - expected: `{"v":"text"}`, - }, - { - v: stringer("string"), - expected: `{"v":"string"}`, - }, - } - - for _, test := range tests { - buf := &bytes.Buffer{} - logger := log.NewJSONLogger(buf) - if err := logger.Log("v", test.v); err != nil { - t.Fatal(err) - } - - if want, have := test.expected+"\n", buf.String(); want != have { - t.Errorf("\nwant %#v\nhave %#v", want, have) - } - } -} - -type stringer string - -func (s stringer) String() string { - return string(s) -} - -type stringError string - -func (s stringError) Error() string { - return string(s) -} - -func BenchmarkJSONLoggerSimple(b *testing.B) { - benchmarkRunner(b, log.NewJSONLogger(ioutil.Discard), baseMessage) -} - -func BenchmarkJSONLoggerContextual(b *testing.B) { - benchmarkRunner(b, log.NewJSONLogger(ioutil.Discard), withMessage) -} - -func TestJSONLoggerConcurrency(t *testing.T) { - t.Parallel() - testConcurrency(t, log.NewJSONLogger(ioutil.Discard), 10000) -} diff --git a/vendor/github.com/go-kit/kit/log/level/benchmark_test.go b/vendor/github.com/go-kit/kit/log/level/benchmark_test.go deleted file mode 100644 index 4fca6f08f..000000000 --- a/vendor/github.com/go-kit/kit/log/level/benchmark_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package level_test - -import ( - "io/ioutil" - "testing" - - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/log/level" -) - -func Benchmark(b *testing.B) { - contexts := []struct { - name string - context func(log.Logger) log.Logger - }{ - {"NoContext", func(l log.Logger) log.Logger { - return l - }}, - {"TimeContext", func(l log.Logger) log.Logger { - return log.With(l, "time", log.DefaultTimestampUTC) - }}, - {"CallerContext", func(l log.Logger) log.Logger { - return log.With(l, "caller", log.DefaultCaller) - }}, - {"TimeCallerReqIDContext", func(l log.Logger) log.Logger { - return log.With(l, "time", log.DefaultTimestampUTC, "caller", log.DefaultCaller, "reqID", 29) - }}, - } - - loggers := []struct { - name string - logger log.Logger - }{ - {"Nop", log.NewNopLogger()}, - {"Logfmt", log.NewLogfmtLogger(ioutil.Discard)}, - {"JSON", log.NewJSONLogger(ioutil.Discard)}, - } - - filters := []struct { - name string - filter func(log.Logger) log.Logger - }{ - {"Baseline", func(l log.Logger) log.Logger { - return l - }}, - {"DisallowedLevel", func(l log.Logger) log.Logger { - return level.NewFilter(l, level.AllowInfo()) - }}, - {"AllowedLevel", func(l log.Logger) log.Logger { - return level.NewFilter(l, level.AllowAll()) - }}, - } - - for _, c := range contexts { - b.Run(c.name, func(b *testing.B) { - for _, f := range filters { - b.Run(f.name, func(b *testing.B) { - for _, l := range loggers { - b.Run(l.name, func(b *testing.B) { - logger := c.context(f.filter(l.logger)) - b.ResetTimer() - b.ReportAllocs() - for i := 0; i < b.N; i++ { - level.Debug(logger).Log("foo", "bar") - } - }) - } - }) - } - }) - } -} diff --git a/vendor/github.com/go-kit/kit/log/level/example_test.go b/vendor/github.com/go-kit/kit/log/level/example_test.go deleted file mode 100644 index fed52e512..000000000 --- a/vendor/github.com/go-kit/kit/log/level/example_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package level_test - -import ( - "errors" - "os" - - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/log/level" -) - -func Example_basic() { - // setup logger with level filter - logger := log.NewLogfmtLogger(os.Stdout) - logger = level.NewFilter(logger, level.AllowInfo()) - logger = log.With(logger, "caller", log.DefaultCaller) - - // use level helpers to log at different levels - level.Error(logger).Log("err", errors.New("bad data")) - level.Info(logger).Log("event", "data saved") - level.Debug(logger).Log("next item", 17) // filtered - - // Output: - // level=error caller=example_test.go:18 err="bad data" - // level=info caller=example_test.go:19 event="data saved" -} diff --git a/vendor/github.com/go-kit/kit/log/level/level_test.go b/vendor/github.com/go-kit/kit/log/level/level_test.go deleted file mode 100644 index e362effc4..000000000 --- a/vendor/github.com/go-kit/kit/log/level/level_test.go +++ /dev/null @@ -1,235 +0,0 @@ -package level_test - -import ( - "bytes" - "errors" - "io" - "strings" - "testing" - - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/log/level" -) - -func TestVariousLevels(t *testing.T) { - testCases := []struct { - name string - allowed level.Option - want string - }{ - { - "AllowAll", - level.AllowAll(), - strings.Join([]string{ - `{"level":"debug","this is":"debug log"}`, - `{"level":"info","this is":"info log"}`, - `{"level":"warn","this is":"warn log"}`, - `{"level":"error","this is":"error log"}`, - }, "\n"), - }, - { - "AllowDebug", - level.AllowDebug(), - strings.Join([]string{ - `{"level":"debug","this is":"debug log"}`, - `{"level":"info","this is":"info log"}`, - `{"level":"warn","this is":"warn log"}`, - `{"level":"error","this is":"error log"}`, - }, "\n"), - }, - { - "AllowInfo", - level.AllowInfo(), - strings.Join([]string{ - `{"level":"info","this is":"info log"}`, - `{"level":"warn","this is":"warn log"}`, - `{"level":"error","this is":"error log"}`, - }, "\n"), - }, - { - "AllowWarn", - level.AllowWarn(), - strings.Join([]string{ - `{"level":"warn","this is":"warn log"}`, - `{"level":"error","this is":"error log"}`, - }, "\n"), - }, - { - "AllowError", - level.AllowError(), - strings.Join([]string{ - `{"level":"error","this is":"error log"}`, - }, "\n"), - }, - { - "AllowNone", - level.AllowNone(), - ``, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - var buf bytes.Buffer - logger := level.NewFilter(log.NewJSONLogger(&buf), tc.allowed) - - level.Debug(logger).Log("this is", "debug log") - level.Info(logger).Log("this is", "info log") - level.Warn(logger).Log("this is", "warn log") - level.Error(logger).Log("this is", "error log") - - if want, have := tc.want, strings.TrimSpace(buf.String()); want != have { - t.Errorf("\nwant:\n%s\nhave:\n%s", want, have) - } - }) - } -} - -func TestErrNotAllowed(t *testing.T) { - myError := errors.New("squelched!") - opts := []level.Option{ - level.AllowWarn(), - level.ErrNotAllowed(myError), - } - logger := level.NewFilter(log.NewNopLogger(), opts...) - - if want, have := myError, level.Info(logger).Log("foo", "bar"); want != have { - t.Errorf("want %#+v, have %#+v", want, have) - } - - if want, have := error(nil), level.Warn(logger).Log("foo", "bar"); want != have { - t.Errorf("want %#+v, have %#+v", want, have) - } -} - -func TestErrNoLevel(t *testing.T) { - myError := errors.New("no level specified") - - var buf bytes.Buffer - opts := []level.Option{ - level.SquelchNoLevel(true), - level.ErrNoLevel(myError), - } - logger := level.NewFilter(log.NewJSONLogger(&buf), opts...) - - if want, have := myError, logger.Log("foo", "bar"); want != have { - t.Errorf("want %v, have %v", want, have) - } - if want, have := ``, strings.TrimSpace(buf.String()); want != have { - t.Errorf("\nwant '%s'\nhave '%s'", want, have) - } -} - -func TestAllowNoLevel(t *testing.T) { - var buf bytes.Buffer - opts := []level.Option{ - level.SquelchNoLevel(false), - level.ErrNoLevel(errors.New("I should never be returned!")), - } - logger := level.NewFilter(log.NewJSONLogger(&buf), opts...) - - if want, have := error(nil), logger.Log("foo", "bar"); want != have { - t.Errorf("want %v, have %v", want, have) - } - if want, have := `{"foo":"bar"}`, strings.TrimSpace(buf.String()); want != have { - t.Errorf("\nwant '%s'\nhave '%s'", want, have) - } -} - -func TestLevelContext(t *testing.T) { - var buf bytes.Buffer - - // Wrapping the level logger with a context allows users to use - // log.DefaultCaller as per normal. - var logger log.Logger - logger = log.NewLogfmtLogger(&buf) - logger = level.NewFilter(logger, level.AllowAll()) - logger = log.With(logger, "caller", log.DefaultCaller) - - level.Info(logger).Log("foo", "bar") - if want, have := `level=info caller=level_test.go:149 foo=bar`, strings.TrimSpace(buf.String()); want != have { - t.Errorf("\nwant '%s'\nhave '%s'", want, have) - } -} - -func TestContextLevel(t *testing.T) { - var buf bytes.Buffer - - // Wrapping a context with the level logger still works, but requires users - // to specify a higher callstack depth value. - var logger log.Logger - logger = log.NewLogfmtLogger(&buf) - logger = log.With(logger, "caller", log.Caller(5)) - logger = level.NewFilter(logger, level.AllowAll()) - - level.Info(logger).Log("foo", "bar") - if want, have := `caller=level_test.go:165 level=info foo=bar`, strings.TrimSpace(buf.String()); want != have { - t.Errorf("\nwant '%s'\nhave '%s'", want, have) - } -} - -func TestLevelFormatting(t *testing.T) { - testCases := []struct { - name string - format func(io.Writer) log.Logger - output string - }{ - { - name: "logfmt", - format: log.NewLogfmtLogger, - output: `level=info foo=bar`, - }, - { - name: "JSON", - format: log.NewJSONLogger, - output: `{"foo":"bar","level":"info"}`, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - var buf bytes.Buffer - - logger := tc.format(&buf) - level.Info(logger).Log("foo", "bar") - if want, have := tc.output, strings.TrimSpace(buf.String()); want != have { - t.Errorf("\nwant: '%s'\nhave '%s'", want, have) - } - }) - } -} - -func TestInjector(t *testing.T) { - var ( - output []interface{} - logger log.Logger - ) - - logger = log.LoggerFunc(func(keyvals ...interface{}) error { - output = keyvals - return nil - }) - logger = level.NewInjector(logger, level.InfoValue()) - - logger.Log("foo", "bar") - if got, want := len(output), 4; got != want { - t.Errorf("missing level not injected: got len==%d, want len==%d", got, want) - } - if got, want := output[0], level.Key(); got != want { - t.Errorf("wrong level key: got %#v, want %#v", got, want) - } - if got, want := output[1], level.InfoValue(); got != want { - t.Errorf("wrong level value: got %#v, want %#v", got, want) - } - - level.Error(logger).Log("foo", "bar") - if got, want := len(output), 4; got != want { - t.Errorf("leveled record modified: got len==%d, want len==%d", got, want) - } - if got, want := output[0], level.Key(); got != want { - t.Errorf("wrong level key: got %#v, want %#v", got, want) - } - if got, want := output[1], level.ErrorValue(); got != want { - t.Errorf("wrong level value: got %#v, want %#v", got, want) - } -} diff --git a/vendor/github.com/go-kit/kit/log/log_test.go b/vendor/github.com/go-kit/kit/log/log_test.go deleted file mode 100644 index 1bf29727e..000000000 --- a/vendor/github.com/go-kit/kit/log/log_test.go +++ /dev/null @@ -1,191 +0,0 @@ -package log_test - -import ( - "bytes" - "fmt" - "sync" - "testing" - - "github.com/go-kit/kit/log" - "github.com/go-stack/stack" -) - -func TestContext(t *testing.T) { - t.Parallel() - buf := &bytes.Buffer{} - logger := log.NewLogfmtLogger(buf) - - kvs := []interface{}{"a", 123} - lc := log.With(logger, kvs...) - kvs[1] = 0 // With should copy its key values - - lc = log.With(lc, "b", "c") // With should stack - if err := lc.Log("msg", "message"); err != nil { - t.Fatal(err) - } - if want, have := "a=123 b=c msg=message\n", buf.String(); want != have { - t.Errorf("\nwant: %shave: %s", want, have) - } - - buf.Reset() - lc = log.WithPrefix(lc, "p", "first") - if err := lc.Log("msg", "message"); err != nil { - t.Fatal(err) - } - if want, have := "p=first a=123 b=c msg=message\n", buf.String(); want != have { - t.Errorf("\nwant: %shave: %s", want, have) - } -} - -func TestContextMissingValue(t *testing.T) { - t.Parallel() - var output []interface{} - logger := log.Logger(log.LoggerFunc(func(keyvals ...interface{}) error { - output = keyvals - return nil - })) - - log.WithPrefix(log.With(logger, "k1"), "k0").Log("k2") - if want, have := 6, len(output); want != have { - t.Errorf("want len(output) == %v, have %v", want, have) - } - for i := 1; i < 6; i += 2 { - if want, have := log.ErrMissingValue, output[i]; want != have { - t.Errorf("want output[%d] == %#v, have %#v", i, want, have) - } - } -} - -// Test that context.Log has a consistent function stack depth when binding -// Valuers, regardless of how many times With has been called. -func TestContextStackDepth(t *testing.T) { - t.Parallel() - fn := fmt.Sprintf("%n", stack.Caller(0)) - - var output []interface{} - - logger := log.Logger(log.LoggerFunc(func(keyvals ...interface{}) error { - output = keyvals - return nil - })) - - stackValuer := log.Valuer(func() interface{} { - for i, c := range stack.Trace() { - if fmt.Sprintf("%n", c) == fn { - return i - } - } - t.Fatal("Test function not found in stack trace.") - return nil - }) - - logger = log.With(logger, "stack", stackValuer) - - // Call through interface to get baseline. - logger.Log("k", "v") - want := output[1].(int) - - for len(output) < 10 { - logger.Log("k", "v") - if have := output[1]; have != want { - t.Errorf("%d Withs: have %v, want %v", len(output)/2-1, have, want) - } - - wrapped := log.With(logger) - wrapped.Log("k", "v") - if have := output[1]; have != want { - t.Errorf("%d Withs: have %v, want %v", len(output)/2-1, have, want) - } - - logger = log.With(logger, "k", "v") - } -} - -// Test that With returns a Logger safe for concurrent use. This test -// validates that the stored logging context does not get corrupted when -// multiple clients concurrently log additional keyvals. -// -// This test must be run with go test -cpu 2 (or more) to achieve its goal. -func TestWithConcurrent(t *testing.T) { - // Create some buckets to count how many events each goroutine logs. - const goroutines = 8 - counts := [goroutines]int{} - - // This logger extracts a goroutine id from the last value field and - // increments the referenced bucket. - logger := log.LoggerFunc(func(kv ...interface{}) error { - goroutine := kv[len(kv)-1].(int) - counts[goroutine]++ - return nil - }) - - // With must be careful about handling slices that can grow without - // copying the underlying array, so give it a challenge. - l := log.With(logger, make([]interface{}, 0, 2)...) - - // Start logging concurrently. Each goroutine logs its id so the logger - // can bucket the event counts. - var wg sync.WaitGroup - wg.Add(goroutines) - const n = 10000 - for i := 0; i < goroutines; i++ { - go func(idx int) { - defer wg.Done() - for j := 0; j < n; j++ { - l.Log("goroutineIdx", idx) - } - }(i) - } - wg.Wait() - - for bucket, have := range counts { - if want := n; want != have { - t.Errorf("bucket %d: want %d, have %d", bucket, want, have) // note Errorf - } - } -} - -func BenchmarkDiscard(b *testing.B) { - logger := log.NewNopLogger() - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - logger.Log("k", "v") - } -} - -func BenchmarkOneWith(b *testing.B) { - logger := log.NewNopLogger() - lc := log.With(logger, "k", "v") - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - lc.Log("k", "v") - } -} - -func BenchmarkTwoWith(b *testing.B) { - logger := log.NewNopLogger() - lc := log.With(logger, "k", "v") - for i := 1; i < 2; i++ { - lc = log.With(lc, "k", "v") - } - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - lc.Log("k", "v") - } -} - -func BenchmarkTenWith(b *testing.B) { - logger := log.NewNopLogger() - lc := log.With(logger, "k", "v") - for i := 1; i < 10; i++ { - lc = log.With(lc, "k", "v") - } - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - lc.Log("k", "v") - } -} diff --git a/vendor/github.com/go-kit/kit/log/logfmt_logger_test.go b/vendor/github.com/go-kit/kit/log/logfmt_logger_test.go deleted file mode 100644 index 91bbca15c..000000000 --- a/vendor/github.com/go-kit/kit/log/logfmt_logger_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package log_test - -import ( - "bytes" - "errors" - "io/ioutil" - "testing" - - "github.com/go-kit/kit/log" - "github.com/go-logfmt/logfmt" -) - -func TestLogfmtLogger(t *testing.T) { - t.Parallel() - buf := &bytes.Buffer{} - logger := log.NewLogfmtLogger(buf) - - if err := logger.Log("hello", "world"); err != nil { - t.Fatal(err) - } - if want, have := "hello=world\n", buf.String(); want != have { - t.Errorf("want %#v, have %#v", want, have) - } - - buf.Reset() - if err := logger.Log("a", 1, "err", errors.New("error")); err != nil { - t.Fatal(err) - } - if want, have := "a=1 err=error\n", buf.String(); want != have { - t.Errorf("want %#v, have %#v", want, have) - } - - buf.Reset() - if err := logger.Log("std_map", map[int]int{1: 2}, "my_map", mymap{0: 0}); err != nil { - t.Fatal(err) - } - if want, have := "std_map=\""+logfmt.ErrUnsupportedValueType.Error()+"\" my_map=special_behavior\n", buf.String(); want != have { - t.Errorf("want %#v, have %#v", want, have) - } -} - -func BenchmarkLogfmtLoggerSimple(b *testing.B) { - benchmarkRunner(b, log.NewLogfmtLogger(ioutil.Discard), baseMessage) -} - -func BenchmarkLogfmtLoggerContextual(b *testing.B) { - benchmarkRunner(b, log.NewLogfmtLogger(ioutil.Discard), withMessage) -} - -func TestLogfmtLoggerConcurrency(t *testing.T) { - t.Parallel() - testConcurrency(t, log.NewLogfmtLogger(ioutil.Discard), 10000) -} - -type mymap map[int]int - -func (m mymap) String() string { return "special_behavior" } diff --git a/vendor/github.com/go-kit/kit/log/nop_logger_test.go b/vendor/github.com/go-kit/kit/log/nop_logger_test.go deleted file mode 100644 index 908ddd816..000000000 --- a/vendor/github.com/go-kit/kit/log/nop_logger_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package log_test - -import ( - "testing" - - "github.com/go-kit/kit/log" -) - -func TestNopLogger(t *testing.T) { - t.Parallel() - logger := log.NewNopLogger() - if err := logger.Log("abc", 123); err != nil { - t.Error(err) - } - if err := log.With(logger, "def", "ghi").Log(); err != nil { - t.Error(err) - } -} - -func BenchmarkNopLoggerSimple(b *testing.B) { - benchmarkRunner(b, log.NewNopLogger(), baseMessage) -} - -func BenchmarkNopLoggerContextual(b *testing.B) { - benchmarkRunner(b, log.NewNopLogger(), withMessage) -} diff --git a/vendor/github.com/go-kit/kit/log/stdlib_test.go b/vendor/github.com/go-kit/kit/log/stdlib_test.go deleted file mode 100644 index 90ebc5fa4..000000000 --- a/vendor/github.com/go-kit/kit/log/stdlib_test.go +++ /dev/null @@ -1,205 +0,0 @@ -package log - -import ( - "bytes" - "fmt" - "log" - "testing" - "time" -) - -func TestStdlibWriter(t *testing.T) { - buf := &bytes.Buffer{} - log.SetOutput(buf) - log.SetFlags(log.LstdFlags) - logger := NewLogfmtLogger(StdlibWriter{}) - logger.Log("key", "val") - timestamp := time.Now().Format("2006/01/02 15:04:05") - if want, have := timestamp+" key=val\n", buf.String(); want != have { - t.Errorf("want %q, have %q", want, have) - } -} - -func TestStdlibAdapterUsage(t *testing.T) { - buf := &bytes.Buffer{} - logger := NewLogfmtLogger(buf) - writer := NewStdlibAdapter(logger) - stdlog := log.New(writer, "", 0) - - now := time.Now() - date := now.Format("2006/01/02") - time := now.Format("15:04:05") - - for flag, want := range map[int]string{ - 0: "msg=hello\n", - log.Ldate: "ts=" + date + " msg=hello\n", - log.Ltime: "ts=" + time + " msg=hello\n", - log.Ldate | log.Ltime: "ts=\"" + date + " " + time + "\" msg=hello\n", - log.Lshortfile: "caller=stdlib_test.go:44 msg=hello\n", - log.Lshortfile | log.Ldate: "ts=" + date + " caller=stdlib_test.go:44 msg=hello\n", - log.Lshortfile | log.Ldate | log.Ltime: "ts=\"" + date + " " + time + "\" caller=stdlib_test.go:44 msg=hello\n", - } { - buf.Reset() - stdlog.SetFlags(flag) - stdlog.Print("hello") - if have := buf.String(); want != have { - t.Errorf("flag=%d: want %#v, have %#v", flag, want, have) - } - } -} - -func TestStdLibAdapterExtraction(t *testing.T) { - buf := &bytes.Buffer{} - logger := NewLogfmtLogger(buf) - writer := NewStdlibAdapter(logger) - for input, want := range map[string]string{ - "hello": "msg=hello\n", - "2009/01/23: hello": "ts=2009/01/23 msg=hello\n", - "2009/01/23 01:23:23: hello": "ts=\"2009/01/23 01:23:23\" msg=hello\n", - "01:23:23: hello": "ts=01:23:23 msg=hello\n", - "2009/01/23 01:23:23.123123: hello": "ts=\"2009/01/23 01:23:23.123123\" msg=hello\n", - "2009/01/23 01:23:23.123123 /a/b/c/d.go:23: hello": "ts=\"2009/01/23 01:23:23.123123\" caller=/a/b/c/d.go:23 msg=hello\n", - "01:23:23.123123 /a/b/c/d.go:23: hello": "ts=01:23:23.123123 caller=/a/b/c/d.go:23 msg=hello\n", - "2009/01/23 01:23:23 /a/b/c/d.go:23: hello": "ts=\"2009/01/23 01:23:23\" caller=/a/b/c/d.go:23 msg=hello\n", - "2009/01/23 /a/b/c/d.go:23: hello": "ts=2009/01/23 caller=/a/b/c/d.go:23 msg=hello\n", - "/a/b/c/d.go:23: hello": "caller=/a/b/c/d.go:23 msg=hello\n", - } { - buf.Reset() - fmt.Fprint(writer, input) - if have := buf.String(); want != have { - t.Errorf("%q: want %#v, have %#v", input, want, have) - } - } -} - -func TestStdlibAdapterSubexps(t *testing.T) { - for input, wantMap := range map[string]map[string]string{ - "hello world": { - "date": "", - "time": "", - "file": "", - "msg": "hello world", - }, - "2009/01/23: hello world": { - "date": "2009/01/23", - "time": "", - "file": "", - "msg": "hello world", - }, - "2009/01/23 01:23:23: hello world": { - "date": "2009/01/23", - "time": "01:23:23", - "file": "", - "msg": "hello world", - }, - "01:23:23: hello world": { - "date": "", - "time": "01:23:23", - "file": "", - "msg": "hello world", - }, - "2009/01/23 01:23:23.123123: hello world": { - "date": "2009/01/23", - "time": "01:23:23.123123", - "file": "", - "msg": "hello world", - }, - "2009/01/23 01:23:23.123123 /a/b/c/d.go:23: hello world": { - "date": "2009/01/23", - "time": "01:23:23.123123", - "file": "/a/b/c/d.go:23", - "msg": "hello world", - }, - "01:23:23.123123 /a/b/c/d.go:23: hello world": { - "date": "", - "time": "01:23:23.123123", - "file": "/a/b/c/d.go:23", - "msg": "hello world", - }, - "2009/01/23 01:23:23 /a/b/c/d.go:23: hello world": { - "date": "2009/01/23", - "time": "01:23:23", - "file": "/a/b/c/d.go:23", - "msg": "hello world", - }, - "2009/01/23 /a/b/c/d.go:23: hello world": { - "date": "2009/01/23", - "time": "", - "file": "/a/b/c/d.go:23", - "msg": "hello world", - }, - "/a/b/c/d.go:23: hello world": { - "date": "", - "time": "", - "file": "/a/b/c/d.go:23", - "msg": "hello world", - }, - "2009/01/23 01:23:23.123123 C:/a/b/c/d.go:23: hello world": { - "date": "2009/01/23", - "time": "01:23:23.123123", - "file": "C:/a/b/c/d.go:23", - "msg": "hello world", - }, - "01:23:23.123123 C:/a/b/c/d.go:23: hello world": { - "date": "", - "time": "01:23:23.123123", - "file": "C:/a/b/c/d.go:23", - "msg": "hello world", - }, - "2009/01/23 01:23:23 C:/a/b/c/d.go:23: hello world": { - "date": "2009/01/23", - "time": "01:23:23", - "file": "C:/a/b/c/d.go:23", - "msg": "hello world", - }, - "2009/01/23 C:/a/b/c/d.go:23: hello world": { - "date": "2009/01/23", - "time": "", - "file": "C:/a/b/c/d.go:23", - "msg": "hello world", - }, - "C:/a/b/c/d.go:23: hello world": { - "date": "", - "time": "", - "file": "C:/a/b/c/d.go:23", - "msg": "hello world", - }, - "2009/01/23 01:23:23.123123 C:/a/b/c/d.go:23: :.;<>_#{[]}\"\\": { - "date": "2009/01/23", - "time": "01:23:23.123123", - "file": "C:/a/b/c/d.go:23", - "msg": ":.;<>_#{[]}\"\\", - }, - "01:23:23.123123 C:/a/b/c/d.go:23: :.;<>_#{[]}\"\\": { - "date": "", - "time": "01:23:23.123123", - "file": "C:/a/b/c/d.go:23", - "msg": ":.;<>_#{[]}\"\\", - }, - "2009/01/23 01:23:23 C:/a/b/c/d.go:23: :.;<>_#{[]}\"\\": { - "date": "2009/01/23", - "time": "01:23:23", - "file": "C:/a/b/c/d.go:23", - "msg": ":.;<>_#{[]}\"\\", - }, - "2009/01/23 C:/a/b/c/d.go:23: :.;<>_#{[]}\"\\": { - "date": "2009/01/23", - "time": "", - "file": "C:/a/b/c/d.go:23", - "msg": ":.;<>_#{[]}\"\\", - }, - "C:/a/b/c/d.go:23: :.;<>_#{[]}\"\\": { - "date": "", - "time": "", - "file": "C:/a/b/c/d.go:23", - "msg": ":.;<>_#{[]}\"\\", - }, - } { - haveMap := subexps([]byte(input)) - for key, want := range wantMap { - if have := haveMap[key]; want != have { - t.Errorf("%q: %q: want %q, have %q", input, key, want, have) - } - } - } -} diff --git a/vendor/github.com/go-kit/kit/log/sync_test.go b/vendor/github.com/go-kit/kit/log/sync_test.go deleted file mode 100644 index 55e6b150d..000000000 --- a/vendor/github.com/go-kit/kit/log/sync_test.go +++ /dev/null @@ -1,83 +0,0 @@ -package log_test - -import ( - "bytes" - "io" - "os" - "testing" - - "github.com/go-kit/kit/log" -) - -func TestSwapLogger(t *testing.T) { - t.Parallel() - var logger log.SwapLogger - - // Zero value does not panic or error. - err := logger.Log("k", "v") - if got, want := err, error(nil); got != want { - t.Errorf("got %v, want %v", got, want) - } - - buf := &bytes.Buffer{} - json := log.NewJSONLogger(buf) - logger.Swap(json) - - if err := logger.Log("k", "v"); err != nil { - t.Error(err) - } - if got, want := buf.String(), `{"k":"v"}`+"\n"; got != want { - t.Errorf("got %v, want %v", got, want) - } - - buf.Reset() - prefix := log.NewLogfmtLogger(buf) - logger.Swap(prefix) - - if err := logger.Log("k", "v"); err != nil { - t.Error(err) - } - if got, want := buf.String(), "k=v\n"; got != want { - t.Errorf("got %v, want %v", got, want) - } - - buf.Reset() - logger.Swap(nil) - - if err := logger.Log("k", "v"); err != nil { - t.Error(err) - } - if got, want := buf.String(), ""; got != want { - t.Errorf("got %v, want %v", got, want) - } -} - -func TestSwapLoggerConcurrency(t *testing.T) { - t.Parallel() - testConcurrency(t, &log.SwapLogger{}, 10000) -} - -func TestSyncLoggerConcurrency(t *testing.T) { - var w io.Writer - w = &bytes.Buffer{} - logger := log.NewLogfmtLogger(w) - logger = log.NewSyncLogger(logger) - testConcurrency(t, logger, 10000) -} - -func TestSyncWriterConcurrency(t *testing.T) { - var w io.Writer - w = &bytes.Buffer{} - w = log.NewSyncWriter(w) - testConcurrency(t, log.NewLogfmtLogger(w), 10000) -} - -func TestSyncWriterFd(t *testing.T) { - _, ok := log.NewSyncWriter(os.Stdout).(interface { - Fd() uintptr - }) - - if !ok { - t.Error("NewSyncWriter does not pass through Fd method") - } -} diff --git a/vendor/github.com/go-kit/kit/log/value_test.go b/vendor/github.com/go-kit/kit/log/value_test.go deleted file mode 100644 index 3a0c835a3..000000000 --- a/vendor/github.com/go-kit/kit/log/value_test.go +++ /dev/null @@ -1,150 +0,0 @@ -package log_test - -import ( - "encoding" - "fmt" - "reflect" - "testing" - "time" - - "github.com/go-kit/kit/log" -) - -func TestValueBinding(t *testing.T) { - t.Parallel() - var output []interface{} - - logger := log.Logger(log.LoggerFunc(func(keyvals ...interface{}) error { - output = keyvals - return nil - })) - - start := time.Date(2015, time.April, 25, 0, 0, 0, 0, time.UTC) - now := start - mocktime := func() time.Time { - now = now.Add(time.Second) - return now - } - - lc := log.With(logger, "ts", log.Timestamp(mocktime), "caller", log.DefaultCaller) - - lc.Log("foo", "bar") - timestamp, ok := output[1].(time.Time) - if !ok { - t.Fatalf("want time.Time, have %T", output[1]) - } - if want, have := start.Add(time.Second), timestamp; want != have { - t.Errorf("output[1]: want %v, have %v", want, have) - } - if want, have := "value_test.go:31", fmt.Sprint(output[3]); want != have { - t.Errorf("output[3]: want %s, have %s", want, have) - } - - // A second attempt to confirm the bindings are truly dynamic. - lc.Log("foo", "bar") - timestamp, ok = output[1].(time.Time) - if !ok { - t.Fatalf("want time.Time, have %T", output[1]) - } - if want, have := start.Add(2*time.Second), timestamp; want != have { - t.Errorf("output[1]: want %v, have %v", want, have) - } - if want, have := "value_test.go:44", fmt.Sprint(output[3]); want != have { - t.Errorf("output[3]: want %s, have %s", want, have) - } -} - -func TestValueBinding_loggingZeroKeyvals(t *testing.T) { - t.Parallel() - var output []interface{} - - logger := log.Logger(log.LoggerFunc(func(keyvals ...interface{}) error { - output = keyvals - return nil - })) - - start := time.Date(2015, time.April, 25, 0, 0, 0, 0, time.UTC) - now := start - mocktime := func() time.Time { - now = now.Add(time.Second) - return now - } - - logger = log.With(logger, "ts", log.Timestamp(mocktime)) - - logger.Log() - timestamp, ok := output[1].(time.Time) - if !ok { - t.Fatalf("want time.Time, have %T", output[1]) - } - if want, have := start.Add(time.Second), timestamp; want != have { - t.Errorf("output[1]: want %v, have %v", want, have) - } - - // A second attempt to confirm the bindings are truly dynamic. - logger.Log() - timestamp, ok = output[1].(time.Time) - if !ok { - t.Fatalf("want time.Time, have %T", output[1]) - } - if want, have := start.Add(2*time.Second), timestamp; want != have { - t.Errorf("output[1]: want %v, have %v", want, have) - } -} - -func TestTimestampFormat(t *testing.T) { - t.Parallel() - - start := time.Date(2015, time.April, 25, 0, 0, 0, 0, time.UTC) - now := start - mocktime := func() time.Time { - now = now.Add(time.Second) - return now - } - - tv := log.TimestampFormat(mocktime, time.RFC822) - - if want, have := now.Add(time.Second).Format(time.RFC822), fmt.Sprint(tv()); want != have { - t.Errorf("wrong time format: want %v, have %v", want, have) - } - - if want, have := now.Add(2*time.Second).Format(time.RFC822), fmt.Sprint(tv()); want != have { - t.Errorf("wrong time format: want %v, have %v", want, have) - } - - mustMarshal := func(v interface{}) []byte { - b, err := v.(encoding.TextMarshaler).MarshalText() - if err != nil { - t.Fatal("error marshaling text:", err) - } - return b - } - - if want, have := now.Add(3*time.Second).AppendFormat(nil, time.RFC822), mustMarshal(tv()); !reflect.DeepEqual(want, have) { - t.Errorf("wrong time format: want %s, have %s", want, have) - } - - if want, have := now.Add(4*time.Second).AppendFormat(nil, time.RFC822), mustMarshal(tv()); !reflect.DeepEqual(want, have) { - t.Errorf("wrong time format: want %s, have %s", want, have) - } -} - -func BenchmarkValueBindingTimestamp(b *testing.B) { - logger := log.NewNopLogger() - lc := log.With(logger, "ts", log.DefaultTimestamp) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - lc.Log("k", "v") - } -} - -func BenchmarkValueBindingCaller(b *testing.B) { - logger := log.NewNopLogger() - lc := log.With(logger, "caller", log.DefaultCaller) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - lc.Log("k", "v") - } -} diff --git a/vendor/github.com/go-logfmt/logfmt/decode-bench_test.go b/vendor/github.com/go-logfmt/logfmt/decode-bench_test.go deleted file mode 100644 index f66dc25a4..000000000 --- a/vendor/github.com/go-logfmt/logfmt/decode-bench_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package logfmt - -import ( - "bufio" - "bytes" - "testing" - - kr "github.com/kr/logfmt" -) - -func BenchmarkDecodeKeyval(b *testing.B) { - const rows = 10000 - data := []byte{} - for i := 0; i < rows; i++ { - data = append(data, "a=1 b=\"bar\" ƒ=2h3s r=\"esc\\tmore stuff\" d x=sf \n"...) - } - - b.SetBytes(int64(len(data))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - var ( - dec = NewDecoder(bytes.NewReader(data)) - j = 0 - ) - for dec.ScanRecord() { - for dec.ScanKeyval() { - } - j++ - } - if err := dec.Err(); err != nil { - b.Errorf("got %v, want %v", err, nil) - } - if j != rows { - b.Errorf("got %v, want %v", j, rows) - } - } -} - -func BenchmarkKRDecode(b *testing.B) { - const rows = 10000 - data := []byte{} - for i := 0; i < rows; i++ { - data = append(data, "a=1 b=\"bar\" ƒ=2h3s r=\"esc\\tmore stuff\" d x=sf \n"...) - } - - b.SetBytes(int64(len(data))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - var ( - s = bufio.NewScanner(bytes.NewReader(data)) - err error - j = 0 - dh discardHandler - ) - for err == nil && s.Scan() { - err = kr.Unmarshal(s.Bytes(), &dh) - j++ - } - if err == nil { - err = s.Err() - } - if err != nil { - b.Errorf("got %v, want %v", err, nil) - } - if j != rows { - b.Errorf("got %v, want %v", j, rows) - } - } -} - -type discardHandler struct{} - -func (discardHandler) HandleLogfmt(key, val []byte) error { - return nil -} diff --git a/vendor/github.com/go-logfmt/logfmt/decode_test.go b/vendor/github.com/go-logfmt/logfmt/decode_test.go deleted file mode 100644 index 363152daf..000000000 --- a/vendor/github.com/go-logfmt/logfmt/decode_test.go +++ /dev/null @@ -1,184 +0,0 @@ -package logfmt - -import ( - "bytes" - "fmt" - "reflect" - "strings" - "testing" -) - -type kv struct { - k, v []byte -} - -func (s kv) String() string { - return fmt.Sprintf("{k:%q v:%q}", s.k, s.v) -} - -func TestDecoder_scan(t *testing.T) { - tests := []struct { - data string - want [][]kv - }{ - {"", nil}, - {"\n\n", [][]kv{nil, nil}}, - {`x= `, [][]kv{{{[]byte("x"), nil}}}}, - {`y=`, [][]kv{{{[]byte("y"), nil}}}}, - {`y`, [][]kv{{{[]byte("y"), nil}}}}, - {`y=f`, [][]kv{{{[]byte("y"), []byte("f")}}}}, - {"y=\"\\tf\"", [][]kv{{{[]byte("y"), []byte("\tf")}}}}, - {"a=1\n", [][]kv{{{[]byte("a"), []byte("1")}}}}, - { - `a=1 b="bar" ƒ=2h3s r="esc\t" d x=sf `, - [][]kv{{ - {[]byte("a"), []byte("1")}, - {[]byte("b"), []byte("bar")}, - {[]byte("ƒ"), []byte("2h3s")}, - {[]byte("r"), []byte("esc\t")}, - {[]byte("d"), nil}, - {[]byte("x"), []byte("sf")}, - }}, - }, - { - "y=f\ny=g", - [][]kv{ - {{[]byte("y"), []byte("f")}}, - {{[]byte("y"), []byte("g")}}, - }, - }, - { - "y=f \n\x1e y=g", - [][]kv{ - {{[]byte("y"), []byte("f")}}, - {{[]byte("y"), []byte("g")}}, - }, - }, - { - "y= d y=g", - [][]kv{{ - {[]byte("y"), nil}, - {[]byte("d"), nil}, - {[]byte("y"), []byte("g")}, - }}, - }, - { - "y=\"f\"\ny=g", - [][]kv{ - {{[]byte("y"), []byte("f")}}, - {{[]byte("y"), []byte("g")}}, - }, - }, - { - "y=\"f\\n\"y=g", - [][]kv{{ - {[]byte("y"), []byte("f\n")}, - {[]byte("y"), []byte("g")}, - }}, - }, - } - - for _, test := range tests { - var got [][]kv - dec := NewDecoder(strings.NewReader(test.data)) - - for dec.ScanRecord() { - var kvs []kv - for dec.ScanKeyval() { - k := dec.Key() - v := dec.Value() - if k != nil { - kvs = append(kvs, kv{k, v}) - } - } - got = append(got, kvs) - } - if err := dec.Err(); err != nil { - t.Errorf("got err: %v", err) - } - if !reflect.DeepEqual(got, test.want) { - t.Errorf("\n in: %q\n got: %+v\nwant: %+v", test.data, got, test.want) - } - } -} - -func TestDecoder_errors(t *testing.T) { - tests := []struct { - data string - want error - }{ - {"a=1\n=bar", &SyntaxError{Msg: "unexpected '='", Line: 2, Pos: 1}}, - {"a=1\n\"k\"=bar", &SyntaxError{Msg: "unexpected '\"'", Line: 2, Pos: 1}}, - {"a=1\nk\"ey=bar", &SyntaxError{Msg: "unexpected '\"'", Line: 2, Pos: 2}}, - {"a=1\nk=b\"ar", &SyntaxError{Msg: "unexpected '\"'", Line: 2, Pos: 4}}, - {"a=1\nk=b =ar", &SyntaxError{Msg: "unexpected '='", Line: 2, Pos: 5}}, - {"a==", &SyntaxError{Msg: "unexpected '='", Line: 1, Pos: 3}}, - {"a=1\nk=b=ar", &SyntaxError{Msg: "unexpected '='", Line: 2, Pos: 4}}, - {"a=\"1", &SyntaxError{Msg: "unterminated quoted value", Line: 1, Pos: 5}}, - {"a=\"1\\", &SyntaxError{Msg: "unterminated quoted value", Line: 1, Pos: 6}}, - {"a=\"\\t1", &SyntaxError{Msg: "unterminated quoted value", Line: 1, Pos: 7}}, - {"a=\"\\u1\"", &SyntaxError{Msg: "invalid quoted value", Line: 1, Pos: 8}}, - {"a\ufffd=bar", &SyntaxError{Msg: "invalid key", Line: 1, Pos: 5}}, - {"\x80=bar", &SyntaxError{Msg: "invalid key", Line: 1, Pos: 2}}, - {"\x80", &SyntaxError{Msg: "invalid key", Line: 1, Pos: 2}}, - } - - for _, test := range tests { - dec := NewDecoder(strings.NewReader(test.data)) - - for dec.ScanRecord() { - for dec.ScanKeyval() { - } - } - if got, want := dec.Err(), test.want; !reflect.DeepEqual(got, want) { - t.Errorf("got: %v, want: %v", got, want) - } - } -} - -func TestDecoder_decode_encode(t *testing.T) { - tests := []struct { - in, out string - }{ - {"", ""}, - {"\n", "\n"}, - {"\n \n", "\n\n"}, - { - "a=1\nb=2\n", - "a=1\nb=2\n", - }, - { - "a=1 b=\"bar\" ƒ=2h3s r=\"esc\\t\" d x=sf ", - "a=1 b=bar ƒ=2h3s r=\"esc\\t\" d= x=sf\n", - }, - } - - for _, test := range tests { - dec := NewDecoder(strings.NewReader(test.in)) - buf := bytes.Buffer{} - enc := NewEncoder(&buf) - - var err error - loop: - for dec.ScanRecord() && err == nil { - for dec.ScanKeyval() { - if dec.Key() == nil { - continue - } - if err = enc.EncodeKeyval(dec.Key(), dec.Value()); err != nil { - break loop - } - } - enc.EndRecord() - } - if err == nil { - err = dec.Err() - } - if err != nil { - t.Errorf("got err: %v", err) - } - if got, want := buf.String(), test.out; got != want { - t.Errorf("\n got: %q\nwant: %q", got, want) - } - } -} diff --git a/vendor/github.com/go-logfmt/logfmt/encode_internal_test.go b/vendor/github.com/go-logfmt/logfmt/encode_internal_test.go deleted file mode 100644 index 926c201c8..000000000 --- a/vendor/github.com/go-logfmt/logfmt/encode_internal_test.go +++ /dev/null @@ -1,273 +0,0 @@ -package logfmt - -import ( - "bytes" - "errors" - "fmt" - "io/ioutil" - "reflect" - "testing" -) - -func TestSafeString(t *testing.T) { - _, ok := safeString((*stringStringer)(nil)) - if got, want := ok, false; got != want { - t.Errorf(" got %v, want %v", got, want) - } -} - -func TestSafeMarshal(t *testing.T) { - kb, err := safeMarshal((*stringMarshaler)(nil)) - if got := kb; got != nil { - t.Errorf(" got %v, want nil", got) - } - if got, want := err, error(nil); got != want { - t.Errorf(" got %v, want %v", got, want) - } -} - -func TestWriteKeyStrings(t *testing.T) { - keygen := []struct { - name string - fn func(string) interface{} - }{ - { - name: "string", - fn: func(s string) interface{} { return s }, - }, - { - name: "named-string", - fn: func(s string) interface{} { return stringData(s) }, - }, - { - name: "Stringer", - fn: func(s string) interface{} { return stringStringer(s) }, - }, - { - name: "TextMarshaler", - fn: func(s string) interface{} { return stringMarshaler(s) }, - }, - } - - data := []struct { - key string - want string - err error - }{ - {key: "k", want: "k"}, - {key: `\`, want: `\`}, - {key: "\n", err: ErrInvalidKey}, - {key: "\x00", err: ErrInvalidKey}, - {key: "\x10", err: ErrInvalidKey}, - {key: "\x1F", err: ErrInvalidKey}, - {key: "", err: ErrInvalidKey}, - {key: " ", err: ErrInvalidKey}, - {key: "=", err: ErrInvalidKey}, - {key: `"`, err: ErrInvalidKey}, - {key: "k\n", want: "k"}, - {key: "k\nk", want: "kk"}, - {key: "k\tk", want: "kk"}, - {key: "k=k", want: "kk"}, - {key: `"kk"`, want: "kk"}, - } - - for _, g := range keygen { - t.Run(g.name, func(t *testing.T) { - for _, d := range data { - w := &bytes.Buffer{} - key := g.fn(d.key) - err := writeKey(w, key) - if err != d.err { - t.Errorf("%#v: got error: %v, want error: %v", key, err, d.err) - } - if err != nil { - continue - } - if got, want := w.String(), d.want; got != want { - t.Errorf("%#v: got '%s', want '%s'", key, got, want) - } - } - }) - } -} - -func TestWriteKey(t *testing.T) { - var ( - nilPtr *int - one = 1 - ptr = &one - ) - - data := []struct { - key interface{} - want string - err error - }{ - {key: nil, err: ErrNilKey}, - {key: nilPtr, err: ErrNilKey}, - {key: (*stringStringer)(nil), err: ErrNilKey}, - {key: (*stringMarshaler)(nil), err: ErrNilKey}, - {key: (*stringerMarshaler)(nil), err: ErrNilKey}, - {key: ptr, want: "1"}, - - {key: errorMarshaler{}, err: &MarshalerError{Type: reflect.TypeOf(errorMarshaler{}), Err: errMarshaling}}, - {key: make(chan int), err: ErrUnsupportedKeyType}, - {key: []int{}, err: ErrUnsupportedKeyType}, - {key: map[int]int{}, err: ErrUnsupportedKeyType}, - {key: [2]int{}, err: ErrUnsupportedKeyType}, - {key: struct{}{}, err: ErrUnsupportedKeyType}, - {key: fmt.Sprint, err: ErrUnsupportedKeyType}, - } - - for _, d := range data { - w := &bytes.Buffer{} - err := writeKey(w, d.key) - if !reflect.DeepEqual(err, d.err) { - t.Errorf("%#v: got error: %v, want error: %v", d.key, err, d.err) - } - if err != nil { - continue - } - if got, want := w.String(), d.want; got != want { - t.Errorf("%#v: got '%s', want '%s'", d.key, got, want) - } - } -} - -func TestWriteValueStrings(t *testing.T) { - keygen := []func(string) interface{}{ - func(s string) interface{} { return s }, - func(s string) interface{} { return errors.New(s) }, - func(s string) interface{} { return stringData(s) }, - func(s string) interface{} { return stringStringer(s) }, - func(s string) interface{} { return stringMarshaler(s) }, - } - - data := []struct { - value string - want string - err error - }{ - {value: "", want: ""}, - {value: "v", want: "v"}, - {value: " ", want: `" "`}, - {value: "=", want: `"="`}, - {value: `\`, want: `\`}, - {value: `"`, want: `"\""`}, - {value: `\"`, want: `"\\\""`}, - {value: "\n", want: `"\n"`}, - {value: "\x00", want: `"\u0000"`}, - {value: "\x10", want: `"\u0010"`}, - {value: "\x1F", want: `"\u001f"`}, - {value: "µ", want: `µ`}, - } - - for _, g := range keygen { - for _, d := range data { - w := &bytes.Buffer{} - value := g(d.value) - err := writeValue(w, value) - if err != d.err { - t.Errorf("%#v (%[1]T): got error: %v, want error: %v", value, err, d.err) - } - if err != nil { - continue - } - if got, want := w.String(), d.want; got != want { - t.Errorf("%#v (%[1]T): got '%s', want '%s'", value, got, want) - } - } - } -} - -func TestWriteValue(t *testing.T) { - var ( - nilPtr *int - one = 1 - ptr = &one - ) - - data := []struct { - value interface{} - want string - err error - }{ - {value: nil, want: "null"}, - {value: nilPtr, want: "null"}, - {value: (*stringStringer)(nil), want: "null"}, - {value: (*stringMarshaler)(nil), want: "null"}, - {value: (*stringerMarshaler)(nil), want: "null"}, - {value: ptr, want: "1"}, - - {value: errorMarshaler{}, err: &MarshalerError{Type: reflect.TypeOf(errorMarshaler{}), Err: errMarshaling}}, - {value: make(chan int), err: ErrUnsupportedValueType}, - {value: []int{}, err: ErrUnsupportedValueType}, - {value: map[int]int{}, err: ErrUnsupportedValueType}, - {value: [2]int{}, err: ErrUnsupportedValueType}, - {value: struct{}{}, err: ErrUnsupportedValueType}, - {value: fmt.Sprint, err: ErrUnsupportedValueType}, - } - - for _, d := range data { - w := &bytes.Buffer{} - err := writeValue(w, d.value) - if !reflect.DeepEqual(err, d.err) { - t.Errorf("%#v: got error: %v, want error: %v", d.value, err, d.err) - } - if err != nil { - continue - } - if got, want := w.String(), d.want; got != want { - t.Errorf("%#v: got '%s', want '%s'", d.value, got, want) - } - } -} - -type stringData string - -type stringStringer string - -func (s stringStringer) String() string { - return string(s) -} - -type stringMarshaler string - -func (s stringMarshaler) MarshalText() ([]byte, error) { - return []byte(s), nil -} - -type stringerMarshaler string - -func (s stringerMarshaler) String() string { - return "String() called" -} - -func (s stringerMarshaler) MarshalText() ([]byte, error) { - return []byte(s), nil -} - -var errMarshaling = errors.New("marshal error") - -type errorMarshaler struct{} - -func (errorMarshaler) MarshalText() ([]byte, error) { - return nil, errMarshaling -} - -func BenchmarkWriteStringKey(b *testing.B) { - keys := []string{ - "k", - "caller", - "has space", - `"quoted"`, - } - - for _, k := range keys { - b.Run(k, func(b *testing.B) { - for i := 0; i < b.N; i++ { - writeStringKey(ioutil.Discard, k) - } - }) - } -} diff --git a/vendor/github.com/go-logfmt/logfmt/encode_test.go b/vendor/github.com/go-logfmt/logfmt/encode_test.go deleted file mode 100644 index 4b6144b9f..000000000 --- a/vendor/github.com/go-logfmt/logfmt/encode_test.go +++ /dev/null @@ -1,224 +0,0 @@ -package logfmt_test - -import ( - "bytes" - "errors" - "fmt" - "io/ioutil" - "reflect" - "testing" - "time" - - "github.com/go-logfmt/logfmt" -) - -func TestEncodeKeyval(t *testing.T) { - data := []struct { - key, value interface{} - want string - err error - }{ - {key: "k", value: "v", want: "k=v"}, - {key: "k", value: nil, want: "k=null"}, - {key: `\`, value: "v", want: `\=v`}, - {key: "k", value: "", want: "k="}, - {key: "k", value: "null", want: `k="null"`}, - {key: "k", value: "", want: `k=`}, - {key: "k", value: true, want: "k=true"}, - {key: "k", value: 1, want: "k=1"}, - {key: "k", value: 1.025, want: "k=1.025"}, - {key: "k", value: 1e-3, want: "k=0.001"}, - {key: "k", value: 3.5 + 2i, want: "k=(3.5+2i)"}, - {key: "k", value: "v v", want: `k="v v"`}, - {key: "k", value: " ", want: `k=" "`}, - {key: "k", value: `"`, want: `k="\""`}, - {key: "k", value: `=`, want: `k="="`}, - {key: "k", value: `\`, want: `k=\`}, - {key: "k", value: `=\`, want: `k="=\\"`}, - {key: "k", value: `\"`, want: `k="\\\""`}, - {key: "k", value: [2]int{2, 19}, err: logfmt.ErrUnsupportedValueType}, - {key: "k", value: []string{"e1", "e 2"}, err: logfmt.ErrUnsupportedValueType}, - {key: "k", value: structData{"a a", 9}, err: logfmt.ErrUnsupportedValueType}, - {key: "k", value: decimalMarshaler{5, 9}, want: "k=5.9"}, - {key: "k", value: (*decimalMarshaler)(nil), want: "k=null"}, - {key: "k", value: decimalStringer{5, 9}, want: "k=5.9"}, - {key: "k", value: (*decimalStringer)(nil), want: "k=null"}, - {key: "k", value: marshalerStringer{5, 9}, want: "k=5.9"}, - {key: "k", value: (*marshalerStringer)(nil), want: "k=null"}, - {key: "k", value: new(nilMarshaler), want: "k=notnilmarshaler"}, - {key: "k", value: (*nilMarshaler)(nil), want: "k=nilmarshaler"}, - {key: (*marshalerStringer)(nil), value: "v", err: logfmt.ErrNilKey}, - {key: decimalMarshaler{5, 9}, value: "v", want: "5.9=v"}, - {key: (*decimalMarshaler)(nil), value: "v", err: logfmt.ErrNilKey}, - {key: decimalStringer{5, 9}, value: "v", want: "5.9=v"}, - {key: (*decimalStringer)(nil), value: "v", err: logfmt.ErrNilKey}, - {key: marshalerStringer{5, 9}, value: "v", want: "5.9=v"}, - {key: "k", value: "\xbd", want: `k="\ufffd"`}, - {key: "k", value: "\ufffd\x00", want: `k="\ufffd\u0000"`}, - {key: "k", value: "\ufffd", want: `k="\ufffd"`}, - {key: "k", value: []byte("\ufffd\x00"), want: `k="\ufffd\u0000"`}, - {key: "k", value: []byte("\ufffd"), want: `k="\ufffd"`}, - } - - for _, d := range data { - w := &bytes.Buffer{} - enc := logfmt.NewEncoder(w) - err := enc.EncodeKeyval(d.key, d.value) - if err != d.err { - t.Errorf("%#v, %#v: got error: %v, want error: %v", d.key, d.value, err, d.err) - } - if got, want := w.String(), d.want; got != want { - t.Errorf("%#v, %#v: got '%s', want '%s'", d.key, d.value, got, want) - } - } -} - -func TestMarshalKeyvals(t *testing.T) { - one := 1 - ptr := &one - nilPtr := (*int)(nil) - - data := []struct { - in []interface{} - want []byte - err error - }{ - {in: nil, want: nil}, - {in: kv(), want: nil}, - {in: kv(nil, "v"), err: logfmt.ErrNilKey}, - {in: kv(nilPtr, "v"), err: logfmt.ErrNilKey}, - {in: kv("\ufffd"), err: logfmt.ErrInvalidKey}, - {in: kv("\xbd"), err: logfmt.ErrInvalidKey}, - {in: kv("k"), want: []byte("k=null")}, - {in: kv("k", nil), want: []byte("k=null")}, - {in: kv("k", ""), want: []byte("k=")}, - {in: kv("k", "null"), want: []byte(`k="null"`)}, - {in: kv("k", "v"), want: []byte("k=v")}, - {in: kv("k", true), want: []byte("k=true")}, - {in: kv("k", 1), want: []byte("k=1")}, - {in: kv("k", ptr), want: []byte("k=1")}, - {in: kv("k", nilPtr), want: []byte("k=null")}, - {in: kv("k", 1.025), want: []byte("k=1.025")}, - {in: kv("k", 1e-3), want: []byte("k=0.001")}, - {in: kv("k", "v v"), want: []byte(`k="v v"`)}, - {in: kv("k", `"`), want: []byte(`k="\""`)}, - {in: kv("k", `=`), want: []byte(`k="="`)}, - {in: kv("k", `\`), want: []byte(`k=\`)}, - {in: kv("k", `=\`), want: []byte(`k="=\\"`)}, - {in: kv("k", `\"`), want: []byte(`k="\\\""`)}, - {in: kv("k1", "v1", "k2", "v2"), want: []byte("k1=v1 k2=v2")}, - {in: kv("k1", "v1", "k2", [2]int{}), want: []byte("k1=v1 k2=\"unsupported value type\"")}, - {in: kv([2]int{}, "v1", "k2", "v2"), want: []byte("k2=v2")}, - {in: kv("k", time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)), want: []byte("k=2009-11-10T23:00:00Z")}, - {in: kv("k", errorMarshaler{}), want: []byte("k=\"error marshaling value of type logfmt_test.errorMarshaler: marshal error\"")}, - {in: kv("k", decimalMarshaler{5, 9}), want: []byte("k=5.9")}, - {in: kv("k", (*decimalMarshaler)(nil)), want: []byte("k=null")}, - {in: kv("k", decimalStringer{5, 9}), want: []byte("k=5.9")}, - {in: kv("k", (*decimalStringer)(nil)), want: []byte("k=null")}, - {in: kv("k", marshalerStringer{5, 9}), want: []byte("k=5.9")}, - {in: kv("k", (*marshalerStringer)(nil)), want: []byte("k=null")}, - {in: kv(one, "v"), want: []byte("1=v")}, - {in: kv(ptr, "v"), want: []byte("1=v")}, - {in: kv((*marshalerStringer)(nil), "v"), err: logfmt.ErrNilKey}, - {in: kv(decimalMarshaler{5, 9}, "v"), want: []byte("5.9=v")}, - {in: kv((*decimalMarshaler)(nil), "v"), err: logfmt.ErrNilKey}, - {in: kv(decimalStringer{5, 9}, "v"), want: []byte("5.9=v")}, - {in: kv((*decimalStringer)(nil), "v"), err: logfmt.ErrNilKey}, - {in: kv(marshalerStringer{5, 9}, "v"), want: []byte("5.9=v")}, - {in: kv("k", panicingStringer{0}), want: []byte("k=ok")}, - {in: kv("k", panicingStringer{1}), want: []byte("k=PANIC:panic1")}, - // Need extra mechanism to test panic-while-printing-panicVal - //{in: kv("k", panicingStringer{2}), want: []byte("?")}, - } - - for _, d := range data { - got, err := logfmt.MarshalKeyvals(d.in...) - if err != d.err { - t.Errorf("%#v: got error: %v, want error: %v", d.in, err, d.err) - } - if !reflect.DeepEqual(got, d.want) { - t.Errorf("%#v: got '%s', want '%s'", d.in, got, d.want) - } - } -} - -func kv(keyvals ...interface{}) []interface{} { - return keyvals -} - -type structData struct { - A string `logfmt:"fieldA"` - B int -} - -type nilMarshaler int - -func (m *nilMarshaler) MarshalText() ([]byte, error) { - if m == nil { - return []byte("nilmarshaler"), nil - } - return []byte("notnilmarshaler"), nil -} - -type decimalMarshaler struct { - a, b int -} - -func (t decimalMarshaler) MarshalText() ([]byte, error) { - buf := &bytes.Buffer{} - fmt.Fprintf(buf, "%d.%d", t.a, t.b) - return buf.Bytes(), nil -} - -type decimalStringer struct { - a, b int -} - -func (s decimalStringer) String() string { - return fmt.Sprintf("%d.%d", s.a, s.b) -} - -type marshalerStringer struct { - a, b int -} - -func (t marshalerStringer) MarshalText() ([]byte, error) { - buf := &bytes.Buffer{} - fmt.Fprintf(buf, "%d.%d", t.a, t.b) - return buf.Bytes(), nil -} - -func (t marshalerStringer) String() string { - return fmt.Sprint(t.a + t.b) -} - -var errMarshal = errors.New("marshal error") - -type errorMarshaler struct{} - -func (errorMarshaler) MarshalText() ([]byte, error) { - return nil, errMarshal -} - -type panicingStringer struct { - a int -} - -func (p panicingStringer) String() string { - switch p.a { - case 1: - panic("panic1") - case 2: - panic(panicingStringer{a: 2}) - } - return "ok" -} - -func BenchmarkEncodeKeyval(b *testing.B) { - b.ReportAllocs() - enc := logfmt.NewEncoder(ioutil.Discard) - for i := 0; i < b.N; i++ { - enc.EncodeKeyval("sk", "10") - enc.EncodeKeyval("some-key", "a rather long string with spaces") - } -} diff --git a/vendor/github.com/go-logfmt/logfmt/example_test.go b/vendor/github.com/go-logfmt/logfmt/example_test.go deleted file mode 100644 index 829dbd567..000000000 --- a/vendor/github.com/go-logfmt/logfmt/example_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package logfmt_test - -import ( - "errors" - "fmt" - "os" - "strings" - "time" - - "github.com/go-logfmt/logfmt" -) - -func ExampleEncoder() { - check := func(err error) { - if err != nil { - panic(err) - } - } - - e := logfmt.NewEncoder(os.Stdout) - - check(e.EncodeKeyval("id", 1)) - check(e.EncodeKeyval("dur", time.Second+time.Millisecond)) - check(e.EndRecord()) - - check(e.EncodeKeyval("id", 1)) - check(e.EncodeKeyval("path", "/path/to/file")) - check(e.EncodeKeyval("err", errors.New("file not found"))) - check(e.EndRecord()) - - // Output: - // id=1 dur=1.001s - // id=1 path=/path/to/file err="file not found" -} - -func ExampleDecoder() { - in := ` -id=1 dur=1.001s -id=1 path=/path/to/file err="file not found" -` - - d := logfmt.NewDecoder(strings.NewReader(in)) - for d.ScanRecord() { - for d.ScanKeyval() { - fmt.Printf("k: %s v: %s\n", d.Key(), d.Value()) - } - fmt.Println() - } - if d.Err() != nil { - panic(d.Err()) - } - - // Output: - // k: id v: 1 - // k: dur v: 1.001s - // - // k: id v: 1 - // k: path v: /path/to/file - // k: err v: file not found -} diff --git a/vendor/github.com/golang/protobuf/AUTHORS b/vendor/github.com/golang/protobuf/AUTHORS new file mode 100644 index 000000000..15167cd74 --- /dev/null +++ b/vendor/github.com/golang/protobuf/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/github.com/golang/protobuf/CONTRIBUTORS b/vendor/github.com/golang/protobuf/CONTRIBUTORS new file mode 100644 index 000000000..1c4577e96 --- /dev/null +++ b/vendor/github.com/golang/protobuf/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/github.com/golang/protobuf/proto/all_test.go b/vendor/github.com/golang/protobuf/proto/all_test.go deleted file mode 100644 index 1bea4b6e8..000000000 --- a/vendor/github.com/golang/protobuf/proto/all_test.go +++ /dev/null @@ -1,2492 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "math" - "math/rand" - "reflect" - "runtime/debug" - "strings" - "sync" - "testing" - "time" - - . "github.com/golang/protobuf/proto" - pb3 "github.com/golang/protobuf/proto/proto3_proto" - . "github.com/golang/protobuf/proto/test_proto" -) - -var globalO *Buffer - -func old() *Buffer { - if globalO == nil { - globalO = NewBuffer(nil) - } - globalO.Reset() - return globalO -} - -func equalbytes(b1, b2 []byte, t *testing.T) { - if len(b1) != len(b2) { - t.Errorf("wrong lengths: 2*%d != %d", len(b1), len(b2)) - return - } - for i := 0; i < len(b1); i++ { - if b1[i] != b2[i] { - t.Errorf("bad byte[%d]:%x %x: %s %s", i, b1[i], b2[i], b1, b2) - } - } -} - -func initGoTestField() *GoTestField { - f := new(GoTestField) - f.Label = String("label") - f.Type = String("type") - return f -} - -// These are all structurally equivalent but the tag numbers differ. -// (It's remarkable that required, optional, and repeated all have -// 8 letters.) -func initGoTest_RequiredGroup() *GoTest_RequiredGroup { - return &GoTest_RequiredGroup{ - RequiredField: String("required"), - } -} - -func initGoTest_OptionalGroup() *GoTest_OptionalGroup { - return &GoTest_OptionalGroup{ - RequiredField: String("optional"), - } -} - -func initGoTest_RepeatedGroup() *GoTest_RepeatedGroup { - return &GoTest_RepeatedGroup{ - RequiredField: String("repeated"), - } -} - -func initGoTest(setdefaults bool) *GoTest { - pb := new(GoTest) - if setdefaults { - pb.F_BoolDefaulted = Bool(Default_GoTest_F_BoolDefaulted) - pb.F_Int32Defaulted = Int32(Default_GoTest_F_Int32Defaulted) - pb.F_Int64Defaulted = Int64(Default_GoTest_F_Int64Defaulted) - pb.F_Fixed32Defaulted = Uint32(Default_GoTest_F_Fixed32Defaulted) - pb.F_Fixed64Defaulted = Uint64(Default_GoTest_F_Fixed64Defaulted) - pb.F_Uint32Defaulted = Uint32(Default_GoTest_F_Uint32Defaulted) - pb.F_Uint64Defaulted = Uint64(Default_GoTest_F_Uint64Defaulted) - pb.F_FloatDefaulted = Float32(Default_GoTest_F_FloatDefaulted) - pb.F_DoubleDefaulted = Float64(Default_GoTest_F_DoubleDefaulted) - pb.F_StringDefaulted = String(Default_GoTest_F_StringDefaulted) - pb.F_BytesDefaulted = Default_GoTest_F_BytesDefaulted - pb.F_Sint32Defaulted = Int32(Default_GoTest_F_Sint32Defaulted) - pb.F_Sint64Defaulted = Int64(Default_GoTest_F_Sint64Defaulted) - pb.F_Sfixed32Defaulted = Int32(Default_GoTest_F_Sfixed32Defaulted) - pb.F_Sfixed64Defaulted = Int64(Default_GoTest_F_Sfixed64Defaulted) - } - - pb.Kind = GoTest_TIME.Enum() - pb.RequiredField = initGoTestField() - pb.F_BoolRequired = Bool(true) - pb.F_Int32Required = Int32(3) - pb.F_Int64Required = Int64(6) - pb.F_Fixed32Required = Uint32(32) - pb.F_Fixed64Required = Uint64(64) - pb.F_Uint32Required = Uint32(3232) - pb.F_Uint64Required = Uint64(6464) - pb.F_FloatRequired = Float32(3232) - pb.F_DoubleRequired = Float64(6464) - pb.F_StringRequired = String("string") - pb.F_BytesRequired = []byte("bytes") - pb.F_Sint32Required = Int32(-32) - pb.F_Sint64Required = Int64(-64) - pb.F_Sfixed32Required = Int32(-32) - pb.F_Sfixed64Required = Int64(-64) - pb.Requiredgroup = initGoTest_RequiredGroup() - - return pb -} - -func hex(c uint8) uint8 { - if '0' <= c && c <= '9' { - return c - '0' - } - if 'a' <= c && c <= 'f' { - return 10 + c - 'a' - } - if 'A' <= c && c <= 'F' { - return 10 + c - 'A' - } - return 0 -} - -func equal(b []byte, s string, t *testing.T) bool { - if 2*len(b) != len(s) { - // fail(fmt.Sprintf("wrong lengths: 2*%d != %d", len(b), len(s)), b, s, t) - fmt.Printf("wrong lengths: 2*%d != %d\n", len(b), len(s)) - return false - } - for i, j := 0, 0; i < len(b); i, j = i+1, j+2 { - x := hex(s[j])*16 + hex(s[j+1]) - if b[i] != x { - // fail(fmt.Sprintf("bad byte[%d]:%x %x", i, b[i], x), b, s, t) - fmt.Printf("bad byte[%d]:%x %x", i, b[i], x) - return false - } - } - return true -} - -func overify(t *testing.T, pb *GoTest, expected string) { - o := old() - err := o.Marshal(pb) - if err != nil { - fmt.Printf("overify marshal-1 err = %v", err) - o.DebugPrint("", o.Bytes()) - t.Fatalf("expected = %s", expected) - } - if !equal(o.Bytes(), expected, t) { - o.DebugPrint("overify neq 1", o.Bytes()) - t.Fatalf("expected = %s", expected) - } - - // Now test Unmarshal by recreating the original buffer. - pbd := new(GoTest) - err = o.Unmarshal(pbd) - if err != nil { - t.Fatalf("overify unmarshal err = %v", err) - o.DebugPrint("", o.Bytes()) - t.Fatalf("string = %s", expected) - } - o.Reset() - err = o.Marshal(pbd) - if err != nil { - t.Errorf("overify marshal-2 err = %v", err) - o.DebugPrint("", o.Bytes()) - t.Fatalf("string = %s", expected) - } - if !equal(o.Bytes(), expected, t) { - o.DebugPrint("overify neq 2", o.Bytes()) - t.Fatalf("string = %s", expected) - } -} - -// Simple tests for numeric encode/decode primitives (varint, etc.) -func TestNumericPrimitives(t *testing.T) { - for i := uint64(0); i < 1e6; i += 111 { - o := old() - if o.EncodeVarint(i) != nil { - t.Error("EncodeVarint") - break - } - x, e := o.DecodeVarint() - if e != nil { - t.Fatal("DecodeVarint") - } - if x != i { - t.Fatal("varint decode fail:", i, x) - } - - o = old() - if o.EncodeFixed32(i) != nil { - t.Fatal("encFixed32") - } - x, e = o.DecodeFixed32() - if e != nil { - t.Fatal("decFixed32") - } - if x != i { - t.Fatal("fixed32 decode fail:", i, x) - } - - o = old() - if o.EncodeFixed64(i*1234567) != nil { - t.Error("encFixed64") - break - } - x, e = o.DecodeFixed64() - if e != nil { - t.Error("decFixed64") - break - } - if x != i*1234567 { - t.Error("fixed64 decode fail:", i*1234567, x) - break - } - - o = old() - i32 := int32(i - 12345) - if o.EncodeZigzag32(uint64(i32)) != nil { - t.Fatal("EncodeZigzag32") - } - x, e = o.DecodeZigzag32() - if e != nil { - t.Fatal("DecodeZigzag32") - } - if x != uint64(uint32(i32)) { - t.Fatal("zigzag32 decode fail:", i32, x) - } - - o = old() - i64 := int64(i - 12345) - if o.EncodeZigzag64(uint64(i64)) != nil { - t.Fatal("EncodeZigzag64") - } - x, e = o.DecodeZigzag64() - if e != nil { - t.Fatal("DecodeZigzag64") - } - if x != uint64(i64) { - t.Fatal("zigzag64 decode fail:", i64, x) - } - } -} - -// fakeMarshaler is a simple struct implementing Marshaler and Message interfaces. -type fakeMarshaler struct { - b []byte - err error -} - -func (f *fakeMarshaler) Marshal() ([]byte, error) { return f.b, f.err } -func (f *fakeMarshaler) String() string { return fmt.Sprintf("Bytes: %v Error: %v", f.b, f.err) } -func (f *fakeMarshaler) ProtoMessage() {} -func (f *fakeMarshaler) Reset() {} - -type msgWithFakeMarshaler struct { - M *fakeMarshaler `protobuf:"bytes,1,opt,name=fake"` -} - -func (m *msgWithFakeMarshaler) String() string { return CompactTextString(m) } -func (m *msgWithFakeMarshaler) ProtoMessage() {} -func (m *msgWithFakeMarshaler) Reset() {} - -// Simple tests for proto messages that implement the Marshaler interface. -func TestMarshalerEncoding(t *testing.T) { - tests := []struct { - name string - m Message - want []byte - errType reflect.Type - }{ - { - name: "Marshaler that fails", - m: &fakeMarshaler{ - err: errors.New("some marshal err"), - b: []byte{5, 6, 7}, - }, - // Since the Marshal method returned bytes, they should be written to the - // buffer. (For efficiency, we assume that Marshal implementations are - // always correct w.r.t. RequiredNotSetError and output.) - want: []byte{5, 6, 7}, - errType: reflect.TypeOf(errors.New("some marshal err")), - }, - { - name: "Marshaler that fails with RequiredNotSetError", - m: &msgWithFakeMarshaler{ - M: &fakeMarshaler{ - err: &RequiredNotSetError{}, - b: []byte{5, 6, 7}, - }, - }, - // Since there's an error that can be continued after, - // the buffer should be written. - want: []byte{ - 10, 3, // for &msgWithFakeMarshaler - 5, 6, 7, // for &fakeMarshaler - }, - errType: reflect.TypeOf(&RequiredNotSetError{}), - }, - { - name: "Marshaler that succeeds", - m: &fakeMarshaler{ - b: []byte{0, 1, 2, 3, 4, 127, 255}, - }, - want: []byte{0, 1, 2, 3, 4, 127, 255}, - }, - } - for _, test := range tests { - b := NewBuffer(nil) - err := b.Marshal(test.m) - if reflect.TypeOf(err) != test.errType { - t.Errorf("%s: got err %T(%v) wanted %T", test.name, err, err, test.errType) - } - if !reflect.DeepEqual(test.want, b.Bytes()) { - t.Errorf("%s: got bytes %v wanted %v", test.name, b.Bytes(), test.want) - } - if size := Size(test.m); size != len(b.Bytes()) { - t.Errorf("%s: Size(_) = %v, but marshaled to %v bytes", test.name, size, len(b.Bytes())) - } - - m, mErr := Marshal(test.m) - if !bytes.Equal(b.Bytes(), m) { - t.Errorf("%s: Marshal returned %v, but (*Buffer).Marshal wrote %v", test.name, m, b.Bytes()) - } - if !reflect.DeepEqual(err, mErr) { - t.Errorf("%s: Marshal err = %q, but (*Buffer).Marshal returned %q", - test.name, fmt.Sprint(mErr), fmt.Sprint(err)) - } - } -} - -// Ensure that Buffer.Marshal uses O(N) memory for N messages -func TestBufferMarshalAllocs(t *testing.T) { - value := &OtherMessage{Key: Int64(1)} - msg := &MyMessage{Count: Int32(1), Others: []*OtherMessage{value}} - - reallocSize := func(t *testing.T, items int, prealloc int) (int64, int64) { - var b Buffer - b.SetBuf(make([]byte, 0, prealloc)) - - var allocSpace int64 - prevCap := cap(b.Bytes()) - for i := 0; i < items; i++ { - err := b.Marshal(msg) - if err != nil { - t.Errorf("Marshal err = %q", err) - break - } - if c := cap(b.Bytes()); prevCap != c { - allocSpace += int64(c) - prevCap = c - } - } - needSpace := int64(len(b.Bytes())) - return allocSpace, needSpace - } - - for _, prealloc := range []int{0, 100, 10000} { - for _, items := range []int{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000} { - runtimeSpace, need := reallocSize(t, items, prealloc) - totalSpace := int64(prealloc) + runtimeSpace - - runtimeRatio := float64(runtimeSpace) / float64(need) - totalRatio := float64(totalSpace) / float64(need) - - if totalRatio < 1 || runtimeRatio > 4 { - t.Errorf("needed %dB, allocated %dB total (ratio %.1f), allocated %dB at runtime (ratio %.1f)", - need, totalSpace, totalRatio, runtimeSpace, runtimeRatio) - } - } - } -} - -// Simple tests for bytes -func TestBytesPrimitives(t *testing.T) { - o := old() - bytes := []byte{'n', 'o', 'w', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 't', 'i', 'm', 'e'} - if o.EncodeRawBytes(bytes) != nil { - t.Error("EncodeRawBytes") - } - decb, e := o.DecodeRawBytes(false) - if e != nil { - t.Error("DecodeRawBytes") - } - equalbytes(bytes, decb, t) -} - -// Simple tests for strings -func TestStringPrimitives(t *testing.T) { - o := old() - s := "now is the time" - if o.EncodeStringBytes(s) != nil { - t.Error("enc_string") - } - decs, e := o.DecodeStringBytes() - if e != nil { - t.Error("dec_string") - } - if s != decs { - t.Error("string encode/decode fail:", s, decs) - } -} - -// Do we catch the "required bit not set" case? -func TestRequiredBit(t *testing.T) { - o := old() - pb := new(GoTest) - err := o.Marshal(pb) - if err == nil { - t.Error("did not catch missing required fields") - } else if !strings.Contains(err.Error(), "Kind") { - t.Error("wrong error type:", err) - } -} - -// Check that all fields are nil. -// Clearly silly, and a residue from a more interesting test with an earlier, -// different initialization property, but it once caught a compiler bug so -// it lives. -func checkInitialized(pb *GoTest, t *testing.T) { - if pb.F_BoolDefaulted != nil { - t.Error("New or Reset did not set boolean:", *pb.F_BoolDefaulted) - } - if pb.F_Int32Defaulted != nil { - t.Error("New or Reset did not set int32:", *pb.F_Int32Defaulted) - } - if pb.F_Int64Defaulted != nil { - t.Error("New or Reset did not set int64:", *pb.F_Int64Defaulted) - } - if pb.F_Fixed32Defaulted != nil { - t.Error("New or Reset did not set fixed32:", *pb.F_Fixed32Defaulted) - } - if pb.F_Fixed64Defaulted != nil { - t.Error("New or Reset did not set fixed64:", *pb.F_Fixed64Defaulted) - } - if pb.F_Uint32Defaulted != nil { - t.Error("New or Reset did not set uint32:", *pb.F_Uint32Defaulted) - } - if pb.F_Uint64Defaulted != nil { - t.Error("New or Reset did not set uint64:", *pb.F_Uint64Defaulted) - } - if pb.F_FloatDefaulted != nil { - t.Error("New or Reset did not set float:", *pb.F_FloatDefaulted) - } - if pb.F_DoubleDefaulted != nil { - t.Error("New or Reset did not set double:", *pb.F_DoubleDefaulted) - } - if pb.F_StringDefaulted != nil { - t.Error("New or Reset did not set string:", *pb.F_StringDefaulted) - } - if pb.F_BytesDefaulted != nil { - t.Error("New or Reset did not set bytes:", string(pb.F_BytesDefaulted)) - } - if pb.F_Sint32Defaulted != nil { - t.Error("New or Reset did not set int32:", *pb.F_Sint32Defaulted) - } - if pb.F_Sint64Defaulted != nil { - t.Error("New or Reset did not set int64:", *pb.F_Sint64Defaulted) - } -} - -// Does Reset() reset? -func TestReset(t *testing.T) { - pb := initGoTest(true) - // muck with some values - pb.F_BoolDefaulted = Bool(false) - pb.F_Int32Defaulted = Int32(237) - pb.F_Int64Defaulted = Int64(12346) - pb.F_Fixed32Defaulted = Uint32(32000) - pb.F_Fixed64Defaulted = Uint64(666) - pb.F_Uint32Defaulted = Uint32(323232) - pb.F_Uint64Defaulted = nil - pb.F_FloatDefaulted = nil - pb.F_DoubleDefaulted = Float64(0) - pb.F_StringDefaulted = String("gotcha") - pb.F_BytesDefaulted = []byte("asdfasdf") - pb.F_Sint32Defaulted = Int32(123) - pb.F_Sint64Defaulted = Int64(789) - pb.Reset() - checkInitialized(pb, t) -} - -// All required fields set, no defaults provided. -func TestEncodeDecode1(t *testing.T) { - pb := initGoTest(false) - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 0x20 - "714000000000000000"+ // field 14, encoding 1, value 0x40 - "78a019"+ // field 15, encoding 0, value 0xca0 = 3232 - "8001c032"+ // field 16, encoding 0, value 0x1940 = 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2, string "string" - "b304"+ // field 70, encoding 3, start group - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // field 70, encoding 4, end group - "aa0605"+"6279746573"+ // field 101, encoding 2, string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "c506e0ffffff"+ // field 104, encoding 5, -32 fixed32 - "c906c0ffffffffffffff") // field 105, encoding 1, -64 fixed64 -} - -// All required fields set, defaults provided. -func TestEncodeDecode2(t *testing.T) { - pb := initGoTest(true) - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "c506e0ffffff"+ // field 104, encoding 5, -32 fixed32 - "c906c0ffffffffffffff"+ // field 105, encoding 1, -64 fixed64 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f"+ // field 403, encoding 0, value 127 - "a519e0ffffff"+ // field 404, encoding 5, -32 fixed32 - "a919c0ffffffffffffff") // field 405, encoding 1, -64 fixed64 - -} - -// All default fields set to their default value by hand -func TestEncodeDecode3(t *testing.T) { - pb := initGoTest(false) - pb.F_BoolDefaulted = Bool(true) - pb.F_Int32Defaulted = Int32(32) - pb.F_Int64Defaulted = Int64(64) - pb.F_Fixed32Defaulted = Uint32(320) - pb.F_Fixed64Defaulted = Uint64(640) - pb.F_Uint32Defaulted = Uint32(3200) - pb.F_Uint64Defaulted = Uint64(6400) - pb.F_FloatDefaulted = Float32(314159) - pb.F_DoubleDefaulted = Float64(271828) - pb.F_StringDefaulted = String("hello, \"world!\"\n") - pb.F_BytesDefaulted = []byte("Bignose") - pb.F_Sint32Defaulted = Int32(-32) - pb.F_Sint64Defaulted = Int64(-64) - pb.F_Sfixed32Defaulted = Int32(-32) - pb.F_Sfixed64Defaulted = Int64(-64) - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "c506e0ffffff"+ // field 104, encoding 5, -32 fixed32 - "c906c0ffffffffffffff"+ // field 105, encoding 1, -64 fixed64 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f"+ // field 403, encoding 0, value 127 - "a519e0ffffff"+ // field 404, encoding 5, -32 fixed32 - "a919c0ffffffffffffff") // field 405, encoding 1, -64 fixed64 - -} - -// All required fields set, defaults provided, all non-defaulted optional fields have values. -func TestEncodeDecode4(t *testing.T) { - pb := initGoTest(true) - pb.Table = String("hello") - pb.Param = Int32(7) - pb.OptionalField = initGoTestField() - pb.F_BoolOptional = Bool(true) - pb.F_Int32Optional = Int32(32) - pb.F_Int64Optional = Int64(64) - pb.F_Fixed32Optional = Uint32(3232) - pb.F_Fixed64Optional = Uint64(6464) - pb.F_Uint32Optional = Uint32(323232) - pb.F_Uint64Optional = Uint64(646464) - pb.F_FloatOptional = Float32(32.) - pb.F_DoubleOptional = Float64(64.) - pb.F_StringOptional = String("hello") - pb.F_BytesOptional = []byte("Bignose") - pb.F_Sint32Optional = Int32(-32) - pb.F_Sint64Optional = Int64(-64) - pb.F_Sfixed32Optional = Int32(-32) - pb.F_Sfixed64Optional = Int64(-64) - pb.Optionalgroup = initGoTest_OptionalGroup() - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "1205"+"68656c6c6f"+ // field 2, encoding 2, string "hello" - "1807"+ // field 3, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "320d"+"0a056c6162656c120474797065"+ // field 6, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "f00101"+ // field 30, encoding 0, value 1 - "f80120"+ // field 31, encoding 0, value 32 - "800240"+ // field 32, encoding 0, value 64 - "8d02a00c0000"+ // field 33, encoding 5, value 3232 - "91024019000000000000"+ // field 34, encoding 1, value 6464 - "9802a0dd13"+ // field 35, encoding 0, value 323232 - "a002c0ba27"+ // field 36, encoding 0, value 646464 - "ad0200000042"+ // field 37, encoding 5, value 32.0 - "b1020000000000005040"+ // field 38, encoding 1, value 64.0 - "ba0205"+"68656c6c6f"+ // field 39, encoding 2, string "hello" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "d305"+ // start group field 90 level 1 - "da0508"+"6f7074696f6e616c"+ // field 91, encoding 2, string "optional" - "d405"+ // end group field 90 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "c506e0ffffff"+ // field 104, encoding 5, -32 fixed32 - "c906c0ffffffffffffff"+ // field 105, encoding 1, -64 fixed64 - "ea1207"+"4269676e6f7365"+ // field 301, encoding 2, string "Bignose" - "f0123f"+ // field 302, encoding 0, value 63 - "f8127f"+ // field 303, encoding 0, value 127 - "8513e0ffffff"+ // field 304, encoding 5, -32 fixed32 - "8913c0ffffffffffffff"+ // field 305, encoding 1, -64 fixed64 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f"+ // field 403, encoding 0, value 127 - "a519e0ffffff"+ // field 404, encoding 5, -32 fixed32 - "a919c0ffffffffffffff") // field 405, encoding 1, -64 fixed64 - -} - -// All required fields set, defaults provided, all repeated fields given two values. -func TestEncodeDecode5(t *testing.T) { - pb := initGoTest(true) - pb.RepeatedField = []*GoTestField{initGoTestField(), initGoTestField()} - pb.F_BoolRepeated = []bool{false, true} - pb.F_Int32Repeated = []int32{32, 33} - pb.F_Int64Repeated = []int64{64, 65} - pb.F_Fixed32Repeated = []uint32{3232, 3333} - pb.F_Fixed64Repeated = []uint64{6464, 6565} - pb.F_Uint32Repeated = []uint32{323232, 333333} - pb.F_Uint64Repeated = []uint64{646464, 656565} - pb.F_FloatRepeated = []float32{32., 33.} - pb.F_DoubleRepeated = []float64{64., 65.} - pb.F_StringRepeated = []string{"hello", "sailor"} - pb.F_BytesRepeated = [][]byte{[]byte("big"), []byte("nose")} - pb.F_Sint32Repeated = []int32{32, -32} - pb.F_Sint64Repeated = []int64{64, -64} - pb.F_Sfixed32Repeated = []int32{32, -32} - pb.F_Sfixed64Repeated = []int64{64, -64} - pb.Repeatedgroup = []*GoTest_RepeatedGroup{initGoTest_RepeatedGroup(), initGoTest_RepeatedGroup()} - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "2a0d"+"0a056c6162656c120474797065"+ // field 5, encoding 2 (GoTestField) - "2a0d"+"0a056c6162656c120474797065"+ // field 5, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "a00100"+ // field 20, encoding 0, value 0 - "a00101"+ // field 20, encoding 0, value 1 - "a80120"+ // field 21, encoding 0, value 32 - "a80121"+ // field 21, encoding 0, value 33 - "b00140"+ // field 22, encoding 0, value 64 - "b00141"+ // field 22, encoding 0, value 65 - "bd01a00c0000"+ // field 23, encoding 5, value 3232 - "bd01050d0000"+ // field 23, encoding 5, value 3333 - "c1014019000000000000"+ // field 24, encoding 1, value 6464 - "c101a519000000000000"+ // field 24, encoding 1, value 6565 - "c801a0dd13"+ // field 25, encoding 0, value 323232 - "c80195ac14"+ // field 25, encoding 0, value 333333 - "d001c0ba27"+ // field 26, encoding 0, value 646464 - "d001b58928"+ // field 26, encoding 0, value 656565 - "dd0100000042"+ // field 27, encoding 5, value 32.0 - "dd0100000442"+ // field 27, encoding 5, value 33.0 - "e1010000000000005040"+ // field 28, encoding 1, value 64.0 - "e1010000000000405040"+ // field 28, encoding 1, value 65.0 - "ea0105"+"68656c6c6f"+ // field 29, encoding 2, string "hello" - "ea0106"+"7361696c6f72"+ // field 29, encoding 2, string "sailor" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "8305"+ // start group field 80 level 1 - "8a0508"+"7265706561746564"+ // field 81, encoding 2, string "repeated" - "8405"+ // end group field 80 level 1 - "8305"+ // start group field 80 level 1 - "8a0508"+"7265706561746564"+ // field 81, encoding 2, string "repeated" - "8405"+ // end group field 80 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "c506e0ffffff"+ // field 104, encoding 5, -32 fixed32 - "c906c0ffffffffffffff"+ // field 105, encoding 1, -64 fixed64 - "ca0c03"+"626967"+ // field 201, encoding 2, string "big" - "ca0c04"+"6e6f7365"+ // field 201, encoding 2, string "nose" - "d00c40"+ // field 202, encoding 0, value 32 - "d00c3f"+ // field 202, encoding 0, value -32 - "d80c8001"+ // field 203, encoding 0, value 64 - "d80c7f"+ // field 203, encoding 0, value -64 - "e50c20000000"+ // field 204, encoding 5, 32 fixed32 - "e50ce0ffffff"+ // field 204, encoding 5, -32 fixed32 - "e90c4000000000000000"+ // field 205, encoding 1, 64 fixed64 - "e90cc0ffffffffffffff"+ // field 205, encoding 1, -64 fixed64 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f"+ // field 403, encoding 0, value 127 - "a519e0ffffff"+ // field 404, encoding 5, -32 fixed32 - "a919c0ffffffffffffff") // field 405, encoding 1, -64 fixed64 - -} - -// All required fields set, all packed repeated fields given two values. -func TestEncodeDecode6(t *testing.T) { - pb := initGoTest(false) - pb.F_BoolRepeatedPacked = []bool{false, true} - pb.F_Int32RepeatedPacked = []int32{32, 33} - pb.F_Int64RepeatedPacked = []int64{64, 65} - pb.F_Fixed32RepeatedPacked = []uint32{3232, 3333} - pb.F_Fixed64RepeatedPacked = []uint64{6464, 6565} - pb.F_Uint32RepeatedPacked = []uint32{323232, 333333} - pb.F_Uint64RepeatedPacked = []uint64{646464, 656565} - pb.F_FloatRepeatedPacked = []float32{32., 33.} - pb.F_DoubleRepeatedPacked = []float64{64., 65.} - pb.F_Sint32RepeatedPacked = []int32{32, -32} - pb.F_Sint64RepeatedPacked = []int64{64, -64} - pb.F_Sfixed32RepeatedPacked = []int32{32, -32} - pb.F_Sfixed64RepeatedPacked = []int64{64, -64} - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "9203020001"+ // field 50, encoding 2, 2 bytes, value 0, value 1 - "9a03022021"+ // field 51, encoding 2, 2 bytes, value 32, value 33 - "a203024041"+ // field 52, encoding 2, 2 bytes, value 64, value 65 - "aa0308"+ // field 53, encoding 2, 8 bytes - "a00c0000050d0000"+ // value 3232, value 3333 - "b20310"+ // field 54, encoding 2, 16 bytes - "4019000000000000a519000000000000"+ // value 6464, value 6565 - "ba0306"+ // field 55, encoding 2, 6 bytes - "a0dd1395ac14"+ // value 323232, value 333333 - "c20306"+ // field 56, encoding 2, 6 bytes - "c0ba27b58928"+ // value 646464, value 656565 - "ca0308"+ // field 57, encoding 2, 8 bytes - "0000004200000442"+ // value 32.0, value 33.0 - "d20310"+ // field 58, encoding 2, 16 bytes - "00000000000050400000000000405040"+ // value 64.0, value 65.0 - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "c506e0ffffff"+ // field 104, encoding 5, -32 fixed32 - "c906c0ffffffffffffff"+ // field 105, encoding 1, -64 fixed64 - "b21f02"+ // field 502, encoding 2, 2 bytes - "403f"+ // value 32, value -32 - "ba1f03"+ // field 503, encoding 2, 3 bytes - "80017f"+ // value 64, value -64 - "c21f08"+ // field 504, encoding 2, 8 bytes - "20000000e0ffffff"+ // value 32, value -32 - "ca1f10"+ // field 505, encoding 2, 16 bytes - "4000000000000000c0ffffffffffffff") // value 64, value -64 - -} - -// Test that we can encode empty bytes fields. -func TestEncodeDecodeBytes1(t *testing.T) { - pb := initGoTest(false) - - // Create our bytes - pb.F_BytesRequired = []byte{} - pb.F_BytesRepeated = [][]byte{{}} - pb.F_BytesOptional = []byte{} - - d, err := Marshal(pb) - if err != nil { - t.Error(err) - } - - pbd := new(GoTest) - if err := Unmarshal(d, pbd); err != nil { - t.Error(err) - } - - if pbd.F_BytesRequired == nil || len(pbd.F_BytesRequired) != 0 { - t.Error("required empty bytes field is incorrect") - } - if pbd.F_BytesRepeated == nil || len(pbd.F_BytesRepeated) == 1 && pbd.F_BytesRepeated[0] == nil { - t.Error("repeated empty bytes field is incorrect") - } - if pbd.F_BytesOptional == nil || len(pbd.F_BytesOptional) != 0 { - t.Error("optional empty bytes field is incorrect") - } -} - -// Test that we encode nil-valued fields of a repeated bytes field correctly. -// Since entries in a repeated field cannot be nil, nil must mean empty value. -func TestEncodeDecodeBytes2(t *testing.T) { - pb := initGoTest(false) - - // Create our bytes - pb.F_BytesRepeated = [][]byte{nil} - - d, err := Marshal(pb) - if err != nil { - t.Error(err) - } - - pbd := new(GoTest) - if err := Unmarshal(d, pbd); err != nil { - t.Error(err) - } - - if len(pbd.F_BytesRepeated) != 1 || pbd.F_BytesRepeated[0] == nil { - t.Error("Unexpected value for repeated bytes field") - } -} - -// All required fields set, defaults provided, all repeated fields given two values. -func TestSkippingUnrecognizedFields(t *testing.T) { - o := old() - pb := initGoTestField() - - // Marshal it normally. - o.Marshal(pb) - - // Now new a GoSkipTest record. - skip := &GoSkipTest{ - SkipInt32: Int32(32), - SkipFixed32: Uint32(3232), - SkipFixed64: Uint64(6464), - SkipString: String("skipper"), - Skipgroup: &GoSkipTest_SkipGroup{ - GroupInt32: Int32(75), - GroupString: String("wxyz"), - }, - } - - // Marshal it into same buffer. - o.Marshal(skip) - - pbd := new(GoTestField) - o.Unmarshal(pbd) - - // The __unrecognized field should be a marshaling of GoSkipTest - skipd := new(GoSkipTest) - - o.SetBuf(pbd.XXX_unrecognized) - o.Unmarshal(skipd) - - if *skipd.SkipInt32 != *skip.SkipInt32 { - t.Error("skip int32", skipd.SkipInt32) - } - if *skipd.SkipFixed32 != *skip.SkipFixed32 { - t.Error("skip fixed32", skipd.SkipFixed32) - } - if *skipd.SkipFixed64 != *skip.SkipFixed64 { - t.Error("skip fixed64", skipd.SkipFixed64) - } - if *skipd.SkipString != *skip.SkipString { - t.Error("skip string", *skipd.SkipString) - } - if *skipd.Skipgroup.GroupInt32 != *skip.Skipgroup.GroupInt32 { - t.Error("skip group int32", skipd.Skipgroup.GroupInt32) - } - if *skipd.Skipgroup.GroupString != *skip.Skipgroup.GroupString { - t.Error("skip group string", *skipd.Skipgroup.GroupString) - } -} - -// Check that unrecognized fields of a submessage are preserved. -func TestSubmessageUnrecognizedFields(t *testing.T) { - nm := &NewMessage{ - Nested: &NewMessage_Nested{ - Name: String("Nigel"), - FoodGroup: String("carbs"), - }, - } - b, err := Marshal(nm) - if err != nil { - t.Fatalf("Marshal of NewMessage: %v", err) - } - - // Unmarshal into an OldMessage. - om := new(OldMessage) - if err := Unmarshal(b, om); err != nil { - t.Fatalf("Unmarshal to OldMessage: %v", err) - } - exp := &OldMessage{ - Nested: &OldMessage_Nested{ - Name: String("Nigel"), - // normal protocol buffer users should not do this - XXX_unrecognized: []byte("\x12\x05carbs"), - }, - } - if !Equal(om, exp) { - t.Errorf("om = %v, want %v", om, exp) - } - - // Clone the OldMessage. - om = Clone(om).(*OldMessage) - if !Equal(om, exp) { - t.Errorf("Clone(om) = %v, want %v", om, exp) - } - - // Marshal the OldMessage, then unmarshal it into an empty NewMessage. - if b, err = Marshal(om); err != nil { - t.Fatalf("Marshal of OldMessage: %v", err) - } - t.Logf("Marshal(%v) -> %q", om, b) - nm2 := new(NewMessage) - if err := Unmarshal(b, nm2); err != nil { - t.Fatalf("Unmarshal to NewMessage: %v", err) - } - if !Equal(nm, nm2) { - t.Errorf("NewMessage round-trip: %v => %v", nm, nm2) - } -} - -// Check that an int32 field can be upgraded to an int64 field. -func TestNegativeInt32(t *testing.T) { - om := &OldMessage{ - Num: Int32(-1), - } - b, err := Marshal(om) - if err != nil { - t.Fatalf("Marshal of OldMessage: %v", err) - } - - // Check the size. It should be 11 bytes; - // 1 for the field/wire type, and 10 for the negative number. - if len(b) != 11 { - t.Errorf("%v marshaled as %q, wanted 11 bytes", om, b) - } - - // Unmarshal into a NewMessage. - nm := new(NewMessage) - if err := Unmarshal(b, nm); err != nil { - t.Fatalf("Unmarshal to NewMessage: %v", err) - } - want := &NewMessage{ - Num: Int64(-1), - } - if !Equal(nm, want) { - t.Errorf("nm = %v, want %v", nm, want) - } -} - -// Check that we can grow an array (repeated field) to have many elements. -// This test doesn't depend only on our encoding; for variety, it makes sure -// we create, encode, and decode the correct contents explicitly. It's therefore -// a bit messier. -// This test also uses (and hence tests) the Marshal/Unmarshal functions -// instead of the methods. -func TestBigRepeated(t *testing.T) { - pb := initGoTest(true) - - // Create the arrays - const N = 50 // Internally the library starts much smaller. - pb.Repeatedgroup = make([]*GoTest_RepeatedGroup, N) - pb.F_Sint64Repeated = make([]int64, N) - pb.F_Sint32Repeated = make([]int32, N) - pb.F_BytesRepeated = make([][]byte, N) - pb.F_StringRepeated = make([]string, N) - pb.F_DoubleRepeated = make([]float64, N) - pb.F_FloatRepeated = make([]float32, N) - pb.F_Uint64Repeated = make([]uint64, N) - pb.F_Uint32Repeated = make([]uint32, N) - pb.F_Fixed64Repeated = make([]uint64, N) - pb.F_Fixed32Repeated = make([]uint32, N) - pb.F_Int64Repeated = make([]int64, N) - pb.F_Int32Repeated = make([]int32, N) - pb.F_BoolRepeated = make([]bool, N) - pb.RepeatedField = make([]*GoTestField, N) - - // Fill in the arrays with checkable values. - igtf := initGoTestField() - igtrg := initGoTest_RepeatedGroup() - for i := 0; i < N; i++ { - pb.Repeatedgroup[i] = igtrg - pb.F_Sint64Repeated[i] = int64(i) - pb.F_Sint32Repeated[i] = int32(i) - s := fmt.Sprint(i) - pb.F_BytesRepeated[i] = []byte(s) - pb.F_StringRepeated[i] = s - pb.F_DoubleRepeated[i] = float64(i) - pb.F_FloatRepeated[i] = float32(i) - pb.F_Uint64Repeated[i] = uint64(i) - pb.F_Uint32Repeated[i] = uint32(i) - pb.F_Fixed64Repeated[i] = uint64(i) - pb.F_Fixed32Repeated[i] = uint32(i) - pb.F_Int64Repeated[i] = int64(i) - pb.F_Int32Repeated[i] = int32(i) - pb.F_BoolRepeated[i] = i%2 == 0 - pb.RepeatedField[i] = igtf - } - - // Marshal. - buf, _ := Marshal(pb) - - // Now test Unmarshal by recreating the original buffer. - pbd := new(GoTest) - Unmarshal(buf, pbd) - - // Check the checkable values - for i := uint64(0); i < N; i++ { - if pbd.Repeatedgroup[i] == nil { // TODO: more checking? - t.Error("pbd.Repeatedgroup bad") - } - if x := uint64(pbd.F_Sint64Repeated[i]); x != i { - t.Error("pbd.F_Sint64Repeated bad", x, i) - } - if x := uint64(pbd.F_Sint32Repeated[i]); x != i { - t.Error("pbd.F_Sint32Repeated bad", x, i) - } - s := fmt.Sprint(i) - equalbytes(pbd.F_BytesRepeated[i], []byte(s), t) - if pbd.F_StringRepeated[i] != s { - t.Error("pbd.F_Sint32Repeated bad", pbd.F_StringRepeated[i], i) - } - if x := uint64(pbd.F_DoubleRepeated[i]); x != i { - t.Error("pbd.F_DoubleRepeated bad", x, i) - } - if x := uint64(pbd.F_FloatRepeated[i]); x != i { - t.Error("pbd.F_FloatRepeated bad", x, i) - } - if x := pbd.F_Uint64Repeated[i]; x != i { - t.Error("pbd.F_Uint64Repeated bad", x, i) - } - if x := uint64(pbd.F_Uint32Repeated[i]); x != i { - t.Error("pbd.F_Uint32Repeated bad", x, i) - } - if x := pbd.F_Fixed64Repeated[i]; x != i { - t.Error("pbd.F_Fixed64Repeated bad", x, i) - } - if x := uint64(pbd.F_Fixed32Repeated[i]); x != i { - t.Error("pbd.F_Fixed32Repeated bad", x, i) - } - if x := uint64(pbd.F_Int64Repeated[i]); x != i { - t.Error("pbd.F_Int64Repeated bad", x, i) - } - if x := uint64(pbd.F_Int32Repeated[i]); x != i { - t.Error("pbd.F_Int32Repeated bad", x, i) - } - if x := pbd.F_BoolRepeated[i]; x != (i%2 == 0) { - t.Error("pbd.F_BoolRepeated bad", x, i) - } - if pbd.RepeatedField[i] == nil { // TODO: more checking? - t.Error("pbd.RepeatedField bad") - } - } -} - -func TestBadWireTypeUnknown(t *testing.T) { - var b []byte - fmt.Sscanf("0a01780d00000000080b101612036161611521000000202c220362626225370000002203636363214200000000000000584d5a036464645900000000000056405d63000000", "%x", &b) - - m := new(MyMessage) - if err := Unmarshal(b, m); err != nil { - t.Errorf("unexpected Unmarshal error: %v", err) - } - - var unknown []byte - fmt.Sscanf("0a01780d0000000010161521000000202c2537000000214200000000000000584d5a036464645d63000000", "%x", &unknown) - if !bytes.Equal(m.XXX_unrecognized, unknown) { - t.Errorf("unknown bytes mismatch:\ngot %x\nwant %x", m.XXX_unrecognized, unknown) - } - DiscardUnknown(m) - - want := &MyMessage{Count: Int32(11), Name: String("aaa"), Pet: []string{"bbb", "ccc"}, Bigfloat: Float64(88)} - if !Equal(m, want) { - t.Errorf("message mismatch:\ngot %v\nwant %v", m, want) - } -} - -func encodeDecode(t *testing.T, in, out Message, msg string) { - buf, err := Marshal(in) - if err != nil { - t.Fatalf("failed marshaling %v: %v", msg, err) - } - if err := Unmarshal(buf, out); err != nil { - t.Fatalf("failed unmarshaling %v: %v", msg, err) - } -} - -func TestPackedNonPackedDecoderSwitching(t *testing.T) { - np, p := new(NonPackedTest), new(PackedTest) - - // non-packed -> packed - np.A = []int32{0, 1, 1, 2, 3, 5} - encodeDecode(t, np, p, "non-packed -> packed") - if !reflect.DeepEqual(np.A, p.B) { - t.Errorf("failed non-packed -> packed; np.A=%+v, p.B=%+v", np.A, p.B) - } - - // packed -> non-packed - np.Reset() - p.B = []int32{3, 1, 4, 1, 5, 9} - encodeDecode(t, p, np, "packed -> non-packed") - if !reflect.DeepEqual(p.B, np.A) { - t.Errorf("failed packed -> non-packed; p.B=%+v, np.A=%+v", p.B, np.A) - } -} - -func TestProto1RepeatedGroup(t *testing.T) { - pb := &MessageList{ - Message: []*MessageList_Message{ - { - Name: String("blah"), - Count: Int32(7), - }, - // NOTE: pb.Message[1] is a nil - nil, - }, - } - - o := old() - err := o.Marshal(pb) - if err == nil || !strings.Contains(err.Error(), "repeated field Message has nil") { - t.Fatalf("unexpected or no error when marshaling: %v", err) - } -} - -// Test that enums work. Checks for a bug introduced by making enums -// named types instead of int32: newInt32FromUint64 would crash with -// a type mismatch in reflect.PointTo. -func TestEnum(t *testing.T) { - pb := new(GoEnum) - pb.Foo = FOO_FOO1.Enum() - o := old() - if err := o.Marshal(pb); err != nil { - t.Fatal("error encoding enum:", err) - } - pb1 := new(GoEnum) - if err := o.Unmarshal(pb1); err != nil { - t.Fatal("error decoding enum:", err) - } - if *pb1.Foo != FOO_FOO1 { - t.Error("expected 7 but got ", *pb1.Foo) - } -} - -// Enum types have String methods. Check that enum fields can be printed. -// We don't care what the value actually is, just as long as it doesn't crash. -func TestPrintingNilEnumFields(t *testing.T) { - pb := new(GoEnum) - _ = fmt.Sprintf("%+v", pb) -} - -// Verify that absent required fields cause Marshal/Unmarshal to return errors. -func TestRequiredFieldEnforcement(t *testing.T) { - pb := new(GoTestField) - _, err := Marshal(pb) - if err == nil { - t.Error("marshal: expected error, got nil") - } else if _, ok := err.(*RequiredNotSetError); !ok || !strings.Contains(err.Error(), "Label") { - t.Errorf("marshal: bad error type: %v", err) - } - - // A slightly sneaky, yet valid, proto. It encodes the same required field twice, - // so simply counting the required fields is insufficient. - // field 1, encoding 2, value "hi" - buf := []byte("\x0A\x02hi\x0A\x02hi") - err = Unmarshal(buf, pb) - if err == nil { - t.Error("unmarshal: expected error, got nil") - } else if _, ok := err.(*RequiredNotSetError); !ok || !strings.Contains(err.Error(), "Type") && !strings.Contains(err.Error(), "{Unknown}") { - // TODO: remove unknown cases once we commit to the new unmarshaler. - t.Errorf("unmarshal: bad error type: %v", err) - } -} - -// Verify that absent required fields in groups cause Marshal/Unmarshal to return errors. -func TestRequiredFieldEnforcementGroups(t *testing.T) { - pb := &GoTestRequiredGroupField{Group: &GoTestRequiredGroupField_Group{}} - if _, err := Marshal(pb); err == nil { - t.Error("marshal: expected error, got nil") - } else if _, ok := err.(*RequiredNotSetError); !ok || !strings.Contains(err.Error(), "Group.Field") { - t.Errorf("marshal: bad error type: %v", err) - } - - buf := []byte{11, 12} - if err := Unmarshal(buf, pb); err == nil { - t.Error("unmarshal: expected error, got nil") - } else if _, ok := err.(*RequiredNotSetError); !ok || !strings.Contains(err.Error(), "Group.Field") && !strings.Contains(err.Error(), "Group.{Unknown}") { - t.Errorf("unmarshal: bad error type: %v", err) - } -} - -func TestTypedNilMarshal(t *testing.T) { - // A typed nil should return ErrNil and not crash. - { - var m *GoEnum - if _, err := Marshal(m); err != ErrNil { - t.Errorf("Marshal(%#v): got %v, want ErrNil", m, err) - } - } - - { - m := &Communique{Union: &Communique_Msg{nil}} - if _, err := Marshal(m); err == nil || err == ErrNil { - t.Errorf("Marshal(%#v): got %v, want errOneofHasNil", m, err) - } - } -} - -// A type that implements the Marshaler interface, but is not nillable. -type nonNillableInt uint64 - -func (nni nonNillableInt) Marshal() ([]byte, error) { - return EncodeVarint(uint64(nni)), nil -} - -type NNIMessage struct { - nni nonNillableInt -} - -func (*NNIMessage) Reset() {} -func (*NNIMessage) String() string { return "" } -func (*NNIMessage) ProtoMessage() {} - -type NMMessage struct{} - -func (*NMMessage) Reset() {} -func (*NMMessage) String() string { return "" } -func (*NMMessage) ProtoMessage() {} - -// Verify a type that uses the Marshaler interface, but has a nil pointer. -func TestNilMarshaler(t *testing.T) { - // Try a struct with a Marshaler field that is nil. - // It should be directly marshable. - nmm := new(NMMessage) - if _, err := Marshal(nmm); err != nil { - t.Error("unexpected error marshaling nmm: ", err) - } - - // Try a struct with a Marshaler field that is not nillable. - nnim := new(NNIMessage) - nnim.nni = 7 - var _ Marshaler = nnim.nni // verify it is truly a Marshaler - if _, err := Marshal(nnim); err != nil { - t.Error("unexpected error marshaling nnim: ", err) - } -} - -func TestAllSetDefaults(t *testing.T) { - // Exercise SetDefaults with all scalar field types. - m := &Defaults{ - // NaN != NaN, so override that here. - F_Nan: Float32(1.7), - } - expected := &Defaults{ - F_Bool: Bool(true), - F_Int32: Int32(32), - F_Int64: Int64(64), - F_Fixed32: Uint32(320), - F_Fixed64: Uint64(640), - F_Uint32: Uint32(3200), - F_Uint64: Uint64(6400), - F_Float: Float32(314159), - F_Double: Float64(271828), - F_String: String(`hello, "world!"` + "\n"), - F_Bytes: []byte("Bignose"), - F_Sint32: Int32(-32), - F_Sint64: Int64(-64), - F_Enum: Defaults_GREEN.Enum(), - F_Pinf: Float32(float32(math.Inf(1))), - F_Ninf: Float32(float32(math.Inf(-1))), - F_Nan: Float32(1.7), - StrZero: String(""), - } - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("SetDefaults failed\n got %v\nwant %v", m, expected) - } -} - -func TestSetDefaultsWithSetField(t *testing.T) { - // Check that a set value is not overridden. - m := &Defaults{ - F_Int32: Int32(12), - } - SetDefaults(m) - if v := m.GetF_Int32(); v != 12 { - t.Errorf("m.FInt32 = %v, want 12", v) - } -} - -func TestSetDefaultsWithSubMessage(t *testing.T) { - m := &OtherMessage{ - Key: Int64(123), - Inner: &InnerMessage{ - Host: String("gopher"), - }, - } - expected := &OtherMessage{ - Key: Int64(123), - Inner: &InnerMessage{ - Host: String("gopher"), - Port: Int32(4000), - }, - } - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("\n got %v\nwant %v", m, expected) - } -} - -func TestSetDefaultsWithRepeatedSubMessage(t *testing.T) { - m := &MyMessage{ - RepInner: []*InnerMessage{{}}, - } - expected := &MyMessage{ - RepInner: []*InnerMessage{{ - Port: Int32(4000), - }}, - } - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("\n got %v\nwant %v", m, expected) - } -} - -func TestSetDefaultWithRepeatedNonMessage(t *testing.T) { - m := &MyMessage{ - Pet: []string{"turtle", "wombat"}, - } - expected := Clone(m) - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("\n got %v\nwant %v", m, expected) - } -} - -func TestMaximumTagNumber(t *testing.T) { - m := &MaxTag{ - LastField: String("natural goat essence"), - } - buf, err := Marshal(m) - if err != nil { - t.Fatalf("proto.Marshal failed: %v", err) - } - m2 := new(MaxTag) - if err := Unmarshal(buf, m2); err != nil { - t.Fatalf("proto.Unmarshal failed: %v", err) - } - if got, want := m2.GetLastField(), *m.LastField; got != want { - t.Errorf("got %q, want %q", got, want) - } -} - -func TestJSON(t *testing.T) { - m := &MyMessage{ - Count: Int32(4), - Pet: []string{"bunny", "kitty"}, - Inner: &InnerMessage{ - Host: String("cauchy"), - }, - Bikeshed: MyMessage_GREEN.Enum(), - } - const expected = `{"count":4,"pet":["bunny","kitty"],"inner":{"host":"cauchy"},"bikeshed":1}` - - b, err := json.Marshal(m) - if err != nil { - t.Fatalf("json.Marshal failed: %v", err) - } - s := string(b) - if s != expected { - t.Errorf("got %s\nwant %s", s, expected) - } - - received := new(MyMessage) - if err := json.Unmarshal(b, received); err != nil { - t.Fatalf("json.Unmarshal failed: %v", err) - } - if !Equal(received, m) { - t.Fatalf("got %s, want %s", received, m) - } - - // Test unmarshalling of JSON with symbolic enum name. - const old = `{"count":4,"pet":["bunny","kitty"],"inner":{"host":"cauchy"},"bikeshed":"GREEN"}` - received.Reset() - if err := json.Unmarshal([]byte(old), received); err != nil { - t.Fatalf("json.Unmarshal failed: %v", err) - } - if !Equal(received, m) { - t.Fatalf("got %s, want %s", received, m) - } -} - -func TestBadWireType(t *testing.T) { - b := []byte{7<<3 | 6} // field 7, wire type 6 - pb := new(OtherMessage) - if err := Unmarshal(b, pb); err == nil { - t.Errorf("Unmarshal did not fail") - } else if !strings.Contains(err.Error(), "unknown wire type") { - t.Errorf("wrong error: %v", err) - } -} - -func TestBytesWithInvalidLength(t *testing.T) { - // If a byte sequence has an invalid (negative) length, Unmarshal should not panic. - b := []byte{2<<3 | WireBytes, 0xff, 0xff, 0xff, 0xff, 0xff, 0} - Unmarshal(b, new(MyMessage)) -} - -func TestLengthOverflow(t *testing.T) { - // Overflowing a length should not panic. - b := []byte{2<<3 | WireBytes, 1, 1, 3<<3 | WireBytes, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01} - Unmarshal(b, new(MyMessage)) -} - -func TestVarintOverflow(t *testing.T) { - // Overflowing a 64-bit length should not be allowed. - b := []byte{1<<3 | WireVarint, 0x01, 3<<3 | WireBytes, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01} - if err := Unmarshal(b, new(MyMessage)); err == nil { - t.Fatalf("Overflowed uint64 length without error") - } -} - -func TestBytesWithInvalidLengthInGroup(t *testing.T) { - // Overflowing a 64-bit length should not be allowed. - b := []byte{0xbb, 0x30, 0xb2, 0x30, 0xb0, 0xb2, 0x83, 0xf1, 0xb0, 0xb2, 0xef, 0xbf, 0xbd, 0x01} - if err := Unmarshal(b, new(MyMessage)); err == nil { - t.Fatalf("Overflowed uint64 length without error") - } -} - -func TestUnmarshalFuzz(t *testing.T) { - const N = 1000 - seed := time.Now().UnixNano() - t.Logf("RNG seed is %d", seed) - rng := rand.New(rand.NewSource(seed)) - buf := make([]byte, 20) - for i := 0; i < N; i++ { - for j := range buf { - buf[j] = byte(rng.Intn(256)) - } - fuzzUnmarshal(t, buf) - } -} - -func TestMergeMessages(t *testing.T) { - pb := &MessageList{Message: []*MessageList_Message{{Name: String("x"), Count: Int32(1)}}} - data, err := Marshal(pb) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - - pb1 := new(MessageList) - if err := Unmarshal(data, pb1); err != nil { - t.Fatalf("first Unmarshal: %v", err) - } - if err := Unmarshal(data, pb1); err != nil { - t.Fatalf("second Unmarshal: %v", err) - } - if len(pb1.Message) != 1 { - t.Errorf("two Unmarshals produced %d Messages, want 1", len(pb1.Message)) - } - - pb2 := new(MessageList) - if err := UnmarshalMerge(data, pb2); err != nil { - t.Fatalf("first UnmarshalMerge: %v", err) - } - if err := UnmarshalMerge(data, pb2); err != nil { - t.Fatalf("second UnmarshalMerge: %v", err) - } - if len(pb2.Message) != 2 { - t.Errorf("two UnmarshalMerges produced %d Messages, want 2", len(pb2.Message)) - } -} - -func TestExtensionMarshalOrder(t *testing.T) { - m := &MyMessage{Count: Int(123)} - if err := SetExtension(m, E_Ext_More, &Ext{Data: String("alpha")}); err != nil { - t.Fatalf("SetExtension: %v", err) - } - if err := SetExtension(m, E_Ext_Text, String("aleph")); err != nil { - t.Fatalf("SetExtension: %v", err) - } - if err := SetExtension(m, E_Ext_Number, Int32(1)); err != nil { - t.Fatalf("SetExtension: %v", err) - } - - // Serialize m several times, and check we get the same bytes each time. - var orig []byte - for i := 0; i < 100; i++ { - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - if i == 0 { - orig = b - continue - } - if !bytes.Equal(b, orig) { - t.Errorf("Bytes differ on attempt #%d", i) - } - } -} - -func TestExtensionMapFieldMarshalDeterministic(t *testing.T) { - m := &MyMessage{Count: Int(123)} - if err := SetExtension(m, E_Ext_More, &Ext{MapField: map[int32]int32{1: 1, 2: 2, 3: 3, 4: 4}}); err != nil { - t.Fatalf("SetExtension: %v", err) - } - marshal := func(m Message) []byte { - var b Buffer - b.SetDeterministic(true) - if err := b.Marshal(m); err != nil { - t.Fatalf("Marshal failed: %v", err) - } - return b.Bytes() - } - - want := marshal(m) - for i := 0; i < 100; i++ { - if got := marshal(m); !bytes.Equal(got, want) { - t.Errorf("Marshal produced inconsistent output with determinism enabled (pass %d).\n got %v\nwant %v", i, got, want) - } - } -} - -// Many extensions, because small maps might not iterate differently on each iteration. -var exts = []*ExtensionDesc{ - E_X201, - E_X202, - E_X203, - E_X204, - E_X205, - E_X206, - E_X207, - E_X208, - E_X209, - E_X210, - E_X211, - E_X212, - E_X213, - E_X214, - E_X215, - E_X216, - E_X217, - E_X218, - E_X219, - E_X220, - E_X221, - E_X222, - E_X223, - E_X224, - E_X225, - E_X226, - E_X227, - E_X228, - E_X229, - E_X230, - E_X231, - E_X232, - E_X233, - E_X234, - E_X235, - E_X236, - E_X237, - E_X238, - E_X239, - E_X240, - E_X241, - E_X242, - E_X243, - E_X244, - E_X245, - E_X246, - E_X247, - E_X248, - E_X249, - E_X250, -} - -func TestMessageSetMarshalOrder(t *testing.T) { - m := &MyMessageSet{} - for _, x := range exts { - if err := SetExtension(m, x, &Empty{}); err != nil { - t.Fatalf("SetExtension: %v", err) - } - } - - buf, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - - // Serialize m several times, and check we get the same bytes each time. - for i := 0; i < 10; i++ { - b1, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - if !bytes.Equal(b1, buf) { - t.Errorf("Bytes differ on re-Marshal #%d", i) - } - - m2 := &MyMessageSet{} - if err := Unmarshal(buf, m2); err != nil { - t.Errorf("Unmarshal: %v", err) - } - b2, err := Marshal(m2) - if err != nil { - t.Errorf("re-Marshal: %v", err) - } - if !bytes.Equal(b2, buf) { - t.Errorf("Bytes differ on round-trip #%d", i) - } - } -} - -func TestUnmarshalMergesMessages(t *testing.T) { - // If a nested message occurs twice in the input, - // the fields should be merged when decoding. - a := &OtherMessage{ - Key: Int64(123), - Inner: &InnerMessage{ - Host: String("polhode"), - Port: Int32(1234), - }, - } - aData, err := Marshal(a) - if err != nil { - t.Fatalf("Marshal(a): %v", err) - } - b := &OtherMessage{ - Weight: Float32(1.2), - Inner: &InnerMessage{ - Host: String("herpolhode"), - Connected: Bool(true), - }, - } - bData, err := Marshal(b) - if err != nil { - t.Fatalf("Marshal(b): %v", err) - } - want := &OtherMessage{ - Key: Int64(123), - Weight: Float32(1.2), - Inner: &InnerMessage{ - Host: String("herpolhode"), - Port: Int32(1234), - Connected: Bool(true), - }, - } - got := new(OtherMessage) - if err := Unmarshal(append(aData, bData...), got); err != nil { - t.Fatalf("Unmarshal: %v", err) - } - if !Equal(got, want) { - t.Errorf("\n got %v\nwant %v", got, want) - } -} - -func TestUnmarshalMergesGroups(t *testing.T) { - // If a nested group occurs twice in the input, - // the fields should be merged when decoding. - a := &GroupNew{ - G: &GroupNew_G{ - X: Int32(7), - Y: Int32(8), - }, - } - aData, err := Marshal(a) - if err != nil { - t.Fatalf("Marshal(a): %v", err) - } - b := &GroupNew{ - G: &GroupNew_G{ - X: Int32(9), - }, - } - bData, err := Marshal(b) - if err != nil { - t.Fatalf("Marshal(b): %v", err) - } - want := &GroupNew{ - G: &GroupNew_G{ - X: Int32(9), - Y: Int32(8), - }, - } - got := new(GroupNew) - if err := Unmarshal(append(aData, bData...), got); err != nil { - t.Fatalf("Unmarshal: %v", err) - } - if !Equal(got, want) { - t.Errorf("\n got %v\nwant %v", got, want) - } -} - -func TestEncodingSizes(t *testing.T) { - tests := []struct { - m Message - n int - }{ - {&Defaults{F_Int32: Int32(math.MaxInt32)}, 6}, - {&Defaults{F_Int32: Int32(math.MinInt32)}, 11}, - {&Defaults{F_Uint32: Uint32(uint32(math.MaxInt32) + 1)}, 6}, - {&Defaults{F_Uint32: Uint32(math.MaxUint32)}, 6}, - } - for _, test := range tests { - b, err := Marshal(test.m) - if err != nil { - t.Errorf("Marshal(%v): %v", test.m, err) - continue - } - if len(b) != test.n { - t.Errorf("Marshal(%v) yielded %d bytes, want %d bytes", test.m, len(b), test.n) - } - } -} - -func TestRequiredNotSetError(t *testing.T) { - pb := initGoTest(false) - pb.RequiredField.Label = nil - pb.F_Int32Required = nil - pb.F_Int64Required = nil - - expected := "0807" + // field 1, encoding 0, value 7 - "2206" + "120474797065" + // field 4, encoding 2 (GoTestField) - "5001" + // field 10, encoding 0, value 1 - "6d20000000" + // field 13, encoding 5, value 0x20 - "714000000000000000" + // field 14, encoding 1, value 0x40 - "78a019" + // field 15, encoding 0, value 0xca0 = 3232 - "8001c032" + // field 16, encoding 0, value 0x1940 = 6464 - "8d0100004a45" + // field 17, encoding 5, value 3232.0 - "9101000000000040b940" + // field 18, encoding 1, value 6464.0 - "9a0106" + "737472696e67" + // field 19, encoding 2, string "string" - "b304" + // field 70, encoding 3, start group - "ba0408" + "7265717569726564" + // field 71, encoding 2, string "required" - "b404" + // field 70, encoding 4, end group - "aa0605" + "6279746573" + // field 101, encoding 2, string "bytes" - "b0063f" + // field 102, encoding 0, 0x3f zigzag32 - "b8067f" + // field 103, encoding 0, 0x7f zigzag64 - "c506e0ffffff" + // field 104, encoding 5, -32 fixed32 - "c906c0ffffffffffffff" // field 105, encoding 1, -64 fixed64 - - o := old() - bytes, err := Marshal(pb) - if _, ok := err.(*RequiredNotSetError); !ok { - fmt.Printf("marshal-1 err = %v, want *RequiredNotSetError", err) - o.DebugPrint("", bytes) - t.Fatalf("expected = %s", expected) - } - if !strings.Contains(err.Error(), "RequiredField.Label") { - t.Errorf("marshal-1 wrong err msg: %v", err) - } - if !equal(bytes, expected, t) { - o.DebugPrint("neq 1", bytes) - t.Fatalf("expected = %s", expected) - } - - // Now test Unmarshal by recreating the original buffer. - pbd := new(GoTest) - err = Unmarshal(bytes, pbd) - if _, ok := err.(*RequiredNotSetError); !ok { - t.Fatalf("unmarshal err = %v, want *RequiredNotSetError", err) - o.DebugPrint("", bytes) - t.Fatalf("string = %s", expected) - } - if !strings.Contains(err.Error(), "RequiredField.Label") && !strings.Contains(err.Error(), "RequiredField.{Unknown}") { - t.Errorf("unmarshal wrong err msg: %v", err) - } - bytes, err = Marshal(pbd) - if _, ok := err.(*RequiredNotSetError); !ok { - t.Errorf("marshal-2 err = %v, want *RequiredNotSetError", err) - o.DebugPrint("", bytes) - t.Fatalf("string = %s", expected) - } - if !strings.Contains(err.Error(), "RequiredField.Label") { - t.Errorf("marshal-2 wrong err msg: %v", err) - } - if !equal(bytes, expected, t) { - o.DebugPrint("neq 2", bytes) - t.Fatalf("string = %s", expected) - } -} - -func TestRequiredNotSetErrorWithBadWireTypes(t *testing.T) { - // Required field expects a varint, and properly found a varint. - if err := Unmarshal([]byte{0x08, 0x00}, new(GoEnum)); err != nil { - t.Errorf("Unmarshal = %v, want nil", err) - } - // Required field expects a varint, but found a fixed32 instead. - if err := Unmarshal([]byte{0x0d, 0x00, 0x00, 0x00, 0x00}, new(GoEnum)); err == nil { - t.Errorf("Unmarshal = nil, want RequiredNotSetError") - } - // Required field expects a varint, and found both a varint and fixed32 (ignored). - m := new(GoEnum) - if err := Unmarshal([]byte{0x08, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00}, m); err != nil { - t.Errorf("Unmarshal = %v, want nil", err) - } - if !bytes.Equal(m.XXX_unrecognized, []byte{0x0d, 0x00, 0x00, 0x00, 0x00}) { - t.Errorf("expected fixed32 to appear as unknown bytes: %x", m.XXX_unrecognized) - } -} - -func fuzzUnmarshal(t *testing.T, data []byte) { - defer func() { - if e := recover(); e != nil { - t.Errorf("These bytes caused a panic: %+v", data) - t.Logf("Stack:\n%s", debug.Stack()) - t.FailNow() - } - }() - - pb := new(MyMessage) - Unmarshal(data, pb) -} - -func TestMapFieldMarshal(t *testing.T) { - m := &MessageWithMap{ - NameMapping: map[int32]string{ - 1: "Rob", - 4: "Ian", - 8: "Dave", - }, - } - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - - // b should be the concatenation of these three byte sequences in some order. - parts := []string{ - "\n\a\b\x01\x12\x03Rob", - "\n\a\b\x04\x12\x03Ian", - "\n\b\b\x08\x12\x04Dave", - } - ok := false - for i := range parts { - for j := range parts { - if j == i { - continue - } - for k := range parts { - if k == i || k == j { - continue - } - try := parts[i] + parts[j] + parts[k] - if bytes.Equal(b, []byte(try)) { - ok = true - break - } - } - } - } - if !ok { - t.Fatalf("Incorrect Marshal output.\n got %q\nwant %q (or a permutation of that)", b, parts[0]+parts[1]+parts[2]) - } - t.Logf("FYI b: %q", b) - - (new(Buffer)).DebugPrint("Dump of b", b) -} - -func TestMapFieldDeterministicMarshal(t *testing.T) { - m := &MessageWithMap{ - NameMapping: map[int32]string{ - 1: "Rob", - 4: "Ian", - 8: "Dave", - }, - } - - marshal := func(m Message) []byte { - var b Buffer - b.SetDeterministic(true) - if err := b.Marshal(m); err != nil { - t.Fatalf("Marshal failed: %v", err) - } - return b.Bytes() - } - - want := marshal(m) - for i := 0; i < 10; i++ { - if got := marshal(m); !bytes.Equal(got, want) { - t.Errorf("Marshal produced inconsistent output with determinism enabled (pass %d).\n got %v\nwant %v", i, got, want) - } - } -} - -func TestMapFieldRoundTrips(t *testing.T) { - m := &MessageWithMap{ - NameMapping: map[int32]string{ - 1: "Rob", - 4: "Ian", - 8: "Dave", - }, - MsgMapping: map[int64]*FloatingPoint{ - 0x7001: {F: Float64(2.0)}, - }, - ByteMapping: map[bool][]byte{ - false: []byte("that's not right!"), - true: []byte("aye, 'tis true!"), - }, - } - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - t.Logf("FYI b: %q", b) - m2 := new(MessageWithMap) - if err := Unmarshal(b, m2); err != nil { - t.Fatalf("Unmarshal: %v", err) - } - if !Equal(m, m2) { - t.Errorf("Map did not survive a round trip.\ninitial: %v\n final: %v", m, m2) - } -} - -func TestMapFieldWithNil(t *testing.T) { - m1 := &MessageWithMap{ - MsgMapping: map[int64]*FloatingPoint{ - 1: nil, - }, - } - b, err := Marshal(m1) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - m2 := new(MessageWithMap) - if err := Unmarshal(b, m2); err != nil { - t.Fatalf("Unmarshal: %v, got these bytes: %v", err, b) - } - if v, ok := m2.MsgMapping[1]; !ok { - t.Error("msg_mapping[1] not present") - } else if v != nil { - t.Errorf("msg_mapping[1] not nil: %v", v) - } -} - -func TestMapFieldWithNilBytes(t *testing.T) { - m1 := &MessageWithMap{ - ByteMapping: map[bool][]byte{ - false: {}, - true: nil, - }, - } - n := Size(m1) - b, err := Marshal(m1) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - if n != len(b) { - t.Errorf("Size(m1) = %d; want len(Marshal(m1)) = %d", n, len(b)) - } - m2 := new(MessageWithMap) - if err := Unmarshal(b, m2); err != nil { - t.Fatalf("Unmarshal: %v, got these bytes: %v", err, b) - } - if v, ok := m2.ByteMapping[false]; !ok { - t.Error("byte_mapping[false] not present") - } else if len(v) != 0 { - t.Errorf("byte_mapping[false] not empty: %#v", v) - } - if v, ok := m2.ByteMapping[true]; !ok { - t.Error("byte_mapping[true] not present") - } else if len(v) != 0 { - t.Errorf("byte_mapping[true] not empty: %#v", v) - } -} - -func TestDecodeMapFieldMissingKey(t *testing.T) { - b := []byte{ - 0x0A, 0x03, // message, tag 1 (name_mapping), of length 3 bytes - // no key - 0x12, 0x01, 0x6D, // string value of length 1 byte, value "m" - } - got := &MessageWithMap{} - err := Unmarshal(b, got) - if err != nil { - t.Fatalf("failed to marshal map with missing key: %v", err) - } - want := &MessageWithMap{NameMapping: map[int32]string{0: "m"}} - if !Equal(got, want) { - t.Errorf("Unmarshaled map with no key was not as expected. got: %v, want %v", got, want) - } -} - -func TestDecodeMapFieldMissingValue(t *testing.T) { - b := []byte{ - 0x0A, 0x02, // message, tag 1 (name_mapping), of length 2 bytes - 0x08, 0x01, // varint key, value 1 - // no value - } - got := &MessageWithMap{} - err := Unmarshal(b, got) - if err != nil { - t.Fatalf("failed to marshal map with missing value: %v", err) - } - want := &MessageWithMap{NameMapping: map[int32]string{1: ""}} - if !Equal(got, want) { - t.Errorf("Unmarshaled map with no value was not as expected. got: %v, want %v", got, want) - } -} - -func TestOneof(t *testing.T) { - m := &Communique{} - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal of empty message with oneof: %v", err) - } - if len(b) != 0 { - t.Errorf("Marshal of empty message yielded too many bytes: %v", b) - } - - m = &Communique{ - Union: &Communique_Name{"Barry"}, - } - - // Round-trip. - b, err = Marshal(m) - if err != nil { - t.Fatalf("Marshal of message with oneof: %v", err) - } - if len(b) != 7 { // name tag/wire (1) + name len (1) + name (5) - t.Errorf("Incorrect marshal of message with oneof: %v", b) - } - m.Reset() - if err := Unmarshal(b, m); err != nil { - t.Fatalf("Unmarshal of message with oneof: %v", err) - } - if x, ok := m.Union.(*Communique_Name); !ok || x.Name != "Barry" { - t.Errorf("After round trip, Union = %+v", m.Union) - } - if name := m.GetName(); name != "Barry" { - t.Errorf("After round trip, GetName = %q, want %q", name, "Barry") - } - - // Let's try with a message in the oneof. - m.Union = &Communique_Msg{&Strings{StringField: String("deep deep string")}} - b, err = Marshal(m) - if err != nil { - t.Fatalf("Marshal of message with oneof set to message: %v", err) - } - if len(b) != 20 { // msg tag/wire (1) + msg len (1) + msg (1 + 1 + 16) - t.Errorf("Incorrect marshal of message with oneof set to message: %v", b) - } - m.Reset() - if err := Unmarshal(b, m); err != nil { - t.Fatalf("Unmarshal of message with oneof set to message: %v", err) - } - ss, ok := m.Union.(*Communique_Msg) - if !ok || ss.Msg.GetStringField() != "deep deep string" { - t.Errorf("After round trip with oneof set to message, Union = %+v", m.Union) - } -} - -func TestOneofNilBytes(t *testing.T) { - // A oneof with nil byte slice should marshal to tag + 0 (size), with no error. - m := &Communique{Union: &Communique_Data{Data: nil}} - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal failed: %v", err) - } - want := []byte{ - 7<<3 | 2, // tag 7, wire type 2 - 0, // size - } - if !bytes.Equal(b, want) { - t.Errorf("Wrong result of Marshal: got %x, want %x", b, want) - } -} - -func TestInefficientPackedBool(t *testing.T) { - // https://github.com/golang/protobuf/issues/76 - inp := []byte{ - 0x12, 0x02, // 0x12 = 2<<3|2; 2 bytes - // Usually a bool should take a single byte, - // but it is permitted to be any varint. - 0xb9, 0x30, - } - if err := Unmarshal(inp, new(MoreRepeated)); err != nil { - t.Error(err) - } -} - -// Make sure pure-reflect-based implementation handles -// []int32-[]enum conversion correctly. -func TestRepeatedEnum2(t *testing.T) { - pb := &RepeatedEnum{ - Color: []RepeatedEnum_Color{RepeatedEnum_RED}, - } - b, err := Marshal(pb) - if err != nil { - t.Fatalf("Marshal failed: %v", err) - } - x := new(RepeatedEnum) - err = Unmarshal(b, x) - if err != nil { - t.Fatalf("Unmarshal failed: %v", err) - } - if !Equal(pb, x) { - t.Errorf("Incorrect result: want: %v got: %v", pb, x) - } -} - -// TestConcurrentMarshal makes sure that it is safe to marshal -// same message in multiple goroutines concurrently. -func TestConcurrentMarshal(t *testing.T) { - pb := initGoTest(true) - const N = 100 - b := make([][]byte, N) - - var wg sync.WaitGroup - for i := 0; i < N; i++ { - wg.Add(1) - go func(i int) { - defer wg.Done() - var err error - b[i], err = Marshal(pb) - if err != nil { - t.Errorf("marshal error: %v", err) - } - }(i) - } - - wg.Wait() - for i := 1; i < N; i++ { - if !bytes.Equal(b[0], b[i]) { - t.Errorf("concurrent marshal result not same: b[0] = %v, b[%d] = %v", b[0], i, b[i]) - } - } -} - -func TestInvalidUTF8(t *testing.T) { - const invalidUTF8 = "\xde\xad\xbe\xef\x80\x00\xff" - tests := []struct { - label string - proto2 Message - proto3 Message - want []byte - }{{ - label: "Scalar", - proto2: &TestUTF8{Scalar: String(invalidUTF8)}, - proto3: &pb3.TestUTF8{Scalar: invalidUTF8}, - want: []byte{0x0a, 0x07, 0xde, 0xad, 0xbe, 0xef, 0x80, 0x00, 0xff}, - }, { - label: "Vector", - proto2: &TestUTF8{Vector: []string{invalidUTF8}}, - proto3: &pb3.TestUTF8{Vector: []string{invalidUTF8}}, - want: []byte{0x12, 0x07, 0xde, 0xad, 0xbe, 0xef, 0x80, 0x00, 0xff}, - }, { - label: "Oneof", - proto2: &TestUTF8{Oneof: &TestUTF8_Field{invalidUTF8}}, - proto3: &pb3.TestUTF8{Oneof: &pb3.TestUTF8_Field{invalidUTF8}}, - want: []byte{0x1a, 0x07, 0xde, 0xad, 0xbe, 0xef, 0x80, 0x00, 0xff}, - }, { - label: "MapKey", - proto2: &TestUTF8{MapKey: map[string]int64{invalidUTF8: 0}}, - proto3: &pb3.TestUTF8{MapKey: map[string]int64{invalidUTF8: 0}}, - want: []byte{0x22, 0x0b, 0x0a, 0x07, 0xde, 0xad, 0xbe, 0xef, 0x80, 0x00, 0xff, 0x10, 0x00}, - }, { - label: "MapValue", - proto2: &TestUTF8{MapValue: map[int64]string{0: invalidUTF8}}, - proto3: &pb3.TestUTF8{MapValue: map[int64]string{0: invalidUTF8}}, - want: []byte{0x2a, 0x0b, 0x08, 0x00, 0x12, 0x07, 0xde, 0xad, 0xbe, 0xef, 0x80, 0x00, 0xff}, - }} - - for _, tt := range tests { - // Proto2 should not validate UTF-8. - b, err := Marshal(tt.proto2) - if err != nil { - t.Errorf("Marshal(proto2.%s) = %v, want nil", tt.label, err) - } - if !bytes.Equal(b, tt.want) { - t.Errorf("Marshal(proto2.%s) = %x, want %x", tt.label, b, tt.want) - } - - m := Clone(tt.proto2) - m.Reset() - if err = Unmarshal(tt.want, m); err != nil { - t.Errorf("Unmarshal(proto2.%s) = %v, want nil", tt.label, err) - } - if !Equal(m, tt.proto2) { - t.Errorf("proto2.%s: output mismatch:\ngot %v\nwant %v", tt.label, m, tt.proto2) - } - - // Proto3 should validate UTF-8. - b, err = Marshal(tt.proto3) - if err == nil { - t.Errorf("Marshal(proto3.%s) = %v, want non-nil", tt.label, err) - } - if !bytes.Equal(b, tt.want) { - t.Errorf("Marshal(proto3.%s) = %x, want %x", tt.label, b, tt.want) - } - - m = Clone(tt.proto3) - m.Reset() - err = Unmarshal(tt.want, m) - if err == nil { - t.Errorf("Unmarshal(proto3.%s) = %v, want non-nil", tt.label, err) - } - if !Equal(m, tt.proto3) { - t.Errorf("proto3.%s: output mismatch:\ngot %v\nwant %v", tt.label, m, tt.proto2) - } - } -} - -func TestRequired(t *testing.T) { - // The F_BoolRequired field appears after all of the required fields. - // It should still be handled even after multiple required field violations. - m := &GoTest{F_BoolRequired: Bool(true)} - got, err := Marshal(m) - if _, ok := err.(*RequiredNotSetError); !ok { - t.Errorf("Marshal() = %v, want RequiredNotSetError error", err) - } - if want := []byte{0x50, 0x01}; !bytes.Equal(got, want) { - t.Errorf("Marshal() = %x, want %x", got, want) - } - - m = new(GoTest) - err = Unmarshal(got, m) - if _, ok := err.(*RequiredNotSetError); !ok { - t.Errorf("Marshal() = %v, want RequiredNotSetError error", err) - } - if !m.GetF_BoolRequired() { - t.Error("m.F_BoolRequired = false, want true") - } -} - -// Benchmarks - -func testMsg() *GoTest { - pb := initGoTest(true) - const N = 1000 // Internally the library starts much smaller. - pb.F_Int32Repeated = make([]int32, N) - pb.F_DoubleRepeated = make([]float64, N) - for i := 0; i < N; i++ { - pb.F_Int32Repeated[i] = int32(i) - pb.F_DoubleRepeated[i] = float64(i) - } - return pb -} - -func bytesMsg() *GoTest { - pb := initGoTest(true) - buf := make([]byte, 4000) - for i := range buf { - buf[i] = byte(i) - } - pb.F_BytesDefaulted = buf - return pb -} - -func benchmarkMarshal(b *testing.B, pb Message, marshal func(Message) ([]byte, error)) { - d, _ := marshal(pb) - b.SetBytes(int64(len(d))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - marshal(pb) - } -} - -func benchmarkBufferMarshal(b *testing.B, pb Message) { - p := NewBuffer(nil) - benchmarkMarshal(b, pb, func(pb0 Message) ([]byte, error) { - p.Reset() - err := p.Marshal(pb0) - return p.Bytes(), err - }) -} - -func benchmarkSize(b *testing.B, pb Message) { - benchmarkMarshal(b, pb, func(pb0 Message) ([]byte, error) { - Size(pb) - return nil, nil - }) -} - -func newOf(pb Message) Message { - in := reflect.ValueOf(pb) - if in.IsNil() { - return pb - } - return reflect.New(in.Type().Elem()).Interface().(Message) -} - -func benchmarkUnmarshal(b *testing.B, pb Message, unmarshal func([]byte, Message) error) { - d, _ := Marshal(pb) - b.SetBytes(int64(len(d))) - pbd := newOf(pb) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - unmarshal(d, pbd) - } -} - -func benchmarkBufferUnmarshal(b *testing.B, pb Message) { - p := NewBuffer(nil) - benchmarkUnmarshal(b, pb, func(d []byte, pb0 Message) error { - p.SetBuf(d) - return p.Unmarshal(pb0) - }) -} - -// Benchmark{Marshal,BufferMarshal,Size,Unmarshal,BufferUnmarshal}{,Bytes} - -func BenchmarkMarshal(b *testing.B) { - benchmarkMarshal(b, testMsg(), Marshal) -} - -func BenchmarkBufferMarshal(b *testing.B) { - benchmarkBufferMarshal(b, testMsg()) -} - -func BenchmarkSize(b *testing.B) { - benchmarkSize(b, testMsg()) -} - -func BenchmarkUnmarshal(b *testing.B) { - benchmarkUnmarshal(b, testMsg(), Unmarshal) -} - -func BenchmarkBufferUnmarshal(b *testing.B) { - benchmarkBufferUnmarshal(b, testMsg()) -} - -func BenchmarkMarshalBytes(b *testing.B) { - benchmarkMarshal(b, bytesMsg(), Marshal) -} - -func BenchmarkBufferMarshalBytes(b *testing.B) { - benchmarkBufferMarshal(b, bytesMsg()) -} - -func BenchmarkSizeBytes(b *testing.B) { - benchmarkSize(b, bytesMsg()) -} - -func BenchmarkUnmarshalBytes(b *testing.B) { - benchmarkUnmarshal(b, bytesMsg(), Unmarshal) -} - -func BenchmarkBufferUnmarshalBytes(b *testing.B) { - benchmarkBufferUnmarshal(b, bytesMsg()) -} - -func BenchmarkUnmarshalUnrecognizedFields(b *testing.B) { - b.StopTimer() - pb := initGoTestField() - skip := &GoSkipTest{ - SkipInt32: Int32(32), - SkipFixed32: Uint32(3232), - SkipFixed64: Uint64(6464), - SkipString: String("skipper"), - Skipgroup: &GoSkipTest_SkipGroup{ - GroupInt32: Int32(75), - GroupString: String("wxyz"), - }, - } - - pbd := new(GoTestField) - p := NewBuffer(nil) - p.Marshal(pb) - p.Marshal(skip) - p2 := NewBuffer(nil) - - b.StartTimer() - for i := 0; i < b.N; i++ { - p2.SetBuf(p.Bytes()) - p2.Unmarshal(pbd) - } -} diff --git a/vendor/github.com/golang/protobuf/proto/any_test.go b/vendor/github.com/golang/protobuf/proto/any_test.go deleted file mode 100644 index 56fc97c11..000000000 --- a/vendor/github.com/golang/protobuf/proto/any_test.go +++ /dev/null @@ -1,300 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2016 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "strings" - "testing" - - "github.com/golang/protobuf/proto" - - pb "github.com/golang/protobuf/proto/proto3_proto" - testpb "github.com/golang/protobuf/proto/test_proto" - anypb "github.com/golang/protobuf/ptypes/any" -) - -var ( - expandedMarshaler = proto.TextMarshaler{ExpandAny: true} - expandedCompactMarshaler = proto.TextMarshaler{Compact: true, ExpandAny: true} -) - -// anyEqual reports whether two messages which may be google.protobuf.Any or may -// contain google.protobuf.Any fields are equal. We can't use proto.Equal for -// comparison, because semantically equivalent messages may be marshaled to -// binary in different tag order. Instead, trust that TextMarshaler with -// ExpandAny option works and compare the text marshaling results. -func anyEqual(got, want proto.Message) bool { - // if messages are proto.Equal, no need to marshal. - if proto.Equal(got, want) { - return true - } - g := expandedMarshaler.Text(got) - w := expandedMarshaler.Text(want) - return g == w -} - -type golden struct { - m proto.Message - t, c string -} - -var goldenMessages = makeGolden() - -func makeGolden() []golden { - nested := &pb.Nested{Bunny: "Monty"} - nb, err := proto.Marshal(nested) - if err != nil { - panic(err) - } - m1 := &pb.Message{ - Name: "David", - ResultCount: 47, - Anything: &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(nested), Value: nb}, - } - m2 := &pb.Message{ - Name: "David", - ResultCount: 47, - Anything: &anypb.Any{TypeUrl: "http://[::1]/type.googleapis.com/" + proto.MessageName(nested), Value: nb}, - } - m3 := &pb.Message{ - Name: "David", - ResultCount: 47, - Anything: &anypb.Any{TypeUrl: `type.googleapis.com/"/` + proto.MessageName(nested), Value: nb}, - } - m4 := &pb.Message{ - Name: "David", - ResultCount: 47, - Anything: &anypb.Any{TypeUrl: "type.googleapis.com/a/path/" + proto.MessageName(nested), Value: nb}, - } - m5 := &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(nested), Value: nb} - - any1 := &testpb.MyMessage{Count: proto.Int32(47), Name: proto.String("David")} - proto.SetExtension(any1, testpb.E_Ext_More, &testpb.Ext{Data: proto.String("foo")}) - proto.SetExtension(any1, testpb.E_Ext_Text, proto.String("bar")) - any1b, err := proto.Marshal(any1) - if err != nil { - panic(err) - } - any2 := &testpb.MyMessage{Count: proto.Int32(42), Bikeshed: testpb.MyMessage_GREEN.Enum(), RepBytes: [][]byte{[]byte("roboto")}} - proto.SetExtension(any2, testpb.E_Ext_More, &testpb.Ext{Data: proto.String("baz")}) - any2b, err := proto.Marshal(any2) - if err != nil { - panic(err) - } - m6 := &pb.Message{ - Name: "David", - ResultCount: 47, - Anything: &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(any1), Value: any1b}, - ManyThings: []*anypb.Any{ - &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(any2), Value: any2b}, - &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(any1), Value: any1b}, - }, - } - - const ( - m1Golden = ` -name: "David" -result_count: 47 -anything: < - [type.googleapis.com/proto3_proto.Nested]: < - bunny: "Monty" - > -> -` - m2Golden = ` -name: "David" -result_count: 47 -anything: < - ["http://[::1]/type.googleapis.com/proto3_proto.Nested"]: < - bunny: "Monty" - > -> -` - m3Golden = ` -name: "David" -result_count: 47 -anything: < - ["type.googleapis.com/\"/proto3_proto.Nested"]: < - bunny: "Monty" - > -> -` - m4Golden = ` -name: "David" -result_count: 47 -anything: < - [type.googleapis.com/a/path/proto3_proto.Nested]: < - bunny: "Monty" - > -> -` - m5Golden = ` -[type.googleapis.com/proto3_proto.Nested]: < - bunny: "Monty" -> -` - m6Golden = ` -name: "David" -result_count: 47 -anything: < - [type.googleapis.com/test_proto.MyMessage]: < - count: 47 - name: "David" - [test_proto.Ext.more]: < - data: "foo" - > - [test_proto.Ext.text]: "bar" - > -> -many_things: < - [type.googleapis.com/test_proto.MyMessage]: < - count: 42 - bikeshed: GREEN - rep_bytes: "roboto" - [test_proto.Ext.more]: < - data: "baz" - > - > -> -many_things: < - [type.googleapis.com/test_proto.MyMessage]: < - count: 47 - name: "David" - [test_proto.Ext.more]: < - data: "foo" - > - [test_proto.Ext.text]: "bar" - > -> -` - ) - return []golden{ - {m1, strings.TrimSpace(m1Golden) + "\n", strings.TrimSpace(compact(m1Golden)) + " "}, - {m2, strings.TrimSpace(m2Golden) + "\n", strings.TrimSpace(compact(m2Golden)) + " "}, - {m3, strings.TrimSpace(m3Golden) + "\n", strings.TrimSpace(compact(m3Golden)) + " "}, - {m4, strings.TrimSpace(m4Golden) + "\n", strings.TrimSpace(compact(m4Golden)) + " "}, - {m5, strings.TrimSpace(m5Golden) + "\n", strings.TrimSpace(compact(m5Golden)) + " "}, - {m6, strings.TrimSpace(m6Golden) + "\n", strings.TrimSpace(compact(m6Golden)) + " "}, - } -} - -func TestMarshalGolden(t *testing.T) { - for _, tt := range goldenMessages { - if got, want := expandedMarshaler.Text(tt.m), tt.t; got != want { - t.Errorf("message %v: got:\n%s\nwant:\n%s", tt.m, got, want) - } - if got, want := expandedCompactMarshaler.Text(tt.m), tt.c; got != want { - t.Errorf("message %v: got:\n`%s`\nwant:\n`%s`", tt.m, got, want) - } - } -} - -func TestUnmarshalGolden(t *testing.T) { - for _, tt := range goldenMessages { - want := tt.m - got := proto.Clone(tt.m) - got.Reset() - if err := proto.UnmarshalText(tt.t, got); err != nil { - t.Errorf("failed to unmarshal\n%s\nerror: %v", tt.t, err) - } - if !anyEqual(got, want) { - t.Errorf("message:\n%s\ngot:\n%s\nwant:\n%s", tt.t, got, want) - } - got.Reset() - if err := proto.UnmarshalText(tt.c, got); err != nil { - t.Errorf("failed to unmarshal\n%s\nerror: %v", tt.c, err) - } - if !anyEqual(got, want) { - t.Errorf("message:\n%s\ngot:\n%s\nwant:\n%s", tt.c, got, want) - } - } -} - -func TestMarshalUnknownAny(t *testing.T) { - m := &pb.Message{ - Anything: &anypb.Any{ - TypeUrl: "foo", - Value: []byte("bar"), - }, - } - want := `anything: < - type_url: "foo" - value: "bar" -> -` - got := expandedMarshaler.Text(m) - if got != want { - t.Errorf("got\n`%s`\nwant\n`%s`", got, want) - } -} - -func TestAmbiguousAny(t *testing.T) { - pb := &anypb.Any{} - err := proto.UnmarshalText(` - type_url: "ttt/proto3_proto.Nested" - value: "\n\x05Monty" - `, pb) - t.Logf("result: %v (error: %v)", expandedMarshaler.Text(pb), err) - if err != nil { - t.Errorf("failed to parse ambiguous Any message: %v", err) - } -} - -func TestUnmarshalOverwriteAny(t *testing.T) { - pb := &anypb.Any{} - err := proto.UnmarshalText(` - [type.googleapis.com/a/path/proto3_proto.Nested]: < - bunny: "Monty" - > - [type.googleapis.com/a/path/proto3_proto.Nested]: < - bunny: "Rabbit of Caerbannog" - > - `, pb) - want := `line 7: Any message unpacked multiple times, or "type_url" already set` - if err.Error() != want { - t.Errorf("incorrect error.\nHave: %v\nWant: %v", err.Error(), want) - } -} - -func TestUnmarshalAnyMixAndMatch(t *testing.T) { - pb := &anypb.Any{} - err := proto.UnmarshalText(` - value: "\n\x05Monty" - [type.googleapis.com/a/path/proto3_proto.Nested]: < - bunny: "Rabbit of Caerbannog" - > - `, pb) - want := `line 5: Any message unpacked multiple times, or "value" already set` - if err.Error() != want { - t.Errorf("incorrect error.\nHave: %v\nWant: %v", err.Error(), want) - } -} diff --git a/vendor/github.com/golang/protobuf/proto/clone_test.go b/vendor/github.com/golang/protobuf/proto/clone_test.go deleted file mode 100644 index 0d3b12737..000000000 --- a/vendor/github.com/golang/protobuf/proto/clone_test.go +++ /dev/null @@ -1,390 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2011 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "testing" - - "github.com/golang/protobuf/proto" - - proto3pb "github.com/golang/protobuf/proto/proto3_proto" - pb "github.com/golang/protobuf/proto/test_proto" -) - -var cloneTestMessage = &pb.MyMessage{ - Count: proto.Int32(42), - Name: proto.String("Dave"), - Pet: []string{"bunny", "kitty", "horsey"}, - Inner: &pb.InnerMessage{ - Host: proto.String("niles"), - Port: proto.Int32(9099), - Connected: proto.Bool(true), - }, - Others: []*pb.OtherMessage{ - { - Value: []byte("some bytes"), - }, - }, - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(6), - }, - RepBytes: [][]byte{[]byte("sham"), []byte("wow")}, -} - -func init() { - ext := &pb.Ext{ - Data: proto.String("extension"), - } - if err := proto.SetExtension(cloneTestMessage, pb.E_Ext_More, ext); err != nil { - panic("SetExtension: " + err.Error()) - } -} - -func TestClone(t *testing.T) { - m := proto.Clone(cloneTestMessage).(*pb.MyMessage) - if !proto.Equal(m, cloneTestMessage) { - t.Fatalf("Clone(%v) = %v", cloneTestMessage, m) - } - - // Verify it was a deep copy. - *m.Inner.Port++ - if proto.Equal(m, cloneTestMessage) { - t.Error("Mutating clone changed the original") - } - // Byte fields and repeated fields should be copied. - if &m.Pet[0] == &cloneTestMessage.Pet[0] { - t.Error("Pet: repeated field not copied") - } - if &m.Others[0] == &cloneTestMessage.Others[0] { - t.Error("Others: repeated field not copied") - } - if &m.Others[0].Value[0] == &cloneTestMessage.Others[0].Value[0] { - t.Error("Others[0].Value: bytes field not copied") - } - if &m.RepBytes[0] == &cloneTestMessage.RepBytes[0] { - t.Error("RepBytes: repeated field not copied") - } - if &m.RepBytes[0][0] == &cloneTestMessage.RepBytes[0][0] { - t.Error("RepBytes[0]: bytes field not copied") - } -} - -func TestCloneNil(t *testing.T) { - var m *pb.MyMessage - if c := proto.Clone(m); !proto.Equal(m, c) { - t.Errorf("Clone(%v) = %v", m, c) - } -} - -var mergeTests = []struct { - src, dst, want proto.Message -}{ - { - src: &pb.MyMessage{ - Count: proto.Int32(42), - }, - dst: &pb.MyMessage{ - Name: proto.String("Dave"), - }, - want: &pb.MyMessage{ - Count: proto.Int32(42), - Name: proto.String("Dave"), - }, - }, - { - src: &pb.MyMessage{ - Inner: &pb.InnerMessage{ - Host: proto.String("hey"), - Connected: proto.Bool(true), - }, - Pet: []string{"horsey"}, - Others: []*pb.OtherMessage{ - { - Value: []byte("some bytes"), - }, - }, - }, - dst: &pb.MyMessage{ - Inner: &pb.InnerMessage{ - Host: proto.String("niles"), - Port: proto.Int32(9099), - }, - Pet: []string{"bunny", "kitty"}, - Others: []*pb.OtherMessage{ - { - Key: proto.Int64(31415926535), - }, - { - // Explicitly test a src=nil field - Inner: nil, - }, - }, - }, - want: &pb.MyMessage{ - Inner: &pb.InnerMessage{ - Host: proto.String("hey"), - Connected: proto.Bool(true), - Port: proto.Int32(9099), - }, - Pet: []string{"bunny", "kitty", "horsey"}, - Others: []*pb.OtherMessage{ - { - Key: proto.Int64(31415926535), - }, - {}, - { - Value: []byte("some bytes"), - }, - }, - }, - }, - { - src: &pb.MyMessage{ - RepBytes: [][]byte{[]byte("wow")}, - }, - dst: &pb.MyMessage{ - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(6), - }, - RepBytes: [][]byte{[]byte("sham")}, - }, - want: &pb.MyMessage{ - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(6), - }, - RepBytes: [][]byte{[]byte("sham"), []byte("wow")}, - }, - }, - // Check that a scalar bytes field replaces rather than appends. - { - src: &pb.OtherMessage{Value: []byte("foo")}, - dst: &pb.OtherMessage{Value: []byte("bar")}, - want: &pb.OtherMessage{Value: []byte("foo")}, - }, - { - src: &pb.MessageWithMap{ - NameMapping: map[int32]string{6: "Nigel"}, - MsgMapping: map[int64]*pb.FloatingPoint{ - 0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)}, - 0x4002: &pb.FloatingPoint{ - F: proto.Float64(2.0), - }, - }, - ByteMapping: map[bool][]byte{true: []byte("wowsa")}, - }, - dst: &pb.MessageWithMap{ - NameMapping: map[int32]string{ - 6: "Bruce", // should be overwritten - 7: "Andrew", - }, - MsgMapping: map[int64]*pb.FloatingPoint{ - 0x4002: &pb.FloatingPoint{ - F: proto.Float64(3.0), - Exact: proto.Bool(true), - }, // the entire message should be overwritten - }, - }, - want: &pb.MessageWithMap{ - NameMapping: map[int32]string{ - 6: "Nigel", - 7: "Andrew", - }, - MsgMapping: map[int64]*pb.FloatingPoint{ - 0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)}, - 0x4002: &pb.FloatingPoint{ - F: proto.Float64(2.0), - }, - }, - ByteMapping: map[bool][]byte{true: []byte("wowsa")}, - }, - }, - // proto3 shouldn't merge zero values, - // in the same way that proto2 shouldn't merge nils. - { - src: &proto3pb.Message{ - Name: "Aaron", - Data: []byte(""), // zero value, but not nil - }, - dst: &proto3pb.Message{ - HeightInCm: 176, - Data: []byte("texas!"), - }, - want: &proto3pb.Message{ - Name: "Aaron", - HeightInCm: 176, - Data: []byte("texas!"), - }, - }, - { // Oneof fields should merge by assignment. - src: &pb.Communique{Union: &pb.Communique_Number{41}}, - dst: &pb.Communique{Union: &pb.Communique_Name{"Bobby Tables"}}, - want: &pb.Communique{Union: &pb.Communique_Number{41}}, - }, - { // Oneof nil is the same as not set. - src: &pb.Communique{}, - dst: &pb.Communique{Union: &pb.Communique_Name{"Bobby Tables"}}, - want: &pb.Communique{Union: &pb.Communique_Name{"Bobby Tables"}}, - }, - { - src: &pb.Communique{Union: &pb.Communique_Number{1337}}, - dst: &pb.Communique{}, - want: &pb.Communique{Union: &pb.Communique_Number{1337}}, - }, - { - src: &pb.Communique{Union: &pb.Communique_Col{pb.MyMessage_RED}}, - dst: &pb.Communique{}, - want: &pb.Communique{Union: &pb.Communique_Col{pb.MyMessage_RED}}, - }, - { - src: &pb.Communique{Union: &pb.Communique_Data{[]byte("hello")}}, - dst: &pb.Communique{}, - want: &pb.Communique{Union: &pb.Communique_Data{[]byte("hello")}}, - }, - { - src: &pb.Communique{Union: &pb.Communique_Msg{&pb.Strings{BytesField: []byte{1, 2, 3}}}}, - dst: &pb.Communique{}, - want: &pb.Communique{Union: &pb.Communique_Msg{&pb.Strings{BytesField: []byte{1, 2, 3}}}}, - }, - { - src: &pb.Communique{Union: &pb.Communique_Msg{}}, - dst: &pb.Communique{}, - want: &pb.Communique{Union: &pb.Communique_Msg{}}, - }, - { - src: &pb.Communique{Union: &pb.Communique_Msg{&pb.Strings{StringField: proto.String("123")}}}, - dst: &pb.Communique{Union: &pb.Communique_Msg{&pb.Strings{BytesField: []byte{1, 2, 3}}}}, - want: &pb.Communique{Union: &pb.Communique_Msg{&pb.Strings{StringField: proto.String("123"), BytesField: []byte{1, 2, 3}}}}, - }, - { - src: &proto3pb.Message{ - Terrain: map[string]*proto3pb.Nested{ - "kay_a": &proto3pb.Nested{Cute: true}, // replace - "kay_b": &proto3pb.Nested{Bunny: "rabbit"}, // insert - }, - }, - dst: &proto3pb.Message{ - Terrain: map[string]*proto3pb.Nested{ - "kay_a": &proto3pb.Nested{Bunny: "lost"}, // replaced - "kay_c": &proto3pb.Nested{Bunny: "bunny"}, // keep - }, - }, - want: &proto3pb.Message{ - Terrain: map[string]*proto3pb.Nested{ - "kay_a": &proto3pb.Nested{Cute: true}, - "kay_b": &proto3pb.Nested{Bunny: "rabbit"}, - "kay_c": &proto3pb.Nested{Bunny: "bunny"}, - }, - }, - }, - { - src: &pb.GoTest{ - F_BoolRepeated: []bool{}, - F_Int32Repeated: []int32{}, - F_Int64Repeated: []int64{}, - F_Uint32Repeated: []uint32{}, - F_Uint64Repeated: []uint64{}, - F_FloatRepeated: []float32{}, - F_DoubleRepeated: []float64{}, - F_StringRepeated: []string{}, - F_BytesRepeated: [][]byte{}, - }, - dst: &pb.GoTest{}, - want: &pb.GoTest{ - F_BoolRepeated: []bool{}, - F_Int32Repeated: []int32{}, - F_Int64Repeated: []int64{}, - F_Uint32Repeated: []uint32{}, - F_Uint64Repeated: []uint64{}, - F_FloatRepeated: []float32{}, - F_DoubleRepeated: []float64{}, - F_StringRepeated: []string{}, - F_BytesRepeated: [][]byte{}, - }, - }, - { - src: &pb.GoTest{}, - dst: &pb.GoTest{ - F_BoolRepeated: []bool{}, - F_Int32Repeated: []int32{}, - F_Int64Repeated: []int64{}, - F_Uint32Repeated: []uint32{}, - F_Uint64Repeated: []uint64{}, - F_FloatRepeated: []float32{}, - F_DoubleRepeated: []float64{}, - F_StringRepeated: []string{}, - F_BytesRepeated: [][]byte{}, - }, - want: &pb.GoTest{ - F_BoolRepeated: []bool{}, - F_Int32Repeated: []int32{}, - F_Int64Repeated: []int64{}, - F_Uint32Repeated: []uint32{}, - F_Uint64Repeated: []uint64{}, - F_FloatRepeated: []float32{}, - F_DoubleRepeated: []float64{}, - F_StringRepeated: []string{}, - F_BytesRepeated: [][]byte{}, - }, - }, - { - src: &pb.GoTest{ - F_BytesRepeated: [][]byte{nil, []byte{}, []byte{0}}, - }, - dst: &pb.GoTest{}, - want: &pb.GoTest{ - F_BytesRepeated: [][]byte{nil, []byte{}, []byte{0}}, - }, - }, - { - src: &pb.MyMessage{ - Others: []*pb.OtherMessage{}, - }, - dst: &pb.MyMessage{}, - want: &pb.MyMessage{ - Others: []*pb.OtherMessage{}, - }, - }, -} - -func TestMerge(t *testing.T) { - for _, m := range mergeTests { - got := proto.Clone(m.dst) - if !proto.Equal(got, m.dst) { - t.Errorf("Clone()\ngot %v\nwant %v", got, m.dst) - continue - } - proto.Merge(got, m.src) - if !proto.Equal(got, m.want) { - t.Errorf("Merge(%v, %v)\ngot %v\nwant %v", m.dst, m.src, got, m.want) - } - } -} diff --git a/vendor/github.com/golang/protobuf/proto/decode_test.go b/vendor/github.com/golang/protobuf/proto/decode_test.go deleted file mode 100644 index 949be3abd..000000000 --- a/vendor/github.com/golang/protobuf/proto/decode_test.go +++ /dev/null @@ -1,255 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// +build go1.7 - -package proto_test - -import ( - "fmt" - "testing" - - "github.com/golang/protobuf/proto" - tpb "github.com/golang/protobuf/proto/proto3_proto" -) - -var msgBlackhole = new(tpb.Message) - -// BenchmarkVarint32ArraySmall shows the performance on an array of small int32 fields (1 and -// 2 bytes long). -func BenchmarkVarint32ArraySmall(b *testing.B) { - for i := uint(1); i <= 10; i++ { - dist := genInt32Dist([7]int{0, 3, 1}, 1<unmarshal. -} - -func TestMarshalUnmarshalRepeatedExtension(t *testing.T) { - // Add a repeated extension to the result. - tests := []struct { - name string - ext []*pb.ComplexExtension - }{ - { - "two fields", - []*pb.ComplexExtension{ - {First: proto.Int32(7)}, - {Second: proto.Int32(11)}, - }, - }, - { - "repeated field", - []*pb.ComplexExtension{ - {Third: []int32{1000}}, - {Third: []int32{2000}}, - }, - }, - { - "two fields and repeated field", - []*pb.ComplexExtension{ - {Third: []int32{1000}}, - {First: proto.Int32(9)}, - {Second: proto.Int32(21)}, - {Third: []int32{2000}}, - }, - }, - } - for _, test := range tests { - // Marshal message with a repeated extension. - msg1 := new(pb.OtherMessage) - err := proto.SetExtension(msg1, pb.E_RComplex, test.ext) - if err != nil { - t.Fatalf("[%s] Error setting extension: %v", test.name, err) - } - b, err := proto.Marshal(msg1) - if err != nil { - t.Fatalf("[%s] Error marshaling message: %v", test.name, err) - } - - // Unmarshal and read the merged proto. - msg2 := new(pb.OtherMessage) - err = proto.Unmarshal(b, msg2) - if err != nil { - t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err) - } - e, err := proto.GetExtension(msg2, pb.E_RComplex) - if err != nil { - t.Fatalf("[%s] Error getting extension: %v", test.name, err) - } - ext := e.([]*pb.ComplexExtension) - if ext == nil { - t.Fatalf("[%s] Invalid extension", test.name) - } - if len(ext) != len(test.ext) { - t.Errorf("[%s] Wrong length of ComplexExtension: got: %v want: %v\n", test.name, len(ext), len(test.ext)) - } - for i := range test.ext { - if !proto.Equal(ext[i], test.ext[i]) { - t.Errorf("[%s] Wrong value for ComplexExtension[%d]: got: %v want: %v\n", test.name, i, ext[i], test.ext[i]) - } - } - } -} - -func TestUnmarshalRepeatingNonRepeatedExtension(t *testing.T) { - // We may see multiple instances of the same extension in the wire - // format. For example, the proto compiler may encode custom options in - // this way. Here, we verify that we merge the extensions together. - tests := []struct { - name string - ext []*pb.ComplexExtension - }{ - { - "two fields", - []*pb.ComplexExtension{ - {First: proto.Int32(7)}, - {Second: proto.Int32(11)}, - }, - }, - { - "repeated field", - []*pb.ComplexExtension{ - {Third: []int32{1000}}, - {Third: []int32{2000}}, - }, - }, - { - "two fields and repeated field", - []*pb.ComplexExtension{ - {Third: []int32{1000}}, - {First: proto.Int32(9)}, - {Second: proto.Int32(21)}, - {Third: []int32{2000}}, - }, - }, - } - for _, test := range tests { - var buf bytes.Buffer - var want pb.ComplexExtension - - // Generate a serialized representation of a repeated extension - // by catenating bytes together. - for i, e := range test.ext { - // Merge to create the wanted proto. - proto.Merge(&want, e) - - // serialize the message - msg := new(pb.OtherMessage) - err := proto.SetExtension(msg, pb.E_Complex, e) - if err != nil { - t.Fatalf("[%s] Error setting extension %d: %v", test.name, i, err) - } - b, err := proto.Marshal(msg) - if err != nil { - t.Fatalf("[%s] Error marshaling message %d: %v", test.name, i, err) - } - buf.Write(b) - } - - // Unmarshal and read the merged proto. - msg2 := new(pb.OtherMessage) - err := proto.Unmarshal(buf.Bytes(), msg2) - if err != nil { - t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err) - } - e, err := proto.GetExtension(msg2, pb.E_Complex) - if err != nil { - t.Fatalf("[%s] Error getting extension: %v", test.name, err) - } - ext := e.(*pb.ComplexExtension) - if ext == nil { - t.Fatalf("[%s] Invalid extension", test.name) - } - if !proto.Equal(ext, &want) { - t.Errorf("[%s] Wrong value for ComplexExtension: got: %s want: %s\n", test.name, ext, &want) - } - } -} - -func TestClearAllExtensions(t *testing.T) { - // unregistered extension - desc := &proto.ExtensionDesc{ - ExtendedType: (*pb.MyMessage)(nil), - ExtensionType: (*bool)(nil), - Field: 101010100, - Name: "emptyextension", - Tag: "varint,0,opt", - } - m := &pb.MyMessage{} - if proto.HasExtension(m, desc) { - t.Errorf("proto.HasExtension(%s): got true, want false", proto.MarshalTextString(m)) - } - if err := proto.SetExtension(m, desc, proto.Bool(true)); err != nil { - t.Errorf("proto.SetExtension(m, desc, true): got error %q, want nil", err) - } - if !proto.HasExtension(m, desc) { - t.Errorf("proto.HasExtension(%s): got false, want true", proto.MarshalTextString(m)) - } - proto.ClearAllExtensions(m) - if proto.HasExtension(m, desc) { - t.Errorf("proto.HasExtension(%s): got true, want false", proto.MarshalTextString(m)) - } -} - -func TestMarshalRace(t *testing.T) { - ext := &pb.Ext{} - m := &pb.MyMessage{Count: proto.Int32(4)} - if err := proto.SetExtension(m, pb.E_Ext_More, ext); err != nil { - t.Fatalf("proto.SetExtension(m, desc, true): got error %q, want nil", err) - } - - b, err := proto.Marshal(m) - if err != nil { - t.Fatalf("Could not marshal message: %v", err) - } - if err := proto.Unmarshal(b, m); err != nil { - t.Fatalf("Could not unmarshal message: %v", err) - } - // after Unmarshal, the extension is in undecoded form. - // GetExtension will decode it lazily. Make sure this does - // not race against Marshal. - - var g errgroup.Group - for n := 3; n > 0; n-- { - g.Go(func() error { - _, err := proto.Marshal(m) - return err - }) - g.Go(func() error { - _, err := proto.GetExtension(m, pb.E_Ext_More) - return err - }) - } - if err := g.Wait(); err != nil { - t.Fatal(err) - } -} diff --git a/vendor/github.com/golang/protobuf/proto/map_test.go b/vendor/github.com/golang/protobuf/proto/map_test.go deleted file mode 100644 index b1e1529ee..000000000 --- a/vendor/github.com/golang/protobuf/proto/map_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package proto_test - -import ( - "fmt" - "reflect" - "testing" - - "github.com/golang/protobuf/proto" - ppb "github.com/golang/protobuf/proto/proto3_proto" -) - -func TestMap(t *testing.T) { - var b []byte - fmt.Sscanf("a2010c0a044b657931120456616c31a201130a044b657932120556616c3261120456616c32a201240a044b6579330d05000000120556616c33621a0556616c3361120456616c331505000000a20100a201260a044b657934130a07536f6d6555524c1209536f6d655469746c651a08536e69707065743114", "%x", &b) - - var m ppb.Message - if err := proto.Unmarshal(b, &m); err != nil { - t.Fatalf("proto.Unmarshal error: %v", err) - } - - got := m.StringMap - want := map[string]string{ - "": "", - "Key1": "Val1", - "Key2": "Val2", - "Key3": "Val3", - "Key4": "", - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("maps differ:\ngot %#v\nwant %#v", got, want) - } -} - -func marshalled() []byte { - m := &ppb.IntMaps{} - for i := 0; i < 1000; i++ { - m.Maps = append(m.Maps, &ppb.IntMap{ - Rtt: map[int32]int32{1: 2}, - }) - } - b, err := proto.Marshal(m) - if err != nil { - panic(fmt.Sprintf("Can't marshal %+v: %v", m, err)) - } - return b -} - -func BenchmarkConcurrentMapUnmarshal(b *testing.B) { - in := marshalled() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - var out ppb.IntMaps - if err := proto.Unmarshal(in, &out); err != nil { - b.Errorf("Can't unmarshal ppb.IntMaps: %v", err) - } - } - }) -} - -func BenchmarkSequentialMapUnmarshal(b *testing.B) { - in := marshalled() - b.ResetTimer() - for i := 0; i < b.N; i++ { - var out ppb.IntMaps - if err := proto.Unmarshal(in, &out); err != nil { - b.Errorf("Can't unmarshal ppb.IntMaps: %v", err) - } - } -} diff --git a/vendor/github.com/golang/protobuf/proto/message_set_test.go b/vendor/github.com/golang/protobuf/proto/message_set_test.go deleted file mode 100644 index 2c170c5f2..000000000 --- a/vendor/github.com/golang/protobuf/proto/message_set_test.go +++ /dev/null @@ -1,77 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2014 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -import ( - "bytes" - "testing" -) - -func TestUnmarshalMessageSetWithDuplicate(t *testing.T) { - // Check that a repeated message set entry will be concatenated. - in := &messageSet{ - Item: []*_MessageSet_Item{ - {TypeId: Int32(12345), Message: []byte("hoo")}, - {TypeId: Int32(12345), Message: []byte("hah")}, - }, - } - b, err := Marshal(in) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - t.Logf("Marshaled bytes: %q", b) - - var extensions XXX_InternalExtensions - if err := UnmarshalMessageSet(b, &extensions); err != nil { - t.Fatalf("UnmarshalMessageSet: %v", err) - } - ext, ok := extensions.p.extensionMap[12345] - if !ok { - t.Fatalf("Didn't retrieve extension 12345; map is %v", extensions.p.extensionMap) - } - // Skip wire type/field number and length varints. - got := skipVarint(skipVarint(ext.enc)) - if want := []byte("hoohah"); !bytes.Equal(got, want) { - t.Errorf("Combined extension is %q, want %q", got, want) - } -} - -func TestMarshalMessageSetJSON_UnknownType(t *testing.T) { - extMap := map[int32]Extension{12345: Extension{}} - got, err := MarshalMessageSetJSON(extMap) - if err != nil { - t.Fatalf("MarshalMessageSetJSON: %v", err) - } - if want := []byte("{}"); !bytes.Equal(got, want) { - t.Errorf("MarshalMessageSetJSON(%v) = %q, want %q", extMap, got, want) - } -} diff --git a/vendor/github.com/golang/protobuf/proto/proto3_test.go b/vendor/github.com/golang/protobuf/proto/proto3_test.go deleted file mode 100644 index 73eed6c0b..000000000 --- a/vendor/github.com/golang/protobuf/proto/proto3_test.go +++ /dev/null @@ -1,151 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2014 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "bytes" - "testing" - - "github.com/golang/protobuf/proto" - pb "github.com/golang/protobuf/proto/proto3_proto" - tpb "github.com/golang/protobuf/proto/test_proto" -) - -func TestProto3ZeroValues(t *testing.T) { - tests := []struct { - desc string - m proto.Message - }{ - {"zero message", &pb.Message{}}, - {"empty bytes field", &pb.Message{Data: []byte{}}}, - } - for _, test := range tests { - b, err := proto.Marshal(test.m) - if err != nil { - t.Errorf("%s: proto.Marshal: %v", test.desc, err) - continue - } - if len(b) > 0 { - t.Errorf("%s: Encoding is non-empty: %q", test.desc, b) - } - } -} - -func TestRoundTripProto3(t *testing.T) { - m := &pb.Message{ - Name: "David", // (2 | 1<<3): 0x0a 0x05 "David" - Hilarity: pb.Message_PUNS, // (0 | 2<<3): 0x10 0x01 - HeightInCm: 178, // (0 | 3<<3): 0x18 0xb2 0x01 - Data: []byte("roboto"), // (2 | 4<<3): 0x20 0x06 "roboto" - ResultCount: 47, // (0 | 7<<3): 0x38 0x2f - TrueScotsman: true, // (0 | 8<<3): 0x40 0x01 - Score: 8.1, // (5 | 9<<3): 0x4d <8.1> - - Key: []uint64{1, 0xdeadbeef}, - Nested: &pb.Nested{ - Bunny: "Monty", - }, - } - t.Logf(" m: %v", m) - - b, err := proto.Marshal(m) - if err != nil { - t.Fatalf("proto.Marshal: %v", err) - } - t.Logf(" b: %q", b) - - m2 := new(pb.Message) - if err := proto.Unmarshal(b, m2); err != nil { - t.Fatalf("proto.Unmarshal: %v", err) - } - t.Logf("m2: %v", m2) - - if !proto.Equal(m, m2) { - t.Errorf("proto.Equal returned false:\n m: %v\nm2: %v", m, m2) - } -} - -func TestGettersForBasicTypesExist(t *testing.T) { - var m pb.Message - if got := m.GetNested().GetBunny(); got != "" { - t.Errorf("m.GetNested().GetBunny() = %q, want empty string", got) - } - if got := m.GetNested().GetCute(); got { - t.Errorf("m.GetNested().GetCute() = %t, want false", got) - } -} - -func TestProto3SetDefaults(t *testing.T) { - in := &pb.Message{ - Terrain: map[string]*pb.Nested{ - "meadow": new(pb.Nested), - }, - Proto2Field: new(tpb.SubDefaults), - Proto2Value: map[string]*tpb.SubDefaults{ - "badlands": new(tpb.SubDefaults), - }, - } - - got := proto.Clone(in).(*pb.Message) - proto.SetDefaults(got) - - // There are no defaults in proto3. Everything should be the zero value, but - // we need to remember to set defaults for nested proto2 messages. - want := &pb.Message{ - Terrain: map[string]*pb.Nested{ - "meadow": new(pb.Nested), - }, - Proto2Field: &tpb.SubDefaults{N: proto.Int64(7)}, - Proto2Value: map[string]*tpb.SubDefaults{ - "badlands": &tpb.SubDefaults{N: proto.Int64(7)}, - }, - } - - if !proto.Equal(got, want) { - t.Errorf("with in = %v\nproto.SetDefaults(in) =>\ngot %v\nwant %v", in, got, want) - } -} - -func TestUnknownFieldPreservation(t *testing.T) { - b1 := "\x0a\x05David" // Known tag 1 - b2 := "\xc2\x0c\x06Google" // Unknown tag 200 - b := []byte(b1 + b2) - - m := new(pb.Message) - if err := proto.Unmarshal(b, m); err != nil { - t.Fatalf("proto.Unmarshal: %v", err) - } - - if !bytes.Equal(m.XXX_unrecognized, []byte(b2)) { - t.Fatalf("mismatching unknown fields:\ngot %q\nwant %q", m.XXX_unrecognized, b2) - } -} diff --git a/vendor/github.com/golang/protobuf/proto/size2_test.go b/vendor/github.com/golang/protobuf/proto/size2_test.go deleted file mode 100644 index 7846b0617..000000000 --- a/vendor/github.com/golang/protobuf/proto/size2_test.go +++ /dev/null @@ -1,63 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2012 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -import ( - "testing" -) - -// This is a separate file and package from size_test.go because that one uses -// generated messages and thus may not be in package proto without having a circular -// dependency, whereas this file tests unexported details of size.go. - -func TestVarintSize(t *testing.T) { - // Check the edge cases carefully. - testCases := []struct { - n uint64 - size int - }{ - {0, 1}, - {1, 1}, - {127, 1}, - {128, 2}, - {16383, 2}, - {16384, 3}, - {1<<63 - 1, 9}, - {1 << 63, 10}, - } - for _, tc := range testCases { - size := SizeVarint(tc.n) - if size != tc.size { - t.Errorf("sizeVarint(%d) = %d, want %d", tc.n, size, tc.size) - } - } -} diff --git a/vendor/github.com/golang/protobuf/proto/size_test.go b/vendor/github.com/golang/protobuf/proto/size_test.go deleted file mode 100644 index 3abac418a..000000000 --- a/vendor/github.com/golang/protobuf/proto/size_test.go +++ /dev/null @@ -1,191 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2012 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "log" - "strings" - "testing" - - . "github.com/golang/protobuf/proto" - proto3pb "github.com/golang/protobuf/proto/proto3_proto" - pb "github.com/golang/protobuf/proto/test_proto" -) - -var messageWithExtension1 = &pb.MyMessage{Count: Int32(7)} - -// messageWithExtension2 is in equal_test.go. -var messageWithExtension3 = &pb.MyMessage{Count: Int32(8)} - -func init() { - if err := SetExtension(messageWithExtension1, pb.E_Ext_More, &pb.Ext{Data: String("Abbott")}); err != nil { - log.Panicf("SetExtension: %v", err) - } - if err := SetExtension(messageWithExtension3, pb.E_Ext_More, &pb.Ext{Data: String("Costello")}); err != nil { - log.Panicf("SetExtension: %v", err) - } - - // Force messageWithExtension3 to have the extension encoded. - Marshal(messageWithExtension3) - -} - -// non-pointer custom message -type nonptrMessage struct{} - -func (m nonptrMessage) ProtoMessage() {} -func (m nonptrMessage) Reset() {} -func (m nonptrMessage) String() string { return "" } - -func (m nonptrMessage) Marshal() ([]byte, error) { - return []byte{42}, nil -} - -// custom message embedding a proto.Message -type messageWithEmbedding struct { - *pb.OtherMessage -} - -func (m *messageWithEmbedding) ProtoMessage() {} -func (m *messageWithEmbedding) Reset() {} -func (m *messageWithEmbedding) String() string { return "" } - -func (m *messageWithEmbedding) Marshal() ([]byte, error) { - return []byte{42}, nil -} - -var SizeTests = []struct { - desc string - pb Message -}{ - {"empty", &pb.OtherMessage{}}, - // Basic types. - {"bool", &pb.Defaults{F_Bool: Bool(true)}}, - {"int32", &pb.Defaults{F_Int32: Int32(12)}}, - {"negative int32", &pb.Defaults{F_Int32: Int32(-1)}}, - {"small int64", &pb.Defaults{F_Int64: Int64(1)}}, - {"big int64", &pb.Defaults{F_Int64: Int64(1 << 20)}}, - {"negative int64", &pb.Defaults{F_Int64: Int64(-1)}}, - {"fixed32", &pb.Defaults{F_Fixed32: Uint32(71)}}, - {"fixed64", &pb.Defaults{F_Fixed64: Uint64(72)}}, - {"uint32", &pb.Defaults{F_Uint32: Uint32(123)}}, - {"uint64", &pb.Defaults{F_Uint64: Uint64(124)}}, - {"float", &pb.Defaults{F_Float: Float32(12.6)}}, - {"double", &pb.Defaults{F_Double: Float64(13.9)}}, - {"string", &pb.Defaults{F_String: String("niles")}}, - {"bytes", &pb.Defaults{F_Bytes: []byte("wowsa")}}, - {"bytes, empty", &pb.Defaults{F_Bytes: []byte{}}}, - {"sint32", &pb.Defaults{F_Sint32: Int32(65)}}, - {"sint64", &pb.Defaults{F_Sint64: Int64(67)}}, - {"enum", &pb.Defaults{F_Enum: pb.Defaults_BLUE.Enum()}}, - // Repeated. - {"empty repeated bool", &pb.MoreRepeated{Bools: []bool{}}}, - {"repeated bool", &pb.MoreRepeated{Bools: []bool{false, true, true, false}}}, - {"packed repeated bool", &pb.MoreRepeated{BoolsPacked: []bool{false, true, true, false, true, true, true}}}, - {"repeated int32", &pb.MoreRepeated{Ints: []int32{1, 12203, 1729, -1}}}, - {"repeated int32 packed", &pb.MoreRepeated{IntsPacked: []int32{1, 12203, 1729}}}, - {"repeated int64 packed", &pb.MoreRepeated{Int64SPacked: []int64{ - // Need enough large numbers to verify that the header is counting the number of bytes - // for the field, not the number of elements. - 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, - 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, - }}}, - {"repeated string", &pb.MoreRepeated{Strings: []string{"r", "ken", "gri"}}}, - {"repeated fixed", &pb.MoreRepeated{Fixeds: []uint32{1, 2, 3, 4}}}, - // Nested. - {"nested", &pb.OldMessage{Nested: &pb.OldMessage_Nested{Name: String("whatever")}}}, - {"group", &pb.GroupOld{G: &pb.GroupOld_G{X: Int32(12345)}}}, - // Other things. - {"unrecognized", &pb.MoreRepeated{XXX_unrecognized: []byte{13<<3 | 0, 4}}}, - {"extension (unencoded)", messageWithExtension1}, - {"extension (encoded)", messageWithExtension3}, - // proto3 message - {"proto3 empty", &proto3pb.Message{}}, - {"proto3 bool", &proto3pb.Message{TrueScotsman: true}}, - {"proto3 int64", &proto3pb.Message{ResultCount: 1}}, - {"proto3 uint32", &proto3pb.Message{HeightInCm: 123}}, - {"proto3 float", &proto3pb.Message{Score: 12.6}}, - {"proto3 string", &proto3pb.Message{Name: "Snezana"}}, - {"proto3 bytes", &proto3pb.Message{Data: []byte("wowsa")}}, - {"proto3 bytes, empty", &proto3pb.Message{Data: []byte{}}}, - {"proto3 enum", &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}}, - {"proto3 map field with empty bytes", &proto3pb.MessageWithMap{ByteMapping: map[bool][]byte{false: []byte{}}}}, - - {"map field", &pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob", 7: "Andrew"}}}, - {"map field with message", &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{0x7001: &pb.FloatingPoint{F: Float64(2.0)}}}}, - {"map field with bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte("this time for sure")}}}, - {"map field with empty bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte{}}}}, - - {"map field with big entry", &pb.MessageWithMap{NameMapping: map[int32]string{8: strings.Repeat("x", 125)}}}, - {"map field with big key and val", &pb.MessageWithMap{StrToStr: map[string]string{strings.Repeat("x", 70): strings.Repeat("y", 70)}}}, - {"map field with big numeric key", &pb.MessageWithMap{NameMapping: map[int32]string{0xf00d: "om nom nom"}}}, - - {"oneof not set", &pb.Oneof{}}, - {"oneof bool", &pb.Oneof{Union: &pb.Oneof_F_Bool{true}}}, - {"oneof zero int32", &pb.Oneof{Union: &pb.Oneof_F_Int32{0}}}, - {"oneof big int32", &pb.Oneof{Union: &pb.Oneof_F_Int32{1 << 20}}}, - {"oneof int64", &pb.Oneof{Union: &pb.Oneof_F_Int64{42}}}, - {"oneof fixed32", &pb.Oneof{Union: &pb.Oneof_F_Fixed32{43}}}, - {"oneof fixed64", &pb.Oneof{Union: &pb.Oneof_F_Fixed64{44}}}, - {"oneof uint32", &pb.Oneof{Union: &pb.Oneof_F_Uint32{45}}}, - {"oneof uint64", &pb.Oneof{Union: &pb.Oneof_F_Uint64{46}}}, - {"oneof float", &pb.Oneof{Union: &pb.Oneof_F_Float{47.1}}}, - {"oneof double", &pb.Oneof{Union: &pb.Oneof_F_Double{48.9}}}, - {"oneof string", &pb.Oneof{Union: &pb.Oneof_F_String{"Rhythmic Fman"}}}, - {"oneof bytes", &pb.Oneof{Union: &pb.Oneof_F_Bytes{[]byte("let go")}}}, - {"oneof sint32", &pb.Oneof{Union: &pb.Oneof_F_Sint32{50}}}, - {"oneof sint64", &pb.Oneof{Union: &pb.Oneof_F_Sint64{51}}}, - {"oneof enum", &pb.Oneof{Union: &pb.Oneof_F_Enum{pb.MyMessage_BLUE}}}, - {"message for oneof", &pb.GoTestField{Label: String("k"), Type: String("v")}}, - {"oneof message", &pb.Oneof{Union: &pb.Oneof_F_Message{&pb.GoTestField{Label: String("k"), Type: String("v")}}}}, - {"oneof group", &pb.Oneof{Union: &pb.Oneof_FGroup{&pb.Oneof_F_Group{X: Int32(52)}}}}, - {"oneof largest tag", &pb.Oneof{Union: &pb.Oneof_F_Largest_Tag{1}}}, - {"multiple oneofs", &pb.Oneof{Union: &pb.Oneof_F_Int32{1}, Tormato: &pb.Oneof_Value{2}}}, - - {"non-pointer message", nonptrMessage{}}, - {"custom message with embedding", &messageWithEmbedding{&pb.OtherMessage{}}}, -} - -func TestSize(t *testing.T) { - for _, tc := range SizeTests { - size := Size(tc.pb) - b, err := Marshal(tc.pb) - if err != nil { - t.Errorf("%v: Marshal failed: %v", tc.desc, err) - continue - } - if size != len(b) { - t.Errorf("%v: Size(%v) = %d, want %d", tc.desc, tc.pb, size, len(b)) - t.Logf("%v: bytes: %#v", tc.desc, b) - } - } -} diff --git a/vendor/github.com/golang/protobuf/proto/text_parser_test.go b/vendor/github.com/golang/protobuf/proto/text_parser_test.go deleted file mode 100644 index a81980879..000000000 --- a/vendor/github.com/golang/protobuf/proto/text_parser_test.go +++ /dev/null @@ -1,706 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "fmt" - "math" - "testing" - - . "github.com/golang/protobuf/proto" - proto3pb "github.com/golang/protobuf/proto/proto3_proto" - . "github.com/golang/protobuf/proto/test_proto" -) - -type UnmarshalTextTest struct { - in string - err string // if "", no error expected - out *MyMessage -} - -func buildExtStructTest(text string) UnmarshalTextTest { - msg := &MyMessage{ - Count: Int32(42), - } - SetExtension(msg, E_Ext_More, &Ext{ - Data: String("Hello, world!"), - }) - return UnmarshalTextTest{in: text, out: msg} -} - -func buildExtDataTest(text string) UnmarshalTextTest { - msg := &MyMessage{ - Count: Int32(42), - } - SetExtension(msg, E_Ext_Text, String("Hello, world!")) - SetExtension(msg, E_Ext_Number, Int32(1729)) - return UnmarshalTextTest{in: text, out: msg} -} - -func buildExtRepStringTest(text string) UnmarshalTextTest { - msg := &MyMessage{ - Count: Int32(42), - } - if err := SetExtension(msg, E_Greeting, []string{"bula", "hola"}); err != nil { - panic(err) - } - return UnmarshalTextTest{in: text, out: msg} -} - -var unMarshalTextTests = []UnmarshalTextTest{ - // Basic - { - in: " count:42\n name:\"Dave\" ", - out: &MyMessage{ - Count: Int32(42), - Name: String("Dave"), - }, - }, - - // Empty quoted string - { - in: `count:42 name:""`, - out: &MyMessage{ - Count: Int32(42), - Name: String(""), - }, - }, - - // Quoted string concatenation with double quotes - { - in: `count:42 name: "My name is "` + "\n" + `"elsewhere"`, - out: &MyMessage{ - Count: Int32(42), - Name: String("My name is elsewhere"), - }, - }, - - // Quoted string concatenation with single quotes - { - in: "count:42 name: 'My name is '\n'elsewhere'", - out: &MyMessage{ - Count: Int32(42), - Name: String("My name is elsewhere"), - }, - }, - - // Quoted string concatenations with mixed quotes - { - in: "count:42 name: 'My name is '\n\"elsewhere\"", - out: &MyMessage{ - Count: Int32(42), - Name: String("My name is elsewhere"), - }, - }, - { - in: "count:42 name: \"My name is \"\n'elsewhere'", - out: &MyMessage{ - Count: Int32(42), - Name: String("My name is elsewhere"), - }, - }, - - // Quoted string with escaped apostrophe - { - in: `count:42 name: "HOLIDAY - New Year\'s Day"`, - out: &MyMessage{ - Count: Int32(42), - Name: String("HOLIDAY - New Year's Day"), - }, - }, - - // Quoted string with single quote - { - in: `count:42 name: 'Roger "The Ramster" Ramjet'`, - out: &MyMessage{ - Count: Int32(42), - Name: String(`Roger "The Ramster" Ramjet`), - }, - }, - - // Quoted string with all the accepted special characters from the C++ test - { - in: `count:42 name: ` + "\"\\\"A string with \\' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"", - out: &MyMessage{ - Count: Int32(42), - Name: String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces"), - }, - }, - - // Quoted string with quoted backslash - { - in: `count:42 name: "\\'xyz"`, - out: &MyMessage{ - Count: Int32(42), - Name: String(`\'xyz`), - }, - }, - - // Quoted string with UTF-8 bytes. - { - in: "count:42 name: '\303\277\302\201\x00\xAB\xCD\xEF'", - out: &MyMessage{ - Count: Int32(42), - Name: String("\303\277\302\201\x00\xAB\xCD\xEF"), - }, - }, - - // Quoted string with unicode escapes. - { - in: `count: 42 name: "\u0047\U00000047\uffff\U0010ffff"`, - out: &MyMessage{ - Count: Int32(42), - Name: String("GG\uffff\U0010ffff"), - }, - }, - - // Bad quoted string - { - in: `inner: < host: "\0" >` + "\n", - err: `line 1.15: invalid quoted string "\0": \0 requires 2 following digits`, - }, - - // Bad \u escape - { - in: `count: 42 name: "\u000"`, - err: `line 1.16: invalid quoted string "\u000": \u requires 4 following digits`, - }, - - // Bad \U escape - { - in: `count: 42 name: "\U0000000"`, - err: `line 1.16: invalid quoted string "\U0000000": \U requires 8 following digits`, - }, - - // Bad \U escape - { - in: `count: 42 name: "\xxx"`, - err: `line 1.16: invalid quoted string "\xxx": \xxx contains non-hexadecimal digits`, - }, - - // Number too large for int64 - { - in: "count: 1 others { key: 123456789012345678901 }", - err: "line 1.23: invalid int64: 123456789012345678901", - }, - - // Number too large for int32 - { - in: "count: 1234567890123", - err: "line 1.7: invalid int32: 1234567890123", - }, - - // Number in hexadecimal - { - in: "count: 0x2beef", - out: &MyMessage{ - Count: Int32(0x2beef), - }, - }, - - // Number in octal - { - in: "count: 024601", - out: &MyMessage{ - Count: Int32(024601), - }, - }, - - // Floating point number with "f" suffix - { - in: "count: 4 others:< weight: 17.0f >", - out: &MyMessage{ - Count: Int32(4), - Others: []*OtherMessage{ - { - Weight: Float32(17), - }, - }, - }, - }, - - // Floating point positive infinity - { - in: "count: 4 bigfloat: inf", - out: &MyMessage{ - Count: Int32(4), - Bigfloat: Float64(math.Inf(1)), - }, - }, - - // Floating point negative infinity - { - in: "count: 4 bigfloat: -inf", - out: &MyMessage{ - Count: Int32(4), - Bigfloat: Float64(math.Inf(-1)), - }, - }, - - // Number too large for float32 - { - in: "others:< weight: 12345678901234567890123456789012345678901234567890 >", - err: "line 1.17: invalid float32: 12345678901234567890123456789012345678901234567890", - }, - - // Number posing as a quoted string - { - in: `inner: < host: 12 >` + "\n", - err: `line 1.15: invalid string: 12`, - }, - - // Quoted string posing as int32 - { - in: `count: "12"`, - err: `line 1.7: invalid int32: "12"`, - }, - - // Quoted string posing a float32 - { - in: `others:< weight: "17.4" >`, - err: `line 1.17: invalid float32: "17.4"`, - }, - - // unclosed bracket doesn't cause infinite loop - { - in: `[`, - err: `line 1.0: unclosed type_url or extension name`, - }, - - // Enum - { - in: `count:42 bikeshed: BLUE`, - out: &MyMessage{ - Count: Int32(42), - Bikeshed: MyMessage_BLUE.Enum(), - }, - }, - - // Repeated field - { - in: `count:42 pet: "horsey" pet:"bunny"`, - out: &MyMessage{ - Count: Int32(42), - Pet: []string{"horsey", "bunny"}, - }, - }, - - // Repeated field with list notation - { - in: `count:42 pet: ["horsey", "bunny"]`, - out: &MyMessage{ - Count: Int32(42), - Pet: []string{"horsey", "bunny"}, - }, - }, - - // Repeated message with/without colon and <>/{} - { - in: `count:42 others:{} others{} others:<> others:{}`, - out: &MyMessage{ - Count: Int32(42), - Others: []*OtherMessage{ - {}, - {}, - {}, - {}, - }, - }, - }, - - // Missing colon for inner message - { - in: `count:42 inner < host: "cauchy.syd" >`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("cauchy.syd"), - }, - }, - }, - - // Missing colon for string field - { - in: `name "Dave"`, - err: `line 1.5: expected ':', found "\"Dave\""`, - }, - - // Missing colon for int32 field - { - in: `count 42`, - err: `line 1.6: expected ':', found "42"`, - }, - - // Missing required field - { - in: `name: "Pawel"`, - err: fmt.Sprintf(`proto: required field "%T.count" not set`, MyMessage{}), - out: &MyMessage{ - Name: String("Pawel"), - }, - }, - - // Missing required field in a required submessage - { - in: `count: 42 we_must_go_deeper < leo_finally_won_an_oscar <> >`, - err: fmt.Sprintf(`proto: required field "%T.host" not set`, InnerMessage{}), - out: &MyMessage{ - Count: Int32(42), - WeMustGoDeeper: &RequiredInnerMessage{LeoFinallyWonAnOscar: &InnerMessage{}}, - }, - }, - - // Repeated non-repeated field - { - in: `name: "Rob" name: "Russ"`, - err: `line 1.12: non-repeated field "name" was repeated`, - }, - - // Group - { - in: `count: 17 SomeGroup { group_field: 12 }`, - out: &MyMessage{ - Count: Int32(17), - Somegroup: &MyMessage_SomeGroup{ - GroupField: Int32(12), - }, - }, - }, - - // Semicolon between fields - { - in: `count:3;name:"Calvin"`, - out: &MyMessage{ - Count: Int32(3), - Name: String("Calvin"), - }, - }, - // Comma between fields - { - in: `count:4,name:"Ezekiel"`, - out: &MyMessage{ - Count: Int32(4), - Name: String("Ezekiel"), - }, - }, - - // Boolean false - { - in: `count:42 inner { host: "example.com" connected: false }`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("example.com"), - Connected: Bool(false), - }, - }, - }, - // Boolean true - { - in: `count:42 inner { host: "example.com" connected: true }`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("example.com"), - Connected: Bool(true), - }, - }, - }, - // Boolean 0 - { - in: `count:42 inner { host: "example.com" connected: 0 }`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("example.com"), - Connected: Bool(false), - }, - }, - }, - // Boolean 1 - { - in: `count:42 inner { host: "example.com" connected: 1 }`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("example.com"), - Connected: Bool(true), - }, - }, - }, - // Boolean f - { - in: `count:42 inner { host: "example.com" connected: f }`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("example.com"), - Connected: Bool(false), - }, - }, - }, - // Boolean t - { - in: `count:42 inner { host: "example.com" connected: t }`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("example.com"), - Connected: Bool(true), - }, - }, - }, - // Boolean False - { - in: `count:42 inner { host: "example.com" connected: False }`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("example.com"), - Connected: Bool(false), - }, - }, - }, - // Boolean True - { - in: `count:42 inner { host: "example.com" connected: True }`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("example.com"), - Connected: Bool(true), - }, - }, - }, - - // Extension - buildExtStructTest(`count: 42 [test_proto.Ext.more]:`), - buildExtStructTest(`count: 42 [test_proto.Ext.more] {data:"Hello, world!"}`), - buildExtDataTest(`count: 42 [test_proto.Ext.text]:"Hello, world!" [test_proto.Ext.number]:1729`), - buildExtRepStringTest(`count: 42 [test_proto.greeting]:"bula" [test_proto.greeting]:"hola"`), - - // Big all-in-one - { - in: "count:42 # Meaning\n" + - `name:"Dave" ` + - `quote:"\"I didn't want to go.\"" ` + - `pet:"bunny" ` + - `pet:"kitty" ` + - `pet:"horsey" ` + - `inner:<` + - ` host:"footrest.syd" ` + - ` port:7001 ` + - ` connected:true ` + - `> ` + - `others:<` + - ` key:3735928559 ` + - ` value:"\x01A\a\f" ` + - `> ` + - `others:<` + - " weight:58.9 # Atomic weight of Co\n" + - ` inner:<` + - ` host:"lesha.mtv" ` + - ` port:8002 ` + - ` >` + - `>`, - out: &MyMessage{ - Count: Int32(42), - Name: String("Dave"), - Quote: String(`"I didn't want to go."`), - Pet: []string{"bunny", "kitty", "horsey"}, - Inner: &InnerMessage{ - Host: String("footrest.syd"), - Port: Int32(7001), - Connected: Bool(true), - }, - Others: []*OtherMessage{ - { - Key: Int64(3735928559), - Value: []byte{0x1, 'A', '\a', '\f'}, - }, - { - Weight: Float32(58.9), - Inner: &InnerMessage{ - Host: String("lesha.mtv"), - Port: Int32(8002), - }, - }, - }, - }, - }, -} - -func TestUnmarshalText(t *testing.T) { - for i, test := range unMarshalTextTests { - pb := new(MyMessage) - err := UnmarshalText(test.in, pb) - if test.err == "" { - // We don't expect failure. - if err != nil { - t.Errorf("Test %d: Unexpected error: %v", i, err) - } else if !Equal(pb, test.out) { - t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v", - i, pb, test.out) - } - } else { - // We do expect failure. - if err == nil { - t.Errorf("Test %d: Didn't get expected error: %v", i, test.err) - } else if err.Error() != test.err { - t.Errorf("Test %d: Incorrect error.\nHave: %v\nWant: %v", - i, err.Error(), test.err) - } else if _, ok := err.(*RequiredNotSetError); ok && test.out != nil && !Equal(pb, test.out) { - t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v", - i, pb, test.out) - } - } - } -} - -func TestUnmarshalTextCustomMessage(t *testing.T) { - msg := &textMessage{} - if err := UnmarshalText("custom", msg); err != nil { - t.Errorf("Unexpected error from custom unmarshal: %v", err) - } - if UnmarshalText("not custom", msg) == nil { - t.Errorf("Didn't get expected error from custom unmarshal") - } -} - -// Regression test; this caused a panic. -func TestRepeatedEnum(t *testing.T) { - pb := new(RepeatedEnum) - if err := UnmarshalText("color: RED", pb); err != nil { - t.Fatal(err) - } - exp := &RepeatedEnum{ - Color: []RepeatedEnum_Color{RepeatedEnum_RED}, - } - if !Equal(pb, exp) { - t.Errorf("Incorrect populated \nHave: %v\nWant: %v", pb, exp) - } -} - -func TestProto3TextParsing(t *testing.T) { - m := new(proto3pb.Message) - const in = `name: "Wallace" true_scotsman: true` - want := &proto3pb.Message{ - Name: "Wallace", - TrueScotsman: true, - } - if err := UnmarshalText(in, m); err != nil { - t.Fatal(err) - } - if !Equal(m, want) { - t.Errorf("\n got %v\nwant %v", m, want) - } -} - -func TestMapParsing(t *testing.T) { - m := new(MessageWithMap) - const in = `name_mapping: name_mapping:` + - `msg_mapping:,>` + // separating commas are okay - `msg_mapping>` + // no colon after "value" - `msg_mapping:>` + // omitted key - `msg_mapping:` + // omitted value - `byte_mapping:` + - `byte_mapping:<>` // omitted key and value - want := &MessageWithMap{ - NameMapping: map[int32]string{ - 1: "Beatles", - 1234: "Feist", - }, - MsgMapping: map[int64]*FloatingPoint{ - -4: {F: Float64(2.0)}, - -2: {F: Float64(4.0)}, - 0: {F: Float64(5.0)}, - 1: nil, - }, - ByteMapping: map[bool][]byte{ - false: nil, - true: []byte("so be it"), - }, - } - if err := UnmarshalText(in, m); err != nil { - t.Fatal(err) - } - if !Equal(m, want) { - t.Errorf("\n got %v\nwant %v", m, want) - } -} - -func TestOneofParsing(t *testing.T) { - const in = `name:"Shrek"` - m := new(Communique) - want := &Communique{Union: &Communique_Name{"Shrek"}} - if err := UnmarshalText(in, m); err != nil { - t.Fatal(err) - } - if !Equal(m, want) { - t.Errorf("\n got %v\nwant %v", m, want) - } - - const inOverwrite = `name:"Shrek" number:42` - m = new(Communique) - testErr := "line 1.13: field 'number' would overwrite already parsed oneof 'Union'" - if err := UnmarshalText(inOverwrite, m); err == nil { - t.Errorf("TestOneofParsing: Didn't get expected error: %v", testErr) - } else if err.Error() != testErr { - t.Errorf("TestOneofParsing: Incorrect error.\nHave: %v\nWant: %v", - err.Error(), testErr) - } - -} - -var benchInput string - -func init() { - benchInput = "count: 4\n" - for i := 0; i < 1000; i++ { - benchInput += "pet: \"fido\"\n" - } - - // Check it is valid input. - pb := new(MyMessage) - err := UnmarshalText(benchInput, pb) - if err != nil { - panic("Bad benchmark input: " + err.Error()) - } -} - -func BenchmarkUnmarshalText(b *testing.B) { - pb := new(MyMessage) - for i := 0; i < b.N; i++ { - UnmarshalText(benchInput, pb) - } - b.SetBytes(int64(len(benchInput))) -} diff --git a/vendor/github.com/golang/protobuf/proto/text_test.go b/vendor/github.com/golang/protobuf/proto/text_test.go deleted file mode 100644 index 3c8b033c0..000000000 --- a/vendor/github.com/golang/protobuf/proto/text_test.go +++ /dev/null @@ -1,518 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "bytes" - "errors" - "io/ioutil" - "math" - "strings" - "sync" - "testing" - - "github.com/golang/protobuf/proto" - - proto3pb "github.com/golang/protobuf/proto/proto3_proto" - pb "github.com/golang/protobuf/proto/test_proto" - anypb "github.com/golang/protobuf/ptypes/any" -) - -// textMessage implements the methods that allow it to marshal and unmarshal -// itself as text. -type textMessage struct { -} - -func (*textMessage) MarshalText() ([]byte, error) { - return []byte("custom"), nil -} - -func (*textMessage) UnmarshalText(bytes []byte) error { - if string(bytes) != "custom" { - return errors.New("expected 'custom'") - } - return nil -} - -func (*textMessage) Reset() {} -func (*textMessage) String() string { return "" } -func (*textMessage) ProtoMessage() {} - -func newTestMessage() *pb.MyMessage { - msg := &pb.MyMessage{ - Count: proto.Int32(42), - Name: proto.String("Dave"), - Quote: proto.String(`"I didn't want to go."`), - Pet: []string{"bunny", "kitty", "horsey"}, - Inner: &pb.InnerMessage{ - Host: proto.String("footrest.syd"), - Port: proto.Int32(7001), - Connected: proto.Bool(true), - }, - Others: []*pb.OtherMessage{ - { - Key: proto.Int64(0xdeadbeef), - Value: []byte{1, 65, 7, 12}, - }, - { - Weight: proto.Float32(6.022), - Inner: &pb.InnerMessage{ - Host: proto.String("lesha.mtv"), - Port: proto.Int32(8002), - }, - }, - }, - Bikeshed: pb.MyMessage_BLUE.Enum(), - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(8), - }, - // One normally wouldn't do this. - // This is an undeclared tag 13, as a varint (wire type 0) with value 4. - XXX_unrecognized: []byte{13<<3 | 0, 4}, - } - ext := &pb.Ext{ - Data: proto.String("Big gobs for big rats"), - } - if err := proto.SetExtension(msg, pb.E_Ext_More, ext); err != nil { - panic(err) - } - greetings := []string{"adg", "easy", "cow"} - if err := proto.SetExtension(msg, pb.E_Greeting, greetings); err != nil { - panic(err) - } - - // Add an unknown extension. We marshal a pb.Ext, and fake the ID. - b, err := proto.Marshal(&pb.Ext{Data: proto.String("3G skiing")}) - if err != nil { - panic(err) - } - b = append(proto.EncodeVarint(201<<3|proto.WireBytes), b...) - proto.SetRawExtension(msg, 201, b) - - // Extensions can be plain fields, too, so let's test that. - b = append(proto.EncodeVarint(202<<3|proto.WireVarint), 19) - proto.SetRawExtension(msg, 202, b) - - return msg -} - -const text = `count: 42 -name: "Dave" -quote: "\"I didn't want to go.\"" -pet: "bunny" -pet: "kitty" -pet: "horsey" -inner: < - host: "footrest.syd" - port: 7001 - connected: true -> -others: < - key: 3735928559 - value: "\001A\007\014" -> -others: < - weight: 6.022 - inner: < - host: "lesha.mtv" - port: 8002 - > -> -bikeshed: BLUE -SomeGroup { - group_field: 8 -} -/* 2 unknown bytes */ -13: 4 -[test_proto.Ext.more]: < - data: "Big gobs for big rats" -> -[test_proto.greeting]: "adg" -[test_proto.greeting]: "easy" -[test_proto.greeting]: "cow" -/* 13 unknown bytes */ -201: "\t3G skiing" -/* 3 unknown bytes */ -202: 19 -` - -func TestMarshalText(t *testing.T) { - buf := new(bytes.Buffer) - if err := proto.MarshalText(buf, newTestMessage()); err != nil { - t.Fatalf("proto.MarshalText: %v", err) - } - s := buf.String() - if s != text { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, text) - } -} - -func TestMarshalTextCustomMessage(t *testing.T) { - buf := new(bytes.Buffer) - if err := proto.MarshalText(buf, &textMessage{}); err != nil { - t.Fatalf("proto.MarshalText: %v", err) - } - s := buf.String() - if s != "custom" { - t.Errorf("Got %q, expected %q", s, "custom") - } -} -func TestMarshalTextNil(t *testing.T) { - want := "" - tests := []proto.Message{nil, (*pb.MyMessage)(nil)} - for i, test := range tests { - buf := new(bytes.Buffer) - if err := proto.MarshalText(buf, test); err != nil { - t.Fatal(err) - } - if got := buf.String(); got != want { - t.Errorf("%d: got %q want %q", i, got, want) - } - } -} - -func TestMarshalTextUnknownEnum(t *testing.T) { - // The Color enum only specifies values 0-2. - m := &pb.MyMessage{Bikeshed: pb.MyMessage_Color(3).Enum()} - got := m.String() - const want = `bikeshed:3 ` - if got != want { - t.Errorf("\n got %q\nwant %q", got, want) - } -} - -func TestTextOneof(t *testing.T) { - tests := []struct { - m proto.Message - want string - }{ - // zero message - {&pb.Communique{}, ``}, - // scalar field - {&pb.Communique{Union: &pb.Communique_Number{4}}, `number:4`}, - // message field - {&pb.Communique{Union: &pb.Communique_Msg{ - &pb.Strings{StringField: proto.String("why hello!")}, - }}, `msg:`}, - // bad oneof (should not panic) - {&pb.Communique{Union: &pb.Communique_Msg{nil}}, `msg:/* nil */`}, - } - for _, test := range tests { - got := strings.TrimSpace(test.m.String()) - if got != test.want { - t.Errorf("\n got %s\nwant %s", got, test.want) - } - } -} - -func BenchmarkMarshalTextBuffered(b *testing.B) { - buf := new(bytes.Buffer) - m := newTestMessage() - for i := 0; i < b.N; i++ { - buf.Reset() - proto.MarshalText(buf, m) - } -} - -func BenchmarkMarshalTextUnbuffered(b *testing.B) { - w := ioutil.Discard - m := newTestMessage() - for i := 0; i < b.N; i++ { - proto.MarshalText(w, m) - } -} - -func compact(src string) string { - // s/[ \n]+/ /g; s/ $//; - dst := make([]byte, len(src)) - space, comment := false, false - j := 0 - for i := 0; i < len(src); i++ { - if strings.HasPrefix(src[i:], "/*") { - comment = true - i++ - continue - } - if comment && strings.HasPrefix(src[i:], "*/") { - comment = false - i++ - continue - } - if comment { - continue - } - c := src[i] - if c == ' ' || c == '\n' { - space = true - continue - } - if j > 0 && (dst[j-1] == ':' || dst[j-1] == '<' || dst[j-1] == '{') { - space = false - } - if c == '{' { - space = false - } - if space { - dst[j] = ' ' - j++ - space = false - } - dst[j] = c - j++ - } - if space { - dst[j] = ' ' - j++ - } - return string(dst[0:j]) -} - -var compactText = compact(text) - -func TestCompactText(t *testing.T) { - s := proto.CompactTextString(newTestMessage()) - if s != compactText { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v\n===\n", s, compactText) - } -} - -func TestStringEscaping(t *testing.T) { - testCases := []struct { - in *pb.Strings - out string - }{ - { - // Test data from C++ test (TextFormatTest.StringEscape). - // Single divergence: we don't escape apostrophes. - &pb.Strings{StringField: proto.String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces")}, - "string_field: \"\\\"A string with ' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"\n", - }, - { - // Test data from the same C++ test. - &pb.Strings{StringField: proto.String("\350\260\267\346\255\214")}, - "string_field: \"\\350\\260\\267\\346\\255\\214\"\n", - }, - { - // Some UTF-8. - &pb.Strings{StringField: proto.String("\x00\x01\xff\x81")}, - `string_field: "\000\001\377\201"` + "\n", - }, - } - - for i, tc := range testCases { - var buf bytes.Buffer - if err := proto.MarshalText(&buf, tc.in); err != nil { - t.Errorf("proto.MarsalText: %v", err) - continue - } - s := buf.String() - if s != tc.out { - t.Errorf("#%d: Got:\n%s\nExpected:\n%s\n", i, s, tc.out) - continue - } - - // Check round-trip. - pb := new(pb.Strings) - if err := proto.UnmarshalText(s, pb); err != nil { - t.Errorf("#%d: UnmarshalText: %v", i, err) - continue - } - if !proto.Equal(pb, tc.in) { - t.Errorf("#%d: Round-trip failed:\nstart: %v\n end: %v", i, tc.in, pb) - } - } -} - -// A limitedWriter accepts some output before it fails. -// This is a proxy for something like a nearly-full or imminently-failing disk, -// or a network connection that is about to die. -type limitedWriter struct { - b bytes.Buffer - limit int -} - -var outOfSpace = errors.New("proto: insufficient space") - -func (w *limitedWriter) Write(p []byte) (n int, err error) { - var avail = w.limit - w.b.Len() - if avail <= 0 { - return 0, outOfSpace - } - if len(p) <= avail { - return w.b.Write(p) - } - n, _ = w.b.Write(p[:avail]) - return n, outOfSpace -} - -func TestMarshalTextFailing(t *testing.T) { - // Try lots of different sizes to exercise more error code-paths. - for lim := 0; lim < len(text); lim++ { - buf := new(limitedWriter) - buf.limit = lim - err := proto.MarshalText(buf, newTestMessage()) - // We expect a certain error, but also some partial results in the buffer. - if err != outOfSpace { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", err, outOfSpace) - } - s := buf.b.String() - x := text[:buf.limit] - if s != x { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, x) - } - } -} - -func TestFloats(t *testing.T) { - tests := []struct { - f float64 - want string - }{ - {0, "0"}, - {4.7, "4.7"}, - {math.Inf(1), "inf"}, - {math.Inf(-1), "-inf"}, - {math.NaN(), "nan"}, - } - for _, test := range tests { - msg := &pb.FloatingPoint{F: &test.f} - got := strings.TrimSpace(msg.String()) - want := `f:` + test.want - if got != want { - t.Errorf("f=%f: got %q, want %q", test.f, got, want) - } - } -} - -func TestRepeatedNilText(t *testing.T) { - m := &pb.MessageList{ - Message: []*pb.MessageList_Message{ - nil, - &pb.MessageList_Message{ - Name: proto.String("Horse"), - }, - nil, - }, - } - want := `Message -Message { - name: "Horse" -} -Message -` - if s := proto.MarshalTextString(m); s != want { - t.Errorf(" got: %s\nwant: %s", s, want) - } -} - -func TestProto3Text(t *testing.T) { - tests := []struct { - m proto.Message - want string - }{ - // zero message - {&proto3pb.Message{}, ``}, - // zero message except for an empty byte slice - {&proto3pb.Message{Data: []byte{}}, ``}, - // trivial case - {&proto3pb.Message{Name: "Rob", HeightInCm: 175}, `name:"Rob" height_in_cm:175`}, - // empty map - {&pb.MessageWithMap{}, ``}, - // non-empty map; map format is the same as a repeated struct, - // and they are sorted by key (numerically for numeric keys). - { - &pb.MessageWithMap{NameMapping: map[int32]string{ - -1: "Negatory", - 7: "Lucky", - 1234: "Feist", - 6345789: "Otis", - }}, - `name_mapping: ` + - `name_mapping: ` + - `name_mapping: ` + - `name_mapping:`, - }, - // map with nil value; not well-defined, but we shouldn't crash - { - &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{7: nil}}, - `msg_mapping:`, - }, - } - for _, test := range tests { - got := strings.TrimSpace(test.m.String()) - if got != test.want { - t.Errorf("\n got %s\nwant %s", got, test.want) - } - } -} - -func TestRacyMarshal(t *testing.T) { - // This test should be run with the race detector. - - any := &pb.MyMessage{Count: proto.Int32(47), Name: proto.String("David")} - proto.SetExtension(any, pb.E_Ext_Text, proto.String("bar")) - b, err := proto.Marshal(any) - if err != nil { - panic(err) - } - m := &proto3pb.Message{ - Name: "David", - ResultCount: 47, - Anything: &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(any), Value: b}, - } - - wantText := proto.MarshalTextString(m) - wantBytes, err := proto.Marshal(m) - if err != nil { - t.Fatalf("proto.Marshal error: %v", err) - } - - var wg sync.WaitGroup - defer wg.Wait() - wg.Add(20) - for i := 0; i < 10; i++ { - go func() { - defer wg.Done() - got := proto.MarshalTextString(m) - if got != wantText { - t.Errorf("proto.MarshalTextString = %q, want %q", got, wantText) - } - }() - go func() { - defer wg.Done() - got, err := proto.Marshal(m) - if !bytes.Equal(got, wantBytes) || err != nil { - t.Errorf("proto.Marshal = (%x, %v), want (%x, nil)", got, err, wantBytes) - } - }() - } -} diff --git a/vendor/github.com/golang/snappy/golden_test.go b/vendor/github.com/golang/snappy/golden_test.go deleted file mode 100644 index e4496f92e..000000000 --- a/vendor/github.com/golang/snappy/golden_test.go +++ /dev/null @@ -1,1965 +0,0 @@ -// Copyright 2016 The Snappy-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package snappy - -// extendMatchGoldenTestCases is the i and j arguments, and the returned value, -// for every extendMatch call issued when encoding the -// testdata/Mark.Twain-Tom.Sawyer.txt file. It is used to benchmark the -// extendMatch implementation. -// -// It was generated manually by adding some print statements to the (pure Go) -// extendMatch implementation: -// -// func extendMatch(src []byte, i, j int) int { -// i0, j0 := i, j -// for ; j < len(src) && src[i] == src[j]; i, j = i+1, j+1 { -// } -// println("{", i0, ",", j0, ",", j, "},") -// return j -// } -// -// and running "go test -test.run=EncodeGoldenInput -tags=noasm". -var extendMatchGoldenTestCases = []struct { - i, j, want int -}{ - {11, 61, 62}, - {80, 81, 82}, - {86, 87, 101}, - {85, 133, 149}, - {152, 153, 162}, - {133, 168, 193}, - {168, 207, 225}, - {81, 255, 275}, - {278, 279, 283}, - {306, 417, 417}, - {373, 428, 430}, - {389, 444, 447}, - {474, 510, 512}, - {465, 533, 533}, - {47, 547, 547}, - {307, 551, 554}, - {420, 582, 587}, - {309, 604, 604}, - {604, 625, 625}, - {538, 629, 629}, - {328, 640, 640}, - {573, 645, 645}, - {319, 657, 657}, - {30, 664, 664}, - {45, 679, 680}, - {621, 684, 684}, - {376, 700, 700}, - {33, 707, 708}, - {601, 733, 733}, - {334, 744, 745}, - {625, 758, 759}, - {382, 763, 763}, - {550, 769, 771}, - {533, 789, 789}, - {804, 813, 813}, - {342, 841, 842}, - {742, 847, 847}, - {74, 852, 852}, - {810, 864, 864}, - {758, 868, 869}, - {714, 883, 883}, - {582, 889, 891}, - {61, 934, 935}, - {894, 942, 942}, - {939, 949, 949}, - {785, 956, 957}, - {886, 978, 978}, - {792, 998, 998}, - {998, 1005, 1005}, - {572, 1032, 1032}, - {698, 1051, 1053}, - {599, 1067, 1069}, - {1056, 1079, 1079}, - {942, 1089, 1090}, - {831, 1094, 1096}, - {1088, 1100, 1103}, - {732, 1113, 1114}, - {1037, 1118, 1118}, - {872, 1128, 1130}, - {1079, 1140, 1142}, - {332, 1162, 1162}, - {207, 1168, 1186}, - {1189, 1190, 1225}, - {105, 1229, 1230}, - {79, 1256, 1257}, - {1190, 1261, 1283}, - {255, 1306, 1306}, - {1319, 1339, 1358}, - {364, 1370, 1370}, - {955, 1378, 1380}, - {122, 1403, 1403}, - {1325, 1407, 1419}, - {664, 1423, 1424}, - {941, 1461, 1463}, - {867, 1477, 1478}, - {757, 1488, 1489}, - {1140, 1499, 1499}, - {31, 1506, 1506}, - {1487, 1510, 1512}, - {1089, 1520, 1521}, - {1467, 1525, 1529}, - {1394, 1537, 1537}, - {1499, 1541, 1541}, - {367, 1558, 1558}, - {1475, 1564, 1564}, - {1525, 1568, 1571}, - {1541, 1582, 1583}, - {864, 1587, 1588}, - {704, 1597, 1597}, - {336, 1602, 1602}, - {1383, 1613, 1613}, - {1498, 1617, 1618}, - {1051, 1623, 1625}, - {401, 1643, 1645}, - {1072, 1654, 1655}, - {1067, 1667, 1669}, - {699, 1673, 1674}, - {1587, 1683, 1684}, - {920, 1696, 1696}, - {1505, 1710, 1710}, - {1550, 1723, 1723}, - {996, 1727, 1727}, - {833, 1733, 1734}, - {1638, 1739, 1740}, - {1654, 1744, 1744}, - {753, 1761, 1761}, - {1548, 1773, 1773}, - {1568, 1777, 1780}, - {1683, 1793, 1794}, - {948, 1801, 1801}, - {1666, 1805, 1808}, - {1502, 1814, 1814}, - {1696, 1822, 1822}, - {502, 1836, 1837}, - {917, 1843, 1843}, - {1733, 1854, 1855}, - {970, 1859, 1859}, - {310, 1863, 1863}, - {657, 1872, 1872}, - {1005, 1876, 1876}, - {1662, 1880, 1880}, - {904, 1892, 1892}, - {1427, 1910, 1910}, - {1772, 1929, 1930}, - {1822, 1937, 1940}, - {1858, 1949, 1950}, - {1602, 1956, 1956}, - {1150, 1962, 1962}, - {1504, 1966, 1967}, - {51, 1971, 1971}, - {1605, 1979, 1979}, - {1458, 1983, 1988}, - {1536, 2001, 2006}, - {1373, 2014, 2018}, - {1494, 2025, 2025}, - {1667, 2029, 2031}, - {1592, 2035, 2035}, - {330, 2045, 2045}, - {1376, 2053, 2053}, - {1991, 2058, 2059}, - {1635, 2065, 2065}, - {1992, 2073, 2074}, - {2014, 2080, 2081}, - {1546, 2085, 2087}, - {59, 2099, 2099}, - {1996, 2106, 2106}, - {1836, 2110, 2110}, - {2068, 2114, 2114}, - {1338, 2122, 2122}, - {1562, 2128, 2130}, - {1934, 2134, 2134}, - {2114, 2141, 2142}, - {977, 2149, 2150}, - {956, 2154, 2155}, - {1407, 2162, 2162}, - {1773, 2166, 2166}, - {883, 2171, 2171}, - {623, 2175, 2178}, - {1520, 2191, 2192}, - {1162, 2200, 2200}, - {912, 2204, 2204}, - {733, 2208, 2208}, - {1777, 2212, 2215}, - {1532, 2219, 2219}, - {718, 2223, 2225}, - {2069, 2229, 2229}, - {2207, 2245, 2246}, - {1139, 2264, 2264}, - {677, 2274, 2274}, - {2099, 2279, 2279}, - {1863, 2283, 2283}, - {1966, 2305, 2306}, - {2279, 2313, 2313}, - {1628, 2319, 2319}, - {755, 2329, 2329}, - {1461, 2334, 2334}, - {2117, 2340, 2340}, - {2313, 2349, 2349}, - {1859, 2353, 2353}, - {1048, 2362, 2362}, - {895, 2366, 2366}, - {2278, 2373, 2373}, - {1884, 2377, 2377}, - {1402, 2387, 2392}, - {700, 2398, 2398}, - {1971, 2402, 2402}, - {2009, 2419, 2419}, - {1441, 2426, 2428}, - {2208, 2432, 2432}, - {2038, 2436, 2436}, - {932, 2443, 2443}, - {1759, 2447, 2448}, - {744, 2452, 2452}, - {1875, 2458, 2458}, - {2405, 2468, 2468}, - {1596, 2472, 2473}, - {1953, 2480, 2482}, - {736, 2487, 2487}, - {1913, 2493, 2493}, - {774, 2497, 2497}, - {1484, 2506, 2508}, - {2432, 2512, 2512}, - {752, 2519, 2519}, - {2497, 2523, 2523}, - {2409, 2528, 2529}, - {2122, 2533, 2533}, - {2396, 2537, 2538}, - {2410, 2547, 2548}, - {1093, 2555, 2560}, - {551, 2564, 2565}, - {2268, 2569, 2569}, - {1362, 2580, 2580}, - {1916, 2584, 2585}, - {994, 2589, 2590}, - {1979, 2596, 2596}, - {1041, 2602, 2602}, - {2104, 2614, 2616}, - {2609, 2621, 2628}, - {2329, 2638, 2638}, - {2211, 2657, 2658}, - {2638, 2662, 2667}, - {2578, 2676, 2679}, - {2153, 2685, 2686}, - {2608, 2696, 2697}, - {598, 2712, 2712}, - {2620, 2719, 2720}, - {1888, 2724, 2728}, - {2709, 2732, 2732}, - {1365, 2739, 2739}, - {784, 2747, 2748}, - {424, 2753, 2753}, - {2204, 2759, 2759}, - {812, 2768, 2769}, - {2455, 2773, 2773}, - {1722, 2781, 2781}, - {1917, 2792, 2792}, - {2705, 2799, 2799}, - {2685, 2806, 2807}, - {2742, 2811, 2811}, - {1370, 2818, 2818}, - {2641, 2830, 2830}, - {2512, 2837, 2837}, - {2457, 2841, 2841}, - {2756, 2845, 2845}, - {2719, 2855, 2855}, - {1423, 2859, 2859}, - {2849, 2863, 2865}, - {1474, 2871, 2871}, - {1161, 2875, 2876}, - {2282, 2880, 2881}, - {2746, 2888, 2888}, - {1783, 2893, 2893}, - {2401, 2899, 2900}, - {2632, 2920, 2923}, - {2422, 2928, 2930}, - {2715, 2939, 2939}, - {2162, 2943, 2943}, - {2859, 2947, 2947}, - {1910, 2951, 2951}, - {1431, 2955, 2956}, - {1439, 2964, 2964}, - {2501, 2968, 2969}, - {2029, 2973, 2976}, - {689, 2983, 2984}, - {1658, 2988, 2988}, - {1031, 2996, 2996}, - {2149, 3001, 3002}, - {25, 3009, 3013}, - {2964, 3023, 3023}, - {953, 3027, 3028}, - {2359, 3036, 3036}, - {3023, 3049, 3049}, - {2880, 3055, 3056}, - {2973, 3076, 3077}, - {2874, 3090, 3090}, - {2871, 3094, 3094}, - {2532, 3100, 3100}, - {2938, 3107, 3108}, - {350, 3115, 3115}, - {2196, 3119, 3121}, - {1133, 3127, 3129}, - {1797, 3134, 3150}, - {3032, 3158, 3158}, - {3016, 3172, 3172}, - {2533, 3179, 3179}, - {3055, 3187, 3188}, - {1384, 3192, 3193}, - {2799, 3199, 3199}, - {2126, 3203, 3207}, - {2334, 3215, 3215}, - {2105, 3220, 3221}, - {3199, 3229, 3229}, - {2891, 3233, 3233}, - {855, 3240, 3240}, - {1852, 3253, 3256}, - {2140, 3263, 3263}, - {1682, 3268, 3270}, - {3243, 3274, 3274}, - {924, 3279, 3279}, - {2212, 3283, 3283}, - {2596, 3287, 3287}, - {2999, 3291, 3291}, - {2353, 3295, 3295}, - {2480, 3302, 3304}, - {1959, 3308, 3311}, - {3000, 3318, 3318}, - {845, 3330, 3330}, - {2283, 3334, 3334}, - {2519, 3342, 3342}, - {3325, 3346, 3348}, - {2397, 3353, 3354}, - {2763, 3358, 3358}, - {3198, 3363, 3364}, - {3211, 3368, 3372}, - {2950, 3376, 3377}, - {3245, 3388, 3391}, - {2264, 3398, 3398}, - {795, 3403, 3403}, - {3287, 3407, 3407}, - {3358, 3411, 3411}, - {3317, 3415, 3415}, - {3232, 3431, 3431}, - {2128, 3435, 3437}, - {3236, 3441, 3441}, - {3398, 3445, 3446}, - {2814, 3450, 3450}, - {3394, 3466, 3466}, - {2425, 3470, 3470}, - {3330, 3476, 3476}, - {1612, 3480, 3480}, - {1004, 3485, 3486}, - {2732, 3490, 3490}, - {1117, 3494, 3495}, - {629, 3501, 3501}, - {3087, 3514, 3514}, - {684, 3518, 3518}, - {3489, 3522, 3524}, - {1760, 3529, 3529}, - {617, 3537, 3537}, - {3431, 3541, 3541}, - {997, 3547, 3547}, - {882, 3552, 3553}, - {2419, 3558, 3558}, - {610, 3562, 3563}, - {1903, 3567, 3569}, - {3005, 3575, 3575}, - {3076, 3585, 3586}, - {3541, 3590, 3590}, - {3490, 3594, 3594}, - {1899, 3599, 3599}, - {3545, 3606, 3606}, - {3290, 3614, 3615}, - {2056, 3619, 3620}, - {3556, 3625, 3625}, - {3294, 3632, 3633}, - {637, 3643, 3644}, - {3609, 3648, 3650}, - {3175, 3658, 3658}, - {3498, 3665, 3665}, - {1597, 3669, 3669}, - {1983, 3673, 3673}, - {3215, 3682, 3682}, - {3544, 3689, 3689}, - {3694, 3698, 3698}, - {3228, 3715, 3716}, - {2594, 3720, 3722}, - {3573, 3726, 3726}, - {2479, 3732, 3735}, - {3191, 3741, 3742}, - {1113, 3746, 3747}, - {2844, 3751, 3751}, - {3445, 3756, 3757}, - {3755, 3766, 3766}, - {3421, 3775, 3780}, - {3593, 3784, 3786}, - {3263, 3796, 3796}, - {3469, 3806, 3806}, - {2602, 3815, 3815}, - {723, 3819, 3821}, - {1608, 3826, 3826}, - {3334, 3830, 3830}, - {2198, 3835, 3835}, - {2635, 3840, 3840}, - {3702, 3852, 3853}, - {3406, 3858, 3859}, - {3681, 3867, 3870}, - {3407, 3880, 3880}, - {340, 3889, 3889}, - {3772, 3893, 3893}, - {593, 3897, 3897}, - {2563, 3914, 3916}, - {2981, 3929, 3929}, - {1835, 3933, 3934}, - {3906, 3951, 3951}, - {1459, 3958, 3958}, - {3889, 3974, 3974}, - {2188, 3982, 3982}, - {3220, 3986, 3987}, - {3585, 3991, 3993}, - {3712, 3997, 4001}, - {2805, 4007, 4007}, - {1879, 4012, 4013}, - {3618, 4018, 4018}, - {1145, 4031, 4032}, - {3901, 4037, 4037}, - {2772, 4046, 4047}, - {2802, 4053, 4054}, - {3299, 4058, 4058}, - {3725, 4066, 4066}, - {2271, 4070, 4070}, - {385, 4075, 4076}, - {3624, 4089, 4090}, - {3745, 4096, 4098}, - {1563, 4102, 4102}, - {4045, 4106, 4111}, - {3696, 4115, 4119}, - {3376, 4125, 4126}, - {1880, 4130, 4130}, - {2048, 4140, 4141}, - {2724, 4149, 4149}, - {1767, 4156, 4156}, - {2601, 4164, 4164}, - {2757, 4168, 4168}, - {3974, 4172, 4172}, - {3914, 4178, 4178}, - {516, 4185, 4185}, - {1032, 4189, 4190}, - {3462, 4197, 4198}, - {3805, 4202, 4203}, - {3910, 4207, 4212}, - {3075, 4221, 4221}, - {3756, 4225, 4226}, - {1872, 4236, 4237}, - {3844, 4241, 4241}, - {3991, 4245, 4249}, - {2203, 4258, 4258}, - {3903, 4267, 4268}, - {705, 4272, 4272}, - {1896, 4276, 4276}, - {1955, 4285, 4288}, - {3746, 4302, 4303}, - {2672, 4311, 4311}, - {3969, 4317, 4317}, - {3883, 4322, 4322}, - {1920, 4339, 4340}, - {3527, 4344, 4346}, - {1160, 4358, 4358}, - {3648, 4364, 4366}, - {2711, 4387, 4387}, - {3619, 4391, 4392}, - {1944, 4396, 4396}, - {4369, 4400, 4400}, - {2736, 4404, 4407}, - {2546, 4411, 4412}, - {4390, 4422, 4422}, - {3610, 4426, 4427}, - {4058, 4431, 4431}, - {4374, 4435, 4435}, - {3463, 4445, 4446}, - {1813, 4452, 4452}, - {3669, 4456, 4456}, - {3830, 4460, 4460}, - {421, 4464, 4465}, - {1719, 4471, 4471}, - {3880, 4475, 4475}, - {1834, 4485, 4487}, - {3590, 4491, 4491}, - {442, 4496, 4497}, - {4435, 4501, 4501}, - {3814, 4509, 4509}, - {987, 4513, 4513}, - {4494, 4518, 4521}, - {3218, 4526, 4529}, - {4221, 4537, 4537}, - {2778, 4543, 4545}, - {4422, 4552, 4552}, - {4031, 4558, 4559}, - {4178, 4563, 4563}, - {3726, 4567, 4574}, - {4027, 4578, 4578}, - {4339, 4585, 4587}, - {3796, 4592, 4595}, - {543, 4600, 4613}, - {2855, 4620, 4621}, - {2795, 4627, 4627}, - {3440, 4631, 4632}, - {4279, 4636, 4639}, - {4245, 4643, 4645}, - {4516, 4649, 4650}, - {3133, 4654, 4654}, - {4042, 4658, 4659}, - {3422, 4663, 4663}, - {4046, 4667, 4668}, - {4267, 4672, 4672}, - {4004, 4676, 4677}, - {2490, 4682, 4682}, - {2451, 4697, 4697}, - {3027, 4705, 4705}, - {4028, 4717, 4717}, - {4460, 4721, 4721}, - {2471, 4725, 4727}, - {3090, 4735, 4735}, - {3192, 4739, 4740}, - {3835, 4760, 4760}, - {4540, 4764, 4764}, - {4007, 4772, 4774}, - {619, 4784, 4784}, - {3561, 4789, 4791}, - {3367, 4805, 4805}, - {4490, 4810, 4811}, - {2402, 4815, 4815}, - {3352, 4819, 4822}, - {2773, 4828, 4828}, - {4552, 4832, 4832}, - {2522, 4840, 4841}, - {316, 4847, 4852}, - {4715, 4858, 4858}, - {2959, 4862, 4862}, - {4858, 4868, 4869}, - {2134, 4873, 4873}, - {578, 4878, 4878}, - {4189, 4889, 4890}, - {2229, 4894, 4894}, - {4501, 4898, 4898}, - {2297, 4903, 4903}, - {2933, 4909, 4909}, - {3008, 4913, 4913}, - {3153, 4917, 4917}, - {4819, 4921, 4921}, - {4921, 4932, 4933}, - {4920, 4944, 4945}, - {4814, 4954, 4955}, - {576, 4966, 4966}, - {1854, 4970, 4971}, - {1374, 4975, 4976}, - {3307, 4980, 4980}, - {974, 4984, 4988}, - {4721, 4992, 4992}, - {4898, 4996, 4996}, - {4475, 5006, 5006}, - {3819, 5012, 5012}, - {1948, 5019, 5021}, - {4954, 5027, 5029}, - {3740, 5038, 5040}, - {4763, 5044, 5045}, - {1936, 5051, 5051}, - {4844, 5055, 5060}, - {4215, 5069, 5072}, - {1146, 5076, 5076}, - {3845, 5082, 5082}, - {4865, 5090, 5090}, - {4624, 5094, 5094}, - {4815, 5098, 5098}, - {5006, 5105, 5105}, - {4980, 5109, 5109}, - {4795, 5113, 5115}, - {5043, 5119, 5121}, - {4782, 5129, 5129}, - {3826, 5139, 5139}, - {3876, 5156, 5156}, - {3111, 5167, 5171}, - {1470, 5177, 5177}, - {4431, 5181, 5181}, - {546, 5189, 5189}, - {4225, 5193, 5193}, - {1672, 5199, 5201}, - {4207, 5205, 5209}, - {4220, 5216, 5217}, - {4658, 5224, 5225}, - {3295, 5235, 5235}, - {2436, 5239, 5239}, - {2349, 5246, 5246}, - {2175, 5250, 5250}, - {5180, 5257, 5258}, - {3161, 5263, 5263}, - {5105, 5272, 5272}, - {3552, 5282, 5282}, - {4944, 5299, 5300}, - {4130, 5312, 5313}, - {902, 5323, 5323}, - {913, 5327, 5327}, - {2987, 5333, 5334}, - {5150, 5344, 5344}, - {5249, 5348, 5348}, - {1965, 5358, 5359}, - {5330, 5364, 5364}, - {2012, 5373, 5377}, - {712, 5384, 5386}, - {5235, 5390, 5390}, - {5044, 5398, 5399}, - {564, 5406, 5406}, - {39, 5410, 5410}, - {4642, 5422, 5425}, - {4421, 5437, 5438}, - {2347, 5449, 5449}, - {5333, 5453, 5454}, - {4136, 5458, 5459}, - {3793, 5468, 5468}, - {2243, 5480, 5480}, - {4889, 5492, 5493}, - {4295, 5504, 5504}, - {2785, 5511, 5511}, - {2377, 5518, 5518}, - {3662, 5525, 5525}, - {5097, 5529, 5530}, - {4781, 5537, 5538}, - {4697, 5547, 5548}, - {436, 5552, 5553}, - {5542, 5558, 5558}, - {3692, 5562, 5562}, - {2696, 5568, 5569}, - {4620, 5578, 5578}, - {2898, 5590, 5590}, - {5557, 5596, 5618}, - {2797, 5623, 5625}, - {2792, 5629, 5629}, - {5243, 5633, 5633}, - {5348, 5637, 5637}, - {5547, 5643, 5643}, - {4296, 5654, 5655}, - {5568, 5662, 5662}, - {3001, 5670, 5671}, - {3794, 5679, 5679}, - {4006, 5685, 5686}, - {4969, 5690, 5692}, - {687, 5704, 5704}, - {4563, 5708, 5708}, - {1723, 5738, 5738}, - {649, 5742, 5742}, - {5163, 5748, 5755}, - {3907, 5759, 5759}, - {3074, 5764, 5764}, - {5326, 5771, 5771}, - {2951, 5776, 5776}, - {5181, 5780, 5780}, - {2614, 5785, 5788}, - {4709, 5794, 5794}, - {2784, 5799, 5799}, - {5518, 5803, 5803}, - {4155, 5812, 5815}, - {921, 5819, 5819}, - {5224, 5823, 5824}, - {2853, 5830, 5836}, - {5776, 5840, 5840}, - {2955, 5844, 5845}, - {5745, 5853, 5853}, - {3291, 5857, 5857}, - {2988, 5861, 5861}, - {2647, 5865, 5865}, - {5398, 5869, 5870}, - {1085, 5874, 5875}, - {4906, 5881, 5881}, - {802, 5886, 5886}, - {5119, 5890, 5893}, - {5802, 5899, 5900}, - {3415, 5904, 5904}, - {5629, 5908, 5908}, - {3714, 5912, 5914}, - {5558, 5921, 5921}, - {2710, 5927, 5928}, - {1094, 5932, 5934}, - {2653, 5940, 5941}, - {4735, 5954, 5954}, - {5861, 5958, 5958}, - {1040, 5971, 5971}, - {5514, 5977, 5977}, - {5048, 5981, 5982}, - {5953, 5992, 5993}, - {3751, 5997, 5997}, - {4991, 6001, 6002}, - {5885, 6006, 6007}, - {5529, 6011, 6012}, - {4974, 6019, 6020}, - {5857, 6024, 6024}, - {3483, 6032, 6032}, - {3594, 6036, 6036}, - {1997, 6040, 6040}, - {5997, 6044, 6047}, - {5197, 6051, 6051}, - {1764, 6055, 6055}, - {6050, 6059, 6059}, - {5239, 6063, 6063}, - {5049, 6067, 6067}, - {5957, 6073, 6074}, - {1022, 6078, 6078}, - {3414, 6083, 6084}, - {3809, 6090, 6090}, - {4562, 6095, 6096}, - {5878, 6104, 6104}, - {594, 6108, 6109}, - {3353, 6115, 6116}, - {4992, 6120, 6121}, - {2424, 6125, 6125}, - {4484, 6130, 6130}, - {3900, 6134, 6135}, - {5793, 6139, 6141}, - {3562, 6145, 6145}, - {1438, 6152, 6153}, - {6058, 6157, 6158}, - {4411, 6162, 6163}, - {4590, 6167, 6171}, - {4748, 6175, 6175}, - {5517, 6183, 6184}, - {6095, 6191, 6192}, - {1471, 6203, 6203}, - {2643, 6209, 6210}, - {450, 6220, 6220}, - {5266, 6226, 6226}, - {2576, 6233, 6233}, - {2607, 6239, 6240}, - {5164, 6244, 6251}, - {6054, 6255, 6255}, - {1789, 6260, 6261}, - {5250, 6265, 6265}, - {6062, 6273, 6278}, - {5990, 6282, 6282}, - {3283, 6286, 6286}, - {5436, 6290, 6290}, - {6059, 6294, 6294}, - {5668, 6298, 6300}, - {3072, 6324, 6329}, - {3132, 6338, 6339}, - {3246, 6343, 6344}, - {28, 6348, 6349}, - {1503, 6353, 6355}, - {6067, 6359, 6359}, - {3384, 6364, 6364}, - {545, 6375, 6376}, - {5803, 6380, 6380}, - {5522, 6384, 6385}, - {5908, 6389, 6389}, - {2796, 6393, 6396}, - {4831, 6403, 6404}, - {6388, 6412, 6412}, - {6005, 6417, 6420}, - {4450, 6430, 6430}, - {4050, 6435, 6435}, - {5372, 6441, 6441}, - {4378, 6447, 6447}, - {6199, 6452, 6452}, - {3026, 6456, 6456}, - {2642, 6460, 6462}, - {6392, 6470, 6470}, - {6459, 6474, 6474}, - {2829, 6487, 6488}, - {2942, 6499, 6504}, - {5069, 6508, 6511}, - {5341, 6515, 6516}, - {5853, 6521, 6525}, - {6104, 6531, 6531}, - {5759, 6535, 6538}, - {4672, 6542, 6543}, - {2443, 6550, 6550}, - {5109, 6554, 6554}, - {6494, 6558, 6560}, - {6006, 6570, 6572}, - {6424, 6576, 6580}, - {4693, 6591, 6592}, - {6439, 6596, 6597}, - {3179, 6601, 6601}, - {5299, 6606, 6607}, - {4148, 6612, 6613}, - {3774, 6617, 6617}, - {3537, 6623, 6624}, - {4975, 6628, 6629}, - {3848, 6636, 6636}, - {856, 6640, 6640}, - {5724, 6645, 6645}, - {6632, 6651, 6651}, - {4630, 6656, 6658}, - {1440, 6662, 6662}, - {4281, 6666, 6667}, - {4302, 6671, 6672}, - {2589, 6676, 6677}, - {5647, 6681, 6687}, - {6082, 6691, 6693}, - {6144, 6698, 6698}, - {6103, 6709, 6710}, - {3710, 6714, 6714}, - {4253, 6718, 6721}, - {2467, 6730, 6730}, - {4778, 6734, 6734}, - {6528, 6738, 6738}, - {4358, 6747, 6747}, - {5889, 6753, 6753}, - {5193, 6757, 6757}, - {5797, 6761, 6761}, - {3858, 6765, 6766}, - {5951, 6776, 6776}, - {6487, 6781, 6782}, - {3282, 6786, 6787}, - {4667, 6797, 6799}, - {1927, 6803, 6806}, - {6583, 6810, 6810}, - {4937, 6814, 6814}, - {6099, 6824, 6824}, - {4415, 6835, 6836}, - {6332, 6840, 6841}, - {5160, 6850, 6850}, - {4764, 6854, 6854}, - {6814, 6858, 6859}, - {3018, 6864, 6864}, - {6293, 6868, 6869}, - {6359, 6877, 6877}, - {3047, 6884, 6886}, - {5262, 6890, 6891}, - {5471, 6900, 6900}, - {3268, 6910, 6912}, - {1047, 6916, 6916}, - {5904, 6923, 6923}, - {5798, 6933, 6938}, - {4149, 6942, 6942}, - {1821, 6946, 6946}, - {3599, 6952, 6952}, - {6470, 6957, 6957}, - {5562, 6961, 6961}, - {6268, 6965, 6967}, - {6389, 6971, 6971}, - {6596, 6975, 6976}, - {6553, 6980, 6981}, - {6576, 6985, 6989}, - {1375, 6993, 6993}, - {652, 6998, 6998}, - {4876, 7002, 7003}, - {5768, 7011, 7013}, - {3973, 7017, 7017}, - {6802, 7025, 7025}, - {6955, 7034, 7036}, - {6974, 7040, 7040}, - {5944, 7044, 7044}, - {6992, 7048, 7054}, - {6872, 7059, 7059}, - {2943, 7063, 7063}, - {6923, 7067, 7067}, - {5094, 7071, 7071}, - {4873, 7075, 7075}, - {5819, 7079, 7079}, - {5945, 7085, 7085}, - {1540, 7090, 7091}, - {2090, 7095, 7095}, - {5024, 7104, 7105}, - {6900, 7109, 7109}, - {6024, 7113, 7114}, - {6000, 7118, 7120}, - {2187, 7124, 7125}, - {6760, 7129, 7130}, - {5898, 7134, 7136}, - {7032, 7144, 7144}, - {4271, 7148, 7148}, - {3706, 7152, 7152}, - {6970, 7156, 7157}, - {7088, 7161, 7163}, - {2718, 7168, 7169}, - {5674, 7175, 7175}, - {4631, 7182, 7182}, - {7070, 7188, 7189}, - {6220, 7196, 7196}, - {3458, 7201, 7202}, - {2041, 7211, 7212}, - {1454, 7216, 7216}, - {5199, 7225, 7227}, - {3529, 7234, 7234}, - {6890, 7238, 7238}, - {3815, 7242, 7243}, - {5490, 7250, 7253}, - {6554, 7257, 7263}, - {5890, 7267, 7269}, - {6877, 7273, 7273}, - {4877, 7277, 7277}, - {2502, 7285, 7285}, - {1483, 7289, 7295}, - {7210, 7304, 7308}, - {6845, 7313, 7316}, - {7219, 7320, 7320}, - {7001, 7325, 7329}, - {6853, 7333, 7334}, - {6120, 7338, 7338}, - {6606, 7342, 7343}, - {7020, 7348, 7350}, - {3509, 7354, 7354}, - {7133, 7359, 7363}, - {3434, 7371, 7374}, - {2787, 7384, 7384}, - {7044, 7388, 7388}, - {6960, 7394, 7395}, - {6676, 7399, 7400}, - {7161, 7404, 7404}, - {7285, 7417, 7418}, - {4558, 7425, 7426}, - {4828, 7430, 7430}, - {6063, 7436, 7436}, - {3597, 7442, 7442}, - {914, 7446, 7446}, - {7320, 7452, 7454}, - {7267, 7458, 7460}, - {5076, 7464, 7464}, - {7430, 7468, 7469}, - {6273, 7473, 7474}, - {7440, 7478, 7487}, - {7348, 7491, 7494}, - {1021, 7510, 7510}, - {7473, 7515, 7515}, - {2823, 7519, 7519}, - {6264, 7527, 7527}, - {7302, 7531, 7531}, - {7089, 7535, 7535}, - {7342, 7540, 7541}, - {3688, 7547, 7551}, - {3054, 7558, 7560}, - {4177, 7566, 7567}, - {6691, 7574, 7575}, - {7156, 7585, 7586}, - {7147, 7590, 7592}, - {7407, 7598, 7598}, - {7403, 7602, 7603}, - {6868, 7607, 7607}, - {6636, 7611, 7611}, - {4805, 7617, 7617}, - {5779, 7623, 7623}, - {7063, 7627, 7627}, - {5079, 7632, 7632}, - {7377, 7637, 7637}, - {7337, 7641, 7642}, - {6738, 7655, 7655}, - {7338, 7659, 7659}, - {6541, 7669, 7671}, - {595, 7675, 7675}, - {7658, 7679, 7680}, - {7647, 7685, 7686}, - {2477, 7690, 7690}, - {5823, 7694, 7694}, - {4156, 7699, 7699}, - {5931, 7703, 7706}, - {6854, 7712, 7712}, - {4931, 7718, 7718}, - {6979, 7722, 7722}, - {5085, 7727, 7727}, - {6965, 7732, 7732}, - {7201, 7736, 7737}, - {3639, 7741, 7743}, - {7534, 7749, 7749}, - {4292, 7753, 7753}, - {3427, 7759, 7763}, - {7273, 7767, 7767}, - {940, 7778, 7778}, - {4838, 7782, 7785}, - {4216, 7790, 7792}, - {922, 7800, 7801}, - {7256, 7810, 7811}, - {7789, 7815, 7819}, - {7225, 7823, 7825}, - {7531, 7829, 7829}, - {6997, 7833, 7833}, - {7757, 7837, 7838}, - {4129, 7842, 7842}, - {7333, 7848, 7849}, - {6776, 7855, 7855}, - {7527, 7859, 7859}, - {4370, 7863, 7863}, - {4512, 7868, 7868}, - {5679, 7880, 7880}, - {3162, 7884, 7885}, - {3933, 7892, 7894}, - {7804, 7899, 7902}, - {6363, 7906, 7907}, - {7848, 7911, 7912}, - {5584, 7917, 7921}, - {874, 7926, 7926}, - {3342, 7930, 7930}, - {4507, 7935, 7937}, - {3672, 7943, 7944}, - {7911, 7948, 7949}, - {6402, 7956, 7956}, - {7940, 7960, 7960}, - {7113, 7964, 7964}, - {1073, 7968, 7968}, - {7740, 7974, 7974}, - {7601, 7978, 7982}, - {6797, 7987, 7988}, - {3528, 7994, 7995}, - {5483, 7999, 7999}, - {5717, 8011, 8011}, - {5480, 8017, 8017}, - {7770, 8023, 8030}, - {2452, 8034, 8034}, - {5282, 8047, 8047}, - {7967, 8051, 8051}, - {1128, 8058, 8066}, - {6348, 8070, 8070}, - {8055, 8077, 8077}, - {7925, 8081, 8086}, - {6810, 8090, 8090}, - {5051, 8101, 8101}, - {4696, 8109, 8110}, - {5129, 8119, 8119}, - {4449, 8123, 8123}, - {7222, 8127, 8127}, - {4649, 8131, 8134}, - {7994, 8138, 8138}, - {5954, 8148, 8148}, - {475, 8152, 8153}, - {7906, 8157, 8157}, - {7458, 8164, 8166}, - {7632, 8171, 8173}, - {3874, 8177, 8183}, - {4391, 8187, 8187}, - {561, 8191, 8191}, - {2417, 8195, 8195}, - {2357, 8204, 8204}, - {2269, 8216, 8218}, - {3968, 8222, 8222}, - {2200, 8226, 8227}, - {3453, 8247, 8247}, - {2439, 8251, 8252}, - {7175, 8257, 8257}, - {976, 8262, 8264}, - {4953, 8273, 8273}, - {4219, 8278, 8278}, - {6, 8285, 8291}, - {5703, 8295, 8296}, - {5272, 8300, 8300}, - {8037, 8304, 8304}, - {8186, 8314, 8314}, - {8304, 8318, 8318}, - {8051, 8326, 8326}, - {8318, 8330, 8330}, - {2671, 8334, 8335}, - {2662, 8339, 8339}, - {8081, 8349, 8350}, - {3328, 8356, 8356}, - {2879, 8360, 8362}, - {8050, 8370, 8371}, - {8330, 8375, 8376}, - {8375, 8386, 8386}, - {4961, 8390, 8390}, - {1017, 8403, 8405}, - {3533, 8416, 8416}, - {4555, 8422, 8422}, - {6445, 8426, 8426}, - {8169, 8432, 8432}, - {990, 8436, 8436}, - {4102, 8440, 8440}, - {7398, 8444, 8446}, - {3480, 8450, 8450}, - {6324, 8462, 8462}, - {7948, 8466, 8467}, - {5950, 8471, 8471}, - {5189, 8476, 8476}, - {4026, 8490, 8490}, - {8374, 8494, 8495}, - {4682, 8501, 8501}, - {7387, 8506, 8506}, - {8164, 8510, 8515}, - {4079, 8524, 8524}, - {8360, 8529, 8531}, - {7446, 8540, 8543}, - {7971, 8547, 8548}, - {4311, 8552, 8552}, - {5204, 8556, 8557}, - {7968, 8562, 8562}, - {7847, 8571, 8573}, - {8547, 8577, 8577}, - {5320, 8581, 8581}, - {8556, 8585, 8586}, - {8504, 8590, 8590}, - {7669, 8602, 8604}, - {5874, 8608, 8609}, - {5828, 8613, 8613}, - {7998, 8617, 8617}, - {8519, 8625, 8625}, - {7250, 8637, 8637}, - {426, 8641, 8641}, - {8436, 8645, 8645}, - {5986, 8649, 8656}, - {8157, 8660, 8660}, - {7182, 8665, 8665}, - {8421, 8675, 8675}, - {8509, 8681, 8681}, - {5137, 8688, 8689}, - {8625, 8694, 8695}, - {5228, 8701, 8702}, - {6661, 8714, 8714}, - {1010, 8719, 8719}, - {6648, 8723, 8723}, - {3500, 8728, 8728}, - {2442, 8735, 8735}, - {8494, 8740, 8741}, - {8171, 8753, 8755}, - {7242, 8763, 8764}, - {4739, 8768, 8769}, - {7079, 8773, 8773}, - {8386, 8777, 8777}, - {8624, 8781, 8787}, - {661, 8791, 8794}, - {8631, 8801, 8801}, - {7753, 8805, 8805}, - {4783, 8809, 8810}, - {1673, 8814, 8815}, - {6623, 8819, 8819}, - {4404, 8823, 8823}, - {8089, 8827, 8828}, - {8773, 8832, 8832}, - {5394, 8836, 8836}, - {6231, 8841, 8843}, - {1015, 8852, 8853}, - {6873, 8857, 8857}, - {6289, 8865, 8865}, - {8577, 8869, 8869}, - {8114, 8873, 8875}, - {8534, 8883, 8883}, - {3007, 8887, 8888}, - {8827, 8892, 8893}, - {4788, 8897, 8900}, - {5698, 8906, 8907}, - {7690, 8911, 8911}, - {6643, 8919, 8919}, - {7206, 8923, 8924}, - {7866, 8929, 8931}, - {8880, 8942, 8942}, - {8630, 8951, 8952}, - {6027, 8958, 8958}, - {7749, 8966, 8967}, - {4932, 8972, 8973}, - {8892, 8980, 8981}, - {634, 9003, 9003}, - {8109, 9007, 9008}, - {8777, 9012, 9012}, - {3981, 9016, 9017}, - {5723, 9025, 9025}, - {7662, 9034, 9038}, - {8955, 9042, 9042}, - {8070, 9060, 9062}, - {8910, 9066, 9066}, - {5363, 9070, 9071}, - {7699, 9075, 9076}, - {8991, 9081, 9081}, - {6850, 9085, 9085}, - {5811, 9092, 9094}, - {9079, 9098, 9102}, - {6456, 9106, 9106}, - {2259, 9111, 9111}, - {4752, 9116, 9116}, - {9060, 9120, 9123}, - {8090, 9127, 9127}, - {5305, 9131, 9132}, - {8623, 9137, 9137}, - {7417, 9141, 9141}, - {6564, 9148, 9149}, - {9126, 9157, 9158}, - {4285, 9169, 9170}, - {8698, 9174, 9174}, - {8869, 9178, 9178}, - {2572, 9182, 9183}, - {6482, 9188, 9190}, - {9181, 9201, 9201}, - {2968, 9208, 9209}, - {2506, 9213, 9215}, - {9127, 9219, 9219}, - {7910, 9225, 9227}, - {5422, 9235, 9239}, - {8813, 9244, 9246}, - {9178, 9250, 9250}, - {8748, 9255, 9255}, - {7354, 9265, 9265}, - {7767, 9269, 9269}, - {7710, 9281, 9283}, - {8826, 9288, 9290}, - {861, 9295, 9295}, - {4482, 9301, 9301}, - {9264, 9305, 9306}, - {8805, 9310, 9310}, - {4995, 9314, 9314}, - {6730, 9318, 9318}, - {7457, 9328, 9328}, - {2547, 9335, 9336}, - {6298, 9340, 9343}, - {9305, 9353, 9354}, - {9269, 9358, 9358}, - {6338, 9370, 9370}, - {7289, 9376, 9379}, - {5780, 9383, 9383}, - {7607, 9387, 9387}, - {2065, 9392, 9392}, - {7238, 9396, 9396}, - {8856, 9400, 9400}, - {8069, 9412, 9413}, - {611, 9420, 9420}, - {7071, 9424, 9424}, - {3089, 9430, 9431}, - {7117, 9435, 9438}, - {1976, 9445, 9445}, - {6640, 9449, 9449}, - {5488, 9453, 9453}, - {8739, 9457, 9459}, - {5958, 9466, 9466}, - {7985, 9470, 9470}, - {8735, 9475, 9475}, - {5009, 9479, 9479}, - {8073, 9483, 9484}, - {2328, 9490, 9491}, - {9250, 9495, 9495}, - {4043, 9502, 9502}, - {7712, 9506, 9506}, - {9012, 9510, 9510}, - {9028, 9514, 9515}, - {2190, 9521, 9524}, - {9029, 9528, 9528}, - {9519, 9532, 9532}, - {9495, 9536, 9536}, - {8527, 9540, 9540}, - {2137, 9550, 9550}, - {8419, 9557, 9557}, - {9383, 9561, 9562}, - {8970, 9575, 9578}, - {8911, 9582, 9582}, - {7828, 9595, 9596}, - {6180, 9600, 9600}, - {8738, 9604, 9607}, - {7540, 9611, 9612}, - {9599, 9616, 9618}, - {9187, 9623, 9623}, - {9294, 9628, 9629}, - {4536, 9639, 9639}, - {3867, 9643, 9643}, - {6305, 9648, 9648}, - {1617, 9654, 9657}, - {5762, 9666, 9666}, - {8314, 9670, 9670}, - {9666, 9674, 9675}, - {9506, 9679, 9679}, - {9669, 9685, 9686}, - {9683, 9690, 9690}, - {8763, 9697, 9698}, - {7468, 9702, 9702}, - {460, 9707, 9707}, - {3115, 9712, 9712}, - {9424, 9716, 9717}, - {7359, 9721, 9724}, - {7547, 9728, 9729}, - {7151, 9733, 9738}, - {7627, 9742, 9742}, - {2822, 9747, 9747}, - {8247, 9751, 9753}, - {9550, 9758, 9758}, - {7585, 9762, 9763}, - {1002, 9767, 9767}, - {7168, 9772, 9773}, - {6941, 9777, 9780}, - {9728, 9784, 9786}, - {9770, 9792, 9796}, - {6411, 9801, 9802}, - {3689, 9806, 9808}, - {9575, 9814, 9816}, - {7025, 9820, 9821}, - {2776, 9826, 9826}, - {9806, 9830, 9830}, - {9820, 9834, 9835}, - {9800, 9839, 9847}, - {9834, 9851, 9852}, - {9829, 9856, 9862}, - {1400, 9866, 9866}, - {3197, 9870, 9871}, - {9851, 9875, 9876}, - {9742, 9883, 9884}, - {3362, 9888, 9889}, - {9883, 9893, 9893}, - {5711, 9899, 9910}, - {7806, 9915, 9915}, - {9120, 9919, 9919}, - {9715, 9925, 9934}, - {2580, 9938, 9938}, - {4907, 9942, 9944}, - {6239, 9953, 9954}, - {6961, 9963, 9963}, - {5295, 9967, 9968}, - {1915, 9972, 9973}, - {3426, 9983, 9985}, - {9875, 9994, 9995}, - {6942, 9999, 9999}, - {6621, 10005, 10005}, - {7589, 10010, 10012}, - {9286, 10020, 10020}, - {838, 10024, 10024}, - {9980, 10028, 10031}, - {9994, 10035, 10041}, - {2702, 10048, 10051}, - {2621, 10059, 10059}, - {10054, 10065, 10065}, - {8612, 10073, 10074}, - {7033, 10078, 10078}, - {916, 10082, 10082}, - {10035, 10086, 10087}, - {8613, 10097, 10097}, - {9919, 10107, 10108}, - {6133, 10114, 10115}, - {10059, 10119, 10119}, - {10065, 10126, 10127}, - {7732, 10131, 10131}, - {7155, 10135, 10136}, - {6728, 10140, 10140}, - {6162, 10144, 10145}, - {4724, 10150, 10150}, - {1665, 10154, 10154}, - {10126, 10163, 10163}, - {9783, 10168, 10168}, - {1715, 10172, 10173}, - {7152, 10177, 10182}, - {8760, 10187, 10187}, - {7829, 10191, 10191}, - {9679, 10196, 10196}, - {9369, 10201, 10201}, - {2928, 10206, 10208}, - {6951, 10214, 10217}, - {5633, 10221, 10221}, - {7199, 10225, 10225}, - {10118, 10230, 10231}, - {9999, 10235, 10236}, - {10045, 10240, 10249}, - {5565, 10256, 10256}, - {9866, 10261, 10261}, - {10163, 10268, 10268}, - {9869, 10272, 10272}, - {9789, 10276, 10283}, - {10235, 10287, 10288}, - {10214, 10298, 10299}, - {6971, 10303, 10303}, - {3346, 10307, 10307}, - {10185, 10311, 10312}, - {9993, 10318, 10320}, - {2779, 10332, 10334}, - {1726, 10338, 10338}, - {741, 10354, 10360}, - {10230, 10372, 10373}, - {10260, 10384, 10385}, - {10131, 10389, 10398}, - {6946, 10406, 10409}, - {10158, 10413, 10420}, - {10123, 10424, 10424}, - {6157, 10428, 10429}, - {4518, 10434, 10434}, - {9893, 10438, 10438}, - {9865, 10442, 10446}, - {7558, 10454, 10454}, - {10434, 10460, 10460}, - {10064, 10466, 10468}, - {2703, 10472, 10474}, - {9751, 10478, 10479}, - {6714, 10485, 10485}, - {8020, 10490, 10490}, - {10303, 10494, 10494}, - {3521, 10499, 10500}, - {9281, 10513, 10515}, - {6028, 10519, 10523}, - {9387, 10527, 10527}, - {7614, 10531, 10531}, - {3611, 10536, 10536}, - {9162, 10540, 10540}, - {10081, 10546, 10547}, - {10034, 10560, 10562}, - {6726, 10567, 10571}, - {8237, 10575, 10575}, - {10438, 10579, 10583}, - {10140, 10587, 10587}, - {5784, 10592, 10592}, - {9819, 10597, 10600}, - {10567, 10604, 10608}, - {9335, 10613, 10613}, - {8300, 10617, 10617}, - {10575, 10621, 10621}, - {9678, 10625, 10626}, - {9962, 10632, 10633}, - {10535, 10637, 10638}, - {8199, 10642, 10642}, - {10372, 10647, 10648}, - {10637, 10656, 10657}, - {10579, 10667, 10668}, - {10465, 10677, 10680}, - {6702, 10684, 10685}, - {10073, 10691, 10692}, - {4505, 10696, 10697}, - {9042, 10701, 10701}, - {6460, 10705, 10706}, - {10010, 10714, 10716}, - {10656, 10720, 10722}, - {7282, 10727, 10729}, - {2327, 10733, 10733}, - {2491, 10740, 10741}, - {10704, 10748, 10750}, - {6465, 10754, 10754}, - {10647, 10758, 10759}, - {10424, 10763, 10763}, - {10748, 10776, 10776}, - {10546, 10780, 10781}, - {10758, 10785, 10786}, - {10287, 10790, 10797}, - {10785, 10801, 10807}, - {10240, 10811, 10826}, - {9509, 10830, 10830}, - {2579, 10836, 10838}, - {9801, 10843, 10845}, - {7555, 10849, 10850}, - {10776, 10860, 10865}, - {8023, 10869, 10869}, - {10046, 10876, 10884}, - {10253, 10888, 10892}, - {9941, 10897, 10897}, - {7898, 10901, 10905}, - {6725, 10909, 10913}, - {10757, 10921, 10923}, - {10160, 10931, 10931}, - {10916, 10935, 10942}, - {10261, 10946, 10946}, - {10318, 10952, 10954}, - {5911, 10959, 10961}, - {10801, 10965, 10966}, - {10946, 10970, 10977}, - {10592, 10982, 10984}, - {9913, 10988, 10990}, - {8510, 10994, 10996}, - {9419, 11000, 11001}, - {6765, 11006, 11007}, - {10725, 11011, 11011}, - {5537, 11017, 11019}, - {9208, 11024, 11025}, - {5850, 11030, 11030}, - {9610, 11034, 11036}, - {8846, 11041, 11047}, - {9697, 11051, 11051}, - {1622, 11055, 11058}, - {2370, 11062, 11062}, - {8393, 11067, 11067}, - {9756, 11071, 11071}, - {10172, 11076, 11076}, - {27, 11081, 11081}, - {7357, 11087, 11092}, - {8151, 11104, 11106}, - {6115, 11110, 11110}, - {10667, 11114, 11115}, - {11099, 11121, 11123}, - {10705, 11127, 11127}, - {8938, 11131, 11131}, - {11114, 11135, 11136}, - {1390, 11140, 11141}, - {10964, 11146, 11148}, - {11140, 11152, 11155}, - {9813, 11159, 11166}, - {624, 11171, 11172}, - {3118, 11177, 11179}, - {11029, 11184, 11186}, - {10186, 11190, 11190}, - {10306, 11196, 11196}, - {8665, 11201, 11201}, - {7382, 11205, 11205}, - {1100, 11210, 11210}, - {2337, 11216, 11217}, - {1609, 11221, 11223}, - {5763, 11228, 11229}, - {5220, 11233, 11233}, - {11061, 11241, 11241}, - {10617, 11246, 11246}, - {11190, 11250, 11251}, - {10144, 11255, 11256}, - {11232, 11260, 11260}, - {857, 11264, 11265}, - {10994, 11269, 11271}, - {3879, 11280, 11281}, - {11184, 11287, 11289}, - {9611, 11293, 11295}, - {11250, 11299, 11299}, - {4495, 11304, 11304}, - {7574, 11308, 11309}, - {9814, 11315, 11317}, - {1713, 11321, 11324}, - {1905, 11328, 11328}, - {8745, 11335, 11340}, - {8883, 11351, 11351}, - {8119, 11358, 11358}, - {1842, 11363, 11364}, - {11237, 11368, 11368}, - {8814, 11373, 11374}, - {5684, 11378, 11378}, - {11011, 11382, 11382}, - {6520, 11389, 11389}, - {11183, 11393, 11396}, - {1790, 11404, 11404}, - {9536, 11408, 11408}, - {11298, 11418, 11419}, - {3929, 11425, 11425}, - {5588, 11429, 11429}, - {8476, 11436, 11436}, - {4096, 11440, 11442}, - {11084, 11446, 11454}, - {10603, 11458, 11463}, - {7332, 11472, 11474}, - {7611, 11483, 11486}, - {4836, 11490, 11491}, - {10024, 11495, 11495}, - {4917, 11501, 11506}, - {6486, 11510, 11512}, - {11269, 11516, 11518}, - {3603, 11522, 11525}, - {11126, 11535, 11535}, - {11418, 11539, 11541}, - {11408, 11545, 11545}, - {9021, 11549, 11552}, - {6745, 11557, 11557}, - {5118, 11561, 11564}, - {7590, 11568, 11569}, - {4426, 11573, 11578}, - {9790, 11582, 11583}, - {6447, 11587, 11587}, - {10229, 11591, 11594}, - {10457, 11598, 11598}, - {10168, 11604, 11604}, - {10543, 11608, 11608}, - {7404, 11612, 11612}, - {11127, 11616, 11616}, - {3337, 11620, 11620}, - {11501, 11624, 11628}, - {4543, 11633, 11635}, - {8449, 11642, 11642}, - {4943, 11646, 11648}, - {10526, 11652, 11654}, - {11620, 11659, 11659}, - {8927, 11664, 11669}, - {532, 11673, 11673}, - {10513, 11677, 11679}, - {10428, 11683, 11683}, - {10999, 11689, 11690}, - {9469, 11695, 11695}, - {3606, 11699, 11699}, - {9560, 11708, 11709}, - {1564, 11714, 11714}, - {10527, 11718, 11718}, - {3071, 11723, 11726}, - {11590, 11731, 11732}, - {6605, 11737, 11737}, - {11624, 11741, 11745}, - {7822, 11749, 11752}, - {5269, 11757, 11758}, - {1339, 11767, 11767}, - {1363, 11771, 11773}, - {3704, 11777, 11777}, - {10952, 11781, 11783}, - {6764, 11793, 11795}, - {8675, 11800, 11800}, - {9963, 11804, 11804}, - {11573, 11808, 11809}, - {9548, 11813, 11813}, - {11591, 11817, 11818}, - {11446, 11822, 11822}, - {9224, 11828, 11828}, - {3158, 11836, 11836}, - {10830, 11840, 11840}, - {7234, 11846, 11846}, - {11299, 11850, 11850}, - {11544, 11854, 11855}, - {11498, 11859, 11859}, - {10993, 11865, 11868}, - {9720, 11872, 11878}, - {10489, 11882, 11890}, - {11712, 11898, 11904}, - {11516, 11908, 11910}, - {11568, 11914, 11915}, - {10177, 11919, 11924}, - {11363, 11928, 11929}, - {10494, 11933, 11933}, - {9870, 11937, 11938}, - {9427, 11942, 11942}, - {11481, 11949, 11949}, - {6030, 11955, 11957}, - {11718, 11961, 11961}, - {10531, 11965, 11983}, - {5126, 11987, 11987}, - {7515, 11991, 11991}, - {10646, 11996, 11997}, - {2947, 12001, 12001}, - {9582, 12009, 12010}, - {6202, 12017, 12018}, - {11714, 12022, 12022}, - {9235, 12033, 12037}, - {9721, 12041, 12044}, - {11932, 12051, 12052}, - {12040, 12056, 12056}, - {12051, 12060, 12060}, - {11601, 12066, 12066}, - {8426, 12070, 12070}, - {4053, 12077, 12077}, - {4262, 12081, 12081}, - {9761, 12086, 12088}, - {11582, 12092, 12093}, - {10965, 12097, 12098}, - {11803, 12103, 12104}, - {11933, 12108, 12109}, - {10688, 12117, 12117}, - {12107, 12125, 12126}, - {6774, 12130, 12132}, - {6286, 12137, 12137}, - {9543, 12141, 12141}, - {12097, 12145, 12146}, - {10790, 12150, 12150}, - {10125, 12154, 12156}, - {12125, 12164, 12164}, - {12064, 12168, 12172}, - {10811, 12178, 12188}, - {12092, 12192, 12193}, - {10058, 12197, 12198}, - {11611, 12211, 12212}, - {3459, 12216, 12216}, - {10291, 12225, 12228}, - {12191, 12232, 12234}, - {12145, 12238, 12238}, - {12001, 12242, 12250}, - {3840, 12255, 12255}, - {12216, 12259, 12259}, - {674, 12272, 12272}, - {12141, 12276, 12276}, - {10766, 12280, 12280}, - {11545, 12284, 12284}, - {6496, 12290, 12290}, - {11381, 12294, 12295}, - {603, 12302, 12303}, - {12276, 12308, 12308}, - {11850, 12313, 12314}, - {565, 12319, 12319}, - {9351, 12324, 12324}, - {11822, 12328, 12328}, - {2691, 12333, 12334}, - {11840, 12338, 12338}, - {11070, 12343, 12343}, - {9510, 12347, 12347}, - {11024, 12352, 12353}, - {7173, 12359, 12359}, - {517, 12363, 12363}, - {6311, 12367, 12368}, - {11367, 12372, 12373}, - {12008, 12377, 12377}, - {11372, 12382, 12384}, - {11358, 12391, 12392}, - {11382, 12396, 12396}, - {6882, 12400, 12401}, - {11246, 12405, 12405}, - {8359, 12409, 12412}, - {10154, 12418, 12418}, - {12016, 12425, 12426}, - {8972, 12434, 12435}, - {10478, 12439, 12440}, - {12395, 12449, 12449}, - {11612, 12454, 12454}, - {12347, 12458, 12458}, - {10700, 12466, 12467}, - {3637, 12471, 12476}, - {1042, 12480, 12481}, - {6747, 12488, 12488}, - {12396, 12492, 12493}, - {9420, 12497, 12497}, - {11285, 12501, 12510}, - {4470, 12515, 12515}, - {9374, 12519, 12519}, - {11293, 12528, 12528}, - {2058, 12534, 12535}, - {6521, 12539, 12539}, - {12492, 12543, 12543}, - {3043, 12547, 12547}, - {2982, 12551, 12553}, - {11030, 12557, 12563}, - {7636, 12568, 12568}, - {9639, 12572, 12572}, - {12543, 12576, 12576}, - {5989, 12580, 12583}, - {11051, 12587, 12587}, - {1061, 12592, 12594}, - {12313, 12599, 12601}, - {11846, 12605, 12605}, - {12576, 12609, 12609}, - {11040, 12618, 12625}, - {12479, 12629, 12629}, - {6903, 12633, 12633}, - {12322, 12639, 12639}, - {12253, 12643, 12645}, - {5594, 12651, 12651}, - {12522, 12655, 12655}, - {11703, 12659, 12659}, - {1377, 12665, 12665}, - {8022, 12669, 12669}, - {12280, 12674, 12674}, - {9023, 12680, 12681}, - {12328, 12685, 12685}, - {3085, 12689, 12693}, - {4700, 12698, 12698}, - {10224, 12702, 12702}, - {8781, 12706, 12706}, - {1651, 12710, 12710}, - {12458, 12714, 12714}, - {12005, 12718, 12721}, - {11908, 12725, 12726}, - {8202, 12733, 12733}, - {11708, 12739, 12740}, - {12599, 12744, 12745}, - {12284, 12749, 12749}, - {5285, 12756, 12756}, - {12055, 12775, 12777}, - {6919, 12782, 12782}, - {12242, 12786, 12786}, - {12009, 12790, 12790}, - {9628, 12794, 12796}, - {11354, 12801, 12802}, - {10225, 12806, 12807}, - {579, 12813, 12813}, - {8935, 12817, 12822}, - {8753, 12827, 12829}, - {11006, 12835, 12835}, - {858, 12841, 12845}, - {476, 12849, 12849}, - {7667, 12854, 12854}, - {12760, 12860, 12871}, - {11677, 12875, 12877}, - {12714, 12881, 12881}, - {12731, 12885, 12890}, - {7108, 12894, 12896}, - {1165, 12900, 12900}, - {4021, 12906, 12906}, - {10829, 12910, 12911}, - {12331, 12915, 12915}, - {8887, 12919, 12921}, - {11639, 12925, 12925}, - {7964, 12929, 12929}, - {12528, 12937, 12937}, - {8148, 12941, 12941}, - {12770, 12948, 12950}, - {12609, 12954, 12954}, - {12685, 12958, 12958}, - {2803, 12962, 12962}, - {9561, 12966, 12966}, - {6671, 12972, 12973}, - {12056, 12977, 12977}, - {6380, 12981, 12981}, - {12048, 12985, 12985}, - {11961, 12989, 12993}, - {3368, 12997, 12999}, - {6634, 13004, 13004}, - {6775, 13009, 13010}, - {12136, 13014, 13019}, - {10341, 13023, 13023}, - {13002, 13027, 13027}, - {10587, 13031, 13031}, - {10307, 13035, 13035}, - {12736, 13039, 13039}, - {12744, 13043, 13044}, - {6175, 13048, 13048}, - {9702, 13053, 13054}, - {662, 13059, 13061}, - {12718, 13065, 13068}, - {12893, 13072, 13075}, - {8299, 13086, 13091}, - {12604, 13095, 13096}, - {12848, 13100, 13101}, - {12749, 13105, 13105}, - {12526, 13109, 13114}, - {9173, 13122, 13122}, - {12769, 13128, 13128}, - {13038, 13132, 13132}, - {12725, 13136, 13137}, - {12639, 13146, 13146}, - {9711, 13150, 13151}, - {12137, 13155, 13155}, - {13039, 13159, 13159}, - {4681, 13163, 13164}, - {12954, 13168, 13168}, - {13158, 13175, 13176}, - {13105, 13180, 13180}, - {10754, 13184, 13184}, - {13167, 13188, 13188}, - {12658, 13192, 13192}, - {4294, 13199, 13200}, - {11682, 13204, 13205}, - {11695, 13209, 13209}, - {11076, 13214, 13214}, - {12232, 13218, 13218}, - {9399, 13223, 13224}, - {12880, 13228, 13229}, - {13048, 13234, 13234}, - {9701, 13238, 13239}, - {13209, 13243, 13243}, - {3658, 13248, 13248}, - {3698, 13252, 13254}, - {12237, 13260, 13260}, - {8872, 13266, 13266}, - {12957, 13272, 13273}, - {1393, 13281, 13281}, - {2013, 13285, 13288}, - {4244, 13296, 13299}, - {9428, 13303, 13303}, - {12702, 13307, 13307}, - {13078, 13311, 13311}, - {6071, 13315, 13315}, - {3061, 13319, 13319}, - {2051, 13324, 13324}, - {11560, 13328, 13331}, - {6584, 13336, 13336}, - {8482, 13340, 13340}, - {5331, 13344, 13344}, - {4171, 13348, 13348}, - {8501, 13352, 13352}, - {9219, 13356, 13356}, - {9473, 13360, 13363}, - {12881, 13367, 13367}, - {13065, 13371, 13375}, - {2979, 13379, 13384}, - {1518, 13388, 13388}, - {11177, 13392, 13392}, - {9457, 13398, 13398}, - {12293, 13407, 13410}, - {3697, 13414, 13417}, - {10338, 13425, 13425}, - {13367, 13429, 13429}, - {11074, 13433, 13437}, - {4201, 13441, 13443}, - {1812, 13447, 13448}, - {13360, 13452, 13456}, - {13188, 13463, 13463}, - {9732, 13470, 13470}, - {11332, 13477, 13477}, - {9918, 13487, 13487}, - {6337, 13497, 13497}, - {13429, 13501, 13501}, - {11413, 13505, 13505}, - {4685, 13512, 13513}, - {13136, 13517, 13519}, - {7416, 13528, 13530}, - {12929, 13534, 13534}, - {11110, 13539, 13539}, - {11521, 13543, 13543}, - {12825, 13553, 13553}, - {13447, 13557, 13558}, - {12299, 13562, 13563}, - {9003, 13570, 13570}, - {12500, 13577, 13577}, - {13501, 13581, 13581}, - {9392, 13586, 13586}, - {12454, 13590, 13590}, - {6189, 13595, 13595}, - {13053, 13599, 13599}, - {11881, 13604, 13604}, - {13159, 13608, 13608}, - {4894, 13612, 13612}, - {13221, 13621, 13621}, - {8950, 13625, 13625}, - {13533, 13629, 13629}, - {9633, 13633, 13633}, - {7892, 13637, 13639}, - {13581, 13643, 13643}, - {13616, 13647, 13649}, - {12794, 13653, 13654}, - {8919, 13659, 13659}, - {9674, 13663, 13663}, - {13577, 13668, 13668}, - {12966, 13672, 13672}, - {12659, 13676, 13683}, - {6124, 13688, 13688}, - {9225, 13693, 13695}, - {11833, 13702, 13702}, - {12904, 13709, 13717}, - {13647, 13721, 13722}, - {11687, 13726, 13727}, - {12434, 13731, 13732}, - {12689, 13736, 13742}, - {13168, 13746, 13746}, - {6151, 13751, 13752}, - {11821, 13756, 13757}, - {6467, 13764, 13764}, - {5730, 13769, 13769}, - {5136, 13780, 13780}, - {724, 13784, 13785}, - {13517, 13789, 13791}, - {640, 13795, 13796}, - {7721, 13800, 13802}, - {11121, 13806, 13807}, - {5791, 13811, 13815}, - {12894, 13819, 13819}, - {11100, 13824, 13824}, - {7011, 13830, 13830}, - {7129, 13834, 13837}, - {13833, 13841, 13841}, - {11276, 13847, 13847}, - {13621, 13853, 13853}, - {13589, 13862, 13863}, - {12989, 13867, 13867}, - {12789, 13871, 13871}, - {1239, 13875, 13875}, - {4675, 13879, 13881}, - {4686, 13885, 13885}, - {707, 13889, 13889}, - {5449, 13897, 13898}, - {13867, 13902, 13903}, - {10613, 13908, 13908}, - {13789, 13912, 13914}, - {4451, 13918, 13919}, - {9200, 13924, 13924}, - {2011, 13930, 13930}, - {11433, 13934, 13936}, - {4695, 13942, 13943}, - {9435, 13948, 13951}, - {13688, 13955, 13957}, - {11694, 13961, 13962}, - {5712, 13966, 13966}, - {5991, 13970, 13972}, - {13477, 13976, 13976}, - {10213, 13987, 13987}, - {11839, 13991, 13993}, - {12272, 13997, 13997}, - {6206, 14001, 14001}, - {13179, 14006, 14007}, - {2939, 14011, 14011}, - {12972, 14016, 14017}, - {13918, 14021, 14022}, - {7436, 14026, 14027}, - {7678, 14032, 14034}, - {13586, 14040, 14040}, - {13347, 14044, 14044}, - {13109, 14048, 14051}, - {9244, 14055, 14057}, - {13315, 14061, 14061}, - {13276, 14067, 14067}, - {11435, 14073, 14074}, - {13853, 14078, 14078}, - {13452, 14082, 14082}, - {14044, 14087, 14087}, - {4440, 14091, 14095}, - {4479, 14100, 14103}, - {9395, 14107, 14109}, - {6834, 14119, 14119}, - {10458, 14123, 14124}, - {1429, 14129, 14129}, - {8443, 14135, 14135}, - {10365, 14140, 14140}, - {5267, 14145, 14145}, - {11834, 14151, 14153}, -} diff --git a/vendor/github.com/golang/snappy/snappy_test.go b/vendor/github.com/golang/snappy/snappy_test.go deleted file mode 100644 index 2712710df..000000000 --- a/vendor/github.com/golang/snappy/snappy_test.go +++ /dev/null @@ -1,1353 +0,0 @@ -// Copyright 2011 The Snappy-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package snappy - -import ( - "bytes" - "encoding/binary" - "flag" - "fmt" - "io" - "io/ioutil" - "math/rand" - "net/http" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - "testing" -) - -var ( - download = flag.Bool("download", false, "If true, download any missing files before running benchmarks") - testdataDir = flag.String("testdataDir", "testdata", "Directory containing the test data") - benchdataDir = flag.String("benchdataDir", "testdata/bench", "Directory containing the benchmark data") -) - -// goEncoderShouldMatchCppEncoder is whether to test that the algorithm used by -// Go's encoder matches byte-for-byte what the C++ snappy encoder produces, on -// this GOARCH. There is more than one valid encoding of any given input, and -// there is more than one good algorithm along the frontier of trading off -// throughput for output size. Nonetheless, we presume that the C++ encoder's -// algorithm is a good one and has been tested on a wide range of inputs, so -// matching that exactly should mean that the Go encoder's algorithm is also -// good, without needing to gather our own corpus of test data. -// -// The exact algorithm used by the C++ code is potentially endian dependent, as -// it puns a byte pointer to a uint32 pointer to load, hash and compare 4 bytes -// at a time. The Go implementation is endian agnostic, in that its output is -// the same (as little-endian C++ code), regardless of the CPU's endianness. -// -// Thus, when comparing Go's output to C++ output generated beforehand, such as -// the "testdata/pi.txt.rawsnappy" file generated by C++ code on a little- -// endian system, we can run that test regardless of the runtime.GOARCH value. -// -// When comparing Go's output to dynamically generated C++ output, i.e. the -// result of fork/exec'ing a C++ program, we can run that test only on -// little-endian systems, because the C++ output might be different on -// big-endian systems. The runtime package doesn't export endianness per se, -// but we can restrict this match-C++ test to common little-endian systems. -const goEncoderShouldMatchCppEncoder = runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "arm" - -func TestMaxEncodedLenOfMaxBlockSize(t *testing.T) { - got := maxEncodedLenOfMaxBlockSize - want := MaxEncodedLen(maxBlockSize) - if got != want { - t.Fatalf("got %d, want %d", got, want) - } -} - -func cmp(a, b []byte) error { - if bytes.Equal(a, b) { - return nil - } - if len(a) != len(b) { - return fmt.Errorf("got %d bytes, want %d", len(a), len(b)) - } - for i := range a { - if a[i] != b[i] { - return fmt.Errorf("byte #%d: got 0x%02x, want 0x%02x", i, a[i], b[i]) - } - } - return nil -} - -func roundtrip(b, ebuf, dbuf []byte) error { - d, err := Decode(dbuf, Encode(ebuf, b)) - if err != nil { - return fmt.Errorf("decoding error: %v", err) - } - if err := cmp(d, b); err != nil { - return fmt.Errorf("roundtrip mismatch: %v", err) - } - return nil -} - -func TestEmpty(t *testing.T) { - if err := roundtrip(nil, nil, nil); err != nil { - t.Fatal(err) - } -} - -func TestSmallCopy(t *testing.T) { - for _, ebuf := range [][]byte{nil, make([]byte, 20), make([]byte, 64)} { - for _, dbuf := range [][]byte{nil, make([]byte, 20), make([]byte, 64)} { - for i := 0; i < 32; i++ { - s := "aaaa" + strings.Repeat("b", i) + "aaaabbbb" - if err := roundtrip([]byte(s), ebuf, dbuf); err != nil { - t.Errorf("len(ebuf)=%d, len(dbuf)=%d, i=%d: %v", len(ebuf), len(dbuf), i, err) - } - } - } - } -} - -func TestSmallRand(t *testing.T) { - rng := rand.New(rand.NewSource(1)) - for n := 1; n < 20000; n += 23 { - b := make([]byte, n) - for i := range b { - b[i] = uint8(rng.Intn(256)) - } - if err := roundtrip(b, nil, nil); err != nil { - t.Fatal(err) - } - } -} - -func TestSmallRegular(t *testing.T) { - for n := 1; n < 20000; n += 23 { - b := make([]byte, n) - for i := range b { - b[i] = uint8(i%10 + 'a') - } - if err := roundtrip(b, nil, nil); err != nil { - t.Fatal(err) - } - } -} - -func TestInvalidVarint(t *testing.T) { - testCases := []struct { - desc string - input string - }{{ - "invalid varint, final byte has continuation bit set", - "\xff", - }, { - "invalid varint, value overflows uint64", - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00", - }, { - // https://github.com/google/snappy/blob/master/format_description.txt - // says that "the stream starts with the uncompressed length [as a - // varint] (up to a maximum of 2^32 - 1)". - "valid varint (as uint64), but value overflows uint32", - "\x80\x80\x80\x80\x10", - }} - - for _, tc := range testCases { - input := []byte(tc.input) - if _, err := DecodedLen(input); err != ErrCorrupt { - t.Errorf("%s: DecodedLen: got %v, want ErrCorrupt", tc.desc, err) - } - if _, err := Decode(nil, input); err != ErrCorrupt { - t.Errorf("%s: Decode: got %v, want ErrCorrupt", tc.desc, err) - } - } -} - -func TestDecode(t *testing.T) { - lit40Bytes := make([]byte, 40) - for i := range lit40Bytes { - lit40Bytes[i] = byte(i) - } - lit40 := string(lit40Bytes) - - testCases := []struct { - desc string - input string - want string - wantErr error - }{{ - `decodedLen=0; valid input`, - "\x00", - "", - nil, - }, { - `decodedLen=3; tagLiteral, 0-byte length; length=3; valid input`, - "\x03" + "\x08\xff\xff\xff", - "\xff\xff\xff", - nil, - }, { - `decodedLen=2; tagLiteral, 0-byte length; length=3; not enough dst bytes`, - "\x02" + "\x08\xff\xff\xff", - "", - ErrCorrupt, - }, { - `decodedLen=3; tagLiteral, 0-byte length; length=3; not enough src bytes`, - "\x03" + "\x08\xff\xff", - "", - ErrCorrupt, - }, { - `decodedLen=40; tagLiteral, 0-byte length; length=40; valid input`, - "\x28" + "\x9c" + lit40, - lit40, - nil, - }, { - `decodedLen=1; tagLiteral, 1-byte length; not enough length bytes`, - "\x01" + "\xf0", - "", - ErrCorrupt, - }, { - `decodedLen=3; tagLiteral, 1-byte length; length=3; valid input`, - "\x03" + "\xf0\x02\xff\xff\xff", - "\xff\xff\xff", - nil, - }, { - `decodedLen=1; tagLiteral, 2-byte length; not enough length bytes`, - "\x01" + "\xf4\x00", - "", - ErrCorrupt, - }, { - `decodedLen=3; tagLiteral, 2-byte length; length=3; valid input`, - "\x03" + "\xf4\x02\x00\xff\xff\xff", - "\xff\xff\xff", - nil, - }, { - `decodedLen=1; tagLiteral, 3-byte length; not enough length bytes`, - "\x01" + "\xf8\x00\x00", - "", - ErrCorrupt, - }, { - `decodedLen=3; tagLiteral, 3-byte length; length=3; valid input`, - "\x03" + "\xf8\x02\x00\x00\xff\xff\xff", - "\xff\xff\xff", - nil, - }, { - `decodedLen=1; tagLiteral, 4-byte length; not enough length bytes`, - "\x01" + "\xfc\x00\x00\x00", - "", - ErrCorrupt, - }, { - `decodedLen=1; tagLiteral, 4-byte length; length=3; not enough dst bytes`, - "\x01" + "\xfc\x02\x00\x00\x00\xff\xff\xff", - "", - ErrCorrupt, - }, { - `decodedLen=4; tagLiteral, 4-byte length; length=3; not enough src bytes`, - "\x04" + "\xfc\x02\x00\x00\x00\xff", - "", - ErrCorrupt, - }, { - `decodedLen=3; tagLiteral, 4-byte length; length=3; valid input`, - "\x03" + "\xfc\x02\x00\x00\x00\xff\xff\xff", - "\xff\xff\xff", - nil, - }, { - `decodedLen=4; tagCopy1, 1 extra length|offset byte; not enough extra bytes`, - "\x04" + "\x01", - "", - ErrCorrupt, - }, { - `decodedLen=4; tagCopy2, 2 extra length|offset bytes; not enough extra bytes`, - "\x04" + "\x02\x00", - "", - ErrCorrupt, - }, { - `decodedLen=4; tagCopy4, 4 extra length|offset bytes; not enough extra bytes`, - "\x04" + "\x03\x00\x00\x00", - "", - ErrCorrupt, - }, { - `decodedLen=4; tagLiteral (4 bytes "abcd"); valid input`, - "\x04" + "\x0cabcd", - "abcd", - nil, - }, { - `decodedLen=13; tagLiteral (4 bytes "abcd"); tagCopy1; length=9 offset=4; valid input`, - "\x0d" + "\x0cabcd" + "\x15\x04", - "abcdabcdabcda", - nil, - }, { - `decodedLen=8; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=4; valid input`, - "\x08" + "\x0cabcd" + "\x01\x04", - "abcdabcd", - nil, - }, { - `decodedLen=8; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=2; valid input`, - "\x08" + "\x0cabcd" + "\x01\x02", - "abcdcdcd", - nil, - }, { - `decodedLen=8; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=1; valid input`, - "\x08" + "\x0cabcd" + "\x01\x01", - "abcddddd", - nil, - }, { - `decodedLen=8; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=0; zero offset`, - "\x08" + "\x0cabcd" + "\x01\x00", - "", - ErrCorrupt, - }, { - `decodedLen=9; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=4; inconsistent dLen`, - "\x09" + "\x0cabcd" + "\x01\x04", - "", - ErrCorrupt, - }, { - `decodedLen=8; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=5; offset too large`, - "\x08" + "\x0cabcd" + "\x01\x05", - "", - ErrCorrupt, - }, { - `decodedLen=7; tagLiteral (4 bytes "abcd"); tagCopy1; length=4 offset=4; length too large`, - "\x07" + "\x0cabcd" + "\x01\x04", - "", - ErrCorrupt, - }, { - `decodedLen=6; tagLiteral (4 bytes "abcd"); tagCopy2; length=2 offset=3; valid input`, - "\x06" + "\x0cabcd" + "\x06\x03\x00", - "abcdbc", - nil, - }, { - `decodedLen=6; tagLiteral (4 bytes "abcd"); tagCopy4; length=2 offset=3; valid input`, - "\x06" + "\x0cabcd" + "\x07\x03\x00\x00\x00", - "abcdbc", - nil, - }} - - const ( - // notPresentXxx defines a range of byte values [0xa0, 0xc5) that are - // not present in either the input or the output. It is written to dBuf - // to check that Decode does not write bytes past the end of - // dBuf[:dLen]. - // - // The magic number 37 was chosen because it is prime. A more 'natural' - // number like 32 might lead to a false negative if, for example, a - // byte was incorrectly copied 4*8 bytes later. - notPresentBase = 0xa0 - notPresentLen = 37 - ) - - var dBuf [100]byte -loop: - for i, tc := range testCases { - input := []byte(tc.input) - for _, x := range input { - if notPresentBase <= x && x < notPresentBase+notPresentLen { - t.Errorf("#%d (%s): input shouldn't contain %#02x\ninput: % x", i, tc.desc, x, input) - continue loop - } - } - - dLen, n := binary.Uvarint(input) - if n <= 0 { - t.Errorf("#%d (%s): invalid varint-encoded dLen", i, tc.desc) - continue - } - if dLen > uint64(len(dBuf)) { - t.Errorf("#%d (%s): dLen %d is too large", i, tc.desc, dLen) - continue - } - - for j := range dBuf { - dBuf[j] = byte(notPresentBase + j%notPresentLen) - } - g, gotErr := Decode(dBuf[:], input) - if got := string(g); got != tc.want || gotErr != tc.wantErr { - t.Errorf("#%d (%s):\ngot %q, %v\nwant %q, %v", - i, tc.desc, got, gotErr, tc.want, tc.wantErr) - continue - } - for j, x := range dBuf { - if uint64(j) < dLen { - continue - } - if w := byte(notPresentBase + j%notPresentLen); x != w { - t.Errorf("#%d (%s): Decode overrun: dBuf[%d] was modified: got %#02x, want %#02x\ndBuf: % x", - i, tc.desc, j, x, w, dBuf) - continue loop - } - } - } -} - -func TestDecodeCopy4(t *testing.T) { - dots := strings.Repeat(".", 65536) - - input := strings.Join([]string{ - "\x89\x80\x04", // decodedLen = 65545. - "\x0cpqrs", // 4-byte literal "pqrs". - "\xf4\xff\xff" + dots, // 65536-byte literal dots. - "\x13\x04\x00\x01\x00", // tagCopy4; length=5 offset=65540. - }, "") - - gotBytes, err := Decode(nil, []byte(input)) - if err != nil { - t.Fatal(err) - } - got := string(gotBytes) - want := "pqrs" + dots + "pqrs." - if len(got) != len(want) { - t.Fatalf("got %d bytes, want %d", len(got), len(want)) - } - if got != want { - for i := 0; i < len(got); i++ { - if g, w := got[i], want[i]; g != w { - t.Fatalf("byte #%d: got %#02x, want %#02x", i, g, w) - } - } - } -} - -// TestDecodeLengthOffset tests decoding an encoding of the form literal + -// copy-length-offset + literal. For example: "abcdefghijkl" + "efghij" + "AB". -func TestDecodeLengthOffset(t *testing.T) { - const ( - prefix = "abcdefghijklmnopqr" - suffix = "ABCDEFGHIJKLMNOPQR" - - // notPresentXxx defines a range of byte values [0xa0, 0xc5) that are - // not present in either the input or the output. It is written to - // gotBuf to check that Decode does not write bytes past the end of - // gotBuf[:totalLen]. - // - // The magic number 37 was chosen because it is prime. A more 'natural' - // number like 32 might lead to a false negative if, for example, a - // byte was incorrectly copied 4*8 bytes later. - notPresentBase = 0xa0 - notPresentLen = 37 - ) - var gotBuf, wantBuf, inputBuf [128]byte - for length := 1; length <= 18; length++ { - for offset := 1; offset <= 18; offset++ { - loop: - for suffixLen := 0; suffixLen <= 18; suffixLen++ { - totalLen := len(prefix) + length + suffixLen - - inputLen := binary.PutUvarint(inputBuf[:], uint64(totalLen)) - inputBuf[inputLen] = tagLiteral + 4*byte(len(prefix)-1) - inputLen++ - inputLen += copy(inputBuf[inputLen:], prefix) - inputBuf[inputLen+0] = tagCopy2 + 4*byte(length-1) - inputBuf[inputLen+1] = byte(offset) - inputBuf[inputLen+2] = 0x00 - inputLen += 3 - if suffixLen > 0 { - inputBuf[inputLen] = tagLiteral + 4*byte(suffixLen-1) - inputLen++ - inputLen += copy(inputBuf[inputLen:], suffix[:suffixLen]) - } - input := inputBuf[:inputLen] - - for i := range gotBuf { - gotBuf[i] = byte(notPresentBase + i%notPresentLen) - } - got, err := Decode(gotBuf[:], input) - if err != nil { - t.Errorf("length=%d, offset=%d; suffixLen=%d: %v", length, offset, suffixLen, err) - continue - } - - wantLen := 0 - wantLen += copy(wantBuf[wantLen:], prefix) - for i := 0; i < length; i++ { - wantBuf[wantLen] = wantBuf[wantLen-offset] - wantLen++ - } - wantLen += copy(wantBuf[wantLen:], suffix[:suffixLen]) - want := wantBuf[:wantLen] - - for _, x := range input { - if notPresentBase <= x && x < notPresentBase+notPresentLen { - t.Errorf("length=%d, offset=%d; suffixLen=%d: input shouldn't contain %#02x\ninput: % x", - length, offset, suffixLen, x, input) - continue loop - } - } - for i, x := range gotBuf { - if i < totalLen { - continue - } - if w := byte(notPresentBase + i%notPresentLen); x != w { - t.Errorf("length=%d, offset=%d; suffixLen=%d; totalLen=%d: "+ - "Decode overrun: gotBuf[%d] was modified: got %#02x, want %#02x\ngotBuf: % x", - length, offset, suffixLen, totalLen, i, x, w, gotBuf) - continue loop - } - } - for _, x := range want { - if notPresentBase <= x && x < notPresentBase+notPresentLen { - t.Errorf("length=%d, offset=%d; suffixLen=%d: want shouldn't contain %#02x\nwant: % x", - length, offset, suffixLen, x, want) - continue loop - } - } - - if !bytes.Equal(got, want) { - t.Errorf("length=%d, offset=%d; suffixLen=%d:\ninput % x\ngot % x\nwant % x", - length, offset, suffixLen, input, got, want) - continue - } - } - } - } -} - -const ( - goldenText = "Mark.Twain-Tom.Sawyer.txt" - goldenCompressed = goldenText + ".rawsnappy" -) - -func TestDecodeGoldenInput(t *testing.T) { - tDir := filepath.FromSlash(*testdataDir) - src, err := ioutil.ReadFile(filepath.Join(tDir, goldenCompressed)) - if err != nil { - t.Fatalf("ReadFile: %v", err) - } - got, err := Decode(nil, src) - if err != nil { - t.Fatalf("Decode: %v", err) - } - want, err := ioutil.ReadFile(filepath.Join(tDir, goldenText)) - if err != nil { - t.Fatalf("ReadFile: %v", err) - } - if err := cmp(got, want); err != nil { - t.Fatal(err) - } -} - -func TestEncodeGoldenInput(t *testing.T) { - tDir := filepath.FromSlash(*testdataDir) - src, err := ioutil.ReadFile(filepath.Join(tDir, goldenText)) - if err != nil { - t.Fatalf("ReadFile: %v", err) - } - got := Encode(nil, src) - want, err := ioutil.ReadFile(filepath.Join(tDir, goldenCompressed)) - if err != nil { - t.Fatalf("ReadFile: %v", err) - } - if err := cmp(got, want); err != nil { - t.Fatal(err) - } -} - -func TestExtendMatchGoldenInput(t *testing.T) { - tDir := filepath.FromSlash(*testdataDir) - src, err := ioutil.ReadFile(filepath.Join(tDir, goldenText)) - if err != nil { - t.Fatalf("ReadFile: %v", err) - } - for i, tc := range extendMatchGoldenTestCases { - got := extendMatch(src, tc.i, tc.j) - if got != tc.want { - t.Errorf("test #%d: i, j = %5d, %5d: got %5d (= j + %6d), want %5d (= j + %6d)", - i, tc.i, tc.j, got, got-tc.j, tc.want, tc.want-tc.j) - } - } -} - -func TestExtendMatch(t *testing.T) { - // ref is a simple, reference implementation of extendMatch. - ref := func(src []byte, i, j int) int { - for ; j < len(src) && src[i] == src[j]; i, j = i+1, j+1 { - } - return j - } - - nums := []int{0, 1, 2, 7, 8, 9, 29, 30, 31, 32, 33, 34, 38, 39, 40} - for yIndex := 40; yIndex > 30; yIndex-- { - xxx := bytes.Repeat([]byte("x"), 40) - if yIndex < len(xxx) { - xxx[yIndex] = 'y' - } - for _, i := range nums { - for _, j := range nums { - if i >= j { - continue - } - got := extendMatch(xxx, i, j) - want := ref(xxx, i, j) - if got != want { - t.Errorf("yIndex=%d, i=%d, j=%d: got %d, want %d", yIndex, i, j, got, want) - } - } - } - } -} - -const snappytoolCmdName = "cmd/snappytool/snappytool" - -func skipTestSameEncodingAsCpp() (msg string) { - if !goEncoderShouldMatchCppEncoder { - return fmt.Sprintf("skipping testing that the encoding is byte-for-byte identical to C++: GOARCH=%s", runtime.GOARCH) - } - if _, err := os.Stat(snappytoolCmdName); err != nil { - return fmt.Sprintf("could not find snappytool: %v", err) - } - return "" -} - -func runTestSameEncodingAsCpp(src []byte) error { - got := Encode(nil, src) - - cmd := exec.Command(snappytoolCmdName, "-e") - cmd.Stdin = bytes.NewReader(src) - want, err := cmd.Output() - if err != nil { - return fmt.Errorf("could not run snappytool: %v", err) - } - return cmp(got, want) -} - -func TestSameEncodingAsCppShortCopies(t *testing.T) { - if msg := skipTestSameEncodingAsCpp(); msg != "" { - t.Skip(msg) - } - src := bytes.Repeat([]byte{'a'}, 20) - for i := 0; i <= len(src); i++ { - if err := runTestSameEncodingAsCpp(src[:i]); err != nil { - t.Errorf("i=%d: %v", i, err) - } - } -} - -func TestSameEncodingAsCppLongFiles(t *testing.T) { - if msg := skipTestSameEncodingAsCpp(); msg != "" { - t.Skip(msg) - } - bDir := filepath.FromSlash(*benchdataDir) - failed := false - for i, tf := range testFiles { - if err := downloadBenchmarkFiles(t, tf.filename); err != nil { - t.Fatalf("failed to download testdata: %s", err) - } - data := readFile(t, filepath.Join(bDir, tf.filename)) - if n := tf.sizeLimit; 0 < n && n < len(data) { - data = data[:n] - } - if err := runTestSameEncodingAsCpp(data); err != nil { - t.Errorf("i=%d: %v", i, err) - failed = true - } - } - if failed { - t.Errorf("was the snappytool program built against the C++ snappy library version " + - "d53de187 or later, commited on 2016-04-05? See " + - "https://github.com/google/snappy/commit/d53de18799418e113e44444252a39b12a0e4e0cc") - } -} - -// TestSlowForwardCopyOverrun tests the "expand the pattern" algorithm -// described in decode_amd64.s and its claim of a 10 byte overrun worst case. -func TestSlowForwardCopyOverrun(t *testing.T) { - const base = 100 - - for length := 1; length < 18; length++ { - for offset := 1; offset < 18; offset++ { - highWaterMark := base - d := base - l := length - o := offset - - // makeOffsetAtLeast8 - for o < 8 { - if end := d + 8; highWaterMark < end { - highWaterMark = end - } - l -= o - d += o - o += o - } - - // fixUpSlowForwardCopy - a := d - d += l - - // finishSlowForwardCopy - for l > 0 { - if end := a + 8; highWaterMark < end { - highWaterMark = end - } - a += 8 - l -= 8 - } - - dWant := base + length - overrun := highWaterMark - dWant - if d != dWant || overrun < 0 || 10 < overrun { - t.Errorf("length=%d, offset=%d: d and overrun: got (%d, %d), want (%d, something in [0, 10])", - length, offset, d, overrun, dWant) - } - } - } -} - -// TestEncodeNoiseThenRepeats encodes input for which the first half is very -// incompressible and the second half is very compressible. The encoded form's -// length should be closer to 50% of the original length than 100%. -func TestEncodeNoiseThenRepeats(t *testing.T) { - for _, origLen := range []int{256 * 1024, 2048 * 1024} { - src := make([]byte, origLen) - rng := rand.New(rand.NewSource(1)) - firstHalf, secondHalf := src[:origLen/2], src[origLen/2:] - for i := range firstHalf { - firstHalf[i] = uint8(rng.Intn(256)) - } - for i := range secondHalf { - secondHalf[i] = uint8(i >> 8) - } - dst := Encode(nil, src) - if got, want := len(dst), origLen*3/4; got >= want { - t.Errorf("origLen=%d: got %d encoded bytes, want less than %d", origLen, got, want) - } - } -} - -func TestFramingFormat(t *testing.T) { - // src is comprised of alternating 1e5-sized sequences of random - // (incompressible) bytes and repeated (compressible) bytes. 1e5 was chosen - // because it is larger than maxBlockSize (64k). - src := make([]byte, 1e6) - rng := rand.New(rand.NewSource(1)) - for i := 0; i < 10; i++ { - if i%2 == 0 { - for j := 0; j < 1e5; j++ { - src[1e5*i+j] = uint8(rng.Intn(256)) - } - } else { - for j := 0; j < 1e5; j++ { - src[1e5*i+j] = uint8(i) - } - } - } - - buf := new(bytes.Buffer) - if _, err := NewWriter(buf).Write(src); err != nil { - t.Fatalf("Write: encoding: %v", err) - } - dst, err := ioutil.ReadAll(NewReader(buf)) - if err != nil { - t.Fatalf("ReadAll: decoding: %v", err) - } - if err := cmp(dst, src); err != nil { - t.Fatal(err) - } -} - -func TestWriterGoldenOutput(t *testing.T) { - buf := new(bytes.Buffer) - w := NewBufferedWriter(buf) - defer w.Close() - w.Write([]byte("abcd")) // Not compressible. - w.Flush() - w.Write(bytes.Repeat([]byte{'A'}, 150)) // Compressible. - w.Flush() - // The next chunk is also compressible, but a naive, greedy encoding of the - // overall length 67 copy as a length 64 copy (the longest expressible as a - // tagCopy1 or tagCopy2) plus a length 3 remainder would be two 3-byte - // tagCopy2 tags (6 bytes), since the minimum length for a tagCopy1 is 4 - // bytes. Instead, we could do it shorter, in 5 bytes: a 3-byte tagCopy2 - // (of length 60) and a 2-byte tagCopy1 (of length 7). - w.Write(bytes.Repeat([]byte{'B'}, 68)) - w.Write([]byte("efC")) // Not compressible. - w.Write(bytes.Repeat([]byte{'C'}, 20)) // Compressible. - w.Write(bytes.Repeat([]byte{'B'}, 20)) // Compressible. - w.Write([]byte("g")) // Not compressible. - w.Flush() - - got := buf.String() - want := strings.Join([]string{ - magicChunk, - "\x01\x08\x00\x00", // Uncompressed chunk, 8 bytes long (including 4 byte checksum). - "\x68\x10\xe6\xb6", // Checksum. - "\x61\x62\x63\x64", // Uncompressed payload: "abcd". - "\x00\x11\x00\x00", // Compressed chunk, 17 bytes long (including 4 byte checksum). - "\x5f\xeb\xf2\x10", // Checksum. - "\x96\x01", // Compressed payload: Uncompressed length (varint encoded): 150. - "\x00\x41", // Compressed payload: tagLiteral, length=1, "A". - "\xfe\x01\x00", // Compressed payload: tagCopy2, length=64, offset=1. - "\xfe\x01\x00", // Compressed payload: tagCopy2, length=64, offset=1. - "\x52\x01\x00", // Compressed payload: tagCopy2, length=21, offset=1. - "\x00\x18\x00\x00", // Compressed chunk, 24 bytes long (including 4 byte checksum). - "\x30\x85\x69\xeb", // Checksum. - "\x70", // Compressed payload: Uncompressed length (varint encoded): 112. - "\x00\x42", // Compressed payload: tagLiteral, length=1, "B". - "\xee\x01\x00", // Compressed payload: tagCopy2, length=60, offset=1. - "\x0d\x01", // Compressed payload: tagCopy1, length=7, offset=1. - "\x08\x65\x66\x43", // Compressed payload: tagLiteral, length=3, "efC". - "\x4e\x01\x00", // Compressed payload: tagCopy2, length=20, offset=1. - "\x4e\x5a\x00", // Compressed payload: tagCopy2, length=20, offset=90. - "\x00\x67", // Compressed payload: tagLiteral, length=1, "g". - }, "") - if got != want { - t.Fatalf("\ngot: % x\nwant: % x", got, want) - } -} - -func TestEmitLiteral(t *testing.T) { - testCases := []struct { - length int - want string - }{ - {1, "\x00"}, - {2, "\x04"}, - {59, "\xe8"}, - {60, "\xec"}, - {61, "\xf0\x3c"}, - {62, "\xf0\x3d"}, - {254, "\xf0\xfd"}, - {255, "\xf0\xfe"}, - {256, "\xf0\xff"}, - {257, "\xf4\x00\x01"}, - {65534, "\xf4\xfd\xff"}, - {65535, "\xf4\xfe\xff"}, - {65536, "\xf4\xff\xff"}, - } - - dst := make([]byte, 70000) - nines := bytes.Repeat([]byte{0x99}, 65536) - for _, tc := range testCases { - lit := nines[:tc.length] - n := emitLiteral(dst, lit) - if !bytes.HasSuffix(dst[:n], lit) { - t.Errorf("length=%d: did not end with that many literal bytes", tc.length) - continue - } - got := string(dst[:n-tc.length]) - if got != tc.want { - t.Errorf("length=%d:\ngot % x\nwant % x", tc.length, got, tc.want) - continue - } - } -} - -func TestEmitCopy(t *testing.T) { - testCases := []struct { - offset int - length int - want string - }{ - {8, 04, "\x01\x08"}, - {8, 11, "\x1d\x08"}, - {8, 12, "\x2e\x08\x00"}, - {8, 13, "\x32\x08\x00"}, - {8, 59, "\xea\x08\x00"}, - {8, 60, "\xee\x08\x00"}, - {8, 61, "\xf2\x08\x00"}, - {8, 62, "\xf6\x08\x00"}, - {8, 63, "\xfa\x08\x00"}, - {8, 64, "\xfe\x08\x00"}, - {8, 65, "\xee\x08\x00\x05\x08"}, - {8, 66, "\xee\x08\x00\x09\x08"}, - {8, 67, "\xee\x08\x00\x0d\x08"}, - {8, 68, "\xfe\x08\x00\x01\x08"}, - {8, 69, "\xfe\x08\x00\x05\x08"}, - {8, 80, "\xfe\x08\x00\x3e\x08\x00"}, - - {256, 04, "\x21\x00"}, - {256, 11, "\x3d\x00"}, - {256, 12, "\x2e\x00\x01"}, - {256, 13, "\x32\x00\x01"}, - {256, 59, "\xea\x00\x01"}, - {256, 60, "\xee\x00\x01"}, - {256, 61, "\xf2\x00\x01"}, - {256, 62, "\xf6\x00\x01"}, - {256, 63, "\xfa\x00\x01"}, - {256, 64, "\xfe\x00\x01"}, - {256, 65, "\xee\x00\x01\x25\x00"}, - {256, 66, "\xee\x00\x01\x29\x00"}, - {256, 67, "\xee\x00\x01\x2d\x00"}, - {256, 68, "\xfe\x00\x01\x21\x00"}, - {256, 69, "\xfe\x00\x01\x25\x00"}, - {256, 80, "\xfe\x00\x01\x3e\x00\x01"}, - - {2048, 04, "\x0e\x00\x08"}, - {2048, 11, "\x2a\x00\x08"}, - {2048, 12, "\x2e\x00\x08"}, - {2048, 13, "\x32\x00\x08"}, - {2048, 59, "\xea\x00\x08"}, - {2048, 60, "\xee\x00\x08"}, - {2048, 61, "\xf2\x00\x08"}, - {2048, 62, "\xf6\x00\x08"}, - {2048, 63, "\xfa\x00\x08"}, - {2048, 64, "\xfe\x00\x08"}, - {2048, 65, "\xee\x00\x08\x12\x00\x08"}, - {2048, 66, "\xee\x00\x08\x16\x00\x08"}, - {2048, 67, "\xee\x00\x08\x1a\x00\x08"}, - {2048, 68, "\xfe\x00\x08\x0e\x00\x08"}, - {2048, 69, "\xfe\x00\x08\x12\x00\x08"}, - {2048, 80, "\xfe\x00\x08\x3e\x00\x08"}, - } - - dst := make([]byte, 1024) - for _, tc := range testCases { - n := emitCopy(dst, tc.offset, tc.length) - got := string(dst[:n]) - if got != tc.want { - t.Errorf("offset=%d, length=%d:\ngot % x\nwant % x", tc.offset, tc.length, got, tc.want) - } - } -} - -func TestNewBufferedWriter(t *testing.T) { - // Test all 32 possible sub-sequences of these 5 input slices. - // - // Their lengths sum to 400,000, which is over 6 times the Writer ibuf - // capacity: 6 * maxBlockSize is 393,216. - inputs := [][]byte{ - bytes.Repeat([]byte{'a'}, 40000), - bytes.Repeat([]byte{'b'}, 150000), - bytes.Repeat([]byte{'c'}, 60000), - bytes.Repeat([]byte{'d'}, 120000), - bytes.Repeat([]byte{'e'}, 30000), - } -loop: - for i := 0; i < 1< 0; { - i := copy(x, src) - x = x[i:] - } - return dst -} - -func benchWords(b *testing.B, n int, decode bool) { - // Note: the file is OS-language dependent so the resulting values are not - // directly comparable for non-US-English OS installations. - data := expand(readFile(b, "/usr/share/dict/words"), n) - if decode { - benchDecode(b, data) - } else { - benchEncode(b, data) - } -} - -func BenchmarkWordsDecode1e1(b *testing.B) { benchWords(b, 1e1, true) } -func BenchmarkWordsDecode1e2(b *testing.B) { benchWords(b, 1e2, true) } -func BenchmarkWordsDecode1e3(b *testing.B) { benchWords(b, 1e3, true) } -func BenchmarkWordsDecode1e4(b *testing.B) { benchWords(b, 1e4, true) } -func BenchmarkWordsDecode1e5(b *testing.B) { benchWords(b, 1e5, true) } -func BenchmarkWordsDecode1e6(b *testing.B) { benchWords(b, 1e6, true) } -func BenchmarkWordsEncode1e1(b *testing.B) { benchWords(b, 1e1, false) } -func BenchmarkWordsEncode1e2(b *testing.B) { benchWords(b, 1e2, false) } -func BenchmarkWordsEncode1e3(b *testing.B) { benchWords(b, 1e3, false) } -func BenchmarkWordsEncode1e4(b *testing.B) { benchWords(b, 1e4, false) } -func BenchmarkWordsEncode1e5(b *testing.B) { benchWords(b, 1e5, false) } -func BenchmarkWordsEncode1e6(b *testing.B) { benchWords(b, 1e6, false) } - -func BenchmarkRandomEncode(b *testing.B) { - rng := rand.New(rand.NewSource(1)) - data := make([]byte, 1<<20) - for i := range data { - data[i] = uint8(rng.Intn(256)) - } - benchEncode(b, data) -} - -// testFiles' values are copied directly from -// https://raw.githubusercontent.com/google/snappy/master/snappy_unittest.cc -// The label field is unused in snappy-go. -var testFiles = []struct { - label string - filename string - sizeLimit int -}{ - {"html", "html", 0}, - {"urls", "urls.10K", 0}, - {"jpg", "fireworks.jpeg", 0}, - {"jpg_200", "fireworks.jpeg", 200}, - {"pdf", "paper-100k.pdf", 0}, - {"html4", "html_x_4", 0}, - {"txt1", "alice29.txt", 0}, - {"txt2", "asyoulik.txt", 0}, - {"txt3", "lcet10.txt", 0}, - {"txt4", "plrabn12.txt", 0}, - {"pb", "geo.protodata", 0}, - {"gaviota", "kppkn.gtb", 0}, -} - -const ( - // The benchmark data files are at this canonical URL. - benchURL = "https://raw.githubusercontent.com/google/snappy/master/testdata/" -) - -func downloadBenchmarkFiles(b testing.TB, basename string) (errRet error) { - bDir := filepath.FromSlash(*benchdataDir) - filename := filepath.Join(bDir, basename) - if stat, err := os.Stat(filename); err == nil && stat.Size() != 0 { - return nil - } - - if !*download { - b.Skipf("test data not found; skipping %s without the -download flag", testOrBenchmark(b)) - } - // Download the official snappy C++ implementation reference test data - // files for benchmarking. - if err := os.MkdirAll(bDir, 0777); err != nil && !os.IsExist(err) { - return fmt.Errorf("failed to create %s: %s", bDir, err) - } - - f, err := os.Create(filename) - if err != nil { - return fmt.Errorf("failed to create %s: %s", filename, err) - } - defer f.Close() - defer func() { - if errRet != nil { - os.Remove(filename) - } - }() - url := benchURL + basename - resp, err := http.Get(url) - if err != nil { - return fmt.Errorf("failed to download %s: %s", url, err) - } - defer resp.Body.Close() - if s := resp.StatusCode; s != http.StatusOK { - return fmt.Errorf("downloading %s: HTTP status code %d (%s)", url, s, http.StatusText(s)) - } - _, err = io.Copy(f, resp.Body) - if err != nil { - return fmt.Errorf("failed to download %s to %s: %s", url, filename, err) - } - return nil -} - -func benchFile(b *testing.B, i int, decode bool) { - if err := downloadBenchmarkFiles(b, testFiles[i].filename); err != nil { - b.Fatalf("failed to download testdata: %s", err) - } - bDir := filepath.FromSlash(*benchdataDir) - data := readFile(b, filepath.Join(bDir, testFiles[i].filename)) - if n := testFiles[i].sizeLimit; 0 < n && n < len(data) { - data = data[:n] - } - if decode { - benchDecode(b, data) - } else { - benchEncode(b, data) - } -} - -// Naming convention is kept similar to what snappy's C++ implementation uses. -func Benchmark_UFlat0(b *testing.B) { benchFile(b, 0, true) } -func Benchmark_UFlat1(b *testing.B) { benchFile(b, 1, true) } -func Benchmark_UFlat2(b *testing.B) { benchFile(b, 2, true) } -func Benchmark_UFlat3(b *testing.B) { benchFile(b, 3, true) } -func Benchmark_UFlat4(b *testing.B) { benchFile(b, 4, true) } -func Benchmark_UFlat5(b *testing.B) { benchFile(b, 5, true) } -func Benchmark_UFlat6(b *testing.B) { benchFile(b, 6, true) } -func Benchmark_UFlat7(b *testing.B) { benchFile(b, 7, true) } -func Benchmark_UFlat8(b *testing.B) { benchFile(b, 8, true) } -func Benchmark_UFlat9(b *testing.B) { benchFile(b, 9, true) } -func Benchmark_UFlat10(b *testing.B) { benchFile(b, 10, true) } -func Benchmark_UFlat11(b *testing.B) { benchFile(b, 11, true) } -func Benchmark_ZFlat0(b *testing.B) { benchFile(b, 0, false) } -func Benchmark_ZFlat1(b *testing.B) { benchFile(b, 1, false) } -func Benchmark_ZFlat2(b *testing.B) { benchFile(b, 2, false) } -func Benchmark_ZFlat3(b *testing.B) { benchFile(b, 3, false) } -func Benchmark_ZFlat4(b *testing.B) { benchFile(b, 4, false) } -func Benchmark_ZFlat5(b *testing.B) { benchFile(b, 5, false) } -func Benchmark_ZFlat6(b *testing.B) { benchFile(b, 6, false) } -func Benchmark_ZFlat7(b *testing.B) { benchFile(b, 7, false) } -func Benchmark_ZFlat8(b *testing.B) { benchFile(b, 8, false) } -func Benchmark_ZFlat9(b *testing.B) { benchFile(b, 9, false) } -func Benchmark_ZFlat10(b *testing.B) { benchFile(b, 10, false) } -func Benchmark_ZFlat11(b *testing.B) { benchFile(b, 11, false) } - -func BenchmarkExtendMatch(b *testing.B) { - tDir := filepath.FromSlash(*testdataDir) - src, err := ioutil.ReadFile(filepath.Join(tDir, goldenText)) - if err != nil { - b.Fatalf("ReadFile: %v", err) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - for _, tc := range extendMatchGoldenTestCases { - extendMatch(src, tc.i, tc.j) - } - } -} diff --git a/vendor/github.com/google/btree/.travis.yml b/vendor/github.com/google/btree/.travis.yml new file mode 100644 index 000000000..4f2ee4d97 --- /dev/null +++ b/vendor/github.com/google/btree/.travis.yml @@ -0,0 +1 @@ +language: go diff --git a/vendor/github.com/google/btree/LICENSE b/vendor/github.com/google/btree/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/vendor/github.com/google/btree/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/google/btree/README.md b/vendor/github.com/google/btree/README.md new file mode 100644 index 000000000..6062a4dac --- /dev/null +++ b/vendor/github.com/google/btree/README.md @@ -0,0 +1,12 @@ +# BTree implementation for Go + +![Travis CI Build Status](https://api.travis-ci.org/google/btree.svg?branch=master) + +This package provides an in-memory B-Tree implementation for Go, useful as +an ordered, mutable data structure. + +The API is based off of the wonderful +http://godoc.org/github.com/petar/GoLLRB/llrb, and is meant to allow btree to +act as a drop-in replacement for gollrb trees. + +See http://godoc.org/github.com/google/btree for documentation. diff --git a/vendor/github.com/google/btree/btree.go b/vendor/github.com/google/btree/btree.go new file mode 100644 index 000000000..6ff062f9b --- /dev/null +++ b/vendor/github.com/google/btree/btree.go @@ -0,0 +1,890 @@ +// Copyright 2014 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package btree implements in-memory B-Trees of arbitrary degree. +// +// btree implements an in-memory B-Tree for use as an ordered data structure. +// It is not meant for persistent storage solutions. +// +// It has a flatter structure than an equivalent red-black or other binary tree, +// which in some cases yields better memory usage and/or performance. +// See some discussion on the matter here: +// http://google-opensource.blogspot.com/2013/01/c-containers-that-save-memory-and-time.html +// Note, though, that this project is in no way related to the C++ B-Tree +// implementation written about there. +// +// Within this tree, each node contains a slice of items and a (possibly nil) +// slice of children. For basic numeric values or raw structs, this can cause +// efficiency differences when compared to equivalent C++ template code that +// stores values in arrays within the node: +// * Due to the overhead of storing values as interfaces (each +// value needs to be stored as the value itself, then 2 words for the +// interface pointing to that value and its type), resulting in higher +// memory use. +// * Since interfaces can point to values anywhere in memory, values are +// most likely not stored in contiguous blocks, resulting in a higher +// number of cache misses. +// These issues don't tend to matter, though, when working with strings or other +// heap-allocated structures, since C++-equivalent structures also must store +// pointers and also distribute their values across the heap. +// +// This implementation is designed to be a drop-in replacement to gollrb.LLRB +// trees, (http://github.com/petar/gollrb), an excellent and probably the most +// widely used ordered tree implementation in the Go ecosystem currently. +// Its functions, therefore, exactly mirror those of +// llrb.LLRB where possible. Unlike gollrb, though, we currently don't +// support storing multiple equivalent values. +package btree + +import ( + "fmt" + "io" + "sort" + "strings" + "sync" +) + +// Item represents a single object in the tree. +type Item interface { + // Less tests whether the current item is less than the given argument. + // + // This must provide a strict weak ordering. + // If !a.Less(b) && !b.Less(a), we treat this to mean a == b (i.e. we can only + // hold one of either a or b in the tree). + Less(than Item) bool +} + +const ( + DefaultFreeListSize = 32 +) + +var ( + nilItems = make(items, 16) + nilChildren = make(children, 16) +) + +// FreeList represents a free list of btree nodes. By default each +// BTree has its own FreeList, but multiple BTrees can share the same +// FreeList. +// Two Btrees using the same freelist are safe for concurrent write access. +type FreeList struct { + mu sync.Mutex + freelist []*node +} + +// NewFreeList creates a new free list. +// size is the maximum size of the returned free list. +func NewFreeList(size int) *FreeList { + return &FreeList{freelist: make([]*node, 0, size)} +} + +func (f *FreeList) newNode() (n *node) { + f.mu.Lock() + index := len(f.freelist) - 1 + if index < 0 { + f.mu.Unlock() + return new(node) + } + n = f.freelist[index] + f.freelist[index] = nil + f.freelist = f.freelist[:index] + f.mu.Unlock() + return +} + +// freeNode adds the given node to the list, returning true if it was added +// and false if it was discarded. +func (f *FreeList) freeNode(n *node) (out bool) { + f.mu.Lock() + if len(f.freelist) < cap(f.freelist) { + f.freelist = append(f.freelist, n) + out = true + } + f.mu.Unlock() + return +} + +// ItemIterator allows callers of Ascend* to iterate in-order over portions of +// the tree. When this function returns false, iteration will stop and the +// associated Ascend* function will immediately return. +type ItemIterator func(i Item) bool + +// New creates a new B-Tree with the given degree. +// +// New(2), for example, will create a 2-3-4 tree (each node contains 1-3 items +// and 2-4 children). +func New(degree int) *BTree { + return NewWithFreeList(degree, NewFreeList(DefaultFreeListSize)) +} + +// NewWithFreeList creates a new B-Tree that uses the given node free list. +func NewWithFreeList(degree int, f *FreeList) *BTree { + if degree <= 1 { + panic("bad degree") + } + return &BTree{ + degree: degree, + cow: ©OnWriteContext{freelist: f}, + } +} + +// items stores items in a node. +type items []Item + +// insertAt inserts a value into the given index, pushing all subsequent values +// forward. +func (s *items) insertAt(index int, item Item) { + *s = append(*s, nil) + if index < len(*s) { + copy((*s)[index+1:], (*s)[index:]) + } + (*s)[index] = item +} + +// removeAt removes a value at a given index, pulling all subsequent values +// back. +func (s *items) removeAt(index int) Item { + item := (*s)[index] + copy((*s)[index:], (*s)[index+1:]) + (*s)[len(*s)-1] = nil + *s = (*s)[:len(*s)-1] + return item +} + +// pop removes and returns the last element in the list. +func (s *items) pop() (out Item) { + index := len(*s) - 1 + out = (*s)[index] + (*s)[index] = nil + *s = (*s)[:index] + return +} + +// truncate truncates this instance at index so that it contains only the +// first index items. index must be less than or equal to length. +func (s *items) truncate(index int) { + var toClear items + *s, toClear = (*s)[:index], (*s)[index:] + for len(toClear) > 0 { + toClear = toClear[copy(toClear, nilItems):] + } +} + +// find returns the index where the given item should be inserted into this +// list. 'found' is true if the item already exists in the list at the given +// index. +func (s items) find(item Item) (index int, found bool) { + i := sort.Search(len(s), func(i int) bool { + return item.Less(s[i]) + }) + if i > 0 && !s[i-1].Less(item) { + return i - 1, true + } + return i, false +} + +// children stores child nodes in a node. +type children []*node + +// insertAt inserts a value into the given index, pushing all subsequent values +// forward. +func (s *children) insertAt(index int, n *node) { + *s = append(*s, nil) + if index < len(*s) { + copy((*s)[index+1:], (*s)[index:]) + } + (*s)[index] = n +} + +// removeAt removes a value at a given index, pulling all subsequent values +// back. +func (s *children) removeAt(index int) *node { + n := (*s)[index] + copy((*s)[index:], (*s)[index+1:]) + (*s)[len(*s)-1] = nil + *s = (*s)[:len(*s)-1] + return n +} + +// pop removes and returns the last element in the list. +func (s *children) pop() (out *node) { + index := len(*s) - 1 + out = (*s)[index] + (*s)[index] = nil + *s = (*s)[:index] + return +} + +// truncate truncates this instance at index so that it contains only the +// first index children. index must be less than or equal to length. +func (s *children) truncate(index int) { + var toClear children + *s, toClear = (*s)[:index], (*s)[index:] + for len(toClear) > 0 { + toClear = toClear[copy(toClear, nilChildren):] + } +} + +// node is an internal node in a tree. +// +// It must at all times maintain the invariant that either +// * len(children) == 0, len(items) unconstrained +// * len(children) == len(items) + 1 +type node struct { + items items + children children + cow *copyOnWriteContext +} + +func (n *node) mutableFor(cow *copyOnWriteContext) *node { + if n.cow == cow { + return n + } + out := cow.newNode() + if cap(out.items) >= len(n.items) { + out.items = out.items[:len(n.items)] + } else { + out.items = make(items, len(n.items), cap(n.items)) + } + copy(out.items, n.items) + // Copy children + if cap(out.children) >= len(n.children) { + out.children = out.children[:len(n.children)] + } else { + out.children = make(children, len(n.children), cap(n.children)) + } + copy(out.children, n.children) + return out +} + +func (n *node) mutableChild(i int) *node { + c := n.children[i].mutableFor(n.cow) + n.children[i] = c + return c +} + +// split splits the given node at the given index. The current node shrinks, +// and this function returns the item that existed at that index and a new node +// containing all items/children after it. +func (n *node) split(i int) (Item, *node) { + item := n.items[i] + next := n.cow.newNode() + next.items = append(next.items, n.items[i+1:]...) + n.items.truncate(i) + if len(n.children) > 0 { + next.children = append(next.children, n.children[i+1:]...) + n.children.truncate(i + 1) + } + return item, next +} + +// maybeSplitChild checks if a child should be split, and if so splits it. +// Returns whether or not a split occurred. +func (n *node) maybeSplitChild(i, maxItems int) bool { + if len(n.children[i].items) < maxItems { + return false + } + first := n.mutableChild(i) + item, second := first.split(maxItems / 2) + n.items.insertAt(i, item) + n.children.insertAt(i+1, second) + return true +} + +// insert inserts an item into the subtree rooted at this node, making sure +// no nodes in the subtree exceed maxItems items. Should an equivalent item be +// be found/replaced by insert, it will be returned. +func (n *node) insert(item Item, maxItems int) Item { + i, found := n.items.find(item) + if found { + out := n.items[i] + n.items[i] = item + return out + } + if len(n.children) == 0 { + n.items.insertAt(i, item) + return nil + } + if n.maybeSplitChild(i, maxItems) { + inTree := n.items[i] + switch { + case item.Less(inTree): + // no change, we want first split node + case inTree.Less(item): + i++ // we want second split node + default: + out := n.items[i] + n.items[i] = item + return out + } + } + return n.mutableChild(i).insert(item, maxItems) +} + +// get finds the given key in the subtree and returns it. +func (n *node) get(key Item) Item { + i, found := n.items.find(key) + if found { + return n.items[i] + } else if len(n.children) > 0 { + return n.children[i].get(key) + } + return nil +} + +// min returns the first item in the subtree. +func min(n *node) Item { + if n == nil { + return nil + } + for len(n.children) > 0 { + n = n.children[0] + } + if len(n.items) == 0 { + return nil + } + return n.items[0] +} + +// max returns the last item in the subtree. +func max(n *node) Item { + if n == nil { + return nil + } + for len(n.children) > 0 { + n = n.children[len(n.children)-1] + } + if len(n.items) == 0 { + return nil + } + return n.items[len(n.items)-1] +} + +// toRemove details what item to remove in a node.remove call. +type toRemove int + +const ( + removeItem toRemove = iota // removes the given item + removeMin // removes smallest item in the subtree + removeMax // removes largest item in the subtree +) + +// remove removes an item from the subtree rooted at this node. +func (n *node) remove(item Item, minItems int, typ toRemove) Item { + var i int + var found bool + switch typ { + case removeMax: + if len(n.children) == 0 { + return n.items.pop() + } + i = len(n.items) + case removeMin: + if len(n.children) == 0 { + return n.items.removeAt(0) + } + i = 0 + case removeItem: + i, found = n.items.find(item) + if len(n.children) == 0 { + if found { + return n.items.removeAt(i) + } + return nil + } + default: + panic("invalid type") + } + // If we get to here, we have children. + if len(n.children[i].items) <= minItems { + return n.growChildAndRemove(i, item, minItems, typ) + } + child := n.mutableChild(i) + // Either we had enough items to begin with, or we've done some + // merging/stealing, because we've got enough now and we're ready to return + // stuff. + if found { + // The item exists at index 'i', and the child we've selected can give us a + // predecessor, since if we've gotten here it's got > minItems items in it. + out := n.items[i] + // We use our special-case 'remove' call with typ=maxItem to pull the + // predecessor of item i (the rightmost leaf of our immediate left child) + // and set it into where we pulled the item from. + n.items[i] = child.remove(nil, minItems, removeMax) + return out + } + // Final recursive call. Once we're here, we know that the item isn't in this + // node and that the child is big enough to remove from. + return child.remove(item, minItems, typ) +} + +// growChildAndRemove grows child 'i' to make sure it's possible to remove an +// item from it while keeping it at minItems, then calls remove to actually +// remove it. +// +// Most documentation says we have to do two sets of special casing: +// 1) item is in this node +// 2) item is in child +// In both cases, we need to handle the two subcases: +// A) node has enough values that it can spare one +// B) node doesn't have enough values +// For the latter, we have to check: +// a) left sibling has node to spare +// b) right sibling has node to spare +// c) we must merge +// To simplify our code here, we handle cases #1 and #2 the same: +// If a node doesn't have enough items, we make sure it does (using a,b,c). +// We then simply redo our remove call, and the second time (regardless of +// whether we're in case 1 or 2), we'll have enough items and can guarantee +// that we hit case A. +func (n *node) growChildAndRemove(i int, item Item, minItems int, typ toRemove) Item { + if i > 0 && len(n.children[i-1].items) > minItems { + // Steal from left child + child := n.mutableChild(i) + stealFrom := n.mutableChild(i - 1) + stolenItem := stealFrom.items.pop() + child.items.insertAt(0, n.items[i-1]) + n.items[i-1] = stolenItem + if len(stealFrom.children) > 0 { + child.children.insertAt(0, stealFrom.children.pop()) + } + } else if i < len(n.items) && len(n.children[i+1].items) > minItems { + // steal from right child + child := n.mutableChild(i) + stealFrom := n.mutableChild(i + 1) + stolenItem := stealFrom.items.removeAt(0) + child.items = append(child.items, n.items[i]) + n.items[i] = stolenItem + if len(stealFrom.children) > 0 { + child.children = append(child.children, stealFrom.children.removeAt(0)) + } + } else { + if i >= len(n.items) { + i-- + } + child := n.mutableChild(i) + // merge with right child + mergeItem := n.items.removeAt(i) + mergeChild := n.children.removeAt(i + 1) + child.items = append(child.items, mergeItem) + child.items = append(child.items, mergeChild.items...) + child.children = append(child.children, mergeChild.children...) + n.cow.freeNode(mergeChild) + } + return n.remove(item, minItems, typ) +} + +type direction int + +const ( + descend = direction(-1) + ascend = direction(+1) +) + +// iterate provides a simple method for iterating over elements in the tree. +// +// When ascending, the 'start' should be less than 'stop' and when descending, +// the 'start' should be greater than 'stop'. Setting 'includeStart' to true +// will force the iterator to include the first item when it equals 'start', +// thus creating a "greaterOrEqual" or "lessThanEqual" rather than just a +// "greaterThan" or "lessThan" queries. +func (n *node) iterate(dir direction, start, stop Item, includeStart bool, hit bool, iter ItemIterator) (bool, bool) { + var ok, found bool + var index int + switch dir { + case ascend: + if start != nil { + index, _ = n.items.find(start) + } + for i := index; i < len(n.items); i++ { + if len(n.children) > 0 { + if hit, ok = n.children[i].iterate(dir, start, stop, includeStart, hit, iter); !ok { + return hit, false + } + } + if !includeStart && !hit && start != nil && !start.Less(n.items[i]) { + hit = true + continue + } + hit = true + if stop != nil && !n.items[i].Less(stop) { + return hit, false + } + if !iter(n.items[i]) { + return hit, false + } + } + if len(n.children) > 0 { + if hit, ok = n.children[len(n.children)-1].iterate(dir, start, stop, includeStart, hit, iter); !ok { + return hit, false + } + } + case descend: + if start != nil { + index, found = n.items.find(start) + if !found { + index = index - 1 + } + } else { + index = len(n.items) - 1 + } + for i := index; i >= 0; i-- { + if start != nil && !n.items[i].Less(start) { + if !includeStart || hit || start.Less(n.items[i]) { + continue + } + } + if len(n.children) > 0 { + if hit, ok = n.children[i+1].iterate(dir, start, stop, includeStart, hit, iter); !ok { + return hit, false + } + } + if stop != nil && !stop.Less(n.items[i]) { + return hit, false // continue + } + hit = true + if !iter(n.items[i]) { + return hit, false + } + } + if len(n.children) > 0 { + if hit, ok = n.children[0].iterate(dir, start, stop, includeStart, hit, iter); !ok { + return hit, false + } + } + } + return hit, true +} + +// Used for testing/debugging purposes. +func (n *node) print(w io.Writer, level int) { + fmt.Fprintf(w, "%sNODE:%v\n", strings.Repeat(" ", level), n.items) + for _, c := range n.children { + c.print(w, level+1) + } +} + +// BTree is an implementation of a B-Tree. +// +// BTree stores Item instances in an ordered structure, allowing easy insertion, +// removal, and iteration. +// +// Write operations are not safe for concurrent mutation by multiple +// goroutines, but Read operations are. +type BTree struct { + degree int + length int + root *node + cow *copyOnWriteContext +} + +// copyOnWriteContext pointers determine node ownership... a tree with a write +// context equivalent to a node's write context is allowed to modify that node. +// A tree whose write context does not match a node's is not allowed to modify +// it, and must create a new, writable copy (IE: it's a Clone). +// +// When doing any write operation, we maintain the invariant that the current +// node's context is equal to the context of the tree that requested the write. +// We do this by, before we descend into any node, creating a copy with the +// correct context if the contexts don't match. +// +// Since the node we're currently visiting on any write has the requesting +// tree's context, that node is modifiable in place. Children of that node may +// not share context, but before we descend into them, we'll make a mutable +// copy. +type copyOnWriteContext struct { + freelist *FreeList +} + +// Clone clones the btree, lazily. Clone should not be called concurrently, +// but the original tree (t) and the new tree (t2) can be used concurrently +// once the Clone call completes. +// +// The internal tree structure of b is marked read-only and shared between t and +// t2. Writes to both t and t2 use copy-on-write logic, creating new nodes +// whenever one of b's original nodes would have been modified. Read operations +// should have no performance degredation. Write operations for both t and t2 +// will initially experience minor slow-downs caused by additional allocs and +// copies due to the aforementioned copy-on-write logic, but should converge to +// the original performance characteristics of the original tree. +func (t *BTree) Clone() (t2 *BTree) { + // Create two entirely new copy-on-write contexts. + // This operation effectively creates three trees: + // the original, shared nodes (old b.cow) + // the new b.cow nodes + // the new out.cow nodes + cow1, cow2 := *t.cow, *t.cow + out := *t + t.cow = &cow1 + out.cow = &cow2 + return &out +} + +// maxItems returns the max number of items to allow per node. +func (t *BTree) maxItems() int { + return t.degree*2 - 1 +} + +// minItems returns the min number of items to allow per node (ignored for the +// root node). +func (t *BTree) minItems() int { + return t.degree - 1 +} + +func (c *copyOnWriteContext) newNode() (n *node) { + n = c.freelist.newNode() + n.cow = c + return +} + +type freeType int + +const ( + ftFreelistFull freeType = iota // node was freed (available for GC, not stored in freelist) + ftStored // node was stored in the freelist for later use + ftNotOwned // node was ignored by COW, since it's owned by another one +) + +// freeNode frees a node within a given COW context, if it's owned by that +// context. It returns what happened to the node (see freeType const +// documentation). +func (c *copyOnWriteContext) freeNode(n *node) freeType { + if n.cow == c { + // clear to allow GC + n.items.truncate(0) + n.children.truncate(0) + n.cow = nil + if c.freelist.freeNode(n) { + return ftStored + } else { + return ftFreelistFull + } + } else { + return ftNotOwned + } +} + +// ReplaceOrInsert adds the given item to the tree. If an item in the tree +// already equals the given one, it is removed from the tree and returned. +// Otherwise, nil is returned. +// +// nil cannot be added to the tree (will panic). +func (t *BTree) ReplaceOrInsert(item Item) Item { + if item == nil { + panic("nil item being added to BTree") + } + if t.root == nil { + t.root = t.cow.newNode() + t.root.items = append(t.root.items, item) + t.length++ + return nil + } else { + t.root = t.root.mutableFor(t.cow) + if len(t.root.items) >= t.maxItems() { + item2, second := t.root.split(t.maxItems() / 2) + oldroot := t.root + t.root = t.cow.newNode() + t.root.items = append(t.root.items, item2) + t.root.children = append(t.root.children, oldroot, second) + } + } + out := t.root.insert(item, t.maxItems()) + if out == nil { + t.length++ + } + return out +} + +// Delete removes an item equal to the passed in item from the tree, returning +// it. If no such item exists, returns nil. +func (t *BTree) Delete(item Item) Item { + return t.deleteItem(item, removeItem) +} + +// DeleteMin removes the smallest item in the tree and returns it. +// If no such item exists, returns nil. +func (t *BTree) DeleteMin() Item { + return t.deleteItem(nil, removeMin) +} + +// DeleteMax removes the largest item in the tree and returns it. +// If no such item exists, returns nil. +func (t *BTree) DeleteMax() Item { + return t.deleteItem(nil, removeMax) +} + +func (t *BTree) deleteItem(item Item, typ toRemove) Item { + if t.root == nil || len(t.root.items) == 0 { + return nil + } + t.root = t.root.mutableFor(t.cow) + out := t.root.remove(item, t.minItems(), typ) + if len(t.root.items) == 0 && len(t.root.children) > 0 { + oldroot := t.root + t.root = t.root.children[0] + t.cow.freeNode(oldroot) + } + if out != nil { + t.length-- + } + return out +} + +// AscendRange calls the iterator for every value in the tree within the range +// [greaterOrEqual, lessThan), until iterator returns false. +func (t *BTree) AscendRange(greaterOrEqual, lessThan Item, iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(ascend, greaterOrEqual, lessThan, true, false, iterator) +} + +// AscendLessThan calls the iterator for every value in the tree within the range +// [first, pivot), until iterator returns false. +func (t *BTree) AscendLessThan(pivot Item, iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(ascend, nil, pivot, false, false, iterator) +} + +// AscendGreaterOrEqual calls the iterator for every value in the tree within +// the range [pivot, last], until iterator returns false. +func (t *BTree) AscendGreaterOrEqual(pivot Item, iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(ascend, pivot, nil, true, false, iterator) +} + +// Ascend calls the iterator for every value in the tree within the range +// [first, last], until iterator returns false. +func (t *BTree) Ascend(iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(ascend, nil, nil, false, false, iterator) +} + +// DescendRange calls the iterator for every value in the tree within the range +// [lessOrEqual, greaterThan), until iterator returns false. +func (t *BTree) DescendRange(lessOrEqual, greaterThan Item, iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(descend, lessOrEqual, greaterThan, true, false, iterator) +} + +// DescendLessOrEqual calls the iterator for every value in the tree within the range +// [pivot, first], until iterator returns false. +func (t *BTree) DescendLessOrEqual(pivot Item, iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(descend, pivot, nil, true, false, iterator) +} + +// DescendGreaterThan calls the iterator for every value in the tree within +// the range (pivot, last], until iterator returns false. +func (t *BTree) DescendGreaterThan(pivot Item, iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(descend, nil, pivot, false, false, iterator) +} + +// Descend calls the iterator for every value in the tree within the range +// [last, first], until iterator returns false. +func (t *BTree) Descend(iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(descend, nil, nil, false, false, iterator) +} + +// Get looks for the key item in the tree, returning it. It returns nil if +// unable to find that item. +func (t *BTree) Get(key Item) Item { + if t.root == nil { + return nil + } + return t.root.get(key) +} + +// Min returns the smallest item in the tree, or nil if the tree is empty. +func (t *BTree) Min() Item { + return min(t.root) +} + +// Max returns the largest item in the tree, or nil if the tree is empty. +func (t *BTree) Max() Item { + return max(t.root) +} + +// Has returns true if the given key is in the tree. +func (t *BTree) Has(key Item) bool { + return t.Get(key) != nil +} + +// Len returns the number of items currently in the tree. +func (t *BTree) Len() int { + return t.length +} + +// Clear removes all items from the btree. If addNodesToFreelist is true, +// t's nodes are added to its freelist as part of this call, until the freelist +// is full. Otherwise, the root node is simply dereferenced and the subtree +// left to Go's normal GC processes. +// +// This can be much faster +// than calling Delete on all elements, because that requires finding/removing +// each element in the tree and updating the tree accordingly. It also is +// somewhat faster than creating a new tree to replace the old one, because +// nodes from the old tree are reclaimed into the freelist for use by the new +// one, instead of being lost to the garbage collector. +// +// This call takes: +// O(1): when addNodesToFreelist is false, this is a single operation. +// O(1): when the freelist is already full, it breaks out immediately +// O(freelist size): when the freelist is empty and the nodes are all owned +// by this tree, nodes are added to the freelist until full. +// O(tree size): when all nodes are owned by another tree, all nodes are +// iterated over looking for nodes to add to the freelist, and due to +// ownership, none are. +func (t *BTree) Clear(addNodesToFreelist bool) { + if t.root != nil && addNodesToFreelist { + t.root.reset(t.cow) + } + t.root, t.length = nil, 0 +} + +// reset returns a subtree to the freelist. It breaks out immediately if the +// freelist is full, since the only benefit of iterating is to fill that +// freelist up. Returns true if parent reset call should continue. +func (n *node) reset(c *copyOnWriteContext) bool { + for _, child := range n.children { + if !child.reset(c) { + return false + } + } + return c.freeNode(n) != ftFreelistFull +} + +// Int implements the Item interface for integers. +type Int int + +// Less returns true if int(a) < int(b). +func (a Int) Less(b Item) bool { + return a < b.(Int) +} diff --git a/vendor/github.com/google/btree/btree_mem.go b/vendor/github.com/google/btree/btree_mem.go new file mode 100644 index 000000000..cb95b7fa1 --- /dev/null +++ b/vendor/github.com/google/btree/btree_mem.go @@ -0,0 +1,76 @@ +// Copyright 2014 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build ignore + +// This binary compares memory usage between btree and gollrb. +package main + +import ( + "flag" + "fmt" + "math/rand" + "runtime" + "time" + + "github.com/google/btree" + "github.com/petar/GoLLRB/llrb" +) + +var ( + size = flag.Int("size", 1000000, "size of the tree to build") + degree = flag.Int("degree", 8, "degree of btree") + gollrb = flag.Bool("llrb", false, "use llrb instead of btree") +) + +func main() { + flag.Parse() + vals := rand.Perm(*size) + var t, v interface{} + v = vals + var stats runtime.MemStats + for i := 0; i < 10; i++ { + runtime.GC() + } + fmt.Println("-------- BEFORE ----------") + runtime.ReadMemStats(&stats) + fmt.Printf("%+v\n", stats) + start := time.Now() + if *gollrb { + tr := llrb.New() + for _, v := range vals { + tr.ReplaceOrInsert(llrb.Int(v)) + } + t = tr // keep it around + } else { + tr := btree.New(*degree) + for _, v := range vals { + tr.ReplaceOrInsert(btree.Int(v)) + } + t = tr // keep it around + } + fmt.Printf("%v inserts in %v\n", *size, time.Since(start)) + fmt.Println("-------- AFTER ----------") + runtime.ReadMemStats(&stats) + fmt.Printf("%+v\n", stats) + for i := 0; i < 10; i++ { + runtime.GC() + } + fmt.Println("-------- AFTER GC ----------") + runtime.ReadMemStats(&stats) + fmt.Printf("%+v\n", stats) + if t == v { + fmt.Println("to make sure vals and tree aren't GC'd") + } +} diff --git a/vendor/github.com/hashicorp/errwrap/README.md b/vendor/github.com/hashicorp/errwrap/README.md index 1c95f5978..444df08f8 100644 --- a/vendor/github.com/hashicorp/errwrap/README.md +++ b/vendor/github.com/hashicorp/errwrap/README.md @@ -48,7 +48,7 @@ func main() { // We can use the Contains helpers to check if an error contains // another error. It is safe to do this with a nil error, or with // an error that doesn't even use the errwrap package. - if errwrap.Contains(err, ErrNotExist) { + if errwrap.Contains(err, "does not exist") { // Do something } if errwrap.ContainsType(err, new(os.PathError)) { diff --git a/vendor/github.com/hashicorp/errwrap/errwrap_test.go b/vendor/github.com/hashicorp/errwrap/errwrap_test.go deleted file mode 100644 index 5ae5f8e3c..000000000 --- a/vendor/github.com/hashicorp/errwrap/errwrap_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package errwrap - -import ( - "fmt" - "testing" -) - -func TestWrappedError_impl(t *testing.T) { - var _ error = new(wrappedError) -} - -func TestGetAll(t *testing.T) { - cases := []struct { - Err error - Msg string - Len int - }{ - {}, - { - fmt.Errorf("foo"), - "foo", - 1, - }, - { - fmt.Errorf("bar"), - "foo", - 0, - }, - { - Wrapf("bar", fmt.Errorf("foo")), - "foo", - 1, - }, - { - Wrapf("{{err}}", fmt.Errorf("foo")), - "foo", - 2, - }, - { - Wrapf("bar", Wrapf("baz", fmt.Errorf("foo"))), - "foo", - 1, - }, - } - - for i, tc := range cases { - actual := GetAll(tc.Err, tc.Msg) - if len(actual) != tc.Len { - t.Fatalf("%d: bad: %#v", i, actual) - } - for _, v := range actual { - if v.Error() != tc.Msg { - t.Fatalf("%d: bad: %#v", i, actual) - } - } - } -} - -func TestGetAllType(t *testing.T) { - cases := []struct { - Err error - Type interface{} - Len int - }{ - {}, - { - fmt.Errorf("foo"), - "foo", - 0, - }, - { - fmt.Errorf("bar"), - fmt.Errorf("foo"), - 1, - }, - { - Wrapf("bar", fmt.Errorf("foo")), - fmt.Errorf("baz"), - 2, - }, - { - Wrapf("bar", Wrapf("baz", fmt.Errorf("foo"))), - Wrapf("", nil), - 0, - }, - } - - for i, tc := range cases { - actual := GetAllType(tc.Err, tc.Type) - if len(actual) != tc.Len { - t.Fatalf("%d: bad: %#v", i, actual) - } - } -} diff --git a/vendor/github.com/hashicorp/errwrap/go.mod b/vendor/github.com/hashicorp/errwrap/go.mod new file mode 100644 index 000000000..c9b84022c --- /dev/null +++ b/vendor/github.com/hashicorp/errwrap/go.mod @@ -0,0 +1 @@ +module github.com/hashicorp/errwrap diff --git a/vendor/github.com/hashicorp/go-immutable-radix/iradix_test.go b/vendor/github.com/hashicorp/go-immutable-radix/iradix_test.go deleted file mode 100644 index 326299de8..000000000 --- a/vendor/github.com/hashicorp/go-immutable-radix/iradix_test.go +++ /dev/null @@ -1,1531 +0,0 @@ -package iradix - -import ( - "fmt" - "reflect" - "sort" - "testing" - - "github.com/hashicorp/go-uuid" -) - -func CopyTree(t *Tree) *Tree { - nt := &Tree{ - root: CopyNode(t.root), - size: t.size, - } - return nt -} - -func CopyNode(n *Node) *Node { - nn := &Node{} - if n.mutateCh != nil { - nn.mutateCh = n.mutateCh - } - if n.prefix != nil { - nn.prefix = make([]byte, len(n.prefix)) - copy(nn.prefix, n.prefix) - } - if n.leaf != nil { - nn.leaf = CopyLeaf(n.leaf) - } - if len(n.edges) != 0 { - nn.edges = make([]edge, len(n.edges)) - for idx, edge := range n.edges { - nn.edges[idx].label = edge.label - nn.edges[idx].node = CopyNode(edge.node) - } - } - return nn -} - -func CopyLeaf(l *leafNode) *leafNode { - ll := &leafNode{ - mutateCh: l.mutateCh, - key: l.key, - val: l.val, - } - return ll -} - -func TestRadix_HugeTxn(t *testing.T) { - r := New() - - // Insert way more nodes than the cache can fit - txn1 := r.Txn() - var expect []string - for i := 0; i < defaultModifiedCache*100; i++ { - gen, err := uuid.GenerateUUID() - if err != nil { - t.Fatalf("err: %v", err) - } - txn1.Insert([]byte(gen), i) - expect = append(expect, gen) - } - r = txn1.Commit() - sort.Strings(expect) - - // Collect the output, should be sorted - var out []string - fn := func(k []byte, v interface{}) bool { - out = append(out, string(k)) - return false - } - r.Root().Walk(fn) - - // Verify the match - if len(out) != len(expect) { - t.Fatalf("length mis-match: %d vs %d", len(out), len(expect)) - } - for i := 0; i < len(out); i++ { - if out[i] != expect[i] { - t.Fatalf("mis-match: %v %v", out[i], expect[i]) - } - } -} - -func TestRadix(t *testing.T) { - var min, max string - inp := make(map[string]interface{}) - for i := 0; i < 1000; i++ { - gen, err := uuid.GenerateUUID() - if err != nil { - t.Fatalf("err: %v", err) - } - inp[gen] = i - if gen < min || i == 0 { - min = gen - } - if gen > max || i == 0 { - max = gen - } - } - - r := New() - rCopy := CopyTree(r) - for k, v := range inp { - newR, _, _ := r.Insert([]byte(k), v) - if !reflect.DeepEqual(r, rCopy) { - t.Errorf("r: %#v rc: %#v", r, rCopy) - t.Errorf("r: %#v rc: %#v", r.root, rCopy.root) - t.Fatalf("structure modified %d", newR.Len()) - } - r = newR - rCopy = CopyTree(r) - } - - if r.Len() != len(inp) { - t.Fatalf("bad length: %v %v", r.Len(), len(inp)) - } - - for k, v := range inp { - out, ok := r.Get([]byte(k)) - if !ok { - t.Fatalf("missing key: %v", k) - } - if out != v { - t.Fatalf("value mis-match: %v %v", out, v) - } - } - - // Check min and max - outMin, _, _ := r.Root().Minimum() - if string(outMin) != min { - t.Fatalf("bad minimum: %v %v", outMin, min) - } - outMax, _, _ := r.Root().Maximum() - if string(outMax) != max { - t.Fatalf("bad maximum: %v %v", outMax, max) - } - - // Copy the full tree before delete - orig := r - origCopy := CopyTree(r) - - for k, v := range inp { - tree, out, ok := r.Delete([]byte(k)) - r = tree - if !ok { - t.Fatalf("missing key: %v", k) - } - if out != v { - t.Fatalf("value mis-match: %v %v", out, v) - } - } - if r.Len() != 0 { - t.Fatalf("bad length: %v", r.Len()) - } - - if !reflect.DeepEqual(orig, origCopy) { - t.Fatalf("structure modified") - } -} - -func TestRoot(t *testing.T) { - r := New() - r, _, ok := r.Delete(nil) - if ok { - t.Fatalf("bad") - } - r, _, ok = r.Insert(nil, true) - if ok { - t.Fatalf("bad") - } - val, ok := r.Get(nil) - if !ok || val != true { - t.Fatalf("bad: %#v", val) - } - r, val, ok = r.Delete(nil) - if !ok || val != true { - t.Fatalf("bad: %v", val) - } -} - -func TestInsert_UpdateFeedback(t *testing.T) { - r := New() - txn1 := r.Txn() - - for i := 0; i < 10; i++ { - var old interface{} - var didUpdate bool - old, didUpdate = txn1.Insert([]byte("helloworld"), i) - if i == 0 { - if old != nil || didUpdate { - t.Fatalf("bad: %d %v %v", i, old, didUpdate) - } - } else { - if old == nil || old.(int) != i-1 || !didUpdate { - t.Fatalf("bad: %d %v %v", i, old, didUpdate) - } - } - } -} - -func TestDelete(t *testing.T) { - r := New() - s := []string{"", "A", "AB"} - - for _, ss := range s { - r, _, _ = r.Insert([]byte(ss), true) - } - var ok bool - for _, ss := range s { - r, _, ok = r.Delete([]byte(ss)) - if !ok { - t.Fatalf("bad %q", ss) - } - } -} - -func TestDeletePrefix(t *testing.T) { - - type exp struct { - desc string - treeNodes []string - prefix string - expectedOut []string - } - - //various test cases where DeletePrefix should succeed - cases := []exp{ - { - "prefix not a node in tree", - []string{ - "", - "test/test1", - "test/test2", - "test/test3", - "R", - "RA"}, - "test", - []string{ - "", - "R", - "RA", - }, - }, - { - "prefix matches a node in tree", - []string{ - "", - "test", - "test/test1", - "test/test2", - "test/test3", - "test/testAAA", - "R", - "RA", - }, - "test", - []string{ - "", - "R", - "RA", - }, - }, - { - "longer prefix, but prefix is not a node in tree", - []string{ - "", - "test/test1", - "test/test2", - "test/test3", - "test/testAAA", - "R", - "RA", - }, - "test/test", - []string{ - "", - "R", - "RA", - }, - }, - { - "prefix only matches one node", - []string{ - "", - "AB", - "ABC", - "AR", - "R", - "RA", - }, - "AR", - []string{ - "", - "AB", - "ABC", - "R", - "RA", - }, - }, - } - - for _, testCase := range cases { - t.Run(testCase.desc, func(t *testing.T) { - r := New() - for _, ss := range testCase.treeNodes { - r, _, _ = r.Insert([]byte(ss), true) - } - if got, want := r.Len(), len(testCase.treeNodes); got != want { - t.Fatalf("Unexpected tree length after insert, got %d want %d ", got, want) - } - r, ok := r.DeletePrefix([]byte(testCase.prefix)) - if !ok { - t.Fatalf("DeletePrefix should have returned true for tree %v, deleting prefix %v", testCase.treeNodes, testCase.prefix) - } - if got, want := r.Len(), len(testCase.expectedOut); got != want { - t.Fatalf("Bad tree length, got %d want %d tree %v, deleting prefix %v ", got, want, testCase.treeNodes, testCase.prefix) - } - - verifyTree(t, testCase.expectedOut, r) - //Delete a non-existant node - r, ok = r.DeletePrefix([]byte("CCCCC")) - if ok { - t.Fatalf("Expected DeletePrefix to return false ") - } - verifyTree(t, testCase.expectedOut, r) - }) - } -} - -func TestTrackMutate_DeletePrefix(t *testing.T) { - - r := New() - - keys := []string{ - "foo", - "foo/bar/baz", - "foo/baz/bar", - "foo/zip/zap", - "bazbaz", - "zipzap", - } - for _, k := range keys { - r, _, _ = r.Insert([]byte(k), nil) - } - if r.Len() != len(keys) { - t.Fatalf("bad len: %v %v", r.Len(), len(keys)) - } - - rootWatch, _, _ := r.Root().GetWatch(nil) - if rootWatch == nil { - t.Fatalf("Should have returned a watch") - } - - nodeWatch1, _, _ := r.Root().GetWatch([]byte("foo/bar/baz")) - if nodeWatch1 == nil { - t.Fatalf("Should have returned a watch") - } - - nodeWatch2, _, _ := r.Root().GetWatch([]byte("foo/baz/bar")) - if nodeWatch2 == nil { - t.Fatalf("Should have returned a watch") - } - - nodeWatch3, _, _ := r.Root().GetWatch([]byte("foo/zip/zap")) - if nodeWatch3 == nil { - t.Fatalf("Should have returned a watch") - } - - unknownNodeWatch, _, _ := r.Root().GetWatch([]byte("bazbaz")) - if unknownNodeWatch == nil { - t.Fatalf("Should have returned a watch") - } - - // Verify that deleting prefixes triggers the right set of watches - txn := r.Txn() - txn.TrackMutate(true) - ok := txn.DeletePrefix([]byte("foo")) - if !ok { - t.Fatalf("Expected delete prefix to return true") - } - if hasAnyClosedMutateCh(r) { - t.Fatalf("Transaction was not committed, no channel should have been closed") - } - - txn.Commit() - - // Verify that all the leaf nodes we set up watches for above get triggered from the delete prefix call - select { - case <-rootWatch: - default: - t.Fatalf("root watch was not triggered") - } - select { - case <-nodeWatch1: - default: - t.Fatalf("node watch was not triggered") - } - select { - case <-nodeWatch2: - default: - t.Fatalf("node watch was not triggered") - } - select { - case <-nodeWatch3: - default: - t.Fatalf("node watch was not triggered") - } - select { - case <-unknownNodeWatch: - t.Fatalf("Unrelated node watch was triggered during a prefix delete") - default: - } - -} - -func verifyTree(t *testing.T, expected []string, r *Tree) { - root := r.Root() - out := []string{} - fn := func(k []byte, v interface{}) bool { - out = append(out, string(k)) - return false - } - root.Walk(fn) - - if !reflect.DeepEqual(expected, out) { - t.Fatalf("Unexpected contents of tree after delete prefix: expected %v, but got %v", expected, out) - } -} - -func TestLongestPrefix(t *testing.T) { - r := New() - - keys := []string{ - "", - "foo", - "foobar", - "foobarbaz", - "foobarbazzip", - "foozip", - } - for _, k := range keys { - r, _, _ = r.Insert([]byte(k), nil) - } - if r.Len() != len(keys) { - t.Fatalf("bad len: %v %v", r.Len(), len(keys)) - } - - type exp struct { - inp string - out string - } - cases := []exp{ - {"a", ""}, - {"abc", ""}, - {"fo", ""}, - {"foo", "foo"}, - {"foob", "foo"}, - {"foobar", "foobar"}, - {"foobarba", "foobar"}, - {"foobarbaz", "foobarbaz"}, - {"foobarbazzi", "foobarbaz"}, - {"foobarbazzip", "foobarbazzip"}, - {"foozi", "foo"}, - {"foozip", "foozip"}, - {"foozipzap", "foozip"}, - } - root := r.Root() - for _, test := range cases { - m, _, ok := root.LongestPrefix([]byte(test.inp)) - if !ok { - t.Fatalf("no match: %v", test) - } - if string(m) != test.out { - t.Fatalf("mis-match: %v %v", m, test) - } - } -} - -func TestWalkPrefix(t *testing.T) { - r := New() - - keys := []string{ - "foobar", - "foo/bar/baz", - "foo/baz/bar", - "foo/zip/zap", - "zipzap", - } - for _, k := range keys { - r, _, _ = r.Insert([]byte(k), nil) - } - if r.Len() != len(keys) { - t.Fatalf("bad len: %v %v", r.Len(), len(keys)) - } - - type exp struct { - inp string - out []string - } - cases := []exp{ - exp{ - "f", - []string{"foobar", "foo/bar/baz", "foo/baz/bar", "foo/zip/zap"}, - }, - exp{ - "foo", - []string{"foobar", "foo/bar/baz", "foo/baz/bar", "foo/zip/zap"}, - }, - exp{ - "foob", - []string{"foobar"}, - }, - exp{ - "foo/", - []string{"foo/bar/baz", "foo/baz/bar", "foo/zip/zap"}, - }, - exp{ - "foo/b", - []string{"foo/bar/baz", "foo/baz/bar"}, - }, - exp{ - "foo/ba", - []string{"foo/bar/baz", "foo/baz/bar"}, - }, - exp{ - "foo/bar", - []string{"foo/bar/baz"}, - }, - exp{ - "foo/bar/baz", - []string{"foo/bar/baz"}, - }, - exp{ - "foo/bar/bazoo", - []string{}, - }, - exp{ - "z", - []string{"zipzap"}, - }, - } - - root := r.Root() - for _, test := range cases { - out := []string{} - fn := func(k []byte, v interface{}) bool { - out = append(out, string(k)) - return false - } - root.WalkPrefix([]byte(test.inp), fn) - sort.Strings(out) - sort.Strings(test.out) - if !reflect.DeepEqual(out, test.out) { - t.Fatalf("mis-match: %v %v", out, test.out) - } - } -} - -func TestWalkPath(t *testing.T) { - r := New() - - keys := []string{ - "foo", - "foo/bar", - "foo/bar/baz", - "foo/baz/bar", - "foo/zip/zap", - "zipzap", - } - for _, k := range keys { - r, _, _ = r.Insert([]byte(k), nil) - } - if r.Len() != len(keys) { - t.Fatalf("bad len: %v %v", r.Len(), len(keys)) - } - - type exp struct { - inp string - out []string - } - cases := []exp{ - exp{ - "f", - []string{}, - }, - exp{ - "foo", - []string{"foo"}, - }, - exp{ - "foo/", - []string{"foo"}, - }, - exp{ - "foo/ba", - []string{"foo"}, - }, - exp{ - "foo/bar", - []string{"foo", "foo/bar"}, - }, - exp{ - "foo/bar/baz", - []string{"foo", "foo/bar", "foo/bar/baz"}, - }, - exp{ - "foo/bar/bazoo", - []string{"foo", "foo/bar", "foo/bar/baz"}, - }, - exp{ - "z", - []string{}, - }, - } - - root := r.Root() - for _, test := range cases { - out := []string{} - fn := func(k []byte, v interface{}) bool { - out = append(out, string(k)) - return false - } - root.WalkPath([]byte(test.inp), fn) - sort.Strings(out) - sort.Strings(test.out) - if !reflect.DeepEqual(out, test.out) { - t.Fatalf("mis-match: %v %v", out, test.out) - } - } -} - -func TestIteratePrefix(t *testing.T) { - r := New() - - keys := []string{ - "foo/bar/baz", - "foo/baz/bar", - "foo/zip/zap", - "foobar", - "zipzap", - } - for _, k := range keys { - r, _, _ = r.Insert([]byte(k), nil) - } - if r.Len() != len(keys) { - t.Fatalf("bad len: %v %v", r.Len(), len(keys)) - } - - type exp struct { - inp string - out []string - } - cases := []exp{ - exp{ - "", - keys, - }, - exp{ - "f", - []string{ - "foo/bar/baz", - "foo/baz/bar", - "foo/zip/zap", - "foobar", - }, - }, - exp{ - "foo", - []string{ - "foo/bar/baz", - "foo/baz/bar", - "foo/zip/zap", - "foobar", - }, - }, - exp{ - "foob", - []string{"foobar"}, - }, - exp{ - "foo/", - []string{"foo/bar/baz", "foo/baz/bar", "foo/zip/zap"}, - }, - exp{ - "foo/b", - []string{"foo/bar/baz", "foo/baz/bar"}, - }, - exp{ - "foo/ba", - []string{"foo/bar/baz", "foo/baz/bar"}, - }, - exp{ - "foo/bar", - []string{"foo/bar/baz"}, - }, - exp{ - "foo/bar/baz", - []string{"foo/bar/baz"}, - }, - exp{ - "foo/bar/bazoo", - []string{}, - }, - exp{ - "z", - []string{"zipzap"}, - }, - } - - root := r.Root() - for idx, test := range cases { - iter := root.Iterator() - if test.inp != "" { - iter.SeekPrefix([]byte(test.inp)) - } - - // Consume all the keys - out := []string{} - for { - key, _, ok := iter.Next() - if !ok { - break - } - out = append(out, string(key)) - } - if !reflect.DeepEqual(out, test.out) { - t.Fatalf("mis-match: %d %v %v", idx, out, test.out) - } - } -} - -func TestMergeChildNilEdges(t *testing.T) { - r := New() - r, _, _ = r.Insert([]byte("foobar"), 42) - r, _, _ = r.Insert([]byte("foozip"), 43) - r, _, _ = r.Delete([]byte("foobar")) - - root := r.Root() - out := []string{} - fn := func(k []byte, v interface{}) bool { - out = append(out, string(k)) - return false - } - root.Walk(fn) - - expect := []string{"foozip"} - sort.Strings(out) - sort.Strings(expect) - if !reflect.DeepEqual(out, expect) { - t.Fatalf("mis-match: %v %v", out, expect) - } -} - -func TestMergeChildVisibility(t *testing.T) { - r := New() - r, _, _ = r.Insert([]byte("foobar"), 42) - r, _, _ = r.Insert([]byte("foobaz"), 43) - r, _, _ = r.Insert([]byte("foozip"), 10) - - txn1 := r.Txn() - txn2 := r.Txn() - - // Ensure we get the expected value foobar and foobaz - if val, ok := txn1.Get([]byte("foobar")); !ok || val != 42 { - t.Fatalf("bad: %v", val) - } - if val, ok := txn1.Get([]byte("foobaz")); !ok || val != 43 { - t.Fatalf("bad: %v", val) - } - if val, ok := txn2.Get([]byte("foobar")); !ok || val != 42 { - t.Fatalf("bad: %v", val) - } - if val, ok := txn2.Get([]byte("foobaz")); !ok || val != 43 { - t.Fatalf("bad: %v", val) - } - - // Delete of foozip will cause a merge child between the - // "foo" and "ba" nodes. - if val, ok := txn2.Delete([]byte("foozip")); !ok || val != 10 { - t.Fatalf("bad: %v", val) - } - - // Insert of "foobaz" will update the slice of the "fooba" node - // in-place to point to the new "foobaz" node. This in-place update - // will cause the visibility of the update to leak into txn1 (prior - // to the fix). - if val, ok := txn2.Insert([]byte("foobaz"), 44); !ok || val != 43 { - t.Fatalf("bad: %v", val) - } - - // Ensure we get the expected value foobar and foobaz - if val, ok := txn1.Get([]byte("foobar")); !ok || val != 42 { - t.Fatalf("bad: %v", val) - } - if val, ok := txn1.Get([]byte("foobaz")); !ok || val != 43 { - t.Fatalf("bad: %v", val) - } - if val, ok := txn2.Get([]byte("foobar")); !ok || val != 42 { - t.Fatalf("bad: %v", val) - } - if val, ok := txn2.Get([]byte("foobaz")); !ok || val != 44 { - t.Fatalf("bad: %v", val) - } - - // Commit txn2 - r = txn2.Commit() - - // Ensure we get the expected value foobar and foobaz - if val, ok := txn1.Get([]byte("foobar")); !ok || val != 42 { - t.Fatalf("bad: %v", val) - } - if val, ok := txn1.Get([]byte("foobaz")); !ok || val != 43 { - t.Fatalf("bad: %v", val) - } - if val, ok := r.Get([]byte("foobar")); !ok || val != 42 { - t.Fatalf("bad: %v", val) - } - if val, ok := r.Get([]byte("foobaz")); !ok || val != 44 { - t.Fatalf("bad: %v", val) - } -} - -// isClosed returns true if the given channel is closed. -func isClosed(ch chan struct{}) bool { - select { - case <-ch: - return true - default: - return false - } -} - -// hasAnyClosedMutateCh scans the given tree and returns true if there are any -// closed mutate channels on any nodes or leaves. -func hasAnyClosedMutateCh(r *Tree) bool { - for iter := r.root.rawIterator(); iter.Front() != nil; iter.Next() { - n := iter.Front() - if isClosed(n.mutateCh) { - return true - } - if n.isLeaf() && isClosed(n.leaf.mutateCh) { - return true - } - } - return false -} - -func TestTrackMutate_SeekPrefixWatch(t *testing.T) { - for i := 0; i < 3; i++ { - r := New() - - keys := []string{ - "foo/bar/baz", - "foo/baz/bar", - "foo/zip/zap", - "foobar", - "zipzap", - } - for _, k := range keys { - r, _, _ = r.Insert([]byte(k), nil) - } - if r.Len() != len(keys) { - t.Fatalf("bad len: %v %v", r.Len(), len(keys)) - } - - iter := r.Root().Iterator() - rootWatch := iter.SeekPrefixWatch([]byte("nope")) - - iter = r.Root().Iterator() - parentWatch := iter.SeekPrefixWatch([]byte("foo")) - - iter = r.Root().Iterator() - leafWatch := iter.SeekPrefixWatch([]byte("foobar")) - - iter = r.Root().Iterator() - missingWatch := iter.SeekPrefixWatch([]byte("foobarbaz")) - - iter = r.Root().Iterator() - otherWatch := iter.SeekPrefixWatch([]byte("foo/b")) - - // Write to a sub-child should trigger the leaf! - txn := r.Txn() - txn.TrackMutate(true) - txn.Insert([]byte("foobarbaz"), nil) - switch i { - case 0: - r = txn.Commit() - case 1: - r = txn.CommitOnly() - txn.Notify() - default: - r = txn.CommitOnly() - txn.slowNotify() - } - if hasAnyClosedMutateCh(r) { - t.Fatalf("bad") - } - - // Verify root and parent triggered, and leaf affected - select { - case <-rootWatch: - default: - t.Fatalf("bad") - } - select { - case <-parentWatch: - default: - t.Fatalf("bad") - } - select { - case <-leafWatch: - default: - t.Fatalf("bad") - } - select { - case <-missingWatch: - default: - t.Fatalf("bad") - } - select { - case <-otherWatch: - t.Fatalf("bad") - default: - } - - iter = r.Root().Iterator() - rootWatch = iter.SeekPrefixWatch([]byte("nope")) - - iter = r.Root().Iterator() - parentWatch = iter.SeekPrefixWatch([]byte("foo")) - - iter = r.Root().Iterator() - leafWatch = iter.SeekPrefixWatch([]byte("foobar")) - - iter = r.Root().Iterator() - missingWatch = iter.SeekPrefixWatch([]byte("foobarbaz")) - - // Delete to a sub-child should trigger the leaf! - txn = r.Txn() - txn.TrackMutate(true) - txn.Delete([]byte("foobarbaz")) - switch i { - case 0: - r = txn.Commit() - case 1: - r = txn.CommitOnly() - txn.Notify() - default: - r = txn.CommitOnly() - txn.slowNotify() - } - if hasAnyClosedMutateCh(r) { - t.Fatalf("bad") - } - - // Verify root and parent triggered, and leaf affected - select { - case <-rootWatch: - default: - t.Fatalf("bad") - } - select { - case <-parentWatch: - default: - t.Fatalf("bad") - } - select { - case <-leafWatch: - default: - t.Fatalf("bad") - } - select { - case <-missingWatch: - default: - t.Fatalf("bad") - } - select { - case <-otherWatch: - t.Fatalf("bad") - default: - } - } -} - -func TestTrackMutate_GetWatch(t *testing.T) { - for i := 0; i < 3; i++ { - r := New() - - keys := []string{ - "foo/bar/baz", - "foo/baz/bar", - "foo/zip/zap", - "foobar", - "zipzap", - } - for _, k := range keys { - r, _, _ = r.Insert([]byte(k), nil) - } - if r.Len() != len(keys) { - t.Fatalf("bad len: %v %v", r.Len(), len(keys)) - } - - rootWatch, _, ok := r.Root().GetWatch(nil) - if rootWatch == nil { - t.Fatalf("bad") - } - - parentWatch, _, ok := r.Root().GetWatch([]byte("foo")) - if parentWatch == nil { - t.Fatalf("bad") - } - - leafWatch, _, ok := r.Root().GetWatch([]byte("foobar")) - if !ok { - t.Fatalf("should be found") - } - if leafWatch == nil { - t.Fatalf("bad") - } - - otherWatch, _, ok := r.Root().GetWatch([]byte("foo/b")) - if otherWatch == nil { - t.Fatalf("bad") - } - - // Write to a sub-child should not trigger the leaf! - txn := r.Txn() - txn.TrackMutate(true) - txn.Insert([]byte("foobarbaz"), nil) - switch i { - case 0: - r = txn.Commit() - case 1: - r = txn.CommitOnly() - txn.Notify() - default: - r = txn.CommitOnly() - txn.slowNotify() - } - if hasAnyClosedMutateCh(r) { - t.Fatalf("bad") - } - - // Verify root and parent triggered, not leaf affected - select { - case <-rootWatch: - default: - t.Fatalf("bad") - } - select { - case <-parentWatch: - default: - t.Fatalf("bad") - } - select { - case <-leafWatch: - t.Fatalf("bad") - default: - } - select { - case <-otherWatch: - t.Fatalf("bad") - default: - } - - // Setup new watchers - rootWatch, _, ok = r.Root().GetWatch(nil) - if rootWatch == nil { - t.Fatalf("bad") - } - - parentWatch, _, ok = r.Root().GetWatch([]byte("foo")) - if parentWatch == nil { - t.Fatalf("bad") - } - - // Write to a exactly leaf should trigger the leaf! - txn = r.Txn() - txn.TrackMutate(true) - txn.Insert([]byte("foobar"), nil) - switch i { - case 0: - r = txn.Commit() - case 1: - r = txn.CommitOnly() - txn.Notify() - default: - r = txn.CommitOnly() - txn.slowNotify() - } - if hasAnyClosedMutateCh(r) { - t.Fatalf("bad") - } - - select { - case <-rootWatch: - default: - t.Fatalf("bad") - } - select { - case <-parentWatch: - default: - t.Fatalf("bad") - } - select { - case <-leafWatch: - default: - t.Fatalf("bad") - } - select { - case <-otherWatch: - t.Fatalf("bad") - default: - } - - // Setup all the watchers again - rootWatch, _, ok = r.Root().GetWatch(nil) - if rootWatch == nil { - t.Fatalf("bad") - } - - parentWatch, _, ok = r.Root().GetWatch([]byte("foo")) - if parentWatch == nil { - t.Fatalf("bad") - } - - leafWatch, _, ok = r.Root().GetWatch([]byte("foobar")) - if !ok { - t.Fatalf("should be found") - } - if leafWatch == nil { - t.Fatalf("bad") - } - - // Delete to a sub-child should not trigger the leaf! - txn = r.Txn() - txn.TrackMutate(true) - txn.Delete([]byte("foobarbaz")) - switch i { - case 0: - r = txn.Commit() - case 1: - r = txn.CommitOnly() - txn.Notify() - default: - r = txn.CommitOnly() - txn.slowNotify() - } - if hasAnyClosedMutateCh(r) { - t.Fatalf("bad") - } - - // Verify root and parent triggered, not leaf affected - select { - case <-rootWatch: - default: - t.Fatalf("bad") - } - select { - case <-parentWatch: - default: - t.Fatalf("bad") - } - select { - case <-leafWatch: - t.Fatalf("bad") - default: - } - select { - case <-otherWatch: - t.Fatalf("bad") - default: - } - - // Setup new watchers - rootWatch, _, ok = r.Root().GetWatch(nil) - if rootWatch == nil { - t.Fatalf("bad") - } - - parentWatch, _, ok = r.Root().GetWatch([]byte("foo")) - if parentWatch == nil { - t.Fatalf("bad") - } - - // Write to a exactly leaf should trigger the leaf! - txn = r.Txn() - txn.TrackMutate(true) - txn.Delete([]byte("foobar")) - switch i { - case 0: - r = txn.Commit() - case 1: - r = txn.CommitOnly() - txn.Notify() - default: - r = txn.CommitOnly() - txn.slowNotify() - } - if hasAnyClosedMutateCh(r) { - t.Fatalf("bad") - } - - select { - case <-rootWatch: - default: - t.Fatalf("bad") - } - select { - case <-parentWatch: - default: - t.Fatalf("bad") - } - select { - case <-leafWatch: - default: - t.Fatalf("bad") - } - select { - case <-otherWatch: - t.Fatalf("bad") - default: - } - } -} - -func TestTrackMutate_HugeTxn(t *testing.T) { - r := New() - - keys := []string{ - "foo/bar/baz", - "foo/baz/bar", - "foo/zip/zap", - "foobar", - "nochange", - } - for i := 0; i < defaultModifiedCache; i++ { - key := fmt.Sprintf("aaa%d", i) - r, _, _ = r.Insert([]byte(key), nil) - } - for _, k := range keys { - r, _, _ = r.Insert([]byte(k), nil) - } - for i := 0; i < defaultModifiedCache; i++ { - key := fmt.Sprintf("zzz%d", i) - r, _, _ = r.Insert([]byte(key), nil) - } - if r.Len() != len(keys)+2*defaultModifiedCache { - t.Fatalf("bad len: %v %v", r.Len(), len(keys)) - } - - rootWatch, _, ok := r.Root().GetWatch(nil) - if rootWatch == nil { - t.Fatalf("bad") - } - - parentWatch, _, ok := r.Root().GetWatch([]byte("foo")) - if parentWatch == nil { - t.Fatalf("bad") - } - - leafWatch, _, ok := r.Root().GetWatch([]byte("foobar")) - if !ok { - t.Fatalf("should be found") - } - if leafWatch == nil { - t.Fatalf("bad") - } - - nopeWatch, _, ok := r.Root().GetWatch([]byte("nochange")) - if !ok { - t.Fatalf("should be found") - } - if nopeWatch == nil { - t.Fatalf("bad") - } - - beforeWatch, _, ok := r.Root().GetWatch([]byte("aaa123")) - if beforeWatch == nil { - t.Fatalf("bad") - } - - afterWatch, _, ok := r.Root().GetWatch([]byte("zzz123")) - if afterWatch == nil { - t.Fatalf("bad") - } - - // Start the transaction. - txn := r.Txn() - txn.TrackMutate(true) - - // Add new nodes on both sides of the tree and delete enough nodes to - // overflow the tracking. - txn.Insert([]byte("aaa"), nil) - for i := 0; i < defaultModifiedCache; i++ { - key := fmt.Sprintf("aaa%d", i) - txn.Delete([]byte(key)) - } - for i := 0; i < defaultModifiedCache; i++ { - key := fmt.Sprintf("zzz%d", i) - txn.Delete([]byte(key)) - } - txn.Insert([]byte("zzz"), nil) - - // Hit the leaf, and add a child so we make multiple mutations to the - // same node. - txn.Insert([]byte("foobar"), nil) - txn.Insert([]byte("foobarbaz"), nil) - - // Commit and make sure we overflowed but didn't take on extra stuff. - r = txn.CommitOnly() - if !txn.trackOverflow || txn.trackChannels != nil { - t.Fatalf("bad") - } - - // Now do the trigger. - txn.Notify() - - // Make sure no closed channels escaped the transaction. - if hasAnyClosedMutateCh(r) { - t.Fatalf("bad") - } - - // Verify the watches fired as expected. - select { - case <-rootWatch: - default: - t.Fatalf("bad") - } - select { - case <-parentWatch: - default: - t.Fatalf("bad") - } - select { - case <-leafWatch: - default: - t.Fatalf("bad") - } - select { - case <-nopeWatch: - t.Fatalf("bad") - default: - } - select { - case <-beforeWatch: - default: - t.Fatalf("bad") - } - select { - case <-afterWatch: - default: - t.Fatalf("bad") - } -} - -func TestTrackMutate_mergeChild(t *testing.T) { - // This case does a delete of the "acb" leaf, which causes the "aca" - // leaf to get merged with the old "ac" node: - // - // [root] [root] - // |a |a - // [node] [node] - // b/ \c b/ \c - // (ab) [node] (ab) (aca) - // a/ \b - // (aca) (acb) - // - for i := 0; i < 3; i++ { - r := New() - r, _, _ = r.Insert([]byte("ab"), nil) - r, _, _ = r.Insert([]byte("aca"), nil) - r, _, _ = r.Insert([]byte("acb"), nil) - snapIter := r.root.rawIterator() - - // Run through all notification methods as there were bugs in - // both that affected these operations. The slowNotify path - // would detect copied but otherwise identical leaves as changed - // and wrongly close channels. The normal path would fail to - // notify on a child node that had been merged. - txn := r.Txn() - txn.TrackMutate(true) - txn.Delete([]byte("acb")) - switch i { - case 0: - r = txn.Commit() - case 1: - r = txn.CommitOnly() - txn.Notify() - default: - r = txn.CommitOnly() - txn.slowNotify() - } - if hasAnyClosedMutateCh(r) { - t.Fatalf("bad") - } - - // Run through the old tree and make sure the exact channels we - // expected were closed. - for ; snapIter.Front() != nil; snapIter.Next() { - n := snapIter.Front() - path := snapIter.Path() - switch path { - case "", "a", "ac": // parent nodes all change - if !isClosed(n.mutateCh) || n.leaf != nil { - t.Fatalf("bad") - } - case "ab": // unrelated node / leaf sees no change - if isClosed(n.mutateCh) || isClosed(n.leaf.mutateCh) { - t.Fatalf("bad") - } - case "aca": // this node gets merged, but the leaf doesn't change - if !isClosed(n.mutateCh) || isClosed(n.leaf.mutateCh) { - t.Fatalf("bad") - } - case "acb": // this node / leaf gets deleted - if !isClosed(n.mutateCh) || !isClosed(n.leaf.mutateCh) { - t.Fatalf("bad") - } - default: - t.Fatalf("bad: %s", path) - } - } - } -} - -func TestTrackMutate_cachedNodeChange(t *testing.T) { - // This case does a delete of the "acb" leaf, which causes the "aca" - // leaf to get merged with the old "ac" node: - // - // [root] [root] - // |a |a - // [node] [node] - // b/ \c b/ \c - // (ab) [node] (ab) (aca*) <- this leaf gets modified - // a/ \b post-merge - // (aca) (acb) - // - // Then it makes a modification to the "aca" leaf on a node that will - // be in the cache, so this makes sure that the leaf watch fires. - for i := 0; i < 3; i++ { - r := New() - r, _, _ = r.Insert([]byte("ab"), nil) - r, _, _ = r.Insert([]byte("aca"), nil) - r, _, _ = r.Insert([]byte("acb"), nil) - snapIter := r.root.rawIterator() - - txn := r.Txn() - txn.TrackMutate(true) - txn.Delete([]byte("acb")) - txn.Insert([]byte("aca"), nil) - switch i { - case 0: - r = txn.Commit() - case 1: - r = txn.CommitOnly() - txn.Notify() - default: - r = txn.CommitOnly() - txn.slowNotify() - } - if hasAnyClosedMutateCh(r) { - t.Fatalf("bad") - } - - // Run through the old tree and make sure the exact channels we - // expected were closed. - for ; snapIter.Front() != nil; snapIter.Next() { - n := snapIter.Front() - path := snapIter.Path() - switch path { - case "", "a", "ac": // parent nodes all change - if !isClosed(n.mutateCh) || n.leaf != nil { - t.Fatalf("bad") - } - case "ab": // unrelated node / leaf sees no change - if isClosed(n.mutateCh) || isClosed(n.leaf.mutateCh) { - t.Fatalf("bad") - } - case "aca": // merge changes the node, then we update the leaf - if !isClosed(n.mutateCh) || !isClosed(n.leaf.mutateCh) { - t.Fatalf("bad") - } - case "acb": // this node / leaf gets deleted - if !isClosed(n.mutateCh) || !isClosed(n.leaf.mutateCh) { - t.Fatalf("bad") - } - default: - t.Fatalf("bad: %s", path) - } - } - } -} - -func TestLenTxn(t *testing.T) { - r := New() - - if r.Len() != 0 { - t.Fatalf("not starting with empty tree") - } - - txn := r.Txn() - keys := []string{ - "foo/bar/baz", - "foo/baz/bar", - "foo/zip/zap", - "foobar", - "nochange", - } - for _, k := range keys { - txn.Insert([]byte(k), nil) - } - r = txn.Commit() - - if r.Len() != len(keys) { - t.Fatalf("bad: expected %d, got %d", len(keys), r.Len()) - } - - txn = r.Txn() - for _, k := range keys { - txn.Delete([]byte(k)) - } - r = txn.Commit() - - if r.Len() != 0 { - t.Fatalf("tree len should be zero, got %d", r.Len()) - } -} diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/bench_test.go b/vendor/github.com/hashicorp/go-msgpack/codec/bench_test.go deleted file mode 100644 index 4d437035e..000000000 --- a/vendor/github.com/hashicorp/go-msgpack/codec/bench_test.go +++ /dev/null @@ -1,319 +0,0 @@ -// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved. -// Use of this source code is governed by a BSD-style license found in the LICENSE file. - -package codec - -import ( - "bytes" - "encoding/gob" - "encoding/json" - "flag" - "fmt" - "reflect" - "runtime" - "testing" - "time" -) - -// Sample way to run: -// go test -bi -bv -bd=1 -benchmem -bench=. - -var ( - _ = fmt.Printf - benchTs *TestStruc - - approxSize int - - benchDoInitBench bool - benchVerify bool - benchUnscientificRes bool = false - //depth of 0 maps to ~400bytes json-encoded string, 1 maps to ~1400 bytes, etc - //For depth>1, we likely trigger stack growth for encoders, making benchmarking unreliable. - benchDepth int - benchInitDebug bool - benchCheckers []benchChecker -) - -type benchEncFn func(interface{}) ([]byte, error) -type benchDecFn func([]byte, interface{}) error -type benchIntfFn func() interface{} - -type benchChecker struct { - name string - encodefn benchEncFn - decodefn benchDecFn -} - -func benchInitFlags() { - flag.BoolVar(&benchInitDebug, "bg", false, "Bench Debug") - flag.IntVar(&benchDepth, "bd", 1, "Bench Depth: If >1, potential unreliable results due to stack growth") - flag.BoolVar(&benchDoInitBench, "bi", false, "Run Bench Init") - flag.BoolVar(&benchVerify, "bv", false, "Verify Decoded Value during Benchmark") - flag.BoolVar(&benchUnscientificRes, "bu", false, "Show Unscientific Results during Benchmark") -} - -func benchInit() { - benchTs = newTestStruc(benchDepth, true) - approxSize = approxDataSize(reflect.ValueOf(benchTs)) - bytesLen := 1024 * 4 * (benchDepth + 1) * (benchDepth + 1) - if bytesLen < approxSize { - bytesLen = approxSize - } - - benchCheckers = append(benchCheckers, - benchChecker{"msgpack", fnMsgpackEncodeFn, fnMsgpackDecodeFn}, - benchChecker{"binc-nosym", fnBincNoSymEncodeFn, fnBincNoSymDecodeFn}, - benchChecker{"binc-sym", fnBincSymEncodeFn, fnBincSymDecodeFn}, - benchChecker{"simple", fnSimpleEncodeFn, fnSimpleDecodeFn}, - benchChecker{"gob", fnGobEncodeFn, fnGobDecodeFn}, - benchChecker{"json", fnJsonEncodeFn, fnJsonDecodeFn}, - ) - if benchDoInitBench { - runBenchInit() - } -} - -func runBenchInit() { - logT(nil, "..............................................") - logT(nil, "BENCHMARK INIT: %v", time.Now()) - logT(nil, "To run full benchmark comparing encodings (MsgPack, Binc, Simple, JSON, GOB, etc), "+ - "use: \"go test -bench=.\"") - logT(nil, "Benchmark: ") - logT(nil, "\tStruct recursive Depth: %d", benchDepth) - if approxSize > 0 { - logT(nil, "\tApproxDeepSize Of benchmark Struct: %d bytes", approxSize) - } - if benchUnscientificRes { - logT(nil, "Benchmark One-Pass Run (with Unscientific Encode/Decode times): ") - } else { - logT(nil, "Benchmark One-Pass Run:") - } - for _, bc := range benchCheckers { - doBenchCheck(bc.name, bc.encodefn, bc.decodefn) - } - logT(nil, "..............................................") - if benchInitDebug { - logT(nil, "<<<<====>>>> depth: %v, ts: %#v\n", benchDepth, benchTs) - } -} - -func fnBenchNewTs() interface{} { - return new(TestStruc) -} - -func doBenchCheck(name string, encfn benchEncFn, decfn benchDecFn) { - runtime.GC() - tnow := time.Now() - buf, err := encfn(benchTs) - if err != nil { - logT(nil, "\t%10s: **** Error encoding benchTs: %v", name, err) - } - encDur := time.Now().Sub(tnow) - encLen := len(buf) - runtime.GC() - if !benchUnscientificRes { - logT(nil, "\t%10s: len: %d bytes\n", name, encLen) - return - } - tnow = time.Now() - if err = decfn(buf, new(TestStruc)); err != nil { - logT(nil, "\t%10s: **** Error decoding into new TestStruc: %v", name, err) - } - decDur := time.Now().Sub(tnow) - logT(nil, "\t%10s: len: %d bytes, encode: %v, decode: %v\n", name, encLen, encDur, decDur) -} - -func fnBenchmarkEncode(b *testing.B, encName string, ts interface{}, encfn benchEncFn) { - runtime.GC() - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, err := encfn(ts) - if err != nil { - logT(b, "Error encoding benchTs: %s: %v", encName, err) - b.FailNow() - } - } -} - -func fnBenchmarkDecode(b *testing.B, encName string, ts interface{}, - encfn benchEncFn, decfn benchDecFn, newfn benchIntfFn, -) { - buf, err := encfn(ts) - if err != nil { - logT(b, "Error encoding benchTs: %s: %v", encName, err) - b.FailNow() - } - runtime.GC() - b.ResetTimer() - for i := 0; i < b.N; i++ { - ts = newfn() - if err = decfn(buf, ts); err != nil { - logT(b, "Error decoding into new TestStruc: %s: %v", encName, err) - b.FailNow() - } - if benchVerify { - if vts, vok := ts.(*TestStruc); vok { - verifyTsTree(b, vts) - } - } - } -} - -func verifyTsTree(b *testing.B, ts *TestStruc) { - var ts0, ts1m, ts2m, ts1s, ts2s *TestStruc - ts0 = ts - - if benchDepth > 0 { - ts1m, ts1s = verifyCheckAndGet(b, ts0) - } - - if benchDepth > 1 { - ts2m, ts2s = verifyCheckAndGet(b, ts1m) - } - for _, tsx := range []*TestStruc{ts0, ts1m, ts2m, ts1s, ts2s} { - if tsx != nil { - verifyOneOne(b, tsx) - } - } -} - -func verifyCheckAndGet(b *testing.B, ts0 *TestStruc) (ts1m *TestStruc, ts1s *TestStruc) { - // if len(ts1m.Ms) <= 2 { - // logT(b, "Error: ts1m.Ms len should be > 2. Got: %v", len(ts1m.Ms)) - // b.FailNow() - // } - if len(ts0.Its) == 0 { - logT(b, "Error: ts0.Islice len should be > 0. Got: %v", len(ts0.Its)) - b.FailNow() - } - ts1m = ts0.Mtsptr["0"] - ts1s = ts0.Its[0] - if ts1m == nil || ts1s == nil { - logT(b, "Error: At benchDepth 1, No *TestStruc found") - b.FailNow() - } - return -} - -func verifyOneOne(b *testing.B, ts *TestStruc) { - if ts.I64slice[2] != int64(3) { - logT(b, "Error: Decode failed by checking values") - b.FailNow() - } -} - -func fnMsgpackEncodeFn(ts interface{}) (bs []byte, err error) { - err = NewEncoderBytes(&bs, testMsgpackH).Encode(ts) - return -} - -func fnMsgpackDecodeFn(buf []byte, ts interface{}) error { - return NewDecoderBytes(buf, testMsgpackH).Decode(ts) -} - -func fnBincEncodeFn(ts interface{}, sym AsSymbolFlag) (bs []byte, err error) { - tSym := testBincH.AsSymbols - testBincH.AsSymbols = sym - err = NewEncoderBytes(&bs, testBincH).Encode(ts) - testBincH.AsSymbols = tSym - return -} - -func fnBincDecodeFn(buf []byte, ts interface{}, sym AsSymbolFlag) (err error) { - tSym := testBincH.AsSymbols - testBincH.AsSymbols = sym - err = NewDecoderBytes(buf, testBincH).Decode(ts) - testBincH.AsSymbols = tSym - return -} - -func fnBincNoSymEncodeFn(ts interface{}) (bs []byte, err error) { - return fnBincEncodeFn(ts, AsSymbolNone) -} - -func fnBincNoSymDecodeFn(buf []byte, ts interface{}) error { - return fnBincDecodeFn(buf, ts, AsSymbolNone) -} - -func fnBincSymEncodeFn(ts interface{}) (bs []byte, err error) { - return fnBincEncodeFn(ts, AsSymbolAll) -} - -func fnBincSymDecodeFn(buf []byte, ts interface{}) error { - return fnBincDecodeFn(buf, ts, AsSymbolAll) -} - -func fnSimpleEncodeFn(ts interface{}) (bs []byte, err error) { - err = NewEncoderBytes(&bs, testSimpleH).Encode(ts) - return -} - -func fnSimpleDecodeFn(buf []byte, ts interface{}) error { - return NewDecoderBytes(buf, testSimpleH).Decode(ts) -} - -func fnGobEncodeFn(ts interface{}) ([]byte, error) { - bbuf := new(bytes.Buffer) - err := gob.NewEncoder(bbuf).Encode(ts) - return bbuf.Bytes(), err -} - -func fnGobDecodeFn(buf []byte, ts interface{}) error { - return gob.NewDecoder(bytes.NewBuffer(buf)).Decode(ts) -} - -func fnJsonEncodeFn(ts interface{}) ([]byte, error) { - return json.Marshal(ts) -} - -func fnJsonDecodeFn(buf []byte, ts interface{}) error { - return json.Unmarshal(buf, ts) -} - -func Benchmark__Msgpack____Encode(b *testing.B) { - fnBenchmarkEncode(b, "msgpack", benchTs, fnMsgpackEncodeFn) -} - -func Benchmark__Msgpack____Decode(b *testing.B) { - fnBenchmarkDecode(b, "msgpack", benchTs, fnMsgpackEncodeFn, fnMsgpackDecodeFn, fnBenchNewTs) -} - -func Benchmark__Binc_NoSym_Encode(b *testing.B) { - fnBenchmarkEncode(b, "binc", benchTs, fnBincNoSymEncodeFn) -} - -func Benchmark__Binc_NoSym_Decode(b *testing.B) { - fnBenchmarkDecode(b, "binc", benchTs, fnBincNoSymEncodeFn, fnBincNoSymDecodeFn, fnBenchNewTs) -} - -func Benchmark__Binc_Sym___Encode(b *testing.B) { - fnBenchmarkEncode(b, "binc", benchTs, fnBincSymEncodeFn) -} - -func Benchmark__Binc_Sym___Decode(b *testing.B) { - fnBenchmarkDecode(b, "binc", benchTs, fnBincSymEncodeFn, fnBincSymDecodeFn, fnBenchNewTs) -} - -func Benchmark__Simple____Encode(b *testing.B) { - fnBenchmarkEncode(b, "simple", benchTs, fnSimpleEncodeFn) -} - -func Benchmark__Simple____Decode(b *testing.B) { - fnBenchmarkDecode(b, "simple", benchTs, fnSimpleEncodeFn, fnSimpleDecodeFn, fnBenchNewTs) -} - -func Benchmark__Gob________Encode(b *testing.B) { - fnBenchmarkEncode(b, "gob", benchTs, fnGobEncodeFn) -} - -func Benchmark__Gob________Decode(b *testing.B) { - fnBenchmarkDecode(b, "gob", benchTs, fnGobEncodeFn, fnGobDecodeFn, fnBenchNewTs) -} - -func Benchmark__Json_______Encode(b *testing.B) { - fnBenchmarkEncode(b, "json", benchTs, fnJsonEncodeFn) -} - -func Benchmark__Json_______Decode(b *testing.B) { - fnBenchmarkDecode(b, "json", benchTs, fnJsonEncodeFn, fnJsonDecodeFn, fnBenchNewTs) -} diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/codecs_test.go b/vendor/github.com/hashicorp/go-msgpack/codec/codecs_test.go deleted file mode 100644 index cb184491f..000000000 --- a/vendor/github.com/hashicorp/go-msgpack/codec/codecs_test.go +++ /dev/null @@ -1,1002 +0,0 @@ -// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved. -// Use of this source code is governed by a BSD-style license found in the LICENSE file. - -package codec - -// Test works by using a slice of interfaces. -// It can test for encoding/decoding into/from a nil interface{} -// or passing the object to encode/decode into. -// -// There are basically 2 main tests here. -// First test internally encodes and decodes things and verifies that -// the artifact was as expected. -// Second test will use python msgpack to create a bunch of golden files, -// read those files, and compare them to what it should be. It then -// writes those files back out and compares the byte streams. -// -// Taken together, the tests are pretty extensive. - -import ( - "bytes" - "encoding/gob" - "flag" - "fmt" - "io/ioutil" - "math" - "net" - "net/rpc" - "os" - "os/exec" - "path/filepath" - "reflect" - "runtime" - "strconv" - "sync/atomic" - "testing" - "time" -) - -type testVerifyArg int - -const ( - testVerifyMapTypeSame testVerifyArg = iota - testVerifyMapTypeStrIntf - testVerifyMapTypeIntfIntf - // testVerifySliceIntf - testVerifyForPython -) - -var ( - testInitDebug bool - testUseIoEncDec bool - testStructToArray bool - testWriteNoSymbols bool - - _ = fmt.Printf - skipVerifyVal interface{} = &(struct{}{}) - - // For Go Time, do not use a descriptive timezone. - // It's unnecessary, and makes it harder to do a reflect.DeepEqual. - // The Offset already tells what the offset should be, if not on UTC and unknown zone name. - timeLoc = time.FixedZone("", -8*60*60) // UTC-08:00 //time.UTC-8 - timeToCompare1 = time.Date(2012, 2, 2, 2, 2, 2, 2000, timeLoc) - timeToCompare2 = time.Date(1900, 2, 2, 2, 2, 2, 2000, timeLoc) - timeToCompare3 = time.Unix(0, 0).UTC() - timeToCompare4 = time.Time{}.UTC() - - table []interface{} // main items we encode - tableVerify []interface{} // we verify encoded things against this after decode - tableTestNilVerify []interface{} // for nil interface, use this to verify (rules are different) - tablePythonVerify []interface{} // for verifying for python, since Python sometimes - // will encode a float32 as float64, or large int as uint - testRpcInt = new(TestRpcInt) - testMsgpackH = &MsgpackHandle{} - testBincH = &BincHandle{} - testSimpleH = &SimpleHandle{} -) - -func testInitFlags() { - // delete(testDecOpts.ExtFuncs, timeTyp) - flag.BoolVar(&testInitDebug, "tg", false, "Test Debug") - flag.BoolVar(&testUseIoEncDec, "ti", false, "Use IO Reader/Writer for Marshal/Unmarshal") - flag.BoolVar(&testStructToArray, "ts", false, "Set StructToArray option") - flag.BoolVar(&testWriteNoSymbols, "tn", false, "Set NoSymbols option") -} - -type AnonInTestStruc struct { - AS string - AI64 int64 - AI16 int16 - AUi64 uint64 - ASslice []string - AI64slice []int64 -} - -type TestStruc struct { - S string - I64 int64 - I16 int16 - Ui64 uint64 - Ui8 uint8 - B bool - By byte - - Sslice []string - I64slice []int64 - I16slice []int16 - Ui64slice []uint64 - Ui8slice []uint8 - Bslice []bool - Byslice []byte - - Islice []interface{} - Iptrslice []*int64 - - AnonInTestStruc - - //M map[interface{}]interface{} `json:"-",bson:"-"` - Ms map[string]interface{} - Msi64 map[string]int64 - - Nintf interface{} //don't set this, so we can test for nil - T time.Time - Nmap map[string]bool //don't set this, so we can test for nil - Nslice []byte //don't set this, so we can test for nil - Nint64 *int64 //don't set this, so we can test for nil - Mtsptr map[string]*TestStruc - Mts map[string]TestStruc - Its []*TestStruc - Nteststruc *TestStruc -} - -type TestABC struct { - A, B, C string -} - -type TestRpcInt struct { - i int -} - -func (r *TestRpcInt) Update(n int, res *int) error { r.i = n; *res = r.i; return nil } -func (r *TestRpcInt) Square(ignore int, res *int) error { *res = r.i * r.i; return nil } -func (r *TestRpcInt) Mult(n int, res *int) error { *res = r.i * n; return nil } -func (r *TestRpcInt) EchoStruct(arg TestABC, res *string) error { - *res = fmt.Sprintf("%#v", arg) - return nil -} -func (r *TestRpcInt) Echo123(args []string, res *string) error { - *res = fmt.Sprintf("%#v", args) - return nil -} - -func testVerifyVal(v interface{}, arg testVerifyArg) (v2 interface{}) { - //for python msgpack, - // - all positive integers are unsigned 64-bit ints - // - all floats are float64 - switch iv := v.(type) { - case int8: - if iv > 0 { - v2 = uint64(iv) - } else { - v2 = int64(iv) - } - case int16: - if iv > 0 { - v2 = uint64(iv) - } else { - v2 = int64(iv) - } - case int32: - if iv > 0 { - v2 = uint64(iv) - } else { - v2 = int64(iv) - } - case int64: - if iv > 0 { - v2 = uint64(iv) - } else { - v2 = int64(iv) - } - case uint8: - v2 = uint64(iv) - case uint16: - v2 = uint64(iv) - case uint32: - v2 = uint64(iv) - case uint64: - v2 = uint64(iv) - case float32: - v2 = float64(iv) - case float64: - v2 = float64(iv) - case []interface{}: - m2 := make([]interface{}, len(iv)) - for j, vj := range iv { - m2[j] = testVerifyVal(vj, arg) - } - v2 = m2 - case map[string]bool: - switch arg { - case testVerifyMapTypeSame: - m2 := make(map[string]bool) - for kj, kv := range iv { - m2[kj] = kv - } - v2 = m2 - case testVerifyMapTypeStrIntf, testVerifyForPython: - m2 := make(map[string]interface{}) - for kj, kv := range iv { - m2[kj] = kv - } - v2 = m2 - case testVerifyMapTypeIntfIntf: - m2 := make(map[interface{}]interface{}) - for kj, kv := range iv { - m2[kj] = kv - } - v2 = m2 - } - case map[string]interface{}: - switch arg { - case testVerifyMapTypeSame: - m2 := make(map[string]interface{}) - for kj, kv := range iv { - m2[kj] = testVerifyVal(kv, arg) - } - v2 = m2 - case testVerifyMapTypeStrIntf, testVerifyForPython: - m2 := make(map[string]interface{}) - for kj, kv := range iv { - m2[kj] = testVerifyVal(kv, arg) - } - v2 = m2 - case testVerifyMapTypeIntfIntf: - m2 := make(map[interface{}]interface{}) - for kj, kv := range iv { - m2[kj] = testVerifyVal(kv, arg) - } - v2 = m2 - } - case map[interface{}]interface{}: - m2 := make(map[interface{}]interface{}) - for kj, kv := range iv { - m2[testVerifyVal(kj, arg)] = testVerifyVal(kv, arg) - } - v2 = m2 - case time.Time: - switch arg { - case testVerifyForPython: - if iv2 := iv.UnixNano(); iv2 > 0 { - v2 = uint64(iv2) - } else { - v2 = int64(iv2) - } - default: - v2 = v - } - default: - v2 = v - } - return -} - -func testInit() { - gob.Register(new(TestStruc)) - if testInitDebug { - ts0 := newTestStruc(2, false) - fmt.Printf("====> depth: %v, ts: %#v\n", 2, ts0) - } - - testBincH.StructToArray = testStructToArray - if testWriteNoSymbols { - testBincH.AsSymbols = AsSymbolNone - } else { - testBincH.AsSymbols = AsSymbolAll - } - testMsgpackH.StructToArray = testStructToArray - testMsgpackH.RawToString = true - // testMsgpackH.AddExt(byteSliceTyp, 0, testMsgpackH.BinaryEncodeExt, testMsgpackH.BinaryDecodeExt) - // testMsgpackH.AddExt(timeTyp, 1, testMsgpackH.TimeEncodeExt, testMsgpackH.TimeDecodeExt) - timeEncExt := func(rv reflect.Value) ([]byte, error) { - return encodeTime(rv.Interface().(time.Time)), nil - } - timeDecExt := func(rv reflect.Value, bs []byte) error { - tt, err := decodeTime(bs) - if err == nil { - rv.Set(reflect.ValueOf(tt)) - } - return err - } - - // add extensions for msgpack, simple for time.Time, so we can encode/decode same way. - testMsgpackH.AddExt(timeTyp, 1, timeEncExt, timeDecExt) - testSimpleH.AddExt(timeTyp, 1, timeEncExt, timeDecExt) - - primitives := []interface{}{ - int8(-8), - int16(-1616), - int32(-32323232), - int64(-6464646464646464), - uint8(192), - uint16(1616), - uint32(32323232), - uint64(6464646464646464), - byte(192), - float32(-3232.0), - float64(-6464646464.0), - float32(3232.0), - float64(6464646464.0), - false, - true, - nil, - "someday", - "", - "bytestring", - timeToCompare1, - timeToCompare2, - timeToCompare3, - timeToCompare4, - } - mapsAndStrucs := []interface{}{ - map[string]bool{ - "true": true, - "false": false, - }, - map[string]interface{}{ - "true": "True", - "false": false, - "uint16(1616)": uint16(1616), - }, - //add a complex combo map in here. (map has list which has map) - //note that after the first thing, everything else should be generic. - map[string]interface{}{ - "list": []interface{}{ - int16(1616), - int32(32323232), - true, - float32(-3232.0), - map[string]interface{}{ - "TRUE": true, - "FALSE": false, - }, - []interface{}{true, false}, - }, - "int32": int32(32323232), - "bool": true, - "LONG STRING": "123456789012345678901234567890123456789012345678901234567890", - "SHORT STRING": "1234567890", - }, - map[interface{}]interface{}{ - true: "true", - uint8(138): false, - "false": uint8(200), - }, - newTestStruc(0, false), - } - - table = []interface{}{} - table = append(table, primitives...) //0-19 are primitives - table = append(table, primitives) //20 is a list of primitives - table = append(table, mapsAndStrucs...) //21-24 are maps. 25 is a *struct - - tableVerify = make([]interface{}, len(table)) - tableTestNilVerify = make([]interface{}, len(table)) - tablePythonVerify = make([]interface{}, len(table)) - - lp := len(primitives) - av := tableVerify - for i, v := range table { - if i == lp+3 { - av[i] = skipVerifyVal - continue - } - //av[i] = testVerifyVal(v, testVerifyMapTypeSame) - switch v.(type) { - case []interface{}: - av[i] = testVerifyVal(v, testVerifyMapTypeSame) - case map[string]interface{}: - av[i] = testVerifyVal(v, testVerifyMapTypeSame) - case map[interface{}]interface{}: - av[i] = testVerifyVal(v, testVerifyMapTypeSame) - default: - av[i] = v - } - } - - av = tableTestNilVerify - for i, v := range table { - if i > lp+3 { - av[i] = skipVerifyVal - continue - } - av[i] = testVerifyVal(v, testVerifyMapTypeStrIntf) - } - - av = tablePythonVerify - for i, v := range table { - if i > lp+3 { - av[i] = skipVerifyVal - continue - } - av[i] = testVerifyVal(v, testVerifyForPython) - } - - tablePythonVerify = tablePythonVerify[:24] -} - -func testUnmarshal(v interface{}, data []byte, h Handle) error { - if testUseIoEncDec { - return NewDecoder(bytes.NewBuffer(data), h).Decode(v) - } - return NewDecoderBytes(data, h).Decode(v) -} - -func testMarshal(v interface{}, h Handle) (bs []byte, err error) { - if testUseIoEncDec { - var buf bytes.Buffer - err = NewEncoder(&buf, h).Encode(v) - bs = buf.Bytes() - return - } - err = NewEncoderBytes(&bs, h).Encode(v) - return -} - -func testMarshalErr(v interface{}, h Handle, t *testing.T, name string) (bs []byte, err error) { - if bs, err = testMarshal(v, h); err != nil { - logT(t, "Error encoding %s: %v, Err: %v", name, v, err) - t.FailNow() - } - return -} - -func testUnmarshalErr(v interface{}, data []byte, h Handle, t *testing.T, name string) (err error) { - if err = testUnmarshal(v, data, h); err != nil { - logT(t, "Error Decoding into %s: %v, Err: %v", name, v, err) - t.FailNow() - } - return -} - -func newTestStruc(depth int, bench bool) (ts *TestStruc) { - var i64a, i64b, i64c, i64d int64 = 64, 6464, 646464, 64646464 - - ts = &TestStruc{ - S: "some string", - I64: math.MaxInt64 * 2 / 3, // 64, - I16: 16, - Ui64: uint64(int64(math.MaxInt64 * 2 / 3)), // 64, //don't use MaxUint64, as bson can't write it - Ui8: 160, - B: true, - By: 5, - - Sslice: []string{"one", "two", "three"}, - I64slice: []int64{1, 2, 3}, - I16slice: []int16{4, 5, 6}, - Ui64slice: []uint64{137, 138, 139}, - Ui8slice: []uint8{210, 211, 212}, - Bslice: []bool{true, false, true, false}, - Byslice: []byte{13, 14, 15}, - - Islice: []interface{}{"true", true, "no", false, uint64(288), float64(0.4)}, - - Ms: map[string]interface{}{ - "true": "true", - "int64(9)": false, - }, - Msi64: map[string]int64{ - "one": 1, - "two": 2, - }, - T: timeToCompare1, - AnonInTestStruc: AnonInTestStruc{ - AS: "A-String", - AI64: 64, - AI16: 16, - AUi64: 64, - ASslice: []string{"Aone", "Atwo", "Athree"}, - AI64slice: []int64{1, 2, 3}, - }, - } - //For benchmarks, some things will not work. - if !bench { - //json and bson require string keys in maps - //ts.M = map[interface{}]interface{}{ - // true: "true", - // int8(9): false, - //} - //gob cannot encode nil in element in array (encodeArray: nil element) - ts.Iptrslice = []*int64{nil, &i64a, nil, &i64b, nil, &i64c, nil, &i64d, nil} - // ts.Iptrslice = nil - } - if depth > 0 { - depth-- - if ts.Mtsptr == nil { - ts.Mtsptr = make(map[string]*TestStruc) - } - if ts.Mts == nil { - ts.Mts = make(map[string]TestStruc) - } - ts.Mtsptr["0"] = newTestStruc(depth, bench) - ts.Mts["0"] = *(ts.Mtsptr["0"]) - ts.Its = append(ts.Its, ts.Mtsptr["0"]) - } - return -} - -// doTestCodecTableOne allows us test for different variations based on arguments passed. -func doTestCodecTableOne(t *testing.T, testNil bool, h Handle, - vs []interface{}, vsVerify []interface{}) { - //if testNil, then just test for when a pointer to a nil interface{} is passed. It should work. - //Current setup allows us test (at least manually) the nil interface or typed interface. - logT(t, "================ TestNil: %v ================\n", testNil) - for i, v0 := range vs { - logT(t, "..............................................") - logT(t, " Testing: #%d:, %T, %#v\n", i, v0, v0) - b0, err := testMarshalErr(v0, h, t, "v0") - if err != nil { - continue - } - logT(t, " Encoded bytes: len: %v, %v\n", len(b0), b0) - - var v1 interface{} - - if testNil { - err = testUnmarshal(&v1, b0, h) - } else { - if v0 != nil { - v0rt := reflect.TypeOf(v0) // ptr - rv1 := reflect.New(v0rt) - err = testUnmarshal(rv1.Interface(), b0, h) - v1 = rv1.Elem().Interface() - // v1 = reflect.Indirect(reflect.ValueOf(v1)).Interface() - } - } - - logT(t, " v1 returned: %T, %#v", v1, v1) - // if v1 != nil { - // logT(t, " v1 returned: %T, %#v", v1, v1) - // //we always indirect, because ptr to typed value may be passed (if not testNil) - // v1 = reflect.Indirect(reflect.ValueOf(v1)).Interface() - // } - if err != nil { - logT(t, "-------- Error: %v. Partial return: %v", err, v1) - failT(t) - continue - } - v0check := vsVerify[i] - if v0check == skipVerifyVal { - logT(t, " Nil Check skipped: Decoded: %T, %#v\n", v1, v1) - continue - } - - if err = deepEqual(v0check, v1); err == nil { - logT(t, "++++++++ Before and After marshal matched\n") - } else { - logT(t, "-------- Before and After marshal do not match: Error: %v"+ - " ====> GOLDEN: (%T) %#v, DECODED: (%T) %#v\n", err, v0check, v0check, v1, v1) - failT(t) - } - } -} - -func testCodecTableOne(t *testing.T, h Handle) { - // func TestMsgpackAllExperimental(t *testing.T) { - // dopts := testDecOpts(nil, nil, false, true, true), - - switch v := h.(type) { - case *MsgpackHandle: - var oldWriteExt, oldRawToString bool - oldWriteExt, v.WriteExt = v.WriteExt, true - oldRawToString, v.RawToString = v.RawToString, true - doTestCodecTableOne(t, false, h, table, tableVerify) - v.WriteExt, v.RawToString = oldWriteExt, oldRawToString - default: - doTestCodecTableOne(t, false, h, table, tableVerify) - } - // func TestMsgpackAll(t *testing.T) { - idxTime, numPrim, numMap := 19, 23, 4 - - //skip []interface{} containing time.Time - doTestCodecTableOne(t, false, h, table[:numPrim], tableVerify[:numPrim]) - doTestCodecTableOne(t, false, h, table[numPrim+1:], tableVerify[numPrim+1:]) - // func TestMsgpackNilStringMap(t *testing.T) { - var oldMapType reflect.Type - v := h.getBasicHandle() - oldMapType, v.MapType = v.MapType, mapStrIntfTyp - - //skip time.Time, []interface{} containing time.Time, last map, and newStruc - doTestCodecTableOne(t, true, h, table[:idxTime], tableTestNilVerify[:idxTime]) - doTestCodecTableOne(t, true, h, table[numPrim+1:numPrim+numMap], tableTestNilVerify[numPrim+1:numPrim+numMap]) - - v.MapType = oldMapType - - // func TestMsgpackNilIntf(t *testing.T) { - - //do newTestStruc and last element of map - doTestCodecTableOne(t, true, h, table[numPrim+numMap:], tableTestNilVerify[numPrim+numMap:]) - //TODO? What is this one? - //doTestCodecTableOne(t, true, h, table[17:18], tableTestNilVerify[17:18]) -} - -func testCodecMiscOne(t *testing.T, h Handle) { - b, err := testMarshalErr(32, h, t, "32") - // Cannot do this nil one, because faster type assertion decoding will panic - // var i *int32 - // if err = testUnmarshal(b, i, nil); err == nil { - // logT(t, "------- Expecting error because we cannot unmarshal to int32 nil ptr") - // t.FailNow() - // } - var i2 int32 = 0 - err = testUnmarshalErr(&i2, b, h, t, "int32-ptr") - if i2 != int32(32) { - logT(t, "------- didn't unmarshal to 32: Received: %d", i2) - t.FailNow() - } - - // func TestMsgpackDecodePtr(t *testing.T) { - ts := newTestStruc(0, false) - b, err = testMarshalErr(ts, h, t, "pointer-to-struct") - if len(b) < 40 { - logT(t, "------- Size must be > 40. Size: %d", len(b)) - t.FailNow() - } - logT(t, "------- b: %v", b) - ts2 := new(TestStruc) - err = testUnmarshalErr(ts2, b, h, t, "pointer-to-struct") - if ts2.I64 != math.MaxInt64*2/3 { - logT(t, "------- Unmarshal wrong. Expect I64 = 64. Got: %v", ts2.I64) - t.FailNow() - } - - // func TestMsgpackIntfDecode(t *testing.T) { - m := map[string]int{"A": 2, "B": 3} - p := []interface{}{m} - bs, err := testMarshalErr(p, h, t, "p") - - m2 := map[string]int{} - p2 := []interface{}{m2} - err = testUnmarshalErr(&p2, bs, h, t, "&p2") - - if m2["A"] != 2 || m2["B"] != 3 { - logT(t, "m2 not as expected: expecting: %v, got: %v", m, m2) - t.FailNow() - } - // log("m: %v, m2: %v, p: %v, p2: %v", m, m2, p, p2) - checkEqualT(t, p, p2, "p=p2") - checkEqualT(t, m, m2, "m=m2") - if err = deepEqual(p, p2); err == nil { - logT(t, "p and p2 match") - } else { - logT(t, "Not Equal: %v. p: %v, p2: %v", err, p, p2) - t.FailNow() - } - if err = deepEqual(m, m2); err == nil { - logT(t, "m and m2 match") - } else { - logT(t, "Not Equal: %v. m: %v, m2: %v", err, m, m2) - t.FailNow() - } - - // func TestMsgpackDecodeStructSubset(t *testing.T) { - // test that we can decode a subset of the stream - mm := map[string]interface{}{"A": 5, "B": 99, "C": 333} - bs, err = testMarshalErr(mm, h, t, "mm") - type ttt struct { - A uint8 - C int32 - } - var t2 ttt - testUnmarshalErr(&t2, bs, h, t, "t2") - t3 := ttt{5, 333} - checkEqualT(t, t2, t3, "t2=t3") - - // println(">>>>>") - // test simple arrays, non-addressable arrays, slices - type tarr struct { - A int64 - B [3]int64 - C []byte - D [3]byte - } - var tarr0 = tarr{1, [3]int64{2, 3, 4}, []byte{4, 5, 6}, [3]byte{7, 8, 9}} - // test both pointer and non-pointer (value) - for _, tarr1 := range []interface{}{tarr0, &tarr0} { - bs, err = testMarshalErr(tarr1, h, t, "tarr1") - var tarr2 tarr - testUnmarshalErr(&tarr2, bs, h, t, "tarr2") - checkEqualT(t, tarr0, tarr2, "tarr0=tarr2") - // fmt.Printf(">>>> err: %v. tarr1: %v, tarr2: %v\n", err, tarr0, tarr2) - } - - // test byte array, even if empty (msgpack only) - if h == testMsgpackH { - type ystruct struct { - Anarray []byte - } - var ya = ystruct{} - testUnmarshalErr(&ya, []byte{0x91, 0x90}, h, t, "ya") - } -} - -func testCodecEmbeddedPointer(t *testing.T, h Handle) { - type Z int - type A struct { - AnInt int - } - type B struct { - *Z - *A - MoreInt int - } - var z Z = 4 - x1 := &B{&z, &A{5}, 6} - bs, err := testMarshalErr(x1, h, t, "x1") - // fmt.Printf("buf: len(%v): %x\n", buf.Len(), buf.Bytes()) - var x2 = new(B) - err = testUnmarshalErr(x2, bs, h, t, "x2") - err = checkEqualT(t, x1, x2, "x1=x2") - _ = err -} - -func doTestRpcOne(t *testing.T, rr Rpc, h Handle, doRequest bool, exitSleepMs time.Duration, -) (port int) { - // rpc needs EOF, which is sent via a panic, and so must be recovered. - if !recoverPanicToErr { - logT(t, "EXPECTED. set recoverPanicToErr=true, since rpc needs EOF") - t.FailNow() - } - srv := rpc.NewServer() - srv.Register(testRpcInt) - ln, err := net.Listen("tcp", "127.0.0.1:0") - // log("listener: %v", ln.Addr()) - checkErrT(t, err) - port = (ln.Addr().(*net.TCPAddr)).Port - // var opts *DecoderOptions - // opts := testDecOpts - // opts.MapType = mapStrIntfTyp - // opts.RawToString = false - serverExitChan := make(chan bool, 1) - var serverExitFlag uint64 = 0 - serverFn := func() { - for { - conn1, err1 := ln.Accept() - // if err1 != nil { - // //fmt.Printf("accept err1: %v\n", err1) - // continue - // } - if atomic.LoadUint64(&serverExitFlag) == 1 { - serverExitChan <- true - conn1.Close() - return // exit serverFn goroutine - } - if err1 == nil { - var sc rpc.ServerCodec = rr.ServerCodec(conn1, h) - srv.ServeCodec(sc) - } - } - } - - clientFn := func(cc rpc.ClientCodec) { - cl := rpc.NewClientWithCodec(cc) - defer cl.Close() - var up, sq, mult int - var rstr string - // log("Calling client") - checkErrT(t, cl.Call("TestRpcInt.Update", 5, &up)) - // log("Called TestRpcInt.Update") - checkEqualT(t, testRpcInt.i, 5, "testRpcInt.i=5") - checkEqualT(t, up, 5, "up=5") - checkErrT(t, cl.Call("TestRpcInt.Square", 1, &sq)) - checkEqualT(t, sq, 25, "sq=25") - checkErrT(t, cl.Call("TestRpcInt.Mult", 20, &mult)) - checkEqualT(t, mult, 100, "mult=100") - checkErrT(t, cl.Call("TestRpcInt.EchoStruct", TestABC{"Aa", "Bb", "Cc"}, &rstr)) - checkEqualT(t, rstr, fmt.Sprintf("%#v", TestABC{"Aa", "Bb", "Cc"}), "rstr=") - checkErrT(t, cl.Call("TestRpcInt.Echo123", []string{"A1", "B2", "C3"}, &rstr)) - checkEqualT(t, rstr, fmt.Sprintf("%#v", []string{"A1", "B2", "C3"}), "rstr=") - } - - connFn := func() (bs net.Conn) { - // log("calling f1") - bs, err2 := net.Dial(ln.Addr().Network(), ln.Addr().String()) - //fmt.Printf("f1. bs: %v, err2: %v\n", bs, err2) - checkErrT(t, err2) - return - } - - exitFn := func() { - atomic.StoreUint64(&serverExitFlag, 1) - bs := connFn() - <-serverExitChan - bs.Close() - // serverExitChan <- true - } - - go serverFn() - runtime.Gosched() - //time.Sleep(100 * time.Millisecond) - if exitSleepMs == 0 { - defer ln.Close() - defer exitFn() - } - if doRequest { - bs := connFn() - cc := rr.ClientCodec(bs, h) - clientFn(cc) - } - if exitSleepMs != 0 { - go func() { - defer ln.Close() - time.Sleep(exitSleepMs) - exitFn() - }() - } - return -} - -// Comprehensive testing that generates data encoded from python msgpack, -// and validates that our code can read and write it out accordingly. -// We keep this unexported here, and put actual test in ext_dep_test.go. -// This way, it can be excluded by excluding file completely. -func doTestMsgpackPythonGenStreams(t *testing.T) { - logT(t, "TestPythonGenStreams") - tmpdir, err := ioutil.TempDir("", "golang-msgpack-test") - if err != nil { - logT(t, "-------- Unable to create temp directory\n") - t.FailNow() - } - defer os.RemoveAll(tmpdir) - logT(t, "tmpdir: %v", tmpdir) - cmd := exec.Command("python", "msgpack_test.py", "testdata", tmpdir) - //cmd.Stdin = strings.NewReader("some input") - //cmd.Stdout = &out - var cmdout []byte - if cmdout, err = cmd.CombinedOutput(); err != nil { - logT(t, "-------- Error running msgpack_test.py testdata. Err: %v", err) - logT(t, " %v", string(cmdout)) - t.FailNow() - } - - oldMapType := testMsgpackH.MapType - for i, v := range tablePythonVerify { - testMsgpackH.MapType = oldMapType - //load up the golden file based on number - //decode it - //compare to in-mem object - //encode it again - //compare to output stream - logT(t, "..............................................") - logT(t, " Testing: #%d: %T, %#v\n", i, v, v) - var bss []byte - bss, err = ioutil.ReadFile(filepath.Join(tmpdir, strconv.Itoa(i)+".golden")) - if err != nil { - logT(t, "-------- Error reading golden file: %d. Err: %v", i, err) - failT(t) - continue - } - testMsgpackH.MapType = mapStrIntfTyp - - var v1 interface{} - if err = testUnmarshal(&v1, bss, testMsgpackH); err != nil { - logT(t, "-------- Error decoding stream: %d: Err: %v", i, err) - failT(t) - continue - } - if v == skipVerifyVal { - continue - } - //no need to indirect, because we pass a nil ptr, so we already have the value - //if v1 != nil { v1 = reflect.Indirect(reflect.ValueOf(v1)).Interface() } - if err = deepEqual(v, v1); err == nil { - logT(t, "++++++++ Objects match") - } else { - logT(t, "-------- Objects do not match: %v. Source: %T. Decoded: %T", err, v, v1) - logT(t, "-------- AGAINST: %#v", v) - logT(t, "-------- DECODED: %#v <====> %#v", v1, reflect.Indirect(reflect.ValueOf(v1)).Interface()) - failT(t) - } - bsb, err := testMarshal(v1, testMsgpackH) - if err != nil { - logT(t, "Error encoding to stream: %d: Err: %v", i, err) - failT(t) - continue - } - if err = deepEqual(bsb, bss); err == nil { - logT(t, "++++++++ Bytes match") - } else { - logT(t, "???????? Bytes do not match. %v.", err) - xs := "--------" - if reflect.ValueOf(v).Kind() == reflect.Map { - xs = " " - logT(t, "%s It's a map. Ok that they don't match (dependent on ordering).", xs) - } else { - logT(t, "%s It's not a map. They should match.", xs) - failT(t) - } - logT(t, "%s FROM_FILE: %4d] %v", xs, len(bss), bss) - logT(t, "%s ENCODED: %4d] %v", xs, len(bsb), bsb) - } - } - testMsgpackH.MapType = oldMapType -} - -// To test MsgpackSpecRpc, we test 3 scenarios: -// - Go Client to Go RPC Service (contained within TestMsgpackRpcSpec) -// - Go client to Python RPC Service (contained within doTestMsgpackRpcSpecGoClientToPythonSvc) -// - Python Client to Go RPC Service (contained within doTestMsgpackRpcSpecPythonClientToGoSvc) -// -// This allows us test the different calling conventions -// - Go Service requires only one argument -// - Python Service allows multiple arguments - -func doTestMsgpackRpcSpecGoClientToPythonSvc(t *testing.T) { - openPort := "6789" - cmd := exec.Command("python", "msgpack_test.py", "rpc-server", openPort, "2") - checkErrT(t, cmd.Start()) - time.Sleep(100 * time.Millisecond) // time for python rpc server to start - bs, err2 := net.Dial("tcp", ":"+openPort) - checkErrT(t, err2) - cc := MsgpackSpecRpc.ClientCodec(bs, testMsgpackH) - cl := rpc.NewClientWithCodec(cc) - defer cl.Close() - var rstr string - checkErrT(t, cl.Call("EchoStruct", TestABC{"Aa", "Bb", "Cc"}, &rstr)) - //checkEqualT(t, rstr, "{'A': 'Aa', 'B': 'Bb', 'C': 'Cc'}") - var mArgs MsgpackSpecRpcMultiArgs = []interface{}{"A1", "B2", "C3"} - checkErrT(t, cl.Call("Echo123", mArgs, &rstr)) - checkEqualT(t, rstr, "1:A1 2:B2 3:C3", "rstr=") -} - -func doTestMsgpackRpcSpecPythonClientToGoSvc(t *testing.T) { - port := doTestRpcOne(t, MsgpackSpecRpc, testMsgpackH, false, 1*time.Second) - //time.Sleep(1000 * time.Millisecond) - cmd := exec.Command("python", "msgpack_test.py", "rpc-client-go-service", strconv.Itoa(port)) - var cmdout []byte - var err error - if cmdout, err = cmd.CombinedOutput(); err != nil { - logT(t, "-------- Error running msgpack_test.py rpc-client-go-service. Err: %v", err) - logT(t, " %v", string(cmdout)) - t.FailNow() - } - checkEqualT(t, string(cmdout), - fmt.Sprintf("%#v\n%#v\n", []string{"A1", "B2", "C3"}, TestABC{"Aa", "Bb", "Cc"}), "cmdout=") -} - -func TestBincCodecsTable(t *testing.T) { - testCodecTableOne(t, testBincH) -} - -func TestBincCodecsMisc(t *testing.T) { - testCodecMiscOne(t, testBincH) -} - -func TestBincCodecsEmbeddedPointer(t *testing.T) { - testCodecEmbeddedPointer(t, testBincH) -} - -func TestSimpleCodecsTable(t *testing.T) { - testCodecTableOne(t, testSimpleH) -} - -func TestSimpleCodecsMisc(t *testing.T) { - testCodecMiscOne(t, testSimpleH) -} - -func TestSimpleCodecsEmbeddedPointer(t *testing.T) { - testCodecEmbeddedPointer(t, testSimpleH) -} - -func TestMsgpackCodecsTable(t *testing.T) { - testCodecTableOne(t, testMsgpackH) -} - -func TestMsgpackCodecsMisc(t *testing.T) { - testCodecMiscOne(t, testMsgpackH) -} - -func TestMsgpackCodecsEmbeddedPointer(t *testing.T) { - testCodecEmbeddedPointer(t, testMsgpackH) -} - -func TestBincRpcGo(t *testing.T) { - doTestRpcOne(t, GoRpc, testBincH, true, 0) -} - -func _TestSimpleRpcGo(t *testing.T) { - doTestRpcOne(t, GoRpc, testSimpleH, true, 0) -} - -func TestMsgpackRpcGo(t *testing.T) { - doTestRpcOne(t, GoRpc, testMsgpackH, true, 0) -} - -func TestMsgpackRpcSpec(t *testing.T) { - doTestRpcOne(t, MsgpackSpecRpc, testMsgpackH, true, 0) -} - -// TODO: -// Add Tests for: -// - decoding empty list/map in stream into a nil slice/map -// - binary(M|Unm)arsher support for time.Time diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/ext_dep_test.go b/vendor/github.com/hashicorp/go-msgpack/codec/ext_dep_test.go deleted file mode 100644 index bdf448d52..000000000 --- a/vendor/github.com/hashicorp/go-msgpack/codec/ext_dep_test.go +++ /dev/null @@ -1,75 +0,0 @@ -// //+build ignore - -// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved. -// Use of this source code is governed by a BSD-style license found in the LICENSE file. - -package codec - -// This file includes benchmarks which have dependencies on 3rdparty -// packages (bson and vmihailenco/msgpack) which must be installed locally. -// -// To run the benchmarks including these 3rdparty packages, first -// - Uncomment first line in this file (put // // in front of it) -// - Get those packages: -// go get github.com/vmihailenco/msgpack -// go get labix.org/v2/mgo/bson -// - Run: -// go test -bi -bench=. - -import ( - "testing" - - vmsgpack "gopkg.in/vmihailenco/msgpack.v2" - "labix.org/v2/mgo/bson" -) - -func init() { - benchCheckers = append(benchCheckers, - benchChecker{"v-msgpack", fnVMsgpackEncodeFn, fnVMsgpackDecodeFn}, - benchChecker{"bson", fnBsonEncodeFn, fnBsonDecodeFn}, - ) -} - -func fnVMsgpackEncodeFn(ts interface{}) ([]byte, error) { - return vmsgpack.Marshal(ts) -} - -func fnVMsgpackDecodeFn(buf []byte, ts interface{}) error { - return vmsgpack.Unmarshal(buf, ts) -} - -func fnBsonEncodeFn(ts interface{}) ([]byte, error) { - return bson.Marshal(ts) -} - -func fnBsonDecodeFn(buf []byte, ts interface{}) error { - return bson.Unmarshal(buf, ts) -} - -func Benchmark__Bson_______Encode(b *testing.B) { - fnBenchmarkEncode(b, "bson", benchTs, fnBsonEncodeFn) -} - -func Benchmark__Bson_______Decode(b *testing.B) { - fnBenchmarkDecode(b, "bson", benchTs, fnBsonEncodeFn, fnBsonDecodeFn, fnBenchNewTs) -} - -func Benchmark__VMsgpack___Encode(b *testing.B) { - fnBenchmarkEncode(b, "v-msgpack", benchTs, fnVMsgpackEncodeFn) -} - -func Benchmark__VMsgpack___Decode(b *testing.B) { - fnBenchmarkDecode(b, "v-msgpack", benchTs, fnVMsgpackEncodeFn, fnVMsgpackDecodeFn, fnBenchNewTs) -} - -func TestMsgpackPythonGenStreams(t *testing.T) { - doTestMsgpackPythonGenStreams(t) -} - -func TestMsgpackRpcSpecGoClientToPythonSvc(t *testing.T) { - doTestMsgpackRpcSpecGoClientToPythonSvc(t) -} - -func TestMsgpackRpcSpecPythonClientToGoSvc(t *testing.T) { - doTestMsgpackRpcSpecPythonClientToGoSvc(t) -} diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/msgpack_test.py b/vendor/github.com/hashicorp/go-msgpack/codec/msgpack_test.py old mode 100755 new mode 100644 diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/z_helper_test.go b/vendor/github.com/hashicorp/go-msgpack/codec/z_helper_test.go deleted file mode 100644 index 2e9b3a0f0..000000000 --- a/vendor/github.com/hashicorp/go-msgpack/codec/z_helper_test.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved. -// Use of this source code is governed by a BSD-style license found in the LICENSE file. - -package codec - -// All non-std package dependencies related to testing live in this file, -// so porting to different environment is easy (just update functions). -// -// Also, this file is called z_helper_test, to give a "hint" to compiler -// that its init() function should be called last. (not guaranteed by spec) - -import ( - "errors" - "reflect" - "flag" - "testing" -) - -var ( - testLogToT = true - failNowOnFail = true -) - -func init() { - testInitFlags() - benchInitFlags() - flag.Parse() - testInit() - benchInit() -} - -func checkErrT(t *testing.T, err error) { - if err != nil { - logT(t, err.Error()) - failT(t) - } -} - -func checkEqualT(t *testing.T, v1 interface{}, v2 interface{}, desc string) (err error) { - if err = deepEqual(v1, v2); err != nil { - logT(t, "Not Equal: %s: %v. v1: %v, v2: %v", desc, err, v1, v2) - failT(t) - } - return -} - -func logT(x interface{}, format string, args ...interface{}) { - if t, ok := x.(*testing.T); ok && t != nil && testLogToT { - t.Logf(format, args...) - } else if b, ok := x.(*testing.B); ok && b != nil && testLogToT { - b.Logf(format, args...) - } else { - debugf(format, args...) - } -} - -func failT(t *testing.T) { - if failNowOnFail { - t.FailNow() - } else { - t.Fail() - } -} - -func deepEqual(v1, v2 interface{}) (err error) { - if !reflect.DeepEqual(v1, v2) { - err = errors.New("Not Match") - } - return -} - -func approxDataSize(rv reflect.Value) (sum int) { - switch rk := rv.Kind(); rk { - case reflect.Invalid: - case reflect.Ptr, reflect.Interface: - sum += int(rv.Type().Size()) - sum += approxDataSize(rv.Elem()) - case reflect.Slice: - sum += int(rv.Type().Size()) - for j := 0; j < rv.Len(); j++ { - sum += approxDataSize(rv.Index(j)) - } - case reflect.String: - sum += int(rv.Type().Size()) - sum += rv.Len() - case reflect.Map: - sum += int(rv.Type().Size()) - for _, mk := range rv.MapKeys() { - sum += approxDataSize(mk) - sum += approxDataSize(rv.MapIndex(mk)) - } - case reflect.Struct: - //struct size already includes the full data size. - //sum += int(rv.Type().Size()) - for j := 0; j < rv.NumField(); j++ { - sum += approxDataSize(rv.Field(j)) - } - default: - //pure value types - sum += int(rv.Type().Size()) - } - return -} diff --git a/vendor/github.com/hashicorp/go-multierror/append_test.go b/vendor/github.com/hashicorp/go-multierror/append_test.go deleted file mode 100644 index 58ddafa8d..000000000 --- a/vendor/github.com/hashicorp/go-multierror/append_test.go +++ /dev/null @@ -1,82 +0,0 @@ -package multierror - -import ( - "errors" - "testing" -) - -func TestAppend_Error(t *testing.T) { - original := &Error{ - Errors: []error{errors.New("foo")}, - } - - result := Append(original, errors.New("bar")) - if len(result.Errors) != 2 { - t.Fatalf("wrong len: %d", len(result.Errors)) - } - - original = &Error{} - result = Append(original, errors.New("bar")) - if len(result.Errors) != 1 { - t.Fatalf("wrong len: %d", len(result.Errors)) - } - - // Test when a typed nil is passed - var e *Error - result = Append(e, errors.New("baz")) - if len(result.Errors) != 1 { - t.Fatalf("wrong len: %d", len(result.Errors)) - } - - // Test flattening - original = &Error{ - Errors: []error{errors.New("foo")}, - } - - result = Append(original, Append(nil, errors.New("foo"), errors.New("bar"))) - if len(result.Errors) != 3 { - t.Fatalf("wrong len: %d", len(result.Errors)) - } -} - -func TestAppend_NilError(t *testing.T) { - var err error - result := Append(err, errors.New("bar")) - if len(result.Errors) != 1 { - t.Fatalf("wrong len: %d", len(result.Errors)) - } -} - -func TestAppend_NilErrorArg(t *testing.T) { - var err error - var nilErr *Error - result := Append(err, nilErr) - if len(result.Errors) != 0 { - t.Fatalf("wrong len: %d", len(result.Errors)) - } -} - -func TestAppend_NilErrorIfaceArg(t *testing.T) { - var err error - var nilErr error - result := Append(err, nilErr) - if len(result.Errors) != 0 { - t.Fatalf("wrong len: %d", len(result.Errors)) - } -} - -func TestAppend_NonError(t *testing.T) { - original := errors.New("foo") - result := Append(original, errors.New("bar")) - if len(result.Errors) != 2 { - t.Fatalf("wrong len: %d", len(result.Errors)) - } -} - -func TestAppend_NonError_Error(t *testing.T) { - original := errors.New("foo") - result := Append(original, Append(nil, errors.New("bar"))) - if len(result.Errors) != 2 { - t.Fatalf("wrong len: %d", len(result.Errors)) - } -} diff --git a/vendor/github.com/hashicorp/go-multierror/flatten_test.go b/vendor/github.com/hashicorp/go-multierror/flatten_test.go deleted file mode 100644 index 9fbacadca..000000000 --- a/vendor/github.com/hashicorp/go-multierror/flatten_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package multierror - -import ( - "errors" - "fmt" - "reflect" - "strings" - "testing" -) - -func TestFlatten(t *testing.T) { - original := &Error{ - Errors: []error{ - errors.New("one"), - &Error{ - Errors: []error{ - errors.New("two"), - &Error{ - Errors: []error{ - errors.New("three"), - }, - }, - }, - }, - }, - } - - expected := strings.TrimSpace(` -3 errors occurred: - -* one -* two -* three - `) - actual := fmt.Sprintf("%s", Flatten(original)) - - if expected != actual { - t.Fatalf("expected: %s, got: %s", expected, actual) - } -} - -func TestFlatten_nonError(t *testing.T) { - err := errors.New("foo") - actual := Flatten(err) - if !reflect.DeepEqual(actual, err) { - t.Fatalf("bad: %#v", actual) - } -} diff --git a/vendor/github.com/hashicorp/go-multierror/format.go b/vendor/github.com/hashicorp/go-multierror/format.go index 6c7a3cc91..47f13c49a 100644 --- a/vendor/github.com/hashicorp/go-multierror/format.go +++ b/vendor/github.com/hashicorp/go-multierror/format.go @@ -13,7 +13,7 @@ type ErrorFormatFunc func([]error) string // that occurred along with a bullet point list of the errors. func ListFormatFunc(es []error) string { if len(es) == 1 { - return fmt.Sprintf("1 error occurred:\n\n* %s", es[0]) + return fmt.Sprintf("1 error occurred:\n\t* %s\n\n", es[0]) } points := make([]string, len(es)) @@ -22,6 +22,6 @@ func ListFormatFunc(es []error) string { } return fmt.Sprintf( - "%d errors occurred:\n\n%s", - len(es), strings.Join(points, "\n")) + "%d errors occurred:\n\t%s\n\n", + len(es), strings.Join(points, "\n\t")) } diff --git a/vendor/github.com/hashicorp/go-multierror/format_test.go b/vendor/github.com/hashicorp/go-multierror/format_test.go deleted file mode 100644 index 3359e0271..000000000 --- a/vendor/github.com/hashicorp/go-multierror/format_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package multierror - -import ( - "errors" - "testing" -) - -func TestListFormatFuncSingle(t *testing.T) { - expected := `1 error occurred: - -* foo` - - errors := []error{ - errors.New("foo"), - } - - actual := ListFormatFunc(errors) - if actual != expected { - t.Fatalf("bad: %#v", actual) - } -} - -func TestListFormatFuncMultiple(t *testing.T) { - expected := `2 errors occurred: - -* foo -* bar` - - errors := []error{ - errors.New("foo"), - errors.New("bar"), - } - - actual := ListFormatFunc(errors) - if actual != expected { - t.Fatalf("bad: %#v", actual) - } -} diff --git a/vendor/github.com/hashicorp/go-multierror/go.mod b/vendor/github.com/hashicorp/go-multierror/go.mod new file mode 100644 index 000000000..2534331d5 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/go.mod @@ -0,0 +1,3 @@ +module github.com/hashicorp/go-multierror + +require github.com/hashicorp/errwrap v1.0.0 diff --git a/vendor/github.com/hashicorp/go-multierror/go.sum b/vendor/github.com/hashicorp/go-multierror/go.sum new file mode 100644 index 000000000..85b1f8ff3 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/go.sum @@ -0,0 +1,4 @@ +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce h1:prjrVgOk2Yg6w+PflHoszQNLTUh4kaByUcEWM/9uin4= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= diff --git a/vendor/github.com/hashicorp/go-multierror/multierror_test.go b/vendor/github.com/hashicorp/go-multierror/multierror_test.go deleted file mode 100644 index 5567d1c2d..000000000 --- a/vendor/github.com/hashicorp/go-multierror/multierror_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package multierror - -import ( - "errors" - "reflect" - "testing" -) - -func TestError_Impl(t *testing.T) { - var _ error = new(Error) -} - -func TestErrorError_custom(t *testing.T) { - errors := []error{ - errors.New("foo"), - errors.New("bar"), - } - - fn := func(es []error) string { - return "foo" - } - - multi := &Error{Errors: errors, ErrorFormat: fn} - if multi.Error() != "foo" { - t.Fatalf("bad: %s", multi.Error()) - } -} - -func TestErrorError_default(t *testing.T) { - expected := `2 errors occurred: - -* foo -* bar` - - errors := []error{ - errors.New("foo"), - errors.New("bar"), - } - - multi := &Error{Errors: errors} - if multi.Error() != expected { - t.Fatalf("bad: %s", multi.Error()) - } -} - -func TestErrorErrorOrNil(t *testing.T) { - err := new(Error) - if err.ErrorOrNil() != nil { - t.Fatalf("bad: %#v", err.ErrorOrNil()) - } - - err.Errors = []error{errors.New("foo")} - if v := err.ErrorOrNil(); v == nil { - t.Fatal("should not be nil") - } else if !reflect.DeepEqual(v, err) { - t.Fatalf("bad: %#v", v) - } -} - -func TestErrorWrappedErrors(t *testing.T) { - errors := []error{ - errors.New("foo"), - errors.New("bar"), - } - - multi := &Error{Errors: errors} - if !reflect.DeepEqual(multi.Errors, multi.WrappedErrors()) { - t.Fatalf("bad: %s", multi.WrappedErrors()) - } -} diff --git a/vendor/github.com/hashicorp/go-multierror/prefix_test.go b/vendor/github.com/hashicorp/go-multierror/prefix_test.go deleted file mode 100644 index 1d4a6f6d3..000000000 --- a/vendor/github.com/hashicorp/go-multierror/prefix_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package multierror - -import ( - "errors" - "testing" -) - -func TestPrefix_Error(t *testing.T) { - original := &Error{ - Errors: []error{errors.New("foo")}, - } - - result := Prefix(original, "bar") - if result.(*Error).Errors[0].Error() != "bar foo" { - t.Fatalf("bad: %s", result) - } -} - -func TestPrefix_NilError(t *testing.T) { - var err error - result := Prefix(err, "bar") - if result != nil { - t.Fatalf("bad: %#v", result) - } -} - -func TestPrefix_NonError(t *testing.T) { - original := errors.New("foo") - result := Prefix(original, "bar") - if result.Error() != "bar foo" { - t.Fatalf("bad: %s", result) - } -} diff --git a/vendor/github.com/hashicorp/go-multierror/sort.go b/vendor/github.com/hashicorp/go-multierror/sort.go new file mode 100644 index 000000000..fecb14e81 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/sort.go @@ -0,0 +1,16 @@ +package multierror + +// Len implements sort.Interface function for length +func (err Error) Len() int { + return len(err.Errors) +} + +// Swap implements sort.Interface function for swapping elements +func (err Error) Swap(i, j int) { + err.Errors[i], err.Errors[j] = err.Errors[j], err.Errors[i] +} + +// Less implements sort.Interface function for determining order +func (err Error) Less(i, j int) bool { + return err.Errors[i].Error() < err.Errors[j].Error() +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/go.mod b/vendor/github.com/hashicorp/go-sockaddr/go.mod new file mode 100644 index 000000000..7c07b5bad --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/go.mod @@ -0,0 +1 @@ +module github.com/hashicorp/go-sockaddr diff --git a/vendor/github.com/hashicorp/go-sockaddr/ifaddr_test.go b/vendor/github.com/hashicorp/go-sockaddr/ifaddr_test.go deleted file mode 100644 index 45a0cc788..000000000 --- a/vendor/github.com/hashicorp/go-sockaddr/ifaddr_test.go +++ /dev/null @@ -1,594 +0,0 @@ -package sockaddr_test - -import ( - "fmt" - "net" - "os" - "strings" - "testing" - - sockaddr "github.com/hashicorp/go-sockaddr" -) - -func boolEnvVar(envvar string, emptyDefault bool) bool { - v := os.Getenv(envvar) - switch strings.ToLower(v) { - case "": - return emptyDefault - case "0", "f", "n": - return false - case "1", "t", "y": - return true - default: - fmt.Fprintf(os.Stderr, "Unsupported %s flag %q", envvar, v) - return true - } -} - -// havePrivateIP is a helper function that returns true when we believe we -// should have a private IP address. This changes the failure mode of various -// tests that expect a private IP address. -// -// When you have a private IP assigned to the host, set the environment variable -// SOCKADDR_HAVE_PRIVATE_IP=1 -func havePrivateIP() bool { - return boolEnvVar("SOCKADDR_HAVE_PRIVATE_IP", true) -} - -// havePublicIP is a helper function that returns true when we believe we should -// have a public IP address. This changes the failure mode of various tests -// that expect a public IP address. -// -// When you have a public IP assigned to the host, set the environment variable -// SOCKADDR_HAVE_PUBLIC_IP=1 -func havePublicIP() bool { - return boolEnvVar("SOCKADDR_HAVE_PUBLIC_IP", false) -} - -func TestGetPrivateIP(t *testing.T) { - reportOnPrivate := func(args ...interface{}) { - if havePrivateIP() { - t.Fatalf(args[0].(string), args[1:]...) - } else { - t.Skipf(args[0].(string), args[1:]...) - } - } - ip, err := sockaddr.GetPrivateIP() - if err != nil { - reportOnPrivate("unable to get a private IP: %v", err) - } - - if ip == "" { - reportOnPrivate("it's hard to test this reliably") - } -} - -func TestGetPrivateIPs(t *testing.T) { - reportOnPrivate := func(args ...interface{}) { - if havePrivateIP() { - t.Fatalf(args[0].(string), args[1:]...) - } else { - t.Skipf(args[0].(string), args[1:]...) - } - } - ips, err := sockaddr.GetPrivateIPs() - if err != nil { - reportOnPrivate("unable to get a private IPs: %v", err) - } - - if ips == "" { - reportOnPrivate("it's hard to test this reliably") - } -} - -func TestGetPublicIP(t *testing.T) { - reportOnPublic := func(args ...interface{}) { - if havePublicIP() { - t.Fatalf(args[0].(string), args[1:]...) - } else { - t.Skipf(args[0].(string), args[1:]...) - } - } - ip, err := sockaddr.GetPublicIP() - if err != nil { - reportOnPublic("unable to get a public IP: %v", err) - } - - if ip == "" { - reportOnPublic("it's hard to test this reliably") - } -} - -func TestGetPublicIPs(t *testing.T) { - reportOnPublic := func(args ...interface{}) { - if havePublicIP() { - t.Fatalf(args[0].(string), args[1:]...) - } else { - t.Skipf(args[0].(string), args[1:]...) - } - } - ips, err := sockaddr.GetPublicIPs() - if err != nil { - reportOnPublic("unable to get a public IPs: %v", err) - } - - if ips == "" { - reportOnPublic("it's hard to test this reliably") - } -} - -func TestGetInterfaceIP(t *testing.T) { - ip, err := sockaddr.GetInterfaceIP(`^.*[\d]$`) - if err != nil { - t.Fatalf("regexp failed: %v", err) - } - - if ip == "" { - t.Skip("it's hard to test this reliably") - } -} - -func TestIfAddrAttr(t *testing.T) { - tests := []struct { - name string - ifAddr sockaddr.IfAddr - attr string - expected string - }{ - { - name: "name", - ifAddr: sockaddr.IfAddr{ - Interface: net.Interface{ - Name: "abc0", - }, - }, - attr: "name", - expected: "abc0", - }, - } - - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d must have a name", i) - } - - result, err := sockaddr.IfAttr(test.attr, test.ifAddr) - if err != nil { - t.Errorf("failed to get attr %q from %v", test.name, test.ifAddr) - } - - if result != test.expected { - t.Errorf("unexpected result") - } - } -} - -func TestIfAddrMath(t *testing.T) { - tests := []struct { - name string - ifAddr sockaddr.IfAddr - operation string - value string - expected string - wantFail bool - }{ - { - name: "ipv4 address +2", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("127.0.0.1/8"), - }, - operation: "address", - value: "+2", - expected: "127.0.0.3/8", - }, - { - name: "ipv4 address -2", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("127.0.0.1/8"), - }, - operation: "address", - value: "-2", - expected: "126.255.255.255/8", - }, - { - name: "ipv4 address + overflow 0xff00ff03", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("127.0.0.1/8"), - }, - operation: "address", - value: fmt.Sprintf("+%d", 0xff00ff03), - expected: "126.0.255.4/8", - }, - { - name: "ipv4 address - underflow 0xff00ff04", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("127.0.0.1/8"), - }, - operation: "address", - value: fmt.Sprintf("-%d", 0xff00ff04), - expected: "127.255.0.253/8", - }, - { - name: "ipv6 address +2", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("::1/128"), - }, - operation: "address", - value: "+2", - expected: "::3", - }, - { - name: "ipv6 address -3", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("::4/128"), - }, - operation: "address", - value: "-3", - expected: "::1", - }, - { - name: "ipv6 address + overflow", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"), - }, - operation: "address", - value: fmt.Sprintf("+%d", 0x03), - expected: "::2", - }, - { - name: "ipv6 address + underflow", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("::1/128"), - }, - operation: "address", - value: fmt.Sprintf("-%d", 0x03), - expected: "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe", - }, - { - name: "ipv4 network +2", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("127.0.0.1/8"), - }, - operation: "network", - value: "+2", - expected: "127.0.0.2/8", - }, - { - name: "ipv4 network -2", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("127.0.0.1/8"), - }, - operation: "network", - value: "-2", - expected: "127.255.255.254/8", - }, - { - // Value exceeds /8 - name: "ipv4 network + overflow 0xff00ff03", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("127.0.0.1/8"), - }, - operation: "network", - value: fmt.Sprintf("+%d", 0xff00ff03), - expected: "127.0.255.3/8", - }, - { - // Value exceeds /8 - name: "ipv4 network - underflow+wrap 0xff00ff04", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("127.0.0.1/8"), - }, - operation: "network", - value: fmt.Sprintf("-%d", 0xff00ff04), - expected: "127.255.0.252/8", - }, - { - name: "ipv6 network +6", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("fe80::1/64"), - }, - operation: "network", - value: "+6", - expected: "fe80::6/64", - }, - { - name: "ipv6 network -6", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("fe80::ff/64"), - }, - operation: "network", - value: "-6", - expected: "fe80::ffff:ffff:ffff:fffa/64", - }, - { - // Value exceeds /104 mask - name: "ipv6 network + overflow 0xff00ff03", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("fe80::1/104"), - }, - operation: "network", - value: fmt.Sprintf("+%d", 0xff00ff03), - expected: "fe80::ff03/104", - }, - { - // Value exceeds /104 - name: "ipv6 network - underflow+wrap 0xff00ff04", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("fe80::1/104"), - }, - operation: "network", - value: fmt.Sprintf("-%d", 0xff00ff04), - expected: "fe80::ff:fc/104", - }, - { - name: "ipv4 address missing sign", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("127.0.0.1/8"), - }, - operation: "address", - value: "123", - wantFail: true, - }, - { - name: "ipv4 network missing sign", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("127.0.0.1/8"), - }, - operation: "network", - value: "123", - wantFail: true, - }, - { - name: "ipv6 address missing sign", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("::1/128"), - }, - operation: "address", - value: "123", - wantFail: true, - }, - { - name: "ipv6 network missing sign", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("::1/128"), - }, - operation: "network", - value: "123", - wantFail: true, - }, - { - name: "ipv4 address bad value", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("127.0.0.1/8"), - }, - operation: "address", - value: "+xyz", - wantFail: true, - }, - { - name: "ipv4 network bad value", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("127.0.0.1/8"), - }, - operation: "network", - value: "-xyz", - wantFail: true, - }, - { - name: "ipv6 address bad value", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("::1/128"), - }, - operation: "address", - value: "+xyz", - wantFail: true, - }, - { - name: "ipv6 network bad value", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("::1/128"), - }, - operation: "network", - value: "-xyz", - wantFail: true, - }, - { - name: "ipv4 bad operation", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("127.0.0.1/8"), - }, - operation: "gooz", - value: "+xyz", - wantFail: true, - }, - { - name: "ipv6 bad operation", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("::1/128"), - }, - operation: "frabba", - value: "+xyz", - wantFail: true, - }, - { - name: "ipv4 mask operand equals input ipv4 subnet mask", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("10.20.30.40/8"), - }, - operation: "mask", - value: "8", - expected: "10.0.0.0/8", - }, - { - name: "ipv4 mask operand larger than input ipv4 subnet mask", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("192.168.10.20/24"), - }, - operation: "mask", - value: "16", - expected: "192.168.0.0/16", - }, - { - name: "ipv4 host upper bound mask operand larger than input ipv4 subnet mask", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("192.168.255.255/24"), - }, - operation: "mask", - value: "16", - expected: "192.168.0.0/16", - }, - { - name: "ipv4 mask operand smaller than ipv4 subnet mask", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("10.20.30.40/8"), - }, - operation: "mask", - value: "16", - expected: "10.20.0.0/8", - }, - { - name: "ipv4 host upper bound mask operand smaller than input ipv4 subnet mask", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("10.20.255.255/8"), - }, - operation: "mask", - value: "16", - expected: "10.20.0.0/8", - }, - { - name: "ipv4 mask bad value upper bound", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("127.0.0.1/8"), - }, - operation: "mask", - value: "33", - wantFail: true, - }, - { - name: "ipv4 mask bad value lower bound", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("127.0.0.1/8"), - }, - operation: "mask", - value: "-1", - wantFail: true, - }, - { - name: "ipv6 mask operand equals input ipv6 subnet mask", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("2001:0db8:85a3::8a2e:0370:7334/64"), - }, - operation: "mask", - value: "64", - expected: "2001:db8:85a3::/64", - }, - { - name: "ipv6 mask operand larger than input ipv6 subnet mask", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("2001:0db8:85a3::8a2e:0370:7334/64"), - }, - operation: "mask", - value: "32", - expected: "2001:db8::/32", - }, - { - name: "ipv6 mask operand smaller than input ipv6 subnet mask", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("2001:0db8:85a3::8a2e:0370:7334/64"), - }, - operation: "mask", - value: "96", - expected: "2001:db8:85a3::8a2e:0:0/64", - }, - { - name: "ipv6 mask bad value upper bound", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("::1/128"), - }, - operation: "mask", - value: "129", - wantFail: true, - }, - { - name: "ipv6 mask bad value lower bound", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("::1/128"), - }, - operation: "mask", - value: "-1", - wantFail: true, - }, - { - name: "unix unsupported operation", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustUnixSock("/tmp/bar"), - }, - operation: "address", - value: "+123", - wantFail: true, - }, - { - name: "unix unsupported operation", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustUnixSock("/tmp/foo"), - }, - operation: "network", - value: "+123", - wantFail: true, - }, - { - name: "unix unsupported operation", - ifAddr: sockaddr.IfAddr{ - SockAddr: sockaddr.MustUnixSock("/tmp/foo"), - }, - operation: "mask", - value: "8", - wantFail: true, - }, - } - - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d must have a name", i) - } - - results, err := sockaddr.IfAddrsMath(test.operation, test.value, sockaddr.IfAddrs{test.ifAddr}) - if test.wantFail { - if err != nil { - continue - } else { - t.Fatalf("%s: failed to fail math operation %q with value %q on %v", test.name, test.operation, test.value, test.ifAddr) - } - } else if err != nil { - t.Fatalf("%s: failed to compute math operation %q with value %q on %v", test.name, test.operation, test.value, test.ifAddr) - } - if len(results) != 1 { - t.Fatalf("%s: bad", test.name) - } - - result := results[0] - - switch saType := result.Type(); saType { - case sockaddr.TypeIPv4: - ipv4 := sockaddr.ToIPv4Addr(result.SockAddr) - if ipv4 == nil { - t.Fatalf("bad: %T %+#v", result, result) - } - - if got := ipv4.String(); got != test.expected { - t.Errorf("unexpected result %q: want %q got %q", test.name, test.expected, got) - } - case sockaddr.TypeIPv6: - ipv6 := sockaddr.ToIPv6Addr(result.SockAddr) - if ipv6 == nil { - t.Fatalf("bad: %T %+#v", result, result) - } - - if got := ipv6.String(); got != test.expected { - t.Errorf("unexpected result %q: want %q got %q", test.name, test.expected, got) - } - default: - t.Fatalf("bad") - } - } -} diff --git a/vendor/github.com/hashicorp/go-sockaddr/ifaddrs_test.go b/vendor/github.com/hashicorp/go-sockaddr/ifaddrs_test.go deleted file mode 100644 index d4bde6e36..000000000 --- a/vendor/github.com/hashicorp/go-sockaddr/ifaddrs_test.go +++ /dev/null @@ -1,1986 +0,0 @@ -package sockaddr_test - -import ( - "fmt" - "net" - "reflect" - "testing" - - sockaddr "github.com/hashicorp/go-sockaddr" -) - -const ( - // NOTE(seanc@): Assume "en0" is the interface with a default route attached - // to it. When this is not the case, change this one constant and tests - // should pass (i.e. "net0"). - ifNameWithDefault = "en0" -) - -// NOTE: A number of these code paths are exercised in template/ and -// cmd/sockaddr/. -// -// TODO(sean@): Add better coverage for filtering functions (e.g. ExcludeBy*, -// IncludeBy*). - -func TestCmpIfAddrFunc(t *testing.T) { - tests := []struct { - name string - t1 sockaddr.IfAddr // must come before t2 according to the ascOp - t2 sockaddr.IfAddr - ascOp sockaddr.CmpIfAddrFunc - ascResult int - descOp sockaddr.CmpIfAddrFunc - descResult int - }{ - { - name: "empty test", - t1: sockaddr.IfAddr{}, - t2: sockaddr.IfAddr{}, - ascOp: sockaddr.AscIfAddress, - descOp: sockaddr.DescIfAddress, - ascResult: 0, - descResult: 0, - }, - { - name: "ipv4 address less", - t1: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.3"), - }, - t2: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - }, - ascOp: sockaddr.AscIfAddress, - descOp: sockaddr.DescIfAddress, - ascResult: -1, - descResult: -1, - }, - { - name: "ipv4 private", - t1: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("10.1.2.3"), - }, - t2: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("203.0.113.3"), - }, - ascOp: sockaddr.AscIfPrivate, - descOp: sockaddr.DescIfPrivate, - ascResult: 0, // not both private, can't complete the test - descResult: 0, - }, - { - name: "IfAddr name", - t1: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("10.1.2.3"), - Interface: net.Interface{ - Name: "abc0", - }, - }, - t2: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("203.0.113.3"), - Interface: net.Interface{ - Name: "xyz0", - }, - }, - ascOp: sockaddr.AscIfName, - descOp: sockaddr.DescIfName, - ascResult: -1, - descResult: -1, - }, - { - name: "IfAddr network size", - t1: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("10.0.0.0/8"), - }, - t2: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("127.0.0.0/24"), - }, - ascOp: sockaddr.AscIfNetworkSize, - descOp: sockaddr.DescIfNetworkSize, - ascResult: -1, - descResult: -1, - }, - { - name: "IfAddr port", - t1: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("10.0.0.0:80"), - }, - t2: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("127.0.0.0:8600"), - }, - ascOp: sockaddr.AscIfPort, - descOp: sockaddr.DescIfPort, - ascResult: -1, - descResult: -1, - }, - { - name: "IfAddr type", - t1: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("10.0.0.0:80"), - }, - t2: sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("[::1]:80"), - }, - ascOp: sockaddr.AscIfType, - descOp: sockaddr.DescIfType, - ascResult: -1, - descResult: -1, - }, - } - - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d must have a name", i) - } - - // Test ascending operation - ascExpected := test.ascResult - ascResult := test.ascOp(&test.t1, &test.t2) - if ascResult != ascExpected { - t.Errorf("%s: Unexpected result %d, expected %d when comparing %v and %v using %v", test.name, ascResult, ascExpected, test.t1, test.t2, test.ascOp) - } - - // Test descending operation - descExpected := test.descResult - descResult := test.descOp(&test.t2, &test.t1) - if descResult != descExpected { - t.Errorf("%s: Unexpected result %d, expected %d when comparing %v and %v using %v", test.name, descResult, descExpected, test.t1, test.t2, test.descOp) - } - - if ascResult != descResult { - t.Fatalf("bad") - } - - // Reverse the args - ascExpected = -1 * test.ascResult - ascResult = test.ascOp(&test.t2, &test.t1) - if ascResult != ascExpected { - t.Errorf("%s: Unexpected result %d, expected %d when comparing %v and %v using %v", test.name, ascResult, ascExpected, test.t1, test.t2, test.ascOp) - } - - descExpected = -1 * test.descResult - descResult = test.descOp(&test.t1, &test.t2) - if descResult != descExpected { - t.Errorf("%s: Unexpected result %d, expected %d when comparing %v and %v using %v", test.name, descResult, descExpected, test.t1, test.t2, test.descOp) - } - - if ascResult != descResult { - t.Fatalf("bad") - } - - // Test equality - ascExpected = 0 - ascResult = test.ascOp(&test.t1, &test.t1) - if ascResult != ascExpected { - t.Errorf("%s: Unexpected result %d, expected %d when comparing %v and %v using %v", test.name, ascResult, ascExpected, test.t1, test.t2, test.ascOp) - } - - descExpected = 0 - descResult = test.descOp(&test.t1, &test.t1) - if descResult != descExpected { - t.Errorf("%s: Unexpected result %d, expected %d when comparing %v and %v using %v", test.name, descResult, descExpected, test.t1, test.t2, test.descOp) - } - } -} - -func TestFilterIfByFlags(t *testing.T) { - tests := []struct { - name string - selector string - ifAddrs sockaddr.IfAddrs - flags net.Flags - fail bool - }{ - { - name: "broadcast", - selector: "broadcast", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{ - Flags: net.FlagBroadcast, - }, - SockAddr: sockaddr.MustIPv4Addr("1.2.3.1"), - }, - }, - }, - { - name: "down", - selector: "down", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{}, - SockAddr: sockaddr.MustIPv4Addr("1.2.3.2"), - }, - }, - }, - { - name: "forwardable IPv4", - selector: "forwardable", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{}, - SockAddr: sockaddr.MustIPv4Addr("1.2.3.3"), - }, - }, - }, - { - name: "forwardable IPv6", - selector: "forwardable", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{}, - SockAddr: sockaddr.MustIPv6Addr("cc::1/128"), - }, - }, - }, - { - name: "global unicast", - selector: "global unicast", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{}, - SockAddr: sockaddr.MustIPv6Addr("cc::2"), - }, - }, - }, - { - name: "interface-local multicast", - selector: "interface-local multicast", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{}, - SockAddr: sockaddr.MustIPv6Addr("ff01::2"), - }, - }, - }, - { - name: "link-local multicast", - selector: "link-local multicast", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{}, - SockAddr: sockaddr.MustIPv6Addr("ff02::3"), - }, - }, - }, - { - name: "link-local unicast IPv4", - selector: "link-local unicast", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{}, - SockAddr: sockaddr.MustIPv4Addr("169.254.1.101"), - }, - }, - }, - { - name: "link-local unicast IPv6", - selector: "link-local unicast", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{}, - SockAddr: sockaddr.MustIPv6Addr("fe80::3"), - }, - }, - }, - { - name: "loopback ipv4", - selector: "loopback", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{ - Flags: net.FlagLoopback, - }, - SockAddr: sockaddr.MustIPv4Addr("127.0.0.1"), - }, - }, - }, - { - name: "loopback ipv6", - selector: "loopback", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{ - Flags: net.FlagLoopback, - }, - SockAddr: sockaddr.MustIPv6Addr("::1"), - }, - }, - }, - { - name: "multicast IPv4", - selector: "multicast", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{ - Flags: net.FlagMulticast, - }, - SockAddr: sockaddr.MustIPv4Addr("224.0.0.1"), - }, - }, - }, - { - name: "multicast IPv6", - selector: "multicast", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{ - Flags: net.FlagMulticast, - }, - SockAddr: sockaddr.MustIPv6Addr("ff05::3"), - }, - }, - }, - { - name: "point-to-point", - selector: "point-to-point", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{ - Flags: net.FlagPointToPoint, - }, - SockAddr: sockaddr.MustIPv6Addr("cc::3"), - }, - }, - }, - { - name: "unspecified", - selector: "unspecified", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{}, - SockAddr: sockaddr.MustIPv6Addr("::"), - }, - }, - }, - { - name: "up", - selector: "up", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{ - Flags: net.FlagUp, - }, - SockAddr: sockaddr.MustIPv6Addr("cc::3"), - }, - }, - }, - { - name: "invalid", - selector: "foo", - fail: true, - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{}, - SockAddr: sockaddr.MustIPv6Addr("cc::3"), - }, - }, - }, - } - - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d needs a name", i) - } - - t.Run(test.name, func(t *testing.T) { - in, out, err := sockaddr.IfByFlag(test.selector, test.ifAddrs) - if test.fail == true && err == nil { - t.Fatalf("%s: expected failure", test.name) - } else if test.fail == true && err != nil { - return - } - - if err != nil && test.fail != true { - t.Fatalf("%s: failed: %v", test.name, err) - } - if ilen := len(in); ilen != 1 { - t.Fatalf("%s: wrong in length %d, expected 1", test.name, ilen) - } - if olen := len(out); olen != 0 { - t.Fatalf("%s: wrong in length %d, expected 0", test.name, olen) - } - }) - } -} - -func TestIfByNetwork(t *testing.T) { - tests := []struct { - name string - input sockaddr.IfAddrs - selector string - matched sockaddr.IfAddrs - excluded sockaddr.IfAddrs - fail bool - }{ - { - name: "exact match", - input: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - }, - }, - selector: "1.2.3.4", - matched: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - }, - }, - }, - { - name: "exact match plural", - input: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.0/24"), - }, - }, - selector: "1.2.3.0/24", - matched: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.0/24"), - }, - }, - }, - { - name: "split plural", - input: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("12.2.3.0/24"), - }, - }, - selector: "1.2.3.0/24", - excluded: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("12.2.3.0/24"), - }, - }, - matched: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - }, - }, - }, - { - name: "excluded plural", - input: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("12.2.3.0/24"), - }, - }, - selector: "10.0.0.0/8", - excluded: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("12.2.3.0/24"), - }, - }, - }, - { - name: "invalid selector", - input: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("12.2.3.0/24"), - }, - }, - selector: "[:]", - fail: true, - }, - } - - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d needs a name", i) - } - - t.Run(test.name, func(t *testing.T) { - matched, excluded, err := sockaddr.IfByNetwork(test.selector, test.input) - if err != nil && !test.fail { - t.Fatal("bad") - } else if err == nil && test.fail { - t.Fatal("bad") - } - - if len(test.matched) != len(matched) { - t.Fatal("bad") - } else if len(test.excluded) != len(excluded) { - t.Fatal("bad") - } - - for i := 0; i < len(test.excluded); i++ { - if !reflect.DeepEqual(test.excluded[i], excluded[i]) { - t.Errorf("wrong excluded: %d %v %v", i, test.excluded[i], excluded[i]) - } - } - - for i := 0; i < len(test.matched); i++ { - if !reflect.DeepEqual(test.matched[i], matched[i]) { - t.Errorf("wrong matched: %d %v %v", i, test.matched[i], matched[i]) - } - } - }) - } -} - -func TestFilterIfByType(t *testing.T) { - tests := []struct { - name string - ifAddrs sockaddr.IfAddrs - ifAddrType sockaddr.SockAddrType - matchedLen int - remainingLen int - }{ - { - name: "include all", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("2.3.4.5"), - }, - }, - ifAddrType: sockaddr.TypeIPv4, - matchedLen: 2, - remainingLen: 0, - }, - { - name: "include some", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("::1"), - }, - }, - ifAddrType: sockaddr.TypeIPv4, - matchedLen: 1, - remainingLen: 1, - }, - { - name: "exclude all", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.5"), - }, - }, - ifAddrType: sockaddr.TypeIPv6, - matchedLen: 0, - remainingLen: 2, - }, - } - - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d needs a name", i) - } - - in, out := sockaddr.FilterIfByType(test.ifAddrs, test.ifAddrType) - if len(in) != test.matchedLen { - t.Fatalf("%s: wrong length %d, expected %d", test.name, len(in), test.matchedLen) - } - - if len(out) != test.remainingLen { - t.Fatalf("%s: wrong length %d, expected %d", test.name, len(out), test.remainingLen) - } - } -} - -// TestGetIfAddrs runs through the motions of calling sockaddr.GetIfAddrs(), but -// doesn't do much in the way of testing beyond verifying that `lo0` has a -// loopback address present. -func TestGetIfAddrs(t *testing.T) { - ifAddrs, err := sockaddr.GetAllInterfaces() - if err != nil { - t.Fatalf("Unable to proceed: %v", err) - } - if len(ifAddrs) == 0 { - t.Skip() - } - - var loInt *sockaddr.IfAddr - for _, ifAddr := range ifAddrs { - val := sockaddr.IfAddrAttr(ifAddr, "name") - if val == "" { - t.Fatalf("name failed") - } else if val == "lo0" || val == "lo" || val == "Loopback Pseudo-Interface 1" { - loInt = &ifAddr - break - } - } - if loInt == nil { - t.Fatalf("No loopback interfaces found, loInt nil") - } - - if val := sockaddr.IfAddrAttr(*loInt, "flags"); !(val == "up|loopback|multicast" || val == "up|loopback") { - t.Fatalf("expected different flags from loopback: %q", val) - } - - if loInt == nil { - t.Fatalf("Expected to find an lo0 interface, didn't find any") - } - - haveIPv4, foundIPv4lo := false, false - haveIPv6, foundIPv6lo := false, false - switch loInt.SockAddr.(type) { - case sockaddr.IPv4Addr: - haveIPv4 = true - - // Make the semi-brittle assumption that if we have - // IPv4, we also have an address at 127.0.0.1 available - // to us. - if loInt.SockAddr.String() == "127.0.0.1/8" { - foundIPv4lo = true - } - case sockaddr.IPv6Addr: - haveIPv6 = true - if loInt.SockAddr.String() == "::1" { - foundIPv6lo = true - } - default: - t.Fatalf("Unsupported type %v for address %v", loInt.Type(), loInt) - } - - // While not wise, it's entirely possible a host doesn't have IPv4 - // enabled. - if haveIPv4 && !foundIPv4lo { - t.Fatalf("Had an IPv4 w/o an expected IPv4 loopback addresses") - } - - // While prudent to run without, a sane environment may still contain an - // IPv6 loopback address. - if haveIPv6 && !foundIPv6lo { - t.Fatalf("Had an IPv6 w/o an expected IPv6 loopback addresses") - } -} - -// TestGetDefaultIfName tests to make sure a default interface name is always -// returned from getDefaultIfName(). -func TestGetDefaultInterface(t *testing.T) { - reportOnDefault := func(args ...interface{}) { - if havePublicIP() || havePrivateIP() { - t.Fatalf(args[0].(string), args[1:]...) - } else { - t.Skipf(args[0].(string), args[1:]...) - } - } - - ifAddrs, err := sockaddr.GetDefaultInterfaces() - if err != nil { - switch { - case len(ifAddrs) == 0: - reportOnDefault("bad: %v", err) - case ifAddrs[0].Flags&net.FlagUp == 0: - reportOnDefault("bad: %v", err) - default: - reportOnDefault("bad: %v", err) - } - } -} - -func TestIfAddrAttrs(t *testing.T) { - const expectedNumAttrs = 2 - attrs := sockaddr.IfAddrAttrs() - if len(attrs) != expectedNumAttrs { - t.Fatalf("wrong number of attrs") - } - - tests := []struct { - name string - ifAddr sockaddr.IfAddr - attr string - expected string - }{ - { - name: "name", - ifAddr: sockaddr.IfAddr{ - Interface: net.Interface{ - Name: "abc0", - }, - }, - attr: "name", - expected: "abc0", - }, - } - - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d must have a name", i) - } - - result, err := sockaddr.IfAttrs(test.attr, sockaddr.IfAddrs{test.ifAddr}) - if err != nil { - t.Errorf("failed to get attr %q from %v", test.name, test.ifAddr) - } - - if result != test.expected { - t.Errorf("unexpected result") - } - } - - // Test an empty array - result, err := sockaddr.IfAttrs("name", sockaddr.IfAddrs{}) - if err != nil { - t.Error(`failed to get attr "name" from an empty array`) - } - - if result != "" { - t.Errorf("unexpected result") - } -} - -func TestGetAllInterfaces(t *testing.T) { - ifAddrs, err := sockaddr.GetAllInterfaces() - if err != nil { - t.Fatalf("unable to gather interfaces: %v", err) - } - - initialLen := len(ifAddrs) - if initialLen == 0 { - t.Fatalf("no interfaces available") - } - - ifAddrs, err = sockaddr.SortIfBy("name,type,port,size,address", ifAddrs) - if err != nil { - t.Fatalf("unable to initially sort address") - } - - ascSorted, err := sockaddr.SortIfBy("name,type,port,size,address", ifAddrs) - if err != nil { - t.Fatalf("unable to asc sort address") - } - - descSorted, err := sockaddr.SortIfBy("name,type,port,size,-address", ascSorted) - if err != nil { - t.Fatalf("unable to desc sort address") - } - - if initialLen != len(ascSorted) && len(ascSorted) != len(descSorted) { - t.Fatalf("wrong len") - } - - for i := initialLen - 1; i >= 0; i-- { - if !reflect.DeepEqual(descSorted[i], ifAddrs[i]) { - t.Errorf("wrong sort order: %d %v %v", i, descSorted[i], ifAddrs[i]) - } - } -} - -func TestGetDefaultInterfaces(t *testing.T) { - reportOnDefault := func(args ...interface{}) { - if havePublicIP() || havePrivateIP() { - t.Fatalf(args[0].(string), args[1:]...) - } else { - t.Skipf(args[0].(string), args[1:]...) - } - } - - ifAddrs, err := sockaddr.GetDefaultInterfaces() - if err != nil { - reportOnDefault("unable to gather default interfaces: %v", err) - } - - if len(ifAddrs) == 0 { - reportOnDefault("no default interfaces available", nil) - } -} - -func TestGetPrivateInterfaces(t *testing.T) { - reportOnPrivate := func(args ...interface{}) { - if havePrivateIP() { - t.Fatalf(args[0].(string), args[1:]...) - } else { - t.Skipf(args[0].(string), args[1:]...) - } - } - - ifAddrs, err := sockaddr.GetPrivateInterfaces() - if err != nil { - reportOnPrivate("failed: %v", err) - } - - if len(ifAddrs) == 0 { - reportOnPrivate("no public IPs found") - } - - if len(ifAddrs[0].String()) == 0 { - reportOnPrivate("no string representation of private IP found") - } -} - -func TestGetPublicInterfaces(t *testing.T) { - reportOnPublic := func(args ...interface{}) { - if havePublicIP() { - t.Fatalf(args[0].(string), args[1:]...) - } else { - t.Skipf(args[0].(string), args[1:]...) - } - } - - ifAddrs, err := sockaddr.GetPublicInterfaces() - if err != nil { - reportOnPublic("failed: %v", err) - } - - if len(ifAddrs) == 0 { - reportOnPublic("no public IPs found") - } -} - -func TestIncludeExcludeIfs(t *testing.T) { - tests := []struct { - name string - ifAddrs sockaddr.IfAddrs - fail bool - excludeNum int - excludeName string - excludeParam string - includeName string - includeParam string - includeNum int - }{ - { - name: "address", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("2.3.4.5"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("3.4.5.6"), - }, - }, - excludeName: "address", - excludeNum: 2, - excludeParam: `^1\..*\.4$`, - includeName: "address", - includeNum: 1, - includeParam: `^1\.2\.3\.`, - }, - { - name: "address invalid", - fail: true, - excludeName: "address", - excludeNum: 0, - excludeParam: `*`, - includeName: "address", - includeNum: 0, - includeParam: `[`, - }, - { - name: "flag", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{ - Flags: net.FlagUp | net.FlagLoopback, - }, - }, - sockaddr.IfAddr{ - Interface: net.Interface{ - Flags: net.FlagLoopback, - }, - }, - sockaddr.IfAddr{ - Interface: net.Interface{ - Flags: net.FlagMulticast, - }, - }, - }, - excludeName: "flags", - excludeNum: 2, - excludeParam: `up|loopback`, - includeName: "flags", - includeNum: 2, - includeParam: `loopback`, - }, - { - name: "flag invalid", - fail: true, - excludeName: "foo", - excludeNum: 0, - excludeParam: `*`, - includeName: "bar", - includeNum: 0, - includeParam: `[`, - }, - { - name: "name", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - Interface: net.Interface{ - Name: "abc0", - }, - }, - sockaddr.IfAddr{ - Interface: net.Interface{ - Name: "xyz0", - }, - }, - sockaddr.IfAddr{ - Interface: net.Interface{ - Name: "docker666", - }, - }, - }, - excludeName: "name", - excludeNum: 2, - excludeParam: `^docker[\d]+$`, - includeName: "name", - includeNum: 2, - includeParam: `^([a-z]+)0$`, - }, - { - name: "name invalid", - fail: true, - excludeName: "name", - excludeNum: 0, - excludeParam: `*`, - includeName: "name", - includeNum: 0, - includeParam: `[`, - }, - { - name: "network", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("10.2.3.4/24"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("10.255.255.4/24"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPAddr("::1"), - }, - }, - excludeName: "network", - excludeNum: 1, - excludeParam: `10.0.0.0/8`, - includeName: "network", - includeNum: 1, - includeParam: `::/127`, - }, - { - name: "port", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:8600"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("2.3.4.5:4646"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("3.4.5.6:4647"), - }, - }, - excludeName: "port", - excludeNum: 2, - excludeParam: `0$`, - includeName: "port", - includeNum: 2, - includeParam: `^46[\d]{2}$`, - }, - { - name: "port invalid", - fail: true, - excludeName: "port", - excludeNum: 0, - excludeParam: `*`, - includeName: "port", - includeNum: 0, - includeParam: `[`, - }, - { - name: "rfc", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("10.2.3.4/24"), - }, - sockaddr.IfAddr{ - // Excluded (/127 vs /128) - SockAddr: sockaddr.MustIPv6Addr("::1/127"), - }, - sockaddr.IfAddr{ - // Excluded (/127 vs /128) - SockAddr: sockaddr.MustIPv6Addr("::/127"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPAddr("203.0.113.0/24"), - }, - }, - excludeName: "rfc", - excludeNum: 2, - excludeParam: `6890`, - includeName: "rfc", - includeNum: 1, - includeParam: `3330`, - }, - { - name: "rfc invalid", - fail: true, - excludeName: "rfc", - excludeNum: 0, - excludeParam: `rfcOneTwoThree`, - includeName: "rfc", - includeNum: 0, - includeParam: `99999999999999`, - }, - { - name: "rfc IPv4 exclude", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("192.169.1.1"), - }, - }, - excludeName: "rfc", - excludeNum: 1, - excludeParam: `1918`, - includeName: "rfc", - includeNum: 0, - includeParam: `1918`, - }, - { - name: "rfc IPv4 include", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("192.168.1.1"), - }, - }, - excludeName: "rfc", - excludeNum: 0, - excludeParam: `1918`, - includeName: "rfc", - includeNum: 1, - includeParam: `1918`, - }, - { - name: "rfc IPv4 excluded RFCs", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("192.168.1.1"), - }, - }, - excludeName: "rfc", - excludeNum: 1, - excludeParam: `4291`, - includeName: "rfc", - includeNum: 0, - includeParam: `4291`, - }, - { - name: "rfc IPv6 exclude", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("cc::1/127"), - }, - }, - excludeName: "rfc", - excludeNum: 1, - excludeParam: `4291`, - includeName: "rfc", - includeNum: 0, - includeParam: `4291`, - }, - { - name: "rfc IPv6 include", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("::1/127"), - }, - }, - excludeName: "rfc", - excludeNum: 0, - excludeParam: `4291`, - includeName: "rfc", - includeNum: 1, - includeParam: `4291`, - }, - { - name: "rfc zero match", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - }, - }, - excludeName: "rfc", - excludeNum: 1, - excludeParam: `1918`, - includeName: "rfc", - includeNum: 0, - includeParam: `1918`, - }, - { - name: "rfc empty list", - ifAddrs: sockaddr.IfAddrs{}, - excludeName: "rfc", - excludeNum: 0, - excludeParam: `4291`, - includeName: "rfc", - includeNum: 0, - includeParam: `1918`, - }, - { - name: "size", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("10.2.3.4/24"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPAddr("203.0.113.0/24"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("::1/24"), - }, - }, - excludeName: "size", - excludeParam: `24`, - excludeNum: 0, - includeName: "size", - includeParam: `24`, - includeNum: 3, - }, - { - name: "size invalid", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("10.2.3.4/24"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("::1/128"), - }, - }, - fail: true, - excludeName: "size", - excludeParam: `33`, - excludeNum: 0, - includeName: "size", - includeParam: `-1`, - includeNum: 0, - }, - { - name: "type", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("10.2.3.4/24"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPAddr("203.0.113.0/24"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv6Addr("::1/127"), - }, - }, - excludeName: "type", - excludeParam: `ipv6`, - excludeNum: 2, - includeName: "type", - includeParam: `ipv4`, - includeNum: 2, - }, - { - name: "type", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("10.2.3.4/24"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPAddr("::1"), - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustUnixSock("/tmp/foo"), - }, - }, - excludeName: "type", - excludeParam: `ip`, - excludeNum: 1, - includeName: "type", - includeParam: `unix`, - includeNum: 1, - }, - { - name: "type invalid arg", - fail: true, - excludeName: "type", - excludeParam: `*`, - excludeNum: 0, - includeName: "type", - includeParam: `[`, - includeNum: 0, - }, - { - name: "type invalid", - fail: true, - excludeName: "foo", - excludeParam: `bar`, - excludeNum: 0, - includeName: "baz", - includeParam: `bur`, - includeNum: 0, - }, - } - - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d must have a name", i) - } - t.Run(fmt.Sprintf("%s-%s", test.name, "include"), func(t *testing.T) { - t.Logf("test.ifAddrs: %v", test.ifAddrs) - inIfAddrs, err := sockaddr.IncludeIfs(test.includeName, test.includeParam, test.ifAddrs) - t.Logf("inIfAddrs: %v", inIfAddrs) - - switch { - case !test.fail && err != nil: - t.Errorf("%s: failed unexpectedly: %v", test.name, err) - case test.fail && err == nil: - t.Errorf("%s: failed to throw an error", test.name) - case test.fail && err != nil: - // expected test failure - return - } - - if len(inIfAddrs) != test.includeNum { - t.Errorf("%s: failed include length check. Expected %d, got %d. Input: %q", test.name, test.includeNum, len(inIfAddrs), test.includeParam) - } - }) - - t.Run(fmt.Sprintf("%s-%s", test.name, "exclude"), func(t *testing.T) { - t.Logf("test.ifAddrs: %v", test.ifAddrs) - outIfAddrs, err := sockaddr.ExcludeIfs(test.excludeName, test.excludeParam, test.ifAddrs) - t.Logf("outIfAddrs: %v", outIfAddrs) - - switch { - case !test.fail && err != nil: - t.Errorf("%s: failed unexpectedly: %v", test.name, err) - case test.fail && err == nil: - t.Errorf("%s: failed to throw an error", test.name) - case test.fail && err != nil: - // expected test failure - return - } - - if len(outIfAddrs) != test.excludeNum { - t.Errorf("%s: failed exclude length check. Expected %d, got %d. Input: %q", test.name, test.excludeNum, len(outIfAddrs), test.excludeParam) - } - }) - } -} - -func TestNewIPAddr(t *testing.T) { - tests := []struct { - name string - input string - output string - pass bool - }{ - { - name: "ipv4", - input: "1.2.3.4", - output: "1.2.3.4", - pass: true, - }, - { - name: "ipv6", - input: "::1", - output: "::1", - pass: true, - }, - { - name: "invalid", - input: "255.255.255.256", - output: "", - pass: false, - }, - } - - for _, test := range tests { - ip, err := sockaddr.NewIPAddr(test.input) - switch { - case err == nil && test.pass, - err != nil && !test.pass: - - default: - t.Errorf("expected %s's success to be %t", test.input, test.pass) - } - - if !test.pass { - continue - } - - if ip.String() != test.output { - t.Errorf("Expected %q to match %q", ip.String(), test.output) - } - - } -} - -func TestIPAttrs(t *testing.T) { - const expectedIPAttrs = 11 - ipAttrs := sockaddr.IPAttrs() - if len(ipAttrs) != expectedIPAttrs { - t.Fatalf("wrong number of args") - } -} - -func TestUniqueIfAddrsBy(t *testing.T) { - tests := []struct { - name string - ifAddrs sockaddr.IfAddrs - fail bool - selector string - expected []string - }{ - { - name: "address", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPAddr("203.0.113.0/24"), - Interface: net.Interface{ - Name: "abc0", - }, - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPAddr("203.0.113.0/24"), - Interface: net.Interface{ - Name: "abc0", - }, - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPAddr("10.2.3.4"), - Interface: net.Interface{ - Name: "foo1", - }, - }, - }, - selector: "address", - expected: []string{"203.0.113.0/24 {0 0 abc0 0}", "10.2.3.4 {0 0 foo1 0}"}, - }, - { - name: "name", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPAddr("::1"), - Interface: net.Interface{ - Name: "lo0", - }, - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPAddr("fe80::1"), - Interface: net.Interface{ - Name: "lo0", - }, - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPAddr("127.0.0.1"), - Interface: net.Interface{ - Name: "foo1", - }, - }, - }, - selector: "name", - expected: []string{"::1 {0 0 lo0 0}", "127.0.0.1 {0 0 foo1 0}"}, - }, - { - name: "invalid", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{}, - }, - fail: true, - selector: "goozfraba", - expected: []string{}, - }, - } - - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d must have a name", i) - } - t.Run(test.name, func(t *testing.T) { - - uniqueAddrs, err := sockaddr.UniqueIfAddrsBy(test.selector, test.ifAddrs) - switch { - case !test.fail && err != nil: - t.Fatalf("%s: failed unexpectedly: %v", test.name, err) - case test.fail && err == nil: - t.Fatalf("%s: failed to throw an error", test.name) - case test.fail && err != nil: - // expected test failure - return - } - - if len(uniqueAddrs) != len(test.expected) { - t.Fatalf("%s: failed uniquify by attribute %s", test.name, test.selector) - } - - for i := 0; i < len(uniqueAddrs); i++ { - got := uniqueAddrs[i].String() - if got != test.expected[i] { - t.Fatalf("%s: expected %q got %q", test.name, test.expected[i], got) - } - } - - }) - } -} - -func TestJoinIfAddrsBy(t *testing.T) { - tests := []struct { - name string - ifAddrs sockaddr.IfAddrs - fail bool - selector string - joinStr string - expected string - }{ - { - name: "address", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPAddr("203.0.113.0/24"), - Interface: net.Interface{ - Name: "abc0", - }, - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPAddr("203.0.113.1"), - Interface: net.Interface{ - Name: "abc0", - }, - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPAddr("10.2.3.4"), - Interface: net.Interface{ - Name: "foo1", - }, - }, - }, - selector: "address", - joinStr: " ", - expected: "203.0.113.0 203.0.113.1 10.2.3.4", - }, - { - name: "name", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPAddr("::1"), - Interface: net.Interface{ - Name: "lo0", - }, - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPAddr("fe80::1"), - Interface: net.Interface{ - Name: "foo0", - }, - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPAddr("127.0.0.1"), - Interface: net.Interface{ - Name: "bar2", - }, - }, - }, - selector: "name", - joinStr: "-/-", - expected: "lo0-/-foo0-/-bar2", - }, - { - name: "invalid", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPAddr("127.0.0.1"), - Interface: net.Interface{ - Name: "bar2", - }, - }, - }, - fail: true, - selector: "goozfraba", - expected: "", - }, - } - - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d must have a name", i) - } - t.Run(test.name, func(t *testing.T) { - - result, err := sockaddr.JoinIfAddrs(test.selector, test.joinStr, test.ifAddrs) - switch { - case !test.fail && err != nil: - t.Fatalf("%s: failed unexpectedly: %v", test.name, err) - case test.fail && err == nil: - t.Fatalf("%s: failed to throw an error", test.name) - case test.fail && err != nil: - // expected test failure - return - } - - if result != test.expected { - t.Fatalf("%s: expected %q got %q", test.name, test.expected, result) - } - - }) - } -} - -func TestLimitOffset(t *testing.T) { - tests := []struct { - name string - ifAddrs sockaddr.IfAddrs - limit uint - offset int - fail bool - expected sockaddr.IfAddrs - }{ - { - name: "basic limit offset", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.0/24")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.1")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.2")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.3")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.4")}, - }, - limit: 2, - offset: 1, - expected: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.1")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.2")}, - }, - }, - { - name: "negative offset with limit", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.0/24")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.1")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.2")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.3")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.4")}, - }, - limit: 2, - offset: -3, - expected: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.2")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.3")}, - }, - }, - { - name: "large limit", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.0/24")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.1")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.2")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.3")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.4")}, - }, - limit: 100, - offset: 3, - expected: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.3")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.4")}, - }, - }, - { - name: "bigger offset than size", - ifAddrs: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.0/24")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPAddr("203.0.113.1")}, - }, - fail: true, - limit: 1, - offset: 3, - }, - } - - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d must have a name", i) - } - t.Run(test.name, func(t *testing.T) { - - offsetResults, err := sockaddr.OffsetIfAddrs(test.offset, test.ifAddrs) - switch { - case !test.fail && err != nil: - t.Fatalf("%s: failed unexpectedly: %v", test.name, err) - case test.fail && err == nil: - t.Fatalf("%s: failed to throw an error", test.name) - case test.fail && err != nil: - // expected test failure - return - } - - limitResults, err := sockaddr.LimitIfAddrs(test.limit, offsetResults) - switch { - case !test.fail && err != nil: - t.Fatalf("%s: failed unexpectedly: %v", test.name, err) - case test.fail && err == nil: - t.Fatalf("%s: failed to throw an error", test.name) - case test.fail && err != nil: - // expected test failure - return - } - - if len(test.expected) != len(limitResults) { - t.Fatalf("bad") - } - - for i := 0; i < len(test.expected); i++ { - if !reflect.DeepEqual(limitResults[i], test.expected[i]) { - t.Errorf("objects in ordered limit") - } - } - }) - } -} - -func TestSortIfBy(t *testing.T) { - tests := []struct { - name string - sortStr string - in sockaddr.IfAddrs - out sockaddr.IfAddrs - fail bool - }{ - { - name: "sort address", - sortStr: "address", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.3")}, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.3")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4")}, - }, - }, - { - name: "sort +address", - sortStr: "+address", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.3")}, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.3")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4")}, - }, - }, - { - name: "sort -address", - sortStr: "-address", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.3")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4")}, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.3")}, - }, - }, - { - // NOTE(seanc@): This test requires macOS, or at least a computer where - // en0 has the default route. - name: "sort default", - sortStr: "default", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - Interface: net.Interface{Name: ifNameWithDefault}, - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.3"), - Interface: net.Interface{Name: "other0"}, - }, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - Interface: net.Interface{Name: ifNameWithDefault}, - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.3"), - Interface: net.Interface{Name: "other0"}, - }, - }, - }, - { - // NOTE(seanc@): This test requires macOS, or at least a computer where - // en0 has the default route. - name: "sort +default", - sortStr: "+default", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - Interface: net.Interface{Name: "other0"}, - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.3"), - Interface: net.Interface{Name: ifNameWithDefault}, - }, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.3"), - Interface: net.Interface{Name: ifNameWithDefault}, - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - Interface: net.Interface{Name: "other0"}, - }, - }, - }, - { - name: "sort -default", - sortStr: "-default", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.3"), - Interface: net.Interface{Name: ifNameWithDefault}, - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - Interface: net.Interface{Name: "other0"}, - }, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.4"), - Interface: net.Interface{Name: "other0"}, - }, - sockaddr.IfAddr{ - SockAddr: sockaddr.MustIPv4Addr("1.2.3.3"), - Interface: net.Interface{Name: ifNameWithDefault}, - }, - }, - }, - { - name: "sort name", - sortStr: "name", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{Interface: net.Interface{Name: "foo"}}, - sockaddr.IfAddr{Interface: net.Interface{Name: "bar"}}, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{Interface: net.Interface{Name: "bar"}}, - sockaddr.IfAddr{Interface: net.Interface{Name: "foo"}}, - }, - }, - { - name: "sort +name", - sortStr: "+name", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{Interface: net.Interface{Name: "foo"}}, - sockaddr.IfAddr{Interface: net.Interface{Name: "bar"}}, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{Interface: net.Interface{Name: "bar"}}, - sockaddr.IfAddr{Interface: net.Interface{Name: "foo"}}, - }, - }, - { - name: "sort -name", - sortStr: "-name", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{Interface: net.Interface{Name: "bar"}}, - sockaddr.IfAddr{Interface: net.Interface{Name: "foo"}}, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{Interface: net.Interface{Name: "foo"}}, - sockaddr.IfAddr{Interface: net.Interface{Name: "bar"}}, - }, - }, - { - name: "sort port", - sortStr: "port", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv6Addr("[::1]:53")}, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv6Addr("[::1]:53")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - }, - }, - { - name: "sort +port", - sortStr: "+port", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv6Addr("[::1]:53")}, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv6Addr("[::1]:53")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - }, - }, - { - name: "sort -port", - sortStr: "-port", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv6Addr("[::1]:53")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv6Addr("[::1]:53")}, - }, - }, - { - name: "sort private", - sortStr: "private", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("192.168.1.1")}, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("192.168.1.1")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - }, - }, - { - name: "sort +private", - sortStr: "+private", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("192.168.1.1")}, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("192.168.1.1")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - }, - }, - { - name: "sort -private", - sortStr: "-private", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("192.168.1.1")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("192.168.1.1")}, - }, - }, - { - name: "sort size", - sortStr: "size", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("192.168.1.1/27")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("192.168.1.1/27")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - }, - }, - { - name: "sort +size", - sortStr: "+size", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("192.168.1.1/27")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("192.168.1.1/27")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - }, - }, - { - name: "sort -size", - sortStr: "-size", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("192.168.1.1/27")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("192.168.1.1/27")}, - }, - }, - { - name: "sort type", - sortStr: "type", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv6Addr("::1")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("192.168.1.1/27")}, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("192.168.1.1/27")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv6Addr("::1")}, - }, - }, - { - name: "sort +type", - sortStr: "+type", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv6Addr("::1")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("192.168.1.1/27")}, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("192.168.1.1/27")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv6Addr("::1")}, - }, - }, - { - name: "sort -type", - sortStr: "-type", - in: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv6Addr("::1")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - }, - out: sockaddr.IfAddrs{ - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv6Addr("::1")}, - sockaddr.IfAddr{SockAddr: sockaddr.MustIPv4Addr("1.2.3.4:80")}, - }, - }, - { - name: "sort invalid", - sortStr: "ENOENT", - fail: true, - }, - } - - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d needs a name", i) - } - - t.Run(test.name, func(t *testing.T) { - sorted, err := sockaddr.SortIfBy(test.sortStr, test.in) - if err != nil && !test.fail { - t.Fatalf("%s: sort failed: %v", test.name, err) - } - - if len(test.in) != len(sorted) { - t.Fatalf("wrong len") - } - - for i := 0; i < len(sorted); i++ { - if !reflect.DeepEqual(sorted[i], test.out[i]) { - t.Errorf("wrong sort order: %d %v %v", i, sorted[i], test.out[i]) - } - } - }) - } -} diff --git a/vendor/github.com/hashicorp/go-sockaddr/ifattr_test.go b/vendor/github.com/hashicorp/go-sockaddr/ifattr_test.go deleted file mode 100644 index cf6ba08c2..000000000 --- a/vendor/github.com/hashicorp/go-sockaddr/ifattr_test.go +++ /dev/null @@ -1,112 +0,0 @@ -package sockaddr_test - -import ( - "testing" - - sockaddr "github.com/hashicorp/go-sockaddr" -) - -func TestIfAttr_net(t *testing.T) { - ifAddrs, err := sockaddr.GetAllInterfaces() - if err != nil { - t.Fatalf("Unable to proceed: %v", err) - } - - for _, ifAddr := range ifAddrs { - testSockAddrAttr(t, ifAddr) - } -} - -func TestIfAttr_unix(t *testing.T) { - newUnixSock := func(path string) sockaddr.UnixSock { - sa, err := sockaddr.NewUnixSock(path) - if err != nil { - t.Fatalf("unable to create new unix socket: %v", err) - } - return sa - } - unixSockets := []sockaddr.SockAddr{ - newUnixSock("/tmp/test"), - } - - for _, sa := range unixSockets { - testSockAddrAttr(t, sa) - } -} - -func testSockAddrAttr(t *testing.T, sai interface{}) { - attrNamesPerType := []struct { - name sockaddr.AttrName - ipv4Pass bool - ipv6Pass bool - unixPass bool - }{ - // Universal - {"type", true, true, true}, - {"string", true, true, true}, - // IP - {"name", true, true, false}, - {"size", true, true, false}, - {"flags", true, true, false}, - {"host", true, true, false}, - {"address", true, true, false}, - {"port", true, true, false}, - {"netmask", true, true, false}, - {"network", true, true, false}, - {"mask_bits", true, true, false}, - {"binary", true, true, false}, - {"hex", true, true, false}, - {"first_usable", true, true, false}, - {"last_usable", true, true, false}, - {"octets", true, true, false}, - // IPv4 - {"broadcast", true, false, false}, - {"uint32", true, false, false}, - // IPv6 - {"uint128", false, true, false}, - // Unix - {"path", false, false, true}, - } - - for _, attrTest := range attrNamesPerType { - switch v := sai.(type) { - case sockaddr.IfAddr: - saType := v.Type() - _, err := v.Attr(attrTest.name) - switch saType { - case sockaddr.TypeIPv4: - if err == nil && attrTest.ipv4Pass || err != nil && !attrTest.ipv4Pass { - // pass - } - // fallthrough - case sockaddr.TypeIPv6: - if err == nil && attrTest.ipv6Pass || err != nil && !attrTest.ipv6Pass { - // pass - } - // fallthrough - case sockaddr.TypeUnix: - if err == nil && attrTest.unixPass || err != nil && !attrTest.unixPass { - // pass - } - // fallthrough - default: - t.Errorf("Unable to fetch attr name %q: %v", attrTest.name, err) - } - case sockaddr.SockAddr: - val, err := sockaddr.Attr(v, attrTest.name) - _ = err - - pass := len(val) > 0 - switch { - case v.Type() == sockaddr.TypeIPv4 && attrTest.ipv4Pass == pass, - v.Type() == sockaddr.TypeIPv6 && attrTest.ipv6Pass == pass, - v.Type() == sockaddr.TypeUnix && attrTest.unixPass == pass: - // pass - default: - t.Errorf("Unable to fetch attr name %q from %v / %v + %+q", attrTest.name, v, v.Type(), val) - } - default: - t.Fatalf("unsupported type %T %v", sai, sai) - } - } -} diff --git a/vendor/github.com/hashicorp/go-sockaddr/ipaddr_test.go b/vendor/github.com/hashicorp/go-sockaddr/ipaddr_test.go deleted file mode 100644 index 68ce2c8b4..000000000 --- a/vendor/github.com/hashicorp/go-sockaddr/ipaddr_test.go +++ /dev/null @@ -1,222 +0,0 @@ -package sockaddr_test - -import ( - "fmt" - "testing" - - "github.com/hashicorp/go-sockaddr" -) - -func TestSockAddr_IPAddr_CmpAddress(t *testing.T) { - tests := []struct { - a string - b string - cmp int - }{ - { // 0: Same IPAddr (v4), same port - a: "208.67.222.222:0", - b: "208.67.222.222/32", - cmp: 0, - }, - { // 1: Same IPAddr (v6), same port - a: "[2607:f0d0:1002:0051:0000:0000:0000:0004]:0", - b: "2607:f0d0:1002:0051:0000:0000:0000:0004/128", - cmp: 0, - }, - { // 2: Same IPAddr (v4), different port - a: "208.67.222.222:4646", - b: "208.67.222.222/32", - cmp: 0, - }, - { // 3: Same IPAddr (v6), different port - a: "[2607:f0d0:1002:0051:0000:0000:0000:0004]:4646", - b: "[2607:f0d0:1002:0051:0000:0000:0000:0004]:4647", - cmp: 0, - }, - { // 4: Different IPAddr (v4), same port - a: "208.67.220.220:4648", - b: "208.67.222.222:4648", - cmp: -1, - }, - { // 5: Different IPAddr (v6), same port - a: "[2607:f0d0:1002:0051:0000:0000:0000:0004]:4648", - b: "[2607:f0d0:1002:0052:0000:0000:0000:0004]:4648", - cmp: -1, - }, - { // 6: Different IPAddr (v4), different port - a: "208.67.220.220:8600", - b: "208.67.222.222:4648", - cmp: -1, - }, - { // 7: Different IPAddr (v6), different port - a: "[2607:f0d0:1002:0051:0000:0000:0000:0004]:8500", - b: "[2607:f0d0:1002:0052:0000:0000:0000:0004]:4648", - cmp: -1, - }, - { // 8: Incompatible IPAddr (v4 vs v6), same port - a: "208.67.220.220:8600", - b: "[2607:f0d0:1002:0051:0000:0000:0000:0004]:8600", - cmp: 0, - }, - { // 9: Incompatible IPAddr (v4 vs v6), different port - a: "208.67.220.220:8500", - b: "[2607:f0d0:1002:0051:0000:0000:0000:0004]:8600", - cmp: 0, - }, - { // 10: Incompatible SockAddr types - a: "128.95.120.1:123", - b: "/tmp/foo.sock", - cmp: 0, - }, - { // 11: Incompatible SockAddr types - a: "[::]:123", - b: "/tmp/foo.sock", - cmp: 0, - }, - } - - for idx, test := range tests { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - saA, err := sockaddr.NewSockAddr(test.a) - if err != nil { - t.Fatalf("[%d] Unable to create a SockAddr from %+q: %v", idx, test.a, err) - } - saB, err := sockaddr.NewSockAddr(test.b) - if err != nil { - t.Fatalf("[%d] Unable to create an SockAddr from %+q: %v", idx, test.b, err) - } - - ipA, ok := saA.(sockaddr.IPAddr) - if !ok { - t.Fatalf("[%d] Unable to convert SockAddr %+q to an IPAddr", idx, test.a) - } - - if x := ipA.CmpAddress(saB); x != test.cmp { - t.Errorf("[%d] IPAddr.CmpAddress() failed with %+q with %+q (expected %d, received %d)", idx, ipA, saB, test.cmp, x) - } - - ipB, ok := saB.(sockaddr.IPAddr) - if !ok { - // Return success for comparing non-IPAddr types - return - } - if x := ipA.CmpAddress(ipB); x != test.cmp { - t.Errorf("[%d] IPAddr.CmpAddress() failed with %+q with %+q (expected %d, received %d)", idx, ipA, ipB, test.cmp, x) - } - if x := ipB.CmpAddress(ipA); x*-1 != test.cmp { - t.Errorf("[%d] IPAddr.CmpAddress() failed with %+q with %+q (expected %d, received %d)", idx, ipB, ipA, test.cmp, x) - } - - if x := ipB.CmpAddress(saA); x*-1 != test.cmp { - t.Errorf("[%d] IPAddr.CmpAddress() failed with %+q with %+q (expected %d, received %d)", idx, ipB, saA, test.cmp, x) - } - }) - } -} - -func TestSockAddr_IPAddr_CmpPort(t *testing.T) { - tests := []struct { - a string - b string - cmp int - }{ - { // 0: Same IPv4Addr, same port - a: "208.67.222.222:0", - b: "208.67.222.222/32", - cmp: 0, - }, - { // 1: Different IPv4Addr, same port - a: "208.67.220.220:0", - b: "208.67.222.222/32", - cmp: 0, - }, - { // 2: Same IPv4Addr, different port - a: "208.67.222.222:80", - b: "208.67.222.222:443", - cmp: -1, - }, - { // 3: Different IPv4Addr, different port - a: "208.67.220.220:8600", - b: "208.67.222.222:53", - cmp: 1, - }, - { // 4: Same IPv6Addr, same port - a: "[::]:0", - b: "::/128", - cmp: 0, - }, - { // 5: Different IPv6Addr, same port - a: "[::]:0", - b: "[2607:f0d0:1002:0051:0000:0000:0000:0004]:0", - cmp: 0, - }, - { // 6: Same IPv6Addr, different port - a: "[::]:8400", - b: "[::]:8600", - cmp: -1, - }, - { // 7: Different IPv6Addr, different port - a: "[::]:8600", - b: "[2607:f0d0:1002:0051:0000:0000:0000:0004]:53", - cmp: 1, - }, - { // 8: Mixed IPAddr types, same port - a: "[::]:53", - b: "208.67.220.220:53", - cmp: 0, - }, - { // 9: Mixed IPAddr types, different port - a: "[::]:53", - b: "128.95.120.1:123", - cmp: -1, - }, - { // 10: Incompatible SockAddr types - a: "128.95.120.1:123", - b: "/tmp/foo.sock", - cmp: 0, - }, - { // 11: Incompatible SockAddr types - a: "[::]:123", - b: "/tmp/foo.sock", - cmp: 0, - }, - } - - for idx, test := range tests { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - saA, err := sockaddr.NewSockAddr(test.a) - if err != nil { - t.Fatalf("[%d] Unable to create a SockAddr from %+q: %v", idx, test.a, err) - } - saB, err := sockaddr.NewSockAddr(test.b) - if err != nil { - t.Fatalf("[%d] Unable to create an SockAddr from %+q: %v", idx, test.b, err) - } - - ipA, ok := saA.(sockaddr.IPAddr) - if !ok { - t.Fatalf("[%d] Unable to convert SockAddr %+q to an IPAddr", idx, test.a) - } - - if x := ipA.CmpPort(saB); x != test.cmp { - t.Errorf("[%d] IPAddr.CmpPort() failed with %+q with %+q (expected %d, received %d)", idx, ipA, saB, test.cmp, x) - } - - ipB, ok := saB.(sockaddr.IPAddr) - if !ok { - // Return success for comparing non-IPAddr types - return - } - if x := ipA.CmpPort(ipB); x != test.cmp { - t.Errorf("[%d] IPAddr.CmpPort() failed with %+q with %+q (expected %d, received %d)", idx, ipA, ipB, test.cmp, x) - } - if x := ipB.CmpPort(ipA); x*-1 != test.cmp { - t.Errorf("[%d] IPAddr.CmpPort() failed with %+q with %+q (expected %d, received %d)", idx, ipB, ipA, test.cmp, x) - } - - if x := ipB.CmpPort(saA); x*-1 != test.cmp { - t.Errorf("[%d] IPAddr.CmpPort() failed with %+q with %+q (expected %d, received %d)", idx, ipB, saA, test.cmp, x) - } - }) - } -} diff --git a/vendor/github.com/hashicorp/go-sockaddr/ipaddrs_test.go b/vendor/github.com/hashicorp/go-sockaddr/ipaddrs_test.go deleted file mode 100644 index a72f77f63..000000000 --- a/vendor/github.com/hashicorp/go-sockaddr/ipaddrs_test.go +++ /dev/null @@ -1,460 +0,0 @@ -package sockaddr_test - -import ( - "fmt" - "sort" - "testing" - - "github.com/hashicorp/go-sockaddr" -) - -type GoodTestIPAddrTest struct { - sockAddrs sockaddr.SockAddrs - sortedBySpecificMasklen sockaddr.SockAddrs - sortedByBroadMasklen sockaddr.SockAddrs - sortedByNetwork sockaddr.SockAddrs -} -type GoodTestIPAddrTests []*GoodTestIPAddrTest - -func makeTestIPAddrs(t *testing.T) GoodTestIPAddrTests { - goodTestInputs := []struct { - sockAddrs []string - sortedBySpecificMasklen []string - sortedByBroadMasklen []string - sortedByNetwork []string - }{ - { - sockAddrs: []string{ - "10.0.0.0/8", - "172.16.1.3/12", - "192.168.0.0/16", - "128.95.120.1/32", - "192.168.1.10/24", - "240.0.0.1/4", - }, - sortedBySpecificMasklen: []string{ - "128.95.120.1/32", - "192.168.1.10/24", - "192.168.0.0/16", - "172.16.1.3/12", - "10.0.0.0/8", - "240.0.0.1/4", - }, - sortedByBroadMasklen: []string{ - "240.0.0.1/4", - "10.0.0.0/8", - "172.16.1.3/12", - "192.168.0.0/16", - "192.168.1.10/24", - "128.95.120.1/32", - }, - sortedByNetwork: []string{ - "10.0.0.0/8", - "128.95.120.1/32", - "172.16.1.3/12", - "192.168.0.0/16", - "192.168.1.10/24", - "240.0.0.1/4", - }, - }, - } - gfs := make(GoodTestIPAddrTests, 0, len(goodTestInputs)) - for idx, gfi := range goodTestInputs { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - gf := new(GoodTestIPAddrTest) - gf.sockAddrs = make(sockaddr.SockAddrs, 0, len(gfi.sockAddrs)) - for _, n := range gfi.sockAddrs { - sa, err := sockaddr.NewSockAddr(n) - if err != nil { - t.Fatalf("Expected valid network") - } - gf.sockAddrs = append(gf.sockAddrs, sa) - } - - gf.sortedBySpecificMasklen = make(sockaddr.SockAddrs, 0, len(gfi.sortedBySpecificMasklen)) - for _, n := range gfi.sortedBySpecificMasklen { - na, err := sockaddr.NewSockAddr(n) - if err != nil { - t.Fatalf("Expected valid network") - } - gf.sortedBySpecificMasklen = append(gf.sortedBySpecificMasklen, na) - } - - if len(gf.sockAddrs) != len(gf.sortedBySpecificMasklen) { - t.Fatalf("Expected same number of sortedBySpecificMasklen networks") - } - - gf.sortedByBroadMasklen = make(sockaddr.SockAddrs, 0, len(gfi.sortedByBroadMasklen)) - for _, n := range gfi.sortedByBroadMasklen { - na, err := sockaddr.NewSockAddr(n) - if err != nil { - t.Fatalf("Expected valid network") - } - gf.sortedByBroadMasklen = append(gf.sortedByBroadMasklen, na) - } - - if len(gf.sockAddrs) != len(gf.sortedByBroadMasklen) { - t.Fatalf("Expected same number of sortedByBroadMasklen networks") - } - - gf.sortedByNetwork = make(sockaddr.SockAddrs, 0, len(gfi.sortedByNetwork)) - for _, n := range gfi.sortedByNetwork { - na, err := sockaddr.NewSockAddr(n) - if err != nil { - t.Fatalf("Expected valid network") - } - gf.sortedByNetwork = append(gf.sortedByNetwork, na) - } - - if len(gf.sockAddrs) != len(gf.sortedByNetwork) { - t.Fatalf("Expected same number of sortedByNetwork networks") - } - }) - } - - return gfs -} - -func TestSockAddr_IPAddrs_BySpecificMaskLen(t *testing.T) { - testInputs := sockAddrStringInputs{ - { - inputAddrs: []string{"10.0.0.0/8", - "172.16.1.3/12", - "192.168.0.0/16", - "128.95.120.1/32", - "192.168.1.10/24", - "240.0.0.1/4", - }, - sortedAddrs: []string{ - "128.95.120.1/32", - "192.168.1.10/24", - "192.168.0.0/16", - "172.16.1.3/12", - "10.0.0.0/8", - "240.0.0.1/4", - }, - }, - } - - for idx, test := range testInputs { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - inputAddrs := convertToSockAddrs(t, test.inputAddrs) - sortedAddrs := convertToSockAddrs(t, test.sortedAddrs) - sockaddrs := append(sockaddr.SockAddrs(nil), inputAddrs...) - filteredAddrs, _ := sockaddrs.FilterByType(sockaddr.TypeIPv4) - ipv4Addrs := make([]sockaddr.IPv4Addr, 0, len(filteredAddrs)) - for _, x := range filteredAddrs { - switch v := x.(type) { - case sockaddr.IPv4Addr: - ipv4Addrs = append(ipv4Addrs, v) - default: - t.Fatalf("invalid type") - } - } - - ipAddrs := make([]sockaddr.IPAddr, 0, len(filteredAddrs)) - for _, x := range filteredAddrs { - ipAddr, ok := x.(sockaddr.IPAddr) - if !ok { - t.Fatalf("Unable to typecast to IPAddr") - } - ipAddrs = append(ipAddrs, ipAddr) - } - sort.Sort(sockaddr.SortIPAddrsBySpecificMaskLen{ipAddrs}) - - var lastLen int = 32 - for i, netaddr := range ipAddrs { - maskLen := netaddr.Maskbits() - if lastLen < maskLen { - t.Fatalf("Sort by specific mask length failed") - } - lastLen = maskLen - - if sortedAddrs[i] != netaddr { - t.Errorf("Expected %s, received %s in iteration %d", sortedAddrs[i], netaddr, i) - } - } - }) - } -} - -func TestSockAddr_IPAddrs_ByBroadMaskLen(t *testing.T) { - testInputs := sockAddrStringInputs{ - { - inputAddrs: []string{"10.0.0.0/8", - "172.16.1.3/12", - "192.168.0.0/16", - "128.95.120.1/32", - "192.168.1.10/24", - "240.0.0.1/4", - }, - sortedAddrs: []string{ - "240.0.0.1/4", - "10.0.0.0/8", - "172.16.1.3/12", - "192.168.0.0/16", - "192.168.1.10/24", - "128.95.120.1/32", - }, - }, - } - - for idx, test := range testInputs { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - inputAddrs := convertToSockAddrs(t, test.inputAddrs) - sortedAddrs := convertToSockAddrs(t, test.sortedAddrs) - sockaddrs := append(sockaddr.SockAddrs(nil), inputAddrs...) - filteredAddrs, _ := sockaddrs.FilterByType(sockaddr.TypeIP) - ipAddrs := make([]sockaddr.IPAddr, 0, len(filteredAddrs)) - for _, x := range filteredAddrs { - ipAddr, ok := x.(sockaddr.IPAddr) - if !ok { - t.Fatalf("Unable to typecast to IPAddr") - } - ipAddrs = append(ipAddrs, ipAddr) - } - sort.Sort(sockaddr.SortIPAddrsByBroadMaskLen{ipAddrs}) - - var lastLen int - for i, netaddr := range ipAddrs { - maskLen := netaddr.Maskbits() - if lastLen > maskLen { - t.Fatalf("Sort by specific mask length failed") - } - lastLen = maskLen - - if sortedAddrs[i] != netaddr { - t.Errorf("Expected %s, received %s in iteration %d", sortedAddrs[i], netaddr, i) - } - } - }) - } -} - -func TestSockAddr_IPAddrs_IPAddrsByNetwork(t *testing.T) { - testInputs := sockAddrStringInputs{ - { - inputAddrs: []string{ - "10.0.0.0/8", - "172.16.1.3/12", - "192.168.0.0/16", - "128.95.120.1/32", - "192.168.1.10/24", - "240.0.0.1/4", - }, - sortedAddrs: []string{ - "10.0.0.0/8", - "128.95.120.1/32", - "172.16.1.3/12", - "192.168.0.0/16", - "192.168.1.10/24", - "240.0.0.1/4", - }, - }, - } - - for idx, test := range testInputs { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - inputAddrs := convertToSockAddrs(t, test.inputAddrs) - sortedAddrs := convertToSockAddrs(t, test.sortedAddrs) - sockaddrs := append(sockaddr.SockAddrs(nil), inputAddrs...) - ipaddrs, _ := sockaddrs.FilterByType(sockaddr.TypeIP) - sockaddr.OrderedAddrBy(sockaddr.AscAddress).Sort(ipaddrs) - - var lastIpUint sockaddr.IPv4Address - for i, sa := range ipaddrs { - ipv4 := *sockaddr.ToIPv4Addr(sa) - if lastIpUint > ipv4.Address { - t.Fatalf("Sort by network failed") - } - lastIpUint = ipv4.Address - - if !ipv4.Equal(sortedAddrs[i]) { - t.Errorf("[%d] Sort equality failed: expected %s, received %s", i, sortedAddrs[i], ipv4) - } - } - }) - } -} - -func TestSockAddr_IPAddrs_IPAddrsByNetworkSize(t *testing.T) { - testInputs := sockAddrStringInputs{ - { - inputAddrs: []string{ - "10.0.0.0/8", - "172.16.1.3/12", - "128.95.120.2:53", - "128.95.120.2/32", - "192.168.0.0/16", - "128.95.120.1/32", - "192.168.1.10/24", - "128.95.120.2:8600", - "240.0.0.1/4", - }, - sortedAddrs: []string{ - "128.95.120.1/32", - "128.95.120.2:53", - "128.95.120.2:8600", - "128.95.120.2/32", - "192.168.1.10/24", - "192.168.0.0/16", - "172.16.1.3/12", - "10.0.0.0/8", - "240.0.0.1/4", - }, - }, - } - - for idx, test := range testInputs { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - inputAddrs := convertToSockAddrs(t, test.inputAddrs) - sortedAddrs := convertToSockAddrs(t, test.sortedAddrs) - - sockaddrs := append(sockaddr.SockAddrs(nil), inputAddrs...) - filteredAddrs, _ := sockaddrs.FilterByType(sockaddr.TypeIP) - ipAddrs := make([]sockaddr.IPAddr, 0, len(filteredAddrs)) - for _, x := range filteredAddrs { - ipAddr, ok := x.(sockaddr.IPAddr) - if !ok { - t.Fatalf("Unable to typecast to IPAddr") - } - ipAddrs = append(ipAddrs, ipAddr) - } - sort.Sort(sockaddr.SortIPAddrsByNetworkSize{ipAddrs}) - - // var prevAddr sockaddr.IPAddr - for i, ipAddr := range ipAddrs { - // if i == 0 { - // prevAddr = ipAddr - // continue - // } - - // if prevAddr.Cmp(ipAddr) > 0 { - // t.Logf("[%d] Prev:\t%v", i, prevAddr) - // t.Logf("[%d] ipAddr:\t%v", i, ipAddr) - // t.Fatalf("Sort by network failed") - // } - // prevAddr = ipAddr - - if !ipAddr.Equal(sortedAddrs[i]) { - t.Errorf("[%d] Sort equality failed: expected %s, received %s", i, sortedAddrs[i], ipAddr) - } - } - }) - } -} - -// func TestSockAddr_IPAddrs_IPAddrsByCmp(t *testing.T) { -// testInputs := testIPAddrsInputs{ -// { -// sockAddrs: []string{ -// "10.0.0.0/8", -// "172.16.1.3/12", -// "128.95.120.2:53", -// "128.95.120.2/32", -// "192.168.0.0/16", -// "128.95.120.1/32", -// "192.168.1.10/24", -// "128.95.120.2:8600", -// "240.0.0.1/4", -// }, -// sortedSockAddrs: []string{ -// "128.95.120.1/32", -// "128.95.120.2:53", -// "128.95.120.2:8600", -// "128.95.120.2/32", -// "192.168.1.10/24", -// "192.168.0.0/16", -// "172.16.1.3/12", -// "10.0.0.0/8", -// "240.0.0.1/4", -// }, -// }, -// } - -// for _, test := range makeTestsFromInput(t, testInputs) { -// sockaddrs := append(sockaddr.SockAddrs(nil), test.sockAddrs...) -// ipAddrs := sockaddrs.FilterByTypeIPAddr() -// sort.Sort(sockaddr.SortIPAddrsByCmp{ipAddrs}) -// t.Logf("Here: %+v", ipAddrs) - -// var prevAddr sockaddr.IPAddr -// for i, ipAddr := range ipAddrs { -// if i == 0 { -// prevAddr = ipAddr -// continue -// } - -// if prevAddr.Cmp(ipAddr) > 0 { -// t.Logf("[%d] Prev:\t%v", i, prevAddr) -// t.Logf("[%d] ipAddr:\t%v", i, ipAddr) -// t.Fatalf("Sort by network failed") -// } -// prevAddr = ipAddr - -// if !ipAddr.Equal(test.sortedSockAddrs[i]) { -// t.Errorf("[%d] Sort equality failed: expected %s, received %s", i, test.sortedSockAddrs[i], ipAddr) -// } -// } -// } -// } - -func TestSockAddr_IPAddrs_IPAddrsByCmp(t *testing.T) { - testInputs := sockAddrStringInputs{ - { - inputAddrs: []string{ - "10.0.0.0/8", - "172.16.1.3/12", - "128.95.120.2:53", - "128.95.120.2:53", - "128.95.120.2/32", - "192.168.0.0/16", - "128.95.120.1/32", - "192.168.1.10/24", - "128.95.120.2:8600", - "0:0:0:0:0:0:0:0", - "0:0:0:0:0:0:0:1", - "2607:f0d0:1002:0051:0000:0000:0000:0004", - "2607:f0d0:1002:0051:0000:0000:0000:0003", - "2607:f0d0:1002:0051:0000:0000:0000:0005", - "[2607:f0d0:1002:0051:0000:0000:0000:0004]:8600", - "240.0.0.1/4", - }, - sortedAddrs: []string{ - "10.0.0.0/8", - "172.16.1.3/12", - "192.168.0.0/16", - "192.168.1.10/24", - "240.0.0.1/4", - "128.95.120.1/32", - "128.95.120.2/32", - "128.95.120.2:53", - "128.95.120.2:53", - "128.95.120.2:8600", - "0:0:0:0:0:0:0:0", - "0:0:0:0:0:0:0:1", - "2607:f0d0:1002:0051:0000:0000:0000:0003", - "2607:f0d0:1002:0051:0000:0000:0000:0004", - "[2607:f0d0:1002:0051:0000:0000:0000:0004]:8600", - "2607:f0d0:1002:0051:0000:0000:0000:0005", - }, - }, - } - - for idx, test := range testInputs { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - shuffleStrings(test.inputAddrs) - - inputAddrs := convertToSockAddrs(t, test.inputAddrs) - sortedAddrs := convertToSockAddrs(t, test.sortedAddrs) - - sockaddr.OrderedAddrBy(sockaddr.AscType, sockaddr.AscPrivate, sockaddr.AscAddress, sockaddr.AscPort).Sort(inputAddrs) - - for i, sockAddr := range inputAddrs { - if !sockAddr.Equal(sortedAddrs[i]) { - t.Errorf("[%d] Sort equality failed: expected %s, received %s", i, sortedAddrs[i], sockAddr) - } - } - }) - } -} diff --git a/vendor/github.com/hashicorp/go-sockaddr/ipv4addr_test.go b/vendor/github.com/hashicorp/go-sockaddr/ipv4addr_test.go deleted file mode 100644 index 1a1bc0530..000000000 --- a/vendor/github.com/hashicorp/go-sockaddr/ipv4addr_test.go +++ /dev/null @@ -1,991 +0,0 @@ -package sockaddr_test - -import ( - "fmt" - "testing" - - "github.com/hashicorp/go-sockaddr" -) - -func TestSockAddr_IPv4Addr(t *testing.T) { - tests := []struct { - z00_input string - z01_addrHexStr string - z02_addrBinStr string - z03_addrStr string - z04_NetIPStringOut string - z05_addrInt sockaddr.IPv4Address - z06_netInt sockaddr.IPv4Network - z07_ipMaskStr string - z08_maskbits int - z09_NetIPNetStringOut string - z10_maskInt sockaddr.IPv4Mask - z11_networkStr string - z12_octets []int - z13_firstUsable string - z14_lastUsable string - z15_broadcast string - z16_portInt sockaddr.IPPort - z17_DialPacketArgs []string - z18_DialStreamArgs []string - z19_ListenPacketArgs []string - z20_ListenStreamArgs []string - z21_IsRFC1918 bool - z22_IsRFC6598 bool - z23_IsRFC6890 bool - z99_pass bool - }{ - { // 0 - z00_input: "0.0.0.0", - z01_addrHexStr: "00000000", - z02_addrBinStr: "00000000000000000000000000000000", - z03_addrStr: "0.0.0.0", - z04_NetIPStringOut: "0.0.0.0", - z05_addrInt: 0, - z06_netInt: 0, - z07_ipMaskStr: "ffffffff", - z08_maskbits: 32, - z09_NetIPNetStringOut: "0.0.0.0/32", - z10_maskInt: sockaddr.IPv4HostMask, - z11_networkStr: "0.0.0.0", - z12_octets: []int{0, 0, 0, 0}, - z13_firstUsable: "0.0.0.0", - z14_lastUsable: "0.0.0.0", - z15_broadcast: "0.0.0.0", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", "0.0.0.0:0"}, - z20_ListenStreamArgs: []string{"tcp4", "0.0.0.0:0"}, - z23_IsRFC6890: true, - z99_pass: true, - }, - { // 1 - z00_input: "0.0.0.0:80", - z01_addrHexStr: "00000000", - z02_addrBinStr: "00000000000000000000000000000000", - z03_addrStr: "0.0.0.0:80", - z04_NetIPStringOut: "0.0.0.0", - z05_addrInt: 0, - z06_netInt: 0, - z07_ipMaskStr: "ffffffff", - z08_maskbits: 32, - z09_NetIPNetStringOut: "0.0.0.0/32", - z10_maskInt: sockaddr.IPv4HostMask, - z11_networkStr: "0.0.0.0", - z12_octets: []int{0, 0, 0, 0}, - z13_firstUsable: "0.0.0.0", - z14_lastUsable: "0.0.0.0", - z15_broadcast: "0.0.0.0", - z16_portInt: 80, - z17_DialPacketArgs: []string{"udp4", "0.0.0.0:80"}, - z18_DialStreamArgs: []string{"tcp4", "0.0.0.0:80"}, - z19_ListenPacketArgs: []string{"udp4", "0.0.0.0:80"}, - z20_ListenStreamArgs: []string{"tcp4", "0.0.0.0:80"}, - z23_IsRFC6890: true, - z99_pass: true, - }, - { // 2 - z00_input: "0.0.0.0/0", - z01_addrHexStr: "00000000", - z02_addrBinStr: "00000000000000000000000000000000", - z03_addrStr: "0.0.0.0/0", - z04_NetIPStringOut: "0.0.0.0", - z05_addrInt: 0, - z06_netInt: 0, - z07_ipMaskStr: "00000000", - z09_NetIPNetStringOut: "0.0.0.0/0", - z10_maskInt: 0, - z11_networkStr: "0.0.0.0/0", - z12_octets: []int{0, 0, 0, 0}, - z13_firstUsable: "0.0.0.1", - z14_lastUsable: "255.255.255.254", - z15_broadcast: "255.255.255.255", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", ""}, - z20_ListenStreamArgs: []string{"tcp4", ""}, - z99_pass: true, - }, - { // 3 - z00_input: "0.0.0.1", - z01_addrHexStr: "00000001", - z02_addrBinStr: "00000000000000000000000000000001", - z03_addrStr: "0.0.0.1", - z04_NetIPStringOut: "0.0.0.1", - z05_addrInt: 1, - z06_netInt: 1, - z07_ipMaskStr: "ffffffff", - z08_maskbits: 32, - z09_NetIPNetStringOut: "0.0.0.1/32", - z10_maskInt: sockaddr.IPv4HostMask, - z11_networkStr: "0.0.0.1", - z12_octets: []int{0, 0, 0, 1}, - z13_firstUsable: "0.0.0.1", - z14_lastUsable: "0.0.0.1", - z15_broadcast: "0.0.0.1", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", "0.0.0.1:0"}, - z20_ListenStreamArgs: []string{"tcp4", "0.0.0.1:0"}, - z23_IsRFC6890: true, - z99_pass: true, - }, - { // 4 - z00_input: "0.0.0.1/1", - z01_addrHexStr: "00000001", - z02_addrBinStr: "00000000000000000000000000000001", - z03_addrStr: "0.0.0.1/1", - z04_NetIPStringOut: "0.0.0.1", - z05_addrInt: 1, - z06_netInt: 0, - z07_ipMaskStr: "80000000", - z08_maskbits: 1, - z09_NetIPNetStringOut: "0.0.0.0/1", - z10_maskInt: 2147483648, - z11_networkStr: "0.0.0.0/1", - z12_octets: []int{0, 0, 0, 1}, - z13_firstUsable: "0.0.0.1", - z14_lastUsable: "127.255.255.254", - z15_broadcast: "127.255.255.255", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", ""}, - z20_ListenStreamArgs: []string{"tcp4", ""}, - z99_pass: true, - }, - { // 5 - z00_input: "1.2.3.4", - z01_addrHexStr: "01020304", - z02_addrBinStr: "00000001000000100000001100000100", - z03_addrStr: "1.2.3.4", - z04_NetIPStringOut: "1.2.3.4", - z05_addrInt: 16909060, - z06_netInt: 16909060, - z07_ipMaskStr: "ffffffff", - z08_maskbits: 32, - z09_NetIPNetStringOut: "1.2.3.4/32", - z10_maskInt: sockaddr.IPv4HostMask, - z11_networkStr: "1.2.3.4", - z12_octets: []int{1, 2, 3, 4}, - z13_firstUsable: "1.2.3.4", - z14_lastUsable: "1.2.3.4", - z15_broadcast: "1.2.3.4", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", "1.2.3.4:0"}, - z20_ListenStreamArgs: []string{"tcp4", "1.2.3.4:0"}, - z99_pass: true, - }, - { // 6 - z00_input: "10.0.0.0/8", - z01_addrHexStr: "0a000000", - z02_addrBinStr: "00001010000000000000000000000000", - z03_addrStr: "10.0.0.0/8", - z04_NetIPStringOut: "10.0.0.0", - z05_addrInt: 167772160, - z06_netInt: 167772160, - z07_ipMaskStr: "ff000000", - z08_maskbits: 8, - z09_NetIPNetStringOut: "10.0.0.0/8", - z10_maskInt: 4278190080, - z11_networkStr: "10.0.0.0/8", - z12_octets: []int{10, 0, 0, 0}, - z13_firstUsable: "10.0.0.1", - z14_lastUsable: "10.255.255.254", - z15_broadcast: "10.255.255.255", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", ""}, - z20_ListenStreamArgs: []string{"tcp4", ""}, - z21_IsRFC1918: true, - z23_IsRFC6890: true, - z99_pass: true, - }, - { // 7 - z00_input: "128.0.0.0", - z01_addrHexStr: "80000000", - z02_addrBinStr: "10000000000000000000000000000000", - z03_addrStr: "128.0.0.0", - z04_NetIPStringOut: "128.0.0.0", - z05_addrInt: 2147483648, - z06_netInt: 2147483648, - z07_ipMaskStr: "ffffffff", - z08_maskbits: 32, - z09_NetIPNetStringOut: "128.0.0.0/32", - z10_maskInt: sockaddr.IPv4HostMask, - z11_networkStr: "128.0.0.0", - z12_octets: []int{128, 0, 0, 0}, - z13_firstUsable: "128.0.0.0", - z14_lastUsable: "128.0.0.0", - z15_broadcast: "128.0.0.0", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", "128.0.0.0:0"}, - z20_ListenStreamArgs: []string{"tcp4", "128.0.0.0:0"}, - z99_pass: true, - }, - { // 8 - z00_input: "128.95.120.1/32", - z01_addrHexStr: "805f7801", - z02_addrBinStr: "10000000010111110111100000000001", - z03_addrStr: "128.95.120.1", - z04_NetIPStringOut: "128.95.120.1", - z05_addrInt: 2153740289, - z06_netInt: 2153740289, - z07_ipMaskStr: "ffffffff", - z08_maskbits: 32, - z09_NetIPNetStringOut: "128.95.120.1/32", - z10_maskInt: sockaddr.IPv4HostMask, - z11_networkStr: "128.95.120.1", - z12_octets: []int{128, 95, 120, 1}, - z13_firstUsable: "128.95.120.1", - z14_lastUsable: "128.95.120.1", - z15_broadcast: "128.95.120.1", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", "128.95.120.1:0"}, - z20_ListenStreamArgs: []string{"tcp4", "128.95.120.1:0"}, - z99_pass: true, - }, - { // 9 - z00_input: "172.16.1.3/12", - z01_addrHexStr: "ac100103", - z02_addrBinStr: "10101100000100000000000100000011", - z03_addrStr: "172.16.1.3/12", - z04_NetIPStringOut: "172.16.1.3", - z05_addrInt: 2886729987, - z06_netInt: 2886729728, - z07_ipMaskStr: "fff00000", - z08_maskbits: 12, - z09_NetIPNetStringOut: "172.16.0.0/12", - z10_maskInt: 4293918720, - z11_networkStr: "172.16.0.0/12", - z12_octets: []int{172, 16, 1, 3}, - z13_firstUsable: "172.16.0.1", - z14_lastUsable: "172.31.255.254", - z15_broadcast: "172.31.255.255", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", ""}, - z20_ListenStreamArgs: []string{"tcp4", ""}, - z21_IsRFC1918: true, - z23_IsRFC6890: true, - z99_pass: true, - }, - { // 10 - z00_input: "192.168.0.0/16", - z01_addrHexStr: "c0a80000", - z02_addrBinStr: "11000000101010000000000000000000", - z03_addrStr: "192.168.0.0/16", - z04_NetIPStringOut: "192.168.0.0", - z05_addrInt: 3232235520, - z06_netInt: 3232235520, - z07_ipMaskStr: "ffff0000", - z08_maskbits: 16, - z09_NetIPNetStringOut: "192.168.0.0/16", - z10_maskInt: 4294901760, - z11_networkStr: "192.168.0.0/16", - z12_octets: []int{192, 168, 0, 0}, - z13_firstUsable: "192.168.0.1", - z14_lastUsable: "192.168.255.254", - z15_broadcast: "192.168.255.255", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", ""}, - z20_ListenStreamArgs: []string{"tcp4", ""}, - z21_IsRFC1918: true, - z23_IsRFC6890: true, - z99_pass: true, - }, - { // 11 - z00_input: "192.168.0.1", - z01_addrHexStr: "c0a80001", - z02_addrBinStr: "11000000101010000000000000000001", - z03_addrStr: "192.168.0.1", - z04_NetIPStringOut: "192.168.0.1", - z05_addrInt: 3232235521, - z06_netInt: 3232235521, - z07_ipMaskStr: "ffffffff", - z08_maskbits: 32, - z09_NetIPNetStringOut: "192.168.0.1/32", - z10_maskInt: sockaddr.IPv4HostMask, - z11_networkStr: "192.168.0.1", - z12_octets: []int{192, 168, 0, 1}, - z13_firstUsable: "192.168.0.1", - z14_lastUsable: "192.168.0.1", - z15_broadcast: "192.168.0.1", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", "192.168.0.1:0"}, - z20_ListenStreamArgs: []string{"tcp4", "192.168.0.1:0"}, - z21_IsRFC1918: true, - z23_IsRFC6890: true, - z99_pass: true, - }, - { // 12 - z00_input: "192.168.0.2/31", - z01_addrHexStr: "c0a80002", - z02_addrBinStr: "11000000101010000000000000000010", - z03_addrStr: "192.168.0.2/31", - z04_NetIPStringOut: "192.168.0.2", - z05_addrInt: 3232235522, - z06_netInt: 3232235522, - z07_ipMaskStr: "fffffffe", - z08_maskbits: 31, - z09_NetIPNetStringOut: "192.168.0.2/31", - z10_maskInt: 4294967294, - z11_networkStr: "192.168.0.2/31", - z12_octets: []int{192, 168, 0, 2}, - z13_firstUsable: "192.168.0.2", - z14_lastUsable: "192.168.0.3", - z15_broadcast: "192.168.0.3", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", ""}, - z20_ListenStreamArgs: []string{"tcp4", ""}, - z21_IsRFC1918: true, - z23_IsRFC6890: true, - z99_pass: true, - }, - { // 13 - z00_input: "192.168.1.10/24", - z01_addrHexStr: "c0a8010a", - z02_addrBinStr: "11000000101010000000000100001010", - z03_addrStr: "192.168.1.10/24", - z04_NetIPStringOut: "192.168.1.10", - z05_addrInt: 3232235786, - z06_netInt: 3232235776, - z07_ipMaskStr: "ffffff00", - z08_maskbits: 24, - z09_NetIPNetStringOut: "192.168.1.0/24", - z10_maskInt: 4294967040, - z11_networkStr: "192.168.1.0/24", - z12_octets: []int{192, 168, 1, 10}, - z13_firstUsable: "192.168.1.1", - z14_lastUsable: "192.168.1.254", - z15_broadcast: "192.168.1.255", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", ""}, - z20_ListenStreamArgs: []string{"tcp4", ""}, - z21_IsRFC1918: true, - z23_IsRFC6890: true, - z99_pass: true, - }, - { // 14 - z00_input: "192.168.10.10/16", - z01_addrHexStr: "c0a80a0a", - z02_addrBinStr: "11000000101010000000101000001010", - z03_addrStr: "192.168.10.10/16", - z04_NetIPStringOut: "192.168.10.10", - z05_addrInt: 3232238090, - z06_netInt: 3232235520, - z07_ipMaskStr: "ffff0000", - z08_maskbits: 16, - z09_NetIPNetStringOut: "192.168.0.0/16", - z10_maskInt: 4294901760, - z11_networkStr: "192.168.0.0/16", - z12_octets: []int{192, 168, 10, 10}, - z13_firstUsable: "192.168.0.1", - z14_lastUsable: "192.168.255.254", - z15_broadcast: "192.168.255.255", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", ""}, - z20_ListenStreamArgs: []string{"tcp4", ""}, - z21_IsRFC1918: true, - z23_IsRFC6890: true, - z99_pass: true, - }, - { // 15 - z00_input: "240.0.0.0/4", - z01_addrHexStr: "f0000000", - z02_addrBinStr: "11110000000000000000000000000000", - z03_addrStr: "240.0.0.0/4", - z04_NetIPStringOut: "240.0.0.0", - z05_addrInt: 4026531840, - z06_netInt: 4026531840, - z07_ipMaskStr: "f0000000", - z08_maskbits: 4, - z09_NetIPNetStringOut: "240.0.0.0/4", - z10_maskInt: 4026531840, - z11_networkStr: "240.0.0.0/4", - z12_octets: []int{240, 0, 0, 0}, - z13_firstUsable: "240.0.0.1", - z14_lastUsable: "255.255.255.254", - z15_broadcast: "255.255.255.255", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", ""}, - z20_ListenStreamArgs: []string{"tcp4", ""}, - z23_IsRFC6890: true, - z99_pass: true, - }, - { // 16 - z00_input: "240.0.0.1/4", - z01_addrHexStr: "f0000001", - z02_addrBinStr: "11110000000000000000000000000001", - z03_addrStr: "240.0.0.1/4", - z04_NetIPStringOut: "240.0.0.1", - z05_addrInt: 4026531841, - z06_netInt: 4026531840, - z07_ipMaskStr: "f0000000", - z08_maskbits: 4, - z09_NetIPNetStringOut: "240.0.0.0/4", - z10_maskInt: 4026531840, - z11_networkStr: "240.0.0.0/4", - z12_octets: []int{240, 0, 0, 1}, - z13_firstUsable: "240.0.0.1", - z14_lastUsable: "255.255.255.254", - z15_broadcast: "255.255.255.255", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", ""}, - z20_ListenStreamArgs: []string{"tcp4", ""}, - z23_IsRFC6890: true, - z99_pass: true, - }, - { // 17 - z00_input: "255.255.255.255", - z01_addrHexStr: "ffffffff", - z02_addrBinStr: "11111111111111111111111111111111", - z03_addrStr: "255.255.255.255", - z04_NetIPStringOut: "255.255.255.255", - z05_addrInt: 4294967295, - z06_netInt: 4294967295, - z07_ipMaskStr: "ffffffff", - z08_maskbits: 32, - z09_NetIPNetStringOut: "255.255.255.255/32", - z10_maskInt: sockaddr.IPv4HostMask, - z11_networkStr: "255.255.255.255", - z12_octets: []int{255, 255, 255, 255}, - z13_firstUsable: "255.255.255.255", - z14_lastUsable: "255.255.255.255", - z15_broadcast: "255.255.255.255", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", "255.255.255.255:0"}, - z20_ListenStreamArgs: []string{"tcp4", "255.255.255.255:0"}, - z23_IsRFC6890: true, - z99_pass: true, - }, - { // 18 - z00_input: "www.hashicorp.com", - z99_pass: false, - }, - { // 19 - z00_input: "2001:DB8::/48", - z99_pass: false, - }, - { // 20 - z00_input: "2001:DB8::", - z99_pass: false, - }, - { // 21 - z00_input: "128.95.120.1:8600", - z01_addrHexStr: "805f7801", - z02_addrBinStr: "10000000010111110111100000000001", - z03_addrStr: "128.95.120.1:8600", - z04_NetIPStringOut: "128.95.120.1", - z05_addrInt: 2153740289, - z06_netInt: 2153740289, - z07_ipMaskStr: "ffffffff", - z08_maskbits: 32, - z09_NetIPNetStringOut: "128.95.120.1/32", - z10_maskInt: sockaddr.IPv4HostMask, - z11_networkStr: "128.95.120.1", - z12_octets: []int{128, 95, 120, 1}, - z13_firstUsable: "128.95.120.1", - z14_lastUsable: "128.95.120.1", - z15_broadcast: "128.95.120.1", - z16_portInt: 8600, - z17_DialPacketArgs: []string{"udp4", "128.95.120.1:8600"}, - z18_DialStreamArgs: []string{"tcp4", "128.95.120.1:8600"}, - z19_ListenPacketArgs: []string{"udp4", "128.95.120.1:8600"}, - z20_ListenStreamArgs: []string{"tcp4", "128.95.120.1:8600"}, - z99_pass: true, - }, - { // 22 - z00_input: "100.64.2.3/23", - z01_addrHexStr: "64400203", - z02_addrBinStr: "01100100010000000000001000000011", - z03_addrStr: "100.64.2.3/23", - z04_NetIPStringOut: "100.64.2.3", - z05_addrInt: 1681916419, - z06_netInt: 1681916416, - z07_ipMaskStr: "fffffe00", - z08_maskbits: 23, - z09_NetIPNetStringOut: "100.64.2.0/23", - z10_maskInt: 4294966784, - z11_networkStr: "100.64.2.0/23", - z12_octets: []int{100, 64, 2, 3}, - z13_firstUsable: "100.64.2.1", - z14_lastUsable: "100.64.3.254", - z15_broadcast: "100.64.3.255", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", ""}, - z20_ListenStreamArgs: []string{"tcp4", ""}, - z22_IsRFC6598: true, - z23_IsRFC6890: true, - z99_pass: true, - }, - { // 23 - z00_input: "192.168.3.53/00ffffff", - z01_addrHexStr: "c0a80335", - z02_addrBinStr: "11000000101010000000001100110101", - z03_addrStr: "192.168.3.53", - z04_NetIPStringOut: "192.168.3.53", - z05_addrInt: 3232236341, - z06_netInt: 3232236341, - z07_ipMaskStr: "ffffffff", - z08_maskbits: 32, - z09_NetIPNetStringOut: "192.168.3.53/32", - z10_maskInt: 4294967295, - z11_networkStr: "192.168.3.53", - z12_octets: []int{192, 168, 3, 53}, - z13_firstUsable: "192.168.3.53", - z14_lastUsable: "192.168.3.53", - z15_broadcast: "192.168.3.53", - z17_DialPacketArgs: []string{"udp4", ""}, - z18_DialStreamArgs: []string{"tcp4", ""}, - z19_ListenPacketArgs: []string{"udp4", "192.168.3.53:0"}, - z20_ListenStreamArgs: []string{"tcp4", "192.168.3.53:0"}, - z21_IsRFC1918: true, - z22_IsRFC6598: false, - z23_IsRFC6890: true, - z99_pass: true, - }, - } - - for idx, test := range tests { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - ipv4, err := sockaddr.NewIPv4Addr(test.z00_input) - if test.z99_pass && err != nil { - t.Fatalf("[%d] Unable to create an IPv4Addr from %+q: %v", idx, test.z00_input, err) - } else if !test.z99_pass && err == nil { - t.Fatalf("[%d] Expected test to fail for %+q", idx, test.z00_input) - } else if !test.z99_pass && err != nil { - // Expected failure, return successfully - return - } - - if type_ := ipv4.Type(); type_ != sockaddr.TypeIPv4 { - t.Errorf("[%d] Expected new IPv4Addr to be Type %d, received %d (int)", idx, sockaddr.TypeIPv4, type_) - } - - h, ok := ipv4.Host().(sockaddr.IPv4Addr) - if !ok { - t.Errorf("[%d] Unable to type assert +%q's Host to IPv4Addr", idx, test.z00_input) - } - - if h.Address != ipv4.Address || h.Mask != sockaddr.IPv4HostMask || h.Port != ipv4.Port { - t.Errorf("[%d] Expected %+q's Host() to return identical IPv4Addr except mask, received %+q", idx, test.z00_input, h.String()) - } - - if c := cap(*ipv4.NetIP()); c != sockaddr.IPv4len { - t.Errorf("[%d] Expected new IPv4Addr's Address capacity to be %d bytes, received %d", idx, sockaddr.IPv4len, c) - } - - if l := len(*ipv4.NetIP()); l != sockaddr.IPv4len { - t.Errorf("[%d] Expected new IPv4Addr's Address length to be %d bytes, received %d", idx, sockaddr.IPv4len, l) - } - - if s := ipv4.AddressHexString(); s != test.z01_addrHexStr { - t.Errorf("[%d] Expected address %+q's hexadecimal representation to be %+q, received %+q", idx, test.z00_input, test.z01_addrHexStr, s) - } - - if s := ipv4.AddressBinString(); s != test.z02_addrBinStr { - t.Errorf("[%d] Expected address %+q's binary representation to be %+q, received %+q", idx, test.z00_input, test.z02_addrBinStr, s) - } - - if s := ipv4.String(); s != test.z03_addrStr { - t.Errorf("[%d] Expected %+q's String to be %+q, received %+q", idx, test.z00_input, test.z03_addrStr, s) - } - - if s := ipv4.NetIP().String(); s != test.z04_NetIPStringOut { - t.Errorf("[%d] Expected %+q's address to be %+q, received %+q", idx, test.z00_input, test.z04_NetIPStringOut, s) - } - - if a := ipv4.Address; a != test.z05_addrInt { - t.Errorf("[%d] Expected %+q's Address to return %d, received %d", idx, test.z00_input, test.z05_addrInt, a) - } - - if n, ok := ipv4.Network().(sockaddr.IPv4Addr); !ok || n.Address != sockaddr.IPv4Address(test.z06_netInt) { - t.Errorf("[%d] Expected %+q's Network to return %d, received %d", idx, test.z00_input, test.z06_netInt, n.Address) - } - - if m := ipv4.NetIPMask().String(); m != test.z07_ipMaskStr { - t.Errorf("[%d] Expected %+q's mask to be %+q, received %+q", idx, test.z00_input, test.z07_ipMaskStr, m) - } - - if m := ipv4.Maskbits(); m != test.z08_maskbits { - t.Errorf("[%d] Expected %+q's port to be %d, received %d", idx, test.z00_input, test.z08_maskbits, m) - } - - if n := ipv4.NetIPNet().String(); n != test.z09_NetIPNetStringOut { - t.Errorf("[%d] Expected %+q's network to be %+q, received %+q", idx, test.z00_input, test.z09_NetIPNetStringOut, n) - } - - if m := ipv4.Mask; m != test.z10_maskInt { - t.Errorf("[%d] Expected %+q's Mask to return %d, received %d", idx, test.z00_input, test.z10_maskInt, m) - } - - // Network()'s mask must match the IPv4Addr's Mask - if n, ok := ipv4.Network().(sockaddr.IPv4Addr); !ok || n.Mask != test.z10_maskInt { - t.Errorf("[%d] Expected %+q's Network's Mask to return %d, received %d", idx, test.z00_input, test.z10_maskInt, n.Mask) - } - - if n := ipv4.Network().String(); n != test.z11_networkStr { - t.Errorf("[%d] Expected %+q's Network() to be %+q, received %+q", idx, test.z00_input, test.z11_networkStr, n) - } - - if o := ipv4.Octets(); len(o) != 4 || o[0] != test.z12_octets[0] || o[1] != test.z12_octets[1] || o[2] != test.z12_octets[2] || o[3] != test.z12_octets[3] { - t.Errorf("[%d] Expected %+q's Octets to be %+v, received %+v", idx, test.z00_input, test.z12_octets, o) - } - - if f := ipv4.FirstUsable().String(); f != test.z13_firstUsable { - t.Errorf("[%d] Expected %+q's FirstUsable() to be %+q, received %+q", idx, test.z00_input, test.z13_firstUsable, f) - } - - if l := ipv4.LastUsable().String(); l != test.z14_lastUsable { - t.Errorf("[%d] Expected %+q's LastUsable() to be %+q, received %+q", idx, test.z00_input, test.z14_lastUsable, l) - } - - if b := ipv4.Broadcast().String(); b != test.z15_broadcast { - t.Errorf("[%d] Expected %+q's broadcast to be %+q, received %+q", idx, test.z00_input, test.z15_broadcast, b) - } - - if p := ipv4.IPPort(); sockaddr.IPPort(p) != test.z16_portInt || sockaddr.IPPort(p) != test.z16_portInt { - t.Errorf("[%d] Expected %+q's port to be %d, received %d", idx, test.z00_input, test.z16_portInt, p) - } - - if dialNet, dialArgs := ipv4.DialPacketArgs(); dialNet != test.z17_DialPacketArgs[0] || dialArgs != test.z17_DialPacketArgs[1] { - t.Errorf("[%d] Expected %+q's DialPacketArgs() to be %+q, received %+q, %+q", idx, test.z00_input, test.z17_DialPacketArgs, dialNet, dialArgs) - } - - if dialNet, dialArgs := ipv4.DialStreamArgs(); dialNet != test.z18_DialStreamArgs[0] || dialArgs != test.z18_DialStreamArgs[1] { - t.Errorf("[%d] Expected %+q's DialStreamArgs() to be %+q, received %+q, %+q", idx, test.z00_input, test.z18_DialStreamArgs, dialNet, dialArgs) - } - - if listenNet, listenArgs := ipv4.ListenPacketArgs(); listenNet != test.z19_ListenPacketArgs[0] || listenArgs != test.z19_ListenPacketArgs[1] { - t.Errorf("[%d] Expected %+q's ListenPacketArgs() to be %+q, received %+q, %+q", idx, test.z00_input, test.z19_ListenPacketArgs, listenNet, listenArgs) - } - - if listenNet, listenArgs := ipv4.ListenStreamArgs(); listenNet != test.z20_ListenStreamArgs[0] || listenArgs != test.z20_ListenStreamArgs[1] { - t.Errorf("[%d] Expected %+q's ListenStreamArgs() to be %+q, received %+q, %+q", idx, test.z00_input, test.z20_ListenStreamArgs, listenNet, listenArgs) - } - - if v := sockaddr.IsRFC(1918, ipv4); v != test.z21_IsRFC1918 { - t.Errorf("[%d] Expected IsRFC(1918, %+q) to be %t, received %t", idx, test.z00_input, test.z21_IsRFC1918, v) - } - - if v := sockaddr.IsRFC(6598, ipv4); v != test.z22_IsRFC6598 { - t.Errorf("[%d] Expected IsRFC(6598, %+q) to be %t, received %t", idx, test.z00_input, test.z22_IsRFC6598, v) - } - - if v := sockaddr.IsRFC(6890, ipv4); v != test.z23_IsRFC6890 { - t.Errorf("[%d] Expected IsRFC(6890, %+q) to be %t, received %t", idx, test.z00_input, test.z23_IsRFC6890, v) - } - }) - } -} - -func TestSockAddr_IPv4Addr_CmpAddress(t *testing.T) { - tests := []struct { - a string - b string - cmp int - }{ - { // 0 - a: "208.67.222.222/32", - b: "208.67.222.222", - cmp: 0, - }, - { // 1 - a: "208.67.222.222/32", - b: "208.67.222.222/32", - cmp: 0, - }, - { // 2 - a: "208.67.222.222/32", - b: "208.67.222.222:0", - cmp: 0, - }, - { // 3 - a: "208.67.222.220/32", - b: "208.67.222.222/32", - cmp: -1, - }, - { // 4 - a: "208.67.222.222/32", - b: "208.67.222.220/32", - cmp: 1, - }, - } - - for idx, test := range tests { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - ipv4a, err := sockaddr.NewIPv4Addr(test.a) - if err != nil { - t.Fatalf("[%d] Unable to create an IPv4Addr from %+q: %v", idx, test.a, err) - } - - ipv4b, err := sockaddr.NewIPv4Addr(test.b) - if err != nil { - t.Fatalf("[%d] Unable to create an IPv4Addr from %+q: %v", idx, test.b, err) - } - - if x := ipv4a.CmpAddress(ipv4b); x != test.cmp { - t.Errorf("[%d] IPv4Addr.CmpAddress() failed with %+q with %+q (expected %d, received %d)", idx, ipv4a, ipv4b, test.cmp, x) - } - - if x := ipv4b.CmpAddress(ipv4a); x*-1 != test.cmp { - t.Errorf("[%d] IPv4Addr.CmpAddress() failed with %+q with %+q (expected %d, received %d)", idx, ipv4a, ipv4b, test.cmp, x) - } - }) - } -} - -func TestSockAddr_IPv4Addr_ContainsAddress(t *testing.T) { - tests := []struct { - input string - pass []string - fail []string - }{ - { // 0 - input: "208.67.222.222/32", - pass: []string{ - "208.67.222.222", - "208.67.222.222/32", - "208.67.222.223/31", - "208.67.222.222/31", - "0.0.0.0/0", - }, - fail: []string{ - "0.0.0.0/1", - "208.67.222.220/31", - "208.67.220.224/31", - "208.67.220.220/32", - }, - }, - } - - for idx, test := range tests { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - ipv4, err := sockaddr.NewIPv4Addr(test.input) - if err != nil { - t.Fatalf("[%d] Unable to create an IPv4Addr from %+q: %v", idx, test.input, err) - } - - for passIdx, passInput := range test.pass { - passAddr, err := sockaddr.NewIPv4Addr(passInput) - if err != nil { - t.Fatalf("[%d/%d] Unable to create an IPv4Addr from %+q: %v", idx, passIdx, passInput, err) - } - - if !passAddr.ContainsAddress(ipv4.Address) { - t.Errorf("[%d/%d] Expected %+q to contain %+q", idx, passIdx, test.input, passInput) - } - } - - for failIdx, failInput := range test.fail { - failAddr, err := sockaddr.NewIPv4Addr(failInput) - if err != nil { - t.Fatalf("[%d/%d] Unable to create an IPv4Addr from %+q: %v", idx, failIdx, failInput, err) - } - - if failAddr.ContainsAddress(ipv4.Address) { - t.Errorf("[%d/%d] Expected %+q to contain %+q", idx, failIdx, test.input, failInput) - } - } - }) - } -} - -func TestSockAddr_IPv4Addr_CmpPort(t *testing.T) { - tests := []struct { - a string - b string - cmp int - }{ - { // 0: Same port, same IP - a: "208.67.222.222:0", - b: "208.67.222.222/32", - cmp: 0, - }, - { // 1: Same port, different IP - a: "208.67.222.220:0", - b: "208.67.222.222/32", - cmp: 0, - }, - { // 2: Same IP, different port - a: "208.67.222.222:80", - b: "208.67.222.222:443", - cmp: -1, - }, - { // 3: Same IP, different port - a: "208.67.222.222:443", - b: "208.67.222.222:80", - cmp: 1, - }, - { // 4: Different IP, different port - a: "208.67.222.222:53", - b: "208.67.220.220:8600", - cmp: -1, - }, - { // 5: Different IP, different port - a: "208.67.222.222:8600", - b: "208.67.220.220:53", - cmp: 1, - }, - } - - for idx, test := range tests { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - ipv4a, err := sockaddr.NewIPv4Addr(test.a) - if err != nil { - t.Fatalf("[%d] Unable to create an IPv4Addr from %+q: %v", idx, test.a, err) - } - - ipv4b, err := sockaddr.NewIPv4Addr(test.b) - if err != nil { - t.Fatalf("[%d] Unable to create an IPv4Addr from %+q: %v", idx, test.b, err) - } - - if x := ipv4a.CmpPort(ipv4b); x != test.cmp { - t.Errorf("[%d] IPv4Addr.CmpPort() failed with %+q with %+q (expected %d, received %d)", idx, ipv4a, ipv4b, test.cmp, x) - } - - if x := ipv4b.CmpPort(ipv4a); x*-1 != test.cmp { - t.Errorf("[%d] IPv4Addr.CmpPort() failed with %+q with %+q (expected %d, received %d)", idx, ipv4a, ipv4b, test.cmp, x) - } - }) - } -} - -func TestSockAddr_IPv4Addr_Equal(t *testing.T) { - tests := []struct { - name string - input string - pass []string - fail []string - }{ - { - name: "passing", - input: "208.67.222.222/32", - pass: []string{"208.67.222.222", "208.67.222.222/32", "208.67.222.222:0"}, - fail: []string{"208.67.222.222/31", "208.67.220.220", "208.67.220.220/32", "208.67.222.222:5432"}, - }, - { - name: "failing", - input: "4.2.2.1", - pass: []string{"4.2.2.1", "4.2.2.1/32"}, - fail: []string{"4.2.2.1/0", "4.2.2.2", "4.2.2.2/32", "::1"}, - }, - } - - for idx, test := range tests { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - ipv4, err := sockaddr.NewIPv4Addr(test.input) - if err != nil { - t.Fatalf("[%d] Unable to create an IPv4Addr from %+q: %v", idx, test.input, err) - } - - for goodIdx, passInput := range test.pass { - good, err := sockaddr.NewIPv4Addr(passInput) - if err != nil { - t.Fatalf("[%d] Unable to create an IPv4Addr from %+q: %v", idx, passInput, err) - } - - if !ipv4.Equal(good) { - t.Errorf("[%d/%d] Expected %+q to be equal to %+q: %+q/%+q", idx, goodIdx, test.input, passInput, ipv4.String(), good.String()) - } - } - - for failIdx, failInput := range test.fail { - fail, err := sockaddr.NewIPAddr(failInput) - if err != nil { - t.Fatalf("[%d] Unable to create an IPv4Addr from %+q: %v", idx, failInput, err) - } - - if ipv4.Equal(fail) { - t.Errorf("[%d/%d] Expected %+q to be not equal to %+q", idx, failIdx, test.input, failInput) - } - } - }) - } -} - -func TestIPv4CmpRFC(t *testing.T) { - tests := []struct { - name string - ipv4 sockaddr.IPv4Addr - rfc uint - sa sockaddr.SockAddr - ret int - }{ - { - name: "ipv4 rfc cmp recv match not arg", - ipv4: sockaddr.MustIPv4Addr("192.168.1.10"), - rfc: 1918, - sa: sockaddr.MustIPv6Addr("::1"), - ret: -1, - }, - { - name: "ipv4 rfc cmp recv match", - ipv4: sockaddr.MustIPv4Addr("192.168.1.2"), - rfc: 1918, - sa: sockaddr.MustIPv4Addr("203.1.2.3"), - ret: -1, - }, - { - name: "ipv4 rfc cmp defer", - ipv4: sockaddr.MustIPv4Addr("192.168.1.3"), - rfc: 1918, - sa: sockaddr.MustIPv4Addr("192.168.1.4"), - ret: 0, - }, - { - name: "ipv4 rfc cmp recv not match", - ipv4: sockaddr.MustIPv4Addr("1.2.3.4"), - rfc: 1918, - sa: sockaddr.MustIPv4Addr("203.1.2.3"), - ret: 0, - }, - { - name: "ipv4 rfc cmp recv not match arg", - ipv4: sockaddr.MustIPv4Addr("1.2.3.4"), - rfc: 1918, - sa: sockaddr.MustIPv6Addr("::1"), - ret: 0, - }, - { - name: "ipv4 rfc cmp arg match", - ipv4: sockaddr.MustIPv4Addr("1.2.3.4"), - rfc: 1918, - sa: sockaddr.MustIPv4Addr("192.168.1.5"), - ret: 1, - }, - } - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d must have a name", i) - } - - t.Run(test.name, func(t *testing.T) { - ipv4 := test.ipv4 - if ret := ipv4.CmpRFC(test.rfc, test.sa); ret != test.ret { - t.Errorf("%s: unexpected ret: wanted %d got %d", test.name, test.ret, ret) - } - }) - } -} - -func TestIPv4Attrs(t *testing.T) { - const expectedNumAttrs = 3 - attrs := sockaddr.IPv4Attrs() - if len(attrs) != expectedNumAttrs { - t.Fatalf("wrong number of IPv4Attrs: %d vs %d", len(attrs), expectedNumAttrs) - } -} diff --git a/vendor/github.com/hashicorp/go-sockaddr/ipv6addr_test.go b/vendor/github.com/hashicorp/go-sockaddr/ipv6addr_test.go deleted file mode 100644 index b46ed8341..000000000 --- a/vendor/github.com/hashicorp/go-sockaddr/ipv6addr_test.go +++ /dev/null @@ -1,725 +0,0 @@ -package sockaddr_test - -import ( - "fmt" - "math/big" - "strings" - "testing" - - "github.com/hashicorp/go-sockaddr" -) - -// ipv6HostMask is an unexported big.Int representing a /128 IPv6 address -var ipv6HostMask sockaddr.IPv6Mask - -func init() { - biMask := big.NewInt(0) - biMask = biMask.SetBytes([]byte{ - 0xff, 0xff, - 0xff, 0xff, - 0xff, 0xff, - 0xff, 0xff, - 0xff, 0xff, - 0xff, 0xff, - 0xff, 0xff, - 0xff, 0xff, - }, - ) - ipv6HostMask = sockaddr.IPv6Mask(biMask) -} - -func newIPv6BigInt(t *testing.T, ipv6Str string) *big.Int { - addr := big.NewInt(0) - addrStr := strings.Join(strings.Split(ipv6Str, ":"), "") - _, ok := addr.SetString(addrStr, 16) - if !ok { - t.Fatalf("Unable to create an IPv6Addr from string %+q", ipv6Str) - } - - return addr -} - -func newIPv6Address(t *testing.T, ipv6Str string) sockaddr.IPv6Address { - return sockaddr.IPv6Address(newIPv6BigInt(t, ipv6Str)) -} - -func newIPv6Mask(t *testing.T, ipv6Str string) sockaddr.IPv6Mask { - return sockaddr.IPv6Mask(newIPv6BigInt(t, ipv6Str)) -} - -func newIPv6Network(t *testing.T, ipv6Str string) sockaddr.IPv6Network { - return sockaddr.IPv6Network(newIPv6BigInt(t, ipv6Str)) -} - -func TestSockAddr_IPv6Addr(t *testing.T) { - tests := []struct { - z00_input string - z01_addrHexStr string - z02_addrBinStr string - z03_addrStr string - z04_NetIPStringOut string - z05_addrInt sockaddr.IPv6Address - z06_netInt sockaddr.IPv6Network - z07_ipMaskStr string - z08_maskbits int - z09_NetIPNetStringOut string - z10_maskInt sockaddr.IPv6Mask - z11_networkStr string - z12_octets []int - z13_firstUsable string - z14_lastUsable string - z16_portInt sockaddr.IPPort - z17_DialPacketArgs []string - z18_DialStreamArgs []string - z19_ListenPacketArgs []string - z20_ListenStreamArgs []string - z99_pass bool - }{ - { // 0 -- IPv4 fail - z00_input: "1.2.3.4", - z99_pass: false, - }, - { // 1 - IPv4 with port - z00_input: "5.6.7.8:80", - z99_pass: false, - }, - { // 2 - Hostname - z00_input: "www.hashicorp.com", - z99_pass: false, - }, - { // 3 - IPv6 with port, but no square brackets - z00_input: "2607:f0d0:1002:0051:0000:0000:0000:0004:8600", - z99_pass: false, - }, - { // 4 - IPv6 with port - z00_input: "[2607:f0d0:1002:0051:0000:0000:0000:0004]:8600", - z01_addrHexStr: "2607f0d0100200510000000000000004", - z02_addrBinStr: "00100110000001111111000011010000000100000000001000000000010100010000000000000000000000000000000000000000000000000000000000000100", - z03_addrStr: "[2607:f0d0:1002:51::4]:8600", - z04_NetIPStringOut: "2607:f0d0:1002:51::4", - z05_addrInt: newIPv6Address(t, "2607:f0d0:1002:0051:0000:0000:0000:0004"), - z06_netInt: newIPv6Network(t, "2607:f0d0:1002:0051:0000:0000:0000:0004"), - z07_ipMaskStr: "ffffffffffffffffffffffffffffffff", - z08_maskbits: 128, - z09_NetIPNetStringOut: "2607:f0d0:1002:51::4/128", - z10_maskInt: newIPv6Mask(t, "ffffffffffffffffffffffffffffffff"), - z11_networkStr: "2607:f0d0:1002:51::4", - z12_octets: []int{0x26, 0x7, 0xf0, 0xd0, 0x10, 0x2, 0x0, 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4}, - z13_firstUsable: "2607:f0d0:1002:51::4", - z14_lastUsable: "2607:f0d0:1002:51::4", - z16_portInt: 8600, - z17_DialPacketArgs: []string{"udp6", "[2607:f0d0:1002:51::4]:8600"}, - z18_DialStreamArgs: []string{"tcp6", "[2607:f0d0:1002:51::4]:8600"}, - z19_ListenPacketArgs: []string{"udp6", "[2607:f0d0:1002:51::4]:8600"}, - z20_ListenStreamArgs: []string{"tcp6", "[2607:f0d0:1002:51::4]:8600"}, - z99_pass: true, - }, - { // 5 - IPv6 - z00_input: "2607:f0d0:1002:0051:0000:0000:0000:0004", - z01_addrHexStr: "2607f0d0100200510000000000000004", - z02_addrBinStr: "00100110000001111111000011010000000100000000001000000000010100010000000000000000000000000000000000000000000000000000000000000100", - z03_addrStr: "2607:f0d0:1002:51::4", - z04_NetIPStringOut: "2607:f0d0:1002:51::4", - z05_addrInt: newIPv6Address(t, "2607:f0d0:1002:0051:0000:0000:0000:0004"), - z06_netInt: newIPv6Network(t, "2607:f0d0:1002:0051:0000:0000:0000:0004"), - z07_ipMaskStr: "ffffffffffffffffffffffffffffffff", - z08_maskbits: 128, - z09_NetIPNetStringOut: "2607:f0d0:1002:51::4/128", - z10_maskInt: newIPv6Mask(t, "ffffffffffffffffffffffffffffffff"), - z11_networkStr: "2607:f0d0:1002:51::4", - z12_octets: []int{0x26, 0x7, 0xf0, 0xd0, 0x10, 0x2, 0x0, 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4}, - z13_firstUsable: "2607:f0d0:1002:51::4", - z14_lastUsable: "2607:f0d0:1002:51::4", - z17_DialPacketArgs: []string{"udp6", ""}, - z18_DialStreamArgs: []string{"tcp6", ""}, - z19_ListenPacketArgs: []string{"udp6", "[2607:f0d0:1002:51::4]:0"}, - z20_ListenStreamArgs: []string{"tcp6", "[2607:f0d0:1002:51::4]:0"}, - z99_pass: true, - }, - { // 6 IPv6 with square brackets, optional - z00_input: "[2607:f0d0:1002:0051:0000:0000:0000:0004]", - z01_addrHexStr: "2607f0d0100200510000000000000004", - z02_addrBinStr: "00100110000001111111000011010000000100000000001000000000010100010000000000000000000000000000000000000000000000000000000000000100", - z03_addrStr: "2607:f0d0:1002:51::4", - z04_NetIPStringOut: "2607:f0d0:1002:51::4", - z05_addrInt: newIPv6Address(t, "2607:f0d0:1002:0051:0000:0000:0000:0004"), - z06_netInt: newIPv6Network(t, "2607:f0d0:1002:0051:0000:0000:0000:0004"), - z07_ipMaskStr: "ffffffffffffffffffffffffffffffff", - z08_maskbits: 128, - z09_NetIPNetStringOut: "2607:f0d0:1002:51::4/128", - z10_maskInt: newIPv6Mask(t, "ffffffffffffffffffffffffffffffff"), - z11_networkStr: "2607:f0d0:1002:51::4", - z12_octets: []int{0x26, 0x7, 0xf0, 0xd0, 0x10, 0x2, 0x0, 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4}, - z13_firstUsable: "2607:f0d0:1002:51::4", - z14_lastUsable: "2607:f0d0:1002:51::4", - z17_DialPacketArgs: []string{"udp6", ""}, - z18_DialStreamArgs: []string{"tcp6", ""}, - z19_ListenPacketArgs: []string{"udp6", "[2607:f0d0:1002:51::4]:0"}, - z20_ListenStreamArgs: []string{"tcp6", "[2607:f0d0:1002:51::4]:0"}, - z99_pass: true, - }, - { // 7 - unspecified address - z00_input: "0:0:0:0:0:0:0:0", - z01_addrHexStr: "00000000000000000000000000000000", - z02_addrBinStr: "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - z03_addrStr: "::", - z04_NetIPStringOut: "::", - z05_addrInt: newIPv6Address(t, "0"), - z06_netInt: newIPv6Network(t, "0"), - z07_ipMaskStr: "ffffffffffffffffffffffffffffffff", - z08_maskbits: 128, - z09_NetIPNetStringOut: "::/128", - z10_maskInt: newIPv6Mask(t, "ffffffffffffffffffffffffffffffff"), - z11_networkStr: "::", - z12_octets: []int{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, - z13_firstUsable: "::", - z14_lastUsable: "::", - z17_DialPacketArgs: []string{"udp6", ""}, - z18_DialStreamArgs: []string{"tcp6", ""}, - z19_ListenPacketArgs: []string{"udp6", "[::]:0"}, - z20_ListenStreamArgs: []string{"tcp6", "[::]:0"}, - z99_pass: true, - }, - { // 8 - loopback address - z00_input: "0:0:0:0:0:0:0:1", - z01_addrHexStr: "00000000000000000000000000000001", - z02_addrBinStr: "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", - z03_addrStr: "::1", - z04_NetIPStringOut: "::1", - z05_addrInt: newIPv6Address(t, "0000:0000:0000:0000:0000:0000:0000:0001"), - z06_netInt: newIPv6Network(t, "0000:0000:0000:0000:0000:0000:0000:0001"), - z07_ipMaskStr: "ffffffffffffffffffffffffffffffff", - z08_maskbits: 128, - z09_NetIPNetStringOut: "::1/128", - z10_maskInt: newIPv6Mask(t, "ffffffffffffffffffffffffffffffff"), - z11_networkStr: "::1", - z12_octets: []int{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01}, - z13_firstUsable: "::1", - z14_lastUsable: "::1", - z17_DialPacketArgs: []string{"udp6", ""}, - z18_DialStreamArgs: []string{"tcp6", ""}, - z19_ListenPacketArgs: []string{"udp6", "[::1]:0"}, - z20_ListenStreamArgs: []string{"tcp6", "[::1]:0"}, - z99_pass: true, - }, - { // 9 - IPv6 with CIDR (RFC 3849) - z00_input: "2001:DB8::/32", - z01_addrHexStr: "20010db8000000000000000000000000", - z02_addrBinStr: "00100000000000010000110110111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - z03_addrStr: "2001:db8::/32", - z04_NetIPStringOut: "2001:db8::", - z05_addrInt: newIPv6Address(t, "20010db8000000000000000000000000"), - z06_netInt: newIPv6Network(t, "20010db8000000000000000000000000"), - z07_ipMaskStr: "ffffffff000000000000000000000000", - z08_maskbits: 32, - z09_NetIPNetStringOut: "2001:db8::/32", - z10_maskInt: newIPv6Mask(t, "ffffffff000000000000000000000000"), - z11_networkStr: "2001:db8::/32", - z12_octets: []int{0x20, 0x01, 0x0d, 0xb8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, - z13_firstUsable: "2001:db8::", - z14_lastUsable: "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff", - z17_DialPacketArgs: []string{"udp6", ""}, - z18_DialStreamArgs: []string{"tcp6", ""}, - z19_ListenPacketArgs: []string{"udp6", ""}, - z20_ListenStreamArgs: []string{"tcp6", ""}, - z99_pass: true, - }, - { // 10 - IPv6 ::1 - z00_input: "::1", - z01_addrHexStr: "00000000000000000000000000000001", - z02_addrBinStr: "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", - z03_addrStr: "::1", - z04_NetIPStringOut: "::1", - z05_addrInt: newIPv6Address(t, "00000000000000000000000000000001"), - z06_netInt: newIPv6Network(t, "00000000000000000000000000000001"), - z07_ipMaskStr: "ffffffffffffffffffffffffffffffff", - z08_maskbits: 128, - z09_NetIPNetStringOut: "::1/128", - z10_maskInt: newIPv6Mask(t, "ffffffffffffffffffffffffffffffff"), - z11_networkStr: "::1", - z12_octets: []int{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}, - z13_firstUsable: "::1", - z14_lastUsable: "::1", - z17_DialPacketArgs: []string{"udp6", ""}, - z18_DialStreamArgs: []string{"tcp6", ""}, - z19_ListenPacketArgs: []string{"udp6", "[::1]:0"}, - z20_ListenStreamArgs: []string{"tcp6", "[::1]:0"}, - z99_pass: true, - }, - { // 11 - IPv6 100:: - z00_input: "100::", - z01_addrHexStr: "01000000000000000000000000000000", - z02_addrBinStr: "00000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - z03_addrStr: "100::", - z04_NetIPStringOut: "100::", - z05_addrInt: newIPv6Address(t, "01000000000000000000000000000000"), - z06_netInt: newIPv6Network(t, "01000000000000000000000000000000"), - z07_ipMaskStr: "ffffffffffffffffffffffffffffffff", - z08_maskbits: 128, - z09_NetIPNetStringOut: "100::/128", - z10_maskInt: newIPv6Mask(t, "ffffffffffffffffffffffffffffffff"), - z11_networkStr: "100::", - z12_octets: []int{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, - z13_firstUsable: "100::", - z14_lastUsable: "100::", - z17_DialPacketArgs: []string{"udp6", ""}, - z18_DialStreamArgs: []string{"tcp6", ""}, - z19_ListenPacketArgs: []string{"udp6", "[100::]:0"}, - z20_ListenStreamArgs: []string{"tcp6", "[100::]:0"}, - z99_pass: true, - }, - { // 12 - IPv6 100::2 - z00_input: "100::2", - z01_addrHexStr: "01000000000000000000000000000002", - z02_addrBinStr: "00000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010", - z03_addrStr: "100::2", - z04_NetIPStringOut: "100::2", - z05_addrInt: newIPv6Address(t, "01000000000000000000000000000002"), - z06_netInt: newIPv6Network(t, "01000000000000000000000000000002"), - z07_ipMaskStr: "ffffffffffffffffffffffffffffffff", - z08_maskbits: 128, - z09_NetIPNetStringOut: "100::2/128", - z10_maskInt: newIPv6Mask(t, "ffffffffffffffffffffffffffffffff"), - z11_networkStr: "100::2", - z12_octets: []int{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x02}, - z13_firstUsable: "100::2", - z14_lastUsable: "100::2", - z17_DialPacketArgs: []string{"udp6", ""}, - z18_DialStreamArgs: []string{"tcp6", ""}, - z19_ListenPacketArgs: []string{"udp6", "[100::2]:0"}, - z20_ListenStreamArgs: []string{"tcp6", "[100::2]:0"}, - z99_pass: true, - }, - { // 13 - IPv6 `[100::2]:80` - z00_input: "[100::2]:80", - z01_addrHexStr: "01000000000000000000000000000002", - z02_addrBinStr: "00000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010", - z03_addrStr: "[100::2]:80", - z04_NetIPStringOut: "100::2", - z05_addrInt: newIPv6Address(t, "01000000000000000000000000000002"), - z06_netInt: newIPv6Network(t, "01000000000000000000000000000002"), - z07_ipMaskStr: "ffffffffffffffffffffffffffffffff", - z08_maskbits: 128, - z09_NetIPNetStringOut: "100::2/128", - z10_maskInt: newIPv6Mask(t, "ffffffffffffffffffffffffffffffff"), - z11_networkStr: "100::2", - z12_octets: []int{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x02}, - z13_firstUsable: "100::2", - z14_lastUsable: "100::2", - z16_portInt: 80, - z17_DialPacketArgs: []string{"udp6", "[100::2]:80"}, - z18_DialStreamArgs: []string{"tcp6", "[100::2]:80"}, - z19_ListenPacketArgs: []string{"udp6", "[100::2]:80"}, - z20_ListenStreamArgs: []string{"tcp6", "[100::2]:80"}, - z99_pass: true, - }, - } - - for idx, test := range tests { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - ipv6, err := sockaddr.NewIPv6Addr(test.z00_input) - if test.z99_pass && err != nil { - t.Fatalf("[%d] Unable to create an IPv6Addr from %+q: %v", idx, test.z00_input, err) - } else if !test.z99_pass && err == nil { - t.Fatalf("[%d] Expected test to fail for %+q", idx, test.z00_input) - } else if !test.z99_pass && err != nil { - // Expected failure, return success - return - } - - if type_ := ipv6.Type(); type_ != sockaddr.TypeIPv6 { - t.Errorf("[%d] Expected new IPv6Addr to be Type %d, received %d (int)", idx, sockaddr.TypeIPv6, type_) - } - - h, ok := ipv6.Host().(sockaddr.IPv6Addr) - if !ok { - t.Errorf("[%d] Unable to type assert +%q's Host to IPv6Addr", idx, test.z00_input) - } - - hAddressBigInt := big.Int(*h.Address) - hMaskBigInt := big.Int(*h.Mask) - if hAddressBigInt.Cmp(ipv6.Address) != 0 || hMaskBigInt.Cmp(ipv6HostMask) != 0 || h.Port != ipv6.Port { - t.Errorf("[%d] Expected %+q's Host() to return identical IPv6Addr except mask, received %+q", idx, test.z00_input, h.String()) - } - - if c := cap(*ipv6.NetIP()); c != sockaddr.IPv6len { - t.Errorf("[%d] Expected new IPv6Addr's Address capacity to be %d bytes, received %d", idx, sockaddr.IPv6len, c) - } - - if l := len(*ipv6.NetIP()); l != sockaddr.IPv6len { - t.Errorf("[%d] Expected new IPv6Addr's Address length to be %d bytes, received %d", idx, sockaddr.IPv6len, l) - } - - if s := ipv6.AddressHexString(); s != test.z01_addrHexStr { - t.Errorf("[%d] Expected address %+q's hexadecimal representation to be %+q, received %+q", idx, test.z00_input, test.z01_addrHexStr, s) - } - - if s := ipv6.AddressBinString(); s != test.z02_addrBinStr { - t.Errorf("[%d] Expected address %+q's binary representation to be %+q, received %+q", idx, test.z00_input, test.z02_addrBinStr, s) - } - - if s := ipv6.String(); s != test.z03_addrStr { - t.Errorf("[%d] Expected %+q's String to be %+q, received %+q", idx, test.z00_input, test.z03_addrStr, s) - } - - if s := ipv6.NetIP().String(); s != test.z04_NetIPStringOut { - t.Errorf("[%d] Expected %+q's address to be %+q, received %+q", idx, test.z00_input, test.z04_NetIPStringOut, s) - } - - if hAddressBigInt.Cmp(test.z05_addrInt) != 0 { - t.Errorf("[%d] Expected %+q's Address to return %+v, received %+v", idx, test.z00_input, test.z05_addrInt, hAddressBigInt) - } - - n, ok := ipv6.Network().(sockaddr.IPv6Addr) - if !ok { - t.Errorf("[%d] Unable to type assert +%q's Network to IPv6Addr", idx, test.z00_input) - } - - nAddressBigInt := big.Int(*n.Address) - if nAddressBigInt.Cmp(test.z06_netInt) != 0 { - t.Errorf("[%d] Expected %+q's Network to return %+v, received %+v", idx, test.z00_input, test.z06_netInt, n.Address) - } - - if m := ipv6.NetIPMask().String(); m != test.z07_ipMaskStr { - t.Errorf("[%d] Expected %+q's mask to be %+q, received %+q", idx, test.z00_input, test.z07_ipMaskStr, m) - } - - if m := ipv6.Maskbits(); m != test.z08_maskbits { - t.Errorf("[%dr] Expected %+q's port to be %+v, received %+v", idx, test.z00_input, test.z08_maskbits, m) - } - - if n := ipv6.NetIPNet().String(); n != test.z09_NetIPNetStringOut { - t.Errorf("[%d] Expected %+q's network to be %+q, received %+q", idx, test.z00_input, test.z09_NetIPNetStringOut, n) - } - - ipv6MaskBigInt := big.Int(*ipv6.Mask) - if ipv6MaskBigInt.Cmp(test.z10_maskInt) != 0 { - t.Errorf("[%d] Expected %+q's Mask to return %+v, received %+v", idx, test.z00_input, test.z10_maskInt, ipv6MaskBigInt) - } - - nMaskBigInt := big.Int(*n.Mask) - if nMaskBigInt.Cmp(test.z10_maskInt) != 0 { - t.Errorf("[%d] Expected %+q's Network's Mask to return %+v, received %+v", idx, test.z00_input, test.z10_maskInt, nMaskBigInt) - } - - // Network()'s mask must match the IPv6Addr's Mask - if n := ipv6.Network().String(); n != test.z11_networkStr { - t.Errorf("[%d] Expected %+q's Network() to be %+q, received %+q", idx, test.z00_input, test.z11_networkStr, n) - } - - if o := ipv6.Octets(); len(o) != 16 || cap(o) != 16 || - o[0] != test.z12_octets[0] || o[1] != test.z12_octets[1] || - o[2] != test.z12_octets[2] || o[3] != test.z12_octets[3] || - o[4] != test.z12_octets[4] || o[5] != test.z12_octets[5] || - o[6] != test.z12_octets[6] || o[7] != test.z12_octets[7] || - o[8] != test.z12_octets[8] || o[9] != test.z12_octets[9] || - o[10] != test.z12_octets[10] || o[11] != test.z12_octets[11] || - o[12] != test.z12_octets[12] || o[13] != test.z12_octets[13] || - o[14] != test.z12_octets[14] || o[15] != test.z12_octets[15] { - t.Errorf("[%d] Expected %+q's Octets to be %x, received %x", idx, test.z00_input, test.z12_octets, o) - } - - if f := ipv6.FirstUsable().String(); f != test.z13_firstUsable { - t.Errorf("[%d] Expected %+q's FirstUsable() to be %+q, received %+q", idx, test.z00_input, test.z13_firstUsable, f) - } - - if l := ipv6.LastUsable().String(); l != test.z14_lastUsable { - t.Errorf("[%d] Expected %+q's LastUsable() to be %+q, received %+q", idx, test.z00_input, test.z14_lastUsable, l) - } - - if p := ipv6.IPPort(); sockaddr.IPPort(p) != test.z16_portInt || sockaddr.IPPort(p) != test.z16_portInt { - t.Errorf("[%d] Expected %+q's port to be %+v, received %+v", idx, test.z00_input, test.z16_portInt, p) - } - - if dialNet, dialArgs := ipv6.DialPacketArgs(); dialNet != test.z17_DialPacketArgs[0] || dialArgs != test.z17_DialPacketArgs[1] { - t.Errorf("[%d] Expected %+q's DialPacketArgs() to be %+q, received %+q, %+q", idx, test.z00_input, test.z17_DialPacketArgs, dialNet, dialArgs) - } - - if dialNet, dialArgs := ipv6.DialStreamArgs(); dialNet != test.z18_DialStreamArgs[0] || dialArgs != test.z18_DialStreamArgs[1] { - t.Errorf("[%d] Expected %+q's DialStreamArgs() to be %+q, received %+q, %+q", idx, test.z00_input, test.z18_DialStreamArgs, dialNet, dialArgs) - } - - if listenNet, listenArgs := ipv6.ListenPacketArgs(); listenNet != test.z19_ListenPacketArgs[0] || listenArgs != test.z19_ListenPacketArgs[1] { - t.Errorf("[%d] Expected %+q's ListenPacketArgs() to be %+q, received %+q, %+q", idx, test.z00_input, test.z19_ListenPacketArgs, listenNet, listenArgs) - } - - if listenNet, listenArgs := ipv6.ListenStreamArgs(); listenNet != test.z20_ListenStreamArgs[0] || listenArgs != test.z20_ListenStreamArgs[1] { - t.Errorf("[%d] Expected %+q's ListenStreamArgs() to be %+q, received %+q, %+q", idx, test.z00_input, test.z20_ListenStreamArgs, listenNet, listenArgs) - } - }) - } -} - -func TestSockAddr_IPv6Addr_CmpAddress(t *testing.T) { - tests := []struct { - a string - b string - cmp int - }{ - { // 0 - a: "2001:4860:0:2001::68/128", - b: "2001:4860:0:2001::68", - cmp: 0, - }, - { // 1 - a: "2607:f0d0:1002:0051:0000:0000:0000:0004/128", - b: "2607:f0d0:1002:0051:0000:0000:0000:0004", - cmp: 0, - }, - { // 2 - a: "2607:f0d0:1002:0051:0000:0000:0000:0004/128", - b: "2607:f0d0:1002:0051:0000:0000:0000:0004/64", - cmp: 0, - }, - { // 3 - a: "2607:f0d0:1002:0051:0000:0000:0000:0004", - b: "2607:f0d0:1002:0051:0000:0000:0000:0005", - cmp: -1, - }, - } - - for idx, test := range tests { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - ipv6a, err := sockaddr.NewIPv6Addr(test.a) - if err != nil { - t.Fatalf("[%d] Unable to create an IPv6Addr from %+q: %v", idx, test.a, err) - } - - ipv6b, err := sockaddr.NewIPv6Addr(test.b) - if err != nil { - t.Fatalf("[%d] Unable to create an IPv6Addr from %+q: %v", idx, test.b, err) - } - - if x := ipv6a.CmpAddress(ipv6b); x != test.cmp { - t.Errorf("[%d] IPv6Addr.CmpAddress() failed with %+q with %+q (expected %d, received %d)", idx, ipv6a, ipv6b, test.cmp, x) - } - - if x := ipv6b.CmpAddress(ipv6a); x*-1 != test.cmp { - t.Errorf("[%d] IPv6Addr.CmpAddress() failed with %+q with %+q (expected %d, received %d)", idx, ipv6a, ipv6b, test.cmp, x) - } - }) - } -} - -func TestSockAddr_IPv6Addr_ContainsAddress(t *testing.T) { - tests := []struct { - name string - input sockaddr.IPv6Addr - cases []sockaddr.IPv6Addr - fail bool - }{ - { - name: "basic", - input: sockaddr.MustIPv6Addr("::1/128"), - cases: []sockaddr.IPv6Addr{ - sockaddr.MustIPv6Addr("::1"), - sockaddr.MustIPv6Addr("[::1/128]"), - }, - }, - { - name: "fail", - input: sockaddr.MustIPv6Addr("::1/128"), - cases: []sockaddr.IPv6Addr{ - sockaddr.MustIPv6Addr("100::"), - }, - fail: true, - }, - { - name: "fail2", - input: sockaddr.MustIPv6Addr("100::/128"), - cases: []sockaddr.IPv6Addr{ - sockaddr.MustIPv6Addr("::1"), - }, - fail: true, - }, - } - - for idx, test := range tests { - if test.name == "" { - t.Fatalf("test %d needs a name", idx) - } - - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - ipv6 := test.input - - for _, tc := range test.cases { - if ipv6.ContainsAddress(tc.Address) == test.fail { - t.Errorf("%s: Expected %q.ContainsAddress(%q)==%t", test.name, ipv6, tc, test.fail) - } - } - }) - } -} - -func TestSockAddr_IPv6Addr_ContainsNetwork(t *testing.T) { - tests := []struct { - input string - pass []string - fail []string - }{ - { // 0 - input: "::1/128", - pass: []string{ - "::1", - "[::1/128]", - }, - fail: []string{ - "100::", - }, - }, - } - - for idx, test := range tests { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - ipv6, err := sockaddr.NewIPv6Addr(test.input) - if err != nil { - t.Fatalf("[%d] Unable to create an IPv6Addr from %+q: %v", idx, test.input, err) - } - - for passIdx, passInput := range test.pass { - passAddr, err := sockaddr.NewIPv6Addr(passInput) - if err != nil { - t.Fatalf("[%d/%d] Unable to create an IPv6Addr from %+q: %v", idx, passIdx, passInput, err) - } - - if !passAddr.ContainsNetwork(ipv6) { - t.Errorf("[%d/%d] Expected %+q to contain %+q", idx, passIdx, test.input, passInput) - } - } - - for failIdx, failInput := range test.fail { - failAddr, err := sockaddr.NewIPv6Addr(failInput) - if err != nil { - t.Fatalf("[%d/%d] Unable to create an IPv6Addr from %+q: %v", idx, failIdx, failInput, err) - } - - if failAddr.ContainsNetwork(ipv6) { - t.Errorf("[%d/%d] Expected %+q to contain %+q", idx, failIdx, test.input, failInput) - } - } - }) - } -} - -func TestSockAddr_IPv6Addr_Equal(t *testing.T) { - tests := []struct { - name string - input sockaddr.IPv6Addr - cases sockaddr.SockAddrs - fail bool - }{ - { - name: "addr equal", - input: sockaddr.MustIPv6Addr("2001:4860:0:2001::68/128"), - cases: sockaddr.SockAddrs{ - sockaddr.MustIPv6Addr("2001:4860:0:2001::68"), - sockaddr.MustIPv6Addr("2001:4860:0:2001::68/128"), - sockaddr.MustIPv6Addr("[2001:4860:0:2001::68]:0"), - }, - }, - { - name: "IPv6Addr not equal", - input: sockaddr.MustIPv6Addr("2001:4860:0:2001::68/128"), - cases: sockaddr.SockAddrs{ - sockaddr.MustIPv6Addr("2001:DB8::/48"), - sockaddr.MustIPv6Addr("2001:4860:0:2001::67/128"), - sockaddr.MustIPv6Addr("2001:4860:0:2001::67"), - sockaddr.MustIPv6Addr("[2001:4860:0:2001::68]:80"), - sockaddr.MustIPv4Addr("1.2.3.4"), - sockaddr.MustUnixSock("/tmp/foo"), - }, - fail: true, - }, - { - name: "equal CIDR", - input: sockaddr.MustIPv6Addr("2001:4860:0:2001::68/64"), - cases: sockaddr.SockAddrs{ - sockaddr.MustIPv6Addr("2001:4860:0:2001::68/64"), - }, - }, - { - name: "not equal CIDR", - input: sockaddr.MustIPv6Addr("2001:4860:0:2001::68/64"), - cases: sockaddr.SockAddrs{ - sockaddr.MustIPv6Addr("2001:DB8::/48"), - sockaddr.MustIPv6Addr("2001:4860:0:2001::67/128"), - sockaddr.MustIPv6Addr("2001:4860:0:2001::67"), - sockaddr.MustIPv6Addr("[2001:4860:0:2001::68]:80"), - sockaddr.MustIPv4Addr("1.2.3.4/32"), - sockaddr.MustUnixSock("/tmp/foo"), - }, - fail: true, - }, - } - - for idx, test := range tests { - if test.name == "" { - t.Fatalf("test %d needs a name", idx) - } - - t.Run(test.name, func(t *testing.T) { - ipv6 := test.input - for _, tc := range test.cases { - if ipv6.Equal(tc) == test.fail { - t.Errorf("%s: Expected %s Equal(%q)=%t", test.name, ipv6, tc, test.fail) - } - } - }) - } -} - -func TestIPv6Addr_CmpRFC(t *testing.T) { - tests := []struct { - name string - recv sockaddr.SockAddr - arg sockaddr.SockAddr - rfcNum uint - want int - }{ - { - name: "simple in RFC", - recv: sockaddr.MustIPv6Addr("::1"), - arg: sockaddr.MustIPv6Addr("100::"), - rfcNum: 6590, - }, - { - name: "ipv6 cmp IPv4", - recv: sockaddr.MustIPv6Addr("2002:c058:6301::/120"), - arg: sockaddr.MustIPv4Addr("192.88.99.0/24"), - rfcNum: 3068, - want: -1, - }, - { - name: "ipv6 cmp IPv4", - recv: sockaddr.MustIPv6Addr("::1"), - arg: sockaddr.MustIPv4Addr("1.2.3.4"), - rfcNum: 6590, - }, - { - name: "ipv6 cmp IPv4", - recv: sockaddr.MustIPv6Addr("::1"), - arg: sockaddr.MustIPv4Addr("192.168.1.1"), - rfcNum: 1918, - }, - } - - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d needs a name", i) - } - - t.Run(test.name, func(t *testing.T) { - if cmp := test.recv.CmpRFC(test.rfcNum, test.arg); cmp != test.want { - t.Fatalf("%s: want %d got %d", test.name, test.want, cmp) - } - }) - } -} - -func TestIPv6Attrs(t *testing.T) { - const expectedNumAttrs = 2 - attrs := sockaddr.IPv6Attrs() - if len(attrs) != expectedNumAttrs { - t.Fatalf("wrong number of IPv6Attrs: %d vs %d", len(attrs), expectedNumAttrs) - } -} diff --git a/vendor/github.com/hashicorp/go-sockaddr/rfc_test.go b/vendor/github.com/hashicorp/go-sockaddr/rfc_test.go deleted file mode 100644 index af669a43f..000000000 --- a/vendor/github.com/hashicorp/go-sockaddr/rfc_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package sockaddr_test - -import ( - "testing" - - sockaddr "github.com/hashicorp/go-sockaddr" -) - -func TestVisitAllRFCs(t *testing.T) { - const expectedNumRFCs = 28 - numRFCs := 0 - sockaddr.VisitAllRFCs(func(rfcNum uint, sas sockaddr.SockAddrs) { - numRFCs++ - }) - if numRFCs != expectedNumRFCs { - t.Fatalf("wrong number of RFCs: %d", numRFCs) - } -} - -func TestIsRFC(t *testing.T) { - tests := []struct { - name string - sa sockaddr.SockAddr - rfcNum uint - result bool - }{ - { - name: "rfc1918 pass", - sa: sockaddr.MustIPv4Addr("192.168.0.0/16"), - rfcNum: 1918, - result: true, - }, - { - name: "rfc1918 fail", - sa: sockaddr.MustIPv4Addr("1.2.3.4"), - rfcNum: 1918, - result: false, - }, - { - name: "rfc1918 pass", - sa: sockaddr.MustIPv4Addr("192.168.1.1"), - rfcNum: 1918, - result: true, - }, - { - name: "invalid rfc", - sa: sockaddr.MustIPv4Addr("192.168.0.0/16"), - rfcNum: 999999999999, - result: false, - }, - } - - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d needs a name", i) - } - - result := sockaddr.IsRFC(test.rfcNum, test.sa) - if result != test.result { - t.Fatalf("expected a match") - } - } -} diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info_test.go b/vendor/github.com/hashicorp/go-sockaddr/route_info_test.go deleted file mode 100644 index 1716327e8..000000000 --- a/vendor/github.com/hashicorp/go-sockaddr/route_info_test.go +++ /dev/null @@ -1,196 +0,0 @@ -package sockaddr - -import "testing" - -func Test_parseBSDDefaultIfName(t *testing.T) { - testCases := []struct { - name string - routeOut string - want string - }{ - { - name: "macOS Sierra 10.12 - Common", - routeOut: ` route to: default -destination: default - mask: default - gateway: 10.23.9.1 - interface: en0 - flags: - recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire - 0 0 0 0 0 0 1500 0 -`, - want: "en0", - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - got, err := parseDefaultIfNameFromRoute(tc.routeOut) - if err != nil { - t.Fatalf("unable to parse default interface from route output: %v", err) - } - - if got != tc.want { - t.Errorf("got %s; want %s", got, tc.want) - } - }) - } -} - -func Test_parseLinuxDefaultIfName(t *testing.T) { - testCases := []struct { - name string - routeOut string - want string - }{ - { - name: "Linux Ubuntu 14.04 - Common", - routeOut: `default via 10.1.2.1 dev eth0 -10.1.2.0/24 dev eth0 proto kernel scope link src 10.1.2.5 -`, - want: "eth0", - }, - { - name: "Chromebook - 8743.85.0 (Official Build) stable-channel gandof, Milestone 54", - routeOut: `default via 192.168.1.1 dev wlan0 metric 1 -192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.174 -`, - want: "wlan0", - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - got, err := parseDefaultIfNameFromIPCmd(tc.routeOut) - if err != nil { - t.Fatalf("unable to parse default interface from route output: %v", err) - } - - if got != tc.want { - t.Errorf("got %+q; want %+q", got, tc.want) - } - }) - } -} - -func Test_parseWindowsDefaultIfName(t *testing.T) { - testCases := []struct { - name string - routeOut string - ipconfigOut string - want string - }{ - { - name: "Windows 10 - Enterprise", - routeOut: `=========================================================================== -Interface List - 10...08 00 27 a2 e9 51 ......Intel(R) PRO/1000 MT Desktop Adapter - 13...08 00 27 35 02 ed ......Intel(R) PRO/1000 MT Desktop Adapter #2 - 1...........................Software Loopback Interface 1 - 5...00 00 00 00 00 00 00 e0 Microsoft ISATAP Adapter - 8...00 00 00 00 00 00 00 e0 Microsoft ISATAP Adapter #3 -=========================================================================== - -IPv4 Route Table -=========================================================================== -Active Routes: -Network Destination Netmask Gateway Interface Metric - 0.0.0.0 0.0.0.0 10.0.2.2 10.0.2.15 25 - 10.0.2.0 255.255.255.0 On-link 10.0.2.15 281 - 10.0.2.15 255.255.255.255 On-link 10.0.2.15 281 - 10.0.2.255 255.255.255.255 On-link 10.0.2.15 281 - 127.0.0.0 255.0.0.0 On-link 127.0.0.1 331 - 127.0.0.1 255.255.255.255 On-link 127.0.0.1 331 - 127.255.255.255 255.255.255.255 On-link 127.0.0.1 331 - 192.168.56.0 255.255.255.0 On-link 192.168.56.100 281 - 192.168.56.100 255.255.255.255 On-link 192.168.56.100 281 - 192.168.56.255 255.255.255.255 On-link 192.168.56.100 281 - 224.0.0.0 240.0.0.0 On-link 127.0.0.1 331 - 224.0.0.0 240.0.0.0 On-link 192.168.56.100 281 - 224.0.0.0 240.0.0.0 On-link 10.0.2.15 281 - 255.255.255.255 255.255.255.255 On-link 127.0.0.1 331 - 255.255.255.255 255.255.255.255 On-link 192.168.56.100 281 - 255.255.255.255 255.255.255.255 On-link 10.0.2.15 281 -=========================================================================== -Persistent Routes: - None - -IPv6 Route Table -=========================================================================== -Active Routes: - If Metric Network Destination Gateway - 1 331 ::1/128 On-link - 13 281 fe80::/64 On-link - 10 281 fe80::/64 On-link - 13 281 fe80::60cc:155f:77a4:ab99/128 - On-link - 10 281 fe80::cccc:710e:f5bb:3088/128 - On-link - 1 331 ff00::/8 On-link - 13 281 ff00::/8 On-link - 10 281 ff00::/8 On-link -=========================================================================== -Persistent Routes: - None -`, - ipconfigOut: `Windows IP Configuration - - -Ethernet adapter Ethernet: - - Connection-specific DNS Suffix . : host.example.org - Link-local IPv6 Address . . . . . : fe80::cccc:710e:f5bb:3088%10 - IPv4 Address. . . . . . . . . . . : 10.0.2.15 - Subnet Mask . . . . . . . . . . . : 255.255.255.0 - Default Gateway . . . . . . . . . : 10.0.2.2 - -Ethernet adapter Ethernet 2: - - Connection-specific DNS Suffix . : - Link-local IPv6 Address . . . . . : fe80::60cc:155f:77a4:ab99%13 - IPv4 Address. . . . . . . . . . . : 192.168.56.100 - Subnet Mask . . . . . . . . . . . : 255.255.255.0 - Default Gateway . . . . . . . . . : - -Tunnel adapter isatap.host.example.org: - - Media State . . . . . . . . . . . : Media disconnected - Connection-specific DNS Suffix . : - -Tunnel adapter Reusable ISATAP Interface {F3F2E4A5-8823-40E5-87EA-1F6881BACC95}: - - Media State . . . . . . . . . . . : Media disconnected - Connection-specific DNS Suffix . : host.example.org -`, - want: "Ethernet", - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - got, err := parseDefaultIfNameWindows(tc.routeOut, tc.ipconfigOut) - if err != nil { - t.Fatalf("unable to parse default interface from route output: %v", err) - } - - if got != tc.want { - t.Errorf("got %s; want %s", got, tc.want) - } - }) - } -} - -func Test_VisitComands(t *testing.T) { - ri, err := NewRouteInfo() - if err != nil { - t.Fatalf("bad: %v", err) - } - - var count int - ri.VisitCommands(func(name string, cmd []string) { - count++ - }) - if count == 0 { - t.Fatalf("Expected more than 0 items") - } -} diff --git a/vendor/github.com/hashicorp/go-sockaddr/sockaddr_test.go b/vendor/github.com/hashicorp/go-sockaddr/sockaddr_test.go deleted file mode 100644 index 2471beb24..000000000 --- a/vendor/github.com/hashicorp/go-sockaddr/sockaddr_test.go +++ /dev/null @@ -1,440 +0,0 @@ -package sockaddr_test - -import ( - "encoding/json" - "fmt" - "testing" - - "github.com/hashicorp/go-sockaddr" -) - -// TODO(sean@): Either extend this test to include IPv6Addr and UnixSock, or -// remove and find a good home to test this functionality elsewhere. - -func TestSockAddr_New(t *testing.T) { - type SockAddrFixture struct { - input string - ResultType string - NetworkAddress string - BroadcastAddress string - IPUint32 sockaddr.IPv4Address - Maskbits int - BinString string - HexString string - FirstUsableAddress string - LastUsableAddress string - } - type SockAddrFixtures []SockAddrFixtures - - goodResults := []SockAddrFixture{ - { - input: "0.0.0.0", - ResultType: "ipv4", - NetworkAddress: "0.0.0.0", - BroadcastAddress: "0.0.0.0", - Maskbits: 32, - IPUint32: 0, - BinString: "00000000000000000000000000000000", - HexString: "00000000", - FirstUsableAddress: "0.0.0.0", - LastUsableAddress: "0.0.0.0", - }, - { - input: "0.0.0.0/0", - ResultType: "ipv4", - NetworkAddress: "0.0.0.0", - BroadcastAddress: "255.255.255.255", - Maskbits: 0, - IPUint32: 0, - BinString: "00000000000000000000000000000000", - HexString: "00000000", - FirstUsableAddress: "0.0.0.1", - LastUsableAddress: "255.255.255.254", - }, - { - input: "0.0.0.1", - ResultType: "ipv4", - NetworkAddress: "0.0.0.1", - BroadcastAddress: "0.0.0.1", - Maskbits: 32, - IPUint32: 1, - BinString: "00000000000000000000000000000001", - HexString: "00000001", - FirstUsableAddress: "0.0.0.1", - LastUsableAddress: "0.0.0.1", - }, - { - input: "0.0.0.1/1", - ResultType: "ipv4", - NetworkAddress: "0.0.0.0", - BroadcastAddress: "127.255.255.255", - Maskbits: 1, - IPUint32: 1, - BinString: "00000000000000000000000000000001", - HexString: "00000001", - FirstUsableAddress: "0.0.0.1", - LastUsableAddress: "127.255.255.254", - }, - { - input: "128.0.0.0", - ResultType: "ipv4", - NetworkAddress: "128.0.0.0", - BroadcastAddress: "128.0.0.0", - Maskbits: 32, - IPUint32: 2147483648, - BinString: "10000000000000000000000000000000", - HexString: "80000000", - FirstUsableAddress: "128.0.0.0", - LastUsableAddress: "128.0.0.0", - }, - { - input: "255.255.255.255", - ResultType: "ipv4", - NetworkAddress: "255.255.255.255", - BroadcastAddress: "255.255.255.255", - Maskbits: 32, - IPUint32: 4294967295, - BinString: "11111111111111111111111111111111", - HexString: "ffffffff", - FirstUsableAddress: "255.255.255.255", - LastUsableAddress: "255.255.255.255", - }, - { - input: "1.2.3.4", - ResultType: "ipv4", - NetworkAddress: "1.2.3.4", - BroadcastAddress: "1.2.3.4", - Maskbits: 32, - IPUint32: 16909060, - BinString: "00000001000000100000001100000100", - HexString: "01020304", - FirstUsableAddress: "1.2.3.4", - LastUsableAddress: "1.2.3.4", - }, - { - input: "192.168.10.10/16", - ResultType: "ipv4", - NetworkAddress: "192.168.0.0", - BroadcastAddress: "192.168.255.255", - Maskbits: 16, - IPUint32: 3232238090, - BinString: "11000000101010000000101000001010", - HexString: "c0a80a0a", - FirstUsableAddress: "192.168.0.1", - LastUsableAddress: "192.168.255.254", - }, - { - input: "192.168.1.10/24", - ResultType: "ipv4", - NetworkAddress: "192.168.1.0", - BroadcastAddress: "192.168.1.255", - Maskbits: 24, - IPUint32: 3232235786, - BinString: "11000000101010000000000100001010", - HexString: "c0a8010a", - FirstUsableAddress: "192.168.1.1", - LastUsableAddress: "192.168.1.254", - }, - { - input: "192.168.0.1", - ResultType: "ipv4", - NetworkAddress: "192.168.0.1", - BroadcastAddress: "192.168.0.1", - Maskbits: 32, - IPUint32: 3232235521, - BinString: "11000000101010000000000000000001", - HexString: "c0a80001", - FirstUsableAddress: "192.168.0.1", - LastUsableAddress: "192.168.0.1", - }, - { - input: "192.168.0.2/31", - ResultType: "ipv4", - NetworkAddress: "192.168.0.2", - BroadcastAddress: "192.168.0.3", - Maskbits: 31, - IPUint32: 3232235522, - BinString: "11000000101010000000000000000010", - HexString: "c0a80002", - FirstUsableAddress: "192.168.0.2", - LastUsableAddress: "192.168.0.3", - }, - { - input: "240.0.0.0/4", - ResultType: "ipv4", - NetworkAddress: "240.0.0.0", - BroadcastAddress: "255.255.255.255", - Maskbits: 4, - IPUint32: 4026531840, - BinString: "11110000000000000000000000000000", - HexString: "f0000000", - FirstUsableAddress: "240.0.0.1", - LastUsableAddress: "255.255.255.254", - }, - } - - for idx, r := range goodResults { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - var ( - addr sockaddr.IPAddr - str string - ) - - sa, err := sockaddr.NewSockAddr(r.input) - if err != nil { - t.Fatalf("Failed parse %s", r.input) - } - - switch r.ResultType { - case "ipv4": - ipv4b, err := sockaddr.NewIPv4Addr(r.input) - if err != nil { - t.Fatalf("[%d] Unable to construct a new IPv4 from %s: %s", idx, r.input, err) - } - if !ipv4b.Equal(sa) { - t.Fatalf("[%d] Equality comparison failed on fresh IPv4", idx) - } - - type_ := sa.Type() - if type_ != sockaddr.TypeIPv4 { - t.Fatalf("[%d] Type mismatch for %s: %d", idx, r.input, type_) - } - - ipv4 := sockaddr.ToIPv4Addr(sa) - if ipv4 == nil { - t.Fatalf("[%d] Failed ToIPv4Addr() %s", idx, r.input) - } - - addr = ipv4.Broadcast() - if addr == nil || addr.NetIP().To4().String() != r.BroadcastAddress { - t.Fatalf("Failed IPv4Addr.BroadcastAddress() %s: expected %+q, received %+q", r.input, r.BroadcastAddress, addr.NetIP().To4().String()) - } - - maskbits := ipv4.Maskbits() - if maskbits != r.Maskbits { - t.Fatalf("Failed Maskbits %s: %d != %d", r.input, maskbits, r.Maskbits) - } - - if ipv4.Address != r.IPUint32 { - t.Fatalf("Failed ToUint32() %s: %d != %d", r.input, ipv4.Address, r.IPUint32) - } - - str = ipv4.AddressBinString() - if str != r.BinString { - t.Fatalf("Failed BinString %s: %s != %s", r.input, str, r.BinString) - } - - str = ipv4.AddressHexString() - if str != r.HexString { - t.Fatalf("Failed HexString %s: %s != %s", r.input, str, r.HexString) - } - - addr = ipv4.Network() - if addr == nil || addr.NetIP().To4().String() != r.NetworkAddress { - t.Fatalf("Failed NetworkAddress %s: %s != %s", r.input, addr.NetIP().To4().String(), r.NetworkAddress) - } - - addr = ipv4.FirstUsable() - if addr == nil || addr.NetIP().To4().String() != r.FirstUsableAddress { - t.Fatalf("Failed FirstUsableAddress %s: %s != %s", r.input, addr.NetIP().To4().String(), r.FirstUsableAddress) - } - - addr = ipv4.LastUsable() - if addr == nil || addr.NetIP().To4().String() != r.LastUsableAddress { - t.Fatalf("Failed LastUsableAddress %s: %s != %s", r.input, addr.NetIP().To4().String(), r.LastUsableAddress) - } - default: - t.Fatalf("Unknown result type: %s", r.ResultType) - } - }) - } - - badResults := []string{ - "256.0.0.0", - "0.0.0.0.0", - } - - for idx, badIP := range badResults { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - sa, err := sockaddr.NewSockAddr(badIP) - if err == nil { - t.Fatalf("Failed should have failed to parse %s: %v", badIP, sa) - } - if sa != nil { - t.Fatalf("SockAddr should be nil") - } - }) - } - -} - -func TestSockAddrAttrs(t *testing.T) { - const expectedNumAttrs = 2 - saa := sockaddr.SockAddrAttrs() - if len(saa) != expectedNumAttrs { - t.Fatalf("wrong number of SockAddrAttrs: %d vs %d", len(saa), expectedNumAttrs) - } - - tests := []struct { - name string - sa sockaddr.SockAddr - attr sockaddr.AttrName - want string - }{ - { - name: "type", - sa: sockaddr.MustIPv4Addr("1.2.3.4"), - attr: "type", - want: "IPv4", - }, - { - name: "string", - sa: sockaddr.MustIPv4Addr("1.2.3.4"), - attr: "string", - want: "1.2.3.4", - }, - { - name: "invalid", - sa: sockaddr.MustIPv4Addr("1.2.3.4"), - attr: "ENOENT", - want: "", - }, - } - - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d needs a name", i) - } - - result := sockaddr.SockAddrAttr(test.sa, test.attr) - if result != test.want { - t.Fatalf("%s: expected %s got %s", test.name, test.want, result) - } - } -} - -func TestToFoo(t *testing.T) { - tests := []struct { - name string - sa sockaddr.SockAddr - passIP bool - passIPv4 bool - passIPv6 bool - passUnix bool - }{ - { - name: "ipv4", - sa: sockaddr.MustIPv4Addr("1.2.3.4"), - passIP: true, - passIPv4: true, - }, - { - name: "ipv6", - sa: sockaddr.MustIPv6Addr("::1"), - passIP: true, - passIPv6: true, - }, - { - name: "unix", - sa: sockaddr.MustUnixSock("/tmp/foo"), - passUnix: true, - }, - } - - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d must have a name", i) - } - - switch us := sockaddr.ToUnixSock(test.sa); { - case us == nil && test.passUnix, - us != nil && !test.passUnix: - t.Fatalf("bad") - } - - switch ip := sockaddr.ToIPAddr(test.sa); { - case ip == nil && test.passIP, - ip != nil && !test.passIP: - t.Fatalf("bad") - } - - switch ipv4 := sockaddr.ToIPv4Addr(test.sa); { - case ipv4 == nil && test.passIPv4, - ipv4 != nil && !test.passIPv4: - t.Fatalf("bad") - } - - switch ipv6 := sockaddr.ToIPv6Addr(test.sa); { - case ipv6 == nil && test.passIPv6, - ipv6 != nil && !test.passIPv6: - t.Fatalf("bad") - } - } - -} - -func TestSockAddrMarshaler(t *testing.T) { - addr := "192.168.10.24/24" - sa, err := sockaddr.NewSockAddr(addr) - if err != nil { - t.Fatal(err) - } - sam := &sockaddr.SockAddrMarshaler{ - SockAddr: sa, - } - marshaled, err := json.Marshal(sam) - if err != nil { - t.Fatal(err) - } - sam2 := &sockaddr.SockAddrMarshaler{} - err = json.Unmarshal(marshaled, sam2) - if err != nil { - t.Fatal(err) - } - if sam.SockAddr.String() != sam2.SockAddr.String() { - t.Fatalf("mismatch after marshaling: %s vs %s", sam.SockAddr.String(), sam2.SockAddr.String()) - } - if sam2.SockAddr.String() != addr { - t.Fatalf("mismatch after marshaling: %s vs %s", addr, sam2.SockAddr.String()) - } -} - -func TestSockAddrMultiMarshaler(t *testing.T) { - addr := "192.168.10.24/24" - type d struct { - Addr *sockaddr.SockAddrMarshaler - Addrs []*sockaddr.SockAddrMarshaler - } - sa, err := sockaddr.NewSockAddr(addr) - if err != nil { - t.Fatal(err) - } - myD := &d{ - Addr: &sockaddr.SockAddrMarshaler{SockAddr: sa}, - Addrs: []*sockaddr.SockAddrMarshaler{ - &sockaddr.SockAddrMarshaler{SockAddr: sa}, - &sockaddr.SockAddrMarshaler{SockAddr: sa}, - &sockaddr.SockAddrMarshaler{SockAddr: sa}, - }, - } - marshaled, err := json.Marshal(myD) - if err != nil { - t.Fatal(err) - } - var myD2 d - err = json.Unmarshal(marshaled, &myD2) - if err != nil { - t.Fatal(err) - } - if myD.Addr.String() != myD2.Addr.String() { - t.Fatalf("mismatch after marshaling: %s vs %s", myD.Addr.String(), myD2.Addr.String()) - } - if len(myD.Addrs) != len(myD2.Addrs) { - t.Fatalf("mismatch after marshaling: %d vs %d", len(myD.Addrs), len(myD2.Addrs)) - } - for i, v := range myD.Addrs { - if v.String() != myD2.Addrs[i].String() { - t.Fatalf("mismatch after marshaling: %s vs %s", v.String(), myD2.Addrs[i].String()) - } - } -} diff --git a/vendor/github.com/hashicorp/go-sockaddr/sockaddrs_test.go b/vendor/github.com/hashicorp/go-sockaddr/sockaddrs_test.go deleted file mode 100644 index a8dcba5ee..000000000 --- a/vendor/github.com/hashicorp/go-sockaddr/sockaddrs_test.go +++ /dev/null @@ -1,338 +0,0 @@ -package sockaddr_test - -import ( - "fmt" - "math/rand" - "testing" - - "github.com/hashicorp/consul/lib" - "github.com/hashicorp/go-sockaddr" -) - -func init() { - lib.SeedMathRand() -} - -// NOTE: A number of these code paths are exercised in template/ and -// cmd/sockaddr/ - -// sockAddrStringInputs allows for easy test creation by developers. -// Parallel arrays of string inputs are converted to their SockAddr -// equivalents for use by unit tests. -type sockAddrStringInputs []struct { - inputAddrs []string - sortedAddrs []string - sortedTypes []sockaddr.SockAddrType - sortFuncs []sockaddr.CmpAddrFunc - numIPv4Inputs int - numIPv6Inputs int - numUnixInputs int -} - -func convertToSockAddrs(t *testing.T, inputs []string) sockaddr.SockAddrs { - sockAddrs := make(sockaddr.SockAddrs, 0, len(inputs)) - for i, input := range inputs { - sa, err := sockaddr.NewSockAddr(input) - if err != nil { - t.Fatalf("[%d] Invalid SockAddr input for %+q: %v", i, input, err) - } - sockAddrs = append(sockAddrs, sa) - } - - return sockAddrs -} - -// shuffleStrings randomly shuffles the list of strings -func shuffleStrings(list []string) { - for i := range list { - j := rand.Intn(i + 1) - list[i], list[j] = list[j], list[i] - } -} - -func TestSockAddr_SockAddrs_AscAddress(t *testing.T) { - testInputs := sockAddrStringInputs{ - { // testNum: 0 - sortFuncs: []sockaddr.CmpAddrFunc{ - sockaddr.AscAddress, - }, - numIPv4Inputs: 9, - numIPv6Inputs: 1, - numUnixInputs: 0, - inputAddrs: []string{ - "10.0.0.0/8", - "172.16.1.3/12", - "128.95.120.2:53", - "128.95.120.2/32", - "192.168.0.0/16", - "128.95.120.1/32", - "192.168.1.10/24", - "128.95.120.2:8600", - "240.0.0.1/4", - "::", - }, - sortedAddrs: []string{ - "10.0.0.0/8", - "128.95.120.1/32", - "128.95.120.2:53", - "128.95.120.2/32", - "128.95.120.2:8600", - "172.16.1.3/12", - "192.168.0.0/16", - "192.168.1.10/24", - "240.0.0.1/4", - "::", - }, - }, - } - - for idx, test := range testInputs { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - shuffleStrings(test.inputAddrs) - inputSockAddrs := convertToSockAddrs(t, test.inputAddrs) - sas := convertToSockAddrs(t, test.sortedAddrs) - sortedIPv4Addrs, nonIPv4Addrs := sas.FilterByType(sockaddr.TypeIPv4) - if l := len(sortedIPv4Addrs); l != test.numIPv4Inputs { - t.Fatalf("[%d] Missing IPv4Addrs: expected %d, received %d", idx, test.numIPv4Inputs, l) - } - if len(nonIPv4Addrs) != test.numIPv6Inputs+test.numUnixInputs { - t.Fatalf("[%d] Non-IPv4 Address in input", idx) - } - - // Copy inputAddrs so we can manipulate it. wtb const. - sockAddrs := append(sockaddr.SockAddrs(nil), inputSockAddrs...) - filteredAddrs, _ := sockAddrs.FilterByType(sockaddr.TypeIPv4) - sockaddr.OrderedAddrBy(test.sortFuncs...).Sort(filteredAddrs) - ipv4SockAddrs, nonIPv4s := filteredAddrs.FilterByType(sockaddr.TypeIPv4) - if len(nonIPv4s) != 0 { - t.Fatalf("[%d] bad", idx) - } - - for i, ipv4SockAddr := range ipv4SockAddrs { - ipv4Addr := sockaddr.ToIPv4Addr(ipv4SockAddr) - sortedIPv4Addr := sockaddr.ToIPv4Addr(sortedIPv4Addrs[i]) - if ipv4Addr.Address != sortedIPv4Addr.Address { - t.Errorf("[%d/%d] Sort equality failed: expected %s, received %s", idx, i, sortedIPv4Addrs[i], ipv4Addr) - } - } - }) - } -} - -func TestSockAddr_SockAddrs_AscPrivate(t *testing.T) { - testInputs := []struct { - sortFuncs []sockaddr.CmpAddrFunc - inputAddrs []string - sortedAddrs []string - }{ - { // testNum: 0 - sortFuncs: []sockaddr.CmpAddrFunc{ - sockaddr.AscType, - sockaddr.AscPrivate, - sockaddr.AscAddress, - sockaddr.AscType, - sockaddr.AscAddress, - sockaddr.AscPort, - }, - inputAddrs: []string{ - "10.0.0.0/8", - "172.16.1.3/12", - "192.168.0.0/16", - "192.168.0.0/16", - "192.168.1.10/24", - "128.95.120.1/32", - "128.95.120.2/32", - "128.95.120.2:53", - "128.95.120.2:8600", - "240.0.0.1/4", - "::", - }, - sortedAddrs: []string{ - "10.0.0.0/8", - "172.16.1.3/12", - "192.168.0.0/16", - "192.168.0.0/16", - "192.168.1.10/24", - "240.0.0.1/4", - "128.95.120.1/32", - "128.95.120.2/32", - // "128.95.120.2:53", - // "128.95.120.2:8600", - // "::", - }, - }, - { - sortFuncs: []sockaddr.CmpAddrFunc{ - sockaddr.AscType, - sockaddr.AscPrivate, - sockaddr.AscAddress, - }, - inputAddrs: []string{ - "1.2.3.4:53", - "192.168.1.2", - "/tmp/foo", - "[cc::1]:8600", - "[::1]:53", - }, - sortedAddrs: []string{ - "/tmp/foo", - "192.168.1.2", - "1.2.3.4:53", - "[::1]:53", - "[cc::1]:8600", - }, - }, - { - sortFuncs: []sockaddr.CmpAddrFunc{ - sockaddr.AscType, - sockaddr.AscPrivate, - sockaddr.AscAddress, - }, - inputAddrs: []string{ - "/tmp/foo", - "/tmp/bar", - "1.2.3.4", - }, - sortedAddrs: []string{ - "/tmp/bar", - "/tmp/foo", - "1.2.3.4", - }, - }, - } - - for idx, test := range testInputs { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - sortedAddrs := convertToSockAddrs(t, test.sortedAddrs) - - inputAddrs := append([]string(nil), test.inputAddrs...) - shuffleStrings(inputAddrs) - inputSockAddrs := convertToSockAddrs(t, inputAddrs) - - sockaddr.OrderedAddrBy(test.sortFuncs...).Sort(inputSockAddrs) - - for i, sockAddr := range sortedAddrs { - if !sockAddr.Equal(inputSockAddrs[i]) { - t.Logf("Input Addrs:\t%+v", inputAddrs) - t.Logf("Sorted Addrs:\t%+v", inputSockAddrs) - t.Logf("Expected Addrs:\t%+v", test.sortedAddrs) - t.Fatalf("[%d/%d] Sort AscType/AscAddress failed: expected %+q, received %+q", idx, i, sockAddr, inputSockAddrs[i]) - } - } - }) - } -} - -func TestSockAddr_SockAddrs_AscPort(t *testing.T) { - testInputs := []struct { - name string - sortFuncs []sockaddr.CmpAddrFunc - inputAddrs []string - sortedAddrs []string - }{ - { - name: "simple port test", - sortFuncs: []sockaddr.CmpAddrFunc{ - sockaddr.AscPort, - sockaddr.AscType, - }, - inputAddrs: []string{ - "1.2.3.4:53", - "/tmp/foo", - "[::1]:53", - }, - sortedAddrs: []string{ - "/tmp/foo", - "1.2.3.4:53", - "[::1]:53", - }, - }, - { - name: "simple port test", - sortFuncs: []sockaddr.CmpAddrFunc{ - sockaddr.AscPort, - sockaddr.AscType, - }, - inputAddrs: []string{ - "1.2.3.4:53", - "/tmp/foo", - }, - sortedAddrs: []string{ - "/tmp/foo", - "1.2.3.4:53", - }, - }, - } - - for idx, test := range testInputs { - t.Run(test.name, func(t *testing.T) { - sortedAddrs := convertToSockAddrs(t, test.sortedAddrs) - - inputAddrs := append([]string(nil), test.inputAddrs...) - shuffleStrings(inputAddrs) - inputSockAddrs := convertToSockAddrs(t, inputAddrs) - - sockaddr.OrderedAddrBy(test.sortFuncs...).Sort(inputSockAddrs) - - for i, sockAddr := range sortedAddrs { - if !sockAddr.Equal(inputSockAddrs[i]) { - t.Logf("Input Addrs:\t%+v", inputAddrs) - t.Logf("Sorted Addrs:\t%+v", inputSockAddrs) - t.Logf("Expected Addrs:\t%+v", test.sortedAddrs) - t.Fatalf("[%d/%d] Sort AscType/AscAddress failed: expected %+q, received %+q", idx, i, sockAddr, inputSockAddrs[i]) - } - } - }) - } -} - -func TestSockAddr_SockAddrs_AscType(t *testing.T) { - testInputs := sockAddrStringInputs{ - { // testNum: 0 - sortFuncs: []sockaddr.CmpAddrFunc{ - sockaddr.AscType, - }, - inputAddrs: []string{ - "10.0.0.0/8", - "172.16.1.3/12", - "128.95.120.2:53", - "::", - "128.95.120.2/32", - "192.168.0.0/16", - "128.95.120.1/32", - "192.168.1.10/24", - "128.95.120.2:8600", - "240.0.0.1/4", - }, - sortedTypes: []sockaddr.SockAddrType{ - sockaddr.TypeIPv4, - sockaddr.TypeIPv4, - sockaddr.TypeIPv4, - sockaddr.TypeIPv4, - sockaddr.TypeIPv4, - sockaddr.TypeIPv4, - sockaddr.TypeIPv4, - sockaddr.TypeIPv4, - sockaddr.TypeIPv4, - sockaddr.TypeIPv6, - }, - }, - } - - for idx, test := range testInputs { - t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { - shuffleStrings(test.inputAddrs) - - inputSockAddrs := convertToSockAddrs(t, test.inputAddrs) - sortedAddrs := convertToSockAddrs(t, test.sortedAddrs) - - sockaddr.OrderedAddrBy(test.sortFuncs...).Sort(inputSockAddrs) - - for i, sockAddr := range sortedAddrs { - if sockAddr.Type() != sortedAddrs[i].Type() { - t.Errorf("[%d/%d] Sort AscType failed: expected %+q, received %+q", idx, i, sortedAddrs[i], sockAddr) - } - } - }) - } -} diff --git a/vendor/github.com/hashicorp/go-sockaddr/unixsock_test.go b/vendor/github.com/hashicorp/go-sockaddr/unixsock_test.go deleted file mode 100644 index 7ed636a29..000000000 --- a/vendor/github.com/hashicorp/go-sockaddr/unixsock_test.go +++ /dev/null @@ -1,108 +0,0 @@ -package sockaddr_test - -import ( - "testing" - - sockaddr "github.com/hashicorp/go-sockaddr" -) - -func TestUnixSock_impl_SockAddr(t *testing.T) { - tests := []struct { - name string - input sockaddr.UnixSock - dialPacketArgs []string - dialStreamArgs []string - listenPacketArgs []string - listenStreamArgs []string - }{ - { - name: "simple", - input: sockaddr.MustUnixSock("/tmp/foo"), - dialPacketArgs: []string{"unixgram", "/tmp/foo"}, - dialStreamArgs: []string{"unixgram", "/tmp/foo"}, - listenPacketArgs: []string{"unixgram", "/tmp/foo"}, - listenStreamArgs: []string{"unixgram", "/tmp/foo"}, - }, - } - - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d needs a name", i) - } - - arg1, arg2 := test.input.DialPacketArgs() - if arg1 != test.dialPacketArgs[0] && arg2 != test.dialPacketArgs[1] { - t.Fatalf("%s: %q %q", test.name, arg1, arg2) - } - - arg1, arg2 = test.input.DialStreamArgs() - if arg1 != test.dialStreamArgs[0] && arg2 != test.dialStreamArgs[1] { - t.Fatalf("%s: %q %q", test.name, arg1, arg2) - } - - arg1, arg2 = test.input.ListenPacketArgs() - if arg1 != test.listenPacketArgs[0] && arg2 != test.listenPacketArgs[1] { - t.Fatalf("%s: %q %q", test.name, arg1, arg2) - } - - arg1, arg2 = test.input.ListenStreamArgs() - if arg1 != test.listenStreamArgs[0] && arg2 != test.listenStreamArgs[1] { - t.Fatalf("%s: %q %q", test.name, arg1, arg2) - } - } -} - -func TestUnixSock_Equal(t *testing.T) { - tests := []struct { - name string - input sockaddr.UnixSock - sa sockaddr.SockAddr - equal bool - }{ - { - name: "equal", - input: sockaddr.MustUnixSock("/tmp/foo"), - sa: sockaddr.MustUnixSock("/tmp/foo"), - equal: true, - }, - { - name: "not equal", - input: sockaddr.MustUnixSock("/tmp/foo"), - sa: sockaddr.MustUnixSock("/tmp/bar"), - equal: false, - }, - { - name: "ipv4", - input: sockaddr.MustUnixSock("/tmp/foo"), - sa: sockaddr.MustIPv4Addr("1.2.3.4"), - equal: false, - }, - { - name: "ipv6", - input: sockaddr.MustUnixSock("/tmp/foo"), - sa: sockaddr.MustIPv6Addr("::1"), - equal: false, - }, - } - - for i, test := range tests { - if test.name == "" { - t.Fatalf("test %d needs a name", i) - } - - t.Run(test.name, func(t *testing.T) { - us := test.input - if ret := us.Equal(test.sa); ret != test.equal { - t.Fatalf("%s: equal: %v %q %q", test.name, ret, us, test.sa) - } - }) - } -} - -func TestUnixSockAttrs(t *testing.T) { - const expectedNumAttrs = 1 - usa := sockaddr.UnixSockAttrs() - if len(usa) != expectedNumAttrs { - t.Fatalf("wrong number of UnixSockAttrs: %d vs %d", len(usa), expectedNumAttrs) - } -} diff --git a/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go b/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go index 68d097a1c..5673773b2 100644 --- a/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go +++ b/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go @@ -36,7 +36,7 @@ func NewLRU(size int, onEvict EvictCallback) (*LRU, error) { return c, nil } -// Purge is used to completely clear the cache +// Purge is used to completely clear the cache. func (c *LRU) Purge() { for k, v := range c.items { if c.onEvict != nil { @@ -47,8 +47,8 @@ func (c *LRU) Purge() { c.evictList.Init() } -// Add adds a value to the cache. Returns true if an eviction occured. -func (c *LRU) Add(key, value interface{}) bool { +// Add adds a value to the cache. Returns true if an eviction occurred. +func (c *LRU) Add(key, value interface{}) (evicted bool) { // Check for existing item if ent, ok := c.items[key]; ok { c.evictList.MoveToFront(ent) @@ -78,17 +78,18 @@ func (c *LRU) Get(key interface{}) (value interface{}, ok bool) { return } -// Check if a key is in the cache, without updating the recent-ness +// Contains checks if a key is in the cache, without updating the recent-ness // or deleting it for being stale. func (c *LRU) Contains(key interface{}) (ok bool) { _, ok = c.items[key] return ok } -// Returns the key value (or undefined if not found) without updating +// Peek returns the key value (or undefined if not found) without updating // the "recently used"-ness of the key. func (c *LRU) Peek(key interface{}) (value interface{}, ok bool) { - if ent, ok := c.items[key]; ok { + var ent *list.Element + if ent, ok = c.items[key]; ok { return ent.Value.(*entry).value, true } return nil, ok @@ -96,7 +97,7 @@ func (c *LRU) Peek(key interface{}) (value interface{}, ok bool) { // Remove removes the provided key from the cache, returning if the // key was contained. -func (c *LRU) Remove(key interface{}) bool { +func (c *LRU) Remove(key interface{}) (present bool) { if ent, ok := c.items[key]; ok { c.removeElement(ent) return true @@ -105,7 +106,7 @@ func (c *LRU) Remove(key interface{}) bool { } // RemoveOldest removes the oldest item from the cache. -func (c *LRU) RemoveOldest() (interface{}, interface{}, bool) { +func (c *LRU) RemoveOldest() (key interface{}, value interface{}, ok bool) { ent := c.evictList.Back() if ent != nil { c.removeElement(ent) @@ -116,7 +117,7 @@ func (c *LRU) RemoveOldest() (interface{}, interface{}, bool) { } // GetOldest returns the oldest entry -func (c *LRU) GetOldest() (interface{}, interface{}, bool) { +func (c *LRU) GetOldest() (key interface{}, value interface{}, ok bool) { ent := c.evictList.Back() if ent != nil { kv := ent.Value.(*entry) diff --git a/vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go b/vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go new file mode 100644 index 000000000..74c707744 --- /dev/null +++ b/vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go @@ -0,0 +1,36 @@ +package simplelru + +// LRUCache is the interface for simple LRU cache. +type LRUCache interface { + // Adds a value to the cache, returns true if an eviction occurred and + // updates the "recently used"-ness of the key. + Add(key, value interface{}) bool + + // Returns key's value from the cache and + // updates the "recently used"-ness of the key. #value, isFound + Get(key interface{}) (value interface{}, ok bool) + + // Check if a key exsists in cache without updating the recent-ness. + Contains(key interface{}) (ok bool) + + // Returns key's value without updating the "recently used"-ness of the key. + Peek(key interface{}) (value interface{}, ok bool) + + // Removes a key from the cache. + Remove(key interface{}) bool + + // Removes the oldest entry from cache. + RemoveOldest() (interface{}, interface{}, bool) + + // Returns the oldest entry from the cache. #key, value, isFound + GetOldest() (interface{}, interface{}, bool) + + // Returns a slice of the keys in the cache, from oldest to newest. + Keys() []interface{} + + // Returns the number of items in the cache. + Len() int + + // Clear all cache entries + Purge() +} diff --git a/vendor/github.com/hashicorp/golang-lru/simplelru/lru_test.go b/vendor/github.com/hashicorp/golang-lru/simplelru/lru_test.go deleted file mode 100644 index 30658ed12..000000000 --- a/vendor/github.com/hashicorp/golang-lru/simplelru/lru_test.go +++ /dev/null @@ -1,167 +0,0 @@ -package simplelru - -import "testing" - -func TestLRU(t *testing.T) { - evictCounter := 0 - onEvicted := func(k interface{}, v interface{}) { - if k != v { - t.Fatalf("Evict values not equal (%v!=%v)", k, v) - } - evictCounter += 1 - } - l, err := NewLRU(128, onEvicted) - if err != nil { - t.Fatalf("err: %v", err) - } - - for i := 0; i < 256; i++ { - l.Add(i, i) - } - if l.Len() != 128 { - t.Fatalf("bad len: %v", l.Len()) - } - - if evictCounter != 128 { - t.Fatalf("bad evict count: %v", evictCounter) - } - - for i, k := range l.Keys() { - if v, ok := l.Get(k); !ok || v != k || v != i+128 { - t.Fatalf("bad key: %v", k) - } - } - for i := 0; i < 128; i++ { - _, ok := l.Get(i) - if ok { - t.Fatalf("should be evicted") - } - } - for i := 128; i < 256; i++ { - _, ok := l.Get(i) - if !ok { - t.Fatalf("should not be evicted") - } - } - for i := 128; i < 192; i++ { - ok := l.Remove(i) - if !ok { - t.Fatalf("should be contained") - } - ok = l.Remove(i) - if ok { - t.Fatalf("should not be contained") - } - _, ok = l.Get(i) - if ok { - t.Fatalf("should be deleted") - } - } - - l.Get(192) // expect 192 to be last key in l.Keys() - - for i, k := range l.Keys() { - if (i < 63 && k != i+193) || (i == 63 && k != 192) { - t.Fatalf("out of order key: %v", k) - } - } - - l.Purge() - if l.Len() != 0 { - t.Fatalf("bad len: %v", l.Len()) - } - if _, ok := l.Get(200); ok { - t.Fatalf("should contain nothing") - } -} - -func TestLRU_GetOldest_RemoveOldest(t *testing.T) { - l, err := NewLRU(128, nil) - if err != nil { - t.Fatalf("err: %v", err) - } - for i := 0; i < 256; i++ { - l.Add(i, i) - } - k, _, ok := l.GetOldest() - if !ok { - t.Fatalf("missing") - } - if k.(int) != 128 { - t.Fatalf("bad: %v", k) - } - - k, _, ok = l.RemoveOldest() - if !ok { - t.Fatalf("missing") - } - if k.(int) != 128 { - t.Fatalf("bad: %v", k) - } - - k, _, ok = l.RemoveOldest() - if !ok { - t.Fatalf("missing") - } - if k.(int) != 129 { - t.Fatalf("bad: %v", k) - } -} - -// Test that Add returns true/false if an eviction occured -func TestLRU_Add(t *testing.T) { - evictCounter := 0 - onEvicted := func(k interface{}, v interface{}) { - evictCounter += 1 - } - - l, err := NewLRU(1, onEvicted) - if err != nil { - t.Fatalf("err: %v", err) - } - - if l.Add(1, 1) == true || evictCounter != 0 { - t.Errorf("should not have an eviction") - } - if l.Add(2, 2) == false || evictCounter != 1 { - t.Errorf("should have an eviction") - } -} - -// Test that Contains doesn't update recent-ness -func TestLRU_Contains(t *testing.T) { - l, err := NewLRU(2, nil) - if err != nil { - t.Fatalf("err: %v", err) - } - - l.Add(1, 1) - l.Add(2, 2) - if !l.Contains(1) { - t.Errorf("1 should be contained") - } - - l.Add(3, 3) - if l.Contains(1) { - t.Errorf("Contains should not have updated recent-ness of 1") - } -} - -// Test that Peek doesn't update recent-ness -func TestLRU_Peek(t *testing.T) { - l, err := NewLRU(2, nil) - if err != nil { - t.Fatalf("err: %v", err) - } - - l.Add(1, 1) - l.Add(2, 2) - if v, ok := l.Peek(1); !ok || v != 1 { - t.Errorf("1 should be set to 1: %v, %v", v, ok) - } - - l.Add(3, 3) - if l.Contains(1) { - t.Errorf("should not have updated recent-ness of 1") - } -} diff --git a/vendor/github.com/hashicorp/memberlist/.travis.yml b/vendor/github.com/hashicorp/memberlist/.travis.yml new file mode 100644 index 000000000..b4f8f1c47 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/.travis.yml @@ -0,0 +1,15 @@ +language: go + +sudo: true + +go: + - "1.x" + +branches: + only: + - master + +install: true + +env: + - GO111MODULE=on # Enable Go modules in 1.11 diff --git a/vendor/github.com/hashicorp/memberlist/Makefile b/vendor/github.com/hashicorp/memberlist/Makefile index e34a0818d..4ee0ee4ef 100644 --- a/vendor/github.com/hashicorp/memberlist/Makefile +++ b/vendor/github.com/hashicorp/memberlist/Makefile @@ -1,4 +1,5 @@ -DEPS = $(go list -f '{{range .Imports}}{{.}} {{end}}' ./...) +DEPS := $(shell go list -f '{{range .Imports}}{{.}} {{end}}' ./...) + test: subnet go test ./... @@ -13,7 +14,7 @@ cov: open /tmp/coverage.html deps: - go get -d -v ./... + go get -t -d -v ./... echo $(DEPS) | xargs -n1 go get -d .PHONY: test cov integ diff --git a/vendor/github.com/hashicorp/memberlist/README.md b/vendor/github.com/hashicorp/memberlist/README.md index e6fed4e64..f47fb81aa 100644 --- a/vendor/github.com/hashicorp/memberlist/README.md +++ b/vendor/github.com/hashicorp/memberlist/README.md @@ -1,4 +1,4 @@ -# memberlist [![GoDoc](https://godoc.org/github.com/hashicorp/memberlist?status.png)](https://godoc.org/github.com/hashicorp/memberlist) +# memberlist [![GoDoc](https://godoc.org/github.com/hashicorp/memberlist?status.png)](https://godoc.org/github.com/hashicorp/memberlist) [![Build Status](https://travis-ci.org/hashicorp/memberlist.svg?branch=master)](https://travis-ci.org/hashicorp/memberlist) memberlist is a [Go](http://www.golang.org) library that manages cluster membership and member failure detection using a gossip based protocol. diff --git a/vendor/github.com/hashicorp/memberlist/alive_delegate.go b/vendor/github.com/hashicorp/memberlist/alive_delegate.go index 51a0ba905..615f4a90a 100644 --- a/vendor/github.com/hashicorp/memberlist/alive_delegate.go +++ b/vendor/github.com/hashicorp/memberlist/alive_delegate.go @@ -7,8 +7,8 @@ package memberlist // a node out and prevent it from being considered a peer // using application specific logic. type AliveDelegate interface { - // NotifyMerge is invoked when a merge could take place. - // Provides a list of the nodes known by the peer. If - // the return value is non-nil, the merge is canceled. + // NotifyAlive is invoked when a message about a live + // node is received from the network. Returning a non-nil + // error prevents the node from being considered a peer. NotifyAlive(peer *Node) error } diff --git a/vendor/github.com/hashicorp/memberlist/awareness_test.go b/vendor/github.com/hashicorp/memberlist/awareness_test.go deleted file mode 100644 index c6ade10af..000000000 --- a/vendor/github.com/hashicorp/memberlist/awareness_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package memberlist - -import ( - "testing" - "time" -) - -func TestAwareness(t *testing.T) { - cases := []struct { - delta int - score int - timeout time.Duration - }{ - {0, 0, 1 * time.Second}, - {-1, 0, 1 * time.Second}, - {-10, 0, 1 * time.Second}, - {1, 1, 2 * time.Second}, - {-1, 0, 1 * time.Second}, - {10, 7, 8 * time.Second}, - {-1, 6, 7 * time.Second}, - {-1, 5, 6 * time.Second}, - {-1, 4, 5 * time.Second}, - {-1, 3, 4 * time.Second}, - {-1, 2, 3 * time.Second}, - {-1, 1, 2 * time.Second}, - {-1, 0, 1 * time.Second}, - {-1, 0, 1 * time.Second}, - } - - a := newAwareness(8) - for i, c := range cases { - a.ApplyDelta(c.delta) - if a.GetHealthScore() != c.score { - t.Errorf("case %d: score mismatch %d != %d", i, a.score, c.score) - } - if timeout := a.ScaleTimeout(1 * time.Second); timeout != c.timeout { - t.Errorf("case %d: scaled timeout mismatch %9.6f != %9.6f", - i, timeout.Seconds(), c.timeout.Seconds()) - } - } -} diff --git a/vendor/github.com/hashicorp/memberlist/broadcast.go b/vendor/github.com/hashicorp/memberlist/broadcast.go index f7e85a119..d07d41bb6 100644 --- a/vendor/github.com/hashicorp/memberlist/broadcast.go +++ b/vendor/github.com/hashicorp/memberlist/broadcast.go @@ -29,6 +29,11 @@ func (b *memberlistBroadcast) Invalidates(other Broadcast) bool { return b.node == mb.node } +// memberlist.NamedBroadcast optional interface +func (b *memberlistBroadcast) Name() string { + return b.node +} + func (b *memberlistBroadcast) Message() []byte { return b.msg } diff --git a/vendor/github.com/hashicorp/memberlist/broadcast_test.go b/vendor/github.com/hashicorp/memberlist/broadcast_test.go deleted file mode 100644 index c6a7302cc..000000000 --- a/vendor/github.com/hashicorp/memberlist/broadcast_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package memberlist - -import ( - "reflect" - "testing" -) - -func TestMemberlistBroadcast_Invalidates(t *testing.T) { - m1 := &memberlistBroadcast{"test", nil, nil} - m2 := &memberlistBroadcast{"foo", nil, nil} - - if m1.Invalidates(m2) || m2.Invalidates(m1) { - t.Fatalf("unexpected invalidation") - } - - if !m1.Invalidates(m1) { - t.Fatalf("expected invalidation") - } -} - -func TestMemberlistBroadcast_Message(t *testing.T) { - m1 := &memberlistBroadcast{"test", []byte("test"), nil} - msg := m1.Message() - if !reflect.DeepEqual(msg, []byte("test")) { - t.Fatalf("messages do not match") - } -} diff --git a/vendor/github.com/hashicorp/memberlist/config.go b/vendor/github.com/hashicorp/memberlist/config.go index c85b1657a..c9cd17644 100644 --- a/vendor/github.com/hashicorp/memberlist/config.go +++ b/vendor/github.com/hashicorp/memberlist/config.go @@ -215,6 +215,11 @@ type Config struct { // This is a legacy name for backward compatibility but should really be // called PacketBufferSize now that we have generalized the transport. UDPBufferSize int + + // DeadNodeReclaimTime controls the time before a dead node's name can be + // reclaimed by one with a different address or port. By default, this is 0, + // meaning nodes cannot be reclaimed this way. + DeadNodeReclaimTime time.Duration } // DefaultLANConfig returns a sane set of configurations for Memberlist. diff --git a/vendor/github.com/hashicorp/memberlist/go.mod b/vendor/github.com/hashicorp/memberlist/go.mod new file mode 100644 index 000000000..0c025ff11 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/go.mod @@ -0,0 +1,20 @@ +module github.com/hashicorp/memberlist + +require ( + github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c + github.com/hashicorp/go-immutable-radix v1.0.0 // indirect + github.com/hashicorp/go-msgpack v0.5.3 + github.com/hashicorp/go-multierror v1.0.0 + github.com/hashicorp/go-sockaddr v1.0.0 + github.com/miekg/dns v1.0.14 + github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 + github.com/stretchr/testify v1.2.2 + golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3 // indirect + golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519 // indirect + golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect + golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5 // indirect +) diff --git a/vendor/github.com/hashicorp/memberlist/go.sum b/vendor/github.com/hashicorp/memberlist/go.sum new file mode 100644 index 000000000..39534ac2f --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/go.sum @@ -0,0 +1,38 @@ +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCSnM= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3 h1:KYQXGkl6vs02hK7pK4eIbw0NpNPedieTSTEiJ//bwGs= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519 h1:x6rhz8Y9CjbgQkccRGmELH6K+LJj7tOoh3XWeC1yaQM= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5 h1:x6r4Jo0KNzOOzYd8lbcRsqjuqEASK6ob3auvWYM4/8U= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/vendor/github.com/hashicorp/memberlist/integ_test.go b/vendor/github.com/hashicorp/memberlist/integ_test.go deleted file mode 100644 index f519c6baa..000000000 --- a/vendor/github.com/hashicorp/memberlist/integ_test.go +++ /dev/null @@ -1,89 +0,0 @@ -package memberlist - -import ( - "fmt" - "log" - "os" - "testing" - "time" -) - -// CheckInteg will skip a test if integration testing is not enabled. -func CheckInteg(t *testing.T) { - if !IsInteg() { - t.SkipNow() - } -} - -// IsInteg returns a boolean telling you if we're in integ testing mode. -func IsInteg() bool { - return os.Getenv("INTEG_TESTS") != "" -} - -// Tests the memberlist by creating a cluster of 100 nodes -// and checking that we get strong convergence of changes. -func TestMemberlist_Integ(t *testing.T) { - CheckInteg(t) - - num := 16 - var members []*Memberlist - - secret := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} - eventCh := make(chan NodeEvent, num) - - addr := "127.0.0.1" - for i := 0; i < num; i++ { - c := DefaultLANConfig() - c.Name = fmt.Sprintf("%s:%d", addr, 12345+i) - c.BindAddr = addr - c.BindPort = 12345 + i - c.ProbeInterval = 20 * time.Millisecond - c.ProbeTimeout = 100 * time.Millisecond - c.GossipInterval = 20 * time.Millisecond - c.PushPullInterval = 200 * time.Millisecond - c.SecretKey = secret - - if i == 0 { - c.Events = &ChannelEventDelegate{eventCh} - } - - m, err := Create(c) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - members = append(members, m) - defer m.Shutdown() - - if i > 0 { - last := members[i-1] - num, err := m.Join([]string{last.config.Name}) - if num == 0 || err != nil { - t.Fatalf("unexpected err: %s", err) - } - } - } - - // Wait and print debug info - breakTimer := time.After(250 * time.Millisecond) -WAIT: - for { - select { - case e := <-eventCh: - if e.Event == NodeJoin { - log.Printf("[DEBUG] Node join: %v (%d)", *e.Node, members[0].NumMembers()) - } else { - log.Printf("[DEBUG] Node leave: %v (%d)", *e.Node, members[0].NumMembers()) - } - case <-breakTimer: - break WAIT - } - } - - for idx, m := range members { - got := m.NumMembers() - if got != num { - t.Errorf("bad num members at idx %d. Expected %d. Got %d.", - idx, num, got) - } - } -} diff --git a/vendor/github.com/hashicorp/memberlist/keyring_test.go b/vendor/github.com/hashicorp/memberlist/keyring_test.go deleted file mode 100644 index eec699fd0..000000000 --- a/vendor/github.com/hashicorp/memberlist/keyring_test.go +++ /dev/null @@ -1,154 +0,0 @@ -package memberlist - -import ( - "bytes" - "testing" -) - -var TestKeys [][]byte = [][]byte{ - []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - []byte{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, - []byte{8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7}, -} - -func TestKeyring_EmptyRing(t *testing.T) { - // Keyrings can be created with no encryption keys (disabled encryption) - keyring, err := NewKeyring(nil, nil) - if err != nil { - t.Fatalf("err: %s", err) - } - - keys := keyring.GetKeys() - if len(keys) != 0 { - t.Fatalf("Expected 0 keys but have %d", len(keys)) - } -} - -func TestKeyring_PrimaryOnly(t *testing.T) { - // Keyrings can be created using only a primary key - keyring, err := NewKeyring(nil, TestKeys[0]) - if err != nil { - t.Fatalf("err: %s", err) - } - - keys := keyring.GetKeys() - if len(keys) != 1 { - t.Fatalf("Expected 1 key but have %d", len(keys)) - } -} - -func TestKeyring_GetPrimaryKey(t *testing.T) { - keyring, err := NewKeyring(TestKeys, TestKeys[1]) - if err != nil { - t.Fatalf("err: %s", err) - } - - // GetPrimaryKey returns correct key - primaryKey := keyring.GetPrimaryKey() - if !bytes.Equal(primaryKey, TestKeys[1]) { - t.Fatalf("Unexpected primary key: %v", primaryKey) - } -} - -func TestKeyring_AddRemoveUse(t *testing.T) { - keyring, err := NewKeyring(nil, TestKeys[1]) - if err != nil { - t.Fatalf("err :%s", err) - } - - // Use non-existent key throws error - if err := keyring.UseKey(TestKeys[2]); err == nil { - t.Fatalf("Expected key not installed error") - } - - // Add key to ring - if err := keyring.AddKey(TestKeys[2]); err != nil { - t.Fatalf("err: %s", err) - } - - keys := keyring.GetKeys() - if !bytes.Equal(keys[0], TestKeys[1]) { - t.Fatalf("Unexpected primary key change") - } - - if len(keys) != 2 { - t.Fatalf("Expected 2 keys but have %d", len(keys)) - } - - // Use key that exists should succeed - if err := keyring.UseKey(TestKeys[2]); err != nil { - t.Fatalf("err: %s", err) - } - - primaryKey := keyring.GetPrimaryKey() - if !bytes.Equal(primaryKey, TestKeys[2]) { - t.Fatalf("Unexpected primary key: %v", primaryKey) - } - - // Removing primary key should fail - if err := keyring.RemoveKey(TestKeys[2]); err == nil { - t.Fatalf("Expected primary key removal error") - } - - // Removing non-primary key should succeed - if err := keyring.RemoveKey(TestKeys[1]); err != nil { - t.Fatalf("err: %s", err) - } - - keys = keyring.GetKeys() - if len(keys) != 1 { - t.Fatalf("Expected 1 key but have %d", len(keys)) - } -} - -func TestKeyRing_MultiKeyEncryptDecrypt(t *testing.T) { - plaintext := []byte("this is a plain text message") - extra := []byte("random data") - - keyring, err := NewKeyring(TestKeys, TestKeys[0]) - if err != nil { - t.Fatalf("err: %s", err) - } - - // First encrypt using the primary key and make sure we can decrypt - var buf bytes.Buffer - err = encryptPayload(1, TestKeys[0], plaintext, extra, &buf) - if err != nil { - t.Fatalf("err: %v", err) - } - - msg, err := decryptPayload(keyring.GetKeys(), buf.Bytes(), extra) - if err != nil { - t.Fatalf("err: %v", err) - } - - if !bytes.Equal(msg, plaintext) { - t.Fatalf("bad: %v", msg) - } - - // Now encrypt with a secondary key and try decrypting again. - buf.Reset() - err = encryptPayload(1, TestKeys[2], plaintext, extra, &buf) - if err != nil { - t.Fatalf("err: %v", err) - } - - msg, err = decryptPayload(keyring.GetKeys(), buf.Bytes(), extra) - if err != nil { - t.Fatalf("err: %v", err) - } - - if !bytes.Equal(msg, plaintext) { - t.Fatalf("bad: %v", msg) - } - - // Remove a key from the ring, and then try decrypting again - if err := keyring.RemoveKey(TestKeys[2]); err != nil { - t.Fatalf("err: %s", err) - } - - msg, err = decryptPayload(keyring.GetKeys(), buf.Bytes(), extra) - if err == nil { - t.Fatalf("Expected no keys to decrypt message") - } -} diff --git a/vendor/github.com/hashicorp/memberlist/logging_test.go b/vendor/github.com/hashicorp/memberlist/logging_test.go deleted file mode 100644 index cc04b8a91..000000000 --- a/vendor/github.com/hashicorp/memberlist/logging_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package memberlist - -import ( - "fmt" - "net" - "testing" -) - -func TestLogging_Address(t *testing.T) { - s := LogAddress(nil) - if s != "from=" { - t.Fatalf("bad: %s", s) - } - - addr, err := net.ResolveIPAddr("ip4", "127.0.0.1") - if err != nil { - t.Fatalf("err: %v", err) - } - - s = LogAddress(addr) - if s != "from=127.0.0.1" { - t.Fatalf("bad: %s", s) - } -} - -func TestLogging_Conn(t *testing.T) { - s := LogConn(nil) - if s != "from=" { - t.Fatalf("bad: %s", s) - } - - ln, err := net.Listen("tcp", ":0") - if err != nil { - t.Fatalf("err: %v", err) - } - - conn, err := net.Dial("tcp", ln.Addr().String()) - if err != nil { - t.Fatalf("err: %v", err) - } - defer conn.Close() - - s = LogConn(conn) - if s != fmt.Sprintf("from=%s", conn.RemoteAddr().String()) { - t.Fatalf("bad: %s", s) - } -} diff --git a/vendor/github.com/hashicorp/memberlist/memberlist.go b/vendor/github.com/hashicorp/memberlist/memberlist.go index bd8abd23f..f289a12ae 100644 --- a/vendor/github.com/hashicorp/memberlist/memberlist.go +++ b/vendor/github.com/hashicorp/memberlist/memberlist.go @@ -72,6 +72,15 @@ type Memberlist struct { logger *log.Logger } +// BuildVsnArray creates the array of Vsn +func (conf *Config) BuildVsnArray() []uint8 { + return []uint8{ + ProtocolVersionMin, ProtocolVersionMax, conf.ProtocolVersion, + conf.DelegateProtocolMin, conf.DelegateProtocolMax, + conf.DelegateProtocolVersion, + } +} + // newMemberlist creates the network listeners. // Does not schedule execution of background maintenance. func newMemberlist(conf *Config) (*Memberlist, error) { @@ -402,11 +411,7 @@ func (m *Memberlist) setAlive() error { Addr: addr, Port: uint16(port), Meta: meta, - Vsn: []uint8{ - ProtocolVersionMin, ProtocolVersionMax, m.config.ProtocolVersion, - m.config.DelegateProtocolMin, m.config.DelegateProtocolMax, - m.config.DelegateProtocolVersion, - }, + Vsn: m.config.BuildVsnArray(), } m.aliveNode(&a, nil, true) return nil @@ -447,11 +452,7 @@ func (m *Memberlist) UpdateNode(timeout time.Duration) error { Addr: state.Addr, Port: state.Port, Meta: meta, - Vsn: []uint8{ - ProtocolVersionMin, ProtocolVersionMax, m.config.ProtocolVersion, - m.config.DelegateProtocolMin, m.config.DelegateProtocolMax, - m.config.DelegateProtocolVersion, - }, + Vsn: m.config.BuildVsnArray(), } notifyCh := make(chan struct{}) m.aliveNode(&a, notifyCh, true) @@ -665,3 +666,27 @@ func (m *Memberlist) hasShutdown() bool { func (m *Memberlist) hasLeft() bool { return atomic.LoadInt32(&m.leave) == 1 } + +func (m *Memberlist) getNodeState(addr string) nodeStateType { + m.nodeLock.RLock() + defer m.nodeLock.RUnlock() + + n := m.nodeMap[addr] + return n.State +} + +func (m *Memberlist) getNodeStateChange(addr string) time.Time { + m.nodeLock.RLock() + defer m.nodeLock.RUnlock() + + n := m.nodeMap[addr] + return n.StateChange +} + +func (m *Memberlist) changeNode(addr string, f func(*nodeState)) { + m.nodeLock.Lock() + defer m.nodeLock.Unlock() + + n := m.nodeMap[addr] + f(n) +} diff --git a/vendor/github.com/hashicorp/memberlist/memberlist_test.go b/vendor/github.com/hashicorp/memberlist/memberlist_test.go deleted file mode 100644 index 0a95c6017..000000000 --- a/vendor/github.com/hashicorp/memberlist/memberlist_test.go +++ /dev/null @@ -1,1544 +0,0 @@ -package memberlist - -import ( - "bytes" - "fmt" - "io/ioutil" - "log" - "net" - "os" - "reflect" - "strings" - "sync" - "testing" - "time" - - "github.com/miekg/dns" - "github.com/stretchr/testify/require" -) - -var bindLock sync.Mutex -var bindNum byte = 10 - -func getBindAddr() net.IP { - bindLock.Lock() - defer bindLock.Unlock() - - result := net.IPv4(127, 0, 0, bindNum) - bindNum++ - if bindNum > 255 { - bindNum = 10 - } - - return result -} - -func testConfig() *Config { - config := DefaultLANConfig() - config.BindAddr = getBindAddr().String() - config.Name = config.BindAddr - return config -} - -func yield() { - time.Sleep(5 * time.Millisecond) -} - -type MockDelegate struct { - meta []byte - msgs [][]byte - broadcasts [][]byte - state []byte - remoteState []byte -} - -func (m *MockDelegate) NodeMeta(limit int) []byte { - return m.meta -} - -func (m *MockDelegate) NotifyMsg(msg []byte) { - cp := make([]byte, len(msg)) - copy(cp, msg) - m.msgs = append(m.msgs, cp) -} - -func (m *MockDelegate) GetBroadcasts(overhead, limit int) [][]byte { - b := m.broadcasts - m.broadcasts = nil - return b -} - -func (m *MockDelegate) LocalState(join bool) []byte { - return m.state -} - -func (m *MockDelegate) MergeRemoteState(s []byte, join bool) { - m.remoteState = s -} - -// Returns a new Memberlist on an open port by trying a range of port numbers -// until something sticks. -func NewMemberlistOnOpenPort(c *Config) (*Memberlist, error) { - c.BindPort = 0 - return newMemberlist(c) -} - -func GetMemberlistDelegate(t *testing.T) (*Memberlist, *MockDelegate) { - d := &MockDelegate{} - - c := testConfig() - c.Delegate = d - - m, err := NewMemberlistOnOpenPort(c) - if err != nil { - t.Fatalf("failed to start: %v", err) - return nil, nil - } - - return m, d -} - -func GetMemberlist(t *testing.T) *Memberlist { - c := testConfig() - - m, err := NewMemberlistOnOpenPort(c) - if err != nil { - t.Fatalf("failed to start: %v", err) - return nil - } - - return m -} - -func TestDefaultLANConfig_protocolVersion(t *testing.T) { - c := DefaultLANConfig() - if c.ProtocolVersion != ProtocolVersion2Compatible { - t.Fatalf("should be max: %d", c.ProtocolVersion) - } -} - -func TestCreate_protocolVersion(t *testing.T) { - cases := []struct { - version uint8 - err bool - }{ - {ProtocolVersionMin, false}, - {ProtocolVersionMax, false}, - // TODO(mitchellh): uncommon when we're over 0 - //{ProtocolVersionMin - 1, true}, - {ProtocolVersionMax + 1, true}, - {ProtocolVersionMax - 1, false}, - } - - for _, tc := range cases { - c := DefaultLANConfig() - c.BindAddr = getBindAddr().String() - c.ProtocolVersion = tc.version - m, err := Create(c) - if tc.err && err == nil { - t.Errorf("Should've failed with version: %d", tc.version) - } else if !tc.err && err != nil { - t.Errorf("Version '%d' error: %s", tc.version, err) - } - - if err == nil { - m.Shutdown() - } - } -} - -func TestCreate_secretKey(t *testing.T) { - cases := []struct { - key []byte - err bool - }{ - {make([]byte, 0), false}, - {[]byte("abc"), true}, - {make([]byte, 16), false}, - {make([]byte, 38), true}, - } - - for _, tc := range cases { - c := DefaultLANConfig() - c.BindAddr = getBindAddr().String() - c.SecretKey = tc.key - m, err := Create(c) - if tc.err && err == nil { - t.Errorf("Should've failed with key: %#v", tc.key) - } else if !tc.err && err != nil { - t.Errorf("Key '%#v' error: %s", tc.key, err) - } - - if err == nil { - m.Shutdown() - } - } -} - -func TestCreate_secretKeyEmpty(t *testing.T) { - c := DefaultLANConfig() - c.BindAddr = getBindAddr().String() - c.SecretKey = make([]byte, 0) - m, err := Create(c) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m.Shutdown() - - if m.config.EncryptionEnabled() { - t.Fatalf("Expected encryption to be disabled") - } -} - -func TestCreate_keyringOnly(t *testing.T) { - c := DefaultLANConfig() - c.BindAddr = getBindAddr().String() - keyring, err := NewKeyring(nil, make([]byte, 16)) - if err != nil { - t.Fatalf("err: %s", err) - } - c.Keyring = keyring - - m, err := Create(c) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m.Shutdown() - - if !m.config.EncryptionEnabled() { - t.Fatalf("Expected encryption to be enabled") - } -} - -func TestCreate_keyringAndSecretKey(t *testing.T) { - c := DefaultLANConfig() - c.BindAddr = getBindAddr().String() - keyring, err := NewKeyring(nil, make([]byte, 16)) - if err != nil { - t.Fatalf("err: %s", err) - } - c.Keyring = keyring - c.SecretKey = []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} - - m, err := Create(c) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m.Shutdown() - - if !m.config.EncryptionEnabled() { - t.Fatalf("Expected encryption to be enabled") - } - - ringKeys := c.Keyring.GetKeys() - if !bytes.Equal(c.SecretKey, ringKeys[0]) { - t.Fatalf("Unexpected primary key %v", ringKeys[0]) - } -} - -func TestCreate_invalidLoggerSettings(t *testing.T) { - c := DefaultLANConfig() - c.BindAddr = getBindAddr().String() - c.Logger = log.New(ioutil.Discard, "", log.LstdFlags) - c.LogOutput = ioutil.Discard - - _, err := Create(c) - if err == nil { - t.Fatal("Memberlist should not allow both LogOutput and Logger to be set, but it did not raise an error") - } -} - -func TestCreate(t *testing.T) { - c := testConfig() - c.ProtocolVersion = ProtocolVersionMin - c.DelegateProtocolVersion = 13 - c.DelegateProtocolMin = 12 - c.DelegateProtocolMax = 24 - - m, err := Create(c) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m.Shutdown() - - yield() - - members := m.Members() - if len(members) != 1 { - t.Fatalf("bad number of members") - } - - if members[0].PMin != ProtocolVersionMin { - t.Fatalf("bad: %#v", members[0]) - } - - if members[0].PMax != ProtocolVersionMax { - t.Fatalf("bad: %#v", members[0]) - } - - if members[0].PCur != c.ProtocolVersion { - t.Fatalf("bad: %#v", members[0]) - } - - if members[0].DMin != c.DelegateProtocolMin { - t.Fatalf("bad: %#v", members[0]) - } - - if members[0].DMax != c.DelegateProtocolMax { - t.Fatalf("bad: %#v", members[0]) - } - - if members[0].DCur != c.DelegateProtocolVersion { - t.Fatalf("bad: %#v", members[0]) - } -} - -func TestMemberList_CreateShutdown(t *testing.T) { - m := GetMemberlist(t) - m.schedule() - if err := m.Shutdown(); err != nil { - t.Fatalf("failed to shutdown %v", err) - } -} - -func TestMemberList_ResolveAddr(t *testing.T) { - m := GetMemberlist(t) - if _, err := m.resolveAddr("localhost"); err != nil { - t.Fatalf("Could not resolve localhost: %s", err) - } - if _, err := m.resolveAddr("[::1]:80"); err != nil { - t.Fatalf("Could not understand ipv6 pair: %s", err) - } - if _, err := m.resolveAddr("[::1]"); err != nil { - t.Fatalf("Could not understand ipv6 non-pair") - } - if _, err := m.resolveAddr(":80"); err == nil { - t.Fatalf("Understood hostless port") - } - if _, err := m.resolveAddr("localhost:80"); err != nil { - t.Fatalf("Could not understand hostname port combo: %s", err) - } - if _, err := m.resolveAddr("localhost:80000"); err == nil { - t.Fatalf("Understood too high port") - } - if _, err := m.resolveAddr("127.0.0.1:80"); err != nil { - t.Fatalf("Could not understand hostname port combo: %s", err) - } - if _, err := m.resolveAddr("[2001:db8:a0b:12f0::1]:80"); err != nil { - t.Fatalf("Could not understand hostname port combo: %s", err) - } - if _, err := m.resolveAddr("127.0.0.1"); err != nil { - t.Fatalf("Could not understand IPv4 only %s", err) - } - if _, err := m.resolveAddr("[2001:db8:a0b:12f0::1]"); err != nil { - t.Fatalf("Could not understand IPv6 only %s", err) - } -} - -type dnsHandler struct { - t *testing.T -} - -func (h dnsHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) { - if len(r.Question) != 1 { - h.t.Fatalf("bad: %#v", r.Question) - } - - name := "join.service.consul." - question := r.Question[0] - if question.Name != name || question.Qtype != dns.TypeANY { - h.t.Fatalf("bad: %#v", question) - } - - m := new(dns.Msg) - m.SetReply(r) - m.Authoritative = true - m.RecursionAvailable = false - m.Answer = append(m.Answer, &dns.A{ - Hdr: dns.RR_Header{ - Name: name, - Rrtype: dns.TypeA, - Class: dns.ClassINET}, - A: net.ParseIP("127.0.0.1"), - }) - m.Answer = append(m.Answer, &dns.AAAA{ - Hdr: dns.RR_Header{ - Name: name, - Rrtype: dns.TypeAAAA, - Class: dns.ClassINET}, - AAAA: net.ParseIP("2001:db8:a0b:12f0::1"), - }) - if err := w.WriteMsg(m); err != nil { - h.t.Fatalf("err: %v", err) - } -} - -func TestMemberList_ResolveAddr_TCP_First(t *testing.T) { - bind := "127.0.0.1:8600" - - var wg sync.WaitGroup - wg.Add(1) - server := &dns.Server{ - Addr: bind, - Handler: dnsHandler{t}, - Net: "tcp", - NotifyStartedFunc: wg.Done, - } - defer server.Shutdown() - - go func() { - if err := server.ListenAndServe(); err != nil && !strings.Contains(err.Error(), "use of closed network connection") { - t.Fatalf("err: %v", err) - } - }() - wg.Wait() - - tmpFile, err := ioutil.TempFile("", "") - if err != nil { - t.Fatalf("err: %v", err) - } - defer os.Remove(tmpFile.Name()) - - content := []byte(fmt.Sprintf("nameserver %s", bind)) - if _, err := tmpFile.Write(content); err != nil { - t.Fatalf("err: %v", err) - } - if err := tmpFile.Close(); err != nil { - t.Fatalf("err: %v", err) - } - - m := GetMemberlist(t) - m.config.DNSConfigPath = tmpFile.Name() - m.setAlive() - m.schedule() - defer m.Shutdown() - - // Try with and without the trailing dot. - hosts := []string{ - "join.service.consul.", - "join.service.consul", - } - for _, host := range hosts { - ips, err := m.resolveAddr(host) - if err != nil { - t.Fatalf("err: %v", err) - } - port := uint16(m.config.BindPort) - expected := []ipPort{ - // Go now parses IPs like this and returns IP4-mapped IPv6 address. - // Confusingly if you print it you see the same as the input since - // IP.String converts IP4-mapped addresses back to dotted decimal notation - // but the underlying IP bytes don't compare as equal to the actual IPv4 - // bytes the resolver will get from DNS. - ipPort{net.ParseIP("127.0.0.1").To4(), port}, - ipPort{net.ParseIP("2001:db8:a0b:12f0::1"), port}, - } - require.Equal(t, expected, ips) - } -} - -func TestMemberList_Members(t *testing.T) { - n1 := &Node{Name: "test"} - n2 := &Node{Name: "test2"} - n3 := &Node{Name: "test3"} - - m := &Memberlist{} - nodes := []*nodeState{ - &nodeState{Node: *n1, State: stateAlive}, - &nodeState{Node: *n2, State: stateDead}, - &nodeState{Node: *n3, State: stateSuspect}, - } - m.nodes = nodes - - members := m.Members() - if !reflect.DeepEqual(members, []*Node{n1, n3}) { - t.Fatalf("bad members") - } -} - -func TestMemberlist_Join(t *testing.T) { - m1 := GetMemberlist(t) - m1.setAlive() - m1.schedule() - defer m1.Shutdown() - - // Create a second node - c := DefaultLANConfig() - addr1 := getBindAddr() - c.Name = addr1.String() - c.BindAddr = addr1.String() - c.BindPort = m1.config.BindPort - - m2, err := Create(c) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - defer m2.Shutdown() - - num, err := m2.Join([]string{m1.config.BindAddr}) - if num != 1 { - t.Fatalf("unexpected 1: %d", num) - } - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - // Check the hosts - if len(m2.Members()) != 2 { - t.Fatalf("should have 2 nodes! %v", m2.Members()) - } - if m2.estNumNodes() != 2 { - t.Fatalf("should have 2 nodes! %v", m2.Members()) - } -} - -type CustomMergeDelegate struct { - invoked bool -} - -func (c *CustomMergeDelegate) NotifyMerge(nodes []*Node) error { - log.Printf("Cancel merge") - c.invoked = true - return fmt.Errorf("Custom merge canceled") -} - -func TestMemberlist_Join_Cancel(t *testing.T) { - m1 := GetMemberlist(t) - merge1 := &CustomMergeDelegate{} - m1.config.Merge = merge1 - m1.setAlive() - m1.schedule() - defer m1.Shutdown() - - // Create a second node - c := DefaultLANConfig() - addr1 := getBindAddr() - c.Name = addr1.String() - c.BindAddr = addr1.String() - c.BindPort = m1.config.BindPort - - m2, err := Create(c) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - merge2 := &CustomMergeDelegate{} - m2.config.Merge = merge2 - defer m2.Shutdown() - - num, err := m2.Join([]string{m1.config.BindAddr}) - if num != 0 { - t.Fatalf("unexpected 0: %d", num) - } - if !strings.Contains(err.Error(), "Custom merge canceled") { - t.Fatalf("unexpected err: %s", err) - } - - // Check the hosts - if len(m2.Members()) != 1 { - t.Fatalf("should have 1 nodes! %v", m2.Members()) - } - if len(m1.Members()) != 1 { - t.Fatalf("should have 1 nodes! %v", m1.Members()) - } - - // Check delegate invocation - if !merge1.invoked { - t.Fatalf("should invoke delegate") - } - if !merge2.invoked { - t.Fatalf("should invoke delegate") - } -} - -type CustomAliveDelegate struct { - Ignore string - count int -} - -func (c *CustomAliveDelegate) NotifyAlive(peer *Node) error { - c.count++ - if peer.Name == c.Ignore { - return nil - } - log.Printf("Cancel alive") - return fmt.Errorf("Custom alive canceled") -} - -func TestMemberlist_Join_Cancel_Passive(t *testing.T) { - m1 := GetMemberlist(t) - alive1 := &CustomAliveDelegate{ - Ignore: m1.config.Name, - } - m1.config.Alive = alive1 - m1.setAlive() - m1.schedule() - defer m1.Shutdown() - - // Create a second node - c := DefaultLANConfig() - addr1 := getBindAddr() - c.Name = addr1.String() - c.BindAddr = addr1.String() - c.BindPort = m1.config.BindPort - - m2, err := Create(c) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - alive2 := &CustomAliveDelegate{ - Ignore: c.Name, - } - m2.config.Alive = alive2 - defer m2.Shutdown() - - num, err := m2.Join([]string{m1.config.BindAddr}) - if num != 1 { - t.Fatalf("unexpected 1: %d", num) - } - if err != nil { - t.Fatalf("err: %s", err) - } - - // Check the hosts - if len(m2.Members()) != 1 { - t.Fatalf("should have 1 nodes! %v", m2.Members()) - } - if len(m1.Members()) != 1 { - t.Fatalf("should have 1 nodes! %v", m1.Members()) - } - - // Check delegate invocation - if alive1.count == 0 { - t.Fatalf("should invoke delegate: %d", alive1.count) - } - if alive2.count == 0 { - t.Fatalf("should invoke delegate: %d", alive2.count) - } -} - -func TestMemberlist_Join_protocolVersions(t *testing.T) { - c1 := testConfig() - c2 := testConfig() - c3 := testConfig() - c3.ProtocolVersion = ProtocolVersionMax - - m1, err := Create(c1) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m1.Shutdown() - - m2, err := Create(c2) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m2.Shutdown() - - m3, err := Create(c3) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m3.Shutdown() - - _, err = m1.Join([]string{c2.BindAddr}) - if err != nil { - t.Fatalf("err: %s", err) - } - - yield() - - _, err = m1.Join([]string{c3.BindAddr}) - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestMemberlist_Leave(t *testing.T) { - m1 := GetMemberlist(t) - m1.setAlive() - m1.schedule() - defer m1.Shutdown() - - // Create a second node - c := DefaultLANConfig() - addr1 := getBindAddr() - c.Name = addr1.String() - c.BindAddr = addr1.String() - c.BindPort = m1.config.BindPort - c.GossipInterval = time.Millisecond - - m2, err := Create(c) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - defer m2.Shutdown() - - num, err := m2.Join([]string{m1.config.BindAddr}) - if num != 1 { - t.Fatalf("unexpected 1: %d", num) - } - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - // Check the hosts - if len(m2.Members()) != 2 { - t.Fatalf("should have 2 nodes! %v", m2.Members()) - } - if len(m1.Members()) != 2 { - t.Fatalf("should have 2 nodes! %v", m2.Members()) - } - - // Leave - m1.Leave(time.Second) - - // Wait for leave - time.Sleep(10 * time.Millisecond) - - // m1 should think dead - if len(m1.Members()) != 1 { - t.Fatalf("should have 1 node") - } - - if len(m2.Members()) != 1 { - t.Fatalf("should have 1 node") - } -} - -func TestMemberlist_JoinShutdown(t *testing.T) { - m1 := GetMemberlist(t) - m1.setAlive() - m1.schedule() - - // Create a second node - c := DefaultLANConfig() - addr1 := getBindAddr() - c.Name = addr1.String() - c.BindAddr = addr1.String() - c.BindPort = m1.config.BindPort - c.ProbeInterval = time.Millisecond - c.ProbeTimeout = 100 * time.Microsecond - c.SuspicionMaxTimeoutMult = 1 - - m2, err := Create(c) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - defer m2.Shutdown() - - num, err := m2.Join([]string{m1.config.BindAddr}) - if num != 1 { - t.Fatalf("unexpected 1: %d", num) - } - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - // Check the hosts - if len(m2.Members()) != 2 { - t.Fatalf("should have 2 nodes! %v", m2.Members()) - } - - m1.Shutdown() - - time.Sleep(10 * time.Millisecond) - - if len(m2.Members()) != 1 { - t.Fatalf("should have 1 nodes! %v", m2.Members()) - } -} - -func TestMemberlist_delegateMeta(t *testing.T) { - c1 := testConfig() - c2 := testConfig() - c1.Delegate = &MockDelegate{meta: []byte("web")} - c2.Delegate = &MockDelegate{meta: []byte("lb")} - - m1, err := Create(c1) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m1.Shutdown() - - m2, err := Create(c2) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m2.Shutdown() - - _, err = m1.Join([]string{c2.BindAddr}) - if err != nil { - t.Fatalf("err: %s", err) - } - - yield() - - var roles map[string]string - - // Check the roles of members of m1 - m1m := m1.Members() - if len(m1m) != 2 { - t.Fatalf("bad: %#v", m1m) - } - - roles = make(map[string]string) - for _, m := range m1m { - roles[m.Name] = string(m.Meta) - } - - if r := roles[c1.Name]; r != "web" { - t.Fatalf("bad role for %s: %s", c1.Name, r) - } - - if r := roles[c2.Name]; r != "lb" { - t.Fatalf("bad role for %s: %s", c2.Name, r) - } - - // Check the roles of members of m2 - m2m := m2.Members() - if len(m2m) != 2 { - t.Fatalf("bad: %#v", m2m) - } - - roles = make(map[string]string) - for _, m := range m2m { - roles[m.Name] = string(m.Meta) - } - - if r := roles[c1.Name]; r != "web" { - t.Fatalf("bad role for %s: %s", c1.Name, r) - } - - if r := roles[c2.Name]; r != "lb" { - t.Fatalf("bad role for %s: %s", c2.Name, r) - } -} - -func TestMemberlist_delegateMeta_Update(t *testing.T) { - c1 := testConfig() - c2 := testConfig() - mock1 := &MockDelegate{meta: []byte("web")} - mock2 := &MockDelegate{meta: []byte("lb")} - c1.Delegate = mock1 - c2.Delegate = mock2 - - m1, err := Create(c1) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m1.Shutdown() - - m2, err := Create(c2) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m2.Shutdown() - - _, err = m1.Join([]string{c2.BindAddr}) - if err != nil { - t.Fatalf("err: %s", err) - } - - yield() - - // Update the meta data roles - mock1.meta = []byte("api") - mock2.meta = []byte("db") - - m1.UpdateNode(0) - m2.UpdateNode(0) - yield() - - // Check the updates have propagated - var roles map[string]string - - // Check the roles of members of m1 - m1m := m1.Members() - if len(m1m) != 2 { - t.Fatalf("bad: %#v", m1m) - } - - roles = make(map[string]string) - for _, m := range m1m { - roles[m.Name] = string(m.Meta) - } - - if r := roles[c1.Name]; r != "api" { - t.Fatalf("bad role for %s: %s", c1.Name, r) - } - - if r := roles[c2.Name]; r != "db" { - t.Fatalf("bad role for %s: %s", c2.Name, r) - } - - // Check the roles of members of m2 - m2m := m2.Members() - if len(m2m) != 2 { - t.Fatalf("bad: %#v", m2m) - } - - roles = make(map[string]string) - for _, m := range m2m { - roles[m.Name] = string(m.Meta) - } - - if r := roles[c1.Name]; r != "api" { - t.Fatalf("bad role for %s: %s", c1.Name, r) - } - - if r := roles[c2.Name]; r != "db" { - t.Fatalf("bad role for %s: %s", c2.Name, r) - } -} - -func TestMemberlist_UserData(t *testing.T) { - m1, d1 := GetMemberlistDelegate(t) - d1.state = []byte("something") - m1.setAlive() - m1.schedule() - defer m1.Shutdown() - - bcasts := [][]byte{ - []byte("test"), - []byte("foobar"), - } - - // Create a second delegate with things to send - d2 := &MockDelegate{} - d2.broadcasts = bcasts - d2.state = []byte("my state") - - // Create a second node - c := DefaultLANConfig() - addr1 := getBindAddr() - c.Name = addr1.String() - c.BindAddr = addr1.String() - c.BindPort = m1.config.BindPort - c.GossipInterval = time.Millisecond - c.PushPullInterval = time.Millisecond - c.Delegate = d2 - - m2, err := Create(c) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - num, err := m2.Join([]string{m1.config.BindAddr}) - if num != 1 { - t.Fatalf("unexpected 1: %d", num) - } - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - defer m2.Shutdown() - - // Check the hosts - if m2.NumMembers() != 2 { - t.Fatalf("should have 2 nodes! %v", m2.Members()) - } - - // Wait for a little while - time.Sleep(3 * time.Millisecond) - - // Ensure we got the messages. Ordering of messages is not guaranteed so just - // check we got them both in either order. - require.ElementsMatch(t, bcasts, d1.msgs) - - // Check the push/pull state - if !reflect.DeepEqual(d1.remoteState, []byte("my state")) { - t.Fatalf("bad state %s", d1.remoteState) - } - if !reflect.DeepEqual(d2.remoteState, []byte("something")) { - t.Fatalf("bad state %s", d2.remoteState) - } -} - -func TestMemberlist_SendTo(t *testing.T) { - m1, d1 := GetMemberlistDelegate(t) - m1.setAlive() - m1.schedule() - defer m1.Shutdown() - - // Create a second delegate with things to send - d2 := &MockDelegate{} - - // Create a second node - c := DefaultLANConfig() - addr1 := getBindAddr() - c.Name = addr1.String() - c.BindAddr = addr1.String() - c.BindPort = m1.config.BindPort - c.GossipInterval = time.Millisecond - c.PushPullInterval = time.Millisecond - c.Delegate = d2 - - m2, err := Create(c) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - defer m2.Shutdown() - - num, err := m2.Join([]string{m1.config.BindAddr}) - if num != 1 { - t.Fatalf("unexpected 1: %d", num) - } - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - // Check the hosts - if m2.NumMembers() != 2 { - t.Fatalf("should have 2 nodes! %v", m2.Members()) - } - - // Try to do a direct send - m2Addr := &net.UDPAddr{IP: addr1, - Port: c.BindPort} - if err := m1.SendTo(m2Addr, []byte("ping")); err != nil { - t.Fatalf("err: %v", err) - } - - m1Addr := &net.UDPAddr{IP: net.ParseIP(m1.config.BindAddr), - Port: m1.config.BindPort} - if err := m2.SendTo(m1Addr, []byte("pong")); err != nil { - t.Fatalf("err: %v", err) - } - - // Wait for a little while - time.Sleep(3 * time.Millisecond) - - // Ensure we got the messages - if len(d1.msgs) != 1 { - t.Fatalf("should have 1 messages!") - } - if !reflect.DeepEqual(d1.msgs[0], []byte("pong")) { - t.Fatalf("bad msg %v", d1.msgs[0]) - } - - if len(d2.msgs) != 1 { - t.Fatalf("should have 1 messages!") - } - if !reflect.DeepEqual(d2.msgs[0], []byte("ping")) { - t.Fatalf("bad msg %v", d2.msgs[0]) - } -} - -func TestMemberlistProtocolVersion(t *testing.T) { - c := DefaultLANConfig() - c.BindAddr = getBindAddr().String() - c.ProtocolVersion = ProtocolVersionMax - m, err := Create(c) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m.Shutdown() - - result := m.ProtocolVersion() - if result != ProtocolVersionMax { - t.Fatalf("bad: %d", result) - } -} - -func TestMemberlist_Join_DeadNode(t *testing.T) { - m1 := GetMemberlist(t) - m1.config.TCPTimeout = 50 * time.Millisecond - m1.setAlive() - m1.schedule() - defer m1.Shutdown() - - // Create a second "node", which is just a TCP listener that - // does not ever respond. This is to test our deadliens - addr1 := getBindAddr() - list, err := net.Listen("tcp", fmt.Sprintf("%s:%d", addr1.String(), m1.config.BindPort)) - if err != nil { - t.Fatalf("err: %v", err) - } - defer list.Close() - - // Ensure we don't hang forever - timer := time.AfterFunc(100*time.Millisecond, func() { - panic("should have timed out by now") - }) - defer timer.Stop() - - num, err := m1.Join([]string{addr1.String()}) - if num != 0 { - t.Fatalf("unexpected 0: %d", num) - } - if err == nil { - t.Fatal("expect err") - } -} - -// Tests that nodes running different versions of the protocol can successfully -// discover each other and add themselves to their respective member lists. -func TestMemberlist_Join_Prototocol_Compatibility(t *testing.T) { - testProtocolVersionPair := func(t *testing.T, pv1 uint8, pv2 uint8) { - c1 := testConfig() - c1.ProtocolVersion = pv1 - m1, err := NewMemberlistOnOpenPort(c1) - if err != nil { - t.Fatalf("failed to start: %v", err) - } - m1.setAlive() - m1.schedule() - defer m1.Shutdown() - - c2 := DefaultLANConfig() - addr1 := getBindAddr() - c2.Name = addr1.String() - c2.BindAddr = addr1.String() - c2.BindPort = m1.config.BindPort - c2.ProtocolVersion = pv2 - - m2, err := Create(c2) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - defer m2.Shutdown() - - num, err := m2.Join([]string{m1.config.BindAddr}) - if num != 1 { - t.Fatalf("unexpected 1: %d", num) - } - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - // Check the hosts - if len(m2.Members()) != 2 { - t.Fatalf("should have 2 nodes! %v", m2.Members()) - } - - // Check the hosts - if len(m1.Members()) != 2 { - t.Fatalf("should have 2 nodes! %v", m1.Members()) - } - } - - testProtocolVersionPair(t, 2, 1) - testProtocolVersionPair(t, 2, 3) - testProtocolVersionPair(t, 3, 2) - testProtocolVersionPair(t, 3, 1) -} - -func TestMemberlist_Join_IPv6(t *testing.T) { - // Since this binds to all interfaces we need to exclude other tests - // from grabbing an interface. - bindLock.Lock() - defer bindLock.Unlock() - - c1 := DefaultLANConfig() - c1.Name = "A" - c1.BindAddr = "[::1]" - var m1 *Memberlist - var err error - for i := 0; i < 100; i++ { - c1.BindPort = 23456 + i - m1, err = Create(c1) - if err == nil { - break - } - } - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - defer m1.Shutdown() - - // Create a second node - c2 := DefaultLANConfig() - c2.Name = "B" - c2.BindAddr = "[::1]" - var m2 *Memberlist - for i := 0; i < 100; i++ { - c2.BindPort = c1.BindPort + 1 + i - m2, err = Create(c2) - if err == nil { - break - } - } - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - defer m2.Shutdown() - - num, err := m2.Join([]string{fmt.Sprintf("%s:%d", m1.config.BindAddr, 23456)}) - if num != 1 { - t.Fatalf("unexpected 1: %d", num) - } - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - // Check the hosts - if len(m2.Members()) != 2 { - t.Fatalf("should have 2 nodes! %v", m2.Members()) - } - - if len(m1.Members()) != 2 { - t.Fatalf("should have 2 nodes! %v", m2.Members()) - } -} - -func TestAdvertiseAddr(t *testing.T) { - c := testConfig() - c.AdvertiseAddr = "127.0.1.100" - c.AdvertisePort = 23456 - - m, err := Create(c) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m.Shutdown() - - yield() - - members := m.Members() - if len(members) != 1 { - t.Fatalf("bad number of members") - } - - if bytes.Compare(members[0].Addr, []byte{127, 0, 1, 100}) != 0 { - t.Fatalf("bad: %#v", members[0]) - } - - if members[0].Port != 23456 { - t.Fatalf("bad: %#v", members[0]) - } -} - -type MockConflict struct { - existing *Node - other *Node -} - -func (m *MockConflict) NotifyConflict(existing, other *Node) { - m.existing = existing - m.other = other -} - -func TestMemberlist_conflictDelegate(t *testing.T) { - c1 := testConfig() - c2 := testConfig() - mock := &MockConflict{} - c1.Conflict = mock - - // Ensure name conflict - c2.Name = c1.Name - - m1, err := Create(c1) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m1.Shutdown() - - m2, err := Create(c2) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m2.Shutdown() - - _, err = m1.Join([]string{c2.BindAddr}) - if err != nil { - t.Fatalf("err: %s", err) - } - - yield() - - // Ensure we were notified - if mock.existing == nil || mock.other == nil { - t.Fatalf("should get notified") - } - if mock.existing.Name != mock.other.Name { - t.Fatalf("bad: %v %v", mock.existing, mock.other) - } -} - -type MockPing struct { - other *Node - rtt time.Duration - payload []byte -} - -func (m *MockPing) NotifyPingComplete(other *Node, rtt time.Duration, payload []byte) { - m.other = other - m.rtt = rtt - m.payload = payload -} - -const DEFAULT_PAYLOAD = "whatever" - -func (m *MockPing) AckPayload() []byte { - return []byte(DEFAULT_PAYLOAD) -} - -func TestMemberlist_PingDelegate(t *testing.T) { - m1 := GetMemberlist(t) - m1.config.Ping = &MockPing{} - m1.setAlive() - m1.schedule() - defer m1.Shutdown() - - // Create a second node - c := DefaultLANConfig() - addr1 := getBindAddr() - c.Name = addr1.String() - c.BindAddr = addr1.String() - c.BindPort = m1.config.BindPort - c.ProbeInterval = time.Millisecond - mock := &MockPing{} - c.Ping = mock - - m2, err := Create(c) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m2.Shutdown() - - _, err = m2.Join([]string{m1.config.BindAddr}) - if err != nil { - t.Fatalf("err: %s", err) - } - - yield() - - // Ensure we were notified - if mock.other == nil { - t.Fatalf("should get notified") - } - - if !reflect.DeepEqual(mock.other, m1.LocalNode()) { - t.Fatalf("not notified about the correct node; expected: %+v; actual: %+v", - m2.LocalNode(), mock.other) - } - - if mock.rtt <= 0 { - t.Fatalf("rtt should be greater than 0") - } - - if bytes.Compare(mock.payload, []byte(DEFAULT_PAYLOAD)) != 0 { - t.Fatalf("incorrect payload. expected: %v; actual: %v", []byte(DEFAULT_PAYLOAD), mock.payload) - } -} - -func TestMemberlist_EncryptedGossipTransition(t *testing.T) { - m1 := GetMemberlist(t) - m1.setAlive() - m1.schedule() - defer m1.Shutdown() - - // Create a second node with the first stage of gossip transition settings - conf2 := DefaultLANConfig() - addr2 := getBindAddr() - conf2.Name = addr2.String() - conf2.BindAddr = addr2.String() - conf2.BindPort = m1.config.BindPort - conf2.GossipInterval = time.Millisecond - conf2.SecretKey = []byte("Hi16ZXu2lNCRVwtr20khAg==") - conf2.GossipVerifyIncoming = false - conf2.GossipVerifyOutgoing = false - - m2, err := Create(conf2) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - defer m2.Shutdown() - - // Join the second node. m1 has no encryption while m2 has encryption configured and - // can receive encrypted gossip, but will not encrypt outgoing gossip. - num, err := m2.Join([]string{m1.config.BindAddr}) - if num != 1 { - t.Fatalf("unexpected 1: %d", num) - } - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - // Check the hosts - if len(m2.Members()) != 2 { - t.Fatalf("should have 2 nodes! %v", m2.Members()) - } - if m2.estNumNodes() != 2 { - t.Fatalf("should have 2 nodes! %v", m2.Members()) - } - - // Leave with the first node - m1.Leave(time.Second) - - // Wait for leave - time.Sleep(10 * time.Millisecond) - - // Create a third node that has the second stage of gossip transition settings - conf3 := DefaultLANConfig() - addr3 := getBindAddr() - conf3.Name = addr3.String() - conf3.BindAddr = addr3.String() - conf3.BindPort = m1.config.BindPort - conf3.GossipInterval = time.Millisecond - conf3.SecretKey = conf2.SecretKey - conf3.GossipVerifyIncoming = false - - m3, err := Create(conf3) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - defer m3.Shutdown() - - // Join the third node to the second node. At this step, both nodes have encryption - // configured but only m3 is sending encrypted gossip. - num, err = m3.Join([]string{m2.config.BindAddr}) - if num != 1 { - t.Fatalf("unexpected 1: %d", num) - } - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - // Check the hosts - if len(m3.Members()) != 2 { - t.Fatalf("should have 2 nodes! %v", m3.Members()) - - } - if m3.estNumNodes() != 2 { - t.Fatalf("should have 2 nodes! %v", m3.Members()) - } - - // Leave with the second node - m2.Leave(time.Second) - - // Wait for leave - time.Sleep(10 * time.Millisecond) - - // Create a fourth node that has the second stage of gossip transition settings - conf4 := DefaultLANConfig() - addr4 := getBindAddr() - conf4.Name = addr4.String() - conf4.BindAddr = addr4.String() - conf4.BindPort = m3.config.BindPort - conf4.GossipInterval = time.Millisecond - conf4.SecretKey = conf2.SecretKey - - m4, err := Create(conf4) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - defer m4.Shutdown() - - // Join the fourth node to the third node. At this step, both m3 and m4 are speaking - // encrypted gossip and m3 is still accepting insecure gossip. - num, err = m4.Join([]string{m3.config.BindAddr}) - if num != 1 { - t.Fatalf("unexpected 1: %d", num) - } - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - // Check the hosts - if len(m4.Members()) != 2 { - t.Fatalf("should have 2 nodes! %v", m4.Members()) - - } - if m4.estNumNodes() != 2 { - t.Fatalf("should have 2 nodes! %v", m4.Members()) - } -} - -// Consul bug, rapid restart (before failure detection), -// with an updated meta data. Should be at incarnation 1 for -// both. -// -// This test is uncommented because it requires that either we -// can rebind the socket (SO_REUSEPORT) which Go does not allow, -// OR we must disable the address conflict checking in memberlist. -// I just comment out that code to test this case. -// -//func TestMemberlist_Restart_delegateMeta_Update(t *testing.T) { -// c1 := testConfig() -// c2 := testConfig() -// mock1 := &MockDelegate{meta: []byte("web")} -// mock2 := &MockDelegate{meta: []byte("lb")} -// c1.Delegate = mock1 -// c2.Delegate = mock2 - -// m1, err := Create(c1) -// if err != nil { -// t.Fatalf("err: %s", err) -// } -// defer m1.Shutdown() - -// m2, err := Create(c2) -// if err != nil { -// t.Fatalf("err: %s", err) -// } -// defer m2.Shutdown() - -// _, err = m1.Join([]string{c2.BindAddr}) -// if err != nil { -// t.Fatalf("err: %s", err) -// } - -// yield() - -// // Recreate m1 with updated meta -// m1.Shutdown() -// c3 := testConfig() -// c3.Name = c1.Name -// c3.Delegate = mock1 -// c3.GossipInterval = time.Millisecond -// mock1.meta = []byte("api") - -// m1, err = Create(c3) -// if err != nil { -// t.Fatalf("err: %s", err) -// } -// defer m1.Shutdown() - -// _, err = m1.Join([]string{c2.BindAddr}) -// if err != nil { -// t.Fatalf("err: %s", err) -// } - -// yield() -// yield() - -// // Check the updates have propagated -// var roles map[string]string - -// // Check the roles of members of m1 -// m1m := m1.Members() -// if len(m1m) != 2 { -// t.Fatalf("bad: %#v", m1m) -// } - -// roles = make(map[string]string) -// for _, m := range m1m { -// roles[m.Name] = string(m.Meta) -// } - -// if r := roles[c1.Name]; r != "api" { -// t.Fatalf("bad role for %s: %s", c1.Name, r) -// } - -// if r := roles[c2.Name]; r != "lb" { -// t.Fatalf("bad role for %s: %s", c2.Name, r) -// } - -// // Check the roles of members of m2 -// m2m := m2.Members() -// if len(m2m) != 2 { -// t.Fatalf("bad: %#v", m2m) -// } - -// roles = make(map[string]string) -// for _, m := range m2m { -// roles[m.Name] = string(m.Meta) -// } - -// if r := roles[c1.Name]; r != "api" { -// t.Fatalf("bad role for %s: %s", c1.Name, r) -// } - -// if r := roles[c2.Name]; r != "lb" { -// t.Fatalf("bad role for %s: %s", c2.Name, r) -// } -//} diff --git a/vendor/github.com/hashicorp/memberlist/net_test.go b/vendor/github.com/hashicorp/memberlist/net_test.go deleted file mode 100644 index 860535855..000000000 --- a/vendor/github.com/hashicorp/memberlist/net_test.go +++ /dev/null @@ -1,814 +0,0 @@ -package memberlist - -import ( - "bytes" - "encoding/binary" - "fmt" - "io" - "log" - "net" - "reflect" - "strings" - "testing" - "time" - - "github.com/hashicorp/go-msgpack/codec" -) - -// As a regression we left this test very low-level and network-ey, even after -// we abstracted the transport. We added some basic network-free transport tests -// in transport_test.go to prove that we didn't hard code some network stuff -// outside of NetTransport. - -func TestHandleCompoundPing(t *testing.T) { - m := GetMemberlist(t) - m.config.EnableCompression = false - defer m.Shutdown() - - var udp *net.UDPConn - for port := 60000; port < 61000; port++ { - udpAddr := fmt.Sprintf("127.0.0.1:%d", port) - udpLn, err := net.ListenPacket("udp", udpAddr) - if err == nil { - udp = udpLn.(*net.UDPConn) - break - } - } - - if udp == nil { - t.Fatalf("no udp listener") - } - - // Encode a ping - ping := ping{SeqNo: 42} - buf, err := encode(pingMsg, ping) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - - // Make a compound message - compound := makeCompoundMessage([][]byte{buf.Bytes(), buf.Bytes(), buf.Bytes()}) - - // Send compound version - addr := &net.UDPAddr{IP: net.ParseIP(m.config.BindAddr), Port: m.config.BindPort} - udp.WriteTo(compound.Bytes(), addr) - - // Wait for responses - doneCh := make(chan struct{}, 1) - go func() { - select { - case <-doneCh: - case <-time.After(2 * time.Second): - panic("timeout") - } - }() - - for i := 0; i < 3; i++ { - in := make([]byte, 1500) - n, _, err := udp.ReadFrom(in) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - in = in[0:n] - - msgType := messageType(in[0]) - if msgType != ackRespMsg { - t.Fatalf("bad response %v", in) - } - - var ack ackResp - if err := decode(in[1:], &ack); err != nil { - t.Fatalf("unexpected err %s", err) - } - - if ack.SeqNo != 42 { - t.Fatalf("bad sequence no") - } - } - - doneCh <- struct{}{} -} - -func TestHandlePing(t *testing.T) { - m := GetMemberlist(t) - m.config.EnableCompression = false - defer m.Shutdown() - - var udp *net.UDPConn - for port := 60000; port < 61000; port++ { - udpAddr := fmt.Sprintf("127.0.0.1:%d", port) - udpLn, err := net.ListenPacket("udp", udpAddr) - if err == nil { - udp = udpLn.(*net.UDPConn) - break - } - } - - if udp == nil { - t.Fatalf("no udp listener") - } - - // Encode a ping - ping := ping{SeqNo: 42} - buf, err := encode(pingMsg, ping) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - - // Send - addr := &net.UDPAddr{IP: net.ParseIP(m.config.BindAddr), Port: m.config.BindPort} - udp.WriteTo(buf.Bytes(), addr) - - // Wait for response - doneCh := make(chan struct{}, 1) - go func() { - select { - case <-doneCh: - case <-time.After(2 * time.Second): - panic("timeout") - } - }() - - in := make([]byte, 1500) - n, _, err := udp.ReadFrom(in) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - in = in[0:n] - - msgType := messageType(in[0]) - if msgType != ackRespMsg { - t.Fatalf("bad response %v", in) - } - - var ack ackResp - if err := decode(in[1:], &ack); err != nil { - t.Fatalf("unexpected err %s", err) - } - - if ack.SeqNo != 42 { - t.Fatalf("bad sequence no") - } - - doneCh <- struct{}{} -} - -func TestHandlePing_WrongNode(t *testing.T) { - m := GetMemberlist(t) - m.config.EnableCompression = false - defer m.Shutdown() - - var udp *net.UDPConn - for port := 60000; port < 61000; port++ { - udpAddr := fmt.Sprintf("127.0.0.1:%d", port) - udpLn, err := net.ListenPacket("udp", udpAddr) - if err == nil { - udp = udpLn.(*net.UDPConn) - break - } - } - - if udp == nil { - t.Fatalf("no udp listener") - } - - // Encode a ping, wrong node! - ping := ping{SeqNo: 42, Node: m.config.Name + "-bad"} - buf, err := encode(pingMsg, ping) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - - // Send - addr := &net.UDPAddr{IP: net.ParseIP(m.config.BindAddr), Port: m.config.BindPort} - udp.WriteTo(buf.Bytes(), addr) - - // Wait for response - udp.SetDeadline(time.Now().Add(50 * time.Millisecond)) - in := make([]byte, 1500) - _, _, err = udp.ReadFrom(in) - - // Should get an i/o timeout - if err == nil { - t.Fatalf("expected err %s", err) - } -} - -func TestHandleIndirectPing(t *testing.T) { - m := GetMemberlist(t) - m.config.EnableCompression = false - defer m.Shutdown() - - var udp *net.UDPConn - for port := 60000; port < 61000; port++ { - udpAddr := fmt.Sprintf("127.0.0.1:%d", port) - udpLn, err := net.ListenPacket("udp", udpAddr) - if err == nil { - udp = udpLn.(*net.UDPConn) - break - } - } - - if udp == nil { - t.Fatalf("no udp listener") - } - - // Encode an indirect ping - ind := indirectPingReq{ - SeqNo: 100, - Target: net.ParseIP(m.config.BindAddr), - Port: uint16(m.config.BindPort), - } - buf, err := encode(indirectPingMsg, &ind) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - - // Send - addr := &net.UDPAddr{IP: net.ParseIP(m.config.BindAddr), Port: m.config.BindPort} - udp.WriteTo(buf.Bytes(), addr) - - // Wait for response - doneCh := make(chan struct{}, 1) - go func() { - select { - case <-doneCh: - case <-time.After(2 * time.Second): - panic("timeout") - } - }() - - in := make([]byte, 1500) - n, _, err := udp.ReadFrom(in) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - in = in[0:n] - - msgType := messageType(in[0]) - if msgType != ackRespMsg { - t.Fatalf("bad response %v", in) - } - - var ack ackResp - if err := decode(in[1:], &ack); err != nil { - t.Fatalf("unexpected err %s", err) - } - - if ack.SeqNo != 100 { - t.Fatalf("bad sequence no") - } - - doneCh <- struct{}{} -} - -func TestTCPPing(t *testing.T) { - var tcp *net.TCPListener - var tcpAddr *net.TCPAddr - for port := 60000; port < 61000; port++ { - tcpAddr = &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: port} - tcpLn, err := net.ListenTCP("tcp", tcpAddr) - if err == nil { - tcp = tcpLn - break - } - } - if tcp == nil { - t.Fatalf("no tcp listener") - } - - // Note that tcp gets closed in the last test, so we avoid a deferred - // Close() call here. - - m := GetMemberlist(t) - defer m.Shutdown() - pingTimeout := m.config.ProbeInterval - pingTimeMax := m.config.ProbeInterval + 10*time.Millisecond - - // Do a normal round trip. - pingOut := ping{SeqNo: 23, Node: "mongo"} - go func() { - tcp.SetDeadline(time.Now().Add(pingTimeMax)) - conn, err := tcp.AcceptTCP() - if err != nil { - t.Fatalf("failed to connect: %s", err) - } - defer conn.Close() - - msgType, _, dec, err := m.readStream(conn) - if err != nil { - t.Fatalf("failed to read ping: %s", err) - } - - if msgType != pingMsg { - t.Fatalf("expecting ping, got message type (%d)", msgType) - } - - var pingIn ping - if err := dec.Decode(&pingIn); err != nil { - t.Fatalf("failed to decode ping: %s", err) - } - - if pingIn.SeqNo != pingOut.SeqNo { - t.Fatalf("sequence number isn't correct (%d) vs (%d)", pingIn.SeqNo, pingOut.SeqNo) - } - - if pingIn.Node != pingOut.Node { - t.Fatalf("node name isn't correct (%s) vs (%s)", pingIn.Node, pingOut.Node) - } - - ack := ackResp{pingIn.SeqNo, nil} - out, err := encode(ackRespMsg, &ack) - if err != nil { - t.Fatalf("failed to encode ack: %s", err) - } - - err = m.rawSendMsgStream(conn, out.Bytes()) - if err != nil { - t.Fatalf("failed to send ack: %s", err) - } - }() - deadline := time.Now().Add(pingTimeout) - didContact, err := m.sendPingAndWaitForAck(tcpAddr.String(), pingOut, deadline) - if err != nil { - t.Fatalf("error trying to ping: %s", err) - } - if !didContact { - t.Fatalf("expected successful ping") - } - - // Make sure a mis-matched sequence number is caught. - go func() { - tcp.SetDeadline(time.Now().Add(pingTimeMax)) - conn, err := tcp.AcceptTCP() - if err != nil { - t.Fatalf("failed to connect: %s", err) - } - defer conn.Close() - - _, _, dec, err := m.readStream(conn) - if err != nil { - t.Fatalf("failed to read ping: %s", err) - } - - var pingIn ping - if err := dec.Decode(&pingIn); err != nil { - t.Fatalf("failed to decode ping: %s", err) - } - - ack := ackResp{pingIn.SeqNo + 1, nil} - out, err := encode(ackRespMsg, &ack) - if err != nil { - t.Fatalf("failed to encode ack: %s", err) - } - - err = m.rawSendMsgStream(conn, out.Bytes()) - if err != nil { - t.Fatalf("failed to send ack: %s", err) - } - }() - deadline = time.Now().Add(pingTimeout) - didContact, err = m.sendPingAndWaitForAck(tcpAddr.String(), pingOut, deadline) - if err == nil || !strings.Contains(err.Error(), "Sequence number") { - t.Fatalf("expected an error from mis-matched sequence number") - } - if didContact { - t.Fatalf("expected failed ping") - } - - // Make sure an unexpected message type is handled gracefully. - go func() { - tcp.SetDeadline(time.Now().Add(pingTimeMax)) - conn, err := tcp.AcceptTCP() - if err != nil { - t.Fatalf("failed to connect: %s", err) - } - defer conn.Close() - - _, _, _, err = m.readStream(conn) - if err != nil { - t.Fatalf("failed to read ping: %s", err) - } - - bogus := indirectPingReq{} - out, err := encode(indirectPingMsg, &bogus) - if err != nil { - t.Fatalf("failed to encode bogus msg: %s", err) - } - - err = m.rawSendMsgStream(conn, out.Bytes()) - if err != nil { - t.Fatalf("failed to send bogus msg: %s", err) - } - }() - deadline = time.Now().Add(pingTimeout) - didContact, err = m.sendPingAndWaitForAck(tcpAddr.String(), pingOut, deadline) - if err == nil || !strings.Contains(err.Error(), "Unexpected msgType") { - t.Fatalf("expected an error from bogus message") - } - if didContact { - t.Fatalf("expected failed ping") - } - - // Make sure failed I/O respects the deadline. In this case we try the - // common case of the receiving node being totally down. - tcp.Close() - deadline = time.Now().Add(pingTimeout) - startPing := time.Now() - didContact, err = m.sendPingAndWaitForAck(tcpAddr.String(), pingOut, deadline) - pingTime := time.Now().Sub(startPing) - if err != nil { - t.Fatalf("expected no error during ping on closed socket, got: %s", err) - } - if didContact { - t.Fatalf("expected failed ping") - } - if pingTime > pingTimeMax { - t.Fatalf("took too long to fail ping, %9.6f", pingTime.Seconds()) - } -} - -func TestTCPPushPull(t *testing.T) { - m := GetMemberlist(t) - defer m.Shutdown() - m.nodes = append(m.nodes, &nodeState{ - Node: Node{ - Name: "Test 0", - Addr: net.ParseIP(m.config.BindAddr), - Port: uint16(m.config.BindPort), - }, - Incarnation: 0, - State: stateSuspect, - StateChange: time.Now().Add(-1 * time.Second), - }) - - addr := fmt.Sprintf("%s:%d", m.config.BindAddr, m.config.BindPort) - conn, err := net.Dial("tcp", addr) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - defer conn.Close() - - localNodes := make([]pushNodeState, 3) - localNodes[0].Name = "Test 0" - localNodes[0].Addr = net.ParseIP(m.config.BindAddr) - localNodes[0].Port = uint16(m.config.BindPort) - localNodes[0].Incarnation = 1 - localNodes[0].State = stateAlive - localNodes[1].Name = "Test 1" - localNodes[1].Addr = net.ParseIP(m.config.BindAddr) - localNodes[1].Port = uint16(m.config.BindPort) - localNodes[1].Incarnation = 1 - localNodes[1].State = stateAlive - localNodes[2].Name = "Test 2" - localNodes[2].Addr = net.ParseIP(m.config.BindAddr) - localNodes[2].Port = uint16(m.config.BindPort) - localNodes[2].Incarnation = 1 - localNodes[2].State = stateAlive - - // Send our node state - header := pushPullHeader{Nodes: 3} - hd := codec.MsgpackHandle{} - enc := codec.NewEncoder(conn, &hd) - - // Send the push/pull indicator - conn.Write([]byte{byte(pushPullMsg)}) - - if err := enc.Encode(&header); err != nil { - t.Fatalf("unexpected err %s", err) - } - for i := 0; i < header.Nodes; i++ { - if err := enc.Encode(&localNodes[i]); err != nil { - t.Fatalf("unexpected err %s", err) - } - } - - // Read the message type - var msgType messageType - if err := binary.Read(conn, binary.BigEndian, &msgType); err != nil { - t.Fatalf("unexpected err %s", err) - } - - var bufConn io.Reader = conn - msghd := codec.MsgpackHandle{} - dec := codec.NewDecoder(bufConn, &msghd) - - // Check if we have a compressed message - if msgType == compressMsg { - var c compress - if err := dec.Decode(&c); err != nil { - t.Fatalf("unexpected err %s", err) - } - decomp, err := decompressBuffer(&c) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - - // Reset the message type - msgType = messageType(decomp[0]) - - // Create a new bufConn - bufConn = bytes.NewReader(decomp[1:]) - - // Create a new decoder - dec = codec.NewDecoder(bufConn, &hd) - } - - // Quit if not push/pull - if msgType != pushPullMsg { - t.Fatalf("bad message type") - } - - if err := dec.Decode(&header); err != nil { - t.Fatalf("unexpected err %s", err) - } - - // Allocate space for the transfer - remoteNodes := make([]pushNodeState, header.Nodes) - - // Try to decode all the states - for i := 0; i < header.Nodes; i++ { - if err := dec.Decode(&remoteNodes[i]); err != nil { - t.Fatalf("unexpected err %s", err) - } - } - - if len(remoteNodes) != 1 { - t.Fatalf("bad response") - } - - n := &remoteNodes[0] - if n.Name != "Test 0" { - t.Fatalf("bad name") - } - if bytes.Compare(n.Addr, net.ParseIP(m.config.BindAddr)) != 0 { - t.Fatal("bad addr") - } - if n.Incarnation != 0 { - t.Fatal("bad incarnation") - } - if n.State != stateSuspect { - t.Fatal("bad state") - } -} - -func TestSendMsg_Piggyback(t *testing.T) { - m := GetMemberlist(t) - defer m.Shutdown() - - // Add a message to be broadcast - a := alive{ - Incarnation: 10, - Node: "rand", - Addr: []byte{127, 0, 0, 255}, - Meta: nil, - } - m.encodeAndBroadcast("rand", aliveMsg, &a) - - var udp *net.UDPConn - for port := 60000; port < 61000; port++ { - udpAddr := fmt.Sprintf("127.0.0.1:%d", port) - udpLn, err := net.ListenPacket("udp", udpAddr) - if err == nil { - udp = udpLn.(*net.UDPConn) - break - } - } - - // Encode a ping - ping := ping{SeqNo: 42} - buf, err := encode(pingMsg, ping) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - - // Send - addr := &net.UDPAddr{IP: net.ParseIP(m.config.BindAddr), Port: m.config.BindPort} - udp.WriteTo(buf.Bytes(), addr) - - // Wait for response - doneCh := make(chan struct{}, 1) - go func() { - select { - case <-doneCh: - case <-time.After(2 * time.Second): - panic("timeout") - } - }() - - in := make([]byte, 1500) - n, _, err := udp.ReadFrom(in) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - in = in[0:n] - - msgType := messageType(in[0]) - if msgType != compoundMsg { - t.Fatalf("bad response %v", in) - } - - // get the parts - trunc, parts, err := decodeCompoundMessage(in[1:]) - if trunc != 0 { - t.Fatalf("unexpected truncation") - } - if len(parts) != 2 { - t.Fatalf("unexpected parts %v", parts) - } - if err != nil { - t.Fatalf("unexpected err %s", err) - } - - var ack ackResp - if err := decode(parts[0][1:], &ack); err != nil { - t.Fatalf("unexpected err %s", err) - } - - if ack.SeqNo != 42 { - t.Fatalf("bad sequence no") - } - - var aliveout alive - if err := decode(parts[1][1:], &aliveout); err != nil { - t.Fatalf("unexpected err %s", err) - } - - if aliveout.Node != "rand" || aliveout.Incarnation != 10 { - t.Fatalf("bad mesg") - } - - doneCh <- struct{}{} -} - -func TestEncryptDecryptState(t *testing.T) { - state := []byte("this is our internal state...") - config := &Config{ - SecretKey: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - ProtocolVersion: ProtocolVersionMax, - } - - m, err := Create(config) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m.Shutdown() - - crypt, err := m.encryptLocalState(state) - if err != nil { - t.Fatalf("err: %v", err) - } - - // Create reader, seek past the type byte - buf := bytes.NewReader(crypt) - buf.Seek(1, 0) - - plain, err := m.decryptRemoteState(buf) - if err != nil { - t.Fatalf("err: %v", err) - } - - if !reflect.DeepEqual(state, plain) { - t.Fatalf("Decrypt failed: %v", plain) - } -} - -func TestRawSendUdp_CRC(t *testing.T) { - m := GetMemberlist(t) - m.config.EnableCompression = false - defer m.Shutdown() - - var udp *net.UDPConn - for port := 60000; port < 61000; port++ { - udpAddr := fmt.Sprintf("127.0.0.1:%d", port) - udpLn, err := net.ListenPacket("udp", udpAddr) - if err == nil { - udp = udpLn.(*net.UDPConn) - break - } - } - - if udp == nil { - t.Fatalf("no udp listener") - } - - // Pass a nil node with no nodes registered, should result in no checksum - payload := []byte{3, 3, 3, 3} - m.rawSendMsgPacket(udp.LocalAddr().String(), nil, payload) - - in := make([]byte, 1500) - n, _, err := udp.ReadFrom(in) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - in = in[0:n] - - if len(in) != 4 { - t.Fatalf("bad: %v", in) - } - - // Pass a non-nil node with PMax >= 5, should result in a checksum - m.rawSendMsgPacket(udp.LocalAddr().String(), &Node{PMax: 5}, payload) - - in = make([]byte, 1500) - n, _, err = udp.ReadFrom(in) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - in = in[0:n] - - if len(in) != 9 { - t.Fatalf("bad: %v", in) - } - - // Register a node with PMax >= 5 to be looked up, should result in a checksum - m.nodeMap["127.0.0.1"] = &nodeState{ - Node: Node{PMax: 5}, - } - m.rawSendMsgPacket(udp.LocalAddr().String(), nil, payload) - - in = make([]byte, 1500) - n, _, err = udp.ReadFrom(in) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - in = in[0:n] - - if len(in) != 9 { - t.Fatalf("bad: %v", in) - } -} - -func TestIngestPacket_CRC(t *testing.T) { - m := GetMemberlist(t) - m.config.EnableCompression = false - defer m.Shutdown() - - var udp *net.UDPConn - for port := 60000; port < 61000; port++ { - udpAddr := fmt.Sprintf("127.0.0.1:%d", port) - udpLn, err := net.ListenPacket("udp", udpAddr) - if err == nil { - udp = udpLn.(*net.UDPConn) - break - } - } - - if udp == nil { - t.Fatalf("no udp listener") - } - - // Get a message with a checksum - payload := []byte{3, 3, 3, 3} - m.rawSendMsgPacket(udp.LocalAddr().String(), &Node{PMax: 5}, payload) - - in := make([]byte, 1500) - n, _, err := udp.ReadFrom(in) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - in = in[0:n] - - if len(in) != 9 { - t.Fatalf("bad: %v", in) - } - - // Corrupt the checksum - in[1] <<= 1 - - logs := &bytes.Buffer{} - logger := log.New(logs, "", 0) - m.logger = logger - m.ingestPacket(in, udp.LocalAddr(), time.Now()) - - if !strings.Contains(logs.String(), "invalid checksum") { - t.Fatalf("bad: %s", logs.String()) - } -} - -func TestGossip_MismatchedKeys(t *testing.T) { - c1 := testConfig() - c2 := testConfig() - - // Create two agents with different gossip keys - c1.SecretKey = []byte("4W6DGn2VQVqDEceOdmuRTQ==") - c2.SecretKey = []byte("XhX/w702/JKKK7/7OtM9Ww==") - - m1, err := Create(c1) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m1.Shutdown() - - m2, err := Create(c2) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m2.Shutdown() - - // Make sure we get this error on the joining side - _, err = m2.Join([]string{c1.BindAddr}) - if err == nil || !strings.Contains(err.Error(), "No installed keys could decrypt the message") { - t.Fatalf("bad: %s", err) - } -} diff --git a/vendor/github.com/hashicorp/memberlist/net_transport.go b/vendor/github.com/hashicorp/memberlist/net_transport.go index e7b88b01f..4723127f5 100644 --- a/vendor/github.com/hashicorp/memberlist/net_transport.go +++ b/vendor/github.com/hashicorp/memberlist/net_transport.go @@ -221,6 +221,16 @@ func (t *NetTransport) Shutdown() error { // and hands them off to the stream channel. func (t *NetTransport) tcpListen(tcpLn *net.TCPListener) { defer t.wg.Done() + + // baseDelay is the initial delay after an AcceptTCP() error before attempting again + const baseDelay = 5 * time.Millisecond + + // maxDelay is the maximum delay after an AcceptTCP() error before attempting again. + // In the case that tcpListen() is error-looping, it will delay the shutdown check. + // Therefore, changes to maxDelay may have an effect on the latency of shutdown. + const maxDelay = 1 * time.Second + + var loopDelay time.Duration for { conn, err := tcpLn.AcceptTCP() if err != nil { @@ -228,9 +238,22 @@ func (t *NetTransport) tcpListen(tcpLn *net.TCPListener) { break } + if loopDelay == 0 { + loopDelay = baseDelay + } else { + loopDelay *= 2 + } + + if loopDelay > maxDelay { + loopDelay = maxDelay + } + t.logger.Printf("[ERR] memberlist: Error accepting TCP connection: %v", err) + time.Sleep(loopDelay) continue } + // No error, reset loop delay + loopDelay = 0 t.streamCh <- conn } diff --git a/vendor/github.com/hashicorp/memberlist/queue.go b/vendor/github.com/hashicorp/memberlist/queue.go index 994b90ff1..c970176e1 100644 --- a/vendor/github.com/hashicorp/memberlist/queue.go +++ b/vendor/github.com/hashicorp/memberlist/queue.go @@ -1,8 +1,10 @@ package memberlist import ( - "sort" + "math" "sync" + + "github.com/google/btree" ) // TransmitLimitedQueue is used to queue messages to broadcast to @@ -19,15 +21,93 @@ type TransmitLimitedQueue struct { // number of retransmissions attempted. RetransmitMult int - sync.Mutex - bcQueue limitedBroadcasts + mu sync.Mutex + tq *btree.BTree // stores *limitedBroadcast as btree.Item + tm map[string]*limitedBroadcast + idGen int64 } type limitedBroadcast struct { - transmits int // Number of transmissions attempted. + transmits int // btree-key[0]: Number of transmissions attempted. + msgLen int64 // btree-key[1]: copied from len(b.Message()) + id int64 // btree-key[2]: unique incrementing id stamped at submission time b Broadcast + + name string // set if Broadcast is a NamedBroadcast +} + +// Less tests whether the current item is less than the given argument. +// +// This must provide a strict weak ordering. +// If !a.Less(b) && !b.Less(a), we treat this to mean a == b (i.e. we can only +// hold one of either a or b in the tree). +// +// default ordering is +// - [transmits=0, ..., transmits=inf] +// - [transmits=0:len=999, ..., transmits=0:len=2, ...] +// - [transmits=0:len=999,id=999, ..., transmits=0:len=999:id=1, ...] +func (b *limitedBroadcast) Less(than btree.Item) bool { + o := than.(*limitedBroadcast) + if b.transmits < o.transmits { + return true + } else if b.transmits > o.transmits { + return false + } + if b.msgLen > o.msgLen { + return true + } else if b.msgLen < o.msgLen { + return false + } + return b.id > o.id +} + +// for testing; emits in transmit order if reverse=false +func (q *TransmitLimitedQueue) orderedView(reverse bool) []*limitedBroadcast { + q.mu.Lock() + defer q.mu.Unlock() + + out := make([]*limitedBroadcast, 0, q.lenLocked()) + q.walkReadOnlyLocked(reverse, func(cur *limitedBroadcast) bool { + out = append(out, cur) + return true + }) + + return out +} + +// walkReadOnlyLocked calls f for each item in the queue traversing it in +// natural order (by Less) when reverse=false and the opposite when true. You +// must hold the mutex. +// +// This method panics if you attempt to mutate the item during traversal. The +// underlying btree should also not be mutated during traversal. +func (q *TransmitLimitedQueue) walkReadOnlyLocked(reverse bool, f func(*limitedBroadcast) bool) { + if q.lenLocked() == 0 { + return + } + + iter := func(item btree.Item) bool { + cur := item.(*limitedBroadcast) + + prevTransmits := cur.transmits + prevMsgLen := cur.msgLen + prevID := cur.id + + keepGoing := f(cur) + + if prevTransmits != cur.transmits || prevMsgLen != cur.msgLen || prevID != cur.id { + panic("edited queue while walking read only") + } + + return keepGoing + } + + if reverse { + q.tq.Descend(iter) // end with transmit 0 + } else { + q.tq.Ascend(iter) // start with transmit 0 + } } -type limitedBroadcasts []*limitedBroadcast // Broadcast is something that can be broadcasted via gossip to // the memberlist cluster. @@ -45,123 +125,298 @@ type Broadcast interface { Finished() } +// NamedBroadcast is an optional extension of the Broadcast interface that +// gives each message a unique string name, and that is used to optimize +// +// You shoud ensure that Invalidates() checks the same uniqueness as the +// example below: +// +// func (b *foo) Invalidates(other Broadcast) bool { +// nb, ok := other.(NamedBroadcast) +// if !ok { +// return false +// } +// return b.Name() == nb.Name() +// } +// +// Invalidates() isn't currently used for NamedBroadcasts, but that may change +// in the future. +type NamedBroadcast interface { + Broadcast + // The unique identity of this broadcast message. + Name() string +} + +// UniqueBroadcast is an optional interface that indicates that each message is +// intrinsically unique and there is no need to scan the broadcast queue for +// duplicates. +// +// You should ensure that Invalidates() always returns false if implementing +// this interface. Invalidates() isn't currently used for UniqueBroadcasts, but +// that may change in the future. +type UniqueBroadcast interface { + Broadcast + // UniqueBroadcast is just a marker method for this interface. + UniqueBroadcast() +} + // QueueBroadcast is used to enqueue a broadcast func (q *TransmitLimitedQueue) QueueBroadcast(b Broadcast) { - q.Lock() - defer q.Unlock() - - // Check if this message invalidates another - n := len(q.bcQueue) - for i := 0; i < n; i++ { - if b.Invalidates(q.bcQueue[i].b) { - q.bcQueue[i].b.Finished() - copy(q.bcQueue[i:], q.bcQueue[i+1:]) - q.bcQueue[n-1] = nil - q.bcQueue = q.bcQueue[:n-1] - n-- + q.queueBroadcast(b, 0) +} + +// lazyInit initializes internal data structures the first time they are +// needed. You must already hold the mutex. +func (q *TransmitLimitedQueue) lazyInit() { + if q.tq == nil { + q.tq = btree.New(32) + } + if q.tm == nil { + q.tm = make(map[string]*limitedBroadcast) + } +} + +// queueBroadcast is like QueueBroadcast but you can use a nonzero value for +// the initial transmit tier assigned to the message. This is meant to be used +// for unit testing. +func (q *TransmitLimitedQueue) queueBroadcast(b Broadcast, initialTransmits int) { + q.mu.Lock() + defer q.mu.Unlock() + + q.lazyInit() + + if q.idGen == math.MaxInt64 { + // it's super duper unlikely to wrap around within the retransmit limit + q.idGen = 1 + } else { + q.idGen++ + } + id := q.idGen + + lb := &limitedBroadcast{ + transmits: initialTransmits, + msgLen: int64(len(b.Message())), + id: id, + b: b, + } + unique := false + if nb, ok := b.(NamedBroadcast); ok { + lb.name = nb.Name() + } else if _, ok := b.(UniqueBroadcast); ok { + unique = true + } + + // Check if this message invalidates another. + if lb.name != "" { + if old, ok := q.tm[lb.name]; ok { + old.b.Finished() + q.deleteItem(old) + } + } else if !unique { + // Slow path, hopefully nothing hot hits this. + var remove []*limitedBroadcast + q.tq.Ascend(func(item btree.Item) bool { + cur := item.(*limitedBroadcast) + + // Special Broadcasts can only invalidate each other. + switch cur.b.(type) { + case NamedBroadcast: + // noop + case UniqueBroadcast: + // noop + default: + if b.Invalidates(cur.b) { + cur.b.Finished() + remove = append(remove, cur) + } + } + return true + }) + for _, cur := range remove { + q.deleteItem(cur) } } - // Append to the queue - q.bcQueue = append(q.bcQueue, &limitedBroadcast{0, b}) + // Append to the relevant queue. + q.addItem(lb) +} + +// deleteItem removes the given item from the overall datastructure. You +// must already hold the mutex. +func (q *TransmitLimitedQueue) deleteItem(cur *limitedBroadcast) { + _ = q.tq.Delete(cur) + if cur.name != "" { + delete(q.tm, cur.name) + } + + if q.tq.Len() == 0 { + // At idle there's no reason to let the id generator keep going + // indefinitely. + q.idGen = 0 + } +} + +// addItem adds the given item into the overall datastructure. You must already +// hold the mutex. +func (q *TransmitLimitedQueue) addItem(cur *limitedBroadcast) { + _ = q.tq.ReplaceOrInsert(cur) + if cur.name != "" { + q.tm[cur.name] = cur + } +} + +// getTransmitRange returns a pair of min/max values for transmit values +// represented by the current queue contents. Both values represent actual +// transmit values on the interval [0, len). You must already hold the mutex. +func (q *TransmitLimitedQueue) getTransmitRange() (minTransmit, maxTransmit int) { + if q.lenLocked() == 0 { + return 0, 0 + } + minItem, maxItem := q.tq.Min(), q.tq.Max() + if minItem == nil || maxItem == nil { + return 0, 0 + } + + min := minItem.(*limitedBroadcast).transmits + max := maxItem.(*limitedBroadcast).transmits + + return min, max } // GetBroadcasts is used to get a number of broadcasts, up to a byte limit // and applying a per-message overhead as provided. func (q *TransmitLimitedQueue) GetBroadcasts(overhead, limit int) [][]byte { - q.Lock() - defer q.Unlock() + q.mu.Lock() + defer q.mu.Unlock() // Fast path the default case - if len(q.bcQueue) == 0 { + if q.lenLocked() == 0 { return nil } transmitLimit := retransmitLimit(q.RetransmitMult, q.NumNodes()) - bytesUsed := 0 - var toSend [][]byte - - for i := len(q.bcQueue) - 1; i >= 0; i-- { - // Check if this is within our limits - b := q.bcQueue[i] - msg := b.b.Message() - if bytesUsed+overhead+len(msg) > limit { + + var ( + bytesUsed int + toSend [][]byte + reinsert []*limitedBroadcast + ) + + // Visit fresher items first, but only look at stuff that will fit. + // We'll go tier by tier, grabbing the largest items first. + minTr, maxTr := q.getTransmitRange() + for transmits := minTr; transmits <= maxTr; /*do not advance automatically*/ { + free := int64(limit - bytesUsed - overhead) + if free <= 0 { + break // bail out early + } + + // Search for the least element on a given tier (by transmit count) as + // defined in the limitedBroadcast.Less function that will fit into our + // remaining space. + greaterOrEqual := &limitedBroadcast{ + transmits: transmits, + msgLen: free, + id: math.MaxInt64, + } + lessThan := &limitedBroadcast{ + transmits: transmits + 1, + msgLen: math.MaxInt64, + id: math.MaxInt64, + } + var keep *limitedBroadcast + q.tq.AscendRange(greaterOrEqual, lessThan, func(item btree.Item) bool { + cur := item.(*limitedBroadcast) + // Check if this is within our limits + if int64(len(cur.b.Message())) > free { + // If this happens it's a bug in the datastructure or + // surrounding use doing something like having len(Message()) + // change over time. There's enough going on here that it's + // probably sane to just skip it and move on for now. + return true + } + keep = cur + return false + }) + if keep == nil { + // No more items of an appropriate size in the tier. + transmits++ continue } + msg := keep.b.Message() + // Add to slice to send bytesUsed += overhead + len(msg) toSend = append(toSend, msg) // Check if we should stop transmission - b.transmits++ - if b.transmits >= transmitLimit { - b.b.Finished() - n := len(q.bcQueue) - q.bcQueue[i], q.bcQueue[n-1] = q.bcQueue[n-1], nil - q.bcQueue = q.bcQueue[:n-1] + q.deleteItem(keep) + if keep.transmits+1 >= transmitLimit { + keep.b.Finished() + } else { + // We need to bump this item down to another transmit tier, but + // because it would be in the same direction that we're walking the + // tiers, we will have to delay the reinsertion until we are + // finished our search. Otherwise we'll possibly re-add the message + // when we ascend to the next tier. + keep.transmits++ + reinsert = append(reinsert, keep) } } - // If we are sending anything, we need to re-sort to deal - // with adjusted transmit counts - if len(toSend) > 0 { - q.bcQueue.Sort() + for _, cur := range reinsert { + q.addItem(cur) } + return toSend } // NumQueued returns the number of queued messages func (q *TransmitLimitedQueue) NumQueued() int { - q.Lock() - defer q.Unlock() - return len(q.bcQueue) + q.mu.Lock() + defer q.mu.Unlock() + return q.lenLocked() } -// Reset clears all the queued messages -func (q *TransmitLimitedQueue) Reset() { - q.Lock() - defer q.Unlock() - for _, b := range q.bcQueue { - b.b.Finished() +// lenLocked returns the length of the overall queue datastructure. You must +// hold the mutex. +func (q *TransmitLimitedQueue) lenLocked() int { + if q.tq == nil { + return 0 } - q.bcQueue = nil + return q.tq.Len() +} + +// Reset clears all the queued messages. Should only be used for tests. +func (q *TransmitLimitedQueue) Reset() { + q.mu.Lock() + defer q.mu.Unlock() + + q.walkReadOnlyLocked(false, func(cur *limitedBroadcast) bool { + cur.b.Finished() + return true + }) + + q.tq = nil + q.tm = nil + q.idGen = 0 } // Prune will retain the maxRetain latest messages, and the rest // will be discarded. This can be used to prevent unbounded queue sizes func (q *TransmitLimitedQueue) Prune(maxRetain int) { - q.Lock() - defer q.Unlock() + q.mu.Lock() + defer q.mu.Unlock() // Do nothing if queue size is less than the limit - n := len(q.bcQueue) - if n < maxRetain { - return - } - - // Invalidate the messages we will be removing - for i := 0; i < n-maxRetain; i++ { - q.bcQueue[i].b.Finished() + for q.tq.Len() > maxRetain { + item := q.tq.Max() + if item == nil { + break + } + cur := item.(*limitedBroadcast) + cur.b.Finished() + q.deleteItem(cur) } - - // Move the messages, and retain only the last maxRetain - copy(q.bcQueue[0:], q.bcQueue[n-maxRetain:]) - q.bcQueue = q.bcQueue[:maxRetain] -} - -func (b limitedBroadcasts) Len() int { - return len(b) -} - -func (b limitedBroadcasts) Less(i, j int) bool { - return b[i].transmits < b[j].transmits -} - -func (b limitedBroadcasts) Swap(i, j int) { - b[i], b[j] = b[j], b[i] -} - -func (b limitedBroadcasts) Sort() { - sort.Sort(sort.Reverse(b)) } diff --git a/vendor/github.com/hashicorp/memberlist/queue_test.go b/vendor/github.com/hashicorp/memberlist/queue_test.go deleted file mode 100644 index 765a3b53d..000000000 --- a/vendor/github.com/hashicorp/memberlist/queue_test.go +++ /dev/null @@ -1,172 +0,0 @@ -package memberlist - -import ( - "testing" -) - -func TestTransmitLimited_Queue(t *testing.T) { - q := &TransmitLimitedQueue{RetransmitMult: 1, NumNodes: func() int { return 1 }} - q.QueueBroadcast(&memberlistBroadcast{"test", nil, nil}) - q.QueueBroadcast(&memberlistBroadcast{"foo", nil, nil}) - q.QueueBroadcast(&memberlistBroadcast{"bar", nil, nil}) - - if len(q.bcQueue) != 3 { - t.Fatalf("bad len") - } - if q.bcQueue[0].b.(*memberlistBroadcast).node != "test" { - t.Fatalf("missing test") - } - if q.bcQueue[1].b.(*memberlistBroadcast).node != "foo" { - t.Fatalf("missing foo") - } - if q.bcQueue[2].b.(*memberlistBroadcast).node != "bar" { - t.Fatalf("missing bar") - } - - // Should invalidate previous message - q.QueueBroadcast(&memberlistBroadcast{"test", nil, nil}) - - if len(q.bcQueue) != 3 { - t.Fatalf("bad len") - } - if q.bcQueue[0].b.(*memberlistBroadcast).node != "foo" { - t.Fatalf("missing foo") - } - if q.bcQueue[1].b.(*memberlistBroadcast).node != "bar" { - t.Fatalf("missing bar") - } - if q.bcQueue[2].b.(*memberlistBroadcast).node != "test" { - t.Fatalf("missing test") - } -} - -func TestTransmitLimited_GetBroadcasts(t *testing.T) { - q := &TransmitLimitedQueue{RetransmitMult: 3, NumNodes: func() int { return 10 }} - - // 18 bytes per message - q.QueueBroadcast(&memberlistBroadcast{"test", []byte("1. this is a test."), nil}) - q.QueueBroadcast(&memberlistBroadcast{"foo", []byte("2. this is a test."), nil}) - q.QueueBroadcast(&memberlistBroadcast{"bar", []byte("3. this is a test."), nil}) - q.QueueBroadcast(&memberlistBroadcast{"baz", []byte("4. this is a test."), nil}) - - // 2 byte overhead per message, should get all 4 messages - all := q.GetBroadcasts(2, 80) - if len(all) != 4 { - t.Fatalf("missing messages: %v", all) - } - - // 3 byte overhead, should only get 3 messages back - partial := q.GetBroadcasts(3, 80) - if len(partial) != 3 { - t.Fatalf("missing messages: %v", partial) - } -} - -func TestTransmitLimited_GetBroadcasts_Limit(t *testing.T) { - q := &TransmitLimitedQueue{RetransmitMult: 1, NumNodes: func() int { return 10 }} - - // 18 bytes per message - q.QueueBroadcast(&memberlistBroadcast{"test", []byte("1. this is a test."), nil}) - q.QueueBroadcast(&memberlistBroadcast{"foo", []byte("2. this is a test."), nil}) - q.QueueBroadcast(&memberlistBroadcast{"bar", []byte("3. this is a test."), nil}) - q.QueueBroadcast(&memberlistBroadcast{"baz", []byte("4. this is a test."), nil}) - - // 3 byte overhead, should only get 3 messages back - partial1 := q.GetBroadcasts(3, 80) - if len(partial1) != 3 { - t.Fatalf("missing messages: %v", partial1) - } - - partial2 := q.GetBroadcasts(3, 80) - if len(partial2) != 3 { - t.Fatalf("missing messages: %v", partial2) - } - - // Only two not expired - partial3 := q.GetBroadcasts(3, 80) - if len(partial3) != 2 { - t.Fatalf("missing messages: %v", partial3) - } - - // Should get nothing - partial5 := q.GetBroadcasts(3, 80) - if len(partial5) != 0 { - t.Fatalf("missing messages: %v", partial5) - } -} - -func TestTransmitLimited_Prune(t *testing.T) { - q := &TransmitLimitedQueue{RetransmitMult: 1, NumNodes: func() int { return 10 }} - - ch1 := make(chan struct{}, 1) - ch2 := make(chan struct{}, 1) - - // 18 bytes per message - q.QueueBroadcast(&memberlistBroadcast{"test", []byte("1. this is a test."), ch1}) - q.QueueBroadcast(&memberlistBroadcast{"foo", []byte("2. this is a test."), ch2}) - q.QueueBroadcast(&memberlistBroadcast{"bar", []byte("3. this is a test."), nil}) - q.QueueBroadcast(&memberlistBroadcast{"baz", []byte("4. this is a test."), nil}) - - // Keep only 2 - q.Prune(2) - - if q.NumQueued() != 2 { - t.Fatalf("bad len") - } - - // Should notify the first two - select { - case <-ch1: - default: - t.Fatalf("expected invalidation") - } - select { - case <-ch2: - default: - t.Fatalf("expected invalidation") - } - - if q.bcQueue[0].b.(*memberlistBroadcast).node != "bar" { - t.Fatalf("missing bar") - } - if q.bcQueue[1].b.(*memberlistBroadcast).node != "baz" { - t.Fatalf("missing baz") - } -} - -func TestLimitedBroadcastSort(t *testing.T) { - bc := limitedBroadcasts([]*limitedBroadcast{ - &limitedBroadcast{ - transmits: 0, - }, - &limitedBroadcast{ - transmits: 10, - }, - &limitedBroadcast{ - transmits: 3, - }, - &limitedBroadcast{ - transmits: 4, - }, - &limitedBroadcast{ - transmits: 7, - }, - }) - bc.Sort() - - if bc[0].transmits != 10 { - t.Fatalf("bad val %v", bc[0]) - } - if bc[1].transmits != 7 { - t.Fatalf("bad val %v", bc[7]) - } - if bc[2].transmits != 4 { - t.Fatalf("bad val %v", bc[2]) - } - if bc[3].transmits != 3 { - t.Fatalf("bad val %v", bc[3]) - } - if bc[4].transmits != 0 { - t.Fatalf("bad val %v", bc[4]) - } -} diff --git a/vendor/github.com/hashicorp/memberlist/security_test.go b/vendor/github.com/hashicorp/memberlist/security_test.go deleted file mode 100644 index 15fa4aa8e..000000000 --- a/vendor/github.com/hashicorp/memberlist/security_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package memberlist - -import ( - "bytes" - "reflect" - "testing" -) - -func TestPKCS7(t *testing.T) { - for i := 0; i <= 255; i++ { - // Make a buffer of size i - buf := []byte{} - for j := 0; j < i; j++ { - buf = append(buf, byte(i)) - } - - // Copy to bytes buffer - inp := bytes.NewBuffer(nil) - inp.Write(buf) - - // Pad this out - pkcs7encode(inp, 0, 16) - - // Unpad - dec := pkcs7decode(inp.Bytes(), 16) - - // Ensure equivilence - if !reflect.DeepEqual(buf, dec) { - t.Fatalf("mismatch: %v %v", buf, dec) - } - } - -} - -func TestEncryptDecrypt_V0(t *testing.T) { - encryptDecryptVersioned(0, t) -} - -func TestEncryptDecrypt_V1(t *testing.T) { - encryptDecryptVersioned(1, t) -} - -func encryptDecryptVersioned(vsn encryptionVersion, t *testing.T) { - k1 := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} - plaintext := []byte("this is a plain text message") - extra := []byte("random data") - - var buf bytes.Buffer - err := encryptPayload(vsn, k1, plaintext, extra, &buf) - if err != nil { - t.Fatalf("err: %v", err) - } - - expLen := encryptedLength(vsn, len(plaintext)) - if buf.Len() != expLen { - t.Fatalf("output length is unexpected %d %d %d", len(plaintext), buf.Len(), expLen) - } - - msg, err := decryptPayload([][]byte{k1}, buf.Bytes(), extra) - if err != nil { - t.Fatalf("err: %v", err) - } - - cmp := bytes.Compare(msg, plaintext) - if cmp != 0 { - t.Errorf("len %d %v", len(msg), msg) - t.Errorf("len %d %v", len(plaintext), plaintext) - t.Fatalf("encrypt/decrypt failed! %d '%s' '%s'", cmp, msg, plaintext) - } -} diff --git a/vendor/github.com/hashicorp/memberlist/state.go b/vendor/github.com/hashicorp/memberlist/state.go index f51692de0..1af62943e 100644 --- a/vendor/github.com/hashicorp/memberlist/state.go +++ b/vendor/github.com/hashicorp/memberlist/state.go @@ -9,7 +9,7 @@ import ( "sync/atomic" "time" - "github.com/armon/go-metrics" + metrics "github.com/armon/go-metrics" ) type nodeStateType int @@ -233,6 +233,15 @@ START: m.probeNode(&node) } +// probeNodeByAddr just safely calls probeNode given only the address of the node (for tests) +func (m *Memberlist) probeNodeByAddr(addr string) { + m.nodeLock.RLock() + n := m.nodeMap[addr] + m.nodeLock.RUnlock() + + m.probeNode(n) +} + // probeNode handles a single round of failure checking on a node. func (m *Memberlist) probeNode(node *nodeState) { defer metrics.MeasureSince([]string{"memberlist", "probeNode"}, time.Now()) @@ -841,11 +850,26 @@ func (m *Memberlist) aliveNode(a *alive, notify chan struct{}, bootstrap bool) { return } + if len(a.Vsn) >= 3 { + pMin := a.Vsn[0] + pMax := a.Vsn[1] + pCur := a.Vsn[2] + if pMin == 0 || pMax == 0 || pMin > pMax { + m.logger.Printf("[WARN] memberlist: Ignoring an alive message for '%s' (%v:%d) because protocol version(s) are wrong: %d <= %d <= %d should be >0", a.Node, net.IP(a.Addr), a.Port, pMin, pCur, pMax) + return + } + } + // Invoke the Alive delegate if any. This can be used to filter out // alive messages based on custom logic. For example, using a cluster name. // Using a merge delegate is not enough, as it is possible for passive // cluster merging to still occur. if m.config.Alive != nil { + if len(a.Vsn) < 6 { + m.logger.Printf("[WARN] memberlist: ignoring alive message for '%s' (%v:%d) because Vsn is not present", + a.Node, net.IP(a.Addr), a.Port) + return + } node := &Node{ Name: a.Node, Addr: a.Addr, @@ -867,6 +891,7 @@ func (m *Memberlist) aliveNode(a *alive, notify chan struct{}, bootstrap bool) { // Check if we've never seen this node before, and if not, then // store this node in our node map. + var updatesNode bool if !ok { state = &nodeState{ Node: Node{ @@ -877,6 +902,14 @@ func (m *Memberlist) aliveNode(a *alive, notify chan struct{}, bootstrap bool) { }, State: stateDead, } + if len(a.Vsn) > 5 { + state.PMin = a.Vsn[0] + state.PMax = a.Vsn[1] + state.PCur = a.Vsn[2] + state.DMin = a.Vsn[3] + state.DMax = a.Vsn[4] + state.DCur = a.Vsn[5] + } // Add to map m.nodeMap[a.Node] = state @@ -894,29 +927,40 @@ func (m *Memberlist) aliveNode(a *alive, notify chan struct{}, bootstrap bool) { // Update numNodes after we've added a new node atomic.AddUint32(&m.numNodes, 1) - } - - // Check if this address is different than the existing node - if !bytes.Equal([]byte(state.Addr), a.Addr) || state.Port != a.Port { - m.logger.Printf("[ERR] memberlist: Conflicting address for %s. Mine: %v:%d Theirs: %v:%d", - state.Name, state.Addr, state.Port, net.IP(a.Addr), a.Port) - - // Inform the conflict delegate if provided - if m.config.Conflict != nil { - other := Node{ - Name: a.Node, - Addr: a.Addr, - Port: a.Port, - Meta: a.Meta, + } else { + // Check if this address is different than the existing node unless the old node is dead. + if !bytes.Equal([]byte(state.Addr), a.Addr) || state.Port != a.Port { + // If DeadNodeReclaimTime is configured, check if enough time has elapsed since the node died. + canReclaim := (m.config.DeadNodeReclaimTime > 0 && + time.Since(state.StateChange) > m.config.DeadNodeReclaimTime) + + // Allow the address to be updated if a dead node is being replaced. + if state.State == stateDead && canReclaim { + m.logger.Printf("[INFO] memberlist: Updating address for failed node %s from %v:%d to %v:%d", + state.Name, state.Addr, state.Port, net.IP(a.Addr), a.Port) + updatesNode = true + } else { + m.logger.Printf("[ERR] memberlist: Conflicting address for %s. Mine: %v:%d Theirs: %v:%d Old state: %v", + state.Name, state.Addr, state.Port, net.IP(a.Addr), a.Port, state.State) + + // Inform the conflict delegate if provided + if m.config.Conflict != nil { + other := Node{ + Name: a.Node, + Addr: a.Addr, + Port: a.Port, + Meta: a.Meta, + } + m.config.Conflict.NotifyConflict(&state.Node, &other) + } + return } - m.config.Conflict.NotifyConflict(&state.Node, &other) } - return } // Bail if the incarnation number is older, and this is not about us isLocalNode := state.Name == m.config.Name - if a.Incarnation <= state.Incarnation && !isLocalNode { + if a.Incarnation <= state.Incarnation && !isLocalNode && !updatesNode { return } @@ -956,9 +1000,8 @@ func (m *Memberlist) aliveNode(a *alive, notify chan struct{}, bootstrap bool) { bytes.Equal(a.Vsn, versions) { return } - m.refute(state, a.Incarnation) - m.logger.Printf("[WARN] memberlist: Refuting an alive message") + m.logger.Printf("[WARN] memberlist: Refuting an alive message for '%s' (%v:%d) meta:(%v VS %v), vsn:(%v VS %v)", a.Node, net.IP(a.Addr), a.Port, a.Meta, state.Meta, a.Vsn, versions) } else { m.encodeBroadcastNotify(a.Node, aliveMsg, a, notify) @@ -975,6 +1018,8 @@ func (m *Memberlist) aliveNode(a *alive, notify chan struct{}, bootstrap bool) { // Update the state and incarnation number state.Incarnation = a.Incarnation state.Meta = a.Meta + state.Addr = a.Addr + state.Port = a.Port if state.State != stateAlive { state.State = stateAlive state.StateChange = time.Now() diff --git a/vendor/github.com/hashicorp/memberlist/state_test.go b/vendor/github.com/hashicorp/memberlist/state_test.go deleted file mode 100644 index d21e071e5..000000000 --- a/vendor/github.com/hashicorp/memberlist/state_test.go +++ /dev/null @@ -1,1932 +0,0 @@ -package memberlist - -import ( - "bytes" - "fmt" - "net" - "testing" - "time" -) - -func HostMemberlist(host string, t *testing.T, f func(*Config)) *Memberlist { - c := DefaultLANConfig() - c.Name = host - c.BindAddr = host - if f != nil { - f(c) - } - - m, err := newMemberlist(c) - if err != nil { - t.Fatalf("failed to get memberlist: %s", err) - } - return m -} - -func TestMemberList_Probe(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = time.Millisecond - c.ProbeInterval = 10 * time.Millisecond - }) - m2 := HostMemberlist(addr2.String(), t, nil) - - a1 := alive{ - Node: addr1.String(), - Addr: []byte(addr1), - Port: uint16(m1.config.BindPort), - Incarnation: 1, - } - m1.aliveNode(&a1, nil, true) - a2 := alive{ - Node: addr2.String(), - Addr: []byte(addr2), - Port: uint16(m2.config.BindPort), - Incarnation: 1, - } - m1.aliveNode(&a2, nil, false) - - // should ping addr2 - m1.probe() - - // Should not be marked suspect - n := m1.nodeMap[addr2.String()] - if n.State != stateAlive { - t.Fatalf("Expect node to be alive") - } - - // Should increment seqno - if m1.sequenceNum != 1 { - t.Fatalf("bad seqno %v", m2.sequenceNum) - } -} - -func TestMemberList_ProbeNode_Suspect(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - addr3 := getBindAddr() - addr4 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - ip3 := []byte(addr3) - ip4 := []byte(addr4) - - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = time.Millisecond - c.ProbeInterval = 10 * time.Millisecond - }) - m2 := HostMemberlist(addr2.String(), t, nil) - m3 := HostMemberlist(addr3.String(), t, nil) - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - a3 := alive{Node: addr3.String(), Addr: ip3, Port: 7946, Incarnation: 1} - m1.aliveNode(&a3, nil, false) - a4 := alive{Node: addr4.String(), Addr: ip4, Port: 7946, Incarnation: 1} - m1.aliveNode(&a4, nil, false) - - n := m1.nodeMap[addr4.String()] - m1.probeNode(n) - - // Should be marked suspect. - if n.State != stateSuspect { - t.Fatalf("Expect node to be suspect") - } - time.Sleep(10 * time.Millisecond) - - // One of the peers should have attempted an indirect probe. - if m2.sequenceNum != 1 && m3.sequenceNum != 1 { - t.Fatalf("bad seqnos %v, %v", m2.sequenceNum, m3.sequenceNum) - } -} - -func TestMemberList_ProbeNode_Suspect_Dogpile(t *testing.T) { - cases := []struct { - numPeers int - confirmations int - expected time.Duration - }{ - {1, 0, 500 * time.Millisecond}, // n=2, k=3 (max timeout disabled) - {2, 0, 500 * time.Millisecond}, // n=3, k=3 - {3, 0, 500 * time.Millisecond}, // n=4, k=3 - {4, 0, 1000 * time.Millisecond}, // n=5, k=3 (max timeout starts to take effect) - {5, 0, 1000 * time.Millisecond}, // n=6, k=3 - {5, 1, 750 * time.Millisecond}, // n=6, k=3 (confirmations start to lower timeout) - {5, 2, 604 * time.Millisecond}, // n=6, k=3 - {5, 3, 500 * time.Millisecond}, // n=6, k=3 (timeout driven to nominal value) - {5, 4, 500 * time.Millisecond}, // n=6, k=3 - } - for i, c := range cases { - // Create the main memberlist under test. - addr := getBindAddr() - m := HostMemberlist(addr.String(), t, func(c *Config) { - c.ProbeTimeout = time.Millisecond - c.ProbeInterval = 100 * time.Millisecond - c.SuspicionMult = 5 - c.SuspicionMaxTimeoutMult = 2 - }) - a := alive{Node: addr.String(), Addr: []byte(addr), Port: 7946, Incarnation: 1} - m.aliveNode(&a, nil, true) - - // Make all but one peer be an real, alive instance. - var peers []*Memberlist - for j := 0; j < c.numPeers-1; j++ { - peerAddr := getBindAddr() - peers = append(peers, HostMemberlist(peerAddr.String(), t, nil)) - a = alive{Node: peerAddr.String(), Addr: []byte(peerAddr), Port: 7946, Incarnation: 1} - m.aliveNode(&a, nil, false) - } - - // Just use a bogus address for the last peer so it doesn't respond - // to pings, but tell the memberlist it's alive. - badPeerAddr := getBindAddr() - a = alive{Node: badPeerAddr.String(), Addr: []byte(badPeerAddr), Port: 7946, Incarnation: 1} - m.aliveNode(&a, nil, false) - - // Force a probe, which should start us into the suspect state. - n := m.nodeMap[badPeerAddr.String()] - m.probeNode(n) - if n.State != stateSuspect { - t.Fatalf("case %d: expected node to be suspect", i) - } - - // Add the requested number of confirmations. - for j := 0; j < c.confirmations; j++ { - from := fmt.Sprintf("peer%d", j) - s := suspect{Node: badPeerAddr.String(), Incarnation: 1, From: from} - m.suspectNode(&s) - } - - // Wait until right before the timeout and make sure the timer - // hasn't fired. - fudge := 25 * time.Millisecond - time.Sleep(c.expected - fudge) - if n.State != stateSuspect { - t.Fatalf("case %d: expected node to still be suspect", i) - } - - // Wait through the timeout and a little after to make sure the - // timer fires. - time.Sleep(2 * fudge) - if n.State != stateDead { - t.Fatalf("case %d: expected node to be dead", i) - } - } -} - -/* -func TestMemberList_ProbeNode_FallbackTCP(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - addr3 := getBindAddr() - addr4 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - ip3 := []byte(addr3) - ip4 := []byte(addr4) - - var probeTimeMax time.Duration - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - probeTimeMax = c.ProbeInterval + 20*time.Millisecond - }) - defer m1.Shutdown() - - m2 := HostMemberlist(addr2.String(), t, nil) - defer m2.Shutdown() - - m3 := HostMemberlist(addr3.String(), t, nil) - defer m3.Shutdown() - - m4 := HostMemberlist(addr4.String(), t, nil) - defer m4.Shutdown() - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - a3 := alive{Node: addr3.String(), Addr: ip3, Port: 7946, Incarnation: 1} - m1.aliveNode(&a3, nil, false) - - // Make sure m4 is configured with the same protocol version as m1 so - // the TCP fallback behavior is enabled. - a4 := alive{ - Node: addr4.String(), - Addr: ip4, - Port: 7946, - Incarnation: 1, - Vsn: []uint8{ - ProtocolVersionMin, - ProtocolVersionMax, - m1.config.ProtocolVersion, - m1.config.DelegateProtocolMin, - m1.config.DelegateProtocolMax, - m1.config.DelegateProtocolVersion, - }, - } - m1.aliveNode(&a4, nil, false) - - // Isolate m4 from UDP traffic by re-opening its listener on the wrong - // port. This should force the TCP fallback path to be used. - var err error - if err = m4.udpListener.Close(); err != nil { - t.Fatalf("err: %v", err) - } - udpAddr := &net.UDPAddr{IP: ip4, Port: 9999} - if m4.udpListener, err = net.ListenUDP("udp", udpAddr); err != nil { - t.Fatalf("err: %v", err) - } - - // Have node m1 probe m4. - n := m1.nodeMap[addr4.String()] - startProbe := time.Now() - m1.probeNode(n) - probeTime := time.Now().Sub(startProbe) - - // Should be marked alive because of the TCP fallback ping. - if n.State != stateAlive { - t.Fatalf("expect node to be alive") - } - - // Make sure TCP activity completed in a timely manner. - if probeTime > probeTimeMax { - t.Fatalf("took to long to probe, %9.6f", probeTime.Seconds()) - } - - // Confirm at least one of the peers attempted an indirect probe. - time.Sleep(probeTimeMax) - if m2.sequenceNum != 1 && m3.sequenceNum != 1 { - t.Fatalf("bad seqnos %v, %v", m2.sequenceNum, m3.sequenceNum) - } - - // Now shutdown all inbound TCP traffic to make sure the TCP fallback - // path properly fails when the node is really unreachable. - if err = m4.tcpListener.Close(); err != nil { - t.Fatalf("err: %v", err) - } - tcpAddr := &net.TCPAddr{IP: ip4, Port: 9999} - if m4.tcpListener, err = net.ListenTCP("tcp", tcpAddr); err != nil { - t.Fatalf("err: %v", err) - } - - // Probe again, this time there should be no contact. - startProbe = time.Now() - m1.probeNode(n) - probeTime = time.Now().Sub(startProbe) - - // Node should be reported suspect. - if n.State != stateSuspect { - t.Fatalf("expect node to be suspect") - } - - // Make sure TCP activity didn't cause us to wait too long before - // timing out. - if probeTime > probeTimeMax { - t.Fatalf("took to long to probe, %9.6f", probeTime.Seconds()) - } - - // Confirm at least one of the peers attempted an indirect probe. - time.Sleep(probeTimeMax) - if m2.sequenceNum != 2 && m3.sequenceNum != 2 { - t.Fatalf("bad seqnos %v, %v", m2.sequenceNum, m3.sequenceNum) - } -} - -func TestMemberList_ProbeNode_FallbackTCP_Disabled(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - addr3 := getBindAddr() - addr4 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - ip3 := []byte(addr3) - ip4 := []byte(addr4) - - var probeTimeMax time.Duration - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - probeTimeMax = c.ProbeInterval + 20*time.Millisecond - }) - defer m1.Shutdown() - - m2 := HostMemberlist(addr2.String(), t, nil) - defer m2.Shutdown() - - m3 := HostMemberlist(addr3.String(), t, nil) - defer m3.Shutdown() - - m4 := HostMemberlist(addr4.String(), t, nil) - defer m4.Shutdown() - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - a3 := alive{Node: addr3.String(), Addr: ip3, Port: 7946, Incarnation: 1} - m1.aliveNode(&a3, nil, false) - - // Make sure m4 is configured with the same protocol version as m1 so - // the TCP fallback behavior is enabled. - a4 := alive{ - Node: addr4.String(), - Addr: ip4, - Port: 7946, - Incarnation: 1, - Vsn: []uint8{ - ProtocolVersionMin, - ProtocolVersionMax, - m1.config.ProtocolVersion, - m1.config.DelegateProtocolMin, - m1.config.DelegateProtocolMax, - m1.config.DelegateProtocolVersion, - }, - } - m1.aliveNode(&a4, nil, false) - - // Isolate m4 from UDP traffic by re-opening its listener on the wrong - // port. This should force the TCP fallback path to be used. - var err error - if err = m4.udpListener.Close(); err != nil { - t.Fatalf("err: %v", err) - } - udpAddr := &net.UDPAddr{IP: ip4, Port: 9999} - if m4.udpListener, err = net.ListenUDP("udp", udpAddr); err != nil { - t.Fatalf("err: %v", err) - } - - // Disable the TCP pings using the config mechanism. - m1.config.DisableTcpPings = true - - // Have node m1 probe m4. - n := m1.nodeMap[addr4.String()] - startProbe := time.Now() - m1.probeNode(n) - probeTime := time.Now().Sub(startProbe) - - // Node should be reported suspect. - if n.State != stateSuspect { - t.Fatalf("expect node to be suspect") - } - - // Make sure TCP activity didn't cause us to wait too long before - // timing out. - if probeTime > probeTimeMax { - t.Fatalf("took to long to probe, %9.6f", probeTime.Seconds()) - } - - // Confirm at least one of the peers attempted an indirect probe. - time.Sleep(probeTimeMax) - if m2.sequenceNum != 1 && m3.sequenceNum != 1 { - t.Fatalf("bad seqnos %v, %v", m2.sequenceNum, m3.sequenceNum) - } -} - -func TestMemberList_ProbeNode_FallbackTCP_OldProtocol(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - addr3 := getBindAddr() - addr4 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - ip3 := []byte(addr3) - ip4 := []byte(addr4) - - var probeTimeMax time.Duration - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - probeTimeMax = c.ProbeInterval + 20*time.Millisecond - }) - defer m1.Shutdown() - - m2 := HostMemberlist(addr2.String(), t, nil) - defer m2.Shutdown() - - m3 := HostMemberlist(addr3.String(), t, nil) - defer m3.Shutdown() - - m4 := HostMemberlist(addr4.String(), t, nil) - defer m4.Shutdown() - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - a3 := alive{Node: addr3.String(), Addr: ip3, Port: 7946, Incarnation: 1} - m1.aliveNode(&a3, nil, false) - - // Set up m4 so that it doesn't understand a version of the protocol - // that supports TCP pings. - a4 := alive{ - Node: addr4.String(), - Addr: ip4, - Port: 7946, - Incarnation: 1, - Vsn: []uint8{ - ProtocolVersionMin, - ProtocolVersion2Compatible, - ProtocolVersion2Compatible, - m1.config.DelegateProtocolMin, - m1.config.DelegateProtocolMax, - m1.config.DelegateProtocolVersion, - }, - } - m1.aliveNode(&a4, nil, false) - - // Isolate m4 from UDP traffic by re-opening its listener on the wrong - // port. This should force the TCP fallback path to be used. - var err error - if err = m4.udpListener.Close(); err != nil { - t.Fatalf("err: %v", err) - } - udpAddr := &net.UDPAddr{IP: ip4, Port: 9999} - if m4.udpListener, err = net.ListenUDP("udp", udpAddr); err != nil { - t.Fatalf("err: %v", err) - } - - // Have node m1 probe m4. - n := m1.nodeMap[addr4.String()] - startProbe := time.Now() - m1.probeNode(n) - probeTime := time.Now().Sub(startProbe) - - // Node should be reported suspect. - if n.State != stateSuspect { - t.Fatalf("expect node to be suspect") - } - - // Make sure TCP activity didn't cause us to wait too long before - // timing out. - if probeTime > probeTimeMax { - t.Fatalf("took to long to probe, %9.6f", probeTime.Seconds()) - } - - // Confirm at least one of the peers attempted an indirect probe. - time.Sleep(probeTimeMax) - if m2.sequenceNum != 1 && m3.sequenceNum != 1 { - t.Fatalf("bad seqnos %v, %v", m2.sequenceNum, m3.sequenceNum) - } -} -*/ - -func TestMemberList_ProbeNode_Awareness_Degraded(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - addr3 := getBindAddr() - addr4 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - ip3 := []byte(addr3) - ip4 := []byte(addr4) - - var probeTimeMin time.Duration - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - probeTimeMin = 2*c.ProbeInterval - 50*time.Millisecond - }) - defer m1.Shutdown() - - m2 := HostMemberlist(addr2.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - }) - defer m2.Shutdown() - - m3 := HostMemberlist(addr3.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - }) - defer m3.Shutdown() - - // This will enable nacks by invoking the latest protocol version. - vsn := []uint8{ - ProtocolVersionMin, - ProtocolVersionMax, - m1.config.ProtocolVersion, - m1.config.DelegateProtocolMin, - m1.config.DelegateProtocolMax, - m1.config.DelegateProtocolVersion, - } - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1, Vsn: vsn} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1, Vsn: vsn} - m1.aliveNode(&a2, nil, false) - a3 := alive{Node: addr3.String(), Addr: ip3, Port: 7946, Incarnation: 1, Vsn: vsn} - m1.aliveNode(&a3, nil, false) - - // Node 4 never gets started. - a4 := alive{Node: addr4.String(), Addr: ip4, Port: 7946, Incarnation: 1, Vsn: vsn} - m1.aliveNode(&a4, nil, false) - - // Start the health in a degraded state. - m1.awareness.ApplyDelta(1) - if score := m1.GetHealthScore(); score != 1 { - t.Fatalf("bad: %d", score) - } - - // Have node m1 probe m4. - n := m1.nodeMap[addr4.String()] - startProbe := time.Now() - m1.probeNode(n) - probeTime := time.Now().Sub(startProbe) - - // Node should be reported suspect. - if n.State != stateSuspect { - t.Fatalf("expect node to be suspect") - } - - // Make sure we timed out approximately on time (note that we accounted - // for the slowed-down failure detector in the probeTimeMin calculation. - if probeTime < probeTimeMin { - t.Fatalf("probed too quickly, %9.6f", probeTime.Seconds()) - } - - // Confirm at least one of the peers attempted an indirect probe. - if m2.sequenceNum != 1 && m3.sequenceNum != 1 { - t.Fatalf("bad seqnos %v, %v", m2.sequenceNum, m3.sequenceNum) - } - - // We should have gotten all the nacks, so our score should remain the - // same, since we didn't get a successful probe. - if score := m1.GetHealthScore(); score != 1 { - t.Fatalf("bad: %d", score) - } -} - -func TestMemberList_ProbeNode_Awareness_Improved(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - }) - defer m1.Shutdown() - - m2 := HostMemberlist(addr2.String(), t, nil) - defer m2.Shutdown() - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - - // Start the health in a degraded state. - m1.awareness.ApplyDelta(1) - if score := m1.GetHealthScore(); score != 1 { - t.Fatalf("bad: %d", score) - } - - // Have node m1 probe m2. - n := m1.nodeMap[addr2.String()] - m1.probeNode(n) - - // Node should be reported alive. - if n.State != stateAlive { - t.Fatalf("expect node to be suspect") - } - - // Our score should have improved since we did a good probe. - if score := m1.GetHealthScore(); score != 0 { - t.Fatalf("bad: %d", score) - } -} - -func TestMemberList_ProbeNode_Awareness_MissedNack(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - addr3 := getBindAddr() - addr4 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - ip3 := []byte(addr3) - ip4 := []byte(addr4) - - var probeTimeMax time.Duration - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - probeTimeMax = c.ProbeInterval + 50*time.Millisecond - }) - defer m1.Shutdown() - - m2 := HostMemberlist(addr2.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - }) - defer m2.Shutdown() - - // This will enable nacks by invoking the latest protocol version. - vsn := []uint8{ - ProtocolVersionMin, - ProtocolVersionMax, - m1.config.ProtocolVersion, - m1.config.DelegateProtocolMin, - m1.config.DelegateProtocolMax, - m1.config.DelegateProtocolVersion, - } - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1, Vsn: vsn} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1, Vsn: vsn} - m1.aliveNode(&a2, nil, false) - - // Node 3 and node 4 never get started. - a3 := alive{Node: addr3.String(), Addr: ip3, Port: 7946, Incarnation: 1, Vsn: vsn} - m1.aliveNode(&a3, nil, false) - a4 := alive{Node: addr4.String(), Addr: ip4, Port: 7946, Incarnation: 1, Vsn: vsn} - m1.aliveNode(&a4, nil, false) - - // Make sure health looks good. - if score := m1.GetHealthScore(); score != 0 { - t.Fatalf("bad: %d", score) - } - - // Have node m1 probe m4. - n := m1.nodeMap[addr4.String()] - startProbe := time.Now() - m1.probeNode(n) - probeTime := time.Now().Sub(startProbe) - - // Node should be reported suspect. - if n.State != stateSuspect { - t.Fatalf("expect node to be suspect") - } - - // Make sure we timed out approximately on time. - if probeTime > probeTimeMax { - t.Fatalf("took to long to probe, %9.6f", probeTime.Seconds()) - } - - // We should have gotten dinged for the missed nack. Note that the code under - // test is waiting for probeTimeMax and then doing some other work before it - // updates the awareness, so we need to wait some extra time. Rather than just - // add longer and longer sleeps, we'll retry a few times. - time.Sleep(probeTimeMax) - retry(t, 5, 10*time.Millisecond, func(failf func(string, ...interface{})) { - if score := m1.GetHealthScore(); score != 1 { - failf("expected health score to decrement on missed nack. want %d, "+ - "got: %d", 1, score) - } - }) -} - -func TestMemberList_ProbeNode_Awareness_OldProtocol(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - addr3 := getBindAddr() - addr4 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - ip3 := []byte(addr3) - ip4 := []byte(addr4) - - var probeTimeMax time.Duration - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - probeTimeMax = c.ProbeInterval + 20*time.Millisecond - }) - defer m1.Shutdown() - - m2 := HostMemberlist(addr2.String(), t, nil) - defer m2.Shutdown() - - m3 := HostMemberlist(addr3.String(), t, nil) - defer m3.Shutdown() - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - a3 := alive{Node: addr3.String(), Addr: ip3, Port: 7946, Incarnation: 1} - m1.aliveNode(&a3, nil, false) - - // Node 4 never gets started. - a4 := alive{Node: addr4.String(), Addr: ip4, Port: 7946, Incarnation: 1} - m1.aliveNode(&a4, nil, false) - - // Make sure health looks good. - if score := m1.GetHealthScore(); score != 0 { - t.Fatalf("bad: %d", score) - } - - // Have node m1 probe m4. - n := m1.nodeMap[addr4.String()] - startProbe := time.Now() - m1.probeNode(n) - probeTime := time.Now().Sub(startProbe) - - // Node should be reported suspect. - if n.State != stateSuspect { - t.Fatalf("expect node to be suspect") - } - - // Make sure we timed out approximately on time. - if probeTime > probeTimeMax { - t.Fatalf("took to long to probe, %9.6f", probeTime.Seconds()) - } - - // Confirm at least one of the peers attempted an indirect probe. - time.Sleep(probeTimeMax) - if m2.sequenceNum != 1 && m3.sequenceNum != 1 { - t.Fatalf("bad seqnos %v, %v", m2.sequenceNum, m3.sequenceNum) - } - - // Since we are using the old protocol here, we should have gotten dinged - // for a failed health check. - if score := m1.GetHealthScore(); score != 1 { - t.Fatalf("bad: %d", score) - } -} - -func TestMemberList_ProbeNode_Buddy(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = time.Millisecond - c.ProbeInterval = 10 * time.Millisecond - }) - m2 := HostMemberlist(addr2.String(), t, nil) - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - - m1.aliveNode(&a1, nil, true) - m1.aliveNode(&a2, nil, false) - m2.aliveNode(&a2, nil, true) - - // Force the state to suspect so we piggyback a suspect message with the ping. - // We should see this get refuted later, and the ping will succeed. - n := m1.nodeMap[addr2.String()] - n.State = stateSuspect - m1.probeNode(n) - - // Make sure a ping was sent. - if m1.sequenceNum != 1 { - t.Fatalf("bad seqno %v", m1.sequenceNum) - } - - // Check a broadcast is queued. - if num := m2.broadcasts.NumQueued(); num != 1 { - t.Fatalf("expected only one queued message: %d", num) - } - - // Should be alive msg. - if messageType(m2.broadcasts.bcQueue[0].b.Message()[0]) != aliveMsg { - t.Fatalf("expected queued alive msg") - } -} - -func TestMemberList_ProbeNode(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = time.Millisecond - c.ProbeInterval = 10 * time.Millisecond - }) - _ = HostMemberlist(addr2.String(), t, nil) - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - - n := m1.nodeMap[addr2.String()] - m1.probeNode(n) - - // Should be marked alive - if n.State != stateAlive { - t.Fatalf("Expect node to be alive") - } - - // Should increment seqno - if m1.sequenceNum != 1 { - t.Fatalf("bad seqno %v", m1.sequenceNum) - } -} - -func TestMemberList_Ping(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = time.Millisecond - c.ProbeInterval = 10 * time.Second - }) - _ = HostMemberlist(addr2.String(), t, nil) - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - - // Do a legit ping. - n := m1.nodeMap[addr2.String()] - addr, err := net.ResolveUDPAddr("udp", net.JoinHostPort(addr2.String(), "7946")) - if err != nil { - t.Fatalf("err: %v", err) - } - rtt, err := m1.Ping(n.Name, addr) - if err != nil { - t.Fatalf("err: %v", err) - } - if !(rtt > 0) { - t.Fatalf("bad: %v", rtt) - } - - // This ping has a bad node name so should timeout. - _, err = m1.Ping("bad", addr) - if _, ok := err.(NoPingResponseError); !ok || err == nil { - t.Fatalf("bad: %v", err) - } -} - -func TestMemberList_ResetNodes(t *testing.T) { - m := GetMemberlist(t) - a1 := alive{Node: "test1", Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a1, nil, false) - a2 := alive{Node: "test2", Addr: []byte{127, 0, 0, 2}, Incarnation: 1} - m.aliveNode(&a2, nil, false) - a3 := alive{Node: "test3", Addr: []byte{127, 0, 0, 3}, Incarnation: 1} - m.aliveNode(&a3, nil, false) - d := dead{Node: "test2", Incarnation: 1} - m.deadNode(&d) - - m.config.GossipToTheDeadTime = 100 * time.Millisecond - m.resetNodes() - if len(m.nodes) != 3 { - t.Fatalf("Bad length") - } - if _, ok := m.nodeMap["test2"]; !ok { - t.Fatalf("test2 should not be unmapped") - } - - time.Sleep(200 * time.Millisecond) - m.resetNodes() - if len(m.nodes) != 2 { - t.Fatalf("Bad length") - } - if _, ok := m.nodeMap["test2"]; ok { - t.Fatalf("test2 should be unmapped") - } -} - -func TestMemberList_NextSeq(t *testing.T) { - m := &Memberlist{} - if m.nextSeqNo() != 1 { - t.Fatalf("bad sequence no") - } - if m.nextSeqNo() != 2 { - t.Fatalf("bad sequence no") - } -} - -func TestMemberList_setProbeChannels(t *testing.T) { - m := &Memberlist{ackHandlers: make(map[uint32]*ackHandler)} - - ch := make(chan ackMessage, 1) - m.setProbeChannels(0, ch, nil, 10*time.Millisecond) - - if _, ok := m.ackHandlers[0]; !ok { - t.Fatalf("missing handler") - } - time.Sleep(20 * time.Millisecond) - - if _, ok := m.ackHandlers[0]; ok { - t.Fatalf("non-reaped handler") - } -} - -func TestMemberList_setAckHandler(t *testing.T) { - m := &Memberlist{ackHandlers: make(map[uint32]*ackHandler)} - - f := func([]byte, time.Time) {} - m.setAckHandler(0, f, 10*time.Millisecond) - - if _, ok := m.ackHandlers[0]; !ok { - t.Fatalf("missing handler") - } - time.Sleep(20 * time.Millisecond) - - if _, ok := m.ackHandlers[0]; ok { - t.Fatalf("non-reaped handler") - } -} - -func TestMemberList_invokeAckHandler(t *testing.T) { - m := &Memberlist{ackHandlers: make(map[uint32]*ackHandler)} - - // Does nothing - m.invokeAckHandler(ackResp{}, time.Now()) - - var b bool - f := func(payload []byte, timestamp time.Time) { b = true } - m.setAckHandler(0, f, 10*time.Millisecond) - - // Should set b - m.invokeAckHandler(ackResp{0, nil}, time.Now()) - if !b { - t.Fatalf("b not set") - } - - if _, ok := m.ackHandlers[0]; ok { - t.Fatalf("non-reaped handler") - } -} - -func TestMemberList_invokeAckHandler_Channel_Ack(t *testing.T) { - m := &Memberlist{ackHandlers: make(map[uint32]*ackHandler)} - - ack := ackResp{0, []byte{0, 0, 0}} - - // Does nothing - m.invokeAckHandler(ack, time.Now()) - - ackCh := make(chan ackMessage, 1) - nackCh := make(chan struct{}, 1) - m.setProbeChannels(0, ackCh, nackCh, 10*time.Millisecond) - - // Should send message - m.invokeAckHandler(ack, time.Now()) - - select { - case v := <-ackCh: - if v.Complete != true { - t.Fatalf("Bad value") - } - if bytes.Compare(v.Payload, ack.Payload) != 0 { - t.Fatalf("wrong payload. expected: %v; actual: %v", ack.Payload, v.Payload) - } - - case <-nackCh: - t.Fatalf("should not get a nack") - - default: - t.Fatalf("message not sent") - } - - if _, ok := m.ackHandlers[0]; ok { - t.Fatalf("non-reaped handler") - } -} - -func TestMemberList_invokeAckHandler_Channel_Nack(t *testing.T) { - m := &Memberlist{ackHandlers: make(map[uint32]*ackHandler)} - - nack := nackResp{0} - - // Does nothing. - m.invokeNackHandler(nack) - - ackCh := make(chan ackMessage, 1) - nackCh := make(chan struct{}, 1) - m.setProbeChannels(0, ackCh, nackCh, 10*time.Millisecond) - - // Should send message. - m.invokeNackHandler(nack) - - select { - case <-ackCh: - t.Fatalf("should not get an ack") - - case <-nackCh: - // Good. - - default: - t.Fatalf("message not sent") - } - - // Getting a nack doesn't reap the handler so that we can still forward - // an ack up to the reap time, if we get one. - if _, ok := m.ackHandlers[0]; !ok { - t.Fatalf("handler should not be reaped") - } - - ack := ackResp{0, []byte{0, 0, 0}} - m.invokeAckHandler(ack, time.Now()) - - select { - case v := <-ackCh: - if v.Complete != true { - t.Fatalf("Bad value") - } - if bytes.Compare(v.Payload, ack.Payload) != 0 { - t.Fatalf("wrong payload. expected: %v; actual: %v", ack.Payload, v.Payload) - } - - case <-nackCh: - t.Fatalf("should not get a nack") - - default: - t.Fatalf("message not sent") - } - - if _, ok := m.ackHandlers[0]; ok { - t.Fatalf("non-reaped handler") - } -} - -func TestMemberList_AliveNode_NewNode(t *testing.T) { - ch := make(chan NodeEvent, 1) - m := GetMemberlist(t) - m.config.Events = &ChannelEventDelegate{ch} - - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, false) - - if len(m.nodes) != 1 { - t.Fatalf("should add node") - } - - state, ok := m.nodeMap["test"] - if !ok { - t.Fatalf("should map node") - } - - if state.Incarnation != 1 { - t.Fatalf("bad incarnation") - } - if state.State != stateAlive { - t.Fatalf("bad state") - } - if time.Now().Sub(state.StateChange) > time.Second { - t.Fatalf("bad change delta") - } - - // Check for a join message - select { - case e := <-ch: - if e.Node.Name != "test" { - t.Fatalf("bad node name") - } - default: - t.Fatalf("no join message") - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 1 { - t.Fatalf("expected queued message") - } -} - -func TestMemberList_AliveNode_SuspectNode(t *testing.T) { - ch := make(chan NodeEvent, 1) - m := GetMemberlist(t) - - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, false) - - // Listen only after first join - m.config.Events = &ChannelEventDelegate{ch} - - // Make suspect - state := m.nodeMap["test"] - state.State = stateSuspect - state.StateChange = state.StateChange.Add(-time.Hour) - - // Old incarnation number, should not change - m.aliveNode(&a, nil, false) - if state.State != stateSuspect { - t.Fatalf("update with old incarnation!") - } - - // Should reset to alive now - a.Incarnation = 2 - m.aliveNode(&a, nil, false) - if state.State != stateAlive { - t.Fatalf("no update with new incarnation!") - } - - if time.Now().Sub(state.StateChange) > time.Second { - t.Fatalf("bad change delta") - } - - // Check for a no join message - select { - case <-ch: - t.Fatalf("got bad join message") - default: - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 1 { - t.Fatalf("expected queued message") - } -} - -func TestMemberList_AliveNode_Idempotent(t *testing.T) { - ch := make(chan NodeEvent, 1) - m := GetMemberlist(t) - - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, false) - - // Listen only after first join - m.config.Events = &ChannelEventDelegate{ch} - - // Make suspect - state := m.nodeMap["test"] - stateTime := state.StateChange - - // Should reset to alive now - a.Incarnation = 2 - m.aliveNode(&a, nil, false) - if state.State != stateAlive { - t.Fatalf("non idempotent") - } - - if stateTime != state.StateChange { - t.Fatalf("should not change state") - } - - // Check for a no join message - select { - case <-ch: - t.Fatalf("got bad join message") - default: - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 1 { - t.Fatalf("expected only one queued message") - } -} - -// Serf Bug: GH-58, Meta data does not update -func TestMemberList_AliveNode_ChangeMeta(t *testing.T) { - ch := make(chan NodeEvent, 1) - m := GetMemberlist(t) - - a := alive{ - Node: "test", - Addr: []byte{127, 0, 0, 1}, - Meta: []byte("val1"), - Incarnation: 1} - m.aliveNode(&a, nil, false) - - // Listen only after first join - m.config.Events = &ChannelEventDelegate{ch} - - // Make suspect - state := m.nodeMap["test"] - - // Should reset to alive now - a.Incarnation = 2 - a.Meta = []byte("val2") - m.aliveNode(&a, nil, false) - - // Check updates - if bytes.Compare(state.Meta, a.Meta) != 0 { - t.Fatalf("meta did not update") - } - - // Check for a NotifyUpdate - select { - case e := <-ch: - if e.Event != NodeUpdate { - t.Fatalf("bad event: %v", e) - } - if e.Node != &state.Node { - t.Fatalf("bad event: %v", e) - } - if bytes.Compare(e.Node.Meta, a.Meta) != 0 { - t.Fatalf("meta did not update") - } - default: - t.Fatalf("missing event!") - } - -} - -func TestMemberList_AliveNode_Refute(t *testing.T) { - m := GetMemberlist(t) - a := alive{Node: m.config.Name, Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, true) - - // Clear queue - m.broadcasts.Reset() - - // Conflicting alive - s := alive{ - Node: m.config.Name, - Addr: []byte{127, 0, 0, 1}, - Incarnation: 2, - Meta: []byte("foo"), - } - m.aliveNode(&s, nil, false) - - state := m.nodeMap[m.config.Name] - if state.State != stateAlive { - t.Fatalf("should still be alive") - } - if state.Meta != nil { - t.Fatalf("meta should still be nil") - } - - // Check a broad cast is queued - if num := m.broadcasts.NumQueued(); num != 1 { - t.Fatalf("expected only one queued message: %d", - num) - } - - // Should be alive mesg - if messageType(m.broadcasts.bcQueue[0].b.Message()[0]) != aliveMsg { - t.Fatalf("expected queued alive msg") - } -} - -func TestMemberList_SuspectNode_NoNode(t *testing.T) { - m := GetMemberlist(t) - s := suspect{Node: "test", Incarnation: 1} - m.suspectNode(&s) - if len(m.nodes) != 0 { - t.Fatalf("don't expect nodes") - } -} - -func TestMemberList_SuspectNode(t *testing.T) { - m := GetMemberlist(t) - m.config.ProbeInterval = time.Millisecond - m.config.SuspicionMult = 1 - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, false) - - state := m.nodeMap["test"] - state.StateChange = state.StateChange.Add(-time.Hour) - - s := suspect{Node: "test", Incarnation: 1} - m.suspectNode(&s) - - if state.State != stateSuspect { - t.Fatalf("Bad state") - } - - change := state.StateChange - if time.Now().Sub(change) > time.Second { - t.Fatalf("bad change delta") - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 1 { - t.Fatalf("expected only one queued message") - } - - // Check its a suspect message - if messageType(m.broadcasts.bcQueue[0].b.Message()[0]) != suspectMsg { - t.Fatalf("expected queued suspect msg") - } - - // Wait for the timeout - time.Sleep(10 * time.Millisecond) - - if state.State != stateDead { - t.Fatalf("Bad state") - } - - if time.Now().Sub(state.StateChange) > time.Second { - t.Fatalf("bad change delta") - } - if !state.StateChange.After(change) { - t.Fatalf("should increment time") - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 1 { - t.Fatalf("expected only one queued message") - } - - // Check its a suspect message - if messageType(m.broadcasts.bcQueue[0].b.Message()[0]) != deadMsg { - t.Fatalf("expected queued dead msg") - } -} - -func TestMemberList_SuspectNode_DoubleSuspect(t *testing.T) { - m := GetMemberlist(t) - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, false) - - state := m.nodeMap["test"] - state.StateChange = state.StateChange.Add(-time.Hour) - - s := suspect{Node: "test", Incarnation: 1} - m.suspectNode(&s) - - if state.State != stateSuspect { - t.Fatalf("Bad state") - } - - change := state.StateChange - if time.Now().Sub(change) > time.Second { - t.Fatalf("bad change delta") - } - - // clear the broadcast queue - m.broadcasts.Reset() - - // Suspect again - m.suspectNode(&s) - - if state.StateChange != change { - t.Fatalf("unexpected state change") - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 0 { - t.Fatalf("expected only one queued message") - } - -} - -func TestMemberList_SuspectNode_OldSuspect(t *testing.T) { - m := GetMemberlist(t) - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 10} - m.aliveNode(&a, nil, false) - - state := m.nodeMap["test"] - state.StateChange = state.StateChange.Add(-time.Hour) - - // Clear queue - m.broadcasts.Reset() - - s := suspect{Node: "test", Incarnation: 1} - m.suspectNode(&s) - - if state.State != stateAlive { - t.Fatalf("Bad state") - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 0 { - t.Fatalf("expected only one queued message") - } -} - -func TestMemberList_SuspectNode_Refute(t *testing.T) { - m := GetMemberlist(t) - a := alive{Node: m.config.Name, Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, true) - - // Clear queue - m.broadcasts.Reset() - - // Make sure health is in a good state - if score := m.GetHealthScore(); score != 0 { - t.Fatalf("bad: %d", score) - } - - s := suspect{Node: m.config.Name, Incarnation: 1} - m.suspectNode(&s) - - state := m.nodeMap[m.config.Name] - if state.State != stateAlive { - t.Fatalf("should still be alive") - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 1 { - t.Fatalf("expected only one queued message") - } - - // Should be alive mesg - if messageType(m.broadcasts.bcQueue[0].b.Message()[0]) != aliveMsg { - t.Fatalf("expected queued alive msg") - } - - // Health should have been dinged - if score := m.GetHealthScore(); score != 1 { - t.Fatalf("bad: %d", score) - } -} - -func TestMemberList_DeadNode_NoNode(t *testing.T) { - m := GetMemberlist(t) - d := dead{Node: "test", Incarnation: 1} - m.deadNode(&d) - if len(m.nodes) != 0 { - t.Fatalf("don't expect nodes") - } -} - -func TestMemberList_DeadNode(t *testing.T) { - ch := make(chan NodeEvent, 1) - m := GetMemberlist(t) - m.config.Events = &ChannelEventDelegate{ch} - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, false) - - // Read the join event - <-ch - - state := m.nodeMap["test"] - state.StateChange = state.StateChange.Add(-time.Hour) - - d := dead{Node: "test", Incarnation: 1} - m.deadNode(&d) - - if state.State != stateDead { - t.Fatalf("Bad state") - } - - change := state.StateChange - if time.Now().Sub(change) > time.Second { - t.Fatalf("bad change delta") - } - - select { - case leave := <-ch: - if leave.Event != NodeLeave || leave.Node.Name != "test" { - t.Fatalf("bad node name") - } - default: - t.Fatalf("no leave message") - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 1 { - t.Fatalf("expected only one queued message") - } - - // Check its a suspect message - if messageType(m.broadcasts.bcQueue[0].b.Message()[0]) != deadMsg { - t.Fatalf("expected queued dead msg") - } -} - -func TestMemberList_DeadNode_Double(t *testing.T) { - ch := make(chan NodeEvent, 1) - m := GetMemberlist(t) - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, false) - - state := m.nodeMap["test"] - state.StateChange = state.StateChange.Add(-time.Hour) - - d := dead{Node: "test", Incarnation: 1} - m.deadNode(&d) - - // Clear queue - m.broadcasts.Reset() - - // Notify after the first dead - m.config.Events = &ChannelEventDelegate{ch} - - // Should do nothing - d.Incarnation = 2 - m.deadNode(&d) - - select { - case <-ch: - t.Fatalf("should not get leave") - default: - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 0 { - t.Fatalf("expected only one queued message") - } -} - -func TestMemberList_DeadNode_OldDead(t *testing.T) { - m := GetMemberlist(t) - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 10} - m.aliveNode(&a, nil, false) - - state := m.nodeMap["test"] - state.StateChange = state.StateChange.Add(-time.Hour) - - d := dead{Node: "test", Incarnation: 1} - m.deadNode(&d) - - if state.State != stateAlive { - t.Fatalf("Bad state") - } -} - -func TestMemberList_DeadNode_AliveReplay(t *testing.T) { - m := GetMemberlist(t) - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 10} - m.aliveNode(&a, nil, false) - - d := dead{Node: "test", Incarnation: 10} - m.deadNode(&d) - - // Replay alive at same incarnation - m.aliveNode(&a, nil, false) - - // Should remain dead - state, ok := m.nodeMap["test"] - if ok && state.State != stateDead { - t.Fatalf("Bad state") - } -} - -func TestMemberList_DeadNode_Refute(t *testing.T) { - m := GetMemberlist(t) - a := alive{Node: m.config.Name, Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, true) - - // Clear queue - m.broadcasts.Reset() - - // Make sure health is in a good state - if score := m.GetHealthScore(); score != 0 { - t.Fatalf("bad: %d", score) - } - - d := dead{Node: m.config.Name, Incarnation: 1} - m.deadNode(&d) - - state := m.nodeMap[m.config.Name] - if state.State != stateAlive { - t.Fatalf("should still be alive") - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 1 { - t.Fatalf("expected only one queued message") - } - - // Should be alive mesg - if messageType(m.broadcasts.bcQueue[0].b.Message()[0]) != aliveMsg { - t.Fatalf("expected queued alive msg") - } - - // We should have been dinged - if score := m.GetHealthScore(); score != 1 { - t.Fatalf("bad: %d", score) - } -} - -func TestMemberList_MergeState(t *testing.T) { - m := GetMemberlist(t) - a1 := alive{Node: "test1", Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a1, nil, false) - a2 := alive{Node: "test2", Addr: []byte{127, 0, 0, 2}, Incarnation: 1} - m.aliveNode(&a2, nil, false) - a3 := alive{Node: "test3", Addr: []byte{127, 0, 0, 3}, Incarnation: 1} - m.aliveNode(&a3, nil, false) - - s := suspect{Node: "test1", Incarnation: 1} - m.suspectNode(&s) - - remote := []pushNodeState{ - pushNodeState{ - Name: "test1", - Addr: []byte{127, 0, 0, 1}, - Incarnation: 2, - State: stateAlive, - }, - pushNodeState{ - Name: "test2", - Addr: []byte{127, 0, 0, 2}, - Incarnation: 1, - State: stateSuspect, - }, - pushNodeState{ - Name: "test3", - Addr: []byte{127, 0, 0, 3}, - Incarnation: 1, - State: stateDead, - }, - pushNodeState{ - Name: "test4", - Addr: []byte{127, 0, 0, 4}, - Incarnation: 2, - State: stateAlive, - }, - } - - // Listen for changes - eventCh := make(chan NodeEvent, 1) - m.config.Events = &ChannelEventDelegate{eventCh} - - // Merge remote state - m.mergeState(remote) - - // Check the states - state := m.nodeMap["test1"] - if state.State != stateAlive || state.Incarnation != 2 { - t.Fatalf("Bad state %v", state) - } - - state = m.nodeMap["test2"] - if state.State != stateSuspect || state.Incarnation != 1 { - t.Fatalf("Bad state %v", state) - } - - state = m.nodeMap["test3"] - if state.State != stateSuspect { - t.Fatalf("Bad state %v", state) - } - - state = m.nodeMap["test4"] - if state.State != stateAlive || state.Incarnation != 2 { - t.Fatalf("Bad state %v", state) - } - - // Check the channels - select { - case e := <-eventCh: - if e.Event != NodeJoin || e.Node.Name != "test4" { - t.Fatalf("bad node %v", e) - } - default: - t.Fatalf("Expect join") - } - - select { - case e := <-eventCh: - t.Fatalf("Unexpect event: %v", e) - default: - } -} - -func TestMemberlist_Gossip(t *testing.T) { - ch := make(chan NodeEvent, 3) - - addr1 := getBindAddr() - addr2 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.GossipInterval = time.Millisecond - }) - m2 := HostMemberlist(addr2.String(), t, func(c *Config) { - c.Events = &ChannelEventDelegate{ch} - c.GossipInterval = time.Millisecond - }) - - defer m1.Shutdown() - defer m2.Shutdown() - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - a3 := alive{Node: "172.0.0.1", Addr: []byte{172, 0, 0, 1}, Incarnation: 1} - m1.aliveNode(&a3, nil, false) - - // Gossip should send all this to m2. Retry a few times because it's UDP and - // timing and stuff makes this flaky without. - retry(t, 5, 10*time.Millisecond, func(failf func(string, ...interface{})) { - m1.gossip() - - time.Sleep(3 * time.Millisecond) - - if len(ch) < 3 { - failf("expected 3 messages from gossip") - } - }) -} - -func retry(t *testing.T, n int, w time.Duration, fn func(func(string, ...interface{}))) { - t.Helper() - for try := 1; try <= n; try++ { - failed := false - failFormat := "" - failArgs := []interface{}{} - failf := func(format string, args ...interface{}) { - failed = true - failFormat = format - failArgs = args - } - - fn(failf) - - if !failed { - return - } - if try == n { - t.Fatalf(failFormat, failArgs...) - } - time.Sleep(w) - } -} - -func TestMemberlist_GossipToDead(t *testing.T) { - ch := make(chan NodeEvent, 2) - - addr1 := getBindAddr() - addr2 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.GossipInterval = time.Millisecond - c.GossipToTheDeadTime = 100 * time.Millisecond - }) - m2 := HostMemberlist(addr2.String(), t, func(c *Config) { - c.Events = &ChannelEventDelegate{ch} - }) - - defer m1.Shutdown() - defer m2.Shutdown() - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - - // Shouldn't send anything to m2 here, node has been dead for 2x the GossipToTheDeadTime - m1.nodeMap[addr2.String()].State = stateDead - m1.nodeMap[addr2.String()].StateChange = time.Now().Add(-200 * time.Millisecond) - m1.gossip() - - select { - case <-ch: - t.Fatalf("shouldn't get gossip") - case <-time.After(50 * time.Millisecond): - } - - // Should gossip to m2 because its state has changed within GossipToTheDeadTime - m1.nodeMap[addr2.String()].StateChange = time.Now().Add(-20 * time.Millisecond) - - retry(t, 5, 10*time.Millisecond, func(failf func(string, ...interface{})) { - m1.gossip() - - time.Sleep(3 * time.Millisecond) - - if len(ch) < 2 { - failf("expected 2 messages from gossip") - } - }) -} - -func TestMemberlist_PushPull(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - - ch := make(chan NodeEvent, 3) - - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.GossipInterval = 10 * time.Second - c.PushPullInterval = time.Millisecond - }) - m2 := HostMemberlist(addr2.String(), t, func(c *Config) { - c.GossipInterval = 10 * time.Second - c.Events = &ChannelEventDelegate{ch} - }) - - defer m1.Shutdown() - defer m2.Shutdown() - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - - // Gossip should send all this to m2. It's UDP though so retry a few times - retry(t, 5, 10*time.Millisecond, func(failf func(string, ...interface{})) { - m1.pushPull() - - time.Sleep(3 * time.Millisecond) - - if len(ch) < 2 { - failf("expected 2 messages from pushPull") - } - }) -} - -func TestVerifyProtocol(t *testing.T) { - cases := []struct { - Anodes [][3]uint8 - Bnodes [][3]uint8 - expected bool - }{ - // Both running identical everything - { - Anodes: [][3]uint8{ - {0, 0, 0}, - }, - Bnodes: [][3]uint8{ - {0, 0, 0}, - }, - expected: true, - }, - - // One can understand newer, but speaking same protocol - { - Anodes: [][3]uint8{ - {0, 0, 0}, - }, - Bnodes: [][3]uint8{ - {0, 1, 0}, - }, - expected: true, - }, - - // One is speaking outside the range - { - Anodes: [][3]uint8{ - {0, 0, 0}, - }, - Bnodes: [][3]uint8{ - {1, 1, 1}, - }, - expected: false, - }, - - // Transitively outside the range - { - Anodes: [][3]uint8{ - {0, 1, 0}, - {0, 2, 1}, - }, - Bnodes: [][3]uint8{ - {1, 3, 1}, - }, - expected: false, - }, - - // Multi-node - { - Anodes: [][3]uint8{ - {0, 3, 2}, - {0, 2, 0}, - }, - Bnodes: [][3]uint8{ - {0, 2, 1}, - {0, 5, 0}, - }, - expected: true, - }, - } - - for _, tc := range cases { - aCore := make([][6]uint8, len(tc.Anodes)) - aApp := make([][6]uint8, len(tc.Anodes)) - for i, n := range tc.Anodes { - aCore[i] = [6]uint8{n[0], n[1], n[2], 0, 0, 0} - aApp[i] = [6]uint8{0, 0, 0, n[0], n[1], n[2]} - } - - bCore := make([][6]uint8, len(tc.Bnodes)) - bApp := make([][6]uint8, len(tc.Bnodes)) - for i, n := range tc.Bnodes { - bCore[i] = [6]uint8{n[0], n[1], n[2], 0, 0, 0} - bApp[i] = [6]uint8{0, 0, 0, n[0], n[1], n[2]} - } - - // Test core protocol verification - testVerifyProtocolSingle(t, aCore, bCore, tc.expected) - testVerifyProtocolSingle(t, bCore, aCore, tc.expected) - - // Test app protocol verification - testVerifyProtocolSingle(t, aApp, bApp, tc.expected) - testVerifyProtocolSingle(t, bApp, aApp, tc.expected) - } -} - -func testVerifyProtocolSingle(t *testing.T, A [][6]uint8, B [][6]uint8, expect bool) { - m := GetMemberlist(t) - defer m.Shutdown() - - m.nodes = make([]*nodeState, len(A)) - for i, n := range A { - m.nodes[i] = &nodeState{ - Node: Node{ - PMin: n[0], - PMax: n[1], - PCur: n[2], - DMin: n[3], - DMax: n[4], - DCur: n[5], - }, - } - } - - remote := make([]pushNodeState, len(B)) - for i, n := range B { - remote[i] = pushNodeState{ - Name: fmt.Sprintf("node %d", i), - Vsn: []uint8{n[0], n[1], n[2], n[3], n[4], n[5]}, - } - } - - err := m.verifyProtocol(remote) - if (err == nil) != expect { - t.Fatalf("bad:\nA: %v\nB: %v\nErr: %s", A, B, err) - } -} diff --git a/vendor/github.com/hashicorp/memberlist/suspicion_test.go b/vendor/github.com/hashicorp/memberlist/suspicion_test.go deleted file mode 100644 index 1b5ca8a5a..000000000 --- a/vendor/github.com/hashicorp/memberlist/suspicion_test.go +++ /dev/null @@ -1,198 +0,0 @@ -package memberlist - -import ( - "testing" - "time" -) - -func TestSuspicion_remainingSuspicionTime(t *testing.T) { - cases := []struct { - n int32 - k int32 - elapsed time.Duration - min time.Duration - max time.Duration - expected time.Duration - }{ - {0, 3, 0, 2 * time.Second, 30 * time.Second, 30 * time.Second}, - {1, 3, 2 * time.Second, 2 * time.Second, 30 * time.Second, 14 * time.Second}, - {2, 3, 3 * time.Second, 2 * time.Second, 30 * time.Second, 4810 * time.Millisecond}, - {3, 3, 4 * time.Second, 2 * time.Second, 30 * time.Second, -2 * time.Second}, - {4, 3, 5 * time.Second, 2 * time.Second, 30 * time.Second, -3 * time.Second}, - {5, 3, 10 * time.Second, 2 * time.Second, 30 * time.Second, -8 * time.Second}, - } - for i, c := range cases { - remaining := remainingSuspicionTime(c.n, c.k, c.elapsed, c.min, c.max) - if remaining != c.expected { - t.Errorf("case %d: remaining %9.6f != expected %9.6f", i, remaining.Seconds(), c.expected.Seconds()) - } - } -} - -func TestSuspicion_Timer(t *testing.T) { - const k = 3 - const min = 500 * time.Millisecond - const max = 2 * time.Second - - type pair struct { - from string - newInfo bool - } - cases := []struct { - numConfirmations int - from string - confirmations []pair - expected time.Duration - }{ - { - 0, - "me", - []pair{}, - max, - }, - { - 1, - "me", - []pair{ - pair{"me", false}, - pair{"foo", true}, - }, - 1250 * time.Millisecond, - }, - { - 1, - "me", - []pair{ - pair{"me", false}, - pair{"foo", true}, - pair{"foo", false}, - pair{"foo", false}, - }, - 1250 * time.Millisecond, - }, - { - 2, - "me", - []pair{ - pair{"me", false}, - pair{"foo", true}, - pair{"bar", true}, - }, - 810 * time.Millisecond, - }, - { - 3, - "me", - []pair{ - pair{"me", false}, - pair{"foo", true}, - pair{"bar", true}, - pair{"baz", true}, - }, - min, - }, - { - 3, - "me", - []pair{ - pair{"me", false}, - pair{"foo", true}, - pair{"bar", true}, - pair{"baz", true}, - pair{"zoo", false}, - }, - min, - }, - } - for i, c := range cases { - ch := make(chan time.Duration, 1) - start := time.Now() - f := func(numConfirmations int) { - if numConfirmations != c.numConfirmations { - t.Errorf("case %d: bad %d != %d", i, numConfirmations, c.numConfirmations) - } - - ch <- time.Now().Sub(start) - } - - // Create the timer and add the requested confirmations. Wait - // the fudge amount to help make sure we calculate the timeout - // overall, and don't accumulate extra time. - s := newSuspicion(c.from, k, min, max, f) - fudge := 25 * time.Millisecond - for _, p := range c.confirmations { - time.Sleep(fudge) - if s.Confirm(p.from) != p.newInfo { - t.Fatalf("case %d: newInfo mismatch for %s", i, p.from) - } - } - - // Wait until right before the timeout and make sure the - // timer hasn't fired. - already := time.Duration(len(c.confirmations)) * fudge - time.Sleep(c.expected - already - fudge) - select { - case d := <-ch: - t.Fatalf("case %d: should not have fired (%9.6f)", i, d.Seconds()) - default: - } - - // Wait through the timeout and a little after and make sure it - // fires. - time.Sleep(2 * fudge) - select { - case <-ch: - default: - t.Fatalf("case %d: should have fired", i) - } - - // Confirm after to make sure it handles a negative remaining - // time correctly and doesn't fire again. - s.Confirm("late") - time.Sleep(c.expected + 2*fudge) - select { - case d := <-ch: - t.Fatalf("case %d: should not have fired (%9.6f)", i, d.Seconds()) - default: - } - } -} - -func TestSuspicion_Timer_ZeroK(t *testing.T) { - ch := make(chan struct{}, 1) - f := func(int) { - ch <- struct{}{} - } - - // This should select the min time since there are no expected - // confirmations to accelerate the timer. - s := newSuspicion("me", 0, 25*time.Millisecond, 30*time.Second, f) - if s.Confirm("foo") { - t.Fatalf("should not provide new information") - } - - select { - case <-ch: - case <-time.After(50 * time.Millisecond): - t.Fatalf("should have fired") - } -} - -func TestSuspicion_Timer_Immediate(t *testing.T) { - ch := make(chan struct{}, 1) - f := func(int) { - ch <- struct{}{} - } - - // This should underflow the timeout and fire immediately. - s := newSuspicion("me", 1, 100*time.Millisecond, 30*time.Second, f) - time.Sleep(200 * time.Millisecond) - s.Confirm("foo") - - // Wait a little while since the function gets called in a goroutine. - select { - case <-ch: - case <-time.After(25 * time.Millisecond): - t.Fatalf("should have fired") - } -} diff --git a/vendor/github.com/hashicorp/memberlist/tag.sh b/vendor/github.com/hashicorp/memberlist/tag.sh old mode 100755 new mode 100644 diff --git a/vendor/github.com/hashicorp/memberlist/transport_test.go b/vendor/github.com/hashicorp/memberlist/transport_test.go deleted file mode 100644 index 32dc4522b..000000000 --- a/vendor/github.com/hashicorp/memberlist/transport_test.go +++ /dev/null @@ -1,129 +0,0 @@ -package memberlist - -import ( - "testing" - "time" - - "github.com/stretchr/testify/require" -) - -func TestTransport_Join(t *testing.T) { - net := &MockNetwork{} - - t1 := net.NewTransport() - - c1 := DefaultLANConfig() - c1.Name = "node1" - c1.Transport = t1 - m1, err := Create(c1) - if err != nil { - t.Fatalf("err: %v", err) - } - m1.setAlive() - m1.schedule() - defer m1.Shutdown() - - c2 := DefaultLANConfig() - c2.Name = "node2" - c2.Transport = net.NewTransport() - m2, err := Create(c2) - if err != nil { - t.Fatalf("err: %v", err) - } - m2.setAlive() - m2.schedule() - defer m2.Shutdown() - - num, err := m2.Join([]string{t1.addr.String()}) - if num != 1 { - t.Fatalf("bad: %d", num) - } - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(m2.Members()) != 2 { - t.Fatalf("bad: %v", m2.Members()) - } - if m2.estNumNodes() != 2 { - t.Fatalf("bad: %v", m2.Members()) - } - -} - -func TestTransport_Send(t *testing.T) { - net := &MockNetwork{} - - t1 := net.NewTransport() - d1 := &MockDelegate{} - - c1 := DefaultLANConfig() - c1.Name = "node1" - c1.Transport = t1 - c1.Delegate = d1 - m1, err := Create(c1) - if err != nil { - t.Fatalf("err: %v", err) - } - m1.setAlive() - m1.schedule() - defer m1.Shutdown() - - c2 := DefaultLANConfig() - c2.Name = "node2" - c2.Transport = net.NewTransport() - m2, err := Create(c2) - if err != nil { - t.Fatalf("err: %v", err) - } - m2.setAlive() - m2.schedule() - defer m2.Shutdown() - - num, err := m2.Join([]string{t1.addr.String()}) - if num != 1 { - t.Fatalf("bad: %d", num) - } - if err != nil { - t.Fatalf("err: %v", err) - } - - if err := m2.SendTo(t1.addr, []byte("SendTo")); err != nil { - t.Fatalf("err: %v", err) - } - - var n1 *Node - for _, n := range m2.Members() { - if n.Name == c1.Name { - n1 = n - break - } - } - if n1 == nil { - t.Fatalf("bad") - } - - if err := m2.SendToUDP(n1, []byte("SendToUDP")); err != nil { - t.Fatalf("err: %v", err) - } - if err := m2.SendToTCP(n1, []byte("SendToTCP")); err != nil { - t.Fatalf("err: %v", err) - } - if err := m2.SendBestEffort(n1, []byte("SendBestEffort")); err != nil { - t.Fatalf("err: %v", err) - } - if err := m2.SendReliable(n1, []byte("SendReliable")); err != nil { - t.Fatalf("err: %v", err) - } - time.Sleep(100 * time.Millisecond) - - expected := []string{"SendTo", "SendToUDP", "SendToTCP", "SendBestEffort", "SendReliable"} - - received := make([]string, len(d1.msgs)) - for i, bs := range d1.msgs { - received[i] = string(bs) - } - // Some of these are UDP so often get re-ordered making the test flaky if we - // assert send ordering. Sort both slices to be tolerant of re-ordering. - require.ElementsMatch(t, expected, received) -} diff --git a/vendor/github.com/hashicorp/memberlist/util.go b/vendor/github.com/hashicorp/memberlist/util.go index e2381a698..1e582a8a1 100644 --- a/vendor/github.com/hashicorp/memberlist/util.go +++ b/vendor/github.com/hashicorp/memberlist/util.go @@ -78,10 +78,9 @@ func retransmitLimit(retransmitMult, n int) int { // shuffleNodes randomly shuffles the input nodes using the Fisher-Yates shuffle func shuffleNodes(nodes []*nodeState) { n := len(nodes) - for i := n - 1; i > 0; i-- { - j := rand.Intn(i + 1) + rand.Shuffle(n, func(i, j int) { nodes[i], nodes[j] = nodes[j], nodes[i] - } + }) } // pushPushScale is used to scale the time interval at which push/pull diff --git a/vendor/github.com/hashicorp/memberlist/util_test.go b/vendor/github.com/hashicorp/memberlist/util_test.go deleted file mode 100644 index b7f2b4199..000000000 --- a/vendor/github.com/hashicorp/memberlist/util_test.go +++ /dev/null @@ -1,358 +0,0 @@ -package memberlist - -import ( - "fmt" - "reflect" - "testing" - "time" -) - -func TestUtil_PortFunctions(t *testing.T) { - tests := []struct { - addr string - hasPort bool - ensurePort string - }{ - {"1.2.3.4", false, "1.2.3.4:8301"}, - {"1.2.3.4:1234", true, "1.2.3.4:1234"}, - {"2600:1f14:e22:1501:f9a:2e0c:a167:67e8", false, "[2600:1f14:e22:1501:f9a:2e0c:a167:67e8]:8301"}, - {"[2600:1f14:e22:1501:f9a:2e0c:a167:67e8]", false, "[2600:1f14:e22:1501:f9a:2e0c:a167:67e8]:8301"}, - {"[2600:1f14:e22:1501:f9a:2e0c:a167:67e8]:1234", true, "[2600:1f14:e22:1501:f9a:2e0c:a167:67e8]:1234"}, - {"localhost", false, "localhost:8301"}, - {"localhost:1234", true, "localhost:1234"}, - {"hashicorp.com", false, "hashicorp.com:8301"}, - {"hashicorp.com:1234", true, "hashicorp.com:1234"}, - } - for _, tt := range tests { - t.Run(tt.addr, func(t *testing.T) { - if got, want := hasPort(tt.addr), tt.hasPort; got != want { - t.Fatalf("got %v want %v", got, want) - } - if got, want := ensurePort(tt.addr, 8301), tt.ensurePort; got != want { - t.Fatalf("got %v want %v", got, want) - } - }) - } -} - -func TestEncodeDecode(t *testing.T) { - msg := &ping{SeqNo: 100} - buf, err := encode(pingMsg, msg) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - var out ping - if err := decode(buf.Bytes()[1:], &out); err != nil { - t.Fatalf("unexpected err: %s", err) - } - if msg.SeqNo != out.SeqNo { - t.Fatalf("bad sequence no") - } -} - -func TestRandomOffset(t *testing.T) { - vals := make(map[int]struct{}) - for i := 0; i < 100; i++ { - offset := randomOffset(2 << 30) - if _, ok := vals[offset]; ok { - t.Fatalf("got collision") - } - vals[offset] = struct{}{} - } -} - -func TestRandomOffset_Zero(t *testing.T) { - offset := randomOffset(0) - if offset != 0 { - t.Fatalf("bad offset") - } -} - -func TestSuspicionTimeout(t *testing.T) { - timeouts := map[int]time.Duration{ - 5: 1000 * time.Millisecond, - 10: 1000 * time.Millisecond, - 50: 1698 * time.Millisecond, - 100: 2000 * time.Millisecond, - 500: 2698 * time.Millisecond, - 1000: 3000 * time.Millisecond, - } - for n, expected := range timeouts { - timeout := suspicionTimeout(3, n, time.Second) / 3 - if timeout != expected { - t.Fatalf("bad: %v, %v", expected, timeout) - } - } -} - -func TestRetransmitLimit(t *testing.T) { - lim := retransmitLimit(3, 0) - if lim != 0 { - t.Fatalf("bad val %v", lim) - } - lim = retransmitLimit(3, 1) - if lim != 3 { - t.Fatalf("bad val %v", lim) - } - lim = retransmitLimit(3, 99) - if lim != 6 { - t.Fatalf("bad val %v", lim) - } -} - -func TestShuffleNodes(t *testing.T) { - orig := []*nodeState{ - &nodeState{ - State: stateDead, - }, - &nodeState{ - State: stateAlive, - }, - &nodeState{ - State: stateAlive, - }, - &nodeState{ - State: stateDead, - }, - &nodeState{ - State: stateAlive, - }, - &nodeState{ - State: stateAlive, - }, - &nodeState{ - State: stateDead, - }, - &nodeState{ - State: stateAlive, - }, - } - nodes := make([]*nodeState, len(orig)) - copy(nodes[:], orig[:]) - - if !reflect.DeepEqual(nodes, orig) { - t.Fatalf("should match") - } - - shuffleNodes(nodes) - - if reflect.DeepEqual(nodes, orig) { - t.Fatalf("should not match") - } -} - -func TestPushPullScale(t *testing.T) { - sec := time.Second - for i := 0; i <= 32; i++ { - if s := pushPullScale(sec, i); s != sec { - t.Fatalf("Bad time scale: %v", s) - } - } - for i := 33; i <= 64; i++ { - if s := pushPullScale(sec, i); s != 2*sec { - t.Fatalf("Bad time scale: %v", s) - } - } - for i := 65; i <= 128; i++ { - if s := pushPullScale(sec, i); s != 3*sec { - t.Fatalf("Bad time scale: %v", s) - } - } -} - -func TestMoveDeadNodes(t *testing.T) { - nodes := []*nodeState{ - &nodeState{ - State: stateDead, - StateChange: time.Now().Add(-20 * time.Second), - }, - &nodeState{ - State: stateAlive, - StateChange: time.Now().Add(-20 * time.Second), - }, - // This dead node should not be moved, as its state changed - // less than the specified GossipToTheDead time ago - &nodeState{ - State: stateDead, - StateChange: time.Now().Add(-10 * time.Second), - }, - &nodeState{ - State: stateAlive, - StateChange: time.Now().Add(-20 * time.Second), - }, - &nodeState{ - State: stateDead, - StateChange: time.Now().Add(-20 * time.Second), - }, - &nodeState{ - State: stateAlive, - StateChange: time.Now().Add(-20 * time.Second), - }, - } - - idx := moveDeadNodes(nodes, (15 * time.Second)) - if idx != 4 { - t.Fatalf("bad index") - } - for i := 0; i < idx; i++ { - switch i { - case 2: - // Recently dead node remains at index 2, - // since nodes are swapped out to move to end. - if nodes[i].State != stateDead { - t.Fatalf("Bad state %d", i) - } - default: - if nodes[i].State != stateAlive { - t.Fatalf("Bad state %d", i) - } - } - } - for i := idx; i < len(nodes); i++ { - if nodes[i].State != stateDead { - t.Fatalf("Bad state %d", i) - } - } -} - -func TestKRandomNodes(t *testing.T) { - nodes := []*nodeState{} - for i := 0; i < 90; i++ { - // Half the nodes are in a bad state - state := stateAlive - switch i % 3 { - case 0: - state = stateAlive - case 1: - state = stateSuspect - case 2: - state = stateDead - } - nodes = append(nodes, &nodeState{ - Node: Node{ - Name: fmt.Sprintf("test%d", i), - }, - State: state, - }) - } - - filterFunc := func(n *nodeState) bool { - if n.Name == "test0" || n.State != stateAlive { - return true - } - return false - } - - s1 := kRandomNodes(3, nodes, filterFunc) - s2 := kRandomNodes(3, nodes, filterFunc) - s3 := kRandomNodes(3, nodes, filterFunc) - - if reflect.DeepEqual(s1, s2) { - t.Fatalf("unexpected equal") - } - if reflect.DeepEqual(s1, s3) { - t.Fatalf("unexpected equal") - } - if reflect.DeepEqual(s2, s3) { - t.Fatalf("unexpected equal") - } - - for _, s := range [][]*nodeState{s1, s2, s3} { - if len(s) != 3 { - t.Fatalf("bad len") - } - for _, n := range s { - if n.Name == "test0" { - t.Fatalf("Bad name") - } - if n.State != stateAlive { - t.Fatalf("Bad state") - } - } - } -} - -func TestMakeCompoundMessage(t *testing.T) { - msg := &ping{SeqNo: 100} - buf, err := encode(pingMsg, msg) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - msgs := [][]byte{buf.Bytes(), buf.Bytes(), buf.Bytes()} - compound := makeCompoundMessage(msgs) - - if compound.Len() != 3*buf.Len()+3*compoundOverhead+compoundHeaderOverhead { - t.Fatalf("bad len") - } -} - -func TestDecodeCompoundMessage(t *testing.T) { - msg := &ping{SeqNo: 100} - buf, err := encode(pingMsg, msg) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - msgs := [][]byte{buf.Bytes(), buf.Bytes(), buf.Bytes()} - compound := makeCompoundMessage(msgs) - - trunc, parts, err := decodeCompoundMessage(compound.Bytes()[1:]) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - if trunc != 0 { - t.Fatalf("should not truncate") - } - if len(parts) != 3 { - t.Fatalf("bad parts") - } - for _, p := range parts { - if len(p) != buf.Len() { - t.Fatalf("bad part len") - } - } -} - -func TestDecodeCompoundMessage_Trunc(t *testing.T) { - msg := &ping{SeqNo: 100} - buf, err := encode(pingMsg, msg) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - msgs := [][]byte{buf.Bytes(), buf.Bytes(), buf.Bytes()} - compound := makeCompoundMessage(msgs) - - trunc, parts, err := decodeCompoundMessage(compound.Bytes()[1:38]) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - if trunc != 1 { - t.Fatalf("truncate: %d", trunc) - } - if len(parts) != 2 { - t.Fatalf("bad parts") - } - for _, p := range parts { - if len(p) != buf.Len() { - t.Fatalf("bad part len") - } - } -} - -func TestCompressDecompressPayload(t *testing.T) { - buf, err := compressPayload([]byte("testing")) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - decomp, err := decompressPayload(buf.Bytes()[1:]) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - if !reflect.DeepEqual(decomp, []byte("testing")) { - t.Fatalf("bad payload: %v", decomp) - } -} diff --git a/vendor/github.com/kr/logfmt/bench_test.go b/vendor/github.com/kr/logfmt/bench_test.go deleted file mode 100644 index 27c61f1a7..000000000 --- a/vendor/github.com/kr/logfmt/bench_test.go +++ /dev/null @@ -1,59 +0,0 @@ -package logfmt - -import ( - "testing" - "time" -) - -func BenchmarkScanner(b *testing.B) { - b.StopTimer() - data := []byte("measure.test=1 measure.foo=bar measure.time=2h measure=\"foo\"") - h := new(nopHandler) - b.SetBytes(int64(len(data))) - b.StartTimer() - for i := 0; i < b.N; i++ { - if err := gotoScanner(data, h); err != nil { - panic(err) - } - } -} - -type nopHandler struct { - called bool -} - -func (h *nopHandler) HandleLogfmt(key, val []byte) error { - h.called = true - return nil -} - -func BenchmarkDecodeCustom(b *testing.B) { - data := []byte(`a=foo b=10ms c=cat E="123" d foo= emp=`) - - h := new(nopHandler) - for i := 0; i < b.N; i++ { - if err := Unmarshal(data, h); err != nil { - panic(err) - } - } - if !h.called { - panic("handler not called") - } -} - -func BenchmarkDecodeDefault(b *testing.B) { - data := []byte(`a=foo b=10ms c=cat E="123" d foo= emp=`) - var g struct { - A string - B time.Duration - C *string - E string - D bool - } - - for i := 0; i < b.N; i++ { - if err := Unmarshal(data, &g); err != nil { - panic(err) - } - } -} diff --git a/vendor/github.com/kr/logfmt/decode_test.go b/vendor/github.com/kr/logfmt/decode_test.go deleted file mode 100644 index bd120c0aa..000000000 --- a/vendor/github.com/kr/logfmt/decode_test.go +++ /dev/null @@ -1,110 +0,0 @@ -package logfmt - -import ( - "reflect" - "testing" - "time" -) - -type pair struct { - k, v string -} - -type coll struct { - a []pair -} - -func (c *coll) HandleLogfmt(key, val []byte) error { - c.a = append(c.a, pair{string(key), string(val)}) - return nil -} - -func TestDecodeCustom(t *testing.T) { - data := []byte(`a=foo b=10ms c=cat E="123" d foo= emp=`) - - g := new(coll) - if err := Unmarshal(data, g); err != nil { - t.Fatal(err) - } - - w := []pair{ - {"a", "foo"}, - {"b", "10ms"}, - {"c", "cat"}, - {"E", "123"}, - {"d", ""}, - {"foo", ""}, - {"emp", ""}, - } - - if !reflect.DeepEqual(w, g.a) { - t.Errorf("\nwant %v\n got %v", w, g) - } -} - -func TestDecodeDefault(t *testing.T) { - var g struct { - Float float64 - NFloat *float64 - String string - Int int - D time.Duration - NB *[]byte - Here bool - This int `logfmt:"that"` - } - - em, err := NewStructHandler(&g) - if err != nil { - t.Fatal(err) - } - - var tests = []struct { - name string - val string - want interface{} - }{ - {"float", "3.14", 3.14}, - {"nfloat", "123", float64(123)}, - {"string", "foobar", "foobar"}, - {"inT", "10", 10}, - {"d", "1h", 1 * time.Hour}, - {"nb", "bytes!", []byte("bytes!")}, - {"here", "", true}, - {"that", "5", 5}, - } - - rv := reflect.Indirect(reflect.ValueOf(&g)) - for i, test := range tests { - err = em.HandleLogfmt([]byte(test.name), []byte(test.val)) - if err != nil { - t.Error(err) - continue - } - - fv := reflect.Indirect(rv.Field(i)) - if !fv.IsValid() { - ft := rv.Type().Field(i) - t.Errorf("%s is invalid", ft.Name) - continue - } - - gv := fv.Interface() - if !reflect.DeepEqual(gv, test.want) { - t.Errorf("want %T %#v, got %T %#v", test.want, test.want, gv, gv) - } - } - - if g.Float != 3.14 { - t.Errorf("want %v, got %v", 3.14, g.Float) - } - - err = em.HandleLogfmt([]byte("nfloat"), []byte("123")) - if err != nil { - t.Fatal(err) - } - - if g.NFloat == nil || *g.NFloat != 123 { - t.Errorf("want %v, got %v", 123, *g.NFloat) - } -} diff --git a/vendor/github.com/kr/logfmt/example_test.go b/vendor/github.com/kr/logfmt/example_test.go deleted file mode 100644 index d608d3e0d..000000000 --- a/vendor/github.com/kr/logfmt/example_test.go +++ /dev/null @@ -1,59 +0,0 @@ -package logfmt_test - -import ( - "bytes" - "fmt" - "github.com/kr/logfmt" - "log" - "strconv" -) - -type Measurement struct { - Key string - Val float64 - Unit string // (e.g. ms, MB, etc) -} - -type Measurements []*Measurement - -var measurePrefix = []byte("measure.") - -func (mm *Measurements) HandleLogfmt(key, val []byte) error { - if !bytes.HasPrefix(key, measurePrefix) { - return nil - } - i := bytes.LastIndexFunc(val, isDigit) - v, err := strconv.ParseFloat(string(val[:i+1]), 10) - if err != nil { - return err - } - m := &Measurement{ - Key: string(key[len(measurePrefix):]), - Val: v, - Unit: string(val[i+1:]), - } - *mm = append(*mm, m) - return nil -} - -// return true if r is an ASCII digit only, as opposed to unicode.IsDigit. -func isDigit(r rune) bool { - return '0' <= r && r <= '9' -} - -func Example_customHandler() { - var data = []byte("measure.a=1ms measure.b=10 measure.c=100MB measure.d=1s garbage") - - mm := make(Measurements, 0) - if err := logfmt.Unmarshal(data, &mm); err != nil { - log.Fatalf("err=%q", err) - } - for _, m := range mm { - fmt.Printf("%v\n", *m) - } - // Output: - // {a 1 ms} - // {b 10 } - // {c 100 MB} - // {d 1 s} -} diff --git a/vendor/github.com/kr/logfmt/scanner_test.go b/vendor/github.com/kr/logfmt/scanner_test.go deleted file mode 100644 index ac9b2f05a..000000000 --- a/vendor/github.com/kr/logfmt/scanner_test.go +++ /dev/null @@ -1,67 +0,0 @@ -package logfmt - -import ( - "reflect" - "testing" -) - -func TestScannerSimple(t *testing.T) { - type T struct { - k string - v string - } - - tests := []struct { - data string - want []T - }{ - { - `a=1 b="bar" ƒ=2h3s r="esc\t" d x=sf `, - []T{ - {"a", "1"}, - {"b", "bar"}, - {"ƒ", "2h3s"}, - {"r", "esc\t"}, - {"d", ""}, - {"x", "sf"}, - }, - }, - {`x= `, []T{{"x", ""}}}, - {`y=`, []T{{"y", ""}}}, - {`y`, []T{{"y", ""}}}, - {`y=f`, []T{{"y", "f"}}}, - } - - for _, test := range tests { - var got []T - h := func(key, val []byte) error { - got = append(got, T{string(key), string(val)}) - return nil - } - gotoScanner([]byte(test.data), HandlerFunc(h)) - if !reflect.DeepEqual(test.want, got) { - t.Errorf("want %q, got %q", test.want, got) - } - } - - var called bool - h := func(key, val []byte) error { called = true; return nil } - err := gotoScanner([]byte(`foo="b`), HandlerFunc(h)) - if err != ErrUnterminatedString { - t.Errorf("want %v, got %v", ErrUnterminatedString, err) - } - if called { - t.Error("did not expect call to handler") - } -} - -func TestScannerAllocs(t *testing.T) { - data := []byte(`a=1 b="bar" ƒ=2h3s r="esc\t" d x=sf `) - h := func(key, val []byte) error { return nil } - allocs := testing.AllocsPerRun(1000, func() { - gotoScanner(data, HandlerFunc(h)) - }) - if allocs > 1 { - t.Errorf("got %f, want <=1", allocs) - } -} diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/all_test.go b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/all_test.go deleted file mode 100644 index a793c8856..000000000 --- a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/all_test.go +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2013 Matt T. Proud -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package pbutil - -import ( - "bytes" - "testing" - - "github.com/golang/protobuf/proto" - - . "github.com/matttproud/golang_protobuf_extensions/testdata" -) - -func TestWriteDelimited(t *testing.T) { - t.Parallel() - for _, test := range []struct { - msg proto.Message - buf []byte - n int - err error - }{ - { - msg: &Empty{}, - n: 1, - buf: []byte{0}, - }, - { - msg: &GoEnum{Foo: FOO_FOO1.Enum()}, - n: 3, - buf: []byte{2, 8, 1}, - }, - { - msg: &Strings{ - StringField: proto.String(`This is my gigantic, unhappy string. It exceeds -the encoding size of a single byte varint. We are using it to fuzz test the -correctness of the header decoding mechanisms, which may prove problematic. -I expect it may. Let's hope you enjoy testing as much as we do.`), - }, - n: 271, - buf: []byte{141, 2, 10, 138, 2, 84, 104, 105, 115, 32, 105, 115, 32, 109, - 121, 32, 103, 105, 103, 97, 110, 116, 105, 99, 44, 32, 117, 110, 104, - 97, 112, 112, 121, 32, 115, 116, 114, 105, 110, 103, 46, 32, 32, 73, - 116, 32, 101, 120, 99, 101, 101, 100, 115, 10, 116, 104, 101, 32, 101, - 110, 99, 111, 100, 105, 110, 103, 32, 115, 105, 122, 101, 32, 111, 102, - 32, 97, 32, 115, 105, 110, 103, 108, 101, 32, 98, 121, 116, 101, 32, - 118, 97, 114, 105, 110, 116, 46, 32, 32, 87, 101, 32, 97, 114, 101, 32, - 117, 115, 105, 110, 103, 32, 105, 116, 32, 116, 111, 32, 102, 117, 122, - 122, 32, 116, 101, 115, 116, 32, 116, 104, 101, 10, 99, 111, 114, 114, - 101, 99, 116, 110, 101, 115, 115, 32, 111, 102, 32, 116, 104, 101, 32, - 104, 101, 97, 100, 101, 114, 32, 100, 101, 99, 111, 100, 105, 110, 103, - 32, 109, 101, 99, 104, 97, 110, 105, 115, 109, 115, 44, 32, 119, 104, - 105, 99, 104, 32, 109, 97, 121, 32, 112, 114, 111, 118, 101, 32, 112, - 114, 111, 98, 108, 101, 109, 97, 116, 105, 99, 46, 10, 73, 32, 101, 120, - 112, 101, 99, 116, 32, 105, 116, 32, 109, 97, 121, 46, 32, 32, 76, 101, - 116, 39, 115, 32, 104, 111, 112, 101, 32, 121, 111, 117, 32, 101, 110, - 106, 111, 121, 32, 116, 101, 115, 116, 105, 110, 103, 32, 97, 115, 32, - 109, 117, 99, 104, 32, 97, 115, 32, 119, 101, 32, 100, 111, 46}, - }, - } { - var buf bytes.Buffer - if n, err := WriteDelimited(&buf, test.msg); n != test.n || err != test.err { - t.Fatalf("WriteDelimited(buf, %#v) = %v, %v; want %v, %v", test.msg, n, err, test.n, test.err) - } - if out := buf.Bytes(); !bytes.Equal(out, test.buf) { - t.Fatalf("WriteDelimited(buf, %#v); buf = %v; want %v", test.msg, out, test.buf) - } - } -} - -func TestReadDelimited(t *testing.T) { - t.Parallel() - for _, test := range []struct { - buf []byte - msg proto.Message - n int - err error - }{ - { - buf: []byte{0}, - msg: &Empty{}, - n: 1, - }, - { - n: 3, - buf: []byte{2, 8, 1}, - msg: &GoEnum{Foo: FOO_FOO1.Enum()}, - }, - { - buf: []byte{141, 2, 10, 138, 2, 84, 104, 105, 115, 32, 105, 115, 32, 109, - 121, 32, 103, 105, 103, 97, 110, 116, 105, 99, 44, 32, 117, 110, 104, - 97, 112, 112, 121, 32, 115, 116, 114, 105, 110, 103, 46, 32, 32, 73, - 116, 32, 101, 120, 99, 101, 101, 100, 115, 10, 116, 104, 101, 32, 101, - 110, 99, 111, 100, 105, 110, 103, 32, 115, 105, 122, 101, 32, 111, 102, - 32, 97, 32, 115, 105, 110, 103, 108, 101, 32, 98, 121, 116, 101, 32, - 118, 97, 114, 105, 110, 116, 46, 32, 32, 87, 101, 32, 97, 114, 101, 32, - 117, 115, 105, 110, 103, 32, 105, 116, 32, 116, 111, 32, 102, 117, 122, - 122, 32, 116, 101, 115, 116, 32, 116, 104, 101, 10, 99, 111, 114, 114, - 101, 99, 116, 110, 101, 115, 115, 32, 111, 102, 32, 116, 104, 101, 32, - 104, 101, 97, 100, 101, 114, 32, 100, 101, 99, 111, 100, 105, 110, 103, - 32, 109, 101, 99, 104, 97, 110, 105, 115, 109, 115, 44, 32, 119, 104, - 105, 99, 104, 32, 109, 97, 121, 32, 112, 114, 111, 118, 101, 32, 112, - 114, 111, 98, 108, 101, 109, 97, 116, 105, 99, 46, 10, 73, 32, 101, 120, - 112, 101, 99, 116, 32, 105, 116, 32, 109, 97, 121, 46, 32, 32, 76, 101, - 116, 39, 115, 32, 104, 111, 112, 101, 32, 121, 111, 117, 32, 101, 110, - 106, 111, 121, 32, 116, 101, 115, 116, 105, 110, 103, 32, 97, 115, 32, - 109, 117, 99, 104, 32, 97, 115, 32, 119, 101, 32, 100, 111, 46}, - msg: &Strings{ - StringField: proto.String(`This is my gigantic, unhappy string. It exceeds -the encoding size of a single byte varint. We are using it to fuzz test the -correctness of the header decoding mechanisms, which may prove problematic. -I expect it may. Let's hope you enjoy testing as much as we do.`), - }, - n: 271, - }, - } { - msg := proto.Clone(test.msg) - msg.Reset() - if n, err := ReadDelimited(bytes.NewBuffer(test.buf), msg); n != test.n || err != test.err { - t.Fatalf("ReadDelimited(%v, msg) = %v, %v; want %v, %v", test.buf, n, err, test.n, test.err) - } - if !proto.Equal(msg, test.msg) { - t.Fatalf("ReadDelimited(%v, msg); msg = %v; want %v", test.buf, msg, test.msg) - } - } -} - -func TestEndToEndValid(t *testing.T) { - t.Parallel() - for _, test := range [][]proto.Message{ - {&Empty{}}, - {&GoEnum{Foo: FOO_FOO1.Enum()}, &Empty{}, &GoEnum{Foo: FOO_FOO1.Enum()}}, - {&GoEnum{Foo: FOO_FOO1.Enum()}}, - {&Strings{ - StringField: proto.String(`This is my gigantic, unhappy string. It exceeds -the encoding size of a single byte varint. We are using it to fuzz test the -correctness of the header decoding mechanisms, which may prove problematic. -I expect it may. Let's hope you enjoy testing as much as we do.`), - }}, - } { - var buf bytes.Buffer - var written int - for i, msg := range test { - n, err := WriteDelimited(&buf, msg) - if err != nil { - // Assumption: TestReadDelimited and TestWriteDelimited are sufficient - // and inputs for this test are explicitly exercised there. - t.Fatalf("WriteDelimited(buf, %v[%d]) = ?, %v; wanted ?, nil", test, i, err) - } - written += n - } - var read int - for i, msg := range test { - out := proto.Clone(msg) - out.Reset() - n, _ := ReadDelimited(&buf, out) - // Decide to do EOF checking? - read += n - if !proto.Equal(out, msg) { - t.Fatalf("out = %v; want %v[%d] = %#v", out, test, i, msg) - } - } - if read != written { - t.Fatalf("%v read = %d; want %d", test, read, written) - } - } -} diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode_test.go b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode_test.go deleted file mode 100644 index 364a7b799..000000000 --- a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode_test.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2016 Matt T. Proud -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package pbutil - -import ( - "bytes" - "io" - "testing" - "testing/iotest" -) - -func TestReadDelimitedIllegalVarint(t *testing.T) { - t.Parallel() - var tests = []struct { - in []byte - n int - err error - }{ - { - in: []byte{255, 255, 255, 255, 255}, - n: 5, - err: errInvalidVarint, - }, - { - in: []byte{255, 255, 255, 255, 255, 255}, - n: 5, - err: errInvalidVarint, - }, - } - for _, test := range tests { - n, err := ReadDelimited(bytes.NewReader(test.in), nil) - if got, want := n, test.n; got != want { - t.Errorf("ReadDelimited(%#v, nil) = %#v, ?; want = %v#, ?", test.in, got, want) - } - if got, want := err, test.err; got != want { - t.Errorf("ReadDelimited(%#v, nil) = ?, %#v; want = ?, %#v", test.in, got, want) - } - } -} - -func TestReadDelimitedPrematureHeader(t *testing.T) { - t.Parallel() - var data = []byte{128, 5} // 256 + 256 + 128 - n, err := ReadDelimited(bytes.NewReader(data[0:1]), nil) - if got, want := n, 1; got != want { - t.Errorf("ReadDelimited(%#v, nil) = %#v, ?; want = %v#, ?", data[0:1], got, want) - } - if got, want := err, io.EOF; got != want { - t.Errorf("ReadDelimited(%#v, nil) = ?, %#v; want = ?, %#v", data[0:1], got, want) - } -} - -func TestReadDelimitedPrematureBody(t *testing.T) { - t.Parallel() - var data = []byte{128, 5, 0, 0, 0} // 256 + 256 + 128 - n, err := ReadDelimited(bytes.NewReader(data[:]), nil) - if got, want := n, 5; got != want { - t.Errorf("ReadDelimited(%#v, nil) = %#v, ?; want = %v#, ?", data, got, want) - } - if got, want := err, io.ErrUnexpectedEOF; got != want { - t.Errorf("ReadDelimited(%#v, nil) = ?, %#v; want = ?, %#v", data, got, want) - } -} - -func TestReadDelimitedPrematureHeaderIncremental(t *testing.T) { - t.Parallel() - var data = []byte{128, 5} // 256 + 256 + 128 - n, err := ReadDelimited(iotest.OneByteReader(bytes.NewReader(data[0:1])), nil) - if got, want := n, 1; got != want { - t.Errorf("ReadDelimited(%#v, nil) = %#v, ?; want = %v#, ?", data[0:1], got, want) - } - if got, want := err, io.EOF; got != want { - t.Errorf("ReadDelimited(%#v, nil) = ?, %#v; want = ?, %#v", data[0:1], got, want) - } -} - -func TestReadDelimitedPrematureBodyIncremental(t *testing.T) { - t.Parallel() - var data = []byte{128, 5, 0, 0, 0} // 256 + 256 + 128 - n, err := ReadDelimited(iotest.OneByteReader(bytes.NewReader(data[:])), nil) - if got, want := n, 5; got != want { - t.Errorf("ReadDelimited(%#v, nil) = %#v, ?; want = %v#, ?", data, got, want) - } - if got, want := err, io.ErrUnexpectedEOF; got != want { - t.Errorf("ReadDelimited(%#v, nil) = ?, %#v; want = ?, %#v", data, got, want) - } -} diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode_test.go b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode_test.go deleted file mode 100644 index f92632b0b..000000000 --- a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode_test.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2016 Matt T. Proud -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package pbutil - -import ( - "bytes" - "errors" - "testing" - - "github.com/golang/protobuf/proto" -) - -var errMarshal = errors.New("pbutil: can't marshal") - -type cantMarshal struct{ proto.Message } - -func (cantMarshal) Marshal() ([]byte, error) { return nil, errMarshal } - -var _ proto.Message = cantMarshal{} - -func TestWriteDelimitedMarshalErr(t *testing.T) { - t.Parallel() - var data cantMarshal - var buf bytes.Buffer - n, err := WriteDelimited(&buf, data) - if got, want := n, 0; got != want { - t.Errorf("WriteDelimited(buf, %#v) = %#v, ?; want = %v#, ?", data, got, want) - } - if got, want := err, errMarshal; got != want { - t.Errorf("WriteDelimited(buf, %#v) = ?, %#v; want = ?, %#v", data, got, want) - } -} - -type canMarshal struct{ proto.Message } - -func (canMarshal) Marshal() ([]byte, error) { return []byte{0, 1, 2, 3, 4, 5}, nil } - -var errWrite = errors.New("pbutil: can't write") - -type cantWrite struct{} - -func (cantWrite) Write([]byte) (int, error) { return 0, errWrite } - -func TestWriteDelimitedWriteErr(t *testing.T) { - t.Parallel() - var data canMarshal - var buf cantWrite - n, err := WriteDelimited(buf, data) - if got, want := n, 0; got != want { - t.Errorf("WriteDelimited(buf, %#v) = %#v, ?; want = %v#, ?", data, got, want) - } - if got, want := err, errWrite; got != want { - t.Errorf("WriteDelimited(buf, %#v) = ?, %#v; want = ?, %#v", data, got, want) - } -} diff --git a/vendor/github.com/miekg/dns/.travis.yml b/vendor/github.com/miekg/dns/.travis.yml index 13e312b4f..18259374e 100644 --- a/vendor/github.com/miekg/dns/.travis.yml +++ b/vendor/github.com/miekg/dns/.travis.yml @@ -1,21 +1,18 @@ language: go sudo: false + go: - 1.10.x - 1.11.x - tip -env: - - TESTS="-race -v -bench=. -coverprofile=coverage.txt -covermode=atomic" - - TESTS="-race -v ./..." - before_install: # don't use the miekg/dns when testing forks - mkdir -p $GOPATH/src/github.com/miekg - ln -s $TRAVIS_BUILD_DIR $GOPATH/src/github.com/miekg/ || true script: - - go test $TESTS + - go test -race -v -bench=. -coverprofile=coverage.txt -covermode=atomic ./... after_success: - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/miekg/dns/Gopkg.lock b/vendor/github.com/miekg/dns/Gopkg.lock index 4455c9836..686632207 100644 --- a/vendor/github.com/miekg/dns/Gopkg.lock +++ b/vendor/github.com/miekg/dns/Gopkg.lock @@ -3,19 +3,55 @@ [[projects]] branch = "master" + digest = "1:6914c49eed986dfb8dffb33516fa129c49929d4d873f41e073c83c11c372b870" name = "golang.org/x/crypto" - packages = ["ed25519","ed25519/internal/edwards25519"] - revision = "b47b1587369238182299fe4dad77d05b8b461e06" + packages = [ + "ed25519", + "ed25519/internal/edwards25519", + ] + pruneopts = "" + revision = "e3636079e1a4c1f337f212cc5cd2aca108f6c900" [[projects]] branch = "master" + digest = "1:08e41d63f8dac84d83797368b56cf0b339e42d0224e5e56668963c28aec95685" name = "golang.org/x/net" - packages = ["bpf","internal/iana","internal/socket","ipv4","ipv6"] - revision = "1e491301e022f8f977054da4c2d852decd59571f" + packages = [ + "bpf", + "context", + "internal/iana", + "internal/socket", + "ipv4", + "ipv6", + ] + pruneopts = "" + revision = "4dfa2610cdf3b287375bbba5b8f2a14d3b01d8de" + +[[projects]] + branch = "master" + digest = "1:b2ea75de0ccb2db2ac79356407f8a4cd8f798fe15d41b381c00abf3ae8e55ed1" + name = "golang.org/x/sync" + packages = ["errgroup"] + pruneopts = "" + revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca" + +[[projects]] + branch = "master" + digest = "1:149a432fabebb8221a80f77731b1cd63597197ded4f14af606ebe3a0959004ec" + name = "golang.org/x/sys" + packages = ["unix"] + pruneopts = "" + revision = "e4b3c5e9061176387e7cea65e4dc5853801f3fb7" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "c4abc38abaeeeeb9be92455c9c02cae32841122b8982aaa067ef25bb8e86ff9d" + input-imports = [ + "golang.org/x/crypto/ed25519", + "golang.org/x/net/ipv4", + "golang.org/x/net/ipv6", + "golang.org/x/sync/errgroup", + "golang.org/x/sys/unix", + ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/vendor/github.com/miekg/dns/Gopkg.toml b/vendor/github.com/miekg/dns/Gopkg.toml index 2f655b2c7..85e6ff31b 100644 --- a/vendor/github.com/miekg/dns/Gopkg.toml +++ b/vendor/github.com/miekg/dns/Gopkg.toml @@ -24,3 +24,15 @@ [[constraint]] branch = "master" name = "golang.org/x/crypto" + +[[constraint]] + branch = "master" + name = "golang.org/x/net" + +[[constraint]] + branch = "master" + name = "golang.org/x/sys" + +[[constraint]] + branch = "master" + name = "golang.org/x/sync" diff --git a/vendor/github.com/miekg/dns/README.md b/vendor/github.com/miekg/dns/README.md index 77874642b..7f1aaa5de 100644 --- a/vendor/github.com/miekg/dns/README.md +++ b/vendor/github.com/miekg/dns/README.md @@ -67,6 +67,7 @@ A not-so-up-to-date-list-that-may-be-actually-current: * https://github.com/xor-gate/sshfp * https://github.com/rs/dnstrace * https://blitiri.com.ar/p/dnss ([github mirror](https://github.com/albertito/dnss)) +* https://github.com/semihalev/sdns Send pull request if you want to be listed here. diff --git a/vendor/github.com/miekg/dns/client.go b/vendor/github.com/miekg/dns/client.go index 7a319b02c..63ced2bd0 100644 --- a/vendor/github.com/miekg/dns/client.go +++ b/vendor/github.com/miekg/dns/client.go @@ -567,7 +567,7 @@ func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, if deadline, ok := ctx.Deadline(); !ok { timeout = 0 } else { - timeout = deadline.Sub(time.Now()) + timeout = time.Until(deadline) } // not passing the context to the underlying calls, as the API does not support // context. For timeouts you should set up Client.Dialer and call Client.Exchange. diff --git a/vendor/github.com/miekg/dns/client_test.go b/vendor/github.com/miekg/dns/client_test.go deleted file mode 100644 index 43163a1f2..000000000 --- a/vendor/github.com/miekg/dns/client_test.go +++ /dev/null @@ -1,610 +0,0 @@ -package dns - -import ( - "context" - "crypto/tls" - "fmt" - "net" - "strconv" - "strings" - "sync" - "testing" - "time" -) - -func TestDialUDP(t *testing.T) { - HandleFunc("miek.nl.", HelloServer) - defer HandleRemove("miek.nl.") - - s, addrstr, err := RunLocalUDPServer(":0") - if err != nil { - t.Fatalf("unable to run test server: %v", err) - } - defer s.Shutdown() - - m := new(Msg) - m.SetQuestion("miek.nl.", TypeSOA) - - c := new(Client) - conn, err := c.Dial(addrstr) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - if conn == nil { - t.Fatalf("conn is nil") - } -} - -func TestClientSync(t *testing.T) { - HandleFunc("miek.nl.", HelloServer) - defer HandleRemove("miek.nl.") - - s, addrstr, err := RunLocalUDPServer(":0") - if err != nil { - t.Fatalf("unable to run test server: %v", err) - } - defer s.Shutdown() - - m := new(Msg) - m.SetQuestion("miek.nl.", TypeSOA) - - c := new(Client) - r, _, err := c.Exchange(m, addrstr) - if err != nil { - t.Fatalf("failed to exchange: %v", err) - } - if r == nil { - t.Fatal("response is nil") - } - if r.Rcode != RcodeSuccess { - t.Errorf("failed to get an valid answer\n%v", r) - } - // And now with plain Exchange(). - r, err = Exchange(m, addrstr) - if err != nil { - t.Errorf("failed to exchange: %v", err) - } - if r == nil || r.Rcode != RcodeSuccess { - t.Errorf("failed to get an valid answer\n%v", r) - } -} - -func TestClientLocalAddress(t *testing.T) { - HandleFunc("miek.nl.", HelloServerEchoAddrPort) - defer HandleRemove("miek.nl.") - - s, addrstr, err := RunLocalUDPServer(":0") - if err != nil { - t.Fatalf("unable to run test server: %v", err) - } - defer s.Shutdown() - - m := new(Msg) - m.SetQuestion("miek.nl.", TypeSOA) - - c := new(Client) - laddr := net.UDPAddr{IP: net.ParseIP("0.0.0.0"), Port: 12345, Zone: ""} - c.Dialer = &net.Dialer{LocalAddr: &laddr} - r, _, err := c.Exchange(m, addrstr) - if err != nil { - t.Fatalf("failed to exchange: %v", err) - } - if r != nil && r.Rcode != RcodeSuccess { - t.Errorf("failed to get an valid answer\n%v", r) - } - if len(r.Extra) != 1 { - t.Errorf("failed to get additional answers\n%v", r) - } - txt := r.Extra[0].(*TXT) - if txt == nil { - t.Errorf("invalid TXT response\n%v", txt) - } - if len(txt.Txt) != 1 || !strings.Contains(txt.Txt[0], ":12345") { - t.Errorf("invalid TXT response\n%v", txt.Txt) - } -} - -func TestClientTLSSyncV4(t *testing.T) { - HandleFunc("miek.nl.", HelloServer) - defer HandleRemove("miek.nl.") - - cert, err := tls.X509KeyPair(CertPEMBlock, KeyPEMBlock) - if err != nil { - t.Fatalf("unable to build certificate: %v", err) - } - - config := tls.Config{ - Certificates: []tls.Certificate{cert}, - } - - s, addrstr, err := RunLocalTLSServer(":0", &config) - if err != nil { - t.Fatalf("unable to run test server: %v", err) - } - defer s.Shutdown() - - m := new(Msg) - m.SetQuestion("miek.nl.", TypeSOA) - - c := new(Client) - - // test tcp-tls - c.Net = "tcp-tls" - c.TLSConfig = &tls.Config{ - InsecureSkipVerify: true, - } - - r, _, err := c.Exchange(m, addrstr) - if err != nil { - t.Fatalf("failed to exchange: %v", err) - } - if r == nil { - t.Fatal("response is nil") - } - if r.Rcode != RcodeSuccess { - t.Errorf("failed to get an valid answer\n%v", r) - } - - // test tcp4-tls - c.Net = "tcp4-tls" - c.TLSConfig = &tls.Config{ - InsecureSkipVerify: true, - } - - r, _, err = c.Exchange(m, addrstr) - if err != nil { - t.Fatalf("failed to exchange: %v", err) - } - if r == nil { - t.Fatal("response is nil") - } - if r.Rcode != RcodeSuccess { - t.Errorf("failed to get an valid answer\n%v", r) - } -} - -func TestClientSyncBadID(t *testing.T) { - HandleFunc("miek.nl.", HelloServerBadID) - defer HandleRemove("miek.nl.") - - s, addrstr, err := RunLocalUDPServer(":0") - if err != nil { - t.Fatalf("unable to run test server: %v", err) - } - defer s.Shutdown() - - m := new(Msg) - m.SetQuestion("miek.nl.", TypeSOA) - - c := new(Client) - if _, _, err := c.Exchange(m, addrstr); err != ErrId { - t.Errorf("did not find a bad Id") - } - // And now with plain Exchange(). - if _, err := Exchange(m, addrstr); err != ErrId { - t.Errorf("did not find a bad Id") - } -} - -func TestClientEDNS0(t *testing.T) { - HandleFunc("miek.nl.", HelloServer) - defer HandleRemove("miek.nl.") - - s, addrstr, err := RunLocalUDPServer(":0") - if err != nil { - t.Fatalf("unable to run test server: %v", err) - } - defer s.Shutdown() - - m := new(Msg) - m.SetQuestion("miek.nl.", TypeDNSKEY) - - m.SetEdns0(2048, true) - - c := new(Client) - r, _, err := c.Exchange(m, addrstr) - if err != nil { - t.Fatalf("failed to exchange: %v", err) - } - - if r != nil && r.Rcode != RcodeSuccess { - t.Errorf("failed to get a valid answer\n%v", r) - } -} - -// Validates the transmission and parsing of local EDNS0 options. -func TestClientEDNS0Local(t *testing.T) { - optStr1 := "1979:0x0707" - optStr2 := strconv.Itoa(EDNS0LOCALSTART) + ":0x0601" - - handler := func(w ResponseWriter, req *Msg) { - m := new(Msg) - m.SetReply(req) - - m.Extra = make([]RR, 1, 2) - m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello local edns"}} - - // If the local options are what we expect, then reflect them back. - ec1 := req.Extra[0].(*OPT).Option[0].(*EDNS0_LOCAL).String() - ec2 := req.Extra[0].(*OPT).Option[1].(*EDNS0_LOCAL).String() - if ec1 == optStr1 && ec2 == optStr2 { - m.Extra = append(m.Extra, req.Extra[0]) - } - - w.WriteMsg(m) - } - - HandleFunc("miek.nl.", handler) - defer HandleRemove("miek.nl.") - - s, addrstr, err := RunLocalUDPServer(":0") - if err != nil { - t.Fatalf("unable to run test server: %s", err) - } - defer s.Shutdown() - - m := new(Msg) - m.SetQuestion("miek.nl.", TypeTXT) - - // Add two local edns options to the query. - ec1 := &EDNS0_LOCAL{Code: 1979, Data: []byte{7, 7}} - ec2 := &EDNS0_LOCAL{Code: EDNS0LOCALSTART, Data: []byte{6, 1}} - o := &OPT{Hdr: RR_Header{Name: ".", Rrtype: TypeOPT}, Option: []EDNS0{ec1, ec2}} - m.Extra = append(m.Extra, o) - - c := new(Client) - r, _, err := c.Exchange(m, addrstr) - if err != nil { - t.Fatalf("failed to exchange: %s", err) - } - - if r == nil { - t.Fatal("response is nil") - } - if r.Rcode != RcodeSuccess { - t.Fatal("failed to get a valid answer") - } - - txt := r.Extra[0].(*TXT).Txt[0] - if txt != "Hello local edns" { - t.Error("Unexpected result for miek.nl", txt, "!= Hello local edns") - } - - // Validate the local options in the reply. - got := r.Extra[1].(*OPT).Option[0].(*EDNS0_LOCAL).String() - if got != optStr1 { - t.Errorf("failed to get local edns0 answer; got %s, expected %s", got, optStr1) - } - - got = r.Extra[1].(*OPT).Option[1].(*EDNS0_LOCAL).String() - if got != optStr2 { - t.Errorf("failed to get local edns0 answer; got %s, expected %s", got, optStr2) - } -} - -func TestClientConn(t *testing.T) { - HandleFunc("miek.nl.", HelloServer) - defer HandleRemove("miek.nl.") - - // This uses TCP just to make it slightly different than TestClientSync - s, addrstr, err := RunLocalTCPServer(":0") - if err != nil { - t.Fatalf("unable to run test server: %v", err) - } - defer s.Shutdown() - - m := new(Msg) - m.SetQuestion("miek.nl.", TypeSOA) - - cn, err := Dial("tcp", addrstr) - if err != nil { - t.Errorf("failed to dial %s: %v", addrstr, err) - } - - err = cn.WriteMsg(m) - if err != nil { - t.Errorf("failed to exchange: %v", err) - } - r, err := cn.ReadMsg() - if err != nil { - t.Errorf("failed to get a valid answer: %v", err) - } - if r == nil || r.Rcode != RcodeSuccess { - t.Errorf("failed to get an valid answer\n%v", r) - } - - err = cn.WriteMsg(m) - if err != nil { - t.Errorf("failed to exchange: %v", err) - } - h := new(Header) - buf, err := cn.ReadMsgHeader(h) - if buf == nil { - t.Errorf("failed to get an valid answer\n%v", r) - } - if err != nil { - t.Errorf("failed to get a valid answer: %v", err) - } - if int(h.Bits&0xF) != RcodeSuccess { - t.Errorf("failed to get an valid answer in ReadMsgHeader\n%v", r) - } - if h.Ancount != 0 || h.Qdcount != 1 || h.Nscount != 0 || h.Arcount != 1 { - t.Errorf("expected to have question and additional in response; got something else: %+v", h) - } - if err = r.Unpack(buf); err != nil { - t.Errorf("unable to unpack message fully: %v", err) - } -} - -func TestTruncatedMsg(t *testing.T) { - m := new(Msg) - m.SetQuestion("miek.nl.", TypeSRV) - cnt := 10 - for i := 0; i < cnt; i++ { - r := &SRV{ - Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeSRV, Class: ClassINET, Ttl: 0}, - Port: uint16(i + 8000), - Target: "target.miek.nl.", - } - m.Answer = append(m.Answer, r) - - re := &A{ - Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeA, Class: ClassINET, Ttl: 0}, - A: net.ParseIP(fmt.Sprintf("127.0.0.%d", i)).To4(), - } - m.Extra = append(m.Extra, re) - } - buf, err := m.Pack() - if err != nil { - t.Errorf("failed to pack: %v", err) - } - - r := new(Msg) - if err = r.Unpack(buf); err != nil { - t.Errorf("unable to unpack message: %v", err) - } - if len(r.Answer) != cnt { - t.Errorf("answer count after regular unpack doesn't match: %d", len(r.Answer)) - } - if len(r.Extra) != cnt { - t.Errorf("extra count after regular unpack doesn't match: %d", len(r.Extra)) - } - - m.Truncated = true - buf, err = m.Pack() - if err != nil { - t.Errorf("failed to pack truncated: %v", err) - } - - r = new(Msg) - if err = r.Unpack(buf); err != nil && err != ErrTruncated { - t.Errorf("unable to unpack truncated message: %v", err) - } - if !r.Truncated { - t.Errorf("truncated message wasn't unpacked as truncated") - } - if len(r.Answer) != cnt { - t.Errorf("answer count after truncated unpack doesn't match: %d", len(r.Answer)) - } - if len(r.Extra) != cnt { - t.Errorf("extra count after truncated unpack doesn't match: %d", len(r.Extra)) - } - - // Now we want to remove almost all of the extra records - // We're going to loop over the extra to get the count of the size of all - // of them - off := 0 - buf1 := make([]byte, m.Len()) - for i := 0; i < len(m.Extra); i++ { - off, err = PackRR(m.Extra[i], buf1, off, nil, m.Compress) - if err != nil { - t.Errorf("failed to pack extra: %v", err) - } - } - - // Remove all of the extra bytes but 10 bytes from the end of buf - off -= 10 - buf1 = buf[:len(buf)-off] - - r = new(Msg) - if err = r.Unpack(buf1); err != nil && err != ErrTruncated { - t.Errorf("unable to unpack cutoff message: %v", err) - } - if !r.Truncated { - t.Error("truncated cutoff message wasn't unpacked as truncated") - } - if len(r.Answer) != cnt { - t.Errorf("answer count after cutoff unpack doesn't match: %d", len(r.Answer)) - } - if len(r.Extra) != 0 { - t.Errorf("extra count after cutoff unpack is not zero: %d", len(r.Extra)) - } - - // Now we want to remove almost all of the answer records too - buf1 = make([]byte, m.Len()) - as := 0 - for i := 0; i < len(m.Extra); i++ { - off1 := off - off, err = PackRR(m.Extra[i], buf1, off, nil, m.Compress) - as = off - off1 - if err != nil { - t.Errorf("failed to pack extra: %v", err) - } - } - - // Keep exactly one answer left - // This should still cause Answer to be nil - off -= as - buf1 = buf[:len(buf)-off] - - r = new(Msg) - if err = r.Unpack(buf1); err != nil && err != ErrTruncated { - t.Errorf("unable to unpack cutoff message: %v", err) - } - if !r.Truncated { - t.Error("truncated cutoff message wasn't unpacked as truncated") - } - if len(r.Answer) != 0 { - t.Errorf("answer count after second cutoff unpack is not zero: %d", len(r.Answer)) - } - - // Now leave only 1 byte of the question - // Since the header is always 12 bytes, we just need to keep 13 - buf1 = buf[:13] - - r = new(Msg) - err = r.Unpack(buf1) - if err == nil || err == ErrTruncated { - t.Errorf("error should not be ErrTruncated from question cutoff unpack: %v", err) - } - - // Finally, if we only have the header, we don't return an error. - buf1 = buf[:12] - - r = new(Msg) - if err = r.Unpack(buf1); err != nil { - t.Errorf("from header-only unpack should not return an error: %v", err) - } -} - -func TestTimeout(t *testing.T) { - // Set up a dummy UDP server that won't respond - addr, err := net.ResolveUDPAddr("udp", ":0") - if err != nil { - t.Fatalf("unable to resolve local udp address: %v", err) - } - conn, err := net.ListenUDP("udp", addr) - if err != nil { - t.Fatalf("unable to run test server: %v", err) - } - defer conn.Close() - addrstr := conn.LocalAddr().String() - - // Message to send - m := new(Msg) - m.SetQuestion("miek.nl.", TypeTXT) - - // Use a channel + timeout to ensure we don't get stuck if the - // Client Timeout is not working properly - done := make(chan struct{}, 2) - - timeout := time.Millisecond - allowable := timeout + 10*time.Millisecond - abortAfter := timeout + 100*time.Millisecond - - start := time.Now() - - go func() { - c := &Client{Timeout: timeout} - _, _, err := c.Exchange(m, addrstr) - if err == nil { - t.Error("no timeout using Client.Exchange") - } - done <- struct{}{} - }() - - go func() { - ctx, cancel := context.WithTimeout(context.Background(), timeout) - defer cancel() - c := &Client{} - _, _, err := c.ExchangeContext(ctx, m, addrstr) - if err == nil { - t.Error("no timeout using Client.ExchangeContext") - } - done <- struct{}{} - }() - - // Wait for both the Exchange and ExchangeContext tests to be done. - for i := 0; i < 2; i++ { - select { - case <-done: - case <-time.After(abortAfter): - } - } - - length := time.Since(start) - - if length > allowable { - t.Errorf("exchange took longer %v than specified Timeout %v", length, allowable) - } -} - -// Check that responses from deduplicated requests aren't shared between callers -func TestConcurrentExchanges(t *testing.T) { - cases := make([]*Msg, 2) - cases[0] = new(Msg) - cases[1] = new(Msg) - cases[1].Truncated = true - for _, m := range cases { - block := make(chan struct{}) - waiting := make(chan struct{}) - - handler := func(w ResponseWriter, req *Msg) { - r := m.Copy() - r.SetReply(req) - - waiting <- struct{}{} - <-block - w.WriteMsg(r) - } - - HandleFunc("miek.nl.", handler) - defer HandleRemove("miek.nl.") - - s, addrstr, err := RunLocalUDPServer(":0") - if err != nil { - t.Fatalf("unable to run test server: %s", err) - } - defer s.Shutdown() - - m := new(Msg) - m.SetQuestion("miek.nl.", TypeSRV) - c := &Client{ - SingleInflight: true, - } - r := make([]*Msg, 2) - - var wg sync.WaitGroup - wg.Add(len(r)) - for i := 0; i < len(r); i++ { - go func(i int) { - defer wg.Done() - r[i], _, _ = c.Exchange(m.Copy(), addrstr) - if r[i] == nil { - t.Errorf("response %d is nil", i) - } - }(i) - } - select { - case <-waiting: - case <-time.After(time.Second): - t.FailNow() - } - close(block) - wg.Wait() - - if r[0] == r[1] { - t.Errorf("got same response, expected non-shared responses") - } - } -} - -func TestDoHExchange(t *testing.T) { - const addrstr = "https://dns.cloudflare.com/dns-query" - - m := new(Msg) - m.SetQuestion("miek.nl.", TypeSOA) - - cl := &Client{Net: "https"} - - r, _, err := cl.Exchange(m, addrstr) - if err != nil { - t.Fatalf("failed to exchange: %v", err) - } - - if r == nil || r.Rcode != RcodeSuccess { - t.Errorf("failed to get an valid answer\n%v", r) - } - - // TODO: proper tests for this -} diff --git a/vendor/github.com/miekg/dns/clientconfig_test.go b/vendor/github.com/miekg/dns/clientconfig_test.go deleted file mode 100644 index ad5d7d086..000000000 --- a/vendor/github.com/miekg/dns/clientconfig_test.go +++ /dev/null @@ -1,181 +0,0 @@ -package dns - -import ( - "io/ioutil" - "os" - "path/filepath" - "strings" - "testing" -) - -const normal string = ` -# Comment -domain somedomain.com -nameserver 10.28.10.2 -nameserver 11.28.10.1 -` - -const missingNewline string = ` -domain somedomain.com -nameserver 10.28.10.2 -nameserver 11.28.10.1` // <- NOTE: NO newline. - -func testConfig(t *testing.T, data string) { - cc, err := ClientConfigFromReader(strings.NewReader(data)) - if err != nil { - t.Errorf("error parsing resolv.conf: %v", err) - } - if l := len(cc.Servers); l != 2 { - t.Errorf("incorrect number of nameservers detected: %d", l) - } - if l := len(cc.Search); l != 1 { - t.Errorf("domain directive not parsed correctly: %v", cc.Search) - } else { - if cc.Search[0] != "somedomain.com" { - t.Errorf("domain is unexpected: %v", cc.Search[0]) - } - } -} - -func TestNameserver(t *testing.T) { testConfig(t, normal) } -func TestMissingFinalNewLine(t *testing.T) { testConfig(t, missingNewline) } - -func TestNdots(t *testing.T) { - ndotsVariants := map[string]int{ - "options ndots:0": 0, - "options ndots:1": 1, - "options ndots:15": 15, - "options ndots:16": 15, - "options ndots:-1": 0, - "": 1, - } - - for data := range ndotsVariants { - cc, err := ClientConfigFromReader(strings.NewReader(data)) - if err != nil { - t.Errorf("error parsing resolv.conf: %v", err) - } - if cc.Ndots != ndotsVariants[data] { - t.Errorf("Ndots not properly parsed: (Expected: %d / Was: %d)", ndotsVariants[data], cc.Ndots) - } - } -} - -func TestClientConfigFromReaderAttempts(t *testing.T) { - testCases := []struct { - data string - expected int - }{ - {data: "options attempts:0", expected: 1}, - {data: "options attempts:1", expected: 1}, - {data: "options attempts:15", expected: 15}, - {data: "options attempts:16", expected: 16}, - {data: "options attempts:-1", expected: 1}, - {data: "options attempt:", expected: 2}, - } - - for _, test := range testCases { - test := test - t.Run(strings.Replace(test.data, ":", " ", -1), func(t *testing.T) { - t.Parallel() - - cc, err := ClientConfigFromReader(strings.NewReader(test.data)) - if err != nil { - t.Errorf("error parsing resolv.conf: %v", err) - } - if cc.Attempts != test.expected { - t.Errorf("A attempts not properly parsed: (Expected: %d / Was: %d)", test.expected, cc.Attempts) - } - }) - } -} - -func TestReadFromFile(t *testing.T) { - tempDir, err := ioutil.TempDir("", "") - if err != nil { - t.Fatalf("tempDir: %v", err) - } - defer os.RemoveAll(tempDir) - - path := filepath.Join(tempDir, "resolv.conf") - if err := ioutil.WriteFile(path, []byte(normal), 0644); err != nil { - t.Fatalf("writeFile: %v", err) - } - cc, err := ClientConfigFromFile(path) - if err != nil { - t.Errorf("error parsing resolv.conf: %v", err) - } - if l := len(cc.Servers); l != 2 { - t.Errorf("incorrect number of nameservers detected: %d", l) - } - if l := len(cc.Search); l != 1 { - t.Errorf("domain directive not parsed correctly: %v", cc.Search) - } else { - if cc.Search[0] != "somedomain.com" { - t.Errorf("domain is unexpected: %v", cc.Search[0]) - } - } -} - -func TestNameListNdots1(t *testing.T) { - cfg := ClientConfig{ - Ndots: 1, - } - // fqdn should be only result returned - names := cfg.NameList("miek.nl.") - if len(names) != 1 { - t.Errorf("NameList returned != 1 names: %v", names) - } else if names[0] != "miek.nl." { - t.Errorf("NameList didn't return sent fqdn domain: %v", names[0]) - } - - cfg.Search = []string{ - "test", - } - // Sent domain has NDots and search - names = cfg.NameList("miek.nl") - if len(names) != 2 { - t.Errorf("NameList returned != 2 names: %v", names) - } else if names[0] != "miek.nl." { - t.Errorf("NameList didn't return sent domain first: %v", names[0]) - } else if names[1] != "miek.nl.test." { - t.Errorf("NameList didn't return search last: %v", names[1]) - } -} -func TestNameListNdots2(t *testing.T) { - cfg := ClientConfig{ - Ndots: 2, - } - - // Sent domain has less than NDots and search - cfg.Search = []string{ - "test", - } - names := cfg.NameList("miek.nl") - - if len(names) != 2 { - t.Errorf("NameList returned != 2 names: %v", names) - } else if names[0] != "miek.nl.test." { - t.Errorf("NameList didn't return search first: %v", names[0]) - } else if names[1] != "miek.nl." { - t.Errorf("NameList didn't return sent domain last: %v", names[1]) - } -} - -func TestNameListNdots0(t *testing.T) { - cfg := ClientConfig{ - Ndots: 0, - } - cfg.Search = []string{ - "test", - } - // Sent domain has less than NDots and search - names := cfg.NameList("miek") - if len(names) != 2 { - t.Errorf("NameList returned != 2 names: %v", names) - } else if names[0] != "miek." { - t.Errorf("NameList didn't return search first: %v", names[0]) - } else if names[1] != "miek.test." { - t.Errorf("NameList didn't return sent domain last: %v", names[1]) - } -} diff --git a/vendor/github.com/miekg/dns/dns_bench_test.go b/vendor/github.com/miekg/dns/dns_bench_test.go deleted file mode 100644 index 7bf8bd211..000000000 --- a/vendor/github.com/miekg/dns/dns_bench_test.go +++ /dev/null @@ -1,230 +0,0 @@ -package dns - -import ( - "net" - "testing" -) - -func BenchmarkMsgLength(b *testing.B) { - b.StopTimer() - makeMsg := func(question string, ans, ns, e []RR) *Msg { - msg := new(Msg) - msg.SetQuestion(Fqdn(question), TypeANY) - msg.Answer = append(msg.Answer, ans...) - msg.Ns = append(msg.Ns, ns...) - msg.Extra = append(msg.Extra, e...) - msg.Compress = true - return msg - } - name1 := "12345678901234567890123456789012345.12345678.123." - rrMx := testRR(name1 + " 3600 IN MX 10 " + name1) - msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil) - b.StartTimer() - for i := 0; i < b.N; i++ { - msg.Len() - } -} - -func BenchmarkMsgLengthNoCompression(b *testing.B) { - b.StopTimer() - makeMsg := func(question string, ans, ns, e []RR) *Msg { - msg := new(Msg) - msg.SetQuestion(Fqdn(question), TypeANY) - msg.Answer = append(msg.Answer, ans...) - msg.Ns = append(msg.Ns, ns...) - msg.Extra = append(msg.Extra, e...) - return msg - } - name1 := "12345678901234567890123456789012345.12345678.123." - rrMx := testRR(name1 + " 3600 IN MX 10 " + name1) - msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil) - b.StartTimer() - for i := 0; i < b.N; i++ { - msg.Len() - } -} - -func BenchmarkMsgLengthPack(b *testing.B) { - makeMsg := func(question string, ans, ns, e []RR) *Msg { - msg := new(Msg) - msg.SetQuestion(Fqdn(question), TypeANY) - msg.Answer = append(msg.Answer, ans...) - msg.Ns = append(msg.Ns, ns...) - msg.Extra = append(msg.Extra, e...) - msg.Compress = true - return msg - } - name1 := "12345678901234567890123456789012345.12345678.123." - rrMx := testRR(name1 + " 3600 IN MX 10 " + name1) - msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = msg.Pack() - } -} - -func BenchmarkPackDomainName(b *testing.B) { - name1 := "12345678901234567890123456789012345.12345678.123." - buf := make([]byte, len(name1)+1) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = PackDomainName(name1, buf, 0, nil, false) - } -} - -func BenchmarkUnpackDomainName(b *testing.B) { - name1 := "12345678901234567890123456789012345.12345678.123." - buf := make([]byte, len(name1)+1) - _, _ = PackDomainName(name1, buf, 0, nil, false) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _, _ = UnpackDomainName(buf, 0) - } -} - -func BenchmarkUnpackDomainNameUnprintable(b *testing.B) { - name1 := "\x02\x02\x02\x025\x02\x02\x02\x02.12345678.123." - buf := make([]byte, len(name1)+1) - _, _ = PackDomainName(name1, buf, 0, nil, false) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _, _ = UnpackDomainName(buf, 0) - } -} - -func BenchmarkCopy(b *testing.B) { - b.ReportAllocs() - m := new(Msg) - m.SetQuestion("miek.nl.", TypeA) - rr := testRR("miek.nl. 2311 IN A 127.0.0.1") - m.Answer = []RR{rr} - rr = testRR("miek.nl. 2311 IN NS 127.0.0.1") - m.Ns = []RR{rr} - rr = testRR("miek.nl. 2311 IN A 127.0.0.1") - m.Extra = []RR{rr} - - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.Copy() - } -} - -func BenchmarkPackA(b *testing.B) { - a := &A{Hdr: RR_Header{Name: ".", Rrtype: TypeA, Class: ClassANY}, A: net.IPv4(127, 0, 0, 1)} - - buf := make([]byte, a.len()) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = PackRR(a, buf, 0, nil, false) - } -} - -func BenchmarkUnpackA(b *testing.B) { - a := &A{Hdr: RR_Header{Name: ".", Rrtype: TypeA, Class: ClassANY}, A: net.IPv4(127, 0, 0, 1)} - - buf := make([]byte, a.len()) - PackRR(a, buf, 0, nil, false) - a = nil - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _, _ = UnpackRR(buf, 0) - } -} - -func BenchmarkPackMX(b *testing.B) { - m := &MX{Hdr: RR_Header{Name: ".", Rrtype: TypeA, Class: ClassANY}, Mx: "mx.miek.nl."} - - buf := make([]byte, m.len()) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = PackRR(m, buf, 0, nil, false) - } -} - -func BenchmarkUnpackMX(b *testing.B) { - m := &MX{Hdr: RR_Header{Name: ".", Rrtype: TypeA, Class: ClassANY}, Mx: "mx.miek.nl."} - - buf := make([]byte, m.len()) - PackRR(m, buf, 0, nil, false) - m = nil - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _, _ = UnpackRR(buf, 0) - } -} - -func BenchmarkPackAAAAA(b *testing.B) { - aaaa := testRR(". IN A ::1") - - buf := make([]byte, aaaa.len()) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = PackRR(aaaa, buf, 0, nil, false) - } -} - -func BenchmarkUnpackAAAA(b *testing.B) { - aaaa := testRR(". IN A ::1") - - buf := make([]byte, aaaa.len()) - PackRR(aaaa, buf, 0, nil, false) - aaaa = nil - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _, _ = UnpackRR(buf, 0) - } -} - -func BenchmarkPackMsg(b *testing.B) { - makeMsg := func(question string, ans, ns, e []RR) *Msg { - msg := new(Msg) - msg.SetQuestion(Fqdn(question), TypeANY) - msg.Answer = append(msg.Answer, ans...) - msg.Ns = append(msg.Ns, ns...) - msg.Extra = append(msg.Extra, e...) - msg.Compress = true - return msg - } - name1 := "12345678901234567890123456789012345.12345678.123." - rrMx := testRR(name1 + " 3600 IN MX 10 " + name1) - msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil) - buf := make([]byte, 512) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = msg.PackBuffer(buf) - } -} - -func BenchmarkUnpackMsg(b *testing.B) { - makeMsg := func(question string, ans, ns, e []RR) *Msg { - msg := new(Msg) - msg.SetQuestion(Fqdn(question), TypeANY) - msg.Answer = append(msg.Answer, ans...) - msg.Ns = append(msg.Ns, ns...) - msg.Extra = append(msg.Extra, e...) - msg.Compress = true - return msg - } - name1 := "12345678901234567890123456789012345.12345678.123." - rrMx := testRR(name1 + " 3600 IN MX 10 " + name1) - msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil) - msgBuf, _ := msg.Pack() - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = msg.Unpack(msgBuf) - } -} - -func BenchmarkIdGeneration(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = id() - } -} diff --git a/vendor/github.com/miekg/dns/dns_test.go b/vendor/github.com/miekg/dns/dns_test.go deleted file mode 100644 index e7b24c120..000000000 --- a/vendor/github.com/miekg/dns/dns_test.go +++ /dev/null @@ -1,318 +0,0 @@ -package dns - -import ( - "bytes" - "encoding/hex" - "net" - "testing" -) - -func TestPackUnpack(t *testing.T) { - out := new(Msg) - out.Answer = make([]RR, 1) - key := new(DNSKEY) - key = &DNSKEY{Flags: 257, Protocol: 3, Algorithm: RSASHA1} - key.Hdr = RR_Header{Name: "miek.nl.", Rrtype: TypeDNSKEY, Class: ClassINET, Ttl: 3600} - key.PublicKey = "AwEAAaHIwpx3w4VHKi6i1LHnTaWeHCL154Jug0Rtc9ji5qwPXpBo6A5sRv7cSsPQKPIwxLpyCrbJ4mr2L0EPOdvP6z6YfljK2ZmTbogU9aSU2fiq/4wjxbdkLyoDVgtO+JsxNN4bjr4WcWhsmk1Hg93FV9ZpkWb0Tbad8DFqNDzr//kZ" - - out.Answer[0] = key - msg, err := out.Pack() - if err != nil { - t.Error("failed to pack msg with DNSKEY") - } - in := new(Msg) - if in.Unpack(msg) != nil { - t.Error("failed to unpack msg with DNSKEY") - } - - sig := new(RRSIG) - sig = &RRSIG{TypeCovered: TypeDNSKEY, Algorithm: RSASHA1, Labels: 2, - OrigTtl: 3600, Expiration: 4000, Inception: 4000, KeyTag: 34641, SignerName: "miek.nl.", - Signature: "AwEAAaHIwpx3w4VHKi6i1LHnTaWeHCL154Jug0Rtc9ji5qwPXpBo6A5sRv7cSsPQKPIwxLpyCrbJ4mr2L0EPOdvP6z6YfljK2ZmTbogU9aSU2fiq/4wjxbdkLyoDVgtO+JsxNN4bjr4WcWhsmk1Hg93FV9ZpkWb0Tbad8DFqNDzr//kZ"} - sig.Hdr = RR_Header{Name: "miek.nl.", Rrtype: TypeRRSIG, Class: ClassINET, Ttl: 3600} - - out.Answer[0] = sig - msg, err = out.Pack() - if err != nil { - t.Error("failed to pack msg with RRSIG") - } - - if in.Unpack(msg) != nil { - t.Error("failed to unpack msg with RRSIG") - } -} - -func TestPackUnpack2(t *testing.T) { - m := new(Msg) - m.Extra = make([]RR, 1) - m.Answer = make([]RR, 1) - dom := "miek.nl." - rr := new(A) - rr.Hdr = RR_Header{Name: dom, Rrtype: TypeA, Class: ClassINET, Ttl: 0} - rr.A = net.IPv4(127, 0, 0, 1) - - x := new(TXT) - x.Hdr = RR_Header{Name: dom, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0} - x.Txt = []string{"heelalaollo"} - - m.Extra[0] = x - m.Answer[0] = rr - _, err := m.Pack() - if err != nil { - t.Error("Packing failed: ", err) - return - } -} - -func TestPackUnpack3(t *testing.T) { - m := new(Msg) - m.Extra = make([]RR, 2) - m.Answer = make([]RR, 1) - dom := "miek.nl." - rr := new(A) - rr.Hdr = RR_Header{Name: dom, Rrtype: TypeA, Class: ClassINET, Ttl: 0} - rr.A = net.IPv4(127, 0, 0, 1) - - x1 := new(TXT) - x1.Hdr = RR_Header{Name: dom, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0} - x1.Txt = []string{} - - x2 := new(TXT) - x2.Hdr = RR_Header{Name: dom, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0} - x2.Txt = []string{"heelalaollo"} - - m.Extra[0] = x1 - m.Extra[1] = x2 - m.Answer[0] = rr - b, err := m.Pack() - if err != nil { - t.Error("packing failed: ", err) - return - } - - var unpackMsg Msg - err = unpackMsg.Unpack(b) - if err != nil { - t.Error("unpacking failed") - return - } -} - -func TestBailiwick(t *testing.T) { - yes := map[string]string{ - "miek1.nl": "miek1.nl", - "miek.nl": "ns.miek.nl", - ".": "miek.nl", - } - for parent, child := range yes { - if !IsSubDomain(parent, child) { - t.Errorf("%s should be child of %s", child, parent) - t.Errorf("comparelabels %d", CompareDomainName(parent, child)) - t.Errorf("lenlabels %d %d", CountLabel(parent), CountLabel(child)) - } - } - no := map[string]string{ - "www.miek.nl": "ns.miek.nl", - "m\\.iek.nl": "ns.miek.nl", - "w\\.iek.nl": "w.iek.nl", - "p\\\\.iek.nl": "ns.p.iek.nl", // p\\.iek.nl , literal \ in domain name - "miek.nl": ".", - } - for parent, child := range no { - if IsSubDomain(parent, child) { - t.Errorf("%s should not be child of %s", child, parent) - t.Errorf("comparelabels %d", CompareDomainName(parent, child)) - t.Errorf("lenlabels %d %d", CountLabel(parent), CountLabel(child)) - } - } -} - -func TestPackNAPTR(t *testing.T) { - for _, n := range []string{ - `apple.com. IN NAPTR 100 50 "se" "SIP+D2U" "" _sip._udp.apple.com.`, - `apple.com. IN NAPTR 90 50 "se" "SIP+D2T" "" _sip._tcp.apple.com.`, - `apple.com. IN NAPTR 50 50 "se" "SIPS+D2T" "" _sips._tcp.apple.com.`, - } { - rr := testRR(n) - msg := make([]byte, rr.len()) - if off, err := PackRR(rr, msg, 0, nil, false); err != nil { - t.Errorf("packing failed: %v", err) - t.Errorf("length %d, need more than %d", rr.len(), off) - } - } -} - -func TestToRFC3597(t *testing.T) { - a := testRR("miek.nl. IN A 10.0.1.1") - x := new(RFC3597) - x.ToRFC3597(a) - if x.String() != `miek.nl. 3600 CLASS1 TYPE1 \# 4 0a000101` { - t.Errorf("string mismatch, got: %s", x) - } - - b := testRR("miek.nl. IN MX 10 mx.miek.nl.") - x.ToRFC3597(b) - if x.String() != `miek.nl. 3600 CLASS1 TYPE15 \# 14 000a026d78046d69656b026e6c00` { - t.Errorf("string mismatch, got: %s", x) - } -} - -func TestNoRdataPack(t *testing.T) { - data := make([]byte, 1024) - for typ, fn := range TypeToRR { - r := fn() - *r.Header() = RR_Header{Name: "miek.nl.", Rrtype: typ, Class: ClassINET, Ttl: 16} - _, err := PackRR(r, data, 0, nil, false) - if err != nil { - t.Errorf("failed to pack RR with zero rdata: %s: %v", TypeToString[typ], err) - } - } -} - -func TestNoRdataUnpack(t *testing.T) { - data := make([]byte, 1024) - for typ, fn := range TypeToRR { - if typ == TypeSOA || typ == TypeTSIG || typ == TypeTKEY { - // SOA, TSIG will not be seen (like this) in dyn. updates? - // TKEY requires length fields to be present for the Key and OtherData fields - continue - } - r := fn() - *r.Header() = RR_Header{Name: "miek.nl.", Rrtype: typ, Class: ClassINET, Ttl: 16} - off, err := PackRR(r, data, 0, nil, false) - if err != nil { - // Should always works, TestNoDataPack should have caught this - t.Errorf("failed to pack RR: %v", err) - continue - } - if _, _, err := UnpackRR(data[:off], 0); err != nil { - t.Errorf("failed to unpack RR with zero rdata: %s: %v", TypeToString[typ], err) - } - } -} - -func TestRdataOverflow(t *testing.T) { - rr := new(RFC3597) - rr.Hdr.Name = "." - rr.Hdr.Class = ClassINET - rr.Hdr.Rrtype = 65280 - rr.Rdata = hex.EncodeToString(make([]byte, 0xFFFF)) - buf := make([]byte, 0xFFFF*2) - if _, err := PackRR(rr, buf, 0, nil, false); err != nil { - t.Fatalf("maximum size rrdata pack failed: %v", err) - } - rr.Rdata += "00" - if _, err := PackRR(rr, buf, 0, nil, false); err != ErrRdata { - t.Fatalf("oversize rrdata pack didn't return ErrRdata - instead: %v", err) - } -} - -func TestCopy(t *testing.T) { - rr := testRR("miek.nl. 2311 IN A 127.0.0.1") // Weird TTL to avoid catching TTL - rr1 := Copy(rr) - if rr.String() != rr1.String() { - t.Fatalf("Copy() failed %s != %s", rr.String(), rr1.String()) - } -} - -func TestMsgCopy(t *testing.T) { - m := new(Msg) - m.SetQuestion("miek.nl.", TypeA) - rr := testRR("miek.nl. 2311 IN A 127.0.0.1") - m.Answer = []RR{rr} - rr = testRR("miek.nl. 2311 IN NS 127.0.0.1") - m.Ns = []RR{rr} - - m1 := m.Copy() - if m.String() != m1.String() { - t.Fatalf("Msg.Copy() failed %s != %s", m.String(), m1.String()) - } - - m1.Answer[0] = testRR("somethingelse.nl. 2311 IN A 127.0.0.1") - if m.String() == m1.String() { - t.Fatalf("Msg.Copy() failed; change to copy changed template %s", m.String()) - } - - rr = testRR("miek.nl. 2311 IN A 127.0.0.2") - m1.Answer = append(m1.Answer, rr) - if m1.Ns[0].String() == m1.Answer[1].String() { - t.Fatalf("Msg.Copy() failed; append changed underlying array %s", m1.Ns[0].String()) - } -} - -func TestMsgPackBuffer(t *testing.T) { - var testMessages = []string{ - // news.ycombinator.com.in.escapemg.com. IN A, response - "586285830001000000010000046e6577730b79636f6d62696e61746f7203636f6d02696e086573636170656d6703636f6d0000010001c0210006000100000e10002c036e7332c02103646e730b67726f6f7665736861726bc02d77ed50e600002a3000000e1000093a8000000e10", - - // news.ycombinator.com.in.escapemg.com. IN A, question - "586201000001000000000000046e6577730b79636f6d62696e61746f7203636f6d02696e086573636170656d6703636f6d0000010001", - - "398781020001000000000000046e6577730b79636f6d62696e61746f7203636f6d0000010001", - } - - for i, hexData := range testMessages { - // we won't fail the decoding of the hex - input, _ := hex.DecodeString(hexData) - m := new(Msg) - if err := m.Unpack(input); err != nil { - t.Errorf("packet %d failed to unpack", i) - continue - } - } -} - -// Make sure we can decode a TKEY packet from the string, modify the RR, and then pack it again. -func TestTKEY(t *testing.T) { - // An example TKEY RR captured. There is no known accepted standard text format for a TKEY - // record so we do this from a hex string instead of from a text readable string. - tkeyStr := "0737362d6d732d370932322d3332633233332463303439663961662d633065612d313165372d363839362d6463333937396666656666640000f900ff0000000000d2086773732d747369670059fd01f359fe53730003000000b8a181b53081b2a0030a0100a10b06092a864882f712010202a2819d04819a60819706092a864886f71201020202006f8187308184a003020105a10302010fa2783076a003020112a26f046db29b1b1d2625da3b20b49dafef930dd1e9aad335e1c5f45dcd95e0005d67a1100f3e573d70506659dbed064553f1ab890f68f65ae10def0dad5b423b39f240ebe666f2886c5fe03819692d29182bbed87b83e1f9d16b7334ec16a3c4fc5ad4a990088e0be43f0c6957916f5fe60000" - tkeyBytes, err := hex.DecodeString(tkeyStr) - if err != nil { - t.Fatal("unable to decode TKEY string ", err) - } - // Decode the RR - rr, tkeyLen, unPackErr := UnpackRR(tkeyBytes, 0) - if unPackErr != nil { - t.Fatal("unable to decode TKEY RR", unPackErr) - } - // Make sure it's a TKEY record - if rr.Header().Rrtype != TypeTKEY { - t.Fatal("Unable to decode TKEY") - } - // Make sure we get back the same length - if rr.len() != len(tkeyBytes) { - t.Fatalf("Lengths don't match %d != %d", rr.len(), len(tkeyBytes)) - } - // make space for it with some fudge room - msg := make([]byte, tkeyLen+1000) - offset, packErr := PackRR(rr, msg, 0, nil, false) - if packErr != nil { - t.Fatal("unable to pack TKEY RR", packErr) - } - if offset != len(tkeyBytes) { - t.Fatalf("mismatched TKEY RR size %d != %d", len(tkeyBytes), offset) - } - if bytes.Compare(tkeyBytes, msg[0:offset]) != 0 { - t.Fatal("mismatched TKEY data after rewriting bytes") - } - - // Now add some bytes to this and make sure we can encode OtherData properly - tkey := rr.(*TKEY) - tkey.OtherData = "abcd" - tkey.OtherLen = 2 - offset, packErr = PackRR(tkey, msg, 0, nil, false) - if packErr != nil { - t.Fatal("unable to pack TKEY RR after modification", packErr) - } - if offset != len(tkeyBytes)+2 { - t.Fatalf("mismatched TKEY RR size %d != %d", offset, len(tkeyBytes)+2) - } - - // Make sure we can parse our string output - tkey.Hdr.Class = ClassINET // https://github.com/miekg/dns/issues/577 - _, newError := NewRR(tkey.String()) - if newError != nil { - t.Fatalf("unable to parse TKEY string: %s", newError) - } -} diff --git a/vendor/github.com/miekg/dns/dnssec_keyscan.go b/vendor/github.com/miekg/dns/dnssec_keyscan.go index 719198659..5e6542230 100644 --- a/vendor/github.com/miekg/dns/dnssec_keyscan.go +++ b/vendor/github.com/miekg/dns/dnssec_keyscan.go @@ -1,6 +1,7 @@ package dns import ( + "bufio" "crypto" "crypto/dsa" "crypto/ecdsa" @@ -194,23 +195,12 @@ func readPrivateKeyED25519(m map[string]string) (ed25519.PrivateKey, error) { // parseKey reads a private key from r. It returns a map[string]string, // with the key-value pairs, or an error when the file is not correct. func parseKey(r io.Reader, file string) (map[string]string, error) { - s, cancel := scanInit(r) m := make(map[string]string) - c := make(chan lex) - k := "" - defer func() { - cancel() - // zlexer can send up to two tokens, the next one and possibly 1 remainders. - // Do a non-blocking read. - _, ok := <-c - _, ok = <-c - if !ok { - // too bad - } - }() - // Start the lexer - go klexer(s, c) - for l := range c { + var k string + + c := newKLexer(r) + + for l, ok := c.Next(); ok; l, ok = c.Next() { // It should alternate switch l.value { case zKey: @@ -219,41 +209,111 @@ func parseKey(r io.Reader, file string) (map[string]string, error) { if k == "" { return nil, &ParseError{file, "no private key seen", l} } - //println("Setting", strings.ToLower(k), "to", l.token, "b") + m[strings.ToLower(k)] = l.token k = "" } } + + // Surface any read errors from r. + if err := c.Err(); err != nil { + return nil, &ParseError{file: file, err: err.Error()} + } + return m, nil } -// klexer scans the sourcefile and returns tokens on the channel c. -func klexer(s *scan, c chan lex) { - var l lex - str := "" // Hold the current read text - commt := false - key := true - x, err := s.tokenText() - defer close(c) - for err == nil { - l.column = s.position.Column - l.line = s.position.Line +type klexer struct { + br io.ByteReader + + readErr error + + line int + column int + + key bool + + eol bool // end-of-line +} + +func newKLexer(r io.Reader) *klexer { + br, ok := r.(io.ByteReader) + if !ok { + br = bufio.NewReaderSize(r, 1024) + } + + return &klexer{ + br: br, + + line: 1, + + key: true, + } +} + +func (kl *klexer) Err() error { + if kl.readErr == io.EOF { + return nil + } + + return kl.readErr +} + +// readByte returns the next byte from the input +func (kl *klexer) readByte() (byte, bool) { + if kl.readErr != nil { + return 0, false + } + + c, err := kl.br.ReadByte() + if err != nil { + kl.readErr = err + return 0, false + } + + // delay the newline handling until the next token is delivered, + // fixes off-by-one errors when reporting a parse error. + if kl.eol { + kl.line++ + kl.column = 0 + kl.eol = false + } + + if c == '\n' { + kl.eol = true + } else { + kl.column++ + } + + return c, true +} + +func (kl *klexer) Next() (lex, bool) { + var ( + l lex + + str strings.Builder + + commt bool + ) + + for x, ok := kl.readByte(); ok; x, ok = kl.readByte() { + l.line, l.column = kl.line, kl.column + switch x { case ':': - if commt { + if commt || !kl.key { break } - l.token = str - if key { - l.value = zKey - c <- l - // Next token is a space, eat it - s.tokenText() - key = false - str = "" - } else { - l.value = zValue - } + + kl.key = false + + // Next token is a space, eat it + kl.readByte() + + l.value = zKey + l.token = str.String() + return l, true case ';': commt = true case '\n': @@ -261,24 +321,32 @@ func klexer(s *scan, c chan lex) { // Reset a comment commt = false } + + kl.key = true + l.value = zValue - l.token = str - c <- l - str = "" - commt = false - key = true + l.token = str.String() + return l, true default: if commt { break } - str += string(x) + + str.WriteByte(x) } - x, err = s.tokenText() } - if len(str) > 0 { + + if kl.readErr != nil && kl.readErr != io.EOF { + // Don't return any tokens after a read error occurs. + return lex{value: zEOF}, false + } + + if str.Len() > 0 { // Send remainder - l.token = str l.value = zValue - c <- l + l.token = str.String() + return l, true } + + return lex{value: zEOF}, false } diff --git a/vendor/github.com/miekg/dns/dnssec_test.go b/vendor/github.com/miekg/dns/dnssec_test.go deleted file mode 100644 index 2dea4e507..000000000 --- a/vendor/github.com/miekg/dns/dnssec_test.go +++ /dev/null @@ -1,860 +0,0 @@ -package dns - -import ( - "crypto" - "crypto/ecdsa" - "crypto/rsa" - "reflect" - "strings" - "testing" - "time" - - "golang.org/x/crypto/ed25519" -) - -func getKey() *DNSKEY { - key := new(DNSKEY) - key.Hdr.Name = "miek.nl." - key.Hdr.Class = ClassINET - key.Hdr.Ttl = 14400 - key.Flags = 256 - key.Protocol = 3 - key.Algorithm = RSASHA256 - key.PublicKey = "AwEAAcNEU67LJI5GEgF9QLNqLO1SMq1EdoQ6E9f85ha0k0ewQGCblyW2836GiVsm6k8Kr5ECIoMJ6fZWf3CQSQ9ycWfTyOHfmI3eQ/1Covhb2y4bAmL/07PhrL7ozWBW3wBfM335Ft9xjtXHPy7ztCbV9qZ4TVDTW/Iyg0PiwgoXVesz" - return key -} - -func getSoa() *SOA { - soa := new(SOA) - soa.Hdr = RR_Header{"miek.nl.", TypeSOA, ClassINET, 14400, 0} - soa.Ns = "open.nlnetlabs.nl." - soa.Mbox = "miekg.atoom.net." - soa.Serial = 1293945905 - soa.Refresh = 14400 - soa.Retry = 3600 - soa.Expire = 604800 - soa.Minttl = 86400 - return soa -} - -func TestSecure(t *testing.T) { - soa := getSoa() - - sig := new(RRSIG) - sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0} - sig.TypeCovered = TypeSOA - sig.Algorithm = RSASHA256 - sig.Labels = 2 - sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05" - sig.Inception = 1293942305 // date -u '+%s' -d"2011-01-02 04:25:05" - sig.OrigTtl = 14400 - sig.KeyTag = 12051 - sig.SignerName = "miek.nl." - sig.Signature = "oMCbslaAVIp/8kVtLSms3tDABpcPRUgHLrOR48OOplkYo+8TeEGWwkSwaz/MRo2fB4FxW0qj/hTlIjUGuACSd+b1wKdH5GvzRJc2pFmxtCbm55ygAh4EUL0F6U5cKtGJGSXxxg6UFCQ0doJCmiGFa78LolaUOXImJrk6AFrGa0M=" - - key := new(DNSKEY) - key.Hdr.Name = "miek.nl." - key.Hdr.Class = ClassINET - key.Hdr.Ttl = 14400 - key.Flags = 256 - key.Protocol = 3 - key.Algorithm = RSASHA256 - key.PublicKey = "AwEAAcNEU67LJI5GEgF9QLNqLO1SMq1EdoQ6E9f85ha0k0ewQGCblyW2836GiVsm6k8Kr5ECIoMJ6fZWf3CQSQ9ycWfTyOHfmI3eQ/1Covhb2y4bAmL/07PhrL7ozWBW3wBfM335Ft9xjtXHPy7ztCbV9qZ4TVDTW/Iyg0PiwgoXVesz" - - // It should validate. Period is checked separately, so this will keep on working - if sig.Verify(key, []RR{soa}) != nil { - t.Error("failure to validate") - } -} - -func TestSignature(t *testing.T) { - sig := new(RRSIG) - sig.Hdr.Name = "miek.nl." - sig.Hdr.Class = ClassINET - sig.Hdr.Ttl = 3600 - sig.TypeCovered = TypeDNSKEY - sig.Algorithm = RSASHA1 - sig.Labels = 2 - sig.OrigTtl = 4000 - sig.Expiration = 1000 //Thu Jan 1 02:06:40 CET 1970 - sig.Inception = 800 //Thu Jan 1 01:13:20 CET 1970 - sig.KeyTag = 34641 - sig.SignerName = "miek.nl." - sig.Signature = "AwEAAaHIwpx3w4VHKi6i1LHnTaWeHCL154Jug0Rtc9ji5qwPXpBo6A5sRv7cSsPQKPIwxLpyCrbJ4mr2L0EPOdvP6z6YfljK2ZmTbogU9aSU2fiq/4wjxbdkLyoDVgtO+JsxNN4bjr4WcWhsmk1Hg93FV9ZpkWb0Tbad8DFqNDzr//kZ" - - // Should not be valid - if sig.ValidityPeriod(time.Now()) { - t.Error("should not be valid") - } - - sig.Inception = 315565800 //Tue Jan 1 10:10:00 CET 1980 - sig.Expiration = 4102477800 //Fri Jan 1 10:10:00 CET 2100 - if !sig.ValidityPeriod(time.Now()) { - t.Error("should be valid") - } -} - -func TestSignVerify(t *testing.T) { - // The record we want to sign - soa := new(SOA) - soa.Hdr = RR_Header{"miek.nl.", TypeSOA, ClassINET, 14400, 0} - soa.Ns = "open.nlnetlabs.nl." - soa.Mbox = "miekg.atoom.net." - soa.Serial = 1293945905 - soa.Refresh = 14400 - soa.Retry = 3600 - soa.Expire = 604800 - soa.Minttl = 86400 - - soa1 := new(SOA) - soa1.Hdr = RR_Header{"*.miek.nl.", TypeSOA, ClassINET, 14400, 0} - soa1.Ns = "open.nlnetlabs.nl." - soa1.Mbox = "miekg.atoom.net." - soa1.Serial = 1293945905 - soa1.Refresh = 14400 - soa1.Retry = 3600 - soa1.Expire = 604800 - soa1.Minttl = 86400 - - srv := new(SRV) - srv.Hdr = RR_Header{"srv.miek.nl.", TypeSRV, ClassINET, 14400, 0} - srv.Port = 1000 - srv.Weight = 800 - srv.Target = "web1.miek.nl." - - hinfo := &HINFO{ - Hdr: RR_Header{ - Name: "miek.nl.", - Rrtype: TypeHINFO, - Class: ClassINET, - Ttl: 3789, - }, - Cpu: "X", - Os: "Y", - } - - // With this key - key := new(DNSKEY) - key.Hdr.Rrtype = TypeDNSKEY - key.Hdr.Name = "miek.nl." - key.Hdr.Class = ClassINET - key.Hdr.Ttl = 14400 - key.Flags = 256 - key.Protocol = 3 - key.Algorithm = RSASHA256 - privkey, _ := key.Generate(512) - - // Fill in the values of the Sig, before signing - sig := new(RRSIG) - sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0} - sig.TypeCovered = soa.Hdr.Rrtype - sig.Labels = uint8(CountLabel(soa.Hdr.Name)) // works for all 3 - sig.OrigTtl = soa.Hdr.Ttl - sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05" - sig.Inception = 1293942305 // date -u '+%s' -d"2011-01-02 04:25:05" - sig.KeyTag = key.KeyTag() // Get the keyfrom the Key - sig.SignerName = key.Hdr.Name - sig.Algorithm = RSASHA256 - - for _, r := range []RR{soa, soa1, srv, hinfo} { - if err := sig.Sign(privkey.(*rsa.PrivateKey), []RR{r}); err != nil { - t.Error("failure to sign the record:", err) - continue - } - if err := sig.Verify(key, []RR{r}); err != nil { - t.Errorf("failure to validate: %s", r.Header().Name) - continue - } - } -} - -func Test65534(t *testing.T) { - t6 := new(RFC3597) - t6.Hdr = RR_Header{"miek.nl.", 65534, ClassINET, 14400, 0} - t6.Rdata = "505D870001" - key := new(DNSKEY) - key.Hdr.Name = "miek.nl." - key.Hdr.Rrtype = TypeDNSKEY - key.Hdr.Class = ClassINET - key.Hdr.Ttl = 14400 - key.Flags = 256 - key.Protocol = 3 - key.Algorithm = RSASHA256 - privkey, _ := key.Generate(1024) - - sig := new(RRSIG) - sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0} - sig.TypeCovered = t6.Hdr.Rrtype - sig.Labels = uint8(CountLabel(t6.Hdr.Name)) - sig.OrigTtl = t6.Hdr.Ttl - sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05" - sig.Inception = 1293942305 // date -u '+%s' -d"2011-01-02 04:25:05" - sig.KeyTag = key.KeyTag() - sig.SignerName = key.Hdr.Name - sig.Algorithm = RSASHA256 - if err := sig.Sign(privkey.(*rsa.PrivateKey), []RR{t6}); err != nil { - t.Error(err) - t.Error("failure to sign the TYPE65534 record") - } - if err := sig.Verify(key, []RR{t6}); err != nil { - t.Error(err) - t.Errorf("failure to validate %s", t6.Header().Name) - } -} - -func TestDnskey(t *testing.T) { - pubkey, err := ReadRR(strings.NewReader(` -miek.nl. IN DNSKEY 256 3 10 AwEAAZuMCu2FdugHkTrXYgl5qixvcDw1aDDlvL46/xJKbHBAHY16fNUb2b65cwko2Js/aJxUYJbZk5dwCDZxYfrfbZVtDPQuc3o8QaChVxC7/JYz2AHc9qHvqQ1j4VrH71RWINlQo6VYjzN/BGpMhOZoZOEwzp1HfsOE3lNYcoWU1smL ;{id = 5240 (zsk), size = 1024b} -`), "Kmiek.nl.+010+05240.key") - if err != nil { - t.Fatal(err) - } - privStr := `Private-key-format: v1.3 -Algorithm: 10 (RSASHA512) -Modulus: m4wK7YV26AeROtdiCXmqLG9wPDVoMOW8vjr/EkpscEAdjXp81RvZvrlzCSjYmz9onFRgltmTl3AINnFh+t9tlW0M9C5zejxBoKFXELv8ljPYAdz2oe+pDWPhWsfvVFYg2VCjpViPM38EakyE5mhk4TDOnUd+w4TeU1hyhZTWyYs= -PublicExponent: AQAB -PrivateExponent: UfCoIQ/Z38l8vB6SSqOI/feGjHEl/fxIPX4euKf0D/32k30fHbSaNFrFOuIFmWMB3LimWVEs6u3dpbB9CQeCVg7hwU5puG7OtuiZJgDAhNeOnxvo5btp4XzPZrJSxR4WNQnwIiYWbl0aFlL1VGgHC/3By89ENZyWaZcMLW4KGWE= -Prime1: yxwC6ogAu8aVcDx2wg1V0b5M5P6jP8qkRFVMxWNTw60Vkn+ECvw6YAZZBHZPaMyRYZLzPgUlyYRd0cjupy4+fQ== -Prime2: xA1bF8M0RTIQ6+A11AoVG6GIR/aPGg5sogRkIZ7ID/sF6g9HMVU/CM2TqVEBJLRPp73cv6ZeC3bcqOCqZhz+pw== -Exponent1: xzkblyZ96bGYxTVZm2/vHMOXswod4KWIyMoOepK6B/ZPcZoIT6omLCgtypWtwHLfqyCz3MK51Nc0G2EGzg8rFQ== -Exponent2: Pu5+mCEb7T5F+kFNZhQadHUklt0JUHbi3hsEvVoHpEGSw3BGDQrtIflDde0/rbWHgDPM4WQY+hscd8UuTXrvLw== -Coefficient: UuRoNqe7YHnKmQzE6iDWKTMIWTuoqqrFAmXPmKQnC+Y+BQzOVEHUo9bXdDnoI9hzXP1gf8zENMYwYLeWpuYlFQ== -` - privkey, err := pubkey.(*DNSKEY).ReadPrivateKey(strings.NewReader(privStr), - "Kmiek.nl.+010+05240.private") - if err != nil { - t.Fatal(err) - } - if pubkey.(*DNSKEY).PublicKey != "AwEAAZuMCu2FdugHkTrXYgl5qixvcDw1aDDlvL46/xJKbHBAHY16fNUb2b65cwko2Js/aJxUYJbZk5dwCDZxYfrfbZVtDPQuc3o8QaChVxC7/JYz2AHc9qHvqQ1j4VrH71RWINlQo6VYjzN/BGpMhOZoZOEwzp1HfsOE3lNYcoWU1smL" { - t.Error("pubkey is not what we've read") - } - if pubkey.(*DNSKEY).PrivateKeyString(privkey) != privStr { - t.Error("privkey is not what we've read") - t.Errorf("%v", pubkey.(*DNSKEY).PrivateKeyString(privkey)) - } -} - -func TestTag(t *testing.T) { - key := new(DNSKEY) - key.Hdr.Name = "miek.nl." - key.Hdr.Rrtype = TypeDNSKEY - key.Hdr.Class = ClassINET - key.Hdr.Ttl = 3600 - key.Flags = 256 - key.Protocol = 3 - key.Algorithm = RSASHA256 - key.PublicKey = "AwEAAcNEU67LJI5GEgF9QLNqLO1SMq1EdoQ6E9f85ha0k0ewQGCblyW2836GiVsm6k8Kr5ECIoMJ6fZWf3CQSQ9ycWfTyOHfmI3eQ/1Covhb2y4bAmL/07PhrL7ozWBW3wBfM335Ft9xjtXHPy7ztCbV9qZ4TVDTW/Iyg0PiwgoXVesz" - - tag := key.KeyTag() - if tag != 12051 { - t.Errorf("wrong key tag: %d for key %v", tag, key) - } -} - -func TestKeyRSA(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - key := new(DNSKEY) - key.Hdr.Name = "miek.nl." - key.Hdr.Rrtype = TypeDNSKEY - key.Hdr.Class = ClassINET - key.Hdr.Ttl = 3600 - key.Flags = 256 - key.Protocol = 3 - key.Algorithm = RSASHA256 - priv, _ := key.Generate(2048) - - soa := new(SOA) - soa.Hdr = RR_Header{"miek.nl.", TypeSOA, ClassINET, 14400, 0} - soa.Ns = "open.nlnetlabs.nl." - soa.Mbox = "miekg.atoom.net." - soa.Serial = 1293945905 - soa.Refresh = 14400 - soa.Retry = 3600 - soa.Expire = 604800 - soa.Minttl = 86400 - - sig := new(RRSIG) - sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0} - sig.TypeCovered = TypeSOA - sig.Algorithm = RSASHA256 - sig.Labels = 2 - sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05" - sig.Inception = 1293942305 // date -u '+%s' -d"2011-01-02 04:25:05" - sig.OrigTtl = soa.Hdr.Ttl - sig.KeyTag = key.KeyTag() - sig.SignerName = key.Hdr.Name - - if err := sig.Sign(priv.(*rsa.PrivateKey), []RR{soa}); err != nil { - t.Error("failed to sign") - return - } - if err := sig.Verify(key, []RR{soa}); err != nil { - t.Error("failed to verify") - } -} - -func TestKeyToDS(t *testing.T) { - key := new(DNSKEY) - key.Hdr.Name = "miek.nl." - key.Hdr.Rrtype = TypeDNSKEY - key.Hdr.Class = ClassINET - key.Hdr.Ttl = 3600 - key.Flags = 256 - key.Protocol = 3 - key.Algorithm = RSASHA256 - key.PublicKey = "AwEAAcNEU67LJI5GEgF9QLNqLO1SMq1EdoQ6E9f85ha0k0ewQGCblyW2836GiVsm6k8Kr5ECIoMJ6fZWf3CQSQ9ycWfTyOHfmI3eQ/1Covhb2y4bAmL/07PhrL7ozWBW3wBfM335Ft9xjtXHPy7ztCbV9qZ4TVDTW/Iyg0PiwgoXVesz" - - ds := key.ToDS(SHA1) - if strings.ToUpper(ds.Digest) != "B5121BDB5B8D86D0CC5FFAFBAAABE26C3E20BAC1" { - t.Errorf("wrong DS digest for SHA1\n%v", ds) - } -} - -func TestSignRSA(t *testing.T) { - pub := "miek.nl. IN DNSKEY 256 3 5 AwEAAb+8lGNCxJgLS8rYVer6EnHVuIkQDghdjdtewDzU3G5R7PbMbKVRvH2Ma7pQyYceoaqWZQirSj72euPWfPxQnMy9ucCylA+FuH9cSjIcPf4PqJfdupHk9X6EBYjxrCLY4p1/yBwgyBIRJtZtAqM3ceAH2WovEJD6rTtOuHo5AluJ" - - priv := `Private-key-format: v1.3 -Algorithm: 5 (RSASHA1) -Modulus: v7yUY0LEmAtLythV6voScdW4iRAOCF2N217APNTcblHs9sxspVG8fYxrulDJhx6hqpZlCKtKPvZ649Z8/FCczL25wLKUD4W4f1xKMhw9/g+ol926keT1foQFiPGsItjinX/IHCDIEhEm1m0Cozdx4AfZai8QkPqtO064ejkCW4k= -PublicExponent: AQAB -PrivateExponent: YPwEmwjk5HuiROKU4xzHQ6l1hG8Iiha4cKRG3P5W2b66/EN/GUh07ZSf0UiYB67o257jUDVEgwCuPJz776zfApcCB4oGV+YDyEu7Hp/rL8KcSN0la0k2r9scKwxTp4BTJT23zyBFXsV/1wRDK1A5NxsHPDMYi2SoK63Enm/1ptk= -Prime1: /wjOG+fD0ybNoSRn7nQ79udGeR1b0YhUA5mNjDx/x2fxtIXzygYk0Rhx9QFfDy6LOBvz92gbNQlzCLz3DJt5hw== -Prime2: wHZsJ8OGhkp5p3mrJFZXMDc2mbYusDVTA+t+iRPdS797Tj0pjvU2HN4vTnTj8KBQp6hmnY7dLp9Y1qserySGbw== -Exponent1: N0A7FsSRIg+IAN8YPQqlawoTtG1t1OkJ+nWrurPootScApX6iMvn8fyvw3p2k51rv84efnzpWAYiC8SUaQDNxQ== -Exponent2: SvuYRaGyvo0zemE3oS+WRm2scxR8eiA8WJGeOc+obwOKCcBgeZblXzfdHGcEC1KaOcetOwNW/vwMA46lpLzJNw== -Coefficient: 8+7ZN/JgByqv0NfULiFKTjtyegUcijRuyij7yNxYbCBneDvZGxJwKNi4YYXWx743pcAj4Oi4Oh86gcmxLs+hGw== -Created: 20110302104537 -Publish: 20110302104537 -Activate: 20110302104537` - - xk := testRR(pub) - k := xk.(*DNSKEY) - p, err := k.NewPrivateKey(priv) - if err != nil { - t.Error(err) - } - switch priv := p.(type) { - case *rsa.PrivateKey: - if 65537 != priv.PublicKey.E { - t.Error("exponenent should be 65537") - } - default: - t.Errorf("we should have read an RSA key: %v", priv) - } - if k.KeyTag() != 37350 { - t.Errorf("keytag should be 37350, got %d %v", k.KeyTag(), k) - } - - soa := new(SOA) - soa.Hdr = RR_Header{"miek.nl.", TypeSOA, ClassINET, 14400, 0} - soa.Ns = "open.nlnetlabs.nl." - soa.Mbox = "miekg.atoom.net." - soa.Serial = 1293945905 - soa.Refresh = 14400 - soa.Retry = 3600 - soa.Expire = 604800 - soa.Minttl = 86400 - - sig := new(RRSIG) - sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0} - sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05" - sig.Inception = 1293942305 // date -u '+%s' -d"2011-01-02 04:25:05" - sig.KeyTag = k.KeyTag() - sig.SignerName = k.Hdr.Name - sig.Algorithm = k.Algorithm - - sig.Sign(p.(*rsa.PrivateKey), []RR{soa}) - if sig.Signature != "D5zsobpQcmMmYsUMLxCVEtgAdCvTu8V/IEeP4EyLBjqPJmjt96bwM9kqihsccofA5LIJ7DN91qkCORjWSTwNhzCv7bMyr2o5vBZElrlpnRzlvsFIoAZCD9xg6ZY7ZyzUJmU6IcTwG4v3xEYajcpbJJiyaw/RqR90MuRdKPiBzSo=" { - t.Errorf("signature is not correct: %v", sig) - } -} - -func TestSignVerifyECDSA(t *testing.T) { - pub := `example.net. 3600 IN DNSKEY 257 3 14 ( - xKYaNhWdGOfJ+nPrL8/arkwf2EY3MDJ+SErKivBVSum1 - w/egsXvSADtNJhyem5RCOpgQ6K8X1DRSEkrbYQ+OB+v8 - /uX45NBwY8rp65F6Glur8I/mlVNgF6W/qTI37m40 )` - priv := `Private-key-format: v1.2 -Algorithm: 14 (ECDSAP384SHA384) -PrivateKey: WURgWHCcYIYUPWgeLmiPY2DJJk02vgrmTfitxgqcL4vwW7BOrbawVmVe0d9V94SR` - - eckey := testRR(pub) - privkey, err := eckey.(*DNSKEY).NewPrivateKey(priv) - if err != nil { - t.Fatal(err) - } - // TODO: Create separate test for this - ds := eckey.(*DNSKEY).ToDS(SHA384) - if ds.KeyTag != 10771 { - t.Fatal("wrong keytag on DS") - } - if ds.Digest != "72d7b62976ce06438e9c0bf319013cf801f09ecc84b8d7e9495f27e305c6a9b0563a9b5f4d288405c3008a946df983d6" { - t.Fatal("wrong DS Digest") - } - a := testRR("www.example.net. 3600 IN A 192.0.2.1") - sig := new(RRSIG) - sig.Hdr = RR_Header{"example.net.", TypeRRSIG, ClassINET, 14400, 0} - sig.Expiration, _ = StringToTime("20100909102025") - sig.Inception, _ = StringToTime("20100812102025") - sig.KeyTag = eckey.(*DNSKEY).KeyTag() - sig.SignerName = eckey.(*DNSKEY).Hdr.Name - sig.Algorithm = eckey.(*DNSKEY).Algorithm - - if sig.Sign(privkey.(*ecdsa.PrivateKey), []RR{a}) != nil { - t.Fatal("failure to sign the record") - } - - if err := sig.Verify(eckey.(*DNSKEY), []RR{a}); err != nil { - t.Fatalf("failure to validate:\n%s\n%s\n%s\n\n%s\n\n%v", - eckey.(*DNSKEY).String(), - a.String(), - sig.String(), - eckey.(*DNSKEY).PrivateKeyString(privkey), - err, - ) - } -} - -func TestSignVerifyECDSA2(t *testing.T) { - srv1 := testRR("srv.miek.nl. IN SRV 1000 800 0 web1.miek.nl.") - srv := srv1.(*SRV) - - // With this key - key := new(DNSKEY) - key.Hdr.Rrtype = TypeDNSKEY - key.Hdr.Name = "miek.nl." - key.Hdr.Class = ClassINET - key.Hdr.Ttl = 14400 - key.Flags = 256 - key.Protocol = 3 - key.Algorithm = ECDSAP256SHA256 - privkey, err := key.Generate(256) - if err != nil { - t.Fatal("failure to generate key") - } - - // Fill in the values of the Sig, before signing - sig := new(RRSIG) - sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0} - sig.TypeCovered = srv.Hdr.Rrtype - sig.Labels = uint8(CountLabel(srv.Hdr.Name)) // works for all 3 - sig.OrigTtl = srv.Hdr.Ttl - sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05" - sig.Inception = 1293942305 // date -u '+%s' -d"2011-01-02 04:25:05" - sig.KeyTag = key.KeyTag() // Get the keyfrom the Key - sig.SignerName = key.Hdr.Name - sig.Algorithm = ECDSAP256SHA256 - - if sig.Sign(privkey.(*ecdsa.PrivateKey), []RR{srv}) != nil { - t.Fatal("failure to sign the record") - } - - err = sig.Verify(key, []RR{srv}) - if err != nil { - t.Errorf("failure to validate:\n%s\n%s\n%s\n\n%s\n\n%v", - key.String(), - srv.String(), - sig.String(), - key.PrivateKeyString(privkey), - err, - ) - } -} - -func TestSignVerifyEd25519(t *testing.T) { - srv1, err := NewRR("srv.miek.nl. IN SRV 1000 800 0 web1.miek.nl.") - if err != nil { - t.Fatal(err) - } - srv := srv1.(*SRV) - - // With this key - key := new(DNSKEY) - key.Hdr.Rrtype = TypeDNSKEY - key.Hdr.Name = "miek.nl." - key.Hdr.Class = ClassINET - key.Hdr.Ttl = 14400 - key.Flags = 256 - key.Protocol = 3 - key.Algorithm = ED25519 - privkey, err := key.Generate(256) - if err != nil { - t.Fatal("failure to generate key") - } - - // Fill in the values of the Sig, before signing - sig := new(RRSIG) - sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0} - sig.TypeCovered = srv.Hdr.Rrtype - sig.Labels = uint8(CountLabel(srv.Hdr.Name)) // works for all 3 - sig.OrigTtl = srv.Hdr.Ttl - sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05" - sig.Inception = 1293942305 // date -u '+%s' -d"2011-01-02 04:25:05" - sig.KeyTag = key.KeyTag() // Get the keyfrom the Key - sig.SignerName = key.Hdr.Name - sig.Algorithm = ED25519 - - if sig.Sign(privkey.(ed25519.PrivateKey), []RR{srv}) != nil { - t.Fatal("failure to sign the record") - } - - err = sig.Verify(key, []RR{srv}) - if err != nil { - t.Logf("failure to validate:\n%s\n%s\n%s\n\n%s\n\n%v", - key.String(), - srv.String(), - sig.String(), - key.PrivateKeyString(privkey), - err, - ) - } -} - -// Here the test vectors from the relevant RFCs are checked. -// rfc6605 6.1 -func TestRFC6605P256(t *testing.T) { - exDNSKEY := `example.net. 3600 IN DNSKEY 257 3 13 ( - GojIhhXUN/u4v54ZQqGSnyhWJwaubCvTmeexv7bR6edb - krSqQpF64cYbcB7wNcP+e+MAnLr+Wi9xMWyQLc8NAA== )` - exPriv := `Private-key-format: v1.2 -Algorithm: 13 (ECDSAP256SHA256) -PrivateKey: GU6SnQ/Ou+xC5RumuIUIuJZteXT2z0O/ok1s38Et6mQ=` - rrDNSKEY := testRR(exDNSKEY) - priv, err := rrDNSKEY.(*DNSKEY).NewPrivateKey(exPriv) - if err != nil { - t.Fatal(err) - } - - exDS := `example.net. 3600 IN DS 55648 13 2 ( - b4c8c1fe2e7477127b27115656ad6256f424625bf5c1 - e2770ce6d6e37df61d17 )` - rrDS := testRR(exDS) - ourDS := rrDNSKEY.(*DNSKEY).ToDS(SHA256) - if !reflect.DeepEqual(ourDS, rrDS.(*DS)) { - t.Errorf("DS record differs:\n%v\n%v", ourDS, rrDS.(*DS)) - } - - exA := `www.example.net. 3600 IN A 192.0.2.1` - exRRSIG := `www.example.net. 3600 IN RRSIG A 13 3 3600 ( - 20100909100439 20100812100439 55648 example.net. - qx6wLYqmh+l9oCKTN6qIc+bw6ya+KJ8oMz0YP107epXA - yGmt+3SNruPFKG7tZoLBLlUzGGus7ZwmwWep666VCw== )` - rrA := testRR(exA) - rrRRSIG := testRR(exRRSIG) - if err := rrRRSIG.(*RRSIG).Verify(rrDNSKEY.(*DNSKEY), []RR{rrA}); err != nil { - t.Errorf("failure to validate the spec RRSIG: %v", err) - } - - ourRRSIG := &RRSIG{ - Hdr: RR_Header{ - Ttl: rrA.Header().Ttl, - }, - KeyTag: rrDNSKEY.(*DNSKEY).KeyTag(), - SignerName: rrDNSKEY.(*DNSKEY).Hdr.Name, - Algorithm: rrDNSKEY.(*DNSKEY).Algorithm, - } - ourRRSIG.Expiration, _ = StringToTime("20100909100439") - ourRRSIG.Inception, _ = StringToTime("20100812100439") - err = ourRRSIG.Sign(priv.(*ecdsa.PrivateKey), []RR{rrA}) - if err != nil { - t.Fatal(err) - } - - if err = ourRRSIG.Verify(rrDNSKEY.(*DNSKEY), []RR{rrA}); err != nil { - t.Errorf("failure to validate our RRSIG: %v", err) - } - - // Signatures are randomized - rrRRSIG.(*RRSIG).Signature = "" - ourRRSIG.Signature = "" - if !reflect.DeepEqual(ourRRSIG, rrRRSIG.(*RRSIG)) { - t.Fatalf("RRSIG record differs:\n%v\n%v", ourRRSIG, rrRRSIG.(*RRSIG)) - } -} - -// rfc6605 6.2 -func TestRFC6605P384(t *testing.T) { - exDNSKEY := `example.net. 3600 IN DNSKEY 257 3 14 ( - xKYaNhWdGOfJ+nPrL8/arkwf2EY3MDJ+SErKivBVSum1 - w/egsXvSADtNJhyem5RCOpgQ6K8X1DRSEkrbYQ+OB+v8 - /uX45NBwY8rp65F6Glur8I/mlVNgF6W/qTI37m40 )` - exPriv := `Private-key-format: v1.2 -Algorithm: 14 (ECDSAP384SHA384) -PrivateKey: WURgWHCcYIYUPWgeLmiPY2DJJk02vgrmTfitxgqcL4vwW7BOrbawVmVe0d9V94SR` - rrDNSKEY := testRR(exDNSKEY) - priv, err := rrDNSKEY.(*DNSKEY).NewPrivateKey(exPriv) - if err != nil { - t.Fatal(err) - } - - exDS := `example.net. 3600 IN DS 10771 14 4 ( - 72d7b62976ce06438e9c0bf319013cf801f09ecc84b8 - d7e9495f27e305c6a9b0563a9b5f4d288405c3008a94 - 6df983d6 )` - rrDS := testRR(exDS) - ourDS := rrDNSKEY.(*DNSKEY).ToDS(SHA384) - if !reflect.DeepEqual(ourDS, rrDS.(*DS)) { - t.Fatalf("DS record differs:\n%v\n%v", ourDS, rrDS.(*DS)) - } - - exA := `www.example.net. 3600 IN A 192.0.2.1` - exRRSIG := `www.example.net. 3600 IN RRSIG A 14 3 3600 ( - 20100909102025 20100812102025 10771 example.net. - /L5hDKIvGDyI1fcARX3z65qrmPsVz73QD1Mr5CEqOiLP - 95hxQouuroGCeZOvzFaxsT8Glr74hbavRKayJNuydCuz - WTSSPdz7wnqXL5bdcJzusdnI0RSMROxxwGipWcJm )` - rrA := testRR(exA) - rrRRSIG := testRR(exRRSIG) - if err != nil { - t.Fatal(err) - } - if err = rrRRSIG.(*RRSIG).Verify(rrDNSKEY.(*DNSKEY), []RR{rrA}); err != nil { - t.Errorf("failure to validate the spec RRSIG: %v", err) - } - - ourRRSIG := &RRSIG{ - Hdr: RR_Header{ - Ttl: rrA.Header().Ttl, - }, - KeyTag: rrDNSKEY.(*DNSKEY).KeyTag(), - SignerName: rrDNSKEY.(*DNSKEY).Hdr.Name, - Algorithm: rrDNSKEY.(*DNSKEY).Algorithm, - } - ourRRSIG.Expiration, _ = StringToTime("20100909102025") - ourRRSIG.Inception, _ = StringToTime("20100812102025") - err = ourRRSIG.Sign(priv.(*ecdsa.PrivateKey), []RR{rrA}) - if err != nil { - t.Fatal(err) - } - - if err = ourRRSIG.Verify(rrDNSKEY.(*DNSKEY), []RR{rrA}); err != nil { - t.Errorf("failure to validate our RRSIG: %v", err) - } - - // Signatures are randomized - rrRRSIG.(*RRSIG).Signature = "" - ourRRSIG.Signature = "" - if !reflect.DeepEqual(ourRRSIG, rrRRSIG.(*RRSIG)) { - t.Fatalf("RRSIG record differs:\n%v\n%v", ourRRSIG, rrRRSIG.(*RRSIG)) - } -} - -// rfc8080 6.1 -func TestRFC8080Ed25519Example1(t *testing.T) { - exDNSKEY := `example.com. 3600 IN DNSKEY 257 3 15 ( - l02Woi0iS8Aa25FQkUd9RMzZHJpBoRQwAQEX1SxZJA4= )` - exPriv := `Private-key-format: v1.2 -Algorithm: 15 (ED25519) -PrivateKey: ODIyNjAzODQ2MjgwODAxMjI2NDUxOTAyMDQxNDIyNjI=` - rrDNSKEY, err := NewRR(exDNSKEY) - if err != nil { - t.Fatal(err) - } - priv, err := rrDNSKEY.(*DNSKEY).NewPrivateKey(exPriv) - if err != nil { - t.Fatal(err) - } - - exDS := `example.com. 3600 IN DS 3613 15 2 ( - 3aa5ab37efce57f737fc1627013fee07bdf241bd10f3b1964ab55c78e79 - a304b )` - rrDS, err := NewRR(exDS) - if err != nil { - t.Fatal(err) - } - ourDS := rrDNSKEY.(*DNSKEY).ToDS(SHA256) - if !reflect.DeepEqual(ourDS, rrDS.(*DS)) { - t.Fatalf("DS record differs:\n%v\n%v", ourDS, rrDS.(*DS)) - } - - exMX := `example.com. 3600 IN MX 10 mail.example.com.` - exRRSIG := `example.com. 3600 IN RRSIG MX 15 2 3600 ( - 1440021600 1438207200 3613 example.com. ( - oL9krJun7xfBOIWcGHi7mag5/hdZrKWw15jPGrHpjQeRAvTdszaPD+QLs3f - x8A4M3e23mRZ9VrbpMngwcrqNAg== ) )` - rrMX, err := NewRR(exMX) - if err != nil { - t.Fatal(err) - } - rrRRSIG, err := NewRR(exRRSIG) - if err != nil { - t.Fatal(err) - } - if err = rrRRSIG.(*RRSIG).Verify(rrDNSKEY.(*DNSKEY), []RR{rrMX}); err != nil { - t.Errorf("failure to validate the spec RRSIG: %v", err) - } - - ourRRSIG := &RRSIG{ - Hdr: RR_Header{ - Ttl: rrMX.Header().Ttl, - }, - KeyTag: rrDNSKEY.(*DNSKEY).KeyTag(), - SignerName: rrDNSKEY.(*DNSKEY).Hdr.Name, - Algorithm: rrDNSKEY.(*DNSKEY).Algorithm, - } - ourRRSIG.Expiration, _ = StringToTime("20150819220000") - ourRRSIG.Inception, _ = StringToTime("20150729220000") - err = ourRRSIG.Sign(priv.(ed25519.PrivateKey), []RR{rrMX}) - if err != nil { - t.Fatal(err) - } - - if err = ourRRSIG.Verify(rrDNSKEY.(*DNSKEY), []RR{rrMX}); err != nil { - t.Errorf("failure to validate our RRSIG: %v", err) - } - - if !reflect.DeepEqual(ourRRSIG, rrRRSIG.(*RRSIG)) { - t.Fatalf("RRSIG record differs:\n%v\n%v", ourRRSIG, rrRRSIG.(*RRSIG)) - } -} - -// rfc8080 6.1 -func TestRFC8080Ed25519Example2(t *testing.T) { - exDNSKEY := `example.com. 3600 IN DNSKEY 257 3 15 ( - zPnZ/QwEe7S8C5SPz2OfS5RR40ATk2/rYnE9xHIEijs= )` - exPriv := `Private-key-format: v1.2 -Algorithm: 15 (ED25519) -PrivateKey: DSSF3o0s0f+ElWzj9E/Osxw8hLpk55chkmx0LYN5WiY=` - rrDNSKEY, err := NewRR(exDNSKEY) - if err != nil { - t.Fatal(err) - } - priv, err := rrDNSKEY.(*DNSKEY).NewPrivateKey(exPriv) - if err != nil { - t.Fatal(err) - } - - exDS := `example.com. 3600 IN DS 35217 15 2 ( - 401781b934e392de492ec77ae2e15d70f6575a1c0bc59c5275c04ebe80c - 6614c )` - rrDS, err := NewRR(exDS) - if err != nil { - t.Fatal(err) - } - ourDS := rrDNSKEY.(*DNSKEY).ToDS(SHA256) - if !reflect.DeepEqual(ourDS, rrDS.(*DS)) { - t.Fatalf("DS record differs:\n%v\n%v", ourDS, rrDS.(*DS)) - } - - exMX := `example.com. 3600 IN MX 10 mail.example.com.` - exRRSIG := `example.com. 3600 IN RRSIG MX 15 2 3600 ( - 1440021600 1438207200 35217 example.com. ( - zXQ0bkYgQTEFyfLyi9QoiY6D8ZdYo4wyUhVioYZXFdT410QPRITQSqJSnzQ - oSm5poJ7gD7AQR0O7KuI5k2pcBg== ) )` - rrMX, err := NewRR(exMX) - if err != nil { - t.Fatal(err) - } - rrRRSIG, err := NewRR(exRRSIG) - if err != nil { - t.Fatal(err) - } - if err = rrRRSIG.(*RRSIG).Verify(rrDNSKEY.(*DNSKEY), []RR{rrMX}); err != nil { - t.Errorf("failure to validate the spec RRSIG: %v", err) - } - - ourRRSIG := &RRSIG{ - Hdr: RR_Header{ - Ttl: rrMX.Header().Ttl, - }, - KeyTag: rrDNSKEY.(*DNSKEY).KeyTag(), - SignerName: rrDNSKEY.(*DNSKEY).Hdr.Name, - Algorithm: rrDNSKEY.(*DNSKEY).Algorithm, - } - ourRRSIG.Expiration, _ = StringToTime("20150819220000") - ourRRSIG.Inception, _ = StringToTime("20150729220000") - err = ourRRSIG.Sign(priv.(ed25519.PrivateKey), []RR{rrMX}) - if err != nil { - t.Fatal(err) - } - - if err = ourRRSIG.Verify(rrDNSKEY.(*DNSKEY), []RR{rrMX}); err != nil { - t.Errorf("failure to validate our RRSIG: %v", err) - } - - if !reflect.DeepEqual(ourRRSIG, rrRRSIG.(*RRSIG)) { - t.Fatalf("RRSIG record differs:\n%v\n%v", ourRRSIG, rrRRSIG.(*RRSIG)) - } -} - -func TestInvalidRRSet(t *testing.T) { - goodRecords := make([]RR, 2) - goodRecords[0] = &TXT{Hdr: RR_Header{Name: "name.cloudflare.com.", Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}} - goodRecords[1] = &TXT{Hdr: RR_Header{Name: "name.cloudflare.com.", Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"_o/"}} - - // Generate key - keyname := "cloudflare.com." - key := &DNSKEY{ - Hdr: RR_Header{Name: keyname, Rrtype: TypeDNSKEY, Class: ClassINET, Ttl: 0}, - Algorithm: ECDSAP256SHA256, - Flags: ZONE, - Protocol: 3, - } - privatekey, err := key.Generate(256) - if err != nil { - t.Fatal(err.Error()) - } - - // Need to fill in: Inception, Expiration, KeyTag, SignerName and Algorithm - curTime := time.Now() - signature := &RRSIG{ - Inception: uint32(curTime.Unix()), - Expiration: uint32(curTime.Add(time.Hour).Unix()), - KeyTag: key.KeyTag(), - SignerName: keyname, - Algorithm: ECDSAP256SHA256, - } - - // Inconsistent name between records - badRecords := make([]RR, 2) - badRecords[0] = &TXT{Hdr: RR_Header{Name: "name.cloudflare.com.", Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}} - badRecords[1] = &TXT{Hdr: RR_Header{Name: "nama.cloudflare.com.", Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"_o/"}} - - if IsRRset(badRecords) { - t.Fatal("Record set with inconsistent names considered valid") - } - - badRecords[0] = &TXT{Hdr: RR_Header{Name: "name.cloudflare.com.", Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}} - badRecords[1] = &A{Hdr: RR_Header{Name: "name.cloudflare.com.", Rrtype: TypeA, Class: ClassINET, Ttl: 0}} - - if IsRRset(badRecords) { - t.Fatal("Record set with inconsistent record types considered valid") - } - - badRecords[0] = &TXT{Hdr: RR_Header{Name: "name.cloudflare.com.", Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}} - badRecords[1] = &TXT{Hdr: RR_Header{Name: "name.cloudflare.com.", Rrtype: TypeTXT, Class: ClassCHAOS, Ttl: 0}, Txt: []string{"_o/"}} - - if IsRRset(badRecords) { - t.Fatal("Record set with inconsistent record class considered valid") - } - - // Sign the good record set and then make sure verification fails on the bad record set - if err := signature.Sign(privatekey.(crypto.Signer), goodRecords); err != nil { - t.Fatal("Signing good records failed") - } - - if err := signature.Verify(key, badRecords); err != ErrRRset { - t.Fatal("Verification did not return ErrRRset with inconsistent records") - } -} - -// Issue #688 - RSA exponent unpacked in reverse -func TestRsaExponentUnpack(t *testing.T) { - zskRrDnskey, _ := NewRR("isc.org. 7200 IN DNSKEY 256 3 5 AwEAAcdkaRUlsRD4gcF63PpPJJ1E6kOIb3yn/UHptVsPEQtEbgJ2y20O eix4unpwoQkz+bIAd2rrOU/95wgV530x0/qqKwBLWoGkxdcnNcvVT4hl 3SOTZy1VjwkAfyayHPU8VisXqJGbB3KWevBZlb6AtrXzFu8AHuBeeAAe /fOgreCh") - kskRrDnskey, _ := NewRR("isc.org. 7200 IN DNSKEY 257 3 5 BEAAAAOhHQDBrhQbtphgq2wQUpEQ5t4DtUHxoMVFu2hWLDMvoOMRXjGr hhCeFvAZih7yJHf8ZGfW6hd38hXG/xylYCO6Krpbdojwx8YMXLA5/kA+ u50WIL8ZR1R6KTbsYVMf/Qx5RiNbPClw+vT+U8eXEJmO20jIS1ULgqy3 47cBB1zMnnz/4LJpA0da9CbKj3A254T515sNIMcwsB8/2+2E63/zZrQz Bkj0BrN/9Bexjpiks3jRhZatEsXn3dTy47R09Uix5WcJt+xzqZ7+ysyL KOOedS39Z7SDmsn2eA0FKtQpwA6LXeG2w+jxmw3oA8lVUgEf/rzeC/bB yBNsO70aEFTd") - kskRrRrsig, _ := NewRR("isc.org. 7200 IN RRSIG DNSKEY 5 2 7200 20180627230244 20180528230244 12892 isc.org. ebKBlhYi1hPGTdPg6zSwvprOIkoFMs+WIhMSjoYW6/K5CS9lDDFdK4cu TgXJRT3etrltTuJiFe2HRpp+7t5cKLy+CeJZVzqrCz200MoHiFuLI9yI DJQGaS5YYCiFbw5+jUGU6aUhZ7Y5/YufeqATkRZzdrKwgK+zri8LPw9T WLoVJPAOW7GR0dgxl9WKmO7Fzi9P8BZR3NuwLV7329X94j+4zyswaw7q e5vif0ybzFveODLsEi/E0a2rTXc4QzzyM0fSVxRkVQyQ7ifIPP4ohnnT d5qpPUbE8xxBzTdWR/TaKADC5aCFkppG9lVAq5CPfClii2949X5RYzy1 rxhuSA==") - zskRrRrsig, _ := NewRR("isc.org. 7200 IN RRSIG DNSKEY 5 2 7200 20180627230244 20180528230244 19923 isc.org. RgCfzUeq4RJPGoe9RRB6cWf6d/Du+tHK5SxI5QL1waA3O5qVtQKFkY1C dq/yyVjwzfjD9F62TObujOaktv8X80ZMcNPmgHbvK1xOqelMBWv5hxj3 xRe+QQObLZ5NPfHFsphQKXvwgO5Sjk8py2B2iCr3BHCZ8S38oIfuSrQx sn8=") - - zsk, ksk := zskRrDnskey.(*DNSKEY), kskRrDnskey.(*DNSKEY) - zskSig, kskSig := zskRrRrsig.(*RRSIG), kskRrRrsig.(*RRSIG) - - if e := zskSig.Verify(zsk, []RR{zsk, ksk}); e != nil { - t.Fatalf("cannot verify RRSIG with keytag [%d]. Cause [%s]", zsk.KeyTag(), e.Error()) - } - - if e := kskSig.Verify(ksk, []RR{zsk, ksk}); e != nil { - t.Fatalf("cannot verify RRSIG with keytag [%d]. Cause [%s]", ksk.KeyTag(), e.Error()) - } -} diff --git a/vendor/github.com/miekg/dns/duplicate_test.go b/vendor/github.com/miekg/dns/duplicate_test.go deleted file mode 100644 index 567796077..000000000 --- a/vendor/github.com/miekg/dns/duplicate_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package dns - -import "testing" - -func TestDuplicateA(t *testing.T) { - a1, _ := NewRR("www.example.org. 2700 IN A 127.0.0.1") - a2, _ := NewRR("www.example.org. IN A 127.0.0.1") - if !IsDuplicate(a1, a2) { - t.Errorf("expected %s/%s to be duplicates, but got false", a1.String(), a2.String()) - } - - a2, _ = NewRR("www.example.org. IN A 127.0.0.2") - if IsDuplicate(a1, a2) { - t.Errorf("expected %s/%s not to be duplicates, but got true", a1.String(), a2.String()) - } -} - -func TestDuplicateTXT(t *testing.T) { - a1, _ := NewRR("www.example.org. IN TXT \"aa\"") - a2, _ := NewRR("www.example.org. IN TXT \"aa\"") - - if !IsDuplicate(a1, a2) { - t.Errorf("expected %s/%s to be duplicates, but got false", a1.String(), a2.String()) - } - - a2, _ = NewRR("www.example.org. IN TXT \"aa\" \"bb\"") - if IsDuplicate(a1, a2) { - t.Errorf("expected %s/%s not to be duplicates, but got true", a1.String(), a2.String()) - } - - a1, _ = NewRR("www.example.org. IN TXT \"aa\" \"bc\"") - if IsDuplicate(a1, a2) { - t.Errorf("expected %s/%s not to be duplicates, but got true", a1.String(), a2.String()) - } -} - -func TestDuplicateOwner(t *testing.T) { - a1, _ := NewRR("www.example.org. IN A 127.0.0.1") - a2, _ := NewRR("www.example.org. IN A 127.0.0.1") - if !IsDuplicate(a1, a2) { - t.Errorf("expected %s/%s to be duplicates, but got false", a1.String(), a2.String()) - } - - a2, _ = NewRR("WWw.exaMPle.org. IN A 127.0.0.2") - if IsDuplicate(a1, a2) { - t.Errorf("expected %s/%s to be duplicates, but got false", a1.String(), a2.String()) - } -} - -func TestDuplicateDomain(t *testing.T) { - a1, _ := NewRR("www.example.org. IN CNAME example.org.") - a2, _ := NewRR("www.example.org. IN CNAME example.org.") - if !IsDuplicate(a1, a2) { - t.Errorf("expected %s/%s to be duplicates, but got false", a1.String(), a2.String()) - } - - a2, _ = NewRR("www.example.org. IN CNAME exAMPLe.oRG.") - if !IsDuplicate(a1, a2) { - t.Errorf("expected %s/%s to be duplicates, but got false", a1.String(), a2.String()) - } -} diff --git a/vendor/github.com/miekg/dns/dyn_test.go b/vendor/github.com/miekg/dns/dyn_test.go deleted file mode 100644 index 09986a5e4..000000000 --- a/vendor/github.com/miekg/dns/dyn_test.go +++ /dev/null @@ -1,3 +0,0 @@ -package dns - -// Find better solution diff --git a/vendor/github.com/miekg/dns/edns_test.go b/vendor/github.com/miekg/dns/edns_test.go deleted file mode 100644 index f7cf15754..000000000 --- a/vendor/github.com/miekg/dns/edns_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package dns - -import "testing" - -func TestOPTTtl(t *testing.T) { - e := &OPT{} - e.Hdr.Name = "." - e.Hdr.Rrtype = TypeOPT - - // verify the default setting of DO=0 - if e.Do() { - t.Errorf("DO bit should be zero") - } - - // There are 6 possible invocations of SetDo(): - // - // 1. Starting with DO=0, using SetDo() - // 2. Starting with DO=0, using SetDo(true) - // 3. Starting with DO=0, using SetDo(false) - // 4. Starting with DO=1, using SetDo() - // 5. Starting with DO=1, using SetDo(true) - // 6. Starting with DO=1, using SetDo(false) - - // verify that invoking SetDo() sets DO=1 (TEST #1) - e.SetDo() - if !e.Do() { - t.Errorf("DO bit should be non-zero") - } - // verify that using SetDo(true) works when DO=1 (TEST #5) - e.SetDo(true) - if !e.Do() { - t.Errorf("DO bit should still be non-zero") - } - // verify that we can use SetDo(false) to set DO=0 (TEST #6) - e.SetDo(false) - if e.Do() { - t.Errorf("DO bit should be zero") - } - // verify that if we call SetDo(false) when DO=0 that it is unchanged (TEST #3) - e.SetDo(false) - if e.Do() { - t.Errorf("DO bit should still be zero") - } - // verify that using SetDo(true) works for DO=0 (TEST #2) - e.SetDo(true) - if !e.Do() { - t.Errorf("DO bit should be non-zero") - } - // verify that using SetDo() works for DO=1 (TEST #4) - e.SetDo() - if !e.Do() { - t.Errorf("DO bit should be non-zero") - } - - if e.Version() != 0 { - t.Errorf("version should be non-zero") - } - - e.SetVersion(42) - if e.Version() != 42 { - t.Errorf("set 42, expected %d, got %d", 42, e.Version()) - } - - e.SetExtendedRcode(42) - if e.ExtendedRcode() != 42 { - t.Errorf("set 42, expected %d, got %d", 42, e.ExtendedRcode()) - } -} diff --git a/vendor/github.com/miekg/dns/example_test.go b/vendor/github.com/miekg/dns/example_test.go deleted file mode 100644 index 64c14962c..000000000 --- a/vendor/github.com/miekg/dns/example_test.go +++ /dev/null @@ -1,146 +0,0 @@ -package dns_test - -import ( - "errors" - "fmt" - "log" - "net" - - "github.com/miekg/dns" -) - -// Retrieve the MX records for miek.nl. -func ExampleMX() { - config, _ := dns.ClientConfigFromFile("/etc/resolv.conf") - c := new(dns.Client) - m := new(dns.Msg) - m.SetQuestion("miek.nl.", dns.TypeMX) - m.RecursionDesired = true - r, _, err := c.Exchange(m, config.Servers[0]+":"+config.Port) - if err != nil { - return - } - if r.Rcode != dns.RcodeSuccess { - return - } - for _, a := range r.Answer { - if mx, ok := a.(*dns.MX); ok { - fmt.Printf("%s\n", mx.String()) - } - } -} - -// Retrieve the DNSKEY records of a zone and convert them -// to DS records for SHA1, SHA256 and SHA384. -func ExampleDS() { - config, _ := dns.ClientConfigFromFile("/etc/resolv.conf") - c := new(dns.Client) - m := new(dns.Msg) - zone := "miek.nl" - m.SetQuestion(dns.Fqdn(zone), dns.TypeDNSKEY) - m.SetEdns0(4096, true) - r, _, err := c.Exchange(m, config.Servers[0]+":"+config.Port) - if err != nil { - return - } - if r.Rcode != dns.RcodeSuccess { - return - } - for _, k := range r.Answer { - if key, ok := k.(*dns.DNSKEY); ok { - for _, alg := range []uint8{dns.SHA1, dns.SHA256, dns.SHA384} { - fmt.Printf("%s; %d\n", key.ToDS(alg).String(), key.Flags) - } - } - } -} - -const TypeAPAIR = 0x0F99 - -type APAIR struct { - addr [2]net.IP -} - -func NewAPAIR() dns.PrivateRdata { return new(APAIR) } - -func (rd *APAIR) String() string { return rd.addr[0].String() + " " + rd.addr[1].String() } -func (rd *APAIR) Parse(txt []string) error { - if len(txt) != 2 { - return errors.New("two addresses required for APAIR") - } - for i, s := range txt { - ip := net.ParseIP(s) - if ip == nil { - return errors.New("invalid IP in APAIR text representation") - } - rd.addr[i] = ip - } - return nil -} - -func (rd *APAIR) Pack(buf []byte) (int, error) { - b := append([]byte(rd.addr[0]), []byte(rd.addr[1])...) - n := copy(buf, b) - if n != len(b) { - return n, dns.ErrBuf - } - return n, nil -} - -func (rd *APAIR) Unpack(buf []byte) (int, error) { - ln := net.IPv4len * 2 - if len(buf) != ln { - return 0, errors.New("invalid length of APAIR rdata") - } - cp := make([]byte, ln) - copy(cp, buf) // clone bytes to use them in IPs - - rd.addr[0] = net.IP(cp[:3]) - rd.addr[1] = net.IP(cp[4:]) - - return len(buf), nil -} - -func (rd *APAIR) Copy(dest dns.PrivateRdata) error { - cp := make([]byte, rd.Len()) - _, err := rd.Pack(cp) - if err != nil { - return err - } - - d := dest.(*APAIR) - d.addr[0] = net.IP(cp[:3]) - d.addr[1] = net.IP(cp[4:]) - return nil -} - -func (rd *APAIR) Len() int { - return net.IPv4len * 2 -} - -func ExamplePrivateHandle() { - dns.PrivateHandle("APAIR", TypeAPAIR, NewAPAIR) - defer dns.PrivateHandleRemove(TypeAPAIR) - - rr, err := dns.NewRR("miek.nl. APAIR (1.2.3.4 1.2.3.5)") - if err != nil { - log.Fatal("could not parse APAIR record: ", err) - } - fmt.Println(rr) - // Output: miek.nl. 3600 IN APAIR 1.2.3.4 1.2.3.5 - - m := new(dns.Msg) - m.Id = 12345 - m.SetQuestion("miek.nl.", TypeAPAIR) - m.Answer = append(m.Answer, rr) - - fmt.Println(m) - // ;; opcode: QUERY, status: NOERROR, id: 12345 - // ;; flags: rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 - // - // ;; QUESTION SECTION: - // ;miek.nl. IN APAIR - // - // ;; ANSWER SECTION: - // miek.nl. 3600 IN APAIR 1.2.3.4 1.2.3.5 -} diff --git a/vendor/github.com/miekg/dns/generate.go b/vendor/github.com/miekg/dns/generate.go index 3a559793f..97bc39f58 100644 --- a/vendor/github.com/miekg/dns/generate.go +++ b/vendor/github.com/miekg/dns/generate.go @@ -2,8 +2,8 @@ package dns import ( "bytes" - "errors" "fmt" + "io" "strconv" "strings" ) @@ -18,152 +18,225 @@ import ( // * rhs (rdata) // But we are lazy here, only the range is parsed *all* occurrences // of $ after that are interpreted. -// Any error are returned as a string value, the empty string signals -// "no error". -func generate(l lex, c chan lex, t chan *Token, o string) string { +func (zp *ZoneParser) generate(l lex) (RR, bool) { + token := l.token step := 1 - if i := strings.IndexAny(l.token, "/"); i != -1 { - if i+1 == len(l.token) { - return "bad step in $GENERATE range" + if i := strings.IndexByte(token, '/'); i >= 0 { + if i+1 == len(token) { + return zp.setParseError("bad step in $GENERATE range", l) } - if s, err := strconv.Atoi(l.token[i+1:]); err == nil { - if s < 0 { - return "bad step in $GENERATE range" - } - step = s - } else { - return "bad step in $GENERATE range" + + s, err := strconv.Atoi(token[i+1:]) + if err != nil || s <= 0 { + return zp.setParseError("bad step in $GENERATE range", l) } - l.token = l.token[:i] + + step = s + token = token[:i] } - sx := strings.SplitN(l.token, "-", 2) + + sx := strings.SplitN(token, "-", 2) if len(sx) != 2 { - return "bad start-stop in $GENERATE range" + return zp.setParseError("bad start-stop in $GENERATE range", l) } + start, err := strconv.Atoi(sx[0]) if err != nil { - return "bad start in $GENERATE range" + return zp.setParseError("bad start in $GENERATE range", l) } + end, err := strconv.Atoi(sx[1]) if err != nil { - return "bad stop in $GENERATE range" + return zp.setParseError("bad stop in $GENERATE range", l) } if end < 0 || start < 0 || end < start { - return "bad range in $GENERATE range" + return zp.setParseError("bad range in $GENERATE range", l) } - <-c // _BLANK + zp.c.Next() // _BLANK + // Create a complete new string, which we then parse again. - s := "" -BuildRR: - l = <-c - if l.value != zNewline && l.value != zEOF { + var s string + for l, ok := zp.c.Next(); ok; l, ok = zp.c.Next() { + if l.err { + return zp.setParseError("bad data in $GENERATE directive", l) + } + if l.value == zNewline { + break + } + s += l.token - goto BuildRR - } - for i := start; i <= end; i += step { - var ( - escape bool - dom bytes.Buffer - mod string - err error - offset int - ) - - for j := 0; j < len(s); j++ { // No 'range' because we need to jump around - switch s[j] { - case '\\': - if escape { - dom.WriteByte('\\') - escape = false - continue - } - escape = true - case '$': - mod = "%d" - offset = 0 - if escape { - dom.WriteByte('$') - escape = false - continue - } - escape = false - if j+1 >= len(s) { // End of the string - dom.WriteString(fmt.Sprintf(mod, i+offset)) - continue - } else { - if s[j+1] == '$' { - dom.WriteByte('$') - j++ - continue - } - } - // Search for { and } - if s[j+1] == '{' { // Modifier block - sep := strings.Index(s[j+2:], "}") - if sep == -1 { - return "bad modifier in $GENERATE" - } - mod, offset, err = modToPrintf(s[j+2 : j+2+sep]) - if err != nil { - return err.Error() - } - j += 2 + sep // Jump to it - } - dom.WriteString(fmt.Sprintf(mod, i+offset)) - default: - if escape { // Pretty useless here - escape = false - continue - } - dom.WriteByte(s[j]) + } + + r := &generateReader{ + s: s, + + cur: start, + start: start, + end: end, + step: step, + + file: zp.file, + lex: &l, + } + zp.sub = NewZoneParser(r, zp.origin, zp.file) + zp.sub.includeDepth, zp.sub.includeAllowed = zp.includeDepth, zp.includeAllowed + zp.sub.SetDefaultTTL(defaultTtl) + return zp.subNext() +} + +type generateReader struct { + s string + si int + + cur int + start int + end int + step int + + mod bytes.Buffer + + escape bool + + eof bool + + file string + lex *lex +} + +func (r *generateReader) parseError(msg string, end int) *ParseError { + r.eof = true // Make errors sticky. + + l := *r.lex + l.token = r.s[r.si-1 : end] + l.column += r.si // l.column starts one zBLANK before r.s + + return &ParseError{r.file, msg, l} +} + +func (r *generateReader) Read(p []byte) (int, error) { + // NewZLexer, through NewZoneParser, should use ReadByte and + // not end up here. + + panic("not implemented") +} + +func (r *generateReader) ReadByte() (byte, error) { + if r.eof { + return 0, io.EOF + } + if r.mod.Len() > 0 { + return r.mod.ReadByte() + } + + if r.si >= len(r.s) { + r.si = 0 + r.cur += r.step + + r.eof = r.cur > r.end || r.cur < 0 + return '\n', nil + } + + si := r.si + r.si++ + + switch r.s[si] { + case '\\': + if r.escape { + r.escape = false + return '\\', nil + } + + r.escape = true + return r.ReadByte() + case '$': + if r.escape { + r.escape = false + return '$', nil + } + + mod := "%d" + + if si >= len(r.s)-1 { + // End of the string + fmt.Fprintf(&r.mod, mod, r.cur) + return r.mod.ReadByte() + } + + if r.s[si+1] == '$' { + r.si++ + return '$', nil + } + + var offset int + + // Search for { and } + if r.s[si+1] == '{' { + // Modifier block + sep := strings.Index(r.s[si+2:], "}") + if sep < 0 { + return 0, r.parseError("bad modifier in $GENERATE", len(r.s)) + } + + var errMsg string + mod, offset, errMsg = modToPrintf(r.s[si+2 : si+2+sep]) + if errMsg != "" { + return 0, r.parseError(errMsg, si+3+sep) + } + if r.start+offset < 0 || r.end+offset > 1<<31-1 { + return 0, r.parseError("bad offset in $GENERATE", si+3+sep) } + + r.si += 2 + sep // Jump to it } - // Re-parse the RR and send it on the current channel t - rx, err := NewRR("$ORIGIN " + o + "\n" + dom.String()) - if err != nil { - return err.Error() + + fmt.Fprintf(&r.mod, mod, r.cur+offset) + return r.mod.ReadByte() + default: + if r.escape { // Pretty useless here + r.escape = false + return r.ReadByte() } - t <- &Token{RR: rx} - // Its more efficient to first built the rrlist and then parse it in - // one go! But is this a problem? + + return r.s[si], nil } - return "" } // Convert a $GENERATE modifier 0,0,d to something Printf can deal with. -func modToPrintf(s string) (string, int, error) { - xs := strings.Split(s, ",") - +func modToPrintf(s string) (string, int, string) { // Modifier is { offset [ ,width [ ,base ] ] } - provide default // values for optional width and type, if necessary. - switch len(xs) { + var offStr, widthStr, base string + switch xs := strings.Split(s, ","); len(xs) { case 1: - xs = append(xs, "0", "d") + offStr, widthStr, base = xs[0], "0", "d" case 2: - xs = append(xs, "d") + offStr, widthStr, base = xs[0], xs[1], "d" case 3: + offStr, widthStr, base = xs[0], xs[1], xs[2] default: - return "", 0, errors.New("bad modifier in $GENERATE") + return "", 0, "bad modifier in $GENERATE" } - // xs[0] is offset, xs[1] is width, xs[2] is base - if xs[2] != "o" && xs[2] != "d" && xs[2] != "x" && xs[2] != "X" { - return "", 0, errors.New("bad base in $GENERATE") + switch base { + case "o", "d", "x", "X": + default: + return "", 0, "bad base in $GENERATE" } - offset, err := strconv.Atoi(xs[0]) - if err != nil || offset > 255 { - return "", 0, errors.New("bad offset in $GENERATE") + + offset, err := strconv.Atoi(offStr) + if err != nil { + return "", 0, "bad offset in $GENERATE" } - width, err := strconv.Atoi(xs[1]) - if err != nil || width > 255 { - return "", offset, errors.New("bad width in $GENERATE") + + width, err := strconv.Atoi(widthStr) + if err != nil || width < 0 || width > 255 { + return "", 0, "bad width in $GENERATE" } - switch { - case width < 0: - return "", offset, errors.New("bad width in $GENERATE") - case width == 0: - return "%" + xs[1] + xs[2], offset, nil + + if width == 0 { + return "%" + base, offset, "" } - return "%0" + xs[1] + xs[2], offset, nil + + return "%0" + widthStr + base, offset, "" } diff --git a/vendor/github.com/miekg/dns/generate_test.go b/vendor/github.com/miekg/dns/generate_test.go deleted file mode 100644 index 1df6abd6c..000000000 --- a/vendor/github.com/miekg/dns/generate_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package dns - -import ( - "testing" -) - -func TestGenerateModToPrintf(t *testing.T) { - tests := []struct { - mod string - wantFmt string - wantOffset int - wantErr bool - }{ - {"0,0,d", "%0d", 0, false}, - {"0,0", "%0d", 0, false}, - {"0", "%0d", 0, false}, - {"3,2,d", "%02d", 3, false}, - {"3,2", "%02d", 3, false}, - {"3", "%0d", 3, false}, - {"0,0,o", "%0o", 0, false}, - {"0,0,x", "%0x", 0, false}, - {"0,0,X", "%0X", 0, false}, - {"0,0,z", "", 0, true}, - {"0,0,0,d", "", 0, true}, - } - for _, test := range tests { - gotFmt, gotOffset, err := modToPrintf(test.mod) - switch { - case err != nil && !test.wantErr: - t.Errorf("modToPrintf(%q) - expected nil-error, but got %v", test.mod, err) - case err == nil && test.wantErr: - t.Errorf("modToPrintf(%q) - expected error, but got nil-error", test.mod) - case gotFmt != test.wantFmt: - t.Errorf("modToPrintf(%q) - expected format %q, but got %q", test.mod, test.wantFmt, gotFmt) - case gotOffset != test.wantOffset: - t.Errorf("modToPrintf(%q) - expected offset %d, but got %d", test.mod, test.wantOffset, gotOffset) - } - } -} diff --git a/vendor/github.com/miekg/dns/issue_test.go b/vendor/github.com/miekg/dns/issue_test.go deleted file mode 100644 index 7299d3143..000000000 --- a/vendor/github.com/miekg/dns/issue_test.go +++ /dev/null @@ -1,62 +0,0 @@ -package dns - -// Tests that solve that an specific issue. - -import ( - "strings" - "testing" -) - -func TestTCPRtt(t *testing.T) { - m := new(Msg) - m.RecursionDesired = true - m.SetQuestion("example.org.", TypeA) - - c := &Client{} - for _, proto := range []string{"udp", "tcp"} { - c.Net = proto - _, rtt, err := c.Exchange(m, "8.8.4.4:53") - if err != nil { - t.Fatal(err) - } - if rtt == 0 { - t.Fatalf("expecting non zero rtt %s, got zero", c.Net) - } - } -} - -func TestNSEC3MissingSalt(t *testing.T) { - rr := testRR("ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. NSEC3 1 1 12 aabbccdd K8UDEMVP1J2F7EG6JEBPS17VP3N8I58H") - m := new(Msg) - m.Answer = []RR{rr} - mb, err := m.Pack() - if err != nil { - t.Fatalf("expected to pack message. err: %s", err) - } - if err := m.Unpack(mb); err != nil { - t.Fatalf("expected to unpack message. missing salt? err: %s", err) - } - in := rr.(*NSEC3).Salt - out := m.Answer[0].(*NSEC3).Salt - if in != out { - t.Fatalf("expected salts to match. packed: `%s`. returned: `%s`", in, out) - } -} - -func TestNSEC3MixedNextDomain(t *testing.T) { - rr := testRR("ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. NSEC3 1 1 12 - k8udemvp1j2f7eg6jebps17vp3n8i58h") - m := new(Msg) - m.Answer = []RR{rr} - mb, err := m.Pack() - if err != nil { - t.Fatalf("expected to pack message. err: %s", err) - } - if err := m.Unpack(mb); err != nil { - t.Fatalf("expected to unpack message. err: %s", err) - } - in := strings.ToUpper(rr.(*NSEC3).NextDomain) - out := m.Answer[0].(*NSEC3).NextDomain - if in != out { - t.Fatalf("expected round trip to produce NextDomain `%s`, instead `%s`", in, out) - } -} diff --git a/vendor/github.com/miekg/dns/labels_test.go b/vendor/github.com/miekg/dns/labels_test.go deleted file mode 100644 index d9bb556df..000000000 --- a/vendor/github.com/miekg/dns/labels_test.go +++ /dev/null @@ -1,201 +0,0 @@ -package dns - -import "testing" - -func TestCompareDomainName(t *testing.T) { - s1 := "www.miek.nl." - s2 := "miek.nl." - s3 := "www.bla.nl." - s4 := "nl.www.bla." - s5 := "nl." - s6 := "miek.nl." - - if CompareDomainName(s1, s2) != 2 { - t.Errorf("%s with %s should be %d", s1, s2, 2) - } - if CompareDomainName(s1, s3) != 1 { - t.Errorf("%s with %s should be %d", s1, s3, 1) - } - if CompareDomainName(s3, s4) != 0 { - t.Errorf("%s with %s should be %d", s3, s4, 0) - } - // Non qualified tests - if CompareDomainName(s1, s5) != 1 { - t.Errorf("%s with %s should be %d", s1, s5, 1) - } - if CompareDomainName(s1, s6) != 2 { - t.Errorf("%s with %s should be %d", s1, s5, 2) - } - - if CompareDomainName(s1, ".") != 0 { - t.Errorf("%s with %s should be %d", s1, s5, 0) - } - if CompareDomainName(".", ".") != 0 { - t.Errorf("%s with %s should be %d", ".", ".", 0) - } - if CompareDomainName("test.com.", "TEST.COM.") != 2 { - t.Errorf("test.com. and TEST.COM. should be an exact match") - } -} - -func TestSplit(t *testing.T) { - splitter := map[string]int{ - "www.miek.nl.": 3, - "www.miek.nl": 3, - "www..miek.nl": 4, - `www\.miek.nl.`: 2, - `www\\.miek.nl.`: 3, - ".": 0, - "nl.": 1, - "nl": 1, - "com.": 1, - ".com.": 2, - } - for s, i := range splitter { - if x := len(Split(s)); x != i { - t.Errorf("labels should be %d, got %d: %s %v", i, x, s, Split(s)) - } - } -} - -func TestSplit2(t *testing.T) { - splitter := map[string][]int{ - "www.miek.nl.": {0, 4, 9}, - "www.miek.nl": {0, 4, 9}, - "nl": {0}, - } - for s, i := range splitter { - x := Split(s) - switch len(i) { - case 1: - if x[0] != i[0] { - t.Errorf("labels should be %v, got %v: %s", i, x, s) - } - default: - if x[0] != i[0] || x[1] != i[1] || x[2] != i[2] { - t.Errorf("labels should be %v, got %v: %s", i, x, s) - } - } - } -} - -func TestPrevLabel(t *testing.T) { - type prev struct { - string - int - } - prever := map[prev]int{ - {"www.miek.nl.", 0}: 12, - {"www.miek.nl.", 1}: 9, - {"www.miek.nl.", 2}: 4, - - {"www.miek.nl", 0}: 11, - {"www.miek.nl", 1}: 9, - {"www.miek.nl", 2}: 4, - - {"www.miek.nl.", 5}: 0, - {"www.miek.nl", 5}: 0, - - {"www.miek.nl.", 3}: 0, - {"www.miek.nl", 3}: 0, - } - for s, i := range prever { - x, ok := PrevLabel(s.string, s.int) - if i != x { - t.Errorf("label should be %d, got %d, %t: preving %d, %s", i, x, ok, s.int, s.string) - } - } -} - -func TestCountLabel(t *testing.T) { - splitter := map[string]int{ - "www.miek.nl.": 3, - "www.miek.nl": 3, - "nl": 1, - ".": 0, - } - for s, i := range splitter { - x := CountLabel(s) - if x != i { - t.Errorf("CountLabel should have %d, got %d", i, x) - } - } -} - -func TestSplitDomainName(t *testing.T) { - labels := map[string][]string{ - "miek.nl": {"miek", "nl"}, - ".": nil, - "www.miek.nl.": {"www", "miek", "nl"}, - "www.miek.nl": {"www", "miek", "nl"}, - "www..miek.nl": {"www", "", "miek", "nl"}, - `www\.miek.nl`: {`www\.miek`, "nl"}, - `www\\.miek.nl`: {`www\\`, "miek", "nl"}, - ".www.miek.nl.": {"", "www", "miek", "nl"}, - } -domainLoop: - for domain, splits := range labels { - parts := SplitDomainName(domain) - if len(parts) != len(splits) { - t.Errorf("SplitDomainName returned %v for %s, expected %v", parts, domain, splits) - continue domainLoop - } - for i := range parts { - if parts[i] != splits[i] { - t.Errorf("SplitDomainName returned %v for %s, expected %v", parts, domain, splits) - continue domainLoop - } - } - } -} - -func TestIsDomainName(t *testing.T) { - type ret struct { - ok bool - lab int - } - names := map[string]*ret{ - "..": {false, 1}, - "@.": {true, 1}, - "www.example.com": {true, 3}, - "www.e%ample.com": {true, 3}, - "www.example.com.": {true, 3}, - "mi\\k.nl.": {true, 2}, - "mi\\k.nl": {true, 2}, - } - for d, ok := range names { - l, k := IsDomainName(d) - if ok.ok != k || ok.lab != l { - t.Errorf(" got %v %d for %s ", k, l, d) - t.Errorf("have %v %d for %s ", ok.ok, ok.lab, d) - } - } -} - -func BenchmarkSplitLabels(b *testing.B) { - for i := 0; i < b.N; i++ { - Split("www.example.com.") - } -} - -func BenchmarkLenLabels(b *testing.B) { - for i := 0; i < b.N; i++ { - CountLabel("www.example.com.") - } -} - -func BenchmarkCompareDomainName(b *testing.B) { - b.ReportAllocs() - for i := 0; i < b.N; i++ { - CompareDomainName("www.example.com.", "aa.example.com.") - } -} - -func BenchmarkIsSubDomain(b *testing.B) { - b.ReportAllocs() - for i := 0; i < b.N; i++ { - IsSubDomain("www.example.com.", "aa.example.com.") - IsSubDomain("example.com.", "aa.example.com.") - IsSubDomain("miek.nl.", "aa.example.com.") - } -} diff --git a/vendor/github.com/miekg/dns/leak_test.go b/vendor/github.com/miekg/dns/leak_test.go deleted file mode 100644 index ff83ac74b..000000000 --- a/vendor/github.com/miekg/dns/leak_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package dns - -import ( - "fmt" - "os" - "runtime" - "sort" - "strings" - "testing" - "time" -) - -// copied from net/http/main_test.go - -func interestingGoroutines() (gs []string) { - buf := make([]byte, 2<<20) - buf = buf[:runtime.Stack(buf, true)] - for _, g := range strings.Split(string(buf), "\n\n") { - sl := strings.SplitN(g, "\n", 2) - if len(sl) != 2 { - continue - } - stack := strings.TrimSpace(sl[1]) - if stack == "" || - strings.Contains(stack, "testing.(*M).before.func1") || - strings.Contains(stack, "os/signal.signal_recv") || - strings.Contains(stack, "created by net.startServer") || - strings.Contains(stack, "created by testing.RunTests") || - strings.Contains(stack, "closeWriteAndWait") || - strings.Contains(stack, "testing.Main(") || - strings.Contains(stack, "testing.(*T).Run(") || - strings.Contains(stack, "created by net/http.(*http2Transport).newClientConn") || - // These only show up with GOTRACEBACK=2; Issue 5005 (comment 28) - strings.Contains(stack, "runtime.goexit") || - strings.Contains(stack, "created by runtime.gc") || - strings.Contains(stack, "dns.interestingGoroutines") || - strings.Contains(stack, "runtime.MHeap_Scavenger") { - continue - } - gs = append(gs, stack) - } - sort.Strings(gs) - return -} - -func goroutineLeaked() error { - if testing.Short() { - // Don't worry about goroutine leaks in -short mode or in - // benchmark mode. Too distracting when there are false positives. - return nil - } - - var stackCount map[string]int - for i := 0; i < 5; i++ { - n := 0 - stackCount = make(map[string]int) - gs := interestingGoroutines() - for _, g := range gs { - stackCount[g]++ - n++ - } - if n == 0 { - return nil - } - // Wait for goroutines to schedule and die off: - time.Sleep(100 * time.Millisecond) - } - for stack, count := range stackCount { - fmt.Fprintf(os.Stderr, "%d instances of:\n%s\n", count, stack) - } - return fmt.Errorf("too many goroutines running after dns test(s)") -} diff --git a/vendor/github.com/miekg/dns/length_test.go b/vendor/github.com/miekg/dns/length_test.go deleted file mode 100644 index 66521a5f2..000000000 --- a/vendor/github.com/miekg/dns/length_test.go +++ /dev/null @@ -1,371 +0,0 @@ -package dns - -import ( - "encoding/hex" - "fmt" - "net" - "reflect" - "strings" - "testing" -) - -func TestCompressLength(t *testing.T) { - m := new(Msg) - m.SetQuestion("miek.nl", TypeMX) - ul := m.Len() - m.Compress = true - if ul != m.Len() { - t.Fatalf("should be equal") - } -} - -// Does the predicted length match final packed length? -func TestMsgCompressLength(t *testing.T) { - makeMsg := func(question string, ans, ns, e []RR) *Msg { - msg := new(Msg) - msg.SetQuestion(Fqdn(question), TypeANY) - msg.Answer = append(msg.Answer, ans...) - msg.Ns = append(msg.Ns, ns...) - msg.Extra = append(msg.Extra, e...) - msg.Compress = true - return msg - } - - name1 := "12345678901234567890123456789012345.12345678.123." - rrA := testRR(name1 + " 3600 IN A 192.0.2.1") - rrMx := testRR(name1 + " 3600 IN MX 10 " + name1) - tests := []*Msg{ - makeMsg(name1, []RR{rrA}, nil, nil), - makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)} - - for _, msg := range tests { - predicted := msg.Len() - buf, err := msg.Pack() - if err != nil { - t.Error(err) - } - if predicted < len(buf) { - t.Errorf("predicted compressed length is wrong: predicted %s (len=%d) %d, actual %d", - msg.Question[0].Name, len(msg.Answer), predicted, len(buf)) - } - } -} - -func TestMsgLength(t *testing.T) { - makeMsg := func(question string, ans, ns, e []RR) *Msg { - msg := new(Msg) - msg.Compress = true - msg.SetQuestion(Fqdn(question), TypeANY) - msg.Answer = append(msg.Answer, ans...) - msg.Ns = append(msg.Ns, ns...) - msg.Extra = append(msg.Extra, e...) - return msg - } - - name1 := "12345678901234567890123456789012345.12345678.123." - rrA := testRR(name1 + " 3600 IN A 192.0.2.1") - rrMx := testRR(name1 + " 3600 IN MX 10 " + name1) - tests := []*Msg{ - makeMsg(name1, []RR{rrA}, nil, nil), - makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)} - - for _, msg := range tests { - predicted := msg.Len() - buf, err := msg.Pack() - if err != nil { - t.Error(err) - } - if predicted < len(buf) { - t.Errorf("predicted length is wrong: predicted %s (len=%d), actual %d", - msg.Question[0].Name, predicted, len(buf)) - } - } -} - -func TestCompressionLenHelper(t *testing.T) { - c := make(map[string]int) - compressionLenHelper(c, "example.com", 12) - if c["example.com"] != 12 { - t.Errorf("bad %d", c["example.com"]) - } - if c["com"] != 20 { - t.Errorf("bad %d", c["com"]) - } - - // Test boundaries - c = make(map[string]int) - // foo label starts at 16379 - // com label starts at 16384 - compressionLenHelper(c, "foo.com", 16379) - if c["foo.com"] != 16379 { - t.Errorf("bad %d", c["foo.com"]) - } - // com label is accessible - if c["com"] != 16383 { - t.Errorf("bad %d", c["com"]) - } - - c = make(map[string]int) - // foo label starts at 16379 - // com label starts at 16385 => outside range - compressionLenHelper(c, "foo.com", 16380) - if c["foo.com"] != 16380 { - t.Errorf("bad %d", c["foo.com"]) - } - // com label is NOT accessible - if c["com"] != 0 { - t.Errorf("bad %d", c["com"]) - } - - c = make(map[string]int) - compressionLenHelper(c, "example.com", 16375) - if c["example.com"] != 16375 { - t.Errorf("bad %d", c["example.com"]) - } - // com starts AFTER 16384 - if c["com"] != 16383 { - t.Errorf("bad %d", c["com"]) - } - - c = make(map[string]int) - compressionLenHelper(c, "example.com", 16376) - if c["example.com"] != 16376 { - t.Errorf("bad %d", c["example.com"]) - } - // com starts AFTER 16384 - if c["com"] != 0 { - t.Errorf("bad %d", c["com"]) - } -} - -func TestCompressionLenSearch(t *testing.T) { - c := make(map[string]int) - compressed, ok, fullSize := compressionLenSearch(c, "a.b.org.") - if compressed != 0 || ok || fullSize != 14 { - panic(fmt.Errorf("Failed: compressed:=%d, ok:=%v, fullSize:=%d", compressed, ok, fullSize)) - } - c["org."] = 3 - compressed, ok, fullSize = compressionLenSearch(c, "a.b.org.") - if compressed != 4 || !ok || fullSize != 8 { - panic(fmt.Errorf("Failed: compressed:=%d, ok:=%v, fullSize:=%d", compressed, ok, fullSize)) - } - c["b.org."] = 5 - compressed, ok, fullSize = compressionLenSearch(c, "a.b.org.") - if compressed != 6 || !ok || fullSize != 4 { - panic(fmt.Errorf("Failed: compressed:=%d, ok:=%v, fullSize:=%d", compressed, ok, fullSize)) - } - // Not found long compression - c["x.b.org."] = 5 - compressed, ok, fullSize = compressionLenSearch(c, "a.b.org.") - if compressed != 6 || !ok || fullSize != 4 { - panic(fmt.Errorf("Failed: compressed:=%d, ok:=%v, fullSize:=%d", compressed, ok, fullSize)) - } - // Found long compression - c["a.b.org."] = 5 - compressed, ok, fullSize = compressionLenSearch(c, "a.b.org.") - if compressed != 8 || !ok || fullSize != 0 { - panic(fmt.Errorf("Failed: compressed:=%d, ok:=%v, fullSize:=%d", compressed, ok, fullSize)) - } -} - -func TestMsgLength2(t *testing.T) { - // Serialized replies - var testMessages = []string{ - // google.com. IN A? - "064e81800001000b0004000506676f6f676c6503636f6d0000010001c00c00010001000000050004adc22986c00c00010001000000050004adc22987c00c00010001000000050004adc22988c00c00010001000000050004adc22989c00c00010001000000050004adc2298ec00c00010001000000050004adc22980c00c00010001000000050004adc22981c00c00010001000000050004adc22982c00c00010001000000050004adc22983c00c00010001000000050004adc22984c00c00010001000000050004adc22985c00c00020001000000050006036e7331c00cc00c00020001000000050006036e7332c00cc00c00020001000000050006036e7333c00cc00c00020001000000050006036e7334c00cc0d800010001000000050004d8ef200ac0ea00010001000000050004d8ef220ac0fc00010001000000050004d8ef240ac10e00010001000000050004d8ef260a0000290500000000050000", - // amazon.com. IN A? (reply has no EDNS0 record) - // TODO(miek): this one is off-by-one, need to find out why - //"6de1818000010004000a000806616d617a6f6e03636f6d0000010001c00c000100010000000500044815c2d4c00c000100010000000500044815d7e8c00c00010001000000050004b02062a6c00c00010001000000050004cdfbf236c00c000200010000000500140570646e733408756c747261646e73036f726700c00c000200010000000500150570646e733508756c747261646e7304696e666f00c00c000200010000000500160570646e733608756c747261646e7302636f02756b00c00c00020001000000050014036e7331037033310664796e656374036e657400c00c00020001000000050006036e7332c0cfc00c00020001000000050006036e7333c0cfc00c00020001000000050006036e7334c0cfc00c000200010000000500110570646e733108756c747261646e73c0dac00c000200010000000500080570646e7332c127c00c000200010000000500080570646e7333c06ec0cb00010001000000050004d04e461fc0eb00010001000000050004cc0dfa1fc0fd00010001000000050004d04e471fc10f00010001000000050004cc0dfb1fc12100010001000000050004cc4a6c01c121001c000100000005001020010502f3ff00000000000000000001c13e00010001000000050004cc4a6d01c13e001c0001000000050010261000a1101400000000000000000001", - // yahoo.com. IN A? - "fc2d81800001000300070008057961686f6f03636f6d0000010001c00c00010001000000050004628afd6dc00c00010001000000050004628bb718c00c00010001000000050004cebe242dc00c00020001000000050006036e7336c00cc00c00020001000000050006036e7338c00cc00c00020001000000050006036e7331c00cc00c00020001000000050006036e7332c00cc00c00020001000000050006036e7333c00cc00c00020001000000050006036e7334c00cc00c00020001000000050006036e7335c00cc07b0001000100000005000444b48310c08d00010001000000050004448eff10c09f00010001000000050004cb54dd35c0b100010001000000050004628a0b9dc0c30001000100000005000477a0f77cc05700010001000000050004ca2bdfaac06900010001000000050004caa568160000290500000000050000", - // microsoft.com. IN A? - "f4368180000100020005000b096d6963726f736f667403636f6d0000010001c00c0001000100000005000440040b25c00c0001000100000005000441373ac9c00c0002000100000005000e036e7331046d736674036e657400c00c00020001000000050006036e7332c04fc00c00020001000000050006036e7333c04fc00c00020001000000050006036e7334c04fc00c00020001000000050006036e7335c04fc04b000100010000000500044137253ec04b001c00010000000500102a010111200500000000000000010001c0650001000100000005000440043badc065001c00010000000500102a010111200600060000000000010001c07700010001000000050004d5c7b435c077001c00010000000500102a010111202000000000000000010001c08900010001000000050004cf2e4bfec089001c00010000000500102404f800200300000000000000010001c09b000100010000000500044137e28cc09b001c00010000000500102a010111200f000100000000000100010000290500000000050000", - // google.com. IN MX? - "724b8180000100050004000b06676f6f676c6503636f6d00000f0001c00c000f000100000005000c000a056173706d78016cc00cc00c000f0001000000050009001404616c7431c02ac00c000f0001000000050009001e04616c7432c02ac00c000f0001000000050009002804616c7433c02ac00c000f0001000000050009003204616c7434c02ac00c00020001000000050006036e7332c00cc00c00020001000000050006036e7333c00cc00c00020001000000050006036e7334c00cc00c00020001000000050006036e7331c00cc02a00010001000000050004adc2421bc02a001c00010000000500102a00145040080c01000000000000001bc04200010001000000050004adc2461bc05700010001000000050004adc2451bc06c000100010000000500044a7d8f1bc081000100010000000500044a7d191bc0ca00010001000000050004d8ef200ac09400010001000000050004d8ef220ac0a600010001000000050004d8ef240ac0b800010001000000050004d8ef260a0000290500000000050000", - // reddit.com. IN A? - "12b98180000100080000000c0672656464697403636f6d0000020001c00c0002000100000005000f046175733204616b616d036e657400c00c000200010000000500070475736534c02dc00c000200010000000500070475737733c02dc00c000200010000000500070475737735c02dc00c00020001000000050008056173696131c02dc00c00020001000000050008056173696139c02dc00c00020001000000050008056e73312d31c02dc00c0002000100000005000a076e73312d313935c02dc02800010001000000050004c30a242ec04300010001000000050004451f1d39c05600010001000000050004451f3bc7c0690001000100000005000460073240c07c000100010000000500046007fb81c090000100010000000500047c283484c090001c00010000000500102a0226f0006700000000000000000064c0a400010001000000050004c16c5b01c0a4001c000100000005001026001401000200000000000000000001c0b800010001000000050004c16c5bc3c0b8001c0001000000050010260014010002000000000000000000c30000290500000000050000", - } - - for i, hexData := range testMessages { - // we won't fail the decoding of the hex - input, _ := hex.DecodeString(hexData) - - m := new(Msg) - m.Unpack(input) - m.Compress = true - lenComp := m.Len() - b, _ := m.Pack() - pacComp := len(b) - m.Compress = false - lenUnComp := m.Len() - b, _ = m.Pack() - pacUnComp := len(b) - if pacComp+1 != lenComp { - t.Errorf("msg.Len(compressed)=%d actual=%d for test %d", lenComp, pacComp, i) - } - if pacUnComp+1 != lenUnComp { - t.Errorf("msg.Len(uncompressed)=%d actual=%d for test %d", lenUnComp, pacUnComp, i) - } - } -} - -func TestMsgLengthCompressionMalformed(t *testing.T) { - // SOA with empty hostmaster, which is illegal - soa := &SOA{Hdr: RR_Header{Name: ".", Rrtype: TypeSOA, Class: ClassINET, Ttl: 12345}, - Ns: ".", - Mbox: "", - Serial: 0, - Refresh: 28800, - Retry: 7200, - Expire: 604800, - Minttl: 60} - m := new(Msg) - m.Compress = true - m.Ns = []RR{soa} - m.Len() // Should not crash. -} - -func TestMsgCompressLength2(t *testing.T) { - msg := new(Msg) - msg.Compress = true - msg.SetQuestion(Fqdn("bliep."), TypeANY) - msg.Answer = append(msg.Answer, &SRV{Hdr: RR_Header{Name: "blaat.", Rrtype: 0x21, Class: 0x1, Ttl: 0x3c}, Port: 0x4c57, Target: "foo.bar."}) - msg.Extra = append(msg.Extra, &A{Hdr: RR_Header{Name: "foo.bar.", Rrtype: 0x1, Class: 0x1, Ttl: 0x3c}, A: net.IP{0xac, 0x11, 0x0, 0x3}}) - predicted := msg.Len() - buf, err := msg.Pack() - if err != nil { - t.Error(err) - } - if predicted != len(buf) { - t.Errorf("predicted compressed length is wrong: predicted %s (len=%d) %d, actual %d", - msg.Question[0].Name, len(msg.Answer), predicted, len(buf)) - } -} - -func TestMsgCompressLengthLargeRecords(t *testing.T) { - msg := new(Msg) - msg.Compress = true - msg.SetQuestion("my.service.acme.", TypeSRV) - j := 1 - for i := 0; i < 250; i++ { - target := fmt.Sprintf("host-redis-1-%d.test.acme.com.node.dc1.consul.", i) - msg.Answer = append(msg.Answer, &SRV{Hdr: RR_Header{Name: "redis.service.consul.", Class: 1, Rrtype: TypeSRV, Ttl: 0x3c}, Port: 0x4c57, Target: target}) - msg.Extra = append(msg.Extra, &CNAME{Hdr: RR_Header{Name: target, Class: 1, Rrtype: TypeCNAME, Ttl: 0x3c}, Target: fmt.Sprintf("fx.168.%d.%d.", j, i)}) - } - predicted := msg.Len() - buf, err := msg.Pack() - if err != nil { - t.Error(err) - } - if predicted != len(buf) { - t.Fatalf("predicted compressed length is wrong: predicted %s (len=%d) %d, actual %d", msg.Question[0].Name, len(msg.Answer), predicted, len(buf)) - } -} - -func TestCompareCompressionMapsForANY(t *testing.T) { - msg := new(Msg) - msg.Compress = true - msg.SetQuestion("a.service.acme.", TypeANY) - // Be sure to have more than 14bits - for i := 0; i < 2000; i++ { - target := fmt.Sprintf("host.app-%d.x%d.test.acme.", i%250, i) - msg.Answer = append(msg.Answer, &AAAA{Hdr: RR_Header{Name: target, Rrtype: TypeAAAA, Class: ClassINET, Ttl: 0x3c}, AAAA: net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, byte(i / 255), byte(i % 255)}}) - msg.Answer = append(msg.Answer, &A{Hdr: RR_Header{Name: target, Rrtype: TypeA, Class: ClassINET, Ttl: 0x3c}, A: net.IP{127, 0, byte(i / 255), byte(i % 255)}}) - if msg.Len() > 16384 { - break - } - } - for labelSize := 0; labelSize < 63; labelSize++ { - msg.SetQuestion(fmt.Sprintf("a%s.service.acme.", strings.Repeat("x", labelSize)), TypeANY) - - compressionFake := make(map[string]int) - lenFake := compressedLenWithCompressionMap(msg, compressionFake) - - compressionReal := make(map[string]int) - buf, err := msg.packBufferWithCompressionMap(nil, compressionReal) - if err != nil { - t.Fatal(err) - } - if lenFake != len(buf) { - t.Fatalf("padding= %d ; Predicted len := %d != real:= %d", labelSize, lenFake, len(buf)) - } - if !reflect.DeepEqual(compressionFake, compressionReal) { - t.Fatalf("padding= %d ; Fake Compression Map != Real Compression Map\n*** Real:= %v\n\n***Fake:= %v", labelSize, compressionReal, compressionFake) - } - } -} - -func TestCompareCompressionMapsForSRV(t *testing.T) { - msg := new(Msg) - msg.Compress = true - msg.SetQuestion("a.service.acme.", TypeSRV) - // Be sure to have more than 14bits - for i := 0; i < 2000; i++ { - target := fmt.Sprintf("host.app-%d.x%d.test.acme.", i%250, i) - msg.Answer = append(msg.Answer, &SRV{Hdr: RR_Header{Name: "redis.service.consul.", Class: ClassINET, Rrtype: TypeSRV, Ttl: 0x3c}, Port: 0x4c57, Target: target}) - msg.Extra = append(msg.Extra, &A{Hdr: RR_Header{Name: target, Rrtype: TypeA, Class: ClassINET, Ttl: 0x3c}, A: net.IP{127, 0, byte(i / 255), byte(i % 255)}}) - if msg.Len() > 16384 { - break - } - } - for labelSize := 0; labelSize < 63; labelSize++ { - msg.SetQuestion(fmt.Sprintf("a%s.service.acme.", strings.Repeat("x", labelSize)), TypeAAAA) - - compressionFake := make(map[string]int) - lenFake := compressedLenWithCompressionMap(msg, compressionFake) - - compressionReal := make(map[string]int) - buf, err := msg.packBufferWithCompressionMap(nil, compressionReal) - if err != nil { - t.Fatal(err) - } - if lenFake != len(buf) { - t.Fatalf("padding= %d ; Predicted len := %d != real:= %d", labelSize, lenFake, len(buf)) - } - if !reflect.DeepEqual(compressionFake, compressionReal) { - t.Fatalf("padding= %d ; Fake Compression Map != Real Compression Map\n*** Real:= %v\n\n***Fake:= %v", labelSize, compressionReal, compressionFake) - } - } -} - -func TestMsgCompressLengthLargeRecordsWithPaddingPermutation(t *testing.T) { - msg := new(Msg) - msg.Compress = true - msg.SetQuestion("my.service.acme.", TypeSRV) - - for i := 0; i < 250; i++ { - target := fmt.Sprintf("host-redis-x-%d.test.acme.com.node.dc1.consul.", i) - msg.Answer = append(msg.Answer, &SRV{Hdr: RR_Header{Name: "redis.service.consul.", Class: 1, Rrtype: TypeSRV, Ttl: 0x3c}, Port: 0x4c57, Target: target}) - msg.Extra = append(msg.Extra, &CNAME{Hdr: RR_Header{Name: target, Class: ClassINET, Rrtype: TypeCNAME, Ttl: 0x3c}, Target: fmt.Sprintf("fx.168.x.%d.", i)}) - } - for labelSize := 1; labelSize < 63; labelSize++ { - msg.SetQuestion(fmt.Sprintf("my.%s.service.acme.", strings.Repeat("x", labelSize)), TypeSRV) - predicted := msg.Len() - buf, err := msg.Pack() - if err != nil { - t.Error(err) - } - if predicted != len(buf) { - t.Fatalf("padding= %d ; predicted compressed length is wrong: predicted %s (len=%d) %d, actual %d", labelSize, msg.Question[0].Name, len(msg.Answer), predicted, len(buf)) - } - } -} - -func TestMsgCompressLengthLargeRecordsAllValues(t *testing.T) { - msg := new(Msg) - msg.Compress = true - msg.SetQuestion("redis.service.consul.", TypeSRV) - for i := 0; i < 900; i++ { - target := fmt.Sprintf("host-redis-%d-%d.test.acme.com.node.dc1.consul.", i/256, i%256) - msg.Answer = append(msg.Answer, &SRV{Hdr: RR_Header{Name: "redis.service.consul.", Class: 1, Rrtype: TypeSRV, Ttl: 0x3c}, Port: 0x4c57, Target: target}) - msg.Extra = append(msg.Extra, &CNAME{Hdr: RR_Header{Name: target, Class: ClassINET, Rrtype: TypeCNAME, Ttl: 0x3c}, Target: fmt.Sprintf("fx.168.%d.%d.", i/256, i%256)}) - predicted := msg.Len() - buf, err := msg.Pack() - if err != nil { - t.Error(err) - } - if predicted != len(buf) { - t.Fatalf("predicted compressed length is wrong for %d records: predicted %s (len=%d) %d, actual %d", i, msg.Question[0].Name, len(msg.Answer), predicted, len(buf)) - } - } -} diff --git a/vendor/github.com/miekg/dns/listen_go111.go b/vendor/github.com/miekg/dns/listen_go111.go index bd024c893..fad195cfe 100644 --- a/vendor/github.com/miekg/dns/listen_go111.go +++ b/vendor/github.com/miekg/dns/listen_go111.go @@ -1,4 +1,5 @@ -// +build go1.11,!windows +// +build go1.11 +// +build aix darwin dragonfly freebsd linux netbsd openbsd package dns diff --git a/vendor/github.com/miekg/dns/listen_go_not111.go b/vendor/github.com/miekg/dns/listen_go_not111.go index f1fc652c4..b9201417a 100644 --- a/vendor/github.com/miekg/dns/listen_go_not111.go +++ b/vendor/github.com/miekg/dns/listen_go_not111.go @@ -1,4 +1,4 @@ -// +build !go1.11 windows +// +build !go1.11 !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd package dns diff --git a/vendor/github.com/miekg/dns/msg.go b/vendor/github.com/miekg/dns/msg.go index f8b847650..47ac6cf28 100644 --- a/vendor/github.com/miekg/dns/msg.go +++ b/vendor/github.com/miekg/dns/msg.go @@ -302,6 +302,12 @@ func packDomainName(s string, msg []byte, off int, compression map[string]int, c } // If we did compression and we find something add the pointer here if pointer != -1 { + // Clear the msg buffer after the pointer location, otherwise + // packDataNsec writes the wrong data to msg. + tainted := msg[nameoffset:off] + for i := range tainted { + tainted[i] = 0 + } // We have two bytes (14 bits) to put the pointer in // if msg == nil, we will never do compression binary.BigEndian.PutUint16(msg[nameoffset:], uint16(pointer^0xC000)) @@ -367,12 +373,10 @@ Loop: var buf [3]byte bufs := strconv.AppendInt(buf[:0], int64(b), 10) s = append(s, '\\') - for i := 0; i < 3-len(bufs); i++ { + for i := len(bufs); i < 3; i++ { s = append(s, '0') } - for _, r := range bufs { - s = append(s, r) - } + s = append(s, bufs...) // presentation-format \DDD escapes add 3 extra bytes maxLen += 3 } else { @@ -512,7 +516,7 @@ func unpackTxt(msg []byte, off0 int) (ss []string, off int, err error) { off = off0 var s string for off < len(msg) && err == nil { - s, off, err = unpackTxtString(msg, off) + s, off, err = unpackString(msg, off) if err == nil { ss = append(ss, s) } @@ -520,39 +524,6 @@ func unpackTxt(msg []byte, off0 int) (ss []string, off int, err error) { return } -func unpackTxtString(msg []byte, offset int) (string, int, error) { - if offset+1 > len(msg) { - return "", offset, &Error{err: "overflow unpacking txt"} - } - l := int(msg[offset]) - if offset+l+1 > len(msg) { - return "", offset, &Error{err: "overflow unpacking txt"} - } - s := make([]byte, 0, l) - for _, b := range msg[offset+1 : offset+1+l] { - switch b { - case '"', '\\': - s = append(s, '\\', b) - default: - if b < 32 || b > 127 { // unprintable - var buf [3]byte - bufs := strconv.AppendInt(buf[:0], int64(b), 10) - s = append(s, '\\') - for i := 0; i < 3-len(bufs); i++ { - s = append(s, '0') - } - for _, r := range bufs { - s = append(s, r) - } - } else { - s = append(s, b) - } - } - } - offset += 1 + l - return string(s), offset, nil -} - // Helpers for dealing with escaped bytes func isDigit(b byte) bool { return b >= '0' && b <= '9' } @@ -560,6 +531,10 @@ func dddToByte(s []byte) byte { return byte((s[0]-'0')*100 + (s[1]-'0')*10 + (s[2] - '0')) } +func dddStringToByte(s string) byte { + return byte((s[0]-'0')*100 + (s[1]-'0')*10 + (s[2] - '0')) +} + // Helper function for packing and unpacking func intToBytes(i *big.Int, length int) []byte { buf := i.Bytes() diff --git a/vendor/github.com/miekg/dns/msg_helpers.go b/vendor/github.com/miekg/dns/msg_helpers.go index ec8cd9a85..81fc2b1be 100644 --- a/vendor/github.com/miekg/dns/msg_helpers.go +++ b/vendor/github.com/miekg/dns/msg_helpers.go @@ -6,7 +6,7 @@ import ( "encoding/binary" "encoding/hex" "net" - "strconv" + "strings" ) // helper functions called from the generated zmsg.go @@ -267,29 +267,21 @@ func unpackString(msg []byte, off int) (string, int, error) { if off+l+1 > len(msg) { return "", off, &Error{err: "overflow unpacking txt"} } - s := make([]byte, 0, l) + var s strings.Builder + s.Grow(l) for _, b := range msg[off+1 : off+1+l] { - switch b { - case '"', '\\': - s = append(s, '\\', b) + switch { + case b == '"' || b == '\\': + s.WriteByte('\\') + s.WriteByte(b) + case b < ' ' || b > '~': // unprintable + writeEscapedByte(&s, b) default: - if b < 32 || b > 127 { // unprintable - var buf [3]byte - bufs := strconv.AppendInt(buf[:0], int64(b), 10) - s = append(s, '\\') - for i := 0; i < 3-len(bufs); i++ { - s = append(s, '0') - } - for _, r := range bufs { - s = append(s, r) - } - } else { - s = append(s, b) - } + s.WriteByte(b) } } off += 1 + l - return string(s), off, nil + return s.String(), off, nil } func packString(s string, msg []byte, off int) (int, error) { diff --git a/vendor/github.com/miekg/dns/msg_helpers_test.go b/vendor/github.com/miekg/dns/msg_helpers_test.go deleted file mode 100644 index adceb882c..000000000 --- a/vendor/github.com/miekg/dns/msg_helpers_test.go +++ /dev/null @@ -1,108 +0,0 @@ -package dns - -import "testing" - -// TestPacketDataNsec tests generated using fuzz.go and with a message pack -// containing the following bytes: 0000\x00\x00000000\x00\x002000000\x0060000\x00\x130000000000000000000" -// That bytes sequence created the overflow error and further permutations of that sequence were able to trigger -// the other code paths. -func TestPackDataNsec(t *testing.T) { - type args struct { - bitmap []uint16 - msg []byte - off int - } - tests := []struct { - name string - args args - want int - wantErr bool - wantErrMsg string - }{ - { - name: "overflow", - args: args{ - bitmap: []uint16{ - 8962, 8963, 8970, 8971, 8978, 8979, - 8986, 8987, 8994, 8995, 9002, 9003, - 9010, 9011, 9018, 9019, 9026, 9027, - 9034, 9035, 9042, 9043, 9050, 9051, - 9058, 9059, 9066, - }, - msg: []byte{ - 48, 48, 48, 48, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 50, - 48, 48, 48, 48, 48, 48, - 0, 54, 48, 48, 48, 48, - 0, 19, 48, 48, - }, - off: 48, - }, - wantErr: true, - wantErrMsg: "dns: overflow packing nsec", - want: 31, - }, - { - name: "disordered nsec bits", - args: args{ - bitmap: []uint16{ - 8962, - 0, - }, - msg: []byte{ - 48, 48, 48, 48, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0, 50, 48, 48, 48, 48, 48, 48, 0, 54, 48, - 48, 48, 48, 0, 19, 48, 48, 48, 48, 48, 48, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 50, 48, 48, - 48, 48, 48, 48, 0, 54, 48, 48, 48, 48, 0, 19, - 48, 48, 48, 48, 48, 48, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 50, 48, 48, 48, 48, 48, 48, 0, - 54, 48, 48, 48, 48, 0, 19, 48, 48, 48, 48, 48, - 48, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 50, - 48, 48, 48, 48, 48, 48, 0, 54, 48, 48, 48, 48, - 0, 19, 48, 48, 48, 48, 48, 48, 0, 0, 0, 1, - 0, 0, 0, 0, 0, 0, 50, 48, 48, 48, 48, 48, - 48, 0, 54, 48, 48, 48, 48, 0, 19, 48, 48, - }, - off: 0, - }, - wantErr: true, - wantErrMsg: "dns: nsec bits out of order", - want: 155, - }, - { - name: "simple message with only one window", - args: args{ - bitmap: []uint16{ - 0, - }, - msg: []byte{ - 48, 48, 48, 48, 0, 0, - 0, 1, 0, 0, 0, 0, - 0, 0, 50, 48, 48, 48, - 48, 48, 48, 0, 54, 48, - 48, 48, 48, 0, 19, 48, 48, - }, - off: 0, - }, - wantErr: false, - want: 3, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := packDataNsec(tt.args.bitmap, tt.args.msg, tt.args.off) - if (err != nil) != tt.wantErr { - t.Errorf("packDataNsec() error = %v, wantErr %v", err, tt.wantErr) - return - } - if err != nil && tt.wantErrMsg != err.Error() { - t.Errorf("packDataNsec() error msg = %v, wantErrMsg %v", err.Error(), tt.wantErrMsg) - return - } - if got != tt.want { - t.Errorf("packDataNsec() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/vendor/github.com/miekg/dns/msg_test.go b/vendor/github.com/miekg/dns/msg_test.go deleted file mode 100644 index afbe6d832..000000000 --- a/vendor/github.com/miekg/dns/msg_test.go +++ /dev/null @@ -1,146 +0,0 @@ -package dns - -import ( - "fmt" - "regexp" - "strconv" - "strings" - "testing" -) - -const ( - maxPrintableLabel = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789x" - tooLongLabel = maxPrintableLabel + "x" -) - -var ( - longDomain = maxPrintableLabel[:53] + strings.TrimSuffix( - strings.Join([]string{".", ".", ".", ".", "."}, maxPrintableLabel[:49]), ".") - reChar = regexp.MustCompile(`.`) - i = -1 - maxUnprintableLabel = reChar.ReplaceAllStringFunc(maxPrintableLabel, func(ch string) string { - if i++; i >= 32 { - i = 0 - } - return fmt.Sprintf("\\%03d", i) - }) -) - -func TestPackNoSideEffect(t *testing.T) { - m := new(Msg) - m.SetQuestion(Fqdn("example.com."), TypeNS) - - a := new(Msg) - o := &OPT{ - Hdr: RR_Header{ - Name: ".", - Rrtype: TypeOPT, - }, - } - o.SetUDPSize(DefaultMsgSize) - - a.Extra = append(a.Extra, o) - a.SetRcode(m, RcodeBadVers) - - a.Pack() - if a.Rcode != RcodeBadVers { - t.Errorf("after pack: Rcode is expected to be BADVERS") - } -} - -func TestUnpackDomainName(t *testing.T) { - var cases = []struct { - label string - input string - expectedOutput string - expectedError string - }{ - {"empty domain", - "\x00", - ".", - ""}, - {"long label", - string(63) + maxPrintableLabel + "\x00", - maxPrintableLabel + ".", - ""}, - {"unprintable label", - string(63) + regexp.MustCompile(`\\[0-9]+`).ReplaceAllStringFunc(maxUnprintableLabel, - func(escape string) string { - n, _ := strconv.ParseInt(escape[1:], 10, 8) - return string(n) - }) + "\x00", - maxUnprintableLabel + ".", - ""}, - {"long domain", - string(53) + strings.Replace(longDomain, ".", string(49), -1) + "\x00", - longDomain + ".", - ""}, - {"compression pointer", - // an unrealistic but functional test referencing an offset _inside_ a label - "\x03foo" + "\x05\x03com\x00" + "\x07example" + "\xC0\x05", - "foo.\\003com\\000.example.com.", - ""}, - - {"too long domain", - string(54) + "x" + strings.Replace(longDomain, ".", string(49), -1) + "\x00", - "x" + longDomain + ".", - ErrLongDomain.Error()}, - {"too long by pointer", - // a matryoshka doll name to get over 255 octets after expansion via internal pointers - string([]byte{ - // 11 length values, first to last - 40, 37, 34, 31, 28, 25, 22, 19, 16, 13, 0, - // 12 filler values - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - // 10 pointers, last to first - 192, 10, 192, 9, 192, 8, 192, 7, 192, 6, 192, 5, 192, 4, 192, 3, 192, 2, 192, 1, - }), - "", - ErrLongDomain.Error()}, - {"long by pointer", - // a matryoshka doll name _not_ exceeding 255 octets after expansion - string([]byte{ - // 11 length values, first to last - 37, 34, 31, 28, 25, 22, 19, 16, 13, 10, 0, - // 9 filler values - 120, 120, 120, 120, 120, 120, 120, 120, 120, - // 10 pointers, last to first - 192, 10, 192, 9, 192, 8, 192, 7, 192, 6, 192, 5, 192, 4, 192, 3, 192, 2, 192, 1, - }), - "" + - (`\"\031\028\025\022\019\016\013\010\000xxxxxxxxx` + - `\192\010\192\009\192\008\192\007\192\006\192\005\192\004\192\003\192\002.`) + - (`\031\028\025\022\019\016\013\010\000xxxxxxxxx` + - `\192\010\192\009\192\008\192\007\192\006\192\005\192\004\192\003.`) + - (`\028\025\022\019\016\013\010\000xxxxxxxxx` + - `\192\010\192\009\192\008\192\007\192\006\192\005\192\004.`) + - (`\025\022\019\016\013\010\000xxxxxxxxx` + - `\192\010\192\009\192\008\192\007\192\006\192\005.`) + - `\022\019\016\013\010\000xxxxxxxxx\192\010\192\009\192\008\192\007\192\006.` + - `\019\016\013\010\000xxxxxxxxx\192\010\192\009\192\008\192\007.` + - `\016\013\010\000xxxxxxxxx\192\010\192\009\192\008.` + - `\013\010\000xxxxxxxxx\192\010\192\009.` + - `\010\000xxxxxxxxx\192\010.` + - `\000xxxxxxxxx.`, - ""}, - {"truncated name", "\x07example\x03", "", "dns: buffer size too small"}, - {"non-absolute name", "\x07example\x03com", "", "dns: buffer size too small"}, - {"compression pointer cycle", - "\x03foo" + "\x03bar" + "\x07example" + "\xC0\x04", - "", - "dns: too many compression pointers"}, - {"reserved compression pointer 0b10", "\x07example\x80", "", "dns: bad rdata"}, - {"reserved compression pointer 0b01", "\x07example\x40", "", "dns: bad rdata"}, - } - for _, test := range cases { - output, idx, err := UnpackDomainName([]byte(test.input), 0) - if test.expectedOutput != "" && output != test.expectedOutput { - t.Errorf("%s: expected %s, got %s", test.label, test.expectedOutput, output) - } - if test.expectedError == "" && err != nil { - t.Errorf("%s: expected no error, got %d %v", test.label, idx, err) - } else if test.expectedError != "" && (err == nil || err.Error() != test.expectedError) { - t.Errorf("%s: expected error %s, got %d %v", test.label, test.expectedError, idx, err) - } - } -} diff --git a/vendor/github.com/miekg/dns/nsecx_test.go b/vendor/github.com/miekg/dns/nsecx_test.go deleted file mode 100644 index 74ebda3f5..000000000 --- a/vendor/github.com/miekg/dns/nsecx_test.go +++ /dev/null @@ -1,141 +0,0 @@ -package dns - -import "testing" - -func TestPackNsec3(t *testing.T) { - nsec3 := HashName("dnsex.nl.", SHA1, 0, "DEAD") - if nsec3 != "ROCCJAE8BJJU7HN6T7NG3TNM8ACRS87J" { - t.Error(nsec3) - } - - nsec3 = HashName("a.b.c.example.org.", SHA1, 2, "DEAD") - if nsec3 != "6LQ07OAHBTOOEU2R9ANI2AT70K5O0RCG" { - t.Error(nsec3) - } -} - -func TestNsec3(t *testing.T) { - nsec3 := testRR("sk4e8fj94u78smusb40o1n0oltbblu2r.nl. IN NSEC3 1 1 5 F10E9F7EA83FC8F3 SK4F38CQ0ATIEI8MH3RGD0P5I4II6QAN NS SOA TXT RRSIG DNSKEY NSEC3PARAM") - if !nsec3.(*NSEC3).Match("nl.") { // name hash = sk4e8fj94u78smusb40o1n0oltbblu2r - t.Fatal("sk4e8fj94u78smusb40o1n0oltbblu2r.nl. should match sk4e8fj94u78smusb40o1n0oltbblu2r.nl.") - } - if !nsec3.(*NSEC3).Match("NL.") { // name hash = sk4e8fj94u78smusb40o1n0oltbblu2r - t.Fatal("sk4e8fj94u78smusb40o1n0oltbblu2r.NL. should match sk4e8fj94u78smusb40o1n0oltbblu2r.nl.") - } - if nsec3.(*NSEC3).Match("com.") { // - t.Fatal("com. is not in the zone nl.") - } - if nsec3.(*NSEC3).Match("test.nl.") { // name hash = gd0ptr5bnfpimpu2d3v6gd4n0bai7s0q - t.Fatal("gd0ptr5bnfpimpu2d3v6gd4n0bai7s0q.nl. should not match sk4e8fj94u78smusb40o1n0oltbblu2r.nl.") - } - nsec3 = testRR("nl. IN NSEC3 1 1 5 F10E9F7EA83FC8F3 SK4F38CQ0ATIEI8MH3RGD0P5I4II6QAN NS SOA TXT RRSIG DNSKEY NSEC3PARAM") - if nsec3.(*NSEC3).Match("nl.") { - t.Fatal("sk4e8fj94u78smusb40o1n0oltbblu2r.nl. should not match a record without a owner hash") - } - - for _, tc := range []struct { - rr *NSEC3 - name string - covers bool - }{ - // positive tests - { // name hash between owner hash and next hash - rr: &NSEC3{ - Hdr: RR_Header{Name: "2N1TB3VAIRUOBL6RKDVII42N9TFMIALP.com."}, - Hash: 1, - Flags: 1, - Iterations: 5, - Salt: "F10E9F7EA83FC8F3", - NextDomain: "PT3RON8N7PM3A0OE989IB84OOSADP7O8", - }, - name: "bsd.com.", - covers: true, - }, - { // end of zone, name hash is after owner hash - rr: &NSEC3{ - Hdr: RR_Header{Name: "3v62ulr0nre83v0rja2vjgtlif9v6rab.com."}, - Hash: 1, - Flags: 1, - Iterations: 5, - Salt: "F10E9F7EA83FC8F3", - NextDomain: "2N1TB3VAIRUOBL6RKDVII42N9TFMIALP", - }, - name: "csd.com.", - covers: true, - }, - { // end of zone, name hash is before beginning of zone - rr: &NSEC3{ - Hdr: RR_Header{Name: "PT3RON8N7PM3A0OE989IB84OOSADP7O8.com."}, - Hash: 1, - Flags: 1, - Iterations: 5, - Salt: "F10E9F7EA83FC8F3", - NextDomain: "3V62ULR0NRE83V0RJA2VJGTLIF9V6RAB", - }, - name: "asd.com.", - covers: true, - }, - // negative tests - { // too short owner name - rr: &NSEC3{ - Hdr: RR_Header{Name: "nl."}, - Hash: 1, - Flags: 1, - Iterations: 5, - Salt: "F10E9F7EA83FC8F3", - NextDomain: "39P99DCGG0MDLARTCRMCF6OFLLUL7PR6", - }, - name: "asd.com.", - covers: false, - }, - { // outside of zone - rr: &NSEC3{ - Hdr: RR_Header{Name: "39p91242oslggest5e6a7cci4iaeqvnk.nl."}, - Hash: 1, - Flags: 1, - Iterations: 5, - Salt: "F10E9F7EA83FC8F3", - NextDomain: "39P99DCGG0MDLARTCRMCF6OFLLUL7PR6", - }, - name: "asd.com.", - covers: false, - }, - { // empty interval - rr: &NSEC3{ - Hdr: RR_Header{Name: "2n1tb3vairuobl6rkdvii42n9tfmialp.com."}, - Hash: 1, - Flags: 1, - Iterations: 5, - Salt: "F10E9F7EA83FC8F3", - NextDomain: "2N1TB3VAIRUOBL6RKDVII42N9TFMIALP", - }, - name: "asd.com.", - covers: false, - }, - { // name hash is before owner hash, not covered - rr: &NSEC3{ - Hdr: RR_Header{Name: "3V62ULR0NRE83V0RJA2VJGTLIF9V6RAB.com."}, - Hash: 1, - Flags: 1, - Iterations: 5, - Salt: "F10E9F7EA83FC8F3", - NextDomain: "PT3RON8N7PM3A0OE989IB84OOSADP7O8", - }, - name: "asd.com.", - covers: false, - }, - } { - covers := tc.rr.Cover(tc.name) - if tc.covers != covers { - t.Fatalf("cover failed for %s: expected %t, got %t [record: %s]", tc.name, tc.covers, covers, tc.rr) - } - } -} - -func TestNsec3EmptySalt(t *testing.T) { - rr, _ := NewRR("CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN NSEC3 1 1 0 - CK0Q1GIN43N1ARRC9OSM6QPQR81H5M9A NS SOA RRSIG DNSKEY NSEC3PARAM") - - if !rr.(*NSEC3).Match("com.") { - t.Fatalf("expected record to match com. label") - } -} diff --git a/vendor/github.com/miekg/dns/parse_test.go b/vendor/github.com/miekg/dns/parse_test.go deleted file mode 100644 index efdaf59af..000000000 --- a/vendor/github.com/miekg/dns/parse_test.go +++ /dev/null @@ -1,1465 +0,0 @@ -package dns - -import ( - "bytes" - "crypto/rsa" - "encoding/hex" - "fmt" - "math/rand" - "net" - "reflect" - "regexp" - "strconv" - "strings" - "testing" - "testing/quick" -) - -func TestDotInName(t *testing.T) { - buf := make([]byte, 20) - PackDomainName("aa\\.bb.nl.", buf, 0, nil, false) - // index 3 must be a real dot - if buf[3] != '.' { - t.Error("dot should be a real dot") - } - - if buf[6] != 2 { - t.Error("this must have the value 2") - } - dom, _, _ := UnpackDomainName(buf, 0) - // printing it should yield the backspace again - if dom != "aa\\.bb.nl." { - t.Error("dot should have been escaped: ", dom) - } -} - -func TestDotLastInLabel(t *testing.T) { - sample := "aa\\..au." - buf := make([]byte, 20) - _, err := PackDomainName(sample, buf, 0, nil, false) - if err != nil { - t.Fatalf("unexpected error packing domain: %v", err) - } - dom, _, _ := UnpackDomainName(buf, 0) - if dom != sample { - t.Fatalf("unpacked domain `%s' doesn't match packed domain", dom) - } -} - -func TestTooLongDomainName(t *testing.T) { - l := "aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrsssttt." - dom := l + l + l + l + l + l + l - _, err := NewRR(dom + " IN A 127.0.0.1") - if err == nil { - t.Error("should be too long") - } - _, err = NewRR("..com. IN A 127.0.0.1") - if err == nil { - t.Error("should fail") - } -} - -func TestDomainName(t *testing.T) { - tests := []string{"r\\.gieben.miek.nl.", "www\\.www.miek.nl.", - "www.*.miek.nl.", "www.*.miek.nl.", - } - dbuff := make([]byte, 40) - - for _, ts := range tests { - if _, err := PackDomainName(ts, dbuff, 0, nil, false); err != nil { - t.Error("not a valid domain name") - continue - } - n, _, err := UnpackDomainName(dbuff, 0) - if err != nil { - t.Error("failed to unpack packed domain name") - continue - } - if ts != n { - t.Errorf("must be equal: in: %s, out: %s", ts, n) - } - } -} - -func TestDomainNameAndTXTEscapes(t *testing.T) { - tests := []byte{'.', '(', ')', ';', ' ', '@', '"', '\\', 9, 13, 10, 0, 255} - for _, b := range tests { - rrbytes := []byte{ - 1, b, 0, // owner - byte(TypeTXT >> 8), byte(TypeTXT), - byte(ClassINET >> 8), byte(ClassINET), - 0, 0, 0, 1, // TTL - 0, 2, 1, b, // Data - } - rr1, _, err := UnpackRR(rrbytes, 0) - if err != nil { - panic(err) - } - s := rr1.String() - rr2, err := NewRR(s) - if err != nil { - t.Errorf("error parsing unpacked RR's string: %v", err) - } - repacked := make([]byte, len(rrbytes)) - if _, err := PackRR(rr2, repacked, 0, nil, false); err != nil { - t.Errorf("error packing parsed RR: %v", err) - } - if !bytes.Equal(repacked, rrbytes) { - t.Error("packed bytes don't match original bytes") - } - } -} - -func TestTXTEscapeParsing(t *testing.T) { - test := [][]string{ - {`";"`, `";"`}, - {`\;`, `";"`}, - {`"\t"`, `"t"`}, - {`"\r"`, `"r"`}, - {`"\ "`, `" "`}, - {`"\;"`, `";"`}, - {`"\;\""`, `";\""`}, - {`"\(a\)"`, `"(a)"`}, - {`"\(a)"`, `"(a)"`}, - {`"(a\)"`, `"(a)"`}, - {`"(a)"`, `"(a)"`}, - {`"\048"`, `"0"`}, - {`"\` + "\t" + `"`, `"\009"`}, - {`"\` + "\n" + `"`, `"\010"`}, - {`"\` + "\r" + `"`, `"\013"`}, - {`"\` + "\x11" + `"`, `"\017"`}, - {`"\'"`, `"'"`}, - } - for _, s := range test { - rr, err := NewRR(fmt.Sprintf("example.com. IN TXT %v", s[0])) - if err != nil { - t.Errorf("could not parse %v TXT: %s", s[0], err) - continue - } - - txt := sprintTxt(rr.(*TXT).Txt) - if txt != s[1] { - t.Errorf("mismatch after parsing `%v` TXT record: `%v` != `%v`", s[0], txt, s[1]) - } - } -} - -func GenerateDomain(r *rand.Rand, size int) []byte { - dnLen := size % 70 // artificially limit size so there's less to interpret if a failure occurs - var dn []byte - done := false - for i := 0; i < dnLen && !done; { - max := dnLen - i - if max > 63 { - max = 63 - } - lLen := max - if lLen != 0 { - lLen = int(r.Int31()) % max - } - done = lLen == 0 - if done { - continue - } - l := make([]byte, lLen+1) - l[0] = byte(lLen) - for j := 0; j < lLen; j++ { - l[j+1] = byte(rand.Int31()) - } - dn = append(dn, l...) - i += 1 + lLen - } - return append(dn, 0) -} - -func TestDomainQuick(t *testing.T) { - r := rand.New(rand.NewSource(0)) - f := func(l int) bool { - db := GenerateDomain(r, l) - ds, _, err := UnpackDomainName(db, 0) - if err != nil { - panic(err) - } - buf := make([]byte, 255) - off, err := PackDomainName(ds, buf, 0, nil, false) - if err != nil { - t.Errorf("error packing domain: %v", err) - t.Errorf(" bytes: %v", db) - t.Errorf("string: %v", ds) - return false - } - if !bytes.Equal(db, buf[:off]) { - t.Errorf("repacked domain doesn't match original:") - t.Errorf("src bytes: %v", db) - t.Errorf(" string: %v", ds) - t.Errorf("out bytes: %v", buf[:off]) - return false - } - return true - } - if err := quick.Check(f, nil); err != nil { - t.Error(err) - } -} - -func GenerateTXT(r *rand.Rand, size int) []byte { - rdLen := size % 300 // artificially limit size so there's less to interpret if a failure occurs - var rd []byte - for i := 0; i < rdLen; { - max := rdLen - 1 - if max > 255 { - max = 255 - } - sLen := max - if max != 0 { - sLen = int(r.Int31()) % max - } - s := make([]byte, sLen+1) - s[0] = byte(sLen) - for j := 0; j < sLen; j++ { - s[j+1] = byte(rand.Int31()) - } - rd = append(rd, s...) - i += 1 + sLen - } - return rd -} - -// Ok, 2 things. 1) this test breaks with the new functionality of splitting up larger txt -// chunks into 255 byte pieces. 2) I don't like the random nature of this thing, because I can't -// place the quotes where they need to be. -// So either add some code the places the quotes in just the right spots, make this non random -// or do something else. -// Disabled for now. (miek) -func testTXTRRQuick(t *testing.T) { - s := rand.NewSource(0) - r := rand.New(s) - typeAndClass := []byte{ - byte(TypeTXT >> 8), byte(TypeTXT), - byte(ClassINET >> 8), byte(ClassINET), - 0, 0, 0, 1, // TTL - } - f := func(l int) bool { - owner := GenerateDomain(r, l) - rdata := GenerateTXT(r, l) - rrbytes := make([]byte, 0, len(owner)+2+2+4+2+len(rdata)) - rrbytes = append(rrbytes, owner...) - rrbytes = append(rrbytes, typeAndClass...) - rrbytes = append(rrbytes, byte(len(rdata)>>8)) - rrbytes = append(rrbytes, byte(len(rdata))) - rrbytes = append(rrbytes, rdata...) - rr, _, err := UnpackRR(rrbytes, 0) - if err != nil { - panic(err) - } - buf := make([]byte, len(rrbytes)*3) - off, err := PackRR(rr, buf, 0, nil, false) - if err != nil { - t.Errorf("pack Error: %v\nRR: %v", err, rr) - return false - } - buf = buf[:off] - if !bytes.Equal(buf, rrbytes) { - t.Errorf("packed bytes don't match original bytes") - t.Errorf("src bytes: %v", rrbytes) - t.Errorf(" struct: %v", rr) - t.Errorf("out bytes: %v", buf) - return false - } - if len(rdata) == 0 { - // string'ing won't produce any data to parse - return true - } - rrString := rr.String() - rr2, err := NewRR(rrString) - if err != nil { - t.Errorf("error parsing own output: %v", err) - t.Errorf("struct: %v", rr) - t.Errorf("string: %v", rrString) - return false - } - if rr2.String() != rrString { - t.Errorf("parsed rr.String() doesn't match original string") - t.Errorf("original: %v", rrString) - t.Errorf(" parsed: %v", rr2.String()) - return false - } - - buf = make([]byte, len(rrbytes)*3) - off, err = PackRR(rr2, buf, 0, nil, false) - if err != nil { - t.Errorf("error packing parsed rr: %v", err) - t.Errorf("unpacked Struct: %v", rr) - t.Errorf(" string: %v", rrString) - t.Errorf(" parsed Struct: %v", rr2) - return false - } - buf = buf[:off] - if !bytes.Equal(buf, rrbytes) { - t.Errorf("parsed packed bytes don't match original bytes") - t.Errorf(" source bytes: %v", rrbytes) - t.Errorf("unpacked struct: %v", rr) - t.Errorf(" string: %v", rrString) - t.Errorf(" parsed struct: %v", rr2) - t.Errorf(" repacked bytes: %v", buf) - return false - } - return true - } - c := &quick.Config{MaxCountScale: 10} - if err := quick.Check(f, c); err != nil { - t.Error(err) - } -} - -func TestParseDirectiveMisc(t *testing.T) { - tests := map[string]string{ - "$ORIGIN miek.nl.\na IN NS b": "a.miek.nl.\t3600\tIN\tNS\tb.miek.nl.", - "$TTL 2H\nmiek.nl. IN NS b.": "miek.nl.\t7200\tIN\tNS\tb.", - "miek.nl. 1D IN NS b.": "miek.nl.\t86400\tIN\tNS\tb.", - `name. IN SOA a6.nstld.com. hostmaster.nic.name. ( - 203362132 ; serial - 5m ; refresh (5 minutes) - 5m ; retry (5 minutes) - 2w ; expire (2 weeks) - 300 ; minimum (5 minutes) -)`: "name.\t3600\tIN\tSOA\ta6.nstld.com. hostmaster.nic.name. 203362132 300 300 1209600 300", - ". 3600000 IN NS ONE.MY-ROOTS.NET.": ".\t3600000\tIN\tNS\tONE.MY-ROOTS.NET.", - "ONE.MY-ROOTS.NET. 3600000 IN A 192.168.1.1": "ONE.MY-ROOTS.NET.\t3600000\tIN\tA\t192.168.1.1", - } - for i, o := range tests { - rr, err := NewRR(i) - if err != nil { - t.Error("failed to parse RR: ", err) - continue - } - if rr.String() != o { - t.Errorf("`%s' should be equal to\n`%s', but is `%s'", i, o, rr.String()) - } - } -} - -func TestNSEC(t *testing.T) { - nsectests := map[string]string{ - "nl. IN NSEC3PARAM 1 0 5 30923C44C6CBBB8F": "nl.\t3600\tIN\tNSEC3PARAM\t1 0 5 30923C44C6CBBB8F", - "p2209hipbpnm681knjnu0m1febshlv4e.nl. IN NSEC3 1 1 5 30923C44C6CBBB8F P90DG1KE8QEAN0B01613LHQDG0SOJ0TA NS SOA TXT RRSIG DNSKEY NSEC3PARAM": "p2209hipbpnm681knjnu0m1febshlv4e.nl.\t3600\tIN\tNSEC3\t1 1 5 30923C44C6CBBB8F P90DG1KE8QEAN0B01613LHQDG0SOJ0TA NS SOA TXT RRSIG DNSKEY NSEC3PARAM", - "localhost.dnssex.nl. IN NSEC www.dnssex.nl. A RRSIG NSEC": "localhost.dnssex.nl.\t3600\tIN\tNSEC\twww.dnssex.nl. A RRSIG NSEC", - "localhost.dnssex.nl. IN NSEC www.dnssex.nl. A RRSIG NSEC TYPE65534": "localhost.dnssex.nl.\t3600\tIN\tNSEC\twww.dnssex.nl. A RRSIG NSEC TYPE65534", - "localhost.dnssex.nl. IN NSEC www.dnssex.nl. A RRSIG NSec Type65534": "localhost.dnssex.nl.\t3600\tIN\tNSEC\twww.dnssex.nl. A RRSIG NSEC TYPE65534", - "44ohaq2njb0idnvolt9ggthvsk1e1uv8.skydns.test. NSEC3 1 0 0 - 44OHAQ2NJB0IDNVOLT9GGTHVSK1E1UVA": "44ohaq2njb0idnvolt9ggthvsk1e1uv8.skydns.test.\t3600\tIN\tNSEC3\t1 0 0 - 44OHAQ2NJB0IDNVOLT9GGTHVSK1E1UVA", - } - for i, o := range nsectests { - rr, err := NewRR(i) - if err != nil { - t.Error("failed to parse RR: ", err) - continue - } - if rr.String() != o { - t.Errorf("`%s' should be equal to\n`%s', but is `%s'", i, o, rr.String()) - } - } -} - -func TestParseLOC(t *testing.T) { - lt := map[string]string{ - "SW1A2AA.find.me.uk. LOC 51 30 12.748 N 00 07 39.611 W 0.00m 0.00m 0.00m 0.00m": "SW1A2AA.find.me.uk.\t3600\tIN\tLOC\t51 30 12.748 N 00 07 39.611 W 0m 0.00m 0.00m 0.00m", - "SW1A2AA.find.me.uk. LOC 51 0 0.0 N 00 07 39.611 W 0.00m 0.00m 0.00m 0.00m": "SW1A2AA.find.me.uk.\t3600\tIN\tLOC\t51 00 0.000 N 00 07 39.611 W 0m 0.00m 0.00m 0.00m", - } - for i, o := range lt { - rr, err := NewRR(i) - if err != nil { - t.Error("failed to parse RR: ", err) - continue - } - if rr.String() != o { - t.Errorf("`%s' should be equal to\n`%s', but is `%s'", i, o, rr.String()) - } - } -} - -func TestParseDS(t *testing.T) { - dt := map[string]string{ - "example.net. 3600 IN DS 40692 12 3 22261A8B0E0D799183E35E24E2AD6BB58533CBA7E3B14D659E9CA09B 2071398F": "example.net.\t3600\tIN\tDS\t40692 12 3 22261A8B0E0D799183E35E24E2AD6BB58533CBA7E3B14D659E9CA09B2071398F", - } - for i, o := range dt { - rr, err := NewRR(i) - if err != nil { - t.Error("failed to parse RR: ", err) - continue - } - if rr.String() != o { - t.Errorf("`%s' should be equal to\n`%s', but is `%s'", i, o, rr.String()) - } - } -} - -func TestQuotes(t *testing.T) { - tests := map[string]string{ - `t.example.com. IN TXT "a bc"`: "t.example.com.\t3600\tIN\tTXT\t\"a bc\"", - `t.example.com. IN TXT "a - bc"`: "t.example.com.\t3600\tIN\tTXT\t\"a\\010 bc\"", - `t.example.com. IN TXT ""`: "t.example.com.\t3600\tIN\tTXT\t\"\"", - `t.example.com. IN TXT "a"`: "t.example.com.\t3600\tIN\tTXT\t\"a\"", - `t.example.com. IN TXT "aa"`: "t.example.com.\t3600\tIN\tTXT\t\"aa\"", - `t.example.com. IN TXT "aaa" ;`: "t.example.com.\t3600\tIN\tTXT\t\"aaa\"", - `t.example.com. IN TXT "abc" "DEF"`: "t.example.com.\t3600\tIN\tTXT\t\"abc\" \"DEF\"", - `t.example.com. IN TXT "abc" ( "DEF" )`: "t.example.com.\t3600\tIN\tTXT\t\"abc\" \"DEF\"", - `t.example.com. IN TXT aaa ;`: "t.example.com.\t3600\tIN\tTXT\t\"aaa\"", - `t.example.com. IN TXT aaa aaa;`: "t.example.com.\t3600\tIN\tTXT\t\"aaa\" \"aaa\"", - `t.example.com. IN TXT aaa aaa`: "t.example.com.\t3600\tIN\tTXT\t\"aaa\" \"aaa\"", - `t.example.com. IN TXT aaa`: "t.example.com.\t3600\tIN\tTXT\t\"aaa\"", - "cid.urn.arpa. NAPTR 100 50 \"s\" \"z3950+I2L+I2C\" \"\" _z3950._tcp.gatech.edu.": "cid.urn.arpa.\t3600\tIN\tNAPTR\t100 50 \"s\" \"z3950+I2L+I2C\" \"\" _z3950._tcp.gatech.edu.", - "cid.urn.arpa. NAPTR 100 50 \"s\" \"rcds+I2C\" \"\" _rcds._udp.gatech.edu.": "cid.urn.arpa.\t3600\tIN\tNAPTR\t100 50 \"s\" \"rcds+I2C\" \"\" _rcds._udp.gatech.edu.", - "cid.urn.arpa. NAPTR 100 50 \"s\" \"http+I2L+I2C+I2R\" \"\" _http._tcp.gatech.edu.": "cid.urn.arpa.\t3600\tIN\tNAPTR\t100 50 \"s\" \"http+I2L+I2C+I2R\" \"\" _http._tcp.gatech.edu.", - "cid.urn.arpa. NAPTR 100 10 \"\" \"\" \"/urn:cid:.+@([^\\.]+\\.)(.*)$/\\2/i\" .": "cid.urn.arpa.\t3600\tIN\tNAPTR\t100 10 \"\" \"\" \"/urn:cid:.+@([^\\.]+\\.)(.*)$/\\2/i\" .", - } - for i, o := range tests { - rr, err := NewRR(i) - if err != nil { - t.Error("failed to parse RR: ", err) - continue - } - if rr.String() != o { - t.Errorf("`%s' should be equal to\n`%s', but is\n`%s'", i, o, rr.String()) - } - } -} - -func TestParseClass(t *testing.T) { - tests := map[string]string{ - "t.example.com. IN A 127.0.0.1": "t.example.com. 3600 IN A 127.0.0.1", - "t.example.com. CS A 127.0.0.1": "t.example.com. 3600 CS A 127.0.0.1", - "t.example.com. CH A 127.0.0.1": "t.example.com. 3600 CH A 127.0.0.1", - // ClassANY can not occur in zone files - // "t.example.com. ANY A 127.0.0.1": "t.example.com. 3600 ANY A 127.0.0.1", - "t.example.com. NONE A 127.0.0.1": "t.example.com. 3600 NONE A 127.0.0.1", - "t.example.com. CLASS255 A 127.0.0.1": "t.example.com. 3600 CLASS255 A 127.0.0.1", - } - for i, o := range tests { - rr, err := NewRR(i) - if err != nil { - t.Error("failed to parse RR: ", err) - continue - } - if rr.String() != o { - t.Errorf("`%s' should be equal to\n`%s', but is\n`%s'", i, o, rr.String()) - } - } -} - -func TestBrace(t *testing.T) { - tests := map[string]string{ - "(miek.nl.) 3600 IN A 127.0.1.1": "miek.nl.\t3600\tIN\tA\t127.0.1.1", - "miek.nl. (3600) IN MX (10) elektron.atoom.net.": "miek.nl.\t3600\tIN\tMX\t10 elektron.atoom.net.", - `miek.nl. IN ( - 3600 A 127.0.0.1)`: "miek.nl.\t3600\tIN\tA\t127.0.0.1", - "(miek.nl.) (A) (127.0.2.1)": "miek.nl.\t3600\tIN\tA\t127.0.2.1", - "miek.nl A 127.0.3.1": "miek.nl.\t3600\tIN\tA\t127.0.3.1", - "_ssh._tcp.local. 60 IN (PTR) stora._ssh._tcp.local.": "_ssh._tcp.local.\t60\tIN\tPTR\tstora._ssh._tcp.local.", - "miek.nl. NS ns.miek.nl": "miek.nl.\t3600\tIN\tNS\tns.miek.nl.", - `(miek.nl.) ( - (IN) - (AAAA) - (::1) )`: "miek.nl.\t3600\tIN\tAAAA\t::1", - `(miek.nl.) ( - (IN) - (AAAA) - (::1))`: "miek.nl.\t3600\tIN\tAAAA\t::1", - "miek.nl. IN AAAA ::2": "miek.nl.\t3600\tIN\tAAAA\t::2", - `((m)(i)ek.(n)l.) (SOA) (soa.) (soa.) ( - 2009032802 ; serial - 21600 ; refresh (6 hours) - 7(2)00 ; retry (2 hours) - 604()800 ; expire (1 week) - 3600 ; minimum (1 hour) - )`: "miek.nl.\t3600\tIN\tSOA\tsoa. soa. 2009032802 21600 7200 604800 3600", - "miek\\.nl. IN A 127.0.0.10": "miek\\.nl.\t3600\tIN\tA\t127.0.0.10", - "miek.nl. IN A 127.0.0.11": "miek.nl.\t3600\tIN\tA\t127.0.0.11", - "miek.nl. A 127.0.0.12": "miek.nl.\t3600\tIN\tA\t127.0.0.12", - `miek.nl. 86400 IN SOA elektron.atoom.net. miekg.atoom.net. ( - 2009032802 ; serial - 21600 ; refresh (6 hours) - 7200 ; retry (2 hours) - 604800 ; expire (1 week) - 3600 ; minimum (1 hour) - )`: "miek.nl.\t86400\tIN\tSOA\telektron.atoom.net. miekg.atoom.net. 2009032802 21600 7200 604800 3600", - } - for i, o := range tests { - rr, err := NewRR(i) - if err != nil { - t.Errorf("failed to parse RR: %v\n\t%s", err, i) - continue - } - if rr.String() != o { - t.Errorf("`%s' should be equal to\n`%s', but is `%s'", i, o, rr.String()) - } - } -} - -func TestParseFailure(t *testing.T) { - tests := []string{"miek.nl. IN A 327.0.0.1", - "miek.nl. IN AAAA ::x", - "miek.nl. IN MX a0 miek.nl.", - "miek.nl aap IN MX mx.miek.nl.", - "miek.nl 200 IN mxx 10 mx.miek.nl.", - "miek.nl. inn MX 10 mx.miek.nl.", - // "miek.nl. IN CNAME ", // actually valid nowadays, zero size rdata - "miek.nl. IN CNAME ..", - "miek.nl. PA MX 10 miek.nl.", - "miek.nl. ) IN MX 10 miek.nl.", - } - - for _, s := range tests { - _, err := NewRR(s) - if err == nil { - t.Errorf("should have triggered an error: \"%s\"", s) - } - } -} - -func TestOmittedTTL(t *testing.T) { - zone := ` -$ORIGIN example.com. -example.com. 42 IN SOA ns1.example.com. hostmaster.example.com. 1 86400 60 86400 3600 ; TTL=42 SOA -example.com. NS 2 ; TTL=42 absolute owner name -@ MD 3 ; TTL=42 current-origin owner name - MF 4 ; TTL=42 leading-space implied owner name - 43 TYPE65280 \# 1 05 ; TTL=43 implied owner name explicit TTL - MB 6 ; TTL=43 leading-tab implied owner name -$TTL 1337 -example.com. 88 MG 7 ; TTL=88 explicit TTL -example.com. MR 8 ; TTL=1337 after first $TTL -$TTL 314 - 1 TXT 9 ; TTL=1 implied owner name explicit TTL -example.com. DNAME 10 ; TTL=314 after second $TTL -` - reCaseFromComment := regexp.MustCompile(`TTL=(\d+)\s+(.*)`) - records := ParseZone(strings.NewReader(zone), "", "") - var i int - for record := range records { - i++ - if record.Error != nil { - t.Error(record.Error) - continue - } - expected := reCaseFromComment.FindStringSubmatch(record.Comment) - expectedTTL, _ := strconv.ParseUint(expected[1], 10, 32) - ttl := record.RR.Header().Ttl - if ttl != uint32(expectedTTL) { - t.Errorf("%s: expected TTL %d, got %d", expected[2], expectedTTL, ttl) - } - } - if i != 10 { - t.Errorf("expected %d records, got %d", 5, i) - } -} - -func TestRelativeNameErrors(t *testing.T) { - var badZones = []struct { - label string - zoneContents string - expectedErr string - }{ - { - "relative owner name without origin", - "example.com 3600 IN SOA ns.example.com. hostmaster.example.com. 1 86400 60 86400 3600", - "bad owner name", - }, - { - "relative owner name in RDATA", - "example.com. 3600 IN SOA ns hostmaster 1 86400 60 86400 3600", - "bad SOA Ns", - }, - { - "origin reference without origin", - "@ 3600 IN SOA ns.example.com. hostmaster.example.com. 1 86400 60 86400 3600", - "bad owner name", - }, - { - "relative owner name in $INCLUDE", - "$INCLUDE file.db example.com", - "bad origin name", - }, - { - "relative owner name in $ORIGIN", - "$ORIGIN example.com", - "bad origin name", - }, - } - for _, errorCase := range badZones { - entries := ParseZone(strings.NewReader(errorCase.zoneContents), "", "") - for entry := range entries { - if entry.Error == nil { - t.Errorf("%s: expected error, got nil", errorCase.label) - continue - } - err := entry.Error.err - if err != errorCase.expectedErr { - t.Errorf("%s: expected error `%s`, got `%s`", errorCase.label, errorCase.expectedErr, err) - } - } - } -} - -func TestHIP(t *testing.T) { - h := `www.example.com. IN HIP ( 2 200100107B1A74DF365639CC39F1D578 - AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p -9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQ -b1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D - rvs1.example.com. - rvs2.example.com. )` - rr, err := NewRR(h) - if err != nil { - t.Fatalf("failed to parse RR: %v", err) - } - msg := new(Msg) - msg.Answer = []RR{rr, rr} - bytes, err := msg.Pack() - if err != nil { - t.Fatalf("failed to pack msg: %v", err) - } - if err := msg.Unpack(bytes); err != nil { - t.Fatalf("failed to unpack msg: %v", err) - } - if len(msg.Answer) != 2 { - t.Fatalf("2 answers expected: %v", msg) - } - for i, rr := range msg.Answer { - rr := rr.(*HIP) - if l := len(rr.RendezvousServers); l != 2 { - t.Fatalf("2 servers expected, only %d in record %d:\n%v", l, i, msg) - } - for j, s := range []string{"rvs1.example.com.", "rvs2.example.com."} { - if rr.RendezvousServers[j] != s { - t.Fatalf("expected server %d of record %d to be %s:\n%v", j, i, s, msg) - } - } - } -} - -// Test with no known RR on the line -func TestLineNumberError2(t *testing.T) { - tests := map[string]string{ - "example.com. 1000 SO master.example.com. admin.example.com. 1 4294967294 4294967293 4294967295 100": "dns: expecting RR type or class, not this...: \"SO\" at line: 1:21", - "example.com 1000 IN TALINK a.example.com. b..example.com.": "dns: bad TALINK NextName: \"b..example.com.\" at line: 1:57", - "example.com 1000 IN TALINK ( a.example.com. b..example.com. )": "dns: bad TALINK NextName: \"b..example.com.\" at line: 1:60", - `example.com 1000 IN TALINK ( a.example.com. - bb..example.com. )`: "dns: bad TALINK NextName: \"bb..example.com.\" at line: 2:18", - // This is a bug, it should report an error on line 1, but the new is already processed. - `example.com 1000 IN TALINK ( a.example.com. b...example.com. - )`: "dns: bad TALINK NextName: \"b...example.com.\" at line: 2:1"} - - for in, errStr := range tests { - _, err := NewRR(in) - if err == nil { - t.Error("err is nil") - } else { - if err.Error() != errStr { - t.Errorf("%s: error should be %s is %v", in, errStr, err) - } - } - } -} - -// Test if the calculations are correct -func TestRfc1982(t *testing.T) { - // If the current time and the timestamp are more than 68 years apart - // it means the date has wrapped. 0 is 1970 - - // fall in the current 68 year span - strtests := []string{"20120525134203", "19700101000000", "20380119031408"} - for _, v := range strtests { - if x, _ := StringToTime(v); v != TimeToString(x) { - t.Errorf("1982 arithmetic string failure %s (%s:%d)", v, TimeToString(x), x) - } - } - - inttests := map[uint32]string{0: "19700101000000", - 1 << 31: "20380119031408", - 1<<32 - 1: "21060207062815", - } - for i, v := range inttests { - if TimeToString(i) != v { - t.Errorf("1982 arithmetic int failure %d:%s (%s)", i, v, TimeToString(i)) - } - } - - // Future tests, these dates get parsed to a date within the current 136 year span - future := map[string]string{"22680119031408": "20631123173144", - "19010101121212": "20370206184028", - "19210101121212": "20570206184028", - "19500101121212": "20860206184028", - "19700101000000": "19700101000000", - "19690101000000": "21050207062816", - "29210101121212": "21040522212236", - } - for from, to := range future { - x, _ := StringToTime(from) - y := TimeToString(x) - if y != to { - t.Errorf("1982 arithmetic future failure %s:%s (%s)", from, to, y) - } - } -} - -func TestEmpty(t *testing.T) { - for range ParseZone(strings.NewReader(""), "", "") { - t.Errorf("should be empty") - } -} - -func TestLowercaseTokens(t *testing.T) { - var testrecords = []string{ - "example.org. 300 IN a 1.2.3.4", - "example.org. 300 in A 1.2.3.4", - "example.org. 300 in a 1.2.3.4", - "example.org. 300 a 1.2.3.4", - "example.org. 300 A 1.2.3.4", - "example.org. IN a 1.2.3.4", - "example.org. in A 1.2.3.4", - "example.org. in a 1.2.3.4", - "example.org. a 1.2.3.4", - "example.org. A 1.2.3.4", - "example.org. a 1.2.3.4", - "$ORIGIN example.org.\n a 1.2.3.4", - "$Origin example.org.\n a 1.2.3.4", - "$origin example.org.\n a 1.2.3.4", - "example.org. Class1 Type1 1.2.3.4", - } - for _, testrr := range testrecords { - _, err := NewRR(testrr) - if err != nil { - t.Errorf("failed to parse %#v, got %v", testrr, err) - } - } -} - -func TestSRVPacking(t *testing.T) { - msg := Msg{} - - things := []string{"1.2.3.4:8484", - "45.45.45.45:8484", - "84.84.84.84:8484", - } - - for i, n := range things { - h, p, err := net.SplitHostPort(n) - if err != nil { - continue - } - port, _ := strconv.ParseUint(p, 10, 16) - - rr := &SRV{ - Hdr: RR_Header{Name: "somename.", - Rrtype: TypeSRV, - Class: ClassINET, - Ttl: 5}, - Priority: uint16(i), - Weight: 5, - Port: uint16(port), - Target: h + ".", - } - - msg.Answer = append(msg.Answer, rr) - } - - _, err := msg.Pack() - if err != nil { - t.Fatalf("couldn't pack %v: %v", msg, err) - } -} - -func TestParseBackslash(t *testing.T) { - if _, err := NewRR("nul\\000gap.test.globnix.net. 600 IN A 192.0.2.10"); err != nil { - t.Errorf("could not create RR with \\000 in it") - } - if _, err := NewRR(`nul\000gap.test.globnix.net. 600 IN TXT "Hello\123"`); err != nil { - t.Errorf("could not create RR with \\000 in it") - } - if _, err := NewRR(`m\ @\ iek.nl. IN 3600 A 127.0.0.1`); err != nil { - t.Errorf("could not create RR with \\ and \\@ in it") - } -} - -func TestILNP(t *testing.T) { - tests := []string{ - "host1.example.com.\t3600\tIN\tNID\t10 0014:4fff:ff20:ee64", - "host1.example.com.\t3600\tIN\tNID\t20 0015:5fff:ff21:ee65", - "host2.example.com.\t3600\tIN\tNID\t10 0016:6fff:ff22:ee66", - "host1.example.com.\t3600\tIN\tL32\t10 10.1.2.0", - "host1.example.com.\t3600\tIN\tL32\t20 10.1.4.0", - "host2.example.com.\t3600\tIN\tL32\t10 10.1.8.0", - "host1.example.com.\t3600\tIN\tL64\t10 2001:0DB8:1140:1000", - "host1.example.com.\t3600\tIN\tL64\t20 2001:0DB8:2140:2000", - "host2.example.com.\t3600\tIN\tL64\t10 2001:0DB8:4140:4000", - "host1.example.com.\t3600\tIN\tLP\t10 l64-subnet1.example.com.", - "host1.example.com.\t3600\tIN\tLP\t10 l64-subnet2.example.com.", - "host1.example.com.\t3600\tIN\tLP\t20 l32-subnet1.example.com.", - } - for _, t1 := range tests { - r, err := NewRR(t1) - if err != nil { - t.Fatalf("an error occurred: %v", err) - } else { - if t1 != r.String() { - t.Fatalf("strings should be equal %s %s", t1, r.String()) - } - } - } -} - -func TestGposEidNimloc(t *testing.T) { - dt := map[string]string{ - "444433332222111199990123000000ff. NSAP-PTR foo.bar.com.": "444433332222111199990123000000ff.\t3600\tIN\tNSAP-PTR\tfoo.bar.com.", - "lillee. IN GPOS -32.6882 116.8652 10.0": "lillee.\t3600\tIN\tGPOS\t-32.6882 116.8652 10.0", - "hinault. IN GPOS -22.6882 116.8652 250.0": "hinault.\t3600\tIN\tGPOS\t-22.6882 116.8652 250.0", - "VENERA. IN NIMLOC 75234159EAC457800920": "VENERA.\t3600\tIN\tNIMLOC\t75234159EAC457800920", - "VAXA. IN EID 3141592653589793": "VAXA.\t3600\tIN\tEID\t3141592653589793", - } - for i, o := range dt { - rr, err := NewRR(i) - if err != nil { - t.Error("failed to parse RR: ", err) - continue - } - if rr.String() != o { - t.Errorf("`%s' should be equal to\n`%s', but is `%s'", i, o, rr.String()) - } - } -} - -func TestPX(t *testing.T) { - dt := map[string]string{ - "*.net2.it. IN PX 10 net2.it. PRMD-net2.ADMD-p400.C-it.": "*.net2.it.\t3600\tIN\tPX\t10 net2.it. PRMD-net2.ADMD-p400.C-it.", - "ab.net2.it. IN PX 10 ab.net2.it. O-ab.PRMD-net2.ADMDb.C-it.": "ab.net2.it.\t3600\tIN\tPX\t10 ab.net2.it. O-ab.PRMD-net2.ADMDb.C-it.", - } - for i, o := range dt { - rr, err := NewRR(i) - if err != nil { - t.Error("failed to parse RR: ", err) - continue - } - if rr.String() != o { - t.Errorf("`%s' should be equal to\n`%s', but is `%s'", i, o, rr.String()) - } - } -} - -func TestComment(t *testing.T) { - // Comments we must see - comments := map[string]bool{"; this is comment 1": true, - "; this is comment 4": true, "; this is comment 6": true, - "; this is comment 7": true, "; this is comment 8": true} - zone := ` -foo. IN A 10.0.0.1 ; this is comment 1 -foo. IN A ( - 10.0.0.2 ; this is comment2 -) -; this is comment3 -foo. IN A 10.0.0.3 -foo. IN A ( 10.0.0.4 ); this is comment 4 - -foo. IN A 10.0.0.5 -; this is comment5 - -foo. IN A 10.0.0.6 - -foo. IN DNSKEY 256 3 5 AwEAAb+8l ; this is comment 6 -foo. IN NSEC miek.nl. TXT RRSIG NSEC; this is comment 7 -foo. IN TXT "THIS IS TEXT MAN"; this is comment 8 -` - for x := range ParseZone(strings.NewReader(zone), ".", "") { - if x.Error == nil { - if x.Comment != "" { - if _, ok := comments[x.Comment]; !ok { - t.Errorf("wrong comment %s", x.Comment) - } - } - } - } -} - -func TestEUIxx(t *testing.T) { - tests := map[string]string{ - "host.example. IN EUI48 00-00-5e-90-01-2a": "host.example.\t3600\tIN\tEUI48\t00-00-5e-90-01-2a", - "host.example. IN EUI64 00-00-5e-ef-00-00-00-2a": "host.example.\t3600\tIN\tEUI64\t00-00-5e-ef-00-00-00-2a", - } - for i, o := range tests { - r, err := NewRR(i) - if err != nil { - t.Errorf("failed to parse %s: %v", i, err) - } - if r.String() != o { - t.Errorf("want %s, got %s", o, r.String()) - } - } -} - -func TestUserRR(t *testing.T) { - tests := map[string]string{ - "host.example. IN UID 1234": "host.example.\t3600\tIN\tUID\t1234", - "host.example. IN GID 1234556": "host.example.\t3600\tIN\tGID\t1234556", - "host.example. IN UINFO \"Miek Gieben\"": "host.example.\t3600\tIN\tUINFO\t\"Miek Gieben\"", - } - for i, o := range tests { - r, err := NewRR(i) - if err != nil { - t.Errorf("failed to parse %s: %v", i, err) - } - if r.String() != o { - t.Errorf("want %s, got %s", o, r.String()) - } - } -} - -func TestTXT(t *testing.T) { - // Test single entry TXT record - rr, err := NewRR(`_raop._tcp.local. 60 IN TXT "single value"`) - if err != nil { - t.Error("failed to parse single value TXT record", err) - } else if rr, ok := rr.(*TXT); !ok { - t.Error("wrong type, record should be of type TXT") - } else { - if len(rr.Txt) != 1 { - t.Error("bad size of TXT value:", len(rr.Txt)) - } else if rr.Txt[0] != "single value" { - t.Error("bad single value") - } - if rr.String() != `_raop._tcp.local. 60 IN TXT "single value"` { - t.Error("bad representation of TXT record:", rr.String()) - } - if rr.len() != 28+1+12 { - t.Error("bad size of serialized record:", rr.len()) - } - } - - // Test multi entries TXT record - rr, err = NewRR(`_raop._tcp.local. 60 IN TXT "a=1" "b=2" "c=3" "d=4"`) - if err != nil { - t.Error("failed to parse multi-values TXT record", err) - } else if rr, ok := rr.(*TXT); !ok { - t.Error("wrong type, record should be of type TXT") - } else { - if len(rr.Txt) != 4 { - t.Error("bad size of TXT multi-value:", len(rr.Txt)) - } else if rr.Txt[0] != "a=1" || rr.Txt[1] != "b=2" || rr.Txt[2] != "c=3" || rr.Txt[3] != "d=4" { - t.Error("bad values in TXT records") - } - if rr.String() != `_raop._tcp.local. 60 IN TXT "a=1" "b=2" "c=3" "d=4"` { - t.Error("bad representation of TXT multi value record:", rr.String()) - } - if rr.len() != 28+1+3+1+3+1+3+1+3 { - t.Error("bad size of serialized multi value record:", rr.len()) - } - } - - // Test empty-string in TXT record - rr, err = NewRR(`_raop._tcp.local. 60 IN TXT ""`) - if err != nil { - t.Error("failed to parse empty-string TXT record", err) - } else if rr, ok := rr.(*TXT); !ok { - t.Error("wrong type, record should be of type TXT") - } else { - if len(rr.Txt) != 1 { - t.Error("bad size of TXT empty-string value:", len(rr.Txt)) - } else if rr.Txt[0] != "" { - t.Error("bad value for empty-string TXT record") - } - if rr.String() != `_raop._tcp.local. 60 IN TXT ""` { - t.Error("bad representation of empty-string TXT record:", rr.String()) - } - if rr.len() != 28+1 { - t.Error("bad size of serialized record:", rr.len()) - } - } - - // Test TXT record with chunk larger than 255 bytes, they should be split up, by the parser - s := "" - for i := 0; i < 255; i++ { - s += "a" - } - s += "b" - rr, err = NewRR(`test.local. 60 IN TXT "` + s + `"`) - if err != nil { - t.Error("failed to parse empty-string TXT record", err) - } - if rr.(*TXT).Txt[1] != "b" { - t.Errorf("Txt should have two chunk, last one my be 'b', but is %s", rr.(*TXT).Txt[1]) - } -} - -func TestTypeXXXX(t *testing.T) { - _, err := NewRR("example.com IN TYPE1234 \\# 4 aabbccdd") - if err != nil { - t.Errorf("failed to parse TYPE1234 RR: %v", err) - } - _, err = NewRR("example.com IN TYPE655341 \\# 8 aabbccddaabbccdd") - if err == nil { - t.Errorf("this should not work, for TYPE655341") - } - _, err = NewRR("example.com IN TYPE1 \\# 4 0a000001") - if err == nil { - t.Errorf("this should not work") - } -} - -func TestPTR(t *testing.T) { - _, err := NewRR("144.2.0.192.in-addr.arpa. 900 IN PTR ilouse03146p0\\(.example.com.") - if err != nil { - t.Error("failed to parse ", err) - } -} - -func TestDigit(t *testing.T) { - tests := map[string]byte{ - "miek\\000.nl. 100 IN TXT \"A\"": 0, - "miek\\001.nl. 100 IN TXT \"A\"": 1, - "miek\\254.nl. 100 IN TXT \"A\"": 254, - "miek\\255.nl. 100 IN TXT \"A\"": 255, - "miek\\256.nl. 100 IN TXT \"A\"": 0, - "miek\\257.nl. 100 IN TXT \"A\"": 1, - "miek\\004.nl. 100 IN TXT \"A\"": 4, - } - for s, i := range tests { - r, err := NewRR(s) - buf := make([]byte, 40) - if err != nil { - t.Fatalf("failed to parse %v", err) - } - PackRR(r, buf, 0, nil, false) - if buf[5] != i { - t.Fatalf("5 pos must be %d, is %d", i, buf[5]) - } - r1, _, _ := UnpackRR(buf, 0) - if r1.Header().Ttl != 100 { - t.Fatalf("TTL should %d, is %d", 100, r1.Header().Ttl) - } - } -} - -func TestParseRRSIGTimestamp(t *testing.T) { - tests := map[string]bool{ - `miek.nl. IN RRSIG SOA 8 2 43200 20140210031301 20140111031301 12051 miek.nl. MVZUyrYwq0iZhMFDDnVXD2BvuNiUJjSYlJAgzyAE6CF875BMvvZa+Sb0 RlSCL7WODQSQHhCx/fegHhVVF+Iz8N8kOLrmXD1+jO3Bm6Prl5UhcsPx WTBsg/kmxbp8sR1kvH4oZJtVfakG3iDerrxNaf0sQwhZzyfJQAqpC7pcBoc=`: true, - `miek.nl. IN RRSIG SOA 8 2 43200 315565800 4102477800 12051 miek.nl. MVZUyrYwq0iZhMFDDnVXD2BvuNiUJjSYlJAgzyAE6CF875BMvvZa+Sb0 RlSCL7WODQSQHhCx/fegHhVVF+Iz8N8kOLrmXD1+jO3Bm6Prl5UhcsPx WTBsg/kmxbp8sR1kvH4oZJtVfakG3iDerrxNaf0sQwhZzyfJQAqpC7pcBoc=`: true, - } - for r := range tests { - _, err := NewRR(r) - if err != nil { - t.Error(err) - } - } -} - -func TestTxtEqual(t *testing.T) { - rr1 := new(TXT) - rr1.Hdr = RR_Header{Name: ".", Rrtype: TypeTXT, Class: ClassINET, Ttl: 0} - rr1.Txt = []string{"a\"a", "\"", "b"} - rr2, _ := NewRR(rr1.String()) - if rr1.String() != rr2.String() { - // This is not an error, but keep this test. - t.Errorf("these two TXT records should match:\n%s\n%s", rr1.String(), rr2.String()) - } -} - -func TestTxtLong(t *testing.T) { - rr1 := new(TXT) - rr1.Hdr = RR_Header{Name: ".", Rrtype: TypeTXT, Class: ClassINET, Ttl: 0} - // Make a long txt record, this breaks when sending the packet, - // but not earlier. - rr1.Txt = []string{"start-"} - for i := 0; i < 200; i++ { - rr1.Txt[0] += "start-" - } - str := rr1.String() - if len(str) < len(rr1.Txt[0]) { - t.Error("string conversion should work") - } -} - -// Basically, don't crash. -func TestMalformedPackets(t *testing.T) { - var packets = []string{ - "0021641c0000000100000000000078787878787878787878787303636f6d0000100001", - } - - // com = 63 6f 6d - for _, packet := range packets { - data, _ := hex.DecodeString(packet) - var msg Msg - msg.Unpack(data) - } -} - -type algorithm struct { - name uint8 - bits int -} - -func TestNewPrivateKey(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - algorithms := []algorithm{ - {ECDSAP256SHA256, 256}, - {ECDSAP384SHA384, 384}, - {RSASHA1, 1024}, - {RSASHA256, 2048}, - {DSA, 1024}, - {ED25519, 256}, - } - - for _, algo := range algorithms { - key := new(DNSKEY) - key.Hdr.Rrtype = TypeDNSKEY - key.Hdr.Name = "miek.nl." - key.Hdr.Class = ClassINET - key.Hdr.Ttl = 14400 - key.Flags = 256 - key.Protocol = 3 - key.Algorithm = algo.name - privkey, err := key.Generate(algo.bits) - if err != nil { - t.Fatal(err) - } - - newPrivKey, err := key.NewPrivateKey(key.PrivateKeyString(privkey)) - if err != nil { - t.Error(key.String()) - t.Error(key.PrivateKeyString(privkey)) - t.Fatal(err) - } - - switch newPrivKey := newPrivKey.(type) { - case *rsa.PrivateKey: - newPrivKey.Precompute() - } - - if !reflect.DeepEqual(privkey, newPrivKey) { - t.Errorf("[%v] Private keys differ:\n%#v\n%#v", AlgorithmToString[algo.name], privkey, newPrivKey) - } - } -} - -// special input test -func TestNewRRSpecial(t *testing.T) { - var ( - rr RR - err error - expect string - ) - - rr, err = NewRR("; comment") - expect = "" - if err != nil { - t.Errorf("unexpected err: %v", err) - } - if rr != nil { - t.Errorf("unexpected result: [%s] != [%s]", rr, expect) - } - - rr, err = NewRR("") - expect = "" - if err != nil { - t.Errorf("unexpected err: %v", err) - } - if rr != nil { - t.Errorf("unexpected result: [%s] != [%s]", rr, expect) - } - - rr, err = NewRR("$ORIGIN foo.") - expect = "" - if err != nil { - t.Errorf("unexpected err: %v", err) - } - if rr != nil { - t.Errorf("unexpected result: [%s] != [%s]", rr, expect) - } - - rr, err = NewRR(" ") - expect = "" - if err != nil { - t.Errorf("unexpected err: %v", err) - } - if rr != nil { - t.Errorf("unexpected result: [%s] != [%s]", rr, expect) - } - - rr, err = NewRR("\n") - expect = "" - if err != nil { - t.Errorf("unexpected err: %v", err) - } - if rr != nil { - t.Errorf("unexpected result: [%s] != [%s]", rr, expect) - } - - rr, err = NewRR("foo. A 1.1.1.1\nbar. A 2.2.2.2") - expect = "foo.\t3600\tIN\tA\t1.1.1.1" - if err != nil { - t.Errorf("unexpected err: %v", err) - } - if rr == nil || rr.String() != expect { - t.Errorf("unexpected result: [%s] != [%s]", rr, expect) - } -} - -func TestPrintfVerbsRdata(t *testing.T) { - x, _ := NewRR("www.miek.nl. IN MX 20 mx.miek.nl.") - if Field(x, 1) != "20" { - t.Errorf("should be 20") - } - if Field(x, 2) != "mx.miek.nl." { - t.Errorf("should be mx.miek.nl.") - } - - x, _ = NewRR("www.miek.nl. IN A 127.0.0.1") - if Field(x, 1) != "127.0.0.1" { - t.Errorf("should be 127.0.0.1") - } - - x, _ = NewRR("www.miek.nl. IN AAAA ::1") - if Field(x, 1) != "::1" { - t.Errorf("should be ::1") - } - - x, _ = NewRR("www.miek.nl. IN NSEC a.miek.nl. A NS SOA MX AAAA") - if Field(x, 1) != "a.miek.nl." { - t.Errorf("should be a.miek.nl.") - } - if Field(x, 2) != "A NS SOA MX AAAA" { - t.Errorf("should be A NS SOA MX AAAA") - } - - x, _ = NewRR("www.miek.nl. IN TXT \"first\" \"second\"") - if Field(x, 1) != "first second" { - t.Errorf("should be first second") - } - if Field(x, 0) != "" { - t.Errorf("should be empty") - } -} - -func TestParseTokenOverflow(t *testing.T) { - _, err := NewRR("_443._tcp.example.org. IN TLSA 0 0 0 308205e8308204d0a00302010202100411de8f53b462f6a5a861b712ec6b59300d06092a864886f70d01010b05003070310b300906035504061302555331153013060355040a130c446967694365727420496e6331193017060355040b13107777772e64696769636572742e636f6d312f302d06035504031326446967694365727420534841322048696768204173737572616e636520536572766572204341301e170d3134313130363030303030305a170d3135313131333132303030305a3081a5310b3009060355040613025553311330110603550408130a43616c69666f726e6961311430120603550407130b4c6f7320416e67656c6573313c303a060355040a1333496e7465726e657420436f72706f726174696f6e20666f722041737369676e6564204e616d657320616e64204e756d6265727331133011060355040b130a546563686e6f6c6f6779311830160603550403130f7777772e6578616d706c652e6f726730820122300d06092a864886f70d01010105000382010f003082010a02820101009e663f52a3d18cb67cdfed547408a4e47e4036538988da2798da3b6655f7240d693ed1cb3fe6d6ad3a9e657ff6efa86b83b0cad24e5d31ff2bf70ec3b78b213f1b4bf61bdc669cbbc07d67154128ca92a9b3cbb4213a836fb823ddd4d7cc04918314d25f06086fa9970ba17e357cca9b458c27eb71760ab95e3f9bc898ae89050ae4d09ba2f7e4259d9ff1e072a6971b18355a8b9e53670c3d5dbdbd283f93a764e71b3a4140ca0746090c08510e2e21078d7d07844bf9c03865b531a0bf2ee766bc401f6451c5a1e6f6fb5d5c1d6a97a0abe91ae8b02e89241e07353909ccd5b41c46de207c06801e08f20713603827f2ae3e68cf15ef881d7e0608f70742e30203010001a382024630820242301f0603551d230418301680145168ff90af0207753cccd9656462a212b859723b301d0603551d0e04160414b000a7f422e9b1ce216117c4c46e7164c8e60c553081810603551d11047a3078820f7777772e6578616d706c652e6f7267820b6578616d706c652e636f6d820b6578616d706c652e656475820b6578616d706c652e6e6574820b6578616d706c652e6f7267820f7777772e6578616d706c652e636f6d820f7777772e6578616d706c652e656475820f7777772e6578616d706c652e6e6574300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b0601050507030230750603551d1f046e306c3034a032a030862e687474703a2f2f63726c332e64696769636572742e636f6d2f736861322d68612d7365727665722d67332e63726c3034a032a030862e687474703a2f2f63726c342e64696769636572742e636f6d2f736861322d68612d7365727665722d67332e63726c30420603551d20043b3039303706096086480186fd6c0101302a302806082b06010505070201161c68747470733a2f2f7777772e64696769636572742e636f6d2f43505330818306082b0601050507010104773075302406082b060105050730018618687474703a2f2f6f6373702e64696769636572742e636f6d304d06082b060105050730028641687474703a2f2f636163657274732e64696769636572742e636f6d2f446967694365727453484132486967684173737572616e636553657276657243412e637274300c0603551d130101ff04023000300d06092a864886f70d01010b050003820101005eac2124dedb3978a86ff3608406acb542d3cb54cb83facd63aec88144d6a1bf15dbf1f215c4a73e241e582365cba9ea50dd306541653b3513af1a0756c1b2720e8d112b34fb67181efad9c4609bdc670fb025fa6e6d42188161b026cf3089a08369c2f3609fc84bcc3479140c1922ede430ca8dbac2b2a3cdacb305ba15dc7361c4c3a5e6daa99cb446cb221b28078a7a944efba70d96f31ac143d959bccd2fd50e30c325ea2624fb6b6dbe9344dbcf133bfbd5b4e892d635dbf31596451672c6b65ba5ac9b3cddea92b35dab1065cae3c8cb6bb450a62ea2f72ea7c6bdc7b65fa09b012392543734083c7687d243f8d0375304d99ccd2e148966a8637a6797") - if err == nil { - t.Fatalf("token overflow should return an error") - } -} - -func TestParseTLSA(t *testing.T) { - lt := []string{ - "_443._tcp.example.org.\t3600\tIN\tTLSA\t1 1 1 c22be239f483c08957bc106219cc2d3ac1a308dfbbdd0a365f17b9351234cf00", - "_443._tcp.example.org.\t3600\tIN\tTLSA\t2 1 2 4e85f45179e9cd6e0e68e2eb5be2e85ec9b92d91c609caf3ef0315213e3f92ece92c38397a607214de95c7fadc0ad0f1c604a469a0387959745032c0d51492f3", - "_443._tcp.example.org.\t3600\tIN\tTLSA\t3 0 2 69ec8d2277360b215d0cd956b0e2747108dff34b27d461a41c800629e38ee6c2d1230cc9e8e36711330adc6766e6ff7c5fbb37f106f248337c1a20ad682888d2", - } - for _, o := range lt { - rr, err := NewRR(o) - if err != nil { - t.Error("failed to parse RR: ", err) - continue - } - if rr.String() != o { - t.Errorf("`%s' should be equal to\n`%s', but is `%s'", o, o, rr.String()) - } - } -} - -func TestParseSMIMEA(t *testing.T) { - lt := map[string]string{ - "2e85e1db3e62be6ea._smimecert.example.com.\t3600\tIN\tSMIMEA\t1 1 2 bd80f334566928fc18f58df7e4928c1886f48f71ca3fd41cd9b1854aca7c2180aaacad2819612ed68e7bd3701cc39be7f2529b017c0bc6a53e8fb3f0c7d48070": "2e85e1db3e62be6ea._smimecert.example.com.\t3600\tIN\tSMIMEA\t1 1 2 bd80f334566928fc18f58df7e4928c1886f48f71ca3fd41cd9b1854aca7c2180aaacad2819612ed68e7bd3701cc39be7f2529b017c0bc6a53e8fb3f0c7d48070", - "2e85e1db3e62be6ea._smimecert.example.com.\t3600\tIN\tSMIMEA\t0 0 1 cdcf0fc66b182928c5217ddd42c826983f5a4b94160ee6c1c9be62d38199f710": "2e85e1db3e62be6ea._smimecert.example.com.\t3600\tIN\tSMIMEA\t0 0 1 cdcf0fc66b182928c5217ddd42c826983f5a4b94160ee6c1c9be62d38199f710", - "2e85e1db3e62be6ea._smimecert.example.com.\t3600\tIN\tSMIMEA\t3 0 2 499a1eda2af8828b552cdb9d80c3744a25872fddd73f3898d8e4afa3549595d2dd4340126e759566fe8c26b251fa0c887ba4869f011a65f7e79967c2eb729f5b": "2e85e1db3e62be6ea._smimecert.example.com.\t3600\tIN\tSMIMEA\t3 0 2 499a1eda2af8828b552cdb9d80c3744a25872fddd73f3898d8e4afa3549595d2dd4340126e759566fe8c26b251fa0c887ba4869f011a65f7e79967c2eb729f5b", - "2e85e1db3e62be6eb._smimecert.example.com.\t3600\tIN\tSMIMEA\t3 0 2 499a1eda2af8828b552cdb9d80c3744a25872fddd73f3898d8e4afa3549595d2dd4340126e759566fe8 c26b251fa0c887ba4869f01 1a65f7e79967c2eb729f5b": "2e85e1db3e62be6eb._smimecert.example.com.\t3600\tIN\tSMIMEA\t3 0 2 499a1eda2af8828b552cdb9d80c3744a25872fddd73f3898d8e4afa3549595d2dd4340126e759566fe8c26b251fa0c887ba4869f011a65f7e79967c2eb729f5b", - } - for i, o := range lt { - rr, err := NewRR(i) - if err != nil { - t.Error("failed to parse RR: ", err) - continue - } - if rr.String() != o { - t.Errorf("`%s' should be equal to\n`%s', but is `%s'", o, o, rr.String()) - } - } -} - -func TestParseSSHFP(t *testing.T) { - lt := []string{ - "test.example.org.\t300\tSSHFP\t1 2 (\n" + - "\t\t\t\t\tBC6533CDC95A79078A39A56EA7635984ED655318ADA9\n" + - "\t\t\t\t\tB6159E30723665DA95BB )", - "test.example.org.\t300\tSSHFP\t1 2 ( BC6533CDC 95A79078A39A56EA7635984ED655318AD A9B6159E3072366 5DA95BB )", - } - result := "test.example.org.\t300\tIN\tSSHFP\t1 2 BC6533CDC95A79078A39A56EA7635984ED655318ADA9B6159E30723665DA95BB" - for _, o := range lt { - rr, err := NewRR(o) - if err != nil { - t.Error("failed to parse RR: ", err) - continue - } - if rr.String() != result { - t.Errorf("`%s' should be equal to\n\n`%s', but is \n`%s'", o, result, rr.String()) - } - } -} - -func TestParseHINFO(t *testing.T) { - dt := map[string]string{ - "example.net. HINFO A B": "example.net. 3600 IN HINFO \"A\" \"B\"", - "example.net. HINFO \"A\" \"B\"": "example.net. 3600 IN HINFO \"A\" \"B\"", - "example.net. HINFO A B C D E F": "example.net. 3600 IN HINFO \"A\" \"B C D E F\"", - "example.net. HINFO AB": "example.net. 3600 IN HINFO \"AB\" \"\"", - // "example.net. HINFO PC-Intel-700mhz \"Redhat Linux 7.1\"": "example.net. 3600 IN HINFO \"PC-Intel-700mhz\" \"Redhat Linux 7.1\"", - // This one is recommended in Pro Bind book http://www.zytrax.com/books/dns/ch8/hinfo.html - // but effectively, even Bind would replace it to correctly formed text when you AXFR - // TODO: remove this set of comments or figure support for quoted/unquoted combinations in endingToTxtSlice function - } - for i, o := range dt { - rr, err := NewRR(i) - if err != nil { - t.Error("failed to parse RR: ", err) - continue - } - if rr.String() != o { - t.Errorf("`%s' should be equal to\n`%s', but is `%s'", i, o, rr.String()) - } - } -} - -func TestParseCAA(t *testing.T) { - lt := map[string]string{ - "example.net. CAA 0 issue \"symantec.com\"": "example.net.\t3600\tIN\tCAA\t0 issue \"symantec.com\"", - "example.net. CAA 0 issuewild \"symantec.com; stuff\"": "example.net.\t3600\tIN\tCAA\t0 issuewild \"symantec.com; stuff\"", - "example.net. CAA 128 tbs \"critical\"": "example.net.\t3600\tIN\tCAA\t128 tbs \"critical\"", - "example.net. CAA 2 auth \"0>09\\006\\010+\\006\\001\\004\\001\\214y\\002\\003\\001\\006\\009`\\134H\\001e\\003\\004\\002\\001\\004 y\\209\\012\\221r\\220\\156Q\\218\\150\\150{\\166\\245:\\231\\182%\\157:\\133\\179}\\1923r\\238\\151\\255\\128q\\145\\002\\001\\000\"": "example.net.\t3600\tIN\tCAA\t2 auth \"0>09\\006\\010+\\006\\001\\004\\001\\214y\\002\\003\\001\\006\\009`\\134H\\001e\\003\\004\\002\\001\\004 y\\209\\012\\221r\\220\\156Q\\218\\150\\150{\\166\\245:\\231\\182%\\157:\\133\\179}\\1923r\\238\\151\\255\\128q\\145\\002\\001\\000\"", - "example.net. TYPE257 0 issue \"symantec.com\"": "example.net.\t3600\tIN\tCAA\t0 issue \"symantec.com\"", - } - for i, o := range lt { - rr, err := NewRR(i) - if err != nil { - t.Error("failed to parse RR: ", err) - continue - } - if rr.String() != o { - t.Errorf("`%s' should be equal to\n`%s', but is `%s'", i, o, rr.String()) - } - } -} - -func TestPackCAA(t *testing.T) { - m := new(Msg) - record := new(CAA) - record.Hdr = RR_Header{Name: "example.com.", Rrtype: TypeCAA, Class: ClassINET, Ttl: 0} - record.Tag = "issue" - record.Value = "symantec.com" - record.Flag = 1 - - m.Answer = append(m.Answer, record) - bytes, err := m.Pack() - if err != nil { - t.Fatalf("failed to pack msg: %v", err) - } - if err := m.Unpack(bytes); err != nil { - t.Fatalf("failed to unpack msg: %v", err) - } - if len(m.Answer) != 1 { - t.Fatalf("incorrect number of answers unpacked") - } - rr := m.Answer[0].(*CAA) - if rr.Tag != "issue" { - t.Fatalf("invalid tag for unpacked answer") - } else if rr.Value != "symantec.com" { - t.Fatalf("invalid value for unpacked answer") - } else if rr.Flag != 1 { - t.Fatalf("invalid flag for unpacked answer") - } -} - -func TestParseURI(t *testing.T) { - lt := map[string]string{ - "_http._tcp. IN URI 10 1 \"http://www.example.com/path\"": "_http._tcp.\t3600\tIN\tURI\t10 1 \"http://www.example.com/path\"", - "_http._tcp. IN URI 10 1 \"\"": "_http._tcp.\t3600\tIN\tURI\t10 1 \"\"", - } - for i, o := range lt { - rr, err := NewRR(i) - if err != nil { - t.Error("failed to parse RR: ", err) - continue - } - if rr.String() != o { - t.Errorf("`%s' should be equal to\n`%s', but is `%s'", i, o, rr.String()) - } - } -} - -func TestParseAVC(t *testing.T) { - avcs := map[string]string{ - `example.org. IN AVC "app-name:WOLFGANG|app-class:OAM|business=yes"`: `example.org. 3600 IN AVC "app-name:WOLFGANG|app-class:OAM|business=yes"`, - } - for avc, o := range avcs { - rr, err := NewRR(avc) - if err != nil { - t.Error("failed to parse RR: ", err) - continue - } - if rr.String() != o { - t.Errorf("`%s' should be equal to\n`%s', but is `%s'", avc, o, rr.String()) - } - } -} - -func TestParseCSYNC(t *testing.T) { - syncs := map[string]string{ - `example.com. 3600 IN CSYNC 66 3 A NS AAAA`: `example.com. 3600 IN CSYNC 66 3 A NS AAAA`, - } - for s, o := range syncs { - rr, err := NewRR(s) - if err != nil { - t.Error("failed to parse RR: ", err) - continue - } - if rr.String() != o { - t.Errorf("`%s' should be equal to\n`%s', but is `%s'", s, o, rr.String()) - } - } -} - -func TestParseBadNAPTR(t *testing.T) { - // Should look like: mplus.ims.vodafone.com. 3600 IN NAPTR 10 100 "S" "SIP+D2U" "" _sip._udp.mplus.ims.vodafone.com. - naptr := `mplus.ims.vodafone.com. 3600 IN NAPTR 10 100 S SIP+D2U _sip._udp.mplus.ims.vodafone.com.` - _, err := NewRR(naptr) // parse fails, we should not have leaked a goroutine. - if err == nil { - t.Fatalf("parsing NAPTR should have failed: %s", naptr) - } - if err := goroutineLeaked(); err != nil { - t.Errorf("leaked goroutines: %s", err) - } -} - -func TestUnbalancedParens(t *testing.T) { - sig := `example.com. 3600 IN RRSIG MX 15 2 3600 ( - 1440021600 1438207200 3613 example.com. ( - oL9krJun7xfBOIWcGHi7mag5/hdZrKWw15jPGrHpjQeRAvTdszaPD+QLs3f - x8A4M3e23mRZ9VrbpMngwcrqNAg== )` - _, err := NewRR(sig) - if err == nil { - t.Fatalf("failed to detect extra opening brace") - } -} - -func TestBad(t *testing.T) { - tests := []string{ - `" TYPE257 9 1E12\x00\x105"`, - `" TYPE256 9 5"`, - `" TYPE257 0\"00000000000000400000000000000000000\x00\x10000000000000000000000000000000000 9 l\x16\x01\x005266"`, - } - for i := range tests { - s, err := strconv.Unquote(tests[i]) - if err != nil { - t.Fatalf("failed to unquote: %q: %s", tests[i], err) - } - if _, err = NewRR(s); err == nil { - t.Errorf("correctly parsed %q", s) - } - } -} diff --git a/vendor/github.com/miekg/dns/privaterr.go b/vendor/github.com/miekg/dns/privaterr.go index 41989e7ae..74544a74e 100644 --- a/vendor/github.com/miekg/dns/privaterr.go +++ b/vendor/github.com/miekg/dns/privaterr.go @@ -105,7 +105,7 @@ func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) return rr, off, err } - setPrivateRR := func(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { + setPrivateRR := func(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := mkPrivateRR(h.Rrtype) rr.Hdr = h @@ -115,7 +115,7 @@ func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) for { // TODO(miek): we could also be returning _QUOTE, this might or might not // be an issue (basically parsing TXT becomes hard) - switch l = <-c; l.value { + switch l, _ = c.Next(); l.value { case zNewline, zEOF: break Fetch case zString: @@ -134,7 +134,7 @@ func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) typeToparserFunc[rtype] = parserFunc{setPrivateRR, true} } -// PrivateHandleRemove removes defenitions required to support private RR type. +// PrivateHandleRemove removes definitions required to support private RR type. func PrivateHandleRemove(rtype uint16) { rtypestr, ok := TypeToString[rtype] if ok { @@ -144,5 +144,4 @@ func PrivateHandleRemove(rtype uint16) { delete(StringToType, rtypestr) delete(typeToUnpack, rtype) } - return } diff --git a/vendor/github.com/miekg/dns/privaterr_test.go b/vendor/github.com/miekg/dns/privaterr_test.go deleted file mode 100644 index fa5ff48fa..000000000 --- a/vendor/github.com/miekg/dns/privaterr_test.go +++ /dev/null @@ -1,166 +0,0 @@ -package dns_test - -import ( - "strings" - "testing" - - "github.com/miekg/dns" -) - -const TypeISBN uint16 = 0xFF00 - -// A crazy new RR type :) -type ISBN struct { - x string // rdata with 10 or 13 numbers, dashes or spaces allowed -} - -func NewISBN() dns.PrivateRdata { return &ISBN{""} } - -func (rd *ISBN) Len() int { return len([]byte(rd.x)) } -func (rd *ISBN) String() string { return rd.x } - -func (rd *ISBN) Parse(txt []string) error { - rd.x = strings.TrimSpace(strings.Join(txt, " ")) - return nil -} - -func (rd *ISBN) Pack(buf []byte) (int, error) { - b := []byte(rd.x) - n := copy(buf, b) - if n != len(b) { - return n, dns.ErrBuf - } - return n, nil -} - -func (rd *ISBN) Unpack(buf []byte) (int, error) { - rd.x = string(buf) - return len(buf), nil -} - -func (rd *ISBN) Copy(dest dns.PrivateRdata) error { - isbn, ok := dest.(*ISBN) - if !ok { - return dns.ErrRdata - } - isbn.x = rd.x - return nil -} - -var testrecord = strings.Join([]string{"example.org.", "3600", "IN", "ISBN", "12-3 456789-0-123"}, "\t") - -func TestPrivateText(t *testing.T) { - dns.PrivateHandle("ISBN", TypeISBN, NewISBN) - defer dns.PrivateHandleRemove(TypeISBN) - - rr, err := dns.NewRR(testrecord) - if err != nil { - t.Fatal(err) - } - if rr.String() != testrecord { - t.Errorf("record string representation did not match original %#v != %#v", rr.String(), testrecord) - } -} - -func TestPrivateByteSlice(t *testing.T) { - dns.PrivateHandle("ISBN", TypeISBN, NewISBN) - defer dns.PrivateHandleRemove(TypeISBN) - - rr, err := dns.NewRR(testrecord) - if err != nil { - t.Fatal(err) - } - - buf := make([]byte, 100) - off, err := dns.PackRR(rr, buf, 0, nil, false) - if err != nil { - t.Errorf("got error packing ISBN: %v", err) - } - - custrr := rr.(*dns.PrivateRR) - if ln := custrr.Data.Len() + len(custrr.Header().Name) + 11; ln != off { - t.Errorf("offset is not matching to length of Private RR: %d!=%d", off, ln) - } - - rr1, off1, err := dns.UnpackRR(buf[:off], 0) - if err != nil { - t.Errorf("got error unpacking ISBN: %v", err) - return - } - - if off1 != off { - t.Errorf("offset after unpacking differs: %d != %d", off1, off) - } - - if rr1.String() != testrecord { - t.Errorf("record string representation did not match original %#v != %#v", rr1.String(), testrecord) - } -} - -const TypeVERSION uint16 = 0xFF01 - -type VERSION struct { - x string -} - -func NewVersion() dns.PrivateRdata { return &VERSION{""} } - -func (rd *VERSION) String() string { return rd.x } -func (rd *VERSION) Parse(txt []string) error { - rd.x = strings.TrimSpace(strings.Join(txt, " ")) - return nil -} - -func (rd *VERSION) Pack(buf []byte) (int, error) { - b := []byte(rd.x) - n := copy(buf, b) - if n != len(b) { - return n, dns.ErrBuf - } - return n, nil -} - -func (rd *VERSION) Unpack(buf []byte) (int, error) { - rd.x = string(buf) - return len(buf), nil -} - -func (rd *VERSION) Copy(dest dns.PrivateRdata) error { - isbn, ok := dest.(*VERSION) - if !ok { - return dns.ErrRdata - } - isbn.x = rd.x - return nil -} - -func (rd *VERSION) Len() int { - return len([]byte(rd.x)) -} - -var smallzone = `$ORIGIN example.org. -@ 3600 IN SOA sns.dns.icann.org. noc.dns.icann.org. ( - 2014091518 7200 3600 1209600 3600 -) - A 1.2.3.4 -ok ISBN 1231-92110-12 -go VERSION ( - 1.3.1 ; comment -) -www ISBN 1231-92110-16 -* CNAME @ -` - -func TestPrivateZoneParser(t *testing.T) { - dns.PrivateHandle("ISBN", TypeISBN, NewISBN) - dns.PrivateHandle("VERSION", TypeVERSION, NewVersion) - defer dns.PrivateHandleRemove(TypeISBN) - defer dns.PrivateHandleRemove(TypeVERSION) - - r := strings.NewReader(smallzone) - for x := range dns.ParseZone(r, ".", "") { - if err := x.Error; err != nil { - t.Fatal(err) - } - } -} diff --git a/vendor/github.com/miekg/dns/remote_test.go b/vendor/github.com/miekg/dns/remote_test.go deleted file mode 100644 index 4cf701fe4..000000000 --- a/vendor/github.com/miekg/dns/remote_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package dns - -import "testing" - -const LinodeAddr = "176.58.119.54:53" - -func TestClientRemote(t *testing.T) { - m := new(Msg) - m.SetQuestion("go.dns.miek.nl.", TypeTXT) - - c := new(Client) - r, _, err := c.Exchange(m, LinodeAddr) - if err != nil { - t.Errorf("failed to exchange: %v", err) - } - if r != nil && r.Rcode != RcodeSuccess { - t.Errorf("failed to get an valid answer\n%v", r) - } -} diff --git a/vendor/github.com/miekg/dns/rr_test.go b/vendor/github.com/miekg/dns/rr_test.go deleted file mode 100644 index 77a153b1e..000000000 --- a/vendor/github.com/miekg/dns/rr_test.go +++ /dev/null @@ -1,7 +0,0 @@ -package dns - -// testRR returns the RR from string s. The error is thrown away. -func testRR(s string) RR { - r, _ := NewRR(s) - return r -} diff --git a/vendor/github.com/miekg/dns/sanitize_test.go b/vendor/github.com/miekg/dns/sanitize_test.go deleted file mode 100644 index b2c0e2081..000000000 --- a/vendor/github.com/miekg/dns/sanitize_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package dns - -import "testing" - -func TestDedup(t *testing.T) { - testcases := map[[3]RR][]string{ - [...]RR{ - testRR("mIek.nl. IN A 127.0.0.1"), - testRR("mieK.nl. IN A 127.0.0.1"), - testRR("miek.Nl. IN A 127.0.0.1"), - }: {"mIek.nl.\t3600\tIN\tA\t127.0.0.1"}, - [...]RR{ - testRR("miEk.nl. 2000 IN A 127.0.0.1"), - testRR("mieK.Nl. 1000 IN A 127.0.0.1"), - testRR("Miek.nL. 500 IN A 127.0.0.1"), - }: {"miEk.nl.\t500\tIN\tA\t127.0.0.1"}, - [...]RR{ - testRR("miek.nl. IN A 127.0.0.1"), - testRR("miek.nl. CH A 127.0.0.1"), - testRR("miek.nl. IN A 127.0.0.1"), - }: {"miek.nl.\t3600\tIN\tA\t127.0.0.1", - "miek.nl.\t3600\tCH\tA\t127.0.0.1", - }, - [...]RR{ - testRR("miek.nl. CH A 127.0.0.1"), - testRR("miek.nl. IN A 127.0.0.1"), - testRR("miek.de. IN A 127.0.0.1"), - }: {"miek.nl.\t3600\tCH\tA\t127.0.0.1", - "miek.nl.\t3600\tIN\tA\t127.0.0.1", - "miek.de.\t3600\tIN\tA\t127.0.0.1", - }, - [...]RR{ - testRR("miek.de. IN A 127.0.0.1"), - testRR("miek.nl. 200 IN A 127.0.0.1"), - testRR("miek.nl. 300 IN A 127.0.0.1"), - }: {"miek.de.\t3600\tIN\tA\t127.0.0.1", - "miek.nl.\t200\tIN\tA\t127.0.0.1", - }, - } - - for rr, expected := range testcases { - out := Dedup([]RR{rr[0], rr[1], rr[2]}, nil) - for i, o := range out { - if o.String() != expected[i] { - t.Fatalf("expected %v, got %v", expected[i], o.String()) - } - } - } -} - -func BenchmarkDedup(b *testing.B) { - rrs := []RR{ - testRR("miEk.nl. 2000 IN A 127.0.0.1"), - testRR("mieK.Nl. 1000 IN A 127.0.0.1"), - testRR("Miek.nL. 500 IN A 127.0.0.1"), - } - m := make(map[string]RR) - for i := 0; i < b.N; i++ { - Dedup(rrs, m) - } -} - -func TestNormalizedString(t *testing.T) { - tests := map[RR]string{ - testRR("mIEk.Nl. 3600 IN A 127.0.0.1"): "miek.nl.\tIN\tA\t127.0.0.1", - testRR("m\\ iek.nL. 3600 IN A 127.0.0.1"): "m\\ iek.nl.\tIN\tA\t127.0.0.1", - testRR("m\\\tIeK.nl. 3600 in A 127.0.0.1"): "m\\009iek.nl.\tIN\tA\t127.0.0.1", - } - for tc, expected := range tests { - n := normalizedString(tc) - if n != expected { - t.Errorf("expected %s, got %s", expected, n) - } - } -} diff --git a/vendor/github.com/miekg/dns/scan.go b/vendor/github.com/miekg/dns/scan.go index f9cd47401..61ace121e 100644 --- a/vendor/github.com/miekg/dns/scan.go +++ b/vendor/github.com/miekg/dns/scan.go @@ -1,6 +1,7 @@ package dns import ( + "bufio" "fmt" "io" "os" @@ -10,7 +11,10 @@ import ( ) const maxTok = 2048 // Largest token we can return. -const maxUint16 = 1<<16 - 1 + +// The maximum depth of $INCLUDE directives supported by the +// ZoneParser API. +const maxIncludeDepth = 7 // Tokinize a RFC 1035 zone file. The tokenizer will normalize it: // * Add ownernames if they are left blank; @@ -75,15 +79,13 @@ func (e *ParseError) Error() (s string) { } type lex struct { - token string // text of the token - tokenUpper string // uppercase text of the token - length int // length of the token - err bool // when true, token text has lexer error - value uint8 // value: zString, _BLANK, etc. - line int // line in the file - column int // column in the file - torc uint16 // type or class as parsed in the lexer, we only need to look this up in the grammar - comment string // any comment text seen + token string // text of the token + err bool // when true, token text has lexer error + value uint8 // value: zString, _BLANK, etc. + torc uint16 // type or class as parsed in the lexer, we only need to look this up in the grammar + line int // line in the file + column int // column in the file + comment string // any comment text seen } // Token holds the token that are returned when a zone file is parsed. @@ -103,10 +105,14 @@ type ttlState struct { } // NewRR reads the RR contained in the string s. Only the first RR is -// returned. If s contains no RR, return nil with no error. The class -// defaults to IN and TTL defaults to 3600. The full zone file syntax -// like $TTL, $ORIGIN, etc. is supported. All fields of the returned -// RR are set, except RR.Header().Rdlength which is set to 0. +// returned. If s contains no records, NewRR will return nil with no +// error. +// +// The class defaults to IN and TTL defaults to 3600. The full zone +// file syntax like $TTL, $ORIGIN, etc. is supported. +// +// All fields of the returned RR are set, except RR.Header().Rdlength +// which is set to 0. func NewRR(s string) (RR, error) { if len(s) > 0 && s[len(s)-1] != '\n' { // We need a closing newline return ReadRR(strings.NewReader(s+"\n"), "") @@ -114,28 +120,31 @@ func NewRR(s string) (RR, error) { return ReadRR(strings.NewReader(s), "") } -// ReadRR reads the RR contained in q. +// ReadRR reads the RR contained in r. +// +// The string file is used in error reporting and to resolve relative +// $INCLUDE directives. +// // See NewRR for more documentation. -func ReadRR(q io.Reader, filename string) (RR, error) { - defttl := &ttlState{defaultTtl, false} - r := <-parseZoneHelper(q, ".", filename, defttl, 1) - if r == nil { - return nil, nil - } - - if r.Error != nil { - return nil, r.Error - } - return r.RR, nil +func ReadRR(r io.Reader, file string) (RR, error) { + zp := NewZoneParser(r, ".", file) + zp.SetDefaultTTL(defaultTtl) + zp.SetIncludeAllowed(true) + rr, _ := zp.Next() + return rr, zp.Err() } -// ParseZone reads a RFC 1035 style zonefile from r. It returns *Tokens on the -// returned channel, each consisting of either a parsed RR and optional comment -// or a nil RR and an error. The string file is only used -// in error reporting. The string origin is used as the initial origin, as -// if the file would start with an $ORIGIN directive. -// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are supported. -// The channel t is closed by ParseZone when the end of r is reached. +// ParseZone reads a RFC 1035 style zonefile from r. It returns +// *Tokens on the returned channel, each consisting of either a +// parsed RR and optional comment or a nil RR and an error. The +// channel is closed by ParseZone when the end of r is reached. +// +// The string file is used in error reporting and to resolve relative +// $INCLUDE directives. The string origin is used as the initial +// origin, as if the file would start with an $ORIGIN directive. +// +// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are all +// supported. // // Basic usage pattern when reading from a string (z) containing the // zone data: @@ -148,91 +157,246 @@ func ReadRR(q io.Reader, filename string) (RR, error) { // } // } // -// Comments specified after an RR (and on the same line!) are returned too: +// Comments specified after an RR (and on the same line!) are +// returned too: // // foo. IN A 10.0.0.1 ; this is a comment // -// The text "; this is comment" is returned in Token.Comment. Comments inside the -// RR are discarded. Comments on a line by themselves are discarded too. +// The text "; this is comment" is returned in Token.Comment. +// Comments inside the RR are returned concatenated along with the +// RR. Comments on a line by themselves are discarded. +// +// To prevent memory leaks it is important to always fully drain the +// returned channel. If an error occurs, it will always be the last +// Token sent on the channel. +// +// Deprecated: New users should prefer the ZoneParser API. func ParseZone(r io.Reader, origin, file string) chan *Token { - return parseZoneHelper(r, origin, file, nil, 10000) -} - -func parseZoneHelper(r io.Reader, origin, file string, defttl *ttlState, chansize int) chan *Token { - t := make(chan *Token, chansize) - go parseZone(r, origin, file, defttl, t, 0) + t := make(chan *Token, 10000) + go parseZone(r, origin, file, t) return t } -func parseZone(r io.Reader, origin, f string, defttl *ttlState, t chan *Token, include int) { - defer func() { - if include == 0 { - close(t) - } - }() - s, cancel := scanInit(r) - c := make(chan lex) - // Start the lexer - go zlexer(s, c) - - defer func() { - cancel() - // zlexer can send up to three tokens, the next one and possibly 2 remainders. - // Do a non-blocking read. - _, ok := <-c - _, ok = <-c - _, ok = <-c +func parseZone(r io.Reader, origin, file string, t chan *Token) { + defer close(t) + + zp := NewZoneParser(r, origin, file) + zp.SetIncludeAllowed(true) + + for rr, ok := zp.Next(); ok; rr, ok = zp.Next() { + t <- &Token{RR: rr, Comment: zp.Comment()} + } + + if err := zp.Err(); err != nil { + pe, ok := err.(*ParseError) if !ok { - // too bad + pe = &ParseError{file: file, err: err.Error()} } - }() - // 6 possible beginnings of a line, _ is a space - // 0. zRRTYPE -> all omitted until the rrtype - // 1. zOwner _ zRrtype -> class/ttl omitted - // 2. zOwner _ zString _ zRrtype -> class omitted - // 3. zOwner _ zString _ zClass _ zRrtype -> ttl/class - // 4. zOwner _ zClass _ zRrtype -> ttl omitted - // 5. zOwner _ zClass _ zString _ zRrtype -> class/ttl (reversed) - // After detecting these, we know the zRrtype so we can jump to functions - // handling the rdata for each of these types. + t <- &Token{Error: pe} + } +} + +// ZoneParser is a parser for an RFC 1035 style zonefile. +// +// Each parsed RR in the zone is returned sequentially from Next. An +// optional comment can be retrieved with Comment. +// +// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are all +// supported. Although $INCLUDE is disabled by default. +// +// Basic usage pattern when reading from a string (z) containing the +// zone data: +// +// zp := NewZoneParser(strings.NewReader(z), "", "") +// +// for rr, ok := zp.Next(); ok; rr, ok = zp.Next() { +// // Do something with rr +// } +// +// if err := zp.Err(); err != nil { +// // log.Println(err) +// } +// +// Comments specified after an RR (and on the same line!) are +// returned too: +// +// foo. IN A 10.0.0.1 ; this is a comment +// +// The text "; this is comment" is returned from Comment. Comments inside +// the RR are returned concatenated along with the RR. Comments on a line +// by themselves are discarded. +type ZoneParser struct { + c *zlexer + + parseErr *ParseError + + origin string + file string + + defttl *ttlState + + h RR_Header + + // sub is used to parse $INCLUDE files and $GENERATE directives. + // Next, by calling subNext, forwards the resulting RRs from this + // sub parser to the calling code. + sub *ZoneParser + osFile *os.File + + com string + + includeDepth uint8 + + includeAllowed bool +} + +// NewZoneParser returns an RFC 1035 style zonefile parser that reads +// from r. +// +// The string file is used in error reporting and to resolve relative +// $INCLUDE directives. The string origin is used as the initial +// origin, as if the file would start with an $ORIGIN directive. +func NewZoneParser(r io.Reader, origin, file string) *ZoneParser { + var pe *ParseError if origin != "" { origin = Fqdn(origin) if _, ok := IsDomainName(origin); !ok { - t <- &Token{Error: &ParseError{f, "bad initial origin name", lex{}}} - return + pe = &ParseError{file, "bad initial origin name", lex{}} } } + return &ZoneParser{ + c: newZLexer(r), + + parseErr: pe, + + origin: origin, + file: file, + } +} + +// SetDefaultTTL sets the parsers default TTL to ttl. +func (zp *ZoneParser) SetDefaultTTL(ttl uint32) { + zp.defttl = &ttlState{ttl, false} +} + +// SetIncludeAllowed controls whether $INCLUDE directives are +// allowed. $INCLUDE directives are not supported by default. +// +// The $INCLUDE directive will open and read from a user controlled +// file on the system. Even if the file is not a valid zonefile, the +// contents of the file may be revealed in error messages, such as: +// +// /etc/passwd: dns: not a TTL: "root:x:0:0:root:/root:/bin/bash" at line: 1:31 +// /etc/shadow: dns: not a TTL: "root:$6$::0:99999:7:::" at line: 1:125 +func (zp *ZoneParser) SetIncludeAllowed(v bool) { + zp.includeAllowed = v +} + +// Err returns the first non-EOF error that was encountered by the +// ZoneParser. +func (zp *ZoneParser) Err() error { + if zp.parseErr != nil { + return zp.parseErr + } + + if zp.sub != nil { + if err := zp.sub.Err(); err != nil { + return err + } + } + + return zp.c.Err() +} + +func (zp *ZoneParser) setParseError(err string, l lex) (RR, bool) { + zp.parseErr = &ParseError{zp.file, err, l} + return nil, false +} + +// Comment returns an optional text comment that occurred alongside +// the RR. +func (zp *ZoneParser) Comment() string { + return zp.com +} + +func (zp *ZoneParser) subNext() (RR, bool) { + if rr, ok := zp.sub.Next(); ok { + zp.com = zp.sub.com + return rr, true + } + + if zp.sub.osFile != nil { + zp.sub.osFile.Close() + zp.sub.osFile = nil + } + + if zp.sub.Err() != nil { + // We have errors to surface. + return nil, false + } + + zp.sub = nil + return zp.Next() +} + +// Next advances the parser to the next RR in the zonefile and +// returns the (RR, true). It will return (nil, false) when the +// parsing stops, either by reaching the end of the input or an +// error. After Next returns (nil, false), the Err method will return +// any error that occurred during parsing. +func (zp *ZoneParser) Next() (RR, bool) { + zp.com = "" + + if zp.parseErr != nil { + return nil, false + } + if zp.sub != nil { + return zp.subNext() + } + + // 6 possible beginnings of a line (_ is a space): + // + // 0. zRRTYPE -> all omitted until the rrtype + // 1. zOwner _ zRrtype -> class/ttl omitted + // 2. zOwner _ zString _ zRrtype -> class omitted + // 3. zOwner _ zString _ zClass _ zRrtype -> ttl/class + // 4. zOwner _ zClass _ zRrtype -> ttl omitted + // 5. zOwner _ zClass _ zString _ zRrtype -> class/ttl (reversed) + // + // After detecting these, we know the zRrtype so we can jump to functions + // handling the rdata for each of these types. + st := zExpectOwnerDir // initial state - var h RR_Header - var prevName string - for l := range c { - // Lexer spotted an error already - if l.err == true { - t <- &Token{Error: &ParseError{f, l.token, l}} - return + h := &zp.h + for l, ok := zp.c.Next(); ok; l, ok = zp.c.Next() { + // zlexer spotted an error already + if l.err { + return zp.setParseError(l.token, l) } + switch st { case zExpectOwnerDir: // We can also expect a directive, like $TTL or $ORIGIN - if defttl != nil { - h.Ttl = defttl.ttl + if zp.defttl != nil { + h.Ttl = zp.defttl.ttl } + h.Class = ClassINET + switch l.value { case zNewline: st = zExpectOwnerDir case zOwner: - h.Name = l.token - name, ok := toAbsoluteName(l.token, origin) + name, ok := toAbsoluteName(l.token, zp.origin) if !ok { - t <- &Token{Error: &ParseError{f, "bad owner name", l}} - return + return zp.setParseError("bad owner name", l) } + h.Name = name - prevName = h.Name + st = zExpectOwnerBl case zDirTTL: st = zExpectDirTTLBl @@ -243,12 +407,12 @@ func parseZone(r io.Reader, origin, f string, defttl *ttlState, t chan *Token, i case zDirGenerate: st = zExpectDirGenerateBl case zRrtpe: - h.Name = prevName h.Rrtype = l.torc + st = zExpectRdata case zClass: - h.Name = prevName h.Class = l.torc + st = zExpectAnyNoClassBl case zBlank: // Discard, can happen when there is nothing on the @@ -256,297 +420,400 @@ func parseZone(r io.Reader, origin, f string, defttl *ttlState, t chan *Token, i case zString: ttl, ok := stringToTTL(l.token) if !ok { - t <- &Token{Error: &ParseError{f, "not a TTL", l}} - return + return zp.setParseError("not a TTL", l) } + h.Ttl = ttl - if defttl == nil || !defttl.isByDirective { - defttl = &ttlState{ttl, false} + + if zp.defttl == nil || !zp.defttl.isByDirective { + zp.defttl = &ttlState{ttl, false} } - st = zExpectAnyNoTTLBl + st = zExpectAnyNoTTLBl default: - t <- &Token{Error: &ParseError{f, "syntax error at beginning", l}} - return + return zp.setParseError("syntax error at beginning", l) } case zExpectDirIncludeBl: if l.value != zBlank { - t <- &Token{Error: &ParseError{f, "no blank after $INCLUDE-directive", l}} - return + return zp.setParseError("no blank after $INCLUDE-directive", l) } + st = zExpectDirInclude case zExpectDirInclude: if l.value != zString { - t <- &Token{Error: &ParseError{f, "expecting $INCLUDE value, not this...", l}} - return + return zp.setParseError("expecting $INCLUDE value, not this...", l) } - neworigin := origin // There may be optionally a new origin set after the filename, if not use current one - switch l := <-c; l.value { + + neworigin := zp.origin // There may be optionally a new origin set after the filename, if not use current one + switch l, _ := zp.c.Next(); l.value { case zBlank: - l := <-c + l, _ := zp.c.Next() if l.value == zString { - name, ok := toAbsoluteName(l.token, origin) + name, ok := toAbsoluteName(l.token, zp.origin) if !ok { - t <- &Token{Error: &ParseError{f, "bad origin name", l}} - return + return zp.setParseError("bad origin name", l) } + neworigin = name } case zNewline, zEOF: // Ok default: - t <- &Token{Error: &ParseError{f, "garbage after $INCLUDE", l}} - return + return zp.setParseError("garbage after $INCLUDE", l) + } + + if !zp.includeAllowed { + return zp.setParseError("$INCLUDE directive not allowed", l) + } + if zp.includeDepth >= maxIncludeDepth { + return zp.setParseError("too deeply nested $INCLUDE", l) } + // Start with the new file includePath := l.token if !filepath.IsAbs(includePath) { - includePath = filepath.Join(filepath.Dir(f), includePath) + includePath = filepath.Join(filepath.Dir(zp.file), includePath) } + r1, e1 := os.Open(includePath) if e1 != nil { - msg := fmt.Sprintf("failed to open `%s'", l.token) + var as string if !filepath.IsAbs(l.token) { - msg += fmt.Sprintf(" as `%s'", includePath) + as = fmt.Sprintf(" as `%s'", includePath) } - t <- &Token{Error: &ParseError{f, msg, l}} - return - } - if include+1 > 7 { - t <- &Token{Error: &ParseError{f, "too deeply nested $INCLUDE", l}} - return + + msg := fmt.Sprintf("failed to open `%s'%s: %v", l.token, as, e1) + return zp.setParseError(msg, l) } - parseZone(r1, neworigin, includePath, defttl, t, include+1) - st = zExpectOwnerDir + + zp.sub = NewZoneParser(r1, neworigin, includePath) + zp.sub.defttl, zp.sub.includeDepth, zp.sub.osFile = zp.defttl, zp.includeDepth+1, r1 + zp.sub.SetIncludeAllowed(true) + return zp.subNext() case zExpectDirTTLBl: if l.value != zBlank { - t <- &Token{Error: &ParseError{f, "no blank after $TTL-directive", l}} - return + return zp.setParseError("no blank after $TTL-directive", l) } + st = zExpectDirTTL case zExpectDirTTL: if l.value != zString { - t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}} - return + return zp.setParseError("expecting $TTL value, not this...", l) } - if e, _ := slurpRemainder(c, f); e != nil { - t <- &Token{Error: e} - return + + if e, _ := slurpRemainder(zp.c, zp.file); e != nil { + zp.parseErr = e + return nil, false } + ttl, ok := stringToTTL(l.token) if !ok { - t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}} - return + return zp.setParseError("expecting $TTL value, not this...", l) } - defttl = &ttlState{ttl, true} + + zp.defttl = &ttlState{ttl, true} + st = zExpectOwnerDir case zExpectDirOriginBl: if l.value != zBlank { - t <- &Token{Error: &ParseError{f, "no blank after $ORIGIN-directive", l}} - return + return zp.setParseError("no blank after $ORIGIN-directive", l) } + st = zExpectDirOrigin case zExpectDirOrigin: if l.value != zString { - t <- &Token{Error: &ParseError{f, "expecting $ORIGIN value, not this...", l}} - return + return zp.setParseError("expecting $ORIGIN value, not this...", l) } - if e, _ := slurpRemainder(c, f); e != nil { - t <- &Token{Error: e} + + if e, _ := slurpRemainder(zp.c, zp.file); e != nil { + zp.parseErr = e + return nil, false } - name, ok := toAbsoluteName(l.token, origin) + + name, ok := toAbsoluteName(l.token, zp.origin) if !ok { - t <- &Token{Error: &ParseError{f, "bad origin name", l}} - return + return zp.setParseError("bad origin name", l) } - origin = name + + zp.origin = name + st = zExpectOwnerDir case zExpectDirGenerateBl: if l.value != zBlank { - t <- &Token{Error: &ParseError{f, "no blank after $GENERATE-directive", l}} - return + return zp.setParseError("no blank after $GENERATE-directive", l) } + st = zExpectDirGenerate case zExpectDirGenerate: if l.value != zString { - t <- &Token{Error: &ParseError{f, "expecting $GENERATE value, not this...", l}} - return + return zp.setParseError("expecting $GENERATE value, not this...", l) } - if errMsg := generate(l, c, t, origin); errMsg != "" { - t <- &Token{Error: &ParseError{f, errMsg, l}} - return - } - st = zExpectOwnerDir + + return zp.generate(l) case zExpectOwnerBl: if l.value != zBlank { - t <- &Token{Error: &ParseError{f, "no blank after owner", l}} - return + return zp.setParseError("no blank after owner", l) } + st = zExpectAny case zExpectAny: switch l.value { case zRrtpe: - if defttl == nil { - t <- &Token{Error: &ParseError{f, "missing TTL with no previous value", l}} - return + if zp.defttl == nil { + return zp.setParseError("missing TTL with no previous value", l) } + h.Rrtype = l.torc + st = zExpectRdata case zClass: h.Class = l.torc + st = zExpectAnyNoClassBl case zString: ttl, ok := stringToTTL(l.token) if !ok { - t <- &Token{Error: &ParseError{f, "not a TTL", l}} - return + return zp.setParseError("not a TTL", l) } + h.Ttl = ttl - if defttl == nil || !defttl.isByDirective { - defttl = &ttlState{ttl, false} + + if zp.defttl == nil || !zp.defttl.isByDirective { + zp.defttl = &ttlState{ttl, false} } + st = zExpectAnyNoTTLBl default: - t <- &Token{Error: &ParseError{f, "expecting RR type, TTL or class, not this...", l}} - return + return zp.setParseError("expecting RR type, TTL or class, not this...", l) } case zExpectAnyNoClassBl: if l.value != zBlank { - t <- &Token{Error: &ParseError{f, "no blank before class", l}} - return + return zp.setParseError("no blank before class", l) } + st = zExpectAnyNoClass case zExpectAnyNoTTLBl: if l.value != zBlank { - t <- &Token{Error: &ParseError{f, "no blank before TTL", l}} - return + return zp.setParseError("no blank before TTL", l) } + st = zExpectAnyNoTTL case zExpectAnyNoTTL: switch l.value { case zClass: h.Class = l.torc + st = zExpectRrtypeBl case zRrtpe: h.Rrtype = l.torc + st = zExpectRdata default: - t <- &Token{Error: &ParseError{f, "expecting RR type or class, not this...", l}} - return + return zp.setParseError("expecting RR type or class, not this...", l) } case zExpectAnyNoClass: switch l.value { case zString: ttl, ok := stringToTTL(l.token) if !ok { - t <- &Token{Error: &ParseError{f, "not a TTL", l}} - return + return zp.setParseError("not a TTL", l) } + h.Ttl = ttl - if defttl == nil || !defttl.isByDirective { - defttl = &ttlState{ttl, false} + + if zp.defttl == nil || !zp.defttl.isByDirective { + zp.defttl = &ttlState{ttl, false} } + st = zExpectRrtypeBl case zRrtpe: h.Rrtype = l.torc + st = zExpectRdata default: - t <- &Token{Error: &ParseError{f, "expecting RR type or TTL, not this...", l}} - return + return zp.setParseError("expecting RR type or TTL, not this...", l) } case zExpectRrtypeBl: if l.value != zBlank { - t <- &Token{Error: &ParseError{f, "no blank before RR type", l}} - return + return zp.setParseError("no blank before RR type", l) } + st = zExpectRrtype case zExpectRrtype: if l.value != zRrtpe { - t <- &Token{Error: &ParseError{f, "unknown RR type", l}} - return + return zp.setParseError("unknown RR type", l) } + h.Rrtype = l.torc + st = zExpectRdata case zExpectRdata: - r, e, c1 := setRR(h, c, origin, f) + r, e, c1 := setRR(*h, zp.c, zp.origin, zp.file) if e != nil { // If e.lex is nil than we have encounter a unknown RR type // in that case we substitute our current lex token if e.lex.token == "" && e.lex.value == 0 { e.lex = l // Uh, dirty } - t <- &Token{Error: e} - return + + zp.parseErr = e + return nil, false } - t <- &Token{RR: r, Comment: c1} - st = zExpectOwnerDir + + zp.com = c1 + return r, true } } + // If we get here, we and the h.Rrtype is still zero, we haven't parsed anything, this // is not an error, because an empty zone file is still a zone file. + return nil, false +} + +type zlexer struct { + br io.ByteReader + + readErr error + + line int + column int + + com string + + l lex + + brace int + quote bool + space bool + commt bool + rrtype bool + owner bool + + nextL bool + + eol bool // end-of-line +} + +func newZLexer(r io.Reader) *zlexer { + br, ok := r.(io.ByteReader) + if !ok { + br = bufio.NewReaderSize(r, 1024) + } + + return &zlexer{ + br: br, + + line: 1, + + owner: true, + } +} + +func (zl *zlexer) Err() error { + if zl.readErr == io.EOF { + return nil + } + + return zl.readErr +} + +// readByte returns the next byte from the input +func (zl *zlexer) readByte() (byte, bool) { + if zl.readErr != nil { + return 0, false + } + + c, err := zl.br.ReadByte() + if err != nil { + zl.readErr = err + return 0, false + } + + // delay the newline handling until the next token is delivered, + // fixes off-by-one errors when reporting a parse error. + if zl.eol { + zl.line++ + zl.column = 0 + zl.eol = false + } + + if c == '\n' { + zl.eol = true + } else { + zl.column++ + } + + return c, true } -// zlexer scans the sourcefile and returns tokens on the channel c. -func zlexer(s *scan, c chan lex) { - var l lex - str := make([]byte, maxTok) // Should be enough for any token - stri := 0 // Offset in str (0 means empty) - com := make([]byte, maxTok) // Hold comment text - comi := 0 - quote := false - escape := false - space := false - commt := false - rrtype := false - owner := true - brace := 0 - x, err := s.tokenText() - defer close(c) - for err == nil { - l.column = s.position.Column - l.line = s.position.Line - if stri >= maxTok { +func (zl *zlexer) Next() (lex, bool) { + l := &zl.l + if zl.nextL { + zl.nextL = false + return *l, true + } + if l.err { + // Parsing errors should be sticky. + return lex{value: zEOF}, false + } + + var ( + str [maxTok]byte // Hold string text + com [maxTok]byte // Hold comment text + + stri int // Offset in str (0 means empty) + comi int // Offset in com (0 means empty) + + escape bool + ) + + if zl.com != "" { + comi = copy(com[:], zl.com) + zl.com = "" + } + + for x, ok := zl.readByte(); ok; x, ok = zl.readByte() { + l.line, l.column = zl.line, zl.column + l.comment = "" + + if stri >= len(str) { l.token = "token length insufficient for parsing" l.err = true - c <- l - return + return *l, true } - if comi >= maxTok { + if comi >= len(com) { l.token = "comment length insufficient for parsing" l.err = true - c <- l - return + return *l, true } switch x { case ' ', '\t': - if escape { - escape = false - str[stri] = x - stri++ - break - } - if quote { - // Inside quotes this is legal + if escape || zl.quote { + // Inside quotes or escaped this is legal. str[stri] = x stri++ + + escape = false break } - if commt { + + if zl.commt { com[comi] = x comi++ break } + + var retL lex if stri == 0 { // Space directly in the beginning, handled in the grammar - } else if owner { + } else if zl.owner { // If we have a string and its the first, make it an owner l.value = zOwner l.token = string(str[:stri]) - l.tokenUpper = strings.ToUpper(l.token) - l.length = stri + // escape $... start with a \ not a $, so this will work - switch l.tokenUpper { + switch strings.ToUpper(l.token) { case "$TTL": l.value = zDirTTL case "$ORIGIN": @@ -556,259 +823,316 @@ func zlexer(s *scan, c chan lex) { case "$GENERATE": l.value = zDirGenerate } - c <- l + + retL = *l } else { l.value = zString l.token = string(str[:stri]) - l.tokenUpper = strings.ToUpper(l.token) - l.length = stri - if !rrtype { - if t, ok := StringToType[l.tokenUpper]; ok { + + if !zl.rrtype { + tokenUpper := strings.ToUpper(l.token) + if t, ok := StringToType[tokenUpper]; ok { l.value = zRrtpe l.torc = t - rrtype = true - } else { - if strings.HasPrefix(l.tokenUpper, "TYPE") { - t, ok := typeToInt(l.token) - if !ok { - l.token = "unknown RR type" - l.err = true - c <- l - return - } - l.value = zRrtpe - rrtype = true - l.torc = t + + zl.rrtype = true + } else if strings.HasPrefix(tokenUpper, "TYPE") { + t, ok := typeToInt(l.token) + if !ok { + l.token = "unknown RR type" + l.err = true + return *l, true } + + l.value = zRrtpe + l.torc = t + + zl.rrtype = true } - if t, ok := StringToClass[l.tokenUpper]; ok { + + if t, ok := StringToClass[tokenUpper]; ok { l.value = zClass l.torc = t - } else { - if strings.HasPrefix(l.tokenUpper, "CLASS") { - t, ok := classToInt(l.token) - if !ok { - l.token = "unknown class" - l.err = true - c <- l - return - } - l.value = zClass - l.torc = t + } else if strings.HasPrefix(tokenUpper, "CLASS") { + t, ok := classToInt(l.token) + if !ok { + l.token = "unknown class" + l.err = true + return *l, true } + + l.value = zClass + l.torc = t } } - c <- l + + retL = *l } - stri = 0 - if !space && !commt { + zl.owner = false + + if !zl.space { + zl.space = true + l.value = zBlank l.token = " " - l.length = 1 - c <- l + + if retL == (lex{}) { + return *l, true + } + + zl.nextL = true + } + + if retL != (lex{}) { + return retL, true } - owner = false - space = true case ';': - if escape { - escape = false + if escape || zl.quote { + // Inside quotes or escaped this is legal. str[stri] = x stri++ + + escape = false break } - if quote { - // Inside quotes this is legal - str[stri] = x - stri++ - break + + zl.commt = true + zl.com = "" + + if comi > 1 { + // A newline was previously seen inside a comment that + // was inside braces and we delayed adding it until now. + com[comi] = ' ' // convert newline to space + comi++ } + + com[comi] = ';' + comi++ + if stri > 0 { + zl.com = string(com[:comi]) + l.value = zString l.token = string(str[:stri]) - l.tokenUpper = strings.ToUpper(l.token) - l.length = stri - c <- l - stri = 0 + return *l, true } - commt = true - com[comi] = ';' - comi++ case '\r': escape = false - if quote { + + if zl.quote { str[stri] = x stri++ - break } + // discard if outside of quotes case '\n': escape = false + // Escaped newline - if quote { + if zl.quote { str[stri] = x stri++ break } - // inside quotes this is legal - if commt { + + if zl.commt { // Reset a comment - commt = false - rrtype = false - stri = 0 + zl.commt = false + zl.rrtype = false + // If not in a brace this ends the comment AND the RR - if brace == 0 { - owner = true - owner = true + if zl.brace == 0 { + zl.owner = true + l.value = zNewline l.token = "\n" - l.tokenUpper = l.token - l.length = 1 l.comment = string(com[:comi]) - c <- l - l.comment = "" - comi = 0 - break + return *l, true } - com[comi] = ' ' // convert newline to space - comi++ + + zl.com = string(com[:comi]) break } - if brace == 0 { + if zl.brace == 0 { // If there is previous text, we should output it here + var retL lex if stri != 0 { l.value = zString l.token = string(str[:stri]) - l.tokenUpper = strings.ToUpper(l.token) - l.length = stri - if !rrtype { - if t, ok := StringToType[l.tokenUpper]; ok { + if !zl.rrtype { + tokenUpper := strings.ToUpper(l.token) + if t, ok := StringToType[tokenUpper]; ok { + zl.rrtype = true + l.value = zRrtpe l.torc = t - rrtype = true } } - c <- l + + retL = *l } + l.value = zNewline l.token = "\n" - l.tokenUpper = l.token - l.length = 1 - c <- l - stri = 0 - commt = false - rrtype = false - owner = true - comi = 0 + l.comment = zl.com + + zl.com = "" + zl.rrtype = false + zl.owner = true + + if retL != (lex{}) { + zl.nextL = true + return retL, true + } + + return *l, true } case '\\': // comments do not get escaped chars, everything is copied - if commt { + if zl.commt { com[comi] = x comi++ break } + // something already escaped must be in string if escape { str[stri] = x stri++ + escape = false break } + // something escaped outside of string gets added to string str[stri] = x stri++ + escape = true case '"': - if commt { + if zl.commt { com[comi] = x comi++ break } + if escape { str[stri] = x stri++ + escape = false break } - space = false + + zl.space = false + // send previous gathered text and the quote + var retL lex if stri != 0 { l.value = zString l.token = string(str[:stri]) - l.tokenUpper = strings.ToUpper(l.token) - l.length = stri - c <- l - stri = 0 + retL = *l } // send quote itself as separate token l.value = zQuote l.token = "\"" - l.tokenUpper = l.token - l.length = 1 - c <- l - quote = !quote + + zl.quote = !zl.quote + + if retL != (lex{}) { + zl.nextL = true + return retL, true + } + + return *l, true case '(', ')': - if commt { + if zl.commt { com[comi] = x comi++ break } - if escape { + + if escape || zl.quote { + // Inside quotes or escaped this is legal. str[stri] = x stri++ + escape = false break } - if quote { - str[stri] = x - stri++ - break - } + switch x { case ')': - brace-- - if brace < 0 { + zl.brace-- + + if zl.brace < 0 { l.token = "extra closing brace" - l.tokenUpper = l.token l.err = true - c <- l - return + return *l, true } case '(': - brace++ + zl.brace++ } default: escape = false - if commt { + + if zl.commt { com[comi] = x comi++ break } + str[stri] = x stri++ - space = false + + zl.space = false } - x, err = s.tokenText() } + + if zl.readErr != nil && zl.readErr != io.EOF { + // Don't return any tokens after a read error occurs. + return lex{value: zEOF}, false + } + + var retL lex if stri > 0 { - // Send remainder - l.token = string(str[:stri]) - l.tokenUpper = strings.ToUpper(l.token) - l.length = stri + // Send remainder of str l.value = zString - c <- l + l.token = string(str[:stri]) + retL = *l + + if comi <= 0 { + return retL, true + } } - if brace != 0 { + + if comi > 0 { + // Send remainder of com + l.value = zNewline + l.token = "\n" + l.comment = string(com[:comi]) + + if retL != (lex{}) { + zl.nextL = true + return retL, true + } + + return *l, true + } + + if zl.brace != 0 { + l.comment = "" // in case there was left over string and comment l.token = "unbalanced brace" - l.tokenUpper = l.token l.err = true - c <- l + return *l, true } + + return lex{value: zEOF}, false } // Extract the class number from CLASSxx @@ -969,12 +1293,12 @@ func locCheckEast(token string, longitude uint32) (uint32, bool) { } // "Eat" the rest of the "line". Return potential comments -func slurpRemainder(c chan lex, f string) (*ParseError, string) { - l := <-c +func slurpRemainder(c *zlexer, f string) (*ParseError, string) { + l, _ := c.Next() com := "" switch l.value { case zBlank: - l = <-c + l, _ = c.Next() com = l.comment if l.value != zNewline && l.value != zEOF { return &ParseError{f, "garbage after rdata", l}, "" diff --git a/vendor/github.com/miekg/dns/scan_rr.go b/vendor/github.com/miekg/dns/scan_rr.go index e9556282d..935d22c3f 100644 --- a/vendor/github.com/miekg/dns/scan_rr.go +++ b/vendor/github.com/miekg/dns/scan_rr.go @@ -11,7 +11,7 @@ type parserFunc struct { // Func defines the function that parses the tokens and returns the RR // or an error. The last string contains any comments in the line as // they returned by the lexer as well. - Func func(h RR_Header, c chan lex, origin string, file string) (RR, *ParseError, string) + Func func(h RR_Header, c *zlexer, origin string, file string) (RR, *ParseError, string) // Signals if the RR ending is of variable length, like TXT or records // that have Hexadecimal or Base64 as their last element in the Rdata. Records // that have a fixed ending or for instance A, AAAA, SOA and etc. @@ -23,7 +23,7 @@ type parserFunc struct { // After the rdata there may come a zBlank and then a zNewline // or immediately a zNewline. If this is not the case we flag // an *ParseError: garbage after rdata. -func setRR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setRR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { parserfunc, ok := typeToparserFunc[h.Rrtype] if ok { r, e, cm := parserfunc.Func(h, c, o, f) @@ -45,9 +45,9 @@ func setRR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { // A remainder of the rdata with embedded spaces, return the parsed string (sans the spaces) // or an error -func endingToString(c chan lex, errstr, f string) (string, *ParseError, string) { +func endingToString(c *zlexer, errstr, f string) (string, *ParseError, string) { s := "" - l := <-c // zString + l, _ := c.Next() // zString for l.value != zNewline && l.value != zEOF { if l.err { return s, &ParseError{f, errstr, l}, "" @@ -59,16 +59,16 @@ func endingToString(c chan lex, errstr, f string) (string, *ParseError, string) default: return "", &ParseError{f, errstr, l}, "" } - l = <-c + l, _ = c.Next() } return s, nil, l.comment } // A remainder of the rdata with embedded spaces, split on unquoted whitespace // and return the parsed string slice or an error -func endingToTxtSlice(c chan lex, errstr, f string) ([]string, *ParseError, string) { +func endingToTxtSlice(c *zlexer, errstr, f string) ([]string, *ParseError, string) { // Get the remaining data until we see a zNewline - l := <-c + l, _ := c.Next() if l.err { return nil, &ParseError{f, errstr, l}, "" } @@ -117,7 +117,7 @@ func endingToTxtSlice(c chan lex, errstr, f string) ([]string, *ParseError, stri default: return nil, &ParseError{f, errstr, l}, "" } - l = <-c + l, _ = c.Next() } if quote { return nil, &ParseError{f, errstr, l}, "" @@ -125,12 +125,12 @@ func endingToTxtSlice(c chan lex, errstr, f string) ([]string, *ParseError, stri return s, nil, l.comment } -func setA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(A) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -141,12 +141,12 @@ func setA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setAAAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setAAAA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(AAAA) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -157,13 +157,13 @@ func setAAAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setNS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setNS(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(NS) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Ns = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -175,13 +175,13 @@ func setNS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setPTR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(PTR) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Ptr = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -193,13 +193,13 @@ func setPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setNSAPPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setNSAPPTR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(NSAPPTR) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Ptr = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -211,13 +211,13 @@ func setNSAPPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) return rr, nil, "" } -func setRP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setRP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(RP) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Mbox = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -227,8 +227,8 @@ func setRP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Mbox = mbox - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() rr.Txt = l.token txt, txtOk := toAbsoluteName(l.token, o) @@ -240,13 +240,13 @@ func setRP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setMR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setMR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(MR) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Mr = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -258,13 +258,13 @@ func setMR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setMB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setMB(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(MB) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Mb = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -276,13 +276,13 @@ func setMB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setMG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setMG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(MG) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Mg = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -294,7 +294,7 @@ func setMG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setHINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setHINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(HINFO) rr.Hdr = h @@ -320,13 +320,13 @@ func setHINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setMINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setMINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(MINFO) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Rmail = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -336,8 +336,8 @@ func setMINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Rmail = rmail - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() rr.Email = l.token email, emailOk := toAbsoluteName(l.token, o) @@ -349,13 +349,13 @@ func setMINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setMF(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setMF(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(MF) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Mf = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -367,13 +367,13 @@ func setMF(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setMD(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setMD(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(MD) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Md = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -385,12 +385,12 @@ func setMD(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setMX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setMX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(MX) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -400,8 +400,8 @@ func setMX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Preference = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Mx = l.token name, nameOk := toAbsoluteName(l.token, o) @@ -413,12 +413,12 @@ func setMX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setRT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setRT(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(RT) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -428,8 +428,8 @@ func setRT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Preference = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Host = l.token name, nameOk := toAbsoluteName(l.token, o) @@ -441,12 +441,12 @@ func setRT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setAFSDB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setAFSDB(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(AFSDB) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -456,8 +456,8 @@ func setAFSDB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Subtype = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Hostname = l.token name, nameOk := toAbsoluteName(l.token, o) @@ -468,12 +468,12 @@ func setAFSDB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setX25(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setX25(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(X25) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -484,12 +484,12 @@ func setX25(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setKX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setKX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(KX) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -499,8 +499,8 @@ func setKX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Preference = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Exchanger = l.token name, nameOk := toAbsoluteName(l.token, o) @@ -511,13 +511,13 @@ func setKX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setCNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setCNAME(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(CNAME) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Target = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -529,13 +529,13 @@ func setCNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setDNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setDNAME(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(DNAME) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Target = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -547,13 +547,13 @@ func setDNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setSOA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(SOA) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.Ns = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -563,8 +563,8 @@ func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Ns = ns - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() rr.Mbox = l.token mbox, mboxOk := toAbsoluteName(l.token, o) @@ -573,14 +573,14 @@ func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Mbox = mbox - <-c // zBlank + c.Next() // zBlank var ( v uint32 ok bool ) for i := 0; i < 5; i++ { - l = <-c + l, _ = c.Next() if l.err { return nil, &ParseError{f, "bad SOA zone parameter", l}, "" } @@ -600,16 +600,16 @@ func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { switch i { case 0: rr.Serial = v - <-c // zBlank + c.Next() // zBlank case 1: rr.Refresh = v - <-c // zBlank + c.Next() // zBlank case 2: rr.Retry = v - <-c // zBlank + c.Next() // zBlank case 3: rr.Expire = v - <-c // zBlank + c.Next() // zBlank case 4: rr.Minttl = v } @@ -617,12 +617,12 @@ func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setSRV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setSRV(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(SRV) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -632,24 +632,24 @@ func setSRV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Priority = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { return nil, &ParseError{f, "bad SRV Weight", l}, "" } rr.Weight = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { return nil, &ParseError{f, "bad SRV Port", l}, "" } rr.Port = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Target = l.token name, nameOk := toAbsoluteName(l.token, o) @@ -660,12 +660,12 @@ func setSRV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setNAPTR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(NAPTR) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -675,8 +675,8 @@ func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Order = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { return nil, &ParseError{f, "bad NAPTR Preference", l}, "" @@ -684,15 +684,15 @@ func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { rr.Preference = uint16(i) // Flags - <-c // zBlank - l = <-c // _QUOTE + c.Next() // zBlank + l, _ = c.Next() // _QUOTE if l.value != zQuote { return nil, &ParseError{f, "bad NAPTR Flags", l}, "" } - l = <-c // Either String or Quote + l, _ = c.Next() // Either String or Quote if l.value == zString { rr.Flags = l.token - l = <-c // _QUOTE + l, _ = c.Next() // _QUOTE if l.value != zQuote { return nil, &ParseError{f, "bad NAPTR Flags", l}, "" } @@ -703,15 +703,15 @@ func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } // Service - <-c // zBlank - l = <-c // _QUOTE + c.Next() // zBlank + l, _ = c.Next() // _QUOTE if l.value != zQuote { return nil, &ParseError{f, "bad NAPTR Service", l}, "" } - l = <-c // Either String or Quote + l, _ = c.Next() // Either String or Quote if l.value == zString { rr.Service = l.token - l = <-c // _QUOTE + l, _ = c.Next() // _QUOTE if l.value != zQuote { return nil, &ParseError{f, "bad NAPTR Service", l}, "" } @@ -722,15 +722,15 @@ func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } // Regexp - <-c // zBlank - l = <-c // _QUOTE + c.Next() // zBlank + l, _ = c.Next() // _QUOTE if l.value != zQuote { return nil, &ParseError{f, "bad NAPTR Regexp", l}, "" } - l = <-c // Either String or Quote + l, _ = c.Next() // Either String or Quote if l.value == zString { rr.Regexp = l.token - l = <-c // _QUOTE + l, _ = c.Next() // _QUOTE if l.value != zQuote { return nil, &ParseError{f, "bad NAPTR Regexp", l}, "" } @@ -741,8 +741,8 @@ func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } // After quote no space?? - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Replacement = l.token name, nameOk := toAbsoluteName(l.token, o) @@ -753,13 +753,13 @@ func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setTALINK(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setTALINK(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(TALINK) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.PreviousName = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -769,8 +769,8 @@ func setTALINK(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.PreviousName = previousName - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() rr.NextName = l.token nextName, nextNameOk := toAbsoluteName(l.token, o) @@ -782,7 +782,7 @@ func setTALINK(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setLOC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(LOC) rr.Hdr = h // Non zero defaults for LOC record, see RFC 1876, Section 3. @@ -792,8 +792,8 @@ func setLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { ok := false // North - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } i, e := strconv.ParseUint(l.token, 10, 32) @@ -802,9 +802,9 @@ func setLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Latitude = 1000 * 60 * 60 * uint32(i) - <-c // zBlank + c.Next() // zBlank // Either number, 'N' or 'S' - l = <-c + l, _ = c.Next() if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok { goto East } @@ -814,16 +814,16 @@ func setLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Latitude += 1000 * 60 * uint32(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() if i, e := strconv.ParseFloat(l.token, 32); e != nil || l.err { return nil, &ParseError{f, "bad LOC Latitude seconds", l}, "" } else { rr.Latitude += uint32(1000 * i) } - <-c // zBlank + c.Next() // zBlank // Either number, 'N' or 'S' - l = <-c + l, _ = c.Next() if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok { goto East } @@ -832,16 +832,16 @@ func setLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { East: // East - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() if i, e := strconv.ParseUint(l.token, 10, 32); e != nil || l.err { return nil, &ParseError{f, "bad LOC Longitude", l}, "" } else { rr.Longitude = 1000 * 60 * 60 * uint32(i) } - <-c // zBlank + c.Next() // zBlank // Either number, 'E' or 'W' - l = <-c + l, _ = c.Next() if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok { goto Altitude } @@ -850,16 +850,16 @@ East: } else { rr.Longitude += 1000 * 60 * uint32(i) } - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() if i, e := strconv.ParseFloat(l.token, 32); e != nil || l.err { return nil, &ParseError{f, "bad LOC Longitude seconds", l}, "" } else { rr.Longitude += uint32(1000 * i) } - <-c // zBlank + c.Next() // zBlank // Either number, 'E' or 'W' - l = <-c + l, _ = c.Next() if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok { goto Altitude } @@ -867,9 +867,9 @@ East: return nil, &ParseError{f, "bad LOC Longitude East/West", l}, "" Altitude: - <-c // zBlank - l = <-c - if l.length == 0 || l.err { + c.Next() // zBlank + l, _ = c.Next() + if len(l.token) == 0 || l.err { return nil, &ParseError{f, "bad LOC Altitude", l}, "" } if l.token[len(l.token)-1] == 'M' || l.token[len(l.token)-1] == 'm' { @@ -882,7 +882,7 @@ Altitude: } // And now optionally the other values - l = <-c + l, _ = c.Next() count := 0 for l.value != zNewline && l.value != zEOF { switch l.value { @@ -913,18 +913,18 @@ Altitude: default: return nil, &ParseError{f, "bad LOC Size, HorizPre or VertPre", l}, "" } - l = <-c + l, _ = c.Next() } return rr, nil, "" } -func setHIP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setHIP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(HIP) rr.Hdr = h // HitLength is not represented - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -934,24 +934,24 @@ func setHIP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.PublicKeyAlgorithm = uint8(i) - <-c // zBlank - l = <-c // zString - if l.length == 0 || l.err { + c.Next() // zBlank + l, _ = c.Next() // zString + if len(l.token) == 0 || l.err { return nil, &ParseError{f, "bad HIP Hit", l}, "" } rr.Hit = l.token // This can not contain spaces, see RFC 5205 Section 6. rr.HitLength = uint8(len(rr.Hit)) / 2 - <-c // zBlank - l = <-c // zString - if l.length == 0 || l.err { + c.Next() // zBlank + l, _ = c.Next() // zString + if len(l.token) == 0 || l.err { return nil, &ParseError{f, "bad HIP PublicKey", l}, "" } rr.PublicKey = l.token // This cannot contain spaces rr.PublicKeyLength = uint16(base64.StdEncoding.DecodedLen(len(rr.PublicKey))) // RendezvousServers (if any) - l = <-c + l, _ = c.Next() var xs []string for l.value != zNewline && l.value != zEOF { switch l.value { @@ -966,18 +966,18 @@ func setHIP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { default: return nil, &ParseError{f, "bad HIP RendezvousServers", l}, "" } - l = <-c + l, _ = c.Next() } rr.RendezvousServers = xs return rr, nil, l.comment } -func setCERT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setCERT(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(CERT) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -988,15 +988,15 @@ func setCERT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } else { rr.Type = uint16(i) } - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString i, e := strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { return nil, &ParseError{f, "bad CERT KeyTag", l}, "" } rr.KeyTag = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString if v, ok := StringToAlgorithm[l.token]; ok { rr.Algorithm = v } else if i, e := strconv.ParseUint(l.token, 10, 8); e != nil { @@ -1012,7 +1012,7 @@ func setCERT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setOPENPGPKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setOPENPGPKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(OPENPGPKEY) rr.Hdr = h @@ -1024,12 +1024,12 @@ func setOPENPGPKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, strin return rr, nil, c1 } -func setCSYNC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setCSYNC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(CSYNC) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } j, e := strconv.ParseUint(l.token, 10, 32) @@ -1039,9 +1039,9 @@ func setCSYNC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Serial = uint32(j) - <-c // zBlank + c.Next() // zBlank - l = <-c + l, _ = c.Next() j, e = strconv.ParseUint(l.token, 10, 16) if e != nil { // Serial must be a number @@ -1054,14 +1054,15 @@ func setCSYNC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { k uint16 ok bool ) - l = <-c + l, _ = c.Next() for l.value != zNewline && l.value != zEOF { switch l.value { case zBlank: // Ok case zString: - if k, ok = StringToType[l.tokenUpper]; !ok { - if k, ok = typeToInt(l.tokenUpper); !ok { + tokenUpper := strings.ToUpper(l.token) + if k, ok = StringToType[tokenUpper]; !ok { + if k, ok = typeToInt(l.token); !ok { return nil, &ParseError{f, "bad CSYNC TypeBitMap", l}, "" } } @@ -1069,12 +1070,12 @@ func setCSYNC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { default: return nil, &ParseError{f, "bad CSYNC TypeBitMap", l}, "" } - l = <-c + l, _ = c.Next() } return rr, nil, l.comment } -func setSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { r, e, s := setRRSIG(h, c, o, f) if r != nil { return &SIG{*r.(*RRSIG)}, e, s @@ -1082,18 +1083,19 @@ func setSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, e, s } -func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setRRSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(RRSIG) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } - if t, ok := StringToType[l.tokenUpper]; !ok { - if strings.HasPrefix(l.tokenUpper, "TYPE") { - t, ok = typeToInt(l.tokenUpper) + tokenUpper := strings.ToUpper(l.token) + if t, ok := StringToType[tokenUpper]; !ok { + if strings.HasPrefix(tokenUpper, "TYPE") { + t, ok = typeToInt(l.token) if !ok { return nil, &ParseError{f, "bad RRSIG Typecovered", l}, "" } @@ -1105,32 +1107,32 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { rr.TypeCovered = t } - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, err := strconv.ParseUint(l.token, 10, 8) if err != nil || l.err { return nil, &ParseError{f, "bad RRSIG Algorithm", l}, "" } rr.Algorithm = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, err = strconv.ParseUint(l.token, 10, 8) if err != nil || l.err { return nil, &ParseError{f, "bad RRSIG Labels", l}, "" } rr.Labels = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, err = strconv.ParseUint(l.token, 10, 32) if err != nil || l.err { return nil, &ParseError{f, "bad RRSIG OrigTtl", l}, "" } rr.OrigTtl = uint32(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() if i, err := StringToTime(l.token); err != nil { // Try to see if all numeric and use it as epoch if i, err := strconv.ParseInt(l.token, 10, 64); err == nil { @@ -1143,8 +1145,8 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { rr.Expiration = i } - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() if i, err := StringToTime(l.token); err != nil { if i, err := strconv.ParseInt(l.token, 10, 64); err == nil { rr.Inception = uint32(i) @@ -1155,16 +1157,16 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { rr.Inception = i } - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, err = strconv.ParseUint(l.token, 10, 16) if err != nil || l.err { return nil, &ParseError{f, "bad RRSIG KeyTag", l}, "" } rr.KeyTag = uint16(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() rr.SignerName = l.token name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { @@ -1181,13 +1183,13 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setNSEC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setNSEC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(NSEC) rr.Hdr = h - l := <-c + l, _ := c.Next() rr.NextDomain = l.token - if l.length == 0 { // dynamic update rr. + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -1202,14 +1204,15 @@ func setNSEC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { k uint16 ok bool ) - l = <-c + l, _ = c.Next() for l.value != zNewline && l.value != zEOF { switch l.value { case zBlank: // Ok case zString: - if k, ok = StringToType[l.tokenUpper]; !ok { - if k, ok = typeToInt(l.tokenUpper); !ok { + tokenUpper := strings.ToUpper(l.token) + if k, ok = StringToType[tokenUpper]; !ok { + if k, ok = typeToInt(l.token); !ok { return nil, &ParseError{f, "bad NSEC TypeBitMap", l}, "" } } @@ -1217,17 +1220,17 @@ func setNSEC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { default: return nil, &ParseError{f, "bad NSEC TypeBitMap", l}, "" } - l = <-c + l, _ = c.Next() } return rr, nil, l.comment } -func setNSEC3(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setNSEC3(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(NSEC3) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -1236,22 +1239,22 @@ func setNSEC3(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad NSEC3 Hash", l}, "" } rr.Hash = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad NSEC3 Flags", l}, "" } rr.Flags = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { return nil, &ParseError{f, "bad NSEC3 Iterations", l}, "" } rr.Iterations = uint16(i) - <-c - l = <-c + c.Next() + l, _ = c.Next() if len(l.token) == 0 || l.err { return nil, &ParseError{f, "bad NSEC3 Salt", l}, "" } @@ -1260,8 +1263,8 @@ func setNSEC3(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { rr.Salt = l.token } - <-c - l = <-c + c.Next() + l, _ = c.Next() if len(l.token) == 0 || l.err { return nil, &ParseError{f, "bad NSEC3 NextDomain", l}, "" } @@ -1273,14 +1276,15 @@ func setNSEC3(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { k uint16 ok bool ) - l = <-c + l, _ = c.Next() for l.value != zNewline && l.value != zEOF { switch l.value { case zBlank: // Ok case zString: - if k, ok = StringToType[l.tokenUpper]; !ok { - if k, ok = typeToInt(l.tokenUpper); !ok { + tokenUpper := strings.ToUpper(l.token) + if k, ok = StringToType[tokenUpper]; !ok { + if k, ok = typeToInt(l.token); !ok { return nil, &ParseError{f, "bad NSEC3 TypeBitMap", l}, "" } } @@ -1288,17 +1292,17 @@ func setNSEC3(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { default: return nil, &ParseError{f, "bad NSEC3 TypeBitMap", l}, "" } - l = <-c + l, _ = c.Next() } return rr, nil, l.comment } -func setNSEC3PARAM(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setNSEC3PARAM(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(NSEC3PARAM) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -1307,22 +1311,22 @@ func setNSEC3PARAM(h RR_Header, c chan lex, o, f string) (RR, *ParseError, strin return nil, &ParseError{f, "bad NSEC3PARAM Hash", l}, "" } rr.Hash = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad NSEC3PARAM Flags", l}, "" } rr.Flags = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { return nil, &ParseError{f, "bad NSEC3PARAM Iterations", l}, "" } rr.Iterations = uint16(i) - <-c - l = <-c + c.Next() + l, _ = c.Next() if l.token != "-" { rr.SaltLength = uint8(len(l.token)) rr.Salt = l.token @@ -1330,16 +1334,16 @@ func setNSEC3PARAM(h RR_Header, c chan lex, o, f string) (RR, *ParseError, strin return rr, nil, "" } -func setEUI48(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setEUI48(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(EUI48) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } - if l.length != 17 || l.err { + if len(l.token) != 17 || l.err { return nil, &ParseError{f, "bad EUI48 Address", l}, "" } addr := make([]byte, 12) @@ -1363,16 +1367,16 @@ func setEUI48(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setEUI64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setEUI64(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(EUI64) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } - if l.length != 23 || l.err { + if len(l.token) != 23 || l.err { return nil, &ParseError{f, "bad EUI64 Address", l}, "" } addr := make([]byte, 16) @@ -1396,12 +1400,12 @@ func setEUI64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setSSHFP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setSSHFP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(SSHFP) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -1410,14 +1414,14 @@ func setSSHFP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad SSHFP Algorithm", l}, "" } rr.Algorithm = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad SSHFP Type", l}, "" } rr.Type = uint8(i) - <-c // zBlank + c.Next() // zBlank s, e1, c1 := endingToString(c, "bad SSHFP Fingerprint", f) if e1 != nil { return nil, e1, c1 @@ -1426,12 +1430,12 @@ func setSSHFP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setDNSKEYs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string) { +func setDNSKEYs(h RR_Header, c *zlexer, o, f, typ string) (RR, *ParseError, string) { rr := new(DNSKEY) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -1440,15 +1444,15 @@ func setDNSKEYs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, str return nil, &ParseError{f, "bad " + typ + " Flags", l}, "" } rr.Flags = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad " + typ + " Protocol", l}, "" } rr.Protocol = uint8(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad " + typ + " Algorithm", l}, "" @@ -1462,7 +1466,7 @@ func setDNSKEYs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, str return rr, nil, c1 } -func setKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { r, e, s := setDNSKEYs(h, c, o, f, "KEY") if r != nil { return &KEY{*r.(*DNSKEY)}, e, s @@ -1470,12 +1474,12 @@ func setKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, e, s } -func setDNSKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setDNSKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { r, e, s := setDNSKEYs(h, c, o, f, "DNSKEY") return r, e, s } -func setCDNSKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setCDNSKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { r, e, s := setDNSKEYs(h, c, o, f, "CDNSKEY") if r != nil { return &CDNSKEY{*r.(*DNSKEY)}, e, s @@ -1483,12 +1487,12 @@ func setCDNSKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) return nil, e, s } -func setRKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setRKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(RKEY) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -1497,15 +1501,15 @@ func setRKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad RKEY Flags", l}, "" } rr.Flags = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad RKEY Protocol", l}, "" } rr.Protocol = uint8(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad RKEY Algorithm", l}, "" @@ -1519,7 +1523,7 @@ func setRKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setEID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setEID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(EID) rr.Hdr = h s, e, c1 := endingToString(c, "bad EID Endpoint", f) @@ -1530,7 +1534,7 @@ func setEID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setNIMLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setNIMLOC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(NIMLOC) rr.Hdr = h s, e, c1 := endingToString(c, "bad NIMLOC Locator", f) @@ -1541,12 +1545,12 @@ func setNIMLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setGPOS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setGPOS(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(GPOS) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -1555,15 +1559,15 @@ func setGPOS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad GPOS Longitude", l}, "" } rr.Longitude = l.token - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() _, e = strconv.ParseFloat(l.token, 64) if e != nil || l.err { return nil, &ParseError{f, "bad GPOS Latitude", l}, "" } rr.Latitude = l.token - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() _, e = strconv.ParseFloat(l.token, 64) if e != nil || l.err { return nil, &ParseError{f, "bad GPOS Altitude", l}, "" @@ -1572,12 +1576,12 @@ func setGPOS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setDSs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string) { +func setDSs(h RR_Header, c *zlexer, o, f, typ string) (RR, *ParseError, string) { rr := new(DS) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -1586,10 +1590,11 @@ func setDSs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string) return nil, &ParseError{f, "bad " + typ + " KeyTag", l}, "" } rr.KeyTag = uint16(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() if i, e = strconv.ParseUint(l.token, 10, 8); e != nil { - i, ok := StringToAlgorithm[l.tokenUpper] + tokenUpper := strings.ToUpper(l.token) + i, ok := StringToAlgorithm[tokenUpper] if !ok || l.err { return nil, &ParseError{f, "bad " + typ + " Algorithm", l}, "" } @@ -1597,8 +1602,8 @@ func setDSs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string) } else { rr.Algorithm = uint8(i) } - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad " + typ + " DigestType", l}, "" @@ -1612,12 +1617,12 @@ func setDSs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string) return rr, nil, c1 } -func setDS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setDS(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { r, e, s := setDSs(h, c, o, f, "DS") return r, e, s } -func setDLV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setDLV(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { r, e, s := setDSs(h, c, o, f, "DLV") if r != nil { return &DLV{*r.(*DS)}, e, s @@ -1625,7 +1630,7 @@ func setDLV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, e, s } -func setCDS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setCDS(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { r, e, s := setDSs(h, c, o, f, "CDS") if r != nil { return &CDS{*r.(*DS)}, e, s @@ -1633,12 +1638,12 @@ func setCDS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, e, s } -func setTA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setTA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(TA) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -1647,10 +1652,11 @@ func setTA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad TA KeyTag", l}, "" } rr.KeyTag = uint16(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() if i, e := strconv.ParseUint(l.token, 10, 8); e != nil { - i, ok := StringToAlgorithm[l.tokenUpper] + tokenUpper := strings.ToUpper(l.token) + i, ok := StringToAlgorithm[tokenUpper] if !ok || l.err { return nil, &ParseError{f, "bad TA Algorithm", l}, "" } @@ -1658,27 +1664,27 @@ func setTA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } else { rr.Algorithm = uint8(i) } - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad TA DigestType", l}, "" } rr.DigestType = uint8(i) - s, e, c1 := endingToString(c, "bad TA Digest", f) - if e != nil { - return nil, e.(*ParseError), c1 + s, err, c1 := endingToString(c, "bad TA Digest", f) + if err != nil { + return nil, err, c1 } rr.Digest = s return rr, nil, c1 } -func setTLSA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setTLSA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(TLSA) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -1687,15 +1693,15 @@ func setTLSA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad TLSA Usage", l}, "" } rr.Usage = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad TLSA Selector", l}, "" } rr.Selector = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad TLSA MatchingType", l}, "" @@ -1710,12 +1716,12 @@ func setTLSA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setSMIMEA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setSMIMEA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(SMIMEA) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -1724,15 +1730,15 @@ func setSMIMEA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad SMIMEA Usage", l}, "" } rr.Usage = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad SMIMEA Selector", l}, "" } rr.Selector = uint8(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 8) if e != nil || l.err { return nil, &ParseError{f, "bad SMIMEA MatchingType", l}, "" @@ -1747,17 +1753,17 @@ func setSMIMEA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setRFC3597(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setRFC3597(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(RFC3597) rr.Hdr = h - l := <-c + l, _ := c.Next() if l.token != "\\#" { return nil, &ParseError{f, "bad RFC3597 Rdata", l}, "" } - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() rdlength, e := strconv.Atoi(l.token) if e != nil || l.err { return nil, &ParseError{f, "bad RFC3597 Rdata ", l}, "" @@ -1774,7 +1780,7 @@ func setRFC3597(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) return rr, nil, c1 } -func setSPF(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setSPF(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(SPF) rr.Hdr = h @@ -1786,7 +1792,7 @@ func setSPF(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setAVC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setAVC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(AVC) rr.Hdr = h @@ -1798,7 +1804,7 @@ func setAVC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setTXT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setTXT(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(TXT) rr.Hdr = h @@ -1812,7 +1818,7 @@ func setTXT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } // identical to setTXT -func setNINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setNINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(NINFO) rr.Hdr = h @@ -1824,12 +1830,12 @@ func setNINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setURI(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setURI(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(URI) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -1838,15 +1844,15 @@ func setURI(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad URI Priority", l}, "" } rr.Priority = uint16(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() i, e = strconv.ParseUint(l.token, 10, 16) if e != nil || l.err { return nil, &ParseError{f, "bad URI Weight", l}, "" } rr.Weight = uint16(i) - <-c // zBlank + c.Next() // zBlank s, err, c1 := endingToTxtSlice(c, "bad URI Target", f) if err != nil { return nil, err, "" @@ -1858,7 +1864,7 @@ func setURI(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setDHCID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setDHCID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { // awesome record to parse! rr := new(DHCID) rr.Hdr = h @@ -1871,12 +1877,12 @@ func setDHCID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setNID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setNID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(NID) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -1885,8 +1891,8 @@ func setNID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad NID Preference", l}, "" } rr.Preference = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString u, err := stringToNodeID(l) if err != nil || l.err { return nil, err, "" @@ -1895,12 +1901,12 @@ func setNID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setL32(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setL32(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(L32) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -1909,8 +1915,8 @@ func setL32(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad L32 Preference", l}, "" } rr.Preference = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Locator32 = net.ParseIP(l.token) if rr.Locator32 == nil || l.err { return nil, &ParseError{f, "bad L32 Locator", l}, "" @@ -1918,12 +1924,12 @@ func setL32(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setLP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setLP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(LP) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -1933,8 +1939,8 @@ func setLP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Preference = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Fqdn = l.token name, nameOk := toAbsoluteName(l.token, o) if l.err || !nameOk { @@ -1945,12 +1951,12 @@ func setLP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setL64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setL64(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(L64) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -1959,8 +1965,8 @@ func setL64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return nil, &ParseError{f, "bad L64 Preference", l}, "" } rr.Preference = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString u, err := stringToNodeID(l) if err != nil || l.err { return nil, err, "" @@ -1969,12 +1975,12 @@ func setL64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setUID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setUID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(UID) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -1986,12 +1992,12 @@ func setUID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setGID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setGID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(GID) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -2003,7 +2009,7 @@ func setGID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setUINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setUINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(UINFO) rr.Hdr = h @@ -2018,12 +2024,12 @@ func setUINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setPX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setPX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(PX) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, "" } @@ -2033,8 +2039,8 @@ func setPX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Preference = uint16(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Map822 = l.token map822, map822Ok := toAbsoluteName(l.token, o) if l.err || !map822Ok { @@ -2042,8 +2048,8 @@ func setPX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Map822 = map822 - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString rr.Mapx400 = l.token mapx400, mapx400Ok := toAbsoluteName(l.token, o) if l.err || !mapx400Ok { @@ -2054,12 +2060,12 @@ func setPX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, "" } -func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setCAA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(CAA) rr.Hdr = h - l := <-c - if l.length == 0 { // dynamic update rr. + l, _ := c.Next() + if len(l.token) == 0 { // dynamic update rr. return rr, nil, l.comment } @@ -2069,14 +2075,14 @@ func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { } rr.Flag = uint8(i) - <-c // zBlank - l = <-c // zString + c.Next() // zBlank + l, _ = c.Next() // zString if l.value != zString { return nil, &ParseError{f, "bad CAA Tag", l}, "" } rr.Tag = l.token - <-c // zBlank + c.Next() // zBlank s, e, c1 := endingToTxtSlice(c, "bad CAA Value", f) if e != nil { return nil, e, "" @@ -2088,43 +2094,43 @@ func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return rr, nil, c1 } -func setTKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { +func setTKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) { rr := new(TKEY) rr.Hdr = h - l := <-c + l, _ := c.Next() // Algorithm if l.value != zString { return nil, &ParseError{f, "bad TKEY algorithm", l}, "" } rr.Algorithm = l.token - <-c // zBlank + c.Next() // zBlank // Get the key length and key values - l = <-c + l, _ = c.Next() i, err := strconv.ParseUint(l.token, 10, 8) if err != nil || l.err { return nil, &ParseError{f, "bad TKEY key length", l}, "" } rr.KeySize = uint16(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() if l.value != zString { return nil, &ParseError{f, "bad TKEY key", l}, "" } rr.Key = l.token - <-c // zBlank + c.Next() // zBlank // Get the otherdata length and string data - l = <-c + l, _ = c.Next() i, err = strconv.ParseUint(l.token, 10, 8) if err != nil || l.err { return nil, &ParseError{f, "bad TKEY otherdata length", l}, "" } rr.OtherLen = uint16(i) - <-c // zBlank - l = <-c + c.Next() // zBlank + l, _ = c.Next() if l.value != zString { return nil, &ParseError{f, "bad TKEY otherday", l}, "" } diff --git a/vendor/github.com/miekg/dns/scan_test.go b/vendor/github.com/miekg/dns/scan_test.go deleted file mode 100644 index 88baa602c..000000000 --- a/vendor/github.com/miekg/dns/scan_test.go +++ /dev/null @@ -1,81 +0,0 @@ -package dns - -import ( - "io/ioutil" - "net" - "os" - "strings" - "testing" -) - -func TestParseZoneGenerate(t *testing.T) { - zone := "$ORIGIN example.org.\n$GENERATE 10-12 foo${2,3,d} IN A 127.0.0.$" - - wantRRs := []RR{ - &A{Hdr: RR_Header{Name: "foo012.example.org."}, A: net.ParseIP("127.0.0.10")}, - &A{Hdr: RR_Header{Name: "foo013.example.org."}, A: net.ParseIP("127.0.0.11")}, - &A{Hdr: RR_Header{Name: "foo014.example.org."}, A: net.ParseIP("127.0.0.12")}, - } - wantIdx := 0 - - tok := ParseZone(strings.NewReader(zone), "", "") - for x := range tok { - if wantIdx >= len(wantRRs) { - t.Fatalf("expected %d RRs, but got more", len(wantRRs)) - } - if x.Error != nil { - t.Fatalf("expected no error, but got %s", x.Error) - } - if got, want := x.RR.Header().Name, wantRRs[wantIdx].Header().Name; got != want { - t.Fatalf("expected name %s, but got %s", want, got) - } - a, ok := x.RR.(*A) - if !ok { - t.Fatalf("expected *A RR, but got %T", x.RR) - } - if got, want := a.A, wantRRs[wantIdx].(*A).A; !got.Equal(want) { - t.Fatalf("expected A with IP %v, but got %v", got, want) - } - wantIdx++ - } -} - -func TestParseZoneInclude(t *testing.T) { - - tmpfile, err := ioutil.TempFile("", "dns") - if err != nil { - t.Fatalf("could not create tmpfile for test: %s", err) - } - - if _, err := tmpfile.WriteString("foo\tIN\tA\t127.0.0.1"); err != nil { - t.Fatalf("unable to write content to tmpfile %q: %s", tmpfile.Name(), err) - } - if err := tmpfile.Close(); err != nil { - t.Fatalf("could not close tmpfile %q: %s", tmpfile.Name(), err) - } - - zone := "$ORIGIN example.org.\n$INCLUDE " + tmpfile.Name() - - tok := ParseZone(strings.NewReader(zone), "", "") - for x := range tok { - if x.Error != nil { - t.Fatalf("expected no error, but got %s", x.Error) - } - if x.RR.Header().Name != "foo.example.org." { - t.Fatalf("expected %s, but got %s", "foo.example.org.", x.RR.Header().Name) - } - } - - os.Remove(tmpfile.Name()) - - tok = ParseZone(strings.NewReader(zone), "", "") - for x := range tok { - if x.Error == nil { - t.Fatalf("expected first token to contain an error but it didn't") - } - if !strings.Contains(x.Error.Error(), "failed to open") || - !strings.Contains(x.Error.Error(), tmpfile.Name()) { - t.Fatalf(`expected error to contain: "failed to open" and %q but got: %s`, tmpfile.Name(), x.Error) - } - } -} diff --git a/vendor/github.com/miekg/dns/scanner.go b/vendor/github.com/miekg/dns/scanner.go deleted file mode 100644 index 424e5af9f..000000000 --- a/vendor/github.com/miekg/dns/scanner.go +++ /dev/null @@ -1,56 +0,0 @@ -package dns - -// Implement a simple scanner, return a byte stream from an io reader. - -import ( - "bufio" - "context" - "io" - "text/scanner" -) - -type scan struct { - src *bufio.Reader - position scanner.Position - eof bool // Have we just seen a eof - ctx context.Context -} - -func scanInit(r io.Reader) (*scan, context.CancelFunc) { - s := new(scan) - s.src = bufio.NewReader(r) - s.position.Line = 1 - - ctx, cancel := context.WithCancel(context.Background()) - s.ctx = ctx - - return s, cancel -} - -// tokenText returns the next byte from the input -func (s *scan) tokenText() (byte, error) { - c, err := s.src.ReadByte() - if err != nil { - return c, err - } - select { - case <-s.ctx.Done(): - return c, context.Canceled - default: - break - } - - // delay the newline handling until the next token is delivered, - // fixes off-by-one errors when reporting a parse error. - if s.eof == true { - s.position.Line++ - s.position.Column = 0 - s.eof = false - } - if c == '\n' { - s.eof = true - return c, nil - } - s.position.Column++ - return c, nil -} diff --git a/vendor/github.com/miekg/dns/serve_mux.go b/vendor/github.com/miekg/dns/serve_mux.go new file mode 100644 index 000000000..ae304db53 --- /dev/null +++ b/vendor/github.com/miekg/dns/serve_mux.go @@ -0,0 +1,147 @@ +package dns + +import ( + "strings" + "sync" +) + +// ServeMux is an DNS request multiplexer. It matches the zone name of +// each incoming request against a list of registered patterns add calls +// the handler for the pattern that most closely matches the zone name. +// +// ServeMux is DNSSEC aware, meaning that queries for the DS record are +// redirected to the parent zone (if that is also registered), otherwise +// the child gets the query. +// +// ServeMux is also safe for concurrent access from multiple goroutines. +// +// The zero ServeMux is empty and ready for use. +type ServeMux struct { + z map[string]Handler + m sync.RWMutex +} + +// NewServeMux allocates and returns a new ServeMux. +func NewServeMux() *ServeMux { + return new(ServeMux) +} + +// DefaultServeMux is the default ServeMux used by Serve. +var DefaultServeMux = NewServeMux() + +func (mux *ServeMux) match(q string, t uint16) Handler { + mux.m.RLock() + defer mux.m.RUnlock() + if mux.z == nil { + return nil + } + + var handler Handler + + // TODO(tmthrgd): Once https://go-review.googlesource.com/c/go/+/137575 + // lands in a go release, replace the following with strings.ToLower. + var sb strings.Builder + for i := 0; i < len(q); i++ { + c := q[i] + if !(c >= 'A' && c <= 'Z') { + continue + } + + sb.Grow(len(q)) + sb.WriteString(q[:i]) + + for ; i < len(q); i++ { + c := q[i] + if c >= 'A' && c <= 'Z' { + c += 'a' - 'A' + } + + sb.WriteByte(c) + } + + q = sb.String() + break + } + + for off, end := 0, false; !end; off, end = NextLabel(q, off) { + if h, ok := mux.z[q[off:]]; ok { + if t != TypeDS { + return h + } + // Continue for DS to see if we have a parent too, if so delegate to the parent + handler = h + } + } + + // Wildcard match, if we have found nothing try the root zone as a last resort. + if h, ok := mux.z["."]; ok { + return h + } + + return handler +} + +// Handle adds a handler to the ServeMux for pattern. +func (mux *ServeMux) Handle(pattern string, handler Handler) { + if pattern == "" { + panic("dns: invalid pattern " + pattern) + } + mux.m.Lock() + if mux.z == nil { + mux.z = make(map[string]Handler) + } + mux.z[Fqdn(pattern)] = handler + mux.m.Unlock() +} + +// HandleFunc adds a handler function to the ServeMux for pattern. +func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) { + mux.Handle(pattern, HandlerFunc(handler)) +} + +// HandleRemove deregisters the handler specific for pattern from the ServeMux. +func (mux *ServeMux) HandleRemove(pattern string) { + if pattern == "" { + panic("dns: invalid pattern " + pattern) + } + mux.m.Lock() + delete(mux.z, Fqdn(pattern)) + mux.m.Unlock() +} + +// ServeDNS dispatches the request to the handler whose pattern most +// closely matches the request message. +// +// ServeDNS is DNSSEC aware, meaning that queries for the DS record +// are redirected to the parent zone (if that is also registered), +// otherwise the child gets the query. +// +// If no handler is found, or there is no question, a standard SERVFAIL +// message is returned +func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) { + var h Handler + if len(req.Question) >= 1 { // allow more than one question + h = mux.match(req.Question[0].Name, req.Question[0].Qtype) + } + + if h != nil { + h.ServeDNS(w, req) + } else { + HandleFailed(w, req) + } +} + +// Handle registers the handler with the given pattern +// in the DefaultServeMux. The documentation for +// ServeMux explains how patterns are matched. +func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) } + +// HandleRemove deregisters the handle with the given pattern +// in the DefaultServeMux. +func HandleRemove(pattern string) { DefaultServeMux.HandleRemove(pattern) } + +// HandleFunc registers the handler function with the given pattern +// in the DefaultServeMux. +func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) { + DefaultServeMux.HandleFunc(pattern, handler) +} diff --git a/vendor/github.com/miekg/dns/server.go b/vendor/github.com/miekg/dns/server.go index d3f526fc1..4b4ec33c8 100644 --- a/vendor/github.com/miekg/dns/server.go +++ b/vendor/github.com/miekg/dns/server.go @@ -4,6 +4,7 @@ package dns import ( "bytes" + "context" "crypto/tls" "encoding/binary" "errors" @@ -31,11 +32,26 @@ const maxIdleWorkersCount = 10000 // The maximum length of time a worker may idle for before being destroyed. const idleWorkerTimeout = 10 * time.Second +// aLongTimeAgo is a non-zero time, far in the past, used for +// immediate cancelation of network operations. +var aLongTimeAgo = time.Unix(1, 0) + // Handler is implemented by any value that implements ServeDNS. type Handler interface { ServeDNS(w ResponseWriter, r *Msg) } +// The HandlerFunc type is an adapter to allow the use of +// ordinary functions as DNS handlers. If f is a function +// with the appropriate signature, HandlerFunc(f) is a +// Handler object that calls f. +type HandlerFunc func(ResponseWriter, *Msg) + +// ServeDNS calls f(w, r). +func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg) { + f(w, r) +} + // A ResponseWriter interface is used by an DNS handler to // construct an DNS response. type ResponseWriter interface { @@ -58,46 +74,24 @@ type ResponseWriter interface { Hijack() } +// A ConnectionStater interface is used by a DNS Handler to access TLS connection state +// when available. +type ConnectionStater interface { + ConnectionState() *tls.ConnectionState +} + type response struct { msg []byte hijacked bool // connection has been hijacked by handler - tsigStatus error tsigTimersOnly bool + tsigStatus error tsigRequestMAC string tsigSecret map[string]string // the tsig secrets udp *net.UDPConn // i/o connection if UDP was used tcp net.Conn // i/o connection if TCP was used udpSession *SessionUDP // oob data to get egress interface right writer Writer // writer to output the raw DNS bits -} - -// ServeMux is an DNS request multiplexer. It matches the -// zone name of each incoming request against a list of -// registered patterns add calls the handler for the pattern -// that most closely matches the zone name. ServeMux is DNSSEC aware, meaning -// that queries for the DS record are redirected to the parent zone (if that -// is also registered), otherwise the child gets the query. -// ServeMux is also safe for concurrent access from multiple goroutines. -type ServeMux struct { - z map[string]Handler - m *sync.RWMutex -} - -// NewServeMux allocates and returns a new ServeMux. -func NewServeMux() *ServeMux { return &ServeMux{z: make(map[string]Handler), m: new(sync.RWMutex)} } - -// DefaultServeMux is the default ServeMux used by Serve. -var DefaultServeMux = NewServeMux() - -// The HandlerFunc type is an adapter to allow the use of -// ordinary functions as DNS handlers. If f is a function -// with the appropriate signature, HandlerFunc(f) is a -// Handler object that calls f. -type HandlerFunc func(ResponseWriter, *Msg) - -// ServeDNS calls f(w, r). -func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg) { - f(w, r) + wg *sync.WaitGroup // for gracefull shutdown } // HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets. @@ -108,8 +102,6 @@ func HandleFailed(w ResponseWriter, r *Msg) { w.WriteMsg(m) } -func failedHandler() Handler { return HandlerFunc(HandleFailed) } - // ListenAndServe Starts a server on address and network specified Invoke handler // for incoming queries. func ListenAndServe(addr string, network string, handler Handler) error { @@ -148,99 +140,6 @@ func ActivateAndServe(l net.Listener, p net.PacketConn, handler Handler) error { return server.ActivateAndServe() } -func (mux *ServeMux) match(q string, t uint16) Handler { - mux.m.RLock() - defer mux.m.RUnlock() - var handler Handler - b := make([]byte, len(q)) // worst case, one label of length q - off := 0 - end := false - for { - l := len(q[off:]) - for i := 0; i < l; i++ { - b[i] = q[off+i] - if b[i] >= 'A' && b[i] <= 'Z' { - b[i] |= 'a' - 'A' - } - } - if h, ok := mux.z[string(b[:l])]; ok { // causes garbage, might want to change the map key - if t != TypeDS { - return h - } - // Continue for DS to see if we have a parent too, if so delegeate to the parent - handler = h - } - off, end = NextLabel(q, off) - if end { - break - } - } - // Wildcard match, if we have found nothing try the root zone as a last resort. - if h, ok := mux.z["."]; ok { - return h - } - return handler -} - -// Handle adds a handler to the ServeMux for pattern. -func (mux *ServeMux) Handle(pattern string, handler Handler) { - if pattern == "" { - panic("dns: invalid pattern " + pattern) - } - mux.m.Lock() - mux.z[Fqdn(pattern)] = handler - mux.m.Unlock() -} - -// HandleFunc adds a handler function to the ServeMux for pattern. -func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) { - mux.Handle(pattern, HandlerFunc(handler)) -} - -// HandleRemove deregistrars the handler specific for pattern from the ServeMux. -func (mux *ServeMux) HandleRemove(pattern string) { - if pattern == "" { - panic("dns: invalid pattern " + pattern) - } - mux.m.Lock() - delete(mux.z, Fqdn(pattern)) - mux.m.Unlock() -} - -// ServeDNS dispatches the request to the handler whose -// pattern most closely matches the request message. If DefaultServeMux -// is used the correct thing for DS queries is done: a possible parent -// is sought. -// If no handler is found a standard SERVFAIL message is returned -// If the request message does not have exactly one question in the -// question section a SERVFAIL is returned, unlesss Unsafe is true. -func (mux *ServeMux) ServeDNS(w ResponseWriter, request *Msg) { - var h Handler - if len(request.Question) < 1 { // allow more than one question - h = failedHandler() - } else { - if h = mux.match(request.Question[0].Name, request.Question[0].Qtype); h == nil { - h = failedHandler() - } - } - h.ServeDNS(w, request) -} - -// Handle registers the handler with the given pattern -// in the DefaultServeMux. The documentation for -// ServeMux explains how patterns are matched. -func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) } - -// HandleRemove deregisters the handle with the given pattern -// in the DefaultServeMux. -func HandleRemove(pattern string) { DefaultServeMux.HandleRemove(pattern) } - -// HandleFunc registers the handler function with the given pattern -// in the DefaultServeMux. -func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) { - DefaultServeMux.HandleFunc(pattern, handler) -} - // Writer writes raw DNS messages; each call to Write should send an entire message. type Writer interface { io.Writer @@ -322,9 +221,12 @@ type Server struct { queue chan *response // Workers count workersCount int32 + // Shutdown handling - lock sync.RWMutex - started bool + lock sync.RWMutex + started bool + shutdown chan struct{} + conns map[net.Conn]struct{} // A pool for UDP message buffers. udpPool sync.Pool @@ -391,6 +293,9 @@ func makeUDPBuffer(size int) func() interface{} { func (srv *Server) init() { srv.queue = make(chan *response) + srv.shutdown = make(chan struct{}) + srv.conns = make(map[net.Conn]struct{}) + if srv.UDPSize == 0 { srv.UDPSize = MinMsgSize } @@ -501,23 +406,57 @@ func (srv *Server) ActivateAndServe() error { // Shutdown shuts down a server. After a call to Shutdown, ListenAndServe and // ActivateAndServe will return. func (srv *Server) Shutdown() error { + return srv.ShutdownContext(context.Background()) +} + +// ShutdownContext shuts down a server. After a call to ShutdownContext, +// ListenAndServe and ActivateAndServe will return. +// +// A context.Context may be passed to limit how long to wait for connections +// to terminate. +func (srv *Server) ShutdownContext(ctx context.Context) error { srv.lock.Lock() if !srv.started { srv.lock.Unlock() return &Error{err: "server not started"} } + srv.started = false - srv.lock.Unlock() if srv.PacketConn != nil { - srv.PacketConn.Close() + srv.PacketConn.SetReadDeadline(aLongTimeAgo) // Unblock reads } + if srv.Listener != nil { srv.Listener.Close() } - return nil + + for rw := range srv.conns { + rw.SetReadDeadline(aLongTimeAgo) // Unblock reads + } + + srv.lock.Unlock() + + if testShutdownNotify != nil { + testShutdownNotify.Broadcast() + } + + var ctxErr error + select { + case <-srv.shutdown: + case <-ctx.Done(): + ctxErr = ctx.Err() + } + + if srv.PacketConn != nil { + srv.PacketConn.Close() + } + + return ctxErr } +var testShutdownNotify *sync.Cond + // getReadTimeout is a helper func to use system timeout if server did not intend to change it. func (srv *Server) getReadTimeout() time.Duration { rtimeout := dnsTimeout @@ -535,19 +474,36 @@ func (srv *Server) serveTCP(l net.Listener) error { srv.NotifyStartedFunc() } - for { + var wg sync.WaitGroup + defer func() { + wg.Wait() + close(srv.shutdown) + }() + + for srv.isStarted() { rw, err := l.Accept() - if !srv.isStarted() { - return nil - } if err != nil { + if !srv.isStarted() { + return nil + } if neterr, ok := err.(net.Error); ok && neterr.Temporary() { continue } return err } - srv.spawnWorker(&response{tsigSecret: srv.TsigSecret, tcp: rw}) + srv.lock.Lock() + // Track the connection to allow unblocking reads on shutdown. + srv.conns[rw] = struct{}{} + srv.lock.Unlock() + wg.Add(1) + srv.spawnWorker(&response{ + tsigSecret: srv.TsigSecret, + tcp: rw, + wg: &wg, + }) } + + return nil } // serveUDP starts a UDP listener for the server. @@ -563,14 +519,20 @@ func (srv *Server) serveUDP(l *net.UDPConn) error { reader = srv.DecorateReader(reader) } + var wg sync.WaitGroup + defer func() { + wg.Wait() + close(srv.shutdown) + }() + rtimeout := srv.getReadTimeout() // deadline is not used here - for { + for srv.isStarted() { m, s, err := reader.ReadUDP(l, rtimeout) - if !srv.isStarted() { - return nil - } if err != nil { + if !srv.isStarted() { + return nil + } if netErr, ok := err.(net.Error); ok && netErr.Temporary() { continue } @@ -582,8 +544,17 @@ func (srv *Server) serveUDP(l *net.UDPConn) error { } continue } - srv.spawnWorker(&response{msg: m, tsigSecret: srv.TsigSecret, udp: l, udpSession: s}) + wg.Add(1) + srv.spawnWorker(&response{ + msg: m, + tsigSecret: srv.TsigSecret, + udp: l, + udpSession: s, + wg: &wg, + }) } + + return nil } func (srv *Server) serve(w *response) { @@ -596,20 +567,28 @@ func (srv *Server) serve(w *response) { if w.udp != nil { // serve UDP srv.serveDNS(w) - return - } - reader := Reader(&defaultReader{srv}) - if srv.DecorateReader != nil { - reader = srv.DecorateReader(reader) + w.wg.Done() + return } defer func() { if !w.hijacked { w.Close() } + + srv.lock.Lock() + delete(srv.conns, w.tcp) + srv.lock.Unlock() + + w.wg.Done() }() + reader := Reader(&defaultReader{srv}) + if srv.DecorateReader != nil { + reader = srv.DecorateReader(reader) + } + idleTimeout := tcpIdleTimeout if srv.IdleTimeout != nil { idleTimeout = srv.IdleTimeout() @@ -622,7 +601,7 @@ func (srv *Server) serve(w *response) { limit = maxTCPQueries } - for q := 0; q < limit || limit == -1; q++ { + for q := 0; (q < limit || limit == -1) && srv.isStarted(); q++ { var err error w.msg, err = reader.ReadTCP(w.tcp, timeout) if err != nil { @@ -642,20 +621,23 @@ func (srv *Server) serve(w *response) { } } -func (srv *Server) serveDNS(w *response) { - req := new(Msg) - err := req.Unpack(w.msg) +func (srv *Server) disposeBuffer(w *response) { if w.udp != nil && cap(w.msg) == srv.UDPSize { srv.udpPool.Put(w.msg[:srv.UDPSize]) } w.msg = nil +} + +func (srv *Server) serveDNS(w *response) { + req := new(Msg) + err := req.Unpack(w.msg) if err != nil { // Send a FormatError back x := new(Msg) x.SetRcodeFormatError(req) w.WriteMsg(x) - return } - if !srv.Unsafe && req.Response { + if err != nil || !srv.Unsafe && req.Response { + srv.disposeBuffer(w) return } @@ -672,6 +654,8 @@ func (srv *Server) serveDNS(w *response) { } } + srv.disposeBuffer(w) + handler := srv.Handler if handler == nil { handler = DefaultServeMux @@ -681,7 +665,16 @@ func (srv *Server) serveDNS(w *response) { } func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) { - conn.SetReadDeadline(time.Now().Add(timeout)) + // If we race with ShutdownContext, the read deadline may + // have been set in the distant past to unblock the read + // below. We must not override it, otherwise we may block + // ShutdownContext. + srv.lock.RLock() + if srv.started { + conn.SetReadDeadline(time.Now().Add(timeout)) + } + srv.lock.RUnlock() + l := make([]byte, 2) n, err := conn.Read(l) if err != nil || n != 2 { @@ -716,7 +709,13 @@ func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) } func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) { - conn.SetReadDeadline(time.Now().Add(timeout)) + srv.lock.RLock() + if srv.started { + // See the comment in readTCP above. + conn.SetReadDeadline(time.Now().Add(timeout)) + } + srv.lock.RUnlock() + m := srv.udpPool.Get().([]byte) n, s, err := ReadFromSessionUDP(conn, m) if err != nil { @@ -768,24 +767,33 @@ func (w *response) Write(m []byte) (int, error) { n, err := io.Copy(w.tcp, bytes.NewReader(m)) return int(n), err + default: + panic("dns: Write called after Close") } - panic("not reached") } // LocalAddr implements the ResponseWriter.LocalAddr method. func (w *response) LocalAddr() net.Addr { - if w.tcp != nil { + switch { + case w.udp != nil: + return w.udp.LocalAddr() + case w.tcp != nil: return w.tcp.LocalAddr() + default: + panic("dns: LocalAddr called after Close") } - return w.udp.LocalAddr() } // RemoteAddr implements the ResponseWriter.RemoteAddr method. func (w *response) RemoteAddr() net.Addr { - if w.tcp != nil { + switch { + case w.udpSession != nil: + return w.udpSession.RemoteAddr() + case w.tcp != nil: return w.tcp.RemoteAddr() + default: + panic("dns: RemoteAddr called after Close") } - return w.udpSession.RemoteAddr() } // TsigStatus implements the ResponseWriter.TsigStatus method. @@ -807,3 +815,15 @@ func (w *response) Close() error { } return nil } + +// ConnectionState() implements the ConnectionStater.ConnectionState() interface. +func (w *response) ConnectionState() *tls.ConnectionState { + type tlsConnectionStater interface { + ConnectionState() tls.ConnectionState + } + if v, ok := w.tcp.(tlsConnectionStater); ok { + t := v.ConnectionState() + return &t + } + return nil +} diff --git a/vendor/github.com/miekg/dns/server_test.go b/vendor/github.com/miekg/dns/server_test.go deleted file mode 100644 index e6f073d7c..000000000 --- a/vendor/github.com/miekg/dns/server_test.go +++ /dev/null @@ -1,853 +0,0 @@ -package dns - -import ( - "crypto/tls" - "fmt" - "io" - "net" - "runtime" - "strings" - "sync" - "testing" - "time" -) - -func HelloServer(w ResponseWriter, req *Msg) { - m := new(Msg) - m.SetReply(req) - - m.Extra = make([]RR, 1) - m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}} - w.WriteMsg(m) -} - -func HelloServerBadID(w ResponseWriter, req *Msg) { - m := new(Msg) - m.SetReply(req) - m.Id++ - - m.Extra = make([]RR, 1) - m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}} - w.WriteMsg(m) -} - -func HelloServerEchoAddrPort(w ResponseWriter, req *Msg) { - m := new(Msg) - m.SetReply(req) - - remoteAddr := w.RemoteAddr().String() - m.Extra = make([]RR, 1) - m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{remoteAddr}} - w.WriteMsg(m) -} - -func AnotherHelloServer(w ResponseWriter, req *Msg) { - m := new(Msg) - m.SetReply(req) - - m.Extra = make([]RR, 1) - m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello example"}} - w.WriteMsg(m) -} - -func RunLocalUDPServer(laddr string) (*Server, string, error) { - server, l, _, err := RunLocalUDPServerWithFinChan(laddr) - - return server, l, err -} - -func RunLocalUDPServerWithFinChan(laddr string) (*Server, string, chan error, error) { - pc, err := net.ListenPacket("udp", laddr) - if err != nil { - return nil, "", nil, err - } - server := &Server{PacketConn: pc, ReadTimeout: time.Hour, WriteTimeout: time.Hour} - - waitLock := sync.Mutex{} - waitLock.Lock() - server.NotifyStartedFunc = waitLock.Unlock - - // fin must be buffered so the goroutine below won't block - // forever if fin is never read from. This always happens - // in RunLocalUDPServer and can happen in TestShutdownUDP. - fin := make(chan error, 1) - - go func() { - fin <- server.ActivateAndServe() - pc.Close() - }() - - waitLock.Lock() - return server, pc.LocalAddr().String(), fin, nil -} - -func RunLocalUDPServerUnsafe(laddr string) (*Server, string, error) { - pc, err := net.ListenPacket("udp", laddr) - if err != nil { - return nil, "", err - } - server := &Server{PacketConn: pc, Unsafe: true, - ReadTimeout: time.Hour, WriteTimeout: time.Hour} - - waitLock := sync.Mutex{} - waitLock.Lock() - server.NotifyStartedFunc = waitLock.Unlock - - go func() { - server.ActivateAndServe() - pc.Close() - }() - - waitLock.Lock() - return server, pc.LocalAddr().String(), nil -} - -func RunLocalTCPServer(laddr string) (*Server, string, error) { - server, l, _, err := RunLocalTCPServerWithFinChan(laddr) - - return server, l, err -} - -func RunLocalTCPServerWithFinChan(laddr string) (*Server, string, chan error, error) { - l, err := net.Listen("tcp", laddr) - if err != nil { - return nil, "", nil, err - } - - server := &Server{Listener: l, ReadTimeout: time.Hour, WriteTimeout: time.Hour} - - waitLock := sync.Mutex{} - waitLock.Lock() - server.NotifyStartedFunc = waitLock.Unlock - - // See the comment in RunLocalUDPServerWithFinChan as to - // why fin must be buffered. - fin := make(chan error, 1) - - go func() { - fin <- server.ActivateAndServe() - l.Close() - }() - - waitLock.Lock() - return server, l.Addr().String(), fin, nil -} - -func RunLocalTLSServer(laddr string, config *tls.Config) (*Server, string, error) { - l, err := tls.Listen("tcp", laddr, config) - if err != nil { - return nil, "", err - } - - server := &Server{Listener: l, ReadTimeout: time.Hour, WriteTimeout: time.Hour} - - waitLock := sync.Mutex{} - waitLock.Lock() - server.NotifyStartedFunc = waitLock.Unlock - - go func() { - server.ActivateAndServe() - l.Close() - }() - - waitLock.Lock() - return server, l.Addr().String(), nil -} - -func TestServing(t *testing.T) { - HandleFunc("miek.nl.", HelloServer) - HandleFunc("example.com.", AnotherHelloServer) - defer HandleRemove("miek.nl.") - defer HandleRemove("example.com.") - - s, addrstr, err := RunLocalUDPServer(":0") - if err != nil { - t.Fatalf("unable to run test server: %v", err) - } - defer s.Shutdown() - - c := new(Client) - m := new(Msg) - m.SetQuestion("miek.nl.", TypeTXT) - r, _, err := c.Exchange(m, addrstr) - if err != nil || len(r.Extra) == 0 { - t.Fatal("failed to exchange miek.nl", err) - } - txt := r.Extra[0].(*TXT).Txt[0] - if txt != "Hello world" { - t.Error("unexpected result for miek.nl", txt, "!= Hello world") - } - - m.SetQuestion("example.com.", TypeTXT) - r, _, err = c.Exchange(m, addrstr) - if err != nil { - t.Fatal("failed to exchange example.com", err) - } - txt = r.Extra[0].(*TXT).Txt[0] - if txt != "Hello example" { - t.Error("unexpected result for example.com", txt, "!= Hello example") - } - - // Test Mixes cased as noticed by Ask. - m.SetQuestion("eXaMplE.cOm.", TypeTXT) - r, _, err = c.Exchange(m, addrstr) - if err != nil { - t.Error("failed to exchange eXaMplE.cOm", err) - } - txt = r.Extra[0].(*TXT).Txt[0] - if txt != "Hello example" { - t.Error("unexpected result for example.com", txt, "!= Hello example") - } -} - -func TestServingTLS(t *testing.T) { - HandleFunc("miek.nl.", HelloServer) - HandleFunc("example.com.", AnotherHelloServer) - defer HandleRemove("miek.nl.") - defer HandleRemove("example.com.") - - cert, err := tls.X509KeyPair(CertPEMBlock, KeyPEMBlock) - if err != nil { - t.Fatalf("unable to build certificate: %v", err) - } - - config := tls.Config{ - Certificates: []tls.Certificate{cert}, - } - - s, addrstr, err := RunLocalTLSServer(":0", &config) - if err != nil { - t.Fatalf("unable to run test server: %v", err) - } - defer s.Shutdown() - - c := new(Client) - c.Net = "tcp-tls" - c.TLSConfig = &tls.Config{ - InsecureSkipVerify: true, - } - - m := new(Msg) - m.SetQuestion("miek.nl.", TypeTXT) - r, _, err := c.Exchange(m, addrstr) - if err != nil || len(r.Extra) == 0 { - t.Fatal("failed to exchange miek.nl", err) - } - txt := r.Extra[0].(*TXT).Txt[0] - if txt != "Hello world" { - t.Error("unexpected result for miek.nl", txt, "!= Hello world") - } - - m.SetQuestion("example.com.", TypeTXT) - r, _, err = c.Exchange(m, addrstr) - if err != nil { - t.Fatal("failed to exchange example.com", err) - } - txt = r.Extra[0].(*TXT).Txt[0] - if txt != "Hello example" { - t.Error("unexpected result for example.com", txt, "!= Hello example") - } - - // Test Mixes cased as noticed by Ask. - m.SetQuestion("eXaMplE.cOm.", TypeTXT) - r, _, err = c.Exchange(m, addrstr) - if err != nil { - t.Error("failed to exchange eXaMplE.cOm", err) - } - txt = r.Extra[0].(*TXT).Txt[0] - if txt != "Hello example" { - t.Error("unexpected result for example.com", txt, "!= Hello example") - } -} - -func TestServingListenAndServe(t *testing.T) { - HandleFunc("example.com.", AnotherHelloServer) - defer HandleRemove("example.com.") - - waitLock := sync.Mutex{} - server := &Server{Addr: ":0", Net: "udp", ReadTimeout: time.Hour, WriteTimeout: time.Hour, NotifyStartedFunc: waitLock.Unlock} - waitLock.Lock() - - go func() { - server.ListenAndServe() - }() - waitLock.Lock() - - c, m := new(Client), new(Msg) - m.SetQuestion("example.com.", TypeTXT) - addr := server.PacketConn.LocalAddr().String() // Get address via the PacketConn that gets set. - r, _, err := c.Exchange(m, addr) - if err != nil { - t.Fatal("failed to exchange example.com", err) - } - txt := r.Extra[0].(*TXT).Txt[0] - if txt != "Hello example" { - t.Error("unexpected result for example.com", txt, "!= Hello example") - } - server.Shutdown() -} - -func TestServingListenAndServeTLS(t *testing.T) { - HandleFunc("example.com.", AnotherHelloServer) - defer HandleRemove("example.com.") - - cert, err := tls.X509KeyPair(CertPEMBlock, KeyPEMBlock) - if err != nil { - t.Fatalf("unable to build certificate: %v", err) - } - - config := &tls.Config{ - Certificates: []tls.Certificate{cert}, - } - - waitLock := sync.Mutex{} - server := &Server{Addr: ":0", Net: "tcp", TLSConfig: config, ReadTimeout: time.Hour, WriteTimeout: time.Hour, NotifyStartedFunc: waitLock.Unlock} - waitLock.Lock() - - go func() { - server.ListenAndServe() - }() - waitLock.Lock() - - c, m := new(Client), new(Msg) - c.Net = "tcp" - m.SetQuestion("example.com.", TypeTXT) - addr := server.Listener.Addr().String() // Get address via the Listener that gets set. - r, _, err := c.Exchange(m, addr) - if err != nil { - t.Fatal(err) - } - txt := r.Extra[0].(*TXT).Txt[0] - if txt != "Hello example" { - t.Error("unexpected result for example.com", txt, "!= Hello example") - } - server.Shutdown() -} - -func BenchmarkServe(b *testing.B) { - b.StopTimer() - HandleFunc("miek.nl.", HelloServer) - defer HandleRemove("miek.nl.") - a := runtime.GOMAXPROCS(4) - - s, addrstr, err := RunLocalUDPServer(":0") - if err != nil { - b.Fatalf("unable to run test server: %v", err) - } - defer s.Shutdown() - - c := new(Client) - m := new(Msg) - m.SetQuestion("miek.nl.", TypeSOA) - - b.StartTimer() - for i := 0; i < b.N; i++ { - _, _, err := c.Exchange(m, addrstr) - if err != nil { - b.Fatalf("Exchange failed: %v", err) - } - } - runtime.GOMAXPROCS(a) -} - -func BenchmarkServe6(b *testing.B) { - b.StopTimer() - HandleFunc("miek.nl.", HelloServer) - defer HandleRemove("miek.nl.") - a := runtime.GOMAXPROCS(4) - s, addrstr, err := RunLocalUDPServer("[::1]:0") - if err != nil { - if strings.Contains(err.Error(), "bind: cannot assign requested address") { - b.Skip("missing IPv6 support") - } - b.Fatalf("unable to run test server: %v", err) - } - defer s.Shutdown() - - c := new(Client) - m := new(Msg) - m.SetQuestion("miek.nl.", TypeSOA) - - b.StartTimer() - for i := 0; i < b.N; i++ { - _, _, err := c.Exchange(m, addrstr) - if err != nil { - b.Fatalf("Exchange failed: %v", err) - } - } - runtime.GOMAXPROCS(a) -} - -func HelloServerCompress(w ResponseWriter, req *Msg) { - m := new(Msg) - m.SetReply(req) - m.Extra = make([]RR, 1) - m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}} - m.Compress = true - w.WriteMsg(m) -} - -func BenchmarkServeCompress(b *testing.B) { - b.StopTimer() - HandleFunc("miek.nl.", HelloServerCompress) - defer HandleRemove("miek.nl.") - a := runtime.GOMAXPROCS(4) - s, addrstr, err := RunLocalUDPServer(":0") - if err != nil { - b.Fatalf("unable to run test server: %v", err) - } - defer s.Shutdown() - - c := new(Client) - m := new(Msg) - m.SetQuestion("miek.nl.", TypeSOA) - b.StartTimer() - for i := 0; i < b.N; i++ { - _, _, err := c.Exchange(m, addrstr) - if err != nil { - b.Fatalf("Exchange failed: %v", err) - } - } - runtime.GOMAXPROCS(a) -} - -func TestDotAsCatchAllWildcard(t *testing.T) { - mux := NewServeMux() - mux.Handle(".", HandlerFunc(HelloServer)) - mux.Handle("example.com.", HandlerFunc(AnotherHelloServer)) - - handler := mux.match("www.miek.nl.", TypeTXT) - if handler == nil { - t.Error("wildcard match failed") - } - - handler = mux.match("www.example.com.", TypeTXT) - if handler == nil { - t.Error("example.com match failed") - } - - handler = mux.match("a.www.example.com.", TypeTXT) - if handler == nil { - t.Error("a.www.example.com match failed") - } - - handler = mux.match("boe.", TypeTXT) - if handler == nil { - t.Error("boe. match failed") - } -} - -func TestCaseFolding(t *testing.T) { - mux := NewServeMux() - mux.Handle("_udp.example.com.", HandlerFunc(HelloServer)) - - handler := mux.match("_dns._udp.example.com.", TypeSRV) - if handler == nil { - t.Error("case sensitive characters folded") - } - - handler = mux.match("_DNS._UDP.EXAMPLE.COM.", TypeSRV) - if handler == nil { - t.Error("case insensitive characters not folded") - } -} - -func TestRootServer(t *testing.T) { - mux := NewServeMux() - mux.Handle(".", HandlerFunc(HelloServer)) - - handler := mux.match(".", TypeNS) - if handler == nil { - t.Error("root match failed") - } -} - -type maxRec struct { - max int - sync.RWMutex -} - -var M = new(maxRec) - -func HelloServerLargeResponse(resp ResponseWriter, req *Msg) { - m := new(Msg) - m.SetReply(req) - m.Authoritative = true - m1 := 0 - M.RLock() - m1 = M.max - M.RUnlock() - for i := 0; i < m1; i++ { - aRec := &A{ - Hdr: RR_Header{ - Name: req.Question[0].Name, - Rrtype: TypeA, - Class: ClassINET, - Ttl: 0, - }, - A: net.ParseIP(fmt.Sprintf("127.0.0.%d", i+1)).To4(), - } - m.Answer = append(m.Answer, aRec) - } - resp.WriteMsg(m) -} - -func TestServingLargeResponses(t *testing.T) { - HandleFunc("example.", HelloServerLargeResponse) - defer HandleRemove("example.") - - s, addrstr, err := RunLocalUDPServer(":0") - if err != nil { - t.Fatalf("unable to run test server: %v", err) - } - defer s.Shutdown() - - // Create request - m := new(Msg) - m.SetQuestion("web.service.example.", TypeANY) - - c := new(Client) - c.Net = "udp" - M.Lock() - M.max = 2 - M.Unlock() - _, _, err = c.Exchange(m, addrstr) - if err != nil { - t.Errorf("failed to exchange: %v", err) - } - // This must fail - M.Lock() - M.max = 20 - M.Unlock() - _, _, err = c.Exchange(m, addrstr) - if err == nil { - t.Error("failed to fail exchange, this should generate packet error") - } - // But this must work again - c.UDPSize = 7000 - _, _, err = c.Exchange(m, addrstr) - if err != nil { - t.Errorf("failed to exchange: %v", err) - } -} - -func TestServingResponse(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - HandleFunc("miek.nl.", HelloServer) - s, addrstr, err := RunLocalUDPServer(":0") - if err != nil { - t.Fatalf("unable to run test server: %v", err) - } - - c := new(Client) - m := new(Msg) - m.SetQuestion("miek.nl.", TypeTXT) - m.Response = false - _, _, err = c.Exchange(m, addrstr) - if err != nil { - t.Fatal("failed to exchange", err) - } - m.Response = true - _, _, err = c.Exchange(m, addrstr) - if err == nil { - t.Fatal("exchanged response message") - } - - s.Shutdown() - s, addrstr, err = RunLocalUDPServerUnsafe(":0") - if err != nil { - t.Fatalf("unable to run test server: %v", err) - } - defer s.Shutdown() - - m.Response = true - _, _, err = c.Exchange(m, addrstr) - if err != nil { - t.Fatal("could exchanged response message in Unsafe mode") - } -} - -func TestShutdownTCP(t *testing.T) { - s, _, fin, err := RunLocalTCPServerWithFinChan(":0") - if err != nil { - t.Fatalf("unable to run test server: %v", err) - } - err = s.Shutdown() - if err != nil { - t.Fatalf("could not shutdown test TCP server, %v", err) - } - select { - case err := <-fin: - if err != nil { - t.Errorf("error returned from ActivateAndServe, %v", err) - } - case <-time.After(2 * time.Second): - t.Error("could not shutdown test TCP server. Gave up waiting") - } -} - -func TestShutdownTLS(t *testing.T) { - cert, err := tls.X509KeyPair(CertPEMBlock, KeyPEMBlock) - if err != nil { - t.Fatalf("unable to build certificate: %v", err) - } - - config := tls.Config{ - Certificates: []tls.Certificate{cert}, - } - - s, _, err := RunLocalTLSServer(":0", &config) - if err != nil { - t.Fatalf("unable to run test server: %v", err) - } - err = s.Shutdown() - if err != nil { - t.Errorf("could not shutdown test TLS server, %v", err) - } -} - -type trigger struct { - done bool - sync.RWMutex -} - -func (t *trigger) Set() { - t.Lock() - defer t.Unlock() - t.done = true -} -func (t *trigger) Get() bool { - t.RLock() - defer t.RUnlock() - return t.done -} - -func TestHandlerCloseTCP(t *testing.T) { - - ln, err := net.Listen("tcp", ":0") - if err != nil { - panic(err) - } - addr := ln.Addr().String() - - server := &Server{Addr: addr, Net: "tcp", Listener: ln} - - hname := "testhandlerclosetcp." - triggered := &trigger{} - HandleFunc(hname, func(w ResponseWriter, r *Msg) { - triggered.Set() - w.Close() - }) - defer HandleRemove(hname) - - go func() { - defer server.Shutdown() - c := &Client{Net: "tcp"} - m := new(Msg).SetQuestion(hname, 1) - tries := 0 - exchange: - _, _, err := c.Exchange(m, addr) - if err != nil && err != io.EOF { - t.Errorf("exchange failed: %s\n", err) - if tries == 3 { - return - } - time.Sleep(time.Second / 10) - tries++ - goto exchange - } - }() - server.ActivateAndServe() - if !triggered.Get() { - t.Fatalf("handler never called") - } -} - -func TestShutdownUDP(t *testing.T) { - s, _, fin, err := RunLocalUDPServerWithFinChan(":0") - if err != nil { - t.Fatalf("unable to run test server: %v", err) - } - err = s.Shutdown() - if err != nil { - t.Errorf("could not shutdown test UDP server, %v", err) - } - select { - case err := <-fin: - if err != nil { - t.Errorf("error returned from ActivateAndServe, %v", err) - } - case <-time.After(2 * time.Second): - t.Error("could not shutdown test UDP server. Gave up waiting") - } -} - -func TestServerStartStopRace(t *testing.T) { - var wg sync.WaitGroup - for i := 0; i < 10; i++ { - wg.Add(1) - s, _, _, err := RunLocalUDPServerWithFinChan(":0") - if err != nil { - t.Fatalf("could not start server: %s", err) - } - go func() { - defer wg.Done() - if err := s.Shutdown(); err != nil { - t.Errorf("could not stop server: %s", err) - } - }() - } - wg.Wait() -} - -func TestServerReuseport(t *testing.T) { - if !supportsReusePort { - t.Skip("reuseport is not supported") - } - - startServer := func(addr string) (*Server, chan error) { - wait := make(chan struct{}) - srv := &Server{ - Net: "udp", - Addr: addr, - NotifyStartedFunc: func() { close(wait) }, - ReusePort: true, - } - - fin := make(chan error, 1) - go func() { - fin <- srv.ListenAndServe() - }() - - select { - case <-wait: - case err := <-fin: - t.Fatalf("failed to start server: %v", err) - } - - return srv, fin - } - - srv1, fin1 := startServer(":0") // :0 is resolved to a random free port by the kernel - srv2, fin2 := startServer(srv1.PacketConn.LocalAddr().String()) - - if err := srv1.Shutdown(); err != nil { - t.Fatalf("failed to shutdown first server: %v", err) - } - if err := srv2.Shutdown(); err != nil { - t.Fatalf("failed to shutdown second server: %v", err) - } - - if err := <-fin1; err != nil { - t.Fatalf("first ListenAndServe returned error after Shutdown: %v", err) - } - if err := <-fin2; err != nil { - t.Fatalf("second ListenAndServe returned error after Shutdown: %v", err) - } -} - -type ExampleFrameLengthWriter struct { - Writer -} - -func (e *ExampleFrameLengthWriter) Write(m []byte) (int, error) { - fmt.Println("writing raw DNS message of length", len(m)) - return e.Writer.Write(m) -} - -func ExampleDecorateWriter() { - // instrument raw DNS message writing - wf := DecorateWriter(func(w Writer) Writer { - return &ExampleFrameLengthWriter{w} - }) - - // simple UDP server - pc, err := net.ListenPacket("udp", ":0") - if err != nil { - fmt.Println(err.Error()) - return - } - server := &Server{ - PacketConn: pc, - DecorateWriter: wf, - ReadTimeout: time.Hour, WriteTimeout: time.Hour, - } - - waitLock := sync.Mutex{} - waitLock.Lock() - server.NotifyStartedFunc = waitLock.Unlock - defer server.Shutdown() - - go func() { - server.ActivateAndServe() - pc.Close() - }() - - waitLock.Lock() - - HandleFunc("miek.nl.", HelloServer) - - c := new(Client) - m := new(Msg) - m.SetQuestion("miek.nl.", TypeTXT) - _, _, err = c.Exchange(m, pc.LocalAddr().String()) - if err != nil { - fmt.Println("failed to exchange", err.Error()) - return - } - // Output: writing raw DNS message of length 56 -} - -var ( - // CertPEMBlock is a X509 data used to test TLS servers (used with tls.X509KeyPair) - CertPEMBlock = []byte(`-----BEGIN CERTIFICATE----- -MIIDAzCCAeugAwIBAgIRAJFYMkcn+b8dpU15wjf++GgwDQYJKoZIhvcNAQELBQAw -EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNjAxMDgxMjAzNTNaFw0xNzAxMDcxMjAz -NTNaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQDXjqO6skvP03k58CNjQggd9G/mt+Wa+xRU+WXiKCCHttawM8x+slq5 -yfsHCwxlwsGn79HmJqecNqgHb2GWBXAvVVokFDTcC1hUP4+gp2gu9Ny27UHTjlLm -O0l/xZ5MN8tfKyYlFw18tXu3fkaPyHj8v/D1RDkuo4ARdFvGSe8TqisbhLk2+9ow -xfIGbEM9Fdiw8qByC2+d+FfvzIKz3GfQVwn0VoRom8L6NBIANq1IGrB5JefZB6nv -DnfuxkBmY7F1513HKuEJ8KsLWWZWV9OPU4j4I4Rt+WJNlKjbD2srHxyrS2RDsr91 -8nCkNoWVNO3sZq0XkWKecdc921vL4ginAgMBAAGjVDBSMA4GA1UdDwEB/wQEAwIC -pDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MBoGA1UdEQQT -MBGCCWxvY2FsaG9zdIcEfwAAATANBgkqhkiG9w0BAQsFAAOCAQEAGcU3iyLBIVZj -aDzSvEDHUd1bnLBl1C58Xu/CyKlPqVU7mLfK0JcgEaYQTSX6fCJVNLbbCrcGLsPJ -fbjlBbyeLjTV413fxPVuona62pBFjqdtbli2Qe8FRH2KBdm41JUJGdo+SdsFu7nc -BFOcubdw6LLIXvsTvwndKcHWx1rMX709QU1Vn1GAIsbJV/DWI231Jyyb+lxAUx/C -8vce5uVxiKcGS+g6OjsN3D3TtiEQGSXLh013W6Wsih8td8yMCMZ3w8LQ38br1GUe -ahLIgUJ9l6HDguM17R7kGqxNvbElsMUHfTtXXP7UDQUiYXDakg8xDP6n9DCDhJ8Y -bSt7OLB7NQ== ------END CERTIFICATE-----`) - - // KeyPEMBlock is a X509 data used to test TLS servers (used with tls.X509KeyPair) - KeyPEMBlock = []byte(`-----BEGIN RSA PRIVATE KEY----- -MIIEpQIBAAKCAQEA146jurJLz9N5OfAjY0IIHfRv5rflmvsUVPll4iggh7bWsDPM -frJaucn7BwsMZcLBp+/R5iannDaoB29hlgVwL1VaJBQ03AtYVD+PoKdoLvTctu1B -045S5jtJf8WeTDfLXysmJRcNfLV7t35Gj8h4/L/w9UQ5LqOAEXRbxknvE6orG4S5 -NvvaMMXyBmxDPRXYsPKgcgtvnfhX78yCs9xn0FcJ9FaEaJvC+jQSADatSBqweSXn -2Qep7w537sZAZmOxdeddxyrhCfCrC1lmVlfTj1OI+COEbfliTZSo2w9rKx8cq0tk -Q7K/dfJwpDaFlTTt7GatF5FinnHXPdtby+IIpwIDAQABAoIBAAJK4RDmPooqTJrC -JA41MJLo+5uvjwCT9QZmVKAQHzByUFw1YNJkITTiognUI0CdzqNzmH7jIFs39ZeG -proKusO2G6xQjrNcZ4cV2fgyb5g4QHStl0qhs94A+WojduiGm2IaumAgm6Mc5wDv -ld6HmknN3Mku/ZCyanVFEIjOVn2WB7ZQLTBs6ZYaebTJG2Xv6p9t2YJW7pPQ9Xce -s9ohAWohyM4X/OvfnfnLtQp2YLw/BxwehBsCR5SXM3ibTKpFNtxJC8hIfTuWtxZu -2ywrmXShYBRB1WgtZt5k04bY/HFncvvcHK3YfI1+w4URKtwdaQgPUQRbVwDwuyBn -flfkCJECgYEA/eWt01iEyE/lXkGn6V9lCocUU7lCU6yk5UT8VXVUc5If4KZKPfCk -p4zJDOqwn2eM673aWz/mG9mtvAvmnugaGjcaVCyXOp/D/GDmKSoYcvW5B/yjfkLy -dK6Yaa5LDRVYlYgyzcdCT5/9Qc626NzFwKCZNI4ncIU8g7ViATRxWJ8CgYEA2Ver -vZ0M606sfgC0H3NtwNBxmuJ+lIF5LNp/wDi07lDfxRR1rnZMX5dnxjcpDr/zvm8J -WtJJX3xMgqjtHuWKL3yKKony9J5ZPjichSbSbhrzfovgYIRZLxLLDy4MP9L3+CX/ -yBXnqMWuSnFX+M5fVGxdDWiYF3V+wmeOv9JvavkCgYEAiXAPDFzaY+R78O3xiu7M -r0o3wqqCMPE/wav6O/hrYrQy9VSO08C0IM6g9pEEUwWmzuXSkZqhYWoQFb8Lc/GI -T7CMXAxXQLDDUpbRgG79FR3Wr3AewHZU8LyiXHKwxcBMV4WGmsXGK3wbh8fyU1NO -6NsGk+BvkQVOoK1LBAPzZ1kCgYEAsBSmD8U33T9s4dxiEYTrqyV0lH3g/SFz8ZHH -pAyNEPI2iC1ONhyjPWKlcWHpAokiyOqeUpVBWnmSZtzC1qAydsxYB6ShT+sl9BHb -RMix/QAauzBJhQhUVJ3OIys0Q1UBDmqCsjCE8SfOT4NKOUnA093C+YT+iyrmmktZ -zDCJkckCgYEAndqM5KXGk5xYo+MAA1paZcbTUXwaWwjLU+XSRSSoyBEi5xMtfvUb -7+a1OMhLwWbuz+pl64wFKrbSUyimMOYQpjVE/1vk/kb99pxbgol27hdKyTH1d+ov -kFsxKCqxAnBVGEWAvVZAiiTOxleQFjz5RnL0BQp9Lg2cQe+dvuUmIAA= ------END RSA PRIVATE KEY-----`) -) diff --git a/vendor/github.com/miekg/dns/sig0.go b/vendor/github.com/miekg/dns/sig0.go index f31e9e684..07c2acb19 100644 --- a/vendor/github.com/miekg/dns/sig0.go +++ b/vendor/github.com/miekg/dns/sig0.go @@ -127,8 +127,7 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error { if offset+1 >= buflen { continue } - var rdlen uint16 - rdlen = binary.BigEndian.Uint16(buf[offset:]) + rdlen := binary.BigEndian.Uint16(buf[offset:]) offset += 2 offset += int(rdlen) } diff --git a/vendor/github.com/miekg/dns/sig0_test.go b/vendor/github.com/miekg/dns/sig0_test.go deleted file mode 100644 index 122de6a8e..000000000 --- a/vendor/github.com/miekg/dns/sig0_test.go +++ /dev/null @@ -1,89 +0,0 @@ -package dns - -import ( - "crypto" - "testing" - "time" -) - -func TestSIG0(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - m := new(Msg) - m.SetQuestion("example.org.", TypeSOA) - for _, alg := range []uint8{ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256, RSASHA512} { - algstr := AlgorithmToString[alg] - keyrr := new(KEY) - keyrr.Hdr.Name = algstr + "." - keyrr.Hdr.Rrtype = TypeKEY - keyrr.Hdr.Class = ClassINET - keyrr.Algorithm = alg - keysize := 1024 - switch alg { - case ECDSAP256SHA256: - keysize = 256 - case ECDSAP384SHA384: - keysize = 384 - } - pk, err := keyrr.Generate(keysize) - if err != nil { - t.Errorf("failed to generate key for “%s”: %v", algstr, err) - continue - } - now := uint32(time.Now().Unix()) - sigrr := new(SIG) - sigrr.Hdr.Name = "." - sigrr.Hdr.Rrtype = TypeSIG - sigrr.Hdr.Class = ClassANY - sigrr.Algorithm = alg - sigrr.Expiration = now + 300 - sigrr.Inception = now - 300 - sigrr.KeyTag = keyrr.KeyTag() - sigrr.SignerName = keyrr.Hdr.Name - mb, err := sigrr.Sign(pk.(crypto.Signer), m) - if err != nil { - t.Errorf("failed to sign message using “%s”: %v", algstr, err) - continue - } - m := new(Msg) - if err := m.Unpack(mb); err != nil { - t.Errorf("failed to unpack message signed using “%s”: %v", algstr, err) - continue - } - if len(m.Extra) != 1 { - t.Errorf("missing SIG for message signed using “%s”", algstr) - continue - } - var sigrrwire *SIG - switch rr := m.Extra[0].(type) { - case *SIG: - sigrrwire = rr - default: - t.Errorf("expected SIG RR, instead: %v", rr) - continue - } - for _, rr := range []*SIG{sigrr, sigrrwire} { - id := "sigrr" - if rr == sigrrwire { - id = "sigrrwire" - } - if err := rr.Verify(keyrr, mb); err != nil { - t.Errorf("failed to verify “%s” signed SIG(%s): %v", algstr, id, err) - continue - } - } - mb[13]++ - if err := sigrr.Verify(keyrr, mb); err == nil { - t.Errorf("verify succeeded on an altered message using “%s”", algstr) - continue - } - sigrr.Expiration = 2 - sigrr.Inception = 1 - mb, _ = sigrr.Sign(pk.(crypto.Signer), m) - if err := sigrr.Verify(keyrr, mb); err == nil { - t.Errorf("verify succeeded on an expired message using “%s”", algstr) - continue - } - } -} diff --git a/vendor/github.com/miekg/dns/tsig_test.go b/vendor/github.com/miekg/dns/tsig_test.go deleted file mode 100644 index 4bc52733c..000000000 --- a/vendor/github.com/miekg/dns/tsig_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package dns - -import ( - "encoding/binary" - "testing" - "time" -) - -func newTsig(algo string) *Msg { - m := new(Msg) - m.SetQuestion("example.org.", TypeA) - m.SetTsig("example.", algo, 300, time.Now().Unix()) - return m -} - -func TestTsig(t *testing.T) { - m := newTsig(HmacMD5) - buf, _, err := TsigGenerate(m, "pRZgBrBvI4NAHZYhxmhs/Q==", "", false) - if err != nil { - t.Fatal(err) - } - err = TsigVerify(buf, "pRZgBrBvI4NAHZYhxmhs/Q==", "", false) - if err != nil { - t.Fatal(err) - } - - // TSIG accounts for ID substitution. This means if the message ID is - // changed by a forwarder, we should still be able to verify the TSIG. - m = newTsig(HmacMD5) - buf, _, err = TsigGenerate(m, "pRZgBrBvI4NAHZYhxmhs/Q==", "", false) - if err != nil { - t.Fatal(err) - } - - binary.BigEndian.PutUint16(buf[0:2], uint16(42)) - err = TsigVerify(buf, "pRZgBrBvI4NAHZYhxmhs/Q==", "", false) - if err != nil { - t.Fatal(err) - } -} - -func TestTsigCase(t *testing.T) { - m := newTsig("HmAc-mD5.sig-ALg.rEg.int.") // HmacMD5 - buf, _, err := TsigGenerate(m, "pRZgBrBvI4NAHZYhxmhs/Q==", "", false) - if err != nil { - t.Fatal(err) - } - err = TsigVerify(buf, "pRZgBrBvI4NAHZYhxmhs/Q==", "", false) - if err != nil { - t.Fatal(err) - } -} diff --git a/vendor/github.com/miekg/dns/types.go b/vendor/github.com/miekg/dns/types.go index a64f4d7d8..115f2c7bd 100644 --- a/vendor/github.com/miekg/dns/types.go +++ b/vendor/github.com/miekg/dns/types.go @@ -419,128 +419,130 @@ type TXT struct { func (rr *TXT) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) } func sprintName(s string) string { - src := []byte(s) - dst := make([]byte, 0, len(src)) - for i := 0; i < len(src); { - if i+1 < len(src) && src[i] == '\\' && src[i+1] == '.' { - dst = append(dst, src[i:i+2]...) + var dst strings.Builder + dst.Grow(len(s)) + for i := 0; i < len(s); { + if i+1 < len(s) && s[i] == '\\' && s[i+1] == '.' { + dst.WriteString(s[i : i+2]) i += 2 - } else { - b, n := nextByte(src, i) - if n == 0 { - i++ // dangling back slash - } else if b == '.' { - dst = append(dst, b) - } else { - dst = appendDomainNameByte(dst, b) - } - i += n + continue } + + b, n := nextByte(s, i) + switch { + case n == 0: + i++ // dangling back slash + case b == '.': + dst.WriteByte('.') + default: + writeDomainNameByte(&dst, b) + } + i += n } - return string(dst) + return dst.String() } func sprintTxtOctet(s string) string { - src := []byte(s) - dst := make([]byte, 0, len(src)) - dst = append(dst, '"') - for i := 0; i < len(src); { - if i+1 < len(src) && src[i] == '\\' && src[i+1] == '.' { - dst = append(dst, src[i:i+2]...) + var dst strings.Builder + dst.Grow(2 + len(s)) + dst.WriteByte('"') + for i := 0; i < len(s); { + if i+1 < len(s) && s[i] == '\\' && s[i+1] == '.' { + dst.WriteString(s[i : i+2]) i += 2 - } else { - b, n := nextByte(src, i) - if n == 0 { - i++ // dangling back slash - } else if b == '.' { - dst = append(dst, b) - } else { - if b < ' ' || b > '~' { - dst = appendByte(dst, b) - } else { - dst = append(dst, b) - } - } - i += n + continue + } + + b, n := nextByte(s, i) + switch { + case n == 0: + i++ // dangling back slash + case b == '.': + dst.WriteByte('.') + case b < ' ' || b > '~': + writeEscapedByte(&dst, b) + default: + dst.WriteByte(b) } + i += n } - dst = append(dst, '"') - return string(dst) + dst.WriteByte('"') + return dst.String() } func sprintTxt(txt []string) string { - var out []byte + var out strings.Builder for i, s := range txt { + out.Grow(3 + len(s)) if i > 0 { - out = append(out, ` "`...) + out.WriteString(` "`) } else { - out = append(out, '"') + out.WriteByte('"') } - bs := []byte(s) - for j := 0; j < len(bs); { - b, n := nextByte(bs, j) + for j := 0; j < len(s); { + b, n := nextByte(s, j) if n == 0 { break } - out = appendTXTStringByte(out, b) + writeTXTStringByte(&out, b) j += n } - out = append(out, '"') + out.WriteByte('"') } - return string(out) + return out.String() } -func appendDomainNameByte(s []byte, b byte) []byte { +func writeDomainNameByte(s *strings.Builder, b byte) { switch b { case '.', ' ', '\'', '@', ';', '(', ')': // additional chars to escape - return append(s, '\\', b) + s.WriteByte('\\') + s.WriteByte(b) + default: + writeTXTStringByte(s, b) } - return appendTXTStringByte(s, b) } -func appendTXTStringByte(s []byte, b byte) []byte { - switch b { - case '"', '\\': - return append(s, '\\', b) +func writeTXTStringByte(s *strings.Builder, b byte) { + switch { + case b == '"' || b == '\\': + s.WriteByte('\\') + s.WriteByte(b) + case b < ' ' || b > '~': + writeEscapedByte(s, b) + default: + s.WriteByte(b) } - if b < ' ' || b > '~' { - return appendByte(s, b) - } - return append(s, b) } -func appendByte(s []byte, b byte) []byte { +func writeEscapedByte(s *strings.Builder, b byte) { var buf [3]byte bufs := strconv.AppendInt(buf[:0], int64(b), 10) - s = append(s, '\\') - for i := 0; i < 3-len(bufs); i++ { - s = append(s, '0') - } - for _, r := range bufs { - s = append(s, r) + s.WriteByte('\\') + for i := len(bufs); i < 3; i++ { + s.WriteByte('0') } - return s + s.Write(bufs) } -func nextByte(b []byte, offset int) (byte, int) { - if offset >= len(b) { +func nextByte(s string, offset int) (byte, int) { + if offset >= len(s) { return 0, 0 } - if b[offset] != '\\' { + if s[offset] != '\\' { // not an escape sequence - return b[offset], 1 + return s[offset], 1 } - switch len(b) - offset { + switch len(s) - offset { case 1: // dangling escape return 0, 0 case 2, 3: // too short to be \ddd default: // maybe \ddd - if isDigit(b[offset+1]) && isDigit(b[offset+2]) && isDigit(b[offset+3]) { - return dddToByte(b[offset+1:]), 4 + if isDigit(s[offset+1]) && isDigit(s[offset+2]) && isDigit(s[offset+3]) { + return dddStringToByte(s[offset+1:]), 4 } } // not \ddd, just an RFC 1035 "quoted" character - return b[offset+1], 2 + return s[offset+1], 2 } // SPF RR. See RFC 4408, Section 3.1.1. diff --git a/vendor/github.com/miekg/dns/types_test.go b/vendor/github.com/miekg/dns/types_test.go deleted file mode 100644 index 3dbddee1e..000000000 --- a/vendor/github.com/miekg/dns/types_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package dns - -import ( - "testing" -) - -func TestCmToM(t *testing.T) { - s := cmToM(0, 0) - if s != "0.00" { - t.Error("0, 0") - } - - s = cmToM(1, 0) - if s != "0.01" { - t.Error("1, 0") - } - - s = cmToM(3, 1) - if s != "0.30" { - t.Error("3, 1") - } - - s = cmToM(4, 2) - if s != "4" { - t.Error("4, 2") - } - - s = cmToM(5, 3) - if s != "50" { - t.Error("5, 3") - } - - s = cmToM(7, 5) - if s != "7000" { - t.Error("7, 5") - } - - s = cmToM(9, 9) - if s != "90000000" { - t.Error("9, 9") - } -} - -func TestSplitN(t *testing.T) { - xs := splitN("abc", 5) - if len(xs) != 1 && xs[0] != "abc" { - t.Errorf("failure to split abc") - } - - s := "" - for i := 0; i < 255; i++ { - s += "a" - } - - xs = splitN(s, 255) - if len(xs) != 1 && xs[0] != s { - t.Errorf("failure to split 255 char long string") - } - - s += "b" - xs = splitN(s, 255) - if len(xs) != 2 || xs[1] != "b" { - t.Errorf("failure to split 256 char long string: %d", len(xs)) - } - - // Make s longer - for i := 0; i < 255; i++ { - s += "a" - } - xs = splitN(s, 255) - if len(xs) != 3 || xs[2] != "a" { - t.Errorf("failure to split 510 char long string: %d", len(xs)) - } -} diff --git a/vendor/github.com/miekg/dns/udp.go b/vendor/github.com/miekg/dns/udp.go index 82ead6939..a4826ee2f 100644 --- a/vendor/github.com/miekg/dns/udp.go +++ b/vendor/github.com/miekg/dns/udp.go @@ -1,3 +1,5 @@ +// +build !windows + package dns import ( diff --git a/vendor/github.com/miekg/dns/udp_test.go b/vendor/github.com/miekg/dns/udp_test.go deleted file mode 100644 index 224802611..000000000 --- a/vendor/github.com/miekg/dns/udp_test.go +++ /dev/null @@ -1,138 +0,0 @@ -package dns - -import ( - "bytes" - "net" - "runtime" - "strings" - "testing" - "time" - - "golang.org/x/net/ipv4" - "golang.org/x/net/ipv6" -) - -func TestSetUDPSocketOptions(t *testing.T) { - // returns an error if we cannot resolve that address - testFamily := func(n, addr string) error { - a, err := net.ResolveUDPAddr(n, addr) - if err != nil { - return err - } - c, err := net.ListenUDP(n, a) - if err != nil { - return err - } - if err := setUDPSocketOptions(c); err != nil { - t.Fatalf("failed to set socket options: %v", err) - } - ch := make(chan *SessionUDP) - go func() { - // Set some deadline so this goroutine doesn't hang forever - c.SetReadDeadline(time.Now().Add(time.Minute)) - b := make([]byte, 1) - _, sess, err := ReadFromSessionUDP(c, b) - if err != nil { - t.Fatalf("failed to read from conn: %v", err) - } - ch <- sess - }() - - c2, err := net.Dial("udp", c.LocalAddr().String()) - if err != nil { - t.Fatalf("failed to dial udp: %v", err) - } - if _, err := c2.Write([]byte{1}); err != nil { - t.Fatalf("failed to write to conn: %v", err) - } - sess := <-ch - if len(sess.context) == 0 { - t.Fatalf("empty session context: %v", sess) - } - ip := parseDstFromOOB(sess.context) - if ip == nil { - t.Fatalf("failed to parse dst: %v", sess) - } - if !strings.Contains(c.LocalAddr().String(), ip.String()) { - t.Fatalf("dst was different than listen addr: %v != %v", ip.String(), c.LocalAddr().String()) - } - return nil - } - - // we require that ipv4 be supported - if err := testFamily("udp4", "127.0.0.1:0"); err != nil { - t.Fatalf("failed to test socket options on IPv4: %v", err) - } - // IPv6 might not be supported so these will just log - if err := testFamily("udp6", "[::1]:0"); err != nil { - t.Logf("failed to test socket options on IPv6-only: %v", err) - } - if err := testFamily("udp", "[::1]:0"); err != nil { - t.Logf("failed to test socket options on IPv6/IPv4: %v", err) - } -} - -func TestParseDstFromOOB(t *testing.T) { - if runtime.GOARCH != "amd64" { - // The cmsghdr struct differs in the width (32/64-bit) of - // lengths and the struct padding between architectures. - // The data below was only written with amd64 in mind, and - // thus the test must be skipped on other architectures. - t.Skip("skipping test on unsupported architecture") - } - - // dst is :ffff:100.100.100.100 - oob := []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 100, 100, 100, 100, 2, 0, 0, 0} - dst := parseDstFromOOB(oob) - dst4 := dst.To4() - if dst4 == nil { - t.Errorf("failed to parse IPv4 in IPv6: %v", dst) - } else if dst4.String() != "100.100.100.100" { - t.Errorf("unexpected IPv4: %v", dst4) - } - - // dst is 2001:db8::1 - oob = []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 32, 1, 13, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0} - dst = parseDstFromOOB(oob) - dst6 := dst.To16() - if dst6 == nil { - t.Errorf("failed to parse IPv6: %v", dst) - } else if dst6.String() != "2001:db8::1" { - t.Errorf("unexpected IPv6: %v", dst4) - } - - // dst is 100.100.100.100 but was received on 10.10.10.10 - oob = []byte{28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 10, 10, 10, 10, 100, 100, 100, 100, 0, 0, 0, 0} - dst = parseDstFromOOB(oob) - dst4 = dst.To4() - if dst4 == nil { - t.Errorf("failed to parse IPv4: %v", dst) - } else if dst4.String() != "100.100.100.100" { - t.Errorf("unexpected IPv4: %v", dst4) - } -} - -func TestCorrectSource(t *testing.T) { - if runtime.GOARCH != "amd64" { - // See comment above in TestParseDstFromOOB. - t.Skip("skipping test on unsupported architecture") - } - - // dst is :ffff:100.100.100.100 which should be counted as IPv4 - oob := []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 100, 100, 100, 100, 2, 0, 0, 0} - soob := correctSource(oob) - cm4 := new(ipv4.ControlMessage) - cm4.Src = net.ParseIP("100.100.100.100") - if !bytes.Equal(soob, cm4.Marshal()) { - t.Errorf("unexpected oob for ipv4 address: %v", soob) - } - - // dst is 2001:db8::1 - oob = []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 32, 1, 13, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0} - soob = correctSource(oob) - cm6 := new(ipv6.ControlMessage) - cm6.Src = net.ParseIP("2001:db8::1") - if !bytes.Equal(soob, cm6.Marshal()) { - t.Errorf("unexpected oob for IPv6 address: %v", soob) - } -} diff --git a/vendor/github.com/miekg/dns/udp_windows.go b/vendor/github.com/miekg/dns/udp_windows.go new file mode 100644 index 000000000..6778c3c6c --- /dev/null +++ b/vendor/github.com/miekg/dns/udp_windows.go @@ -0,0 +1,37 @@ +// +build windows + +package dns + +import "net" + +// SessionUDP holds the remote address +type SessionUDP struct { + raddr *net.UDPAddr +} + +// RemoteAddr returns the remote network address. +func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr } + +// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a +// net.UDPAddr. +// TODO(fastest963): Once go1.10 is released, use ReadMsgUDP. +func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) { + n, raddr, err := conn.ReadFrom(b) + if err != nil { + return n, nil, err + } + session := &SessionUDP{raddr.(*net.UDPAddr)} + return n, session, err +} + +// WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr. +// TODO(fastest963): Once go1.10 is released, use WriteMsgUDP. +func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) { + n, err := conn.WriteTo(b, session.raddr) + return n, err +} + +// TODO(fastest963): Once go1.10 is released and we can use *MsgUDP methods +// use the standard method in udp.go for these. +func setUDPSocketOptions(*net.UDPConn) error { return nil } +func parseDstFromOOB([]byte, net.IP) net.IP { return nil } diff --git a/vendor/github.com/miekg/dns/update_test.go b/vendor/github.com/miekg/dns/update_test.go deleted file mode 100644 index 5dba413a4..000000000 --- a/vendor/github.com/miekg/dns/update_test.go +++ /dev/null @@ -1,139 +0,0 @@ -package dns - -import ( - "bytes" - "testing" -) - -func TestDynamicUpdateParsing(t *testing.T) { - prefix := "example.com. IN " - for _, typ := range TypeToString { - if typ == "OPT" || typ == "AXFR" || typ == "IXFR" || typ == "ANY" || typ == "TKEY" || - typ == "TSIG" || typ == "ISDN" || typ == "UNSPEC" || typ == "NULL" || typ == "ATMA" || - typ == "Reserved" || typ == "None" || typ == "NXT" || typ == "MAILB" || typ == "MAILA" { - continue - } - if _, err := NewRR(prefix + typ); err != nil { - t.Errorf("failure to parse: %s %s: %v", prefix, typ, err) - } - } -} - -func TestDynamicUpdateUnpack(t *testing.T) { - // From https://github.com/miekg/dns/issues/150#issuecomment-62296803 - // It should be an update message for the zone "example.", - // deleting the A RRset "example." and then adding an A record at "example.". - // class ANY, TYPE A - buf := []byte{171, 68, 40, 0, 0, 1, 0, 0, 0, 2, 0, 0, 7, 101, 120, 97, 109, 112, 108, 101, 0, 0, 6, 0, 1, 192, 12, 0, 1, 0, 255, 0, 0, 0, 0, 0, 0, 192, 12, 0, 1, 0, 1, 0, 0, 0, 0, 0, 4, 127, 0, 0, 1} - msg := new(Msg) - err := msg.Unpack(buf) - if err != nil { - t.Errorf("failed to unpack: %v\n%s", err, msg.String()) - } -} - -func TestDynamicUpdateZeroRdataUnpack(t *testing.T) { - m := new(Msg) - rr := &RR_Header{Name: ".", Rrtype: 0, Class: 1, Ttl: ^uint32(0), Rdlength: 0} - m.Answer = []RR{rr, rr, rr, rr, rr} - m.Ns = m.Answer - for n, s := range TypeToString { - rr.Rrtype = n - bytes, err := m.Pack() - if err != nil { - t.Errorf("failed to pack %s: %v", s, err) - continue - } - if err := new(Msg).Unpack(bytes); err != nil { - t.Errorf("failed to unpack %s: %v", s, err) - } - } -} - -func TestRemoveRRset(t *testing.T) { - // Should add a zero data RR in Class ANY with a TTL of 0 - // for each set mentioned in the RRs provided to it. - rr := testRR(". 100 IN A 127.0.0.1") - m := new(Msg) - m.Ns = []RR{&RR_Header{Name: ".", Rrtype: TypeA, Class: ClassANY, Ttl: 0, Rdlength: 0}} - expectstr := m.String() - expect, err := m.Pack() - if err != nil { - t.Fatalf("error packing expected msg: %v", err) - } - - m.Ns = nil - m.RemoveRRset([]RR{rr}) - actual, err := m.Pack() - if err != nil { - t.Fatalf("error packing actual msg: %v", err) - } - if !bytes.Equal(actual, expect) { - tmp := new(Msg) - if err := tmp.Unpack(actual); err != nil { - t.Fatalf("error unpacking actual msg: %v\nexpected: %v\ngot: %v\n", err, expect, actual) - } - t.Errorf("expected msg:\n%s", expectstr) - t.Errorf("actual msg:\n%v", tmp) - } -} - -func TestPreReqAndRemovals(t *testing.T) { - // Build a list of multiple prereqs and then somes removes followed by an insert. - // We should be able to add multiple prereqs and updates. - m := new(Msg) - m.SetUpdate("example.org.") - m.Id = 1234 - - // Use a full set of RRs each time, so we are sure the rdata is stripped. - rrName1 := testRR("name_used. 3600 IN A 127.0.0.1") - rrName2 := testRR("name_not_used. 3600 IN A 127.0.0.1") - rrRemove1 := testRR("remove1. 3600 IN A 127.0.0.1") - rrRemove2 := testRR("remove2. 3600 IN A 127.0.0.1") - rrRemove3 := testRR("remove3. 3600 IN A 127.0.0.1") - rrInsert := testRR("insert. 3600 IN A 127.0.0.1") - rrRrset1 := testRR("rrset_used1. 3600 IN A 127.0.0.1") - rrRrset2 := testRR("rrset_used2. 3600 IN A 127.0.0.1") - rrRrset3 := testRR("rrset_not_used. 3600 IN A 127.0.0.1") - - // Handle the prereqs. - m.NameUsed([]RR{rrName1}) - m.NameNotUsed([]RR{rrName2}) - m.RRsetUsed([]RR{rrRrset1}) - m.Used([]RR{rrRrset2}) - m.RRsetNotUsed([]RR{rrRrset3}) - - // and now the updates. - m.RemoveName([]RR{rrRemove1}) - m.RemoveRRset([]RR{rrRemove2}) - m.Remove([]RR{rrRemove3}) - m.Insert([]RR{rrInsert}) - - // This test function isn't a Example function because we print these RR with tabs at the - // end and the Example function trim these, thus they never match. - // TODO(miek): don't print these tabs and make this into an Example function. - expect := `;; opcode: UPDATE, status: NOERROR, id: 1234 -;; flags:; QUERY: 1, ANSWER: 5, AUTHORITY: 4, ADDITIONAL: 0 - -;; QUESTION SECTION: -;example.org. IN SOA - -;; ANSWER SECTION: -name_used. 0 CLASS255 ANY -name_not_used. 0 NONE ANY -rrset_used1. 0 CLASS255 A -rrset_used2. 3600 IN A 127.0.0.1 -rrset_not_used. 0 NONE A - -;; AUTHORITY SECTION: -remove1. 0 CLASS255 ANY -remove2. 0 CLASS255 A -remove3. 0 NONE A 127.0.0.1 -insert. 3600 IN A 127.0.0.1 -` - - if m.String() != expect { - t.Errorf("expected msg:\n%s", expect) - t.Errorf("actual msg:\n%v", m.String()) - } -} diff --git a/vendor/github.com/miekg/dns/version.go b/vendor/github.com/miekg/dns/version.go index dcc84e4a7..0b0e9b6d8 100644 --- a/vendor/github.com/miekg/dns/version.go +++ b/vendor/github.com/miekg/dns/version.go @@ -3,7 +3,7 @@ package dns import "fmt" // Version is current version of this library. -var Version = V{1, 0, 8} +var Version = V{1, 0, 14} // V holds the version of this library. type V struct { diff --git a/vendor/github.com/miekg/dns/version_test.go b/vendor/github.com/miekg/dns/version_test.go deleted file mode 100644 index 61c404848..000000000 --- a/vendor/github.com/miekg/dns/version_test.go +++ /dev/null @@ -1,10 +0,0 @@ -package dns - -import "testing" - -func TestVersion(t *testing.T) { - v := V{1, 0, 0} - if x := v.String(); x != "1.0.0" { - t.Fatalf("Failed to convert version %v, got: %s", v, x) - } -} diff --git a/vendor/github.com/oklog/run/example_test.go b/vendor/github.com/oklog/run/example_test.go deleted file mode 100644 index a31d8b283..000000000 --- a/vendor/github.com/oklog/run/example_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package run_test - -import ( - "context" - "errors" - "fmt" - "net" - "net/http" - "time" - - "github.com/oklog/run" -) - -func ExampleGroup_Add_basic() { - var g run.Group - { - cancel := make(chan struct{}) - g.Add(func() error { - select { - case <-time.After(time.Second): - fmt.Printf("The first actor had its time elapsed\n") - return nil - case <-cancel: - fmt.Printf("The first actor was canceled\n") - return nil - } - }, func(err error) { - fmt.Printf("The first actor was interrupted with: %v\n", err) - close(cancel) - }) - } - { - g.Add(func() error { - fmt.Printf("The second actor is returning immediately\n") - return errors.New("immediate teardown") - }, func(err error) { - // Note that this interrupt function is called, even though the - // corresponding execute function has already returned. - fmt.Printf("The second actor was interrupted with: %v\n", err) - }) - } - fmt.Printf("The group was terminated with: %v\n", g.Run()) - // Output: - // The second actor is returning immediately - // The first actor was interrupted with: immediate teardown - // The second actor was interrupted with: immediate teardown - // The first actor was canceled - // The group was terminated with: immediate teardown -} - -func ExampleGroup_Add_context() { - ctx, cancel := context.WithCancel(context.Background()) - var g run.Group - { - ctx, cancel := context.WithCancel(ctx) // note: shadowed - g.Add(func() error { - return runUntilCanceled(ctx) - }, func(error) { - cancel() - }) - } - go cancel() - fmt.Printf("The group was terminated with: %v\n", g.Run()) - // Output: - // The group was terminated with: context canceled -} - -func ExampleGroup_Add_listener() { - var g run.Group - { - ln, _ := net.Listen("tcp", ":0") - g.Add(func() error { - defer fmt.Printf("http.Serve returned\n") - return http.Serve(ln, http.NewServeMux()) - }, func(error) { - ln.Close() - }) - } - { - g.Add(func() error { - return errors.New("immediate teardown") - }, func(error) { - // - }) - } - fmt.Printf("The group was terminated with: %v\n", g.Run()) - // Output: - // http.Serve returned - // The group was terminated with: immediate teardown -} - -func runUntilCanceled(ctx context.Context) error { - <-ctx.Done() - return ctx.Err() -} diff --git a/vendor/github.com/oklog/run/group_test.go b/vendor/github.com/oklog/run/group_test.go deleted file mode 100644 index ccc450f7a..000000000 --- a/vendor/github.com/oklog/run/group_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package run_test - -import ( - "errors" - "testing" - "time" - - "github.com/oklog/run" -) - -func TestZero(t *testing.T) { - var g run.Group - res := make(chan error) - go func() { res <- g.Run() }() - select { - case err := <-res: - if err != nil { - t.Errorf("%v", err) - } - case <-time.After(100 * time.Millisecond): - t.Error("timeout") - } -} - -func TestOne(t *testing.T) { - myError := errors.New("foobar") - var g run.Group - g.Add(func() error { return myError }, func(error) {}) - res := make(chan error) - go func() { res <- g.Run() }() - select { - case err := <-res: - if want, have := myError, err; want != have { - t.Errorf("want %v, have %v", want, have) - } - case <-time.After(100 * time.Millisecond): - t.Error("timeout") - } -} - -func TestMany(t *testing.T) { - interrupt := errors.New("interrupt") - var g run.Group - g.Add(func() error { return interrupt }, func(error) {}) - cancel := make(chan struct{}) - g.Add(func() error { <-cancel; return nil }, func(error) { close(cancel) }) - res := make(chan error) - go func() { res <- g.Run() }() - select { - case err := <-res: - if want, have := interrupt, err; want != have { - t.Errorf("want %v, have %v", want, have) - } - case <-time.After(100 * time.Millisecond): - t.Errorf("timeout") - } -} diff --git a/vendor/github.com/oklog/ulid/ulid.go b/vendor/github.com/oklog/ulid/ulid.go index 2eb0d3a73..c5d0d66fd 100644 --- a/vendor/github.com/oklog/ulid/ulid.go +++ b/vendor/github.com/oklog/ulid/ulid.go @@ -82,9 +82,6 @@ var ( // // ErrBigTime is returned when passing a timestamp bigger than MaxTime. // Reading from the entropy source may also return an error. -// -// Safety for concurrent use is only dependent on the safety of the -// entropy source. func New(ms uint64, entropy io.Reader) (id ULID, err error) { if err = id.SetTime(ms); err != nil { return id, err diff --git a/vendor/github.com/oklog/ulid/ulid_test.go b/vendor/github.com/oklog/ulid/ulid_test.go deleted file mode 100644 index 048adbf1c..000000000 --- a/vendor/github.com/oklog/ulid/ulid_test.go +++ /dev/null @@ -1,785 +0,0 @@ -// Copyright 2016 The Oklog Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ulid_test - -import ( - "bytes" - crand "crypto/rand" - "fmt" - "io" - "math" - "math/rand" - "strings" - "testing" - "testing/iotest" - "testing/quick" - "time" - - "github.com/oklog/ulid" -) - -func ExampleULID() { - t := time.Unix(1000000, 0) - entropy := ulid.Monotonic(rand.New(rand.NewSource(t.UnixNano())), 0) - fmt.Println(ulid.MustNew(ulid.Timestamp(t), entropy)) - // Output: 0000XSNJG0MQJHBF4QX1EFD6Y3 -} - -func TestNew(t *testing.T) { - t.Parallel() - - t.Run("ULID", testULID(func(ms uint64, e io.Reader) ulid.ULID { - id, err := ulid.New(ms, e) - if err != nil { - t.Fatal(err) - } - return id - })) - - t.Run("Error", func(t *testing.T) { - _, err := ulid.New(ulid.MaxTime()+1, nil) - if got, want := err, ulid.ErrBigTime; got != want { - t.Errorf("got err %v, want %v", got, want) - } - - _, err = ulid.New(0, strings.NewReader("")) - if got, want := err, io.EOF; got != want { - t.Errorf("got err %v, want %v", got, want) - } - }) -} - -func TestMustNew(t *testing.T) { - t.Parallel() - - t.Run("ULID", testULID(ulid.MustNew)) - - t.Run("Panic", func(t *testing.T) { - defer func() { - if got, want := recover(), io.EOF; got != want { - t.Errorf("panic with err %v, want %v", got, want) - } - }() - _ = ulid.MustNew(0, strings.NewReader("")) - }) -} - -func TestMustParse(t *testing.T) { - t.Parallel() - - for _, tc := range []struct { - name string - fn func(string) ulid.ULID - }{ - {"MustParse", ulid.MustParse}, - {"MustParseStrict", ulid.MustParseStrict}, - } { - t.Run(tc.name, func(t *testing.T) { - defer func() { - if got, want := recover(), ulid.ErrDataSize; got != want { - t.Errorf("got panic %v, want %v", got, want) - } - }() - _ = tc.fn("") - }) - - } -} - -func testULID(mk func(uint64, io.Reader) ulid.ULID) func(*testing.T) { - return func(t *testing.T) { - want := ulid.ULID{0x0, 0x0, 0x0, 0x1, 0x86, 0xa0} - if got := mk(1e5, nil); got != want { // optional entropy - t.Errorf("\ngot %#v\nwant %#v", got, want) - } - - entropy := bytes.Repeat([]byte{0xFF}, 16) - copy(want[6:], entropy) - if got := mk(1e5, bytes.NewReader(entropy)); got != want { - t.Errorf("\ngot %#v\nwant %#v", got, want) - } - } -} - -func TestRoundTrips(t *testing.T) { - t.Parallel() - - prop := func(id ulid.ULID) bool { - bin, err := id.MarshalBinary() - if err != nil { - t.Fatal(err) - } - - txt, err := id.MarshalText() - if err != nil { - t.Fatal(err) - } - - var a ulid.ULID - if err = a.UnmarshalBinary(bin); err != nil { - t.Fatal(err) - } - - var b ulid.ULID - if err = b.UnmarshalText(txt); err != nil { - t.Fatal(err) - } - - return id == a && b == id && - id == ulid.MustParse(id.String()) && - id == ulid.MustParseStrict(id.String()) - } - - err := quick.Check(prop, &quick.Config{MaxCount: 1E5}) - if err != nil { - t.Fatal(err) - } -} - -func TestMarshalingErrors(t *testing.T) { - t.Parallel() - - var id ulid.ULID - for _, tc := range []struct { - name string - fn func([]byte) error - err error - }{ - {"UnmarshalBinary", id.UnmarshalBinary, ulid.ErrDataSize}, - {"UnmarshalText", id.UnmarshalText, ulid.ErrDataSize}, - {"MarshalBinaryTo", id.MarshalBinaryTo, ulid.ErrBufferSize}, - {"MarshalTextTo", id.MarshalTextTo, ulid.ErrBufferSize}, - } { - t.Run(tc.name, func(t *testing.T) { - if got, want := tc.fn([]byte{}), tc.err; got != want { - t.Errorf("got err %v, want %v", got, want) - } - }) - - } -} - -func TestParseStrictInvalidCharacters(t *testing.T) { - t.Parallel() - - type testCase struct { - name string - input string - } - testCases := []testCase{} - base := "0000XSNJG0MQJHBF4QX1EFD6Y3" - for i := 0; i < ulid.EncodedSize; i++ { - testCases = append(testCases, testCase{ - name: fmt.Sprintf("Invalid 0xFF at index %d", i), - input: base[:i] + "\xff" + base[i+1:], - }) - testCases = append(testCases, testCase{ - name: fmt.Sprintf("Invalid 0x00 at index %d", i), - input: base[:i] + "\x00" + base[i+1:], - }) - } - - for _, tt := range testCases { - t.Run(tt.name, func(t *testing.T) { - _, err := ulid.ParseStrict(tt.input) - if err != ulid.ErrInvalidCharacters { - t.Errorf("Parse(%q): got err %v, want %v", tt.input, err, ulid.ErrInvalidCharacters) - } - }) - } -} - -func TestAlizainCompatibility(t *testing.T) { - t.Parallel() - - ts := uint64(1469918176385) - got := ulid.MustNew(ts, bytes.NewReader(make([]byte, 16))) - want := ulid.MustParse("01ARYZ6S410000000000000000") - if got != want { - t.Fatalf("with time=%d, got %q, want %q", ts, got, want) - } -} - -func TestEncoding(t *testing.T) { - t.Parallel() - - enc := make(map[rune]bool, len(ulid.Encoding)) - for _, r := range ulid.Encoding { - enc[r] = true - } - - prop := func(id ulid.ULID) bool { - for _, r := range id.String() { - if !enc[r] { - return false - } - } - return true - } - - if err := quick.Check(prop, &quick.Config{MaxCount: 1E5}); err != nil { - t.Fatal(err) - } -} - -func TestLexicographicalOrder(t *testing.T) { - t.Parallel() - - prop := func(a, b ulid.ULID) bool { - t1, t2 := a.Time(), b.Time() - s1, s2 := a.String(), b.String() - ord := bytes.Compare(a[:], b[:]) - return t1 == t2 || - (t1 > t2 && s1 > s2 && ord == +1) || - (t1 < t2 && s1 < s2 && ord == -1) - } - - top := ulid.MustNew(ulid.MaxTime(), nil) - for i := 0; i < 10; i++ { // test upper boundary state space - next := ulid.MustNew(top.Time()-1, nil) - if !prop(top, next) { - t.Fatalf("bad lexicographical order: (%v, %q) > (%v, %q) == false", - top.Time(), top, - next.Time(), next, - ) - } - top = next - } - - if err := quick.Check(prop, &quick.Config{MaxCount: 1E6}); err != nil { - t.Fatal(err) - } -} - -func TestCaseInsensitivity(t *testing.T) { - t.Parallel() - - upper := func(id ulid.ULID) (out ulid.ULID) { - return ulid.MustParse(strings.ToUpper(id.String())) - } - - lower := func(id ulid.ULID) (out ulid.ULID) { - return ulid.MustParse(strings.ToLower(id.String())) - } - - err := quick.CheckEqual(upper, lower, nil) - if err != nil { - t.Fatal(err) - } -} - -func TestParseRobustness(t *testing.T) { - t.Parallel() - - cases := [][]byte{ - {0x1, 0xc0, 0x73, 0x62, 0x4a, 0xaf, 0x39, 0x78, 0x51, 0x4e, 0xf8, 0x44, 0x3b, - 0xb2, 0xa8, 0x59, 0xc7, 0x5f, 0xc3, 0xcc, 0x6a, 0xf2, 0x6d, 0x5a, 0xaa, 0x20}, - } - - for _, tc := range cases { - if _, err := ulid.Parse(string(tc)); err != nil { - t.Error(err) - } - } - - prop := func(s [26]byte) (ok bool) { - defer func() { - if err := recover(); err != nil { - t.Error(err) - ok = false - } - }() - - // quick.Check doesn't constrain input, - // so we need to do so artificially. - if s[0] > '7' { - s[0] %= '7' - } - - var err error - if _, err = ulid.Parse(string(s[:])); err != nil { - t.Error(err) - } - - return err == nil - } - - err := quick.Check(prop, &quick.Config{MaxCount: 1E4}) - if err != nil { - t.Fatal(err) - } -} - -func TestNow(t *testing.T) { - t.Parallel() - - before := ulid.Now() - after := ulid.Timestamp(time.Now().UTC().Add(time.Millisecond)) - - if before >= after { - t.Fatalf("clock went mad: before %v, after %v", before, after) - } -} - -func TestTimestamp(t *testing.T) { - t.Parallel() - - tm := time.Unix(1, 1000) // will be truncated - if got, want := ulid.Timestamp(tm), uint64(1000); got != want { - t.Errorf("for %v, got %v, want %v", tm, got, want) - } - - mt := ulid.MaxTime() - dt := time.Unix(int64(mt/1000), int64((mt%1000)*1000000)).Truncate(time.Millisecond) - ts := ulid.Timestamp(dt) - if got, want := ts, mt; got != want { - t.Errorf("got timestamp %d, want %d", got, want) - } -} - -func TestTime(t *testing.T) { - t.Parallel() - - original := time.Now() - diff := original.Sub(ulid.Time(ulid.Timestamp(original))) - if diff >= time.Millisecond { - t.Errorf("difference between original and recovered time (%d) greater"+ - "than a millisecond", diff) - } - -} - -func TestTimestampRoundTrips(t *testing.T) { - t.Parallel() - - prop := func(ts uint64) bool { - return ts == ulid.Timestamp(ulid.Time(ts)) - } - - err := quick.Check(prop, &quick.Config{MaxCount: 1E5}) - if err != nil { - t.Fatal(err) - } -} - -func TestULIDTime(t *testing.T) { - t.Parallel() - - maxTime := ulid.MaxTime() - - var id ulid.ULID - if got, want := id.SetTime(maxTime+1), ulid.ErrBigTime; got != want { - t.Errorf("got err %v, want %v", got, want) - } - - rng := rand.New(rand.NewSource(time.Now().UnixNano())) - for i := 0; i < 1e6; i++ { - ms := uint64(rng.Int63n(int64(maxTime))) - - var id ulid.ULID - if err := id.SetTime(ms); err != nil { - t.Fatal(err) - } - - if got, want := id.Time(), ms; got != want { - t.Fatalf("\nfor %v:\ngot %v\nwant %v", id, got, want) - } - } -} - -func TestEntropy(t *testing.T) { - t.Parallel() - - var id ulid.ULID - if got, want := id.SetEntropy([]byte{}), ulid.ErrDataSize; got != want { - t.Errorf("got err %v, want %v", got, want) - } - - prop := func(e [10]byte) bool { - var id ulid.ULID - if err := id.SetEntropy(e[:]); err != nil { - t.Fatalf("got err %v", err) - } - - got, want := id.Entropy(), e[:] - eq := bytes.Equal(got, want) - if !eq { - t.Errorf("\n(!= %v\n %v)", got, want) - } - - return eq - } - - if err := quick.Check(prop, nil); err != nil { - t.Fatal(err) - } -} - -func TestEntropyRead(t *testing.T) { - t.Parallel() - - prop := func(e [10]byte) bool { - flakyReader := iotest.HalfReader(bytes.NewReader(e[:])) - - id, err := ulid.New(ulid.Now(), flakyReader) - if err != nil { - t.Fatalf("got err %v", err) - } - - got, want := id.Entropy(), e[:] - eq := bytes.Equal(got, want) - if !eq { - t.Errorf("\n(!= %v\n %v)", got, want) - } - - return eq - } - - if err := quick.Check(prop, &quick.Config{MaxCount: 1E4}); err != nil { - t.Fatal(err) - } -} - -func TestCompare(t *testing.T) { - t.Parallel() - - a := func(a, b ulid.ULID) int { - return strings.Compare(a.String(), b.String()) - } - - b := func(a, b ulid.ULID) int { - return a.Compare(b) - } - - err := quick.CheckEqual(a, b, &quick.Config{MaxCount: 1E5}) - if err != nil { - t.Error(err) - } -} - -func TestOverflowHandling(t *testing.T) { - t.Parallel() - - for s, want := range map[string]error{ - "00000000000000000000000000": nil, - "70000000000000000000000000": nil, - "7ZZZZZZZZZZZZZZZZZZZZZZZZZ": nil, - "80000000000000000000000000": ulid.ErrOverflow, - "80000000000000000000000001": ulid.ErrOverflow, - "ZZZZZZZZZZZZZZZZZZZZZZZZZZ": ulid.ErrOverflow, - } { - if _, have := ulid.Parse(s); want != have { - t.Errorf("%s: want error %v, have %v", s, want, have) - } - } -} - -func TestScan(t *testing.T) { - id := ulid.MustNew(123, crand.Reader) - - for _, tc := range []struct { - name string - in interface{} - out ulid.ULID - err error - }{ - {"string", id.String(), id, nil}, - {"bytes", id[:], id, nil}, - {"nil", nil, ulid.ULID{}, nil}, - {"other", 44, ulid.ULID{}, ulid.ErrScanValue}, - } { - tc := tc - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - var out ulid.ULID - err := out.Scan(tc.in) - if got, want := out, tc.out; got.Compare(want) != 0 { - t.Errorf("got ULID %s, want %s", got, want) - } - - if got, want := fmt.Sprint(err), fmt.Sprint(tc.err); got != want { - t.Errorf("got err %q, want %q", got, want) - } - }) - } -} - -func TestMonotonic(t *testing.T) { - now := ulid.Now() - for _, e := range []struct { - name string - mk func() io.Reader - }{ - {"cryptorand", func() io.Reader { return crand.Reader }}, - {"mathrand", func() io.Reader { return rand.New(rand.NewSource(int64(now))) }}, - } { - for _, inc := range []uint64{ - 0, - 1, - 2, - math.MaxUint8 + 1, - math.MaxUint16 + 1, - math.MaxUint32 + 1, - } { - inc := inc - entropy := ulid.Monotonic(e.mk(), uint64(inc)) - - t.Run(fmt.Sprintf("entropy=%s/inc=%d", e.name, inc), func(t *testing.T) { - t.Parallel() - - var prev ulid.ULID - for i := 0; i < 10000; i++ { - next, err := ulid.New(123, entropy) - if err != nil { - t.Fatal(err) - } - - if prev.Compare(next) >= 0 { - t.Fatalf("prev: %v %v > next: %v %v", - prev.Time(), prev.Entropy(), next.Time(), next.Entropy()) - } - - prev = next - } - }) - } - } -} - -func TestMonotonicOverflow(t *testing.T) { - t.Parallel() - - entropy := ulid.Monotonic( - io.MultiReader( - bytes.NewReader(bytes.Repeat([]byte{0xFF}, 10)), // Entropy for first ULID - crand.Reader, // Following random entropy - ), - 0, - ) - - prev, err := ulid.New(0, entropy) - if err != nil { - t.Fatal(err) - } - - next, err := ulid.New(prev.Time(), entropy) - if have, want := err, ulid.ErrMonotonicOverflow; have != want { - t.Errorf("have ulid: %v %v err: %v, want err: %v", - next.Time(), next.Entropy(), have, want) - } -} - -func BenchmarkNew(b *testing.B) { - benchmarkMakeULID(b, func(timestamp uint64, entropy io.Reader) { - _, _ = ulid.New(timestamp, entropy) - }) -} - -func BenchmarkMustNew(b *testing.B) { - benchmarkMakeULID(b, func(timestamp uint64, entropy io.Reader) { - _ = ulid.MustNew(timestamp, entropy) - }) -} - -func benchmarkMakeULID(b *testing.B, f func(uint64, io.Reader)) { - b.ReportAllocs() - b.SetBytes(int64(len(ulid.ULID{}))) - - rng := rand.New(rand.NewSource(time.Now().UnixNano())) - - for _, tc := range []struct { - name string - timestamps []uint64 - entropy io.Reader - }{ - {"WithCrypoEntropy", []uint64{123}, crand.Reader}, - {"WithEntropy", []uint64{123}, rng}, - {"WithMonotonicEntropy_SameTimestamp_Inc0", []uint64{123}, ulid.Monotonic(rng, 0)}, - {"WithMonotonicEntropy_DifferentTimestamp_Inc0", []uint64{122, 123}, ulid.Monotonic(rng, 0)}, - {"WithMonotonicEntropy_SameTimestamp_Inc1", []uint64{123}, ulid.Monotonic(rng, 1)}, - {"WithMonotonicEntropy_DifferentTimestamp_Inc1", []uint64{122, 123}, ulid.Monotonic(rng, 1)}, - {"WithCryptoMonotonicEntropy_SameTimestamp_Inc1", []uint64{123}, ulid.Monotonic(crand.Reader, 1)}, - {"WithCryptoMonotonicEntropy_DifferentTimestamp_Inc1", []uint64{122, 123}, ulid.Monotonic(crand.Reader, 1)}, - {"WithoutEntropy", []uint64{123}, nil}, - } { - tc := tc - b.Run(tc.name, func(b *testing.B) { - b.StopTimer() - b.ResetTimer() - b.StartTimer() - for i := 0; i < b.N; i++ { - f(tc.timestamps[i%len(tc.timestamps)], tc.entropy) - } - }) - } -} - -func BenchmarkParse(b *testing.B) { - const s = "0000XSNJG0MQJHBF4QX1EFD6Y3" - b.SetBytes(int64(len(s))) - for i := 0; i < b.N; i++ { - _, _ = ulid.Parse(s) - } -} - -func BenchmarkParseStrict(b *testing.B) { - const s = "0000XSNJG0MQJHBF4QX1EFD6Y3" - b.SetBytes(int64(len(s))) - for i := 0; i < b.N; i++ { - _, _ = ulid.ParseStrict(s) - } -} - -func BenchmarkMustParse(b *testing.B) { - const s = "0000XSNJG0MQJHBF4QX1EFD6Y3" - b.SetBytes(int64(len(s))) - for i := 0; i < b.N; i++ { - _ = ulid.MustParse(s) - } -} - -func BenchmarkString(b *testing.B) { - entropy := rand.New(rand.NewSource(time.Now().UnixNano())) - id := ulid.MustNew(123456, entropy) - b.SetBytes(int64(len(id))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = id.String() - } -} - -func BenchmarkMarshal(b *testing.B) { - entropy := rand.New(rand.NewSource(time.Now().UnixNano())) - buf := make([]byte, ulid.EncodedSize) - id := ulid.MustNew(123456, entropy) - - b.Run("Text", func(b *testing.B) { - b.SetBytes(int64(len(id))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = id.MarshalText() - } - }) - - b.Run("TextTo", func(b *testing.B) { - b.SetBytes(int64(len(id))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = id.MarshalTextTo(buf) - } - }) - - b.Run("Binary", func(b *testing.B) { - b.SetBytes(int64(len(id))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = id.MarshalBinary() - } - }) - - b.Run("BinaryTo", func(b *testing.B) { - b.SetBytes(int64(len(id))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = id.MarshalBinaryTo(buf) - } - }) -} - -func BenchmarkUnmarshal(b *testing.B) { - var id ulid.ULID - s := "0000XSNJG0MQJHBF4QX1EFD6Y3" - txt := []byte(s) - bin, _ := ulid.MustParse(s).MarshalBinary() - - b.Run("Text", func(b *testing.B) { - b.SetBytes(int64(len(txt))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = id.UnmarshalText(txt) - } - }) - - b.Run("Binary", func(b *testing.B) { - b.SetBytes(int64(len(bin))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = id.UnmarshalBinary(bin) - } - }) -} - -func BenchmarkNow(b *testing.B) { - b.SetBytes(8) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = ulid.Now() - } -} - -func BenchmarkTimestamp(b *testing.B) { - now := time.Now() - b.SetBytes(8) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = ulid.Timestamp(now) - } -} - -func BenchmarkTime(b *testing.B) { - id := ulid.MustNew(123456789, nil) - b.SetBytes(8) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = id.Time() - } -} - -func BenchmarkSetTime(b *testing.B) { - var id ulid.ULID - b.SetBytes(8) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = id.SetTime(123456789) - } -} - -func BenchmarkEntropy(b *testing.B) { - id := ulid.MustNew(0, strings.NewReader("ABCDEFGHIJKLMNOP")) - b.SetBytes(10) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = id.Entropy() - } -} - -func BenchmarkSetEntropy(b *testing.B) { - var id ulid.ULID - e := []byte("ABCDEFGHIJKLMNOP") - b.SetBytes(10) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = id.SetEntropy(e) - } -} - -func BenchmarkCompare(b *testing.B) { - id, other := ulid.MustNew(12345, nil), ulid.MustNew(54321, nil) - b.SetBytes(int64(len(id) * 2)) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = id.Compare(other) - } -} diff --git a/vendor/github.com/opentracing/opentracing-go/.gitignore b/vendor/github.com/opentracing/opentracing-go/.gitignore index c57100a59..565f0f732 100644 --- a/vendor/github.com/opentracing/opentracing-go/.gitignore +++ b/vendor/github.com/opentracing/opentracing-go/.gitignore @@ -1 +1,13 @@ -coverage.txt +# IntelliJ project files +.idea/ +opentracing-go.iml +opentracing-go.ipr +opentracing-go.iws + +# Test results +*.cov +*.html +test.log + +# Build dir +build/ diff --git a/vendor/github.com/opentracing/opentracing-go/.travis.yml b/vendor/github.com/opentracing/opentracing-go/.travis.yml index 9580e48d6..9a2fd0e3d 100644 --- a/vendor/github.com/opentracing/opentracing-go/.travis.yml +++ b/vendor/github.com/opentracing/opentracing-go/.travis.yml @@ -1,22 +1,13 @@ language: go -matrix: - include: - - go: "1.7.x" - - go: "1.8.x" - - go: "1.9.x" - - go: "tip" - env: - - LINT=true - - COVERAGE=true +go: + - 1.6 + - 1.7 + - tip install: - - if [ "$LINT" == true ]; then go get -u golang.org/x/lint/golint/... ; else echo 'skipping lint'; fi - - go get -u github.com/stretchr/testify/... - - go get -u golang.org/x/net/context - + - go get -d -t github.com/opentracing/opentracing-go/... + - go get -u github.com/golang/lint/... script: - - make test + - make test lint - go build ./... - - if [ "$LINT" == true ]; then make lint ; else echo 'skipping lint'; fi - - if [ "$COVERAGE" == true ]; then make cover && bash <(curl -s https://codecov.io/bash) ; else echo 'skipping coverage'; fi diff --git a/vendor/github.com/opentracing/opentracing-go/CHANGELOG.md b/vendor/github.com/opentracing/opentracing-go/CHANGELOG.md index ecfb7e3b7..1fc9fdf7f 100644 --- a/vendor/github.com/opentracing/opentracing-go/CHANGELOG.md +++ b/vendor/github.com/opentracing/opentracing-go/CHANGELOG.md @@ -10,5 +10,5 @@ Changes by Version 1.0.0 (2016-09-26) ------------------- -- This release implements OpenTracing Specification 1.0 (https://opentracing.io/spec) +- This release implements OpenTracing Specification 1.0 (http://opentracing.io/spec) diff --git a/vendor/github.com/opentracing/opentracing-go/LICENSE b/vendor/github.com/opentracing/opentracing-go/LICENSE index f0027349e..148509a40 100644 --- a/vendor/github.com/opentracing/opentracing-go/LICENSE +++ b/vendor/github.com/opentracing/opentracing-go/LICENSE @@ -1,201 +1,21 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2016 The OpenTracing Authors - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. +The MIT License (MIT) + +Copyright (c) 2016 The OpenTracing Authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/opentracing/opentracing-go/Makefile b/vendor/github.com/opentracing/opentracing-go/Makefile index 62abb63f5..2f491f157 100644 --- a/vendor/github.com/opentracing/opentracing-go/Makefile +++ b/vendor/github.com/opentracing/opentracing-go/Makefile @@ -1,15 +1,26 @@ +PACKAGES := . ./mocktracer/... ./ext/... + .DEFAULT_GOAL := test-and-lint -.PHONY: test-and-lint +.PHONE: test-and-lint + test-and-lint: test lint .PHONY: test test: - go test -v -cover -race ./... + go test -v -cover ./... -.PHONY: cover cover: - go test -v -coverprofile=coverage.txt -covermode=atomic -race ./... + @rm -rf cover-all.out + $(foreach pkg, $(PACKAGES), $(MAKE) cover-pkg PKG=$(pkg) || true;) + @grep mode: cover.out > coverage.out + @cat cover-all.out >> coverage.out + go tool cover -html=coverage.out -o cover.html + @rm -rf cover.out cover-all.out coverage.out + +cover-pkg: + go test -coverprofile cover.out $(PKG) + @grep -v mode: cover.out >> cover-all.out .PHONY: lint lint: @@ -18,3 +29,4 @@ lint: @# Run again with magic to exit non-zero if golint outputs anything. @! (golint ./... | read dummy) go vet ./... + diff --git a/vendor/github.com/opentracing/opentracing-go/README.md b/vendor/github.com/opentracing/opentracing-go/README.md index 6ef1d7c9d..5641a6d64 100644 --- a/vendor/github.com/opentracing/opentracing-go/README.md +++ b/vendor/github.com/opentracing/opentracing-go/README.md @@ -1,5 +1,4 @@ [![Gitter chat](http://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg)](https://gitter.im/opentracing/public) [![Build Status](https://travis-ci.org/opentracing/opentracing-go.svg?branch=master)](https://travis-ci.org/opentracing/opentracing-go) [![GoDoc](https://godoc.org/github.com/opentracing/opentracing-go?status.svg)](http://godoc.org/github.com/opentracing/opentracing-go) -[![Sourcegraph Badge](https://sourcegraph.com/github.com/opentracing/opentracing-go/-/badge.svg)](https://sourcegraph.com/github.com/opentracing/opentracing-go?badge) # OpenTracing API for Go @@ -8,8 +7,8 @@ This package is a Go platform API for OpenTracing. ## Required Reading In order to understand the Go platform API, one must first be familiar with the -[OpenTracing project](https://opentracing.io) and -[terminology](https://opentracing.io/specification/) more specifically. +[OpenTracing project](http://opentracing.io) and +[terminology](http://opentracing.io/documentation/pages/spec.html) more specifically. ## API overview for those adding instrumentation @@ -27,7 +26,7 @@ The simplest starting point is `./default_tracer.go`. As early as possible, call import ".../some_tracing_impl" func main() { - opentracing.SetGlobalTracer( + opentracing.InitGlobalTracer( // tracing impl specific: some_tracing_impl.New(...), ) @@ -35,7 +34,7 @@ The simplest starting point is `./default_tracer.go`. As early as possible, call } ``` -#### Non-Singleton initialization +##### Non-Singleton initialization If you prefer direct control to singletons, manage ownership of the `opentracing.Tracer` implementation explicitly. @@ -96,7 +95,7 @@ reference. // Transmit the span's TraceContext as HTTP headers on our // outbound request. - opentracing.GlobalTracer().Inject( + tracer.Inject( span.Context(), opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(httpReq.Header)) @@ -134,21 +133,6 @@ reference. } ``` -#### Conditionally capture a field using `log.Noop` - -In some situations, you may want to dynamically decide whether or not -to log a field. For example, you may want to capture additional data, -such as a customer ID, in non-production environments: - -```go - func Customer(order *Order) log.Field { - if os.Getenv("ENVIRONMENT") == "dev" { - return log.String("customer", order.Customer.ID) - } - return log.Noop() - } -``` - #### Goroutine-safety The entire public API is goroutine-safe and does not require external @@ -161,11 +145,3 @@ Tracing system implementors may be able to reuse or copy-paste-modify the `basic ## API compatibility For the time being, "mild" backwards-incompatible changes may be made without changing the major version number. As OpenTracing and `opentracing-go` mature, backwards compatibility will become more of a priority. - -## Tracer test suite - -A test suite is available in the [harness](https://godoc.org/github.com/opentracing/opentracing-go/harness) package that can assist Tracer implementors to assert that their Tracer is working correctly. - -## Licensing - -[Apache 2.0 License](./LICENSE). diff --git a/vendor/github.com/opentracing/opentracing-go/globaltracer.go b/vendor/github.com/opentracing/opentracing-go/globaltracer.go index 4f7066a92..8c8e793ff 100644 --- a/vendor/github.com/opentracing/opentracing-go/globaltracer.go +++ b/vendor/github.com/opentracing/opentracing-go/globaltracer.go @@ -1,12 +1,7 @@ package opentracing -type registeredTracer struct { - tracer Tracer - isRegistered bool -} - var ( - globalTracer = registeredTracer{NoopTracer{}, false} + globalTracer Tracer = NoopTracer{} ) // SetGlobalTracer sets the [singleton] opentracing.Tracer returned by @@ -16,27 +11,22 @@ var ( // Prior to calling `SetGlobalTracer`, any Spans started via the `StartSpan` // (etc) globals are noops. func SetGlobalTracer(tracer Tracer) { - globalTracer = registeredTracer{tracer, true} + globalTracer = tracer } // GlobalTracer returns the global singleton `Tracer` implementation. // Before `SetGlobalTracer()` is called, the `GlobalTracer()` is a noop // implementation that drops all data handed to it. func GlobalTracer() Tracer { - return globalTracer.tracer + return globalTracer } // StartSpan defers to `Tracer.StartSpan`. See `GlobalTracer()`. func StartSpan(operationName string, opts ...StartSpanOption) Span { - return globalTracer.tracer.StartSpan(operationName, opts...) + return globalTracer.StartSpan(operationName, opts...) } // InitGlobalTracer is deprecated. Please use SetGlobalTracer. func InitGlobalTracer(tracer Tracer) { SetGlobalTracer(tracer) } - -// IsGlobalTracerRegistered returns a `bool` to indicate if a tracer has been globally registered -func IsGlobalTracerRegistered() bool { - return globalTracer.isRegistered -} diff --git a/vendor/github.com/opentracing/opentracing-go/globaltracer_test.go b/vendor/github.com/opentracing/opentracing-go/globaltracer_test.go deleted file mode 100644 index 59fb3b4f7..000000000 --- a/vendor/github.com/opentracing/opentracing-go/globaltracer_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package opentracing - -import ( - "reflect" - "testing" -) - -func TestIsGlobalTracerRegisteredDefaultIsFalse(t *testing.T) { - if IsGlobalTracerRegistered() { - t.Errorf("Should return false when no global tracer is registered.") - } -} - -func TestAfterSettingGlobalTracerIsGlobalTracerRegisteredReturnsTrue(t *testing.T) { - SetGlobalTracer(NoopTracer{}) - - if !IsGlobalTracerRegistered() { - t.Errorf("Should return true after a tracer has been registered.") - } -} - -func TestDefaultTracerIsNoopTracer(t *testing.T) { - if reflect.TypeOf(GlobalTracer()) != reflect.TypeOf(NoopTracer{}) { - t.Errorf("Should return false when no global tracer is registered.") - } -} diff --git a/vendor/github.com/opentracing/opentracing-go/gocontext.go b/vendor/github.com/opentracing/opentracing-go/gocontext.go index 05a62e70b..222a65202 100644 --- a/vendor/github.com/opentracing/opentracing-go/gocontext.go +++ b/vendor/github.com/opentracing/opentracing-go/gocontext.go @@ -1,6 +1,6 @@ package opentracing -import "context" +import "golang.org/x/net/context" type contextKey struct{} @@ -46,9 +46,12 @@ func StartSpanFromContext(ctx context.Context, operationName string, opts ...Sta // startSpanFromContextWithTracer is factored out for testing purposes. func startSpanFromContextWithTracer(ctx context.Context, tracer Tracer, operationName string, opts ...StartSpanOption) (Span, context.Context) { + var span Span if parentSpan := SpanFromContext(ctx); parentSpan != nil { opts = append(opts, ChildOf(parentSpan.Context())) + span = tracer.StartSpan(operationName, opts...) + } else { + span = tracer.StartSpan(operationName, opts...) } - span := tracer.StartSpan(operationName, opts...) return span, ContextWithSpan(ctx, span) } diff --git a/vendor/github.com/opentracing/opentracing-go/gocontext_test.go b/vendor/github.com/opentracing/opentracing-go/gocontext_test.go deleted file mode 100644 index 1e99deaa5..000000000 --- a/vendor/github.com/opentracing/opentracing-go/gocontext_test.go +++ /dev/null @@ -1,81 +0,0 @@ -package opentracing - -import ( - "context" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestContextWithSpan(t *testing.T) { - span := &noopSpan{} - ctx := ContextWithSpan(context.Background(), span) - span2 := SpanFromContext(ctx) - if span != span2 { - t.Errorf("Not the same span returned from context, expected=%+v, actual=%+v", span, span2) - } - - ctx = context.Background() - span2 = SpanFromContext(ctx) - if span2 != nil { - t.Errorf("Expected nil span, found %+v", span2) - } - - ctx = ContextWithSpan(ctx, span) - span2 = SpanFromContext(ctx) - if span != span2 { - t.Errorf("Not the same span returned from context, expected=%+v, actual=%+v", span, span2) - } -} - -func TestStartSpanFromContext(t *testing.T) { - testTracer := testTracer{} - - // Test the case where there *is* a Span in the Context. - { - parentSpan := &testSpan{} - parentCtx := ContextWithSpan(context.Background(), parentSpan) - childSpan, childCtx := startSpanFromContextWithTracer(parentCtx, testTracer, "child") - if !childSpan.Context().(testSpanContext).HasParent { - t.Errorf("Failed to find parent: %v", childSpan) - } - if !childSpan.(testSpan).Equal(SpanFromContext(childCtx)) { - t.Errorf("Unable to find child span in context: %v", childCtx) - } - } - - // Test the case where there *is not* a Span in the Context. - { - emptyCtx := context.Background() - childSpan, childCtx := startSpanFromContextWithTracer(emptyCtx, testTracer, "child") - if childSpan.Context().(testSpanContext).HasParent { - t.Errorf("Should not have found parent: %v", childSpan) - } - if !childSpan.(testSpan).Equal(SpanFromContext(childCtx)) { - t.Errorf("Unable to find child span in context: %v", childCtx) - } - } -} - -func TestStartSpanFromContextOptions(t *testing.T) { - testTracer := testTracer{} - - // Test options are passed to tracer - - startTime := time.Now().Add(-10 * time.Second) // ten seconds ago - span, ctx := startSpanFromContextWithTracer( - context.Background(), testTracer, "parent", StartTime(startTime), Tag{"component", "test"}) - - assert.Equal(t, "test", span.(testSpan).Tags["component"]) - assert.Equal(t, startTime, span.(testSpan).StartTime) - - // Test it also works for a child span - - childStartTime := startTime.Add(3 * time.Second) - childSpan, _ := startSpanFromContextWithTracer( - ctx, testTracer, "child", StartTime(childStartTime)) - - assert.Equal(t, childSpan.(testSpan).Tags["component"], nil) - assert.Equal(t, childSpan.(testSpan).StartTime, childStartTime) -} diff --git a/vendor/github.com/opentracing/opentracing-go/log/field.go b/vendor/github.com/opentracing/opentracing-go/log/field.go index 50feea341..d2cd39a16 100644 --- a/vendor/github.com/opentracing/opentracing-go/log/field.go +++ b/vendor/github.com/opentracing/opentracing-go/log/field.go @@ -20,7 +20,6 @@ const ( errorType objectType lazyLoggerType - noopType ) // Field instances are constructed via LogBool, LogString, and so on. @@ -153,25 +152,6 @@ func Lazy(ll LazyLogger) Field { } } -// Noop creates a no-op log field that should be ignored by the tracer. -// It can be used to capture optional fields, for example those that should -// only be logged in non-production environment: -// -// func customerField(order *Order) log.Field { -// if os.Getenv("ENVIRONMENT") == "dev" { -// return log.String("customer", order.Customer.ID) -// } -// return log.Noop() -// } -// -// span.LogFields(log.String("event", "purchase"), customerField(order)) -// -func Noop() Field { - return Field{ - fieldType: noopType, - } -} - // Encoder allows access to the contents of a Field (via a call to // Field.Marshal). // @@ -223,8 +203,6 @@ func (lf Field) Marshal(visitor Encoder) { visitor.EmitObject(lf.key, lf.interfaceVal) case lazyLoggerType: visitor.EmitLazyLogger(lf.interfaceVal.(LazyLogger)) - case noopType: - // intentionally left blank } } @@ -256,8 +234,6 @@ func (lf Field) Value() interface{} { return math.Float64frombits(uint64(lf.numericVal)) case errorType, objectType, lazyLoggerType: return lf.interfaceVal - case noopType: - return nil default: return nil } diff --git a/vendor/github.com/opentracing/opentracing-go/log/field_test.go b/vendor/github.com/opentracing/opentracing-go/log/field_test.go deleted file mode 100644 index 73ab172d3..000000000 --- a/vendor/github.com/opentracing/opentracing-go/log/field_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package log - -import ( - "fmt" - "testing" -) - -func TestFieldString(t *testing.T) { - testCases := []struct { - field Field - expected string - }{ - { - field: String("key", "value"), - expected: "key:value", - }, - { - field: Bool("key", true), - expected: "key:true", - }, - { - field: Int("key", 5), - expected: "key:5", - }, - { - field: Error(fmt.Errorf("err msg")), - expected: "error:err msg", - }, - { - field: Error(nil), - expected: "error:", - }, - { - field: Noop(), - expected: ":", - }, - } - for i, tc := range testCases { - if str := tc.field.String(); str != tc.expected { - t.Errorf("%d: expected '%s', got '%s'", i, tc.expected, str) - } - } -} - -func TestNoopDoesNotMarshal(t *testing.T) { - mockEncoder := struct { - Encoder - }{} - f := Noop() - f.Marshal(mockEncoder) // panics if any Encoder method is invoked -} diff --git a/vendor/github.com/opentracing/opentracing-go/options_test.go b/vendor/github.com/opentracing/opentracing-go/options_test.go deleted file mode 100644 index 56a543bfe..000000000 --- a/vendor/github.com/opentracing/opentracing-go/options_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package opentracing - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestChildOfAndFollowsFrom(t *testing.T) { - tests := []struct { - newOpt func(SpanContext) SpanReference - refType SpanReferenceType - name string - }{ - {ChildOf, ChildOfRef, "ChildOf"}, - {FollowsFrom, FollowsFromRef, "FollowsFrom"}, - } - - for _, test := range tests { - opts := new(StartSpanOptions) - - test.newOpt(nil).Apply(opts) - require.Nil(t, opts.References, "%s(nil) must not append a reference", test.name) - - ctx := new(noopSpanContext) - test.newOpt(ctx).Apply(opts) - require.Equal(t, []SpanReference{ - SpanReference{ReferencedContext: ctx, Type: test.refType}, - }, opts.References, "%s(ctx) must append a reference", test.name) - } -} diff --git a/vendor/github.com/opentracing/opentracing-go/propagation.go b/vendor/github.com/opentracing/opentracing-go/propagation.go index b0c275eb0..9583fc53a 100644 --- a/vendor/github.com/opentracing/opentracing-go/propagation.go +++ b/vendor/github.com/opentracing/opentracing-go/propagation.go @@ -72,18 +72,18 @@ const ( // // For Tracer.Extract(): the carrier must be a `TextMapReader`. // - // See HTTPHeadersCarrier for an implementation of both TextMapWriter + // See HTTPHeaderCarrier for an implementation of both TextMapWriter // and TextMapReader that defers to an http.Header instance for storage. // For example, Inject(): // // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header) // err := span.Tracer().Inject( - // span.Context(), opentracing.HTTPHeaders, carrier) + // span, opentracing.HTTPHeaders, carrier) // // Or Extract(): // // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header) - // clientContext, err := tracer.Extract( + // span, err := tracer.Extract( // opentracing.HTTPHeaders, carrier) // HTTPHeaders @@ -144,15 +144,15 @@ func (c TextMapCarrier) Set(key, val string) { // // Example usage for server side: // -// carrier := opentracing.HTTPHeadersCarrier(httpReq.Header) -// clientContext, err := tracer.Extract(opentracing.HTTPHeaders, carrier) +// carrier := opentracing.HttpHeadersCarrier(httpReq.Header) +// spanContext, err := tracer.Extract(opentracing.HttpHeaders, carrier) // // Example usage for client side: // // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header) // err := tracer.Inject( // span.Context(), -// opentracing.HTTPHeaders, +// opentracing.HttpHeaders, // carrier) // type HTTPHeadersCarrier http.Header @@ -160,7 +160,7 @@ type HTTPHeadersCarrier http.Header // Set conforms to the TextMapWriter interface. func (c HTTPHeadersCarrier) Set(key, val string) { h := http.Header(c) - h.Set(key, val) + h.Add(key, val) } // ForeachKey conforms to the TextMapReader interface. diff --git a/vendor/github.com/opentracing/opentracing-go/propagation_test.go b/vendor/github.com/opentracing/opentracing-go/propagation_test.go deleted file mode 100644 index e3dad5597..000000000 --- a/vendor/github.com/opentracing/opentracing-go/propagation_test.go +++ /dev/null @@ -1,93 +0,0 @@ -package opentracing - -import ( - "net/http" - "strconv" - "testing" -) - -const testHeaderPrefix = "testprefix-" - -func TestTextMapCarrierInject(t *testing.T) { - m := make(map[string]string) - m["NotOT"] = "blah" - m["opname"] = "AlsoNotOT" - tracer := testTracer{} - span := tracer.StartSpan("someSpan") - fakeID := span.Context().(testSpanContext).FakeID - - carrier := TextMapCarrier(m) - if err := span.Tracer().Inject(span.Context(), TextMap, carrier); err != nil { - t.Fatal(err) - } - - if len(m) != 3 { - t.Errorf("Unexpected header length: %v", len(m)) - } - // The prefix comes from just above; the suffix comes from - // testTracer.Inject(). - if m["testprefix-fakeid"] != strconv.Itoa(fakeID) { - t.Errorf("Could not find fakeid at expected key") - } -} - -func TestTextMapCarrierExtract(t *testing.T) { - m := make(map[string]string) - m["NotOT"] = "blah" - m["opname"] = "AlsoNotOT" - m["testprefix-fakeid"] = "42" - tracer := testTracer{} - - carrier := TextMapCarrier(m) - extractedContext, err := tracer.Extract(TextMap, carrier) - if err != nil { - t.Fatal(err) - } - - if extractedContext.(testSpanContext).FakeID != 42 { - t.Errorf("Failed to read testprefix-fakeid correctly") - } -} - -func TestHTTPHeaderInject(t *testing.T) { - h := http.Header{} - h.Add("NotOT", "blah") - h.Add("opname", "AlsoNotOT") - tracer := testTracer{} - span := tracer.StartSpan("someSpan") - fakeID := span.Context().(testSpanContext).FakeID - - // Use HTTPHeadersCarrier to wrap around `h`. - carrier := HTTPHeadersCarrier(h) - if err := span.Tracer().Inject(span.Context(), HTTPHeaders, carrier); err != nil { - t.Fatal(err) - } - - if len(h) != 3 { - t.Errorf("Unexpected header length: %v", len(h)) - } - // The prefix comes from just above; the suffix comes from - // testTracer.Inject(). - if h.Get("testprefix-fakeid") != strconv.Itoa(fakeID) { - t.Errorf("Could not find fakeid at expected key") - } -} - -func TestHTTPHeaderExtract(t *testing.T) { - h := http.Header{} - h.Add("NotOT", "blah") - h.Add("opname", "AlsoNotOT") - h.Add("testprefix-fakeid", "42") - tracer := testTracer{} - - // Use HTTPHeadersCarrier to wrap around `h`. - carrier := HTTPHeadersCarrier(h) - spanContext, err := tracer.Extract(HTTPHeaders, carrier) - if err != nil { - t.Fatal(err) - } - - if spanContext.(testSpanContext).FakeID != 42 { - t.Errorf("Failed to read testprefix-fakeid correctly") - } -} diff --git a/vendor/github.com/opentracing/opentracing-go/span.go b/vendor/github.com/opentracing/opentracing-go/span.go index 0d3fb5341..f6c3234ac 100644 --- a/vendor/github.com/opentracing/opentracing-go/span.go +++ b/vendor/github.com/opentracing/opentracing-go/span.go @@ -41,8 +41,6 @@ type Span interface { Context() SpanContext // Sets or changes the operation name. - // - // Returns a reference to this Span for chaining. SetOperationName(operationName string) Span // Adds a tag to the span. @@ -53,8 +51,6 @@ type Span interface { // other tag value types is undefined at the OpenTracing level. If a // tracing system does not know how to handle a particular value type, it // may ignore the tag, but shall not panic. - // - // Returns a reference to this Span for chaining. SetTag(key string, value interface{}) Span // LogFields is an efficient and type-checked way to record key:value diff --git a/vendor/github.com/opentracing/opentracing-go/testtracer_test.go b/vendor/github.com/opentracing/opentracing-go/testtracer_test.go deleted file mode 100644 index dd13788cf..000000000 --- a/vendor/github.com/opentracing/opentracing-go/testtracer_test.go +++ /dev/null @@ -1,138 +0,0 @@ -package opentracing - -import ( - "strconv" - "strings" - "time" - - "github.com/opentracing/opentracing-go/log" -) - -const testHTTPHeaderPrefix = "testprefix-" - -// testTracer is a most-noop Tracer implementation that makes it possible for -// unittests to verify whether certain methods were / were not called. -type testTracer struct{} - -var fakeIDSource = 1 - -func nextFakeID() int { - fakeIDSource++ - return fakeIDSource -} - -type testSpanContext struct { - HasParent bool - FakeID int -} - -func (n testSpanContext) ForeachBaggageItem(handler func(k, v string) bool) {} - -type testSpan struct { - spanContext testSpanContext - OperationName string - StartTime time.Time - Tags map[string]interface{} -} - -func (n testSpan) Equal(os Span) bool { - other, ok := os.(testSpan) - if !ok { - return false - } - if n.spanContext != other.spanContext { - return false - } - if n.OperationName != other.OperationName { - return false - } - if !n.StartTime.Equal(other.StartTime) { - return false - } - if len(n.Tags) != len(other.Tags) { - return false - } - - for k, v := range n.Tags { - if ov, ok := other.Tags[k]; !ok || ov != v { - return false - } - } - - return true -} - -// testSpan: -func (n testSpan) Context() SpanContext { return n.spanContext } -func (n testSpan) SetTag(key string, value interface{}) Span { return n } -func (n testSpan) Finish() {} -func (n testSpan) FinishWithOptions(opts FinishOptions) {} -func (n testSpan) LogFields(fields ...log.Field) {} -func (n testSpan) LogKV(kvs ...interface{}) {} -func (n testSpan) SetOperationName(operationName string) Span { return n } -func (n testSpan) Tracer() Tracer { return testTracer{} } -func (n testSpan) SetBaggageItem(key, val string) Span { return n } -func (n testSpan) BaggageItem(key string) string { return "" } -func (n testSpan) LogEvent(event string) {} -func (n testSpan) LogEventWithPayload(event string, payload interface{}) {} -func (n testSpan) Log(data LogData) {} - -// StartSpan belongs to the Tracer interface. -func (n testTracer) StartSpan(operationName string, opts ...StartSpanOption) Span { - sso := StartSpanOptions{} - for _, o := range opts { - o.Apply(&sso) - } - return n.startSpanWithOptions(operationName, sso) -} - -func (n testTracer) startSpanWithOptions(name string, opts StartSpanOptions) Span { - fakeID := nextFakeID() - if len(opts.References) > 0 { - fakeID = opts.References[0].ReferencedContext.(testSpanContext).FakeID - } - - return testSpan{ - OperationName: name, - StartTime: opts.StartTime, - Tags: opts.Tags, - spanContext: testSpanContext{ - HasParent: len(opts.References) > 0, - FakeID: fakeID, - }, - } -} - -// Inject belongs to the Tracer interface. -func (n testTracer) Inject(sp SpanContext, format interface{}, carrier interface{}) error { - spanContext := sp.(testSpanContext) - switch format { - case HTTPHeaders, TextMap: - carrier.(TextMapWriter).Set(testHTTPHeaderPrefix+"fakeid", strconv.Itoa(spanContext.FakeID)) - return nil - } - return ErrUnsupportedFormat -} - -// Extract belongs to the Tracer interface. -func (n testTracer) Extract(format interface{}, carrier interface{}) (SpanContext, error) { - switch format { - case HTTPHeaders, TextMap: - // Just for testing purposes... generally not a worthwhile thing to - // propagate. - sm := testSpanContext{} - err := carrier.(TextMapReader).ForeachKey(func(key, val string) error { - switch strings.ToLower(key) { - case testHTTPHeaderPrefix + "fakeid": - i, err := strconv.Atoi(val) - if err != nil { - return err - } - sm.FakeID = i - } - return nil - }) - return sm, err - } - return nil, ErrSpanContextNotFound -} diff --git a/vendor/github.com/opentracing/opentracing-go/tracer.go b/vendor/github.com/opentracing/opentracing-go/tracer.go index 7bca1f736..fd77c1df3 100644 --- a/vendor/github.com/opentracing/opentracing-go/tracer.go +++ b/vendor/github.com/opentracing/opentracing-go/tracer.go @@ -30,7 +30,7 @@ type Tracer interface { // sp := tracer.StartSpan( // "GetFeed", // opentracing.ChildOf(parentSpan.Context()), - // opentracing.Tag{"user_agent", loggedReq.UserAgent}, + // opentracing.Tag("user_agent", loggedReq.UserAgent), // opentracing.StartTime(loggedReq.Timestamp), // ) // diff --git a/vendor/github.com/pkg/errors/bench_test.go b/vendor/github.com/pkg/errors/bench_test.go deleted file mode 100644 index 0416a3cbb..000000000 --- a/vendor/github.com/pkg/errors/bench_test.go +++ /dev/null @@ -1,59 +0,0 @@ -// +build go1.7 - -package errors - -import ( - "fmt" - "testing" - - stderrors "errors" -) - -func noErrors(at, depth int) error { - if at >= depth { - return stderrors.New("no error") - } - return noErrors(at+1, depth) -} -func yesErrors(at, depth int) error { - if at >= depth { - return New("ye error") - } - return yesErrors(at+1, depth) -} - -func BenchmarkErrors(b *testing.B) { - var toperr error - type run struct { - stack int - std bool - } - runs := []run{ - {10, false}, - {10, true}, - {100, false}, - {100, true}, - {1000, false}, - {1000, true}, - } - for _, r := range runs { - part := "pkg/errors" - if r.std { - part = "errors" - } - name := fmt.Sprintf("%s-stack-%d", part, r.stack) - b.Run(name, func(b *testing.B) { - var err error - f := yesErrors - if r.std { - f = noErrors - } - b.ReportAllocs() - for i := 0; i < b.N; i++ { - err = f(0, r.stack) - } - b.StopTimer() - toperr = err - }) - } -} diff --git a/vendor/github.com/pkg/errors/errors_test.go b/vendor/github.com/pkg/errors/errors_test.go deleted file mode 100644 index 1d8c63558..000000000 --- a/vendor/github.com/pkg/errors/errors_test.go +++ /dev/null @@ -1,226 +0,0 @@ -package errors - -import ( - "errors" - "fmt" - "io" - "reflect" - "testing" -) - -func TestNew(t *testing.T) { - tests := []struct { - err string - want error - }{ - {"", fmt.Errorf("")}, - {"foo", fmt.Errorf("foo")}, - {"foo", New("foo")}, - {"string with format specifiers: %v", errors.New("string with format specifiers: %v")}, - } - - for _, tt := range tests { - got := New(tt.err) - if got.Error() != tt.want.Error() { - t.Errorf("New.Error(): got: %q, want %q", got, tt.want) - } - } -} - -func TestWrapNil(t *testing.T) { - got := Wrap(nil, "no error") - if got != nil { - t.Errorf("Wrap(nil, \"no error\"): got %#v, expected nil", got) - } -} - -func TestWrap(t *testing.T) { - tests := []struct { - err error - message string - want string - }{ - {io.EOF, "read error", "read error: EOF"}, - {Wrap(io.EOF, "read error"), "client error", "client error: read error: EOF"}, - } - - for _, tt := range tests { - got := Wrap(tt.err, tt.message).Error() - if got != tt.want { - t.Errorf("Wrap(%v, %q): got: %v, want %v", tt.err, tt.message, got, tt.want) - } - } -} - -type nilError struct{} - -func (nilError) Error() string { return "nil error" } - -func TestCause(t *testing.T) { - x := New("error") - tests := []struct { - err error - want error - }{{ - // nil error is nil - err: nil, - want: nil, - }, { - // explicit nil error is nil - err: (error)(nil), - want: nil, - }, { - // typed nil is nil - err: (*nilError)(nil), - want: (*nilError)(nil), - }, { - // uncaused error is unaffected - err: io.EOF, - want: io.EOF, - }, { - // caused error returns cause - err: Wrap(io.EOF, "ignored"), - want: io.EOF, - }, { - err: x, // return from errors.New - want: x, - }, { - WithMessage(nil, "whoops"), - nil, - }, { - WithMessage(io.EOF, "whoops"), - io.EOF, - }, { - WithStack(nil), - nil, - }, { - WithStack(io.EOF), - io.EOF, - }} - - for i, tt := range tests { - got := Cause(tt.err) - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("test %d: got %#v, want %#v", i+1, got, tt.want) - } - } -} - -func TestWrapfNil(t *testing.T) { - got := Wrapf(nil, "no error") - if got != nil { - t.Errorf("Wrapf(nil, \"no error\"): got %#v, expected nil", got) - } -} - -func TestWrapf(t *testing.T) { - tests := []struct { - err error - message string - want string - }{ - {io.EOF, "read error", "read error: EOF"}, - {Wrapf(io.EOF, "read error without format specifiers"), "client error", "client error: read error without format specifiers: EOF"}, - {Wrapf(io.EOF, "read error with %d format specifier", 1), "client error", "client error: read error with 1 format specifier: EOF"}, - } - - for _, tt := range tests { - got := Wrapf(tt.err, tt.message).Error() - if got != tt.want { - t.Errorf("Wrapf(%v, %q): got: %v, want %v", tt.err, tt.message, got, tt.want) - } - } -} - -func TestErrorf(t *testing.T) { - tests := []struct { - err error - want string - }{ - {Errorf("read error without format specifiers"), "read error without format specifiers"}, - {Errorf("read error with %d format specifier", 1), "read error with 1 format specifier"}, - } - - for _, tt := range tests { - got := tt.err.Error() - if got != tt.want { - t.Errorf("Errorf(%v): got: %q, want %q", tt.err, got, tt.want) - } - } -} - -func TestWithStackNil(t *testing.T) { - got := WithStack(nil) - if got != nil { - t.Errorf("WithStack(nil): got %#v, expected nil", got) - } -} - -func TestWithStack(t *testing.T) { - tests := []struct { - err error - want string - }{ - {io.EOF, "EOF"}, - {WithStack(io.EOF), "EOF"}, - } - - for _, tt := range tests { - got := WithStack(tt.err).Error() - if got != tt.want { - t.Errorf("WithStack(%v): got: %v, want %v", tt.err, got, tt.want) - } - } -} - -func TestWithMessageNil(t *testing.T) { - got := WithMessage(nil, "no error") - if got != nil { - t.Errorf("WithMessage(nil, \"no error\"): got %#v, expected nil", got) - } -} - -func TestWithMessage(t *testing.T) { - tests := []struct { - err error - message string - want string - }{ - {io.EOF, "read error", "read error: EOF"}, - {WithMessage(io.EOF, "read error"), "client error", "client error: read error: EOF"}, - } - - for _, tt := range tests { - got := WithMessage(tt.err, tt.message).Error() - if got != tt.want { - t.Errorf("WithMessage(%v, %q): got: %q, want %q", tt.err, tt.message, got, tt.want) - } - } - -} - -// errors.New, etc values are not expected to be compared by value -// but the change in errors#27 made them incomparable. Assert that -// various kinds of errors have a functional equality operator, even -// if the result of that equality is always false. -func TestErrorEquality(t *testing.T) { - vals := []error{ - nil, - io.EOF, - errors.New("EOF"), - New("EOF"), - Errorf("EOF"), - Wrap(io.EOF, "EOF"), - Wrapf(io.EOF, "EOF%d", 2), - WithMessage(nil, "whoops"), - WithMessage(io.EOF, "whoops"), - WithStack(io.EOF), - WithStack(nil), - } - - for i := range vals { - for j := range vals { - _ = vals[i] == vals[j] // mustn't panic - } - } -} diff --git a/vendor/github.com/pkg/errors/example_test.go b/vendor/github.com/pkg/errors/example_test.go deleted file mode 100644 index c1fc13e38..000000000 --- a/vendor/github.com/pkg/errors/example_test.go +++ /dev/null @@ -1,205 +0,0 @@ -package errors_test - -import ( - "fmt" - - "github.com/pkg/errors" -) - -func ExampleNew() { - err := errors.New("whoops") - fmt.Println(err) - - // Output: whoops -} - -func ExampleNew_printf() { - err := errors.New("whoops") - fmt.Printf("%+v", err) - - // Example output: - // whoops - // github.com/pkg/errors_test.ExampleNew_printf - // /home/dfc/src/github.com/pkg/errors/example_test.go:17 - // testing.runExample - // /home/dfc/go/src/testing/example.go:114 - // testing.RunExamples - // /home/dfc/go/src/testing/example.go:38 - // testing.(*M).Run - // /home/dfc/go/src/testing/testing.go:744 - // main.main - // /github.com/pkg/errors/_test/_testmain.go:106 - // runtime.main - // /home/dfc/go/src/runtime/proc.go:183 - // runtime.goexit - // /home/dfc/go/src/runtime/asm_amd64.s:2059 -} - -func ExampleWithMessage() { - cause := errors.New("whoops") - err := errors.WithMessage(cause, "oh noes") - fmt.Println(err) - - // Output: oh noes: whoops -} - -func ExampleWithStack() { - cause := errors.New("whoops") - err := errors.WithStack(cause) - fmt.Println(err) - - // Output: whoops -} - -func ExampleWithStack_printf() { - cause := errors.New("whoops") - err := errors.WithStack(cause) - fmt.Printf("%+v", err) - - // Example Output: - // whoops - // github.com/pkg/errors_test.ExampleWithStack_printf - // /home/fabstu/go/src/github.com/pkg/errors/example_test.go:55 - // testing.runExample - // /usr/lib/go/src/testing/example.go:114 - // testing.RunExamples - // /usr/lib/go/src/testing/example.go:38 - // testing.(*M).Run - // /usr/lib/go/src/testing/testing.go:744 - // main.main - // github.com/pkg/errors/_test/_testmain.go:106 - // runtime.main - // /usr/lib/go/src/runtime/proc.go:183 - // runtime.goexit - // /usr/lib/go/src/runtime/asm_amd64.s:2086 - // github.com/pkg/errors_test.ExampleWithStack_printf - // /home/fabstu/go/src/github.com/pkg/errors/example_test.go:56 - // testing.runExample - // /usr/lib/go/src/testing/example.go:114 - // testing.RunExamples - // /usr/lib/go/src/testing/example.go:38 - // testing.(*M).Run - // /usr/lib/go/src/testing/testing.go:744 - // main.main - // github.com/pkg/errors/_test/_testmain.go:106 - // runtime.main - // /usr/lib/go/src/runtime/proc.go:183 - // runtime.goexit - // /usr/lib/go/src/runtime/asm_amd64.s:2086 -} - -func ExampleWrap() { - cause := errors.New("whoops") - err := errors.Wrap(cause, "oh noes") - fmt.Println(err) - - // Output: oh noes: whoops -} - -func fn() error { - e1 := errors.New("error") - e2 := errors.Wrap(e1, "inner") - e3 := errors.Wrap(e2, "middle") - return errors.Wrap(e3, "outer") -} - -func ExampleCause() { - err := fn() - fmt.Println(err) - fmt.Println(errors.Cause(err)) - - // Output: outer: middle: inner: error - // error -} - -func ExampleWrap_extended() { - err := fn() - fmt.Printf("%+v\n", err) - - // Example output: - // error - // github.com/pkg/errors_test.fn - // /home/dfc/src/github.com/pkg/errors/example_test.go:47 - // github.com/pkg/errors_test.ExampleCause_printf - // /home/dfc/src/github.com/pkg/errors/example_test.go:63 - // testing.runExample - // /home/dfc/go/src/testing/example.go:114 - // testing.RunExamples - // /home/dfc/go/src/testing/example.go:38 - // testing.(*M).Run - // /home/dfc/go/src/testing/testing.go:744 - // main.main - // /github.com/pkg/errors/_test/_testmain.go:104 - // runtime.main - // /home/dfc/go/src/runtime/proc.go:183 - // runtime.goexit - // /home/dfc/go/src/runtime/asm_amd64.s:2059 - // github.com/pkg/errors_test.fn - // /home/dfc/src/github.com/pkg/errors/example_test.go:48: inner - // github.com/pkg/errors_test.fn - // /home/dfc/src/github.com/pkg/errors/example_test.go:49: middle - // github.com/pkg/errors_test.fn - // /home/dfc/src/github.com/pkg/errors/example_test.go:50: outer -} - -func ExampleWrapf() { - cause := errors.New("whoops") - err := errors.Wrapf(cause, "oh noes #%d", 2) - fmt.Println(err) - - // Output: oh noes #2: whoops -} - -func ExampleErrorf_extended() { - err := errors.Errorf("whoops: %s", "foo") - fmt.Printf("%+v", err) - - // Example output: - // whoops: foo - // github.com/pkg/errors_test.ExampleErrorf - // /home/dfc/src/github.com/pkg/errors/example_test.go:101 - // testing.runExample - // /home/dfc/go/src/testing/example.go:114 - // testing.RunExamples - // /home/dfc/go/src/testing/example.go:38 - // testing.(*M).Run - // /home/dfc/go/src/testing/testing.go:744 - // main.main - // /github.com/pkg/errors/_test/_testmain.go:102 - // runtime.main - // /home/dfc/go/src/runtime/proc.go:183 - // runtime.goexit - // /home/dfc/go/src/runtime/asm_amd64.s:2059 -} - -func Example_stackTrace() { - type stackTracer interface { - StackTrace() errors.StackTrace - } - - err, ok := errors.Cause(fn()).(stackTracer) - if !ok { - panic("oops, err does not implement stackTracer") - } - - st := err.StackTrace() - fmt.Printf("%+v", st[0:2]) // top two frames - - // Example output: - // github.com/pkg/errors_test.fn - // /home/dfc/src/github.com/pkg/errors/example_test.go:47 - // github.com/pkg/errors_test.Example_stackTrace - // /home/dfc/src/github.com/pkg/errors/example_test.go:127 -} - -func ExampleCause_printf() { - err := errors.Wrap(func() error { - return func() error { - return errors.Errorf("hello %s", fmt.Sprintf("world")) - }() - }(), "failed") - - fmt.Printf("%v", err) - - // Output: failed: hello world -} diff --git a/vendor/github.com/pkg/errors/format_test.go b/vendor/github.com/pkg/errors/format_test.go deleted file mode 100644 index 15fd7d89d..000000000 --- a/vendor/github.com/pkg/errors/format_test.go +++ /dev/null @@ -1,535 +0,0 @@ -package errors - -import ( - "errors" - "fmt" - "io" - "regexp" - "strings" - "testing" -) - -func TestFormatNew(t *testing.T) { - tests := []struct { - error - format string - want string - }{{ - New("error"), - "%s", - "error", - }, { - New("error"), - "%v", - "error", - }, { - New("error"), - "%+v", - "error\n" + - "github.com/pkg/errors.TestFormatNew\n" + - "\t.+/github.com/pkg/errors/format_test.go:26", - }, { - New("error"), - "%q", - `"error"`, - }} - - for i, tt := range tests { - testFormatRegexp(t, i, tt.error, tt.format, tt.want) - } -} - -func TestFormatErrorf(t *testing.T) { - tests := []struct { - error - format string - want string - }{{ - Errorf("%s", "error"), - "%s", - "error", - }, { - Errorf("%s", "error"), - "%v", - "error", - }, { - Errorf("%s", "error"), - "%+v", - "error\n" + - "github.com/pkg/errors.TestFormatErrorf\n" + - "\t.+/github.com/pkg/errors/format_test.go:56", - }} - - for i, tt := range tests { - testFormatRegexp(t, i, tt.error, tt.format, tt.want) - } -} - -func TestFormatWrap(t *testing.T) { - tests := []struct { - error - format string - want string - }{{ - Wrap(New("error"), "error2"), - "%s", - "error2: error", - }, { - Wrap(New("error"), "error2"), - "%v", - "error2: error", - }, { - Wrap(New("error"), "error2"), - "%+v", - "error\n" + - "github.com/pkg/errors.TestFormatWrap\n" + - "\t.+/github.com/pkg/errors/format_test.go:82", - }, { - Wrap(io.EOF, "error"), - "%s", - "error: EOF", - }, { - Wrap(io.EOF, "error"), - "%v", - "error: EOF", - }, { - Wrap(io.EOF, "error"), - "%+v", - "EOF\n" + - "error\n" + - "github.com/pkg/errors.TestFormatWrap\n" + - "\t.+/github.com/pkg/errors/format_test.go:96", - }, { - Wrap(Wrap(io.EOF, "error1"), "error2"), - "%+v", - "EOF\n" + - "error1\n" + - "github.com/pkg/errors.TestFormatWrap\n" + - "\t.+/github.com/pkg/errors/format_test.go:103\n", - }, { - Wrap(New("error with space"), "context"), - "%q", - `"context: error with space"`, - }} - - for i, tt := range tests { - testFormatRegexp(t, i, tt.error, tt.format, tt.want) - } -} - -func TestFormatWrapf(t *testing.T) { - tests := []struct { - error - format string - want string - }{{ - Wrapf(io.EOF, "error%d", 2), - "%s", - "error2: EOF", - }, { - Wrapf(io.EOF, "error%d", 2), - "%v", - "error2: EOF", - }, { - Wrapf(io.EOF, "error%d", 2), - "%+v", - "EOF\n" + - "error2\n" + - "github.com/pkg/errors.TestFormatWrapf\n" + - "\t.+/github.com/pkg/errors/format_test.go:134", - }, { - Wrapf(New("error"), "error%d", 2), - "%s", - "error2: error", - }, { - Wrapf(New("error"), "error%d", 2), - "%v", - "error2: error", - }, { - Wrapf(New("error"), "error%d", 2), - "%+v", - "error\n" + - "github.com/pkg/errors.TestFormatWrapf\n" + - "\t.+/github.com/pkg/errors/format_test.go:149", - }} - - for i, tt := range tests { - testFormatRegexp(t, i, tt.error, tt.format, tt.want) - } -} - -func TestFormatWithStack(t *testing.T) { - tests := []struct { - error - format string - want []string - }{{ - WithStack(io.EOF), - "%s", - []string{"EOF"}, - }, { - WithStack(io.EOF), - "%v", - []string{"EOF"}, - }, { - WithStack(io.EOF), - "%+v", - []string{"EOF", - "github.com/pkg/errors.TestFormatWithStack\n" + - "\t.+/github.com/pkg/errors/format_test.go:175"}, - }, { - WithStack(New("error")), - "%s", - []string{"error"}, - }, { - WithStack(New("error")), - "%v", - []string{"error"}, - }, { - WithStack(New("error")), - "%+v", - []string{"error", - "github.com/pkg/errors.TestFormatWithStack\n" + - "\t.+/github.com/pkg/errors/format_test.go:189", - "github.com/pkg/errors.TestFormatWithStack\n" + - "\t.+/github.com/pkg/errors/format_test.go:189"}, - }, { - WithStack(WithStack(io.EOF)), - "%+v", - []string{"EOF", - "github.com/pkg/errors.TestFormatWithStack\n" + - "\t.+/github.com/pkg/errors/format_test.go:197", - "github.com/pkg/errors.TestFormatWithStack\n" + - "\t.+/github.com/pkg/errors/format_test.go:197"}, - }, { - WithStack(WithStack(Wrapf(io.EOF, "message"))), - "%+v", - []string{"EOF", - "message", - "github.com/pkg/errors.TestFormatWithStack\n" + - "\t.+/github.com/pkg/errors/format_test.go:205", - "github.com/pkg/errors.TestFormatWithStack\n" + - "\t.+/github.com/pkg/errors/format_test.go:205", - "github.com/pkg/errors.TestFormatWithStack\n" + - "\t.+/github.com/pkg/errors/format_test.go:205"}, - }, { - WithStack(Errorf("error%d", 1)), - "%+v", - []string{"error1", - "github.com/pkg/errors.TestFormatWithStack\n" + - "\t.+/github.com/pkg/errors/format_test.go:216", - "github.com/pkg/errors.TestFormatWithStack\n" + - "\t.+/github.com/pkg/errors/format_test.go:216"}, - }} - - for i, tt := range tests { - testFormatCompleteCompare(t, i, tt.error, tt.format, tt.want, true) - } -} - -func TestFormatWithMessage(t *testing.T) { - tests := []struct { - error - format string - want []string - }{{ - WithMessage(New("error"), "error2"), - "%s", - []string{"error2: error"}, - }, { - WithMessage(New("error"), "error2"), - "%v", - []string{"error2: error"}, - }, { - WithMessage(New("error"), "error2"), - "%+v", - []string{ - "error", - "github.com/pkg/errors.TestFormatWithMessage\n" + - "\t.+/github.com/pkg/errors/format_test.go:244", - "error2"}, - }, { - WithMessage(io.EOF, "addition1"), - "%s", - []string{"addition1: EOF"}, - }, { - WithMessage(io.EOF, "addition1"), - "%v", - []string{"addition1: EOF"}, - }, { - WithMessage(io.EOF, "addition1"), - "%+v", - []string{"EOF", "addition1"}, - }, { - WithMessage(WithMessage(io.EOF, "addition1"), "addition2"), - "%v", - []string{"addition2: addition1: EOF"}, - }, { - WithMessage(WithMessage(io.EOF, "addition1"), "addition2"), - "%+v", - []string{"EOF", "addition1", "addition2"}, - }, { - Wrap(WithMessage(io.EOF, "error1"), "error2"), - "%+v", - []string{"EOF", "error1", "error2", - "github.com/pkg/errors.TestFormatWithMessage\n" + - "\t.+/github.com/pkg/errors/format_test.go:272"}, - }, { - WithMessage(Errorf("error%d", 1), "error2"), - "%+v", - []string{"error1", - "github.com/pkg/errors.TestFormatWithMessage\n" + - "\t.+/github.com/pkg/errors/format_test.go:278", - "error2"}, - }, { - WithMessage(WithStack(io.EOF), "error"), - "%+v", - []string{ - "EOF", - "github.com/pkg/errors.TestFormatWithMessage\n" + - "\t.+/github.com/pkg/errors/format_test.go:285", - "error"}, - }, { - WithMessage(Wrap(WithStack(io.EOF), "inside-error"), "outside-error"), - "%+v", - []string{ - "EOF", - "github.com/pkg/errors.TestFormatWithMessage\n" + - "\t.+/github.com/pkg/errors/format_test.go:293", - "inside-error", - "github.com/pkg/errors.TestFormatWithMessage\n" + - "\t.+/github.com/pkg/errors/format_test.go:293", - "outside-error"}, - }} - - for i, tt := range tests { - testFormatCompleteCompare(t, i, tt.error, tt.format, tt.want, true) - } -} - -func TestFormatGeneric(t *testing.T) { - starts := []struct { - err error - want []string - }{ - {New("new-error"), []string{ - "new-error", - "github.com/pkg/errors.TestFormatGeneric\n" + - "\t.+/github.com/pkg/errors/format_test.go:315"}, - }, {Errorf("errorf-error"), []string{ - "errorf-error", - "github.com/pkg/errors.TestFormatGeneric\n" + - "\t.+/github.com/pkg/errors/format_test.go:319"}, - }, {errors.New("errors-new-error"), []string{ - "errors-new-error"}, - }, - } - - wrappers := []wrapper{ - { - func(err error) error { return WithMessage(err, "with-message") }, - []string{"with-message"}, - }, { - func(err error) error { return WithStack(err) }, - []string{ - "github.com/pkg/errors.(func·002|TestFormatGeneric.func2)\n\t" + - ".+/github.com/pkg/errors/format_test.go:333", - }, - }, { - func(err error) error { return Wrap(err, "wrap-error") }, - []string{ - "wrap-error", - "github.com/pkg/errors.(func·003|TestFormatGeneric.func3)\n\t" + - ".+/github.com/pkg/errors/format_test.go:339", - }, - }, { - func(err error) error { return Wrapf(err, "wrapf-error%d", 1) }, - []string{ - "wrapf-error1", - "github.com/pkg/errors.(func·004|TestFormatGeneric.func4)\n\t" + - ".+/github.com/pkg/errors/format_test.go:346", - }, - }, - } - - for s := range starts { - err := starts[s].err - want := starts[s].want - testFormatCompleteCompare(t, s, err, "%+v", want, false) - testGenericRecursive(t, err, want, wrappers, 3) - } -} - -func testFormatRegexp(t *testing.T, n int, arg interface{}, format, want string) { - got := fmt.Sprintf(format, arg) - gotLines := strings.SplitN(got, "\n", -1) - wantLines := strings.SplitN(want, "\n", -1) - - if len(wantLines) > len(gotLines) { - t.Errorf("test %d: wantLines(%d) > gotLines(%d):\n got: %q\nwant: %q", n+1, len(wantLines), len(gotLines), got, want) - return - } - - for i, w := range wantLines { - match, err := regexp.MatchString(w, gotLines[i]) - if err != nil { - t.Fatal(err) - } - if !match { - t.Errorf("test %d: line %d: fmt.Sprintf(%q, err):\n got: %q\nwant: %q", n+1, i+1, format, got, want) - } - } -} - -var stackLineR = regexp.MustCompile(`\.`) - -// parseBlocks parses input into a slice, where: -// - incase entry contains a newline, its a stacktrace -// - incase entry contains no newline, its a solo line. -// -// Detecting stack boundaries only works incase the WithStack-calls are -// to be found on the same line, thats why it is optionally here. -// -// Example use: -// -// for _, e := range blocks { -// if strings.ContainsAny(e, "\n") { -// // Match as stack -// } else { -// // Match as line -// } -// } -// -func parseBlocks(input string, detectStackboundaries bool) ([]string, error) { - var blocks []string - - stack := "" - wasStack := false - lines := map[string]bool{} // already found lines - - for _, l := range strings.Split(input, "\n") { - isStackLine := stackLineR.MatchString(l) - - switch { - case !isStackLine && wasStack: - blocks = append(blocks, stack, l) - stack = "" - lines = map[string]bool{} - case isStackLine: - if wasStack { - // Detecting two stacks after another, possible cause lines match in - // our tests due to WithStack(WithStack(io.EOF)) on same line. - if detectStackboundaries { - if lines[l] { - if len(stack) == 0 { - return nil, errors.New("len of block must not be zero here") - } - - blocks = append(blocks, stack) - stack = l - lines = map[string]bool{l: true} - continue - } - } - - stack = stack + "\n" + l - } else { - stack = l - } - lines[l] = true - case !isStackLine && !wasStack: - blocks = append(blocks, l) - default: - return nil, errors.New("must not happen") - } - - wasStack = isStackLine - } - - // Use up stack - if stack != "" { - blocks = append(blocks, stack) - } - return blocks, nil -} - -func testFormatCompleteCompare(t *testing.T, n int, arg interface{}, format string, want []string, detectStackBoundaries bool) { - gotStr := fmt.Sprintf(format, arg) - - got, err := parseBlocks(gotStr, detectStackBoundaries) - if err != nil { - t.Fatal(err) - } - - if len(got) != len(want) { - t.Fatalf("test %d: fmt.Sprintf(%s, err) -> wrong number of blocks: got(%d) want(%d)\n got: %s\nwant: %s\ngotStr: %q", - n+1, format, len(got), len(want), prettyBlocks(got), prettyBlocks(want), gotStr) - } - - for i := range got { - if strings.ContainsAny(want[i], "\n") { - // Match as stack - match, err := regexp.MatchString(want[i], got[i]) - if err != nil { - t.Fatal(err) - } - if !match { - t.Fatalf("test %d: block %d: fmt.Sprintf(%q, err):\ngot:\n%q\nwant:\n%q\nall-got:\n%s\nall-want:\n%s\n", - n+1, i+1, format, got[i], want[i], prettyBlocks(got), prettyBlocks(want)) - } - } else { - // Match as message - if got[i] != want[i] { - t.Fatalf("test %d: fmt.Sprintf(%s, err) at block %d got != want:\n got: %q\nwant: %q", n+1, format, i+1, got[i], want[i]) - } - } - } -} - -type wrapper struct { - wrap func(err error) error - want []string -} - -func prettyBlocks(blocks []string, prefix ...string) string { - var out []string - - for _, b := range blocks { - out = append(out, fmt.Sprintf("%v", b)) - } - - return " " + strings.Join(out, "\n ") -} - -func testGenericRecursive(t *testing.T, beforeErr error, beforeWant []string, list []wrapper, maxDepth int) { - if len(beforeWant) == 0 { - panic("beforeWant must not be empty") - } - for _, w := range list { - if len(w.want) == 0 { - panic("want must not be empty") - } - - err := w.wrap(beforeErr) - - // Copy required cause append(beforeWant, ..) modified beforeWant subtly. - beforeCopy := make([]string, len(beforeWant)) - copy(beforeCopy, beforeWant) - - beforeWant := beforeCopy - last := len(beforeWant) - 1 - var want []string - - // Merge two stacks behind each other. - if strings.ContainsAny(beforeWant[last], "\n") && strings.ContainsAny(w.want[0], "\n") { - want = append(beforeWant[:last], append([]string{beforeWant[last] + "((?s).*)" + w.want[0]}, w.want[1:]...)...) - } else { - want = append(beforeWant, w.want...) - } - - testFormatCompleteCompare(t, maxDepth, err, "%+v", want, false) - if maxDepth > 0 { - testGenericRecursive(t, err, want, list, maxDepth-1) - } - } -} diff --git a/vendor/github.com/pkg/errors/stack_test.go b/vendor/github.com/pkg/errors/stack_test.go deleted file mode 100644 index 510c27a9f..000000000 --- a/vendor/github.com/pkg/errors/stack_test.go +++ /dev/null @@ -1,292 +0,0 @@ -package errors - -import ( - "fmt" - "runtime" - "testing" -) - -var initpc, _, _, _ = runtime.Caller(0) - -func TestFrameLine(t *testing.T) { - var tests = []struct { - Frame - want int - }{{ - Frame(initpc), - 9, - }, { - func() Frame { - var pc, _, _, _ = runtime.Caller(0) - return Frame(pc) - }(), - 20, - }, { - func() Frame { - var pc, _, _, _ = runtime.Caller(1) - return Frame(pc) - }(), - 28, - }, { - Frame(0), // invalid PC - 0, - }} - - for _, tt := range tests { - got := tt.Frame.line() - want := tt.want - if want != got { - t.Errorf("Frame(%v): want: %v, got: %v", uintptr(tt.Frame), want, got) - } - } -} - -type X struct{} - -func (x X) val() Frame { - var pc, _, _, _ = runtime.Caller(0) - return Frame(pc) -} - -func (x *X) ptr() Frame { - var pc, _, _, _ = runtime.Caller(0) - return Frame(pc) -} - -func TestFrameFormat(t *testing.T) { - var tests = []struct { - Frame - format string - want string - }{{ - Frame(initpc), - "%s", - "stack_test.go", - }, { - Frame(initpc), - "%+s", - "github.com/pkg/errors.init\n" + - "\t.+/github.com/pkg/errors/stack_test.go", - }, { - Frame(0), - "%s", - "unknown", - }, { - Frame(0), - "%+s", - "unknown", - }, { - Frame(initpc), - "%d", - "9", - }, { - Frame(0), - "%d", - "0", - }, { - Frame(initpc), - "%n", - "init", - }, { - func() Frame { - var x X - return x.ptr() - }(), - "%n", - `\(\*X\).ptr`, - }, { - func() Frame { - var x X - return x.val() - }(), - "%n", - "X.val", - }, { - Frame(0), - "%n", - "", - }, { - Frame(initpc), - "%v", - "stack_test.go:9", - }, { - Frame(initpc), - "%+v", - "github.com/pkg/errors.init\n" + - "\t.+/github.com/pkg/errors/stack_test.go:9", - }, { - Frame(0), - "%v", - "unknown:0", - }} - - for i, tt := range tests { - testFormatRegexp(t, i, tt.Frame, tt.format, tt.want) - } -} - -func TestFuncname(t *testing.T) { - tests := []struct { - name, want string - }{ - {"", ""}, - {"runtime.main", "main"}, - {"github.com/pkg/errors.funcname", "funcname"}, - {"funcname", "funcname"}, - {"io.copyBuffer", "copyBuffer"}, - {"main.(*R).Write", "(*R).Write"}, - } - - for _, tt := range tests { - got := funcname(tt.name) - want := tt.want - if got != want { - t.Errorf("funcname(%q): want: %q, got %q", tt.name, want, got) - } - } -} - -func TestTrimGOPATH(t *testing.T) { - var tests = []struct { - Frame - want string - }{{ - Frame(initpc), - "github.com/pkg/errors/stack_test.go", - }} - - for i, tt := range tests { - pc := tt.Frame.pc() - fn := runtime.FuncForPC(pc) - file, _ := fn.FileLine(pc) - got := trimGOPATH(fn.Name(), file) - testFormatRegexp(t, i, got, "%s", tt.want) - } -} - -func TestStackTrace(t *testing.T) { - tests := []struct { - err error - want []string - }{{ - New("ooh"), []string{ - "github.com/pkg/errors.TestStackTrace\n" + - "\t.+/github.com/pkg/errors/stack_test.go:172", - }, - }, { - Wrap(New("ooh"), "ahh"), []string{ - "github.com/pkg/errors.TestStackTrace\n" + - "\t.+/github.com/pkg/errors/stack_test.go:177", // this is the stack of Wrap, not New - }, - }, { - Cause(Wrap(New("ooh"), "ahh")), []string{ - "github.com/pkg/errors.TestStackTrace\n" + - "\t.+/github.com/pkg/errors/stack_test.go:182", // this is the stack of New - }, - }, { - func() error { return New("ooh") }(), []string{ - `github.com/pkg/errors.(func·009|TestStackTrace.func1)` + - "\n\t.+/github.com/pkg/errors/stack_test.go:187", // this is the stack of New - "github.com/pkg/errors.TestStackTrace\n" + - "\t.+/github.com/pkg/errors/stack_test.go:187", // this is the stack of New's caller - }, - }, { - Cause(func() error { - return func() error { - return Errorf("hello %s", fmt.Sprintf("world")) - }() - }()), []string{ - `github.com/pkg/errors.(func·010|TestStackTrace.func2.1)` + - "\n\t.+/github.com/pkg/errors/stack_test.go:196", // this is the stack of Errorf - `github.com/pkg/errors.(func·011|TestStackTrace.func2)` + - "\n\t.+/github.com/pkg/errors/stack_test.go:197", // this is the stack of Errorf's caller - "github.com/pkg/errors.TestStackTrace\n" + - "\t.+/github.com/pkg/errors/stack_test.go:198", // this is the stack of Errorf's caller's caller - }, - }} - for i, tt := range tests { - x, ok := tt.err.(interface { - StackTrace() StackTrace - }) - if !ok { - t.Errorf("expected %#v to implement StackTrace() StackTrace", tt.err) - continue - } - st := x.StackTrace() - for j, want := range tt.want { - testFormatRegexp(t, i, st[j], "%+v", want) - } - } -} - -func stackTrace() StackTrace { - const depth = 8 - var pcs [depth]uintptr - n := runtime.Callers(1, pcs[:]) - var st stack = pcs[0:n] - return st.StackTrace() -} - -func TestStackTraceFormat(t *testing.T) { - tests := []struct { - StackTrace - format string - want string - }{{ - nil, - "%s", - `\[\]`, - }, { - nil, - "%v", - `\[\]`, - }, { - nil, - "%+v", - "", - }, { - nil, - "%#v", - `\[\]errors.Frame\(nil\)`, - }, { - make(StackTrace, 0), - "%s", - `\[\]`, - }, { - make(StackTrace, 0), - "%v", - `\[\]`, - }, { - make(StackTrace, 0), - "%+v", - "", - }, { - make(StackTrace, 0), - "%#v", - `\[\]errors.Frame{}`, - }, { - stackTrace()[:2], - "%s", - `\[stack_test.go stack_test.go\]`, - }, { - stackTrace()[:2], - "%v", - `\[stack_test.go:225 stack_test.go:272\]`, - }, { - stackTrace()[:2], - "%+v", - "\n" + - "github.com/pkg/errors.stackTrace\n" + - "\t.+/github.com/pkg/errors/stack_test.go:225\n" + - "github.com/pkg/errors.TestStackTraceFormat\n" + - "\t.+/github.com/pkg/errors/stack_test.go:276", - }, { - stackTrace()[:2], - "%#v", - `\[\]errors.Frame{stack_test.go:225, stack_test.go:284}`, - }} - - for i, tt := range tests { - testFormatRegexp(t, i, tt.StackTrace, tt.format, tt.want) - } -} diff --git a/vendor/github.com/pquerna/cachecontrol/api_test.go b/vendor/github.com/pquerna/cachecontrol/api_test.go deleted file mode 100644 index 208f5f0aa..000000000 --- a/vendor/github.com/pquerna/cachecontrol/api_test.go +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Copyright 2015 Paul Querna - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package cachecontrol - -import ( - "github.com/pquerna/cachecontrol/cacheobject" - "github.com/stretchr/testify/require" - - "fmt" - "io/ioutil" - "net/http" - "net/http/httptest" - "testing" - "time" -) - -func roundTrip(t *testing.T, fnc func(w http.ResponseWriter, r *http.Request)) (*http.Request, *http.Response) { - ts := httptest.NewServer(http.HandlerFunc(fnc)) - defer ts.Close() - - req, err := http.NewRequest("GET", ts.URL, nil) - require.NoError(t, err) - - res, err := http.DefaultClient.Do(req) - require.NoError(t, err) - - _, err = ioutil.ReadAll(res.Body) - res.Body.Close() - require.NoError(t, err) - return req, res -} - -func TestCachableResponsePublic(t *testing.T) { - req, res := roundTrip(t, func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.Header().Set("Cache-Control", "public") - w.Header().Set("Last-Modified", - time.Now().UTC().Add(time.Duration(time.Hour*-5)).Format(http.TimeFormat)) - fmt.Fprintln(w, `{}`) - }) - - opts := Options{} - reasons, expires, err := CachableResponse(req, res, opts) - require.NoError(t, err) - require.Len(t, reasons, 0) - require.WithinDuration(t, - time.Now().UTC().Add(time.Duration(float64(time.Hour)*0.5)), - expires, - 10*time.Second) -} - -func TestCachableResponsePrivate(t *testing.T) { - req, res := roundTrip(t, func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.Header().Set("Cache-Control", "private") - fmt.Fprintln(w, `{}`) - }) - - opts := Options{} - reasons, expires, err := CachableResponse(req, res, opts) - require.NoError(t, err) - require.Len(t, reasons, 1) - require.Equal(t, reasons[0], cacheobject.ReasonResponsePrivate) - require.Equal(t, time.Time{}, expires) - - opts.PrivateCache = true - reasons, expires, err = CachableResponse(req, res, opts) - require.NoError(t, err) - require.Len(t, reasons, 0) - require.Equal(t, time.Time{}, expires) -} - -func TestResponseWriter(t *testing.T) { - var resp http.ResponseWriter - var req *http.Request - _, _ = roundTrip(t, func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.Header().Set("Cache-Control", "private") - fmt.Fprintln(w, `{}`) - resp = w - req = r - }) - - opts := Options{} - reasons, expires, err := CachableResponseWriter(req, 200, resp, opts) - require.NoError(t, err) - require.Len(t, reasons, 1) - require.Equal(t, reasons[0], cacheobject.ReasonResponsePrivate) - require.Equal(t, time.Time{}, expires) - - opts.PrivateCache = true - reasons, expires, err = CachableResponseWriter(req, 200, resp, opts) - require.NoError(t, err) - require.Len(t, reasons, 0) - require.Equal(t, time.Time{}, expires) -} diff --git a/vendor/github.com/pquerna/cachecontrol/cacheobject/directive_test.go b/vendor/github.com/pquerna/cachecontrol/cacheobject/directive_test.go deleted file mode 100644 index f420fec88..000000000 --- a/vendor/github.com/pquerna/cachecontrol/cacheobject/directive_test.go +++ /dev/null @@ -1,454 +0,0 @@ -/** - * Copyright 2015 Paul Querna - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package cacheobject - -import ( - "github.com/stretchr/testify/require" - - "fmt" - "math" - "testing" -) - -func TestMaxAge(t *testing.T) { - cd, err := ParseResponseCacheControl("") - require.NoError(t, err) - require.Equal(t, cd.MaxAge, DeltaSeconds(-1)) - - cd, err = ParseResponseCacheControl("max-age") - require.Error(t, err) - - cd, err = ParseResponseCacheControl("max-age=20") - require.NoError(t, err) - require.Equal(t, cd.MaxAge, DeltaSeconds(20)) - - cd, err = ParseResponseCacheControl("max-age=0") - require.NoError(t, err) - require.Equal(t, cd.MaxAge, DeltaSeconds(0)) - - cd, err = ParseResponseCacheControl("max-age=-1") - require.Error(t, err) -} - -func TestSMaxAge(t *testing.T) { - cd, err := ParseResponseCacheControl("") - require.NoError(t, err) - require.Equal(t, cd.SMaxAge, DeltaSeconds(-1)) - - cd, err = ParseResponseCacheControl("s-maxage") - require.Error(t, err) - - cd, err = ParseResponseCacheControl("s-maxage=20") - require.NoError(t, err) - require.Equal(t, cd.SMaxAge, DeltaSeconds(20)) - - cd, err = ParseResponseCacheControl("s-maxage=0") - require.NoError(t, err) - require.Equal(t, cd.SMaxAge, DeltaSeconds(0)) - - cd, err = ParseResponseCacheControl("s-maxage=-1") - require.Error(t, err) -} - -func TestResNoCache(t *testing.T) { - cd, err := ParseResponseCacheControl("") - require.NoError(t, err) - require.Equal(t, cd.SMaxAge, DeltaSeconds(-1)) - - cd, err = ParseResponseCacheControl("no-cache") - require.NoError(t, err) - require.Equal(t, cd.NoCachePresent, true) - require.Equal(t, len(cd.NoCache), 0) - - cd, err = ParseResponseCacheControl("no-cache=MyThing") - require.NoError(t, err) - require.Equal(t, cd.NoCachePresent, true) - require.Equal(t, len(cd.NoCache), 1) -} - -func TestResSpaceOnly(t *testing.T) { - cd, err := ParseResponseCacheControl(" ") - require.NoError(t, err) - require.Equal(t, cd.SMaxAge, DeltaSeconds(-1)) -} - -func TestResTabOnly(t *testing.T) { - cd, err := ParseResponseCacheControl("\t") - require.NoError(t, err) - require.Equal(t, cd.SMaxAge, DeltaSeconds(-1)) -} - -func TestResPrivateExtensionQuoted(t *testing.T) { - cd, err := ParseResponseCacheControl(`private="Set-Cookie,Request-Id" public`) - require.NoError(t, err) - require.Equal(t, cd.Public, true) - require.Equal(t, cd.PrivatePresent, true) - require.Equal(t, len(cd.Private), 2) - require.Equal(t, len(cd.Extensions), 0) - require.Equal(t, cd.Private["Set-Cookie"], true) - require.Equal(t, cd.Private["Request-Id"], true) -} - -func TestResCommaFollowingBare(t *testing.T) { - cd, err := ParseResponseCacheControl(`public, max-age=500`) - require.NoError(t, err) - require.Equal(t, cd.Public, true) - require.Equal(t, cd.MaxAge, DeltaSeconds(500)) - require.Equal(t, cd.PrivatePresent, false) - require.Equal(t, len(cd.Extensions), 0) -} - -func TestResCommaFollowingKV(t *testing.T) { - cd, err := ParseResponseCacheControl(`max-age=500, public`) - require.NoError(t, err) - require.Equal(t, cd.Public, true) - require.Equal(t, cd.MaxAge, DeltaSeconds(500)) - require.Equal(t, cd.PrivatePresent, false) - require.Equal(t, len(cd.Extensions), 0) -} - -func TestResPrivateTrailingComma(t *testing.T) { - cd, err := ParseResponseCacheControl(`private=Set-Cookie, public`) - require.NoError(t, err) - require.Equal(t, cd.Public, true) - require.Equal(t, cd.PrivatePresent, true) - require.Equal(t, len(cd.Private), 1) - require.Equal(t, len(cd.Extensions), 0) - require.Equal(t, cd.Private["Set-Cookie"], true) -} - -func TestResPrivateExtension(t *testing.T) { - cd, err := ParseResponseCacheControl(`private=Set-Cookie,Request-Id public`) - require.NoError(t, err) - require.Equal(t, cd.Public, true) - require.Equal(t, cd.PrivatePresent, true) - require.Equal(t, len(cd.Private), 2) - require.Equal(t, len(cd.Extensions), 0) - require.Equal(t, cd.Private["Set-Cookie"], true) - require.Equal(t, cd.Private["Request-Id"], true) -} - -func TestResMultipleNoCacheTabExtension(t *testing.T) { - cd, err := ParseResponseCacheControl("no-cache " + "\t" + "no-cache=Mything aasdfdsfa") - require.NoError(t, err) - require.Equal(t, cd.NoCachePresent, true) - require.Equal(t, len(cd.NoCache), 1) - require.Equal(t, len(cd.Extensions), 1) - require.Equal(t, cd.NoCache["Mything"], true) -} - -func TestResExtensionsEmptyQuote(t *testing.T) { - cd, err := ParseResponseCacheControl(`foo="" bar="hi"`) - require.NoError(t, err) - require.Equal(t, cd.SMaxAge, DeltaSeconds(-1)) - require.Equal(t, len(cd.Extensions), 2) - require.Contains(t, cd.Extensions, "bar=hi") - require.Contains(t, cd.Extensions, "foo=") -} - -func TestResQuoteMismatch(t *testing.T) { - cd, err := ParseResponseCacheControl(`foo="`) - require.Error(t, err) - require.Nil(t, cd) - require.Equal(t, err, ErrQuoteMismatch) -} - -func TestResMustRevalidateNoArgs(t *testing.T) { - cd, err := ParseResponseCacheControl(`must-revalidate=234`) - require.Error(t, err) - require.Nil(t, cd) - require.Equal(t, err, ErrMustRevalidateNoArgs) -} - -func TestResNoTransformNoArgs(t *testing.T) { - cd, err := ParseResponseCacheControl(`no-transform="xxx"`) - require.Error(t, err) - require.Nil(t, cd) - require.Equal(t, err, ErrNoTransformNoArgs) -} - -func TestResNoStoreNoArgs(t *testing.T) { - cd, err := ParseResponseCacheControl(`no-store=""`) - require.Error(t, err) - require.Nil(t, cd) - require.Equal(t, err, ErrNoStoreNoArgs) -} - -func TestResProxyRevalidateNoArgs(t *testing.T) { - cd, err := ParseResponseCacheControl(`proxy-revalidate=23432`) - require.Error(t, err) - require.Nil(t, cd) - require.Equal(t, err, ErrProxyRevalidateNoArgs) -} - -func TestResPublicNoArgs(t *testing.T) { - cd, err := ParseResponseCacheControl(`public=999Vary`) - require.Error(t, err) - require.Nil(t, cd) - require.Equal(t, err, ErrPublicNoArgs) -} - -func TestResMustRevalidate(t *testing.T) { - cd, err := ParseResponseCacheControl(`must-revalidate`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Equal(t, cd.MustRevalidate, true) -} - -func TestResNoTransform(t *testing.T) { - cd, err := ParseResponseCacheControl(`no-transform`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Equal(t, cd.NoTransform, true) -} - -func TestResNoStore(t *testing.T) { - cd, err := ParseResponseCacheControl(`no-store`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Equal(t, cd.NoStore, true) -} - -func TestResProxyRevalidate(t *testing.T) { - cd, err := ParseResponseCacheControl(`proxy-revalidate`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Equal(t, cd.ProxyRevalidate, true) -} - -func TestResPublic(t *testing.T) { - cd, err := ParseResponseCacheControl(`public`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Equal(t, cd.Public, true) -} - -func TestResPrivate(t *testing.T) { - cd, err := ParseResponseCacheControl(`private`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Len(t, cd.Private, 0) - require.Equal(t, cd.PrivatePresent, true) -} - -func TestResImmutable(t *testing.T) { - cd, err := ParseResponseCacheControl(`immutable`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Equal(t, cd.Immutable, true) -} - -func TestResStaleIfError(t *testing.T) { - cd, err := ParseResponseCacheControl(`stale-if-error=99999`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Equal(t, cd.StaleIfError, DeltaSeconds(99999)) -} - -func TestResStaleWhileRevalidate(t *testing.T) { - cd, err := ParseResponseCacheControl(`stale-while-revalidate=99999`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Equal(t, cd.StaleWhileRevalidate, DeltaSeconds(99999)) -} - -func TestParseDeltaSecondsZero(t *testing.T) { - ds, err := parseDeltaSeconds("0") - require.NoError(t, err) - require.Equal(t, ds, DeltaSeconds(0)) -} - -func TestParseDeltaSecondsLarge(t *testing.T) { - ds, err := parseDeltaSeconds(fmt.Sprintf("%d", int64(math.MaxInt32)*2)) - require.NoError(t, err) - require.Equal(t, ds, DeltaSeconds(math.MaxInt32)) -} - -func TestParseDeltaSecondsVeryLarge(t *testing.T) { - ds, err := parseDeltaSeconds(fmt.Sprintf("%d", int64(math.MaxInt64))) - require.NoError(t, err) - require.Equal(t, ds, DeltaSeconds(math.MaxInt32)) -} - -func TestParseDeltaSecondsNegative(t *testing.T) { - ds, err := parseDeltaSeconds("-60") - require.Error(t, err) - require.Equal(t, DeltaSeconds(-1), ds) -} - -func TestReqNoCacheNoArgs(t *testing.T) { - cd, err := ParseRequestCacheControl(`no-cache=234`) - require.Error(t, err) - require.Nil(t, cd) - require.Equal(t, err, ErrNoCacheNoArgs) -} - -func TestReqNoStoreNoArgs(t *testing.T) { - cd, err := ParseRequestCacheControl(`no-store=,,x`) - require.Error(t, err) - require.Nil(t, cd) - require.Equal(t, err, ErrNoStoreNoArgs) -} - -func TestReqNoTransformNoArgs(t *testing.T) { - cd, err := ParseRequestCacheControl(`no-transform=akx`) - require.Error(t, err) - require.Nil(t, cd) - require.Equal(t, err, ErrNoTransformNoArgs) -} - -func TestReqOnlyIfCachedNoArgs(t *testing.T) { - cd, err := ParseRequestCacheControl(`only-if-cached=no-store`) - require.Error(t, err) - require.Nil(t, cd) - require.Equal(t, err, ErrOnlyIfCachedNoArgs) -} - -func TestReqMaxAge(t *testing.T) { - cd, err := ParseRequestCacheControl(`max-age=99999`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Equal(t, cd.MaxAge, DeltaSeconds(99999)) - require.Equal(t, cd.MaxStale, DeltaSeconds(-1)) -} - -func TestReqMaxStale(t *testing.T) { - cd, err := ParseRequestCacheControl(`max-stale=99999`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Equal(t, cd.MaxStale, DeltaSeconds(99999)) - require.Equal(t, cd.MaxAge, DeltaSeconds(-1)) - require.Equal(t, cd.MinFresh, DeltaSeconds(-1)) -} - -func TestReqMaxAgeBroken(t *testing.T) { - cd, err := ParseRequestCacheControl(`max-age`) - require.Error(t, err) - require.Equal(t, ErrMaxAgeDeltaSeconds, err) - require.Nil(t, cd) -} - -func TestReqMaxStaleBroken(t *testing.T) { - cd, err := ParseRequestCacheControl(`max-stale`) - require.Error(t, err) - require.Equal(t, ErrMaxStaleDeltaSeconds, err) - require.Nil(t, cd) -} - -func TestReqMinFresh(t *testing.T) { - cd, err := ParseRequestCacheControl(`min-fresh=99999`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Equal(t, cd.MinFresh, DeltaSeconds(99999)) - require.Equal(t, cd.MaxAge, DeltaSeconds(-1)) - require.Equal(t, cd.MaxStale, DeltaSeconds(-1)) -} - -func TestReqMinFreshBroken(t *testing.T) { - cd, err := ParseRequestCacheControl(`min-fresh`) - require.Error(t, err) - require.Equal(t, ErrMinFreshDeltaSeconds, err) - require.Nil(t, cd) -} - -func TestReqMinFreshJunk(t *testing.T) { - cd, err := ParseRequestCacheControl(`min-fresh=a99a`) - require.Equal(t, ErrMinFreshDeltaSeconds, err) - require.Nil(t, cd) -} - -func TestReqMinFreshBadValue(t *testing.T) { - cd, err := ParseRequestCacheControl(`min-fresh=-1`) - require.Equal(t, ErrMinFreshDeltaSeconds, err) - require.Nil(t, cd) -} - -func TestReqExtensions(t *testing.T) { - cd, err := ParseRequestCacheControl(`min-fresh=99999 foobar=1 cats`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Equal(t, cd.MinFresh, DeltaSeconds(99999)) - require.Equal(t, cd.MaxAge, DeltaSeconds(-1)) - require.Equal(t, cd.MaxStale, DeltaSeconds(-1)) - require.Len(t, cd.Extensions, 2) - require.Contains(t, cd.Extensions, "foobar=1") - require.Contains(t, cd.Extensions, "cats") -} - -func TestReqMultiple(t *testing.T) { - cd, err := ParseRequestCacheControl(`no-store no-transform`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Equal(t, cd.NoStore, true) - require.Equal(t, cd.NoTransform, true) - require.Equal(t, cd.OnlyIfCached, false) - require.Len(t, cd.Extensions, 0) -} - -func TestReqMultipleComma(t *testing.T) { - cd, err := ParseRequestCacheControl(`no-cache,only-if-cached`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Equal(t, cd.NoCache, true) - require.Equal(t, cd.NoStore, false) - require.Equal(t, cd.NoTransform, false) - require.Equal(t, cd.OnlyIfCached, true) - require.Len(t, cd.Extensions, 0) -} - -func TestReqLeadingComma(t *testing.T) { - cd, err := ParseRequestCacheControl(`,no-cache`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Len(t, cd.Extensions, 0) - require.Equal(t, cd.NoCache, true) - require.Equal(t, cd.NoStore, false) - require.Equal(t, cd.NoTransform, false) - require.Equal(t, cd.OnlyIfCached, false) -} - -func TestReqMinFreshQuoted(t *testing.T) { - cd, err := ParseRequestCacheControl(`min-fresh="99999"`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Equal(t, cd.MinFresh, DeltaSeconds(99999)) - require.Equal(t, cd.MaxAge, DeltaSeconds(-1)) - require.Equal(t, cd.MaxStale, DeltaSeconds(-1)) -} - -func TestNoSpacesIssue3(t *testing.T) { - cd, err := ParseResponseCacheControl(`no-cache,no-store,max-age=0,must-revalidate`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Equal(t, cd.NoCachePresent, true) - require.Equal(t, cd.NoStore, true) - require.Equal(t, cd.MaxAge, DeltaSeconds(0)) - require.Equal(t, cd.MustRevalidate, true) -} - -func TestNoSpacesIssue3PrivateFields(t *testing.T) { - cd, err := ParseResponseCacheControl(`no-cache, no-store, private=set-cookie,hello, max-age=0, must-revalidate`) - require.NoError(t, err) - require.NotNil(t, cd) - require.Equal(t, cd.NoCachePresent, true) - require.Equal(t, cd.NoStore, true) - require.Equal(t, cd.MaxAge, DeltaSeconds(0)) - require.Equal(t, cd.MustRevalidate, true) - require.Equal(t, true, cd.Private["Set-Cookie"]) - require.Equal(t, true, cd.Private["Hello"]) -} diff --git a/vendor/github.com/pquerna/cachecontrol/cacheobject/object_http_test.go b/vendor/github.com/pquerna/cachecontrol/cacheobject/object_http_test.go deleted file mode 100644 index 5d77f5714..000000000 --- a/vendor/github.com/pquerna/cachecontrol/cacheobject/object_http_test.go +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Copyright 2015 Paul Querna - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package cacheobject - -import ( - "github.com/stretchr/testify/require" - - "fmt" - "io/ioutil" - "net/http" - "net/http/httptest" - "testing" - "time" -) - -func roundTrip(t *testing.T, fnc func(w http.ResponseWriter, r *http.Request)) (*http.Request, *http.Response) { - ts := httptest.NewServer(http.HandlerFunc(fnc)) - defer ts.Close() - - req, err := http.NewRequest("GET", ts.URL, nil) - require.NoError(t, err) - - res, err := http.DefaultClient.Do(req) - require.NoError(t, err) - - _, err = ioutil.ReadAll(res.Body) - res.Body.Close() - require.NoError(t, err) - return req, res -} - -func TestCachableResponsePublic(t *testing.T) { - req, res := roundTrip(t, func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.Header().Set("Cache-Control", "public") - w.Header().Set("Last-Modified", - time.Now().UTC().Add(time.Duration(time.Hour*-5)).Format(http.TimeFormat)) - fmt.Fprintln(w, `{}`) - }) - - reasons, expires, err := UsingRequestResponse(req, res.StatusCode, res.Header, false) - - require.NoError(t, err) - require.Len(t, reasons, 0) - require.WithinDuration(t, - time.Now().UTC().Add(time.Duration(float64(time.Hour)*0.5)), - expires, - 10*time.Second) -} - -func TestCachableResponseNoHeaders(t *testing.T) { - req, res := roundTrip(t, func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - fmt.Fprintln(w, `{}`) - }) - - reasons, expires, err := UsingRequestResponse(req, res.StatusCode, res.Header, false) - - require.NoError(t, err) - require.Len(t, reasons, 0) - require.True(t, expires.IsZero()) -} - -func TestCachableResponseBadExpires(t *testing.T) { - req, res := roundTrip(t, func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.Header().Set("Expires", "-1") - fmt.Fprintln(w, `{}`) - }) - - reasons, expires, err := UsingRequestResponse(req, res.StatusCode, res.Header, false) - - require.NoError(t, err) - require.Len(t, reasons, 0) - require.True(t, expires.IsZero()) -} diff --git a/vendor/github.com/pquerna/cachecontrol/cacheobject/object_test.go b/vendor/github.com/pquerna/cachecontrol/cacheobject/object_test.go deleted file mode 100644 index 6986a7e04..000000000 --- a/vendor/github.com/pquerna/cachecontrol/cacheobject/object_test.go +++ /dev/null @@ -1,394 +0,0 @@ -/** - * Copyright 2015 Paul Querna - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package cacheobject - -import ( - "github.com/stretchr/testify/require" - - "net/http" - "testing" - "time" -) - -func TestCachableStatusCode(t *testing.T) { - ok := []int{200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501} - for _, v := range ok { - require.True(t, cachableStatusCode(v), "status code should be cacheable: %d", v) - } - - notok := []int{201, 429, 500, 504} - for _, v := range notok { - require.False(t, cachableStatusCode(v), "status code should not be cachable: %d", v) - } -} - -func fill(t *testing.T, now time.Time) Object { - RespDirectives, err := ParseResponseCacheControl("") - require.NoError(t, err) - ReqDirectives, err := ParseRequestCacheControl("") - require.NoError(t, err) - - obj := Object{ - RespDirectives: RespDirectives, - RespHeaders: http.Header{}, - RespStatusCode: 200, - RespDateHeader: now, - - ReqDirectives: ReqDirectives, - ReqHeaders: http.Header{}, - ReqMethod: "GET", - - NowUTC: now, - } - - return obj -} - -func TestGETPrivate(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - RespDirectives, err := ParseResponseCacheControl("private") - require.NoError(t, err) - - obj.RespDirectives = RespDirectives - - rv := ObjectResults{} - CachableObject(&obj, &rv) - require.NoError(t, rv.OutErr) - require.Len(t, rv.OutReasons, 1) - require.Contains(t, rv.OutReasons, ReasonResponsePrivate) -} - -func TestGETPrivateWithPrivateCache(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - RespDirectives, err := ParseResponseCacheControl("private") - require.NoError(t, err) - - obj.CacheIsPrivate = true - obj.RespDirectives = RespDirectives - - rv := ObjectResults{} - CachableObject(&obj, &rv) - require.NoError(t, rv.OutErr) - require.Len(t, rv.OutReasons, 0) -} - -func TestUncachableMethods(t *testing.T) { - type methodPair struct { - m string - r Reason - } - - tc := []methodPair{ - {"PUT", ReasonRequestMethodPUT}, - {"DELETE", ReasonRequestMethodDELETE}, - {"CONNECT", ReasonRequestMethodCONNECT}, - {"OPTIONS", ReasonRequestMethodOPTIONS}, - {"CONNECT", ReasonRequestMethodCONNECT}, - {"TRACE", ReasonRequestMethodTRACE}, - {"MADEUP", ReasonRequestMethodUnkown}, - } - - for _, mp := range tc { - now := time.Now().UTC() - - obj := fill(t, now) - obj.ReqMethod = mp.m - - rv := ObjectResults{} - CachableObject(&obj, &rv) - require.NoError(t, rv.OutErr) - require.Len(t, rv.OutReasons, 1) - require.Contains(t, rv.OutReasons, mp.r) - } -} - -func TestHEAD(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - obj.ReqMethod = "HEAD" - obj.RespLastModifiedHeader = now.Add(time.Hour * -1) - - rv := ObjectResults{} - CachableObject(&obj, &rv) - require.NoError(t, rv.OutErr) - require.Len(t, rv.OutReasons, 0) - - ExpirationObject(&obj, &rv) - require.NoError(t, rv.OutErr) - require.Len(t, rv.OutReasons, 0) - require.False(t, rv.OutExpirationTime.IsZero()) -} - -func TestHEADLongLastModified(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - obj.ReqMethod = "HEAD" - obj.RespLastModifiedHeader = now.Add(time.Hour * -70000) - - rv := ObjectResults{} - CachableObject(&obj, &rv) - require.NoError(t, rv.OutErr) - require.Len(t, rv.OutReasons, 0) - - ExpirationObject(&obj, &rv) - require.NoError(t, rv.OutErr) - require.Len(t, rv.OutReasons, 0) - require.False(t, rv.OutExpirationTime.IsZero()) - require.WithinDuration(t, now.Add(twentyFourHours), rv.OutExpirationTime, time.Second*60) -} - -func TestNonCachablePOST(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - obj.ReqMethod = "POST" - - rv := ObjectResults{} - CachableObject(&obj, &rv) - require.NoError(t, rv.OutErr) - require.Len(t, rv.OutReasons, 1) - require.Contains(t, rv.OutReasons, ReasonRequestMethodPOST) -} - -func TestCachablePOSTExpiresHeader(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - obj.ReqMethod = "POST" - obj.RespExpiresHeader = now.Add(time.Hour * 1) - - rv := ObjectResults{} - CachableObject(&obj, &rv) - require.NoError(t, rv.OutErr) - require.Len(t, rv.OutReasons, 0) -} - -func TestCachablePOSTSMax(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - obj.ReqMethod = "POST" - obj.RespDirectives.SMaxAge = DeltaSeconds(900) - - rv := ObjectResults{} - CachableObject(&obj, &rv) - require.NoError(t, rv.OutErr) - require.Len(t, rv.OutReasons, 0) -} - -func TestNonCachablePOSTSMax(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - obj.ReqMethod = "POST" - obj.CacheIsPrivate = true - obj.RespDirectives.SMaxAge = DeltaSeconds(900) - - rv := ObjectResults{} - CachableObject(&obj, &rv) - require.NoError(t, rv.OutErr) - require.Len(t, rv.OutReasons, 1) - require.Contains(t, rv.OutReasons, ReasonRequestMethodPOST) -} - -func TestCachablePOSTMax(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - obj.ReqMethod = "POST" - obj.RespDirectives.MaxAge = DeltaSeconds(9000) - - rv := ObjectResults{} - CachableObject(&obj, &rv) - require.NoError(t, rv.OutErr) - require.Len(t, rv.OutReasons, 0) -} - -func TestPUTs(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - obj.ReqMethod = "PUT" - - rv := ObjectResults{} - CachableObject(&obj, &rv) - require.NoError(t, rv.OutErr) - require.Len(t, rv.OutReasons, 1) - require.Contains(t, rv.OutReasons, ReasonRequestMethodPUT) -} - -func TestPUTWithExpires(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - obj.ReqMethod = "PUT" - obj.RespExpiresHeader = now.Add(time.Hour * 1) - - rv := ObjectResults{} - CachableObject(&obj, &rv) - require.NoError(t, rv.OutErr) - require.Len(t, rv.OutReasons, 1) - require.Contains(t, rv.OutReasons, ReasonRequestMethodPUT) -} - -func TestAuthorization(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - obj.ReqHeaders.Set("Authorization", "bearer random") - - rv := ObjectResults{} - CachableObject(&obj, &rv) - require.NoError(t, rv.OutErr) - require.Len(t, rv.OutReasons, 1) - require.Contains(t, rv.OutReasons, ReasonRequestAuthorizationHeader) -} - -func TestCachableAuthorization(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - obj.ReqHeaders.Set("Authorization", "bearer random") - obj.RespDirectives.Public = true - obj.RespDirectives.MaxAge = DeltaSeconds(300) - - rv := ObjectResults{} - CachableObject(&obj, &rv) - require.NoError(t, rv.OutErr) - require.Len(t, rv.OutReasons, 0) -} - -func TestRespNoStore(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - obj.RespDirectives.NoStore = true - - rv := ObjectResults{} - CachableObject(&obj, &rv) - require.Len(t, rv.OutReasons, 1) - require.Contains(t, rv.OutReasons, ReasonResponseNoStore) -} - -func TestReqNoStore(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - obj.ReqDirectives.NoStore = true - - rv := ObjectResults{} - CachableObject(&obj, &rv) - require.Len(t, rv.OutReasons, 1) - require.Contains(t, rv.OutReasons, ReasonRequestNoStore) -} - -func TestResp500(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - obj.RespStatusCode = 500 - - rv := ObjectResults{} - CachableObject(&obj, &rv) - require.Len(t, rv.OutReasons, 1) - require.Contains(t, rv.OutReasons, ReasonResponseUncachableByDefault) -} - -func TestExpirationSMaxShared(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - obj.RespDirectives.SMaxAge = DeltaSeconds(60) - - rv := ObjectResults{} - ExpirationObject(&obj, &rv) - require.Len(t, rv.OutWarnings, 0) - require.WithinDuration(t, now.Add(time.Second*60), rv.OutExpirationTime, time.Second*1) -} - -func TestExpirationSMaxPrivate(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - obj.CacheIsPrivate = true - obj.RespDirectives.SMaxAge = DeltaSeconds(60) - - rv := ObjectResults{} - ExpirationObject(&obj, &rv) - require.Len(t, rv.OutWarnings, 0) - require.True(t, rv.OutExpirationTime.IsZero()) -} - -func TestExpirationMax(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - obj.RespDirectives.MaxAge = DeltaSeconds(60) - - rv := ObjectResults{} - ExpirationObject(&obj, &rv) - require.Len(t, rv.OutWarnings, 0) - require.WithinDuration(t, now.Add(time.Second*60), rv.OutExpirationTime, time.Second*1) -} - -func TestExpirationMaxAndSMax(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - // cache should select the SMax age since this is a shared cache. - obj.RespDirectives.MaxAge = DeltaSeconds(60) - obj.RespDirectives.SMaxAge = DeltaSeconds(900) - - rv := ObjectResults{} - ExpirationObject(&obj, &rv) - require.Len(t, rv.OutWarnings, 0) - require.WithinDuration(t, now.Add(time.Second*900), rv.OutExpirationTime, time.Second*1) -} - -func TestExpirationExpires(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - // cache should select the SMax age since this is a shared cache. - obj.RespExpiresHeader = now.Add(time.Second * 1500) - - rv := ObjectResults{} - ExpirationObject(&obj, &rv) - require.Len(t, rv.OutWarnings, 0) - require.WithinDuration(t, now.Add(time.Second*1500), rv.OutExpirationTime, time.Second*1) -} - -func TestExpirationExpiresNoServerDate(t *testing.T) { - now := time.Now().UTC() - - obj := fill(t, now) - // cache should select the SMax age since this is a shared cache. - obj.RespDateHeader = time.Time{} - obj.RespExpiresHeader = now.Add(time.Second * 1500) - - rv := ObjectResults{} - ExpirationObject(&obj, &rv) - require.Len(t, rv.OutWarnings, 0) - require.WithinDuration(t, now.Add(time.Second*1500), rv.OutExpirationTime, time.Second*1) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/benchmark_test.go b/vendor/github.com/prometheus/client_golang/prometheus/benchmark_test.go deleted file mode 100644 index 4a05721dc..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/benchmark_test.go +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "sync" - "testing" -) - -func BenchmarkCounterWithLabelValues(b *testing.B) { - m := NewCounterVec( - CounterOpts{ - Name: "benchmark_counter", - Help: "A counter to benchmark it.", - }, - []string{"one", "two", "three"}, - ) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.WithLabelValues("eins", "zwei", "drei").Inc() - } -} - -func BenchmarkCounterWithLabelValuesConcurrent(b *testing.B) { - m := NewCounterVec( - CounterOpts{ - Name: "benchmark_counter", - Help: "A counter to benchmark it.", - }, - []string{"one", "two", "three"}, - ) - b.ReportAllocs() - b.ResetTimer() - wg := sync.WaitGroup{} - for i := 0; i < 10; i++ { - wg.Add(1) - go func() { - for j := 0; j < b.N/10; j++ { - m.WithLabelValues("eins", "zwei", "drei").Inc() - } - wg.Done() - }() - } - wg.Wait() -} - -func BenchmarkCounterWithMappedLabels(b *testing.B) { - m := NewCounterVec( - CounterOpts{ - Name: "benchmark_counter", - Help: "A counter to benchmark it.", - }, - []string{"one", "two", "three"}, - ) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.With(Labels{"two": "zwei", "one": "eins", "three": "drei"}).Inc() - } -} - -func BenchmarkCounterWithPreparedMappedLabels(b *testing.B) { - m := NewCounterVec( - CounterOpts{ - Name: "benchmark_counter", - Help: "A counter to benchmark it.", - }, - []string{"one", "two", "three"}, - ) - b.ReportAllocs() - b.ResetTimer() - labels := Labels{"two": "zwei", "one": "eins", "three": "drei"} - for i := 0; i < b.N; i++ { - m.With(labels).Inc() - } -} - -func BenchmarkCounterNoLabels(b *testing.B) { - m := NewCounter(CounterOpts{ - Name: "benchmark_counter", - Help: "A counter to benchmark it.", - }) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.Inc() - } -} - -func BenchmarkGaugeWithLabelValues(b *testing.B) { - m := NewGaugeVec( - GaugeOpts{ - Name: "benchmark_gauge", - Help: "A gauge to benchmark it.", - }, - []string{"one", "two", "three"}, - ) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.WithLabelValues("eins", "zwei", "drei").Set(3.1415) - } -} - -func BenchmarkGaugeNoLabels(b *testing.B) { - m := NewGauge(GaugeOpts{ - Name: "benchmark_gauge", - Help: "A gauge to benchmark it.", - }) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.Set(3.1415) - } -} - -func BenchmarkSummaryWithLabelValues(b *testing.B) { - m := NewSummaryVec( - SummaryOpts{ - Name: "benchmark_summary", - Help: "A summary to benchmark it.", - Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, - }, - []string{"one", "two", "three"}, - ) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.WithLabelValues("eins", "zwei", "drei").Observe(3.1415) - } -} - -func BenchmarkSummaryNoLabels(b *testing.B) { - m := NewSummary(SummaryOpts{ - Name: "benchmark_summary", - Help: "A summary to benchmark it.", - Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, - }, - ) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.Observe(3.1415) - } -} - -func BenchmarkHistogramWithLabelValues(b *testing.B) { - m := NewHistogramVec( - HistogramOpts{ - Name: "benchmark_histogram", - Help: "A histogram to benchmark it.", - }, - []string{"one", "two", "three"}, - ) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.WithLabelValues("eins", "zwei", "drei").Observe(3.1415) - } -} - -func BenchmarkHistogramNoLabels(b *testing.B) { - m := NewHistogram(HistogramOpts{ - Name: "benchmark_histogram", - Help: "A histogram to benchmark it.", - }, - ) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.Observe(3.1415) - } -} - -func BenchmarkParallelCounter(b *testing.B) { - c := NewCounter(CounterOpts{ - Name: "benchmark_counter", - Help: "A Counter to benchmark it.", - }) - b.ReportAllocs() - b.ResetTimer() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - c.Inc() - } - }) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/collector_test.go b/vendor/github.com/prometheus/client_golang/prometheus/collector_test.go deleted file mode 100644 index 45eab3ea4..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/collector_test.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import "testing" - -type collectorDescribedByCollect struct { - cnt Counter - gge Gauge -} - -func (c collectorDescribedByCollect) Collect(ch chan<- Metric) { - ch <- c.cnt - ch <- c.gge -} - -func (c collectorDescribedByCollect) Describe(ch chan<- *Desc) { - DescribeByCollect(c, ch) -} - -func TestDescribeByCollect(t *testing.T) { - - goodCollector := collectorDescribedByCollect{ - cnt: NewCounter(CounterOpts{Name: "c1", Help: "help c1"}), - gge: NewGauge(GaugeOpts{Name: "g1", Help: "help g1"}), - } - collidingCollector := collectorDescribedByCollect{ - cnt: NewCounter(CounterOpts{Name: "c2", Help: "help c2"}), - gge: NewGauge(GaugeOpts{Name: "g1", Help: "help g1"}), - } - inconsistentCollector := collectorDescribedByCollect{ - cnt: NewCounter(CounterOpts{Name: "c3", Help: "help c3"}), - gge: NewGauge(GaugeOpts{Name: "c3", Help: "help inconsistent"}), - } - - reg := NewPedanticRegistry() - - if err := reg.Register(goodCollector); err != nil { - t.Error("registration failed:", err) - } - if err := reg.Register(collidingCollector); err == nil { - t.Error("registration unexpectedly succeeded") - } - if err := reg.Register(inconsistentCollector); err == nil { - t.Error("registration unexpectedly succeeded") - } - - if _, err := reg.Gather(); err != nil { - t.Error("gathering failed:", err) - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/counter.go b/vendor/github.com/prometheus/client_golang/prometheus/counter.go index 765e4550c..d463e36d3 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/counter.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/counter.go @@ -136,7 +136,7 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec { return &CounterVec{ metricVec: newMetricVec(desc, func(lvs ...string) Metric { if len(lvs) != len(desc.variableLabels) { - panic(errInconsistentCardinality) + panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs)) } result := &counter{desc: desc, labelPairs: makeLabelPairs(desc, lvs)} result.init(result) // Init self-collection. diff --git a/vendor/github.com/prometheus/client_golang/prometheus/counter_test.go b/vendor/github.com/prometheus/client_golang/prometheus/counter_test.go deleted file mode 100644 index 5062f51af..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/counter_test.go +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "fmt" - "math" - "testing" - - dto "github.com/prometheus/client_model/go" -) - -func TestCounterAdd(t *testing.T) { - counter := NewCounter(CounterOpts{ - Name: "test", - Help: "test help", - ConstLabels: Labels{"a": "1", "b": "2"}, - }).(*counter) - counter.Inc() - if expected, got := 0.0, math.Float64frombits(counter.valBits); expected != got { - t.Errorf("Expected %f, got %f.", expected, got) - } - if expected, got := uint64(1), counter.valInt; expected != got { - t.Errorf("Expected %d, got %d.", expected, got) - } - counter.Add(42) - if expected, got := 0.0, math.Float64frombits(counter.valBits); expected != got { - t.Errorf("Expected %f, got %f.", expected, got) - } - if expected, got := uint64(43), counter.valInt; expected != got { - t.Errorf("Expected %d, got %d.", expected, got) - } - - counter.Add(24.42) - if expected, got := 24.42, math.Float64frombits(counter.valBits); expected != got { - t.Errorf("Expected %f, got %f.", expected, got) - } - if expected, got := uint64(43), counter.valInt; expected != got { - t.Errorf("Expected %d, got %d.", expected, got) - } - - if expected, got := "counter cannot decrease in value", decreaseCounter(counter).Error(); expected != got { - t.Errorf("Expected error %q, got %q.", expected, got) - } - - m := &dto.Metric{} - counter.Write(m) - - if expected, got := `label: label: counter: `, m.String(); expected != got { - t.Errorf("expected %q, got %q", expected, got) - } -} - -func decreaseCounter(c *counter) (err error) { - defer func() { - if e := recover(); e != nil { - err = e.(error) - } - }() - c.Add(-1) - return nil -} - -func TestCounterVecGetMetricWithInvalidLabelValues(t *testing.T) { - testCases := []struct { - desc string - labels Labels - }{ - { - desc: "non utf8 label value", - labels: Labels{"a": "\xFF"}, - }, - { - desc: "not enough label values", - labels: Labels{}, - }, - { - desc: "too many label values", - labels: Labels{"a": "1", "b": "2"}, - }, - } - - for _, test := range testCases { - counterVec := NewCounterVec(CounterOpts{ - Name: "test", - }, []string{"a"}) - - labelValues := make([]string, len(test.labels)) - for _, val := range test.labels { - labelValues = append(labelValues, val) - } - - expectPanic(t, func() { - counterVec.WithLabelValues(labelValues...) - }, fmt.Sprintf("WithLabelValues: expected panic because: %s", test.desc)) - expectPanic(t, func() { - counterVec.With(test.labels) - }, fmt.Sprintf("WithLabelValues: expected panic because: %s", test.desc)) - - if _, err := counterVec.GetMetricWithLabelValues(labelValues...); err == nil { - t.Errorf("GetMetricWithLabelValues: expected error because: %s", test.desc) - } - if _, err := counterVec.GetMetricWith(test.labels); err == nil { - t.Errorf("GetMetricWith: expected error because: %s", test.desc) - } - } -} - -func expectPanic(t *testing.T, op func(), errorMsg string) { - defer func() { - if err := recover(); err == nil { - t.Error(errorMsg) - } - }() - - op() -} - -func TestCounterAddInf(t *testing.T) { - counter := NewCounter(CounterOpts{ - Name: "test", - Help: "test help", - }).(*counter) - - counter.Inc() - if expected, got := 0.0, math.Float64frombits(counter.valBits); expected != got { - t.Errorf("Expected %f, got %f.", expected, got) - } - if expected, got := uint64(1), counter.valInt; expected != got { - t.Errorf("Expected %d, got %d.", expected, got) - } - - counter.Add(math.Inf(1)) - if expected, got := math.Inf(1), math.Float64frombits(counter.valBits); expected != got { - t.Errorf("valBits expected %f, got %f.", expected, got) - } - if expected, got := uint64(1), counter.valInt; expected != got { - t.Errorf("valInts expected %d, got %d.", expected, got) - } - - counter.Inc() - if expected, got := math.Inf(1), math.Float64frombits(counter.valBits); expected != got { - t.Errorf("Expected %f, got %f.", expected, got) - } - if expected, got := uint64(2), counter.valInt; expected != got { - t.Errorf("Expected %d, got %d.", expected, got) - } - - m := &dto.Metric{} - counter.Write(m) - - if expected, got := `counter: `, m.String(); expected != got { - t.Errorf("expected %q, got %q", expected, got) - } -} - -func TestCounterAddLarge(t *testing.T) { - counter := NewCounter(CounterOpts{ - Name: "test", - Help: "test help", - }).(*counter) - - // large overflows the underlying type and should therefore be stored in valBits. - large := float64(math.MaxUint64 + 1) - counter.Add(large) - if expected, got := large, math.Float64frombits(counter.valBits); expected != got { - t.Errorf("valBits expected %f, got %f.", expected, got) - } - if expected, got := uint64(0), counter.valInt; expected != got { - t.Errorf("valInts expected %d, got %d.", expected, got) - } - - m := &dto.Metric{} - counter.Write(m) - - if expected, got := fmt.Sprintf("counter: ", large), m.String(); expected != got { - t.Errorf("expected %q, got %q", expected, got) - } -} - -func TestCounterAddSmall(t *testing.T) { - counter := NewCounter(CounterOpts{ - Name: "test", - Help: "test help", - }).(*counter) - small := 0.000000000001 - counter.Add(small) - if expected, got := small, math.Float64frombits(counter.valBits); expected != got { - t.Errorf("valBits expected %f, got %f.", expected, got) - } - if expected, got := uint64(0), counter.valInt; expected != got { - t.Errorf("valInts expected %d, got %d.", expected, got) - } - - m := &dto.Metric{} - counter.Write(m) - - if expected, got := fmt.Sprintf("counter: ", small), m.String(); expected != got { - t.Errorf("expected %q, got %q", expected, got) - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/desc_test.go b/vendor/github.com/prometheus/client_golang/prometheus/desc_test.go deleted file mode 100644 index 5f854db0b..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/desc_test.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "testing" -) - -func TestNewDescInvalidLabelValues(t *testing.T) { - desc := NewDesc( - "sample_label", - "sample label", - nil, - Labels{"a": "\xFF"}, - ) - if desc.err == nil { - t.Errorf("NewDesc: expected error because: %s", desc.err) - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/example_clustermanager_test.go b/vendor/github.com/prometheus/client_golang/prometheus/example_clustermanager_test.go deleted file mode 100644 index 9a5a4b8a2..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/example_clustermanager_test.go +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus_test - -import "github.com/prometheus/client_golang/prometheus" - -// ClusterManager is an example for a system that might have been built without -// Prometheus in mind. It models a central manager of jobs running in a -// cluster. Thus, we implement a custom Collector called -// ClusterManagerCollector, which collects information from a ClusterManager -// using its provided methods and turns them into Prometheus Metrics for -// collection. -// -// An additional challenge is that multiple instances of the ClusterManager are -// run within the same binary, each in charge of a different zone. We need to -// make use of wrapping Registerers to be able to register each -// ClusterManagerCollector instance with Prometheus. -type ClusterManager struct { - Zone string - // Contains many more fields not listed in this example. -} - -// ReallyExpensiveAssessmentOfTheSystemState is a mock for the data gathering a -// real cluster manager would have to do. Since it may actually be really -// expensive, it must only be called once per collection. This implementation, -// obviously, only returns some made-up data. -func (c *ClusterManager) ReallyExpensiveAssessmentOfTheSystemState() ( - oomCountByHost map[string]int, ramUsageByHost map[string]float64, -) { - // Just example fake data. - oomCountByHost = map[string]int{ - "foo.example.org": 42, - "bar.example.org": 2001, - } - ramUsageByHost = map[string]float64{ - "foo.example.org": 6.023e23, - "bar.example.org": 3.14, - } - return -} - -// ClusterManagerCollector implements the Collector interface. -type ClusterManagerCollector struct { - ClusterManager *ClusterManager -} - -// Descriptors used by the ClusterManagerCollector below. -var ( - oomCountDesc = prometheus.NewDesc( - "clustermanager_oom_crashes_total", - "Number of OOM crashes.", - []string{"host"}, nil, - ) - ramUsageDesc = prometheus.NewDesc( - "clustermanager_ram_usage_bytes", - "RAM usage as reported to the cluster manager.", - []string{"host"}, nil, - ) -) - -// Describe is implemented with DescribeByCollect. That's possible because the -// Collect method will always return the same two metrics with the same two -// descriptors. -func (cc ClusterManagerCollector) Describe(ch chan<- *prometheus.Desc) { - prometheus.DescribeByCollect(cc, ch) -} - -// Collect first triggers the ReallyExpensiveAssessmentOfTheSystemState. Then it -// creates constant metrics for each host on the fly based on the returned data. -// -// Note that Collect could be called concurrently, so we depend on -// ReallyExpensiveAssessmentOfTheSystemState to be concurrency-safe. -func (cc ClusterManagerCollector) Collect(ch chan<- prometheus.Metric) { - oomCountByHost, ramUsageByHost := cc.ClusterManager.ReallyExpensiveAssessmentOfTheSystemState() - for host, oomCount := range oomCountByHost { - ch <- prometheus.MustNewConstMetric( - oomCountDesc, - prometheus.CounterValue, - float64(oomCount), - host, - ) - } - for host, ramUsage := range ramUsageByHost { - ch <- prometheus.MustNewConstMetric( - ramUsageDesc, - prometheus.GaugeValue, - ramUsage, - host, - ) - } -} - -// NewClusterManager first creates a Prometheus-ignorant ClusterManager -// instance. Then, it creates a ClusterManagerCollector for the just created -// ClusterManager. Finally, it registers the ClusterManagerCollector with a -// wrapping Registerer that adds the zone as a label. In this way, the metrics -// collected by different ClusterManagerCollectors do not collide. -func NewClusterManager(zone string, reg prometheus.Registerer) *ClusterManager { - c := &ClusterManager{ - Zone: zone, - } - cc := ClusterManagerCollector{ClusterManager: c} - prometheus.WrapRegistererWith(prometheus.Labels{"zone": zone}, reg).MustRegister(cc) - return c -} - -func ExampleCollector() { - // Since we are dealing with custom Collector implementations, it might - // be a good idea to try it out with a pedantic registry. - reg := prometheus.NewPedanticRegistry() - - // Construct cluster managers. In real code, we would assign them to - // variables to then do something with them. - NewClusterManager("db", reg) - NewClusterManager("ca", reg) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/example_timer_complex_test.go b/vendor/github.com/prometheus/client_golang/prometheus/example_timer_complex_test.go deleted file mode 100644 index c5e7de5e5..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/example_timer_complex_test.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus_test - -import ( - "net/http" - - "github.com/prometheus/client_golang/prometheus" -) - -var ( - // apiRequestDuration tracks the duration separate for each HTTP status - // class (1xx, 2xx, ...). This creates a fair amount of time series on - // the Prometheus server. Usually, you would track the duration of - // serving HTTP request without partitioning by outcome. Do something - // like this only if needed. Also note how only status classes are - // tracked, not every single status code. The latter would create an - // even larger amount of time series. Request counters partitioned by - // status code are usually OK as each counter only creates one time - // series. Histograms are way more expensive, so partition with care and - // only where you really need separate latency tracking. Partitioning by - // status class is only an example. In concrete cases, other partitions - // might make more sense. - apiRequestDuration = prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "api_request_duration_seconds", - Help: "Histogram for the request duration of the public API, partitioned by status class.", - Buckets: prometheus.ExponentialBuckets(0.1, 1.5, 5), - }, - []string{"status_class"}, - ) -) - -func handler(w http.ResponseWriter, r *http.Request) { - status := http.StatusOK - // The ObserverFunc gets called by the deferred ObserveDuration and - // decides which Histogram's Observe method is called. - timer := prometheus.NewTimer(prometheus.ObserverFunc(func(v float64) { - switch { - case status >= 500: // Server error. - apiRequestDuration.WithLabelValues("5xx").Observe(v) - case status >= 400: // Client error. - apiRequestDuration.WithLabelValues("4xx").Observe(v) - case status >= 300: // Redirection. - apiRequestDuration.WithLabelValues("3xx").Observe(v) - case status >= 200: // Success. - apiRequestDuration.WithLabelValues("2xx").Observe(v) - default: // Informational. - apiRequestDuration.WithLabelValues("1xx").Observe(v) - } - })) - defer timer.ObserveDuration() - - // Handle the request. Set status accordingly. - // ... -} - -func ExampleTimer_complex() { - http.HandleFunc("/api", handler) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/example_timer_gauge_test.go b/vendor/github.com/prometheus/client_golang/prometheus/example_timer_gauge_test.go deleted file mode 100644 index 7184a0d1d..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/example_timer_gauge_test.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus_test - -import ( - "os" - - "github.com/prometheus/client_golang/prometheus" -) - -var ( - // If a function is called rarely (i.e. not more often than scrapes - // happen) or ideally only once (like in a batch job), it can make sense - // to use a Gauge for timing the function call. For timing a batch job - // and pushing the result to a Pushgateway, see also the comprehensive - // example in the push package. - funcDuration = prometheus.NewGauge(prometheus.GaugeOpts{ - Name: "example_function_duration_seconds", - Help: "Duration of the last call of an example function.", - }) -) - -func run() error { - // The Set method of the Gauge is used to observe the duration. - timer := prometheus.NewTimer(prometheus.ObserverFunc(funcDuration.Set)) - defer timer.ObserveDuration() - - // Do something. Return errors as encountered. The use of 'defer' above - // makes sure the function is still timed properly. - return nil -} - -func ExampleTimer_gauge() { - if err := run(); err != nil { - os.Exit(1) - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/example_timer_test.go b/vendor/github.com/prometheus/client_golang/prometheus/example_timer_test.go deleted file mode 100644 index bd86bb472..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/example_timer_test.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus_test - -import ( - "math/rand" - "time" - - "github.com/prometheus/client_golang/prometheus" -) - -var ( - requestDuration = prometheus.NewHistogram(prometheus.HistogramOpts{ - Name: "example_request_duration_seconds", - Help: "Histogram for the runtime of a simple example function.", - Buckets: prometheus.LinearBuckets(0.01, 0.01, 10), - }) -) - -func ExampleTimer() { - // timer times this example function. It uses a Histogram, but a Summary - // would also work, as both implement Observer. Check out - // https://prometheus.io/docs/practices/histograms/ for differences. - timer := prometheus.NewTimer(requestDuration) - defer timer.ObserveDuration() - - // Do something here that takes time. - time.Sleep(time.Duration(rand.NormFloat64()*10000+50000) * time.Microsecond) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/examples_test.go b/vendor/github.com/prometheus/client_golang/prometheus/examples_test.go deleted file mode 100644 index 538a23999..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/examples_test.go +++ /dev/null @@ -1,742 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus_test - -import ( - "bytes" - "fmt" - "math" - "net/http" - "runtime" - "strings" - "time" - - "github.com/golang/protobuf/proto" - "github.com/prometheus/common/expfmt" - - dto "github.com/prometheus/client_model/go" - - "github.com/prometheus/client_golang/prometheus" -) - -func ExampleGauge() { - opsQueued := prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "our_company", - Subsystem: "blob_storage", - Name: "ops_queued", - Help: "Number of blob storage operations waiting to be processed.", - }) - prometheus.MustRegister(opsQueued) - - // 10 operations queued by the goroutine managing incoming requests. - opsQueued.Add(10) - // A worker goroutine has picked up a waiting operation. - opsQueued.Dec() - // And once more... - opsQueued.Dec() -} - -func ExampleGaugeVec() { - opsQueued := prometheus.NewGaugeVec( - prometheus.GaugeOpts{ - Namespace: "our_company", - Subsystem: "blob_storage", - Name: "ops_queued", - Help: "Number of blob storage operations waiting to be processed, partitioned by user and type.", - }, - []string{ - // Which user has requested the operation? - "user", - // Of what type is the operation? - "type", - }, - ) - prometheus.MustRegister(opsQueued) - - // Increase a value using compact (but order-sensitive!) WithLabelValues(). - opsQueued.WithLabelValues("bob", "put").Add(4) - // Increase a value with a map using WithLabels. More verbose, but order - // doesn't matter anymore. - opsQueued.With(prometheus.Labels{"type": "delete", "user": "alice"}).Inc() -} - -func ExampleGaugeFunc() { - if err := prometheus.Register(prometheus.NewGaugeFunc( - prometheus.GaugeOpts{ - Subsystem: "runtime", - Name: "goroutines_count", - Help: "Number of goroutines that currently exist.", - }, - func() float64 { return float64(runtime.NumGoroutine()) }, - )); err == nil { - fmt.Println("GaugeFunc 'goroutines_count' registered.") - } - // Note that the count of goroutines is a gauge (and not a counter) as - // it can go up and down. - - // Output: - // GaugeFunc 'goroutines_count' registered. -} - -func ExampleCounterVec() { - httpReqs := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "http_requests_total", - Help: "How many HTTP requests processed, partitioned by status code and HTTP method.", - }, - []string{"code", "method"}, - ) - prometheus.MustRegister(httpReqs) - - httpReqs.WithLabelValues("404", "POST").Add(42) - - // If you have to access the same set of labels very frequently, it - // might be good to retrieve the metric only once and keep a handle to - // it. But beware of deletion of that metric, see below! - m := httpReqs.WithLabelValues("200", "GET") - for i := 0; i < 1000000; i++ { - m.Inc() - } - // Delete a metric from the vector. If you have previously kept a handle - // to that metric (as above), future updates via that handle will go - // unseen (even if you re-create a metric with the same label set - // later). - httpReqs.DeleteLabelValues("200", "GET") - // Same thing with the more verbose Labels syntax. - httpReqs.Delete(prometheus.Labels{"method": "GET", "code": "200"}) -} - -func ExampleInstrumentHandler() { - // Handle the "/doc" endpoint with the standard http.FileServer handler. - // By wrapping the handler with InstrumentHandler, request count, - // request and response sizes, and request latency are automatically - // exported to Prometheus, partitioned by HTTP status code and method - // and by the handler name (here "fileserver"). - http.Handle("/doc", prometheus.InstrumentHandler( - "fileserver", http.FileServer(http.Dir("/usr/share/doc")), - )) - // The Prometheus handler still has to be registered to handle the - // "/metrics" endpoint. The handler returned by prometheus.Handler() is - // already instrumented - with "prometheus" as the handler name. In this - // example, we want the handler name to be "metrics", so we instrument - // the uninstrumented Prometheus handler ourselves. - http.Handle("/metrics", prometheus.InstrumentHandler( - "metrics", prometheus.UninstrumentedHandler(), - )) -} - -func ExampleRegister() { - // Imagine you have a worker pool and want to count the tasks completed. - taskCounter := prometheus.NewCounter(prometheus.CounterOpts{ - Subsystem: "worker_pool", - Name: "completed_tasks_total", - Help: "Total number of tasks completed.", - }) - // This will register fine. - if err := prometheus.Register(taskCounter); err != nil { - fmt.Println(err) - } else { - fmt.Println("taskCounter registered.") - } - // Don't forget to tell the HTTP server about the Prometheus handler. - // (In a real program, you still need to start the HTTP server...) - http.Handle("/metrics", prometheus.Handler()) - - // Now you can start workers and give every one of them a pointer to - // taskCounter and let it increment it whenever it completes a task. - taskCounter.Inc() // This has to happen somewhere in the worker code. - - // But wait, you want to see how individual workers perform. So you need - // a vector of counters, with one element for each worker. - taskCounterVec := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Subsystem: "worker_pool", - Name: "completed_tasks_total", - Help: "Total number of tasks completed.", - }, - []string{"worker_id"}, - ) - - // Registering will fail because we already have a metric of that name. - if err := prometheus.Register(taskCounterVec); err != nil { - fmt.Println("taskCounterVec not registered:", err) - } else { - fmt.Println("taskCounterVec registered.") - } - - // To fix, first unregister the old taskCounter. - if prometheus.Unregister(taskCounter) { - fmt.Println("taskCounter unregistered.") - } - - // Try registering taskCounterVec again. - if err := prometheus.Register(taskCounterVec); err != nil { - fmt.Println("taskCounterVec not registered:", err) - } else { - fmt.Println("taskCounterVec registered.") - } - // Bummer! Still doesn't work. - - // Prometheus will not allow you to ever export metrics with - // inconsistent help strings or label names. After unregistering, the - // unregistered metrics will cease to show up in the /metrics HTTP - // response, but the registry still remembers that those metrics had - // been exported before. For this example, we will now choose a - // different name. (In a real program, you would obviously not export - // the obsolete metric in the first place.) - taskCounterVec = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Subsystem: "worker_pool", - Name: "completed_tasks_by_id", - Help: "Total number of tasks completed.", - }, - []string{"worker_id"}, - ) - if err := prometheus.Register(taskCounterVec); err != nil { - fmt.Println("taskCounterVec not registered:", err) - } else { - fmt.Println("taskCounterVec registered.") - } - // Finally it worked! - - // The workers have to tell taskCounterVec their id to increment the - // right element in the metric vector. - taskCounterVec.WithLabelValues("42").Inc() // Code from worker 42. - - // Each worker could also keep a reference to their own counter element - // around. Pick the counter at initialization time of the worker. - myCounter := taskCounterVec.WithLabelValues("42") // From worker 42 initialization code. - myCounter.Inc() // Somewhere in the code of that worker. - - // Note that something like WithLabelValues("42", "spurious arg") would - // panic (because you have provided too many label values). If you want - // to get an error instead, use GetMetricWithLabelValues(...) instead. - notMyCounter, err := taskCounterVec.GetMetricWithLabelValues("42", "spurious arg") - if err != nil { - fmt.Println("Worker initialization failed:", err) - } - if notMyCounter == nil { - fmt.Println("notMyCounter is nil.") - } - - // A different (and somewhat tricky) approach is to use - // ConstLabels. ConstLabels are pairs of label names and label values - // that never change. You might ask what those labels are good for (and - // rightfully so - if they never change, they could as well be part of - // the metric name). There are essentially two use-cases: The first is - // if labels are constant throughout the lifetime of a binary execution, - // but they vary over time or between different instances of a running - // binary. The second is what we have here: Each worker creates and - // registers an own Counter instance where the only difference is in the - // value of the ConstLabels. Those Counters can all be registered - // because the different ConstLabel values guarantee that each worker - // will increment a different Counter metric. - counterOpts := prometheus.CounterOpts{ - Subsystem: "worker_pool", - Name: "completed_tasks", - Help: "Total number of tasks completed.", - ConstLabels: prometheus.Labels{"worker_id": "42"}, - } - taskCounterForWorker42 := prometheus.NewCounter(counterOpts) - if err := prometheus.Register(taskCounterForWorker42); err != nil { - fmt.Println("taskCounterVForWorker42 not registered:", err) - } else { - fmt.Println("taskCounterForWorker42 registered.") - } - // Obviously, in real code, taskCounterForWorker42 would be a member - // variable of a worker struct, and the "42" would be retrieved with a - // GetId() method or something. The Counter would be created and - // registered in the initialization code of the worker. - - // For the creation of the next Counter, we can recycle - // counterOpts. Just change the ConstLabels. - counterOpts.ConstLabels = prometheus.Labels{"worker_id": "2001"} - taskCounterForWorker2001 := prometheus.NewCounter(counterOpts) - if err := prometheus.Register(taskCounterForWorker2001); err != nil { - fmt.Println("taskCounterVForWorker2001 not registered:", err) - } else { - fmt.Println("taskCounterForWorker2001 registered.") - } - - taskCounterForWorker2001.Inc() - taskCounterForWorker42.Inc() - taskCounterForWorker2001.Inc() - - // Yet another approach would be to turn the workers themselves into - // Collectors and register them. See the Collector example for details. - - // Output: - // taskCounter registered. - // taskCounterVec not registered: a previously registered descriptor with the same fully-qualified name as Desc{fqName: "worker_pool_completed_tasks_total", help: "Total number of tasks completed.", constLabels: {}, variableLabels: [worker_id]} has different label names or a different help string - // taskCounter unregistered. - // taskCounterVec not registered: a previously registered descriptor with the same fully-qualified name as Desc{fqName: "worker_pool_completed_tasks_total", help: "Total number of tasks completed.", constLabels: {}, variableLabels: [worker_id]} has different label names or a different help string - // taskCounterVec registered. - // Worker initialization failed: inconsistent label cardinality - // notMyCounter is nil. - // taskCounterForWorker42 registered. - // taskCounterForWorker2001 registered. -} - -func ExampleSummary() { - temps := prometheus.NewSummary(prometheus.SummaryOpts{ - Name: "pond_temperature_celsius", - Help: "The temperature of the frog pond.", - Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, - }) - - // Simulate some observations. - for i := 0; i < 1000; i++ { - temps.Observe(30 + math.Floor(120*math.Sin(float64(i)*0.1))/10) - } - - // Just for demonstration, let's check the state of the summary by - // (ab)using its Write method (which is usually only used by Prometheus - // internally). - metric := &dto.Metric{} - temps.Write(metric) - fmt.Println(proto.MarshalTextString(metric)) - - // Output: - // summary: < - // sample_count: 1000 - // sample_sum: 29969.50000000001 - // quantile: < - // quantile: 0.5 - // value: 31.1 - // > - // quantile: < - // quantile: 0.9 - // value: 41.3 - // > - // quantile: < - // quantile: 0.99 - // value: 41.9 - // > - // > -} - -func ExampleSummaryVec() { - temps := prometheus.NewSummaryVec( - prometheus.SummaryOpts{ - Name: "pond_temperature_celsius", - Help: "The temperature of the frog pond.", - Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, - }, - []string{"species"}, - ) - - // Simulate some observations. - for i := 0; i < 1000; i++ { - temps.WithLabelValues("litoria-caerulea").Observe(30 + math.Floor(120*math.Sin(float64(i)*0.1))/10) - temps.WithLabelValues("lithobates-catesbeianus").Observe(32 + math.Floor(100*math.Cos(float64(i)*0.11))/10) - } - - // Create a Summary without any observations. - temps.WithLabelValues("leiopelma-hochstetteri") - - // Just for demonstration, let's check the state of the summary vector - // by registering it with a custom registry and then let it collect the - // metrics. - reg := prometheus.NewRegistry() - reg.MustRegister(temps) - - metricFamilies, err := reg.Gather() - if err != nil || len(metricFamilies) != 1 { - panic("unexpected behavior of custom test registry") - } - fmt.Println(proto.MarshalTextString(metricFamilies[0])) - - // Output: - // name: "pond_temperature_celsius" - // help: "The temperature of the frog pond." - // type: SUMMARY - // metric: < - // label: < - // name: "species" - // value: "leiopelma-hochstetteri" - // > - // summary: < - // sample_count: 0 - // sample_sum: 0 - // quantile: < - // quantile: 0.5 - // value: nan - // > - // quantile: < - // quantile: 0.9 - // value: nan - // > - // quantile: < - // quantile: 0.99 - // value: nan - // > - // > - // > - // metric: < - // label: < - // name: "species" - // value: "lithobates-catesbeianus" - // > - // summary: < - // sample_count: 1000 - // sample_sum: 31956.100000000017 - // quantile: < - // quantile: 0.5 - // value: 32.4 - // > - // quantile: < - // quantile: 0.9 - // value: 41.4 - // > - // quantile: < - // quantile: 0.99 - // value: 41.9 - // > - // > - // > - // metric: < - // label: < - // name: "species" - // value: "litoria-caerulea" - // > - // summary: < - // sample_count: 1000 - // sample_sum: 29969.50000000001 - // quantile: < - // quantile: 0.5 - // value: 31.1 - // > - // quantile: < - // quantile: 0.9 - // value: 41.3 - // > - // quantile: < - // quantile: 0.99 - // value: 41.9 - // > - // > - // > -} - -func ExampleNewConstSummary() { - desc := prometheus.NewDesc( - "http_request_duration_seconds", - "A summary of the HTTP request durations.", - []string{"code", "method"}, - prometheus.Labels{"owner": "example"}, - ) - - // Create a constant summary from values we got from a 3rd party telemetry system. - s := prometheus.MustNewConstSummary( - desc, - 4711, 403.34, - map[float64]float64{0.5: 42.3, 0.9: 323.3}, - "200", "get", - ) - - // Just for demonstration, let's check the state of the summary by - // (ab)using its Write method (which is usually only used by Prometheus - // internally). - metric := &dto.Metric{} - s.Write(metric) - fmt.Println(proto.MarshalTextString(metric)) - - // Output: - // label: < - // name: "code" - // value: "200" - // > - // label: < - // name: "method" - // value: "get" - // > - // label: < - // name: "owner" - // value: "example" - // > - // summary: < - // sample_count: 4711 - // sample_sum: 403.34 - // quantile: < - // quantile: 0.5 - // value: 42.3 - // > - // quantile: < - // quantile: 0.9 - // value: 323.3 - // > - // > -} - -func ExampleHistogram() { - temps := prometheus.NewHistogram(prometheus.HistogramOpts{ - Name: "pond_temperature_celsius", - Help: "The temperature of the frog pond.", // Sorry, we can't measure how badly it smells. - Buckets: prometheus.LinearBuckets(20, 5, 5), // 5 buckets, each 5 centigrade wide. - }) - - // Simulate some observations. - for i := 0; i < 1000; i++ { - temps.Observe(30 + math.Floor(120*math.Sin(float64(i)*0.1))/10) - } - - // Just for demonstration, let's check the state of the histogram by - // (ab)using its Write method (which is usually only used by Prometheus - // internally). - metric := &dto.Metric{} - temps.Write(metric) - fmt.Println(proto.MarshalTextString(metric)) - - // Output: - // histogram: < - // sample_count: 1000 - // sample_sum: 29969.50000000001 - // bucket: < - // cumulative_count: 192 - // upper_bound: 20 - // > - // bucket: < - // cumulative_count: 366 - // upper_bound: 25 - // > - // bucket: < - // cumulative_count: 501 - // upper_bound: 30 - // > - // bucket: < - // cumulative_count: 638 - // upper_bound: 35 - // > - // bucket: < - // cumulative_count: 816 - // upper_bound: 40 - // > - // > -} - -func ExampleNewConstHistogram() { - desc := prometheus.NewDesc( - "http_request_duration_seconds", - "A histogram of the HTTP request durations.", - []string{"code", "method"}, - prometheus.Labels{"owner": "example"}, - ) - - // Create a constant histogram from values we got from a 3rd party telemetry system. - h := prometheus.MustNewConstHistogram( - desc, - 4711, 403.34, - map[float64]uint64{25: 121, 50: 2403, 100: 3221, 200: 4233}, - "200", "get", - ) - - // Just for demonstration, let's check the state of the histogram by - // (ab)using its Write method (which is usually only used by Prometheus - // internally). - metric := &dto.Metric{} - h.Write(metric) - fmt.Println(proto.MarshalTextString(metric)) - - // Output: - // label: < - // name: "code" - // value: "200" - // > - // label: < - // name: "method" - // value: "get" - // > - // label: < - // name: "owner" - // value: "example" - // > - // histogram: < - // sample_count: 4711 - // sample_sum: 403.34 - // bucket: < - // cumulative_count: 121 - // upper_bound: 25 - // > - // bucket: < - // cumulative_count: 2403 - // upper_bound: 50 - // > - // bucket: < - // cumulative_count: 3221 - // upper_bound: 100 - // > - // bucket: < - // cumulative_count: 4233 - // upper_bound: 200 - // > - // > -} - -func ExampleAlreadyRegisteredError() { - reqCounter := prometheus.NewCounter(prometheus.CounterOpts{ - Name: "requests_total", - Help: "The total number of requests served.", - }) - if err := prometheus.Register(reqCounter); err != nil { - if are, ok := err.(prometheus.AlreadyRegisteredError); ok { - // A counter for that metric has been registered before. - // Use the old counter from now on. - reqCounter = are.ExistingCollector.(prometheus.Counter) - } else { - // Something else went wrong! - panic(err) - } - } - reqCounter.Inc() -} - -func ExampleGatherers() { - reg := prometheus.NewRegistry() - temp := prometheus.NewGaugeVec( - prometheus.GaugeOpts{ - Name: "temperature_kelvin", - Help: "Temperature in Kelvin.", - }, - []string{"location"}, - ) - reg.MustRegister(temp) - temp.WithLabelValues("outside").Set(273.14) - temp.WithLabelValues("inside").Set(298.44) - - var parser expfmt.TextParser - - text := ` -# TYPE humidity_percent gauge -# HELP humidity_percent Humidity in %. -humidity_percent{location="outside"} 45.4 -humidity_percent{location="inside"} 33.2 -# TYPE temperature_kelvin gauge -# HELP temperature_kelvin Temperature in Kelvin. -temperature_kelvin{location="somewhere else"} 4.5 -` - - parseText := func() ([]*dto.MetricFamily, error) { - parsed, err := parser.TextToMetricFamilies(strings.NewReader(text)) - if err != nil { - return nil, err - } - var result []*dto.MetricFamily - for _, mf := range parsed { - result = append(result, mf) - } - return result, nil - } - - gatherers := prometheus.Gatherers{ - reg, - prometheus.GathererFunc(parseText), - } - - gathering, err := gatherers.Gather() - if err != nil { - fmt.Println(err) - } - - out := &bytes.Buffer{} - for _, mf := range gathering { - if _, err := expfmt.MetricFamilyToText(out, mf); err != nil { - panic(err) - } - } - fmt.Print(out.String()) - fmt.Println("----------") - - // Note how the temperature_kelvin metric family has been merged from - // different sources. Now try - text = ` -# TYPE humidity_percent gauge -# HELP humidity_percent Humidity in %. -humidity_percent{location="outside"} 45.4 -humidity_percent{location="inside"} 33.2 -# TYPE temperature_kelvin gauge -# HELP temperature_kelvin Temperature in Kelvin. -# Duplicate metric: -temperature_kelvin{location="outside"} 265.3 - # Missing location label (note that this is undesirable but valid): -temperature_kelvin 4.5 -` - - gathering, err = gatherers.Gather() - if err != nil { - fmt.Println(err) - } - // Note that still as many metrics as possible are returned: - out.Reset() - for _, mf := range gathering { - if _, err := expfmt.MetricFamilyToText(out, mf); err != nil { - panic(err) - } - } - fmt.Print(out.String()) - - // Output: - // # HELP humidity_percent Humidity in %. - // # TYPE humidity_percent gauge - // humidity_percent{location="inside"} 33.2 - // humidity_percent{location="outside"} 45.4 - // # HELP temperature_kelvin Temperature in Kelvin. - // # TYPE temperature_kelvin gauge - // temperature_kelvin{location="inside"} 298.44 - // temperature_kelvin{location="outside"} 273.14 - // temperature_kelvin{location="somewhere else"} 4.5 - // ---------- - // collected metric "temperature_kelvin" { label: gauge: } was collected before with the same name and label values - // # HELP humidity_percent Humidity in %. - // # TYPE humidity_percent gauge - // humidity_percent{location="inside"} 33.2 - // humidity_percent{location="outside"} 45.4 - // # HELP temperature_kelvin Temperature in Kelvin. - // # TYPE temperature_kelvin gauge - // temperature_kelvin 4.5 - // temperature_kelvin{location="inside"} 298.44 - // temperature_kelvin{location="outside"} 273.14 -} - -func ExampleNewMetricWithTimestamp() { - desc := prometheus.NewDesc( - "temperature_kelvin", - "Current temperature in Kelvin.", - nil, nil, - ) - - // Create a constant gauge from values we got from an external - // temperature reporting system. Those values are reported with a slight - // delay, so we want to add the timestamp of the actual measurement. - temperatureReportedByExternalSystem := 298.15 - timeReportedByExternalSystem := time.Date(2009, time.November, 10, 23, 0, 0, 12345678, time.UTC) - s := prometheus.NewMetricWithTimestamp( - timeReportedByExternalSystem, - prometheus.MustNewConstMetric( - desc, prometheus.GaugeValue, temperatureReportedByExternalSystem, - ), - ) - - // Just for demonstration, let's check the state of the gauge by - // (ab)using its Write method (which is usually only used by Prometheus - // internally). - metric := &dto.Metric{} - s.Write(metric) - fmt.Println(proto.MarshalTextString(metric)) - - // Output: - // gauge: < - // value: 298.15 - // > - // timestamp_ms: 1257894000012 -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector_test.go b/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector_test.go deleted file mode 100644 index 6bcd9b692..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector_test.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus_test - -import ( - "expvar" - "fmt" - "sort" - "strings" - - dto "github.com/prometheus/client_model/go" - - "github.com/prometheus/client_golang/prometheus" -) - -func ExampleNewExpvarCollector() { - expvarCollector := prometheus.NewExpvarCollector(map[string]*prometheus.Desc{ - "memstats": prometheus.NewDesc( - "expvar_memstats", - "All numeric memstats as one metric family. Not a good role-model, actually... ;-)", - []string{"type"}, nil, - ), - "lone-int": prometheus.NewDesc( - "expvar_lone_int", - "Just an expvar int as an example.", - nil, nil, - ), - "http-request-map": prometheus.NewDesc( - "expvar_http_request_total", - "How many http requests processed, partitioned by status code and http method.", - []string{"code", "method"}, nil, - ), - }) - prometheus.MustRegister(expvarCollector) - - // The Prometheus part is done here. But to show that this example is - // doing anything, we have to manually export something via expvar. In - // real-life use-cases, some library would already have exported via - // expvar what we want to re-export as Prometheus metrics. - expvar.NewInt("lone-int").Set(42) - expvarMap := expvar.NewMap("http-request-map") - var ( - expvarMap1, expvarMap2 expvar.Map - expvarInt11, expvarInt12, expvarInt21, expvarInt22 expvar.Int - ) - expvarMap1.Init() - expvarMap2.Init() - expvarInt11.Set(3) - expvarInt12.Set(13) - expvarInt21.Set(11) - expvarInt22.Set(212) - expvarMap1.Set("POST", &expvarInt11) - expvarMap1.Set("GET", &expvarInt12) - expvarMap2.Set("POST", &expvarInt21) - expvarMap2.Set("GET", &expvarInt22) - expvarMap.Set("404", &expvarMap1) - expvarMap.Set("200", &expvarMap2) - // Results in the following expvar map: - // "http-request-count": {"200": {"POST": 11, "GET": 212}, "404": {"POST": 3, "GET": 13}} - - // Let's see what the scrape would yield, but exclude the memstats metrics. - metricStrings := []string{} - metric := dto.Metric{} - metricChan := make(chan prometheus.Metric) - go func() { - expvarCollector.Collect(metricChan) - close(metricChan) - }() - for m := range metricChan { - if !strings.Contains(m.Desc().String(), "expvar_memstats") { - metric.Reset() - m.Write(&metric) - metricStrings = append(metricStrings, metric.String()) - } - } - sort.Strings(metricStrings) - for _, s := range metricStrings { - fmt.Println(strings.TrimRight(s, " ")) - } - // Output: - // label: label: untyped: - // label: label: untyped: - // label: label: untyped: - // label: label: untyped: - // untyped: -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/gauge.go b/vendor/github.com/prometheus/client_golang/prometheus/gauge.go index 17c72d7eb..71d406bd9 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/gauge.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/gauge.go @@ -147,7 +147,7 @@ func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec { return &GaugeVec{ metricVec: newMetricVec(desc, func(lvs ...string) Metric { if len(lvs) != len(desc.variableLabels) { - panic(errInconsistentCardinality) + panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs)) } result := &gauge{desc: desc, labelPairs: makeLabelPairs(desc, lvs)} result.init(result) // Init self-collection. diff --git a/vendor/github.com/prometheus/client_golang/prometheus/gauge_test.go b/vendor/github.com/prometheus/client_golang/prometheus/gauge_test.go deleted file mode 100644 index a2e3c1416..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/gauge_test.go +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "math" - "math/rand" - "sync" - "testing" - "testing/quick" - "time" - - dto "github.com/prometheus/client_model/go" -) - -func listenGaugeStream(vals, result chan float64, done chan struct{}) { - var sum float64 -outer: - for { - select { - case <-done: - close(vals) - for v := range vals { - sum += v - } - break outer - case v := <-vals: - sum += v - } - } - result <- sum - close(result) -} - -func TestGaugeConcurrency(t *testing.T) { - it := func(n uint32) bool { - mutations := int(n % 10000) - concLevel := int(n%15 + 1) - - var start, end sync.WaitGroup - start.Add(1) - end.Add(concLevel) - - sStream := make(chan float64, mutations*concLevel) - result := make(chan float64) - done := make(chan struct{}) - - go listenGaugeStream(sStream, result, done) - go func() { - end.Wait() - close(done) - }() - - gge := NewGauge(GaugeOpts{ - Name: "test_gauge", - Help: "no help can be found here", - }) - for i := 0; i < concLevel; i++ { - vals := make([]float64, mutations) - for j := 0; j < mutations; j++ { - vals[j] = rand.Float64() - 0.5 - } - - go func(vals []float64) { - start.Wait() - for _, v := range vals { - sStream <- v - gge.Add(v) - } - end.Done() - }(vals) - } - start.Done() - - if expected, got := <-result, math.Float64frombits(gge.(*gauge).valBits); math.Abs(expected-got) > 0.000001 { - t.Fatalf("expected approx. %f, got %f", expected, got) - return false - } - return true - } - - if err := quick.Check(it, nil); err != nil { - t.Fatal(err) - } -} - -func TestGaugeVecConcurrency(t *testing.T) { - it := func(n uint32) bool { - mutations := int(n % 10000) - concLevel := int(n%15 + 1) - vecLength := int(n%5 + 1) - - var start, end sync.WaitGroup - start.Add(1) - end.Add(concLevel) - - sStreams := make([]chan float64, vecLength) - results := make([]chan float64, vecLength) - done := make(chan struct{}) - - for i := 0; i < vecLength; i++ { - sStreams[i] = make(chan float64, mutations*concLevel) - results[i] = make(chan float64) - go listenGaugeStream(sStreams[i], results[i], done) - } - - go func() { - end.Wait() - close(done) - }() - - gge := NewGaugeVec( - GaugeOpts{ - Name: "test_gauge", - Help: "no help can be found here", - }, - []string{"label"}, - ) - for i := 0; i < concLevel; i++ { - vals := make([]float64, mutations) - pick := make([]int, mutations) - for j := 0; j < mutations; j++ { - vals[j] = rand.Float64() - 0.5 - pick[j] = rand.Intn(vecLength) - } - - go func(vals []float64) { - start.Wait() - for i, v := range vals { - sStreams[pick[i]] <- v - gge.WithLabelValues(string('A' + pick[i])).Add(v) - } - end.Done() - }(vals) - } - start.Done() - - for i := range sStreams { - if expected, got := <-results[i], math.Float64frombits(gge.WithLabelValues(string('A'+i)).(*gauge).valBits); math.Abs(expected-got) > 0.000001 { - t.Fatalf("expected approx. %f, got %f", expected, got) - return false - } - } - return true - } - - if err := quick.Check(it, nil); err != nil { - t.Fatal(err) - } -} - -func TestGaugeFunc(t *testing.T) { - gf := NewGaugeFunc( - GaugeOpts{ - Name: "test_name", - Help: "test help", - ConstLabels: Labels{"a": "1", "b": "2"}, - }, - func() float64 { return 3.1415 }, - ) - - if expected, got := `Desc{fqName: "test_name", help: "test help", constLabels: {a="1",b="2"}, variableLabels: []}`, gf.Desc().String(); expected != got { - t.Errorf("expected %q, got %q", expected, got) - } - - m := &dto.Metric{} - gf.Write(m) - - if expected, got := `label: label: gauge: `, m.String(); expected != got { - t.Errorf("expected %q, got %q", expected, got) - } -} - -func TestGaugeSetCurrentTime(t *testing.T) { - g := NewGauge(GaugeOpts{ - Name: "test_name", - Help: "test help", - }) - g.SetToCurrentTime() - unixTime := float64(time.Now().Unix()) - - m := &dto.Metric{} - g.Write(m) - - delta := unixTime - m.GetGauge().GetValue() - // This is just a smoke test to make sure SetToCurrentTime is not - // totally off. Tests with current time involved are hard... - if math.Abs(delta) > 5 { - t.Errorf("Gauge set to current time deviates from current time by more than 5s, delta is %f seconds", delta) - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/go_collector_test.go b/vendor/github.com/prometheus/client_golang/prometheus/go_collector_test.go deleted file mode 100644 index f93dcdcfc..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/go_collector_test.go +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "runtime" - "testing" - "time" - - dto "github.com/prometheus/client_model/go" -) - -func TestGoCollector(t *testing.T) { - var ( - c = NewGoCollector() - ch = make(chan Metric) - waitc = make(chan struct{}) - closec = make(chan struct{}) - old = -1 - ) - defer close(closec) - - go func() { - c.Collect(ch) - go func(c <-chan struct{}) { - <-c - }(closec) - <-waitc - c.Collect(ch) - }() - - for { - select { - case m := <-ch: - // m can be Gauge or Counter, - // currently just test the go_goroutines Gauge - // and ignore others. - if m.Desc().fqName != "go_goroutines" { - continue - } - pb := &dto.Metric{} - m.Write(pb) - if pb.GetGauge() == nil { - continue - } - - if old == -1 { - old = int(pb.GetGauge().GetValue()) - close(waitc) - continue - } - - if diff := int(pb.GetGauge().GetValue()) - old; diff != 1 { - // TODO: This is flaky in highly concurrent situations. - t.Errorf("want 1 new goroutine, got %d", diff) - } - - // GoCollector performs three sends per call. - // On line 27 we need to receive three more sends - // to shut down cleanly. - <-ch - <-ch - <-ch - return - case <-time.After(1 * time.Second): - t.Fatalf("expected collect timed out") - } - } -} - -func TestGCCollector(t *testing.T) { - var ( - c = NewGoCollector() - ch = make(chan Metric) - waitc = make(chan struct{}) - closec = make(chan struct{}) - oldGC uint64 - oldPause float64 - ) - defer close(closec) - - go func() { - c.Collect(ch) - // force GC - runtime.GC() - <-waitc - c.Collect(ch) - }() - - first := true - for { - select { - case metric := <-ch: - pb := &dto.Metric{} - metric.Write(pb) - if pb.GetSummary() == nil { - continue - } - if len(pb.GetSummary().Quantile) != 5 { - t.Errorf("expected 4 buckets, got %d", len(pb.GetSummary().Quantile)) - } - for idx, want := range []float64{0.0, 0.25, 0.5, 0.75, 1.0} { - if *pb.GetSummary().Quantile[idx].Quantile != want { - t.Errorf("bucket #%d is off, got %f, want %f", idx, *pb.GetSummary().Quantile[idx].Quantile, want) - } - } - if first { - first = false - oldGC = *pb.GetSummary().SampleCount - oldPause = *pb.GetSummary().SampleSum - close(waitc) - continue - } - if diff := *pb.GetSummary().SampleCount - oldGC; diff != 1 { - t.Errorf("want 1 new garbage collection run, got %d", diff) - } - if diff := *pb.GetSummary().SampleSum - oldPause; diff <= 0 { - t.Errorf("want moar pause, got %f", diff) - } - return - case <-time.After(1 * time.Second): - t.Fatalf("expected collect timed out") - } - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go index 4d7fa976e..f88da707b 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go @@ -165,7 +165,7 @@ func NewHistogram(opts HistogramOpts) Histogram { func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogram { if len(desc.variableLabels) != len(labelValues) { - panic(errInconsistentCardinality) + panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, labelValues)) } for _, n := range desc.variableLabels { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/histogram_test.go b/vendor/github.com/prometheus/client_golang/prometheus/histogram_test.go deleted file mode 100644 index 9546b8776..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/histogram_test.go +++ /dev/null @@ -1,393 +0,0 @@ -// Copyright 2015 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "math" - "math/rand" - "reflect" - "runtime" - "sort" - "sync" - "testing" - "testing/quick" - - dto "github.com/prometheus/client_model/go" -) - -func benchmarkHistogramObserve(w int, b *testing.B) { - b.StopTimer() - - wg := new(sync.WaitGroup) - wg.Add(w) - - g := new(sync.WaitGroup) - g.Add(1) - - s := NewHistogram(HistogramOpts{}) - - for i := 0; i < w; i++ { - go func() { - g.Wait() - - for i := 0; i < b.N; i++ { - s.Observe(float64(i)) - } - - wg.Done() - }() - } - - b.StartTimer() - g.Done() - wg.Wait() -} - -func BenchmarkHistogramObserve1(b *testing.B) { - benchmarkHistogramObserve(1, b) -} - -func BenchmarkHistogramObserve2(b *testing.B) { - benchmarkHistogramObserve(2, b) -} - -func BenchmarkHistogramObserve4(b *testing.B) { - benchmarkHistogramObserve(4, b) -} - -func BenchmarkHistogramObserve8(b *testing.B) { - benchmarkHistogramObserve(8, b) -} - -func benchmarkHistogramWrite(w int, b *testing.B) { - b.StopTimer() - - wg := new(sync.WaitGroup) - wg.Add(w) - - g := new(sync.WaitGroup) - g.Add(1) - - s := NewHistogram(HistogramOpts{}) - - for i := 0; i < 1000000; i++ { - s.Observe(float64(i)) - } - - for j := 0; j < w; j++ { - outs := make([]dto.Metric, b.N) - - go func(o []dto.Metric) { - g.Wait() - - for i := 0; i < b.N; i++ { - s.Write(&o[i]) - } - - wg.Done() - }(outs) - } - - b.StartTimer() - g.Done() - wg.Wait() -} - -func BenchmarkHistogramWrite1(b *testing.B) { - benchmarkHistogramWrite(1, b) -} - -func BenchmarkHistogramWrite2(b *testing.B) { - benchmarkHistogramWrite(2, b) -} - -func BenchmarkHistogramWrite4(b *testing.B) { - benchmarkHistogramWrite(4, b) -} - -func BenchmarkHistogramWrite8(b *testing.B) { - benchmarkHistogramWrite(8, b) -} - -func TestHistogramNonMonotonicBuckets(t *testing.T) { - testCases := map[string][]float64{ - "not strictly monotonic": {1, 2, 2, 3}, - "not monotonic at all": {1, 2, 4, 3, 5}, - "have +Inf in the middle": {1, 2, math.Inf(+1), 3}, - } - for name, buckets := range testCases { - func() { - defer func() { - if r := recover(); r == nil { - t.Errorf("Buckets %v are %s but NewHistogram did not panic.", buckets, name) - } - }() - _ = NewHistogram(HistogramOpts{ - Name: "test_histogram", - Help: "helpless", - Buckets: buckets, - }) - }() - } -} - -// Intentionally adding +Inf here to test if that case is handled correctly. -// Also, getCumulativeCounts depends on it. -var testBuckets = []float64{-2, -1, -0.5, 0, 0.5, 1, 2, math.Inf(+1)} - -func TestHistogramConcurrency(t *testing.T) { - if testing.Short() { - t.Skip("Skipping test in short mode.") - } - - rand.Seed(42) - - it := func(n uint32) bool { - mutations := int(n%1e4 + 1e4) - concLevel := int(n%5 + 1) - total := mutations * concLevel - - var start, end sync.WaitGroup - start.Add(1) - end.Add(concLevel) - - sum := NewHistogram(HistogramOpts{ - Name: "test_histogram", - Help: "helpless", - Buckets: testBuckets, - }) - - allVars := make([]float64, total) - var sampleSum float64 - for i := 0; i < concLevel; i++ { - vals := make([]float64, mutations) - for j := 0; j < mutations; j++ { - v := rand.NormFloat64() - vals[j] = v - allVars[i*mutations+j] = v - sampleSum += v - } - - go func(vals []float64) { - start.Wait() - for _, v := range vals { - sum.Observe(v) - } - end.Done() - }(vals) - } - sort.Float64s(allVars) - start.Done() - end.Wait() - - m := &dto.Metric{} - sum.Write(m) - if got, want := int(*m.Histogram.SampleCount), total; got != want { - t.Errorf("got sample count %d, want %d", got, want) - } - if got, want := *m.Histogram.SampleSum, sampleSum; math.Abs((got-want)/want) > 0.001 { - t.Errorf("got sample sum %f, want %f", got, want) - } - - wantCounts := getCumulativeCounts(allVars) - - if got, want := len(m.Histogram.Bucket), len(testBuckets)-1; got != want { - t.Errorf("got %d buckets in protobuf, want %d", got, want) - } - for i, wantBound := range testBuckets { - if i == len(testBuckets)-1 { - break // No +Inf bucket in protobuf. - } - if gotBound := *m.Histogram.Bucket[i].UpperBound; gotBound != wantBound { - t.Errorf("got bound %f, want %f", gotBound, wantBound) - } - if gotCount, wantCount := *m.Histogram.Bucket[i].CumulativeCount, wantCounts[i]; gotCount != wantCount { - t.Errorf("got count %d, want %d", gotCount, wantCount) - } - } - return true - } - - if err := quick.Check(it, nil); err != nil { - t.Error(err) - } -} - -func TestHistogramVecConcurrency(t *testing.T) { - if testing.Short() { - t.Skip("Skipping test in short mode.") - } - - rand.Seed(42) - - objectives := make([]float64, 0, len(DefObjectives)) - for qu := range DefObjectives { - - objectives = append(objectives, qu) - } - sort.Float64s(objectives) - - it := func(n uint32) bool { - mutations := int(n%1e4 + 1e4) - concLevel := int(n%7 + 1) - vecLength := int(n%3 + 1) - - var start, end sync.WaitGroup - start.Add(1) - end.Add(concLevel) - - his := NewHistogramVec( - HistogramOpts{ - Name: "test_histogram", - Help: "helpless", - Buckets: []float64{-2, -1, -0.5, 0, 0.5, 1, 2, math.Inf(+1)}, - }, - []string{"label"}, - ) - - allVars := make([][]float64, vecLength) - sampleSums := make([]float64, vecLength) - for i := 0; i < concLevel; i++ { - vals := make([]float64, mutations) - picks := make([]int, mutations) - for j := 0; j < mutations; j++ { - v := rand.NormFloat64() - vals[j] = v - pick := rand.Intn(vecLength) - picks[j] = pick - allVars[pick] = append(allVars[pick], v) - sampleSums[pick] += v - } - - go func(vals []float64) { - start.Wait() - for i, v := range vals { - his.WithLabelValues(string('A' + picks[i])).Observe(v) - } - end.Done() - }(vals) - } - for _, vars := range allVars { - sort.Float64s(vars) - } - start.Done() - end.Wait() - - for i := 0; i < vecLength; i++ { - m := &dto.Metric{} - s := his.WithLabelValues(string('A' + i)) - s.(Histogram).Write(m) - - if got, want := len(m.Histogram.Bucket), len(testBuckets)-1; got != want { - t.Errorf("got %d buckets in protobuf, want %d", got, want) - } - if got, want := int(*m.Histogram.SampleCount), len(allVars[i]); got != want { - t.Errorf("got sample count %d, want %d", got, want) - } - if got, want := *m.Histogram.SampleSum, sampleSums[i]; math.Abs((got-want)/want) > 0.001 { - t.Errorf("got sample sum %f, want %f", got, want) - } - - wantCounts := getCumulativeCounts(allVars[i]) - - for j, wantBound := range testBuckets { - if j == len(testBuckets)-1 { - break // No +Inf bucket in protobuf. - } - if gotBound := *m.Histogram.Bucket[j].UpperBound; gotBound != wantBound { - t.Errorf("got bound %f, want %f", gotBound, wantBound) - } - if gotCount, wantCount := *m.Histogram.Bucket[j].CumulativeCount, wantCounts[j]; gotCount != wantCount { - t.Errorf("got count %d, want %d", gotCount, wantCount) - } - } - } - return true - } - - if err := quick.Check(it, nil); err != nil { - t.Error(err) - } -} - -func getCumulativeCounts(vars []float64) []uint64 { - counts := make([]uint64, len(testBuckets)) - for _, v := range vars { - for i := len(testBuckets) - 1; i >= 0; i-- { - if v > testBuckets[i] { - break - } - counts[i]++ - } - } - return counts -} - -func TestBuckets(t *testing.T) { - got := LinearBuckets(-15, 5, 6) - want := []float64{-15, -10, -5, 0, 5, 10} - if !reflect.DeepEqual(got, want) { - t.Errorf("linear buckets: got %v, want %v", got, want) - } - - got = ExponentialBuckets(100, 1.2, 3) - want = []float64{100, 120, 144} - if !reflect.DeepEqual(got, want) { - t.Errorf("exponential buckets: got %v, want %v", got, want) - } -} - -func TestHistogramAtomicObserve(t *testing.T) { - var ( - quit = make(chan struct{}) - his = NewHistogram(HistogramOpts{ - Buckets: []float64{0.5, 10, 20}, - }) - ) - - defer func() { close(quit) }() - - observe := func() { - for { - select { - case <-quit: - return - default: - his.Observe(1) - } - } - } - - go observe() - go observe() - go observe() - - for i := 0; i < 100; i++ { - m := &dto.Metric{} - if err := his.Write(m); err != nil { - t.Fatal("unexpected error writing histogram:", err) - } - h := m.GetHistogram() - if h.GetSampleCount() != uint64(h.GetSampleSum()) || - h.GetSampleCount() != h.GetBucket()[1].GetCumulativeCount() || - h.GetSampleCount() != h.GetBucket()[2].GetCumulativeCount() { - t.Fatalf( - "inconsistent counts in histogram: count=%d sum=%f buckets=[%d, %d]", - h.GetSampleCount(), h.GetSampleSum(), - h.GetBucket()[1].GetCumulativeCount(), h.GetBucket()[2].GetCumulativeCount(), - ) - } - runtime.Gosched() - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/http.go b/vendor/github.com/prometheus/client_golang/prometheus/http.go index 4b8e60273..9f0875bfc 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/http.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/http.go @@ -15,9 +15,7 @@ package prometheus import ( "bufio" - "bytes" "compress/gzip" - "fmt" "io" "net" "net/http" @@ -41,19 +39,10 @@ const ( acceptEncodingHeader = "Accept-Encoding" ) -var bufPool sync.Pool - -func getBuf() *bytes.Buffer { - buf := bufPool.Get() - if buf == nil { - return &bytes.Buffer{} - } - return buf.(*bytes.Buffer) -} - -func giveBuf(buf *bytes.Buffer) { - buf.Reset() - bufPool.Put(buf) +var gzipPool = sync.Pool{ + New: func() interface{} { + return gzip.NewWriter(nil) + }, } // Handler returns an HTTP handler for the DefaultGatherer. It is @@ -71,58 +60,40 @@ func Handler() http.Handler { // Deprecated: Use promhttp.HandlerFor(DefaultGatherer, promhttp.HandlerOpts{}) // instead. See there for further documentation. func UninstrumentedHandler() http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + return http.HandlerFunc(func(rsp http.ResponseWriter, req *http.Request) { mfs, err := DefaultGatherer.Gather() if err != nil { - http.Error(w, "An error has occurred during metrics collection:\n\n"+err.Error(), http.StatusInternalServerError) + httpError(rsp, err) return } contentType := expfmt.Negotiate(req.Header) - buf := getBuf() - defer giveBuf(buf) - writer, encoding := decorateWriter(req, buf) - enc := expfmt.NewEncoder(writer, contentType) - var lastErr error + header := rsp.Header() + header.Set(contentTypeHeader, string(contentType)) + + w := io.Writer(rsp) + if gzipAccepted(req.Header) { + header.Set(contentEncodingHeader, "gzip") + gz := gzipPool.Get().(*gzip.Writer) + defer gzipPool.Put(gz) + + gz.Reset(w) + defer gz.Close() + + w = gz + } + + enc := expfmt.NewEncoder(w, contentType) + for _, mf := range mfs { if err := enc.Encode(mf); err != nil { - lastErr = err - http.Error(w, "An error has occurred during metrics encoding:\n\n"+err.Error(), http.StatusInternalServerError) + httpError(rsp, err) return } } - if closer, ok := writer.(io.Closer); ok { - closer.Close() - } - if lastErr != nil && buf.Len() == 0 { - http.Error(w, "No metrics encoded, last error:\n\n"+lastErr.Error(), http.StatusInternalServerError) - return - } - header := w.Header() - header.Set(contentTypeHeader, string(contentType)) - header.Set(contentLengthHeader, fmt.Sprint(buf.Len())) - if encoding != "" { - header.Set(contentEncodingHeader, encoding) - } - w.Write(buf.Bytes()) }) } -// decorateWriter wraps a writer to handle gzip compression if requested. It -// returns the decorated writer and the appropriate "Content-Encoding" header -// (which is empty if no compression is enabled). -func decorateWriter(request *http.Request, writer io.Writer) (io.Writer, string) { - header := request.Header.Get(acceptEncodingHeader) - parts := strings.Split(header, ",") - for _, part := range parts { - part = strings.TrimSpace(part) - if part == "gzip" || strings.HasPrefix(part, "gzip;") { - return gzip.NewWriter(writer), "gzip" - } - } - return writer, "" -} - var instLabels = []string{"method", "code"} type nower interface { @@ -503,3 +474,31 @@ func sanitizeCode(s int) string { return strconv.Itoa(s) } } + +// gzipAccepted returns whether the client will accept gzip-encoded content. +func gzipAccepted(header http.Header) bool { + a := header.Get(acceptEncodingHeader) + parts := strings.Split(a, ",") + for _, part := range parts { + part = strings.TrimSpace(part) + if part == "gzip" || strings.HasPrefix(part, "gzip;") { + return true + } + } + return false +} + +// httpError removes any content-encoding header and then calls http.Error with +// the provided error and http.StatusInternalServerErrer. Error contents is +// supposed to be uncompressed plain text. However, same as with a plain +// http.Error, any header settings will be void if the header has already been +// sent. The error message will still be written to the writer, but it will +// probably be of limited use. +func httpError(rsp http.ResponseWriter, err error) { + rsp.Header().Del(contentEncodingHeader) + http.Error( + rsp, + "An error has occurred while serving metrics:\n\n"+err.Error(), + http.StatusInternalServerError, + ) +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/http_test.go b/vendor/github.com/prometheus/client_golang/prometheus/http_test.go deleted file mode 100644 index dd89ccf1a..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/http_test.go +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "net/http" - "net/http/httptest" - "testing" - "time" - - dto "github.com/prometheus/client_model/go" -) - -type respBody string - -func (b respBody) ServeHTTP(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusTeapot) - w.Write([]byte(b)) -} - -func nowSeries(t ...time.Time) nower { - return nowFunc(func() time.Time { - defer func() { - t = t[1:] - }() - - return t[0] - }) -} - -func TestInstrumentHandler(t *testing.T) { - defer func(n nower) { - now = n.(nower) - }(now) - - instant := time.Now() - end := instant.Add(30 * time.Second) - now = nowSeries(instant, end) - body := respBody("Howdy there!") - - hndlr := InstrumentHandler("test-handler", body) - - opts := SummaryOpts{ - Subsystem: "http", - ConstLabels: Labels{"handler": "test-handler"}, - Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, - } - - reqCnt := NewCounterVec( - CounterOpts{ - Namespace: opts.Namespace, - Subsystem: opts.Subsystem, - Name: "requests_total", - Help: "Total number of HTTP requests made.", - ConstLabels: opts.ConstLabels, - }, - instLabels, - ) - err := Register(reqCnt) - if err == nil { - t.Fatal("expected reqCnt to be registered already") - } - if are, ok := err.(AlreadyRegisteredError); ok { - reqCnt = are.ExistingCollector.(*CounterVec) - } else { - t.Fatal("unexpected registration error:", err) - } - - opts.Name = "request_duration_microseconds" - opts.Help = "The HTTP request latencies in microseconds." - reqDur := NewSummary(opts) - err = Register(reqDur) - if err == nil { - t.Fatal("expected reqDur to be registered already") - } - if are, ok := err.(AlreadyRegisteredError); ok { - reqDur = are.ExistingCollector.(Summary) - } else { - t.Fatal("unexpected registration error:", err) - } - - opts.Name = "request_size_bytes" - opts.Help = "The HTTP request sizes in bytes." - reqSz := NewSummary(opts) - err = Register(reqSz) - if err == nil { - t.Fatal("expected reqSz to be registered already") - } - if _, ok := err.(AlreadyRegisteredError); !ok { - t.Fatal("unexpected registration error:", err) - } - - opts.Name = "response_size_bytes" - opts.Help = "The HTTP response sizes in bytes." - resSz := NewSummary(opts) - err = Register(resSz) - if err == nil { - t.Fatal("expected resSz to be registered already") - } - if _, ok := err.(AlreadyRegisteredError); !ok { - t.Fatal("unexpected registration error:", err) - } - - reqCnt.Reset() - - resp := httptest.NewRecorder() - req := &http.Request{ - Method: "GET", - } - - hndlr.ServeHTTP(resp, req) - - if resp.Code != http.StatusTeapot { - t.Fatalf("expected status %d, got %d", http.StatusTeapot, resp.Code) - } - if resp.Body.String() != "Howdy there!" { - t.Fatalf("expected body %s, got %s", "Howdy there!", resp.Body.String()) - } - - out := &dto.Metric{} - reqDur.Write(out) - if want, got := "test-handler", out.Label[0].GetValue(); want != got { - t.Errorf("want label value %q in reqDur, got %q", want, got) - } - if want, got := uint64(1), out.Summary.GetSampleCount(); want != got { - t.Errorf("want sample count %d in reqDur, got %d", want, got) - } - - out.Reset() - if want, got := 1, len(reqCnt.metricMap.metrics); want != got { - t.Errorf("want %d children in reqCnt, got %d", want, got) - } - cnt, err := reqCnt.GetMetricWithLabelValues("get", "418") - if err != nil { - t.Fatal(err) - } - cnt.Write(out) - if want, got := "418", out.Label[0].GetValue(); want != got { - t.Errorf("want label value %q in reqCnt, got %q", want, got) - } - if want, got := "test-handler", out.Label[1].GetValue(); want != got { - t.Errorf("want label value %q in reqCnt, got %q", want, got) - } - if want, got := "get", out.Label[2].GetValue(); want != got { - t.Errorf("want label value %q in reqCnt, got %q", want, got) - } - if out.Counter == nil { - t.Fatal("expected non-nil counter in reqCnt") - } - if want, got := 1., out.Counter.GetValue(); want != got { - t.Errorf("want reqCnt of %f, got %f", want, got) - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/labels.go b/vendor/github.com/prometheus/client_golang/prometheus/labels.go index e68f132ec..2744443ac 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/labels.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/labels.go @@ -37,9 +37,22 @@ const reservedLabelPrefix = "__" var errInconsistentCardinality = errors.New("inconsistent label cardinality") +func makeInconsistentCardinalityError(fqName string, labels, labelValues []string) error { + return fmt.Errorf( + "%s: %q has %d variable labels named %q but %d values %q were provided", + errInconsistentCardinality, fqName, + len(labels), labels, + len(labelValues), labelValues, + ) +} + func validateValuesInLabels(labels Labels, expectedNumberOfValues int) error { if len(labels) != expectedNumberOfValues { - return errInconsistentCardinality + return fmt.Errorf( + "%s: expected %d label values but got %d in %#v", + errInconsistentCardinality, expectedNumberOfValues, + len(labels), labels, + ) } for name, val := range labels { @@ -53,7 +66,11 @@ func validateValuesInLabels(labels Labels, expectedNumberOfValues int) error { func validateLabelValues(vals []string, expectedNumberOfValues int) error { if len(vals) != expectedNumberOfValues { - return errInconsistentCardinality + return fmt.Errorf( + "%s: expected %d label values but got %d in %#v", + errInconsistentCardinality, expectedNumberOfValues, + len(vals), vals, + ) } for _, val := range vals { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/metric_test.go b/vendor/github.com/prometheus/client_golang/prometheus/metric_test.go deleted file mode 100644 index 7145f5e53..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/metric_test.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import "testing" - -func TestBuildFQName(t *testing.T) { - scenarios := []struct{ namespace, subsystem, name, result string }{ - {"a", "b", "c", "a_b_c"}, - {"", "b", "c", "b_c"}, - {"a", "", "c", "a_c"}, - {"", "", "c", "c"}, - {"a", "b", "", ""}, - {"a", "", "", ""}, - {"", "b", "", ""}, - {" ", "", "", ""}, - } - - for i, s := range scenarios { - if want, got := s.result, BuildFQName(s.namespace, s.subsystem, s.name); want != got { - t.Errorf("%d. want %s, got %s", i, want, got) - } - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_test.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_test.go deleted file mode 100644 index 8651d4f13..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_test.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// +build linux - -package prometheus - -import ( - "bytes" - "errors" - "os" - "regexp" - "testing" - - "github.com/prometheus/common/expfmt" - "github.com/prometheus/procfs" - - dto "github.com/prometheus/client_model/go" -) - -func TestProcessCollector(t *testing.T) { - if _, err := procfs.Self(); err != nil { - t.Skipf("skipping TestProcessCollector, procfs not available: %s", err) - } - - registry := NewRegistry() - if err := registry.Register(NewProcessCollector(ProcessCollectorOpts{})); err != nil { - t.Fatal(err) - } - if err := registry.Register(NewProcessCollector(ProcessCollectorOpts{ - PidFn: func() (int, error) { return os.Getpid(), nil }, - Namespace: "foobar", - ReportErrors: true, // No errors expected, just to see if none are reported. - })); err != nil { - t.Fatal(err) - } - - mfs, err := registry.Gather() - if err != nil { - t.Fatal(err) - } - - var buf bytes.Buffer - for _, mf := range mfs { - if _, err := expfmt.MetricFamilyToText(&buf, mf); err != nil { - t.Fatal(err) - } - } - - for _, re := range []*regexp.Regexp{ - regexp.MustCompile("\nprocess_cpu_seconds_total [0-9]"), - regexp.MustCompile("\nprocess_max_fds [1-9]"), - regexp.MustCompile("\nprocess_open_fds [1-9]"), - regexp.MustCompile("\nprocess_virtual_memory_max_bytes (-1|[1-9])"), - regexp.MustCompile("\nprocess_virtual_memory_bytes [1-9]"), - regexp.MustCompile("\nprocess_resident_memory_bytes [1-9]"), - regexp.MustCompile("\nprocess_start_time_seconds [0-9.]{10,}"), - regexp.MustCompile("\nfoobar_process_cpu_seconds_total [0-9]"), - regexp.MustCompile("\nfoobar_process_max_fds [1-9]"), - regexp.MustCompile("\nfoobar_process_open_fds [1-9]"), - regexp.MustCompile("\nfoobar_process_virtual_memory_max_bytes (-1|[1-9])"), - regexp.MustCompile("\nfoobar_process_virtual_memory_bytes [1-9]"), - regexp.MustCompile("\nfoobar_process_resident_memory_bytes [1-9]"), - regexp.MustCompile("\nfoobar_process_start_time_seconds [0-9.]{10,}"), - } { - if !re.Match(buf.Bytes()) { - t.Errorf("want body to match %s\n%s", re, buf.String()) - } - } - - brokenProcessCollector := NewProcessCollector(ProcessCollectorOpts{ - PidFn: func() (int, error) { return 0, errors.New("boo") }, - ReportErrors: true, - }) - - ch := make(chan Metric) - go func() { - brokenProcessCollector.Collect(ch) - close(ch) - }() - n := 0 - for m := range ch { - n++ - pb := &dto.Metric{} - err := m.Write(pb) - if err == nil { - t.Error("metric collected from broken process collector is unexpectedly valid") - } - } - if n != 1 { - t.Errorf("%d metrics collected, want 1", n) - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promauto/auto.go b/vendor/github.com/prometheus/client_golang/prometheus/promauto/auto.go deleted file mode 100644 index a00ba1eb8..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promauto/auto.go +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package promauto provides constructors for the usual Prometheus metrics that -// return them already registered with the global registry -// (prometheus.DefaultRegisterer). This allows very compact code, avoiding any -// references to the registry altogether, but all the constructors in this -// package will panic if the registration fails. -// -// The following example is a complete program to create a histogram of normally -// distributed random numbers from the math/rand package: -// -// package main -// -// import ( -// "math/rand" -// "net/http" -// -// "github.com/prometheus/client_golang/prometheus" -// "github.com/prometheus/client_golang/prometheus/promauto" -// "github.com/prometheus/client_golang/prometheus/promhttp" -// ) -// -// var histogram = promauto.NewHistogram(prometheus.HistogramOpts{ -// Name: "random_numbers", -// Help: "A histogram of normally distributed random numbers.", -// Buckets: prometheus.LinearBuckets(-3, .1, 61), -// }) -// -// func Random() { -// for { -// histogram.Observe(rand.NormFloat64()) -// } -// } -// -// func main() { -// go Random() -// http.Handle("/metrics", promhttp.Handler()) -// http.ListenAndServe(":1971", nil) -// } -// -// Prometheus's version of a minimal hello-world program: -// -// package main -// -// import ( -// "fmt" -// "net/http" -// -// "github.com/prometheus/client_golang/prometheus" -// "github.com/prometheus/client_golang/prometheus/promauto" -// "github.com/prometheus/client_golang/prometheus/promhttp" -// ) -// -// func main() { -// http.Handle("/", promhttp.InstrumentHandlerCounter( -// promauto.NewCounterVec( -// prometheus.CounterOpts{ -// Name: "hello_requests_total", -// Help: "Total number of hello-world requests by HTTP code.", -// }, -// []string{"code"}, -// ), -// http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -// fmt.Fprint(w, "Hello, world!") -// }), -// )) -// http.Handle("/metrics", promhttp.Handler()) -// http.ListenAndServe(":1971", nil) -// } -// -// This appears very handy. So why are these constructors locked away in a -// separate package? There are two caveats: -// -// First, in more complex programs, global state is often quite problematic. -// That's the reason why the metrics constructors in the prometheus package do -// not interact with the global prometheus.DefaultRegisterer on their own. You -// are free to use the Register or MustRegister functions to register them with -// the global prometheus.DefaultRegisterer, but you could as well choose a local -// Registerer (usually created with prometheus.NewRegistry, but there are other -// scenarios, e.g. testing). -// -// The second issue is that registration may fail, e.g. if a metric inconsistent -// with the newly to be registered one is already registered. But how to signal -// and handle a panic in the automatic registration with the default registry? -// The only way is panicking. While panicking on invalid input provided by the -// programmer is certainly fine, things are a bit more subtle in this case: You -// might just add another package to the program, and that package (in its init -// function) happens to register a metric with the same name as your code. Now, -// all of a sudden, either your code or the code of the newly imported package -// panics, depending on initialization order, without any opportunity to handle -// the case gracefully. Even worse is a scenario where registration happens -// later during the runtime (e.g. upon loading some kind of plugin), where the -// panic could be triggered long after the code has been deployed to -// production. A possibility to panic should be explicitly called out by the -// Must… idiom, cf. prometheus.MustRegister. But adding a separate set of -// constructors in the prometheus package called MustRegisterNewCounterVec or -// similar would be quite unwieldy. Adding an extra MustRegister method to each -// metric, returning the registered metric, would result in nice code for those -// using the method, but would pollute every single metric interface for -// everybody avoiding the global registry. -// -// To address both issues, the problematic auto-registering and possibly -// panicking constructors are all in this package with a clear warning -// ahead. And whoever cares about avoiding global state and possibly panicking -// function calls can simply ignore the existence of the promauto package -// altogether. -// -// A final note: There is a similar case in the net/http package of the standard -// library. It has DefaultServeMux as a global instance of ServeMux, and the -// Handle function acts on it, panicking if a handler for the same pattern has -// already been registered. However, one might argue that the whole HTTP routing -// is usually set up closely together in the same package or file, while -// Prometheus metrics tend to be spread widely over the codebase, increasing the -// chance of surprising registration failures. Furthermore, the use of global -// state in net/http has been criticized widely, and some avoid it altogether. -package promauto - -import "github.com/prometheus/client_golang/prometheus" - -// NewCounter works like the function of the same name in the prometheus package -// but it automatically registers the Counter with the -// prometheus.DefaultRegisterer. If the registration fails, NewCounter panics. -func NewCounter(opts prometheus.CounterOpts) prometheus.Counter { - c := prometheus.NewCounter(opts) - prometheus.MustRegister(c) - return c -} - -// NewCounterVec works like the function of the same name in the prometheus -// package but it automatically registers the CounterVec with the -// prometheus.DefaultRegisterer. If the registration fails, NewCounterVec -// panics. -func NewCounterVec(opts prometheus.CounterOpts, labelNames []string) *prometheus.CounterVec { - c := prometheus.NewCounterVec(opts, labelNames) - prometheus.MustRegister(c) - return c -} - -// NewCounterFunc works like the function of the same name in the prometheus -// package but it automatically registers the CounterFunc with the -// prometheus.DefaultRegisterer. If the registration fails, NewCounterFunc -// panics. -func NewCounterFunc(opts prometheus.CounterOpts, function func() float64) prometheus.CounterFunc { - g := prometheus.NewCounterFunc(opts, function) - prometheus.MustRegister(g) - return g -} - -// NewGauge works like the function of the same name in the prometheus package -// but it automatically registers the Gauge with the -// prometheus.DefaultRegisterer. If the registration fails, NewGauge panics. -func NewGauge(opts prometheus.GaugeOpts) prometheus.Gauge { - g := prometheus.NewGauge(opts) - prometheus.MustRegister(g) - return g -} - -// NewGaugeVec works like the function of the same name in the prometheus -// package but it automatically registers the GaugeVec with the -// prometheus.DefaultRegisterer. If the registration fails, NewGaugeVec panics. -func NewGaugeVec(opts prometheus.GaugeOpts, labelNames []string) *prometheus.GaugeVec { - g := prometheus.NewGaugeVec(opts, labelNames) - prometheus.MustRegister(g) - return g -} - -// NewGaugeFunc works like the function of the same name in the prometheus -// package but it automatically registers the GaugeFunc with the -// prometheus.DefaultRegisterer. If the registration fails, NewGaugeFunc panics. -func NewGaugeFunc(opts prometheus.GaugeOpts, function func() float64) prometheus.GaugeFunc { - g := prometheus.NewGaugeFunc(opts, function) - prometheus.MustRegister(g) - return g -} - -// NewSummary works like the function of the same name in the prometheus package -// but it automatically registers the Summary with the -// prometheus.DefaultRegisterer. If the registration fails, NewSummary panics. -func NewSummary(opts prometheus.SummaryOpts) prometheus.Summary { - s := prometheus.NewSummary(opts) - prometheus.MustRegister(s) - return s -} - -// NewSummaryVec works like the function of the same name in the prometheus -// package but it automatically registers the SummaryVec with the -// prometheus.DefaultRegisterer. If the registration fails, NewSummaryVec -// panics. -func NewSummaryVec(opts prometheus.SummaryOpts, labelNames []string) *prometheus.SummaryVec { - s := prometheus.NewSummaryVec(opts, labelNames) - prometheus.MustRegister(s) - return s -} - -// NewHistogram works like the function of the same name in the prometheus -// package but it automatically registers the Histogram with the -// prometheus.DefaultRegisterer. If the registration fails, NewHistogram panics. -func NewHistogram(opts prometheus.HistogramOpts) prometheus.Histogram { - h := prometheus.NewHistogram(opts) - prometheus.MustRegister(h) - return h -} - -// NewHistogramVec works like the function of the same name in the prometheus -// package but it automatically registers the HistogramVec with the -// prometheus.DefaultRegisterer. If the registration fails, NewHistogramVec -// panics. -func NewHistogramVec(opts prometheus.HistogramOpts, labelNames []string) *prometheus.HistogramVec { - h := prometheus.NewHistogramVec(opts, labelNames) - prometheus.MustRegister(h) - return h -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go index 01357374f..668eb6b3c 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go @@ -32,7 +32,6 @@ package promhttp import ( - "bytes" "compress/gzip" "fmt" "io" @@ -53,19 +52,10 @@ const ( acceptEncodingHeader = "Accept-Encoding" ) -var bufPool sync.Pool - -func getBuf() *bytes.Buffer { - buf := bufPool.Get() - if buf == nil { - return &bytes.Buffer{} - } - return buf.(*bytes.Buffer) -} - -func giveBuf(buf *bytes.Buffer) { - buf.Reset() - bufPool.Put(buf) +var gzipPool = sync.Pool{ + New: func() interface{} { + return gzip.NewWriter(nil) + }, } // Handler returns an http.Handler for the prometheus.DefaultGatherer, using @@ -100,19 +90,18 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { inFlightSem = make(chan struct{}, opts.MaxRequestsInFlight) } - h := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + h := http.HandlerFunc(func(rsp http.ResponseWriter, req *http.Request) { if inFlightSem != nil { select { case inFlightSem <- struct{}{}: // All good, carry on. defer func() { <-inFlightSem }() default: - http.Error(w, fmt.Sprintf( + http.Error(rsp, fmt.Sprintf( "Limit of concurrent requests reached (%d), try again later.", opts.MaxRequestsInFlight, ), http.StatusServiceUnavailable) return } } - mfs, err := reg.Gather() if err != nil { if opts.ErrorLog != nil { @@ -123,26 +112,40 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { panic(err) case ContinueOnError: if len(mfs) == 0 { - http.Error(w, "No metrics gathered, last error:\n\n"+err.Error(), http.StatusInternalServerError) + // Still report the error if no metrics have been gathered. + httpError(rsp, err) return } case HTTPErrorOnError: - http.Error(w, "An error has occurred during metrics gathering:\n\n"+err.Error(), http.StatusInternalServerError) + httpError(rsp, err) return } } contentType := expfmt.Negotiate(req.Header) - buf := getBuf() - defer giveBuf(buf) - writer, encoding := decorateWriter(req, buf, opts.DisableCompression) - enc := expfmt.NewEncoder(writer, contentType) + header := rsp.Header() + header.Set(contentTypeHeader, string(contentType)) + + w := io.Writer(rsp) + if !opts.DisableCompression && gzipAccepted(req.Header) { + header.Set(contentEncodingHeader, "gzip") + gz := gzipPool.Get().(*gzip.Writer) + defer gzipPool.Put(gz) + + gz.Reset(w) + defer gz.Close() + + w = gz + } + + enc := expfmt.NewEncoder(w, contentType) + var lastErr error for _, mf := range mfs { if err := enc.Encode(mf); err != nil { lastErr = err if opts.ErrorLog != nil { - opts.ErrorLog.Println("error encoding metric family:", err) + opts.ErrorLog.Println("error encoding and sending metric family:", err) } switch opts.ErrorHandling { case PanicOnError: @@ -150,28 +153,15 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { case ContinueOnError: // Handled later. case HTTPErrorOnError: - http.Error(w, "An error has occurred during metrics encoding:\n\n"+err.Error(), http.StatusInternalServerError) + httpError(rsp, err) return } } } - if closer, ok := writer.(io.Closer); ok { - closer.Close() - } - if lastErr != nil && buf.Len() == 0 { - http.Error(w, "No metrics encoded, last error:\n\n"+lastErr.Error(), http.StatusInternalServerError) - return - } - header := w.Header() - header.Set(contentTypeHeader, string(contentType)) - header.Set(contentLengthHeader, fmt.Sprint(buf.Len())) - if encoding != "" { - header.Set(contentEncodingHeader, encoding) - } - if _, err := w.Write(buf.Bytes()); err != nil && opts.ErrorLog != nil { - opts.ErrorLog.Println("error while sending encoded metrics:", err) + + if lastErr != nil { + httpError(rsp, lastErr) } - // TODO(beorn7): Consider streaming serving of metrics. }) if opts.Timeout <= 0 { @@ -292,20 +282,30 @@ type HandlerOpts struct { Timeout time.Duration } -// decorateWriter wraps a writer to handle gzip compression if requested. It -// returns the decorated writer and the appropriate "Content-Encoding" header -// (which is empty if no compression is enabled). -func decorateWriter(request *http.Request, writer io.Writer, compressionDisabled bool) (io.Writer, string) { - if compressionDisabled { - return writer, "" - } - header := request.Header.Get(acceptEncodingHeader) - parts := strings.Split(header, ",") +// gzipAccepted returns whether the client will accept gzip-encoded content. +func gzipAccepted(header http.Header) bool { + a := header.Get(acceptEncodingHeader) + parts := strings.Split(a, ",") for _, part := range parts { part = strings.TrimSpace(part) if part == "gzip" || strings.HasPrefix(part, "gzip;") { - return gzip.NewWriter(writer), "gzip" + return true } } - return writer, "" + return false +} + +// httpError removes any content-encoding header and then calls http.Error with +// the provided error and http.StatusInternalServerErrer. Error contents is +// supposed to be uncompressed plain text. However, same as with a plain +// http.Error, any header settings will be void if the header has already been +// sent. The error message will still be written to the writer, but it will +// probably be of limited use. +func httpError(rsp http.ResponseWriter, err error) { + rsp.Header().Del(contentEncodingHeader) + http.Error( + rsp, + "An error has occurred while serving metrics:\n\n"+err.Error(), + http.StatusInternalServerError, + ) } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http_test.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http_test.go deleted file mode 100644 index 24d2f8cff..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http_test.go +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright 2016 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package promhttp - -import ( - "bytes" - "errors" - "log" - "net/http" - "net/http/httptest" - "strings" - "testing" - "time" - - "github.com/prometheus/client_golang/prometheus" -) - -type errorCollector struct{} - -func (e errorCollector) Describe(ch chan<- *prometheus.Desc) { - ch <- prometheus.NewDesc("invalid_metric", "not helpful", nil, nil) -} - -func (e errorCollector) Collect(ch chan<- prometheus.Metric) { - ch <- prometheus.NewInvalidMetric( - prometheus.NewDesc("invalid_metric", "not helpful", nil, nil), - errors.New("collect error"), - ) -} - -type blockingCollector struct { - CollectStarted, Block chan struct{} -} - -func (b blockingCollector) Describe(ch chan<- *prometheus.Desc) { - ch <- prometheus.NewDesc("dummy_desc", "not helpful", nil, nil) -} - -func (b blockingCollector) Collect(ch chan<- prometheus.Metric) { - select { - case b.CollectStarted <- struct{}{}: - default: - } - // Collects nothing, just waits for a channel receive. - <-b.Block -} - -func TestHandlerErrorHandling(t *testing.T) { - - // Create a registry that collects a MetricFamily with two elements, - // another with one, and reports an error. - reg := prometheus.NewRegistry() - - cnt := prometheus.NewCounter(prometheus.CounterOpts{ - Name: "the_count", - Help: "Ah-ah-ah! Thunder and lightning!", - }) - reg.MustRegister(cnt) - - cntVec := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "name", - Help: "docstring", - ConstLabels: prometheus.Labels{"constname": "constvalue"}, - }, - []string{"labelname"}, - ) - cntVec.WithLabelValues("val1").Inc() - cntVec.WithLabelValues("val2").Inc() - reg.MustRegister(cntVec) - - reg.MustRegister(errorCollector{}) - - logBuf := &bytes.Buffer{} - logger := log.New(logBuf, "", 0) - - writer := httptest.NewRecorder() - request, _ := http.NewRequest("GET", "/", nil) - request.Header.Add("Accept", "test/plain") - - errorHandler := HandlerFor(reg, HandlerOpts{ - ErrorLog: logger, - ErrorHandling: HTTPErrorOnError, - }) - continueHandler := HandlerFor(reg, HandlerOpts{ - ErrorLog: logger, - ErrorHandling: ContinueOnError, - }) - panicHandler := HandlerFor(reg, HandlerOpts{ - ErrorLog: logger, - ErrorHandling: PanicOnError, - }) - wantMsg := `error gathering metrics: error collecting metric Desc{fqName: "invalid_metric", help: "not helpful", constLabels: {}, variableLabels: []}: collect error -` - wantErrorBody := `An error has occurred during metrics gathering: - -error collecting metric Desc{fqName: "invalid_metric", help: "not helpful", constLabels: {}, variableLabels: []}: collect error -` - wantOKBody := `# HELP name docstring -# TYPE name counter -name{constname="constvalue",labelname="val1"} 1 -name{constname="constvalue",labelname="val2"} 1 -# HELP the_count Ah-ah-ah! Thunder and lightning! -# TYPE the_count counter -the_count 0 -` - - errorHandler.ServeHTTP(writer, request) - if got, want := writer.Code, http.StatusInternalServerError; got != want { - t.Errorf("got HTTP status code %d, want %d", got, want) - } - if got := logBuf.String(); got != wantMsg { - t.Errorf("got log message:\n%s\nwant log message:\n%s\n", got, wantMsg) - } - if got := writer.Body.String(); got != wantErrorBody { - t.Errorf("got body:\n%s\nwant body:\n%s\n", got, wantErrorBody) - } - logBuf.Reset() - writer.Body.Reset() - writer.Code = http.StatusOK - - continueHandler.ServeHTTP(writer, request) - if got, want := writer.Code, http.StatusOK; got != want { - t.Errorf("got HTTP status code %d, want %d", got, want) - } - if got := logBuf.String(); got != wantMsg { - t.Errorf("got log message %q, want %q", got, wantMsg) - } - if got := writer.Body.String(); got != wantOKBody { - t.Errorf("got body %q, want %q", got, wantOKBody) - } - - defer func() { - if err := recover(); err == nil { - t.Error("expected panic from panicHandler") - } - }() - panicHandler.ServeHTTP(writer, request) -} - -func TestInstrumentMetricHandler(t *testing.T) { - reg := prometheus.NewRegistry() - handler := InstrumentMetricHandler(reg, HandlerFor(reg, HandlerOpts{})) - // Do it again to test idempotency. - InstrumentMetricHandler(reg, HandlerFor(reg, HandlerOpts{})) - writer := httptest.NewRecorder() - request, _ := http.NewRequest("GET", "/", nil) - request.Header.Add("Accept", "test/plain") - - handler.ServeHTTP(writer, request) - if got, want := writer.Code, http.StatusOK; got != want { - t.Errorf("got HTTP status code %d, want %d", got, want) - } - - want := "promhttp_metric_handler_requests_in_flight 1\n" - if got := writer.Body.String(); !strings.Contains(got, want) { - t.Errorf("got body %q, does not contain %q", got, want) - } - want = "promhttp_metric_handler_requests_total{code=\"200\"} 0\n" - if got := writer.Body.String(); !strings.Contains(got, want) { - t.Errorf("got body %q, does not contain %q", got, want) - } - - writer.Body.Reset() - handler.ServeHTTP(writer, request) - if got, want := writer.Code, http.StatusOK; got != want { - t.Errorf("got HTTP status code %d, want %d", got, want) - } - - want = "promhttp_metric_handler_requests_in_flight 1\n" - if got := writer.Body.String(); !strings.Contains(got, want) { - t.Errorf("got body %q, does not contain %q", got, want) - } - want = "promhttp_metric_handler_requests_total{code=\"200\"} 1\n" - if got := writer.Body.String(); !strings.Contains(got, want) { - t.Errorf("got body %q, does not contain %q", got, want) - } -} - -func TestHandlerMaxRequestsInFlight(t *testing.T) { - reg := prometheus.NewRegistry() - handler := HandlerFor(reg, HandlerOpts{MaxRequestsInFlight: 1}) - w1 := httptest.NewRecorder() - w2 := httptest.NewRecorder() - w3 := httptest.NewRecorder() - request, _ := http.NewRequest("GET", "/", nil) - request.Header.Add("Accept", "test/plain") - - c := blockingCollector{Block: make(chan struct{}), CollectStarted: make(chan struct{}, 1)} - reg.MustRegister(c) - - rq1Done := make(chan struct{}) - go func() { - handler.ServeHTTP(w1, request) - close(rq1Done) - }() - <-c.CollectStarted - - handler.ServeHTTP(w2, request) - - if got, want := w2.Code, http.StatusServiceUnavailable; got != want { - t.Errorf("got HTTP status code %d, want %d", got, want) - } - if got, want := w2.Body.String(), "Limit of concurrent requests reached (1), try again later.\n"; got != want { - t.Errorf("got body %q, want %q", got, want) - } - - close(c.Block) - <-rq1Done - - handler.ServeHTTP(w3, request) - - if got, want := w3.Code, http.StatusOK; got != want { - t.Errorf("got HTTP status code %d, want %d", got, want) - } -} - -func TestHandlerTimeout(t *testing.T) { - reg := prometheus.NewRegistry() - handler := HandlerFor(reg, HandlerOpts{Timeout: time.Millisecond}) - w := httptest.NewRecorder() - - request, _ := http.NewRequest("GET", "/", nil) - request.Header.Add("Accept", "test/plain") - - c := blockingCollector{Block: make(chan struct{}), CollectStarted: make(chan struct{}, 1)} - reg.MustRegister(c) - - handler.ServeHTTP(w, request) - - if got, want := w.Code, http.StatusServiceUnavailable; got != want { - t.Errorf("got HTTP status code %d, want %d", got, want) - } - if got, want := w.Body.String(), "Exceeded configured timeout of 1ms.\n"; got != want { - t.Errorf("got body %q, want %q", got, want) - } - - close(c.Block) // To not leak a goroutine. -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8_test.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8_test.go deleted file mode 100644 index 7e3f5229f..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8_test.go +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// +build go1.8 - -package promhttp - -import ( - "log" - "net/http" - "testing" - "time" - - "github.com/prometheus/client_golang/prometheus" -) - -func TestClientMiddlewareAPI(t *testing.T) { - client := http.DefaultClient - client.Timeout = 1 * time.Second - - reg := prometheus.NewRegistry() - - inFlightGauge := prometheus.NewGauge(prometheus.GaugeOpts{ - Name: "client_in_flight_requests", - Help: "A gauge of in-flight requests for the wrapped client.", - }) - - counter := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "client_api_requests_total", - Help: "A counter for requests from the wrapped client.", - }, - []string{"code", "method"}, - ) - - dnsLatencyVec := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "dns_duration_seconds", - Help: "Trace dns latency histogram.", - Buckets: []float64{.005, .01, .025, .05}, - }, - []string{"event"}, - ) - - tlsLatencyVec := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "tls_duration_seconds", - Help: "Trace tls latency histogram.", - Buckets: []float64{.05, .1, .25, .5}, - }, - []string{"event"}, - ) - - histVec := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "request_duration_seconds", - Help: "A histogram of request latencies.", - Buckets: prometheus.DefBuckets, - }, - []string{"method"}, - ) - - reg.MustRegister(counter, tlsLatencyVec, dnsLatencyVec, histVec, inFlightGauge) - - trace := &InstrumentTrace{ - DNSStart: func(t float64) { - dnsLatencyVec.WithLabelValues("dns_start") - }, - DNSDone: func(t float64) { - dnsLatencyVec.WithLabelValues("dns_done") - }, - TLSHandshakeStart: func(t float64) { - tlsLatencyVec.WithLabelValues("tls_handshake_start") - }, - TLSHandshakeDone: func(t float64) { - tlsLatencyVec.WithLabelValues("tls_handshake_done") - }, - } - - client.Transport = InstrumentRoundTripperInFlight(inFlightGauge, - InstrumentRoundTripperCounter(counter, - InstrumentRoundTripperTrace(trace, - InstrumentRoundTripperDuration(histVec, http.DefaultTransport), - ), - ), - ) - - resp, err := client.Get("http://google.com") - if err != nil { - t.Fatalf("%v", err) - } - defer resp.Body.Close() -} - -func ExampleInstrumentRoundTripperDuration() { - client := http.DefaultClient - client.Timeout = 1 * time.Second - - inFlightGauge := prometheus.NewGauge(prometheus.GaugeOpts{ - Name: "client_in_flight_requests", - Help: "A gauge of in-flight requests for the wrapped client.", - }) - - counter := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "client_api_requests_total", - Help: "A counter for requests from the wrapped client.", - }, - []string{"code", "method"}, - ) - - // dnsLatencyVec uses custom buckets based on expected dns durations. - // It has an instance label "event", which is set in the - // DNSStart and DNSDonehook functions defined in the - // InstrumentTrace struct below. - dnsLatencyVec := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "dns_duration_seconds", - Help: "Trace dns latency histogram.", - Buckets: []float64{.005, .01, .025, .05}, - }, - []string{"event"}, - ) - - // tlsLatencyVec uses custom buckets based on expected tls durations. - // It has an instance label "event", which is set in the - // TLSHandshakeStart and TLSHandshakeDone hook functions defined in the - // InstrumentTrace struct below. - tlsLatencyVec := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "tls_duration_seconds", - Help: "Trace tls latency histogram.", - Buckets: []float64{.05, .1, .25, .5}, - }, - []string{"event"}, - ) - - // histVec has no labels, making it a zero-dimensional ObserverVec. - histVec := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "request_duration_seconds", - Help: "A histogram of request latencies.", - Buckets: prometheus.DefBuckets, - }, - []string{}, - ) - - // Register all of the metrics in the standard registry. - prometheus.MustRegister(counter, tlsLatencyVec, dnsLatencyVec, histVec, inFlightGauge) - - // Define functions for the available httptrace.ClientTrace hook - // functions that we want to instrument. - trace := &InstrumentTrace{ - DNSStart: func(t float64) { - dnsLatencyVec.WithLabelValues("dns_start") - }, - DNSDone: func(t float64) { - dnsLatencyVec.WithLabelValues("dns_done") - }, - TLSHandshakeStart: func(t float64) { - tlsLatencyVec.WithLabelValues("tls_handshake_start") - }, - TLSHandshakeDone: func(t float64) { - tlsLatencyVec.WithLabelValues("tls_handshake_done") - }, - } - - // Wrap the default RoundTripper with middleware. - roundTripper := InstrumentRoundTripperInFlight(inFlightGauge, - InstrumentRoundTripperCounter(counter, - InstrumentRoundTripperTrace(trace, - InstrumentRoundTripperDuration(histVec, http.DefaultTransport), - ), - ), - ) - - // Set the RoundTripper on our client. - client.Transport = roundTripper - - resp, err := client.Get("http://google.com") - if err != nil { - log.Printf("error: %v", err) - } - defer resp.Body.Close() -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server_test.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server_test.go deleted file mode 100644 index 716c6f45e..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server_test.go +++ /dev/null @@ -1,401 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package promhttp - -import ( - "io" - "log" - "net/http" - "net/http/httptest" - "testing" - - "github.com/prometheus/client_golang/prometheus" -) - -func TestLabelCheck(t *testing.T) { - scenarios := map[string]struct { - varLabels []string - constLabels []string - curriedLabels []string - ok bool - }{ - "empty": { - varLabels: []string{}, - constLabels: []string{}, - curriedLabels: []string{}, - ok: true, - }, - "code as single var label": { - varLabels: []string{"code"}, - constLabels: []string{}, - curriedLabels: []string{}, - ok: true, - }, - "method as single var label": { - varLabels: []string{"method"}, - constLabels: []string{}, - curriedLabels: []string{}, - ok: true, - }, - "cade and method as var labels": { - varLabels: []string{"method", "code"}, - constLabels: []string{}, - curriedLabels: []string{}, - ok: true, - }, - "valid case with all labels used": { - varLabels: []string{"code", "method"}, - constLabels: []string{"foo", "bar"}, - curriedLabels: []string{"dings", "bums"}, - ok: true, - }, - "unsupported var label": { - varLabels: []string{"foo"}, - constLabels: []string{}, - curriedLabels: []string{}, - ok: false, - }, - "mixed var labels": { - varLabels: []string{"method", "foo", "code"}, - constLabels: []string{}, - curriedLabels: []string{}, - ok: false, - }, - "unsupported var label but curried": { - varLabels: []string{}, - constLabels: []string{}, - curriedLabels: []string{"foo"}, - ok: true, - }, - "mixed var labels but unsupported curried": { - varLabels: []string{"code", "method"}, - constLabels: []string{}, - curriedLabels: []string{"foo"}, - ok: true, - }, - "supported label as const and curry": { - varLabels: []string{}, - constLabels: []string{"code"}, - curriedLabels: []string{"method"}, - ok: true, - }, - "supported label as const and curry with unsupported as var": { - varLabels: []string{"foo"}, - constLabels: []string{"code"}, - curriedLabels: []string{"method"}, - ok: false, - }, - } - - for name, sc := range scenarios { - t.Run(name, func(t *testing.T) { - constLabels := prometheus.Labels{} - for _, l := range sc.constLabels { - constLabels[l] = "dummy" - } - c := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "c", - Help: "c help", - ConstLabels: constLabels, - }, - append(sc.varLabels, sc.curriedLabels...), - ) - o := prometheus.ObserverVec(prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "c", - Help: "c help", - ConstLabels: constLabels, - }, - append(sc.varLabels, sc.curriedLabels...), - )) - for _, l := range sc.curriedLabels { - c = c.MustCurryWith(prometheus.Labels{l: "dummy"}) - o = o.MustCurryWith(prometheus.Labels{l: "dummy"}) - } - - func() { - defer func() { - if err := recover(); err != nil { - if sc.ok { - t.Error("unexpected panic:", err) - } - } else if !sc.ok { - t.Error("expected panic") - } - }() - InstrumentHandlerCounter(c, nil) - }() - func() { - defer func() { - if err := recover(); err != nil { - if sc.ok { - t.Error("unexpected panic:", err) - } - } else if !sc.ok { - t.Error("expected panic") - } - }() - InstrumentHandlerDuration(o, nil) - }() - if sc.ok { - // Test if wantCode and wantMethod were detected correctly. - var wantCode, wantMethod bool - for _, l := range sc.varLabels { - if l == "code" { - wantCode = true - } - if l == "method" { - wantMethod = true - } - } - gotCode, gotMethod := checkLabels(c) - if gotCode != wantCode { - t.Errorf("wanted code=%t for counter, got code=%t", wantCode, gotCode) - } - if gotMethod != wantMethod { - t.Errorf("wanted method=%t for counter, got method=%t", wantMethod, gotMethod) - } - gotCode, gotMethod = checkLabels(o) - if gotCode != wantCode { - t.Errorf("wanted code=%t for observer, got code=%t", wantCode, gotCode) - } - if gotMethod != wantMethod { - t.Errorf("wanted method=%t for observer, got method=%t", wantMethod, gotMethod) - } - } - }) - } -} - -func TestMiddlewareAPI(t *testing.T) { - reg := prometheus.NewRegistry() - - inFlightGauge := prometheus.NewGauge(prometheus.GaugeOpts{ - Name: "in_flight_requests", - Help: "A gauge of requests currently being served by the wrapped handler.", - }) - - counter := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "api_requests_total", - Help: "A counter for requests to the wrapped handler.", - }, - []string{"code", "method"}, - ) - - histVec := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "response_duration_seconds", - Help: "A histogram of request latencies.", - Buckets: prometheus.DefBuckets, - ConstLabels: prometheus.Labels{"handler": "api"}, - }, - []string{"method"}, - ) - - writeHeaderVec := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "write_header_duration_seconds", - Help: "A histogram of time to first write latencies.", - Buckets: prometheus.DefBuckets, - ConstLabels: prometheus.Labels{"handler": "api"}, - }, - []string{}, - ) - - responseSize := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "push_request_size_bytes", - Help: "A histogram of request sizes for requests.", - Buckets: []float64{200, 500, 900, 1500}, - }, - []string{}, - ) - - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("OK")) - }) - - reg.MustRegister(inFlightGauge, counter, histVec, responseSize, writeHeaderVec) - - chain := InstrumentHandlerInFlight(inFlightGauge, - InstrumentHandlerCounter(counter, - InstrumentHandlerDuration(histVec, - InstrumentHandlerTimeToWriteHeader(writeHeaderVec, - InstrumentHandlerResponseSize(responseSize, handler), - ), - ), - ), - ) - - r, _ := http.NewRequest("GET", "www.example.com", nil) - w := httptest.NewRecorder() - chain.ServeHTTP(w, r) -} - -func TestInstrumentTimeToFirstWrite(t *testing.T) { - var i int - dobs := &responseWriterDelegator{ - ResponseWriter: httptest.NewRecorder(), - observeWriteHeader: func(status int) { - i = status - }, - } - d := newDelegator(dobs, nil) - - d.WriteHeader(http.StatusOK) - - if i != http.StatusOK { - t.Fatalf("failed to execute observeWriteHeader") - } -} - -// testResponseWriter is an http.ResponseWriter that also implements -// http.CloseNotifier, http.Flusher, and io.ReaderFrom. -type testResponseWriter struct { - closeNotifyCalled, flushCalled, readFromCalled bool -} - -func (t *testResponseWriter) Header() http.Header { return nil } -func (t *testResponseWriter) Write([]byte) (int, error) { return 0, nil } -func (t *testResponseWriter) WriteHeader(int) {} -func (t *testResponseWriter) CloseNotify() <-chan bool { - t.closeNotifyCalled = true - return nil -} -func (t *testResponseWriter) Flush() { t.flushCalled = true } -func (t *testResponseWriter) ReadFrom(io.Reader) (int64, error) { - t.readFromCalled = true - return 0, nil -} - -// testFlusher is an http.ResponseWriter that also implements http.Flusher. -type testFlusher struct { - flushCalled bool -} - -func (t *testFlusher) Header() http.Header { return nil } -func (t *testFlusher) Write([]byte) (int, error) { return 0, nil } -func (t *testFlusher) WriteHeader(int) {} -func (t *testFlusher) Flush() { t.flushCalled = true } - -func TestInterfaceUpgrade(t *testing.T) { - w := &testResponseWriter{} - d := newDelegator(w, nil) - d.(http.CloseNotifier).CloseNotify() - if !w.closeNotifyCalled { - t.Error("CloseNotify not called") - } - d.(http.Flusher).Flush() - if !w.flushCalled { - t.Error("Flush not called") - } - d.(io.ReaderFrom).ReadFrom(nil) - if !w.readFromCalled { - t.Error("ReadFrom not called") - } - if _, ok := d.(http.Hijacker); ok { - t.Error("delegator unexpectedly implements http.Hijacker") - } - - f := &testFlusher{} - d = newDelegator(f, nil) - if _, ok := d.(http.CloseNotifier); ok { - t.Error("delegator unexpectedly implements http.CloseNotifier") - } - d.(http.Flusher).Flush() - if !w.flushCalled { - t.Error("Flush not called") - } - if _, ok := d.(io.ReaderFrom); ok { - t.Error("delegator unexpectedly implements io.ReaderFrom") - } - if _, ok := d.(http.Hijacker); ok { - t.Error("delegator unexpectedly implements http.Hijacker") - } -} - -func ExampleInstrumentHandlerDuration() { - inFlightGauge := prometheus.NewGauge(prometheus.GaugeOpts{ - Name: "in_flight_requests", - Help: "A gauge of requests currently being served by the wrapped handler.", - }) - - counter := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "api_requests_total", - Help: "A counter for requests to the wrapped handler.", - }, - []string{"code", "method"}, - ) - - // duration is partitioned by the HTTP method and handler. It uses custom - // buckets based on the expected request duration. - duration := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "request_duration_seconds", - Help: "A histogram of latencies for requests.", - Buckets: []float64{.25, .5, 1, 2.5, 5, 10}, - }, - []string{"handler", "method"}, - ) - - // responseSize has no labels, making it a zero-dimensional - // ObserverVec. - responseSize := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "response_size_bytes", - Help: "A histogram of response sizes for requests.", - Buckets: []float64{200, 500, 900, 1500}, - }, - []string{}, - ) - - // Create the handlers that will be wrapped by the middleware. - pushHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("Push")) - }) - pullHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("Pull")) - }) - - // Register all of the metrics in the standard registry. - prometheus.MustRegister(inFlightGauge, counter, duration, responseSize) - - // Instrument the handlers with all the metrics, injecting the "handler" - // label by currying. - pushChain := InstrumentHandlerInFlight(inFlightGauge, - InstrumentHandlerDuration(duration.MustCurryWith(prometheus.Labels{"handler": "push"}), - InstrumentHandlerCounter(counter, - InstrumentHandlerResponseSize(responseSize, pushHandler), - ), - ), - ) - pullChain := InstrumentHandlerInFlight(inFlightGauge, - InstrumentHandlerDuration(duration.MustCurryWith(prometheus.Labels{"handler": "pull"}), - InstrumentHandlerCounter(counter, - InstrumentHandlerResponseSize(responseSize, pullHandler), - ), - ), - ) - - http.Handle("/metrics", Handler()) - http.Handle("/push", pushChain) - http.Handle("/pull", pullChain) - - if err := http.ListenAndServe(":3000", nil); err != nil { - log.Fatal(err) - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/registry.go b/vendor/github.com/prometheus/client_golang/prometheus/registry.go index e422ef383..f98c81a86 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/registry.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/registry.go @@ -16,6 +16,9 @@ package prometheus import ( "bytes" "fmt" + "io/ioutil" + "os" + "path/filepath" "runtime" "sort" "strings" @@ -23,6 +26,7 @@ import ( "unicode/utf8" "github.com/golang/protobuf/proto" + "github.com/prometheus/common/expfmt" dto "github.com/prometheus/client_model/go" @@ -533,6 +537,38 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) { return internal.NormalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap() } +// WriteToTextfile calls Gather on the provided Gatherer, encodes the result in the +// Prometheus text format, and writes it to a temporary file. Upon success, the +// temporary file is renamed to the provided filename. +// +// This is intended for use with the textfile collector of the node exporter. +// Note that the node exporter expects the filename to be suffixed with ".prom". +func WriteToTextfile(filename string, g Gatherer) error { + tmp, err := ioutil.TempFile(filepath.Dir(filename), filepath.Base(filename)) + if err != nil { + return err + } + defer os.Remove(tmp.Name()) + + mfs, err := g.Gather() + if err != nil { + return err + } + for _, mf := range mfs { + if _, err := expfmt.MetricFamilyToText(tmp, mf); err != nil { + return err + } + } + if err := tmp.Close(); err != nil { + return err + } + + if err := os.Chmod(tmp.Name(), 0644); err != nil { + return err + } + return os.Rename(tmp.Name(), filename) +} + // processMetric is an internal helper method only used by the Gather method. func processMetric( metric Metric, diff --git a/vendor/github.com/prometheus/client_golang/prometheus/registry_test.go b/vendor/github.com/prometheus/client_golang/prometheus/registry_test.go deleted file mode 100644 index d05ac9ad0..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/registry_test.go +++ /dev/null @@ -1,873 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Copyright (c) 2013, The Prometheus Authors -// All rights reserved. -// -// Use of this source code is governed by a BSD-style license that can be found -// in the LICENSE file. - -package prometheus_test - -import ( - "bytes" - "math/rand" - "net/http" - "net/http/httptest" - "sync" - "testing" - "time" - - dto "github.com/prometheus/client_model/go" - - "github.com/golang/protobuf/proto" - "github.com/prometheus/common/expfmt" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" -) - -// uncheckedCollector wraps a Collector but its Describe method yields no Desc. -type uncheckedCollector struct { - c prometheus.Collector -} - -func (u uncheckedCollector) Describe(_ chan<- *prometheus.Desc) {} -func (u uncheckedCollector) Collect(c chan<- prometheus.Metric) { - u.c.Collect(c) -} - -func testHandler(t testing.TB) { - // TODO(beorn7): This test is a bit too "end-to-end". It tests quite a - // few moving parts that are not strongly coupled. They could/should be - // tested separately. However, the changes planned for v0.10 will - // require a major rework of this test anyway, at which time I will - // structure it in a better way. - - metricVec := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "name", - Help: "docstring", - ConstLabels: prometheus.Labels{"constname": "constvalue"}, - }, - []string{"labelname"}, - ) - - metricVec.WithLabelValues("val1").Inc() - metricVec.WithLabelValues("val2").Inc() - - externalMetricFamily := &dto.MetricFamily{ - Name: proto.String("externalname"), - Help: proto.String("externaldocstring"), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{ - { - Label: []*dto.LabelPair{ - { - Name: proto.String("externalconstname"), - Value: proto.String("externalconstvalue"), - }, - { - Name: proto.String("externallabelname"), - Value: proto.String("externalval1"), - }, - }, - Counter: &dto.Counter{ - Value: proto.Float64(1), - }, - }, - }, - } - externalBuf := &bytes.Buffer{} - enc := expfmt.NewEncoder(externalBuf, expfmt.FmtProtoDelim) - if err := enc.Encode(externalMetricFamily); err != nil { - t.Fatal(err) - } - externalMetricFamilyAsBytes := externalBuf.Bytes() - externalMetricFamilyAsText := []byte(`# HELP externalname externaldocstring -# TYPE externalname counter -externalname{externalconstname="externalconstvalue",externallabelname="externalval1"} 1 -`) - externalMetricFamilyAsProtoText := []byte(`name: "externalname" -help: "externaldocstring" -type: COUNTER -metric: < - label: < - name: "externalconstname" - value: "externalconstvalue" - > - label: < - name: "externallabelname" - value: "externalval1" - > - counter: < - value: 1 - > -> - -`) - externalMetricFamilyAsProtoCompactText := []byte(`name:"externalname" help:"externaldocstring" type:COUNTER metric: label: counter: > -`) - - expectedMetricFamily := &dto.MetricFamily{ - Name: proto.String("name"), - Help: proto.String("docstring"), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{ - { - Label: []*dto.LabelPair{ - { - Name: proto.String("constname"), - Value: proto.String("constvalue"), - }, - { - Name: proto.String("labelname"), - Value: proto.String("val1"), - }, - }, - Counter: &dto.Counter{ - Value: proto.Float64(1), - }, - }, - { - Label: []*dto.LabelPair{ - { - Name: proto.String("constname"), - Value: proto.String("constvalue"), - }, - { - Name: proto.String("labelname"), - Value: proto.String("val2"), - }, - }, - Counter: &dto.Counter{ - Value: proto.Float64(1), - }, - }, - }, - } - buf := &bytes.Buffer{} - enc = expfmt.NewEncoder(buf, expfmt.FmtProtoDelim) - if err := enc.Encode(expectedMetricFamily); err != nil { - t.Fatal(err) - } - expectedMetricFamilyAsBytes := buf.Bytes() - expectedMetricFamilyAsText := []byte(`# HELP name docstring -# TYPE name counter -name{constname="constvalue",labelname="val1"} 1 -name{constname="constvalue",labelname="val2"} 1 -`) - expectedMetricFamilyAsProtoText := []byte(`name: "name" -help: "docstring" -type: COUNTER -metric: < - label: < - name: "constname" - value: "constvalue" - > - label: < - name: "labelname" - value: "val1" - > - counter: < - value: 1 - > -> -metric: < - label: < - name: "constname" - value: "constvalue" - > - label: < - name: "labelname" - value: "val2" - > - counter: < - value: 1 - > -> - -`) - expectedMetricFamilyAsProtoCompactText := []byte(`name:"name" help:"docstring" type:COUNTER metric: label: counter: > metric: label: counter: > -`) - - externalMetricFamilyWithSameName := &dto.MetricFamily{ - Name: proto.String("name"), - Help: proto.String("docstring"), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{ - { - Label: []*dto.LabelPair{ - { - Name: proto.String("constname"), - Value: proto.String("constvalue"), - }, - { - Name: proto.String("labelname"), - Value: proto.String("different_val"), - }, - }, - Counter: &dto.Counter{ - Value: proto.Float64(42), - }, - }, - }, - } - - expectedMetricFamilyMergedWithExternalAsProtoCompactText := []byte(`name:"name" help:"docstring" type:COUNTER metric: label: counter: > metric: label: counter: > metric: label: counter: > -`) - - externalMetricFamilyWithInvalidLabelValue := &dto.MetricFamily{ - Name: proto.String("name"), - Help: proto.String("docstring"), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{ - { - Label: []*dto.LabelPair{ - { - Name: proto.String("constname"), - Value: proto.String("\xFF"), - }, - { - Name: proto.String("labelname"), - Value: proto.String("different_val"), - }, - }, - Counter: &dto.Counter{ - Value: proto.Float64(42), - }, - }, - }, - } - - expectedMetricFamilyInvalidLabelValueAsText := []byte(`An error has occurred during metrics gathering: - -collected metric "name" { label: label: counter: } has a label named "constname" whose value is not utf8: "\xff" -`) - - summary := prometheus.NewSummary(prometheus.SummaryOpts{ - Name: "complex", - Help: "A metric to check collisions with _sum and _count.", - }) - summaryAsText := []byte(`# HELP complex A metric to check collisions with _sum and _count. -# TYPE complex summary -complex{quantile="0.5"} NaN -complex{quantile="0.9"} NaN -complex{quantile="0.99"} NaN -complex_sum 0 -complex_count 0 -`) - histogram := prometheus.NewHistogram(prometheus.HistogramOpts{ - Name: "complex", - Help: "A metric to check collisions with _sun, _count, and _bucket.", - }) - externalMetricFamilyWithBucketSuffix := &dto.MetricFamily{ - Name: proto.String("complex_bucket"), - Help: proto.String("externaldocstring"), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{ - { - Counter: &dto.Counter{ - Value: proto.Float64(1), - }, - }, - }, - } - externalMetricFamilyWithBucketSuffixAsText := []byte(`# HELP complex_bucket externaldocstring -# TYPE complex_bucket counter -complex_bucket 1 -`) - externalMetricFamilyWithCountSuffix := &dto.MetricFamily{ - Name: proto.String("complex_count"), - Help: proto.String("externaldocstring"), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{ - { - Counter: &dto.Counter{ - Value: proto.Float64(1), - }, - }, - }, - } - bucketCollisionMsg := []byte(`An error has occurred during metrics gathering: - -collected metric named "complex_bucket" collides with previously collected histogram named "complex" -`) - summaryCountCollisionMsg := []byte(`An error has occurred during metrics gathering: - -collected metric named "complex_count" collides with previously collected summary named "complex" -`) - histogramCountCollisionMsg := []byte(`An error has occurred during metrics gathering: - -collected metric named "complex_count" collides with previously collected histogram named "complex" -`) - externalMetricFamilyWithDuplicateLabel := &dto.MetricFamily{ - Name: proto.String("broken_metric"), - Help: proto.String("The registry should detect the duplicate label."), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{ - { - Label: []*dto.LabelPair{ - { - Name: proto.String("foo"), - Value: proto.String("bar"), - }, - { - Name: proto.String("foo"), - Value: proto.String("baz"), - }, - }, - Counter: &dto.Counter{ - Value: proto.Float64(2.7), - }, - }, - }, - } - duplicateLabelMsg := []byte(`An error has occurred during metrics gathering: - -collected metric "broken_metric" { label: label: counter: } has two or more labels with the same name: foo -`) - - type output struct { - headers map[string]string - body []byte - } - - var scenarios = []struct { - headers map[string]string - out output - collector prometheus.Collector - externalMF []*dto.MetricFamily - }{ - { // 0 - headers: map[string]string{ - "Accept": "foo/bar;q=0.2, dings/bums;q=0.8", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; version=0.0.4; charset=utf-8`, - }, - body: []byte{}, - }, - }, - { // 1 - headers: map[string]string{ - "Accept": "foo/bar;q=0.2, application/quark;q=0.8", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; version=0.0.4; charset=utf-8`, - }, - body: []byte{}, - }, - }, - { // 2 - headers: map[string]string{ - "Accept": "foo/bar;q=0.2, application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=bla;q=0.8", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; version=0.0.4; charset=utf-8`, - }, - body: []byte{}, - }, - }, - { // 3 - headers: map[string]string{ - "Accept": "text/plain;q=0.2, application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited;q=0.8", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`, - }, - body: []byte{}, - }, - }, - { // 4 - headers: map[string]string{ - "Accept": "application/json", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; version=0.0.4; charset=utf-8`, - }, - body: expectedMetricFamilyAsText, - }, - collector: metricVec, - }, - { // 5 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`, - }, - body: expectedMetricFamilyAsBytes, - }, - collector: metricVec, - }, - { // 6 - headers: map[string]string{ - "Accept": "application/json", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; version=0.0.4; charset=utf-8`, - }, - body: externalMetricFamilyAsText, - }, - externalMF: []*dto.MetricFamily{externalMetricFamily}, - }, - { // 7 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`, - }, - body: externalMetricFamilyAsBytes, - }, - externalMF: []*dto.MetricFamily{externalMetricFamily}, - }, - { // 8 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`, - }, - body: bytes.Join( - [][]byte{ - externalMetricFamilyAsBytes, - expectedMetricFamilyAsBytes, - }, - []byte{}, - ), - }, - collector: metricVec, - externalMF: []*dto.MetricFamily{externalMetricFamily}, - }, - { // 9 - headers: map[string]string{ - "Accept": "text/plain", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; version=0.0.4; charset=utf-8`, - }, - body: []byte{}, - }, - }, - { // 10 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=bla;q=0.2, text/plain;q=0.5", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; version=0.0.4; charset=utf-8`, - }, - body: expectedMetricFamilyAsText, - }, - collector: metricVec, - }, - { // 11 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=bla;q=0.2, text/plain;q=0.5;version=0.0.4", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; version=0.0.4; charset=utf-8`, - }, - body: bytes.Join( - [][]byte{ - externalMetricFamilyAsText, - expectedMetricFamilyAsText, - }, - []byte{}, - ), - }, - collector: metricVec, - externalMF: []*dto.MetricFamily{externalMetricFamily}, - }, - { // 12 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited;q=0.2, text/plain;q=0.5;version=0.0.2", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`, - }, - body: bytes.Join( - [][]byte{ - externalMetricFamilyAsBytes, - expectedMetricFamilyAsBytes, - }, - []byte{}, - ), - }, - collector: metricVec, - externalMF: []*dto.MetricFamily{externalMetricFamily}, - }, - { // 13 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=text;q=0.5, application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited;q=0.4", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=text`, - }, - body: bytes.Join( - [][]byte{ - externalMetricFamilyAsProtoText, - expectedMetricFamilyAsProtoText, - }, - []byte{}, - ), - }, - collector: metricVec, - externalMF: []*dto.MetricFamily{externalMetricFamily}, - }, - { // 14 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=compact-text", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=compact-text`, - }, - body: bytes.Join( - [][]byte{ - externalMetricFamilyAsProtoCompactText, - expectedMetricFamilyAsProtoCompactText, - }, - []byte{}, - ), - }, - collector: metricVec, - externalMF: []*dto.MetricFamily{externalMetricFamily}, - }, - { // 15 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=compact-text", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=compact-text`, - }, - body: bytes.Join( - [][]byte{ - externalMetricFamilyAsProtoCompactText, - expectedMetricFamilyMergedWithExternalAsProtoCompactText, - }, - []byte{}, - ), - }, - collector: metricVec, - externalMF: []*dto.MetricFamily{ - externalMetricFamily, - externalMetricFamilyWithSameName, - }, - }, - { // 16 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=compact-text", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; charset=utf-8`, - }, - body: expectedMetricFamilyInvalidLabelValueAsText, - }, - collector: metricVec, - externalMF: []*dto.MetricFamily{ - externalMetricFamily, - externalMetricFamilyWithInvalidLabelValue, - }, - }, - { // 17 - headers: map[string]string{ - "Accept": "text/plain", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; version=0.0.4; charset=utf-8`, - }, - body: expectedMetricFamilyAsText, - }, - collector: uncheckedCollector{metricVec}, - }, - { // 18 - headers: map[string]string{ - "Accept": "text/plain", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; charset=utf-8`, - }, - body: histogramCountCollisionMsg, - }, - collector: histogram, - externalMF: []*dto.MetricFamily{ - externalMetricFamilyWithCountSuffix, - }, - }, - { // 19 - headers: map[string]string{ - "Accept": "text/plain", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; charset=utf-8`, - }, - body: bucketCollisionMsg, - }, - collector: histogram, - externalMF: []*dto.MetricFamily{ - externalMetricFamilyWithBucketSuffix, - }, - }, - { // 20 - headers: map[string]string{ - "Accept": "text/plain", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; charset=utf-8`, - }, - body: summaryCountCollisionMsg, - }, - collector: summary, - externalMF: []*dto.MetricFamily{ - externalMetricFamilyWithCountSuffix, - }, - }, - { // 21 - headers: map[string]string{ - "Accept": "text/plain", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; version=0.0.4; charset=utf-8`, - }, - body: bytes.Join( - [][]byte{ - summaryAsText, - externalMetricFamilyWithBucketSuffixAsText, - }, - []byte{}, - ), - }, - collector: summary, - externalMF: []*dto.MetricFamily{ - externalMetricFamilyWithBucketSuffix, - }, - }, - { // 22 - headers: map[string]string{ - "Accept": "text/plain", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; charset=utf-8`, - }, - body: duplicateLabelMsg, - }, - externalMF: []*dto.MetricFamily{ - externalMetricFamilyWithDuplicateLabel, - }, - }, - } - for i, scenario := range scenarios { - registry := prometheus.NewPedanticRegistry() - gatherer := prometheus.Gatherer(registry) - if scenario.externalMF != nil { - gatherer = prometheus.Gatherers{ - registry, - prometheus.GathererFunc(func() ([]*dto.MetricFamily, error) { - return scenario.externalMF, nil - }), - } - } - - if scenario.collector != nil { - registry.MustRegister(scenario.collector) - } - writer := httptest.NewRecorder() - handler := prometheus.InstrumentHandler("prometheus", promhttp.HandlerFor(gatherer, promhttp.HandlerOpts{})) - request, _ := http.NewRequest("GET", "/", nil) - for key, value := range scenario.headers { - request.Header.Add(key, value) - } - handler(writer, request) - - for key, value := range scenario.out.headers { - if writer.Header().Get(key) != value { - t.Errorf( - "%d. expected %q for header %q, got %q", - i, value, key, writer.Header().Get(key), - ) - } - } - - if !bytes.Equal(scenario.out.body, writer.Body.Bytes()) { - t.Errorf( - "%d. expected body:\n%s\ngot body:\n%s\n", - i, scenario.out.body, writer.Body.Bytes(), - ) - } - } -} - -func TestHandler(t *testing.T) { - testHandler(t) -} - -func BenchmarkHandler(b *testing.B) { - for i := 0; i < b.N; i++ { - testHandler(b) - } -} - -func TestAlreadyRegistered(t *testing.T) { - reg := prometheus.NewRegistry() - original := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "test", - Help: "help", - }, - []string{"foo", "bar"}, - ) - equalButNotSame := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "test", - Help: "help", - }, - []string{"foo", "bar"}, - ) - var err error - if err = reg.Register(original); err != nil { - t.Fatal(err) - } - if err = reg.Register(equalButNotSame); err == nil { - t.Fatal("expected error when registering equal collector") - } - if are, ok := err.(prometheus.AlreadyRegisteredError); ok { - if are.ExistingCollector != original { - t.Error("expected original collector but got something else") - } - if are.ExistingCollector == equalButNotSame { - t.Error("expected original callector but got new one") - } - } else { - t.Error("unexpected error:", err) - } -} - -// TestHistogramVecRegisterGatherConcurrency is an end-to-end test that -// concurrently calls Observe on random elements of a HistogramVec while the -// same HistogramVec is registered concurrently and the Gather method of the -// registry is called concurrently. -func TestHistogramVecRegisterGatherConcurrency(t *testing.T) { - var ( - reg = prometheus.NewPedanticRegistry() - hv = prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "test_histogram", - Help: "This helps testing.", - ConstLabels: prometheus.Labels{"foo": "bar"}, - }, - []string{"one", "two", "three"}, - ) - labelValues = []string{"a", "b", "c", "alpha", "beta", "gamma", "aleph", "beth", "gimel"} - quit = make(chan struct{}) - wg sync.WaitGroup - ) - - observe := func() { - defer wg.Done() - for { - select { - case <-quit: - return - default: - obs := rand.NormFloat64()*.1 + .2 - hv.WithLabelValues( - labelValues[rand.Intn(len(labelValues))], - labelValues[rand.Intn(len(labelValues))], - labelValues[rand.Intn(len(labelValues))], - ).Observe(obs) - } - } - } - - register := func() { - defer wg.Done() - for { - select { - case <-quit: - return - default: - if err := reg.Register(hv); err != nil { - if _, ok := err.(prometheus.AlreadyRegisteredError); !ok { - t.Error("Registering failed:", err) - } - } - time.Sleep(7 * time.Millisecond) - } - } - } - - gather := func() { - defer wg.Done() - for { - select { - case <-quit: - return - default: - if g, err := reg.Gather(); err != nil { - t.Error("Gathering failed:", err) - } else { - if len(g) == 0 { - continue - } - if len(g) != 1 { - t.Error("Gathered unexpected number of metric families:", len(g)) - } - if len(g[0].Metric[0].Label) != 4 { - t.Error("Gathered unexpected number of label pairs:", len(g[0].Metric[0].Label)) - } - } - time.Sleep(4 * time.Millisecond) - } - } - } - - wg.Add(10) - go observe() - go observe() - go register() - go observe() - go gather() - go observe() - go register() - go observe() - go gather() - go observe() - - time.Sleep(time.Second) - close(quit) - wg.Wait() -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/summary.go b/vendor/github.com/prometheus/client_golang/prometheus/summary.go index f7e92d829..2980614df 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/summary.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/summary.go @@ -181,7 +181,7 @@ func NewSummary(opts SummaryOpts) Summary { func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary { if len(desc.variableLabels) != len(labelValues) { - panic(errInconsistentCardinality) + panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, labelValues)) } for _, n := range desc.variableLabels { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/summary_test.go b/vendor/github.com/prometheus/client_golang/prometheus/summary_test.go deleted file mode 100644 index 8b1a62eee..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/summary_test.go +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "math" - "math/rand" - "sort" - "sync" - "testing" - "testing/quick" - "time" - - dto "github.com/prometheus/client_model/go" -) - -func TestSummaryWithDefaultObjectives(t *testing.T) { - reg := NewRegistry() - summaryWithDefaultObjectives := NewSummary(SummaryOpts{ - Name: "default_objectives", - Help: "Test help.", - }) - if err := reg.Register(summaryWithDefaultObjectives); err != nil { - t.Error(err) - } - - m := &dto.Metric{} - if err := summaryWithDefaultObjectives.Write(m); err != nil { - t.Error(err) - } - if len(m.GetSummary().Quantile) != len(DefObjectives) { - t.Error("expected default objectives in summary") - } -} - -func TestSummaryWithoutObjectives(t *testing.T) { - reg := NewRegistry() - summaryWithEmptyObjectives := NewSummary(SummaryOpts{ - Name: "empty_objectives", - Help: "Test help.", - Objectives: map[float64]float64{}, - }) - if err := reg.Register(summaryWithEmptyObjectives); err != nil { - t.Error(err) - } - - m := &dto.Metric{} - if err := summaryWithEmptyObjectives.Write(m); err != nil { - t.Error(err) - } - if len(m.GetSummary().Quantile) != 0 { - t.Error("expected no objectives in summary") - } -} - -func TestSummaryWithQuantileLabel(t *testing.T) { - defer func() { - if r := recover(); r == nil { - t.Error("Attempt to create Summary with 'quantile' label did not panic.") - } - }() - _ = NewSummary(SummaryOpts{ - Name: "test_summary", - Help: "less", - ConstLabels: Labels{"quantile": "test"}, - }) -} - -func TestSummaryVecWithQuantileLabel(t *testing.T) { - defer func() { - if r := recover(); r == nil { - t.Error("Attempt to create SummaryVec with 'quantile' label did not panic.") - } - }() - _ = NewSummaryVec(SummaryOpts{ - Name: "test_summary", - Help: "less", - }, []string{"quantile"}) -} - -func benchmarkSummaryObserve(w int, b *testing.B) { - b.StopTimer() - - wg := new(sync.WaitGroup) - wg.Add(w) - - g := new(sync.WaitGroup) - g.Add(1) - - s := NewSummary(SummaryOpts{}) - - for i := 0; i < w; i++ { - go func() { - g.Wait() - - for i := 0; i < b.N; i++ { - s.Observe(float64(i)) - } - - wg.Done() - }() - } - - b.StartTimer() - g.Done() - wg.Wait() -} - -func BenchmarkSummaryObserve1(b *testing.B) { - benchmarkSummaryObserve(1, b) -} - -func BenchmarkSummaryObserve2(b *testing.B) { - benchmarkSummaryObserve(2, b) -} - -func BenchmarkSummaryObserve4(b *testing.B) { - benchmarkSummaryObserve(4, b) -} - -func BenchmarkSummaryObserve8(b *testing.B) { - benchmarkSummaryObserve(8, b) -} - -func benchmarkSummaryWrite(w int, b *testing.B) { - b.StopTimer() - - wg := new(sync.WaitGroup) - wg.Add(w) - - g := new(sync.WaitGroup) - g.Add(1) - - s := NewSummary(SummaryOpts{}) - - for i := 0; i < 1000000; i++ { - s.Observe(float64(i)) - } - - for j := 0; j < w; j++ { - outs := make([]dto.Metric, b.N) - - go func(o []dto.Metric) { - g.Wait() - - for i := 0; i < b.N; i++ { - s.Write(&o[i]) - } - - wg.Done() - }(outs) - } - - b.StartTimer() - g.Done() - wg.Wait() -} - -func BenchmarkSummaryWrite1(b *testing.B) { - benchmarkSummaryWrite(1, b) -} - -func BenchmarkSummaryWrite2(b *testing.B) { - benchmarkSummaryWrite(2, b) -} - -func BenchmarkSummaryWrite4(b *testing.B) { - benchmarkSummaryWrite(4, b) -} - -func BenchmarkSummaryWrite8(b *testing.B) { - benchmarkSummaryWrite(8, b) -} - -func TestSummaryConcurrency(t *testing.T) { - if testing.Short() { - t.Skip("Skipping test in short mode.") - } - - rand.Seed(42) - - it := func(n uint32) bool { - mutations := int(n%1e4 + 1e4) - concLevel := int(n%5 + 1) - total := mutations * concLevel - - var start, end sync.WaitGroup - start.Add(1) - end.Add(concLevel) - - sum := NewSummary(SummaryOpts{ - Name: "test_summary", - Help: "helpless", - Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, - }) - - allVars := make([]float64, total) - var sampleSum float64 - for i := 0; i < concLevel; i++ { - vals := make([]float64, mutations) - for j := 0; j < mutations; j++ { - v := rand.NormFloat64() - vals[j] = v - allVars[i*mutations+j] = v - sampleSum += v - } - - go func(vals []float64) { - start.Wait() - for _, v := range vals { - sum.Observe(v) - } - end.Done() - }(vals) - } - sort.Float64s(allVars) - start.Done() - end.Wait() - - m := &dto.Metric{} - sum.Write(m) - if got, want := int(*m.Summary.SampleCount), total; got != want { - t.Errorf("got sample count %d, want %d", got, want) - } - if got, want := *m.Summary.SampleSum, sampleSum; math.Abs((got-want)/want) > 0.001 { - t.Errorf("got sample sum %f, want %f", got, want) - } - - objectives := make([]float64, 0, len(DefObjectives)) - for qu := range DefObjectives { - objectives = append(objectives, qu) - } - sort.Float64s(objectives) - - for i, wantQ := range objectives { - ε := DefObjectives[wantQ] - gotQ := *m.Summary.Quantile[i].Quantile - gotV := *m.Summary.Quantile[i].Value - min, max := getBounds(allVars, wantQ, ε) - if gotQ != wantQ { - t.Errorf("got quantile %f, want %f", gotQ, wantQ) - } - if gotV < min || gotV > max { - t.Errorf("got %f for quantile %f, want [%f,%f]", gotV, gotQ, min, max) - } - } - return true - } - - if err := quick.Check(it, nil); err != nil { - t.Error(err) - } -} - -func TestSummaryVecConcurrency(t *testing.T) { - if testing.Short() { - t.Skip("Skipping test in short mode.") - } - - rand.Seed(42) - - objectives := make([]float64, 0, len(DefObjectives)) - for qu := range DefObjectives { - - objectives = append(objectives, qu) - } - sort.Float64s(objectives) - - it := func(n uint32) bool { - mutations := int(n%1e4 + 1e4) - concLevel := int(n%7 + 1) - vecLength := int(n%3 + 1) - - var start, end sync.WaitGroup - start.Add(1) - end.Add(concLevel) - - sum := NewSummaryVec( - SummaryOpts{ - Name: "test_summary", - Help: "helpless", - Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, - }, - []string{"label"}, - ) - - allVars := make([][]float64, vecLength) - sampleSums := make([]float64, vecLength) - for i := 0; i < concLevel; i++ { - vals := make([]float64, mutations) - picks := make([]int, mutations) - for j := 0; j < mutations; j++ { - v := rand.NormFloat64() - vals[j] = v - pick := rand.Intn(vecLength) - picks[j] = pick - allVars[pick] = append(allVars[pick], v) - sampleSums[pick] += v - } - - go func(vals []float64) { - start.Wait() - for i, v := range vals { - sum.WithLabelValues(string('A' + picks[i])).Observe(v) - } - end.Done() - }(vals) - } - for _, vars := range allVars { - sort.Float64s(vars) - } - start.Done() - end.Wait() - - for i := 0; i < vecLength; i++ { - m := &dto.Metric{} - s := sum.WithLabelValues(string('A' + i)) - s.(Summary).Write(m) - if got, want := int(*m.Summary.SampleCount), len(allVars[i]); got != want { - t.Errorf("got sample count %d for label %c, want %d", got, 'A'+i, want) - } - if got, want := *m.Summary.SampleSum, sampleSums[i]; math.Abs((got-want)/want) > 0.001 { - t.Errorf("got sample sum %f for label %c, want %f", got, 'A'+i, want) - } - for j, wantQ := range objectives { - ε := DefObjectives[wantQ] - gotQ := *m.Summary.Quantile[j].Quantile - gotV := *m.Summary.Quantile[j].Value - min, max := getBounds(allVars[i], wantQ, ε) - if gotQ != wantQ { - t.Errorf("got quantile %f for label %c, want %f", gotQ, 'A'+i, wantQ) - } - if gotV < min || gotV > max { - t.Errorf("got %f for quantile %f for label %c, want [%f,%f]", gotV, gotQ, 'A'+i, min, max) - } - } - } - return true - } - - if err := quick.Check(it, nil); err != nil { - t.Error(err) - } -} - -func TestSummaryDecay(t *testing.T) { - if testing.Short() { - t.Skip("Skipping test in short mode.") - // More because it depends on timing than because it is particularly long... - } - - sum := NewSummary(SummaryOpts{ - Name: "test_summary", - Help: "helpless", - MaxAge: 100 * time.Millisecond, - Objectives: map[float64]float64{0.1: 0.001}, - AgeBuckets: 10, - }) - - m := &dto.Metric{} - i := 0 - tick := time.NewTicker(time.Millisecond) - for range tick.C { - i++ - sum.Observe(float64(i)) - if i%10 == 0 { - sum.Write(m) - if got, want := *m.Summary.Quantile[0].Value, math.Max(float64(i)/10, float64(i-90)); math.Abs(got-want) > 20 { - t.Errorf("%d. got %f, want %f", i, got, want) - } - m.Reset() - } - if i >= 1000 { - break - } - } - tick.Stop() - // Wait for MaxAge without observations and make sure quantiles are NaN. - time.Sleep(100 * time.Millisecond) - sum.Write(m) - if got := *m.Summary.Quantile[0].Value; !math.IsNaN(got) { - t.Errorf("got %f, want NaN after expiration", got) - } -} - -func getBounds(vars []float64, q, ε float64) (min, max float64) { - // TODO(beorn7): This currently tolerates an error of up to 2*ε. The - // error must be at most ε, but for some reason, it's sometimes slightly - // higher. That's a bug. - n := float64(len(vars)) - lower := int((q - 2*ε) * n) - upper := int(math.Ceil((q + 2*ε) * n)) - min = vars[0] - if lower > 1 { - min = vars[lower-1] - } - max = vars[len(vars)-1] - if upper < len(vars) { - max = vars[upper-1] - } - return -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/timer_test.go b/vendor/github.com/prometheus/client_golang/prometheus/timer_test.go deleted file mode 100644 index 294902068..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/timer_test.go +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2016 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "testing" - - dto "github.com/prometheus/client_model/go" -) - -func TestTimerObserve(t *testing.T) { - var ( - his = NewHistogram(HistogramOpts{Name: "test_histogram"}) - sum = NewSummary(SummaryOpts{Name: "test_summary"}) - gauge = NewGauge(GaugeOpts{Name: "test_gauge"}) - ) - - func() { - hisTimer := NewTimer(his) - sumTimer := NewTimer(sum) - gaugeTimer := NewTimer(ObserverFunc(gauge.Set)) - defer hisTimer.ObserveDuration() - defer sumTimer.ObserveDuration() - defer gaugeTimer.ObserveDuration() - }() - - m := &dto.Metric{} - his.Write(m) - if want, got := uint64(1), m.GetHistogram().GetSampleCount(); want != got { - t.Errorf("want %d observations for histogram, got %d", want, got) - } - m.Reset() - sum.Write(m) - if want, got := uint64(1), m.GetSummary().GetSampleCount(); want != got { - t.Errorf("want %d observations for summary, got %d", want, got) - } - m.Reset() - gauge.Write(m) - if got := m.GetGauge().GetValue(); got <= 0 { - t.Errorf("want value > 0 for gauge, got %f", got) - } -} - -func TestTimerEmpty(t *testing.T) { - emptyTimer := NewTimer(nil) - emptyTimer.ObserveDuration() - // Do nothing, just demonstrate it works without panic. -} - -func TestTimerConditionalTiming(t *testing.T) { - var ( - his = NewHistogram(HistogramOpts{ - Name: "test_histogram", - }) - timeMe = true - m = &dto.Metric{} - ) - - timedFunc := func() { - timer := NewTimer(ObserverFunc(func(v float64) { - if timeMe { - his.Observe(v) - } - })) - defer timer.ObserveDuration() - } - - timedFunc() // This will time. - his.Write(m) - if want, got := uint64(1), m.GetHistogram().GetSampleCount(); want != got { - t.Errorf("want %d observations for histogram, got %d", want, got) - } - - timeMe = false - timedFunc() // This will not time again. - m.Reset() - his.Write(m) - if want, got := uint64(1), m.GetHistogram().GetSampleCount(); want != got { - t.Errorf("want %d observations for histogram, got %d", want, got) - } -} - -func TestTimerByOutcome(t *testing.T) { - var ( - his = NewHistogramVec( - HistogramOpts{Name: "test_histogram"}, - []string{"outcome"}, - ) - outcome = "foo" - m = &dto.Metric{} - ) - - timedFunc := func() { - timer := NewTimer(ObserverFunc(func(v float64) { - his.WithLabelValues(outcome).Observe(v) - })) - defer timer.ObserveDuration() - - if outcome == "foo" { - outcome = "bar" - return - } - outcome = "foo" - } - - timedFunc() - his.WithLabelValues("foo").(Histogram).Write(m) - if want, got := uint64(0), m.GetHistogram().GetSampleCount(); want != got { - t.Errorf("want %d observations for 'foo' histogram, got %d", want, got) - } - m.Reset() - his.WithLabelValues("bar").(Histogram).Write(m) - if want, got := uint64(1), m.GetHistogram().GetSampleCount(); want != got { - t.Errorf("want %d observations for 'bar' histogram, got %d", want, got) - } - - timedFunc() - m.Reset() - his.WithLabelValues("foo").(Histogram).Write(m) - if want, got := uint64(1), m.GetHistogram().GetSampleCount(); want != got { - t.Errorf("want %d observations for 'foo' histogram, got %d", want, got) - } - m.Reset() - his.WithLabelValues("bar").(Histogram).Write(m) - if want, got := uint64(1), m.GetHistogram().GetSampleCount(); want != got { - t.Errorf("want %d observations for 'bar' histogram, got %d", want, got) - } - - timedFunc() - m.Reset() - his.WithLabelValues("foo").(Histogram).Write(m) - if want, got := uint64(1), m.GetHistogram().GetSampleCount(); want != got { - t.Errorf("want %d observations for 'foo' histogram, got %d", want, got) - } - m.Reset() - his.WithLabelValues("bar").(Histogram).Write(m) - if want, got := uint64(2), m.GetHistogram().GetSampleCount(); want != got { - t.Errorf("want %d observations for 'bar' histogram, got %d", want, got) - } - -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/value_test.go b/vendor/github.com/prometheus/client_golang/prometheus/value_test.go deleted file mode 100644 index 51867b5e4..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/value_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "fmt" - "testing" -) - -func TestNewConstMetricInvalidLabelValues(t *testing.T) { - testCases := []struct { - desc string - labels Labels - }{ - { - desc: "non utf8 label value", - labels: Labels{"a": "\xFF"}, - }, - { - desc: "not enough label values", - labels: Labels{}, - }, - { - desc: "too many label values", - labels: Labels{"a": "1", "b": "2"}, - }, - } - - for _, test := range testCases { - metricDesc := NewDesc( - "sample_value", - "sample value", - []string{"a"}, - Labels{}, - ) - - expectPanic(t, func() { - MustNewConstMetric(metricDesc, CounterValue, 0.3, "\xFF") - }, fmt.Sprintf("WithLabelValues: expected panic because: %s", test.desc)) - - if _, err := NewConstMetric(metricDesc, CounterValue, 0.3, "\xFF"); err == nil { - t.Errorf("NewConstMetric: expected error because: %s", test.desc) - } - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/vec_test.go b/vendor/github.com/prometheus/client_golang/prometheus/vec_test.go deleted file mode 100644 index bd18a9f4e..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/vec_test.go +++ /dev/null @@ -1,535 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "fmt" - "testing" - - dto "github.com/prometheus/client_model/go" -) - -func TestDelete(t *testing.T) { - vec := NewGaugeVec( - GaugeOpts{ - Name: "test", - Help: "helpless", - }, - []string{"l1", "l2"}, - ) - testDelete(t, vec) -} - -func TestDeleteWithCollisions(t *testing.T) { - vec := NewGaugeVec( - GaugeOpts{ - Name: "test", - Help: "helpless", - }, - []string{"l1", "l2"}, - ) - vec.hashAdd = func(h uint64, s string) uint64 { return 1 } - vec.hashAddByte = func(h uint64, b byte) uint64 { return 1 } - testDelete(t, vec) -} - -func testDelete(t *testing.T, vec *GaugeVec) { - if got, want := vec.Delete(Labels{"l1": "v1", "l2": "v2"}), false; got != want { - t.Errorf("got %v, want %v", got, want) - } - - vec.With(Labels{"l1": "v1", "l2": "v2"}).(Gauge).Set(42) - if got, want := vec.Delete(Labels{"l1": "v1", "l2": "v2"}), true; got != want { - t.Errorf("got %v, want %v", got, want) - } - if got, want := vec.Delete(Labels{"l1": "v1", "l2": "v2"}), false; got != want { - t.Errorf("got %v, want %v", got, want) - } - - vec.With(Labels{"l1": "v1", "l2": "v2"}).(Gauge).Set(42) - if got, want := vec.Delete(Labels{"l2": "v2", "l1": "v1"}), true; got != want { - t.Errorf("got %v, want %v", got, want) - } - if got, want := vec.Delete(Labels{"l2": "v2", "l1": "v1"}), false; got != want { - t.Errorf("got %v, want %v", got, want) - } - - vec.With(Labels{"l1": "v1", "l2": "v2"}).(Gauge).Set(42) - if got, want := vec.Delete(Labels{"l2": "v1", "l1": "v2"}), false; got != want { - t.Errorf("got %v, want %v", got, want) - } - if got, want := vec.Delete(Labels{"l1": "v1"}), false; got != want { - t.Errorf("got %v, want %v", got, want) - } -} - -func TestDeleteLabelValues(t *testing.T) { - vec := NewGaugeVec( - GaugeOpts{ - Name: "test", - Help: "helpless", - }, - []string{"l1", "l2"}, - ) - testDeleteLabelValues(t, vec) -} - -func TestDeleteLabelValuesWithCollisions(t *testing.T) { - vec := NewGaugeVec( - GaugeOpts{ - Name: "test", - Help: "helpless", - }, - []string{"l1", "l2"}, - ) - vec.hashAdd = func(h uint64, s string) uint64 { return 1 } - vec.hashAddByte = func(h uint64, b byte) uint64 { return 1 } - testDeleteLabelValues(t, vec) -} - -func testDeleteLabelValues(t *testing.T, vec *GaugeVec) { - if got, want := vec.DeleteLabelValues("v1", "v2"), false; got != want { - t.Errorf("got %v, want %v", got, want) - } - - vec.With(Labels{"l1": "v1", "l2": "v2"}).(Gauge).Set(42) - vec.With(Labels{"l1": "v1", "l2": "v3"}).(Gauge).Set(42) // Add junk data for collision. - if got, want := vec.DeleteLabelValues("v1", "v2"), true; got != want { - t.Errorf("got %v, want %v", got, want) - } - if got, want := vec.DeleteLabelValues("v1", "v2"), false; got != want { - t.Errorf("got %v, want %v", got, want) - } - if got, want := vec.DeleteLabelValues("v1", "v3"), true; got != want { - t.Errorf("got %v, want %v", got, want) - } - - vec.With(Labels{"l1": "v1", "l2": "v2"}).(Gauge).Set(42) - // Delete out of order. - if got, want := vec.DeleteLabelValues("v2", "v1"), false; got != want { - t.Errorf("got %v, want %v", got, want) - } - if got, want := vec.DeleteLabelValues("v1"), false; got != want { - t.Errorf("got %v, want %v", got, want) - } -} - -func TestMetricVec(t *testing.T) { - vec := NewGaugeVec( - GaugeOpts{ - Name: "test", - Help: "helpless", - }, - []string{"l1", "l2"}, - ) - testMetricVec(t, vec) -} - -func TestMetricVecWithCollisions(t *testing.T) { - vec := NewGaugeVec( - GaugeOpts{ - Name: "test", - Help: "helpless", - }, - []string{"l1", "l2"}, - ) - vec.hashAdd = func(h uint64, s string) uint64 { return 1 } - vec.hashAddByte = func(h uint64, b byte) uint64 { return 1 } - testMetricVec(t, vec) -} - -func testMetricVec(t *testing.T, vec *GaugeVec) { - vec.Reset() // Actually test Reset now! - - var pair [2]string - // Keep track of metrics. - expected := map[[2]string]int{} - - for i := 0; i < 1000; i++ { - pair[0], pair[1] = fmt.Sprint(i%4), fmt.Sprint(i%5) // Varying combinations multiples. - expected[pair]++ - vec.WithLabelValues(pair[0], pair[1]).Inc() - - expected[[2]string{"v1", "v2"}]++ - vec.WithLabelValues("v1", "v2").(Gauge).Inc() - } - - var total int - for _, metrics := range vec.metricMap.metrics { - for _, metric := range metrics { - total++ - copy(pair[:], metric.values) - - var metricOut dto.Metric - if err := metric.metric.Write(&metricOut); err != nil { - t.Fatal(err) - } - actual := *metricOut.Gauge.Value - - var actualPair [2]string - for i, label := range metricOut.Label { - actualPair[i] = *label.Value - } - - // Test output pair against metric.values to ensure we've selected - // the right one. We check this to ensure the below check means - // anything at all. - if actualPair != pair { - t.Fatalf("unexpected pair association in metric map: %v != %v", actualPair, pair) - } - - if actual != float64(expected[pair]) { - t.Fatalf("incorrect counter value for %v: %v != %v", pair, actual, expected[pair]) - } - } - } - - if total != len(expected) { - t.Fatalf("unexpected number of metrics: %v != %v", total, len(expected)) - } - - vec.Reset() - - if len(vec.metricMap.metrics) > 0 { - t.Fatalf("reset failed") - } -} - -func TestCounterVecEndToEndWithCollision(t *testing.T) { - vec := NewCounterVec( - CounterOpts{ - Name: "test", - Help: "helpless", - }, - []string{"labelname"}, - ) - vec.WithLabelValues("77kepQFQ8Kl").Inc() - vec.WithLabelValues("!0IC=VloaY").Add(2) - - m := &dto.Metric{} - if err := vec.WithLabelValues("77kepQFQ8Kl").Write(m); err != nil { - t.Fatal(err) - } - if got, want := m.GetLabel()[0].GetValue(), "77kepQFQ8Kl"; got != want { - t.Errorf("got label value %q, want %q", got, want) - } - if got, want := m.GetCounter().GetValue(), 1.; got != want { - t.Errorf("got value %f, want %f", got, want) - } - m.Reset() - if err := vec.WithLabelValues("!0IC=VloaY").Write(m); err != nil { - t.Fatal(err) - } - if got, want := m.GetLabel()[0].GetValue(), "!0IC=VloaY"; got != want { - t.Errorf("got label value %q, want %q", got, want) - } - if got, want := m.GetCounter().GetValue(), 2.; got != want { - t.Errorf("got value %f, want %f", got, want) - } -} - -func TestCurryVec(t *testing.T) { - vec := NewCounterVec( - CounterOpts{ - Name: "test", - Help: "helpless", - }, - []string{"one", "two", "three"}, - ) - testCurryVec(t, vec) -} - -func TestCurryVecWithCollisions(t *testing.T) { - vec := NewCounterVec( - CounterOpts{ - Name: "test", - Help: "helpless", - }, - []string{"one", "two", "three"}, - ) - vec.hashAdd = func(h uint64, s string) uint64 { return 1 } - vec.hashAddByte = func(h uint64, b byte) uint64 { return 1 } - testCurryVec(t, vec) -} - -func testCurryVec(t *testing.T, vec *CounterVec) { - - assertMetrics := func(t *testing.T) { - n := 0 - for _, m := range vec.metricMap.metrics { - n += len(m) - } - if n != 2 { - t.Error("expected two metrics, got", n) - } - m := &dto.Metric{} - c1, err := vec.GetMetricWithLabelValues("1", "2", "3") - if err != nil { - t.Fatal("unexpected error getting metric:", err) - } - c1.Write(m) - if want, got := 1., m.GetCounter().GetValue(); want != got { - t.Errorf("want %f as counter value, got %f", want, got) - } - m.Reset() - c2, err := vec.GetMetricWithLabelValues("11", "22", "33") - if err != nil { - t.Fatal("unexpected error getting metric:", err) - } - c2.Write(m) - if want, got := 1., m.GetCounter().GetValue(); want != got { - t.Errorf("want %f as counter value, got %f", want, got) - } - } - - assertNoMetric := func(t *testing.T) { - if n := len(vec.metricMap.metrics); n != 0 { - t.Error("expected no metrics, got", n) - } - } - - t.Run("zero labels", func(t *testing.T) { - c1 := vec.MustCurryWith(nil) - c2 := vec.MustCurryWith(nil) - c1.WithLabelValues("1", "2", "3").Inc() - c2.With(Labels{"one": "11", "two": "22", "three": "33"}).Inc() - assertMetrics(t) - if !c1.Delete(Labels{"one": "1", "two": "2", "three": "3"}) { - t.Error("deletion failed") - } - if !c2.DeleteLabelValues("11", "22", "33") { - t.Error("deletion failed") - } - assertNoMetric(t) - }) - t.Run("first label", func(t *testing.T) { - c1 := vec.MustCurryWith(Labels{"one": "1"}) - c2 := vec.MustCurryWith(Labels{"one": "11"}) - c1.WithLabelValues("2", "3").Inc() - c2.With(Labels{"two": "22", "three": "33"}).Inc() - assertMetrics(t) - if c1.Delete(Labels{"two": "22", "three": "33"}) { - t.Error("deletion unexpectedly succeeded") - } - if c2.DeleteLabelValues("2", "3") { - t.Error("deletion unexpectedly succeeded") - } - if !c1.Delete(Labels{"two": "2", "three": "3"}) { - t.Error("deletion failed") - } - if !c2.DeleteLabelValues("22", "33") { - t.Error("deletion failed") - } - assertNoMetric(t) - }) - t.Run("middle label", func(t *testing.T) { - c1 := vec.MustCurryWith(Labels{"two": "2"}) - c2 := vec.MustCurryWith(Labels{"two": "22"}) - c1.WithLabelValues("1", "3").Inc() - c2.With(Labels{"one": "11", "three": "33"}).Inc() - assertMetrics(t) - if c1.Delete(Labels{"one": "11", "three": "33"}) { - t.Error("deletion unexpectedly succeeded") - } - if c2.DeleteLabelValues("1", "3") { - t.Error("deletion unexpectedly succeeded") - } - if !c1.Delete(Labels{"one": "1", "three": "3"}) { - t.Error("deletion failed") - } - if !c2.DeleteLabelValues("11", "33") { - t.Error("deletion failed") - } - assertNoMetric(t) - }) - t.Run("last label", func(t *testing.T) { - c1 := vec.MustCurryWith(Labels{"three": "3"}) - c2 := vec.MustCurryWith(Labels{"three": "33"}) - c1.WithLabelValues("1", "2").Inc() - c2.With(Labels{"one": "11", "two": "22"}).Inc() - assertMetrics(t) - if c1.Delete(Labels{"two": "22", "one": "11"}) { - t.Error("deletion unexpectedly succeeded") - } - if c2.DeleteLabelValues("1", "2") { - t.Error("deletion unexpectedly succeeded") - } - if !c1.Delete(Labels{"two": "2", "one": "1"}) { - t.Error("deletion failed") - } - if !c2.DeleteLabelValues("11", "22") { - t.Error("deletion failed") - } - assertNoMetric(t) - }) - t.Run("two labels", func(t *testing.T) { - c1 := vec.MustCurryWith(Labels{"three": "3", "one": "1"}) - c2 := vec.MustCurryWith(Labels{"three": "33", "one": "11"}) - c1.WithLabelValues("2").Inc() - c2.With(Labels{"two": "22"}).Inc() - assertMetrics(t) - if c1.Delete(Labels{"two": "22"}) { - t.Error("deletion unexpectedly succeeded") - } - if c2.DeleteLabelValues("2") { - t.Error("deletion unexpectedly succeeded") - } - if !c1.Delete(Labels{"two": "2"}) { - t.Error("deletion failed") - } - if !c2.DeleteLabelValues("22") { - t.Error("deletion failed") - } - assertNoMetric(t) - }) - t.Run("all labels", func(t *testing.T) { - c1 := vec.MustCurryWith(Labels{"three": "3", "two": "2", "one": "1"}) - c2 := vec.MustCurryWith(Labels{"three": "33", "one": "11", "two": "22"}) - c1.WithLabelValues().Inc() - c2.With(nil).Inc() - assertMetrics(t) - if !c1.Delete(Labels{}) { - t.Error("deletion failed") - } - if !c2.DeleteLabelValues() { - t.Error("deletion failed") - } - assertNoMetric(t) - }) - t.Run("double curry", func(t *testing.T) { - c1 := vec.MustCurryWith(Labels{"three": "3"}).MustCurryWith(Labels{"one": "1"}) - c2 := vec.MustCurryWith(Labels{"three": "33"}).MustCurryWith(Labels{"one": "11"}) - c1.WithLabelValues("2").Inc() - c2.With(Labels{"two": "22"}).Inc() - assertMetrics(t) - if c1.Delete(Labels{"two": "22"}) { - t.Error("deletion unexpectedly succeeded") - } - if c2.DeleteLabelValues("2") { - t.Error("deletion unexpectedly succeeded") - } - if !c1.Delete(Labels{"two": "2"}) { - t.Error("deletion failed") - } - if !c2.DeleteLabelValues("22") { - t.Error("deletion failed") - } - assertNoMetric(t) - }) - t.Run("use already curried label", func(t *testing.T) { - c1 := vec.MustCurryWith(Labels{"three": "3"}) - if _, err := c1.GetMetricWithLabelValues("1", "2", "3"); err == nil { - t.Error("expected error when using already curried label") - } - if _, err := c1.GetMetricWith(Labels{"one": "1", "two": "2", "three": "3"}); err == nil { - t.Error("expected error when using already curried label") - } - assertNoMetric(t) - c1.WithLabelValues("1", "2").Inc() - if c1.Delete(Labels{"one": "1", "two": "2", "three": "3"}) { - t.Error("deletion unexpectedly succeeded") - } - if !c1.Delete(Labels{"one": "1", "two": "2"}) { - t.Error("deletion failed") - } - assertNoMetric(t) - }) - t.Run("curry already curried label", func(t *testing.T) { - if _, err := vec.MustCurryWith(Labels{"three": "3"}).CurryWith(Labels{"three": "33"}); err == nil { - t.Error("currying unexpectedly succeeded") - } else if err.Error() != `label name "three" is already curried` { - t.Error("currying returned unexpected error:", err) - } - - }) - t.Run("unknown label", func(t *testing.T) { - if _, err := vec.CurryWith(Labels{"foo": "bar"}); err == nil { - t.Error("currying unexpectedly succeeded") - } else if err.Error() != "1 unknown label(s) found during currying" { - t.Error("currying returned unexpected error:", err) - } - }) -} - -func BenchmarkMetricVecWithLabelValuesBasic(b *testing.B) { - benchmarkMetricVecWithLabelValues(b, map[string][]string{ - "l1": {"onevalue"}, - "l2": {"twovalue"}, - }) -} - -func BenchmarkMetricVecWithLabelValues2Keys10ValueCardinality(b *testing.B) { - benchmarkMetricVecWithLabelValuesCardinality(b, 2, 10) -} - -func BenchmarkMetricVecWithLabelValues4Keys10ValueCardinality(b *testing.B) { - benchmarkMetricVecWithLabelValuesCardinality(b, 4, 10) -} - -func BenchmarkMetricVecWithLabelValues2Keys100ValueCardinality(b *testing.B) { - benchmarkMetricVecWithLabelValuesCardinality(b, 2, 100) -} - -func BenchmarkMetricVecWithLabelValues10Keys100ValueCardinality(b *testing.B) { - benchmarkMetricVecWithLabelValuesCardinality(b, 10, 100) -} - -func BenchmarkMetricVecWithLabelValues10Keys1000ValueCardinality(b *testing.B) { - benchmarkMetricVecWithLabelValuesCardinality(b, 10, 1000) -} - -func benchmarkMetricVecWithLabelValuesCardinality(b *testing.B, nkeys, nvalues int) { - labels := map[string][]string{} - - for i := 0; i < nkeys; i++ { - var ( - k = fmt.Sprintf("key-%v", i) - vs = make([]string, 0, nvalues) - ) - for j := 0; j < nvalues; j++ { - vs = append(vs, fmt.Sprintf("value-%v", j)) - } - labels[k] = vs - } - - benchmarkMetricVecWithLabelValues(b, labels) -} - -func benchmarkMetricVecWithLabelValues(b *testing.B, labels map[string][]string) { - var keys []string - for k := range labels { // Map order dependent, who cares though. - keys = append(keys, k) - } - - values := make([]string, len(labels)) // Value cache for permutations. - vec := NewGaugeVec( - GaugeOpts{ - Name: "test", - Help: "helpless", - }, - keys, - ) - - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - // Varies input across provide map entries based on key size. - for j, k := range keys { - candidates := labels[k] - values[j] = candidates[i%len(candidates)] - } - - vec.WithLabelValues(values...) - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/wrap_test.go b/vendor/github.com/prometheus/client_golang/prometheus/wrap_test.go deleted file mode 100644 index bed103e5e..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/wrap_test.go +++ /dev/null @@ -1,322 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package prometheus - -import ( - "fmt" - "reflect" - "strings" - "testing" - - "github.com/gogo/protobuf/proto" - - dto "github.com/prometheus/client_model/go" -) - -// uncheckedCollector wraps a Collector but its Describe method yields no Desc. -type uncheckedCollector struct { - c Collector -} - -func (u uncheckedCollector) Describe(_ chan<- *Desc) {} -func (u uncheckedCollector) Collect(c chan<- Metric) { - u.c.Collect(c) -} - -func toMetricFamilies(cs ...Collector) []*dto.MetricFamily { - reg := NewRegistry() - reg.MustRegister(cs...) - out, err := reg.Gather() - if err != nil { - panic(err) - } - return out -} - -func TestWrap(t *testing.T) { - - simpleCnt := NewCounter(CounterOpts{ - Name: "simpleCnt", - Help: "helpSimpleCnt", - }) - simpleCnt.Inc() - - simpleGge := NewGauge(GaugeOpts{ - Name: "simpleGge", - Help: "helpSimpleGge", - }) - simpleGge.Set(3.14) - - preCnt := NewCounter(CounterOpts{ - Name: "pre_simpleCnt", - Help: "helpSimpleCnt", - }) - preCnt.Inc() - - barLabeledCnt := NewCounter(CounterOpts{ - Name: "simpleCnt", - Help: "helpSimpleCnt", - ConstLabels: Labels{"foo": "bar"}, - }) - barLabeledCnt.Inc() - - bazLabeledCnt := NewCounter(CounterOpts{ - Name: "simpleCnt", - Help: "helpSimpleCnt", - ConstLabels: Labels{"foo": "baz"}, - }) - bazLabeledCnt.Inc() - - labeledPreCnt := NewCounter(CounterOpts{ - Name: "pre_simpleCnt", - Help: "helpSimpleCnt", - ConstLabels: Labels{"foo": "bar"}, - }) - labeledPreCnt.Inc() - - twiceLabeledPreCnt := NewCounter(CounterOpts{ - Name: "pre_simpleCnt", - Help: "helpSimpleCnt", - ConstLabels: Labels{"foo": "bar", "dings": "bums"}, - }) - twiceLabeledPreCnt.Inc() - - barLabeledUncheckedCollector := uncheckedCollector{barLabeledCnt} - - scenarios := map[string]struct { - prefix string // First wrap with this prefix. - labels Labels // Then wrap the result with these labels. - labels2 Labels // If any, wrap the prefix-wrapped one again. - preRegister []Collector - toRegister []struct { // If there are any labels2, register every other with that one. - collector Collector - registrationFails bool - } - gatherFails bool - output []Collector - }{ - "wrap nothing": { - prefix: "pre_", - labels: Labels{"foo": "bar"}, - }, - "wrap with nothing": { - preRegister: []Collector{simpleGge}, - toRegister: []struct { - collector Collector - registrationFails bool - }{{simpleCnt, false}}, - output: []Collector{simpleGge, simpleCnt}, - }, - "wrap counter with prefix": { - prefix: "pre_", - preRegister: []Collector{simpleGge}, - toRegister: []struct { - collector Collector - registrationFails bool - }{{simpleCnt, false}}, - output: []Collector{simpleGge, preCnt}, - }, - "wrap counter with label pair": { - labels: Labels{"foo": "bar"}, - preRegister: []Collector{simpleGge}, - toRegister: []struct { - collector Collector - registrationFails bool - }{{simpleCnt, false}}, - output: []Collector{simpleGge, barLabeledCnt}, - }, - "wrap counter with label pair and prefix": { - prefix: "pre_", - labels: Labels{"foo": "bar"}, - preRegister: []Collector{simpleGge}, - toRegister: []struct { - collector Collector - registrationFails bool - }{{simpleCnt, false}}, - output: []Collector{simpleGge, labeledPreCnt}, - }, - "wrap counter with invalid prefix": { - prefix: "1+1", - preRegister: []Collector{simpleGge}, - toRegister: []struct { - collector Collector - registrationFails bool - }{{simpleCnt, true}}, - output: []Collector{simpleGge}, - }, - "wrap counter with invalid label": { - preRegister: []Collector{simpleGge}, - labels: Labels{"42": "bar"}, - toRegister: []struct { - collector Collector - registrationFails bool - }{{simpleCnt, true}}, - output: []Collector{simpleGge}, - }, - "counter registered twice but wrapped with different label values": { - labels: Labels{"foo": "bar"}, - labels2: Labels{"foo": "baz"}, - toRegister: []struct { - collector Collector - registrationFails bool - }{{simpleCnt, false}, {simpleCnt, false}}, - output: []Collector{barLabeledCnt, bazLabeledCnt}, - }, - "counter registered twice but wrapped with different inconsistent label values": { - labels: Labels{"foo": "bar"}, - labels2: Labels{"bar": "baz"}, - toRegister: []struct { - collector Collector - registrationFails bool - }{{simpleCnt, false}, {simpleCnt, true}}, - output: []Collector{barLabeledCnt}, - }, - "wrap counter with prefix and two labels": { - prefix: "pre_", - labels: Labels{"foo": "bar", "dings": "bums"}, - preRegister: []Collector{simpleGge}, - toRegister: []struct { - collector Collector - registrationFails bool - }{{simpleCnt, false}}, - output: []Collector{simpleGge, twiceLabeledPreCnt}, - }, - "wrap labeled counter with prefix and another label": { - prefix: "pre_", - labels: Labels{"dings": "bums"}, - preRegister: []Collector{simpleGge}, - toRegister: []struct { - collector Collector - registrationFails bool - }{{barLabeledCnt, false}}, - output: []Collector{simpleGge, twiceLabeledPreCnt}, - }, - "wrap labeled counter with prefix and inconsistent label": { - prefix: "pre_", - labels: Labels{"foo": "bums"}, - preRegister: []Collector{simpleGge}, - toRegister: []struct { - collector Collector - registrationFails bool - }{{barLabeledCnt, true}}, - output: []Collector{simpleGge}, - }, - "wrap labeled counter with prefix and the same label again": { - prefix: "pre_", - labels: Labels{"foo": "bar"}, - preRegister: []Collector{simpleGge}, - toRegister: []struct { - collector Collector - registrationFails bool - }{{barLabeledCnt, true}}, - output: []Collector{simpleGge}, - }, - "wrap labeled unchecked collector with prefix and another label": { - prefix: "pre_", - labels: Labels{"dings": "bums"}, - preRegister: []Collector{simpleGge}, - toRegister: []struct { - collector Collector - registrationFails bool - }{{barLabeledUncheckedCollector, false}}, - output: []Collector{simpleGge, twiceLabeledPreCnt}, - }, - "wrap labeled unchecked collector with prefix and inconsistent label": { - prefix: "pre_", - labels: Labels{"foo": "bums"}, - preRegister: []Collector{simpleGge}, - toRegister: []struct { - collector Collector - registrationFails bool - }{{barLabeledUncheckedCollector, false}}, - gatherFails: true, - output: []Collector{simpleGge}, - }, - "wrap labeled unchecked collector with prefix and the same label again": { - prefix: "pre_", - labels: Labels{"foo": "bar"}, - preRegister: []Collector{simpleGge}, - toRegister: []struct { - collector Collector - registrationFails bool - }{{barLabeledUncheckedCollector, false}}, - gatherFails: true, - output: []Collector{simpleGge}, - }, - "wrap labeled unchecked collector with prefix and another label resulting in collision with pre-registered counter": { - prefix: "pre_", - labels: Labels{"dings": "bums"}, - preRegister: []Collector{twiceLabeledPreCnt}, - toRegister: []struct { - collector Collector - registrationFails bool - }{{barLabeledUncheckedCollector, false}}, - gatherFails: true, - output: []Collector{twiceLabeledPreCnt}, - }, - } - - for n, s := range scenarios { - t.Run(n, func(t *testing.T) { - reg := NewPedanticRegistry() - for _, c := range s.preRegister { - if err := reg.Register(c); err != nil { - t.Fatal("error registering with unwrapped registry:", err) - } - } - preReg := WrapRegistererWithPrefix(s.prefix, reg) - lReg := WrapRegistererWith(s.labels, preReg) - l2Reg := WrapRegistererWith(s.labels2, preReg) - for i, tr := range s.toRegister { - var err error - if i%2 != 0 && len(s.labels2) != 0 { - err = l2Reg.Register(tr.collector) - } else { - err = lReg.Register(tr.collector) - } - if tr.registrationFails && err == nil { - t.Fatalf("registration with wrapping registry unexpectedly succeded for collector #%d", i) - } - if !tr.registrationFails && err != nil { - t.Fatalf("registration with wrapping registry failed for collector #%d: %s", i, err) - } - } - wantMF := toMetricFamilies(s.output...) - gotMF, err := reg.Gather() - if s.gatherFails && err == nil { - t.Fatal("gathering unexpectedly succeded") - } - if !s.gatherFails && err != nil { - t.Fatal("gathering failed:", err) - } - if !reflect.DeepEqual(gotMF, wantMF) { - var want, got []string - - for i, mf := range wantMF { - want = append(want, fmt.Sprintf("%3d: %s", i, proto.MarshalTextString(mf))) - } - for i, mf := range gotMF { - got = append(got, fmt.Sprintf("%3d: %s", i, proto.MarshalTextString(mf))) - } - - t.Fatalf( - "unexpected output of gathering:\n\nWANT:\n%s\n\nGOT:\n%s\n", - strings.Join(want, "\n"), - strings.Join(got, "\n"), - ) - } - }) - } - -} diff --git a/vendor/github.com/prometheus/common/expfmt/bench_test.go b/vendor/github.com/prometheus/common/expfmt/bench_test.go deleted file mode 100644 index e539bfc13..000000000 --- a/vendor/github.com/prometheus/common/expfmt/bench_test.go +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2015 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package expfmt - -import ( - "bytes" - "compress/gzip" - "io" - "io/ioutil" - "testing" - - "github.com/matttproud/golang_protobuf_extensions/pbutil" - - dto "github.com/prometheus/client_model/go" -) - -var parser TextParser - -// Benchmarks to show how much penalty text format parsing actually inflicts. -// -// Example results on Linux 3.13.0, Intel(R) Core(TM) i7-4700MQ CPU @ 2.40GHz, go1.4. -// -// BenchmarkParseText 1000 1188535 ns/op 205085 B/op 6135 allocs/op -// BenchmarkParseTextGzip 1000 1376567 ns/op 246224 B/op 6151 allocs/op -// BenchmarkParseProto 10000 172790 ns/op 52258 B/op 1160 allocs/op -// BenchmarkParseProtoGzip 5000 324021 ns/op 94931 B/op 1211 allocs/op -// BenchmarkParseProtoMap 10000 187946 ns/op 58714 B/op 1203 allocs/op -// -// CONCLUSION: The overhead for the map is negligible. Text format needs ~5x more allocations. -// Without compression, it needs ~7x longer, but with compression (the more relevant scenario), -// the difference becomes less relevant, only ~4x. -// -// The test data contains 248 samples. - -// BenchmarkParseText benchmarks the parsing of a text-format scrape into metric -// family DTOs. -func BenchmarkParseText(b *testing.B) { - b.StopTimer() - data, err := ioutil.ReadFile("testdata/text") - if err != nil { - b.Fatal(err) - } - b.StartTimer() - - for i := 0; i < b.N; i++ { - if _, err := parser.TextToMetricFamilies(bytes.NewReader(data)); err != nil { - b.Fatal(err) - } - } -} - -// BenchmarkParseTextGzip benchmarks the parsing of a gzipped text-format scrape -// into metric family DTOs. -func BenchmarkParseTextGzip(b *testing.B) { - b.StopTimer() - data, err := ioutil.ReadFile("testdata/text.gz") - if err != nil { - b.Fatal(err) - } - b.StartTimer() - - for i := 0; i < b.N; i++ { - in, err := gzip.NewReader(bytes.NewReader(data)) - if err != nil { - b.Fatal(err) - } - if _, err := parser.TextToMetricFamilies(in); err != nil { - b.Fatal(err) - } - } -} - -// BenchmarkParseProto benchmarks the parsing of a protobuf-format scrape into -// metric family DTOs. Note that this does not build a map of metric families -// (as the text version does), because it is not required for Prometheus -// ingestion either. (However, it is required for the text-format parsing, as -// the metric family might be sprinkled all over the text, while the -// protobuf-format guarantees bundling at one place.) -func BenchmarkParseProto(b *testing.B) { - b.StopTimer() - data, err := ioutil.ReadFile("testdata/protobuf") - if err != nil { - b.Fatal(err) - } - b.StartTimer() - - for i := 0; i < b.N; i++ { - family := &dto.MetricFamily{} - in := bytes.NewReader(data) - for { - family.Reset() - if _, err := pbutil.ReadDelimited(in, family); err != nil { - if err == io.EOF { - break - } - b.Fatal(err) - } - } - } -} - -// BenchmarkParseProtoGzip is like BenchmarkParseProto above, but parses gzipped -// protobuf format. -func BenchmarkParseProtoGzip(b *testing.B) { - b.StopTimer() - data, err := ioutil.ReadFile("testdata/protobuf.gz") - if err != nil { - b.Fatal(err) - } - b.StartTimer() - - for i := 0; i < b.N; i++ { - family := &dto.MetricFamily{} - in, err := gzip.NewReader(bytes.NewReader(data)) - if err != nil { - b.Fatal(err) - } - for { - family.Reset() - if _, err := pbutil.ReadDelimited(in, family); err != nil { - if err == io.EOF { - break - } - b.Fatal(err) - } - } - } -} - -// BenchmarkParseProtoMap is like BenchmarkParseProto but DOES put the parsed -// metric family DTOs into a map. This is not happening during Prometheus -// ingestion. It is just here to measure the overhead of that map creation and -// separate it from the overhead of the text format parsing. -func BenchmarkParseProtoMap(b *testing.B) { - b.StopTimer() - data, err := ioutil.ReadFile("testdata/protobuf") - if err != nil { - b.Fatal(err) - } - b.StartTimer() - - for i := 0; i < b.N; i++ { - families := map[string]*dto.MetricFamily{} - in := bytes.NewReader(data) - for { - family := &dto.MetricFamily{} - if _, err := pbutil.ReadDelimited(in, family); err != nil { - if err == io.EOF { - break - } - b.Fatal(err) - } - families[family.GetName()] = family - } - } -} diff --git a/vendor/github.com/prometheus/common/expfmt/decode_test.go b/vendor/github.com/prometheus/common/expfmt/decode_test.go deleted file mode 100644 index 669d56c07..000000000 --- a/vendor/github.com/prometheus/common/expfmt/decode_test.go +++ /dev/null @@ -1,494 +0,0 @@ -// Copyright 2015 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package expfmt - -import ( - "io" - "net/http" - "reflect" - "sort" - "strings" - "testing" - - "github.com/golang/protobuf/proto" - dto "github.com/prometheus/client_model/go" - - "github.com/prometheus/common/model" -) - -func TestTextDecoder(t *testing.T) { - var ( - ts = model.Now() - in = ` -# Only a quite simple scenario with two metric families. -# More complicated tests of the parser itself can be found in the text package. -# TYPE mf2 counter -mf2 3 -mf1{label="value1"} -3.14 123456 -mf1{label="value2"} 42 -mf2 4 -` - out = model.Vector{ - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "mf1", - "label": "value1", - }, - Value: -3.14, - Timestamp: 123456, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "mf1", - "label": "value2", - }, - Value: 42, - Timestamp: ts, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "mf2", - }, - Value: 3, - Timestamp: ts, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "mf2", - }, - Value: 4, - Timestamp: ts, - }, - } - ) - - dec := &SampleDecoder{ - Dec: &textDecoder{r: strings.NewReader(in)}, - Opts: &DecodeOptions{ - Timestamp: ts, - }, - } - var all model.Vector - for { - var smpls model.Vector - err := dec.Decode(&smpls) - if err == io.EOF { - break - } - if err != nil { - t.Fatal(err) - } - all = append(all, smpls...) - } - sort.Sort(all) - sort.Sort(out) - if !reflect.DeepEqual(all, out) { - t.Fatalf("output does not match") - } -} - -func TestProtoDecoder(t *testing.T) { - - var testTime = model.Now() - - scenarios := []struct { - in string - expected model.Vector - fail bool - }{ - { - in: "", - }, - { - in: "\x8f\x01\n\rrequest_count\x12\x12Number of requests\x18\x00\"0\n#\n\x0fsome_!abel_name\x12\x10some_label_value\x1a\t\t\x00\x00\x00\x00\x00\x00E\xc0\"6\n)\n\x12another_label_name\x12\x13another_label_value\x1a\t\t\x00\x00\x00\x00\x00\x00U@", - fail: true, - }, - { - in: "\x8f\x01\n\rrequest_count\x12\x12Number of requests\x18\x00\"0\n#\n\x0fsome_label_name\x12\x10some_label_value\x1a\t\t\x00\x00\x00\x00\x00\x00E\xc0\"6\n)\n\x12another_label_name\x12\x13another_label_value\x1a\t\t\x00\x00\x00\x00\x00\x00U@", - expected: model.Vector{ - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count", - "some_label_name": "some_label_value", - }, - Value: -42, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count", - "another_label_name": "another_label_value", - }, - Value: 84, - Timestamp: testTime, - }, - }, - }, - { - in: "\xb9\x01\n\rrequest_count\x12\x12Number of requests\x18\x02\"O\n#\n\x0fsome_label_name\x12\x10some_label_value\"(\x1a\x12\t\xaeG\xe1z\x14\xae\xef?\x11\x00\x00\x00\x00\x00\x00E\xc0\x1a\x12\t+\x87\x16\xd9\xce\xf7\xef?\x11\x00\x00\x00\x00\x00\x00U\xc0\"A\n)\n\x12another_label_name\x12\x13another_label_value\"\x14\x1a\x12\t\x00\x00\x00\x00\x00\x00\xe0?\x11\x00\x00\x00\x00\x00\x00$@", - expected: model.Vector{ - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count_count", - "some_label_name": "some_label_value", - }, - Value: 0, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count_sum", - "some_label_name": "some_label_value", - }, - Value: 0, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count", - "some_label_name": "some_label_value", - "quantile": "0.99", - }, - Value: -42, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count", - "some_label_name": "some_label_value", - "quantile": "0.999", - }, - Value: -84, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count_count", - "another_label_name": "another_label_value", - }, - Value: 0, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count_sum", - "another_label_name": "another_label_value", - }, - Value: 0, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count", - "another_label_name": "another_label_value", - "quantile": "0.5", - }, - Value: 10, - Timestamp: testTime, - }, - }, - }, - { - in: "\x8d\x01\n\x1drequest_duration_microseconds\x12\x15The response latency.\x18\x04\"S:Q\b\x85\x15\x11\xcd\xcc\xccL\x8f\xcb:A\x1a\v\b{\x11\x00\x00\x00\x00\x00\x00Y@\x1a\f\b\x9c\x03\x11\x00\x00\x00\x00\x00\x00^@\x1a\f\b\xd0\x04\x11\x00\x00\x00\x00\x00\x00b@\x1a\f\b\xf4\v\x11\x9a\x99\x99\x99\x99\x99e@\x1a\f\b\x85\x15\x11\x00\x00\x00\x00\x00\x00\xf0\u007f", - expected: model.Vector{ - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_duration_microseconds_bucket", - "le": "100", - }, - Value: 123, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_duration_microseconds_bucket", - "le": "120", - }, - Value: 412, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_duration_microseconds_bucket", - "le": "144", - }, - Value: 592, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_duration_microseconds_bucket", - "le": "172.8", - }, - Value: 1524, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_duration_microseconds_bucket", - "le": "+Inf", - }, - Value: 2693, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_duration_microseconds_sum", - }, - Value: 1756047.3, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_duration_microseconds_count", - }, - Value: 2693, - Timestamp: testTime, - }, - }, - }, - { - in: "\u007f\n\x1drequest_duration_microseconds\x12\x15The response latency.\x18\x04\"E:C\b\x85\x15\x11\xcd\xcc\xccL\x8f\xcb:A\x1a\v\b{\x11\x00\x00\x00\x00\x00\x00Y@\x1a\f\b\x9c\x03\x11\x00\x00\x00\x00\x00\x00^@\x1a\f\b\xd0\x04\x11\x00\x00\x00\x00\x00\x00b@\x1a\f\b\xf4\v\x11\x9a\x99\x99\x99\x99\x99e@", - expected: model.Vector{ - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_duration_microseconds_count", - }, - Value: 2693, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - "le": "+Inf", - model.MetricNameLabel: "request_duration_microseconds_bucket", - }, - Value: 2693, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_duration_microseconds_sum", - }, - Value: 1756047.3, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - "le": "172.8", - model.MetricNameLabel: "request_duration_microseconds_bucket", - }, - Value: 1524, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - "le": "144", - model.MetricNameLabel: "request_duration_microseconds_bucket", - }, - Value: 592, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - "le": "120", - model.MetricNameLabel: "request_duration_microseconds_bucket", - }, - Value: 412, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - "le": "100", - model.MetricNameLabel: "request_duration_microseconds_bucket", - }, - Value: 123, - Timestamp: testTime, - }, - }, - }, - { - // The metric type is unset in this protobuf, which needs to be handled - // correctly by the decoder. - in: "\x1c\n\rrequest_count\"\v\x1a\t\t\x00\x00\x00\x00\x00\x00\xf0?", - expected: model.Vector{ - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count", - }, - Value: 1, - Timestamp: testTime, - }, - }, - }, - } - - for i, scenario := range scenarios { - dec := &SampleDecoder{ - Dec: &protoDecoder{r: strings.NewReader(scenario.in)}, - Opts: &DecodeOptions{ - Timestamp: testTime, - }, - } - - var all model.Vector - for { - var smpls model.Vector - err := dec.Decode(&smpls) - if err == io.EOF { - break - } - if scenario.fail { - if err == nil { - t.Fatal("Expected error but got none") - } - break - } - if err != nil { - t.Fatal(err) - } - all = append(all, smpls...) - } - sort.Sort(all) - sort.Sort(scenario.expected) - if !reflect.DeepEqual(all, scenario.expected) { - t.Fatalf("%d. output does not match, want: %#v, got %#v", i, scenario.expected, all) - } - } -} - -func testDiscriminatorHTTPHeader(t testing.TB) { - var scenarios = []struct { - input map[string]string - output Format - err error - }{ - { - input: map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="io.prometheus.client.MetricFamily"; encoding="delimited"`}, - output: FmtProtoDelim, - }, - { - input: map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="illegal"; encoding="delimited"`}, - output: FmtUnknown, - }, - { - input: map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="io.prometheus.client.MetricFamily"; encoding="illegal"`}, - output: FmtUnknown, - }, - { - input: map[string]string{"Content-Type": `text/plain; version=0.0.4`}, - output: FmtText, - }, - { - input: map[string]string{"Content-Type": `text/plain`}, - output: FmtText, - }, - { - input: map[string]string{"Content-Type": `text/plain; version=0.0.3`}, - output: FmtUnknown, - }, - } - - for i, scenario := range scenarios { - var header http.Header - - if len(scenario.input) > 0 { - header = http.Header{} - } - - for key, value := range scenario.input { - header.Add(key, value) - } - - actual := ResponseFormat(header) - - if scenario.output != actual { - t.Errorf("%d. expected %s, got %s", i, scenario.output, actual) - } - } -} - -func TestDiscriminatorHTTPHeader(t *testing.T) { - testDiscriminatorHTTPHeader(t) -} - -func BenchmarkDiscriminatorHTTPHeader(b *testing.B) { - for i := 0; i < b.N; i++ { - testDiscriminatorHTTPHeader(b) - } -} - -func TestExtractSamples(t *testing.T) { - var ( - goodMetricFamily1 = &dto.MetricFamily{ - Name: proto.String("foo"), - Help: proto.String("Help for foo."), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Counter: &dto.Counter{ - Value: proto.Float64(4711), - }, - }, - }, - } - goodMetricFamily2 = &dto.MetricFamily{ - Name: proto.String("bar"), - Help: proto.String("Help for bar."), - Type: dto.MetricType_GAUGE.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Gauge: &dto.Gauge{ - Value: proto.Float64(3.14), - }, - }, - }, - } - badMetricFamily = &dto.MetricFamily{ - Name: proto.String("bad"), - Help: proto.String("Help for bad."), - Type: dto.MetricType(42).Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Gauge: &dto.Gauge{ - Value: proto.Float64(2.7), - }, - }, - }, - } - - opts = &DecodeOptions{ - Timestamp: 42, - } - ) - - got, err := ExtractSamples(opts, goodMetricFamily1, goodMetricFamily2) - if err != nil { - t.Error("Unexpected error from ExtractSamples:", err) - } - want := model.Vector{ - &model.Sample{Metric: model.Metric{model.MetricNameLabel: "foo"}, Value: 4711, Timestamp: 42}, - &model.Sample{Metric: model.Metric{model.MetricNameLabel: "bar"}, Value: 3.14, Timestamp: 42}, - } - if !reflect.DeepEqual(got, want) { - t.Errorf("unexpected samples extracted, got: %v, want: %v", got, want) - } - - got, err = ExtractSamples(opts, goodMetricFamily1, badMetricFamily, goodMetricFamily2) - if err == nil { - t.Error("Expected error from ExtractSamples") - } - if !reflect.DeepEqual(got, want) { - t.Errorf("unexpected samples extracted, got: %v, want: %v", got, want) - } -} diff --git a/vendor/github.com/prometheus/common/expfmt/encode_test.go b/vendor/github.com/prometheus/common/expfmt/encode_test.go deleted file mode 100644 index 1b2287333..000000000 --- a/vendor/github.com/prometheus/common/expfmt/encode_test.go +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package expfmt - -import ( - "bytes" - "github.com/golang/protobuf/proto" - dto "github.com/prometheus/client_model/go" - "net/http" - "testing" -) - -func TestNegotiate(t *testing.T) { - acceptValuePrefix := "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily" - tests := []struct { - name string - acceptHeaderValue string - expectedFmt string - }{ - { - name: "delimited format", - acceptHeaderValue: acceptValuePrefix + ";encoding=delimited", - expectedFmt: string(FmtProtoDelim), - }, - { - name: "text format", - acceptHeaderValue: acceptValuePrefix + ";encoding=text", - expectedFmt: string(FmtProtoText), - }, - { - name: "compact text format", - acceptHeaderValue: acceptValuePrefix + ";encoding=compact-text", - expectedFmt: string(FmtProtoCompact), - }, - { - name: "plain text format", - acceptHeaderValue: "text/plain;version=0.0.4", - expectedFmt: string(FmtText), - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - h := http.Header{} - h.Add(hdrAccept, test.acceptHeaderValue) - actualFmt := string(Negotiate(h)) - if actualFmt != test.expectedFmt { - t.Errorf("expected Negotiate to return format %s, but got %s instead", test.expectedFmt, actualFmt) - } - }) - } -} - -func TestEncode(t *testing.T) { - var buff bytes.Buffer - delimEncoder := NewEncoder(&buff, FmtProtoDelim) - metric := &dto.MetricFamily{ - Name: proto.String("foo_metric"), - Type: dto.MetricType_UNTYPED.Enum(), - Metric: []*dto.Metric{ - { - Untyped: &dto.Untyped{ - Value: proto.Float64(1.234), - }, - }, - }, - } - - err := delimEncoder.Encode(metric) - if err != nil { - t.Errorf("unexpected error during encode: %s", err.Error()) - } - - out := buff.Bytes() - if len(out) == 0 { - t.Errorf("expected the output bytes buffer to be non-empty") - } - - buff.Reset() - - compactEncoder := NewEncoder(&buff, FmtProtoCompact) - err = compactEncoder.Encode(metric) - if err != nil { - t.Errorf("unexpected error during encode: %s", err.Error()) - } - - out = buff.Bytes() - if len(out) == 0 { - t.Errorf("expected the output bytes buffer to be non-empty") - } - - buff.Reset() - - protoTextEncoder := NewEncoder(&buff, FmtProtoText) - err = protoTextEncoder.Encode(metric) - if err != nil { - t.Errorf("unexpected error during encode: %s", err.Error()) - } - - out = buff.Bytes() - if len(out) == 0 { - t.Errorf("expected the output bytes buffer to be non-empty") - } - - buff.Reset() - - textEncoder := NewEncoder(&buff, FmtText) - err = textEncoder.Encode(metric) - if err != nil { - t.Errorf("unexpected error during encode: %s", err.Error()) - } - - out = buff.Bytes() - if len(out) == 0 { - t.Errorf("expected the output bytes buffer to be non-empty") - } - - expected := "# TYPE foo_metric untyped\n" + - "foo_metric 1.234\n" - - if string(out) != expected { - t.Errorf("expected TextEncoder to return %s, but got %s instead", expected, string(out)) - } -} diff --git a/vendor/github.com/prometheus/common/expfmt/text_create_test.go b/vendor/github.com/prometheus/common/expfmt/text_create_test.go deleted file mode 100644 index 86e767c19..000000000 --- a/vendor/github.com/prometheus/common/expfmt/text_create_test.go +++ /dev/null @@ -1,561 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package expfmt - -import ( - "bytes" - "math" - "strings" - "testing" - - "github.com/golang/protobuf/proto" - - dto "github.com/prometheus/client_model/go" -) - -func TestCreate(t *testing.T) { - var scenarios = []struct { - in *dto.MetricFamily - out string - }{ - // 0: Counter, NaN as value, timestamp given. - { - in: &dto.MetricFamily{ - Name: proto.String("name"), - Help: proto.String("two-line\n doc str\\ing"), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("labelname"), - Value: proto.String("val1"), - }, - &dto.LabelPair{ - Name: proto.String("basename"), - Value: proto.String("basevalue"), - }, - }, - Counter: &dto.Counter{ - Value: proto.Float64(math.NaN()), - }, - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("labelname"), - Value: proto.String("val2"), - }, - &dto.LabelPair{ - Name: proto.String("basename"), - Value: proto.String("basevalue"), - }, - }, - Counter: &dto.Counter{ - Value: proto.Float64(.23), - }, - TimestampMs: proto.Int64(1234567890), - }, - }, - }, - out: `# HELP name two-line\n doc str\\ing -# TYPE name counter -name{labelname="val1",basename="basevalue"} NaN -name{labelname="val2",basename="basevalue"} 0.23 1234567890 -`, - }, - // 1: Gauge, some escaping required, +Inf as value, multi-byte characters in label values. - { - in: &dto.MetricFamily{ - Name: proto.String("gauge_name"), - Help: proto.String("gauge\ndoc\nstr\"ing"), - Type: dto.MetricType_GAUGE.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("name_1"), - Value: proto.String("val with\nnew line"), - }, - &dto.LabelPair{ - Name: proto.String("name_2"), - Value: proto.String("val with \\backslash and \"quotes\""), - }, - }, - Gauge: &dto.Gauge{ - Value: proto.Float64(math.Inf(+1)), - }, - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("name_1"), - Value: proto.String("Björn"), - }, - &dto.LabelPair{ - Name: proto.String("name_2"), - Value: proto.String("佖佥"), - }, - }, - Gauge: &dto.Gauge{ - Value: proto.Float64(3.14E42), - }, - }, - }, - }, - out: `# HELP gauge_name gauge\ndoc\nstr"ing -# TYPE gauge_name gauge -gauge_name{name_1="val with\nnew line",name_2="val with \\backslash and \"quotes\""} +Inf -gauge_name{name_1="Björn",name_2="佖佥"} 3.14e+42 -`, - }, - // 2: Untyped, no help, one sample with no labels and -Inf as value, another sample with one label. - { - in: &dto.MetricFamily{ - Name: proto.String("untyped_name"), - Type: dto.MetricType_UNTYPED.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Untyped: &dto.Untyped{ - Value: proto.Float64(math.Inf(-1)), - }, - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("name_1"), - Value: proto.String("value 1"), - }, - }, - Untyped: &dto.Untyped{ - Value: proto.Float64(-1.23e-45), - }, - }, - }, - }, - out: `# TYPE untyped_name untyped -untyped_name -Inf -untyped_name{name_1="value 1"} -1.23e-45 -`, - }, - // 3: Summary. - { - in: &dto.MetricFamily{ - Name: proto.String("summary_name"), - Help: proto.String("summary docstring"), - Type: dto.MetricType_SUMMARY.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Summary: &dto.Summary{ - SampleCount: proto.Uint64(42), - SampleSum: proto.Float64(-3.4567), - Quantile: []*dto.Quantile{ - &dto.Quantile{ - Quantile: proto.Float64(0.5), - Value: proto.Float64(-1.23), - }, - &dto.Quantile{ - Quantile: proto.Float64(0.9), - Value: proto.Float64(.2342354), - }, - &dto.Quantile{ - Quantile: proto.Float64(0.99), - Value: proto.Float64(0), - }, - }, - }, - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("name_1"), - Value: proto.String("value 1"), - }, - &dto.LabelPair{ - Name: proto.String("name_2"), - Value: proto.String("value 2"), - }, - }, - Summary: &dto.Summary{ - SampleCount: proto.Uint64(4711), - SampleSum: proto.Float64(2010.1971), - Quantile: []*dto.Quantile{ - &dto.Quantile{ - Quantile: proto.Float64(0.5), - Value: proto.Float64(1), - }, - &dto.Quantile{ - Quantile: proto.Float64(0.9), - Value: proto.Float64(2), - }, - &dto.Quantile{ - Quantile: proto.Float64(0.99), - Value: proto.Float64(3), - }, - }, - }, - }, - }, - }, - out: `# HELP summary_name summary docstring -# TYPE summary_name summary -summary_name{quantile="0.5"} -1.23 -summary_name{quantile="0.9"} 0.2342354 -summary_name{quantile="0.99"} 0 -summary_name_sum -3.4567 -summary_name_count 42 -summary_name{name_1="value 1",name_2="value 2",quantile="0.5"} 1 -summary_name{name_1="value 1",name_2="value 2",quantile="0.9"} 2 -summary_name{name_1="value 1",name_2="value 2",quantile="0.99"} 3 -summary_name_sum{name_1="value 1",name_2="value 2"} 2010.1971 -summary_name_count{name_1="value 1",name_2="value 2"} 4711 -`, - }, - // 4: Histogram - { - in: &dto.MetricFamily{ - Name: proto.String("request_duration_microseconds"), - Help: proto.String("The response latency."), - Type: dto.MetricType_HISTOGRAM.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Histogram: &dto.Histogram{ - SampleCount: proto.Uint64(2693), - SampleSum: proto.Float64(1756047.3), - Bucket: []*dto.Bucket{ - &dto.Bucket{ - UpperBound: proto.Float64(100), - CumulativeCount: proto.Uint64(123), - }, - &dto.Bucket{ - UpperBound: proto.Float64(120), - CumulativeCount: proto.Uint64(412), - }, - &dto.Bucket{ - UpperBound: proto.Float64(144), - CumulativeCount: proto.Uint64(592), - }, - &dto.Bucket{ - UpperBound: proto.Float64(172.8), - CumulativeCount: proto.Uint64(1524), - }, - &dto.Bucket{ - UpperBound: proto.Float64(math.Inf(+1)), - CumulativeCount: proto.Uint64(2693), - }, - }, - }, - }, - }, - }, - out: `# HELP request_duration_microseconds The response latency. -# TYPE request_duration_microseconds histogram -request_duration_microseconds_bucket{le="100"} 123 -request_duration_microseconds_bucket{le="120"} 412 -request_duration_microseconds_bucket{le="144"} 592 -request_duration_microseconds_bucket{le="172.8"} 1524 -request_duration_microseconds_bucket{le="+Inf"} 2693 -request_duration_microseconds_sum 1.7560473e+06 -request_duration_microseconds_count 2693 -`, - }, - // 5: Histogram with missing +Inf bucket. - { - in: &dto.MetricFamily{ - Name: proto.String("request_duration_microseconds"), - Help: proto.String("The response latency."), - Type: dto.MetricType_HISTOGRAM.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Histogram: &dto.Histogram{ - SampleCount: proto.Uint64(2693), - SampleSum: proto.Float64(1756047.3), - Bucket: []*dto.Bucket{ - &dto.Bucket{ - UpperBound: proto.Float64(100), - CumulativeCount: proto.Uint64(123), - }, - &dto.Bucket{ - UpperBound: proto.Float64(120), - CumulativeCount: proto.Uint64(412), - }, - &dto.Bucket{ - UpperBound: proto.Float64(144), - CumulativeCount: proto.Uint64(592), - }, - &dto.Bucket{ - UpperBound: proto.Float64(172.8), - CumulativeCount: proto.Uint64(1524), - }, - }, - }, - }, - }, - }, - out: `# HELP request_duration_microseconds The response latency. -# TYPE request_duration_microseconds histogram -request_duration_microseconds_bucket{le="100"} 123 -request_duration_microseconds_bucket{le="120"} 412 -request_duration_microseconds_bucket{le="144"} 592 -request_duration_microseconds_bucket{le="172.8"} 1524 -request_duration_microseconds_bucket{le="+Inf"} 2693 -request_duration_microseconds_sum 1.7560473e+06 -request_duration_microseconds_count 2693 -`, - }, - // 6: No metric type, should result in default type Counter. - { - in: &dto.MetricFamily{ - Name: proto.String("name"), - Help: proto.String("doc string"), - Metric: []*dto.Metric{ - &dto.Metric{ - Counter: &dto.Counter{ - Value: proto.Float64(math.Inf(-1)), - }, - }, - }, - }, - out: `# HELP name doc string -# TYPE name counter -name -Inf -`, - }, - } - - for i, scenario := range scenarios { - out := bytes.NewBuffer(make([]byte, 0, len(scenario.out))) - n, err := MetricFamilyToText(out, scenario.in) - if err != nil { - t.Errorf("%d. error: %s", i, err) - continue - } - if expected, got := len(scenario.out), n; expected != got { - t.Errorf( - "%d. expected %d bytes written, got %d", - i, expected, got, - ) - } - if expected, got := scenario.out, out.String(); expected != got { - t.Errorf( - "%d. expected out=%q, got %q", - i, expected, got, - ) - } - } - -} - -func BenchmarkCreate(b *testing.B) { - mf := &dto.MetricFamily{ - Name: proto.String("request_duration_microseconds"), - Help: proto.String("The response latency."), - Type: dto.MetricType_HISTOGRAM.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("name_1"), - Value: proto.String("val with\nnew line"), - }, - &dto.LabelPair{ - Name: proto.String("name_2"), - Value: proto.String("val with \\backslash and \"quotes\""), - }, - &dto.LabelPair{ - Name: proto.String("name_3"), - Value: proto.String("Just a quite long label value to test performance."), - }, - }, - Histogram: &dto.Histogram{ - SampleCount: proto.Uint64(2693), - SampleSum: proto.Float64(1756047.3), - Bucket: []*dto.Bucket{ - &dto.Bucket{ - UpperBound: proto.Float64(100), - CumulativeCount: proto.Uint64(123), - }, - &dto.Bucket{ - UpperBound: proto.Float64(120), - CumulativeCount: proto.Uint64(412), - }, - &dto.Bucket{ - UpperBound: proto.Float64(144), - CumulativeCount: proto.Uint64(592), - }, - &dto.Bucket{ - UpperBound: proto.Float64(172.8), - CumulativeCount: proto.Uint64(1524), - }, - &dto.Bucket{ - UpperBound: proto.Float64(math.Inf(+1)), - CumulativeCount: proto.Uint64(2693), - }, - }, - }, - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("name_1"), - Value: proto.String("Björn"), - }, - &dto.LabelPair{ - Name: proto.String("name_2"), - Value: proto.String("佖佥"), - }, - &dto.LabelPair{ - Name: proto.String("name_3"), - Value: proto.String("Just a quite long label value to test performance."), - }, - }, - Histogram: &dto.Histogram{ - SampleCount: proto.Uint64(5699), - SampleSum: proto.Float64(49484343543.4343), - Bucket: []*dto.Bucket{ - &dto.Bucket{ - UpperBound: proto.Float64(100), - CumulativeCount: proto.Uint64(120), - }, - &dto.Bucket{ - UpperBound: proto.Float64(120), - CumulativeCount: proto.Uint64(412), - }, - &dto.Bucket{ - UpperBound: proto.Float64(144), - CumulativeCount: proto.Uint64(596), - }, - &dto.Bucket{ - UpperBound: proto.Float64(172.8), - CumulativeCount: proto.Uint64(1535), - }, - }, - }, - TimestampMs: proto.Int64(1234567890), - }, - }, - } - out := bytes.NewBuffer(make([]byte, 0, 1024)) - - for i := 0; i < b.N; i++ { - _, err := MetricFamilyToText(out, mf) - if err != nil { - b.Fatal(err) - } - out.Reset() - } -} - -func BenchmarkCreateBuildInfo(b *testing.B) { - mf := &dto.MetricFamily{ - Name: proto.String("benchmark_build_info"), - Help: proto.String("Test the creation of constant 1-value build_info metric."), - Type: dto.MetricType_GAUGE.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("version"), - Value: proto.String("1.2.3"), - }, - &dto.LabelPair{ - Name: proto.String("revision"), - Value: proto.String("2e84f5e4eacdffb574035810305191ff390360fe"), - }, - &dto.LabelPair{ - Name: proto.String("go_version"), - Value: proto.String("1.11.1"), - }, - }, - Gauge: &dto.Gauge{ - Value: proto.Float64(1), - }, - }, - }, - } - out := bytes.NewBuffer(make([]byte, 0, 1024)) - - for i := 0; i < b.N; i++ { - _, err := MetricFamilyToText(out, mf) - if err != nil { - b.Fatal(err) - } - out.Reset() - } -} - -func TestCreateError(t *testing.T) { - var scenarios = []struct { - in *dto.MetricFamily - err string - }{ - // 0: No metric. - { - in: &dto.MetricFamily{ - Name: proto.String("name"), - Help: proto.String("doc string"), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{}, - }, - err: "MetricFamily has no metrics", - }, - // 1: No metric name. - { - in: &dto.MetricFamily{ - Help: proto.String("doc string"), - Type: dto.MetricType_UNTYPED.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Untyped: &dto.Untyped{ - Value: proto.Float64(math.Inf(-1)), - }, - }, - }, - }, - err: "MetricFamily has no name", - }, - // 2: Wrong type. - { - in: &dto.MetricFamily{ - Name: proto.String("name"), - Help: proto.String("doc string"), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Untyped: &dto.Untyped{ - Value: proto.Float64(math.Inf(-1)), - }, - }, - }, - }, - err: "expected counter in metric", - }, - } - - for i, scenario := range scenarios { - var out bytes.Buffer - _, err := MetricFamilyToText(&out, scenario.in) - if err == nil { - t.Errorf("%d. expected error, got nil", i) - continue - } - if expected, got := scenario.err, err.Error(); strings.Index(got, expected) != 0 { - t.Errorf( - "%d. expected error starting with %q, got %q", - i, expected, got, - ) - } - } - -} diff --git a/vendor/github.com/prometheus/common/expfmt/text_parse_test.go b/vendor/github.com/prometheus/common/expfmt/text_parse_test.go deleted file mode 100644 index 76c951185..000000000 --- a/vendor/github.com/prometheus/common/expfmt/text_parse_test.go +++ /dev/null @@ -1,593 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package expfmt - -import ( - "math" - "strings" - "testing" - - "github.com/golang/protobuf/proto" - dto "github.com/prometheus/client_model/go" -) - -func testTextParse(t testing.TB) { - var scenarios = []struct { - in string - out []*dto.MetricFamily - }{ - // 0: Empty lines as input. - { - in: ` - -`, - out: []*dto.MetricFamily{}, - }, - // 1: Minimal case. - { - in: ` -minimal_metric 1.234 -another_metric -3e3 103948 -# Even that: -no_labels{} 3 -# HELP line for non-existing metric will be ignored. -`, - out: []*dto.MetricFamily{ - &dto.MetricFamily{ - Name: proto.String("minimal_metric"), - Type: dto.MetricType_UNTYPED.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Untyped: &dto.Untyped{ - Value: proto.Float64(1.234), - }, - }, - }, - }, - &dto.MetricFamily{ - Name: proto.String("another_metric"), - Type: dto.MetricType_UNTYPED.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Untyped: &dto.Untyped{ - Value: proto.Float64(-3e3), - }, - TimestampMs: proto.Int64(103948), - }, - }, - }, - &dto.MetricFamily{ - Name: proto.String("no_labels"), - Type: dto.MetricType_UNTYPED.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Untyped: &dto.Untyped{ - Value: proto.Float64(3), - }, - }, - }, - }, - }, - }, - // 2: Counters & gauges, docstrings, various whitespace, escape sequences. - { - in: ` -# A normal comment. -# -# TYPE name counter -name{labelname="val1",basename="basevalue"} NaN -name {labelname="val2",basename="base\"v\\al\nue"} 0.23 1234567890 -# HELP name two-line\n doc str\\ing - - # HELP name2 doc str"ing 2 - # TYPE name2 gauge -name2{labelname="val2" ,basename = "basevalue2" } +Inf 54321 -name2{ labelname = "val1" , }-Inf -`, - out: []*dto.MetricFamily{ - &dto.MetricFamily{ - Name: proto.String("name"), - Help: proto.String("two-line\n doc str\\ing"), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("labelname"), - Value: proto.String("val1"), - }, - &dto.LabelPair{ - Name: proto.String("basename"), - Value: proto.String("basevalue"), - }, - }, - Counter: &dto.Counter{ - Value: proto.Float64(math.NaN()), - }, - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("labelname"), - Value: proto.String("val2"), - }, - &dto.LabelPair{ - Name: proto.String("basename"), - Value: proto.String("base\"v\\al\nue"), - }, - }, - Counter: &dto.Counter{ - Value: proto.Float64(.23), - }, - TimestampMs: proto.Int64(1234567890), - }, - }, - }, - &dto.MetricFamily{ - Name: proto.String("name2"), - Help: proto.String("doc str\"ing 2"), - Type: dto.MetricType_GAUGE.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("labelname"), - Value: proto.String("val2"), - }, - &dto.LabelPair{ - Name: proto.String("basename"), - Value: proto.String("basevalue2"), - }, - }, - Gauge: &dto.Gauge{ - Value: proto.Float64(math.Inf(+1)), - }, - TimestampMs: proto.Int64(54321), - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("labelname"), - Value: proto.String("val1"), - }, - }, - Gauge: &dto.Gauge{ - Value: proto.Float64(math.Inf(-1)), - }, - }, - }, - }, - }, - }, - // 3: The evil summary, mixed with other types and funny comments. - { - in: ` -# TYPE my_summary summary -my_summary{n1="val1",quantile="0.5"} 110 -decoy -1 -2 -my_summary{n1="val1",quantile="0.9"} 140 1 -my_summary_count{n1="val1"} 42 -# Latest timestamp wins in case of a summary. -my_summary_sum{n1="val1"} 4711 2 -fake_sum{n1="val1"} 2001 -# TYPE another_summary summary -another_summary_count{n2="val2",n1="val1"} 20 -my_summary_count{n2="val2",n1="val1"} 5 5 -another_summary{n1="val1",n2="val2",quantile=".3"} -1.2 -my_summary_sum{n1="val2"} 08 15 -my_summary{n1="val3", quantile="0.2"} 4711 - my_summary{n1="val1",n2="val2",quantile="-12.34",} NaN -# some -# funny comments -# HELP -# HELP -# HELP my_summary -# HELP my_summary -`, - out: []*dto.MetricFamily{ - &dto.MetricFamily{ - Name: proto.String("fake_sum"), - Type: dto.MetricType_UNTYPED.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("n1"), - Value: proto.String("val1"), - }, - }, - Untyped: &dto.Untyped{ - Value: proto.Float64(2001), - }, - }, - }, - }, - &dto.MetricFamily{ - Name: proto.String("decoy"), - Type: dto.MetricType_UNTYPED.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Untyped: &dto.Untyped{ - Value: proto.Float64(-1), - }, - TimestampMs: proto.Int64(-2), - }, - }, - }, - &dto.MetricFamily{ - Name: proto.String("my_summary"), - Type: dto.MetricType_SUMMARY.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("n1"), - Value: proto.String("val1"), - }, - }, - Summary: &dto.Summary{ - SampleCount: proto.Uint64(42), - SampleSum: proto.Float64(4711), - Quantile: []*dto.Quantile{ - &dto.Quantile{ - Quantile: proto.Float64(0.5), - Value: proto.Float64(110), - }, - &dto.Quantile{ - Quantile: proto.Float64(0.9), - Value: proto.Float64(140), - }, - }, - }, - TimestampMs: proto.Int64(2), - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("n2"), - Value: proto.String("val2"), - }, - &dto.LabelPair{ - Name: proto.String("n1"), - Value: proto.String("val1"), - }, - }, - Summary: &dto.Summary{ - SampleCount: proto.Uint64(5), - Quantile: []*dto.Quantile{ - &dto.Quantile{ - Quantile: proto.Float64(-12.34), - Value: proto.Float64(math.NaN()), - }, - }, - }, - TimestampMs: proto.Int64(5), - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("n1"), - Value: proto.String("val2"), - }, - }, - Summary: &dto.Summary{ - SampleSum: proto.Float64(8), - }, - TimestampMs: proto.Int64(15), - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("n1"), - Value: proto.String("val3"), - }, - }, - Summary: &dto.Summary{ - Quantile: []*dto.Quantile{ - &dto.Quantile{ - Quantile: proto.Float64(0.2), - Value: proto.Float64(4711), - }, - }, - }, - }, - }, - }, - &dto.MetricFamily{ - Name: proto.String("another_summary"), - Type: dto.MetricType_SUMMARY.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("n2"), - Value: proto.String("val2"), - }, - &dto.LabelPair{ - Name: proto.String("n1"), - Value: proto.String("val1"), - }, - }, - Summary: &dto.Summary{ - SampleCount: proto.Uint64(20), - Quantile: []*dto.Quantile{ - &dto.Quantile{ - Quantile: proto.Float64(0.3), - Value: proto.Float64(-1.2), - }, - }, - }, - }, - }, - }, - }, - }, - // 4: The histogram. - { - in: ` -# HELP request_duration_microseconds The response latency. -# TYPE request_duration_microseconds histogram -request_duration_microseconds_bucket{le="100"} 123 -request_duration_microseconds_bucket{le="120"} 412 -request_duration_microseconds_bucket{le="144"} 592 -request_duration_microseconds_bucket{le="172.8"} 1524 -request_duration_microseconds_bucket{le="+Inf"} 2693 -request_duration_microseconds_sum 1.7560473e+06 -request_duration_microseconds_count 2693 -`, - out: []*dto.MetricFamily{ - { - Name: proto.String("request_duration_microseconds"), - Help: proto.String("The response latency."), - Type: dto.MetricType_HISTOGRAM.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Histogram: &dto.Histogram{ - SampleCount: proto.Uint64(2693), - SampleSum: proto.Float64(1756047.3), - Bucket: []*dto.Bucket{ - &dto.Bucket{ - UpperBound: proto.Float64(100), - CumulativeCount: proto.Uint64(123), - }, - &dto.Bucket{ - UpperBound: proto.Float64(120), - CumulativeCount: proto.Uint64(412), - }, - &dto.Bucket{ - UpperBound: proto.Float64(144), - CumulativeCount: proto.Uint64(592), - }, - &dto.Bucket{ - UpperBound: proto.Float64(172.8), - CumulativeCount: proto.Uint64(1524), - }, - &dto.Bucket{ - UpperBound: proto.Float64(math.Inf(+1)), - CumulativeCount: proto.Uint64(2693), - }, - }, - }, - }, - }, - }, - }, - }, - } - - for i, scenario := range scenarios { - out, err := parser.TextToMetricFamilies(strings.NewReader(scenario.in)) - if err != nil { - t.Errorf("%d. error: %s", i, err) - continue - } - if expected, got := len(scenario.out), len(out); expected != got { - t.Errorf( - "%d. expected %d MetricFamilies, got %d", - i, expected, got, - ) - } - for _, expected := range scenario.out { - got, ok := out[expected.GetName()] - if !ok { - t.Errorf( - "%d. expected MetricFamily %q, found none", - i, expected.GetName(), - ) - continue - } - if expected.String() != got.String() { - t.Errorf( - "%d. expected MetricFamily %s, got %s", - i, expected, got, - ) - } - } - } -} - -func TestTextParse(t *testing.T) { - testTextParse(t) -} - -func BenchmarkTextParse(b *testing.B) { - for i := 0; i < b.N; i++ { - testTextParse(b) - } -} - -func testTextParseError(t testing.TB) { - var scenarios = []struct { - in string - err string - }{ - // 0: No new-line at end of input. - { - in: ` -bla 3.14 -blubber 42`, - err: "text format parsing error in line 3: unexpected end of input stream", - }, - // 1: Invalid escape sequence in label value. - { - in: `metric{label="\t"} 3.14`, - err: "text format parsing error in line 1: invalid escape sequence", - }, - // 2: Newline in label value. - { - in: ` -metric{label="new -line"} 3.14 -`, - err: `text format parsing error in line 2: label value "new" contains unescaped new-line`, - }, - // 3: - { - in: `metric{@="bla"} 3.14`, - err: "text format parsing error in line 1: invalid label name for metric", - }, - // 4: - { - in: `metric{__name__="bla"} 3.14`, - err: `text format parsing error in line 1: label name "__name__" is reserved`, - }, - // 5: - { - in: `metric{label+="bla"} 3.14`, - err: "text format parsing error in line 1: expected '=' after label name", - }, - // 6: - { - in: `metric{label=bla} 3.14`, - err: "text format parsing error in line 1: expected '\"' at start of label value", - }, - // 7: - { - in: ` -# TYPE metric summary -metric{quantile="bla"} 3.14 -`, - err: "text format parsing error in line 3: expected float as value for 'quantile' label", - }, - // 8: - { - in: `metric{label="bla"+} 3.14`, - err: "text format parsing error in line 1: unexpected end of label value", - }, - // 9: - { - in: `metric{label="bla"} 3.14 2.72 -`, - err: "text format parsing error in line 1: expected integer as timestamp", - }, - // 10: - { - in: `metric{label="bla"} 3.14 2 3 -`, - err: "text format parsing error in line 1: spurious string after timestamp", - }, - // 11: - { - in: `metric{label="bla"} blubb -`, - err: "text format parsing error in line 1: expected float as value", - }, - // 12: - { - in: ` -# HELP metric one -# HELP metric two -`, - err: "text format parsing error in line 3: second HELP line for metric name", - }, - // 13: - { - in: ` -# TYPE metric counter -# TYPE metric untyped -`, - err: `text format parsing error in line 3: second TYPE line for metric name "metric", or TYPE reported after samples`, - }, - // 14: - { - in: ` -metric 4.12 -# TYPE metric counter -`, - err: `text format parsing error in line 3: second TYPE line for metric name "metric", or TYPE reported after samples`, - }, - // 14: - { - in: ` -# TYPE metric bla -`, - err: "text format parsing error in line 2: unknown metric type", - }, - // 15: - { - in: ` -# TYPE met-ric -`, - err: "text format parsing error in line 2: invalid metric name in comment", - }, - // 16: - { - in: `@invalidmetric{label="bla"} 3.14 2`, - err: "text format parsing error in line 1: invalid metric name", - }, - // 17: - { - in: `{label="bla"} 3.14 2`, - err: "text format parsing error in line 1: invalid metric name", - }, - // 18: - { - in: ` -# TYPE metric histogram -metric_bucket{le="bla"} 3.14 -`, - err: "text format parsing error in line 3: expected float as value for 'le' label", - }, - // 19: Invalid UTF-8 in label value. - { - in: "metric{l=\"\xbd\"} 3.14\n", - err: "text format parsing error in line 1: invalid label value \"\\xbd\"", - }, - } - - for i, scenario := range scenarios { - _, err := parser.TextToMetricFamilies(strings.NewReader(scenario.in)) - if err == nil { - t.Errorf("%d. expected error, got nil", i) - continue - } - if expected, got := scenario.err, err.Error(); strings.Index(got, expected) != 0 { - t.Errorf( - "%d. expected error starting with %q, got %q", - i, expected, got, - ) - } - } - -} - -func TestTextParseError(t *testing.T) { - testTextParseError(t) -} - -func BenchmarkParseError(b *testing.B) { - for i := 0; i < b.N; i++ { - testTextParseError(b) - } -} diff --git a/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg_test.go b/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg_test.go deleted file mode 100644 index aa424b3da..000000000 --- a/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg_test.go +++ /dev/null @@ -1,73 +0,0 @@ -/* -Copyright (c) 2011, Open Knowledge Foundation Ltd. -All rights reserved. - -HTTP Content-Type Autonegotiation. - -The functions in this package implement the behaviour specified in -http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - Neither the name of the Open Knowledge Foundation Ltd. nor the - names of its contributors may be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -*/ -package goautoneg - -import ( - "testing" -) - -var chrome = "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5" - -func TestParseAccept(t *testing.T) { - alternatives := []string{"text/html", "image/png"} - content_type := Negotiate(chrome, alternatives) - if content_type != "image/png" { - t.Errorf("got %s expected image/png", content_type) - } - - alternatives = []string{"text/html", "text/plain", "text/n3"} - content_type = Negotiate(chrome, alternatives) - if content_type != "text/html" { - t.Errorf("got %s expected text/html", content_type) - } - - alternatives = []string{"text/n3", "text/plain"} - content_type = Negotiate(chrome, alternatives) - if content_type != "text/plain" { - t.Errorf("got %s expected text/plain", content_type) - } - - alternatives = []string{"text/n3", "application/rdf+xml"} - content_type = Negotiate(chrome, alternatives) - if content_type != "text/n3" { - t.Errorf("got %s expected text/n3", content_type) - } -} diff --git a/vendor/github.com/prometheus/common/model/alert_test.go b/vendor/github.com/prometheus/common/model/alert_test.go deleted file mode 100644 index e4c93a392..000000000 --- a/vendor/github.com/prometheus/common/model/alert_test.go +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright 2013 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "fmt" - "sort" - "strings" - "testing" - "time" -) - -func TestAlertValidate(t *testing.T) { - ts := time.Now() - - var cases = []struct { - alert *Alert - err string - }{ - { - alert: &Alert{ - Labels: LabelSet{"a": "b"}, - StartsAt: ts, - }, - }, - { - alert: &Alert{ - Labels: LabelSet{"a": "b"}, - }, - err: "start time missing", - }, - { - alert: &Alert{ - Labels: LabelSet{"a": "b"}, - StartsAt: ts, - EndsAt: ts, - }, - }, - { - alert: &Alert{ - Labels: LabelSet{"a": "b"}, - StartsAt: ts, - EndsAt: ts.Add(1 * time.Minute), - }, - }, - { - alert: &Alert{ - Labels: LabelSet{"a": "b"}, - StartsAt: ts, - EndsAt: ts.Add(-1 * time.Minute), - }, - err: "start time must be before end time", - }, - { - alert: &Alert{ - StartsAt: ts, - }, - err: "at least one label pair required", - }, - { - alert: &Alert{ - Labels: LabelSet{"a": "b", "!bad": "label"}, - StartsAt: ts, - }, - err: "invalid label set: invalid name", - }, - { - alert: &Alert{ - Labels: LabelSet{"a": "b", "bad": "\xfflabel"}, - StartsAt: ts, - }, - err: "invalid label set: invalid value", - }, - { - alert: &Alert{ - Labels: LabelSet{"a": "b"}, - Annotations: LabelSet{"!bad": "label"}, - StartsAt: ts, - }, - err: "invalid annotations: invalid name", - }, - { - alert: &Alert{ - Labels: LabelSet{"a": "b"}, - Annotations: LabelSet{"bad": "\xfflabel"}, - StartsAt: ts, - }, - err: "invalid annotations: invalid value", - }, - } - - for i, c := range cases { - err := c.alert.Validate() - if err == nil { - if c.err == "" { - continue - } - t.Errorf("%d. Expected error %q but got none", i, c.err) - continue - } - if c.err == "" && err != nil { - t.Errorf("%d. Expected no error but got %q", i, err) - continue - } - if !strings.Contains(err.Error(), c.err) { - t.Errorf("%d. Expected error to contain %q but got %q", i, c.err, err) - } - } -} - -func TestAlert(t *testing.T) { - // Verifying that an alert with no EndsAt field is unresolved and has firing status. - alert := &Alert{ - Labels: LabelSet{"foo": "bar", "lorem": "ipsum"}, - StartsAt: time.Now(), - } - - actual := fmt.Sprint(alert) - expected := "[d181d0f][active]" - - if actual != expected { - t.Errorf("expected %s, but got %s", expected, actual) - } - - actualStatus := string(alert.Status()) - expectedStatus := "firing" - - if actualStatus != expectedStatus { - t.Errorf("expected alertStatus %s, but got %s", expectedStatus, actualStatus) - } - - // Verifying that an alert with an EndsAt time before the current time is resolved and has resolved status. - ts := time.Now() - ts1 := ts.Add(-2 * time.Minute) - ts2 := ts.Add(-1 * time.Minute) - alert = &Alert{ - Labels: LabelSet{"foo": "bar", "lorem": "ipsum"}, - StartsAt: ts1, - EndsAt: ts2, - } - - actual = fmt.Sprint(alert) - expected = "[d181d0f][resolved]" - - if actual != expected { - t.Errorf("expected %s, but got %s", expected, actual) - } - - actualStatus = string(alert.Status()) - expectedStatus = "resolved" - - if actualStatus != expectedStatus { - t.Errorf("expected alertStatus %s, but got %s", expectedStatus, actualStatus) - } -} - -func TestSortAlerts(t *testing.T) { - ts := time.Now() - alerts := Alerts{ - { - Labels: LabelSet{ - "alertname": "InternalError", - "dev": "sda3", - }, - StartsAt: ts.Add(-6 * time.Minute), - EndsAt: ts.Add(-3 * time.Minute), - }, - { - Labels: LabelSet{ - "alertname": "DiskFull", - "dev": "sda1", - }, - StartsAt: ts.Add(-5 * time.Minute), - EndsAt: ts.Add(-4 * time.Minute), - }, - { - Labels: LabelSet{ - "alertname": "OutOfMemory", - "dev": "sda1", - }, - StartsAt: ts.Add(-2 * time.Minute), - EndsAt: ts.Add(-1 * time.Minute), - }, - { - Labels: LabelSet{ - "alertname": "DiskFull", - "dev": "sda2", - }, - StartsAt: ts.Add(-2 * time.Minute), - EndsAt: ts.Add(-3 * time.Minute), - }, - { - Labels: LabelSet{ - "alertname": "OutOfMemory", - "dev": "sda2", - }, - StartsAt: ts.Add(-5 * time.Minute), - EndsAt: ts.Add(-2 * time.Minute), - }, - } - - sort.Sort(alerts) - - expected := []string{ - "DiskFull[5ffe595][resolved]", - "InternalError[09cfd46][resolved]", - "OutOfMemory[d43a602][resolved]", - "DiskFull[5ff4595][resolved]", - "OutOfMemory[d444602][resolved]", - } - - for i := range alerts { - if alerts[i].String() != expected[i] { - t.Errorf("expected alert %s at index %d, but got %s", expected[i], i, alerts[i].String()) - } - } -} - -func TestAlertsStatus(t *testing.T) { - firingAlerts := Alerts{ - { - Labels: LabelSet{ - "foo": "bar", - }, - StartsAt: time.Now(), - }, - { - Labels: LabelSet{ - "bar": "baz", - }, - StartsAt: time.Now(), - }, - } - - actualStatus := firingAlerts.Status() - expectedStatus := AlertFiring - - if actualStatus != expectedStatus { - t.Errorf("expected status %s, but got %s", expectedStatus, actualStatus) - } - - ts := time.Now() - resolvedAlerts := Alerts{ - { - Labels: LabelSet{ - "foo": "bar", - }, - StartsAt: ts.Add(-1 * time.Minute), - EndsAt: ts, - }, - { - Labels: LabelSet{ - "bar": "baz", - }, - StartsAt: ts.Add(-1 * time.Minute), - EndsAt: ts, - }, - } - - actualStatus = resolvedAlerts.Status() - expectedStatus = AlertResolved - - if actualStatus != expectedStatus { - t.Errorf("expected status %s, but got %s", expectedStatus, actualStatus) - } -} diff --git a/vendor/github.com/prometheus/common/model/fingerprinting_test.go b/vendor/github.com/prometheus/common/model/fingerprinting_test.go deleted file mode 100644 index b12375100..000000000 --- a/vendor/github.com/prometheus/common/model/fingerprinting_test.go +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright 2019 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "sort" - "testing" -) - -func TestFingerprintFromString(t *testing.T) { - fs := "4294967295" - - f, err := FingerprintFromString(fs) - - if err != nil { - t.Errorf("unexpected error while getting Fingerprint from string: %s", err.Error()) - } - - expected := Fingerprint(285960729237) - - if expected != f { - t.Errorf("expected to get %d, but got %d instead", f, expected) - } - - f, err = ParseFingerprint(fs) - - if err != nil { - t.Errorf("unexpected error while getting Fingerprint from string: %s", err.Error()) - } - - if expected != f { - t.Errorf("expected to get %d, but got %d instead", f, expected) - } -} - -func TestFingerprintsSort(t *testing.T) { - fingerPrints := Fingerprints{ - 14695981039346656037, - 285960729237, - 0, - 4294967295, - 285960729237, - 18446744073709551615, - } - - sort.Sort(fingerPrints) - - expected := Fingerprints{ - 0, - 4294967295, - 285960729237, - 285960729237, - 14695981039346656037, - 18446744073709551615, - } - - for i, f := range fingerPrints { - if f != expected[i] { - t.Errorf("expected Fingerprint %d, but got %d for index %d", expected[i], f, i) - } - } -} - -func TestFingerprintSet(t *testing.T) { - // Testing with two sets of unequal length. - f := FingerprintSet{ - 14695981039346656037: struct{}{}, - 0: struct{}{}, - 4294967295: struct{}{}, - 285960729237: struct{}{}, - 18446744073709551615: struct{}{}, - } - - f2 := FingerprintSet{ - 285960729237: struct{}{}, - } - - if f.Equal(f2) { - t.Errorf("expected two FingerPrintSets of unequal length to be unequal") - } - - // Testing with two unequal sets of equal length. - f = FingerprintSet{ - 14695981039346656037: struct{}{}, - 0: struct{}{}, - 4294967295: struct{}{}, - } - - f2 = FingerprintSet{ - 14695981039346656037: struct{}{}, - 0: struct{}{}, - 285960729237: struct{}{}, - } - - if f.Equal(f2) { - t.Errorf("expected two FingerPrintSets of unequal content to be unequal") - } - - // Testing with equal sets of equal length. - f = FingerprintSet{ - 14695981039346656037: struct{}{}, - 0: struct{}{}, - 4294967295: struct{}{}, - } - - f2 = FingerprintSet{ - 14695981039346656037: struct{}{}, - 0: struct{}{}, - 4294967295: struct{}{}, - } - - if !f.Equal(f2) { - t.Errorf("expected two FingerPrintSets of equal content to be equal") - } -} - -func TestFingerprintIntersection(t *testing.T) { - scenarios := []struct { - name string - input1 FingerprintSet - input2 FingerprintSet - expected FingerprintSet - }{ - { - name: "two empty sets", - input1: FingerprintSet{}, - input2: FingerprintSet{}, - expected: FingerprintSet{}, - }, - { - name: "one empty set", - input1: FingerprintSet{ - 0: struct{}{}, - }, - input2: FingerprintSet{}, - expected: FingerprintSet{}, - }, - { - name: "two non-empty unequal sets", - input1: FingerprintSet{ - 14695981039346656037: struct{}{}, - 0: struct{}{}, - 4294967295: struct{}{}, - }, - - input2: FingerprintSet{ - 14695981039346656037: struct{}{}, - 0: struct{}{}, - 4294967295: struct{}{}, - }, - expected: FingerprintSet{ - 14695981039346656037: struct{}{}, - 0: struct{}{}, - 4294967295: struct{}{}, - }, - }, - { - name: "two non-empty equal sets", - input1: FingerprintSet{ - 14695981039346656037: struct{}{}, - 0: struct{}{}, - 285960729237: struct{}{}, - }, - - input2: FingerprintSet{ - 14695981039346656037: struct{}{}, - 0: struct{}{}, - 4294967295: struct{}{}, - }, - expected: FingerprintSet{ - 14695981039346656037: struct{}{}, - 0: struct{}{}, - }, - }, - { - name: "two non-empty equal sets of unequal length", - input1: FingerprintSet{ - 14695981039346656037: struct{}{}, - 0: struct{}{}, - 285960729237: struct{}{}, - }, - - input2: FingerprintSet{ - 14695981039346656037: struct{}{}, - 0: struct{}{}, - }, - expected: FingerprintSet{ - 14695981039346656037: struct{}{}, - 0: struct{}{}, - }, - }, - } - - for _, scenario := range scenarios { - s1 := scenario.input1 - s2 := scenario.input2 - actual := s1.Intersection(s2) - - if !actual.Equal(scenario.expected) { - t.Errorf("expected %v to be equal to %v", actual, scenario.expected) - } - } -} diff --git a/vendor/github.com/prometheus/common/model/labels_test.go b/vendor/github.com/prometheus/common/model/labels_test.go deleted file mode 100644 index 2ee5b31a3..000000000 --- a/vendor/github.com/prometheus/common/model/labels_test.go +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2013 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "sort" - "testing" -) - -func testLabelNames(t testing.TB) { - var scenarios = []struct { - in LabelNames - out LabelNames - }{ - { - in: LabelNames{"ZZZ", "zzz"}, - out: LabelNames{"ZZZ", "zzz"}, - }, - { - in: LabelNames{"aaa", "AAA"}, - out: LabelNames{"AAA", "aaa"}, - }, - } - - for i, scenario := range scenarios { - sort.Sort(scenario.in) - - for j, expected := range scenario.out { - if expected != scenario.in[j] { - t.Errorf("%d.%d expected %s, got %s", i, j, expected, scenario.in[j]) - } - } - } -} - -func TestLabelNames(t *testing.T) { - testLabelNames(t) -} - -func BenchmarkLabelNames(b *testing.B) { - for i := 0; i < b.N; i++ { - testLabelNames(b) - } -} - -func testLabelValues(t testing.TB) { - var scenarios = []struct { - in LabelValues - out LabelValues - }{ - { - in: LabelValues{"ZZZ", "zzz"}, - out: LabelValues{"ZZZ", "zzz"}, - }, - { - in: LabelValues{"aaa", "AAA"}, - out: LabelValues{"AAA", "aaa"}, - }, - } - - for i, scenario := range scenarios { - sort.Sort(scenario.in) - - for j, expected := range scenario.out { - if expected != scenario.in[j] { - t.Errorf("%d.%d expected %s, got %s", i, j, expected, scenario.in[j]) - } - } - } -} - -func TestLabelValues(t *testing.T) { - testLabelValues(t) -} - -func BenchmarkLabelValues(b *testing.B) { - for i := 0; i < b.N; i++ { - testLabelValues(b) - } -} - -func TestLabelNameIsValid(t *testing.T) { - var scenarios = []struct { - ln LabelName - valid bool - }{ - { - ln: "Avalid_23name", - valid: true, - }, - { - ln: "_Avalid_23name", - valid: true, - }, - { - ln: "1valid_23name", - valid: false, - }, - { - ln: "avalid_23name", - valid: true, - }, - { - ln: "Ava:lid_23name", - valid: false, - }, - { - ln: "a lid_23name", - valid: false, - }, - { - ln: ":leading_colon", - valid: false, - }, - { - ln: "colon:in:the:middle", - valid: false, - }, - } - - for _, s := range scenarios { - if s.ln.IsValid() != s.valid { - t.Errorf("Expected %v for %q using IsValid method", s.valid, s.ln) - } - if LabelNameRE.MatchString(string(s.ln)) != s.valid { - t.Errorf("Expected %v for %q using regexp match", s.valid, s.ln) - } - } -} - -func TestSortLabelPairs(t *testing.T) { - labelPairs := LabelPairs{ - { - Name: "FooName", - Value: "FooValue", - }, - { - Name: "FooName", - Value: "BarValue", - }, - { - Name: "BarName", - Value: "FooValue", - }, - { - Name: "BazName", - Value: "BazValue", - }, - { - Name: "BarName", - Value: "FooValue", - }, - { - Name: "BazName", - Value: "FazValue", - }, - } - - sort.Sort(labelPairs) - - expectedLabelPairs := LabelPairs{ - { - Name: "BarName", - Value: "FooValue", - }, - { - Name: "BarName", - Value: "FooValue", - }, - { - Name: "BazName", - Value: "BazValue", - }, - { - Name: "BazName", - Value: "FazValue", - }, - { - Name: "FooName", - Value: "BarValue", - }, - } - - for i, expected := range expectedLabelPairs { - if expected.Name != labelPairs[i].Name || expected.Value != labelPairs[i].Value { - t.Errorf("%d expected %s, got %s", i, expected, labelPairs[i]) - } - } -} diff --git a/vendor/github.com/prometheus/common/model/labelset_test.go b/vendor/github.com/prometheus/common/model/labelset_test.go deleted file mode 100644 index dfdfc5949..000000000 --- a/vendor/github.com/prometheus/common/model/labelset_test.go +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2019 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "encoding/json" - "testing" -) - -func TestUnmarshalJSONLabelSet(t *testing.T) { - type testConfig struct { - LabelSet LabelSet `yaml:"labelSet,omitempty"` - } - - // valid LabelSet JSON - labelSetJSON := `{ - "labelSet": { - "monitor": "codelab", - "foo": "bar" - } -}` - var c testConfig - err := json.Unmarshal([]byte(labelSetJSON), &c) - - if err != nil { - t.Errorf("unexpected error while marshalling JSON : %s", err.Error()) - } - - labelSetString := c.LabelSet.String() - - expected := `{foo="bar", monitor="codelab"}` - - if expected != labelSetString { - t.Errorf("expected %s but got %s", expected, labelSetString) - } - - // invalid LabelSet JSON - invalidlabelSetJSON := `{ - "labelSet": { - "1nvalid_23name": "codelab", - "foo": "bar" - } -}` - - err = json.Unmarshal([]byte(invalidlabelSetJSON), &c) - expectedErr := `"1nvalid_23name" is not a valid label name` - if err == nil || err.Error() != expectedErr { - t.Errorf("expected an error with message '%s' to be thrown", expectedErr) - } -} - -func TestLabelSetClone(t *testing.T) { - labelSet := LabelSet{ - "monitor": "codelab", - "foo": "bar", - "bar": "baz", - } - - cloneSet := labelSet.Clone() - - if len(labelSet) != len(cloneSet) { - t.Errorf("expected the length of the cloned Label set to be %d, but got %d", - len(labelSet), len(cloneSet)) - } - - for ln, lv := range labelSet { - expected := cloneSet[ln] - if expected != lv { - t.Errorf("expected to get LabelValue %s, but got %s for LabelName %s", expected, lv, ln) - } - } -} - -func TestLabelSetMerge(t *testing.T) { - labelSet := LabelSet{ - "monitor": "codelab", - "foo": "bar", - "bar": "baz", - } - - labelSet2 := LabelSet{ - "monitor": "codelab", - "dolor": "mi", - "lorem": "ipsum", - } - - expectedSet := LabelSet{ - "monitor": "codelab", - "foo": "bar", - "bar": "baz", - "dolor": "mi", - "lorem": "ipsum", - } - - mergedSet := labelSet.Merge(labelSet2) - - if len(mergedSet) != len(expectedSet) { - t.Errorf("expected the length of the cloned Label set to be %d, but got %d", - len(expectedSet), len(mergedSet)) - } - - for ln, lv := range mergedSet { - expected := expectedSet[ln] - if expected != lv { - t.Errorf("expected to get LabelValue %s, but got %s for LabelName %s", expected, lv, ln) - } - } - -} diff --git a/vendor/github.com/prometheus/common/model/metric_test.go b/vendor/github.com/prometheus/common/model/metric_test.go deleted file mode 100644 index db447f6f2..000000000 --- a/vendor/github.com/prometheus/common/model/metric_test.go +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright 2013 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import "testing" - -func testMetric(t testing.TB) { - var scenarios = []struct { - input LabelSet - fingerprint Fingerprint - fastFingerprint Fingerprint - }{ - { - input: LabelSet{}, - fingerprint: 14695981039346656037, - fastFingerprint: 14695981039346656037, - }, - { - input: LabelSet{ - "first_name": "electro", - "occupation": "robot", - "manufacturer": "westinghouse", - }, - fingerprint: 5911716720268894962, - fastFingerprint: 11310079640881077873, - }, - { - input: LabelSet{ - "x": "y", - }, - fingerprint: 8241431561484471700, - fastFingerprint: 13948396922932177635, - }, - { - input: LabelSet{ - "a": "bb", - "b": "c", - }, - fingerprint: 3016285359649981711, - fastFingerprint: 3198632812309449502, - }, - { - input: LabelSet{ - "a": "b", - "bb": "c", - }, - fingerprint: 7122421792099404749, - fastFingerprint: 5774953389407657638, - }, - } - - for i, scenario := range scenarios { - input := Metric(scenario.input) - - if scenario.fingerprint != input.Fingerprint() { - t.Errorf("%d. expected %d, got %d", i, scenario.fingerprint, input.Fingerprint()) - } - if scenario.fastFingerprint != input.FastFingerprint() { - t.Errorf("%d. expected %d, got %d", i, scenario.fastFingerprint, input.FastFingerprint()) - } - } -} - -func TestMetric(t *testing.T) { - testMetric(t) -} - -func BenchmarkMetric(b *testing.B) { - for i := 0; i < b.N; i++ { - testMetric(b) - } -} - -func TestMetricNameIsValid(t *testing.T) { - var scenarios = []struct { - mn LabelValue - valid bool - }{ - { - mn: "Avalid_23name", - valid: true, - }, - { - mn: "_Avalid_23name", - valid: true, - }, - { - mn: "1valid_23name", - valid: false, - }, - { - mn: "avalid_23name", - valid: true, - }, - { - mn: "Ava:lid_23name", - valid: true, - }, - { - mn: "a lid_23name", - valid: false, - }, - { - mn: ":leading_colon", - valid: true, - }, - { - mn: "colon:in:the:middle", - valid: true, - }, - { - mn: "", - valid: false, - }, - } - - for _, s := range scenarios { - if IsValidMetricName(s.mn) != s.valid { - t.Errorf("Expected %v for %q using IsValidMetricName function", s.valid, s.mn) - } - if MetricNameRE.MatchString(string(s.mn)) != s.valid { - t.Errorf("Expected %v for %q using regexp matching", s.valid, s.mn) - } - } -} - -func TestMetricClone(t *testing.T) { - m := Metric{ - "first_name": "electro", - "occupation": "robot", - "manufacturer": "westinghouse", - } - - m2 := m.Clone() - - if len(m) != len(m2) { - t.Errorf("expected the length of the cloned metric to be equal to the input metric") - } - - for ln, lv := range m2 { - expected := m[ln] - if expected != lv { - t.Errorf("expected label value %s but got %s for label name %s", expected, lv, ln) - } - } -} - -func TestMetricToString(t *testing.T) { - scenarios := []struct { - name string - input Metric - expected string - }{ - { - name: "valid metric without __name__ label", - input: Metric{ - "first_name": "electro", - "occupation": "robot", - "manufacturer": "westinghouse", - }, - expected: `{first_name="electro", manufacturer="westinghouse", occupation="robot"}`, - }, - { - name: "valid metric with __name__ label", - input: Metric{ - "__name__": "electro", - "occupation": "robot", - "manufacturer": "westinghouse", - }, - expected: `electro{manufacturer="westinghouse", occupation="robot"}`, - }, - { - name: "empty metric with __name__ label", - input: Metric{ - "__name__": "fooname", - }, - expected: "fooname", - }, - { - name: "empty metric", - input: Metric{}, - expected: "{}", - }, - } - - for _, scenario := range scenarios { - t.Run(scenario.name, func(t *testing.T) { - actual := scenario.input.String() - if actual != scenario.expected { - t.Errorf("expected string output %s but got %s", actual, scenario.expected) - } - }) - } -} diff --git a/vendor/github.com/prometheus/common/model/signature_test.go b/vendor/github.com/prometheus/common/model/signature_test.go deleted file mode 100644 index 0c7970586..000000000 --- a/vendor/github.com/prometheus/common/model/signature_test.go +++ /dev/null @@ -1,325 +0,0 @@ -// Copyright 2014 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "fmt" - "runtime" - "sync" - "testing" -) - -func TestLabelsToSignature(t *testing.T) { - var scenarios = []struct { - in map[string]string - out uint64 - }{ - { - in: map[string]string{}, - out: 14695981039346656037, - }, - { - in: map[string]string{"name": "garland, briggs", "fear": "love is not enough"}, - out: 5799056148416392346, - }, - } - - for i, scenario := range scenarios { - actual := LabelsToSignature(scenario.in) - - if actual != scenario.out { - t.Errorf("%d. expected %d, got %d", i, scenario.out, actual) - } - } -} - -func TestMetricToFingerprint(t *testing.T) { - var scenarios = []struct { - in LabelSet - out Fingerprint - }{ - { - in: LabelSet{}, - out: 14695981039346656037, - }, - { - in: LabelSet{"name": "garland, briggs", "fear": "love is not enough"}, - out: 5799056148416392346, - }, - } - - for i, scenario := range scenarios { - actual := labelSetToFingerprint(scenario.in) - - if actual != scenario.out { - t.Errorf("%d. expected %d, got %d", i, scenario.out, actual) - } - } -} - -func TestMetricToFastFingerprint(t *testing.T) { - var scenarios = []struct { - in LabelSet - out Fingerprint - }{ - { - in: LabelSet{}, - out: 14695981039346656037, - }, - { - in: LabelSet{"name": "garland, briggs", "fear": "love is not enough"}, - out: 12952432476264840823, - }, - } - - for i, scenario := range scenarios { - actual := labelSetToFastFingerprint(scenario.in) - - if actual != scenario.out { - t.Errorf("%d. expected %d, got %d", i, scenario.out, actual) - } - } -} - -func TestSignatureForLabels(t *testing.T) { - var scenarios = []struct { - in Metric - labels LabelNames - out uint64 - }{ - { - in: Metric{}, - labels: nil, - out: 14695981039346656037, - }, - { - in: Metric{}, - labels: LabelNames{"empty"}, - out: 7187873163539638612, - }, - { - in: Metric{"name": "garland, briggs", "fear": "love is not enough"}, - labels: LabelNames{"empty"}, - out: 7187873163539638612, - }, - { - in: Metric{"name": "garland, briggs", "fear": "love is not enough"}, - labels: LabelNames{"fear", "name"}, - out: 5799056148416392346, - }, - { - in: Metric{"name": "garland, briggs", "fear": "love is not enough", "foo": "bar"}, - labels: LabelNames{"fear", "name"}, - out: 5799056148416392346, - }, - { - in: Metric{"name": "garland, briggs", "fear": "love is not enough"}, - labels: LabelNames{}, - out: 14695981039346656037, - }, - { - in: Metric{"name": "garland, briggs", "fear": "love is not enough"}, - labels: nil, - out: 14695981039346656037, - }, - } - - for i, scenario := range scenarios { - actual := SignatureForLabels(scenario.in, scenario.labels...) - - if actual != scenario.out { - t.Errorf("%d. expected %d, got %d", i, scenario.out, actual) - } - } -} - -func TestSignatureWithoutLabels(t *testing.T) { - var scenarios = []struct { - in Metric - labels map[LabelName]struct{} - out uint64 - }{ - { - in: Metric{}, - labels: nil, - out: 14695981039346656037, - }, - { - in: Metric{"name": "garland, briggs", "fear": "love is not enough"}, - labels: map[LabelName]struct{}{"fear": struct{}{}, "name": struct{}{}}, - out: 14695981039346656037, - }, - { - in: Metric{"name": "garland, briggs", "fear": "love is not enough", "foo": "bar"}, - labels: map[LabelName]struct{}{"foo": struct{}{}}, - out: 5799056148416392346, - }, - { - in: Metric{"name": "garland, briggs", "fear": "love is not enough"}, - labels: map[LabelName]struct{}{}, - out: 5799056148416392346, - }, - { - in: Metric{"name": "garland, briggs", "fear": "love is not enough"}, - labels: nil, - out: 5799056148416392346, - }, - } - - for i, scenario := range scenarios { - actual := SignatureWithoutLabels(scenario.in, scenario.labels) - - if actual != scenario.out { - t.Errorf("%d. expected %d, got %d", i, scenario.out, actual) - } - } -} - -func benchmarkLabelToSignature(b *testing.B, l map[string]string, e uint64) { - for i := 0; i < b.N; i++ { - if a := LabelsToSignature(l); a != e { - b.Fatalf("expected signature of %d for %s, got %d", e, l, a) - } - } -} - -func BenchmarkLabelToSignatureScalar(b *testing.B) { - benchmarkLabelToSignature(b, nil, 14695981039346656037) -} - -func BenchmarkLabelToSignatureSingle(b *testing.B) { - benchmarkLabelToSignature(b, map[string]string{"first-label": "first-label-value"}, 5146282821936882169) -} - -func BenchmarkLabelToSignatureDouble(b *testing.B) { - benchmarkLabelToSignature(b, map[string]string{"first-label": "first-label-value", "second-label": "second-label-value"}, 3195800080984914717) -} - -func BenchmarkLabelToSignatureTriple(b *testing.B) { - benchmarkLabelToSignature(b, map[string]string{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 13843036195897128121) -} - -func benchmarkMetricToFingerprint(b *testing.B, ls LabelSet, e Fingerprint) { - for i := 0; i < b.N; i++ { - if a := labelSetToFingerprint(ls); a != e { - b.Fatalf("expected signature of %d for %s, got %d", e, ls, a) - } - } -} - -func BenchmarkMetricToFingerprintScalar(b *testing.B) { - benchmarkMetricToFingerprint(b, nil, 14695981039346656037) -} - -func BenchmarkMetricToFingerprintSingle(b *testing.B) { - benchmarkMetricToFingerprint(b, LabelSet{"first-label": "first-label-value"}, 5146282821936882169) -} - -func BenchmarkMetricToFingerprintDouble(b *testing.B) { - benchmarkMetricToFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value"}, 3195800080984914717) -} - -func BenchmarkMetricToFingerprintTriple(b *testing.B) { - benchmarkMetricToFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 13843036195897128121) -} - -func benchmarkMetricToFastFingerprint(b *testing.B, ls LabelSet, e Fingerprint) { - for i := 0; i < b.N; i++ { - if a := labelSetToFastFingerprint(ls); a != e { - b.Fatalf("expected signature of %d for %s, got %d", e, ls, a) - } - } -} - -func BenchmarkMetricToFastFingerprintScalar(b *testing.B) { - benchmarkMetricToFastFingerprint(b, nil, 14695981039346656037) -} - -func BenchmarkMetricToFastFingerprintSingle(b *testing.B) { - benchmarkMetricToFastFingerprint(b, LabelSet{"first-label": "first-label-value"}, 5147259542624943964) -} - -func BenchmarkMetricToFastFingerprintDouble(b *testing.B) { - benchmarkMetricToFastFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value"}, 18269973311206963528) -} - -func BenchmarkMetricToFastFingerprintTriple(b *testing.B) { - benchmarkMetricToFastFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676) -} - -func BenchmarkEmptyLabelSignature(b *testing.B) { - input := []map[string]string{nil, {}} - - var ms runtime.MemStats - runtime.ReadMemStats(&ms) - - alloc := ms.Alloc - - for _, labels := range input { - LabelsToSignature(labels) - } - - runtime.ReadMemStats(&ms) - - if got := ms.Alloc; alloc != got { - b.Fatal("expected LabelsToSignature with empty labels not to perform allocations") - } -} - -func benchmarkMetricToFastFingerprintConc(b *testing.B, ls LabelSet, e Fingerprint, concLevel int) { - var start, end sync.WaitGroup - start.Add(1) - end.Add(concLevel) - errc := make(chan error, 1) - - for i := 0; i < concLevel; i++ { - go func() { - start.Wait() - for j := b.N / concLevel; j >= 0; j-- { - if a := labelSetToFastFingerprint(ls); a != e { - select { - case errc <- fmt.Errorf("expected signature of %d for %s, got %d", e, ls, a): - default: - } - } - } - end.Done() - }() - } - b.ResetTimer() - start.Done() - end.Wait() - - select { - case err := <-errc: - b.Fatal(err) - default: - } -} - -func BenchmarkMetricToFastFingerprintTripleConc1(b *testing.B) { - benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 1) -} - -func BenchmarkMetricToFastFingerprintTripleConc2(b *testing.B) { - benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 2) -} - -func BenchmarkMetricToFastFingerprintTripleConc4(b *testing.B) { - benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 4) -} - -func BenchmarkMetricToFastFingerprintTripleConc8(b *testing.B) { - benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 8) -} diff --git a/vendor/github.com/prometheus/common/model/silence_test.go b/vendor/github.com/prometheus/common/model/silence_test.go deleted file mode 100644 index f9aae4fc3..000000000 --- a/vendor/github.com/prometheus/common/model/silence_test.go +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2015 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "strings" - "testing" - "time" -) - -func TestMatcherValidate(t *testing.T) { - var cases = []struct { - matcher *Matcher - err string - }{ - { - matcher: &Matcher{ - Name: "name", - Value: "value", - }, - }, - { - matcher: &Matcher{ - Name: "name", - Value: "value", - IsRegex: true, - }, - }, - { - matcher: &Matcher{ - Name: "name!", - Value: "value", - }, - err: "invalid name", - }, - { - matcher: &Matcher{ - Name: "", - Value: "value", - }, - err: "invalid name", - }, - { - matcher: &Matcher{ - Name: "name", - Value: "value\xff", - }, - err: "invalid value", - }, - { - matcher: &Matcher{ - Name: "name", - Value: "", - }, - err: "invalid value", - }, - } - - for i, c := range cases { - err := c.matcher.Validate() - if err == nil { - if c.err == "" { - continue - } - t.Errorf("%d. Expected error %q but got none", i, c.err) - continue - } - if c.err == "" && err != nil { - t.Errorf("%d. Expected no error but got %q", i, err) - continue - } - if !strings.Contains(err.Error(), c.err) { - t.Errorf("%d. Expected error to contain %q but got %q", i, c.err, err) - } - } -} - -func TestSilenceValidate(t *testing.T) { - ts := time.Now() - - var cases = []struct { - sil *Silence - err string - }{ - { - sil: &Silence{ - Matchers: []*Matcher{ - {Name: "name", Value: "value"}, - }, - StartsAt: ts, - EndsAt: ts, - CreatedAt: ts, - CreatedBy: "name", - Comment: "comment", - }, - }, - { - sil: &Silence{ - Matchers: []*Matcher{ - {Name: "name", Value: "value"}, - {Name: "name", Value: "value"}, - {Name: "name", Value: "value"}, - {Name: "name", Value: "value", IsRegex: true}, - }, - StartsAt: ts, - EndsAt: ts, - CreatedAt: ts, - CreatedBy: "name", - Comment: "comment", - }, - }, - { - sil: &Silence{ - Matchers: []*Matcher{ - {Name: "name", Value: "value"}, - }, - StartsAt: ts, - EndsAt: ts.Add(-1 * time.Minute), - CreatedAt: ts, - CreatedBy: "name", - Comment: "comment", - }, - err: "start time must be before end time", - }, - { - sil: &Silence{ - Matchers: []*Matcher{ - {Name: "name", Value: "value"}, - }, - StartsAt: ts, - CreatedAt: ts, - CreatedBy: "name", - Comment: "comment", - }, - err: "end time missing", - }, - { - sil: &Silence{ - Matchers: []*Matcher{ - {Name: "name", Value: "value"}, - }, - EndsAt: ts, - CreatedAt: ts, - CreatedBy: "name", - Comment: "comment", - }, - err: "start time missing", - }, - { - sil: &Silence{ - Matchers: []*Matcher{ - {Name: "!name", Value: "value"}, - }, - StartsAt: ts, - EndsAt: ts, - CreatedAt: ts, - CreatedBy: "name", - Comment: "comment", - }, - err: "invalid matcher", - }, - { - sil: &Silence{ - Matchers: []*Matcher{ - {Name: "name", Value: "value"}, - }, - StartsAt: ts, - EndsAt: ts, - CreatedAt: ts, - CreatedBy: "name", - }, - err: "comment missing", - }, - { - sil: &Silence{ - Matchers: []*Matcher{ - {Name: "name", Value: "value"}, - }, - StartsAt: ts, - EndsAt: ts, - CreatedBy: "name", - Comment: "comment", - }, - err: "creation timestamp missing", - }, - { - sil: &Silence{ - Matchers: []*Matcher{ - {Name: "name", Value: "value"}, - }, - StartsAt: ts, - EndsAt: ts, - CreatedAt: ts, - Comment: "comment", - }, - err: "creator information missing", - }, - { - sil: &Silence{ - Matchers: []*Matcher{}, - StartsAt: ts, - EndsAt: ts, - CreatedAt: ts, - Comment: "comment", - }, - err: "at least one matcher required", - }, - } - - for i, c := range cases { - err := c.sil.Validate() - if err == nil { - if c.err == "" { - continue - } - t.Errorf("%d. Expected error %q but got none", i, c.err) - continue - } - if c.err == "" && err != nil { - t.Errorf("%d. Expected no error but got %q", i, err) - continue - } - if !strings.Contains(err.Error(), c.err) { - t.Errorf("%d. Expected error to contain %q but got %q", i, c.err, err) - } - } -} diff --git a/vendor/github.com/prometheus/common/model/time_test.go b/vendor/github.com/prometheus/common/model/time_test.go deleted file mode 100644 index 3efdd65ff..000000000 --- a/vendor/github.com/prometheus/common/model/time_test.go +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2013 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "testing" - "time" -) - -func TestComparators(t *testing.T) { - t1a := TimeFromUnix(0) - t1b := TimeFromUnix(0) - t2 := TimeFromUnix(2*second - 1) - - if !t1a.Equal(t1b) { - t.Fatalf("Expected %s to be equal to %s", t1a, t1b) - } - if t1a.Equal(t2) { - t.Fatalf("Expected %s to not be equal to %s", t1a, t2) - } - - if !t1a.Before(t2) { - t.Fatalf("Expected %s to be before %s", t1a, t2) - } - if t1a.Before(t1b) { - t.Fatalf("Expected %s to not be before %s", t1a, t1b) - } - - if !t2.After(t1a) { - t.Fatalf("Expected %s to be after %s", t2, t1a) - } - if t1b.After(t1a) { - t.Fatalf("Expected %s to not be after %s", t1b, t1a) - } -} - -func TestTimeConversions(t *testing.T) { - unixSecs := int64(1136239445) - unixNsecs := int64(123456789) - unixNano := unixSecs*1e9 + unixNsecs - - t1 := time.Unix(unixSecs, unixNsecs-unixNsecs%nanosPerTick) - t2 := time.Unix(unixSecs, unixNsecs) - - ts := TimeFromUnixNano(unixNano) - if !ts.Time().Equal(t1) { - t.Fatalf("Expected %s, got %s", t1, ts.Time()) - } - - // Test available precision. - ts = TimeFromUnixNano(t2.UnixNano()) - if !ts.Time().Equal(t1) { - t.Fatalf("Expected %s, got %s", t1, ts.Time()) - } - - if ts.UnixNano() != unixNano-unixNano%nanosPerTick { - t.Fatalf("Expected %d, got %d", unixNano, ts.UnixNano()) - } -} - -func TestDuration(t *testing.T) { - duration := time.Second + time.Minute + time.Hour - goTime := time.Unix(1136239445, 0) - - ts := TimeFromUnix(goTime.Unix()) - if !goTime.Add(duration).Equal(ts.Add(duration).Time()) { - t.Fatalf("Expected %s to be equal to %s", goTime.Add(duration), ts.Add(duration)) - } - - earlier := ts.Add(-duration) - delta := ts.Sub(earlier) - if delta != duration { - t.Fatalf("Expected %s to be equal to %s", delta, duration) - } -} - -func TestParseDuration(t *testing.T) { - var cases = []struct { - in string - out time.Duration - }{ - { - in: "0s", - out: 0, - }, { - in: "324ms", - out: 324 * time.Millisecond, - }, { - in: "3s", - out: 3 * time.Second, - }, { - in: "5m", - out: 5 * time.Minute, - }, { - in: "1h", - out: time.Hour, - }, { - in: "4d", - out: 4 * 24 * time.Hour, - }, { - in: "3w", - out: 3 * 7 * 24 * time.Hour, - }, { - in: "10y", - out: 10 * 365 * 24 * time.Hour, - }, - } - - for _, c := range cases { - d, err := ParseDuration(c.in) - if err != nil { - t.Errorf("Unexpected error on input %q", c.in) - } - if time.Duration(d) != c.out { - t.Errorf("Expected %v but got %v", c.out, d) - } - if d.String() != c.in { - t.Errorf("Expected duration string %q but got %q", c.in, d.String()) - } - } -} diff --git a/vendor/github.com/prometheus/common/model/value_test.go b/vendor/github.com/prometheus/common/model/value_test.go deleted file mode 100644 index 7936a06e8..000000000 --- a/vendor/github.com/prometheus/common/model/value_test.go +++ /dev/null @@ -1,480 +0,0 @@ -// Copyright 2013 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "encoding/json" - "math" - "reflect" - "sort" - "testing" -) - -func TestEqualValues(t *testing.T) { - tests := map[string]struct { - in1, in2 SampleValue - want bool - }{ - "equal floats": { - in1: 3.14, - in2: 3.14, - want: true, - }, - "unequal floats": { - in1: 3.14, - in2: 3.1415, - want: false, - }, - "positive inifinities": { - in1: SampleValue(math.Inf(+1)), - in2: SampleValue(math.Inf(+1)), - want: true, - }, - "negative inifinities": { - in1: SampleValue(math.Inf(-1)), - in2: SampleValue(math.Inf(-1)), - want: true, - }, - "different inifinities": { - in1: SampleValue(math.Inf(+1)), - in2: SampleValue(math.Inf(-1)), - want: false, - }, - "number and infinity": { - in1: 42, - in2: SampleValue(math.Inf(+1)), - want: false, - }, - "number and NaN": { - in1: 42, - in2: SampleValue(math.NaN()), - want: false, - }, - "NaNs": { - in1: SampleValue(math.NaN()), - in2: SampleValue(math.NaN()), - want: true, // !!! - }, - } - - for name, test := range tests { - got := test.in1.Equal(test.in2) - if got != test.want { - t.Errorf("Comparing %s, %f and %f: got %t, want %t", name, test.in1, test.in2, got, test.want) - } - } -} - -func TestEqualSamples(t *testing.T) { - testSample := &Sample{} - - tests := map[string]struct { - in1, in2 *Sample - want bool - }{ - "equal pointers": { - in1: testSample, - in2: testSample, - want: true, - }, - "different metrics": { - in1: &Sample{Metric: Metric{"foo": "bar"}}, - in2: &Sample{Metric: Metric{"foo": "biz"}}, - want: false, - }, - "different timestamp": { - in1: &Sample{Timestamp: 0}, - in2: &Sample{Timestamp: 1}, - want: false, - }, - "different value": { - in1: &Sample{Value: 0}, - in2: &Sample{Value: 1}, - want: false, - }, - "equal samples": { - in1: &Sample{ - Metric: Metric{"foo": "bar"}, - Timestamp: 0, - Value: 1, - }, - in2: &Sample{ - Metric: Metric{"foo": "bar"}, - Timestamp: 0, - Value: 1, - }, - want: true, - }, - } - - for name, test := range tests { - got := test.in1.Equal(test.in2) - if got != test.want { - t.Errorf("Comparing %s, %v and %v: got %t, want %t", name, test.in1, test.in2, got, test.want) - } - } - -} - -func TestSamplePairJSON(t *testing.T) { - input := []struct { - plain string - value SamplePair - }{ - { - plain: `[1234.567,"123.1"]`, - value: SamplePair{ - Value: 123.1, - Timestamp: 1234567, - }, - }, - } - - for _, test := range input { - b, err := json.Marshal(test.value) - if err != nil { - t.Error(err) - continue - } - - if string(b) != test.plain { - t.Errorf("encoding error: expected %q, got %q", test.plain, b) - continue - } - - var sp SamplePair - err = json.Unmarshal(b, &sp) - if err != nil { - t.Error(err) - continue - } - - if sp != test.value { - t.Errorf("decoding error: expected %v, got %v", test.value, sp) - } - } -} - -func TestSampleJSON(t *testing.T) { - input := []struct { - plain string - value Sample - }{ - { - plain: `{"metric":{"__name__":"test_metric"},"value":[1234.567,"123.1"]}`, - value: Sample{ - Metric: Metric{ - MetricNameLabel: "test_metric", - }, - Value: 123.1, - Timestamp: 1234567, - }, - }, - } - - for _, test := range input { - b, err := json.Marshal(test.value) - if err != nil { - t.Error(err) - continue - } - - if string(b) != test.plain { - t.Errorf("encoding error: expected %q, got %q", test.plain, b) - continue - } - - var sv Sample - err = json.Unmarshal(b, &sv) - if err != nil { - t.Error(err) - continue - } - - if !reflect.DeepEqual(sv, test.value) { - t.Errorf("decoding error: expected %v, got %v", test.value, sv) - } - } -} - -func TestVectorJSON(t *testing.T) { - input := []struct { - plain string - value Vector - }{ - { - plain: `[]`, - value: Vector{}, - }, - { - plain: `[{"metric":{"__name__":"test_metric"},"value":[1234.567,"123.1"]}]`, - value: Vector{&Sample{ - Metric: Metric{ - MetricNameLabel: "test_metric", - }, - Value: 123.1, - Timestamp: 1234567, - }}, - }, - { - plain: `[{"metric":{"__name__":"test_metric"},"value":[1234.567,"123.1"]},{"metric":{"foo":"bar"},"value":[1.234,"+Inf"]}]`, - value: Vector{ - &Sample{ - Metric: Metric{ - MetricNameLabel: "test_metric", - }, - Value: 123.1, - Timestamp: 1234567, - }, - &Sample{ - Metric: Metric{ - "foo": "bar", - }, - Value: SampleValue(math.Inf(1)), - Timestamp: 1234, - }, - }, - }, - } - - for _, test := range input { - b, err := json.Marshal(test.value) - if err != nil { - t.Error(err) - continue - } - - if string(b) != test.plain { - t.Errorf("encoding error: expected %q, got %q", test.plain, b) - continue - } - - var vec Vector - err = json.Unmarshal(b, &vec) - if err != nil { - t.Error(err) - continue - } - - if !reflect.DeepEqual(vec, test.value) { - t.Errorf("decoding error: expected %v, got %v", test.value, vec) - } - } -} - -func TestScalarJSON(t *testing.T) { - input := []struct { - plain string - value Scalar - }{ - { - plain: `[123.456,"456"]`, - value: Scalar{ - Timestamp: 123456, - Value: 456, - }, - }, - { - plain: `[123123.456,"+Inf"]`, - value: Scalar{ - Timestamp: 123123456, - Value: SampleValue(math.Inf(1)), - }, - }, - { - plain: `[123123.456,"-Inf"]`, - value: Scalar{ - Timestamp: 123123456, - Value: SampleValue(math.Inf(-1)), - }, - }, - } - - for _, test := range input { - b, err := json.Marshal(test.value) - if err != nil { - t.Error(err) - continue - } - - if string(b) != test.plain { - t.Errorf("encoding error: expected %q, got %q", test.plain, b) - continue - } - - var sv Scalar - err = json.Unmarshal(b, &sv) - if err != nil { - t.Error(err) - continue - } - - if sv != test.value { - t.Errorf("decoding error: expected %v, got %v", test.value, sv) - } - } -} - -func TestStringJSON(t *testing.T) { - input := []struct { - plain string - value String - }{ - { - plain: `[123.456,"test"]`, - value: String{ - Timestamp: 123456, - Value: "test", - }, - }, - { - plain: `[123123.456,"台北"]`, - value: String{ - Timestamp: 123123456, - Value: "台北", - }, - }, - } - - for _, test := range input { - b, err := json.Marshal(test.value) - if err != nil { - t.Error(err) - continue - } - - if string(b) != test.plain { - t.Errorf("encoding error: expected %q, got %q", test.plain, b) - continue - } - - var sv String - err = json.Unmarshal(b, &sv) - if err != nil { - t.Error(err) - continue - } - - if sv != test.value { - t.Errorf("decoding error: expected %v, got %v", test.value, sv) - } - } -} - -func TestVectorSort(t *testing.T) { - input := Vector{ - &Sample{ - Metric: Metric{ - MetricNameLabel: "A", - }, - Timestamp: 1, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "A", - }, - Timestamp: 2, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "C", - }, - Timestamp: 1, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "C", - }, - Timestamp: 2, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "B", - }, - Timestamp: 3, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "B", - }, - Timestamp: 2, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "B", - }, - Timestamp: 1, - }, - } - - expected := Vector{ - &Sample{ - Metric: Metric{ - MetricNameLabel: "A", - }, - Timestamp: 1, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "A", - }, - Timestamp: 2, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "B", - }, - Timestamp: 1, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "B", - }, - Timestamp: 2, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "B", - }, - Timestamp: 3, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "C", - }, - Timestamp: 1, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "C", - }, - Timestamp: 2, - }, - } - - sort.Sort(input) - - for i, actual := range input { - actualFp := actual.Metric.Fingerprint() - expectedFp := expected[i].Metric.Fingerprint() - - if actualFp != expectedFp { - t.Fatalf("%d. Incorrect fingerprint. Got %s; want %s", i, actualFp.String(), expectedFp.String()) - } - - if actual.Timestamp != expected[i].Timestamp { - t.Fatalf("%d. Incorrect timestamp. Got %s; want %s", i, actual.Timestamp, expected[i].Timestamp) - } - } -} diff --git a/vendor/github.com/prometheus/procfs/.gitignore b/vendor/github.com/prometheus/procfs/.gitignore new file mode 100644 index 000000000..25e3659ab --- /dev/null +++ b/vendor/github.com/prometheus/procfs/.gitignore @@ -0,0 +1 @@ +/fixtures/ diff --git a/vendor/github.com/prometheus/procfs/.travis.yml b/vendor/github.com/prometheus/procfs/.travis.yml deleted file mode 100644 index a9e28bf5d..000000000 --- a/vendor/github.com/prometheus/procfs/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -sudo: false -language: go -go: - - 1.6.4 - - 1.7.4 diff --git a/vendor/github.com/prometheus/procfs/Makefile b/vendor/github.com/prometheus/procfs/Makefile index c264a49d1..4d1098394 100644 --- a/vendor/github.com/prometheus/procfs/Makefile +++ b/vendor/github.com/prometheus/procfs/Makefile @@ -1,6 +1,77 @@ -ci: - ! gofmt -l *.go | read nothing - go vet - go test -v ./... - go get github.com/golang/lint/golint - golint *.go +# Copyright 2018 The Prometheus Authors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Ensure GOBIN is not set during build so that promu is installed to the correct path +unexport GOBIN + +GO ?= go +GOFMT ?= $(GO)fmt +FIRST_GOPATH := $(firstword $(subst :, ,$(shell $(GO) env GOPATH))) +STATICCHECK := $(FIRST_GOPATH)/bin/staticcheck +pkgs = $(shell $(GO) list ./... | grep -v /vendor/) + +PREFIX ?= $(shell pwd) +BIN_DIR ?= $(shell pwd) + +ifdef DEBUG + bindata_flags = -debug +endif + +STATICCHECK_IGNORE = + +all: format staticcheck build test + +style: + @echo ">> checking code style" + @! $(GOFMT) -d $(shell find . -path ./vendor -prune -o -name '*.go' -print) | grep '^' + +check_license: + @echo ">> checking license header" + @./scripts/check_license.sh + +test: fixtures/.unpacked sysfs/fixtures/.unpacked + @echo ">> running all tests" + @$(GO) test -race $(shell $(GO) list ./... | grep -v /vendor/ | grep -v examples) + +format: + @echo ">> formatting code" + @$(GO) fmt $(pkgs) + +vet: + @echo ">> vetting code" + @$(GO) vet $(pkgs) + +staticcheck: $(STATICCHECK) + @echo ">> running staticcheck" + @$(STATICCHECK) -ignore "$(STATICCHECK_IGNORE)" $(pkgs) + +%/.unpacked: %.ttar + ./ttar -C $(dir $*) -x -f $*.ttar + touch $@ + +update_fixtures: fixtures.ttar sysfs/fixtures.ttar + +%fixtures.ttar: %/fixtures + rm -v $(dir $*)fixtures/.unpacked + ./ttar -C $(dir $*) -c -f $*fixtures.ttar fixtures/ + +$(FIRST_GOPATH)/bin/staticcheck: + @GOOS= GOARCH= $(GO) get -u honnef.co/go/tools/cmd/staticcheck + +.PHONY: all style check_license format test vet staticcheck + +# Declaring the binaries at their default locations as PHONY targets is a hack +# to ensure the latest version is downloaded on every make execution. +# If this is not desired, copy/symlink these binaries to a different path and +# set the respective environment variables. +.PHONY: $(GOPATH)/bin/staticcheck diff --git a/vendor/github.com/prometheus/procfs/buddyinfo.go b/vendor/github.com/prometheus/procfs/buddyinfo.go index 680a9842a..d3a826807 100644 --- a/vendor/github.com/prometheus/procfs/buddyinfo.go +++ b/vendor/github.com/prometheus/procfs/buddyinfo.go @@ -62,7 +62,7 @@ func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) { for scanner.Scan() { var err error line := scanner.Text() - parts := strings.Fields(string(line)) + parts := strings.Fields(line) if len(parts) < 4 { return nil, fmt.Errorf("invalid number of fields when parsing buddyinfo") diff --git a/vendor/github.com/prometheus/procfs/buddyinfo_test.go b/vendor/github.com/prometheus/procfs/buddyinfo_test.go deleted file mode 100644 index bcf9355ca..000000000 --- a/vendor/github.com/prometheus/procfs/buddyinfo_test.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package procfs - -import ( - "strings" - "testing" -) - -func TestBuddyInfo(t *testing.T) { - buddyInfo, err := FS("fixtures/buddyinfo/valid").NewBuddyInfo() - if err != nil { - t.Fatal(err) - } - - if want, got := "DMA", buddyInfo[0].Zone; want != got { - t.Errorf("want Node 0, Zone %s, got %s", want, got) - } - - if want, got := "Normal", buddyInfo[2].Zone; want != got { - t.Errorf("want Node 0, Zone %s, got %s", want, got) - } - - if want, got := 4381.0, buddyInfo[2].Sizes[0]; want != got { - t.Errorf("want Node 0, Zone Normal %f, got %f", want, got) - } - - if want, got := 572.0, buddyInfo[1].Sizes[1]; want != got { - t.Errorf("want Node 0, Zone DMA32 %f, got %f", want, got) - } -} - -func TestBuddyInfoShort(t *testing.T) { - _, err := FS("fixtures/buddyinfo/short").NewBuddyInfo() - if err == nil { - t.Errorf("expected error, but none occurred") - } - - if want, got := "invalid number of fields when parsing buddyinfo", err.Error(); want != got { - t.Errorf("wrong error returned, wanted %q, got %q", want, got) - } -} - -func TestBuddyInfoSizeMismatch(t *testing.T) { - _, err := FS("fixtures/buddyinfo/sizemismatch").NewBuddyInfo() - if err == nil { - t.Errorf("expected error, but none occurred") - } - - if want, got := "mismatch in number of buddyinfo buckets", err.Error(); !strings.HasPrefix(got, want) { - t.Errorf("wrong error returned, wanted prefix %q, got %q", want, got) - } -} diff --git a/vendor/github.com/prometheus/procfs/fixtures.ttar b/vendor/github.com/prometheus/procfs/fixtures.ttar new file mode 100644 index 000000000..13c831ef5 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/fixtures.ttar @@ -0,0 +1,462 @@ +# Archive created by ttar -c -f fixtures.ttar fixtures/ +Directory: fixtures +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/26231 +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/cmdline +Lines: 1 +vimNULLBYTEtest.goNULLBYTE+10NULLBYTEEOF +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/comm +Lines: 1 +vim +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/cwd +SymlinkTo: /usr/bin +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/exe +SymlinkTo: /usr/bin/vim +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/26231/fd +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/fd/0 +SymlinkTo: ../../symlinktargets/abc +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/fd/1 +SymlinkTo: ../../symlinktargets/def +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/fd/10 +SymlinkTo: ../../symlinktargets/xyz +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/fd/2 +SymlinkTo: ../../symlinktargets/ghi +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/fd/3 +SymlinkTo: ../../symlinktargets/uvw +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/io +Lines: 7 +rchar: 750339 +wchar: 818609 +syscr: 7405 +syscw: 5245 +read_bytes: 1024 +write_bytes: 2048 +cancelled_write_bytes: -1024 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/limits +Lines: 17 +Limit Soft Limit Hard Limit Units +Max cpu time unlimited unlimited seconds +Max file size unlimited unlimited bytes +Max data size unlimited unlimited bytes +Max stack size 8388608 unlimited bytes +Max core file size 0 unlimited bytes +Max resident set unlimited unlimited bytes +Max processes 62898 62898 processes +Max open files 2048 4096 files +Max locked memory 65536 65536 bytes +Max address space 8589934592 unlimited bytes +Max file locks unlimited unlimited locks +Max pending signals 62898 62898 signals +Max msgqueue size 819200 819200 bytes +Max nice priority 0 0 +Max realtime priority 0 0 +Max realtime timeout unlimited unlimited us +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/mountstats +Lines: 19 +device rootfs mounted on / with fstype rootfs +device sysfs mounted on /sys with fstype sysfs +device proc mounted on /proc with fstype proc +device /dev/sda1 mounted on / with fstype ext4 +device 192.168.1.1:/srv/test mounted on /mnt/nfs/test with fstype nfs4 statvers=1.1 + opts: rw,vers=4.0,rsize=1048576,wsize=1048576,namlen=255,acregmin=3,acregmax=60,acdirmin=30,acdirmax=60,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=192.168.1.5,local_lock=none + age: 13968 + caps: caps=0xfff7,wtmult=512,dtsize=32768,bsize=0,namlen=255 + nfsv4: bm0=0xfdffafff,bm1=0xf9be3e,bm2=0x0,acl=0x0,pnfs=not configured + sec: flavor=1,pseudoflavor=1 + events: 52 226 0 0 1 13 398 0 0 331 0 47 0 0 77 0 0 77 0 0 0 0 0 0 0 0 0 + bytes: 1207640230 0 0 0 1210214218 0 295483 0 + RPC iostats version: 1.0 p/v: 100003/4 (nfs) + xprt: tcp 832 0 1 0 11 6428 6428 0 12154 0 24 26 5726 + per-op statistics + NULL: 0 0 0 0 0 0 0 0 + READ: 1298 1298 0 207680 1210292152 6 79386 79407 + WRITE: 0 0 0 0 0 0 0 0 + +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/26231/net +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/net/dev +Lines: 4 +Inter-| Receive | Transmit + face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed + lo: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + eth0: 438 5 0 0 0 0 0 0 648 8 0 0 0 0 0 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/26231/ns +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/ns/mnt +SymlinkTo: mnt:[4026531840] +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/ns/net +SymlinkTo: net:[4026531993] +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/root +SymlinkTo: / +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26231/stat +Lines: 1 +26231 (vim) R 5392 7446 5392 34835 7446 4218880 32533 309516 26 82 1677 44 158 99 20 0 1 0 82375 56274944 1981 18446744073709551615 4194304 6294284 140736914091744 140736914087944 139965136429984 0 0 12288 1870679807 0 0 0 17 0 0 0 31 0 0 8391624 8481048 16420864 140736914093252 140736914093279 140736914093279 140736914096107 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/26232 +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/cmdline +Lines: 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/comm +Lines: 1 +ata_sff +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/cwd +SymlinkTo: /does/not/exist +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/26232/fd +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/fd/0 +SymlinkTo: ../../symlinktargets/abc +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/fd/1 +SymlinkTo: ../../symlinktargets/def +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/fd/2 +SymlinkTo: ../../symlinktargets/ghi +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/fd/3 +SymlinkTo: ../../symlinktargets/uvw +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/fd/4 +SymlinkTo: ../../symlinktargets/xyz +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/limits +Lines: 17 +Limit Soft Limit Hard Limit Units +Max cpu time unlimited unlimited seconds +Max file size unlimited unlimited bytes +Max data size unlimited unlimited bytes +Max stack size 8388608 unlimited bytes +Max core file size 0 unlimited bytes +Max resident set unlimited unlimited bytes +Max processes 29436 29436 processes +Max open files 1024 4096 files +Max locked memory 65536 65536 bytes +Max address space unlimited unlimited bytes +Max file locks unlimited unlimited locks +Max pending signals 29436 29436 signals +Max msgqueue size 819200 819200 bytes +Max nice priority 0 0 +Max realtime priority 0 0 +Max realtime timeout unlimited unlimited us +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/root +SymlinkTo: /does/not/exist +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26232/stat +Lines: 1 +33 (ata_sff) S 2 0 0 0 -1 69238880 0 0 0 0 0 0 0 0 0 -20 1 0 5 0 0 18446744073709551615 0 0 0 0 0 0 0 2147483647 0 18446744073709551615 0 0 17 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/26233 +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/26233/cmdline +Lines: 1 +com.github.uiautomatorNULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTEEOF +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/584 +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/584/stat +Lines: 2 +1020 ((a b ) ( c d) ) R 28378 1020 28378 34842 1020 4218880 286 0 0 0 0 0 0 0 20 0 1 0 10839175 10395648 155 18446744073709551615 4194304 4238788 140736466511168 140736466511168 140609271124624 0 0 0 0 0 0 0 17 5 0 0 0 0 0 6336016 6337300 25579520 140736466515030 140736466515061 140736466515061 140736466518002 0 +#!/bin/cat /proc/self/stat +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/buddyinfo +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/buddyinfo/short +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/buddyinfo/short/buddyinfo +Lines: 3 +Node 0, zone +Node 0, zone +Node 0, zone +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/buddyinfo/sizemismatch +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/buddyinfo/sizemismatch/buddyinfo +Lines: 3 +Node 0, zone DMA 1 0 1 0 2 1 1 0 1 1 3 +Node 0, zone DMA32 759 572 791 475 194 45 12 0 0 0 0 0 +Node 0, zone Normal 4381 1093 185 1530 567 102 4 0 0 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/buddyinfo/valid +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/buddyinfo/valid/buddyinfo +Lines: 3 +Node 0, zone DMA 1 0 1 0 2 1 1 0 1 1 3 +Node 0, zone DMA32 759 572 791 475 194 45 12 0 0 0 0 +Node 0, zone Normal 4381 1093 185 1530 567 102 4 0 0 0 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/fs +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/fs/xfs +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/fs/xfs/stat +Lines: 23 +extent_alloc 92447 97589 92448 93751 +abt 0 0 0 0 +blk_map 1767055 188820 184891 92447 92448 2140766 0 +bmbt 0 0 0 0 +dir 185039 92447 92444 136422 +trans 706 944304 0 +ig 185045 58807 0 126238 0 33637 22 +log 2883 113448 9 17360 739 +push_ail 945014 0 134260 15483 0 3940 464 159985 0 40 +xstrat 92447 0 +rw 107739 94045 +attr 4 0 0 0 +icluster 8677 7849 135802 +vnodes 92601 0 0 0 92444 92444 92444 0 +buf 2666287 7122 2659202 3599 2 7085 0 10297 7085 +abtb2 184941 1277345 13257 13278 0 0 0 0 0 0 0 0 0 0 2746147 +abtc2 345295 2416764 172637 172658 0 0 0 0 0 0 0 0 0 0 21406023 +bmbt2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +ibt2 343004 1358467 0 0 0 0 0 0 0 0 0 0 0 0 0 +fibt2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +qm 0 0 0 0 0 0 0 0 +xpc 399724544 92823103 86219234 +debug 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/mdstat +Lines: 26 +Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] +md3 : active raid6 sda1[8] sdh1[7] sdg1[6] sdf1[5] sde1[11] sdd1[3] sdc1[10] sdb1[9] + 5853468288 blocks super 1.2 level 6, 64k chunk, algorithm 2 [8/8] [UUUUUUUU] + +md127 : active raid1 sdi2[0] sdj2[1] + 312319552 blocks [2/2] [UU] + +md0 : active raid1 sdk[2](S) sdi1[0] sdj1[1] + 248896 blocks [2/2] [UU] + +md4 : inactive raid1 sda3[0] sdb3[1] + 4883648 blocks [2/2] [UU] + +md6 : active raid1 sdb2[2] sda2[0] + 195310144 blocks [2/1] [U_] + [=>...................] recovery = 8.5% (16775552/195310144) finish=17.0min speed=259783K/sec + +md8 : active raid1 sdb1[1] sda1[0] + 195310144 blocks [2/2] [UU] + [=>...................] resync = 8.5% (16775552/195310144) finish=17.0min speed=259783K/sec + +md7 : active raid6 sdb1[0] sde1[3] sdd1[2] sdc1[1] + 7813735424 blocks super 1.2 level 6, 512k chunk, algorithm 2 [4/3] [U_UU] + bitmap: 0/30 pages [0KB], 65536KB chunk + +unused devices: +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/net +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/net/dev +Lines: 6 +Inter-| Receive | Transmit + face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed +vethf345468: 648 8 0 0 0 0 0 0 438 5 0 0 0 0 0 0 + lo: 1664039048 1566805 0 0 0 0 0 0 1664039048 1566805 0 0 0 0 0 0 +docker0: 2568 38 0 0 0 0 0 0 438 5 0 0 0 0 0 0 + eth0: 874354587 1036395 0 0 0 0 0 0 563352563 732147 0 0 0 0 0 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/net/ip_vs +Lines: 21 +IP Virtual Server version 1.2.1 (size=4096) +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP C0A80016:0CEA wlc + -> C0A85216:0CEA Tunnel 100 248 2 + -> C0A85318:0CEA Tunnel 100 248 2 + -> C0A85315:0CEA Tunnel 100 248 1 +TCP C0A80039:0CEA wlc + -> C0A85416:0CEA Tunnel 0 0 0 + -> C0A85215:0CEA Tunnel 100 1499 0 + -> C0A83215:0CEA Tunnel 100 1498 0 +TCP C0A80037:0CEA wlc + -> C0A8321A:0CEA Tunnel 0 0 0 + -> C0A83120:0CEA Tunnel 100 0 0 +TCP [2620:0000:0000:0000:0000:0000:0000:0001]:0050 sh + -> [2620:0000:0000:0000:0000:0000:0000:0002]:0050 Route 1 0 0 + -> [2620:0000:0000:0000:0000:0000:0000:0003]:0050 Route 1 0 0 + -> [2620:0000:0000:0000:0000:0000:0000:0004]:0050 Route 1 1 1 +FWM 10001000 wlc + -> C0A8321A:0CEA Route 0 0 1 + -> C0A83215:0CEA Route 0 0 2 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/net/ip_vs_stats +Lines: 6 + Total Incoming Outgoing Incoming Outgoing + Conns Packets Packets Bytes Bytes + 16AA370 E33656E5 0 51D8C8883AB3 0 + + Conns/s Pkts/s Pkts/s Bytes/s Bytes/s + 4 1FB3C 0 1282A8F 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/net/rpc +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/net/rpc/nfs +Lines: 5 +net 18628 0 18628 6 +rpc 4329785 0 4338291 +proc2 18 2 69 0 0 4410 0 0 0 0 0 0 0 0 0 0 0 99 2 +proc3 22 1 4084749 29200 94754 32580 186 47747 7981 8639 0 6356 0 6962 0 7958 0 0 241 4 4 2 39 +proc4 61 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/net/rpc/nfsd +Lines: 11 +rc 0 6 18622 +fh 0 0 0 0 0 +io 157286400 0 +th 8 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 +ra 32 0 0 0 0 0 0 0 0 0 0 0 +net 18628 0 18628 6 +rpc 18628 0 0 0 0 +proc2 18 2 69 0 0 4410 0 0 0 0 0 0 0 0 0 0 0 99 2 +proc3 22 2 112 0 2719 111 0 0 0 0 0 0 0 0 0 0 0 27 216 0 2 1 0 +proc4 2 2 10853 +proc4ops 72 0 0 0 1098 2 0 0 0 0 8179 5896 0 0 0 0 5900 0 0 2 0 2 0 9609 0 2 150 1272 0 0 0 1236 0 0 0 0 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/net/xfrm_stat +Lines: 28 +XfrmInError 1 +XfrmInBufferError 2 +XfrmInHdrError 4 +XfrmInNoStates 3 +XfrmInStateProtoError 40 +XfrmInStateModeError 100 +XfrmInStateSeqError 6000 +XfrmInStateExpired 4 +XfrmInStateMismatch 23451 +XfrmInStateInvalid 55555 +XfrmInTmplMismatch 51 +XfrmInNoPols 65432 +XfrmInPolBlock 100 +XfrmInPolError 10000 +XfrmOutError 1000000 +XfrmOutBundleGenError 43321 +XfrmOutBundleCheckError 555 +XfrmOutNoStates 869 +XfrmOutStateProtoError 4542 +XfrmOutStateModeError 4 +XfrmOutStateSeqError 543 +XfrmOutStateExpired 565 +XfrmOutPolBlock 43456 +XfrmOutPolDead 7656 +XfrmOutPolError 1454 +XfrmFwdHdrError 6654 +XfrmOutStateInvalid 28765 +XfrmAcquireError 24532 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/self +SymlinkTo: 26231 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/stat +Lines: 16 +cpu 301854 612 111922 8979004 3552 2 3944 0 0 0 +cpu0 44490 19 21045 1087069 220 1 3410 0 0 0 +cpu1 47869 23 16474 1110787 591 0 46 0 0 0 +cpu2 46504 36 15916 1112321 441 0 326 0 0 0 +cpu3 47054 102 15683 1113230 533 0 60 0 0 0 +cpu4 28413 25 10776 1140321 217 0 8 0 0 0 +cpu5 29271 101 11586 1136270 672 0 30 0 0 0 +cpu6 29152 36 10276 1139721 319 0 29 0 0 0 +cpu7 29098 268 10164 1139282 555 0 31 0 0 0 +intr 8885917 17 0 0 0 0 0 0 0 1 79281 0 0 0 0 0 0 0 231237 0 0 0 0 250586 103 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 223424 190745 13 906 1283803 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +ctxt 38014093 +btime 1418183276 +processes 26442 +procs_running 2 +procs_blocked 1 +softirq 5057579 250191 1481983 1647 211099 186066 0 1783454 622196 12499 508444 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/symlinktargets +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/symlinktargets/README +Lines: 2 +This directory contains some empty files that are the symlinks the files in the "fd" directory point to. +They are otherwise ignored by the tests +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/symlinktargets/abc +Lines: 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/symlinktargets/def +Lines: 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/symlinktargets/ghi +Lines: 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/symlinktargets/uvw +Lines: 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/symlinktargets/xyz +Lines: 0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/.unpacked +Lines: 0 +Mode: 664 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/prometheus/procfs/fs.go b/vendor/github.com/prometheus/procfs/fs.go index 17546756b..b6c6b2ce1 100644 --- a/vendor/github.com/prometheus/procfs/fs.go +++ b/vendor/github.com/prometheus/procfs/fs.go @@ -1,3 +1,16 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package procfs import ( @@ -5,6 +18,7 @@ import ( "os" "path" + "github.com/prometheus/procfs/nfs" "github.com/prometheus/procfs/xfs" ) @@ -44,3 +58,25 @@ func (fs FS) XFSStats() (*xfs.Stats, error) { return xfs.ParseStats(f) } + +// NFSClientRPCStats retrieves NFS client RPC statistics. +func (fs FS) NFSClientRPCStats() (*nfs.ClientRPCStats, error) { + f, err := os.Open(fs.Path("net/rpc/nfs")) + if err != nil { + return nil, err + } + defer f.Close() + + return nfs.ParseClientRPCStats(f) +} + +// NFSdServerRPCStats retrieves NFS daemon RPC statistics. +func (fs FS) NFSdServerRPCStats() (*nfs.ServerRPCStats, error) { + f, err := os.Open(fs.Path("net/rpc/nfsd")) + if err != nil { + return nil, err + } + defer f.Close() + + return nfs.ParseServerRPCStats(f) +} diff --git a/vendor/github.com/prometheus/procfs/fs_test.go b/vendor/github.com/prometheus/procfs/fs_test.go deleted file mode 100644 index e492cde55..000000000 --- a/vendor/github.com/prometheus/procfs/fs_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package procfs - -import "testing" - -func TestNewFS(t *testing.T) { - if _, err := NewFS("foobar"); err == nil { - t.Error("want NewFS to fail for non-existing mount point") - } - - if _, err := NewFS("procfs.go"); err == nil { - t.Error("want NewFS to fail if mount point is not a directory") - } -} - -func TestFSXFSStats(t *testing.T) { - stats, err := FS("fixtures").XFSStats() - if err != nil { - t.Fatalf("failed to parse XFS stats: %v", err) - } - - // Very lightweight test just to sanity check the path used - // to open XFS stats. Heavier tests in package xfs. - if want, got := uint32(92447), stats.ExtentAllocation.ExtentsAllocated; want != got { - t.Errorf("unexpected extents allocated:\nwant: %d\nhave: %d", want, got) - } -} diff --git a/vendor/github.com/prometheus/procfs/internal/util/parse.go b/vendor/github.com/prometheus/procfs/internal/util/parse.go new file mode 100644 index 000000000..2ff228e9d --- /dev/null +++ b/vendor/github.com/prometheus/procfs/internal/util/parse.go @@ -0,0 +1,59 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package util + +import ( + "io/ioutil" + "strconv" + "strings" +) + +// ParseUint32s parses a slice of strings into a slice of uint32s. +func ParseUint32s(ss []string) ([]uint32, error) { + us := make([]uint32, 0, len(ss)) + for _, s := range ss { + u, err := strconv.ParseUint(s, 10, 32) + if err != nil { + return nil, err + } + + us = append(us, uint32(u)) + } + + return us, nil +} + +// ParseUint64s parses a slice of strings into a slice of uint64s. +func ParseUint64s(ss []string) ([]uint64, error) { + us := make([]uint64, 0, len(ss)) + for _, s := range ss { + u, err := strconv.ParseUint(s, 10, 64) + if err != nil { + return nil, err + } + + us = append(us, u) + } + + return us, nil +} + +// ReadUintFromFile reads a file and attempts to parse a uint64 from it. +func ReadUintFromFile(path string) (uint64, error) { + data, err := ioutil.ReadFile(path) + if err != nil { + return 0, err + } + return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64) +} diff --git a/vendor/github.com/prometheus/procfs/internal/util/sysreadfile_linux.go b/vendor/github.com/prometheus/procfs/internal/util/sysreadfile_linux.go new file mode 100644 index 000000000..df0d567b7 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/internal/util/sysreadfile_linux.go @@ -0,0 +1,45 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !windows + +package util + +import ( + "bytes" + "os" + "syscall" +) + +// SysReadFile is a simplified ioutil.ReadFile that invokes syscall.Read directly. +// https://github.com/prometheus/node_exporter/pull/728/files +func SysReadFile(file string) (string, error) { + f, err := os.Open(file) + if err != nil { + return "", err + } + defer f.Close() + + // On some machines, hwmon drivers are broken and return EAGAIN. This causes + // Go's ioutil.ReadFile implementation to poll forever. + // + // Since we either want to read data or bail immediately, do the simplest + // possible read using syscall directly. + b := make([]byte, 128) + n, err := syscall.Read(int(f.Fd()), b) + if err != nil { + return "", err + } + + return string(bytes.TrimSpace(b[:n])), nil +} diff --git a/vendor/github.com/prometheus/procfs/ipvs.go b/vendor/github.com/prometheus/procfs/ipvs.go index 696d114e7..e36d4a3bd 100644 --- a/vendor/github.com/prometheus/procfs/ipvs.go +++ b/vendor/github.com/prometheus/procfs/ipvs.go @@ -1,3 +1,16 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package procfs import ( @@ -31,16 +44,16 @@ type IPVSStats struct { type IPVSBackendStatus struct { // The local (virtual) IP address. LocalAddress net.IP + // The remote (real) IP address. + RemoteAddress net.IP // The local (virtual) port. LocalPort uint16 + // The remote (real) port. + RemotePort uint16 // The local firewall mark LocalMark string // The transport protocol (TCP, UDP). Proto string - // The remote (real) IP address. - RemoteAddress net.IP - // The remote (real) port. - RemotePort uint16 // The current number of active connections for this virtual/real address pair. ActiveConn uint64 // The current number of inactive connections for this virtual/real address pair. @@ -151,7 +164,7 @@ func parseIPVSBackendStatus(file io.Reader) ([]IPVSBackendStatus, error) { ) for scanner.Scan() { - fields := strings.Fields(string(scanner.Text())) + fields := strings.Fields(scanner.Text()) if len(fields) == 0 { continue } diff --git a/vendor/github.com/prometheus/procfs/ipvs_test.go b/vendor/github.com/prometheus/procfs/ipvs_test.go deleted file mode 100644 index 13ceab80e..000000000 --- a/vendor/github.com/prometheus/procfs/ipvs_test.go +++ /dev/null @@ -1,237 +0,0 @@ -package procfs - -import ( - "net" - "testing" -) - -var ( - expectedIPVSStats = IPVSStats{ - Connections: 23765872, - IncomingPackets: 3811989221, - OutgoingPackets: 0, - IncomingBytes: 89991519156915, - OutgoingBytes: 0, - } - expectedIPVSBackendStatuses = []IPVSBackendStatus{ - { - LocalAddress: net.ParseIP("192.168.0.22"), - LocalPort: 3306, - RemoteAddress: net.ParseIP("192.168.82.22"), - RemotePort: 3306, - Proto: "TCP", - Weight: 100, - ActiveConn: 248, - InactConn: 2, - }, - { - LocalAddress: net.ParseIP("192.168.0.22"), - LocalPort: 3306, - RemoteAddress: net.ParseIP("192.168.83.24"), - RemotePort: 3306, - Proto: "TCP", - Weight: 100, - ActiveConn: 248, - InactConn: 2, - }, - { - LocalAddress: net.ParseIP("192.168.0.22"), - LocalPort: 3306, - RemoteAddress: net.ParseIP("192.168.83.21"), - RemotePort: 3306, - Proto: "TCP", - Weight: 100, - ActiveConn: 248, - InactConn: 1, - }, - { - LocalAddress: net.ParseIP("192.168.0.57"), - LocalPort: 3306, - RemoteAddress: net.ParseIP("192.168.84.22"), - RemotePort: 3306, - Proto: "TCP", - Weight: 0, - ActiveConn: 0, - InactConn: 0, - }, - { - LocalAddress: net.ParseIP("192.168.0.57"), - LocalPort: 3306, - RemoteAddress: net.ParseIP("192.168.82.21"), - RemotePort: 3306, - Proto: "TCP", - Weight: 100, - ActiveConn: 1499, - InactConn: 0, - }, - { - LocalAddress: net.ParseIP("192.168.0.57"), - LocalPort: 3306, - RemoteAddress: net.ParseIP("192.168.50.21"), - RemotePort: 3306, - Proto: "TCP", - Weight: 100, - ActiveConn: 1498, - InactConn: 0, - }, - { - LocalAddress: net.ParseIP("192.168.0.55"), - LocalPort: 3306, - RemoteAddress: net.ParseIP("192.168.50.26"), - RemotePort: 3306, - Proto: "TCP", - Weight: 0, - ActiveConn: 0, - InactConn: 0, - }, - { - LocalAddress: net.ParseIP("192.168.0.55"), - LocalPort: 3306, - RemoteAddress: net.ParseIP("192.168.49.32"), - RemotePort: 3306, - Proto: "TCP", - Weight: 100, - ActiveConn: 0, - InactConn: 0, - }, - { - LocalAddress: net.ParseIP("2620::1"), - LocalPort: 80, - RemoteAddress: net.ParseIP("2620::2"), - RemotePort: 80, - Proto: "TCP", - Weight: 1, - ActiveConn: 0, - InactConn: 0, - }, - { - LocalAddress: net.ParseIP("2620::1"), - LocalPort: 80, - RemoteAddress: net.ParseIP("2620::3"), - RemotePort: 80, - Proto: "TCP", - Weight: 1, - ActiveConn: 0, - InactConn: 0, - }, - { - LocalAddress: net.ParseIP("2620::1"), - LocalPort: 80, - RemoteAddress: net.ParseIP("2620::4"), - RemotePort: 80, - Proto: "TCP", - Weight: 1, - ActiveConn: 1, - InactConn: 1, - }, - { - LocalMark: "10001000", - RemoteAddress: net.ParseIP("192.168.50.26"), - RemotePort: 3306, - Proto: "FWM", - Weight: 0, - ActiveConn: 0, - InactConn: 1, - }, - { - LocalMark: "10001000", - RemoteAddress: net.ParseIP("192.168.50.21"), - RemotePort: 3306, - Proto: "FWM", - Weight: 0, - ActiveConn: 0, - InactConn: 2, - }, - } -) - -func TestIPVSStats(t *testing.T) { - stats, err := FS("fixtures").NewIPVSStats() - if err != nil { - t.Fatal(err) - } - - if stats != expectedIPVSStats { - t.Errorf("want %+v, have %+v", expectedIPVSStats, stats) - } -} - -func TestParseIPPort(t *testing.T) { - ip := net.ParseIP("192.168.0.22") - port := uint16(3306) - - gotIP, gotPort, err := parseIPPort("C0A80016:0CEA") - if err != nil { - t.Fatal(err) - } - if !(gotIP.Equal(ip) && port == gotPort) { - t.Errorf("want %s:%d, have %s:%d", ip, port, gotIP, gotPort) - } -} - -func TestParseIPPortInvalid(t *testing.T) { - testcases := []string{ - "", - "C0A80016", - "C0A800:1234", - "FOOBARBA:1234", - "C0A80016:0CEA:1234", - } - - for _, s := range testcases { - ip, port, err := parseIPPort(s) - if ip != nil || port != uint16(0) || err == nil { - t.Errorf("Expected error for input %s, have ip = %s, port = %v, err = %v", s, ip, port, err) - } - } -} - -func TestParseIPPortIPv6(t *testing.T) { - ip := net.ParseIP("dead:beef::1") - port := uint16(8080) - - gotIP, gotPort, err := parseIPPort("[DEAD:BEEF:0000:0000:0000:0000:0000:0001]:1F90") - if err != nil { - t.Fatal(err) - } - if !(gotIP.Equal(ip) && port == gotPort) { - t.Errorf("want %s:%d, have %s:%d", ip, port, gotIP, gotPort) - } -} - -func TestIPVSBackendStatus(t *testing.T) { - backendStats, err := FS("fixtures").NewIPVSBackendStatus() - if err != nil { - t.Fatal(err) - } - if want, have := len(expectedIPVSBackendStatuses), len(backendStats); want != have { - t.Fatalf("want %d backend statuses, have %d", want, have) - } - - for idx, expect := range expectedIPVSBackendStatuses { - if !backendStats[idx].LocalAddress.Equal(expect.LocalAddress) { - t.Errorf("want LocalAddress %s, have %s", expect.LocalAddress, backendStats[idx].LocalAddress) - } - if backendStats[idx].LocalPort != expect.LocalPort { - t.Errorf("want LocalPort %d, have %d", expect.LocalPort, backendStats[idx].LocalPort) - } - if !backendStats[idx].RemoteAddress.Equal(expect.RemoteAddress) { - t.Errorf("want RemoteAddress %s, have %s", expect.RemoteAddress, backendStats[idx].RemoteAddress) - } - if backendStats[idx].RemotePort != expect.RemotePort { - t.Errorf("want RemotePort %d, have %d", expect.RemotePort, backendStats[idx].RemotePort) - } - if backendStats[idx].Proto != expect.Proto { - t.Errorf("want Proto %s, have %s", expect.Proto, backendStats[idx].Proto) - } - if backendStats[idx].Weight != expect.Weight { - t.Errorf("want Weight %d, have %d", expect.Weight, backendStats[idx].Weight) - } - if backendStats[idx].ActiveConn != expect.ActiveConn { - t.Errorf("want ActiveConn %d, have %d", expect.ActiveConn, backendStats[idx].ActiveConn) - } - if backendStats[idx].InactConn != expect.InactConn { - t.Errorf("want InactConn %d, have %d", expect.InactConn, backendStats[idx].InactConn) - } - } -} diff --git a/vendor/github.com/prometheus/procfs/mdstat.go b/vendor/github.com/prometheus/procfs/mdstat.go index d7a248c0d..9dc19583d 100644 --- a/vendor/github.com/prometheus/procfs/mdstat.go +++ b/vendor/github.com/prometheus/procfs/mdstat.go @@ -1,3 +1,16 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package procfs import ( diff --git a/vendor/github.com/prometheus/procfs/mdstat_test.go b/vendor/github.com/prometheus/procfs/mdstat_test.go deleted file mode 100644 index fa463c2fb..000000000 --- a/vendor/github.com/prometheus/procfs/mdstat_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package procfs - -import ( - "testing" -) - -func TestMDStat(t *testing.T) { - mdStates, err := FS("fixtures").ParseMDStat() - if err != nil { - t.Fatalf("parsing of reference-file failed entirely: %s", err) - } - - refs := map[string]MDStat{ - "md3": {"md3", "active", 8, 8, 5853468288, 5853468288}, - "md127": {"md127", "active", 2, 2, 312319552, 312319552}, - "md0": {"md0", "active", 2, 2, 248896, 248896}, - "md4": {"md4", "inactive", 2, 2, 4883648, 4883648}, - "md6": {"md6", "active", 1, 2, 195310144, 16775552}, - "md8": {"md8", "active", 2, 2, 195310144, 16775552}, - "md7": {"md7", "active", 3, 4, 7813735424, 7813735424}, - } - - if want, have := len(refs), len(mdStates); want != have { - t.Errorf("want %d parsed md-devices, have %d", want, have) - } - for _, md := range mdStates { - if want, have := refs[md.Name], md; want != have { - t.Errorf("%s: want %v, have %v", md.Name, want, have) - } - } -} diff --git a/vendor/github.com/prometheus/procfs/mountstats.go b/vendor/github.com/prometheus/procfs/mountstats.go index 6b2b0ba9d..7a8a1e099 100644 --- a/vendor/github.com/prometheus/procfs/mountstats.go +++ b/vendor/github.com/prometheus/procfs/mountstats.go @@ -1,3 +1,16 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package procfs // While implementing parsing of /proc/[pid]/mountstats, this blog was used @@ -26,8 +39,11 @@ const ( statVersion10 = "1.0" statVersion11 = "1.1" - fieldTransport10Len = 10 - fieldTransport11Len = 13 + fieldTransport10TCPLen = 10 + fieldTransport10UDPLen = 7 + + fieldTransport11TCPLen = 13 + fieldTransport11UDPLen = 10 ) // A Mount is a device mount parsed from /proc/[pid]/mountstats. @@ -173,6 +189,8 @@ type NFSOperationStats struct { // A NFSTransportStats contains statistics for the NFS mount RPC requests and // responses. type NFSTransportStats struct { + // The transport protocol used for the NFS mount. + Protocol string // The local port used for the NFS mount. Port uint64 // Number of times the client has had to establish a connection from scratch @@ -347,7 +365,7 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e return nil, fmt.Errorf("not enough information for NFS transport stats: %v", ss) } - tstats, err := parseNFSTransportStats(ss[2:], statVersion) + tstats, err := parseNFSTransportStats(ss[1:], statVersion) if err != nil { return nil, err } @@ -509,13 +527,33 @@ func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) { // parseNFSTransportStats parses a NFSTransportStats line using an input set of // integer fields matched to a specific stats version. func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats, error) { + // Extract the protocol field. It is the only string value in the line + protocol := ss[0] + ss = ss[1:] + switch statVersion { case statVersion10: - if len(ss) != fieldTransport10Len { + var expectedLength int + if protocol == "tcp" { + expectedLength = fieldTransport10TCPLen + } else if protocol == "udp" { + expectedLength = fieldTransport10UDPLen + } else { + return nil, fmt.Errorf("invalid NFS protocol \"%s\" in stats 1.0 statement: %v", protocol, ss) + } + if len(ss) != expectedLength { return nil, fmt.Errorf("invalid NFS transport stats 1.0 statement: %v", ss) } case statVersion11: - if len(ss) != fieldTransport11Len { + var expectedLength int + if protocol == "tcp" { + expectedLength = fieldTransport11TCPLen + } else if protocol == "udp" { + expectedLength = fieldTransport11UDPLen + } else { + return nil, fmt.Errorf("invalid NFS protocol \"%s\" in stats 1.1 statement: %v", protocol, ss) + } + if len(ss) != expectedLength { return nil, fmt.Errorf("invalid NFS transport stats 1.1 statement: %v", ss) } default: @@ -523,12 +561,13 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats } // Allocate enough for v1.1 stats since zero value for v1.1 stats will be okay - // in a v1.0 response. + // in a v1.0 response. Since the stat length is bigger for TCP stats, we use + // the TCP length here. // // Note: slice length must be set to length of v1.1 stats to avoid a panic when // only v1.0 stats are present. // See: https://github.com/prometheus/node_exporter/issues/571. - ns := make([]uint64, fieldTransport11Len) + ns := make([]uint64, fieldTransport11TCPLen) for i, s := range ss { n, err := strconv.ParseUint(s, 10, 64) if err != nil { @@ -538,7 +577,18 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats ns[i] = n } + // The fields differ depending on the transport protocol (TCP or UDP) + // From https://utcc.utoronto.ca/%7Ecks/space/blog/linux/NFSMountstatsXprt + // + // For the udp RPC transport there is no connection count, connect idle time, + // or idle time (fields #3, #4, and #5); all other fields are the same. So + // we set them to 0 here. + if protocol == "udp" { + ns = append(ns[:2], append(make([]uint64, 3), ns[2:]...)...) + } + return &NFSTransportStats{ + Protocol: protocol, Port: ns[0], Bind: ns[1], Connect: ns[2], diff --git a/vendor/github.com/prometheus/procfs/mountstats_test.go b/vendor/github.com/prometheus/procfs/mountstats_test.go deleted file mode 100644 index 8f04f5355..000000000 --- a/vendor/github.com/prometheus/procfs/mountstats_test.go +++ /dev/null @@ -1,273 +0,0 @@ -package procfs - -import ( - "fmt" - "reflect" - "strings" - "testing" - "time" -) - -func TestMountStats(t *testing.T) { - tests := []struct { - name string - s string - mounts []*Mount - invalid bool - }{ - { - name: "no devices", - s: `hello`, - }, - { - name: "device has too few fields", - s: `device foo`, - invalid: true, - }, - { - name: "device incorrect format", - s: `device rootfs BAD on / with fstype rootfs`, - invalid: true, - }, - { - name: "device incorrect format", - s: `device rootfs mounted BAD / with fstype rootfs`, - invalid: true, - }, - { - name: "device incorrect format", - s: `device rootfs mounted on / BAD fstype rootfs`, - invalid: true, - }, - { - name: "device incorrect format", - s: `device rootfs mounted on / with BAD rootfs`, - invalid: true, - }, - { - name: "device rootfs cannot have stats", - s: `device rootfs mounted on / with fstype rootfs stats`, - invalid: true, - }, - { - name: "NFSv4 device with too little info", - s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nhello", - invalid: true, - }, - { - name: "NFSv4 device with bad bytes", - s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nbytes: 0", - invalid: true, - }, - { - name: "NFSv4 device with bad events", - s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nevents: 0", - invalid: true, - }, - { - name: "NFSv4 device with bad per-op stats", - s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nper-op statistics\nFOO 0", - invalid: true, - }, - { - name: "NFSv4 device with bad transport stats", - s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nxprt: tcp", - invalid: true, - }, - { - name: "NFSv4 device with bad transport version", - s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=foo\nxprt: tcp 0", - invalid: true, - }, - { - name: "NFSv4 device with bad transport stats version 1.0", - s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.0\nxprt: tcp 0 0 0 0 0 0 0 0 0 0 0 0 0", - invalid: true, - }, - { - name: "NFSv4 device with bad transport stats version 1.1", - s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nxprt: tcp 0 0 0 0 0 0 0 0 0 0", - invalid: true, - }, - { - name: "NFSv3 device with transport stats version 1.0 OK", - s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs statvers=1.0\nxprt: tcp 1 2 3 4 5 6 7 8 9 10", - mounts: []*Mount{{ - Device: "192.168.1.1:/srv", - Mount: "/mnt/nfs", - Type: "nfs", - Stats: &MountStatsNFS{ - StatVersion: "1.0", - Transport: NFSTransportStats{ - Port: 1, - Bind: 2, - Connect: 3, - ConnectIdleTime: 4, - IdleTime: 5 * time.Second, - Sends: 6, - Receives: 7, - BadTransactionIDs: 8, - CumulativeActiveRequests: 9, - CumulativeBacklog: 10, - }, - }, - }}, - }, - { - name: "device rootfs OK", - s: `device rootfs mounted on / with fstype rootfs`, - mounts: []*Mount{{ - Device: "rootfs", - Mount: "/", - Type: "rootfs", - }}, - }, - { - name: "NFSv3 device with minimal stats OK", - s: `device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs statvers=1.1`, - mounts: []*Mount{{ - Device: "192.168.1.1:/srv", - Mount: "/mnt/nfs", - Type: "nfs", - Stats: &MountStatsNFS{ - StatVersion: "1.1", - }, - }}, - }, - { - name: "fixtures OK", - mounts: []*Mount{ - { - Device: "rootfs", - Mount: "/", - Type: "rootfs", - }, - { - Device: "sysfs", - Mount: "/sys", - Type: "sysfs", - }, - { - Device: "proc", - Mount: "/proc", - Type: "proc", - }, - { - Device: "/dev/sda1", - Mount: "/", - Type: "ext4", - }, - { - Device: "192.168.1.1:/srv/test", - Mount: "/mnt/nfs/test", - Type: "nfs4", - Stats: &MountStatsNFS{ - StatVersion: "1.1", - Age: 13968 * time.Second, - Bytes: NFSBytesStats{ - Read: 1207640230, - ReadTotal: 1210214218, - ReadPages: 295483, - }, - Events: NFSEventsStats{ - InodeRevalidate: 52, - DnodeRevalidate: 226, - VFSOpen: 1, - VFSLookup: 13, - VFSAccess: 398, - VFSReadPages: 331, - VFSWritePages: 47, - VFSFlush: 77, - VFSFileRelease: 77, - }, - Operations: []NFSOperationStats{ - { - Operation: "NULL", - }, - { - Operation: "READ", - Requests: 1298, - Transmissions: 1298, - BytesSent: 207680, - BytesReceived: 1210292152, - CumulativeQueueTime: 6 * time.Millisecond, - CumulativeTotalResponseTime: 79386 * time.Millisecond, - CumulativeTotalRequestTime: 79407 * time.Millisecond, - }, - { - Operation: "WRITE", - }, - }, - Transport: NFSTransportStats{ - Port: 832, - Connect: 1, - IdleTime: 11 * time.Second, - Sends: 6428, - Receives: 6428, - CumulativeActiveRequests: 12154, - MaximumRPCSlotsUsed: 24, - CumulativeSendingQueue: 26, - CumulativePendingQueue: 5726, - }, - }, - }, - }, - }, - } - - for i, tt := range tests { - t.Logf("[%02d] test %q", i, tt.name) - - var mounts []*Mount - var err error - - if tt.s != "" { - mounts, err = parseMountStats(strings.NewReader(tt.s)) - } else { - proc, e := FS("fixtures").NewProc(26231) - if e != nil { - t.Fatalf("failed to create proc: %v", err) - } - - mounts, err = proc.MountStats() - } - - if tt.invalid && err == nil { - t.Error("expected an error, but none occurred") - } - if !tt.invalid && err != nil { - t.Errorf("unexpected error: %v", err) - } - - if want, have := tt.mounts, mounts; !reflect.DeepEqual(want, have) { - t.Errorf("mounts:\nwant:\n%v\nhave:\n%v", mountsStr(want), mountsStr(have)) - } - } -} - -func mountsStr(mounts []*Mount) string { - var out string - for i, m := range mounts { - out += fmt.Sprintf("[%d] %q on %q (%q)", i, m.Device, m.Mount, m.Type) - - stats, ok := m.Stats.(*MountStatsNFS) - if !ok { - out += "\n" - continue - } - - out += fmt.Sprintf("\n\t- v%s, age: %s", stats.StatVersion, stats.Age) - out += fmt.Sprintf("\n\t- bytes: %v", stats.Bytes) - out += fmt.Sprintf("\n\t- events: %v", stats.Events) - out += fmt.Sprintf("\n\t- transport: %v", stats.Transport) - out += fmt.Sprintf("\n\t- per-operation stats:") - - for _, o := range stats.Operations { - out += fmt.Sprintf("\n\t\t- %v", o) - } - - out += "\n" - } - - return out -} diff --git a/vendor/github.com/prometheus/procfs/net_dev.go b/vendor/github.com/prometheus/procfs/net_dev.go new file mode 100644 index 000000000..3f2523371 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/net_dev.go @@ -0,0 +1,216 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "errors" + "os" + "sort" + "strconv" + "strings" +) + +// NetDevLine is single line parsed from /proc/net/dev or /proc/[pid]/net/dev. +type NetDevLine struct { + Name string `json:"name"` // The name of the interface. + RxBytes uint64 `json:"rx_bytes"` // Cumulative count of bytes received. + RxPackets uint64 `json:"rx_packets"` // Cumulative count of packets received. + RxErrors uint64 `json:"rx_errors"` // Cumulative count of receive errors encountered. + RxDropped uint64 `json:"rx_dropped"` // Cumulative count of packets dropped while receiving. + RxFIFO uint64 `json:"rx_fifo"` // Cumulative count of FIFO buffer errors. + RxFrame uint64 `json:"rx_frame"` // Cumulative count of packet framing errors. + RxCompressed uint64 `json:"rx_compressed"` // Cumulative count of compressed packets received by the device driver. + RxMulticast uint64 `json:"rx_multicast"` // Cumulative count of multicast frames received by the device driver. + TxBytes uint64 `json:"tx_bytes"` // Cumulative count of bytes transmitted. + TxPackets uint64 `json:"tx_packets"` // Cumulative count of packets transmitted. + TxErrors uint64 `json:"tx_errors"` // Cumulative count of transmit errors encountered. + TxDropped uint64 `json:"tx_dropped"` // Cumulative count of packets dropped while transmitting. + TxFIFO uint64 `json:"tx_fifo"` // Cumulative count of FIFO buffer errors. + TxCollisions uint64 `json:"tx_collisions"` // Cumulative count of collisions detected on the interface. + TxCarrier uint64 `json:"tx_carrier"` // Cumulative count of carrier losses detected by the device driver. + TxCompressed uint64 `json:"tx_compressed"` // Cumulative count of compressed packets transmitted by the device driver. +} + +// NetDev is parsed from /proc/net/dev or /proc/[pid]/net/dev. The map keys +// are interface names. +type NetDev map[string]NetDevLine + +// NewNetDev returns kernel/system statistics read from /proc/net/dev. +func NewNetDev() (NetDev, error) { + fs, err := NewFS(DefaultMountPoint) + if err != nil { + return nil, err + } + + return fs.NewNetDev() +} + +// NewNetDev returns kernel/system statistics read from /proc/net/dev. +func (fs FS) NewNetDev() (NetDev, error) { + return newNetDev(fs.Path("net/dev")) +} + +// NewNetDev returns kernel/system statistics read from /proc/[pid]/net/dev. +func (p Proc) NewNetDev() (NetDev, error) { + return newNetDev(p.path("net/dev")) +} + +// newNetDev creates a new NetDev from the contents of the given file. +func newNetDev(file string) (NetDev, error) { + f, err := os.Open(file) + if err != nil { + return NetDev{}, err + } + defer f.Close() + + nd := NetDev{} + s := bufio.NewScanner(f) + for n := 0; s.Scan(); n++ { + // Skip the 2 header lines. + if n < 2 { + continue + } + + line, err := nd.parseLine(s.Text()) + if err != nil { + return nd, err + } + + nd[line.Name] = *line + } + + return nd, s.Err() +} + +// parseLine parses a single line from the /proc/net/dev file. Header lines +// must be filtered prior to calling this method. +func (nd NetDev) parseLine(rawLine string) (*NetDevLine, error) { + parts := strings.SplitN(rawLine, ":", 2) + if len(parts) != 2 { + return nil, errors.New("invalid net/dev line, missing colon") + } + fields := strings.Fields(strings.TrimSpace(parts[1])) + + var err error + line := &NetDevLine{} + + // Interface Name + line.Name = strings.TrimSpace(parts[0]) + if line.Name == "" { + return nil, errors.New("invalid net/dev line, empty interface name") + } + + // RX + line.RxBytes, err = strconv.ParseUint(fields[0], 10, 64) + if err != nil { + return nil, err + } + line.RxPackets, err = strconv.ParseUint(fields[1], 10, 64) + if err != nil { + return nil, err + } + line.RxErrors, err = strconv.ParseUint(fields[2], 10, 64) + if err != nil { + return nil, err + } + line.RxDropped, err = strconv.ParseUint(fields[3], 10, 64) + if err != nil { + return nil, err + } + line.RxFIFO, err = strconv.ParseUint(fields[4], 10, 64) + if err != nil { + return nil, err + } + line.RxFrame, err = strconv.ParseUint(fields[5], 10, 64) + if err != nil { + return nil, err + } + line.RxCompressed, err = strconv.ParseUint(fields[6], 10, 64) + if err != nil { + return nil, err + } + line.RxMulticast, err = strconv.ParseUint(fields[7], 10, 64) + if err != nil { + return nil, err + } + + // TX + line.TxBytes, err = strconv.ParseUint(fields[8], 10, 64) + if err != nil { + return nil, err + } + line.TxPackets, err = strconv.ParseUint(fields[9], 10, 64) + if err != nil { + return nil, err + } + line.TxErrors, err = strconv.ParseUint(fields[10], 10, 64) + if err != nil { + return nil, err + } + line.TxDropped, err = strconv.ParseUint(fields[11], 10, 64) + if err != nil { + return nil, err + } + line.TxFIFO, err = strconv.ParseUint(fields[12], 10, 64) + if err != nil { + return nil, err + } + line.TxCollisions, err = strconv.ParseUint(fields[13], 10, 64) + if err != nil { + return nil, err + } + line.TxCarrier, err = strconv.ParseUint(fields[14], 10, 64) + if err != nil { + return nil, err + } + line.TxCompressed, err = strconv.ParseUint(fields[15], 10, 64) + if err != nil { + return nil, err + } + + return line, nil +} + +// Total aggregates the values across interfaces and returns a new NetDevLine. +// The Name field will be a sorted comma separated list of interface names. +func (nd NetDev) Total() NetDevLine { + total := NetDevLine{} + + names := make([]string, 0, len(nd)) + for _, ifc := range nd { + names = append(names, ifc.Name) + total.RxBytes += ifc.RxBytes + total.RxPackets += ifc.RxPackets + total.RxPackets += ifc.RxPackets + total.RxErrors += ifc.RxErrors + total.RxDropped += ifc.RxDropped + total.RxFIFO += ifc.RxFIFO + total.RxFrame += ifc.RxFrame + total.RxCompressed += ifc.RxCompressed + total.RxMulticast += ifc.RxMulticast + total.TxBytes += ifc.TxBytes + total.TxPackets += ifc.TxPackets + total.TxErrors += ifc.TxErrors + total.TxDropped += ifc.TxDropped + total.TxFIFO += ifc.TxFIFO + total.TxCollisions += ifc.TxCollisions + total.TxCarrier += ifc.TxCarrier + total.TxCompressed += ifc.TxCompressed + } + sort.Strings(names) + total.Name = strings.Join(names, ", ") + + return total +} diff --git a/vendor/github.com/prometheus/procfs/nfs/nfs.go b/vendor/github.com/prometheus/procfs/nfs/nfs.go new file mode 100644 index 000000000..651bf6819 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/nfs/nfs.go @@ -0,0 +1,263 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package nfs implements parsing of /proc/net/rpc/nfsd. +// Fields are documented in https://www.svennd.be/nfsd-stats-explained-procnetrpcnfsd/ +package nfs + +// ReplyCache models the "rc" line. +type ReplyCache struct { + Hits uint64 + Misses uint64 + NoCache uint64 +} + +// FileHandles models the "fh" line. +type FileHandles struct { + Stale uint64 + TotalLookups uint64 + AnonLookups uint64 + DirNoCache uint64 + NoDirNoCache uint64 +} + +// InputOutput models the "io" line. +type InputOutput struct { + Read uint64 + Write uint64 +} + +// Threads models the "th" line. +type Threads struct { + Threads uint64 + FullCnt uint64 +} + +// ReadAheadCache models the "ra" line. +type ReadAheadCache struct { + CacheSize uint64 + CacheHistogram []uint64 + NotFound uint64 +} + +// Network models the "net" line. +type Network struct { + NetCount uint64 + UDPCount uint64 + TCPCount uint64 + TCPConnect uint64 +} + +// ClientRPC models the nfs "rpc" line. +type ClientRPC struct { + RPCCount uint64 + Retransmissions uint64 + AuthRefreshes uint64 +} + +// ServerRPC models the nfsd "rpc" line. +type ServerRPC struct { + RPCCount uint64 + BadCnt uint64 + BadFmt uint64 + BadAuth uint64 + BadcInt uint64 +} + +// V2Stats models the "proc2" line. +type V2Stats struct { + Null uint64 + GetAttr uint64 + SetAttr uint64 + Root uint64 + Lookup uint64 + ReadLink uint64 + Read uint64 + WrCache uint64 + Write uint64 + Create uint64 + Remove uint64 + Rename uint64 + Link uint64 + SymLink uint64 + MkDir uint64 + RmDir uint64 + ReadDir uint64 + FsStat uint64 +} + +// V3Stats models the "proc3" line. +type V3Stats struct { + Null uint64 + GetAttr uint64 + SetAttr uint64 + Lookup uint64 + Access uint64 + ReadLink uint64 + Read uint64 + Write uint64 + Create uint64 + MkDir uint64 + SymLink uint64 + MkNod uint64 + Remove uint64 + RmDir uint64 + Rename uint64 + Link uint64 + ReadDir uint64 + ReadDirPlus uint64 + FsStat uint64 + FsInfo uint64 + PathConf uint64 + Commit uint64 +} + +// ClientV4Stats models the nfs "proc4" line. +type ClientV4Stats struct { + Null uint64 + Read uint64 + Write uint64 + Commit uint64 + Open uint64 + OpenConfirm uint64 + OpenNoattr uint64 + OpenDowngrade uint64 + Close uint64 + Setattr uint64 + FsInfo uint64 + Renew uint64 + SetClientID uint64 + SetClientIDConfirm uint64 + Lock uint64 + Lockt uint64 + Locku uint64 + Access uint64 + Getattr uint64 + Lookup uint64 + LookupRoot uint64 + Remove uint64 + Rename uint64 + Link uint64 + Symlink uint64 + Create uint64 + Pathconf uint64 + StatFs uint64 + ReadLink uint64 + ReadDir uint64 + ServerCaps uint64 + DelegReturn uint64 + GetACL uint64 + SetACL uint64 + FsLocations uint64 + ReleaseLockowner uint64 + Secinfo uint64 + FsidPresent uint64 + ExchangeID uint64 + CreateSession uint64 + DestroySession uint64 + Sequence uint64 + GetLeaseTime uint64 + ReclaimComplete uint64 + LayoutGet uint64 + GetDeviceInfo uint64 + LayoutCommit uint64 + LayoutReturn uint64 + SecinfoNoName uint64 + TestStateID uint64 + FreeStateID uint64 + GetDeviceList uint64 + BindConnToSession uint64 + DestroyClientID uint64 + Seek uint64 + Allocate uint64 + DeAllocate uint64 + LayoutStats uint64 + Clone uint64 +} + +// ServerV4Stats models the nfsd "proc4" line. +type ServerV4Stats struct { + Null uint64 + Compound uint64 +} + +// V4Ops models the "proc4ops" line: NFSv4 operations +// Variable list, see: +// v4.0 https://tools.ietf.org/html/rfc3010 (38 operations) +// v4.1 https://tools.ietf.org/html/rfc5661 (58 operations) +// v4.2 https://tools.ietf.org/html/draft-ietf-nfsv4-minorversion2-41 (71 operations) +type V4Ops struct { + //Values uint64 // Variable depending on v4.x sub-version. TODO: Will this always at least include the fields in this struct? + Op0Unused uint64 + Op1Unused uint64 + Op2Future uint64 + Access uint64 + Close uint64 + Commit uint64 + Create uint64 + DelegPurge uint64 + DelegReturn uint64 + GetAttr uint64 + GetFH uint64 + Link uint64 + Lock uint64 + Lockt uint64 + Locku uint64 + Lookup uint64 + LookupRoot uint64 + Nverify uint64 + Open uint64 + OpenAttr uint64 + OpenConfirm uint64 + OpenDgrd uint64 + PutFH uint64 + PutPubFH uint64 + PutRootFH uint64 + Read uint64 + ReadDir uint64 + ReadLink uint64 + Remove uint64 + Rename uint64 + Renew uint64 + RestoreFH uint64 + SaveFH uint64 + SecInfo uint64 + SetAttr uint64 + Verify uint64 + Write uint64 + RelLockOwner uint64 +} + +// ClientRPCStats models all stats from /proc/net/rpc/nfs. +type ClientRPCStats struct { + Network Network + ClientRPC ClientRPC + V2Stats V2Stats + V3Stats V3Stats + ClientV4Stats ClientV4Stats +} + +// ServerRPCStats models all stats from /proc/net/rpc/nfsd. +type ServerRPCStats struct { + ReplyCache ReplyCache + FileHandles FileHandles + InputOutput InputOutput + Threads Threads + ReadAheadCache ReadAheadCache + Network Network + ServerRPC ServerRPC + V2Stats V2Stats + V3Stats V3Stats + ServerV4Stats ServerV4Stats + V4Ops V4Ops +} diff --git a/vendor/github.com/prometheus/procfs/nfs/parse.go b/vendor/github.com/prometheus/procfs/nfs/parse.go new file mode 100644 index 000000000..95a83cc5b --- /dev/null +++ b/vendor/github.com/prometheus/procfs/nfs/parse.go @@ -0,0 +1,317 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package nfs + +import ( + "fmt" +) + +func parseReplyCache(v []uint64) (ReplyCache, error) { + if len(v) != 3 { + return ReplyCache{}, fmt.Errorf("invalid ReplyCache line %q", v) + } + + return ReplyCache{ + Hits: v[0], + Misses: v[1], + NoCache: v[2], + }, nil +} + +func parseFileHandles(v []uint64) (FileHandles, error) { + if len(v) != 5 { + return FileHandles{}, fmt.Errorf("invalid FileHandles, line %q", v) + } + + return FileHandles{ + Stale: v[0], + TotalLookups: v[1], + AnonLookups: v[2], + DirNoCache: v[3], + NoDirNoCache: v[4], + }, nil +} + +func parseInputOutput(v []uint64) (InputOutput, error) { + if len(v) != 2 { + return InputOutput{}, fmt.Errorf("invalid InputOutput line %q", v) + } + + return InputOutput{ + Read: v[0], + Write: v[1], + }, nil +} + +func parseThreads(v []uint64) (Threads, error) { + if len(v) != 2 { + return Threads{}, fmt.Errorf("invalid Threads line %q", v) + } + + return Threads{ + Threads: v[0], + FullCnt: v[1], + }, nil +} + +func parseReadAheadCache(v []uint64) (ReadAheadCache, error) { + if len(v) != 12 { + return ReadAheadCache{}, fmt.Errorf("invalid ReadAheadCache line %q", v) + } + + return ReadAheadCache{ + CacheSize: v[0], + CacheHistogram: v[1:11], + NotFound: v[11], + }, nil +} + +func parseNetwork(v []uint64) (Network, error) { + if len(v) != 4 { + return Network{}, fmt.Errorf("invalid Network line %q", v) + } + + return Network{ + NetCount: v[0], + UDPCount: v[1], + TCPCount: v[2], + TCPConnect: v[3], + }, nil +} + +func parseServerRPC(v []uint64) (ServerRPC, error) { + if len(v) != 5 { + return ServerRPC{}, fmt.Errorf("invalid RPC line %q", v) + } + + return ServerRPC{ + RPCCount: v[0], + BadCnt: v[1], + BadFmt: v[2], + BadAuth: v[3], + BadcInt: v[4], + }, nil +} + +func parseClientRPC(v []uint64) (ClientRPC, error) { + if len(v) != 3 { + return ClientRPC{}, fmt.Errorf("invalid RPC line %q", v) + } + + return ClientRPC{ + RPCCount: v[0], + Retransmissions: v[1], + AuthRefreshes: v[2], + }, nil +} + +func parseV2Stats(v []uint64) (V2Stats, error) { + values := int(v[0]) + if len(v[1:]) != values || values != 18 { + return V2Stats{}, fmt.Errorf("invalid V2Stats line %q", v) + } + + return V2Stats{ + Null: v[1], + GetAttr: v[2], + SetAttr: v[3], + Root: v[4], + Lookup: v[5], + ReadLink: v[6], + Read: v[7], + WrCache: v[8], + Write: v[9], + Create: v[10], + Remove: v[11], + Rename: v[12], + Link: v[13], + SymLink: v[14], + MkDir: v[15], + RmDir: v[16], + ReadDir: v[17], + FsStat: v[18], + }, nil +} + +func parseV3Stats(v []uint64) (V3Stats, error) { + values := int(v[0]) + if len(v[1:]) != values || values != 22 { + return V3Stats{}, fmt.Errorf("invalid V3Stats line %q", v) + } + + return V3Stats{ + Null: v[1], + GetAttr: v[2], + SetAttr: v[3], + Lookup: v[4], + Access: v[5], + ReadLink: v[6], + Read: v[7], + Write: v[8], + Create: v[9], + MkDir: v[10], + SymLink: v[11], + MkNod: v[12], + Remove: v[13], + RmDir: v[14], + Rename: v[15], + Link: v[16], + ReadDir: v[17], + ReadDirPlus: v[18], + FsStat: v[19], + FsInfo: v[20], + PathConf: v[21], + Commit: v[22], + }, nil +} + +func parseClientV4Stats(v []uint64) (ClientV4Stats, error) { + values := int(v[0]) + if len(v[1:]) != values { + return ClientV4Stats{}, fmt.Errorf("invalid ClientV4Stats line %q", v) + } + + // This function currently supports mapping 59 NFS v4 client stats. Older + // kernels may emit fewer stats, so we must detect this and pad out the + // values to match the expected slice size. + if values < 59 { + newValues := make([]uint64, 60) + copy(newValues, v) + v = newValues + } + + return ClientV4Stats{ + Null: v[1], + Read: v[2], + Write: v[3], + Commit: v[4], + Open: v[5], + OpenConfirm: v[6], + OpenNoattr: v[7], + OpenDowngrade: v[8], + Close: v[9], + Setattr: v[10], + FsInfo: v[11], + Renew: v[12], + SetClientID: v[13], + SetClientIDConfirm: v[14], + Lock: v[15], + Lockt: v[16], + Locku: v[17], + Access: v[18], + Getattr: v[19], + Lookup: v[20], + LookupRoot: v[21], + Remove: v[22], + Rename: v[23], + Link: v[24], + Symlink: v[25], + Create: v[26], + Pathconf: v[27], + StatFs: v[28], + ReadLink: v[29], + ReadDir: v[30], + ServerCaps: v[31], + DelegReturn: v[32], + GetACL: v[33], + SetACL: v[34], + FsLocations: v[35], + ReleaseLockowner: v[36], + Secinfo: v[37], + FsidPresent: v[38], + ExchangeID: v[39], + CreateSession: v[40], + DestroySession: v[41], + Sequence: v[42], + GetLeaseTime: v[43], + ReclaimComplete: v[44], + LayoutGet: v[45], + GetDeviceInfo: v[46], + LayoutCommit: v[47], + LayoutReturn: v[48], + SecinfoNoName: v[49], + TestStateID: v[50], + FreeStateID: v[51], + GetDeviceList: v[52], + BindConnToSession: v[53], + DestroyClientID: v[54], + Seek: v[55], + Allocate: v[56], + DeAllocate: v[57], + LayoutStats: v[58], + Clone: v[59], + }, nil +} + +func parseServerV4Stats(v []uint64) (ServerV4Stats, error) { + values := int(v[0]) + if len(v[1:]) != values || values != 2 { + return ServerV4Stats{}, fmt.Errorf("invalid V4Stats line %q", v) + } + + return ServerV4Stats{ + Null: v[1], + Compound: v[2], + }, nil +} + +func parseV4Ops(v []uint64) (V4Ops, error) { + values := int(v[0]) + if len(v[1:]) != values || values < 39 { + return V4Ops{}, fmt.Errorf("invalid V4Ops line %q", v) + } + + stats := V4Ops{ + Op0Unused: v[1], + Op1Unused: v[2], + Op2Future: v[3], + Access: v[4], + Close: v[5], + Commit: v[6], + Create: v[7], + DelegPurge: v[8], + DelegReturn: v[9], + GetAttr: v[10], + GetFH: v[11], + Link: v[12], + Lock: v[13], + Lockt: v[14], + Locku: v[15], + Lookup: v[16], + LookupRoot: v[17], + Nverify: v[18], + Open: v[19], + OpenAttr: v[20], + OpenConfirm: v[21], + OpenDgrd: v[22], + PutFH: v[23], + PutPubFH: v[24], + PutRootFH: v[25], + Read: v[26], + ReadDir: v[27], + ReadLink: v[28], + Remove: v[29], + Rename: v[30], + Renew: v[31], + RestoreFH: v[32], + SaveFH: v[33], + SecInfo: v[34], + SetAttr: v[35], + Verify: v[36], + Write: v[37], + RelLockOwner: v[38], + } + + return stats, nil +} diff --git a/vendor/github.com/prometheus/procfs/nfs/parse_nfs.go b/vendor/github.com/prometheus/procfs/nfs/parse_nfs.go new file mode 100644 index 000000000..c0d3a5ad9 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/nfs/parse_nfs.go @@ -0,0 +1,67 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package nfs + +import ( + "bufio" + "fmt" + "io" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// ParseClientRPCStats returns stats read from /proc/net/rpc/nfs +func ParseClientRPCStats(r io.Reader) (*ClientRPCStats, error) { + stats := &ClientRPCStats{} + + scanner := bufio.NewScanner(r) + for scanner.Scan() { + line := scanner.Text() + parts := strings.Fields(scanner.Text()) + // require at least + if len(parts) < 2 { + return nil, fmt.Errorf("invalid NFS metric line %q", line) + } + + values, err := util.ParseUint64s(parts[1:]) + if err != nil { + return nil, fmt.Errorf("error parsing NFS metric line: %s", err) + } + + switch metricLine := parts[0]; metricLine { + case "net": + stats.Network, err = parseNetwork(values) + case "rpc": + stats.ClientRPC, err = parseClientRPC(values) + case "proc2": + stats.V2Stats, err = parseV2Stats(values) + case "proc3": + stats.V3Stats, err = parseV3Stats(values) + case "proc4": + stats.ClientV4Stats, err = parseClientV4Stats(values) + default: + return nil, fmt.Errorf("unknown NFS metric line %q", metricLine) + } + if err != nil { + return nil, fmt.Errorf("errors parsing NFS metric line: %s", err) + } + } + + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("error scanning NFS file: %s", err) + } + + return stats, nil +} diff --git a/vendor/github.com/prometheus/procfs/nfs/parse_nfsd.go b/vendor/github.com/prometheus/procfs/nfs/parse_nfsd.go new file mode 100644 index 000000000..57bb4a358 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/nfs/parse_nfsd.go @@ -0,0 +1,89 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package nfs + +import ( + "bufio" + "fmt" + "io" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// ParseServerRPCStats returns stats read from /proc/net/rpc/nfsd +func ParseServerRPCStats(r io.Reader) (*ServerRPCStats, error) { + stats := &ServerRPCStats{} + + scanner := bufio.NewScanner(r) + for scanner.Scan() { + line := scanner.Text() + parts := strings.Fields(scanner.Text()) + // require at least + if len(parts) < 2 { + return nil, fmt.Errorf("invalid NFSd metric line %q", line) + } + label := parts[0] + + var values []uint64 + var err error + if label == "th" { + if len(parts) < 3 { + return nil, fmt.Errorf("invalid NFSd th metric line %q", line) + } + values, err = util.ParseUint64s(parts[1:3]) + } else { + values, err = util.ParseUint64s(parts[1:]) + } + if err != nil { + return nil, fmt.Errorf("error parsing NFSd metric line: %s", err) + } + + switch metricLine := parts[0]; metricLine { + case "rc": + stats.ReplyCache, err = parseReplyCache(values) + case "fh": + stats.FileHandles, err = parseFileHandles(values) + case "io": + stats.InputOutput, err = parseInputOutput(values) + case "th": + stats.Threads, err = parseThreads(values) + case "ra": + stats.ReadAheadCache, err = parseReadAheadCache(values) + case "net": + stats.Network, err = parseNetwork(values) + case "rpc": + stats.ServerRPC, err = parseServerRPC(values) + case "proc2": + stats.V2Stats, err = parseV2Stats(values) + case "proc3": + stats.V3Stats, err = parseV3Stats(values) + case "proc4": + stats.ServerV4Stats, err = parseServerV4Stats(values) + case "proc4ops": + stats.V4Ops, err = parseV4Ops(values) + default: + return nil, fmt.Errorf("unknown NFSd metric line %q", metricLine) + } + if err != nil { + return nil, fmt.Errorf("errors parsing NFSd metric line: %s", err) + } + } + + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("error scanning NFSd file: %s", err) + } + + return stats, nil +} diff --git a/vendor/github.com/prometheus/procfs/proc.go b/vendor/github.com/prometheus/procfs/proc.go index 8717e1fe0..06bed0ef4 100644 --- a/vendor/github.com/prometheus/procfs/proc.go +++ b/vendor/github.com/prometheus/procfs/proc.go @@ -1,6 +1,20 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package procfs import ( + "bytes" "fmt" "io/ioutil" "os" @@ -113,7 +127,7 @@ func (p Proc) CmdLine() ([]string, error) { return []string{}, nil } - return strings.Split(string(data[:len(data)-1]), string(byte(0))), nil + return strings.Split(string(bytes.TrimRight(data, string("\x00"))), string(byte(0))), nil } // Comm returns the command name of a process. @@ -142,6 +156,26 @@ func (p Proc) Executable() (string, error) { return exe, err } +// Cwd returns the absolute path to the current working directory of the process. +func (p Proc) Cwd() (string, error) { + wd, err := os.Readlink(p.path("cwd")) + if os.IsNotExist(err) { + return "", nil + } + + return wd, err +} + +// RootDir returns the absolute path to the process's root directory (as set by chroot) +func (p Proc) RootDir() (string, error) { + rdir, err := os.Readlink(p.path("root")) + if os.IsNotExist(err) { + return "", nil + } + + return rdir, err +} + // FileDescriptors returns the currently open file descriptors of a process. func (p Proc) FileDescriptors() ([]uintptr, error) { names, err := p.fileDescriptors() diff --git a/vendor/github.com/prometheus/procfs/proc_io.go b/vendor/github.com/prometheus/procfs/proc_io.go index b4e31d7ba..0251c83bf 100644 --- a/vendor/github.com/prometheus/procfs/proc_io.go +++ b/vendor/github.com/prometheus/procfs/proc_io.go @@ -1,3 +1,16 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package procfs import ( @@ -47,9 +60,6 @@ func (p Proc) NewIO() (ProcIO, error) { _, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR, &pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes) - if err != nil { - return pio, err - } - return pio, nil + return pio, err } diff --git a/vendor/github.com/prometheus/procfs/proc_io_test.go b/vendor/github.com/prometheus/procfs/proc_io_test.go deleted file mode 100644 index 3aa1a1293..000000000 --- a/vendor/github.com/prometheus/procfs/proc_io_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package procfs - -import "testing" - -func TestProcIO(t *testing.T) { - p, err := FS("fixtures").NewProc(26231) - if err != nil { - t.Fatal(err) - } - - s, err := p.NewIO() - if err != nil { - t.Fatal(err) - } - - for _, test := range []struct { - name string - want int64 - have int64 - }{ - {name: "RChar", want: 750339, have: int64(s.RChar)}, - {name: "WChar", want: 818609, have: int64(s.WChar)}, - {name: "SyscR", want: 7405, have: int64(s.SyscR)}, - {name: "SyscW", want: 5245, have: int64(s.SyscW)}, - {name: "ReadBytes", want: 1024, have: int64(s.ReadBytes)}, - {name: "WriteBytes", want: 2048, have: int64(s.WriteBytes)}, - {name: "CancelledWriteBytes", want: -1024, have: s.CancelledWriteBytes}, - } { - if test.want != test.have { - t.Errorf("want %s %d, have %d", test.name, test.want, test.have) - } - } -} diff --git a/vendor/github.com/prometheus/procfs/proc_limits.go b/vendor/github.com/prometheus/procfs/proc_limits.go index 2df997ce1..f04ba6fda 100644 --- a/vendor/github.com/prometheus/procfs/proc_limits.go +++ b/vendor/github.com/prometheus/procfs/proc_limits.go @@ -1,3 +1,16 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package procfs import ( @@ -13,46 +26,46 @@ import ( // http://man7.org/linux/man-pages/man2/getrlimit.2.html. type ProcLimits struct { // CPU time limit in seconds. - CPUTime int + CPUTime int64 // Maximum size of files that the process may create. - FileSize int + FileSize int64 // Maximum size of the process's data segment (initialized data, // uninitialized data, and heap). - DataSize int + DataSize int64 // Maximum size of the process stack in bytes. - StackSize int + StackSize int64 // Maximum size of a core file. - CoreFileSize int + CoreFileSize int64 // Limit of the process's resident set in pages. - ResidentSet int + ResidentSet int64 // Maximum number of processes that can be created for the real user ID of // the calling process. - Processes int + Processes int64 // Value one greater than the maximum file descriptor number that can be // opened by this process. - OpenFiles int + OpenFiles int64 // Maximum number of bytes of memory that may be locked into RAM. - LockedMemory int + LockedMemory int64 // Maximum size of the process's virtual memory address space in bytes. - AddressSpace int + AddressSpace int64 // Limit on the combined number of flock(2) locks and fcntl(2) leases that // this process may establish. - FileLocks int + FileLocks int64 // Limit of signals that may be queued for the real user ID of the calling // process. - PendingSignals int + PendingSignals int64 // Limit on the number of bytes that can be allocated for POSIX message // queues for the real user ID of the calling process. - MsqqueueSize int + MsqqueueSize int64 // Limit of the nice priority set using setpriority(2) or nice(2). - NicePriority int + NicePriority int64 // Limit of the real-time priority set using sched_setscheduler(2) or // sched_setparam(2). - RealtimePriority int + RealtimePriority int64 // Limit (in microseconds) on the amount of CPU time that a process // scheduled under a real-time scheduling policy may consume without making // a blocking system call. - RealtimeTimeout int + RealtimeTimeout int64 } const ( @@ -125,13 +138,13 @@ func (p Proc) NewLimits() (ProcLimits, error) { return l, s.Err() } -func parseInt(s string) (int, error) { +func parseInt(s string) (int64, error) { if s == limitsUnlimited { return -1, nil } - i, err := strconv.ParseInt(s, 10, 32) + i, err := strconv.ParseInt(s, 10, 64) if err != nil { return 0, fmt.Errorf("couldn't parse value %s: %s", s, err) } - return int(i), nil + return i, nil } diff --git a/vendor/github.com/prometheus/procfs/proc_limits_test.go b/vendor/github.com/prometheus/procfs/proc_limits_test.go deleted file mode 100644 index 70bf04ec2..000000000 --- a/vendor/github.com/prometheus/procfs/proc_limits_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package procfs - -import "testing" - -func TestNewLimits(t *testing.T) { - p, err := FS("fixtures").NewProc(26231) - if err != nil { - t.Fatal(err) - } - - l, err := p.NewLimits() - if err != nil { - t.Fatal(err) - } - - for _, test := range []struct { - name string - want int - have int - }{ - {name: "cpu time", want: -1, have: l.CPUTime}, - {name: "open files", want: 2048, have: l.OpenFiles}, - {name: "msgqueue size", want: 819200, have: l.MsqqueueSize}, - {name: "nice priority", want: 0, have: l.NicePriority}, - {name: "address space", want: -1, have: l.AddressSpace}, - } { - if test.want != test.have { - t.Errorf("want %s %d, have %d", test.name, test.want, test.have) - } - } -} diff --git a/vendor/github.com/prometheus/procfs/proc_ns.go b/vendor/github.com/prometheus/procfs/proc_ns.go new file mode 100644 index 000000000..d06c26eba --- /dev/null +++ b/vendor/github.com/prometheus/procfs/proc_ns.go @@ -0,0 +1,68 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "fmt" + "os" + "strconv" + "strings" +) + +// Namespace represents a single namespace of a process. +type Namespace struct { + Type string // Namespace type. + Inode uint32 // Inode number of the namespace. If two processes are in the same namespace their inodes will match. +} + +// Namespaces contains all of the namespaces that the process is contained in. +type Namespaces map[string]Namespace + +// NewNamespaces reads from /proc/[pid/ns/* to get the namespaces of which the +// process is a member. +func (p Proc) NewNamespaces() (Namespaces, error) { + d, err := os.Open(p.path("ns")) + if err != nil { + return nil, err + } + defer d.Close() + + names, err := d.Readdirnames(-1) + if err != nil { + return nil, fmt.Errorf("failed to read contents of ns dir: %v", err) + } + + ns := make(Namespaces, len(names)) + for _, name := range names { + target, err := os.Readlink(p.path("ns", name)) + if err != nil { + return nil, err + } + + fields := strings.SplitN(target, ":", 2) + if len(fields) != 2 { + return nil, fmt.Errorf("failed to parse namespace type and inode from '%v'", target) + } + + typ := fields[0] + inode, err := strconv.ParseUint(strings.Trim(fields[1], "[]"), 10, 32) + if err != nil { + return nil, fmt.Errorf("failed to parse inode from '%v': %v", fields[1], err) + } + + ns[name] = Namespace{typ, uint32(inode)} + } + + return ns, nil +} diff --git a/vendor/github.com/prometheus/procfs/proc_stat.go b/vendor/github.com/prometheus/procfs/proc_stat.go index 724e271b9..3cf2a9f18 100644 --- a/vendor/github.com/prometheus/procfs/proc_stat.go +++ b/vendor/github.com/prometheus/procfs/proc_stat.go @@ -1,3 +1,16 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package procfs import ( diff --git a/vendor/github.com/prometheus/procfs/proc_stat_test.go b/vendor/github.com/prometheus/procfs/proc_stat_test.go deleted file mode 100644 index a2ebcde78..000000000 --- a/vendor/github.com/prometheus/procfs/proc_stat_test.go +++ /dev/null @@ -1,110 +0,0 @@ -package procfs - -import ( - "os" - "testing" -) - -func TestProcStat(t *testing.T) { - p, err := FS("fixtures").NewProc(26231) - if err != nil { - t.Fatal(err) - } - - s, err := p.NewStat() - if err != nil { - t.Fatal(err) - } - - for _, test := range []struct { - name string - want int - have int - }{ - {name: "pid", want: 26231, have: s.PID}, - {name: "user time", want: 1677, have: int(s.UTime)}, - {name: "system time", want: 44, have: int(s.STime)}, - {name: "start time", want: 82375, have: int(s.Starttime)}, - {name: "virtual memory size", want: 56274944, have: s.VSize}, - {name: "resident set size", want: 1981, have: s.RSS}, - } { - if test.want != test.have { - t.Errorf("want %s %d, have %d", test.name, test.want, test.have) - } - } -} - -func TestProcStatComm(t *testing.T) { - s1, err := testProcStat(26231) - if err != nil { - t.Fatal(err) - } - if want, have := "vim", s1.Comm; want != have { - t.Errorf("want comm %s, have %s", want, have) - } - - s2, err := testProcStat(584) - if err != nil { - t.Fatal(err) - } - if want, have := "(a b ) ( c d) ", s2.Comm; want != have { - t.Errorf("want comm %s, have %s", want, have) - } -} - -func TestProcStatVirtualMemory(t *testing.T) { - s, err := testProcStat(26231) - if err != nil { - t.Fatal(err) - } - - if want, have := 56274944, s.VirtualMemory(); want != have { - t.Errorf("want virtual memory %d, have %d", want, have) - } -} - -func TestProcStatResidentMemory(t *testing.T) { - s, err := testProcStat(26231) - if err != nil { - t.Fatal(err) - } - - if want, have := 1981*os.Getpagesize(), s.ResidentMemory(); want != have { - t.Errorf("want resident memory %d, have %d", want, have) - } -} - -func TestProcStatStartTime(t *testing.T) { - s, err := testProcStat(26231) - if err != nil { - t.Fatal(err) - } - - time, err := s.StartTime() - if err != nil { - t.Fatal(err) - } - if want, have := 1418184099.75, time; want != have { - t.Errorf("want start time %f, have %f", want, have) - } -} - -func TestProcStatCPUTime(t *testing.T) { - s, err := testProcStat(26231) - if err != nil { - t.Fatal(err) - } - - if want, have := 17.21, s.CPUTime(); want != have { - t.Errorf("want cpu time %f, have %f", want, have) - } -} - -func testProcStat(pid int) (ProcStat, error) { - p, err := FS("fixtures").NewProc(pid) - if err != nil { - return ProcStat{}, err - } - - return p.NewStat() -} diff --git a/vendor/github.com/prometheus/procfs/proc_test.go b/vendor/github.com/prometheus/procfs/proc_test.go deleted file mode 100644 index 104b3245d..000000000 --- a/vendor/github.com/prometheus/procfs/proc_test.go +++ /dev/null @@ -1,160 +0,0 @@ -package procfs - -import ( - "reflect" - "sort" - "testing" -) - -func TestSelf(t *testing.T) { - fs := FS("fixtures") - - p1, err := fs.NewProc(26231) - if err != nil { - t.Fatal(err) - } - p2, err := fs.Self() - if err != nil { - t.Fatal(err) - } - - if !reflect.DeepEqual(p1, p2) { - t.Errorf("want process %v, have %v", p1, p2) - } -} - -func TestAllProcs(t *testing.T) { - procs, err := FS("fixtures").AllProcs() - if err != nil { - t.Fatal(err) - } - sort.Sort(procs) - for i, p := range []*Proc{{PID: 584}, {PID: 26231}} { - if want, have := p.PID, procs[i].PID; want != have { - t.Errorf("want processes %d, have %d", want, have) - } - } -} - -func TestCmdLine(t *testing.T) { - for _, tt := range []struct { - process int - want []string - }{ - {process: 26231, want: []string{"vim", "test.go", "+10"}}, - {process: 26232, want: []string{}}, - } { - p1, err := FS("fixtures").NewProc(tt.process) - if err != nil { - t.Fatal(err) - } - c1, err := p1.CmdLine() - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(tt.want, c1) { - t.Errorf("want cmdline %v, have %v", tt.want, c1) - } - } -} - -func TestComm(t *testing.T) { - for _, tt := range []struct { - process int - want string - }{ - {process: 26231, want: "vim"}, - {process: 26232, want: "ata_sff"}, - } { - p1, err := FS("fixtures").NewProc(tt.process) - if err != nil { - t.Fatal(err) - } - c1, err := p1.Comm() - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(tt.want, c1) { - t.Errorf("want comm %v, have %v", tt.want, c1) - } - } -} - -func TestExecutable(t *testing.T) { - for _, tt := range []struct { - process int - want string - }{ - {process: 26231, want: "/usr/bin/vim"}, - {process: 26232, want: ""}, - } { - p, err := FS("fixtures").NewProc(tt.process) - if err != nil { - t.Fatal(err) - } - exe, err := p.Executable() - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(tt.want, exe) { - t.Errorf("want absolute path to cmdline %v, have %v", tt.want, exe) - } - } -} - -func TestFileDescriptors(t *testing.T) { - p1, err := FS("fixtures").NewProc(26231) - if err != nil { - t.Fatal(err) - } - fds, err := p1.FileDescriptors() - if err != nil { - t.Fatal(err) - } - sort.Sort(byUintptr(fds)) - if want := []uintptr{0, 1, 2, 3, 10}; !reflect.DeepEqual(want, fds) { - t.Errorf("want fds %v, have %v", want, fds) - } -} - -func TestFileDescriptorTargets(t *testing.T) { - p1, err := FS("fixtures").NewProc(26231) - if err != nil { - t.Fatal(err) - } - fds, err := p1.FileDescriptorTargets() - if err != nil { - t.Fatal(err) - } - sort.Strings(fds) - var want = []string{ - "../../symlinktargets/abc", - "../../symlinktargets/def", - "../../symlinktargets/ghi", - "../../symlinktargets/uvw", - "../../symlinktargets/xyz", - } - if !reflect.DeepEqual(want, fds) { - t.Errorf("want fds %v, have %v", want, fds) - } -} - -func TestFileDescriptorsLen(t *testing.T) { - p1, err := FS("fixtures").NewProc(26231) - if err != nil { - t.Fatal(err) - } - l, err := p1.FileDescriptorsLen() - if err != nil { - t.Fatal(err) - } - if want, have := 5, l; want != have { - t.Errorf("want fds %d, have %d", want, have) - } -} - -type byUintptr []uintptr - -func (a byUintptr) Len() int { return len(a) } -func (a byUintptr) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a byUintptr) Less(i, j int) bool { return a[i] < a[j] } diff --git a/vendor/github.com/prometheus/procfs/stat.go b/vendor/github.com/prometheus/procfs/stat.go index 1ca217e8c..61eb6b0e3 100644 --- a/vendor/github.com/prometheus/procfs/stat.go +++ b/vendor/github.com/prometheus/procfs/stat.go @@ -1,17 +1,81 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package procfs import ( "bufio" "fmt" + "io" "os" "strconv" "strings" ) +// CPUStat shows how much time the cpu spend in various stages. +type CPUStat struct { + User float64 + Nice float64 + System float64 + Idle float64 + Iowait float64 + IRQ float64 + SoftIRQ float64 + Steal float64 + Guest float64 + GuestNice float64 +} + +// SoftIRQStat represent the softirq statistics as exported in the procfs stat file. +// A nice introduction can be found at https://0xax.gitbooks.io/linux-insides/content/interrupts/interrupts-9.html +// It is possible to get per-cpu stats by reading /proc/softirqs +type SoftIRQStat struct { + Hi uint64 + Timer uint64 + NetTx uint64 + NetRx uint64 + Block uint64 + BlockIoPoll uint64 + Tasklet uint64 + Sched uint64 + Hrtimer uint64 + Rcu uint64 +} + // Stat represents kernel/system statistics. type Stat struct { // Boot time in seconds since the Epoch. - BootTime int64 + BootTime uint64 + // Summed up cpu statistics. + CPUTotal CPUStat + // Per-CPU statistics. + CPU []CPUStat + // Number of times interrupts were handled, which contains numbered and unnumbered IRQs. + IRQTotal uint64 + // Number of times a numbered IRQ was triggered. + IRQ []uint64 + // Number of times a context switch happened. + ContextSwitches uint64 + // Number of times a process was created. + ProcessCreated uint64 + // Number of processes currently running. + ProcessesRunning uint64 + // Number of processes currently blocked (waiting for IO). + ProcessesBlocked uint64 + // Number of times a softirq was scheduled. + SoftIRQTotal uint64 + // Detailed softirq statistics. + SoftIRQ SoftIRQStat } // NewStat returns kernel/system statistics read from /proc/stat. @@ -24,33 +88,145 @@ func NewStat() (Stat, error) { return fs.NewStat() } +// Parse a cpu statistics line and returns the CPUStat struct plus the cpu id (or -1 for the overall sum). +func parseCPUStat(line string) (CPUStat, int64, error) { + cpuStat := CPUStat{} + var cpu string + + count, err := fmt.Sscanf(line, "%s %f %f %f %f %f %f %f %f %f %f", + &cpu, + &cpuStat.User, &cpuStat.Nice, &cpuStat.System, &cpuStat.Idle, + &cpuStat.Iowait, &cpuStat.IRQ, &cpuStat.SoftIRQ, &cpuStat.Steal, + &cpuStat.Guest, &cpuStat.GuestNice) + + if err != nil && err != io.EOF { + return CPUStat{}, -1, fmt.Errorf("couldn't parse %s (cpu): %s", line, err) + } + if count == 0 { + return CPUStat{}, -1, fmt.Errorf("couldn't parse %s (cpu): 0 elements parsed", line) + } + + cpuStat.User /= userHZ + cpuStat.Nice /= userHZ + cpuStat.System /= userHZ + cpuStat.Idle /= userHZ + cpuStat.Iowait /= userHZ + cpuStat.IRQ /= userHZ + cpuStat.SoftIRQ /= userHZ + cpuStat.Steal /= userHZ + cpuStat.Guest /= userHZ + cpuStat.GuestNice /= userHZ + + if cpu == "cpu" { + return cpuStat, -1, nil + } + + cpuID, err := strconv.ParseInt(cpu[3:], 10, 64) + if err != nil { + return CPUStat{}, -1, fmt.Errorf("couldn't parse %s (cpu/cpuid): %s", line, err) + } + + return cpuStat, cpuID, nil +} + +// Parse a softirq line. +func parseSoftIRQStat(line string) (SoftIRQStat, uint64, error) { + softIRQStat := SoftIRQStat{} + var total uint64 + var prefix string + + _, err := fmt.Sscanf(line, "%s %d %d %d %d %d %d %d %d %d %d %d", + &prefix, &total, + &softIRQStat.Hi, &softIRQStat.Timer, &softIRQStat.NetTx, &softIRQStat.NetRx, + &softIRQStat.Block, &softIRQStat.BlockIoPoll, + &softIRQStat.Tasklet, &softIRQStat.Sched, + &softIRQStat.Hrtimer, &softIRQStat.Rcu) + + if err != nil { + return SoftIRQStat{}, 0, fmt.Errorf("couldn't parse %s (softirq): %s", line, err) + } + + return softIRQStat, total, nil +} + // NewStat returns an information about current kernel/system statistics. func (fs FS) NewStat() (Stat, error) { + // See https://www.kernel.org/doc/Documentation/filesystems/proc.txt + f, err := os.Open(fs.Path("stat")) if err != nil { return Stat{}, err } defer f.Close() - s := bufio.NewScanner(f) - for s.Scan() { - line := s.Text() - if !strings.HasPrefix(line, "btime") { + stat := Stat{} + + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := scanner.Text() + parts := strings.Fields(scanner.Text()) + // require at least + if len(parts) < 2 { continue } - fields := strings.Fields(line) - if len(fields) != 2 { - return Stat{}, fmt.Errorf("couldn't parse %s line %s", f.Name(), line) - } - i, err := strconv.ParseInt(fields[1], 10, 32) - if err != nil { - return Stat{}, fmt.Errorf("couldn't parse %s: %s", fields[1], err) + switch { + case parts[0] == "btime": + if stat.BootTime, err = strconv.ParseUint(parts[1], 10, 64); err != nil { + return Stat{}, fmt.Errorf("couldn't parse %s (btime): %s", parts[1], err) + } + case parts[0] == "intr": + if stat.IRQTotal, err = strconv.ParseUint(parts[1], 10, 64); err != nil { + return Stat{}, fmt.Errorf("couldn't parse %s (intr): %s", parts[1], err) + } + numberedIRQs := parts[2:] + stat.IRQ = make([]uint64, len(numberedIRQs)) + for i, count := range numberedIRQs { + if stat.IRQ[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Stat{}, fmt.Errorf("couldn't parse %s (intr%d): %s", count, i, err) + } + } + case parts[0] == "ctxt": + if stat.ContextSwitches, err = strconv.ParseUint(parts[1], 10, 64); err != nil { + return Stat{}, fmt.Errorf("couldn't parse %s (ctxt): %s", parts[1], err) + } + case parts[0] == "processes": + if stat.ProcessCreated, err = strconv.ParseUint(parts[1], 10, 64); err != nil { + return Stat{}, fmt.Errorf("couldn't parse %s (processes): %s", parts[1], err) + } + case parts[0] == "procs_running": + if stat.ProcessesRunning, err = strconv.ParseUint(parts[1], 10, 64); err != nil { + return Stat{}, fmt.Errorf("couldn't parse %s (procs_running): %s", parts[1], err) + } + case parts[0] == "procs_blocked": + if stat.ProcessesBlocked, err = strconv.ParseUint(parts[1], 10, 64); err != nil { + return Stat{}, fmt.Errorf("couldn't parse %s (procs_blocked): %s", parts[1], err) + } + case parts[0] == "softirq": + softIRQStats, total, err := parseSoftIRQStat(line) + if err != nil { + return Stat{}, err + } + stat.SoftIRQTotal = total + stat.SoftIRQ = softIRQStats + case strings.HasPrefix(parts[0], "cpu"): + cpuStat, cpuID, err := parseCPUStat(line) + if err != nil { + return Stat{}, err + } + if cpuID == -1 { + stat.CPUTotal = cpuStat + } else { + for int64(len(stat.CPU)) <= cpuID { + stat.CPU = append(stat.CPU, CPUStat{}) + } + stat.CPU[cpuID] = cpuStat + } } - return Stat{BootTime: i}, nil } - if err := s.Err(); err != nil { + + if err := scanner.Err(); err != nil { return Stat{}, fmt.Errorf("couldn't parse %s: %s", f.Name(), err) } - return Stat{}, fmt.Errorf("couldn't parse %s, missing btime", f.Name()) + return stat, nil } diff --git a/vendor/github.com/prometheus/procfs/stat_test.go b/vendor/github.com/prometheus/procfs/stat_test.go deleted file mode 100644 index 6eb792478..000000000 --- a/vendor/github.com/prometheus/procfs/stat_test.go +++ /dev/null @@ -1,14 +0,0 @@ -package procfs - -import "testing" - -func TestStat(t *testing.T) { - s, err := FS("fixtures").NewStat() - if err != nil { - t.Fatal(err) - } - - if want, have := int64(1418183276), s.BootTime; want != have { - t.Errorf("want boot time %d, have %d", want, have) - } -} diff --git a/vendor/github.com/prometheus/procfs/ttar b/vendor/github.com/prometheus/procfs/ttar new file mode 100644 index 000000000..b0171a12b --- /dev/null +++ b/vendor/github.com/prometheus/procfs/ttar @@ -0,0 +1,389 @@ +#!/usr/bin/env bash + +# Purpose: plain text tar format +# Limitations: - only suitable for text files, directories, and symlinks +# - stores only filename, content, and mode +# - not designed for untrusted input +# +# Note: must work with bash version 3.2 (macOS) + +# Copyright 2017 Roger Luethi +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit -o nounset + +# Sanitize environment (for instance, standard sorting of glob matches) +export LC_ALL=C + +path="" +CMD="" +ARG_STRING="$*" + +#------------------------------------------------------------------------------ +# Not all sed implementations can work on null bytes. In order to make ttar +# work out of the box on macOS, use Python as a stream editor. + +USE_PYTHON=0 + +PYTHON_CREATE_FILTER=$(cat << 'PCF' +#!/usr/bin/env python + +import re +import sys + +for line in sys.stdin: + line = re.sub(r'EOF', r'\EOF', line) + line = re.sub(r'NULLBYTE', r'\NULLBYTE', line) + line = re.sub('\x00', r'NULLBYTE', line) + sys.stdout.write(line) +PCF +) + +PYTHON_EXTRACT_FILTER=$(cat << 'PEF' +#!/usr/bin/env python + +import re +import sys + +for line in sys.stdin: + line = re.sub(r'(?/dev/null; then + echo "ERROR Python not found. Aborting." + exit 2 + fi + USE_PYTHON=1 + fi +} + +#------------------------------------------------------------------------------ + +function usage { + bname=$(basename "$0") + cat << USAGE +Usage: $bname [-C ] -c -f (create archive) + $bname -t -f (list archive contents) + $bname [-C ] -x -f (extract archive) + +Options: + -C (change directory) + -v (verbose) + +Example: Change to sysfs directory, create ttar file from fixtures directory + $bname -C sysfs -c -f sysfs/fixtures.ttar fixtures/ +USAGE +exit "$1" +} + +function vecho { + if [ "${VERBOSE:-}" == "yes" ]; then + echo >&7 "$@" + fi +} + +function set_cmd { + if [ -n "$CMD" ]; then + echo "ERROR: more than one command given" + echo + usage 2 + fi + CMD=$1 +} + +unset VERBOSE + +while getopts :cf:htxvC: opt; do + case $opt in + c) + set_cmd "create" + ;; + f) + ARCHIVE=$OPTARG + ;; + h) + usage 0 + ;; + t) + set_cmd "list" + ;; + x) + set_cmd "extract" + ;; + v) + VERBOSE=yes + exec 7>&1 + ;; + C) + CDIR=$OPTARG + ;; + *) + echo >&2 "ERROR: invalid option -$OPTARG" + echo + usage 1 + ;; + esac +done + +# Remove processed options from arguments +shift $(( OPTIND - 1 )); + +if [ "${CMD:-}" == "" ]; then + echo >&2 "ERROR: no command given" + echo + usage 1 +elif [ "${ARCHIVE:-}" == "" ]; then + echo >&2 "ERROR: no archive name given" + echo + usage 1 +fi + +function list { + local path="" + local size=0 + local line_no=0 + local ttar_file=$1 + if [ -n "${2:-}" ]; then + echo >&2 "ERROR: too many arguments." + echo + usage 1 + fi + if [ ! -e "$ttar_file" ]; then + echo >&2 "ERROR: file not found ($ttar_file)" + echo + usage 1 + fi + while read -r line; do + line_no=$(( line_no + 1 )) + if [ $size -gt 0 ]; then + size=$(( size - 1 )) + continue + fi + if [[ $line =~ ^Path:\ (.*)$ ]]; then + path=${BASH_REMATCH[1]} + elif [[ $line =~ ^Lines:\ (.*)$ ]]; then + size=${BASH_REMATCH[1]} + echo "$path" + elif [[ $line =~ ^Directory:\ (.*)$ ]]; then + path=${BASH_REMATCH[1]} + echo "$path/" + elif [[ $line =~ ^SymlinkTo:\ (.*)$ ]]; then + echo "$path -> ${BASH_REMATCH[1]}" + fi + done < "$ttar_file" +} + +function extract { + local path="" + local size=0 + local line_no=0 + local ttar_file=$1 + if [ -n "${2:-}" ]; then + echo >&2 "ERROR: too many arguments." + echo + usage 1 + fi + if [ ! -e "$ttar_file" ]; then + echo >&2 "ERROR: file not found ($ttar_file)" + echo + usage 1 + fi + while IFS= read -r line; do + line_no=$(( line_no + 1 )) + local eof_without_newline + if [ "$size" -gt 0 ]; then + if [[ "$line" =~ [^\\]EOF ]]; then + # An EOF not preceeded by a backslash indicates that the line + # does not end with a newline + eof_without_newline=1 + else + eof_without_newline=0 + fi + # Replace NULLBYTE with null byte if at beginning of line + # Replace NULLBYTE with null byte unless preceeded by backslash + # Remove one backslash in front of NULLBYTE (if any) + # Remove EOF unless preceeded by backslash + # Remove one backslash in front of EOF + if [ $USE_PYTHON -eq 1 ]; then + echo -n "$line" | python -c "$PYTHON_EXTRACT_FILTER" >> "$path" + else + # The repeated pattern makes up for sed's lack of negative + # lookbehind assertions (for consecutive null bytes). + echo -n "$line" | \ + sed -e 's/^NULLBYTE/\x0/g; + s/\([^\\]\)NULLBYTE/\1\x0/g; + s/\([^\\]\)NULLBYTE/\1\x0/g; + s/\\NULLBYTE/NULLBYTE/g; + s/\([^\\]\)EOF/\1/g; + s/\\EOF/EOF/g; + ' >> "$path" + fi + if [[ "$eof_without_newline" -eq 0 ]]; then + echo >> "$path" + fi + size=$(( size - 1 )) + continue + fi + if [[ $line =~ ^Path:\ (.*)$ ]]; then + path=${BASH_REMATCH[1]} + if [ -e "$path" ] || [ -L "$path" ]; then + rm "$path" + fi + elif [[ $line =~ ^Lines:\ (.*)$ ]]; then + size=${BASH_REMATCH[1]} + # Create file even if it is zero-length. + touch "$path" + vecho " $path" + elif [[ $line =~ ^Mode:\ (.*)$ ]]; then + mode=${BASH_REMATCH[1]} + chmod "$mode" "$path" + vecho "$mode" + elif [[ $line =~ ^Directory:\ (.*)$ ]]; then + path=${BASH_REMATCH[1]} + mkdir -p "$path" + vecho " $path/" + elif [[ $line =~ ^SymlinkTo:\ (.*)$ ]]; then + ln -s "${BASH_REMATCH[1]}" "$path" + vecho " $path -> ${BASH_REMATCH[1]}" + elif [[ $line =~ ^# ]]; then + # Ignore comments between files + continue + else + echo >&2 "ERROR: Unknown keyword on line $line_no: $line" + exit 1 + fi + done < "$ttar_file" +} + +function div { + echo "# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" \ + "- - - - - -" +} + +function get_mode { + local mfile=$1 + if [ -z "${STAT_OPTION:-}" ]; then + if stat -c '%a' "$mfile" >/dev/null 2>&1; then + # GNU stat + STAT_OPTION='-c' + STAT_FORMAT='%a' + else + # BSD stat + STAT_OPTION='-f' + # Octal output, user/group/other (omit file type, sticky bit) + STAT_FORMAT='%OLp' + fi + fi + stat "${STAT_OPTION}" "${STAT_FORMAT}" "$mfile" +} + +function _create { + shopt -s nullglob + local mode + local eof_without_newline + while (( "$#" )); do + file=$1 + if [ -L "$file" ]; then + echo "Path: $file" + symlinkTo=$(readlink "$file") + echo "SymlinkTo: $symlinkTo" + vecho " $file -> $symlinkTo" + div + elif [ -d "$file" ]; then + # Strip trailing slash (if there is one) + file=${file%/} + echo "Directory: $file" + mode=$(get_mode "$file") + echo "Mode: $mode" + vecho "$mode $file/" + div + # Find all files and dirs, including hidden/dot files + for x in "$file/"{*,.[^.]*}; do + _create "$x" + done + elif [ -f "$file" ]; then + echo "Path: $file" + lines=$(wc -l "$file"|awk '{print $1}') + eof_without_newline=0 + if [[ "$(wc -c "$file"|awk '{print $1}')" -gt 0 ]] && \ + [[ "$(tail -c 1 "$file" | wc -l)" -eq 0 ]]; then + eof_without_newline=1 + lines=$((lines+1)) + fi + echo "Lines: $lines" + # Add backslash in front of EOF + # Add backslash in front of NULLBYTE + # Replace null byte with NULLBYTE + if [ $USE_PYTHON -eq 1 ]; then + < "$file" python -c "$PYTHON_CREATE_FILTER" + else + < "$file" \ + sed 's/EOF/\\EOF/g; + s/NULLBYTE/\\NULLBYTE/g; + s/\x0/NULLBYTE/g; + ' + fi + if [[ "$eof_without_newline" -eq 1 ]]; then + # Finish line with EOF to indicate that the original line did + # not end with a linefeed + echo "EOF" + fi + mode=$(get_mode "$file") + echo "Mode: $mode" + vecho "$mode $file" + div + else + echo >&2 "ERROR: file not found ($file in $(pwd))" + exit 2 + fi + shift + done +} + +function create { + ttar_file=$1 + shift + if [ -z "${1:-}" ]; then + echo >&2 "ERROR: missing arguments." + echo + usage 1 + fi + if [ -e "$ttar_file" ]; then + rm "$ttar_file" + fi + exec > "$ttar_file" + echo "# Archive created by ttar $ARG_STRING" + _create "$@" +} + +test_environment + +if [ -n "${CDIR:-}" ]; then + if [[ "$ARCHIVE" != /* ]]; then + # Relative path: preserve the archive's location before changing + # directory + ARCHIVE="$(pwd)/$ARCHIVE" + fi + cd "$CDIR" +fi + +"$CMD" "$ARCHIVE" "$@" diff --git a/vendor/github.com/prometheus/procfs/xfrm.go b/vendor/github.com/prometheus/procfs/xfrm.go index ffe9df50d..8f1508f0f 100644 --- a/vendor/github.com/prometheus/procfs/xfrm.go +++ b/vendor/github.com/prometheus/procfs/xfrm.go @@ -113,7 +113,7 @@ func (fs FS) NewXfrmStat() (XfrmStat, error) { if len(fields) != 2 { return XfrmStat{}, fmt.Errorf( - "couldnt parse %s line %s", file.Name(), s.Text()) + "couldn't parse %s line %s", file.Name(), s.Text()) } name := fields[0] diff --git a/vendor/github.com/prometheus/procfs/xfrm_test.go b/vendor/github.com/prometheus/procfs/xfrm_test.go deleted file mode 100644 index 5918c390e..000000000 --- a/vendor/github.com/prometheus/procfs/xfrm_test.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2017 Prometheus Team -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package procfs - -import ( - "testing" -) - -func TestXfrmStats(t *testing.T) { - xfrmStats, err := FS("fixtures").NewXfrmStat() - if err != nil { - t.Fatal(err) - } - - for _, test := range []struct { - name string - want int - got int - }{ - {name: "XfrmInError", want: 1, got: xfrmStats.XfrmInError}, - {name: "XfrmInBufferError", want: 2, got: xfrmStats.XfrmInBufferError}, - {name: "XfrmInHdrError", want: 4, got: xfrmStats.XfrmInHdrError}, - {name: "XfrmInNoStates", want: 3, got: xfrmStats.XfrmInNoStates}, - {name: "XfrmInStateProtoError", want: 40, got: xfrmStats.XfrmInStateProtoError}, - {name: "XfrmInStateModeError", want: 100, got: xfrmStats.XfrmInStateModeError}, - {name: "XfrmInStateSeqError", want: 6000, got: xfrmStats.XfrmInStateSeqError}, - {name: "XfrmInStateExpired", want: 4, got: xfrmStats.XfrmInStateExpired}, - {name: "XfrmInStateMismatch", want: 23451, got: xfrmStats.XfrmInStateMismatch}, - {name: "XfrmInStateInvalid", want: 55555, got: xfrmStats.XfrmInStateInvalid}, - {name: "XfrmInTmplMismatch", want: 51, got: xfrmStats.XfrmInTmplMismatch}, - {name: "XfrmInNoPols", want: 65432, got: xfrmStats.XfrmInNoPols}, - {name: "XfrmInPolBlock", want: 100, got: xfrmStats.XfrmInPolBlock}, - {name: "XfrmInPolError", want: 10000, got: xfrmStats.XfrmInPolError}, - {name: "XfrmOutError", want: 1000000, got: xfrmStats.XfrmOutError}, - {name: "XfrmOutBundleGenError", want: 43321, got: xfrmStats.XfrmOutBundleGenError}, - {name: "XfrmOutBundleCheckError", want: 555, got: xfrmStats.XfrmOutBundleCheckError}, - {name: "XfrmOutNoStates", want: 869, got: xfrmStats.XfrmOutNoStates}, - {name: "XfrmOutStateProtoError", want: 4542, got: xfrmStats.XfrmOutStateProtoError}, - {name: "XfrmOutStateModeError", want: 4, got: xfrmStats.XfrmOutStateModeError}, - {name: "XfrmOutStateSeqError", want: 543, got: xfrmStats.XfrmOutStateSeqError}, - {name: "XfrmOutStateExpired", want: 565, got: xfrmStats.XfrmOutStateExpired}, - {name: "XfrmOutPolBlock", want: 43456, got: xfrmStats.XfrmOutPolBlock}, - {name: "XfrmOutPolDead", want: 7656, got: xfrmStats.XfrmOutPolDead}, - {name: "XfrmOutPolError", want: 1454, got: xfrmStats.XfrmOutPolError}, - {name: "XfrmFwdHdrError", want: 6654, got: xfrmStats.XfrmFwdHdrError}, - {name: "XfrmOutStateInvaliad", want: 28765, got: xfrmStats.XfrmOutStateInvalid}, - {name: "XfrmAcquireError", want: 24532, got: xfrmStats.XfrmAcquireError}, - {name: "XfrmInStateInvalid", want: 55555, got: xfrmStats.XfrmInStateInvalid}, - {name: "XfrmOutError", want: 1000000, got: xfrmStats.XfrmOutError}, - } { - if test.want != test.got { - t.Errorf("Want %s %d, have %d", test.name, test.want, test.got) - } - } -} diff --git a/vendor/github.com/prometheus/procfs/xfs/parse.go b/vendor/github.com/prometheus/procfs/xfs/parse.go index c8f6279f3..2bc0ef342 100644 --- a/vendor/github.com/prometheus/procfs/xfs/parse.go +++ b/vendor/github.com/prometheus/procfs/xfs/parse.go @@ -17,8 +17,9 @@ import ( "bufio" "fmt" "io" - "strconv" "strings" + + "github.com/prometheus/procfs/internal/util" ) // ParseStats parses a Stats from an input io.Reader, using the format @@ -68,7 +69,7 @@ func ParseStats(r io.Reader) (*Stats, error) { // Extended precision counters are uint64 values. if label == fieldXpc { - us, err := parseUint64s(ss[1:]) + us, err := util.ParseUint64s(ss[1:]) if err != nil { return nil, err } @@ -82,7 +83,7 @@ func ParseStats(r io.Reader) (*Stats, error) { } // All other counters are uint32 values. - us, err := parseUint32s(ss[1:]) + us, err := util.ParseUint32s(ss[1:]) if err != nil { return nil, err } @@ -327,33 +328,3 @@ func extendedPrecisionStats(us []uint64) (ExtendedPrecisionStats, error) { ReadBytes: us[2], }, nil } - -// parseUint32s parses a slice of strings into a slice of uint32s. -func parseUint32s(ss []string) ([]uint32, error) { - us := make([]uint32, 0, len(ss)) - for _, s := range ss { - u, err := strconv.ParseUint(s, 10, 32) - if err != nil { - return nil, err - } - - us = append(us, uint32(u)) - } - - return us, nil -} - -// parseUint64s parses a slice of strings into a slice of uint64s. -func parseUint64s(ss []string) ([]uint64, error) { - us := make([]uint64, 0, len(ss)) - for _, s := range ss { - u, err := strconv.ParseUint(s, 10, 64) - if err != nil { - return nil, err - } - - us = append(us, u) - } - - return us, nil -} diff --git a/vendor/github.com/prometheus/procfs/xfs/parse_test.go b/vendor/github.com/prometheus/procfs/xfs/parse_test.go deleted file mode 100644 index 2e946c2c5..000000000 --- a/vendor/github.com/prometheus/procfs/xfs/parse_test.go +++ /dev/null @@ -1,442 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package xfs_test - -import ( - "reflect" - "strings" - "testing" - - "github.com/prometheus/procfs" - "github.com/prometheus/procfs/xfs" -) - -func TestParseStats(t *testing.T) { - tests := []struct { - name string - s string - fs bool - stats *xfs.Stats - invalid bool - }{ - { - name: "empty file OK", - }, - { - name: "short or empty lines and unknown labels ignored", - s: "one\n\ntwo 1 2 3\n", - stats: &xfs.Stats{}, - }, - { - name: "bad uint32", - s: "extent_alloc XXX", - invalid: true, - }, - { - name: "bad uint64", - s: "xpc XXX", - invalid: true, - }, - { - name: "extent_alloc bad", - s: "extent_alloc 1", - invalid: true, - }, - { - name: "extent_alloc OK", - s: "extent_alloc 1 2 3 4", - stats: &xfs.Stats{ - ExtentAllocation: xfs.ExtentAllocationStats{ - ExtentsAllocated: 1, - BlocksAllocated: 2, - ExtentsFreed: 3, - BlocksFreed: 4, - }, - }, - }, - { - name: "abt bad", - s: "abt 1", - invalid: true, - }, - { - name: "abt OK", - s: "abt 1 2 3 4", - stats: &xfs.Stats{ - AllocationBTree: xfs.BTreeStats{ - Lookups: 1, - Compares: 2, - RecordsInserted: 3, - RecordsDeleted: 4, - }, - }, - }, - { - name: "blk_map bad", - s: "blk_map 1", - invalid: true, - }, - { - name: "blk_map OK", - s: "blk_map 1 2 3 4 5 6 7", - stats: &xfs.Stats{ - BlockMapping: xfs.BlockMappingStats{ - Reads: 1, - Writes: 2, - Unmaps: 3, - ExtentListInsertions: 4, - ExtentListDeletions: 5, - ExtentListLookups: 6, - ExtentListCompares: 7, - }, - }, - }, - { - name: "bmbt bad", - s: "bmbt 1", - invalid: true, - }, - { - name: "bmbt OK", - s: "bmbt 1 2 3 4", - stats: &xfs.Stats{ - BlockMapBTree: xfs.BTreeStats{ - Lookups: 1, - Compares: 2, - RecordsInserted: 3, - RecordsDeleted: 4, - }, - }, - }, - { - name: "dir bad", - s: "dir 1", - invalid: true, - }, - { - name: "dir OK", - s: "dir 1 2 3 4", - stats: &xfs.Stats{ - DirectoryOperation: xfs.DirectoryOperationStats{ - Lookups: 1, - Creates: 2, - Removes: 3, - Getdents: 4, - }, - }, - }, - { - name: "trans bad", - s: "trans 1", - invalid: true, - }, - { - name: "trans OK", - s: "trans 1 2 3", - stats: &xfs.Stats{ - Transaction: xfs.TransactionStats{ - Sync: 1, - Async: 2, - Empty: 3, - }, - }, - }, - { - name: "ig bad", - s: "ig 1", - invalid: true, - }, - { - name: "ig OK", - s: "ig 1 2 3 4 5 6 7", - stats: &xfs.Stats{ - InodeOperation: xfs.InodeOperationStats{ - Attempts: 1, - Found: 2, - Recycle: 3, - Missed: 4, - Duplicate: 5, - Reclaims: 6, - AttributeChange: 7, - }, - }, - }, - { - name: "log bad", - s: "log 1", - invalid: true, - }, - { - name: "log OK", - s: "log 1 2 3 4 5", - stats: &xfs.Stats{ - LogOperation: xfs.LogOperationStats{ - Writes: 1, - Blocks: 2, - NoInternalBuffers: 3, - Force: 4, - ForceSleep: 5, - }, - }, - }, - { - name: "rw bad", - s: "rw 1", - invalid: true, - }, - { - name: "rw OK", - s: "rw 1 2", - stats: &xfs.Stats{ - ReadWrite: xfs.ReadWriteStats{ - Read: 1, - Write: 2, - }, - }, - }, - { - name: "attr bad", - s: "attr 1", - invalid: true, - }, - { - name: "attr OK", - s: "attr 1 2 3 4", - stats: &xfs.Stats{ - AttributeOperation: xfs.AttributeOperationStats{ - Get: 1, - Set: 2, - Remove: 3, - List: 4, - }, - }, - }, - { - name: "icluster bad", - s: "icluster 1", - invalid: true, - }, - { - name: "icluster OK", - s: "icluster 1 2 3", - stats: &xfs.Stats{ - InodeClustering: xfs.InodeClusteringStats{ - Iflush: 1, - Flush: 2, - FlushInode: 3, - }, - }, - }, - { - name: "vnodes bad", - s: "vnodes 1", - invalid: true, - }, - { - name: "vnodes (missing free) OK", - s: "vnodes 1 2 3 4 5 6 7", - stats: &xfs.Stats{ - Vnode: xfs.VnodeStats{ - Active: 1, - Allocate: 2, - Get: 3, - Hold: 4, - Release: 5, - Reclaim: 6, - Remove: 7, - }, - }, - }, - { - name: "vnodes (with free) OK", - s: "vnodes 1 2 3 4 5 6 7 8", - stats: &xfs.Stats{ - Vnode: xfs.VnodeStats{ - Active: 1, - Allocate: 2, - Get: 3, - Hold: 4, - Release: 5, - Reclaim: 6, - Remove: 7, - Free: 8, - }, - }, - }, - { - name: "buf bad", - s: "buf 1", - invalid: true, - }, - { - name: "buf OK", - s: "buf 1 2 3 4 5 6 7 8 9", - stats: &xfs.Stats{ - Buffer: xfs.BufferStats{ - Get: 1, - Create: 2, - GetLocked: 3, - GetLockedWaited: 4, - BusyLocked: 5, - MissLocked: 6, - PageRetries: 7, - PageFound: 8, - GetRead: 9, - }, - }, - }, - { - name: "xpc bad", - s: "xpc 1", - invalid: true, - }, - { - name: "xpc OK", - s: "xpc 1 2 3", - stats: &xfs.Stats{ - ExtendedPrecision: xfs.ExtendedPrecisionStats{ - FlushBytes: 1, - WriteBytes: 2, - ReadBytes: 3, - }, - }, - }, - { - name: "fixtures OK", - fs: true, - stats: &xfs.Stats{ - ExtentAllocation: xfs.ExtentAllocationStats{ - ExtentsAllocated: 92447, - BlocksAllocated: 97589, - ExtentsFreed: 92448, - BlocksFreed: 93751, - }, - AllocationBTree: xfs.BTreeStats{ - Lookups: 0, - Compares: 0, - RecordsInserted: 0, - RecordsDeleted: 0, - }, - BlockMapping: xfs.BlockMappingStats{ - Reads: 1767055, - Writes: 188820, - Unmaps: 184891, - ExtentListInsertions: 92447, - ExtentListDeletions: 92448, - ExtentListLookups: 2140766, - ExtentListCompares: 0, - }, - BlockMapBTree: xfs.BTreeStats{ - Lookups: 0, - Compares: 0, - RecordsInserted: 0, - RecordsDeleted: 0, - }, - DirectoryOperation: xfs.DirectoryOperationStats{ - Lookups: 185039, - Creates: 92447, - Removes: 92444, - Getdents: 136422, - }, - Transaction: xfs.TransactionStats{ - Sync: 706, - Async: 944304, - Empty: 0, - }, - InodeOperation: xfs.InodeOperationStats{ - Attempts: 185045, - Found: 58807, - Recycle: 0, - Missed: 126238, - Duplicate: 0, - Reclaims: 33637, - AttributeChange: 22, - }, - LogOperation: xfs.LogOperationStats{ - Writes: 2883, - Blocks: 113448, - NoInternalBuffers: 9, - Force: 17360, - ForceSleep: 739, - }, - ReadWrite: xfs.ReadWriteStats{ - Read: 107739, - Write: 94045, - }, - AttributeOperation: xfs.AttributeOperationStats{ - Get: 4, - Set: 0, - Remove: 0, - List: 0, - }, - InodeClustering: xfs.InodeClusteringStats{ - Iflush: 8677, - Flush: 7849, - FlushInode: 135802, - }, - Vnode: xfs.VnodeStats{ - Active: 92601, - Allocate: 0, - Get: 0, - Hold: 0, - Release: 92444, - Reclaim: 92444, - Remove: 92444, - Free: 0, - }, - Buffer: xfs.BufferStats{ - Get: 2666287, - Create: 7122, - GetLocked: 2659202, - GetLockedWaited: 3599, - BusyLocked: 2, - MissLocked: 7085, - PageRetries: 0, - PageFound: 10297, - GetRead: 7085, - }, - ExtendedPrecision: xfs.ExtendedPrecisionStats{ - FlushBytes: 399724544, - WriteBytes: 92823103, - ReadBytes: 86219234, - }, - }, - }, - } - - for _, tt := range tests { - var ( - stats *xfs.Stats - err error - ) - - if tt.s != "" { - stats, err = xfs.ParseStats(strings.NewReader(tt.s)) - } - if tt.fs { - stats, err = procfs.FS("../fixtures").XFSStats() - } - - if tt.invalid && err == nil { - t.Error("expected an error, but none occurred") - } - if !tt.invalid && err != nil { - t.Errorf("unexpected error: %v", err) - } - - if want, have := tt.stats, stats; !reflect.DeepEqual(want, have) { - t.Errorf("unexpected XFS stats:\nwant:\n%v\nhave:\n%v", want, have) - } - } -} diff --git a/vendor/github.com/prometheus/prometheus/pkg/labels/matcher_test.go b/vendor/github.com/prometheus/prometheus/pkg/labels/matcher_test.go deleted file mode 100644 index dfedf8d84..000000000 --- a/vendor/github.com/prometheus/prometheus/pkg/labels/matcher_test.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package labels - -import "testing" - -func mustNewMatcher(t *testing.T, mType MatchType, value string) *Matcher { - m, err := NewMatcher(mType, "", value) - if err != nil { - t.Fatal(err) - } - return m -} - -func TestMatcher(t *testing.T) { - tests := []struct { - matcher *Matcher - value string - match bool - }{ - { - matcher: mustNewMatcher(t, MatchEqual, "bar"), - value: "bar", - match: true, - }, - { - matcher: mustNewMatcher(t, MatchEqual, "bar"), - value: "foo-bar", - match: false, - }, - { - matcher: mustNewMatcher(t, MatchNotEqual, "bar"), - value: "bar", - match: false, - }, - { - matcher: mustNewMatcher(t, MatchNotEqual, "bar"), - value: "foo-bar", - match: true, - }, - { - matcher: mustNewMatcher(t, MatchRegexp, "bar"), - value: "bar", - match: true, - }, - { - matcher: mustNewMatcher(t, MatchRegexp, "bar"), - value: "foo-bar", - match: false, - }, - { - matcher: mustNewMatcher(t, MatchRegexp, ".*bar"), - value: "foo-bar", - match: true, - }, - { - matcher: mustNewMatcher(t, MatchNotRegexp, "bar"), - value: "bar", - match: false, - }, - { - matcher: mustNewMatcher(t, MatchNotRegexp, "bar"), - value: "foo-bar", - match: true, - }, - { - matcher: mustNewMatcher(t, MatchNotRegexp, ".*bar"), - value: "foo-bar", - match: false, - }, - } - - for _, test := range tests { - if test.matcher.Matches(test.value) != test.match { - t.Fatalf("Unexpected match result for matcher %v and value %q; want %v, got %v", test.matcher, test.value, test.match, !test.match) - } - } -} diff --git a/vendor/github.com/prometheus/prometheus/pkg/textparse/openmetricsparse_test.go b/vendor/github.com/prometheus/prometheus/pkg/textparse/openmetricsparse_test.go deleted file mode 100644 index aad307b1d..000000000 --- a/vendor/github.com/prometheus/prometheus/pkg/textparse/openmetricsparse_test.go +++ /dev/null @@ -1,440 +0,0 @@ -// Copyright 2017 The OMetheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package textparse - -import ( - "io" - "testing" - - "github.com/prometheus/prometheus/pkg/labels" - "github.com/stretchr/testify/require" -) - -func TestOpenMetricsParse(t *testing.T) { - input := `# HELP go_gc_duration_seconds A summary of the GC invocation durations. -# TYPE go_gc_duration_seconds summary -# UNIT go_gc_duration_seconds seconds -go_gc_duration_seconds{quantile="0"} 4.9351e-05 -go_gc_duration_seconds{quantile="0.25"} 7.424100000000001e-05 -go_gc_duration_seconds{quantile="0.5",a="b"} 8.3835e-05 -# HELP nohelp1 -# HELP help2 escape \ \n \\ \" \x chars -# UNIT nounit -go_gc_duration_seconds{quantile="1.0",a="b"} 8.3835e-05 -go_gc_duration_seconds_count 99 -some:aggregate:rate5m{a_b="c"} 1 -# HELP go_goroutines Number of goroutines that currently exist. -# TYPE go_goroutines gauge -go_goroutines 33 123.123 -# TYPE hh histogram -hh_bucket{le="+Inf"} 1 # {} 4 -# TYPE gh gaugehistogram -gh_bucket{le="+Inf"} 1 # {} 4 -# TYPE ii info -ii{foo="bar"} 1 -# TYPE ss stateset -ss{ss="foo"} 1 -ss{ss="bar"} 0 -# TYPE un unknown -_metric_starting_with_underscore 1 -testmetric{_label_starting_with_underscore="foo"} 1 -testmetric{label="\"bar\""} 1` - - input += "\n# HELP metric foo\x00bar" - input += "\nnull_byte_metric{a=\"abc\x00\"} 1" - input += "\n# EOF\n" - - int64p := func(x int64) *int64 { return &x } - - exp := []struct { - lset labels.Labels - m string - t *int64 - v float64 - typ MetricType - help string - unit string - comment string - }{ - { - m: "go_gc_duration_seconds", - help: "A summary of the GC invocation durations.", - }, { - m: "go_gc_duration_seconds", - typ: MetricTypeSummary, - }, { - m: "go_gc_duration_seconds", - unit: "seconds", - }, { - m: `go_gc_duration_seconds{quantile="0"}`, - v: 4.9351e-05, - lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "0"), - }, { - m: `go_gc_duration_seconds{quantile="0.25"}`, - v: 7.424100000000001e-05, - lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "0.25"), - }, { - m: `go_gc_duration_seconds{quantile="0.5",a="b"}`, - v: 8.3835e-05, - lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "0.5", "a", "b"), - }, { - m: "nohelp1", - help: "", - }, { - m: "help2", - help: "escape \\ \n \\ \" \\x chars", - }, { - m: "nounit", - unit: "", - }, { - m: `go_gc_duration_seconds{quantile="1.0",a="b"}`, - v: 8.3835e-05, - lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "1.0", "a", "b"), - }, { - m: `go_gc_duration_seconds_count`, - v: 99, - lset: labels.FromStrings("__name__", "go_gc_duration_seconds_count"), - }, { - m: `some:aggregate:rate5m{a_b="c"}`, - v: 1, - lset: labels.FromStrings("__name__", "some:aggregate:rate5m", "a_b", "c"), - }, { - m: "go_goroutines", - help: "Number of goroutines that currently exist.", - }, { - m: "go_goroutines", - typ: MetricTypeGauge, - }, { - m: `go_goroutines`, - v: 33, - t: int64p(123123), - lset: labels.FromStrings("__name__", "go_goroutines"), - }, { - m: "hh", - typ: MetricTypeHistogram, - }, { - m: `hh_bucket{le="+Inf"}`, - v: 1, - lset: labels.FromStrings("__name__", "hh_bucket", "le", "+Inf"), - }, { - m: "gh", - typ: MetricTypeGaugeHistogram, - }, { - m: `gh_bucket{le="+Inf"}`, - v: 1, - lset: labels.FromStrings("__name__", "gh_bucket", "le", "+Inf"), - }, { - m: "ii", - typ: MetricTypeInfo, - }, { - m: `ii{foo="bar"}`, - v: 1, - lset: labels.FromStrings("__name__", "ii", "foo", "bar"), - }, { - m: "ss", - typ: MetricTypeStateset, - }, { - m: `ss{ss="foo"}`, - v: 1, - lset: labels.FromStrings("__name__", "ss", "ss", "foo"), - }, { - m: `ss{ss="bar"}`, - v: 0, - lset: labels.FromStrings("__name__", "ss", "ss", "bar"), - }, { - m: "un", - typ: MetricTypeUnknown, - }, { - m: "_metric_starting_with_underscore", - v: 1, - lset: labels.FromStrings("__name__", "_metric_starting_with_underscore"), - }, { - m: "testmetric{_label_starting_with_underscore=\"foo\"}", - v: 1, - lset: labels.FromStrings("__name__", "testmetric", "_label_starting_with_underscore", "foo"), - }, { - m: "testmetric{label=\"\\\"bar\\\"\"}", - v: 1, - lset: labels.FromStrings("__name__", "testmetric", "label", `"bar"`), - }, { - m: "metric", - help: "foo\x00bar", - }, { - m: "null_byte_metric{a=\"abc\x00\"}", - v: 1, - lset: labels.FromStrings("__name__", "null_byte_metric", "a", "abc\x00"), - }, - } - - p := NewOpenMetricsParser([]byte(input)) - i := 0 - - var res labels.Labels - - for { - et, err := p.Next() - if err == io.EOF { - break - } - require.NoError(t, err) - - switch et { - case EntrySeries: - m, ts, v := p.Series() - - p.Metric(&res) - - require.Equal(t, exp[i].m, string(m)) - require.Equal(t, exp[i].t, ts) - require.Equal(t, exp[i].v, v) - require.Equal(t, exp[i].lset, res) - res = res[:0] - - case EntryType: - m, typ := p.Type() - require.Equal(t, exp[i].m, string(m)) - require.Equal(t, exp[i].typ, typ) - - case EntryHelp: - m, h := p.Help() - require.Equal(t, exp[i].m, string(m)) - require.Equal(t, exp[i].help, string(h)) - - case EntryUnit: - m, u := p.Unit() - require.Equal(t, exp[i].m, string(m)) - require.Equal(t, exp[i].unit, string(u)) - - case EntryComment: - require.Equal(t, exp[i].comment, string(p.Comment())) - } - - i++ - } - require.Equal(t, len(exp), i) -} - -func TestOpenMetricsParseErrors(t *testing.T) { - cases := []struct { - input string - err string - }{ - { - input: "", - err: "unexpected end of data, got \"EOF\"", - }, - { - input: "a", - err: "expected value after metric, got \"MNAME\"", - }, - { - input: "\n", - err: "\"INVALID\" \"\\n\" is not a valid start token", - }, - { - input: " a 1\n", - err: "\"INVALID\" \" \" is not a valid start token", - }, - { - input: "9\n", - err: "\"INVALID\" \"9\" is not a valid start token", - }, - { - input: "# TYPE u untyped\n", - err: "invalid metric type \"untyped\"", - }, - { - input: "# TYPE c counter \n", - err: "invalid metric type \"counter \"", - }, - { - input: "# TYPE c counter\n", - err: "\"INVALID\" \" \" is not a valid start token", - }, - { - input: "# UNIT metric suffix\n", - err: "unit not a suffix of metric \"metric\"", - }, - { - input: "# UNIT metricsuffix suffix\n", - err: "unit not a suffix of metric \"metricsuffix\"", - }, - { - input: "# UNIT m suffix\n", - err: "unit not a suffix of metric \"m\"", - }, - { - input: "# HELP m\n", - err: "expected text in HELP, got \"INVALID\"", - }, - { - input: "a\t1\n", - err: "expected value after metric, got \"MNAME\"", - }, - { - input: "a 1\t2\n", - err: "strconv.ParseFloat: parsing \"1\\t2\": invalid syntax", - }, - { - input: "a 1 2 \n", - err: "expected next entry after timestamp, got \"MNAME\"", - }, - { - input: "a 1 2 #\n", - err: "expected next entry after timestamp, got \"MNAME\"", - }, - { - input: "a 1 1z\n", - err: "strconv.ParseFloat: parsing \"1z\": invalid syntax", - }, - { - input: " # EOF\n", - err: "\"INVALID\" \" \" is not a valid start token", - }, - { - input: "# EOF\na 1", - err: "unexpected data after # EOF", - }, - { - input: "# EOF\n\n", - err: "unexpected data after # EOF", - }, - { - input: "# EOFa 1", - err: "unexpected data after # EOF", - }, - { - input: "#\tTYPE c counter\n", - err: "\"INVALID\" \"\\t\" is not a valid start token", - }, - { - input: "# TYPE c counter\n", - err: "invalid metric type \" counter\"", - }, - { - input: "a 1 1 1\n", - err: "expected next entry after timestamp, got \"MNAME\"", - }, - { - input: "a{b='c'} 1\n", - err: "expected label value, got \"INVALID\"", - }, - { - input: "a{b=\"c\",} 1\n", - err: "expected label name, got \"BCLOSE\"", - }, - { - input: "a{,b=\"c\"} 1\n", - err: "expected label name or left brace, got \"COMMA\"", - }, - { - input: "a{b=\"c\"d=\"e\"} 1\n", - err: "expected comma, got \"LNAME\"", - }, - { - input: "a{b=\"c\",,d=\"e\"} 1\n", - err: "expected label name, got \"COMMA\"", - }, - { - input: "a{b=\n", - err: "expected label value, got \"INVALID\"", - }, - { - input: "a{\xff=\"foo\"} 1\n", - err: "expected label name or left brace, got \"INVALID\"", - }, - { - input: "a{b=\"\xff\"} 1\n", - err: "invalid UTF-8 label value", - }, - { - input: "a true\n", - err: "strconv.ParseFloat: parsing \"true\": invalid syntax", - }, - { - input: "something_weird{problem=\"", - err: "expected label value, got \"INVALID\"", - }, - { - input: "empty_label_name{=\"\"} 0", - err: "expected label name or left brace, got \"EQUAL\"", - }, - } - - for i, c := range cases { - p := NewOpenMetricsParser([]byte(c.input)) - var err error - for err == nil { - _, err = p.Next() - } - require.NotNil(t, err) - require.Equal(t, c.err, err.Error(), "test %d", i) - } -} - -func TestOMNullByteHandling(t *testing.T) { - cases := []struct { - input string - err string - }{ - { - input: "null_byte_metric{a=\"abc\x00\"} 1\n# EOF\n", - err: "", - }, - { - input: "a{b=\"\x00ss\"} 1\n# EOF\n", - err: "", - }, - { - input: "a{b=\"\x00\"} 1\n# EOF\n", - err: "", - }, - { - input: "a{b=\"\x00\"} 1\n# EOF", - err: "", - }, - { - input: "a{b=\x00\"ssss\"} 1\n# EOF\n", - err: "expected label value, got \"INVALID\"", - }, - { - input: "a{b=\"\x00", - err: "expected label value, got \"INVALID\"", - }, - { - input: "a{b\x00=\"hiih\"} 1", - err: "expected equal, got \"INVALID\"", - }, - { - input: "a\x00{b=\"ddd\"} 1", - err: "expected value after metric, got \"MNAME\"", - }, - } - - for i, c := range cases { - p := NewOpenMetricsParser([]byte(c.input)) - var err error - for err == nil { - _, err = p.Next() - } - - if c.err == "" { - require.Equal(t, io.EOF, err, "test %d", i) - continue - } - - require.Error(t, err) - require.Equal(t, c.err, err.Error(), "test %d", i) - } -} diff --git a/vendor/github.com/prometheus/prometheus/pkg/textparse/promparse_test.go b/vendor/github.com/prometheus/prometheus/pkg/textparse/promparse_test.go deleted file mode 100644 index b090fb5fc..000000000 --- a/vendor/github.com/prometheus/prometheus/pkg/textparse/promparse_test.go +++ /dev/null @@ -1,496 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package textparse - -import ( - "bytes" - "compress/gzip" - "io" - "io/ioutil" - "os" - "testing" - - "github.com/prometheus/common/expfmt" - "github.com/prometheus/common/model" - "github.com/prometheus/prometheus/pkg/labels" - "github.com/stretchr/testify/require" -) - -func TestPromParse(t *testing.T) { - input := `# HELP go_gc_duration_seconds A summary of the GC invocation durations. -# TYPE go_gc_duration_seconds summary -go_gc_duration_seconds{quantile="0"} 4.9351e-05 -go_gc_duration_seconds{quantile="0.25",} 7.424100000000001e-05 -go_gc_duration_seconds{quantile="0.5",a="b"} 8.3835e-05 -go_gc_duration_seconds{quantile="0.8", a="b"} 8.3835e-05 -go_gc_duration_seconds{ quantile="0.9", a="b"} 8.3835e-05 -# Hrandom comment starting with prefix of HELP -# -# comment with escaped \n newline -# comment with escaped \ escape character -# HELP nohelp1 -# HELP nohelp2 -go_gc_duration_seconds{ quantile="1.0", a="b" } 8.3835e-05 -go_gc_duration_seconds { quantile="1.0", a="b" } 8.3835e-05 -go_gc_duration_seconds { quantile= "1.0", a= "b", } 8.3835e-05 -go_gc_duration_seconds { quantile = "1.0", a = "b" } 8.3835e-05 -go_gc_duration_seconds_count 99 -some:aggregate:rate5m{a_b="c"} 1 -# HELP go_goroutines Number of goroutines that currently exist. -# TYPE go_goroutines gauge -go_goroutines 33 123123 -_metric_starting_with_underscore 1 -testmetric{_label_starting_with_underscore="foo"} 1 -testmetric{label="\"bar\""} 1` - input += "\n# HELP metric foo\x00bar" - input += "\nnull_byte_metric{a=\"abc\x00\"} 1" - - int64p := func(x int64) *int64 { return &x } - - exp := []struct { - lset labels.Labels - m string - t *int64 - v float64 - typ MetricType - help string - comment string - }{ - { - m: "go_gc_duration_seconds", - help: "A summary of the GC invocation durations.", - }, { - m: "go_gc_duration_seconds", - typ: MetricTypeSummary, - }, { - m: `go_gc_duration_seconds{quantile="0"}`, - v: 4.9351e-05, - lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "0"), - }, { - m: `go_gc_duration_seconds{quantile="0.25",}`, - v: 7.424100000000001e-05, - lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "0.25"), - }, { - m: `go_gc_duration_seconds{quantile="0.5",a="b"}`, - v: 8.3835e-05, - lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "0.5", "a", "b"), - }, { - m: `go_gc_duration_seconds{quantile="0.8", a="b"}`, - v: 8.3835e-05, - lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "0.8", "a", "b"), - }, { - m: `go_gc_duration_seconds{ quantile="0.9", a="b"}`, - v: 8.3835e-05, - lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "0.9", "a", "b"), - }, { - comment: "# Hrandom comment starting with prefix of HELP", - }, { - comment: "#", - }, { - comment: "# comment with escaped \\n newline", - }, { - comment: "# comment with escaped \\ escape character", - }, { - m: "nohelp1", - help: "", - }, { - m: "nohelp2", - help: "", - }, { - m: `go_gc_duration_seconds{ quantile="1.0", a="b" }`, - v: 8.3835e-05, - lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "1.0", "a", "b"), - }, { - m: `go_gc_duration_seconds { quantile="1.0", a="b" }`, - v: 8.3835e-05, - lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "1.0", "a", "b"), - }, { - m: `go_gc_duration_seconds { quantile= "1.0", a= "b", }`, - v: 8.3835e-05, - lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "1.0", "a", "b"), - }, { - m: `go_gc_duration_seconds { quantile = "1.0", a = "b" }`, - v: 8.3835e-05, - lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "1.0", "a", "b"), - }, { - m: `go_gc_duration_seconds_count`, - v: 99, - lset: labels.FromStrings("__name__", "go_gc_duration_seconds_count"), - }, { - m: `some:aggregate:rate5m{a_b="c"}`, - v: 1, - lset: labels.FromStrings("__name__", "some:aggregate:rate5m", "a_b", "c"), - }, { - m: "go_goroutines", - help: "Number of goroutines that currently exist.", - }, { - m: "go_goroutines", - typ: MetricTypeGauge, - }, { - m: `go_goroutines`, - v: 33, - t: int64p(123123), - lset: labels.FromStrings("__name__", "go_goroutines"), - }, { - m: "_metric_starting_with_underscore", - v: 1, - lset: labels.FromStrings("__name__", "_metric_starting_with_underscore"), - }, { - m: "testmetric{_label_starting_with_underscore=\"foo\"}", - v: 1, - lset: labels.FromStrings("__name__", "testmetric", "_label_starting_with_underscore", "foo"), - }, { - m: "testmetric{label=\"\\\"bar\\\"\"}", - v: 1, - lset: labels.FromStrings("__name__", "testmetric", "label", `"bar"`), - }, { - m: "metric", - help: "foo\x00bar", - }, { - m: "null_byte_metric{a=\"abc\x00\"}", - v: 1, - lset: labels.FromStrings("__name__", "null_byte_metric", "a", "abc\x00"), - }, - } - - p := NewPromParser([]byte(input)) - i := 0 - - var res labels.Labels - - for { - et, err := p.Next() - if err == io.EOF { - break - } - require.NoError(t, err) - - switch et { - case EntrySeries: - m, ts, v := p.Series() - - p.Metric(&res) - - require.Equal(t, exp[i].m, string(m)) - require.Equal(t, exp[i].t, ts) - require.Equal(t, exp[i].v, v) - require.Equal(t, exp[i].lset, res) - res = res[:0] - - case EntryType: - m, typ := p.Type() - require.Equal(t, exp[i].m, string(m)) - require.Equal(t, exp[i].typ, typ) - - case EntryHelp: - m, h := p.Help() - require.Equal(t, exp[i].m, string(m)) - require.Equal(t, exp[i].help, string(h)) - - case EntryComment: - require.Equal(t, exp[i].comment, string(p.Comment())) - } - - i++ - } - require.Equal(t, len(exp), i) -} - -func TestPromParseErrors(t *testing.T) { - cases := []struct { - input string - err string - }{ - { - input: "a", - err: "expected value after metric, got \"MNAME\"", - }, - { - input: "a{b='c'} 1\n", - err: "expected label value, got \"INVALID\"", - }, - { - input: "a{b=\n", - err: "expected label value, got \"INVALID\"", - }, - { - input: "a{\xff=\"foo\"} 1\n", - err: "expected label name, got \"INVALID\"", - }, - { - input: "a{b=\"\xff\"} 1\n", - err: "invalid UTF-8 label value", - }, - { - input: "a true\n", - err: "strconv.ParseFloat: parsing \"true\": invalid syntax", - }, - { - input: "something_weird{problem=\"", - err: "expected label value, got \"INVALID\"", - }, - { - input: "empty_label_name{=\"\"} 0", - err: "expected label name, got \"EQUAL\"", - }, - } - - for i, c := range cases { - p := NewPromParser([]byte(c.input)) - var err error - for err == nil { - _, err = p.Next() - } - require.NotNil(t, err) - require.Equal(t, c.err, err.Error(), "test %d", i) - } -} - -func TestPromNullByteHandling(t *testing.T) { - cases := []struct { - input string - err string - }{ - { - input: "null_byte_metric{a=\"abc\x00\"} 1", - err: "", - }, - { - input: "a{b=\"\x00ss\"} 1\n", - err: "", - }, - { - input: "a{b=\"\x00\"} 1\n", - err: "", - }, - { - input: "a{b=\"\x00\"} 1\n", - err: "", - }, - { - input: "a{b=\x00\"ssss\"} 1\n", - err: "expected label value, got \"INVALID\"", - }, - { - input: "a{b=\"\x00", - err: "expected label value, got \"INVALID\"", - }, - { - input: "a{b\x00=\"hiih\"} 1", - err: "expected equal, got \"INVALID\"", - }, - { - input: "a\x00{b=\"ddd\"} 1", - err: "expected value after metric, got \"MNAME\"", - }, - } - - for i, c := range cases { - p := NewPromParser([]byte(c.input)) - var err error - for err == nil { - _, err = p.Next() - } - - if c.err == "" { - require.Equal(t, io.EOF, err, "test %d", i) - continue - } - - require.Error(t, err) - require.Equal(t, c.err, err.Error(), "test %d", i) - } -} - -const ( - promtestdataSampleCount = 410 -) - -func BenchmarkParse(b *testing.B) { - for parserName, parser := range map[string]func([]byte) Parser{ - "prometheus": NewPromParser, - "openmetrics": NewOpenMetricsParser, - } { - - for _, fn := range []string{"promtestdata.txt", "promtestdata.nometa.txt"} { - f, err := os.Open(fn) - require.NoError(b, err) - defer f.Close() - - buf, err := ioutil.ReadAll(f) - require.NoError(b, err) - - b.Run(parserName+"/no-decode-metric/"+fn, func(b *testing.B) { - total := 0 - - b.SetBytes(int64(len(buf) * (b.N / promtestdataSampleCount))) - b.ReportAllocs() - b.ResetTimer() - - for i := 0; i < b.N; i += promtestdataSampleCount { - p := parser(buf) - - Outer: - for i < b.N { - t, err := p.Next() - switch t { - case EntryInvalid: - if err == io.EOF { - break Outer - } - b.Fatal(err) - case EntrySeries: - m, _, _ := p.Series() - total += len(m) - i++ - } - } - } - _ = total - }) - b.Run(parserName+"/decode-metric/"+fn, func(b *testing.B) { - total := 0 - - b.SetBytes(int64(len(buf) * (b.N / promtestdataSampleCount))) - b.ReportAllocs() - b.ResetTimer() - - for i := 0; i < b.N; i += promtestdataSampleCount { - p := parser(buf) - - Outer: - for i < b.N { - t, err := p.Next() - switch t { - case EntryInvalid: - if err == io.EOF { - break Outer - } - b.Fatal(err) - case EntrySeries: - m, _, _ := p.Series() - - res := make(labels.Labels, 0, 5) - p.Metric(&res) - - total += len(m) - i++ - } - } - } - _ = total - }) - b.Run(parserName+"/decode-metric-reuse/"+fn, func(b *testing.B) { - total := 0 - res := make(labels.Labels, 0, 5) - - b.SetBytes(int64(len(buf) * (b.N / promtestdataSampleCount))) - b.ReportAllocs() - b.ResetTimer() - - for i := 0; i < b.N; i += promtestdataSampleCount { - p := parser(buf) - - Outer: - for i < b.N { - t, err := p.Next() - switch t { - case EntryInvalid: - if err == io.EOF { - break Outer - } - b.Fatal(err) - case EntrySeries: - m, _, _ := p.Series() - - p.Metric(&res) - - total += len(m) - i++ - res = res[:0] - } - } - } - _ = total - }) - b.Run("expfmt-text/"+fn, func(b *testing.B) { - b.SetBytes(int64(len(buf) * (b.N / promtestdataSampleCount))) - b.ReportAllocs() - b.ResetTimer() - - total := 0 - - for i := 0; i < b.N; i += promtestdataSampleCount { - var ( - decSamples = make(model.Vector, 0, 50) - ) - sdec := expfmt.SampleDecoder{ - Dec: expfmt.NewDecoder(bytes.NewReader(buf), expfmt.FmtText), - Opts: &expfmt.DecodeOptions{ - Timestamp: model.TimeFromUnixNano(0), - }, - } - - for { - if err = sdec.Decode(&decSamples); err != nil { - break - } - total += len(decSamples) - decSamples = decSamples[:0] - } - } - _ = total - }) - } - } -} -func BenchmarkGzip(b *testing.B) { - for _, fn := range []string{"promtestdata.txt", "promtestdata.nometa.txt"} { - b.Run(fn, func(b *testing.B) { - f, err := os.Open(fn) - require.NoError(b, err) - defer f.Close() - - var buf bytes.Buffer - gw := gzip.NewWriter(&buf) - - n, err := io.Copy(gw, f) - require.NoError(b, err) - require.NoError(b, gw.Close()) - - gbuf, err := ioutil.ReadAll(&buf) - require.NoError(b, err) - - k := b.N / promtestdataSampleCount - - b.ReportAllocs() - b.SetBytes(int64(k) * int64(n)) - b.ResetTimer() - - total := 0 - - for i := 0; i < k; i++ { - gr, err := gzip.NewReader(bytes.NewReader(gbuf)) - require.NoError(b, err) - - d, err := ioutil.ReadAll(gr) - require.NoError(b, err) - require.NoError(b, gr.Close()) - - total += len(d) - } - _ = total - }) - } -} diff --git a/vendor/github.com/prometheus/prometheus/promql/bench_test.go b/vendor/github.com/prometheus/prometheus/promql/bench_test.go deleted file mode 100644 index 1f8fa7947..000000000 --- a/vendor/github.com/prometheus/prometheus/promql/bench_test.go +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright 2015 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, softwar -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package promql - -import ( - "context" - "fmt" - "strconv" - "strings" - "testing" - "time" - - "github.com/prometheus/prometheus/pkg/labels" - "github.com/prometheus/prometheus/util/testutil" -) - -func BenchmarkRangeQuery(b *testing.B) { - storage := testutil.NewStorage(b) - defer storage.Close() - opts := EngineOpts{ - Logger: nil, - Reg: nil, - MaxConcurrent: 10, - MaxSamples: 50000000, - Timeout: 100 * time.Second, - } - engine := NewEngine(opts) - - metrics := []labels.Labels{} - metrics = append(metrics, labels.FromStrings("__name__", "a_one")) - metrics = append(metrics, labels.FromStrings("__name__", "b_one")) - for j := 0; j < 10; j++ { - metrics = append(metrics, labels.FromStrings("__name__", "h_one", "le", strconv.Itoa(j))) - } - metrics = append(metrics, labels.FromStrings("__name__", "h_one", "le", "+Inf")) - - for i := 0; i < 10; i++ { - metrics = append(metrics, labels.FromStrings("__name__", "a_ten", "l", strconv.Itoa(i))) - metrics = append(metrics, labels.FromStrings("__name__", "b_ten", "l", strconv.Itoa(i))) - for j := 0; j < 10; j++ { - metrics = append(metrics, labels.FromStrings("__name__", "h_ten", "l", strconv.Itoa(i), "le", strconv.Itoa(j))) - } - metrics = append(metrics, labels.FromStrings("__name__", "h_ten", "l", strconv.Itoa(i), "le", "+Inf")) - } - - for i := 0; i < 100; i++ { - metrics = append(metrics, labels.FromStrings("__name__", "a_hundred", "l", strconv.Itoa(i))) - metrics = append(metrics, labels.FromStrings("__name__", "b_hundred", "l", strconv.Itoa(i))) - for j := 0; j < 10; j++ { - metrics = append(metrics, labels.FromStrings("__name__", "h_hundred", "l", strconv.Itoa(i), "le", strconv.Itoa(j))) - } - metrics = append(metrics, labels.FromStrings("__name__", "h_hundred", "l", strconv.Itoa(i), "le", "+Inf")) - } - refs := make([]uint64, len(metrics)) - - // A day of data plus 10k steps. - numIntervals := 8640 + 10000 - - for s := 0; s < numIntervals; s++ { - a, err := storage.Appender() - if err != nil { - b.Fatal(err) - } - ts := int64(s * 10000) // 10s interval. - for i, metric := range metrics { - err := a.AddFast(metric, refs[i], ts, float64(s)) - if err != nil { - refs[i], _ = a.Add(metric, ts, float64(s)) - } - } - if err := a.Commit(); err != nil { - b.Fatal(err) - } - } - - type benchCase struct { - expr string - steps int - } - cases := []benchCase{ - // Plain retrieval. - { - expr: "a_X", - }, - // Simple rate. - { - expr: "rate(a_X[1m])", - }, - { - expr: "rate(a_X[1m])", - steps: 10000, - }, - // Holt-Winters and long ranges. - { - expr: "holt_winters(a_X[1d], 0.3, 0.3)", - }, - { - expr: "changes(a_X[1d])", - }, - { - expr: "rate(a_X[1d])", - }, - // Unary operators. - { - expr: "-a_X", - }, - // Binary operators. - { - expr: "a_X - b_X", - }, - { - expr: "a_X - b_X", - steps: 10000, - }, - { - expr: "a_X and b_X{l=~'.*[0-4]$'}", - }, - { - expr: "a_X or b_X{l=~'.*[0-4]$'}", - }, - { - expr: "a_X unless b_X{l=~'.*[0-4]$'}", - }, - // Simple functions. - { - expr: "abs(a_X)", - }, - { - expr: "label_replace(a_X, 'l2', '$1', 'l', '(.*)')", - }, - { - expr: "label_join(a_X, 'l2', '-', 'l', 'l')", - }, - // Simple aggregations. - { - expr: "sum(a_X)", - }, - { - expr: "sum without (l)(h_X)", - }, - { - expr: "sum without (le)(h_X)", - }, - { - expr: "sum by (l)(h_X)", - }, - { - expr: "sum by (le)(h_X)", - }, - // Combinations. - { - expr: "rate(a_X[1m]) + rate(b_X[1m])", - }, - { - expr: "sum without (l)(rate(a_X[1m]))", - }, - { - expr: "sum without (l)(rate(a_X[1m])) / sum without (l)(rate(b_X[1m]))", - }, - { - expr: "histogram_quantile(0.9, rate(h_X[5m]))", - }, - } - - // X in an expr will be replaced by different metric sizes. - tmp := []benchCase{} - for _, c := range cases { - if !strings.Contains(c.expr, "X") { - tmp = append(tmp, c) - } else { - tmp = append(tmp, benchCase{expr: strings.Replace(c.expr, "X", "one", -1), steps: c.steps}) - tmp = append(tmp, benchCase{expr: strings.Replace(c.expr, "X", "ten", -1), steps: c.steps}) - tmp = append(tmp, benchCase{expr: strings.Replace(c.expr, "X", "hundred", -1), steps: c.steps}) - } - } - cases = tmp - - // No step will be replaced by cases with the standard step. - tmp = []benchCase{} - for _, c := range cases { - if c.steps != 0 { - tmp = append(tmp, c) - } else { - tmp = append(tmp, benchCase{expr: c.expr, steps: 1}) - tmp = append(tmp, benchCase{expr: c.expr, steps: 10}) - tmp = append(tmp, benchCase{expr: c.expr, steps: 100}) - tmp = append(tmp, benchCase{expr: c.expr, steps: 1000}) - } - } - cases = tmp - for _, c := range cases { - name := fmt.Sprintf("expr=%s,steps=%d", c.expr, c.steps) - b.Run(name, func(b *testing.B) { - b.ReportAllocs() - for i := 0; i < b.N; i++ { - qry, err := engine.NewRangeQuery( - storage, c.expr, - time.Unix(int64((numIntervals-c.steps)*10), 0), - time.Unix(int64(numIntervals*10), 0), time.Second*10) - if err != nil { - b.Fatal(err) - } - res := qry.Exec(context.Background()) - if res.Err != nil { - b.Fatal(res.Err) - } - qry.Close() - } - }) - } -} diff --git a/vendor/github.com/prometheus/prometheus/promql/engine_test.go b/vendor/github.com/prometheus/prometheus/promql/engine_test.go deleted file mode 100644 index a56d00141..000000000 --- a/vendor/github.com/prometheus/prometheus/promql/engine_test.go +++ /dev/null @@ -1,916 +0,0 @@ -// Copyright 2016 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package promql - -import ( - "context" - "fmt" - "reflect" - "testing" - "time" - - "github.com/go-kit/kit/log" - "github.com/prometheus/prometheus/pkg/labels" - "github.com/prometheus/prometheus/storage" - "github.com/prometheus/prometheus/util/testutil" -) - -func TestQueryConcurrency(t *testing.T) { - opts := EngineOpts{ - Logger: nil, - Reg: nil, - MaxConcurrent: 10, - MaxSamples: 10, - Timeout: 100 * time.Second, - } - - engine := NewEngine(opts) - ctx, cancelCtx := context.WithCancel(context.Background()) - defer cancelCtx() - - block := make(chan struct{}) - processing := make(chan struct{}) - - f := func(context.Context) error { - processing <- struct{}{} - <-block - return nil - } - - for i := 0; i < opts.MaxConcurrent; i++ { - q := engine.newTestQuery(f) - go q.Exec(ctx) - select { - case <-processing: - // Expected. - case <-time.After(20 * time.Millisecond): - t.Fatalf("Query within concurrency threshold not being executed") - } - } - - q := engine.newTestQuery(f) - go q.Exec(ctx) - - select { - case <-processing: - t.Fatalf("Query above concurrency threshold being executed") - case <-time.After(20 * time.Millisecond): - // Expected. - } - - // Terminate a running query. - block <- struct{}{} - - select { - case <-processing: - // Expected. - case <-time.After(20 * time.Millisecond): - t.Fatalf("Query within concurrency threshold not being executed") - } - - // Terminate remaining queries. - for i := 0; i < opts.MaxConcurrent; i++ { - block <- struct{}{} - } -} - -func TestQueryTimeout(t *testing.T) { - opts := EngineOpts{ - Logger: nil, - Reg: nil, - MaxConcurrent: 20, - MaxSamples: 10, - Timeout: 5 * time.Millisecond, - } - engine := NewEngine(opts) - ctx, cancelCtx := context.WithCancel(context.Background()) - defer cancelCtx() - - query := engine.newTestQuery(func(ctx context.Context) error { - time.Sleep(50 * time.Millisecond) - return contextDone(ctx, "test statement execution") - }) - - res := query.Exec(ctx) - if res.Err == nil { - t.Fatalf("expected timeout error but got none") - } - if _, ok := res.Err.(ErrQueryTimeout); res.Err != nil && !ok { - t.Fatalf("expected timeout error but got: %s", res.Err) - } -} - -func TestQueryCancel(t *testing.T) { - opts := EngineOpts{ - Logger: nil, - Reg: nil, - MaxConcurrent: 10, - MaxSamples: 10, - Timeout: 10 * time.Second, - } - engine := NewEngine(opts) - ctx, cancelCtx := context.WithCancel(context.Background()) - defer cancelCtx() - - // Cancel a running query before it completes. - block := make(chan struct{}) - processing := make(chan struct{}) - - query1 := engine.newTestQuery(func(ctx context.Context) error { - processing <- struct{}{} - <-block - return contextDone(ctx, "test statement execution") - }) - - var res *Result - - go func() { - res = query1.Exec(ctx) - processing <- struct{}{} - }() - - <-processing - query1.Cancel() - block <- struct{}{} - <-processing - - if res.Err == nil { - t.Fatalf("expected cancellation error for query1 but got none") - } - if ee := ErrQueryCanceled("test statement execution"); res.Err != ee { - t.Fatalf("expected error %q, got %q", ee, res.Err) - } - - // Canceling a query before starting it must have no effect. - query2 := engine.newTestQuery(func(ctx context.Context) error { - return contextDone(ctx, "test statement execution") - }) - - query2.Cancel() - res = query2.Exec(ctx) - if res.Err != nil { - t.Fatalf("unexpected error on executing query2: %s", res.Err) - } -} - -// errQuerier implements storage.Querier which always returns error. -type errQuerier struct { - err error -} - -func (q *errQuerier) Select(*storage.SelectParams, ...*labels.Matcher) (storage.SeriesSet, storage.Warnings, error) { - return errSeriesSet{err: q.err}, nil, q.err -} -func (*errQuerier) LabelValues(name string) ([]string, error) { return nil, nil } -func (*errQuerier) LabelNames() ([]string, error) { return nil, nil } -func (*errQuerier) Close() error { return nil } - -// errSeriesSet implements storage.SeriesSet which always returns error. -type errSeriesSet struct { - err error -} - -func (errSeriesSet) Next() bool { return false } -func (errSeriesSet) At() storage.Series { return nil } -func (e errSeriesSet) Err() error { return e.err } - -func TestQueryError(t *testing.T) { - opts := EngineOpts{ - Logger: nil, - Reg: nil, - MaxConcurrent: 10, - MaxSamples: 10, - Timeout: 10 * time.Second, - } - engine := NewEngine(opts) - errStorage := ErrStorage{fmt.Errorf("storage error")} - queryable := storage.QueryableFunc(func(ctx context.Context, mint, maxt int64) (storage.Querier, error) { - return &errQuerier{err: errStorage}, nil - }) - ctx, cancelCtx := context.WithCancel(context.Background()) - defer cancelCtx() - - vectorQuery, err := engine.NewInstantQuery(queryable, "foo", time.Unix(1, 0)) - if err != nil { - t.Fatalf("unexpected error creating query: %q", err) - } - res := vectorQuery.Exec(ctx) - if res.Err == nil { - t.Fatalf("expected error on failed select but got none") - } - if res.Err != errStorage { - t.Fatalf("expected error %q, got %q", errStorage, res.Err) - } - - matrixQuery, err := engine.NewInstantQuery(queryable, "foo[1m]", time.Unix(1, 0)) - if err != nil { - t.Fatalf("unexpected error creating query: %q", err) - } - res = matrixQuery.Exec(ctx) - if res.Err == nil { - t.Fatalf("expected error on failed select but got none") - } - if res.Err != errStorage { - t.Fatalf("expected error %q, got %q", errStorage, res.Err) - } -} - -func TestEngineShutdown(t *testing.T) { - opts := EngineOpts{ - Logger: nil, - Reg: nil, - MaxConcurrent: 10, - MaxSamples: 10, - Timeout: 10 * time.Second, - } - engine := NewEngine(opts) - ctx, cancelCtx := context.WithCancel(context.Background()) - - block := make(chan struct{}) - processing := make(chan struct{}) - - // Shutdown engine on first handler execution. Should handler execution ever become - // concurrent this test has to be adjusted accordingly. - f := func(ctx context.Context) error { - processing <- struct{}{} - <-block - return contextDone(ctx, "test statement execution") - } - query1 := engine.newTestQuery(f) - - // Stopping the engine must cancel the base context. While executing queries is - // still possible, their context is canceled from the beginning and execution should - // terminate immediately. - - var res *Result - go func() { - res = query1.Exec(ctx) - processing <- struct{}{} - }() - - <-processing - cancelCtx() - block <- struct{}{} - <-processing - - if res.Err == nil { - t.Fatalf("expected error on shutdown during query but got none") - } - if ee := ErrQueryCanceled("test statement execution"); res.Err != ee { - t.Fatalf("expected error %q, got %q", ee, res.Err) - } - - query2 := engine.newTestQuery(func(context.Context) error { - t.Fatalf("reached query execution unexpectedly") - return nil - }) - - // The second query is started after the engine shut down. It must - // be canceled immediately. - res2 := query2.Exec(ctx) - if res2.Err == nil { - t.Fatalf("expected error on querying with canceled context but got none") - } - if _, ok := res2.Err.(ErrQueryCanceled); !ok { - t.Fatalf("expected cancellation error, got %q", res2.Err) - } -} - -func TestEngineEvalStmtTimestamps(t *testing.T) { - test, err := NewTest(t, ` -load 10s - metric 1 2 -`) - if err != nil { - t.Fatalf("unexpected error creating test: %q", err) - } - defer test.Close() - - err = test.Run() - if err != nil { - t.Fatalf("unexpected error initializing test: %q", err) - } - - cases := []struct { - Query string - Result Value - Start time.Time - End time.Time - Interval time.Duration - ShouldError bool - }{ - // Instant queries. - { - Query: "1", - Result: Scalar{V: 1, T: 1000}, - Start: time.Unix(1, 0), - }, - { - Query: "metric", - Result: Vector{ - Sample{Point: Point{V: 1, T: 1000}, - Metric: labels.FromStrings("__name__", "metric")}, - }, - Start: time.Unix(1, 0), - }, - { - Query: "metric[20s]", - Result: Matrix{Series{ - Points: []Point{{V: 1, T: 0}, {V: 2, T: 10000}}, - Metric: labels.FromStrings("__name__", "metric")}, - }, - Start: time.Unix(10, 0), - }, - // Range queries. - { - Query: "1", - Result: Matrix{Series{ - Points: []Point{{V: 1, T: 0}, {V: 1, T: 1000}, {V: 1, T: 2000}}, - Metric: labels.FromStrings()}, - }, - Start: time.Unix(0, 0), - End: time.Unix(2, 0), - Interval: time.Second, - }, - { - Query: "metric", - Result: Matrix{Series{ - Points: []Point{{V: 1, T: 0}, {V: 1, T: 1000}, {V: 1, T: 2000}}, - Metric: labels.FromStrings("__name__", "metric")}, - }, - Start: time.Unix(0, 0), - End: time.Unix(2, 0), - Interval: time.Second, - }, - { - Query: "metric", - Result: Matrix{Series{ - Points: []Point{{V: 1, T: 0}, {V: 1, T: 5000}, {V: 2, T: 10000}}, - Metric: labels.FromStrings("__name__", "metric")}, - }, - Start: time.Unix(0, 0), - End: time.Unix(10, 0), - Interval: 5 * time.Second, - }, - { - Query: `count_values("wrong label!", metric)`, - ShouldError: true, - }, - } - - for _, c := range cases { - var err error - var qry Query - if c.Interval == 0 { - qry, err = test.QueryEngine().NewInstantQuery(test.Queryable(), c.Query, c.Start) - } else { - qry, err = test.QueryEngine().NewRangeQuery(test.Queryable(), c.Query, c.Start, c.End, c.Interval) - } - if err != nil { - t.Fatalf("unexpected error creating query: %q", err) - } - res := qry.Exec(test.Context()) - if c.ShouldError { - testutil.NotOk(t, res.Err, "expected error for the query %q", c.Query) - continue - } - if res.Err != nil { - t.Fatalf("unexpected error running query: %q", res.Err) - } - if !reflect.DeepEqual(res.Value, c.Result) { - t.Fatalf("unexpected result for query %q: got %q wanted %q", c.Query, res.Value.String(), c.Result.String()) - } - } - -} - -func TestMaxQuerySamples(t *testing.T) { - test, err := NewTest(t, ` -load 10s - metric 1 2 -`) - - if err != nil { - t.Fatalf("unexpected error creating test: %q", err) - } - defer test.Close() - - err = test.Run() - if err != nil { - t.Fatalf("unexpected error initializing test: %q", err) - } - - cases := []struct { - Query string - MaxSamples int - Result Result - Start time.Time - End time.Time - Interval time.Duration - }{ - // Instant queries. - { - Query: "1", - MaxSamples: 1, - Result: Result{ - nil, - Scalar{V: 1, T: 1000}, - nil}, - Start: time.Unix(1, 0), - }, - { - Query: "1", - MaxSamples: 0, - Result: Result{ - ErrTooManySamples(env), - nil, - nil, - }, - Start: time.Unix(1, 0), - }, - { - Query: "metric", - MaxSamples: 0, - Result: Result{ - ErrTooManySamples(env), - nil, - nil, - }, - Start: time.Unix(1, 0), - }, - { - Query: "metric", - MaxSamples: 1, - Result: Result{ - nil, - Vector{ - Sample{Point: Point{V: 1, T: 1000}, - Metric: labels.FromStrings("__name__", "metric")}, - }, - nil, - }, - Start: time.Unix(1, 0), - }, - { - Query: "metric[20s]", - MaxSamples: 2, - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 1, T: 0}, {V: 2, T: 10000}}, - Metric: labels.FromStrings("__name__", "metric")}, - }, - nil, - }, - Start: time.Unix(10, 0), - }, - { - Query: "rate(metric[20s])", - MaxSamples: 3, - Result: Result{ - nil, - Vector{ - Sample{ - Point: Point{V: 0.1, T: 10000}, - Metric: labels.Labels{}, - }, - }, - nil, - }, - Start: time.Unix(10, 0), - }, - { - Query: "metric[20s:5s]", - MaxSamples: 3, - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 1, T: 0}, {V: 1, T: 5000}, {V: 2, T: 10000}}, - Metric: labels.FromStrings("__name__", "metric")}, - }, - nil, - }, - Start: time.Unix(10, 0), - }, - { - Query: "metric[20s]", - MaxSamples: 0, - Result: Result{ - ErrTooManySamples(env), - nil, - nil, - }, - Start: time.Unix(10, 0), - }, - // Range queries. - { - Query: "1", - MaxSamples: 3, - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 1, T: 0}, {V: 1, T: 1000}, {V: 1, T: 2000}}, - Metric: labels.FromStrings()}, - }, - nil, - }, - Start: time.Unix(0, 0), - End: time.Unix(2, 0), - Interval: time.Second, - }, - { - Query: "1", - MaxSamples: 0, - Result: Result{ - ErrTooManySamples(env), - nil, - nil, - }, - Start: time.Unix(0, 0), - End: time.Unix(2, 0), - Interval: time.Second, - }, - { - Query: "metric", - MaxSamples: 3, - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 1, T: 0}, {V: 1, T: 1000}, {V: 1, T: 2000}}, - Metric: labels.FromStrings("__name__", "metric")}, - }, - nil, - }, - Start: time.Unix(0, 0), - End: time.Unix(2, 0), - Interval: time.Second, - }, - { - Query: "metric", - MaxSamples: 2, - Result: Result{ - ErrTooManySamples(env), - nil, - nil, - }, - Start: time.Unix(0, 0), - End: time.Unix(2, 0), - Interval: time.Second, - }, - { - Query: "metric", - MaxSamples: 3, - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 1, T: 0}, {V: 1, T: 5000}, {V: 2, T: 10000}}, - Metric: labels.FromStrings("__name__", "metric")}, - }, - nil, - }, - Start: time.Unix(0, 0), - End: time.Unix(10, 0), - Interval: 5 * time.Second, - }, - { - Query: "metric", - MaxSamples: 2, - Result: Result{ - ErrTooManySamples(env), - nil, - nil, - }, - Start: time.Unix(0, 0), - End: time.Unix(10, 0), - Interval: 5 * time.Second, - }, - } - - engine := test.QueryEngine() - for _, c := range cases { - var err error - var qry Query - - engine.maxSamplesPerQuery = c.MaxSamples - - if c.Interval == 0 { - qry, err = engine.NewInstantQuery(test.Queryable(), c.Query, c.Start) - } else { - qry, err = engine.NewRangeQuery(test.Queryable(), c.Query, c.Start, c.End, c.Interval) - } - if err != nil { - t.Fatalf("unexpected error creating query: %q", err) - } - res := qry.Exec(test.Context()) - if res.Err != nil && res.Err != c.Result.Err { - t.Fatalf("unexpected error running query: %q, expected to get result: %q", res.Err, c.Result.Value) - } - if !reflect.DeepEqual(res.Value, c.Result.Value) { - t.Fatalf("unexpected result for query %q: got %q wanted %q", c.Query, res.Value.String(), c.Result.String()) - } - } -} - -func TestRecoverEvaluatorRuntime(t *testing.T) { - ev := &evaluator{logger: log.NewNopLogger()} - - var err error - defer ev.recover(&err) - - // Cause a runtime panic. - var a []int - a[123] = 1 - - if err.Error() != "unexpected error" { - t.Fatalf("wrong error message: %q, expected %q", err, "unexpected error") - } -} - -func TestRecoverEvaluatorError(t *testing.T) { - ev := &evaluator{logger: log.NewNopLogger()} - var err error - - e := fmt.Errorf("custom error") - - defer func() { - if err.Error() != e.Error() { - t.Fatalf("wrong error message: %q, expected %q", err, e) - } - }() - defer ev.recover(&err) - - panic(e) -} - -func TestSubquerySelector(t *testing.T) { - tests := []struct { - loadString string - cases []struct { - Query string - Result Result - Start time.Time - } - }{ - { - loadString: `load 10s - metric 1 2`, - cases: []struct { - Query string - Result Result - Start time.Time - }{ - { - Query: "metric[20s:10s]", - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 1, T: 0}, {V: 2, T: 10000}}, - Metric: labels.FromStrings("__name__", "metric")}, - }, - nil, - }, - Start: time.Unix(10, 0), - }, - { - Query: "metric[20s:5s]", - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 1, T: 0}, {V: 1, T: 5000}, {V: 2, T: 10000}}, - Metric: labels.FromStrings("__name__", "metric")}, - }, - nil, - }, - Start: time.Unix(10, 0), - }, - { - Query: "metric[20s:5s] offset 2s", - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 1, T: 0}, {V: 1, T: 5000}, {V: 2, T: 10000}}, - Metric: labels.FromStrings("__name__", "metric")}, - }, - nil, - }, - Start: time.Unix(12, 0), - }, - { - Query: "metric[20s:5s] offset 6s", - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 1, T: 0}, {V: 1, T: 5000}, {V: 2, T: 10000}}, - Metric: labels.FromStrings("__name__", "metric")}, - }, - nil, - }, - Start: time.Unix(20, 0), - }, - { - Query: "metric[20s:5s] offset 4s", - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 2, T: 15000}, {V: 2, T: 20000}, {V: 2, T: 25000}, {V: 2, T: 30000}}, - Metric: labels.FromStrings("__name__", "metric")}, - }, - nil, - }, - Start: time.Unix(35, 0), - }, - { - Query: "metric[20s:5s] offset 5s", - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 2, T: 10000}, {V: 2, T: 15000}, {V: 2, T: 20000}, {V: 2, T: 25000}, {V: 2, T: 30000}}, - Metric: labels.FromStrings("__name__", "metric")}, - }, - nil, - }, - Start: time.Unix(35, 0), - }, - { - Query: "metric[20s:5s] offset 6s", - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 2, T: 10000}, {V: 2, T: 15000}, {V: 2, T: 20000}, {V: 2, T: 25000}}, - Metric: labels.FromStrings("__name__", "metric")}, - }, - nil, - }, - Start: time.Unix(35, 0), - }, - { - Query: "metric[20s:5s] offset 7s", - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 2, T: 10000}, {V: 2, T: 15000}, {V: 2, T: 20000}, {V: 2, T: 25000}}, - Metric: labels.FromStrings("__name__", "metric")}, - }, - nil, - }, - Start: time.Unix(35, 0), - }, - }, - }, - { - loadString: `load 10s - http_requests{job="api-server", instance="0", group="production"} 0+10x1000 100+30x1000 - http_requests{job="api-server", instance="1", group="production"} 0+20x1000 200+30x1000 - http_requests{job="api-server", instance="0", group="canary"} 0+30x1000 300+80x1000 - http_requests{job="api-server", instance="1", group="canary"} 0+40x2000`, - cases: []struct { - Query string - Result Result - Start time.Time - }{ - { // Normal selector. - Query: `http_requests{group=~"pro.*",instance="0"}[30s:10s]`, - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 9990, T: 9990000}, {V: 10000, T: 10000000}, {V: 100, T: 10010000}, {V: 130, T: 10020000}}, - Metric: labels.FromStrings("__name__", "http_requests", "job", "api-server", "instance", "0", "group", "production")}, - }, - nil, - }, - Start: time.Unix(10020, 0), - }, - { // Default step. - Query: `http_requests{group=~"pro.*",instance="0"}[5m:]`, - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 9840, T: 9840000}, {V: 9900, T: 9900000}, {V: 9960, T: 9960000}, {V: 130, T: 10020000}, {V: 310, T: 10080000}}, - Metric: labels.FromStrings("__name__", "http_requests", "job", "api-server", "instance", "0", "group", "production")}, - }, - nil, - }, - Start: time.Unix(10100, 0), - }, - { // Checking if high offset (>LookbackDelta) is being taken care of. - Query: `http_requests{group=~"pro.*",instance="0"}[5m:] offset 20m`, - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 8640, T: 8640000}, {V: 8700, T: 8700000}, {V: 8760, T: 8760000}, {V: 8820, T: 8820000}, {V: 8880, T: 8880000}}, - Metric: labels.FromStrings("__name__", "http_requests", "job", "api-server", "instance", "0", "group", "production")}, - }, - nil, - }, - Start: time.Unix(10100, 0), - }, - { - Query: `rate(http_requests[1m])[15s:5s]`, - Result: Result{ - nil, - Matrix{ - Series{ - Points: []Point{{V: 3, T: 7985000}, {V: 3, T: 7990000}, {V: 3, T: 7995000}, {V: 3, T: 8000000}}, - Metric: labels.FromStrings("job", "api-server", "instance", "0", "group", "canary"), - }, - Series{ - Points: []Point{{V: 4, T: 7985000}, {V: 4, T: 7990000}, {V: 4, T: 7995000}, {V: 4, T: 8000000}}, - Metric: labels.FromStrings("job", "api-server", "instance", "1", "group", "canary"), - }, - Series{ - Points: []Point{{V: 1, T: 7985000}, {V: 1, T: 7990000}, {V: 1, T: 7995000}, {V: 1, T: 8000000}}, - Metric: labels.FromStrings("job", "api-server", "instance", "0", "group", "production"), - }, - Series{ - Points: []Point{{V: 2, T: 7985000}, {V: 2, T: 7990000}, {V: 2, T: 7995000}, {V: 2, T: 8000000}}, - Metric: labels.FromStrings("job", "api-server", "instance", "1", "group", "production"), - }, - }, - nil, - }, - Start: time.Unix(8000, 0), - }, - { - Query: `sum(http_requests{group=~"pro.*"})[30s:10s]`, - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 270, T: 90000}, {V: 300, T: 100000}, {V: 330, T: 110000}, {V: 360, T: 120000}}, - Metric: labels.Labels{}}, - }, - nil, - }, - Start: time.Unix(120, 0), - }, - { - Query: `sum(http_requests)[40s:10s]`, - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 800, T: 80000}, {V: 900, T: 90000}, {V: 1000, T: 100000}, {V: 1100, T: 110000}, {V: 1200, T: 120000}}, - Metric: labels.Labels{}}, - }, - nil, - }, - Start: time.Unix(120, 0), - }, - { - Query: `(sum(http_requests{group=~"p.*"})+sum(http_requests{group=~"c.*"}))[20s:5s]`, - Result: Result{ - nil, - Matrix{Series{ - Points: []Point{{V: 1000, T: 100000}, {V: 1000, T: 105000}, {V: 1100, T: 110000}, {V: 1100, T: 115000}, {V: 1200, T: 120000}}, - Metric: labels.Labels{}}, - }, - nil, - }, - Start: time.Unix(120, 0), - }, - }, - }, - } - - SetDefaultEvaluationInterval(1 * time.Minute) - for _, tst := range tests { - test, err := NewTest(t, tst.loadString) - - if err != nil { - t.Fatalf("unexpected error creating test: %q", err) - } - defer test.Close() - - err = test.Run() - if err != nil { - t.Fatalf("unexpected error initializing test: %q", err) - } - - engine := test.QueryEngine() - for _, c := range tst.cases { - var err error - var qry Query - - qry, err = engine.NewInstantQuery(test.Queryable(), c.Query, c.Start) - if err != nil { - t.Fatalf("unexpected error creating query: %q", err) - } - res := qry.Exec(test.Context()) - if res.Err != nil && res.Err != c.Result.Err { - t.Fatalf("unexpected error running query: %q, expected to get result: %q", res.Err, c.Result.Value) - } - if !reflect.DeepEqual(res.Value, c.Result.Value) { - t.Fatalf("unexpected result for query %q: got %q wanted %q", c.Query, res.Value.String(), c.Result.String()) - } - } - } -} diff --git a/vendor/github.com/prometheus/prometheus/promql/functions_test.go b/vendor/github.com/prometheus/prometheus/promql/functions_test.go deleted file mode 100644 index d7134b3d7..000000000 --- a/vendor/github.com/prometheus/prometheus/promql/functions_test.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2015 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package promql - -import ( - "context" - "testing" - "time" - - "github.com/prometheus/prometheus/pkg/labels" - "github.com/prometheus/prometheus/pkg/timestamp" - "github.com/prometheus/prometheus/util/testutil" -) - -func TestDeriv(t *testing.T) { - // https://github.com/prometheus/prometheus/issues/2674#issuecomment-315439393 - // This requires more precision than the usual test system offers, - // so we test it by hand. - storage := testutil.NewStorage(t) - defer storage.Close() - opts := EngineOpts{ - Logger: nil, - Reg: nil, - MaxConcurrent: 10, - MaxSamples: 10000, - Timeout: 10 * time.Second, - } - engine := NewEngine(opts) - - a, err := storage.Appender() - testutil.Ok(t, err) - - metric := labels.FromStrings("__name__", "foo") - a.Add(metric, 1493712816939, 1.0) - a.Add(metric, 1493712846939, 1.0) - - err = a.Commit() - testutil.Ok(t, err) - - query, err := engine.NewInstantQuery(storage, "deriv(foo[30m])", timestamp.Time(1493712846939)) - testutil.Ok(t, err) - - result := query.Exec(context.Background()) - testutil.Ok(t, result.Err) - - vec, _ := result.Vector() - testutil.Assert(t, len(vec) == 1, "Expected 1 result, got %d", len(vec)) - testutil.Assert(t, vec[0].V == 0.0, "Expected 0.0 as value, got %f", vec[0].V) -} diff --git a/vendor/github.com/prometheus/prometheus/promql/lex_test.go b/vendor/github.com/prometheus/prometheus/promql/lex_test.go deleted file mode 100644 index 86eb3fdf3..000000000 --- a/vendor/github.com/prometheus/prometheus/promql/lex_test.go +++ /dev/null @@ -1,711 +0,0 @@ -// Copyright 2015 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package promql - -import ( - "fmt" - "reflect" - "testing" -) - -type testCase struct { - input string - expected []item - fail bool - seriesDesc bool // Whether to lex a series description. -} - -var tests = []struct { - name string - tests []testCase -}{ - { - name: "common", - tests: []testCase{ - { - input: ",", - expected: []item{{itemComma, 0, ","}}, - }, { - input: "()", - expected: []item{{itemLeftParen, 0, `(`}, {itemRightParen, 1, `)`}}, - }, { - input: "{}", - expected: []item{{itemLeftBrace, 0, `{`}, {itemRightBrace, 1, `}`}}, - }, { - input: "[5m]", - expected: []item{ - {itemLeftBracket, 0, `[`}, - {itemDuration, 1, `5m`}, - {itemRightBracket, 3, `]`}, - }, - }, { - input: "\r\n\r", - expected: []item{}, - }, - }, - }, - { - name: "numbers", - tests: []testCase{ - { - input: "1", - expected: []item{{itemNumber, 0, "1"}}, - }, { - input: "4.23", - expected: []item{{itemNumber, 0, "4.23"}}, - }, { - input: ".3", - expected: []item{{itemNumber, 0, ".3"}}, - }, { - input: "5.", - expected: []item{{itemNumber, 0, "5."}}, - }, { - input: "NaN", - expected: []item{{itemNumber, 0, "NaN"}}, - }, { - input: "nAN", - expected: []item{{itemNumber, 0, "nAN"}}, - }, { - input: "NaN 123", - expected: []item{{itemNumber, 0, "NaN"}, {itemNumber, 4, "123"}}, - }, { - input: "NaN123", - expected: []item{{itemIdentifier, 0, "NaN123"}}, - }, { - input: "iNf", - expected: []item{{itemNumber, 0, "iNf"}}, - }, { - input: "Inf", - expected: []item{{itemNumber, 0, "Inf"}}, - }, { - input: "+Inf", - expected: []item{{itemADD, 0, "+"}, {itemNumber, 1, "Inf"}}, - }, { - input: "+Inf 123", - expected: []item{{itemADD, 0, "+"}, {itemNumber, 1, "Inf"}, {itemNumber, 5, "123"}}, - }, { - input: "-Inf", - expected: []item{{itemSUB, 0, "-"}, {itemNumber, 1, "Inf"}}, - }, { - input: "Infoo", - expected: []item{{itemIdentifier, 0, "Infoo"}}, - }, { - input: "-Infoo", - expected: []item{{itemSUB, 0, "-"}, {itemIdentifier, 1, "Infoo"}}, - }, { - input: "-Inf 123", - expected: []item{{itemSUB, 0, "-"}, {itemNumber, 1, "Inf"}, {itemNumber, 5, "123"}}, - }, { - input: "0x123", - expected: []item{{itemNumber, 0, "0x123"}}, - }, - }, - }, - { - name: "strings", - tests: []testCase{ - { - input: "\"test\\tsequence\"", - expected: []item{{itemString, 0, `"test\tsequence"`}}, - }, - { - input: "\"test\\\\.expression\"", - expected: []item{{itemString, 0, `"test\\.expression"`}}, - }, - { - input: "\"test\\.expression\"", - expected: []item{ - {itemError, 0, "unknown escape sequence U+002E '.'"}, - {itemString, 0, `"test\.expression"`}, - }, - }, - { - input: "`test\\.expression`", - expected: []item{{itemString, 0, "`test\\.expression`"}}, - }, - { - // See https://github.com/prometheus/prometheus/issues/939. - input: ".٩", - fail: true, - }, - }, - }, - { - name: "durations", - tests: []testCase{ - { - input: "5s", - expected: []item{{itemDuration, 0, "5s"}}, - }, { - input: "123m", - expected: []item{{itemDuration, 0, "123m"}}, - }, { - input: "1h", - expected: []item{{itemDuration, 0, "1h"}}, - }, { - input: "3w", - expected: []item{{itemDuration, 0, "3w"}}, - }, { - input: "1y", - expected: []item{{itemDuration, 0, "1y"}}, - }, - }, - }, - { - name: "identifiers", - tests: []testCase{ - { - input: "abc", - expected: []item{{itemIdentifier, 0, "abc"}}, - }, { - input: "a:bc", - expected: []item{{itemMetricIdentifier, 0, "a:bc"}}, - }, { - input: "abc d", - expected: []item{{itemIdentifier, 0, "abc"}, {itemIdentifier, 4, "d"}}, - }, { - input: ":bc", - expected: []item{{itemMetricIdentifier, 0, ":bc"}}, - }, { - input: "0a:bc", - fail: true, - }, - }, - }, - { - name: "comments", - tests: []testCase{ - { - input: "# some comment", - expected: []item{{itemComment, 0, "# some comment"}}, - }, { - input: "5 # 1+1\n5", - expected: []item{ - {itemNumber, 0, "5"}, - {itemComment, 2, "# 1+1"}, - {itemNumber, 8, "5"}, - }, - }, - }, - }, - { - name: "operators", - tests: []testCase{ - { - input: `=`, - expected: []item{{itemAssign, 0, `=`}}, - }, { - // Inside braces equality is a single '=' character. - input: `{=}`, - expected: []item{{itemLeftBrace, 0, `{`}, {itemEQL, 1, `=`}, {itemRightBrace, 2, `}`}}, - }, { - input: `==`, - expected: []item{{itemEQL, 0, `==`}}, - }, { - input: `!=`, - expected: []item{{itemNEQ, 0, `!=`}}, - }, { - input: `<`, - expected: []item{{itemLSS, 0, `<`}}, - }, { - input: `>`, - expected: []item{{itemGTR, 0, `>`}}, - }, { - input: `>=`, - expected: []item{{itemGTE, 0, `>=`}}, - }, { - input: `<=`, - expected: []item{{itemLTE, 0, `<=`}}, - }, { - input: `+`, - expected: []item{{itemADD, 0, `+`}}, - }, { - input: `-`, - expected: []item{{itemSUB, 0, `-`}}, - }, { - input: `*`, - expected: []item{{itemMUL, 0, `*`}}, - }, { - input: `/`, - expected: []item{{itemDIV, 0, `/`}}, - }, { - input: `^`, - expected: []item{{itemPOW, 0, `^`}}, - }, { - input: `%`, - expected: []item{{itemMOD, 0, `%`}}, - }, { - input: `AND`, - expected: []item{{itemLAND, 0, `AND`}}, - }, { - input: `or`, - expected: []item{{itemLOR, 0, `or`}}, - }, { - input: `unless`, - expected: []item{{itemLUnless, 0, `unless`}}, - }, - }, - }, - { - name: "aggregators", - tests: []testCase{ - { - input: `sum`, - expected: []item{{itemSum, 0, `sum`}}, - }, { - input: `AVG`, - expected: []item{{itemAvg, 0, `AVG`}}, - }, { - input: `MAX`, - expected: []item{{itemMax, 0, `MAX`}}, - }, { - input: `min`, - expected: []item{{itemMin, 0, `min`}}, - }, { - input: `count`, - expected: []item{{itemCount, 0, `count`}}, - }, { - input: `stdvar`, - expected: []item{{itemStdvar, 0, `stdvar`}}, - }, { - input: `stddev`, - expected: []item{{itemStddev, 0, `stddev`}}, - }, - }, - }, - { - name: "keywords", - tests: []testCase{ - { - input: "offset", - expected: []item{{itemOffset, 0, "offset"}}, - }, { - input: "by", - expected: []item{{itemBy, 0, "by"}}, - }, { - input: "without", - expected: []item{{itemWithout, 0, "without"}}, - }, { - input: "on", - expected: []item{{itemOn, 0, "on"}}, - }, { - input: "ignoring", - expected: []item{{itemIgnoring, 0, "ignoring"}}, - }, { - input: "group_left", - expected: []item{{itemGroupLeft, 0, "group_left"}}, - }, { - input: "group_right", - expected: []item{{itemGroupRight, 0, "group_right"}}, - }, { - input: "bool", - expected: []item{{itemBool, 0, "bool"}}, - }, - }, - }, - { - name: "selectors", - tests: []testCase{ - { - input: `台北`, - fail: true, - }, { - input: `{台北='a'}`, - fail: true, - }, { - input: `{0a='a'}`, - fail: true, - }, { - input: `{foo='bar'}`, - expected: []item{ - {itemLeftBrace, 0, `{`}, - {itemIdentifier, 1, `foo`}, - {itemEQL, 4, `=`}, - {itemString, 5, `'bar'`}, - {itemRightBrace, 10, `}`}, - }, - }, { - input: `{foo="bar"}`, - expected: []item{ - {itemLeftBrace, 0, `{`}, - {itemIdentifier, 1, `foo`}, - {itemEQL, 4, `=`}, - {itemString, 5, `"bar"`}, - {itemRightBrace, 10, `}`}, - }, - }, { - input: `{foo="bar\"bar"}`, - expected: []item{ - {itemLeftBrace, 0, `{`}, - {itemIdentifier, 1, `foo`}, - {itemEQL, 4, `=`}, - {itemString, 5, `"bar\"bar"`}, - {itemRightBrace, 15, `}`}, - }, - }, { - input: `{NaN != "bar" }`, - expected: []item{ - {itemLeftBrace, 0, `{`}, - {itemIdentifier, 1, `NaN`}, - {itemNEQ, 5, `!=`}, - {itemString, 8, `"bar"`}, - {itemRightBrace, 14, `}`}, - }, - }, { - input: `{alert=~"bar" }`, - expected: []item{ - {itemLeftBrace, 0, `{`}, - {itemIdentifier, 1, `alert`}, - {itemEQLRegex, 6, `=~`}, - {itemString, 8, `"bar"`}, - {itemRightBrace, 14, `}`}, - }, - }, { - input: `{on!~"bar"}`, - expected: []item{ - {itemLeftBrace, 0, `{`}, - {itemIdentifier, 1, `on`}, - {itemNEQRegex, 3, `!~`}, - {itemString, 5, `"bar"`}, - {itemRightBrace, 10, `}`}, - }, - }, { - input: `{alert!#"bar"}`, fail: true, - }, { - input: `{foo:a="bar"}`, fail: true, - }, - }, - }, - { - name: "common errors", - tests: []testCase{ - { - input: `=~`, fail: true, - }, { - input: `!~`, fail: true, - }, { - input: `!(`, fail: true, - }, { - input: "1a", fail: true, - }, - }, - }, - { - name: "mismatched parentheses", - tests: []testCase{ - { - input: `(`, fail: true, - }, { - input: `())`, fail: true, - }, { - input: `(()`, fail: true, - }, { - input: `{`, fail: true, - }, { - input: `}`, fail: true, - }, { - input: "{{", fail: true, - }, { - input: "{{}}", fail: true, - }, { - input: `[`, fail: true, - }, { - input: `[[`, fail: true, - }, { - input: `[]]`, fail: true, - }, { - input: `[[]]`, fail: true, - }, { - input: `]`, fail: true, - }, - }, - }, - { - name: "encoding issues", - tests: []testCase{ - { - input: "\"\xff\"", fail: true, - }, - { - input: "`\xff`", fail: true, - }, - }, - }, - { - name: "series descriptions", - tests: []testCase{ - { - input: `{} _ 1 x .3`, - expected: []item{ - {itemLeftBrace, 0, `{`}, - {itemRightBrace, 1, `}`}, - {itemSpace, 2, ` `}, - {itemBlank, 3, `_`}, - {itemSpace, 4, ` `}, - {itemNumber, 5, `1`}, - {itemSpace, 6, ` `}, - {itemTimes, 7, `x`}, - {itemSpace, 8, ` `}, - {itemNumber, 9, `.3`}, - }, - seriesDesc: true, - }, - { - input: `metric +Inf Inf NaN`, - expected: []item{ - {itemIdentifier, 0, `metric`}, - {itemSpace, 6, ` `}, - {itemADD, 7, `+`}, - {itemNumber, 8, `Inf`}, - {itemSpace, 11, ` `}, - {itemNumber, 12, `Inf`}, - {itemSpace, 15, ` `}, - {itemNumber, 16, `NaN`}, - }, - seriesDesc: true, - }, - { - input: `metric 1+1x4`, - expected: []item{ - {itemIdentifier, 0, `metric`}, - {itemSpace, 6, ` `}, - {itemNumber, 7, `1`}, - {itemADD, 8, `+`}, - {itemNumber, 9, `1`}, - {itemTimes, 10, `x`}, - {itemNumber, 11, `4`}, - }, - seriesDesc: true, - }, - }, - }, - { - name: "subqueries", - tests: []testCase{ - { - input: `test_name{on!~"bar"}[4m:4s]`, - expected: []item{ - {itemIdentifier, 0, `test_name`}, - {itemLeftBrace, 9, `{`}, - {itemIdentifier, 10, `on`}, - {itemNEQRegex, 12, `!~`}, - {itemString, 14, `"bar"`}, - {itemRightBrace, 19, `}`}, - {itemLeftBracket, 20, `[`}, - {itemDuration, 21, `4m`}, - {itemColon, 23, `:`}, - {itemDuration, 24, `4s`}, - {itemRightBracket, 26, `]`}, - }, - }, - { - input: `test:name{on!~"bar"}[4m:4s]`, - expected: []item{ - {itemMetricIdentifier, 0, `test:name`}, - {itemLeftBrace, 9, `{`}, - {itemIdentifier, 10, `on`}, - {itemNEQRegex, 12, `!~`}, - {itemString, 14, `"bar"`}, - {itemRightBrace, 19, `}`}, - {itemLeftBracket, 20, `[`}, - {itemDuration, 21, `4m`}, - {itemColon, 23, `:`}, - {itemDuration, 24, `4s`}, - {itemRightBracket, 26, `]`}, - }, - }, { - input: `test:name{on!~"b:ar"}[4m:4s]`, - expected: []item{ - {itemMetricIdentifier, 0, `test:name`}, - {itemLeftBrace, 9, `{`}, - {itemIdentifier, 10, `on`}, - {itemNEQRegex, 12, `!~`}, - {itemString, 14, `"b:ar"`}, - {itemRightBrace, 20, `}`}, - {itemLeftBracket, 21, `[`}, - {itemDuration, 22, `4m`}, - {itemColon, 24, `:`}, - {itemDuration, 25, `4s`}, - {itemRightBracket, 27, `]`}, - }, - }, { - input: `test:name{on!~"b:ar"}[4m:]`, - expected: []item{ - {itemMetricIdentifier, 0, `test:name`}, - {itemLeftBrace, 9, `{`}, - {itemIdentifier, 10, `on`}, - {itemNEQRegex, 12, `!~`}, - {itemString, 14, `"b:ar"`}, - {itemRightBrace, 20, `}`}, - {itemLeftBracket, 21, `[`}, - {itemDuration, 22, `4m`}, - {itemColon, 24, `:`}, - {itemRightBracket, 25, `]`}, - }, - }, { // Nested Subquery. - input: `min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s]`, - expected: []item{ - - {itemIdentifier, 0, `min_over_time`}, - {itemLeftParen, 13, `(`}, - {itemIdentifier, 14, `rate`}, - {itemLeftParen, 18, `(`}, - {itemIdentifier, 19, `foo`}, - {itemLeftBrace, 22, `{`}, - {itemIdentifier, 23, `bar`}, - {itemEQL, 26, `=`}, - {itemString, 27, `"baz"`}, - {itemRightBrace, 32, `}`}, - {itemLeftBracket, 33, `[`}, - {itemDuration, 34, `2s`}, - {itemRightBracket, 36, `]`}, - {itemRightParen, 37, `)`}, - {itemLeftBracket, 38, `[`}, - {itemDuration, 39, `5m`}, - {itemColon, 41, `:`}, - {itemRightBracket, 42, `]`}, - {itemRightParen, 43, `)`}, - {itemLeftBracket, 44, `[`}, - {itemDuration, 45, `4m`}, - {itemColon, 47, `:`}, - {itemDuration, 48, `3s`}, - {itemRightBracket, 50, `]`}, - }, - }, - // Subquery with offset. - { - input: `test:name{on!~"b:ar"}[4m:4s] offset 10m`, - expected: []item{ - {itemMetricIdentifier, 0, `test:name`}, - {itemLeftBrace, 9, `{`}, - {itemIdentifier, 10, `on`}, - {itemNEQRegex, 12, `!~`}, - {itemString, 14, `"b:ar"`}, - {itemRightBrace, 20, `}`}, - {itemLeftBracket, 21, `[`}, - {itemDuration, 22, `4m`}, - {itemColon, 24, `:`}, - {itemDuration, 25, `4s`}, - {itemRightBracket, 27, `]`}, - {itemOffset, 29, "offset"}, - {itemDuration, 36, "10m"}, - }, - }, { - input: `min_over_time(rate(foo{bar="baz"}[2s])[5m:] offset 6m)[4m:3s]`, - expected: []item{ - - {itemIdentifier, 0, `min_over_time`}, - {itemLeftParen, 13, `(`}, - {itemIdentifier, 14, `rate`}, - {itemLeftParen, 18, `(`}, - {itemIdentifier, 19, `foo`}, - {itemLeftBrace, 22, `{`}, - {itemIdentifier, 23, `bar`}, - {itemEQL, 26, `=`}, - {itemString, 27, `"baz"`}, - {itemRightBrace, 32, `}`}, - {itemLeftBracket, 33, `[`}, - {itemDuration, 34, `2s`}, - {itemRightBracket, 36, `]`}, - {itemRightParen, 37, `)`}, - {itemLeftBracket, 38, `[`}, - {itemDuration, 39, `5m`}, - {itemColon, 41, `:`}, - {itemRightBracket, 42, `]`}, - {itemOffset, 44, `offset`}, - {itemDuration, 51, `6m`}, - {itemRightParen, 53, `)`}, - {itemLeftBracket, 54, `[`}, - {itemDuration, 55, `4m`}, - {itemColon, 57, `:`}, - {itemDuration, 58, `3s`}, - {itemRightBracket, 60, `]`}, - }, - }, - { - input: `test:name{o:n!~"bar"}[4m:4s]`, - fail: true, - }, - { - input: `test:name{on!~"bar"}[4m:4s:4h]`, - fail: true, - }, - { - input: `test:name{on!~"bar"}[4m:4s:]`, - fail: true, - }, - { - input: `test:name{on!~"bar"}[4m::]`, - fail: true, - }, - { - input: `test:name{on!~"bar"}[:4s]`, - fail: true, - }, - }, - }, -} - -// TestLexer tests basic functionality of the lexer. More elaborate tests are implemented -// for the parser to avoid duplicated effort. -func TestLexer(t *testing.T) { - for _, typ := range tests { - t.Run(typ.name, func(t *testing.T) { - for i, test := range typ.tests { - l := &lexer{ - input: test.input, - items: make(chan item), - seriesDesc: test.seriesDesc, - } - go l.run() - - out := []item{} - for it := range l.items { - out = append(out, it) - } - - lastItem := out[len(out)-1] - if test.fail { - if lastItem.typ != itemError { - t.Logf("%d: input %q", i, test.input) - t.Fatalf("expected lexing error but did not fail") - } - continue - } - if lastItem.typ == itemError { - t.Logf("%d: input %q", i, test.input) - t.Fatalf("unexpected lexing error at position %d: %s", lastItem.pos, lastItem) - } - - if !reflect.DeepEqual(lastItem, item{itemEOF, Pos(len(test.input)), ""}) { - t.Logf("%d: input %q", i, test.input) - t.Fatalf("lexing error: expected output to end with EOF item.\ngot:\n%s", expectedList(out)) - } - out = out[:len(out)-1] - if !reflect.DeepEqual(out, test.expected) { - t.Logf("%d: input %q", i, test.input) - t.Fatalf("lexing mismatch:\nexpected:\n%s\ngot:\n%s", expectedList(test.expected), expectedList(out)) - } - } - }) - } -} - -func expectedList(exp []item) string { - s := "" - for _, it := range exp { - s += fmt.Sprintf("\t%#v\n", it) - } - return s -} diff --git a/vendor/github.com/prometheus/prometheus/promql/parse_test.go b/vendor/github.com/prometheus/prometheus/promql/parse_test.go deleted file mode 100644 index b826c7c88..000000000 --- a/vendor/github.com/prometheus/prometheus/promql/parse_test.go +++ /dev/null @@ -1,1808 +0,0 @@ -// Copyright 2015 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package promql - -import ( - "fmt" - "math" - "reflect" - "strings" - "testing" - "time" - - "github.com/prometheus/common/model" - "github.com/prometheus/prometheus/pkg/labels" - "github.com/stretchr/testify/require" -) - -var testExpr = []struct { - input string // The input to be parsed. - expected Expr // The expected expression AST. - fail bool // Whether parsing is supposed to fail. - errMsg string // If not empty the parsing error has to contain this string. -}{ - // Scalars and scalar-to-scalar operations. - { - input: "1", - expected: &NumberLiteral{1}, - }, { - input: "+Inf", - expected: &NumberLiteral{math.Inf(1)}, - }, { - input: "-Inf", - expected: &NumberLiteral{math.Inf(-1)}, - }, { - input: ".5", - expected: &NumberLiteral{0.5}, - }, { - input: "5.", - expected: &NumberLiteral{5}, - }, { - input: "123.4567", - expected: &NumberLiteral{123.4567}, - }, { - input: "5e-3", - expected: &NumberLiteral{0.005}, - }, { - input: "5e3", - expected: &NumberLiteral{5000}, - }, { - input: "0xc", - expected: &NumberLiteral{12}, - }, { - input: "0755", - expected: &NumberLiteral{493}, - }, { - input: "+5.5e-3", - expected: &NumberLiteral{0.0055}, - }, { - input: "-0755", - expected: &NumberLiteral{-493}, - }, { - input: "1 + 1", - expected: &BinaryExpr{itemADD, &NumberLiteral{1}, &NumberLiteral{1}, nil, false}, - }, { - input: "1 - 1", - expected: &BinaryExpr{itemSUB, &NumberLiteral{1}, &NumberLiteral{1}, nil, false}, - }, { - input: "1 * 1", - expected: &BinaryExpr{itemMUL, &NumberLiteral{1}, &NumberLiteral{1}, nil, false}, - }, { - input: "1 % 1", - expected: &BinaryExpr{itemMOD, &NumberLiteral{1}, &NumberLiteral{1}, nil, false}, - }, { - input: "1 / 1", - expected: &BinaryExpr{itemDIV, &NumberLiteral{1}, &NumberLiteral{1}, nil, false}, - }, { - input: "1 == bool 1", - expected: &BinaryExpr{itemEQL, &NumberLiteral{1}, &NumberLiteral{1}, nil, true}, - }, { - input: "1 != bool 1", - expected: &BinaryExpr{itemNEQ, &NumberLiteral{1}, &NumberLiteral{1}, nil, true}, - }, { - input: "1 > bool 1", - expected: &BinaryExpr{itemGTR, &NumberLiteral{1}, &NumberLiteral{1}, nil, true}, - }, { - input: "1 >= bool 1", - expected: &BinaryExpr{itemGTE, &NumberLiteral{1}, &NumberLiteral{1}, nil, true}, - }, { - input: "1 < bool 1", - expected: &BinaryExpr{itemLSS, &NumberLiteral{1}, &NumberLiteral{1}, nil, true}, - }, { - input: "1 <= bool 1", - expected: &BinaryExpr{itemLTE, &NumberLiteral{1}, &NumberLiteral{1}, nil, true}, - }, { - input: "+1 + -2 * 1", - expected: &BinaryExpr{ - Op: itemADD, - LHS: &NumberLiteral{1}, - RHS: &BinaryExpr{ - Op: itemMUL, LHS: &NumberLiteral{-2}, RHS: &NumberLiteral{1}, - }, - }, - }, { - input: "1 + 2/(3*1)", - expected: &BinaryExpr{ - Op: itemADD, - LHS: &NumberLiteral{1}, - RHS: &BinaryExpr{ - Op: itemDIV, - LHS: &NumberLiteral{2}, - RHS: &ParenExpr{&BinaryExpr{ - Op: itemMUL, LHS: &NumberLiteral{3}, RHS: &NumberLiteral{1}, - }}, - }, - }, - }, { - input: "1 < bool 2 - 1 * 2", - expected: &BinaryExpr{ - Op: itemLSS, - ReturnBool: true, - LHS: &NumberLiteral{1}, - RHS: &BinaryExpr{ - Op: itemSUB, - LHS: &NumberLiteral{2}, - RHS: &BinaryExpr{ - Op: itemMUL, LHS: &NumberLiteral{1}, RHS: &NumberLiteral{2}, - }, - }, - }, - }, { - input: "-some_metric", - expected: &UnaryExpr{ - Op: itemSUB, - Expr: &VectorSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - }, - }, - }, { - input: "+some_metric", - expected: &UnaryExpr{ - Op: itemADD, - Expr: &VectorSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - }, - }, - }, { - input: "", - fail: true, - errMsg: "no expression found in input", - }, { - input: "# just a comment\n\n", - fail: true, - errMsg: "no expression found in input", - }, { - input: "1+", - fail: true, - errMsg: "no valid expression found", - }, { - input: ".", - fail: true, - errMsg: "unexpected character: '.'", - }, { - input: "2.5.", - fail: true, - errMsg: "could not parse remaining input \".\"...", - }, { - input: "100..4", - fail: true, - errMsg: "could not parse remaining input \".4\"...", - }, { - input: "0deadbeef", - fail: true, - errMsg: "bad number or duration syntax: \"0de\"", - }, { - input: "1 /", - fail: true, - errMsg: "no valid expression found", - }, { - input: "*1", - fail: true, - errMsg: "no valid expression found", - }, { - input: "(1))", - fail: true, - errMsg: "could not parse remaining input \")\"...", - }, { - input: "((1)", - fail: true, - errMsg: "unclosed left parenthesis", - }, { - input: "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", - fail: true, - errMsg: "out of range", - }, { - input: "(", - fail: true, - errMsg: "unclosed left parenthesis", - }, { - input: "1 and 1", - fail: true, - errMsg: "set operator \"and\" not allowed in binary scalar expression", - }, { - input: "1 == 1", - fail: true, - errMsg: "parse error at char 7: comparisons between scalars must use BOOL modifier", - }, { - input: "1 or 1", - fail: true, - errMsg: "set operator \"or\" not allowed in binary scalar expression", - }, { - input: "1 unless 1", - fail: true, - errMsg: "set operator \"unless\" not allowed in binary scalar expression", - }, { - input: "1 !~ 1", - fail: true, - errMsg: "could not parse remaining input \"!~ 1\"...", - }, { - input: "1 =~ 1", - fail: true, - errMsg: "could not parse remaining input \"=~ 1\"...", - }, { - input: `-"string"`, - fail: true, - errMsg: `unary expression only allowed on expressions of type scalar or instant vector, got "string"`, - }, { - input: `-test[5m]`, - fail: true, - errMsg: `unary expression only allowed on expressions of type scalar or instant vector, got "range vector"`, - }, { - input: `*test`, - fail: true, - errMsg: "no valid expression found", - }, { - input: "1 offset 1d", - fail: true, - errMsg: "offset modifier must be preceded by an instant or range selector", - }, { - input: "a - on(b) ignoring(c) d", - fail: true, - errMsg: "parse error at char 11: no valid expression found", - }, - // Vector binary operations. - { - input: "foo * bar", - expected: &BinaryExpr{ - Op: itemMUL, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - VectorMatching: &VectorMatching{Card: CardOneToOne}, - }, - }, { - input: "foo == 1", - expected: &BinaryExpr{ - Op: itemEQL, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &NumberLiteral{1}, - }, - }, { - input: "foo == bool 1", - expected: &BinaryExpr{ - Op: itemEQL, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &NumberLiteral{1}, - ReturnBool: true, - }, - }, { - input: "2.5 / bar", - expected: &BinaryExpr{ - Op: itemDIV, - LHS: &NumberLiteral{2.5}, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - }, - }, { - input: "foo and bar", - expected: &BinaryExpr{ - Op: itemLAND, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - VectorMatching: &VectorMatching{Card: CardManyToMany}, - }, - }, { - input: "foo or bar", - expected: &BinaryExpr{ - Op: itemLOR, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - VectorMatching: &VectorMatching{Card: CardManyToMany}, - }, - }, { - input: "foo unless bar", - expected: &BinaryExpr{ - Op: itemLUnless, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - VectorMatching: &VectorMatching{Card: CardManyToMany}, - }, - }, { - // Test and/or precedence and reassigning of operands. - input: "foo + bar or bla and blub", - expected: &BinaryExpr{ - Op: itemLOR, - LHS: &BinaryExpr{ - Op: itemADD, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - VectorMatching: &VectorMatching{Card: CardOneToOne}, - }, - RHS: &BinaryExpr{ - Op: itemLAND, - LHS: &VectorSelector{ - Name: "bla", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bla"), - }, - }, - RHS: &VectorSelector{ - Name: "blub", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "blub"), - }, - }, - VectorMatching: &VectorMatching{Card: CardManyToMany}, - }, - VectorMatching: &VectorMatching{Card: CardManyToMany}, - }, - }, { - // Test and/or/unless precedence. - input: "foo and bar unless baz or qux", - expected: &BinaryExpr{ - Op: itemLOR, - LHS: &BinaryExpr{ - Op: itemLUnless, - LHS: &BinaryExpr{ - Op: itemLAND, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - VectorMatching: &VectorMatching{Card: CardManyToMany}, - }, - RHS: &VectorSelector{ - Name: "baz", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "baz"), - }, - }, - VectorMatching: &VectorMatching{Card: CardManyToMany}, - }, - RHS: &VectorSelector{ - Name: "qux", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "qux"), - }, - }, - VectorMatching: &VectorMatching{Card: CardManyToMany}, - }, - }, { - // Test precedence and reassigning of operands. - input: "bar + on(foo) bla / on(baz, buz) group_right(test) blub", - expected: &BinaryExpr{ - Op: itemADD, - LHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - RHS: &BinaryExpr{ - Op: itemDIV, - LHS: &VectorSelector{ - Name: "bla", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bla"), - }, - }, - RHS: &VectorSelector{ - Name: "blub", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "blub"), - }, - }, - VectorMatching: &VectorMatching{ - Card: CardOneToMany, - MatchingLabels: []string{"baz", "buz"}, - On: true, - Include: []string{"test"}, - }, - }, - VectorMatching: &VectorMatching{ - Card: CardOneToOne, - MatchingLabels: []string{"foo"}, - On: true, - }, - }, - }, { - input: "foo * on(test,blub) bar", - expected: &BinaryExpr{ - Op: itemMUL, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - VectorMatching: &VectorMatching{ - Card: CardOneToOne, - MatchingLabels: []string{"test", "blub"}, - On: true, - }, - }, - }, { - input: "foo * on(test,blub) group_left bar", - expected: &BinaryExpr{ - Op: itemMUL, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - VectorMatching: &VectorMatching{ - Card: CardManyToOne, - MatchingLabels: []string{"test", "blub"}, - On: true, - }, - }, - }, { - input: "foo and on(test,blub) bar", - expected: &BinaryExpr{ - Op: itemLAND, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - VectorMatching: &VectorMatching{ - Card: CardManyToMany, - MatchingLabels: []string{"test", "blub"}, - On: true, - }, - }, - }, { - input: "foo and on() bar", - expected: &BinaryExpr{ - Op: itemLAND, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - VectorMatching: &VectorMatching{ - Card: CardManyToMany, - MatchingLabels: []string{}, - On: true, - }, - }, - }, { - input: "foo and ignoring(test,blub) bar", - expected: &BinaryExpr{ - Op: itemLAND, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - VectorMatching: &VectorMatching{ - Card: CardManyToMany, - MatchingLabels: []string{"test", "blub"}, - }, - }, - }, { - input: "foo and ignoring() bar", - expected: &BinaryExpr{ - Op: itemLAND, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - VectorMatching: &VectorMatching{ - Card: CardManyToMany, - MatchingLabels: []string{}, - }, - }, - }, { - input: "foo unless on(bar) baz", - expected: &BinaryExpr{ - Op: itemLUnless, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "baz", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "baz"), - }, - }, - VectorMatching: &VectorMatching{ - Card: CardManyToMany, - MatchingLabels: []string{"bar"}, - On: true, - }, - }, - }, { - input: "foo / on(test,blub) group_left(bar) bar", - expected: &BinaryExpr{ - Op: itemDIV, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - VectorMatching: &VectorMatching{ - Card: CardManyToOne, - MatchingLabels: []string{"test", "blub"}, - On: true, - Include: []string{"bar"}, - }, - }, - }, { - input: "foo / ignoring(test,blub) group_left(blub) bar", - expected: &BinaryExpr{ - Op: itemDIV, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - VectorMatching: &VectorMatching{ - Card: CardManyToOne, - MatchingLabels: []string{"test", "blub"}, - Include: []string{"blub"}, - }, - }, - }, { - input: "foo / ignoring(test,blub) group_left(bar) bar", - expected: &BinaryExpr{ - Op: itemDIV, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - VectorMatching: &VectorMatching{ - Card: CardManyToOne, - MatchingLabels: []string{"test", "blub"}, - Include: []string{"bar"}, - }, - }, - }, { - input: "foo - on(test,blub) group_right(bar,foo) bar", - expected: &BinaryExpr{ - Op: itemSUB, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - VectorMatching: &VectorMatching{ - Card: CardOneToMany, - MatchingLabels: []string{"test", "blub"}, - Include: []string{"bar", "foo"}, - On: true, - }, - }, - }, { - input: "foo - ignoring(test,blub) group_right(bar,foo) bar", - expected: &BinaryExpr{ - Op: itemSUB, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - VectorMatching: &VectorMatching{ - Card: CardOneToMany, - MatchingLabels: []string{"test", "blub"}, - Include: []string{"bar", "foo"}, - }, - }, - }, { - input: "foo and 1", - fail: true, - errMsg: "set operator \"and\" not allowed in binary scalar expression", - }, { - input: "1 and foo", - fail: true, - errMsg: "set operator \"and\" not allowed in binary scalar expression", - }, { - input: "foo or 1", - fail: true, - errMsg: "set operator \"or\" not allowed in binary scalar expression", - }, { - input: "1 or foo", - fail: true, - errMsg: "set operator \"or\" not allowed in binary scalar expression", - }, { - input: "foo unless 1", - fail: true, - errMsg: "set operator \"unless\" not allowed in binary scalar expression", - }, { - input: "1 unless foo", - fail: true, - errMsg: "set operator \"unless\" not allowed in binary scalar expression", - }, { - input: "1 or on(bar) foo", - fail: true, - errMsg: "vector matching only allowed between instant vectors", - }, { - input: "foo == on(bar) 10", - fail: true, - errMsg: "vector matching only allowed between instant vectors", - }, { - input: "foo and on(bar) group_left(baz) bar", - fail: true, - errMsg: "no grouping allowed for \"and\" operation", - }, { - input: "foo and on(bar) group_right(baz) bar", - fail: true, - errMsg: "no grouping allowed for \"and\" operation", - }, { - input: "foo or on(bar) group_left(baz) bar", - fail: true, - errMsg: "no grouping allowed for \"or\" operation", - }, { - input: "foo or on(bar) group_right(baz) bar", - fail: true, - errMsg: "no grouping allowed for \"or\" operation", - }, { - input: "foo unless on(bar) group_left(baz) bar", - fail: true, - errMsg: "no grouping allowed for \"unless\" operation", - }, { - input: "foo unless on(bar) group_right(baz) bar", - fail: true, - errMsg: "no grouping allowed for \"unless\" operation", - }, { - input: `http_requests{group="production"} + on(instance) group_left(job,instance) cpu_count{type="smp"}`, - fail: true, - errMsg: "label \"instance\" must not occur in ON and GROUP clause at once", - }, { - input: "foo + bool bar", - fail: true, - errMsg: "bool modifier can only be used on comparison operators", - }, { - input: "foo + bool 10", - fail: true, - errMsg: "bool modifier can only be used on comparison operators", - }, { - input: "foo and bool 10", - fail: true, - errMsg: "bool modifier can only be used on comparison operators", - }, - // Test Vector selector. - { - input: "foo", - expected: &VectorSelector{ - Name: "foo", - Offset: 0, - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - }, { - input: "foo offset 5m", - expected: &VectorSelector{ - Name: "foo", - Offset: 5 * time.Minute, - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - }, { - input: `foo:bar{a="bc"}`, - expected: &VectorSelector{ - Name: "foo:bar", - Offset: 0, - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, "a", "bc"), - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo:bar"), - }, - }, - }, { - input: `foo{NaN='bc'}`, - expected: &VectorSelector{ - Name: "foo", - Offset: 0, - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, "NaN", "bc"), - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - }, { - input: `foo{a="b", foo!="bar", test=~"test", bar!~"baz"}`, - expected: &VectorSelector{ - Name: "foo", - Offset: 0, - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, "a", "b"), - mustLabelMatcher(labels.MatchNotEqual, "foo", "bar"), - mustLabelMatcher(labels.MatchRegexp, "test", "test"), - mustLabelMatcher(labels.MatchNotRegexp, "bar", "baz"), - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - }, { - input: `{`, - fail: true, - errMsg: "unexpected end of input inside braces", - }, { - input: `}`, - fail: true, - errMsg: "unexpected character: '}'", - }, { - input: `some{`, - fail: true, - errMsg: "unexpected end of input inside braces", - }, { - input: `some}`, - fail: true, - errMsg: "could not parse remaining input \"}\"...", - }, { - input: `some_metric{a=b}`, - fail: true, - errMsg: "unexpected identifier \"b\" in label matching, expected string", - }, { - input: `some_metric{a:b="b"}`, - fail: true, - errMsg: "unexpected character inside braces: ':'", - }, { - input: `foo{a*"b"}`, - fail: true, - errMsg: "unexpected character inside braces: '*'", - }, { - input: `foo{a>="b"}`, - fail: true, - // TODO(fabxc): willingly lexing wrong tokens allows for more precrise error - // messages from the parser - consider if this is an option. - errMsg: "unexpected character inside braces: '>'", - }, { - input: "some_metric{a=\"\xff\"}", - fail: true, - errMsg: "parse error at char 15: invalid UTF-8 rune", - }, { - input: `foo{gibberish}`, - fail: true, - errMsg: "expected label matching operator but got }", - }, { - input: `foo{1}`, - fail: true, - errMsg: "unexpected character inside braces: '1'", - }, { - input: `{}`, - fail: true, - errMsg: "vector selector must contain label matchers or metric name", - }, { - input: `{x=""}`, - fail: true, - errMsg: "vector selector must contain at least one non-empty matcher", - }, { - input: `{x=~".*"}`, - fail: true, - errMsg: "vector selector must contain at least one non-empty matcher", - }, { - input: `{x!~".+"}`, - fail: true, - errMsg: "vector selector must contain at least one non-empty matcher", - }, { - input: `{x!="a"}`, - fail: true, - errMsg: "vector selector must contain at least one non-empty matcher", - }, { - input: `foo{__name__="bar"}`, - fail: true, - errMsg: "metric name must not be set twice: \"foo\" or \"bar\"", - }, - // Test matrix selector. - { - input: "test[5s]", - expected: &MatrixSelector{ - Name: "test", - Offset: 0, - Range: 5 * time.Second, - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "test"), - }, - }, - }, { - input: "test[5m]", - expected: &MatrixSelector{ - Name: "test", - Offset: 0, - Range: 5 * time.Minute, - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "test"), - }, - }, - }, { - input: "test[5h] OFFSET 5m", - expected: &MatrixSelector{ - Name: "test", - Offset: 5 * time.Minute, - Range: 5 * time.Hour, - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "test"), - }, - }, - }, { - input: "test[5d] OFFSET 10s", - expected: &MatrixSelector{ - Name: "test", - Offset: 10 * time.Second, - Range: 5 * 24 * time.Hour, - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "test"), - }, - }, - }, { - input: "test[5w] offset 2w", - expected: &MatrixSelector{ - Name: "test", - Offset: 14 * 24 * time.Hour, - Range: 5 * 7 * 24 * time.Hour, - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "test"), - }, - }, - }, { - input: `test{a="b"}[5y] OFFSET 3d`, - expected: &MatrixSelector{ - Name: "test", - Offset: 3 * 24 * time.Hour, - Range: 5 * 365 * 24 * time.Hour, - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, "a", "b"), - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "test"), - }, - }, - }, { - input: `foo[5mm]`, - fail: true, - errMsg: "bad duration syntax: \"5mm\"", - }, { - input: `foo[0m]`, - fail: true, - errMsg: "duration must be greater than 0", - }, { - input: `foo[5m30s]`, - fail: true, - errMsg: "bad duration syntax: \"5m3\"", - }, { - input: `foo[5m] OFFSET 1h30m`, - fail: true, - errMsg: "bad number or duration syntax: \"1h3\"", - }, { - input: `foo["5m"]`, - fail: true, - }, { - input: `foo[]`, - fail: true, - errMsg: "missing unit character in duration", - }, { - input: `foo[1]`, - fail: true, - errMsg: "missing unit character in duration", - }, { - input: `some_metric[5m] OFFSET 1`, - fail: true, - errMsg: "unexpected number \"1\" in offset, expected duration", - }, { - input: `some_metric[5m] OFFSET 1mm`, - fail: true, - errMsg: "bad number or duration syntax: \"1mm\"", - }, { - input: `some_metric[5m] OFFSET`, - fail: true, - errMsg: "unexpected end of input in offset, expected duration", - }, { - input: `some_metric OFFSET 1m[5m]`, - fail: true, - errMsg: "parse error at char 25: unexpected \"]\" in subquery selector, expected \":\"", - }, { - input: `(foo + bar)[5m]`, - fail: true, - errMsg: "parse error at char 15: unexpected \"]\" in subquery selector, expected \":\"", - }, - // Test aggregation. - { - input: "sum by (foo)(some_metric)", - expected: &AggregateExpr{ - Op: itemSum, - Expr: &VectorSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - }, - Grouping: []string{"foo"}, - }, - }, { - input: "avg by (foo)(some_metric)", - expected: &AggregateExpr{ - Op: itemAvg, - Expr: &VectorSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - }, - Grouping: []string{"foo"}, - }, - }, { - input: "max by (foo)(some_metric)", - expected: &AggregateExpr{ - Op: itemMax, - Expr: &VectorSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - }, - Grouping: []string{"foo"}, - }, - }, { - input: "sum without (foo) (some_metric)", - expected: &AggregateExpr{ - Op: itemSum, - Without: true, - Expr: &VectorSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - }, - Grouping: []string{"foo"}, - }, - }, { - input: "sum (some_metric) without (foo)", - expected: &AggregateExpr{ - Op: itemSum, - Without: true, - Expr: &VectorSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - }, - Grouping: []string{"foo"}, - }, - }, { - input: "stddev(some_metric)", - expected: &AggregateExpr{ - Op: itemStddev, - Expr: &VectorSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - }, - }, - }, { - input: "stdvar by (foo)(some_metric)", - expected: &AggregateExpr{ - Op: itemStdvar, - Expr: &VectorSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - }, - Grouping: []string{"foo"}, - }, - }, { - input: "sum by ()(some_metric)", - expected: &AggregateExpr{ - Op: itemSum, - Expr: &VectorSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - }, - Grouping: []string{}, - }, - }, { - input: "topk(5, some_metric)", - expected: &AggregateExpr{ - Op: itemTopK, - Expr: &VectorSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - }, - Param: &NumberLiteral{5}, - }, - }, { - input: "count_values(\"value\", some_metric)", - expected: &AggregateExpr{ - Op: itemCountValues, - Expr: &VectorSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - }, - Param: &StringLiteral{"value"}, - }, - }, { - // Test usage of keywords as label names. - input: "sum without(and, by, avg, count, alert, annotations)(some_metric)", - expected: &AggregateExpr{ - Op: itemSum, - Without: true, - Expr: &VectorSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - }, - Grouping: []string{"and", "by", "avg", "count", "alert", "annotations"}, - }, - }, { - input: "sum without(==)(some_metric)", - fail: true, - errMsg: "unexpected in grouping opts, expected label", - }, { - input: `sum some_metric by (test)`, - fail: true, - errMsg: "unexpected identifier \"some_metric\" in aggregation, expected \"(\"", - }, { - input: `sum (some_metric) by test`, - fail: true, - errMsg: "unexpected identifier \"test\" in grouping opts, expected \"(\"", - }, { - input: `sum (some_metric) by test`, - fail: true, - errMsg: "unexpected identifier \"test\" in grouping opts, expected \"(\"", - }, { - input: `sum () by (test)`, - fail: true, - errMsg: "no valid expression found", - }, { - input: "MIN keep_common (some_metric)", - fail: true, - errMsg: "parse error at char 5: unexpected identifier \"keep_common\" in aggregation, expected \"(\"", - }, { - input: "MIN (some_metric) keep_common", - fail: true, - errMsg: "could not parse remaining input \"keep_common\"...", - }, { - input: `sum (some_metric) without (test) by (test)`, - fail: true, - errMsg: "could not parse remaining input \"by (test)\"...", - }, { - input: `sum without (test) (some_metric) by (test)`, - fail: true, - errMsg: "could not parse remaining input \"by (test)\"...", - }, { - input: `topk(some_metric)`, - fail: true, - errMsg: "parse error at char 17: unexpected \")\" in aggregation, expected \",\"", - }, { - input: `topk(some_metric, other_metric)`, - fail: true, - errMsg: "parse error at char 32: expected type scalar in aggregation parameter, got instant vector", - }, { - input: `count_values(5, other_metric)`, - fail: true, - errMsg: "parse error at char 30: expected type string in aggregation parameter, got scalar", - }, - // Test function calls. - { - input: "time()", - expected: &Call{ - Func: mustGetFunction("time"), - }, - }, { - input: `floor(some_metric{foo!="bar"})`, - expected: &Call{ - Func: mustGetFunction("floor"), - Args: Expressions{ - &VectorSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchNotEqual, "foo", "bar"), - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - }, - }, - }, - }, { - input: "rate(some_metric[5m])", - expected: &Call{ - Func: mustGetFunction("rate"), - Args: Expressions{ - &MatrixSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - Range: 5 * time.Minute, - }, - }, - }, - }, { - input: "round(some_metric)", - expected: &Call{ - Func: mustGetFunction("round"), - Args: Expressions{ - &VectorSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - }, - }, - }, - }, { - input: "round(some_metric, 5)", - expected: &Call{ - Func: mustGetFunction("round"), - Args: Expressions{ - &VectorSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - }, - &NumberLiteral{5}, - }, - }, - }, { - input: "floor()", - fail: true, - errMsg: "expected 1 argument(s) in call to \"floor\", got 0", - }, { - input: "floor(some_metric, other_metric)", - fail: true, - errMsg: "expected 1 argument(s) in call to \"floor\", got 2", - }, { - input: "floor(1)", - fail: true, - errMsg: "expected type instant vector in call to function \"floor\", got scalar", - }, { - input: "non_existent_function_far_bar()", - fail: true, - errMsg: "unknown function with name \"non_existent_function_far_bar\"", - }, { - input: "rate(some_metric)", - fail: true, - errMsg: "expected type range vector in call to function \"rate\", got instant vector", - }, { - input: "label_replace(a, `b`, `c\xff`, `d`, `.*`)", - fail: true, - errMsg: "parse error at char 23: invalid UTF-8 rune", - }, - // Fuzzing regression tests. - { - input: "-=", - fail: true, - errMsg: `no valid expression found`, - }, { - input: "++-++-+-+-<", - fail: true, - errMsg: `no valid expression found`, - }, { - input: "e-+=/(0)", - fail: true, - errMsg: `no valid expression found`, - }, - // String quoting and escape sequence interpretation tests. - { - input: `"double-quoted string \" with escaped quote"`, - expected: &StringLiteral{ - Val: "double-quoted string \" with escaped quote", - }, - }, { - input: `'single-quoted string \' with escaped quote'`, - expected: &StringLiteral{ - Val: "single-quoted string ' with escaped quote", - }, - }, { - input: "`backtick-quoted string`", - expected: &StringLiteral{ - Val: "backtick-quoted string", - }, - }, { - input: `"\a\b\f\n\r\t\v\\\" - \xFF\377\u1234\U00010111\U0001011111☺"`, - expected: &StringLiteral{ - Val: "\a\b\f\n\r\t\v\\\" - \xFF\377\u1234\U00010111\U0001011111☺", - }, - }, { - input: `'\a\b\f\n\r\t\v\\\' - \xFF\377\u1234\U00010111\U0001011111☺'`, - expected: &StringLiteral{ - Val: "\a\b\f\n\r\t\v\\' - \xFF\377\u1234\U00010111\U0001011111☺", - }, - }, { - input: "`" + `\a\b\f\n\r\t\v\\\"\' - \xFF\377\u1234\U00010111\U0001011111☺` + "`", - expected: &StringLiteral{ - Val: `\a\b\f\n\r\t\v\\\"\' - \xFF\377\u1234\U00010111\U0001011111☺`, - }, - }, { - input: "`\\``", - fail: true, - errMsg: "could not parse remaining input", - }, { - input: `"\`, - fail: true, - errMsg: "escape sequence not terminated", - }, { - input: `"\c"`, - fail: true, - errMsg: "unknown escape sequence U+0063 'c'", - }, { - input: `"\x."`, - fail: true, - errMsg: "illegal character U+002E '.' in escape sequence", - }, - // Subquery. - { - input: `foo{bar="baz"}[10m:6s]`, - expected: &SubqueryExpr{ - Expr: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, "bar", "baz"), - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - Range: 10 * time.Minute, - Step: 6 * time.Second, - }, - }, { - input: `foo[10m:]`, - expected: &SubqueryExpr{ - Expr: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - Range: 10 * time.Minute, - }, - }, { - input: `min_over_time(rate(foo{bar="baz"}[2s])[5m:5s])`, - expected: &Call{ - Func: mustGetFunction("min_over_time"), - Args: Expressions{ - &SubqueryExpr{ - Expr: &Call{ - Func: mustGetFunction("rate"), - Args: Expressions{ - &MatrixSelector{ - Name: "foo", - Range: 2 * time.Second, - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, "bar", "baz"), - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - }, - }, - Range: 5 * time.Minute, - Step: 5 * time.Second, - }, - }, - }, - }, { - input: `min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s]`, - expected: &SubqueryExpr{ - Expr: &Call{ - Func: mustGetFunction("min_over_time"), - Args: Expressions{ - &SubqueryExpr{ - Expr: &Call{ - Func: mustGetFunction("rate"), - Args: Expressions{ - &MatrixSelector{ - Name: "foo", - Range: 2 * time.Second, - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, "bar", "baz"), - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - }, - }, - Range: 5 * time.Minute, - }, - }, - }, - Range: 4 * time.Minute, - Step: 3 * time.Second, - }, - }, { - input: `min_over_time(rate(foo{bar="baz"}[2s])[5m:] offset 4m)[4m:3s]`, - expected: &SubqueryExpr{ - Expr: &Call{ - Func: mustGetFunction("min_over_time"), - Args: Expressions{ - &SubqueryExpr{ - Expr: &Call{ - Func: mustGetFunction("rate"), - Args: Expressions{ - &MatrixSelector{ - Name: "foo", - Range: 2 * time.Second, - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, "bar", "baz"), - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - }, - }, - Range: 5 * time.Minute, - Offset: 4 * time.Minute, - }, - }, - }, - Range: 4 * time.Minute, - Step: 3 * time.Second, - }, - }, { - input: "sum without(and, by, avg, count, alert, annotations)(some_metric) [30m:10s]", - expected: &SubqueryExpr{ - Expr: &AggregateExpr{ - Op: itemSum, - Without: true, - Expr: &VectorSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - }, - Grouping: []string{"and", "by", "avg", "count", "alert", "annotations"}, - }, - Range: 30 * time.Minute, - Step: 10 * time.Second, - }, - }, { - input: `some_metric OFFSET 1m [10m:5s]`, - expected: &SubqueryExpr{ - Expr: &VectorSelector{ - Name: "some_metric", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "some_metric"), - }, - Offset: 1 * time.Minute, - }, - Range: 10 * time.Minute, - Step: 5 * time.Second, - }, - }, { - input: `(foo + bar{nm="val"})[5m:]`, - expected: &SubqueryExpr{ - Expr: &ParenExpr{ - Expr: &BinaryExpr{ - Op: itemADD, - VectorMatching: &VectorMatching{ - Card: CardOneToOne, - }, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, "nm", "val"), - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - }, - }, - Range: 5 * time.Minute, - }, - }, { - input: `(foo + bar{nm="val"})[5m:] offset 10m`, - expected: &SubqueryExpr{ - Expr: &ParenExpr{ - Expr: &BinaryExpr{ - Op: itemADD, - VectorMatching: &VectorMatching{ - Card: CardOneToOne, - }, - LHS: &VectorSelector{ - Name: "foo", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "foo"), - }, - }, - RHS: &VectorSelector{ - Name: "bar", - LabelMatchers: []*labels.Matcher{ - mustLabelMatcher(labels.MatchEqual, "nm", "val"), - mustLabelMatcher(labels.MatchEqual, string(model.MetricNameLabel), "bar"), - }, - }, - }, - }, - Range: 5 * time.Minute, - Offset: 10 * time.Minute, - }, - }, { - input: "test[5d] OFFSET 10s [10m:5s]", - fail: true, - errMsg: "parse error at char 29: subquery is only allowed on instant vector, got matrix in \"test[5d] offset 10s[10m:5s]\"", - }, { - input: `(foo + bar{nm="val"})[5m:][10m:5s]`, - fail: true, - errMsg: "parse error at char 27: could not parse remaining input \"[10m:5s]\"...", - }, -} - -func TestParseExpressions(t *testing.T) { - for _, test := range testExpr { - expr, err := ParseExpr(test.input) - - // Unexpected errors are always caused by a bug. - if err == errUnexpected { - t.Fatalf("unexpected error occurred") - } - - if !test.fail && err != nil { - t.Errorf("error in input '%s'", test.input) - t.Fatalf("could not parse: %s", err) - } - - if test.fail && err != nil { - if !strings.Contains(err.Error(), test.errMsg) { - t.Errorf("unexpected error on input '%s'", test.input) - t.Fatalf("expected error to contain %q but got %q", test.errMsg, err) - } - continue - } - - if !reflect.DeepEqual(expr, test.expected) { - t.Errorf("error on input '%s'", test.input) - t.Fatalf("no match\n\nexpected:\n%s\ngot: \n%s\n", Tree(test.expected), Tree(expr)) - } - } -} - -// NaN has no equality. Thus, we need a separate test for it. -func TestNaNExpression(t *testing.T) { - expr, err := ParseExpr("NaN") - if err != nil { - t.Errorf("error on input 'NaN'") - t.Fatalf("could not parse: %s", err) - } - - nl, ok := expr.(*NumberLiteral) - if !ok { - t.Errorf("error on input 'NaN'") - t.Fatalf("expected number literal but got %T", expr) - } - - if !math.IsNaN(float64(nl.Val)) { - t.Errorf("error on input 'NaN'") - t.Fatalf("expected 'NaN' in number literal but got %v", nl.Val) - } -} - -func mustLabelMatcher(mt labels.MatchType, name, val string) *labels.Matcher { - m, err := labels.NewMatcher(mt, name, val) - if err != nil { - panic(err) - } - return m -} - -func mustGetFunction(name string) *Function { - f, ok := getFunction(name) - if !ok { - panic(fmt.Errorf("function %q does not exist", name)) - } - return f -} - -var testSeries = []struct { - input string - expectedMetric labels.Labels - expectedValues []sequenceValue - fail bool -}{ - { - input: `{} 1 2 3`, - expectedMetric: labels.Labels{}, - expectedValues: newSeq(1, 2, 3), - }, { - input: `{a="b"} -1 2 3`, - expectedMetric: labels.FromStrings("a", "b"), - expectedValues: newSeq(-1, 2, 3), - }, { - input: `my_metric 1 2 3`, - expectedMetric: labels.FromStrings(labels.MetricName, "my_metric"), - expectedValues: newSeq(1, 2, 3), - }, { - input: `my_metric{} 1 2 3`, - expectedMetric: labels.FromStrings(labels.MetricName, "my_metric"), - expectedValues: newSeq(1, 2, 3), - }, { - input: `my_metric{a="b"} 1 2 3`, - expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"), - expectedValues: newSeq(1, 2, 3), - }, { - input: `my_metric{a="b"} 1 2 3-10x4`, - expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"), - expectedValues: newSeq(1, 2, 3, -7, -17, -27, -37), - }, { - input: `my_metric{a="b"} 1 2 3-0x4`, - expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"), - expectedValues: newSeq(1, 2, 3, 3, 3, 3, 3), - }, { - input: `my_metric{a="b"} 1 3 _ 5 _x4`, - expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"), - expectedValues: newSeq(1, 3, none, 5, none, none, none, none), - }, { - input: `my_metric{a="b"} 1 3 _ 5 _a4`, - fail: true, - }, { - input: `my_metric{a="b"} 1 -1`, - expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"), - expectedValues: newSeq(1, -1), - }, { - input: `my_metric{a="b"} 1 +1`, - expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"), - expectedValues: newSeq(1, 1), - }, { - input: `my_metric{a="b"} 1 -1 -3-10x4 7 9 +5`, - expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"), - expectedValues: newSeq(1, -1, -3, -13, -23, -33, -43, 7, 9, 5), - }, { - input: `my_metric{a="b"} 1 +1 +4 -6 -2 8`, - expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"), - expectedValues: newSeq(1, 1, 4, -6, -2, 8), - }, { - // Trailing spaces should be correctly handles. - input: `my_metric{a="b"} 1 2 3 `, - expectedMetric: labels.FromStrings(labels.MetricName, "my_metric", "a", "b"), - expectedValues: newSeq(1, 2, 3), - }, { - input: `my_metric{a="b"} -3-3 -3`, - fail: true, - }, { - input: `my_metric{a="b"} -3 -3-3`, - fail: true, - }, { - input: `my_metric{a="b"} -3 _-2`, - fail: true, - }, { - input: `my_metric{a="b"} -3 3+3x4-4`, - fail: true, - }, -} - -// For these tests only, we use the smallest float64 to signal an omitted value. -const none = math.SmallestNonzeroFloat64 - -func newSeq(vals ...float64) (res []sequenceValue) { - for _, v := range vals { - if v == none { - res = append(res, sequenceValue{omitted: true}) - } else { - res = append(res, sequenceValue{value: v}) - } - } - return res -} - -func TestParseSeries(t *testing.T) { - for _, test := range testSeries { - metric, vals, err := parseSeriesDesc(test.input) - - // Unexpected errors are always caused by a bug. - if err == errUnexpected { - t.Fatalf("unexpected error occurred") - } - - if test.fail { - if err != nil { - continue - } - t.Errorf("error in input: \n\n%s\n", test.input) - t.Fatalf("failure expected, but passed") - } else { - if err != nil { - t.Errorf("error in input: \n\n%s\n", test.input) - t.Fatalf("could not parse: %s", err) - } - } - - require.Equal(t, test.expectedMetric, metric) - require.Equal(t, test.expectedValues, vals) - - if !reflect.DeepEqual(vals, test.expectedValues) || !reflect.DeepEqual(metric, test.expectedMetric) { - t.Errorf("error in input: \n\n%s\n", test.input) - t.Fatalf("no match\n\nexpected:\n%s %s\ngot: \n%s %s\n", test.expectedMetric, test.expectedValues, metric, vals) - } - } -} - -func TestRecoverParserRuntime(t *testing.T) { - p := newParser("foo bar") - var err error - - defer func() { - if err != errUnexpected { - t.Fatalf("wrong error message: %q, expected %q", err, errUnexpected) - } - - if _, ok := <-p.lex.items; ok { - t.Fatalf("lex.items was not closed") - } - }() - defer p.recover(&err) - // Cause a runtime panic. - var a []int - a[123] = 1 -} - -func TestRecoverParserError(t *testing.T) { - p := newParser("foo bar") - var err error - - e := fmt.Errorf("custom error") - - defer func() { - if err.Error() != e.Error() { - t.Fatalf("wrong error message: %q, expected %q", err, e) - } - }() - defer p.recover(&err) - - panic(e) -} diff --git a/vendor/github.com/prometheus/prometheus/promql/printer_test.go b/vendor/github.com/prometheus/prometheus/promql/printer_test.go deleted file mode 100644 index 9abb59557..000000000 --- a/vendor/github.com/prometheus/prometheus/promql/printer_test.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2015 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package promql - -import ( - "testing" -) - -func TestExprString(t *testing.T) { - // A list of valid expressions that are expected to be - // returned as out when calling String(). If out is empty the output - // is expected to equal the input. - inputs := []struct { - in, out string - }{ - { - in: `sum by() (task:errors:rate10s{job="s"})`, - out: `sum(task:errors:rate10s{job="s"})`, - }, - { - in: `sum by(code) (task:errors:rate10s{job="s"})`, - }, - { - in: `sum without() (task:errors:rate10s{job="s"})`, - }, - { - in: `sum without(instance) (task:errors:rate10s{job="s"})`, - }, - { - in: `topk(5, task:errors:rate10s{job="s"})`, - }, - { - in: `count_values("value", task:errors:rate10s{job="s"})`, - }, - { - in: `a - on() c`, - }, - { - in: `a - on(b) c`, - }, - { - in: `a - on(b) group_left(x) c`, - }, - { - in: `a - on(b) group_left(x, y) c`, - }, - { - in: `a - on(b) group_left c`, - out: `a - on(b) group_left() c`, - }, - { - in: `a - on(b) group_left() (c)`, - }, - { - in: `a - ignoring(b) c`, - }, - { - in: `a - ignoring() c`, - out: `a - c`, - }, - { - in: `up > bool 0`, - }, - { - in: `a offset 1m`, - }, - { - in: `a{c="d"}[5m] offset 1m`, - }, - { - in: `a[5m] offset 1m`, - }, - } - - for _, test := range inputs { - expr, err := ParseExpr(test.in) - if err != nil { - t.Fatalf("parsing error for %q: %s", test.in, err) - } - exp := test.in - if test.out != "" { - exp = test.out - } - if expr.String() != exp { - t.Fatalf("expected %q to be returned as:\n%s\ngot:\n%s\n", test.in, exp, expr.String()) - } - } -} diff --git a/vendor/github.com/prometheus/prometheus/promql/promql_test.go b/vendor/github.com/prometheus/prometheus/promql/promql_test.go deleted file mode 100644 index 77f8aa31b..000000000 --- a/vendor/github.com/prometheus/prometheus/promql/promql_test.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2015 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package promql - -import ( - "path/filepath" - "testing" -) - -func TestEvaluations(t *testing.T) { - files, err := filepath.Glob("testdata/*.test") - if err != nil { - t.Fatal(err) - } - for _, fn := range files { - test, err := newTestFromFile(t, fn) - if err != nil { - t.Errorf("error creating test for %s: %s", fn, err) - } - err = test.Run() - if err != nil { - t.Errorf("error running test %s: %s", fn, err) - } - test.Close() - } -} diff --git a/vendor/github.com/prometheus/prometheus/promql/test_test.go b/vendor/github.com/prometheus/prometheus/promql/test_test.go deleted file mode 100644 index 140a8595c..000000000 --- a/vendor/github.com/prometheus/prometheus/promql/test_test.go +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2019 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package promql - -import ( - "math" - "testing" - "time" - - "github.com/prometheus/prometheus/pkg/labels" - - "github.com/prometheus/prometheus/util/testutil" -) - -func TestLazyLoader_WithSamplesTill(t *testing.T) { - type testCase struct { - ts time.Time - series []Series // Each series is checked separately. Need not mention all series here. - checkOnlyError bool // If this is true, series is not checked. - } - - cases := []struct { - loadString string - // These testCases are run in sequence. So the testCase being run is dependant on the previous testCase. - testCases []testCase - }{ - { - loadString: ` - load 10s - metric1 1+1x10 - `, - testCases: []testCase{ - { - ts: time.Unix(40, 0), - series: []Series{ - { - Metric: labels.FromStrings("__name__", "metric1"), - Points: []Point{ - {0, 1}, {10000, 2}, {20000, 3}, {30000, 4}, {40000, 5}, - }, - }, - }, - }, - { - ts: time.Unix(10, 0), - series: []Series{ - { - Metric: labels.FromStrings("__name__", "metric1"), - Points: []Point{ - {0, 1}, {10000, 2}, {20000, 3}, {30000, 4}, {40000, 5}, - }, - }, - }, - }, - { - ts: time.Unix(60, 0), - series: []Series{ - { - Metric: labels.FromStrings("__name__", "metric1"), - Points: []Point{ - {0, 1}, {10000, 2}, {20000, 3}, {30000, 4}, {40000, 5}, {50000, 6}, {60000, 7}, - }, - }, - }, - }, - }, - }, - { - loadString: ` - load 10s - metric1 1+0x5 - metric2 1+1x100 - `, - testCases: []testCase{ - { // Adds all samples of metric1. - ts: time.Unix(70, 0), - series: []Series{ - { - Metric: labels.FromStrings("__name__", "metric1"), - Points: []Point{ - {0, 1}, {10000, 1}, {20000, 1}, {30000, 1}, {40000, 1}, {50000, 1}, - }, - }, - { - Metric: labels.FromStrings("__name__", "metric2"), - Points: []Point{ - {0, 1}, {10000, 2}, {20000, 3}, {30000, 4}, {40000, 5}, {50000, 6}, {60000, 7}, {70000, 8}, - }, - }, - }, - }, - { // This tests fix for https://github.com/prometheus/prometheus/issues/5064. - ts: time.Unix(300, 0), - checkOnlyError: true, - }, - }, - }, - } - - for _, c := range cases { - suite, err := NewLazyLoader(t, c.loadString) - testutil.Ok(t, err) - defer suite.Close() - - for _, tc := range c.testCases { - suite.WithSamplesTill(tc.ts, func(err error) { - testutil.Ok(t, err) - if tc.checkOnlyError { - return - } - - // Check the series. - queryable := suite.Queryable() - querier, err := queryable.Querier(suite.Context(), math.MinInt64, math.MaxInt64) - testutil.Ok(t, err) - for _, s := range tc.series { - var matchers []*labels.Matcher - for _, label := range s.Metric { - m, err := labels.NewMatcher(labels.MatchEqual, label.Name, label.Value) - testutil.Ok(t, err) - matchers = append(matchers, m) - } - - // Get the series for the matcher. - ss, _, err := querier.Select(nil, matchers...) - testutil.Ok(t, err) - testutil.Assert(t, ss.Next(), "") - storageSeries := ss.At() - testutil.Assert(t, !ss.Next(), "Expecting only 1 series") - - // Convert `storage.Series` to `promql.Series`. - got := Series{ - Metric: storageSeries.Labels(), - } - it := storageSeries.Iterator() - for it.Next() { - t, v := it.At() - got.Points = append(got.Points, Point{T: t, V: v}) - } - testutil.Ok(t, it.Err()) - - testutil.Equals(t, s, got) - } - }) - } - } -} diff --git a/vendor/github.com/prometheus/prometheus/storage/buffer_test.go b/vendor/github.com/prometheus/prometheus/storage/buffer_test.go deleted file mode 100644 index da4376fa9..000000000 --- a/vendor/github.com/prometheus/prometheus/storage/buffer_test.go +++ /dev/null @@ -1,272 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package storage - -import ( - "math/rand" - "sort" - "testing" - - "github.com/prometheus/prometheus/pkg/labels" - "github.com/stretchr/testify/require" -) - -func TestSampleRing(t *testing.T) { - cases := []struct { - input []int64 - delta int64 - size int - }{ - { - input: []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, - delta: 2, - size: 1, - }, - { - input: []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, - delta: 2, - size: 2, - }, - { - input: []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, - delta: 7, - size: 3, - }, - { - input: []int64{1, 2, 3, 4, 5, 16, 17, 18, 19, 20}, - delta: 7, - size: 1, - }, - { - input: []int64{1, 2, 3, 4, 6}, - delta: 4, - size: 4, - }, - } - for _, c := range cases { - r := newSampleRing(c.delta, c.size) - - input := []sample{} - for _, t := range c.input { - input = append(input, sample{ - t: t, - v: float64(rand.Intn(100)), - }) - } - - for i, s := range input { - r.add(s.t, s.v) - buffered := r.samples() - - for _, sold := range input[:i] { - found := false - for _, bs := range buffered { - if bs.t == sold.t && bs.v == sold.v { - found = true - break - } - } - if sold.t >= s.t-c.delta && !found { - t.Fatalf("%d: expected sample %d to be in buffer but was not; buffer %v", i, sold.t, buffered) - } - if sold.t < s.t-c.delta && found { - t.Fatalf("%d: unexpected sample %d in buffer; buffer %v", i, sold.t, buffered) - } - } - } - } -} - -func TestBufferedSeriesIterator(t *testing.T) { - var it *BufferedSeriesIterator - - bufferEq := func(exp []sample) { - var b []sample - bit := it.Buffer() - for bit.Next() { - t, v := bit.At() - b = append(b, sample{t: t, v: v}) - } - require.Equal(t, exp, b, "buffer mismatch") - } - sampleEq := func(ets int64, ev float64) { - ts, v := it.Values() - require.Equal(t, ets, ts, "timestamp mismatch") - require.Equal(t, ev, v, "value mismatch") - } - - it = NewBufferIterator(newListSeriesIterator([]sample{ - {t: 1, v: 2}, - {t: 2, v: 3}, - {t: 3, v: 4}, - {t: 4, v: 5}, - {t: 5, v: 6}, - {t: 99, v: 8}, - {t: 100, v: 9}, - {t: 101, v: 10}, - }), 2) - - require.True(t, it.Seek(-123), "seek failed") - sampleEq(1, 2) - bufferEq(nil) - - require.True(t, it.Next(), "next failed") - sampleEq(2, 3) - bufferEq([]sample{{t: 1, v: 2}}) - - require.True(t, it.Next(), "next failed") - require.True(t, it.Next(), "next failed") - require.True(t, it.Next(), "next failed") - sampleEq(5, 6) - bufferEq([]sample{{t: 2, v: 3}, {t: 3, v: 4}, {t: 4, v: 5}}) - - require.True(t, it.Seek(5), "seek failed") - sampleEq(5, 6) - bufferEq([]sample{{t: 2, v: 3}, {t: 3, v: 4}, {t: 4, v: 5}}) - - require.True(t, it.Seek(101), "seek failed") - sampleEq(101, 10) - bufferEq([]sample{{t: 99, v: 8}, {t: 100, v: 9}}) - - require.False(t, it.Next(), "next succeeded unexpectedly") -} - -// At() should not be called once Next() returns false. -func TestBufferedSeriesIteratorNoBadAt(t *testing.T) { - done := false - - m := &mockSeriesIterator{ - seek: func(int64) bool { return false }, - at: func() (int64, float64) { - require.False(t, done) - done = true - return 0, 0 - }, - next: func() bool { return !done }, - err: func() error { return nil }, - } - - it := NewBufferIterator(m, 60) - it.Next() - it.Next() -} - -func BenchmarkBufferedSeriesIterator(b *testing.B) { - // Simulate a 5 minute rate. - it := NewBufferIterator(newFakeSeriesIterator(int64(b.N), 30), 5*60) - - b.SetBytes(int64(b.N * 16)) - b.ReportAllocs() - b.ResetTimer() - - for it.Next() { - // scan everything - } - require.NoError(b, it.Err()) -} - -type mockSeriesIterator struct { - seek func(int64) bool - at func() (int64, float64) - next func() bool - err func() error -} - -func (m *mockSeriesIterator) Seek(t int64) bool { return m.seek(t) } -func (m *mockSeriesIterator) At() (int64, float64) { return m.at() } -func (m *mockSeriesIterator) Next() bool { return m.next() } -func (m *mockSeriesIterator) Err() error { return m.err() } - -type mockSeries struct { - labels func() labels.Labels - iterator func() SeriesIterator -} - -func newMockSeries(lset labels.Labels, samples []sample) Series { - return &mockSeries{ - labels: func() labels.Labels { - return lset - }, - iterator: func() SeriesIterator { - return newListSeriesIterator(samples) - }, - } -} - -func (m *mockSeries) Labels() labels.Labels { return m.labels() } -func (m *mockSeries) Iterator() SeriesIterator { return m.iterator() } - -type listSeriesIterator struct { - list []sample - idx int -} - -func newListSeriesIterator(list []sample) *listSeriesIterator { - return &listSeriesIterator{list: list, idx: -1} -} - -func (it *listSeriesIterator) At() (int64, float64) { - s := it.list[it.idx] - return s.t, s.v -} - -func (it *listSeriesIterator) Next() bool { - it.idx++ - return it.idx < len(it.list) -} - -func (it *listSeriesIterator) Seek(t int64) bool { - if it.idx == -1 { - it.idx = 0 - } - // Do binary search between current position and end. - it.idx = sort.Search(len(it.list)-it.idx, func(i int) bool { - s := it.list[i+it.idx] - return s.t >= t - }) - - return it.idx < len(it.list) -} - -func (it *listSeriesIterator) Err() error { - return nil -} - -type fakeSeriesIterator struct { - nsamples int64 - step int64 - idx int64 -} - -func newFakeSeriesIterator(nsamples, step int64) *fakeSeriesIterator { - return &fakeSeriesIterator{nsamples: nsamples, step: step, idx: -1} -} - -func (it *fakeSeriesIterator) At() (int64, float64) { - return it.idx * it.step, 123 // value doesn't matter -} - -func (it *fakeSeriesIterator) Next() bool { - it.idx++ - return it.idx < it.nsamples -} - -func (it *fakeSeriesIterator) Seek(t int64) bool { - it.idx = t / it.step - return it.idx < it.nsamples -} - -func (it *fakeSeriesIterator) Err() error { - return nil -} diff --git a/vendor/github.com/prometheus/prometheus/storage/fanout_test.go b/vendor/github.com/prometheus/prometheus/storage/fanout_test.go deleted file mode 100644 index cf637f5f1..000000000 --- a/vendor/github.com/prometheus/prometheus/storage/fanout_test.go +++ /dev/null @@ -1,294 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package storage - -import ( - "fmt" - "math" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/prometheus/prometheus/pkg/labels" -) - -func TestMergeStringSlices(t *testing.T) { - for _, tc := range []struct { - input [][]string - expected []string - }{ - {}, - {[][]string{{"foo"}}, []string{"foo"}}, - {[][]string{{"foo"}, {"bar"}}, []string{"bar", "foo"}}, - {[][]string{{"foo"}, {"bar"}, {"baz"}}, []string{"bar", "baz", "foo"}}, - } { - require.Equal(t, tc.expected, mergeStringSlices(tc.input)) - } -} - -func TestMergeTwoStringSlices(t *testing.T) { - for _, tc := range []struct { - a, b, expected []string - }{ - {[]string{}, []string{}, []string{}}, - {[]string{"foo"}, nil, []string{"foo"}}, - {nil, []string{"bar"}, []string{"bar"}}, - {[]string{"foo"}, []string{"bar"}, []string{"bar", "foo"}}, - {[]string{"foo"}, []string{"bar", "baz"}, []string{"bar", "baz", "foo"}}, - {[]string{"foo"}, []string{"foo"}, []string{"foo"}}, - } { - require.Equal(t, tc.expected, mergeTwoStringSlices(tc.a, tc.b)) - } -} - -func TestMergeSeriesSet(t *testing.T) { - for _, tc := range []struct { - input []SeriesSet - expected SeriesSet - }{ - { - input: []SeriesSet{newMockSeriesSet()}, - expected: newMockSeriesSet(), - }, - - { - input: []SeriesSet{newMockSeriesSet( - newMockSeries(labels.FromStrings("bar", "baz"), []sample{{1, 1}, {2, 2}}), - newMockSeries(labels.FromStrings("foo", "bar"), []sample{{0, 0}, {1, 1}}), - )}, - expected: newMockSeriesSet( - newMockSeries(labels.FromStrings("bar", "baz"), []sample{{1, 1}, {2, 2}}), - newMockSeries(labels.FromStrings("foo", "bar"), []sample{{0, 0}, {1, 1}}), - ), - }, - - { - input: []SeriesSet{newMockSeriesSet( - newMockSeries(labels.FromStrings("foo", "bar"), []sample{{0, 0}, {1, 1}}), - ), newMockSeriesSet( - newMockSeries(labels.FromStrings("bar", "baz"), []sample{{1, 1}, {2, 2}}), - )}, - expected: newMockSeriesSet( - newMockSeries(labels.FromStrings("bar", "baz"), []sample{{1, 1}, {2, 2}}), - newMockSeries(labels.FromStrings("foo", "bar"), []sample{{0, 0}, {1, 1}}), - ), - }, - - { - input: []SeriesSet{newMockSeriesSet( - newMockSeries(labels.FromStrings("bar", "baz"), []sample{{1, 1}, {2, 2}}), - newMockSeries(labels.FromStrings("foo", "bar"), []sample{{0, 0}, {1, 1}}), - ), newMockSeriesSet( - newMockSeries(labels.FromStrings("bar", "baz"), []sample{{3, 3}, {4, 4}}), - newMockSeries(labels.FromStrings("foo", "bar"), []sample{{2, 2}, {3, 3}}), - )}, - expected: newMockSeriesSet( - newMockSeries(labels.FromStrings("bar", "baz"), []sample{{1, 1}, {2, 2}, {3, 3}, {4, 4}}), - newMockSeries(labels.FromStrings("foo", "bar"), []sample{{0, 0}, {1, 1}, {2, 2}, {3, 3}}), - ), - }, - { - input: []SeriesSet{newMockSeriesSet( - newMockSeries(labels.FromStrings("foo", "bar"), []sample{{0, math.NaN()}}), - ), newMockSeriesSet( - newMockSeries(labels.FromStrings("foo", "bar"), []sample{{0, math.NaN()}}), - )}, - expected: newMockSeriesSet( - newMockSeries(labels.FromStrings("foo", "bar"), []sample{{0, math.NaN()}}), - ), - }, - } { - merged := NewMergeSeriesSet(tc.input, nil) - for merged.Next() { - require.True(t, tc.expected.Next()) - actualSeries := merged.At() - expectedSeries := tc.expected.At() - require.Equal(t, expectedSeries.Labels(), actualSeries.Labels()) - require.Equal(t, drainSamples(expectedSeries.Iterator()), drainSamples(actualSeries.Iterator())) - } - require.False(t, tc.expected.Next()) - } -} - -func TestMergeIterator(t *testing.T) { - for _, tc := range []struct { - input []SeriesIterator - expected []sample - }{ - { - input: []SeriesIterator{ - newListSeriesIterator([]sample{{0, 0}, {1, 1}}), - }, - expected: []sample{{0, 0}, {1, 1}}, - }, - { - input: []SeriesIterator{ - newListSeriesIterator([]sample{{0, 0}, {1, 1}}), - newListSeriesIterator([]sample{{2, 2}, {3, 3}}), - }, - expected: []sample{{0, 0}, {1, 1}, {2, 2}, {3, 3}}, - }, - { - input: []SeriesIterator{ - newListSeriesIterator([]sample{{0, 0}, {3, 3}}), - newListSeriesIterator([]sample{{1, 1}, {4, 4}}), - newListSeriesIterator([]sample{{2, 2}, {5, 5}}), - }, - expected: []sample{{0, 0}, {1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}, - }, - { - input: []SeriesIterator{ - newListSeriesIterator([]sample{{0, 0}, {1, 1}}), - newListSeriesIterator([]sample{{0, 0}, {2, 2}}), - newListSeriesIterator([]sample{{2, 2}, {3, 3}}), - }, - expected: []sample{{0, 0}, {1, 1}, {2, 2}, {3, 3}}, - }, - } { - merged := newMergeIterator(tc.input) - actual := drainSamples(merged) - require.Equal(t, tc.expected, actual) - } -} - -func TestMergeIteratorSeek(t *testing.T) { - for _, tc := range []struct { - input []SeriesIterator - seek int64 - expected []sample - }{ - { - input: []SeriesIterator{ - newListSeriesIterator([]sample{{0, 0}, {1, 1}, {2, 2}}), - }, - seek: 1, - expected: []sample{{1, 1}, {2, 2}}, - }, - { - input: []SeriesIterator{ - newListSeriesIterator([]sample{{0, 0}, {1, 1}}), - newListSeriesIterator([]sample{{2, 2}, {3, 3}}), - }, - seek: 2, - expected: []sample{{2, 2}, {3, 3}}, - }, - { - input: []SeriesIterator{ - newListSeriesIterator([]sample{{0, 0}, {3, 3}}), - newListSeriesIterator([]sample{{1, 1}, {4, 4}}), - newListSeriesIterator([]sample{{2, 2}, {5, 5}}), - }, - seek: 2, - expected: []sample{{2, 2}, {3, 3}, {4, 4}, {5, 5}}, - }, - } { - merged := newMergeIterator(tc.input) - actual := []sample{} - if merged.Seek(tc.seek) { - t, v := merged.At() - actual = append(actual, sample{t, v}) - } - actual = append(actual, drainSamples(merged)...) - require.Equal(t, tc.expected, actual) - } -} - -func drainSamples(iter SeriesIterator) []sample { - result := []sample{} - for iter.Next() { - t, v := iter.At() - // NaNs can't be compared normally, so substitute for another value. - if math.IsNaN(v) { - v = -42 - } - result = append(result, sample{t, v}) - } - return result -} - -type mockSeriesSet struct { - idx int - series []Series -} - -func newMockSeriesSet(series ...Series) SeriesSet { - return &mockSeriesSet{ - idx: -1, - series: series, - } -} - -func (m *mockSeriesSet) Next() bool { - m.idx++ - return m.idx < len(m.series) -} - -func (m *mockSeriesSet) At() Series { - return m.series[m.idx] -} - -func (m *mockSeriesSet) Err() error { - return nil -} - -var result []sample - -func makeSeriesSet(numSeries, numSamples int) SeriesSet { - series := []Series{} - for j := 0; j < numSeries; j++ { - labels := labels.Labels{{Name: "foo", Value: fmt.Sprintf("bar%d", j)}} - samples := []sample{} - for k := 0; k < numSamples; k++ { - samples = append(samples, sample{t: int64(k), v: float64(k)}) - } - series = append(series, newMockSeries(labels, samples)) - } - return newMockSeriesSet(series...) -} - -func makeMergeSeriesSet(numSeriesSets, numSeries, numSamples int) SeriesSet { - seriesSets := []SeriesSet{} - for i := 0; i < numSeriesSets; i++ { - seriesSets = append(seriesSets, makeSeriesSet(numSeries, numSamples)) - } - return NewMergeSeriesSet(seriesSets, nil) -} - -func benchmarkDrain(seriesSet SeriesSet, b *testing.B) { - for n := 0; n < b.N; n++ { - for seriesSet.Next() { - result = drainSamples(seriesSet.At().Iterator()) - } - } -} - -func BenchmarkNoMergeSeriesSet_100_100(b *testing.B) { - seriesSet := makeSeriesSet(100, 100) - benchmarkDrain(seriesSet, b) -} - -func BenchmarkMergeSeriesSet(b *testing.B) { - for _, bm := range []struct { - numSeriesSets, numSeries, numSamples int - }{ - {1, 100, 100}, - {10, 100, 100}, - {100, 100, 100}, - } { - seriesSet := makeMergeSeriesSet(bm.numSeriesSets, bm.numSeries, bm.numSamples) - b.Run(fmt.Sprintf("%d_%d_%d", bm.numSeriesSets, bm.numSeries, bm.numSamples), func(b *testing.B) { - benchmarkDrain(seriesSet, b) - }) - } -} diff --git a/vendor/github.com/prometheus/prometheus/storage/tsdb/tsdb_export_test.go b/vendor/github.com/prometheus/prometheus/storage/tsdb/tsdb_export_test.go deleted file mode 100644 index 5821e9425..000000000 --- a/vendor/github.com/prometheus/prometheus/storage/tsdb/tsdb_export_test.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tsdb - -// Export the internal variables only for tests. -var ( - StartTime = &startTime - HeadMaxTime = &headMaxTime - HeadMinTime = &headMinTime -) diff --git a/vendor/github.com/prometheus/prometheus/storage/tsdb/tsdb_test.go b/vendor/github.com/prometheus/prometheus/storage/tsdb/tsdb_test.go deleted file mode 100644 index 85a8e43a9..000000000 --- a/vendor/github.com/prometheus/prometheus/storage/tsdb/tsdb_test.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tsdb_test - -import ( - "testing" - - dto "github.com/prometheus/client_model/go" - "github.com/prometheus/common/model" - "github.com/prometheus/prometheus/pkg/labels" - "github.com/prometheus/prometheus/storage/tsdb" - "github.com/prometheus/prometheus/util/testutil" -) - -func TestMetrics(t *testing.T) { - db := testutil.NewStorage(t) - defer db.Close() - - metrics := &dto.Metric{} - startTime := *tsdb.StartTime - headMinTime := *tsdb.HeadMinTime - headMaxTime := *tsdb.HeadMaxTime - - // Check initial values. - testutil.Ok(t, startTime.Write(metrics)) - testutil.Equals(t, float64(model.Latest)/1000, metrics.Gauge.GetValue()) - - testutil.Ok(t, headMinTime.Write(metrics)) - testutil.Equals(t, float64(model.Latest)/1000, metrics.Gauge.GetValue()) - - testutil.Ok(t, headMaxTime.Write(metrics)) - testutil.Equals(t, float64(model.Earliest)/1000, metrics.Gauge.GetValue()) - - app, err := db.Appender() - testutil.Ok(t, err) - - app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 1, 1) - app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 2, 1) - app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 3, 1) - testutil.Ok(t, app.Commit()) - - // Check after adding some samples. - testutil.Ok(t, startTime.Write(metrics)) - testutil.Equals(t, 0.001, metrics.Gauge.GetValue()) - - testutil.Ok(t, headMinTime.Write(metrics)) - testutil.Equals(t, 0.001, metrics.Gauge.GetValue()) - - testutil.Ok(t, headMaxTime.Write(metrics)) - testutil.Equals(t, 0.003, metrics.Gauge.GetValue()) - -} diff --git a/vendor/github.com/prometheus/prometheus/util/stats/stats_test.go b/vendor/github.com/prometheus/prometheus/util/stats/stats_test.go deleted file mode 100644 index 6a4c2cedc..000000000 --- a/vendor/github.com/prometheus/prometheus/util/stats/stats_test.go +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package stats - -import ( - "encoding/json" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/prometheus/util/testutil" - "regexp" - "testing" - "time" -) - -func TestTimerGroupNewTimer(t *testing.T) { - tg := NewTimerGroup() - timer := tg.GetTimer(ExecTotalTime) - if duration := timer.Duration(); duration != 0 { - t.Fatalf("Expected duration of 0, but it was %f instead.", duration) - } - minimum := 2 * time.Millisecond - timer.Start() - time.Sleep(minimum) - timer.Stop() - if duration := timer.Duration(); duration == 0 { - t.Fatalf("Expected duration greater than 0, but it was %f instead.", duration) - } - if elapsed := timer.ElapsedTime(); elapsed < minimum { - t.Fatalf("Expected elapsed time to be greater than time slept, elapsed was %d, and time slept was %d.", elapsed.Nanoseconds(), minimum) - } -} - -func TestQueryStatsWithTimers(t *testing.T) { - qt := NewQueryTimers() - timer := qt.GetTimer(ExecTotalTime) - timer.Start() - time.Sleep(2 * time.Millisecond) - timer.Stop() - - qs := NewQueryStats(qt) - actual, err := json.Marshal(qs) - if err != nil { - t.Fatalf("Unexpected error during serialization: %v", err) - } - // Timing value is one of multiple fields, unit is seconds (float). - match, err := regexp.MatchString(`[,{]"execTotalTime":\d+\.\d+[,}]`, string(actual)) - if err != nil { - t.Fatalf("Unexpected error while matching string: %v", err) - } - if !match { - t.Fatalf("Expected timings with one non-zero entry, but got %s.", actual) - } -} - -func TestQueryStatsWithSpanTimers(t *testing.T) { - qt := NewQueryTimers() - ctx := &testutil.MockContext{DoneCh: make(chan struct{})} - qst, _ := qt.GetSpanTimer(ctx, ExecQueueTime, prometheus.NewSummary(prometheus.SummaryOpts{})) - time.Sleep(5 * time.Millisecond) - qst.Finish() - qs := NewQueryStats(qt) - actual, err := json.Marshal(qs) - if err != nil { - t.Fatalf("Unexpected error during serialization: %v", err) - } - // Timing value is one of multiple fields, unit is seconds (float). - match, err := regexp.MatchString(`[,{]"execQueueTime":\d+\.\d+[,}]`, string(actual)) - if err != nil { - t.Fatalf("Unexpected error while matching string: %v", err) - } - if !match { - t.Fatalf("Expected timings with one non-zero entry, but got %s.", actual) - } -} - -func TestTimerGroup(t *testing.T) { - tg := NewTimerGroup() - execTotalTimer := tg.GetTimer(ExecTotalTime) - if tg.GetTimer(ExecTotalTime).String() != "Exec total time: 0s" { - t.Fatalf("Expected string %s, but got %s", "", execTotalTimer.String()) - } - execQueueTimer := tg.GetTimer(ExecQueueTime) - if tg.GetTimer(ExecQueueTime).String() != "Exec queue wait time: 0s" { - t.Fatalf("Expected string %s, but got %s", "", execQueueTimer.String()) - } - innerEvalTimer := tg.GetTimer(InnerEvalTime) - if tg.GetTimer(InnerEvalTime).String() != "Inner eval time: 0s" { - t.Fatalf("Expected string %s, but got %s", "", innerEvalTimer.String()) - } - queryPreparationTimer := tg.GetTimer(QueryPreparationTime) - if tg.GetTimer(QueryPreparationTime).String() != "Query preparation time: 0s" { - t.Fatalf("Expected string %s, but got %s", "", queryPreparationTimer.String()) - } - resultSortTimer := tg.GetTimer(ResultSortTime) - if tg.GetTimer(ResultSortTime).String() != "Result sorting time: 0s" { - t.Fatalf("Expected string %s, but got %s", "", resultSortTimer.String()) - } - evalTotalTimer := tg.GetTimer(EvalTotalTime) - if tg.GetTimer(EvalTotalTime).String() != "Eval total time: 0s" { - t.Fatalf("Expected string %s, but got %s", "", evalTotalTimer.String()) - } - - actual := tg.String() - expected := "Exec total time: 0s\nExec queue wait time: 0s\nInner eval time: 0s\nQuery preparation time: 0s\nResult sorting time: 0s\nEval total time: 0s\n" - - if actual != expected { - t.Fatalf("Expected timerGroup string %s, but got %s.", expected, actual) - } - -} diff --git a/vendor/github.com/prometheus/prometheus/util/strutil/quote_test.go b/vendor/github.com/prometheus/prometheus/util/strutil/quote_test.go deleted file mode 100644 index 32aea0940..000000000 --- a/vendor/github.com/prometheus/prometheus/util/strutil/quote_test.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2015 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package strutil - -import ( - "testing" -) - -type quoteTest struct { - in string - out string - ascii string -} - -var quotetests = []quoteTest{ - {"\a\b\f\r\n\t\v", `"\a\b\f\r\n\t\v"`, `"\a\b\f\r\n\t\v"`}, - {"\\", `"\\"`, `"\\"`}, - {"abc\xffdef", `"abc\xffdef"`, `"abc\xffdef"`}, - {"\u263a", `"☺"`, `"\u263a"`}, - {"\U0010ffff", `"\U0010ffff"`, `"\U0010ffff"`}, - {"\x04", `"\x04"`, `"\x04"`}, -} - -type unQuoteTest struct { - in string - out string -} - -var unquotetests = []unQuoteTest{ - {`""`, ""}, - {`"a"`, "a"}, - {`"abc"`, "abc"}, - {`"☺"`, "☺"}, - {`"hello world"`, "hello world"}, - {`"\xFF"`, "\xFF"}, - {`"\377"`, "\377"}, - {`"\u1234"`, "\u1234"}, - {`"\U00010111"`, "\U00010111"}, - {`"\U0001011111"`, "\U0001011111"}, - {`"\a\b\f\n\r\t\v\\\""`, "\a\b\f\n\r\t\v\\\""}, - {`"'"`, "'"}, - - {`''`, ""}, - {`'a'`, "a"}, - {`'abc'`, "abc"}, - {`'☺'`, "☺"}, - {`'hello world'`, "hello world"}, - {`'\ahéllo world'`, "\ahéllo world"}, - {`'\xFF'`, "\xFF"}, - {`'\377'`, "\377"}, - {`'\u1234'`, "\u1234"}, - {`'\U00010111'`, "\U00010111"}, - {`'\U0001011111'`, "\U0001011111"}, - {`'\a\b\f\n\r\t\v\\\''`, "\a\b\f\n\r\t\v\\'"}, - {`'"'`, "\""}, - - {"``", ``}, - {"`a`", `a`}, - {"`abc`", `abc`}, - {"`☺`", `☺`}, - {"`hello world`", `hello world`}, - {"`\\xFF`", `\xFF`}, - {"`\\377`", `\377`}, - {"`\\`", `\`}, - {"`\n`", "\n"}, - {"` `", ` `}, -} - -var misquoted = []string{ - ``, - `"`, - `"a`, - `"'`, - `b"`, - `"\"`, - `"\9"`, - `"\19"`, - `"\129"`, - `'\'`, - `'\9'`, - `'\19'`, - `'\129'`, - `"\x1!"`, - `"\U12345678"`, - `"\z"`, - "`", - "`xxx", - "`\"", - `"\'"`, - `'\"'`, - "\"\n\"", - "\"\\n\n\"", - "'\n'", - "`1`9`", - `1231`, - `'\xF'`, - `""12345"`, -} - -func TestUnquote(t *testing.T) { - for _, tt := range unquotetests { - if out, err := Unquote(tt.in); err != nil && out != tt.out { - t.Errorf("Unquote(%#q) = %q, %v want %q, nil", tt.in, out, err, tt.out) - } - } - - // Run the quote tests too, backward. - for _, tt := range quotetests { - if in, err := Unquote(tt.out); in != tt.in { - t.Errorf("Unquote(%#q) = %q, %v, want %q, nil", tt.out, in, err, tt.in) - } - } - - for _, s := range misquoted { - if out, err := Unquote(s); out != "" || err != ErrSyntax { - t.Errorf("Unquote(%#q) = %q, %v want %q, %v", s, out, err, "", ErrSyntax) - } - } -} diff --git a/vendor/github.com/prometheus/prometheus/util/strutil/strconv_test.go b/vendor/github.com/prometheus/prometheus/util/strutil/strconv_test.go deleted file mode 100644 index e47bb45e7..000000000 --- a/vendor/github.com/prometheus/prometheus/util/strutil/strconv_test.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2016 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package strutil - -import ( - "testing" -) - -type linkTest struct { - expression string - expectedGraphLink string - expectedTableLink string -} - -var linkTests = []linkTest{ - { - "sum(incoming_http_requests_total) by (system)", - "/graph?g0.expr=sum%28incoming_http_requests_total%29+by+%28system%29&g0.tab=0", - "/graph?g0.expr=sum%28incoming_http_requests_total%29+by+%28system%29&g0.tab=1", - }, - { - "sum(incoming_http_requests_total{system=\"trackmetadata\"})", - "/graph?g0.expr=sum%28incoming_http_requests_total%7Bsystem%3D%22trackmetadata%22%7D%29&g0.tab=0", - "/graph?g0.expr=sum%28incoming_http_requests_total%7Bsystem%3D%22trackmetadata%22%7D%29&g0.tab=1", - }, -} - -func TestLink(t *testing.T) { - for _, tt := range linkTests { - if graphLink := GraphLinkForExpression(tt.expression); graphLink != tt.expectedGraphLink { - t.Errorf("GraphLinkForExpression failed for expression (%#q), want %q got %q", tt.expression, tt.expectedGraphLink, graphLink) - } - - if tableLink := TableLinkForExpression(tt.expression); tableLink != tt.expectedTableLink { - t.Errorf("TableLinkForExpression failed for expression (%#q), want %q got %q", tt.expression, tt.expectedTableLink, tableLink) - } - } -} - -func TestSanitizeLabelName(t *testing.T) { - actual := SanitizeLabelName("fooClientLABEL") - expected := "fooClientLABEL" - - if actual != expected { - t.Errorf("SanitizeLabelName failed for label (%s), want %s got %s", "fooClientLABEL", expected, actual) - } - - actual = SanitizeLabelName("barClient.LABEL$$##") - expected = "barClient_LABEL____" - - if actual != expected { - t.Errorf("SanitizeLabelName failed for label (%s), want %s got %s", "barClient.LABEL$$##", expected, actual) - } -} diff --git a/vendor/github.com/prometheus/tsdb/.travis.yml b/vendor/github.com/prometheus/tsdb/.travis.yml index c146e026b..c5012a34a 100644 --- a/vendor/github.com/prometheus/tsdb/.travis.yml +++ b/vendor/github.com/prometheus/tsdb/.travis.yml @@ -1,3 +1,5 @@ +# sudo is enabled because it provides more memory which was needed to run go test -race +sudo: required dist: trusty language: go os: @@ -8,7 +10,6 @@ os: go: - 1.10.x - 1.11.x - - 1.12.x go_import_path: github.com/prometheus/tsdb @@ -19,4 +20,5 @@ install: - make deps script: - - if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then make test; else make all; fi + # `staticcheck` target is omitted due to linting errors + - if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then make test; else make; fi diff --git a/vendor/github.com/prometheus/tsdb/CHANGELOG.md b/vendor/github.com/prometheus/tsdb/CHANGELOG.md index 534de25cb..184734537 100644 --- a/vendor/github.com/prometheus/tsdb/CHANGELOG.md +++ b/vendor/github.com/prometheus/tsdb/CHANGELOG.md @@ -1,30 +1,12 @@ ## master / unreleased -## 0.6.0 - - [CHANGE] `AllowOverlappingBlock` is now `AllowOverlappingBlocks`. - -## 0.5.0 - - [FEATURE] Time-ovelapping blocks are now allowed. [#370](https://github.com/prometheus/tsdb/pull/370) - - Disabled by default and can be enabled via `AllowOverlappingBlock` option. - - Added `MergeChunks` function in `chunkenc/xor.go` to merge 2 time-overlapping chunks. - - Added `MergeOverlappingChunks` function in `chunks/chunks.go` to merge multiple time-overlapping Chunk Metas. - - Added `MinTime` and `MaxTime` method for `BlockReader`. - - [FEATURE] New `dump` command to tsdb tool to dump all samples. - - [FEATURE] New `encoding` package for common binary encoding/decoding helpers. - - Added to remove some code duplication. - - [ENHANCEMENT] When closing the db any running compaction will be cancelled so it doesn't block. - - `NewLeveledCompactor` takes a context. - - [CHANGE] `prometheus_tsdb_storage_blocks_bytes_total` is now `prometheus_tsdb_storage_blocks_bytes`. - - [BUGFIX] Improved Postings Merge performance. Fixes a regression from the the previous release. - - [BUGFIX] LiveReader can get into an infinite loop on corrupt WALs. - ## 0.4.0 - [CHANGE] New `WALSegmentSize` option to override the `DefaultOptions.WALSegmentSize`. Added to allow using smaller wal files. For example using tmpfs on a RPI to minimise the SD card wear out from the constant WAL writes. As part of this change the `DefaultOptions.WALSegmentSize` constant was also exposed. - [CHANGE] Empty blocks are not written during compaction [#374](https://github.com/prometheus/tsdb/pull/374) - [FEATURE] Size base retention through `Options.MaxBytes`. As part of this change: - - Added new metrics - `prometheus_tsdb_storage_blocks_bytes_total`, `prometheus_tsdb_size_retentions_total`, `prometheus_tsdb_time_retentions_total` - - New public interface `SizeReader: Size() int64` - - `OpenBlock` signature changed to take a logger. + - added new metrics - `prometheus_tsdb_storage_blocks_bytes_total`, `prometheus_tsdb_size_retentions_total`, `prometheus_tsdb_time_retentions_total` + - new public interface `SizeReader: Size() int64` + - `OpenBlock` signature changed to take a logger. - [REMOVED] `PrefixMatcher` is considered unused so was removed. - [CLEANUP] `Options.WALFlushInterval` is removed as it wasn't used anywhere. - [FEATURE] Add new `LiveReader` to WAL pacakge. Added to allow live tailing of a WAL segment, used by Prometheus Remote Write after refactor. The main difference between the new reader and the existing `Reader` is that for `LiveReader` a call to `Next()` that returns false does not mean that there will never be more data to read. @@ -39,4 +21,4 @@ - [CHANGE] `Head.Init()` is changed to `Head.Init(minValidTime int64)` - [CHANGE] `SymbolTable()` renamed to `SymbolTableSize()` to make the name consistent with the `Block{ symbolTableSize uint64 }` field. - [CHANGE] `wal.Reader{}` now exposes `Segment()` for the current segment being read and `Offset()` for the current offset. - - [FEATURE] tsdbutil analyze subcomand to find churn, high cardinality, etc. + -[FEATURE] tsdbutil analyze subcomand to find churn, high cardinality, etc. diff --git a/vendor/github.com/prometheus/tsdb/Makefile.common b/vendor/github.com/prometheus/tsdb/Makefile.common index 7105cff02..741579e60 100644 --- a/vendor/github.com/prometheus/tsdb/Makefile.common +++ b/vendor/github.com/prometheus/tsdb/Makefile.common @@ -29,15 +29,12 @@ GO ?= go GOFMT ?= $(GO)fmt FIRST_GOPATH := $(firstword $(subst :, ,$(shell $(GO) env GOPATH))) GOOPTS ?= -GOHOSTOS ?= $(shell $(GO) env GOHOSTOS) -GOHOSTARCH ?= $(shell $(GO) env GOHOSTARCH) GO_VERSION ?= $(shell $(GO) version) GO_VERSION_NUMBER ?= $(word 3, $(GO_VERSION)) PRE_GO_111 ?= $(shell echo $(GO_VERSION_NUMBER) | grep -E 'go1\.(10|[0-9])\.') -GOVENDOR := -GO111MODULE := +unexport GOVENDOR ifeq (, $(PRE_GO_111)) ifneq (,$(wildcard go.mod)) # Enforce Go modules support just in case the directory is inside GOPATH (and for Travis CI). @@ -58,43 +55,32 @@ $(warning Some recipes may not work as expected as the current Go runtime is '$( # This repository isn't using Go modules (yet). GOVENDOR := $(FIRST_GOPATH)/bin/govendor endif + + unexport GO111MODULE endif PROMU := $(FIRST_GOPATH)/bin/promu STATICCHECK := $(FIRST_GOPATH)/bin/staticcheck pkgs = ./... -ifeq (arm, $(GOHOSTARCH)) - GOHOSTARM ?= $(shell GOARM= $(GO) env GOARM) - GO_BUILD_PLATFORM ?= $(GOHOSTOS)-$(GOHOSTARCH)v$(GOHOSTARM) -else - GO_BUILD_PLATFORM ?= $(GOHOSTOS)-$(GOHOSTARCH) -endif +GO_VERSION ?= $(shell $(GO) version) +GO_BUILD_PLATFORM ?= $(subst /,-,$(lastword $(GO_VERSION))) -PROMU_VERSION ?= 0.3.0 +PROMU_VERSION ?= 0.2.0 PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz -STATICCHECK_VERSION ?= 2019.1 -STATICCHECK_URL := https://github.com/dominikh/go-tools/releases/download/$(STATICCHECK_VERSION)/staticcheck_$(GOHOSTOS)_$(GOHOSTARCH) PREFIX ?= $(shell pwd) BIN_DIR ?= $(shell pwd) DOCKER_IMAGE_TAG ?= $(subst /,-,$(shell git rev-parse --abbrev-ref HEAD)) DOCKER_REPO ?= prom -ifeq ($(GOHOSTARCH),amd64) - ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux freebsd darwin windows)) - # Only supported on amd64 - test-flags := -race - endif -endif +.PHONY: all +all: precheck style staticcheck unused build test # This rule is used to forward a target like "build" to "common-build". This # allows a new "build" target to be defined in a Makefile which includes this # one and override "common-build" without override warnings. %: common-% ; -.PHONY: common-all -common-all: precheck style check_license staticcheck unused build test - .PHONY: common-style common-style: @echo ">> checking code style" @@ -124,12 +110,12 @@ common-test-short: .PHONY: common-test common-test: @echo ">> running all tests" - GO111MODULE=$(GO111MODULE) $(GO) test $(test-flags) $(GOOPTS) $(pkgs) + GO111MODULE=$(GO111MODULE) $(GO) test -race $(GOOPTS) $(pkgs) .PHONY: common-format common-format: @echo ">> formatting code" - GO111MODULE=$(GO111MODULE) $(GO) fmt $(pkgs) + GO111MODULE=$(GO111MODULE) $(GO) fmt $(GOOPTS) $(pkgs) .PHONY: common-vet common-vet: @@ -139,12 +125,8 @@ common-vet: .PHONY: common-staticcheck common-staticcheck: $(STATICCHECK) @echo ">> running staticcheck" - chmod +x $(STATICCHECK) ifdef GO111MODULE -# 'go list' needs to be executed before staticcheck to prepopulate the modules cache. -# Otherwise staticcheck might fail randomly for some reason not yet explained. - GO111MODULE=$(GO111MODULE) $(GO) list -e -compiled -test=true -export=false -deps=true -find=false -tags= -- ./... > /dev/null - GO111MODULE=$(GO111MODULE) $(STATICCHECK) -ignore "$(STATICCHECK_IGNORE)" $(pkgs) + GO111MODULE=$(GO111MODULE) $(STATICCHECK) -ignore "$(STATICCHECK_IGNORE)" -checks "SA*" $(pkgs) else $(STATICCHECK) -ignore "$(STATICCHECK_IGNORE)" $(pkgs) endif @@ -158,9 +140,8 @@ else ifdef GO111MODULE @echo ">> running check for unused/missing packages in go.mod" GO111MODULE=$(GO111MODULE) $(GO) mod tidy -ifeq (,$(wildcard vendor)) @git diff --exit-code -- go.sum go.mod -else +ifneq (,$(wildcard vendor)) @echo ">> running check for unused packages in vendor/" GO111MODULE=$(GO111MODULE) $(GO) mod vendor @git diff --exit-code -- go.sum go.mod vendor/ @@ -194,20 +175,30 @@ common-docker-tag-latest: promu: $(PROMU) $(PROMU): - $(eval PROMU_TMP := $(shell mktemp -d)) - curl -s -L $(PROMU_URL) | tar -xvzf - -C $(PROMU_TMP) - mkdir -p $(FIRST_GOPATH)/bin - cp $(PROMU_TMP)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM)/promu $(FIRST_GOPATH)/bin/promu - rm -r $(PROMU_TMP) + curl -s -L $(PROMU_URL) | tar -xvz -C /tmp + mkdir -v -p $(FIRST_GOPATH)/bin + cp -v /tmp/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM)/promu $(PROMU) .PHONY: proto proto: @echo ">> generating code from proto files" @./scripts/genproto.sh +.PHONY: $(STATICCHECK) $(STATICCHECK): - mkdir -p $(FIRST_GOPATH)/bin - curl -s -L $(STATICCHECK_URL) > $(STATICCHECK) +ifdef GO111MODULE +# Get staticcheck from a temporary directory to avoid modifying the local go.{mod,sum}. +# See https://github.com/golang/go/issues/27643. +# For now, we are using the next branch of staticcheck because master isn't compatible yet with Go modules. + tmpModule=$$(mktemp -d 2>&1) && \ + mkdir -p $${tmpModule}/staticcheck && \ + cd "$${tmpModule}"/staticcheck && \ + GO111MODULE=on $(GO) mod init example.com/staticcheck && \ + GO111MODULE=on GOOS= GOARCH= $(GO) get -u honnef.co/go/tools/cmd/staticcheck@next && \ + rm -rf $${tmpModule}; +else + GOOS= GOARCH= GO111MODULE=off $(GO) get -u honnef.co/go/tools/cmd/staticcheck +endif ifdef GOVENDOR .PHONY: $(GOVENDOR) diff --git a/vendor/github.com/prometheus/tsdb/block.go b/vendor/github.com/prometheus/tsdb/block.go index d9570bdd6..42e11d951 100644 --- a/vendor/github.com/prometheus/tsdb/block.go +++ b/vendor/github.com/prometheus/tsdb/block.go @@ -16,7 +16,6 @@ package tsdb import ( "encoding/json" - "io" "io/ioutil" "os" "path/filepath" @@ -135,12 +134,6 @@ type BlockReader interface { // Tombstones returns a TombstoneReader over the block's deleted data. Tombstones() (TombstoneReader, error) - - // MinTime returns the min time of the block. - MinTime() int64 - - // MaxTime returns the max time of the block. - MaxTime() int64 } // Appendable defines an entity to which data can be appended. @@ -276,19 +269,10 @@ type Block struct { // OpenBlock opens the block in the directory. It can be passed a chunk pool, which is used // to instantiate chunk structs. -func OpenBlock(logger log.Logger, dir string, pool chunkenc.Pool) (pb *Block, err error) { +func OpenBlock(logger log.Logger, dir string, pool chunkenc.Pool) (*Block, error) { if logger == nil { logger = log.NewNopLogger() } - var closers []io.Closer - defer func() { - if err != nil { - var merr MultiError - merr.Add(err) - merr.Add(closeAll(closers)) - err = merr.Err() - } - }() meta, err := readMetaFile(dir) if err != nil { return nil, err @@ -298,19 +282,15 @@ func OpenBlock(logger log.Logger, dir string, pool chunkenc.Pool) (pb *Block, er if err != nil { return nil, err } - closers = append(closers, cr) - - ir, err := index.NewFileReader(filepath.Join(dir, indexFilename)) + ir, err := index.NewFileReader(filepath.Join(dir, "index")) if err != nil { return nil, err } - closers = append(closers, ir) tr, tsr, err := readTombstones(dir) if err != nil { return nil, err } - closers = append(closers, tr) // TODO refactor to set this at block creation time as // that would be the logical place for a block size to be calculated. @@ -321,7 +301,7 @@ func OpenBlock(logger log.Logger, dir string, pool chunkenc.Pool) (pb *Block, er level.Warn(logger).Log("msg", "couldn't write the meta file for the block size", "block", dir, "err", err) } - pb = &Block{ + pb := &Block{ dir: dir, meta: *meta, chunkr: cr, @@ -369,12 +349,6 @@ func (pb *Block) Dir() string { return pb.dir } // Meta returns meta information about the block. func (pb *Block) Meta() BlockMeta { return pb.meta } -// MinTime returns the min time of the meta. -func (pb *Block) MinTime() int64 { return pb.meta.MinTime } - -// MaxTime returns the max time of the meta. -func (pb *Block) MaxTime() int64 { return pb.meta.MaxTime } - // Size returns the number of bytes that the block takes up. func (pb *Block) Size() int64 { return pb.meta.Stats.NumBytes } diff --git a/vendor/github.com/prometheus/tsdb/block_test.go b/vendor/github.com/prometheus/tsdb/block_test.go deleted file mode 100644 index dd0972d6e..000000000 --- a/vendor/github.com/prometheus/tsdb/block_test.go +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tsdb - -import ( - "context" - "io/ioutil" - "math/rand" - "os" - "path/filepath" - "testing" - - "github.com/go-kit/kit/log" - "github.com/prometheus/tsdb/testutil" - "github.com/prometheus/tsdb/tsdbutil" -) - -// In Prometheus 2.1.0 we had a bug where the meta.json version was falsely bumped -// to 2. We had a migration in place resetting it to 1 but we should move immediately to -// version 3 next time to avoid confusion and issues. -func TestBlockMetaMustNeverBeVersion2(t *testing.T) { - dir, err := ioutil.TempDir("", "metaversion") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - testutil.Ok(t, writeMetaFile(dir, &BlockMeta{})) - - meta, err := readMetaFile(dir) - testutil.Ok(t, err) - testutil.Assert(t, meta.Version != 2, "meta.json version must never be 2") -} - -func TestSetCompactionFailed(t *testing.T) { - tmpdir, err := ioutil.TempDir("", "test") - testutil.Ok(t, err) - defer os.RemoveAll(tmpdir) - - blockDir := createBlock(t, tmpdir, genSeries(1, 1, 0, 0)) - b, err := OpenBlock(nil, blockDir, nil) - testutil.Ok(t, err) - testutil.Equals(t, false, b.meta.Compaction.Failed) - testutil.Ok(t, b.setCompactionFailed()) - testutil.Equals(t, true, b.meta.Compaction.Failed) - testutil.Ok(t, b.Close()) - - b, err = OpenBlock(nil, blockDir, nil) - testutil.Ok(t, err) - testutil.Equals(t, true, b.meta.Compaction.Failed) - testutil.Ok(t, b.Close()) -} - -// createBlock creates a block with given set of series and returns its dir. -func createBlock(tb testing.TB, dir string, series []Series) string { - head, err := NewHead(nil, nil, nil, 2*60*60*1000) - testutil.Ok(tb, err) - defer head.Close() - - app := head.Appender() - for _, s := range series { - ref := uint64(0) - it := s.Iterator() - for it.Next() { - t, v := it.At() - if ref != 0 { - err := app.AddFast(ref, t, v) - if err == nil { - continue - } - } - ref, err = app.Add(s.Labels(), t, v) - testutil.Ok(tb, err) - } - testutil.Ok(tb, it.Err()) - } - err = app.Commit() - testutil.Ok(tb, err) - - compactor, err := NewLeveledCompactor(context.Background(), nil, log.NewNopLogger(), []int64{1000000}, nil) - testutil.Ok(tb, err) - - testutil.Ok(tb, os.MkdirAll(dir, 0777)) - - ulid, err := compactor.Write(dir, head, head.MinTime(), head.MaxTime(), nil) - testutil.Ok(tb, err) - return filepath.Join(dir, ulid.String()) -} - -// genSeries generates series with a given number of labels and values. -func genSeries(totalSeries, labelCount int, mint, maxt int64) []Series { - if totalSeries == 0 || labelCount == 0 { - return nil - } - - series := make([]Series, totalSeries) - for i := 0; i < totalSeries; i++ { - lbls := make(map[string]string, labelCount) - for len(lbls) < labelCount { - lbls[randString()] = randString() - } - samples := make([]tsdbutil.Sample, 0, maxt-mint+1) - for t := mint; t <= maxt; t++ { - samples = append(samples, sample{t: t, v: rand.Float64()}) - } - series[i] = newSeries(lbls, samples) - } - return series -} - -// populateSeries generates series from given labels, mint and maxt. -func populateSeries(lbls []map[string]string, mint, maxt int64) []Series { - if len(lbls) == 0 { - return nil - } - - series := make([]Series, 0, len(lbls)) - for _, lbl := range lbls { - if len(lbl) == 0 { - continue - } - samples := make([]tsdbutil.Sample, 0, maxt-mint+1) - for t := mint; t <= maxt; t++ { - samples = append(samples, sample{t: t, v: rand.Float64()}) - } - series = append(series, newSeries(lbl, samples)) - } - return series -} - -const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" -const ( - letterIdxBits = 6 // 6 bits to represent a letter index - letterIdxMask = 1<= 0; { - if remain == 0 { - cache, remain = rand.Int63(), letterIdxMax - } - if idx := int(cache & letterIdxMask); idx < len(letterBytes) { - b[i] = letterBytes[idx] - i-- - } - cache >>= letterIdxBits - remain-- - } - - return string(b) -} diff --git a/vendor/github.com/prometheus/tsdb/checkpoint_test.go b/vendor/github.com/prometheus/tsdb/checkpoint_test.go deleted file mode 100644 index 8b13c152a..000000000 --- a/vendor/github.com/prometheus/tsdb/checkpoint_test.go +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright 2018 The Prometheus Authors - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tsdb - -import ( - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strings" - "testing" - - "github.com/pkg/errors" - "github.com/prometheus/tsdb/fileutil" - "github.com/prometheus/tsdb/labels" - "github.com/prometheus/tsdb/testutil" - "github.com/prometheus/tsdb/wal" -) - -func TestLastCheckpoint(t *testing.T) { - dir, err := ioutil.TempDir("", "test_checkpoint") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - _, _, err = LastCheckpoint(dir) - testutil.Equals(t, ErrNotFound, err) - - testutil.Ok(t, os.MkdirAll(filepath.Join(dir, "checkpoint.0000"), 0777)) - s, k, err := LastCheckpoint(dir) - testutil.Ok(t, err) - testutil.Equals(t, filepath.Join(dir, "checkpoint.0000"), s) - testutil.Equals(t, 0, k) - - testutil.Ok(t, os.MkdirAll(filepath.Join(dir, "checkpoint.xyz"), 0777)) - s, k, err = LastCheckpoint(dir) - testutil.Ok(t, err) - testutil.Equals(t, filepath.Join(dir, "checkpoint.0000"), s) - testutil.Equals(t, 0, k) - - testutil.Ok(t, os.MkdirAll(filepath.Join(dir, "checkpoint.1"), 0777)) - s, k, err = LastCheckpoint(dir) - testutil.Ok(t, err) - testutil.Equals(t, filepath.Join(dir, "checkpoint.1"), s) - testutil.Equals(t, 1, k) - - testutil.Ok(t, os.MkdirAll(filepath.Join(dir, "checkpoint.1000"), 0777)) - s, k, err = LastCheckpoint(dir) - testutil.Ok(t, err) - testutil.Equals(t, filepath.Join(dir, "checkpoint.1000"), s) - testutil.Equals(t, 1000, k) -} - -func TestDeleteCheckpoints(t *testing.T) { - dir, err := ioutil.TempDir("", "test_checkpoint") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - testutil.Ok(t, DeleteCheckpoints(dir, 0)) - - testutil.Ok(t, os.MkdirAll(filepath.Join(dir, "checkpoint.00"), 0777)) - testutil.Ok(t, os.MkdirAll(filepath.Join(dir, "checkpoint.01"), 0777)) - testutil.Ok(t, os.MkdirAll(filepath.Join(dir, "checkpoint.02"), 0777)) - testutil.Ok(t, os.MkdirAll(filepath.Join(dir, "checkpoint.03"), 0777)) - - testutil.Ok(t, DeleteCheckpoints(dir, 2)) - - files, err := fileutil.ReadDir(dir) - testutil.Ok(t, err) - testutil.Equals(t, []string{"checkpoint.02", "checkpoint.03"}, files) -} - -func TestCheckpoint(t *testing.T) { - dir, err := ioutil.TempDir("", "test_checkpoint") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - var enc RecordEncoder - // Create a dummy segment to bump the initial number. - seg, err := wal.CreateSegment(dir, 100) - testutil.Ok(t, err) - testutil.Ok(t, seg.Close()) - - // Manually create checkpoint for 99 and earlier. - w, err := wal.New(nil, nil, filepath.Join(dir, "checkpoint.0099")) - testutil.Ok(t, err) - - // Add some data we expect to be around later. - err = w.Log(enc.Series([]RefSeries{ - {Ref: 0, Labels: labels.FromStrings("a", "b", "c", "0")}, - {Ref: 1, Labels: labels.FromStrings("a", "b", "c", "1")}, - }, nil)) - testutil.Ok(t, err) - testutil.Ok(t, w.Close()) - - // Start a WAL and write records to it as usual. - w, err = wal.NewSize(nil, nil, dir, 64*1024) - testutil.Ok(t, err) - - var last int64 - for i := 0; ; i++ { - _, n, err := w.Segments() - testutil.Ok(t, err) - if n >= 106 { - break - } - // Write some series initially. - if i == 0 { - b := enc.Series([]RefSeries{ - {Ref: 2, Labels: labels.FromStrings("a", "b", "c", "2")}, - {Ref: 3, Labels: labels.FromStrings("a", "b", "c", "3")}, - {Ref: 4, Labels: labels.FromStrings("a", "b", "c", "4")}, - {Ref: 5, Labels: labels.FromStrings("a", "b", "c", "5")}, - }, nil) - testutil.Ok(t, w.Log(b)) - } - // Write samples until the WAL has enough segments. - // Make them have drifting timestamps within a record to see that they - // get filtered properly. - b := enc.Samples([]RefSample{ - {Ref: 0, T: last, V: float64(i)}, - {Ref: 1, T: last + 10000, V: float64(i)}, - {Ref: 2, T: last + 20000, V: float64(i)}, - {Ref: 3, T: last + 30000, V: float64(i)}, - }, nil) - testutil.Ok(t, w.Log(b)) - - last += 100 - } - testutil.Ok(t, w.Close()) - - _, err = Checkpoint(w, 100, 106, func(x uint64) bool { - return x%2 == 0 - }, last/2) - testutil.Ok(t, err) - testutil.Ok(t, w.Truncate(107)) - testutil.Ok(t, DeleteCheckpoints(w.Dir(), 106)) - - // Only the new checkpoint should be left. - files, err := fileutil.ReadDir(dir) - testutil.Ok(t, err) - testutil.Equals(t, 1, len(files)) - testutil.Equals(t, "checkpoint.000106", files[0]) - - sr, err := wal.NewSegmentsReader(filepath.Join(dir, "checkpoint.000106")) - testutil.Ok(t, err) - defer sr.Close() - - var dec RecordDecoder - var series []RefSeries - r := wal.NewReader(sr) - - for r.Next() { - rec := r.Record() - - switch dec.Type(rec) { - case RecordSeries: - series, err = dec.Series(rec, series) - testutil.Ok(t, err) - case RecordSamples: - samples, err := dec.Samples(rec, nil) - testutil.Ok(t, err) - for _, s := range samples { - testutil.Assert(t, s.T >= last/2, "sample with wrong timestamp") - } - } - } - testutil.Ok(t, r.Err()) - testutil.Equals(t, []RefSeries{ - {Ref: 0, Labels: labels.FromStrings("a", "b", "c", "0")}, - {Ref: 2, Labels: labels.FromStrings("a", "b", "c", "2")}, - {Ref: 4, Labels: labels.FromStrings("a", "b", "c", "4")}, - }, series) -} - -func TestCheckpointNoTmpFolderAfterError(t *testing.T) { - // Create a new wal with an invalid records. - dir, err := ioutil.TempDir("", "test_checkpoint") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - w, err := wal.NewSize(nil, nil, dir, 64*1024) - testutil.Ok(t, err) - testutil.Ok(t, w.Log([]byte{99})) - w.Close() - - // Run the checkpoint and since the wal contains an invalid records this should return an error. - _, err = Checkpoint(w, 0, 1, nil, 0) - testutil.NotOk(t, err) - - // Walk the wal dir to make sure there are no tmp folder left behind after the error. - err = filepath.Walk(w.Dir(), func(path string, info os.FileInfo, err error) error { - if err != nil { - return errors.Wrapf(err, "access err %q: %v\n", path, err) - } - if info.IsDir() && strings.HasSuffix(info.Name(), ".tmp") { - return fmt.Errorf("wal dir contains temporary folder:%s", info.Name()) - } - return nil - }) - testutil.Ok(t, err) -} diff --git a/vendor/github.com/prometheus/tsdb/chunkenc/bstream.go b/vendor/github.com/prometheus/tsdb/chunkenc/bstream.go index 0a02a7303..ef04d44ba 100644 --- a/vendor/github.com/prometheus/tsdb/chunkenc/bstream.go +++ b/vendor/github.com/prometheus/tsdb/chunkenc/bstream.go @@ -53,6 +53,16 @@ func newBReader(b []byte) bstream { return bstream{stream: b, count: 8} } +func newBWriter(size int) *bstream { + return &bstream{stream: make([]byte, 0, size), count: 0} +} + +func (b *bstream) clone() *bstream { + d := make([]byte, len(b.stream)) + copy(d, b.stream) + return &bstream{stream: d, count: b.count} +} + func (b *bstream) bytes() []byte { return b.stream } diff --git a/vendor/github.com/prometheus/tsdb/chunkenc/chunk.go b/vendor/github.com/prometheus/tsdb/chunkenc/chunk.go index 12dc75403..4c85fa054 100644 --- a/vendor/github.com/prometheus/tsdb/chunkenc/chunk.go +++ b/vendor/github.com/prometheus/tsdb/chunkenc/chunk.go @@ -52,7 +52,7 @@ type Chunk interface { func FromData(e Encoding, d []byte) (Chunk, error) { switch e { case EncXOR: - return &XORChunk{b: bstream{count: 0, stream: d}}, nil + return &XORChunk{b: &bstream{count: 0, stream: d}}, nil } return nil, fmt.Errorf("unknown chunk encoding: %d", e) } @@ -94,7 +94,7 @@ func NewPool() Pool { return &pool{ xor: sync.Pool{ New: func() interface{} { - return &XORChunk{b: bstream{}} + return &XORChunk{b: &bstream{}} }, }, } diff --git a/vendor/github.com/prometheus/tsdb/chunkenc/chunk_test.go b/vendor/github.com/prometheus/tsdb/chunkenc/chunk_test.go deleted file mode 100644 index 11dc19079..000000000 --- a/vendor/github.com/prometheus/tsdb/chunkenc/chunk_test.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package chunkenc - -import ( - "fmt" - "io" - "math/rand" - "reflect" - "testing" - - "github.com/prometheus/tsdb/testutil" -) - -type pair struct { - t int64 - v float64 -} - -func TestChunk(t *testing.T) { - for enc, nc := range map[Encoding]func() Chunk{ - EncXOR: func() Chunk { return NewXORChunk() }, - } { - t.Run(fmt.Sprintf("%v", enc), func(t *testing.T) { - for range make([]struct{}, 1) { - c := nc() - if err := testChunk(c); err != nil { - t.Fatal(err) - } - } - }) - } -} - -func testChunk(c Chunk) error { - app, err := c.Appender() - if err != nil { - return err - } - - var exp []pair - var ( - ts = int64(1234123324) - v = 1243535.123 - ) - for i := 0; i < 300; i++ { - ts += int64(rand.Intn(10000) + 1) - // v = rand.Float64() - if i%2 == 0 { - v += float64(rand.Intn(1000000)) - } else { - v -= float64(rand.Intn(1000000)) - } - - // Start with a new appender every 10th sample. This emulates starting - // appending to a partially filled chunk. - if i%10 == 0 { - app, err = c.Appender() - if err != nil { - return err - } - } - - app.Append(ts, v) - exp = append(exp, pair{t: ts, v: v}) - // fmt.Println("appended", len(c.Bytes()), c.Bytes()) - } - - it := c.Iterator() - var res []pair - for it.Next() { - ts, v := it.At() - res = append(res, pair{t: ts, v: v}) - } - if it.Err() != nil { - return it.Err() - } - if !reflect.DeepEqual(exp, res) { - return fmt.Errorf("unexpected result\n\ngot: %v\n\nexp: %v", res, exp) - } - return nil -} - -func benchmarkIterator(b *testing.B, newChunk func() Chunk) { - var ( - t = int64(1234123324) - v = 1243535.123 - ) - var exp []pair - for i := 0; i < b.N; i++ { - // t += int64(rand.Intn(10000) + 1) - t += int64(1000) - // v = rand.Float64() - v += float64(100) - exp = append(exp, pair{t: t, v: v}) - } - - var chunks []Chunk - for i := 0; i < b.N; { - c := newChunk() - - a, err := c.Appender() - if err != nil { - b.Fatalf("get appender: %s", err) - } - j := 0 - for _, p := range exp { - if j > 250 { - break - } - a.Append(p.t, p.v) - i++ - j++ - } - chunks = append(chunks, c) - } - - b.ReportAllocs() - b.ResetTimer() - - fmt.Println("num", b.N, "created chunks", len(chunks)) - - res := make([]float64, 0, 1024) - - for i := 0; i < len(chunks); i++ { - c := chunks[i] - it := c.Iterator() - - for it.Next() { - _, v := it.At() - res = append(res, v) - } - if it.Err() != io.EOF { - testutil.Ok(b, it.Err()) - } - res = res[:0] - } -} - -func BenchmarkXORIterator(b *testing.B) { - benchmarkIterator(b, func() Chunk { - return NewXORChunk() - }) -} - -func BenchmarkXORAppender(b *testing.B) { - benchmarkAppender(b, func() Chunk { - return NewXORChunk() - }) -} - -func benchmarkAppender(b *testing.B, newChunk func() Chunk) { - var ( - t = int64(1234123324) - v = 1243535.123 - ) - var exp []pair - for i := 0; i < b.N; i++ { - // t += int64(rand.Intn(10000) + 1) - t += int64(1000) - // v = rand.Float64() - v += float64(100) - exp = append(exp, pair{t: t, v: v}) - } - - b.ReportAllocs() - b.ResetTimer() - - var chunks []Chunk - for i := 0; i < b.N; { - c := newChunk() - - a, err := c.Appender() - if err != nil { - b.Fatalf("get appender: %s", err) - } - j := 0 - for _, p := range exp { - if j > 250 { - break - } - a.Append(p.t, p.v) - i++ - j++ - } - chunks = append(chunks, c) - } - - fmt.Println("num", b.N, "created chunks", len(chunks)) -} diff --git a/vendor/github.com/prometheus/tsdb/chunkenc/xor.go b/vendor/github.com/prometheus/tsdb/chunkenc/xor.go index 1518772b3..77cc3208b 100644 --- a/vendor/github.com/prometheus/tsdb/chunkenc/xor.go +++ b/vendor/github.com/prometheus/tsdb/chunkenc/xor.go @@ -51,13 +51,13 @@ import ( // XORChunk holds XOR encoded sample data. type XORChunk struct { - b bstream + b *bstream } // NewXORChunk returns a new chunk with XOR encoding of the given size. func NewXORChunk() *XORChunk { b := make([]byte, 2, 128) - return &XORChunk{b: bstream{stream: b, count: 0}} + return &XORChunk{b: &bstream{stream: b, count: 0}} } // Encoding returns the encoding type. @@ -89,7 +89,7 @@ func (c *XORChunk) Appender() (Appender, error) { } a := &xorAppender{ - b: &c.b, + b: c.b, t: it.t, v: it.val, tDelta: it.tDelta, diff --git a/vendor/github.com/prometheus/tsdb/chunks/chunks.go b/vendor/github.com/prometheus/tsdb/chunks/chunks.go index 3f643bc74..8fb288384 100644 --- a/vendor/github.com/prometheus/tsdb/chunks/chunks.go +++ b/vendor/github.com/prometheus/tsdb/chunks/chunks.go @@ -64,7 +64,9 @@ func (cm *Meta) OverlapsClosedInterval(mint, maxt int64) bool { } var ( - errInvalidSize = fmt.Errorf("invalid size") + errInvalidSize = fmt.Errorf("invalid size") + errInvalidFlag = fmt.Errorf("invalid flag") + errInvalidChecksum = fmt.Errorf("invalid checksum") ) var castagnoliTable *crc32.Table @@ -196,84 +198,6 @@ func (w *Writer) write(b []byte) error { return err } -// MergeOverlappingChunks removes the samples whose timestamp is overlapping. -// The last appearing sample is retained in case there is overlapping. -// This assumes that `chks []Meta` is sorted w.r.t. MinTime. -func MergeOverlappingChunks(chks []Meta) ([]Meta, error) { - if len(chks) < 2 { - return chks, nil - } - newChks := make([]Meta, 0, len(chks)) // Will contain the merged chunks. - newChks = append(newChks, chks[0]) - last := 0 - for _, c := range chks[1:] { - // We need to check only the last chunk in newChks. - // Reason: (1) newChks[last-1].MaxTime < newChks[last].MinTime (non overlapping) - // (2) As chks are sorted w.r.t. MinTime, newChks[last].MinTime < c.MinTime. - // So never overlaps with newChks[last-1] or anything before that. - if c.MinTime > newChks[last].MaxTime { - newChks = append(newChks, c) - continue - } - nc := &newChks[last] - if c.MaxTime > nc.MaxTime { - nc.MaxTime = c.MaxTime - } - chk, err := MergeChunks(nc.Chunk, c.Chunk) - if err != nil { - return nil, err - } - nc.Chunk = chk - } - - return newChks, nil -} - -// MergeChunks vertically merges a and b, i.e., if there is any sample -// with same timestamp in both a and b, the sample in a is discarded. -func MergeChunks(a, b chunkenc.Chunk) (*chunkenc.XORChunk, error) { - newChunk := chunkenc.NewXORChunk() - app, err := newChunk.Appender() - if err != nil { - return nil, err - } - ait := a.Iterator() - bit := b.Iterator() - aok, bok := ait.Next(), bit.Next() - for aok && bok { - at, av := ait.At() - bt, bv := bit.At() - if at < bt { - app.Append(at, av) - aok = ait.Next() - } else if bt < at { - app.Append(bt, bv) - bok = bit.Next() - } else { - app.Append(bt, bv) - aok = ait.Next() - bok = bit.Next() - } - } - for aok { - at, av := ait.At() - app.Append(at, av) - aok = ait.Next() - } - for bok { - bt, bv := bit.At() - app.Append(bt, bv) - bok = bit.Next() - } - if ait.Err() != nil { - return nil, ait.Err() - } - if bit.Err() != nil { - return nil, bit.Err() - } - return newChunk, nil -} - func (w *Writer) WriteChunks(chks ...Meta) error { // Calculate maximum space we need and cut a new segment in case // we don't fit into the current one. @@ -420,7 +344,7 @@ func NewDirReader(dir string, pool chunkenc.Pool) (*Reader, error) { } func (s *Reader) Close() error { - return closeAll(s.cs) + return closeAll(s.cs...) } // Size returns the size of the chunks. @@ -428,31 +352,30 @@ func (s *Reader) Size() int64 { return s.size } -// Chunk returns a chunk from a given reference. func (s *Reader) Chunk(ref uint64) (chunkenc.Chunk, error) { var ( - sgmSeq = int(ref >> 32) - sgmOffset = int((ref << 32) >> 32) + seq = int(ref >> 32) + off = int((ref << 32) >> 32) ) - if sgmSeq >= len(s.bs) { - return nil, errors.Errorf("reference sequence %d out of range", sgmSeq) + if seq >= len(s.bs) { + return nil, errors.Errorf("reference sequence %d out of range", seq) } - chkS := s.bs[sgmSeq] + b := s.bs[seq] - if sgmOffset >= chkS.Len() { - return nil, errors.Errorf("offset %d beyond data size %d", sgmOffset, chkS.Len()) + if off >= b.Len() { + return nil, errors.Errorf("offset %d beyond data size %d", off, b.Len()) } // With the minimum chunk length this should never cause us reading // over the end of the slice. - chk := chkS.Range(sgmOffset, sgmOffset+binary.MaxVarintLen32) + r := b.Range(off, off+binary.MaxVarintLen32) - chkLen, n := binary.Uvarint(chk) + l, n := binary.Uvarint(r) if n <= 0 { return nil, errors.Errorf("reading chunk length failed with %d", n) } - chk = chkS.Range(sgmOffset+n, sgmOffset+n+1+int(chkLen)) + r = b.Range(off+n, off+n+int(l)) - return s.pool.Get(chunkenc.Encoding(chk[0]), chk[1:1+chkLen]) + return s.pool.Get(chunkenc.Encoding(r[0]), r[1:1+l]) } func nextSequenceFile(dir string) (string, int, error) { @@ -488,7 +411,7 @@ func sequenceFiles(dir string) ([]string, error) { return res, nil } -func closeAll(cs []io.Closer) (err error) { +func closeAll(cs ...io.Closer) (err error) { for _, c := range cs { if e := c.Close(); e != nil { err = e diff --git a/vendor/github.com/prometheus/tsdb/chunks/chunks_test.go b/vendor/github.com/prometheus/tsdb/chunks/chunks_test.go deleted file mode 100644 index e153029b7..000000000 --- a/vendor/github.com/prometheus/tsdb/chunks/chunks_test.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package chunks - -import ( - "testing" - - "github.com/prometheus/tsdb/testutil" -) - -func TestReaderWithInvalidBuffer(t *testing.T) { - b := realByteSlice([]byte{0x81, 0x81, 0x81, 0x81, 0x81, 0x81}) - r := &Reader{bs: []ByteSlice{b}} - - _, err := r.Chunk(0) - testutil.NotOk(t, err) -} diff --git a/vendor/github.com/prometheus/tsdb/compact.go b/vendor/github.com/prometheus/tsdb/compact.go index a1a7aa76f..5d8155f51 100644 --- a/vendor/github.com/prometheus/tsdb/compact.go +++ b/vendor/github.com/prometheus/tsdb/compact.go @@ -14,10 +14,8 @@ package tsdb import ( - "context" "fmt" "io" - "math" "math/rand" "os" "path/filepath" @@ -51,8 +49,8 @@ func ExponentialBlockRanges(minSize int64, steps, stepSize int) []int64 { // Compactor provides compaction against an underlying storage // of time series data. type Compactor interface { - // Plan returns a set of directories that can be compacted concurrently. - // The directories can be overlapping. + // Plan returns a set of non-overlapping directories that can + // be compacted concurrently. // Results returned when compactions are in progress are undefined. Plan(dir string) ([]string, error) @@ -73,22 +71,20 @@ type Compactor interface { // LeveledCompactor implements the Compactor interface. type LeveledCompactor struct { + dir string metrics *compactorMetrics logger log.Logger ranges []int64 chunkPool chunkenc.Pool - ctx context.Context } type compactorMetrics struct { - ran prometheus.Counter - populatingBlocks prometheus.Gauge - failed prometheus.Counter - overlappingBlocks prometheus.Counter - duration prometheus.Histogram - chunkSize prometheus.Histogram - chunkSamples prometheus.Histogram - chunkRange prometheus.Histogram + ran prometheus.Counter + failed prometheus.Counter + duration prometheus.Histogram + chunkSize prometheus.Histogram + chunkSamples prometheus.Histogram + chunkRange prometheus.Histogram } func newCompactorMetrics(r prometheus.Registerer) *compactorMetrics { @@ -98,18 +94,10 @@ func newCompactorMetrics(r prometheus.Registerer) *compactorMetrics { Name: "prometheus_tsdb_compactions_total", Help: "Total number of compactions that were executed for the partition.", }) - m.populatingBlocks = prometheus.NewGauge(prometheus.GaugeOpts{ - Name: "prometheus_tsdb_compaction_populating_block", - Help: "Set to 1 when a block is currently being written to the disk.", - }) m.failed = prometheus.NewCounter(prometheus.CounterOpts{ Name: "prometheus_tsdb_compactions_failed_total", Help: "Total number of compactions that failed for the partition.", }) - m.overlappingBlocks = prometheus.NewCounter(prometheus.CounterOpts{ - Name: "prometheus_tsdb_vertical_compactions_total", - Help: "Total number of compactions done on overlapping blocks.", - }) m.duration = prometheus.NewHistogram(prometheus.HistogramOpts{ Name: "prometheus_tsdb_compaction_duration_seconds", Help: "Duration of compaction runs", @@ -134,9 +122,7 @@ func newCompactorMetrics(r prometheus.Registerer) *compactorMetrics { if r != nil { r.MustRegister( m.ran, - m.populatingBlocks, m.failed, - m.overlappingBlocks, m.duration, m.chunkRange, m.chunkSamples, @@ -147,22 +133,18 @@ func newCompactorMetrics(r prometheus.Registerer) *compactorMetrics { } // NewLeveledCompactor returns a LeveledCompactor. -func NewLeveledCompactor(ctx context.Context, r prometheus.Registerer, l log.Logger, ranges []int64, pool chunkenc.Pool) (*LeveledCompactor, error) { +func NewLeveledCompactor(r prometheus.Registerer, l log.Logger, ranges []int64, pool chunkenc.Pool) (*LeveledCompactor, error) { if len(ranges) == 0 { return nil, errors.Errorf("at least one range must be provided") } if pool == nil { pool = chunkenc.NewPool() } - if l == nil { - l = log.NewNopLogger() - } return &LeveledCompactor{ ranges: ranges, chunkPool: pool, logger: l, metrics: newCompactorMetrics(r), - ctx: ctx, }, nil } @@ -197,15 +179,11 @@ func (c *LeveledCompactor) plan(dms []dirMeta) ([]string, error) { return dms[i].meta.MinTime < dms[j].meta.MinTime }) - res := c.selectOverlappingDirs(dms) - if len(res) > 0 { - return res, nil - } - // No overlapping blocks, do compaction the usual way. // We do not include a recently created block with max(minTime), so the block which was just created from WAL. // This gives users a window of a full block size to piece-wise backup new data without having to care about data overlap. dms = dms[:len(dms)-1] + var res []string for _, dm := range c.selectDirs(dms) { res = append(res, dm.dir) } @@ -266,28 +244,6 @@ func (c *LeveledCompactor) selectDirs(ds []dirMeta) []dirMeta { return nil } -// selectOverlappingDirs returns all dirs with overlaping time ranges. -// It expects sorted input by mint. -func (c *LeveledCompactor) selectOverlappingDirs(ds []dirMeta) []string { - if len(ds) < 2 { - return nil - } - var overlappingDirs []string - globalMaxt := ds[0].meta.MaxTime - for i, d := range ds[1:] { - if d.meta.MinTime < globalMaxt { - if len(overlappingDirs) == 0 { // When it is the first overlap, need to add the last one as well. - overlappingDirs = append(overlappingDirs, ds[i].dir) - } - overlappingDirs = append(overlappingDirs, d.dir) - } - if d.meta.MaxTime > globalMaxt { - globalMaxt = d.meta.MaxTime - } - } - return overlappingDirs -} - // splitByRange splits the directories by the time range. The range sequence starts at 0. // // For example, if we have blocks [0-10, 10-20, 50-60, 90-100] and the split range tr is 30 @@ -335,17 +291,12 @@ func compactBlockMetas(uid ulid.ULID, blocks ...*BlockMeta) *BlockMeta { res := &BlockMeta{ ULID: uid, MinTime: blocks[0].MinTime, + MaxTime: blocks[len(blocks)-1].MaxTime, } sources := map[ulid.ULID]struct{}{} - // For overlapping blocks, the Maxt can be - // in any block so we track it globally. - maxt := int64(math.MinInt64) for _, b := range blocks { - if b.MaxTime > maxt { - maxt = b.MaxTime - } if b.Compaction.Level > res.Compaction.Level { res.Compaction.Level = b.Compaction.Level } @@ -367,7 +318,6 @@ func compactBlockMetas(uid ulid.ULID, blocks ...*BlockMeta) *BlockMeta { return res.Compaction.Sources[i].Compare(res.Compaction.Sources[j]) < 0 }) - res.MaxTime = maxt return res } @@ -453,11 +403,10 @@ func (c *LeveledCompactor) Compact(dest string, dirs []string, open []*Block) (u var merr MultiError merr.Add(err) - if err != context.Canceled { - for _, b := range bs { - if err := b.setCompactionFailed(); err != nil { - merr.Add(errors.Wrapf(err, "setting compaction failed for block: %s", b.Dir())) - } + + for _, b := range bs { + if err := b.setCompactionFailed(); err != nil { + merr.Add(errors.Wrapf(err, "setting compaction failed for block: %s", b.Dir())) } } @@ -465,8 +414,6 @@ func (c *LeveledCompactor) Compact(dest string, dirs []string, open []*Block) (u } func (c *LeveledCompactor) Write(dest string, b BlockReader, mint, maxt int64, parent *BlockMeta) (ulid.ULID, error) { - start := time.Now() - entropy := rand.New(rand.NewSource(time.Now().UnixNano())) uid := ulid.MustNew(ulid.Now(), entropy) @@ -493,13 +440,7 @@ func (c *LeveledCompactor) Write(dest string, b BlockReader, mint, maxt int64, p return ulid.ULID{}, nil } - level.Info(c.logger).Log( - "msg", "write block", - "mint", meta.MinTime, - "maxt", meta.MaxTime, - "ulid", meta.ULID, - "duration", time.Since(start), - ) + level.Info(c.logger).Log("msg", "write block", "mint", meta.MinTime, "maxt", meta.MaxTime, "ulid", meta.ULID) return uid, nil } @@ -527,19 +468,14 @@ func (w *instrumentedChunkWriter) WriteChunks(chunks ...chunks.Meta) error { func (c *LeveledCompactor) write(dest string, meta *BlockMeta, blocks ...BlockReader) (err error) { dir := filepath.Join(dest, meta.ULID.String()) tmp := dir + ".tmp" - var closers []io.Closer - defer func(t time.Time) { - var merr MultiError - merr.Add(err) - merr.Add(closeAll(closers)) - err = merr.Err() - // RemoveAll returns no error when tmp doesn't exist so it is safe to always run it. - if err := os.RemoveAll(tmp); err != nil { - level.Error(c.logger).Log("msg", "removed tmp folder after failed compaction", "err", err.Error()) - } + defer func(t time.Time) { if err != nil { c.metrics.failed.Inc() + // TODO(gouthamve): Handle error how? + if err := os.RemoveAll(tmp); err != nil { + level.Error(c.logger).Log("msg", "removed tmp folder after failed compaction", "err", err.Error()) + } } c.metrics.ran.Inc() c.metrics.duration.Observe(time.Since(t).Seconds()) @@ -561,7 +497,7 @@ func (c *LeveledCompactor) write(dest string, meta *BlockMeta, blocks ...BlockRe if err != nil { return errors.Wrap(err, "open chunk writer") } - closers = append(closers, chunkw) + defer chunkw.Close() // Record written chunk sizes on level 1 compactions. if meta.Compaction.Level == 1 { chunkw = &instrumentedChunkWriter{ @@ -576,33 +512,27 @@ func (c *LeveledCompactor) write(dest string, meta *BlockMeta, blocks ...BlockRe if err != nil { return errors.Wrap(err, "open index writer") } - closers = append(closers, indexw) + defer indexw.Close() if err := c.populateBlock(blocks, meta, indexw, chunkw); err != nil { return errors.Wrap(err, "write compaction") } - - select { - case <-c.ctx.Done(): - return c.ctx.Err() - default: - } - // We are explicitly closing them here to check for error even // though these are covered under defer. This is because in Windows, // you cannot delete these unless they are closed and the defer is to // make sure they are closed if the function exits due to an error above. - var merr MultiError - for _, w := range closers { - merr.Add(w.Close()) + if err = chunkw.Close(); err != nil { + return errors.Wrap(err, "close chunk writer") } - closers = closers[:0] // Avoid closing the writers twice in the defer. - if merr.Err() != nil { - return merr.Err() + if err = indexw.Close(); err != nil { + return errors.Wrap(err, "close index writer") } - // Populated block is empty, so exit early. + // Populated block is empty, so cleanup and exit. if meta.Stats.NumSamples == 0 { + if err := os.RemoveAll(tmp); err != nil { + return errors.Wrap(err, "remove tmp folder after empty block failed") + } return nil } @@ -645,46 +575,19 @@ func (c *LeveledCompactor) write(dest string, meta *BlockMeta, blocks ...BlockRe // populateBlock fills the index and chunk writers with new data gathered as the union // of the provided blocks. It returns meta information for the new block. -// It expects sorted blocks input by mint. -func (c *LeveledCompactor) populateBlock(blocks []BlockReader, meta *BlockMeta, indexw IndexWriter, chunkw ChunkWriter) (err error) { +func (c *LeveledCompactor) populateBlock(blocks []BlockReader, meta *BlockMeta, indexw IndexWriter, chunkw ChunkWriter) error { if len(blocks) == 0 { return errors.New("cannot populate block from no readers") } var ( - set ChunkSeriesSet - allSymbols = make(map[string]struct{}, 1<<16) - closers = []io.Closer{} - overlapping bool + set ChunkSeriesSet + allSymbols = make(map[string]struct{}, 1<<16) + closers = []io.Closer{} ) - defer func() { - var merr MultiError - merr.Add(err) - merr.Add(closeAll(closers)) - err = merr.Err() - c.metrics.populatingBlocks.Set(0) - }() - c.metrics.populatingBlocks.Set(1) + defer func() { closeAll(closers...) }() - globalMaxt := blocks[0].MaxTime() for i, b := range blocks { - select { - case <-c.ctx.Done(): - return c.ctx.Err() - default: - } - - if !overlapping { - if i > 0 && b.MinTime() < globalMaxt { - c.metrics.overlappingBlocks.Inc() - overlapping = true - level.Warn(c.logger).Log("msg", "found overlapping blocks during compaction", "ulid", meta.ULID) - } - if b.MaxTime() > globalMaxt { - globalMaxt = b.MaxTime() - } - } - indexr, err := b.Index() if err != nil { return errors.Wrapf(err, "open index reader for block %s", b) @@ -741,19 +644,7 @@ func (c *LeveledCompactor) populateBlock(blocks []BlockReader, meta *BlockMeta, } for set.Next() { - select { - case <-c.ctx.Done(): - return c.ctx.Err() - default: - } - lset, chks, dranges := set.At() // The chunks here are not fully deleted. - if overlapping { - // If blocks are overlapping, it is possible to have unsorted chunks. - sort.Slice(chks, func(i, j int) bool { - return chks[i].MinTime < chks[j].MinTime - }) - } // Skip the series with all deleted chunks. if len(chks) == 0 { @@ -787,28 +678,21 @@ func (c *LeveledCompactor) populateBlock(blocks []BlockReader, meta *BlockMeta, } } - mergedChks := chks - if overlapping { - mergedChks, err = chunks.MergeOverlappingChunks(chks) - if err != nil { - return errors.Wrap(err, "merge overlapping chunks") - } - } - if err := chunkw.WriteChunks(mergedChks...); err != nil { + if err := chunkw.WriteChunks(chks...); err != nil { return errors.Wrap(err, "write chunks") } - if err := indexw.AddSeries(i, lset, mergedChks...); err != nil { + if err := indexw.AddSeries(i, lset, chks...); err != nil { return errors.Wrap(err, "add series") } - meta.Stats.NumChunks += uint64(len(mergedChks)) + meta.Stats.NumChunks += uint64(len(chks)) meta.Stats.NumSeries++ - for _, chk := range mergedChks { + for _, chk := range chks { meta.Stats.NumSamples += uint64(chk.Chunk.NumSamples()) } - for _, chk := range mergedChks { + for _, chk := range chks { if err := c.chunkPool.Put(chk.Chunk); err != nil { return errors.Wrap(err, "put chunk") } diff --git a/vendor/github.com/prometheus/tsdb/compact_test.go b/vendor/github.com/prometheus/tsdb/compact_test.go deleted file mode 100644 index 9dc9396a7..000000000 --- a/vendor/github.com/prometheus/tsdb/compact_test.go +++ /dev/null @@ -1,994 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tsdb - -import ( - "context" - "fmt" - "io/ioutil" - "math" - "os" - "path" - "path/filepath" - "testing" - "time" - - "github.com/go-kit/kit/log" - "github.com/pkg/errors" - prom_testutil "github.com/prometheus/client_golang/prometheus/testutil" - dto "github.com/prometheus/client_model/go" - "github.com/prometheus/tsdb/chunks" - "github.com/prometheus/tsdb/fileutil" - "github.com/prometheus/tsdb/labels" - "github.com/prometheus/tsdb/testutil" -) - -func TestSplitByRange(t *testing.T) { - cases := []struct { - trange int64 - ranges [][2]int64 - output [][][2]int64 - }{ - { - trange: 60, - ranges: [][2]int64{{0, 10}}, - output: [][][2]int64{ - {{0, 10}}, - }, - }, - { - trange: 60, - ranges: [][2]int64{{0, 60}}, - output: [][][2]int64{ - {{0, 60}}, - }, - }, - { - trange: 60, - ranges: [][2]int64{{0, 10}, {9, 15}, {30, 60}}, - output: [][][2]int64{ - {{0, 10}, {9, 15}, {30, 60}}, - }, - }, - { - trange: 60, - ranges: [][2]int64{{70, 90}, {125, 130}, {130, 180}, {1000, 1001}}, - output: [][][2]int64{ - {{70, 90}}, - {{125, 130}, {130, 180}}, - {{1000, 1001}}, - }, - }, - // Mis-aligned or too-large blocks are ignored. - { - trange: 60, - ranges: [][2]int64{{50, 70}, {70, 80}}, - output: [][][2]int64{ - {{70, 80}}, - }, - }, - { - trange: 72, - ranges: [][2]int64{{0, 144}, {144, 216}, {216, 288}}, - output: [][][2]int64{ - {{144, 216}}, - {{216, 288}}, - }, - }, - // Various awkward edge cases easy to hit with negative numbers. - { - trange: 60, - ranges: [][2]int64{{-10, -5}}, - output: [][][2]int64{ - {{-10, -5}}, - }, - }, - { - trange: 60, - ranges: [][2]int64{{-60, -50}, {-10, -5}}, - output: [][][2]int64{ - {{-60, -50}, {-10, -5}}, - }, - }, - { - trange: 60, - ranges: [][2]int64{{-60, -50}, {-10, -5}, {0, 15}}, - output: [][][2]int64{ - {{-60, -50}, {-10, -5}}, - {{0, 15}}, - }, - }, - } - - for _, c := range cases { - // Transform input range tuples into dirMetas. - blocks := make([]dirMeta, 0, len(c.ranges)) - for _, r := range c.ranges { - blocks = append(blocks, dirMeta{ - meta: &BlockMeta{ - MinTime: r[0], - MaxTime: r[1], - }, - }) - } - - // Transform output range tuples into dirMetas. - exp := make([][]dirMeta, len(c.output)) - for i, group := range c.output { - for _, r := range group { - exp[i] = append(exp[i], dirMeta{ - meta: &BlockMeta{MinTime: r[0], MaxTime: r[1]}, - }) - } - } - - testutil.Equals(t, exp, splitByRange(blocks, c.trange)) - } -} - -// See https://github.com/prometheus/prometheus/issues/3064 -func TestNoPanicFor0Tombstones(t *testing.T) { - metas := []dirMeta{ - { - dir: "1", - meta: &BlockMeta{ - MinTime: 0, - MaxTime: 100, - }, - }, - { - dir: "2", - meta: &BlockMeta{ - MinTime: 101, - MaxTime: 200, - }, - }, - } - - c, err := NewLeveledCompactor(context.Background(), nil, nil, []int64{50}, nil) - testutil.Ok(t, err) - - c.plan(metas) -} - -func TestLeveledCompactor_plan(t *testing.T) { - // This mimicks our default ExponentialBlockRanges with min block size equals to 20. - compactor, err := NewLeveledCompactor(context.Background(), nil, nil, []int64{ - 20, - 60, - 180, - 540, - 1620, - }, nil) - testutil.Ok(t, err) - - cases := []struct { - metas []dirMeta - expected []string - }{ - { - metas: []dirMeta{ - metaRange("1", 0, 20, nil), - }, - expected: nil, - }, - // We should wait for four blocks of size 20 to appear before compacting. - { - metas: []dirMeta{ - metaRange("1", 0, 20, nil), - metaRange("2", 20, 40, nil), - }, - expected: nil, - }, - // We should wait for a next block of size 20 to appear before compacting - // the existing ones. We have three, but we ignore the fresh one from WAl. - { - metas: []dirMeta{ - metaRange("1", 0, 20, nil), - metaRange("2", 20, 40, nil), - metaRange("3", 40, 60, nil), - }, - expected: nil, - }, - // Block to fill the entire parent range appeared – should be compacted. - { - metas: []dirMeta{ - metaRange("1", 0, 20, nil), - metaRange("2", 20, 40, nil), - metaRange("3", 40, 60, nil), - metaRange("4", 60, 80, nil), - }, - expected: []string{"1", "2", "3"}, - }, - // Block for the next parent range appeared with gap with size 20. Nothing will happen in the first one - // anymore but we ignore fresh one still, so no compaction. - { - metas: []dirMeta{ - metaRange("1", 0, 20, nil), - metaRange("2", 20, 40, nil), - metaRange("3", 60, 80, nil), - }, - expected: nil, - }, - // Block for the next parent range appeared, and we have a gap with size 20 between second and third block. - // We will not get this missed gap anymore and we should compact just these two. - { - metas: []dirMeta{ - metaRange("1", 0, 20, nil), - metaRange("2", 20, 40, nil), - metaRange("3", 60, 80, nil), - metaRange("4", 80, 100, nil), - }, - expected: []string{"1", "2"}, - }, - { - // We have 20, 20, 20, 60, 60 range blocks. "5" is marked as fresh one. - metas: []dirMeta{ - metaRange("1", 0, 20, nil), - metaRange("2", 20, 40, nil), - metaRange("3", 40, 60, nil), - metaRange("4", 60, 120, nil), - metaRange("5", 120, 180, nil), - }, - expected: []string{"1", "2", "3"}, - }, - { - // We have 20, 60, 20, 60, 240 range blocks. We can compact 20 + 60 + 60. - metas: []dirMeta{ - metaRange("2", 20, 40, nil), - metaRange("4", 60, 120, nil), - metaRange("5", 960, 980, nil), // Fresh one. - metaRange("6", 120, 180, nil), - metaRange("7", 720, 960, nil), - }, - expected: []string{"2", "4", "6"}, - }, - // Do not select large blocks that have many tombstones when there is no fresh block. - { - metas: []dirMeta{ - metaRange("1", 0, 540, &BlockStats{ - NumSeries: 10, - NumTombstones: 3, - }), - }, - expected: nil, - }, - // Select large blocks that have many tombstones when fresh appears. - { - metas: []dirMeta{ - metaRange("1", 0, 540, &BlockStats{ - NumSeries: 10, - NumTombstones: 3, - }), - metaRange("2", 540, 560, nil), - }, - expected: []string{"1"}, - }, - // For small blocks, do not compact tombstones, even when fresh appears. - { - metas: []dirMeta{ - metaRange("1", 0, 60, &BlockStats{ - NumSeries: 10, - NumTombstones: 3, - }), - metaRange("2", 60, 80, nil), - }, - expected: nil, - }, - // Regression test: we were stuck in a compact loop where we always recompacted - // the same block when tombstones and series counts were zero. - { - metas: []dirMeta{ - metaRange("1", 0, 540, &BlockStats{ - NumSeries: 0, - NumTombstones: 0, - }), - metaRange("2", 540, 560, nil), - }, - expected: nil, - }, - // Regression test: we were wrongly assuming that new block is fresh from WAL when its ULID is newest. - // We need to actually look on max time instead. - // - // With previous, wrong approach "8" block was ignored, so we were wrongly compacting 5 and 7 and introducing - // block overlaps. - { - metas: []dirMeta{ - metaRange("5", 0, 360, nil), - metaRange("6", 540, 560, nil), // Fresh one. - metaRange("7", 360, 420, nil), - metaRange("8", 420, 540, nil), - }, - expected: []string{"7", "8"}, - }, - // For overlapping blocks. - { - metas: []dirMeta{ - metaRange("1", 0, 20, nil), - metaRange("2", 19, 40, nil), - metaRange("3", 40, 60, nil), - }, - expected: []string{"1", "2"}, - }, - { - metas: []dirMeta{ - metaRange("1", 0, 20, nil), - metaRange("2", 20, 40, nil), - metaRange("3", 30, 50, nil), - }, - expected: []string{"2", "3"}, - }, - { - metas: []dirMeta{ - metaRange("1", 0, 20, nil), - metaRange("2", 10, 40, nil), - metaRange("3", 30, 50, nil), - }, - expected: []string{"1", "2", "3"}, - }, - { - metas: []dirMeta{ - metaRange("5", 0, 360, nil), - metaRange("6", 340, 560, nil), - metaRange("7", 360, 420, nil), - metaRange("8", 420, 540, nil), - }, - expected: []string{"5", "6", "7", "8"}, - }, - } - - for _, c := range cases { - if !t.Run("", func(t *testing.T) { - res, err := compactor.plan(c.metas) - testutil.Ok(t, err) - testutil.Equals(t, c.expected, res) - }) { - return - } - } -} - -func TestRangeWithFailedCompactionWontGetSelected(t *testing.T) { - compactor, err := NewLeveledCompactor(context.Background(), nil, nil, []int64{ - 20, - 60, - 240, - 720, - 2160, - }, nil) - testutil.Ok(t, err) - - cases := []struct { - metas []dirMeta - }{ - { - metas: []dirMeta{ - metaRange("1", 0, 20, nil), - metaRange("2", 20, 40, nil), - metaRange("3", 40, 60, nil), - metaRange("4", 60, 80, nil), - }, - }, - { - metas: []dirMeta{ - metaRange("1", 0, 20, nil), - metaRange("2", 20, 40, nil), - metaRange("3", 60, 80, nil), - metaRange("4", 80, 100, nil), - }, - }, - { - metas: []dirMeta{ - metaRange("1", 0, 20, nil), - metaRange("2", 20, 40, nil), - metaRange("3", 40, 60, nil), - metaRange("4", 60, 120, nil), - metaRange("5", 120, 180, nil), - metaRange("6", 180, 200, nil), - }, - }, - } - - for _, c := range cases { - c.metas[1].meta.Compaction.Failed = true - res, err := compactor.plan(c.metas) - testutil.Ok(t, err) - - testutil.Equals(t, []string(nil), res) - } -} - -func TestCompactionFailWillCleanUpTempDir(t *testing.T) { - compactor, err := NewLeveledCompactor(context.Background(), nil, log.NewNopLogger(), []int64{ - 20, - 60, - 240, - 720, - 2160, - }, nil) - testutil.Ok(t, err) - - tmpdir, err := ioutil.TempDir("", "test") - testutil.Ok(t, err) - defer os.RemoveAll(tmpdir) - - testutil.NotOk(t, compactor.write(tmpdir, &BlockMeta{}, erringBReader{})) - _, err = os.Stat(filepath.Join(tmpdir, BlockMeta{}.ULID.String()) + ".tmp") - testutil.Assert(t, os.IsNotExist(err), "directory is not cleaned up") -} - -func metaRange(name string, mint, maxt int64, stats *BlockStats) dirMeta { - meta := &BlockMeta{MinTime: mint, MaxTime: maxt} - if stats != nil { - meta.Stats = *stats - } - return dirMeta{ - dir: name, - meta: meta, - } -} - -type erringBReader struct{} - -func (erringBReader) Index() (IndexReader, error) { return nil, errors.New("index") } -func (erringBReader) Chunks() (ChunkReader, error) { return nil, errors.New("chunks") } -func (erringBReader) Tombstones() (TombstoneReader, error) { return nil, errors.New("tombstones") } -func (erringBReader) MinTime() int64 { return 0 } -func (erringBReader) MaxTime() int64 { return 0 } - -type nopChunkWriter struct{} - -func (nopChunkWriter) WriteChunks(chunks ...chunks.Meta) error { return nil } -func (nopChunkWriter) Close() error { return nil } - -func TestCompaction_populateBlock(t *testing.T) { - var populateBlocksCases = []struct { - title string - inputSeriesSamples [][]seriesSamples - compactMinTime int64 - compactMaxTime int64 // When not defined the test runner sets a default of math.MaxInt64. - expSeriesSamples []seriesSamples - expErr error - }{ - { - title: "Populate block from empty input should return error.", - inputSeriesSamples: [][]seriesSamples{}, - expErr: errors.New("cannot populate block from no readers"), - }, - { - // Populate from single block without chunks. We expect these kind of series being ignored. - inputSeriesSamples: [][]seriesSamples{ - { - { - lset: map[string]string{"a": "b"}, - }, - }, - }, - }, - { - title: "Populate from single block. We expect the same samples at the output.", - inputSeriesSamples: [][]seriesSamples{ - { - { - lset: map[string]string{"a": "b"}, - chunks: [][]sample{{{t: 0}, {t: 10}}, {{t: 11}, {t: 20}}}, - }, - }, - }, - expSeriesSamples: []seriesSamples{ - { - lset: map[string]string{"a": "b"}, - chunks: [][]sample{{{t: 0}, {t: 10}}, {{t: 11}, {t: 20}}}, - }, - }, - }, - { - title: "Populate from two blocks.", - inputSeriesSamples: [][]seriesSamples{ - { - { - lset: map[string]string{"a": "b"}, - chunks: [][]sample{{{t: 0}, {t: 10}}, {{t: 11}, {t: 20}}}, - }, - { - lset: map[string]string{"a": "c"}, - chunks: [][]sample{{{t: 1}, {t: 9}}, {{t: 10}, {t: 19}}}, - }, - { - // no-chunk series should be dropped. - lset: map[string]string{"a": "empty"}, - }, - }, - { - { - lset: map[string]string{"a": "b"}, - chunks: [][]sample{{{t: 21}, {t: 30}}}, - }, - { - lset: map[string]string{"a": "c"}, - chunks: [][]sample{{{t: 40}, {t: 45}}}, - }, - }, - }, - expSeriesSamples: []seriesSamples{ - { - lset: map[string]string{"a": "b"}, - chunks: [][]sample{{{t: 0}, {t: 10}}, {{t: 11}, {t: 20}}, {{t: 21}, {t: 30}}}, - }, - { - lset: map[string]string{"a": "c"}, - chunks: [][]sample{{{t: 1}, {t: 9}}, {{t: 10}, {t: 19}}, {{t: 40}, {t: 45}}}, - }, - }, - }, - { - title: "Populate from two blocks showing that order is maintained.", - inputSeriesSamples: [][]seriesSamples{ - { - { - lset: map[string]string{"a": "b"}, - chunks: [][]sample{{{t: 0}, {t: 10}}, {{t: 11}, {t: 20}}}, - }, - { - lset: map[string]string{"a": "c"}, - chunks: [][]sample{{{t: 1}, {t: 9}}, {{t: 10}, {t: 19}}}, - }, - }, - { - { - lset: map[string]string{"a": "b"}, - chunks: [][]sample{{{t: 21}, {t: 30}}}, - }, - { - lset: map[string]string{"a": "c"}, - chunks: [][]sample{{{t: 40}, {t: 45}}}, - }, - }, - }, - expSeriesSamples: []seriesSamples{ - { - lset: map[string]string{"a": "b"}, - chunks: [][]sample{{{t: 0}, {t: 10}}, {{t: 11}, {t: 20}}, {{t: 21}, {t: 30}}}, - }, - { - lset: map[string]string{"a": "c"}, - chunks: [][]sample{{{t: 1}, {t: 9}}, {{t: 10}, {t: 19}}, {{t: 40}, {t: 45}}}, - }, - }, - }, - { - title: "Populate from two blocks showing that order of series is sorted.", - inputSeriesSamples: [][]seriesSamples{ - { - { - lset: map[string]string{"a": "4"}, - chunks: [][]sample{{{t: 5}, {t: 7}}}, - }, - { - lset: map[string]string{"a": "3"}, - chunks: [][]sample{{{t: 5}, {t: 6}}}, - }, - { - lset: map[string]string{"a": "same"}, - chunks: [][]sample{{{t: 1}, {t: 4}}}, - }, - }, - { - { - lset: map[string]string{"a": "2"}, - chunks: [][]sample{{{t: 1}, {t: 3}}}, - }, - { - lset: map[string]string{"a": "1"}, - chunks: [][]sample{{{t: 1}, {t: 2}}}, - }, - { - lset: map[string]string{"a": "same"}, - chunks: [][]sample{{{t: 5}, {t: 8}}}, - }, - }, - }, - expSeriesSamples: []seriesSamples{ - { - lset: map[string]string{"a": "1"}, - chunks: [][]sample{{{t: 1}, {t: 2}}}, - }, - { - lset: map[string]string{"a": "2"}, - chunks: [][]sample{{{t: 1}, {t: 3}}}, - }, - { - lset: map[string]string{"a": "3"}, - chunks: [][]sample{{{t: 5}, {t: 6}}}, - }, - { - lset: map[string]string{"a": "4"}, - chunks: [][]sample{{{t: 5}, {t: 7}}}, - }, - { - lset: map[string]string{"a": "same"}, - chunks: [][]sample{{{t: 1}, {t: 4}}, {{t: 5}, {t: 8}}}, - }, - }, - }, - { - // This should not happened because head block is making sure the chunks are not crossing block boundaries. - title: "Populate from single block containing chunk outside of compact meta time range.", - inputSeriesSamples: [][]seriesSamples{ - { - { - lset: map[string]string{"a": "b"}, - chunks: [][]sample{{{t: 1}, {t: 2}}, {{t: 10}, {t: 30}}}, - }, - }, - }, - compactMinTime: 0, - compactMaxTime: 20, - expErr: errors.New("found chunk with minTime: 10 maxTime: 30 outside of compacted minTime: 0 maxTime: 20"), - }, - { - // Introduced by https://github.com/prometheus/tsdb/issues/347. - title: "Populate from single block containing extra chunk", - inputSeriesSamples: [][]seriesSamples{ - { - { - lset: map[string]string{"a": "issue347"}, - chunks: [][]sample{{{t: 1}, {t: 2}}, {{t: 10}, {t: 20}}}, - }, - }, - }, - compactMinTime: 0, - compactMaxTime: 10, - expErr: errors.New("found chunk with minTime: 10 maxTime: 20 outside of compacted minTime: 0 maxTime: 10"), - }, - { - // No special deduplication expected. - title: "Populate from two blocks containing duplicated chunk.", - inputSeriesSamples: [][]seriesSamples{ - { - { - lset: map[string]string{"a": "b"}, - chunks: [][]sample{{{t: 1}, {t: 2}}, {{t: 10}, {t: 20}}}, - }, - }, - { - { - lset: map[string]string{"a": "b"}, - chunks: [][]sample{{{t: 10}, {t: 20}}}, - }, - }, - }, - expSeriesSamples: []seriesSamples{ - { - lset: map[string]string{"a": "b"}, - chunks: [][]sample{{{t: 1}, {t: 2}}, {{t: 10}, {t: 20}}, {{t: 10}, {t: 20}}}, - }, - }, - }, - } - - for _, tc := range populateBlocksCases { - if ok := t.Run(tc.title, func(t *testing.T) { - blocks := make([]BlockReader, 0, len(tc.inputSeriesSamples)) - for _, b := range tc.inputSeriesSamples { - ir, cr, mint, maxt := createIdxChkReaders(b) - blocks = append(blocks, &mockBReader{ir: ir, cr: cr, mint: mint, maxt: maxt}) - } - - c, err := NewLeveledCompactor(context.Background(), nil, nil, []int64{0}, nil) - testutil.Ok(t, err) - - meta := &BlockMeta{ - MinTime: tc.compactMinTime, - MaxTime: tc.compactMaxTime, - } - if meta.MaxTime == 0 { - meta.MaxTime = math.MaxInt64 - } - - iw := &mockIndexWriter{} - err = c.populateBlock(blocks, meta, iw, nopChunkWriter{}) - if tc.expErr != nil { - testutil.NotOk(t, err) - testutil.Equals(t, tc.expErr.Error(), err.Error()) - return - } - testutil.Ok(t, err) - - testutil.Equals(t, tc.expSeriesSamples, iw.series) - - // Check if stats are calculated properly. - s := BlockStats{ - NumSeries: uint64(len(tc.expSeriesSamples)), - } - for _, series := range tc.expSeriesSamples { - s.NumChunks += uint64(len(series.chunks)) - for _, chk := range series.chunks { - s.NumSamples += uint64(len(chk)) - } - } - testutil.Equals(t, s, meta.Stats) - }); !ok { - return - } - } -} - -func BenchmarkCompaction(b *testing.B) { - cases := []struct { - ranges [][2]int64 - compactionType string - }{ - { - ranges: [][2]int64{{0, 100}, {200, 300}, {400, 500}, {600, 700}}, - compactionType: "normal", - }, - { - ranges: [][2]int64{{0, 1000}, {2000, 3000}, {4000, 5000}, {6000, 7000}}, - compactionType: "normal", - }, - { - ranges: [][2]int64{{0, 10000}, {20000, 30000}, {40000, 50000}, {60000, 70000}}, - compactionType: "normal", - }, - { - ranges: [][2]int64{{0, 100000}, {200000, 300000}, {400000, 500000}, {600000, 700000}}, - compactionType: "normal", - }, - // 40% overlaps. - { - ranges: [][2]int64{{0, 100}, {60, 160}, {120, 220}, {180, 280}}, - compactionType: "vertical", - }, - { - ranges: [][2]int64{{0, 1000}, {600, 1600}, {1200, 2200}, {1800, 2800}}, - compactionType: "vertical", - }, - { - ranges: [][2]int64{{0, 10000}, {6000, 16000}, {12000, 22000}, {18000, 28000}}, - compactionType: "vertical", - }, - { - ranges: [][2]int64{{0, 100000}, {60000, 160000}, {120000, 220000}, {180000, 280000}}, - compactionType: "vertical", - }, - } - - nSeries := 10000 - for _, c := range cases { - nBlocks := len(c.ranges) - b.Run(fmt.Sprintf("type=%s,blocks=%d,series=%d,samplesPerSeriesPerBlock=%d", c.compactionType, nBlocks, nSeries, c.ranges[0][1]-c.ranges[0][0]+1), func(b *testing.B) { - dir, err := ioutil.TempDir("", "bench_compaction") - testutil.Ok(b, err) - defer func() { - testutil.Ok(b, os.RemoveAll(dir)) - }() - blockDirs := make([]string, 0, len(c.ranges)) - var blocks []*Block - for _, r := range c.ranges { - block, err := OpenBlock(nil, createBlock(b, dir, genSeries(nSeries, 10, r[0], r[1])), nil) - testutil.Ok(b, err) - blocks = append(blocks, block) - defer func() { - testutil.Ok(b, block.Close()) - }() - blockDirs = append(blockDirs, block.Dir()) - } - - c, err := NewLeveledCompactor(context.Background(), nil, log.NewNopLogger(), []int64{0}, nil) - testutil.Ok(b, err) - - b.ResetTimer() - b.ReportAllocs() - _, err = c.Compact(dir, blockDirs, blocks) - testutil.Ok(b, err) - }) - } -} - -// TestDisableAutoCompactions checks that we can -// disable and enable the auto compaction. -// This is needed for unit tests that rely on -// checking state before and after a compaction. -func TestDisableAutoCompactions(t *testing.T) { - db, delete := openTestDB(t, nil) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - - blockRange := DefaultOptions.BlockRanges[0] - label := labels.FromStrings("foo", "bar") - - // Trigger a compaction to check that it was skipped and - // no new blocks were created when compaction is disabled. - db.DisableCompactions() - app := db.Appender() - for i := int64(0); i < 3; i++ { - _, err := app.Add(label, i*blockRange, 0) - testutil.Ok(t, err) - _, err = app.Add(label, i*blockRange+1000, 0) - testutil.Ok(t, err) - } - testutil.Ok(t, app.Commit()) - - select { - case db.compactc <- struct{}{}: - default: - } - - m := &dto.Metric{} - for x := 0; x < 10; x++ { - db.metrics.compactionsSkipped.Write(m) - if *m.Counter.Value > float64(0) { - break - } - time.Sleep(10 * time.Millisecond) - } - - testutil.Assert(t, *m.Counter.Value > float64(0), "No compaction was skipped after the set timeout.") - testutil.Equals(t, 0, len(db.blocks)) - - // Enable the compaction, trigger it and check that the block is persisted. - db.EnableCompactions() - select { - case db.compactc <- struct{}{}: - default: - } - for x := 0; x < 100; x++ { - if len(db.Blocks()) > 0 { - break - } - time.Sleep(100 * time.Millisecond) - } - testutil.Assert(t, len(db.Blocks()) > 0, "No block was persisted after the set timeout.") -} - -// TestCancelCompactions ensures that when the db is closed -// any running compaction is cancelled to unblock closing the db. -func TestCancelCompactions(t *testing.T) { - tmpdir, err := ioutil.TempDir("", "testCancelCompaction") - testutil.Ok(t, err) - defer os.RemoveAll(tmpdir) - - // Create some blocks to fall within the compaction range. - createBlock(t, tmpdir, genSeries(10, 10000, 0, 1000)) - createBlock(t, tmpdir, genSeries(10, 10000, 1000, 2000)) - createBlock(t, tmpdir, genSeries(1, 1, 2000, 2001)) // The most recent block is ignored so can be e small one. - - // Copy the db so we have an exact copy to compare compaction times. - tmpdirCopy := tmpdir + "Copy" - err = fileutil.CopyDirs(tmpdir, tmpdirCopy) - testutil.Ok(t, err) - defer os.RemoveAll(tmpdirCopy) - - // Measure the compaction time without interupting it. - var timeCompactionUninterrupted time.Duration - { - db, err := Open(tmpdir, log.NewNopLogger(), nil, &Options{BlockRanges: []int64{1, 2000}}) - testutil.Ok(t, err) - testutil.Equals(t, 3, len(db.Blocks()), "initial block count mismatch") - testutil.Equals(t, 0.0, prom_testutil.ToFloat64(db.compactor.(*LeveledCompactor).metrics.ran), "initial compaction counter mismatch") - db.compactc <- struct{}{} // Trigger a compaction. - var start time.Time - for prom_testutil.ToFloat64(db.compactor.(*LeveledCompactor).metrics.populatingBlocks) <= 0 { - time.Sleep(3 * time.Millisecond) - } - start = time.Now() - - for prom_testutil.ToFloat64(db.compactor.(*LeveledCompactor).metrics.ran) != 1 { - time.Sleep(3 * time.Millisecond) - } - timeCompactionUninterrupted = time.Since(start) - - testutil.Ok(t, db.Close()) - } - // Measure the compaction time when closing the db in the middle of compaction. - { - db, err := Open(tmpdirCopy, log.NewNopLogger(), nil, &Options{BlockRanges: []int64{1, 2000}}) - testutil.Ok(t, err) - testutil.Equals(t, 3, len(db.Blocks()), "initial block count mismatch") - testutil.Equals(t, 0.0, prom_testutil.ToFloat64(db.compactor.(*LeveledCompactor).metrics.ran), "initial compaction counter mismatch") - db.compactc <- struct{}{} // Trigger a compaction. - dbClosed := make(chan struct{}) - - for prom_testutil.ToFloat64(db.compactor.(*LeveledCompactor).metrics.populatingBlocks) <= 0 { - time.Sleep(3 * time.Millisecond) - } - go func() { - testutil.Ok(t, db.Close()) - close(dbClosed) - }() - - start := time.Now() - <-dbClosed - actT := time.Since(start) - expT := time.Duration(timeCompactionUninterrupted / 2) // Closing the db in the middle of compaction should less than half the time. - testutil.Assert(t, actT < expT, "closing the db took more than expected. exp: <%v, act: %v", expT, actT) - } -} - -// TestDeleteCompactionBlockAfterFailedReload ensures that a failed reload immediately after a compaction -// deletes the resulting block to avoid creatings blocks with the same time range. -func TestDeleteCompactionBlockAfterFailedReload(t *testing.T) { - - tests := map[string]func(*DB) int{ - "Test Head Compaction": func(db *DB) int { - rangeToTriggerCompaction := db.opts.BlockRanges[0]/2*3 - 1 - defaultLabel := labels.FromStrings("foo", "bar") - - // Add some data to the head that is enough to trigger a compaction. - app := db.Appender() - _, err := app.Add(defaultLabel, 1, 0) - testutil.Ok(t, err) - _, err = app.Add(defaultLabel, 2, 0) - testutil.Ok(t, err) - _, err = app.Add(defaultLabel, 3+rangeToTriggerCompaction, 0) - testutil.Ok(t, err) - testutil.Ok(t, app.Commit()) - - return 0 - }, - "Test Block Compaction": func(db *DB) int { - blocks := []*BlockMeta{ - {MinTime: 0, MaxTime: 100}, - {MinTime: 100, MaxTime: 150}, - {MinTime: 150, MaxTime: 200}, - } - for _, m := range blocks { - createBlock(t, db.Dir(), genSeries(1, 1, m.MinTime, m.MaxTime)) - } - testutil.Ok(t, db.reload()) - testutil.Equals(t, len(blocks), len(db.Blocks()), "unexpected block count after a reload") - - return len(blocks) - }, - } - - for title, bootStrap := range tests { - t.Run(title, func(t *testing.T) { - db, delete := openTestDB(t, &Options{ - BlockRanges: []int64{1, 100}, - }) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - db.DisableCompactions() - - expBlocks := bootStrap(db) - - // Create a block that will trigger the reload to fail. - blockPath := createBlock(t, db.Dir(), genSeries(1, 1, 200, 300)) - lastBlockIndex := path.Join(blockPath, indexFilename) - actBlocks, err := blockDirs(db.Dir()) - testutil.Ok(t, err) - testutil.Equals(t, expBlocks, len(actBlocks)-1) // -1 to exclude the corrupted block. - testutil.Ok(t, os.RemoveAll(lastBlockIndex)) // Corrupt the block by removing the index file. - - testutil.Equals(t, 0.0, prom_testutil.ToFloat64(db.metrics.reloadsFailed), "initial 'failed db reload' count metrics mismatch") - testutil.Equals(t, 0.0, prom_testutil.ToFloat64(db.compactor.(*LeveledCompactor).metrics.ran), "initial `compactions` count metric mismatch") - - // Do the compaction and check the metrics. - // Compaction should succeed, but the reload should fail and - // the new block created from the compaction should be deleted. - testutil.NotOk(t, db.compact()) - testutil.Equals(t, 1.0, prom_testutil.ToFloat64(db.metrics.reloadsFailed), "'failed db reload' count metrics mismatch") - testutil.Equals(t, 1.0, prom_testutil.ToFloat64(db.compactor.(*LeveledCompactor).metrics.ran), "`compaction` count metric mismatch") - actBlocks, err = blockDirs(db.Dir()) - testutil.Ok(t, err) - testutil.Equals(t, expBlocks, len(actBlocks)-1, "block count should be the same as before the compaction") // -1 to exclude the corrupted block. - }) - } -} diff --git a/vendor/github.com/prometheus/tsdb/db.go b/vendor/github.com/prometheus/tsdb/db.go index 7b03a209c..1349dfbd5 100644 --- a/vendor/github.com/prometheus/tsdb/db.go +++ b/vendor/github.com/prometheus/tsdb/db.go @@ -16,7 +16,6 @@ package tsdb import ( "bytes" - "context" "fmt" "io" "io/ioutil" @@ -45,11 +44,10 @@ import ( // DefaultOptions used for the DB. They are sane for setups using // millisecond precision timestamps. var DefaultOptions = &Options{ - WALSegmentSize: wal.DefaultSegmentSize, - RetentionDuration: 15 * 24 * 60 * 60 * 1000, // 15 days in milliseconds - BlockRanges: ExponentialBlockRanges(int64(2*time.Hour)/1e6, 3, 5), - NoLockfile: false, - AllowOverlappingBlocks: false, + WALSegmentSize: wal.DefaultSegmentSize, + RetentionDuration: 15 * 24 * 60 * 60 * 1000, // 15 days in milliseconds + BlockRanges: ExponentialBlockRanges(int64(2*time.Hour)/1e6, 3, 5), + NoLockfile: false, } // Options of the DB storage. @@ -72,10 +70,6 @@ type Options struct { // NoLockfile disables creation and consideration of a lock file. NoLockfile bool - - // Overlapping blocks are allowed if AllowOverlappingBlocks is true. - // This in-turn enables vertical compaction and vertical query merge. - AllowOverlappingBlocks bool } // Appender allows appending a batch of data. It must be completed with a @@ -132,9 +126,6 @@ type DB struct { // changing the autoCompact var. autoCompactMtx sync.Mutex autoCompact bool - - // Cancel a running compaction when a shutdown is initiated. - compactCancel context.CancelFunc } type dbMetrics struct { @@ -211,7 +202,7 @@ func newDBMetrics(db *DB, r prometheus.Registerer) *dbMetrics { Help: "The time taken to recompact blocks to remove tombstones.", }) m.blocksBytes = prometheus.NewGauge(prometheus.GaugeOpts{ - Name: "prometheus_tsdb_storage_blocks_bytes", + Name: "prometheus_tsdb_storage_blocks_bytes_total", Help: "The number of bytes that are currently used for local storage by all blocks.", }) m.sizeRetentionCount = prometheus.NewCounter(prometheus.CounterOpts{ @@ -280,13 +271,10 @@ func Open(dir string, l log.Logger, r prometheus.Registerer, opts *Options) (db db.lockf = lockf } - ctx, cancel := context.WithCancel(context.Background()) - db.compactor, err = NewLeveledCompactor(ctx, r, l, opts.BlockRanges, db.chunkPool) + db.compactor, err = NewLeveledCompactor(r, l, opts.BlockRanges, db.chunkPool) if err != nil { - cancel() return nil, errors.Wrap(err, "create leveled compactor") } - db.compactCancel = cancel segmentSize := wal.DefaultSegmentSize if opts.WALSegmentSize > 0 { @@ -437,9 +425,6 @@ func (db *DB) compact() (err error) { runtime.GC() if err := db.reload(); err != nil { - if err := os.RemoveAll(filepath.Join(db.dir, uid.String())); err != nil { - return errors.Wrapf(err, "delete persisted head block after failed db reload:%s", uid) - } return errors.Wrap(err, "reload blocks") } if (uid == ulid.ULID{}) { @@ -469,16 +454,12 @@ func (db *DB) compact() (err error) { default: } - uid, err := db.compactor.Compact(db.dir, plan, db.blocks) - if err != nil { + if _, err := db.compactor.Compact(db.dir, plan, db.blocks); err != nil { return errors.Wrapf(err, "compact %s", plan) } runtime.GC() if err := db.reload(); err != nil { - if err := os.RemoveAll(filepath.Join(db.dir, uid.String())); err != nil { - return errors.Wrapf(err, "delete compacted block after failed db reload:%s", uid) - } return errors.Wrap(err, "reload blocks") } runtime.GC() @@ -524,13 +505,7 @@ func (db *DB) reload() (err error) { } } if len(corrupted) > 0 { - // Close all new blocks to release the lock for windows. - for _, block := range loadable { - if _, loaded := db.getBlock(block.Meta().ULID); !loaded { - block.Close() - } - } - return fmt.Errorf("unexpected corrupted block:%v", corrupted) + return errors.Wrap(err, "unexpected corrupted block") } // All deletable blocks should not be loaded. @@ -551,12 +526,10 @@ func (db *DB) reload() (err error) { db.metrics.blocksBytes.Set(float64(blocksSize)) sort.Slice(loadable, func(i, j int) bool { - return loadable[i].Meta().MinTime < loadable[j].Meta().MinTime + return loadable[i].Meta().MaxTime < loadable[j].Meta().MaxTime }) - if !db.opts.AllowOverlappingBlocks { - if err := validateBlockSequence(loadable); err != nil { - return errors.Wrap(err, "invalid block sequence") - } + if err := validateBlockSequence(loadable); err != nil { + return errors.Wrap(err, "invalid block sequence") } // Swap new blocks first for subsequently created readers to be seen. @@ -565,14 +538,6 @@ func (db *DB) reload() (err error) { db.blocks = loadable db.mtx.Unlock() - blockMetas := make([]BlockMeta, 0, len(loadable)) - for _, b := range loadable { - blockMetas = append(blockMetas, b.Meta()) - } - if overlaps := OverlappingBlocks(blockMetas); len(overlaps) > 0 { - level.Warn(db.logger).Log("msg", "overlapping blocks found during reload", "detail", overlaps.String()) - } - for _, b := range oldBlocks { if _, ok := deletable[b.Meta().ULID]; ok { deletable[b.Meta().ULID] = b @@ -848,7 +813,6 @@ func (db *DB) Head() *Head { // Close the partition. func (db *DB) Close() error { close(db.stopc) - db.compactCancel() <-db.donec db.mtx.Lock() @@ -924,7 +888,6 @@ func (db *DB) Snapshot(dir string, withHead bool) error { // A goroutine must not handle more than one open Querier. func (db *DB) Querier(mint, maxt int64) (Querier, error) { var blocks []BlockReader - var blockMetas []BlockMeta db.mtx.RLock() defer db.mtx.RUnlock() @@ -932,7 +895,6 @@ func (db *DB) Querier(mint, maxt int64) (Querier, error) { for _, b := range db.blocks { if b.OverlapsClosedInterval(mint, maxt) { blocks = append(blocks, b) - blockMetas = append(blockMetas, b.Meta()) } } if maxt >= db.head.MinTime() { @@ -943,31 +905,22 @@ func (db *DB) Querier(mint, maxt int64) (Querier, error) { }) } - blockQueriers := make([]Querier, 0, len(blocks)) + sq := &querier{ + blocks: make([]Querier, 0, len(blocks)), + } for _, b := range blocks { q, err := NewBlockQuerier(b, mint, maxt) if err == nil { - blockQueriers = append(blockQueriers, q) + sq.blocks = append(sq.blocks, q) continue } // If we fail, all previously opened queriers must be closed. - for _, q := range blockQueriers { + for _, q := range sq.blocks { q.Close() } return nil, errors.Wrapf(err, "open querier for block %s", b) } - - if len(OverlappingBlocks(blockMetas)) > 0 { - return &verticalQuerier{ - querier: querier{ - blocks: blockQueriers, - }, - }, nil - } - - return &querier{ - blocks: blockQueriers, - }, nil + return sq, nil } func rangeForTimestamp(t int64, width int64) (maxt int64) { @@ -1131,7 +1084,7 @@ func (es MultiError) Err() error { return es } -func closeAll(cs []io.Closer) error { +func closeAll(cs ...io.Closer) error { var merr MultiError for _, c := range cs { diff --git a/vendor/github.com/prometheus/tsdb/db_test.go b/vendor/github.com/prometheus/tsdb/db_test.go deleted file mode 100644 index eda807f3f..000000000 --- a/vendor/github.com/prometheus/tsdb/db_test.go +++ /dev/null @@ -1,2069 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tsdb - -import ( - "fmt" - "io/ioutil" - "math" - "math/rand" - "os" - "path" - "path/filepath" - "sort" - "testing" - "time" - - "github.com/go-kit/kit/log" - "github.com/oklog/ulid" - "github.com/pkg/errors" - "github.com/prometheus/client_golang/prometheus" - prom_testutil "github.com/prometheus/client_golang/prometheus/testutil" - "github.com/prometheus/tsdb/chunks" - "github.com/prometheus/tsdb/index" - "github.com/prometheus/tsdb/labels" - "github.com/prometheus/tsdb/testutil" - "github.com/prometheus/tsdb/tsdbutil" - "github.com/prometheus/tsdb/wal" -) - -func openTestDB(t testing.TB, opts *Options) (db *DB, close func()) { - tmpdir, err := ioutil.TempDir("", "test") - testutil.Ok(t, err) - - db, err = Open(tmpdir, nil, nil, opts) - testutil.Ok(t, err) - - // Do not close the test database by default as it will deadlock on test failures. - return db, func() { - testutil.Ok(t, os.RemoveAll(tmpdir)) - } -} - -// query runs a matcher query against the querier and fully expands its data. -func query(t testing.TB, q Querier, matchers ...labels.Matcher) map[string][]tsdbutil.Sample { - ss, err := q.Select(matchers...) - defer func() { - testutil.Ok(t, q.Close()) - }() - testutil.Ok(t, err) - - result := map[string][]tsdbutil.Sample{} - - for ss.Next() { - series := ss.At() - - samples := []tsdbutil.Sample{} - it := series.Iterator() - for it.Next() { - t, v := it.At() - samples = append(samples, sample{t: t, v: v}) - } - testutil.Ok(t, it.Err()) - - name := series.Labels().String() - result[name] = samples - } - testutil.Ok(t, ss.Err()) - - return result -} - -// Ensure that blocks are held in memory in their time order -// and not in ULID order as they are read from the directory. -func TestDB_reloadOrder(t *testing.T) { - db, delete := openTestDB(t, nil) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - - metas := []BlockMeta{ - {MinTime: 90, MaxTime: 100}, - {MinTime: 70, MaxTime: 80}, - {MinTime: 100, MaxTime: 110}, - } - for _, m := range metas { - createBlock(t, db.Dir(), genSeries(1, 1, m.MinTime, m.MaxTime)) - } - - testutil.Ok(t, db.reload()) - blocks := db.Blocks() - for _, b := range blocks { - b.meta.Stats.NumBytes = 0 - } - testutil.Equals(t, 3, len(blocks)) - testutil.Equals(t, metas[1].MinTime, blocks[0].Meta().MinTime) - testutil.Equals(t, metas[1].MaxTime, blocks[0].Meta().MaxTime) - testutil.Equals(t, metas[0].MinTime, blocks[1].Meta().MinTime) - testutil.Equals(t, metas[0].MaxTime, blocks[1].Meta().MaxTime) - testutil.Equals(t, metas[2].MinTime, blocks[2].Meta().MinTime) - testutil.Equals(t, metas[2].MaxTime, blocks[2].Meta().MaxTime) -} - -func TestDataAvailableOnlyAfterCommit(t *testing.T) { - db, delete := openTestDB(t, nil) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - - app := db.Appender() - - _, err := app.Add(labels.FromStrings("foo", "bar"), 0, 0) - testutil.Ok(t, err) - - querier, err := db.Querier(0, 1) - testutil.Ok(t, err) - seriesSet := query(t, querier, labels.NewEqualMatcher("foo", "bar")) - testutil.Equals(t, map[string][]tsdbutil.Sample{}, seriesSet) - - err = app.Commit() - testutil.Ok(t, err) - - querier, err = db.Querier(0, 1) - testutil.Ok(t, err) - defer querier.Close() - - seriesSet = query(t, querier, labels.NewEqualMatcher("foo", "bar")) - - testutil.Equals(t, map[string][]tsdbutil.Sample{`{foo="bar"}`: {sample{t: 0, v: 0}}}, seriesSet) -} - -func TestDataNotAvailableAfterRollback(t *testing.T) { - db, delete := openTestDB(t, nil) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - - app := db.Appender() - _, err := app.Add(labels.FromStrings("foo", "bar"), 0, 0) - testutil.Ok(t, err) - - err = app.Rollback() - testutil.Ok(t, err) - - querier, err := db.Querier(0, 1) - testutil.Ok(t, err) - defer querier.Close() - - seriesSet := query(t, querier, labels.NewEqualMatcher("foo", "bar")) - - testutil.Equals(t, map[string][]tsdbutil.Sample{}, seriesSet) -} - -func TestDBAppenderAddRef(t *testing.T) { - db, delete := openTestDB(t, nil) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - - app1 := db.Appender() - - ref1, err := app1.Add(labels.FromStrings("a", "b"), 123, 0) - testutil.Ok(t, err) - - // Reference should already work before commit. - err = app1.AddFast(ref1, 124, 1) - testutil.Ok(t, err) - - err = app1.Commit() - testutil.Ok(t, err) - - app2 := db.Appender() - - // first ref should already work in next transaction. - err = app2.AddFast(ref1, 125, 0) - testutil.Ok(t, err) - - ref2, err := app2.Add(labels.FromStrings("a", "b"), 133, 1) - testutil.Ok(t, err) - - testutil.Assert(t, ref1 == ref2, "") - - // Reference must be valid to add another sample. - err = app2.AddFast(ref2, 143, 2) - testutil.Ok(t, err) - - err = app2.AddFast(9999999, 1, 1) - testutil.Equals(t, ErrNotFound, errors.Cause(err)) - - testutil.Ok(t, app2.Commit()) - - q, err := db.Querier(0, 200) - testutil.Ok(t, err) - - res := query(t, q, labels.NewEqualMatcher("a", "b")) - - testutil.Equals(t, map[string][]tsdbutil.Sample{ - labels.FromStrings("a", "b").String(): { - sample{t: 123, v: 0}, - sample{t: 124, v: 1}, - sample{t: 125, v: 0}, - sample{t: 133, v: 1}, - sample{t: 143, v: 2}, - }, - }, res) -} - -func TestDeleteSimple(t *testing.T) { - numSamples := int64(10) - - cases := []struct { - intervals Intervals - remaint []int64 - }{ - { - intervals: Intervals{{0, 3}}, - remaint: []int64{4, 5, 6, 7, 8, 9}, - }, - { - intervals: Intervals{{1, 3}}, - remaint: []int64{0, 4, 5, 6, 7, 8, 9}, - }, - { - intervals: Intervals{{1, 3}, {4, 7}}, - remaint: []int64{0, 8, 9}, - }, - { - intervals: Intervals{{1, 3}, {4, 700}}, - remaint: []int64{0}, - }, - { // This case is to ensure that labels and symbols are deleted. - intervals: Intervals{{0, 9}}, - remaint: []int64{}, - }, - } - -Outer: - for _, c := range cases { - db, delete := openTestDB(t, nil) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - - app := db.Appender() - - smpls := make([]float64, numSamples) - for i := int64(0); i < numSamples; i++ { - smpls[i] = rand.Float64() - app.Add(labels.Labels{{"a", "b"}}, i, smpls[i]) - } - - testutil.Ok(t, app.Commit()) - - // TODO(gouthamve): Reset the tombstones somehow. - // Delete the ranges. - for _, r := range c.intervals { - testutil.Ok(t, db.Delete(r.Mint, r.Maxt, labels.NewEqualMatcher("a", "b"))) - } - - // Compare the result. - q, err := db.Querier(0, numSamples) - testutil.Ok(t, err) - - res, err := q.Select(labels.NewEqualMatcher("a", "b")) - testutil.Ok(t, err) - - expSamples := make([]tsdbutil.Sample, 0, len(c.remaint)) - for _, ts := range c.remaint { - expSamples = append(expSamples, sample{ts, smpls[ts]}) - } - - expss := newMockSeriesSet([]Series{ - newSeries(map[string]string{"a": "b"}, expSamples), - }) - - lns, err := q.LabelNames() - testutil.Ok(t, err) - lvs, err := q.LabelValues("a") - testutil.Ok(t, err) - if len(expSamples) == 0 { - testutil.Equals(t, 0, len(lns)) - testutil.Equals(t, 0, len(lvs)) - testutil.Assert(t, res.Next() == false, "") - continue - } else { - testutil.Equals(t, 1, len(lns)) - testutil.Equals(t, 1, len(lvs)) - testutil.Equals(t, "a", lns[0]) - testutil.Equals(t, "b", lvs[0]) - } - - for { - eok, rok := expss.Next(), res.Next() - testutil.Equals(t, eok, rok) - - if !eok { - continue Outer - } - sexp := expss.At() - sres := res.At() - - testutil.Equals(t, sexp.Labels(), sres.Labels()) - - smplExp, errExp := expandSeriesIterator(sexp.Iterator()) - smplRes, errRes := expandSeriesIterator(sres.Iterator()) - - testutil.Equals(t, errExp, errRes) - testutil.Equals(t, smplExp, smplRes) - } - } -} - -func TestAmendDatapointCausesError(t *testing.T) { - db, delete := openTestDB(t, nil) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - - app := db.Appender() - _, err := app.Add(labels.Labels{}, 0, 0) - testutil.Ok(t, err) - testutil.Ok(t, app.Commit()) - - app = db.Appender() - _, err = app.Add(labels.Labels{}, 0, 1) - testutil.Equals(t, ErrAmendSample, err) - testutil.Ok(t, app.Rollback()) -} - -func TestDuplicateNaNDatapointNoAmendError(t *testing.T) { - db, delete := openTestDB(t, nil) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - - app := db.Appender() - _, err := app.Add(labels.Labels{}, 0, math.NaN()) - testutil.Ok(t, err) - testutil.Ok(t, app.Commit()) - - app = db.Appender() - _, err = app.Add(labels.Labels{}, 0, math.NaN()) - testutil.Ok(t, err) -} - -func TestNonDuplicateNaNDatapointsCausesAmendError(t *testing.T) { - db, delete := openTestDB(t, nil) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - app := db.Appender() - _, err := app.Add(labels.Labels{}, 0, math.Float64frombits(0x7ff0000000000001)) - testutil.Ok(t, err) - testutil.Ok(t, app.Commit()) - - app = db.Appender() - _, err = app.Add(labels.Labels{}, 0, math.Float64frombits(0x7ff0000000000002)) - testutil.Equals(t, ErrAmendSample, err) -} - -func TestSkippingInvalidValuesInSameTxn(t *testing.T) { - db, delete := openTestDB(t, nil) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - - // Append AmendedValue. - app := db.Appender() - _, err := app.Add(labels.Labels{{"a", "b"}}, 0, 1) - testutil.Ok(t, err) - _, err = app.Add(labels.Labels{{"a", "b"}}, 0, 2) - testutil.Ok(t, err) - testutil.Ok(t, app.Commit()) - - // Make sure the right value is stored. - q, err := db.Querier(0, 10) - testutil.Ok(t, err) - - ssMap := query(t, q, labels.NewEqualMatcher("a", "b")) - - testutil.Equals(t, map[string][]tsdbutil.Sample{ - labels.New(labels.Label{"a", "b"}).String(): {sample{0, 1}}, - }, ssMap) - - // Append Out of Order Value. - app = db.Appender() - _, err = app.Add(labels.Labels{{"a", "b"}}, 10, 3) - testutil.Ok(t, err) - _, err = app.Add(labels.Labels{{"a", "b"}}, 7, 5) - testutil.Ok(t, err) - testutil.Ok(t, app.Commit()) - - q, err = db.Querier(0, 10) - testutil.Ok(t, err) - - ssMap = query(t, q, labels.NewEqualMatcher("a", "b")) - - testutil.Equals(t, map[string][]tsdbutil.Sample{ - labels.New(labels.Label{"a", "b"}).String(): {sample{0, 1}, sample{10, 3}}, - }, ssMap) -} - -func TestDB_Snapshot(t *testing.T) { - db, delete := openTestDB(t, nil) - defer delete() - - // append data - app := db.Appender() - mint := int64(1414141414000) - for i := 0; i < 1000; i++ { - _, err := app.Add(labels.FromStrings("foo", "bar"), mint+int64(i), 1.0) - testutil.Ok(t, err) - } - testutil.Ok(t, app.Commit()) - testutil.Ok(t, app.Rollback()) - - // create snapshot - snap, err := ioutil.TempDir("", "snap") - testutil.Ok(t, err) - - defer os.RemoveAll(snap) - testutil.Ok(t, db.Snapshot(snap, true)) - testutil.Ok(t, db.Close()) - - // reopen DB from snapshot - db, err = Open(snap, nil, nil, nil) - testutil.Ok(t, err) - defer func() { testutil.Ok(t, db.Close()) }() - - querier, err := db.Querier(mint, mint+1000) - testutil.Ok(t, err) - defer func() { testutil.Ok(t, querier.Close()) }() - - // sum values - seriesSet, err := querier.Select(labels.NewEqualMatcher("foo", "bar")) - testutil.Ok(t, err) - - sum := 0.0 - for seriesSet.Next() { - series := seriesSet.At().Iterator() - for series.Next() { - _, v := series.At() - sum += v - } - testutil.Ok(t, series.Err()) - } - testutil.Ok(t, seriesSet.Err()) - testutil.Equals(t, 1000.0, sum) -} - -func TestDB_SnapshotWithDelete(t *testing.T) { - numSamples := int64(10) - - db, delete := openTestDB(t, nil) - defer delete() - - app := db.Appender() - - smpls := make([]float64, numSamples) - for i := int64(0); i < numSamples; i++ { - smpls[i] = rand.Float64() - app.Add(labels.Labels{{"a", "b"}}, i, smpls[i]) - } - - testutil.Ok(t, app.Commit()) - cases := []struct { - intervals Intervals - remaint []int64 - }{ - { - intervals: Intervals{{1, 3}, {4, 7}}, - remaint: []int64{0, 8, 9}, - }, - } - -Outer: - for _, c := range cases { - // TODO(gouthamve): Reset the tombstones somehow. - // Delete the ranges. - for _, r := range c.intervals { - testutil.Ok(t, db.Delete(r.Mint, r.Maxt, labels.NewEqualMatcher("a", "b"))) - } - - // create snapshot - snap, err := ioutil.TempDir("", "snap") - testutil.Ok(t, err) - - defer os.RemoveAll(snap) - testutil.Ok(t, db.Snapshot(snap, true)) - testutil.Ok(t, db.Close()) - - // reopen DB from snapshot - db, err = Open(snap, nil, nil, nil) - testutil.Ok(t, err) - defer func() { testutil.Ok(t, db.Close()) }() - - // Compare the result. - q, err := db.Querier(0, numSamples) - testutil.Ok(t, err) - defer func() { testutil.Ok(t, q.Close()) }() - - res, err := q.Select(labels.NewEqualMatcher("a", "b")) - testutil.Ok(t, err) - - expSamples := make([]tsdbutil.Sample, 0, len(c.remaint)) - for _, ts := range c.remaint { - expSamples = append(expSamples, sample{ts, smpls[ts]}) - } - - expss := newMockSeriesSet([]Series{ - newSeries(map[string]string{"a": "b"}, expSamples), - }) - - if len(expSamples) == 0 { - testutil.Assert(t, res.Next() == false, "") - continue - } - - for { - eok, rok := expss.Next(), res.Next() - testutil.Equals(t, eok, rok) - - if !eok { - continue Outer - } - sexp := expss.At() - sres := res.At() - - testutil.Equals(t, sexp.Labels(), sres.Labels()) - - smplExp, errExp := expandSeriesIterator(sexp.Iterator()) - smplRes, errRes := expandSeriesIterator(sres.Iterator()) - - testutil.Equals(t, errExp, errRes) - testutil.Equals(t, smplExp, smplRes) - } - } -} - -func TestDB_e2e(t *testing.T) { - const ( - numDatapoints = 1000 - numRanges = 1000 - timeInterval = int64(3) - ) - // Create 8 series with 1000 data-points of different ranges and run queries. - lbls := [][]labels.Label{ - { - {"a", "b"}, - {"instance", "localhost:9090"}, - {"job", "prometheus"}, - }, - { - {"a", "b"}, - {"instance", "127.0.0.1:9090"}, - {"job", "prometheus"}, - }, - { - {"a", "b"}, - {"instance", "127.0.0.1:9090"}, - {"job", "prom-k8s"}, - }, - { - {"a", "b"}, - {"instance", "localhost:9090"}, - {"job", "prom-k8s"}, - }, - { - {"a", "c"}, - {"instance", "localhost:9090"}, - {"job", "prometheus"}, - }, - { - {"a", "c"}, - {"instance", "127.0.0.1:9090"}, - {"job", "prometheus"}, - }, - { - {"a", "c"}, - {"instance", "127.0.0.1:9090"}, - {"job", "prom-k8s"}, - }, - { - {"a", "c"}, - {"instance", "localhost:9090"}, - {"job", "prom-k8s"}, - }, - } - - seriesMap := map[string][]tsdbutil.Sample{} - for _, l := range lbls { - seriesMap[labels.New(l...).String()] = []tsdbutil.Sample{} - } - - db, delete := openTestDB(t, nil) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - - app := db.Appender() - - for _, l := range lbls { - lset := labels.New(l...) - series := []tsdbutil.Sample{} - - ts := rand.Int63n(300) - for i := 0; i < numDatapoints; i++ { - v := rand.Float64() - - series = append(series, sample{ts, v}) - - _, err := app.Add(lset, ts, v) - testutil.Ok(t, err) - - ts += rand.Int63n(timeInterval) + 1 - } - - seriesMap[lset.String()] = series - } - - testutil.Ok(t, app.Commit()) - - // Query each selector on 1000 random time-ranges. - queries := []struct { - ms []labels.Matcher - }{ - { - ms: []labels.Matcher{labels.NewEqualMatcher("a", "b")}, - }, - { - ms: []labels.Matcher{ - labels.NewEqualMatcher("a", "b"), - labels.NewEqualMatcher("job", "prom-k8s"), - }, - }, - { - ms: []labels.Matcher{ - labels.NewEqualMatcher("a", "c"), - labels.NewEqualMatcher("instance", "localhost:9090"), - labels.NewEqualMatcher("job", "prometheus"), - }, - }, - // TODO: Add Regexp Matchers. - } - - for _, qry := range queries { - matched := labels.Slice{} - for _, ls := range lbls { - s := labels.Selector(qry.ms) - if s.Matches(ls) { - matched = append(matched, ls) - } - } - - sort.Sort(matched) - - for i := 0; i < numRanges; i++ { - mint := rand.Int63n(300) - maxt := mint + rand.Int63n(timeInterval*int64(numDatapoints)) - - expected := map[string][]tsdbutil.Sample{} - - // Build the mockSeriesSet. - for _, m := range matched { - smpls := boundedSamples(seriesMap[m.String()], mint, maxt) - if len(smpls) > 0 { - expected[m.String()] = smpls - } - } - - q, err := db.Querier(mint, maxt) - testutil.Ok(t, err) - - ss, err := q.Select(qry.ms...) - testutil.Ok(t, err) - - result := map[string][]tsdbutil.Sample{} - - for ss.Next() { - x := ss.At() - - smpls, err := expandSeriesIterator(x.Iterator()) - testutil.Ok(t, err) - - if len(smpls) > 0 { - result[x.Labels().String()] = smpls - } - } - - testutil.Ok(t, ss.Err()) - testutil.Equals(t, expected, result) - - q.Close() - } - } -} - -func TestWALFlushedOnDBClose(t *testing.T) { - db, delete := openTestDB(t, nil) - defer delete() - - dirDb := db.Dir() - - lbls := labels.Labels{labels.Label{Name: "labelname", Value: "labelvalue"}} - - app := db.Appender() - _, err := app.Add(lbls, 0, 1) - testutil.Ok(t, err) - testutil.Ok(t, app.Commit()) - - testutil.Ok(t, db.Close()) - - db, err = Open(dirDb, nil, nil, nil) - testutil.Ok(t, err) - defer func() { testutil.Ok(t, db.Close()) }() - - q, err := db.Querier(0, 1) - testutil.Ok(t, err) - - values, err := q.LabelValues("labelname") - testutil.Ok(t, err) - testutil.Equals(t, []string{"labelvalue"}, values) -} - -func TestWALSegmentSizeOption(t *testing.T) { - options := *DefaultOptions - options.WALSegmentSize = 2 * 32 * 1024 - db, delete := openTestDB(t, &options) - defer delete() - app := db.Appender() - for i := int64(0); i < 155; i++ { - _, err := app.Add(labels.Labels{labels.Label{Name: "wal", Value: "size"}}, i, rand.Float64()) - testutil.Ok(t, err) - testutil.Ok(t, app.Commit()) - } - - dbDir := db.Dir() - db.Close() - files, err := ioutil.ReadDir(filepath.Join(dbDir, "wal")) - testutil.Assert(t, len(files) > 1, "current WALSegmentSize should result in more than a single WAL file.") - testutil.Ok(t, err) - for i, f := range files { - if len(files)-1 != i { - testutil.Equals(t, int64(options.WALSegmentSize), f.Size(), "WAL file size doesn't match WALSegmentSize option, filename: %v", f.Name()) - continue - } - testutil.Assert(t, int64(options.WALSegmentSize) > f.Size(), "last WAL file size is not smaller than the WALSegmentSize option, filename: %v", f.Name()) - } -} - -func TestTombstoneClean(t *testing.T) { - numSamples := int64(10) - - db, delete := openTestDB(t, nil) - defer delete() - - app := db.Appender() - - smpls := make([]float64, numSamples) - for i := int64(0); i < numSamples; i++ { - smpls[i] = rand.Float64() - app.Add(labels.Labels{{"a", "b"}}, i, smpls[i]) - } - - testutil.Ok(t, app.Commit()) - cases := []struct { - intervals Intervals - remaint []int64 - }{ - { - intervals: Intervals{{1, 3}, {4, 7}}, - remaint: []int64{0, 8, 9}, - }, - } - - for _, c := range cases { - // Delete the ranges. - - // create snapshot - snap, err := ioutil.TempDir("", "snap") - testutil.Ok(t, err) - - defer os.RemoveAll(snap) - testutil.Ok(t, db.Snapshot(snap, true)) - testutil.Ok(t, db.Close()) - - // reopen DB from snapshot - db, err = Open(snap, nil, nil, nil) - testutil.Ok(t, err) - defer db.Close() - - for _, r := range c.intervals { - testutil.Ok(t, db.Delete(r.Mint, r.Maxt, labels.NewEqualMatcher("a", "b"))) - } - - // All of the setup for THIS line. - testutil.Ok(t, db.CleanTombstones()) - - // Compare the result. - q, err := db.Querier(0, numSamples) - testutil.Ok(t, err) - defer q.Close() - - res, err := q.Select(labels.NewEqualMatcher("a", "b")) - testutil.Ok(t, err) - - expSamples := make([]tsdbutil.Sample, 0, len(c.remaint)) - for _, ts := range c.remaint { - expSamples = append(expSamples, sample{ts, smpls[ts]}) - } - - expss := newMockSeriesSet([]Series{ - newSeries(map[string]string{"a": "b"}, expSamples), - }) - - if len(expSamples) == 0 { - testutil.Assert(t, res.Next() == false, "") - continue - } - - for { - eok, rok := expss.Next(), res.Next() - testutil.Equals(t, eok, rok) - - if !eok { - break - } - sexp := expss.At() - sres := res.At() - - testutil.Equals(t, sexp.Labels(), sres.Labels()) - - smplExp, errExp := expandSeriesIterator(sexp.Iterator()) - smplRes, errRes := expandSeriesIterator(sres.Iterator()) - - testutil.Equals(t, errExp, errRes) - testutil.Equals(t, smplExp, smplRes) - } - - for _, b := range db.Blocks() { - testutil.Equals(t, newMemTombstones(), b.tombstones) - } - } -} - -// TestTombstoneCleanFail tests that a failing TombstoneClean doesn't leave any blocks behind. -// When TombstoneClean errors the original block that should be rebuilt doesn't get deleted so -// if TombstoneClean leaves any blocks behind these will overlap. -func TestTombstoneCleanFail(t *testing.T) { - - db, delete := openTestDB(t, nil) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - - var expectedBlockDirs []string - - // Create some empty blocks pending for compaction. - // totalBlocks should be >=2 so we have enough blocks to trigger compaction failure. - totalBlocks := 2 - for i := 0; i < totalBlocks; i++ { - blockDir := createBlock(t, db.Dir(), genSeries(1, 1, 0, 0)) - block, err := OpenBlock(nil, blockDir, nil) - testutil.Ok(t, err) - // Add some some fake tombstones to trigger the compaction. - tomb := newMemTombstones() - tomb.addInterval(0, Interval{0, 1}) - block.tombstones = tomb - - db.blocks = append(db.blocks, block) - expectedBlockDirs = append(expectedBlockDirs, blockDir) - } - - // Initialize the mockCompactorFailing with a room for a single compaction iteration. - // mockCompactorFailing will fail on the second iteration so we can check if the cleanup works as expected. - db.compactor = &mockCompactorFailing{ - t: t, - blocks: db.blocks, - max: totalBlocks + 1, - } - - // The compactor should trigger a failure here. - testutil.NotOk(t, db.CleanTombstones()) - - // Now check that the CleanTombstones didn't leave any blocks behind after a failure. - actualBlockDirs, err := blockDirs(db.dir) - testutil.Ok(t, err) - testutil.Equals(t, expectedBlockDirs, actualBlockDirs) -} - -// mockCompactorFailing creates a new empty block on every write and fails when reached the max allowed total. -type mockCompactorFailing struct { - t *testing.T - blocks []*Block - max int -} - -func (*mockCompactorFailing) Plan(dir string) ([]string, error) { - return nil, nil -} -func (c *mockCompactorFailing) Write(dest string, b BlockReader, mint, maxt int64, parent *BlockMeta) (ulid.ULID, error) { - if len(c.blocks) >= c.max { - return ulid.ULID{}, fmt.Errorf("the compactor already did the maximum allowed blocks so it is time to fail") - } - - block, err := OpenBlock(nil, createBlock(c.t, dest, genSeries(1, 1, 0, 0)), nil) - testutil.Ok(c.t, err) - testutil.Ok(c.t, block.Close()) // Close block as we won't be using anywhere. - c.blocks = append(c.blocks, block) - - // Now check that all expected blocks are actually persisted on disk. - // This way we make sure that the we have some blocks that are supposed to be removed. - var expectedBlocks []string - for _, b := range c.blocks { - expectedBlocks = append(expectedBlocks, filepath.Join(dest, b.Meta().ULID.String())) - } - actualBlockDirs, err := blockDirs(dest) - testutil.Ok(c.t, err) - - testutil.Equals(c.t, expectedBlocks, actualBlockDirs) - - return block.Meta().ULID, nil -} - -func (*mockCompactorFailing) Compact(dest string, dirs []string, open []*Block) (ulid.ULID, error) { - return ulid.ULID{}, nil - -} - -func TestTimeRetention(t *testing.T) { - db, delete := openTestDB(t, &Options{ - BlockRanges: []int64{1000}, - }) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - - blocks := []*BlockMeta{ - {MinTime: 500, MaxTime: 900}, // Oldest block - {MinTime: 1000, MaxTime: 1500}, - {MinTime: 1500, MaxTime: 2000}, // Newest Block - } - - for _, m := range blocks { - createBlock(t, db.Dir(), genSeries(10, 10, m.MinTime, m.MaxTime)) - } - - testutil.Ok(t, db.reload()) // Reload the db to register the new blocks. - testutil.Equals(t, len(blocks), len(db.Blocks())) // Ensure all blocks are registered. - - db.opts.RetentionDuration = uint64(blocks[2].MaxTime - blocks[1].MinTime) - testutil.Ok(t, db.reload()) - - expBlocks := blocks[1:] - actBlocks := db.Blocks() - - testutil.Equals(t, 1, int(prom_testutil.ToFloat64(db.metrics.timeRetentionCount)), "metric retention count mismatch") - testutil.Equals(t, len(expBlocks), len(actBlocks)) - testutil.Equals(t, expBlocks[0].MaxTime, actBlocks[0].meta.MaxTime) - testutil.Equals(t, expBlocks[len(expBlocks)-1].MaxTime, actBlocks[len(actBlocks)-1].meta.MaxTime) -} - -func TestSizeRetention(t *testing.T) { - db, delete := openTestDB(t, &Options{ - BlockRanges: []int64{100}, - }) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - - blocks := []*BlockMeta{ - {MinTime: 100, MaxTime: 200}, // Oldest block - {MinTime: 200, MaxTime: 300}, - {MinTime: 300, MaxTime: 400}, - {MinTime: 400, MaxTime: 500}, - {MinTime: 500, MaxTime: 600}, // Newest Block - } - - for _, m := range blocks { - createBlock(t, db.Dir(), genSeries(100, 10, m.MinTime, m.MaxTime)) - } - - // Test that registered size matches the actual disk size. - testutil.Ok(t, db.reload()) // Reload the db to register the new db size. - testutil.Equals(t, len(blocks), len(db.Blocks())) // Ensure all blocks are registered. - expSize := int64(prom_testutil.ToFloat64(db.metrics.blocksBytes)) // Use the the actual internal metrics. - actSize := dbDiskSize(db.Dir()) - testutil.Equals(t, expSize, actSize, "registered size doesn't match actual disk size") - - // Decrease the max bytes limit so that a delete is triggered. - // Check total size, total count and check that the oldest block was deleted. - firstBlockSize := db.Blocks()[0].Size() - sizeLimit := actSize - firstBlockSize - db.opts.MaxBytes = sizeLimit // Set the new db size limit one block smaller that the actual size. - testutil.Ok(t, db.reload()) // Reload the db to register the new db size. - - expBlocks := blocks[1:] - actBlocks := db.Blocks() - expSize = int64(prom_testutil.ToFloat64(db.metrics.blocksBytes)) - actRetentCount := int(prom_testutil.ToFloat64(db.metrics.sizeRetentionCount)) - actSize = dbDiskSize(db.Dir()) - - testutil.Equals(t, 1, actRetentCount, "metric retention count mismatch") - testutil.Equals(t, actSize, expSize, "metric db size doesn't match actual disk size") - testutil.Assert(t, expSize <= sizeLimit, "actual size (%v) is expected to be less than or equal to limit (%v)", expSize, sizeLimit) - testutil.Equals(t, len(blocks)-1, len(actBlocks), "new block count should be decreased from:%v to:%v", len(blocks), len(blocks)-1) - testutil.Equals(t, expBlocks[0].MaxTime, actBlocks[0].meta.MaxTime, "maxT mismatch of the first block") - testutil.Equals(t, expBlocks[len(expBlocks)-1].MaxTime, actBlocks[len(actBlocks)-1].meta.MaxTime, "maxT mismatch of the last block") - -} - -func dbDiskSize(dir string) int64 { - var statSize int64 - filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { - // Include only index,tombstone and chunks. - if filepath.Dir(path) == chunkDir(filepath.Dir(filepath.Dir(path))) || - info.Name() == indexFilename || - info.Name() == tombstoneFilename { - statSize += info.Size() - } - return nil - }) - return statSize -} - -func TestNotMatcherSelectsLabelsUnsetSeries(t *testing.T) { - db, delete := openTestDB(t, nil) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - - labelpairs := []labels.Labels{ - labels.FromStrings("a", "abcd", "b", "abcde"), - labels.FromStrings("labelname", "labelvalue"), - } - - app := db.Appender() - for _, lbls := range labelpairs { - _, err := app.Add(lbls, 0, 1) - testutil.Ok(t, err) - } - testutil.Ok(t, app.Commit()) - - cases := []struct { - selector labels.Selector - series []labels.Labels - }{{ - selector: labels.Selector{ - labels.Not(labels.NewEqualMatcher("lname", "lvalue")), - }, - series: labelpairs, - }, { - selector: labels.Selector{ - labels.NewEqualMatcher("a", "abcd"), - labels.Not(labels.NewEqualMatcher("b", "abcde")), - }, - series: []labels.Labels{}, - }, { - selector: labels.Selector{ - labels.NewEqualMatcher("a", "abcd"), - labels.Not(labels.NewEqualMatcher("b", "abc")), - }, - series: []labels.Labels{labelpairs[0]}, - }, { - selector: labels.Selector{ - labels.Not(labels.NewMustRegexpMatcher("a", "abd.*")), - }, - series: labelpairs, - }, { - selector: labels.Selector{ - labels.Not(labels.NewMustRegexpMatcher("a", "abc.*")), - }, - series: labelpairs[1:], - }, { - selector: labels.Selector{ - labels.Not(labels.NewMustRegexpMatcher("c", "abd.*")), - }, - series: labelpairs, - }, { - selector: labels.Selector{ - labels.Not(labels.NewMustRegexpMatcher("labelname", "labelvalue")), - }, - series: labelpairs[:1], - }} - - q, err := db.Querier(0, 10) - testutil.Ok(t, err) - defer func() { testutil.Ok(t, q.Close()) }() - - for _, c := range cases { - ss, err := q.Select(c.selector...) - testutil.Ok(t, err) - - lres, err := expandSeriesSet(ss) - testutil.Ok(t, err) - - testutil.Equals(t, c.series, lres) - } -} - -func expandSeriesSet(ss SeriesSet) ([]labels.Labels, error) { - result := []labels.Labels{} - for ss.Next() { - result = append(result, ss.At().Labels()) - } - - return result, ss.Err() -} - -func TestOverlappingBlocksDetectsAllOverlaps(t *testing.T) { - // Create 10 blocks that does not overlap (0-10, 10-20, ..., 100-110) but in reverse order to ensure our algorithm - // will handle that. - var metas = make([]BlockMeta, 11) - for i := 10; i >= 0; i-- { - metas[i] = BlockMeta{MinTime: int64(i * 10), MaxTime: int64((i + 1) * 10)} - } - - testutil.Assert(t, len(OverlappingBlocks(metas)) == 0, "we found unexpected overlaps") - - // Add overlapping blocks. We've to establish order again since we aren't interested - // in trivial overlaps caused by unorderedness. - add := func(ms ...BlockMeta) []BlockMeta { - repl := append(append([]BlockMeta{}, metas...), ms...) - sort.Slice(repl, func(i, j int) bool { - return repl[i].MinTime < repl[j].MinTime - }) - return repl - } - - // o1 overlaps with 10-20. - o1 := BlockMeta{MinTime: 15, MaxTime: 17} - testutil.Equals(t, Overlaps{ - {Min: 15, Max: 17}: {metas[1], o1}, - }, OverlappingBlocks(add(o1))) - - // o2 overlaps with 20-30 and 30-40. - o2 := BlockMeta{MinTime: 21, MaxTime: 31} - testutil.Equals(t, Overlaps{ - {Min: 21, Max: 30}: {metas[2], o2}, - {Min: 30, Max: 31}: {o2, metas[3]}, - }, OverlappingBlocks(add(o2))) - - // o3a and o3b overlaps with 30-40 and each other. - o3a := BlockMeta{MinTime: 33, MaxTime: 39} - o3b := BlockMeta{MinTime: 34, MaxTime: 36} - testutil.Equals(t, Overlaps{ - {Min: 34, Max: 36}: {metas[3], o3a, o3b}, - }, OverlappingBlocks(add(o3a, o3b))) - - // o4 is 1:1 overlap with 50-60. - o4 := BlockMeta{MinTime: 50, MaxTime: 60} - testutil.Equals(t, Overlaps{ - {Min: 50, Max: 60}: {metas[5], o4}, - }, OverlappingBlocks(add(o4))) - - // o5 overlaps with 60-70, 70-80 and 80-90. - o5 := BlockMeta{MinTime: 61, MaxTime: 85} - testutil.Equals(t, Overlaps{ - {Min: 61, Max: 70}: {metas[6], o5}, - {Min: 70, Max: 80}: {o5, metas[7]}, - {Min: 80, Max: 85}: {o5, metas[8]}, - }, OverlappingBlocks(add(o5))) - - // o6a overlaps with 90-100, 100-110 and o6b, o6b overlaps with 90-100 and o6a. - o6a := BlockMeta{MinTime: 92, MaxTime: 105} - o6b := BlockMeta{MinTime: 94, MaxTime: 99} - testutil.Equals(t, Overlaps{ - {Min: 94, Max: 99}: {metas[9], o6a, o6b}, - {Min: 100, Max: 105}: {o6a, metas[10]}, - }, OverlappingBlocks(add(o6a, o6b))) - - // All together. - testutil.Equals(t, Overlaps{ - {Min: 15, Max: 17}: {metas[1], o1}, - {Min: 21, Max: 30}: {metas[2], o2}, {Min: 30, Max: 31}: {o2, metas[3]}, - {Min: 34, Max: 36}: {metas[3], o3a, o3b}, - {Min: 50, Max: 60}: {metas[5], o4}, - {Min: 61, Max: 70}: {metas[6], o5}, {Min: 70, Max: 80}: {o5, metas[7]}, {Min: 80, Max: 85}: {o5, metas[8]}, - {Min: 94, Max: 99}: {metas[9], o6a, o6b}, {Min: 100, Max: 105}: {o6a, metas[10]}, - }, OverlappingBlocks(add(o1, o2, o3a, o3b, o4, o5, o6a, o6b))) - - // Additional case. - var nc1 []BlockMeta - nc1 = append(nc1, BlockMeta{MinTime: 1, MaxTime: 5}) - nc1 = append(nc1, BlockMeta{MinTime: 2, MaxTime: 3}) - nc1 = append(nc1, BlockMeta{MinTime: 2, MaxTime: 3}) - nc1 = append(nc1, BlockMeta{MinTime: 2, MaxTime: 3}) - nc1 = append(nc1, BlockMeta{MinTime: 2, MaxTime: 3}) - nc1 = append(nc1, BlockMeta{MinTime: 2, MaxTime: 6}) - nc1 = append(nc1, BlockMeta{MinTime: 3, MaxTime: 5}) - nc1 = append(nc1, BlockMeta{MinTime: 5, MaxTime: 7}) - nc1 = append(nc1, BlockMeta{MinTime: 7, MaxTime: 10}) - nc1 = append(nc1, BlockMeta{MinTime: 8, MaxTime: 9}) - testutil.Equals(t, Overlaps{ - {Min: 2, Max: 3}: {nc1[0], nc1[1], nc1[2], nc1[3], nc1[4], nc1[5]}, // 1-5, 2-3, 2-3, 2-3, 2-3, 2,6 - {Min: 3, Max: 5}: {nc1[0], nc1[5], nc1[6]}, // 1-5, 2-6, 3-5 - {Min: 5, Max: 6}: {nc1[5], nc1[7]}, // 2-6, 5-7 - {Min: 8, Max: 9}: {nc1[8], nc1[9]}, // 7-10, 8-9 - }, OverlappingBlocks(nc1)) -} - -// Regression test for https://github.com/prometheus/tsdb/issues/347 -func TestChunkAtBlockBoundary(t *testing.T) { - db, delete := openTestDB(t, nil) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - - app := db.Appender() - - blockRange := DefaultOptions.BlockRanges[0] - label := labels.FromStrings("foo", "bar") - - for i := int64(0); i < 3; i++ { - _, err := app.Add(label, i*blockRange, 0) - testutil.Ok(t, err) - _, err = app.Add(label, i*blockRange+1000, 0) - testutil.Ok(t, err) - } - - err := app.Commit() - testutil.Ok(t, err) - - err = db.compact() - testutil.Ok(t, err) - - for _, block := range db.Blocks() { - r, err := block.Index() - testutil.Ok(t, err) - defer r.Close() - - meta := block.Meta() - - p, err := r.Postings(index.AllPostingsKey()) - testutil.Ok(t, err) - - var ( - lset labels.Labels - chks []chunks.Meta - ) - - chunkCount := 0 - - for p.Next() { - err = r.Series(p.At(), &lset, &chks) - testutil.Ok(t, err) - for _, c := range chks { - testutil.Assert(t, meta.MinTime <= c.MinTime && c.MaxTime <= meta.MaxTime, - "chunk spans beyond block boundaries: [block.MinTime=%d, block.MaxTime=%d]; [chunk.MinTime=%d, chunk.MaxTime=%d]", - meta.MinTime, meta.MaxTime, c.MinTime, c.MaxTime) - chunkCount++ - } - } - testutil.Assert(t, chunkCount == 1, "expected 1 chunk in block %s, got %d", meta.ULID, chunkCount) - } -} - -func TestQuerierWithBoundaryChunks(t *testing.T) { - db, delete := openTestDB(t, nil) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - - app := db.Appender() - - blockRange := DefaultOptions.BlockRanges[0] - label := labels.FromStrings("foo", "bar") - - for i := int64(0); i < 5; i++ { - _, err := app.Add(label, i*blockRange, 0) - testutil.Ok(t, err) - } - - err := app.Commit() - testutil.Ok(t, err) - - err = db.compact() - testutil.Ok(t, err) - - testutil.Assert(t, len(db.blocks) >= 3, "invalid test, less than three blocks in DB") - - q, err := db.Querier(blockRange, 2*blockRange) - testutil.Ok(t, err) - defer q.Close() - - // The requested interval covers 2 blocks, so the querier should contain 2 blocks. - count := len(q.(*querier).blocks) - testutil.Assert(t, count == 2, "expected 2 blocks in querier, got %d", count) -} - -// TestInitializeHeadTimestamp ensures that the h.minTime is set properly. -// - no blocks no WAL: set to the time of the first appended sample -// - no blocks with WAL: set to the smallest sample from the WAL -// - with blocks no WAL: set to the last block maxT -// - with blocks with WAL: same as above -func TestInitializeHeadTimestamp(t *testing.T) { - t.Run("clean", func(t *testing.T) { - dir, err := ioutil.TempDir("", "test_head_init") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - db, err := Open(dir, nil, nil, nil) - testutil.Ok(t, err) - - // Should be set to init values if no WAL or blocks exist so far. - testutil.Equals(t, int64(math.MaxInt64), db.head.MinTime()) - testutil.Equals(t, int64(math.MinInt64), db.head.MaxTime()) - - // First added sample initializes the writable range. - app := db.Appender() - _, err = app.Add(labels.FromStrings("a", "b"), 1000, 1) - testutil.Ok(t, err) - - testutil.Equals(t, int64(1000), db.head.MinTime()) - testutil.Equals(t, int64(1000), db.head.MaxTime()) - }) - t.Run("wal-only", func(t *testing.T) { - dir, err := ioutil.TempDir("", "test_head_init") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - testutil.Ok(t, os.MkdirAll(path.Join(dir, "wal"), 0777)) - w, err := wal.New(nil, nil, path.Join(dir, "wal")) - testutil.Ok(t, err) - - var enc RecordEncoder - err = w.Log( - enc.Series([]RefSeries{ - {Ref: 123, Labels: labels.FromStrings("a", "1")}, - {Ref: 124, Labels: labels.FromStrings("a", "2")}, - }, nil), - enc.Samples([]RefSample{ - {Ref: 123, T: 5000, V: 1}, - {Ref: 124, T: 15000, V: 1}, - }, nil), - ) - testutil.Ok(t, err) - testutil.Ok(t, w.Close()) - - db, err := Open(dir, nil, nil, nil) - testutil.Ok(t, err) - - testutil.Equals(t, int64(5000), db.head.MinTime()) - testutil.Equals(t, int64(15000), db.head.MaxTime()) - }) - t.Run("existing-block", func(t *testing.T) { - dir, err := ioutil.TempDir("", "test_head_init") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - createBlock(t, dir, genSeries(1, 1, 1000, 2000)) - - db, err := Open(dir, nil, nil, nil) - testutil.Ok(t, err) - - testutil.Equals(t, int64(2000), db.head.MinTime()) - testutil.Equals(t, int64(2000), db.head.MaxTime()) - }) - t.Run("existing-block-and-wal", func(t *testing.T) { - dir, err := ioutil.TempDir("", "test_head_init") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - createBlock(t, dir, genSeries(1, 1, 1000, 6000)) - - testutil.Ok(t, os.MkdirAll(path.Join(dir, "wal"), 0777)) - w, err := wal.New(nil, nil, path.Join(dir, "wal")) - testutil.Ok(t, err) - - var enc RecordEncoder - err = w.Log( - enc.Series([]RefSeries{ - {Ref: 123, Labels: labels.FromStrings("a", "1")}, - {Ref: 124, Labels: labels.FromStrings("a", "2")}, - }, nil), - enc.Samples([]RefSample{ - {Ref: 123, T: 5000, V: 1}, - {Ref: 124, T: 15000, V: 1}, - }, nil), - ) - testutil.Ok(t, err) - testutil.Ok(t, w.Close()) - - r := prometheus.NewRegistry() - - db, err := Open(dir, nil, r, nil) - testutil.Ok(t, err) - - testutil.Equals(t, int64(6000), db.head.MinTime()) - testutil.Equals(t, int64(15000), db.head.MaxTime()) - // Check that old series has been GCed. - testutil.Equals(t, 1.0, prom_testutil.ToFloat64(db.head.metrics.series)) - }) -} - -func TestNoEmptyBlocks(t *testing.T) { - db, delete := openTestDB(t, &Options{ - BlockRanges: []int64{100}, - }) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - db.DisableCompactions() - - rangeToTriggerCompaction := db.opts.BlockRanges[0]/2*3 - 1 - defaultLabel := labels.FromStrings("foo", "bar") - defaultMatcher := labels.NewMustRegexpMatcher("", ".*") - - t.Run("Test no blocks after compact with empty head.", func(t *testing.T) { - testutil.Ok(t, db.compact()) - actBlocks, err := blockDirs(db.Dir()) - testutil.Ok(t, err) - testutil.Equals(t, len(db.Blocks()), len(actBlocks)) - testutil.Equals(t, 0, len(actBlocks)) - testutil.Equals(t, 0, int(prom_testutil.ToFloat64(db.compactor.(*LeveledCompactor).metrics.ran)), "no compaction should be triggered here") - }) - - t.Run("Test no blocks after deleting all samples from head.", func(t *testing.T) { - app := db.Appender() - _, err := app.Add(defaultLabel, 1, 0) - testutil.Ok(t, err) - _, err = app.Add(defaultLabel, 2, 0) - testutil.Ok(t, err) - _, err = app.Add(defaultLabel, 3+rangeToTriggerCompaction, 0) - testutil.Ok(t, err) - testutil.Ok(t, app.Commit()) - testutil.Ok(t, db.Delete(math.MinInt64, math.MaxInt64, defaultMatcher)) - testutil.Ok(t, db.compact()) - testutil.Equals(t, 1, int(prom_testutil.ToFloat64(db.compactor.(*LeveledCompactor).metrics.ran)), "compaction should have been triggered here") - - actBlocks, err := blockDirs(db.Dir()) - testutil.Ok(t, err) - testutil.Equals(t, len(db.Blocks()), len(actBlocks)) - testutil.Equals(t, 0, len(actBlocks)) - - app = db.Appender() - _, err = app.Add(defaultLabel, 1, 0) - testutil.Assert(t, err == ErrOutOfBounds, "the head should be truncated so no samples in the past should be allowed") - - // Adding new blocks. - currentTime := db.Head().MaxTime() - _, err = app.Add(defaultLabel, currentTime, 0) - testutil.Ok(t, err) - _, err = app.Add(defaultLabel, currentTime+1, 0) - testutil.Ok(t, err) - _, err = app.Add(defaultLabel, currentTime+rangeToTriggerCompaction, 0) - testutil.Ok(t, err) - testutil.Ok(t, app.Commit()) - - testutil.Ok(t, db.compact()) - testutil.Equals(t, 2, int(prom_testutil.ToFloat64(db.compactor.(*LeveledCompactor).metrics.ran)), "compaction should have been triggered here") - actBlocks, err = blockDirs(db.Dir()) - testutil.Ok(t, err) - testutil.Equals(t, len(db.Blocks()), len(actBlocks)) - testutil.Assert(t, len(actBlocks) == 1, "No blocks created when compacting with >0 samples") - }) - - t.Run(`When no new block is created from head, and there are some blocks on disk - compaction should not run into infinite loop (was seen during development).`, func(t *testing.T) { - oldBlocks := db.Blocks() - app := db.Appender() - currentTime := db.Head().MaxTime() - _, err := app.Add(defaultLabel, currentTime, 0) - testutil.Ok(t, err) - _, err = app.Add(defaultLabel, currentTime+1, 0) - testutil.Ok(t, err) - _, err = app.Add(defaultLabel, currentTime+rangeToTriggerCompaction, 0) - testutil.Ok(t, err) - testutil.Ok(t, app.Commit()) - testutil.Ok(t, db.head.Delete(math.MinInt64, math.MaxInt64, defaultMatcher)) - testutil.Ok(t, db.compact()) - testutil.Equals(t, 3, int(prom_testutil.ToFloat64(db.compactor.(*LeveledCompactor).metrics.ran)), "compaction should have been triggered here") - testutil.Equals(t, oldBlocks, db.Blocks()) - }) - - t.Run("Test no blocks remaining after deleting all samples from disk.", func(t *testing.T) { - currentTime := db.Head().MaxTime() - blocks := []*BlockMeta{ - {MinTime: currentTime, MaxTime: currentTime + db.opts.BlockRanges[0]}, - {MinTime: currentTime + 100, MaxTime: currentTime + 100 + db.opts.BlockRanges[0]}, - } - for _, m := range blocks { - createBlock(t, db.Dir(), genSeries(2, 2, m.MinTime, m.MaxTime)) - } - - oldBlocks := db.Blocks() - testutil.Ok(t, db.reload()) // Reload the db to register the new blocks. - testutil.Equals(t, len(blocks)+len(oldBlocks), len(db.Blocks())) // Ensure all blocks are registered. - testutil.Ok(t, db.Delete(math.MinInt64, math.MaxInt64, defaultMatcher)) - testutil.Ok(t, db.compact()) - testutil.Equals(t, 5, int(prom_testutil.ToFloat64(db.compactor.(*LeveledCompactor).metrics.ran)), "compaction should have been triggered here once for each block that have tombstones") - - actBlocks, err := blockDirs(db.Dir()) - testutil.Ok(t, err) - testutil.Equals(t, len(db.Blocks()), len(actBlocks)) - testutil.Equals(t, 1, len(actBlocks), "All samples are deleted. Only the most recent block should remain after compaction.") - }) -} - -func TestDB_LabelNames(t *testing.T) { - tests := []struct { - // Add 'sampleLabels1' -> Test Head -> Compact -> Test Disk -> - // -> Add 'sampleLabels2' -> Test Head+Disk - - sampleLabels1 [][2]string // For checking head and disk separately. - // To test Head+Disk, sampleLabels2 should have - // at least 1 unique label name which is not in sampleLabels1. - sampleLabels2 [][2]string // // For checking head and disk together. - exp1 []string // after adding sampleLabels1. - exp2 []string // after adding sampleLabels1 and sampleLabels2. - }{ - { - sampleLabels1: [][2]string{ - [2]string{"name1", ""}, - [2]string{"name3", ""}, - [2]string{"name2", ""}, - }, - sampleLabels2: [][2]string{ - [2]string{"name4", ""}, - [2]string{"name1", ""}, - }, - exp1: []string{"name1", "name2", "name3"}, - exp2: []string{"name1", "name2", "name3", "name4"}, - }, - { - sampleLabels1: [][2]string{ - [2]string{"name2", ""}, - [2]string{"name1", ""}, - [2]string{"name2", ""}, - }, - sampleLabels2: [][2]string{ - [2]string{"name6", ""}, - [2]string{"name0", ""}, - }, - exp1: []string{"name1", "name2"}, - exp2: []string{"name0", "name1", "name2", "name6"}, - }, - } - - blockRange := DefaultOptions.BlockRanges[0] - // Appends samples into the database. - appendSamples := func(db *DB, mint, maxt int64, sampleLabels [][2]string) { - t.Helper() - app := db.Appender() - for i := mint; i <= maxt; i++ { - for _, tuple := range sampleLabels { - label := labels.FromStrings(tuple[0], tuple[1]) - _, err := app.Add(label, i*blockRange, 0) - testutil.Ok(t, err) - } - } - err := app.Commit() - testutil.Ok(t, err) - } - for _, tst := range tests { - db, delete := openTestDB(t, nil) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - - appendSamples(db, 0, 4, tst.sampleLabels1) - - // Testing head. - headIndexr, err := db.head.Index() - testutil.Ok(t, err) - labelNames, err := headIndexr.LabelNames() - testutil.Ok(t, err) - testutil.Equals(t, tst.exp1, labelNames) - testutil.Ok(t, headIndexr.Close()) - - // Testing disk. - err = db.compact() - testutil.Ok(t, err) - // All blocks have same label names, hence check them individually. - // No need to aggregrate and check. - for _, b := range db.Blocks() { - blockIndexr, err := b.Index() - testutil.Ok(t, err) - labelNames, err = blockIndexr.LabelNames() - testutil.Ok(t, err) - testutil.Equals(t, tst.exp1, labelNames) - testutil.Ok(t, blockIndexr.Close()) - } - - // Addings more samples to head with new label names - // so that we can test (head+disk).LabelNames() (the union). - appendSamples(db, 5, 9, tst.sampleLabels2) - - // Testing DB (union). - q, err := db.Querier(math.MinInt64, math.MaxInt64) - testutil.Ok(t, err) - labelNames, err = q.LabelNames() - testutil.Ok(t, err) - testutil.Ok(t, q.Close()) - testutil.Equals(t, tst.exp2, labelNames) - } -} - -func TestCorrectNumTombstones(t *testing.T) { - db, delete := openTestDB(t, nil) - defer func() { - testutil.Ok(t, db.Close()) - delete() - }() - - blockRange := DefaultOptions.BlockRanges[0] - defaultLabel := labels.FromStrings("foo", "bar") - defaultMatcher := labels.NewEqualMatcher(defaultLabel[0].Name, defaultLabel[0].Value) - - app := db.Appender() - for i := int64(0); i < 3; i++ { - for j := int64(0); j < 15; j++ { - _, err := app.Add(defaultLabel, i*blockRange+j, 0) - testutil.Ok(t, err) - } - } - testutil.Ok(t, app.Commit()) - - err := db.compact() - testutil.Ok(t, err) - testutil.Equals(t, 1, len(db.blocks)) - - testutil.Ok(t, db.Delete(0, 1, defaultMatcher)) - testutil.Equals(t, uint64(1), db.blocks[0].meta.Stats.NumTombstones) - - // {0, 1} and {2, 3} are merged to form 1 tombstone. - testutil.Ok(t, db.Delete(2, 3, defaultMatcher)) - testutil.Equals(t, uint64(1), db.blocks[0].meta.Stats.NumTombstones) - - testutil.Ok(t, db.Delete(5, 6, defaultMatcher)) - testutil.Equals(t, uint64(2), db.blocks[0].meta.Stats.NumTombstones) - - testutil.Ok(t, db.Delete(9, 11, defaultMatcher)) - testutil.Equals(t, uint64(3), db.blocks[0].meta.Stats.NumTombstones) -} - -func TestVerticalCompaction(t *testing.T) { - cases := []struct { - blockSeries [][]Series - expSeries map[string][]tsdbutil.Sample - }{ - // Case 0 - // |--------------| - // |----------------| - { - blockSeries: [][]Series{ - []Series{ - newSeries(map[string]string{"a": "b"}, []tsdbutil.Sample{ - sample{0, 0}, sample{1, 0}, sample{2, 0}, sample{4, 0}, - sample{5, 0}, sample{7, 0}, sample{8, 0}, sample{9, 0}, - }), - }, - []Series{ - newSeries(map[string]string{"a": "b"}, []tsdbutil.Sample{ - sample{3, 99}, sample{5, 99}, sample{6, 99}, sample{7, 99}, - sample{8, 99}, sample{9, 99}, sample{10, 99}, sample{11, 99}, - sample{12, 99}, sample{13, 99}, sample{14, 99}, - }), - }, - }, - expSeries: map[string][]tsdbutil.Sample{`{a="b"}`: { - sample{0, 0}, sample{1, 0}, sample{2, 0}, sample{3, 99}, - sample{4, 0}, sample{5, 99}, sample{6, 99}, sample{7, 99}, - sample{8, 99}, sample{9, 99}, sample{10, 99}, sample{11, 99}, - sample{12, 99}, sample{13, 99}, sample{14, 99}, - }}, - }, - // Case 1 - // |-------------------------------| - // |----------------| - { - blockSeries: [][]Series{ - []Series{ - newSeries(map[string]string{"a": "b"}, []tsdbutil.Sample{ - sample{0, 0}, sample{1, 0}, sample{2, 0}, sample{4, 0}, - sample{5, 0}, sample{7, 0}, sample{8, 0}, sample{9, 0}, - sample{11, 0}, sample{13, 0}, sample{17, 0}, - }), - }, - []Series{ - newSeries(map[string]string{"a": "b"}, []tsdbutil.Sample{ - sample{3, 99}, sample{5, 99}, sample{6, 99}, sample{7, 99}, - sample{8, 99}, sample{9, 99}, sample{10, 99}, - }), - }, - }, - expSeries: map[string][]tsdbutil.Sample{`{a="b"}`: { - sample{0, 0}, sample{1, 0}, sample{2, 0}, sample{3, 99}, - sample{4, 0}, sample{5, 99}, sample{6, 99}, sample{7, 99}, - sample{8, 99}, sample{9, 99}, sample{10, 99}, sample{11, 0}, - sample{13, 0}, sample{17, 0}, - }}, - }, - // Case 2 - // |-------------------------------| - // |------------| - // |--------------------| - { - blockSeries: [][]Series{ - []Series{ - newSeries(map[string]string{"a": "b"}, []tsdbutil.Sample{ - sample{0, 0}, sample{1, 0}, sample{2, 0}, sample{4, 0}, - sample{5, 0}, sample{7, 0}, sample{8, 0}, sample{9, 0}, - sample{11, 0}, sample{13, 0}, sample{17, 0}, - }), - }, - []Series{ - newSeries(map[string]string{"a": "b"}, []tsdbutil.Sample{ - sample{3, 99}, sample{5, 99}, sample{6, 99}, sample{7, 99}, - sample{8, 99}, sample{9, 99}, - }), - }, - []Series{ - newSeries(map[string]string{"a": "b"}, []tsdbutil.Sample{ - sample{14, 59}, sample{15, 59}, sample{17, 59}, sample{20, 59}, - sample{21, 59}, sample{22, 59}, - }), - }, - }, - expSeries: map[string][]tsdbutil.Sample{`{a="b"}`: { - sample{0, 0}, sample{1, 0}, sample{2, 0}, sample{3, 99}, - sample{4, 0}, sample{5, 99}, sample{6, 99}, sample{7, 99}, - sample{8, 99}, sample{9, 99}, sample{11, 0}, sample{13, 0}, - sample{14, 59}, sample{15, 59}, sample{17, 59}, sample{20, 59}, - sample{21, 59}, sample{22, 59}, - }}, - }, - // Case 3 - // |-------------------| - // |--------------------| - // |----------------| - { - blockSeries: [][]Series{ - []Series{ - newSeries(map[string]string{"a": "b"}, []tsdbutil.Sample{ - sample{0, 0}, sample{1, 0}, sample{2, 0}, sample{4, 0}, - sample{5, 0}, sample{8, 0}, sample{9, 0}, - }), - }, - []Series{ - newSeries(map[string]string{"a": "b"}, []tsdbutil.Sample{ - sample{14, 59}, sample{15, 59}, sample{17, 59}, sample{20, 59}, - sample{21, 59}, sample{22, 59}, - }), - }, - []Series{ - newSeries(map[string]string{"a": "b"}, []tsdbutil.Sample{ - sample{5, 99}, sample{6, 99}, sample{7, 99}, sample{8, 99}, - sample{9, 99}, sample{10, 99}, sample{13, 99}, sample{15, 99}, - sample{16, 99}, sample{17, 99}, - }), - }, - }, - expSeries: map[string][]tsdbutil.Sample{`{a="b"}`: { - sample{0, 0}, sample{1, 0}, sample{2, 0}, sample{4, 0}, - sample{5, 99}, sample{6, 99}, sample{7, 99}, sample{8, 99}, - sample{9, 99}, sample{10, 99}, sample{13, 99}, sample{14, 59}, - sample{15, 59}, sample{16, 99}, sample{17, 59}, sample{20, 59}, - sample{21, 59}, sample{22, 59}, - }}, - }, - // Case 4 - // |-------------------------------------| - // |------------| - // |-------------------------| - { - blockSeries: [][]Series{ - []Series{ - newSeries(map[string]string{"a": "b"}, []tsdbutil.Sample{ - sample{0, 0}, sample{1, 0}, sample{2, 0}, sample{4, 0}, - sample{5, 0}, sample{8, 0}, sample{9, 0}, sample{10, 0}, - sample{13, 0}, sample{15, 0}, sample{16, 0}, sample{17, 0}, - sample{20, 0}, sample{22, 0}, - }), - }, - []Series{ - newSeries(map[string]string{"a": "b"}, []tsdbutil.Sample{ - sample{7, 59}, sample{8, 59}, sample{9, 59}, sample{10, 59}, - sample{11, 59}, - }), - }, - []Series{ - newSeries(map[string]string{"a": "b"}, []tsdbutil.Sample{ - sample{3, 99}, sample{5, 99}, sample{6, 99}, sample{8, 99}, - sample{9, 99}, sample{10, 99}, sample{13, 99}, sample{15, 99}, - sample{16, 99}, sample{17, 99}, - }), - }, - }, - expSeries: map[string][]tsdbutil.Sample{`{a="b"}`: { - sample{0, 0}, sample{1, 0}, sample{2, 0}, sample{3, 99}, - sample{4, 0}, sample{5, 99}, sample{6, 99}, sample{7, 59}, - sample{8, 59}, sample{9, 59}, sample{10, 59}, sample{11, 59}, - sample{13, 99}, sample{15, 99}, sample{16, 99}, sample{17, 99}, - sample{20, 0}, sample{22, 0}, - }}, - }, - // Case 5: series are merged properly when there are multiple series. - // |-------------------------------------| - // |------------| - // |-------------------------| - { - blockSeries: [][]Series{ - []Series{ - newSeries(map[string]string{"a": "b"}, []tsdbutil.Sample{ - sample{0, 0}, sample{1, 0}, sample{2, 0}, sample{4, 0}, - sample{5, 0}, sample{8, 0}, sample{9, 0}, sample{10, 0}, - sample{13, 0}, sample{15, 0}, sample{16, 0}, sample{17, 0}, - sample{20, 0}, sample{22, 0}, - }), - newSeries(map[string]string{"b": "c"}, []tsdbutil.Sample{ - sample{0, 0}, sample{1, 0}, sample{2, 0}, sample{4, 0}, - sample{5, 0}, sample{8, 0}, sample{9, 0}, sample{10, 0}, - sample{13, 0}, sample{15, 0}, sample{16, 0}, sample{17, 0}, - sample{20, 0}, sample{22, 0}, - }), - newSeries(map[string]string{"c": "d"}, []tsdbutil.Sample{ - sample{0, 0}, sample{1, 0}, sample{2, 0}, sample{4, 0}, - sample{5, 0}, sample{8, 0}, sample{9, 0}, sample{10, 0}, - sample{13, 0}, sample{15, 0}, sample{16, 0}, sample{17, 0}, - sample{20, 0}, sample{22, 0}, - }), - }, - []Series{ - newSeries(map[string]string{"__name__": "a"}, []tsdbutil.Sample{ - sample{7, 59}, sample{8, 59}, sample{9, 59}, sample{10, 59}, - sample{11, 59}, - }), - newSeries(map[string]string{"a": "b"}, []tsdbutil.Sample{ - sample{7, 59}, sample{8, 59}, sample{9, 59}, sample{10, 59}, - sample{11, 59}, - }), - newSeries(map[string]string{"aa": "bb"}, []tsdbutil.Sample{ - sample{7, 59}, sample{8, 59}, sample{9, 59}, sample{10, 59}, - sample{11, 59}, - }), - newSeries(map[string]string{"c": "d"}, []tsdbutil.Sample{ - sample{7, 59}, sample{8, 59}, sample{9, 59}, sample{10, 59}, - sample{11, 59}, - }), - }, - []Series{ - newSeries(map[string]string{"a": "b"}, []tsdbutil.Sample{ - sample{3, 99}, sample{5, 99}, sample{6, 99}, sample{8, 99}, - sample{9, 99}, sample{10, 99}, sample{13, 99}, sample{15, 99}, - sample{16, 99}, sample{17, 99}, - }), - newSeries(map[string]string{"aa": "bb"}, []tsdbutil.Sample{ - sample{3, 99}, sample{5, 99}, sample{6, 99}, sample{8, 99}, - sample{9, 99}, sample{10, 99}, sample{13, 99}, sample{15, 99}, - sample{16, 99}, sample{17, 99}, - }), - newSeries(map[string]string{"c": "d"}, []tsdbutil.Sample{ - sample{3, 99}, sample{5, 99}, sample{6, 99}, sample{8, 99}, - sample{9, 99}, sample{10, 99}, sample{13, 99}, sample{15, 99}, - sample{16, 99}, sample{17, 99}, - }), - }, - }, - expSeries: map[string][]tsdbutil.Sample{ - `{__name__="a"}`: { - sample{7, 59}, sample{8, 59}, sample{9, 59}, sample{10, 59}, - sample{11, 59}, - }, - `{a="b"}`: { - sample{0, 0}, sample{1, 0}, sample{2, 0}, sample{3, 99}, - sample{4, 0}, sample{5, 99}, sample{6, 99}, sample{7, 59}, - sample{8, 59}, sample{9, 59}, sample{10, 59}, sample{11, 59}, - sample{13, 99}, sample{15, 99}, sample{16, 99}, sample{17, 99}, - sample{20, 0}, sample{22, 0}, - }, - `{aa="bb"}`: { - sample{3, 99}, sample{5, 99}, sample{6, 99}, sample{7, 59}, - sample{8, 59}, sample{9, 59}, sample{10, 59}, sample{11, 59}, - sample{13, 99}, sample{15, 99}, sample{16, 99}, sample{17, 99}, - }, - `{b="c"}`: { - sample{0, 0}, sample{1, 0}, sample{2, 0}, sample{4, 0}, - sample{5, 0}, sample{8, 0}, sample{9, 0}, sample{10, 0}, - sample{13, 0}, sample{15, 0}, sample{16, 0}, sample{17, 0}, - sample{20, 0}, sample{22, 0}, - }, - `{c="d"}`: { - sample{0, 0}, sample{1, 0}, sample{2, 0}, sample{3, 99}, - sample{4, 0}, sample{5, 99}, sample{6, 99}, sample{7, 59}, - sample{8, 59}, sample{9, 59}, sample{10, 59}, sample{11, 59}, - sample{13, 99}, sample{15, 99}, sample{16, 99}, sample{17, 99}, - sample{20, 0}, sample{22, 0}, - }, - }, - }, - } - - defaultMatcher := labels.NewMustRegexpMatcher("__name__", ".*") - for _, c := range cases { - if ok := t.Run("", func(t *testing.T) { - - tmpdir, err := ioutil.TempDir("", "data") - testutil.Ok(t, err) - defer func() { - testutil.Ok(t, os.RemoveAll(tmpdir)) - }() - - for _, series := range c.blockSeries { - createBlock(t, tmpdir, series) - } - opts := *DefaultOptions - opts.AllowOverlappingBlocks = true - db, err := Open(tmpdir, nil, nil, &opts) - testutil.Ok(t, err) - defer func() { - testutil.Ok(t, db.Close()) - }() - db.DisableCompactions() - testutil.Assert(t, len(db.blocks) == len(c.blockSeries), "Wrong number of blocks [before compact].") - - // Vertical Query Merging test. - querier, err := db.Querier(0, 100) - testutil.Ok(t, err) - actSeries := query(t, querier, defaultMatcher) - testutil.Equals(t, c.expSeries, actSeries) - - // Vertical compaction. - lc := db.compactor.(*LeveledCompactor) - testutil.Equals(t, 0, int(prom_testutil.ToFloat64(lc.metrics.overlappingBlocks)), "overlapping blocks count should be still 0 here") - err = db.compact() - testutil.Ok(t, err) - testutil.Equals(t, 1, len(db.Blocks()), "Wrong number of blocks [after compact]") - - testutil.Equals(t, 1, int(prom_testutil.ToFloat64(lc.metrics.overlappingBlocks)), "overlapping blocks count mismatch") - - // Query test after merging the overlapping blocks. - querier, err = db.Querier(0, 100) - testutil.Ok(t, err) - actSeries = query(t, querier, defaultMatcher) - testutil.Equals(t, c.expSeries, actSeries) - }); !ok { - return - } - } -} - -// TestBlockRanges checks the following use cases: -// - No samples can be added with timestamps lower than the last block maxt. -// - The compactor doesn't create overlapping blocks -// even when the last blocks is not within the default boundaries. -// - Lower boundary is based on the smallest sample in the head and -// upper boundary is rounded to the configured block range. -// -// This ensures that a snapshot that includes the head and creates a block with a custom time range -// will not overlap with the first block created by the next compaction. -func TestBlockRanges(t *testing.T) { - logger := log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr)) - - dir, err := ioutil.TempDir("", "test_storage") - if err != nil { - t.Fatalf("Opening test dir failed: %s", err) - } - - rangeToTriggercompaction := DefaultOptions.BlockRanges[0]/2*3 + 1 - - // Test that the compactor doesn't create overlapping blocks - // when a non standard block already exists. - firstBlockMaxT := int64(3) - createBlock(t, dir, genSeries(1, 1, 0, firstBlockMaxT)) - db, err := Open(dir, logger, nil, DefaultOptions) - if err != nil { - t.Fatalf("Opening test storage failed: %s", err) - } - defer func() { - os.RemoveAll(dir) - }() - app := db.Appender() - lbl := labels.Labels{{"a", "b"}} - _, err = app.Add(lbl, firstBlockMaxT-1, rand.Float64()) - if err == nil { - t.Fatalf("appending a sample with a timestamp covered by a previous block shouldn't be possible") - } - _, err = app.Add(lbl, firstBlockMaxT+1, rand.Float64()) - testutil.Ok(t, err) - _, err = app.Add(lbl, firstBlockMaxT+2, rand.Float64()) - testutil.Ok(t, err) - secondBlockMaxt := firstBlockMaxT + rangeToTriggercompaction - _, err = app.Add(lbl, secondBlockMaxt, rand.Float64()) // Add samples to trigger a new compaction - - testutil.Ok(t, err) - testutil.Ok(t, app.Commit()) - for x := 0; x < 100; x++ { - if len(db.Blocks()) == 2 { - break - } - time.Sleep(100 * time.Millisecond) - } - testutil.Equals(t, 2, len(db.Blocks()), "no new block created after the set timeout") - - if db.Blocks()[0].Meta().MaxTime > db.Blocks()[1].Meta().MinTime { - t.Fatalf("new block overlaps old:%v,new:%v", db.Blocks()[0].Meta(), db.Blocks()[1].Meta()) - } - - // Test that wal records are skipped when an existing block covers the same time ranges - // and compaction doesn't create an overlapping block. - db.DisableCompactions() - _, err = app.Add(lbl, secondBlockMaxt+1, rand.Float64()) - testutil.Ok(t, err) - _, err = app.Add(lbl, secondBlockMaxt+2, rand.Float64()) - testutil.Ok(t, err) - _, err = app.Add(lbl, secondBlockMaxt+3, rand.Float64()) - testutil.Ok(t, err) - _, err = app.Add(lbl, secondBlockMaxt+4, rand.Float64()) - testutil.Ok(t, err) - testutil.Ok(t, app.Commit()) - testutil.Ok(t, db.Close()) - - thirdBlockMaxt := secondBlockMaxt + 2 - createBlock(t, dir, genSeries(1, 1, secondBlockMaxt+1, thirdBlockMaxt)) - - db, err = Open(dir, logger, nil, DefaultOptions) - if err != nil { - t.Fatalf("Opening test storage failed: %s", err) - } - defer db.Close() - testutil.Equals(t, 3, len(db.Blocks()), "db doesn't include expected number of blocks") - testutil.Equals(t, db.Blocks()[2].Meta().MaxTime, thirdBlockMaxt, "unexpected maxt of the last block") - - app = db.Appender() - _, err = app.Add(lbl, thirdBlockMaxt+rangeToTriggercompaction, rand.Float64()) // Trigger a compaction - testutil.Ok(t, err) - testutil.Ok(t, app.Commit()) - for x := 0; x < 100; x++ { - if len(db.Blocks()) == 4 { - break - } - time.Sleep(100 * time.Millisecond) - } - - testutil.Equals(t, 4, len(db.Blocks()), "no new block created after the set timeout") - - if db.Blocks()[2].Meta().MaxTime > db.Blocks()[3].Meta().MinTime { - t.Fatalf("new block overlaps old:%v,new:%v", db.Blocks()[2].Meta(), db.Blocks()[3].Meta()) - } -} diff --git a/vendor/github.com/prometheus/tsdb/encoding/encoding.go b/vendor/github.com/prometheus/tsdb/encoding/encoding.go deleted file mode 100644 index 395e11cf8..000000000 --- a/vendor/github.com/prometheus/tsdb/encoding/encoding.go +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package encoding - -import ( - "encoding/binary" - "hash" - "hash/crc32" - "unsafe" - - "github.com/pkg/errors" -) - -var ( - ErrInvalidSize = errors.New("invalid size") - ErrInvalidChecksum = errors.New("invalid checksum") -) - -// enbuf is a helper type to populate a byte slice with various types. -type Encbuf struct { - B []byte - C [binary.MaxVarintLen64]byte -} - -func (e *Encbuf) Reset() { e.B = e.B[:0] } -func (e *Encbuf) Get() []byte { return e.B } -func (e *Encbuf) Len() int { return len(e.B) } - -func (e *Encbuf) PutString(s string) { e.B = append(e.B, s...) } -func (e *Encbuf) PutByte(c byte) { e.B = append(e.B, c) } - -func (e *Encbuf) PutBE32int(x int) { e.PutBE32(uint32(x)) } -func (e *Encbuf) PutUvarint32(x uint32) { e.PutUvarint64(uint64(x)) } -func (e *Encbuf) PutBE64int64(x int64) { e.PutBE64(uint64(x)) } -func (e *Encbuf) PutUvarint(x int) { e.PutUvarint64(uint64(x)) } - -func (e *Encbuf) PutBE32(x uint32) { - binary.BigEndian.PutUint32(e.C[:], x) - e.B = append(e.B, e.C[:4]...) -} - -func (e *Encbuf) PutBE64(x uint64) { - binary.BigEndian.PutUint64(e.C[:], x) - e.B = append(e.B, e.C[:8]...) -} - -func (e *Encbuf) PutUvarint64(x uint64) { - n := binary.PutUvarint(e.C[:], x) - e.B = append(e.B, e.C[:n]...) -} - -func (e *Encbuf) PutVarint64(x int64) { - n := binary.PutVarint(e.C[:], x) - e.B = append(e.B, e.C[:n]...) -} - -// putVarintStr writes a string to the buffer prefixed by its varint length (in bytes!). -func (e *Encbuf) PutUvarintStr(s string) { - b := *(*[]byte)(unsafe.Pointer(&s)) - e.PutUvarint(len(b)) - e.PutString(s) -} - -// putHash appends a hash over the buffers current contents to the buffer. -func (e *Encbuf) PutHash(h hash.Hash) { - h.Reset() - _, err := h.Write(e.B) - if err != nil { - panic(err) // The CRC32 implementation does not error - } - e.B = h.Sum(e.B) -} - -// decbuf provides safe methods to extract data from a byte slice. It does all -// necessary bounds checking and advancing of the byte slice. -// Several datums can be extracted without checking for errors. However, before using -// any datum, the err() method must be checked. -type Decbuf struct { - B []byte - E error -} - -// NewDecbufAt returns a new decoding buffer. It expects the first 4 bytes -// after offset to hold the big endian encoded content length, followed by the contents and the expected -// checksum. -func NewDecbufAt(bs ByteSlice, off int, castagnoliTable *crc32.Table) Decbuf { - if bs.Len() < off+4 { - return Decbuf{E: ErrInvalidSize} - } - b := bs.Range(off, off+4) - l := int(binary.BigEndian.Uint32(b)) - - if bs.Len() < off+4+l+4 { - return Decbuf{E: ErrInvalidSize} - } - - // Load bytes holding the contents plus a CRC32 checksum. - b = bs.Range(off+4, off+4+l+4) - dec := Decbuf{B: b[:len(b)-4]} - - if exp := binary.BigEndian.Uint32(b[len(b)-4:]); dec.Crc32(castagnoliTable) != exp { - return Decbuf{E: ErrInvalidChecksum} - } - return dec -} - -// NewDecbufUvarintAt returns a new decoding buffer. It expects the first bytes -// after offset to hold the uvarint-encoded buffers length, followed by the contents and the expected -// checksum. -func NewDecbufUvarintAt(bs ByteSlice, off int, castagnoliTable *crc32.Table) Decbuf { - // We never have to access this method at the far end of the byte slice. Thus just checking - // against the MaxVarintLen32 is sufficient. - if bs.Len() < off+binary.MaxVarintLen32 { - return Decbuf{E: ErrInvalidSize} - } - b := bs.Range(off, off+binary.MaxVarintLen32) - - l, n := binary.Uvarint(b) - if n <= 0 || n > binary.MaxVarintLen32 { - return Decbuf{E: errors.Errorf("invalid uvarint %d", n)} - } - - if bs.Len() < off+n+int(l)+4 { - return Decbuf{E: ErrInvalidSize} - } - - // Load bytes holding the contents plus a CRC32 checksum. - b = bs.Range(off+n, off+n+int(l)+4) - dec := Decbuf{B: b[:len(b)-4]} - - if dec.Crc32(castagnoliTable) != binary.BigEndian.Uint32(b[len(b)-4:]) { - return Decbuf{E: ErrInvalidChecksum} - } - return dec -} - -func (d *Decbuf) Uvarint() int { return int(d.Uvarint64()) } -func (d *Decbuf) Be32int() int { return int(d.Be32()) } -func (d *Decbuf) Be64int64() int64 { return int64(d.Be64()) } - -// Crc32 returns a CRC32 checksum over the remaining bytes. -func (d *Decbuf) Crc32(castagnoliTable *crc32.Table) uint32 { - return crc32.Checksum(d.B, castagnoliTable) -} - -func (d *Decbuf) UvarintStr() string { - l := d.Uvarint64() - if d.E != nil { - return "" - } - if len(d.B) < int(l) { - d.E = ErrInvalidSize - return "" - } - s := string(d.B[:l]) - d.B = d.B[l:] - return s -} - -func (d *Decbuf) Varint64() int64 { - if d.E != nil { - return 0 - } - x, n := binary.Varint(d.B) - if n < 1 { - d.E = ErrInvalidSize - return 0 - } - d.B = d.B[n:] - return x -} - -func (d *Decbuf) Uvarint64() uint64 { - if d.E != nil { - return 0 - } - x, n := binary.Uvarint(d.B) - if n < 1 { - d.E = ErrInvalidSize - return 0 - } - d.B = d.B[n:] - return x -} - -func (d *Decbuf) Be64() uint64 { - if d.E != nil { - return 0 - } - if len(d.B) < 8 { - d.E = ErrInvalidSize - return 0 - } - x := binary.BigEndian.Uint64(d.B) - d.B = d.B[8:] - return x -} - -func (d *Decbuf) Be32() uint32 { - if d.E != nil { - return 0 - } - if len(d.B) < 4 { - d.E = ErrInvalidSize - return 0 - } - x := binary.BigEndian.Uint32(d.B) - d.B = d.B[4:] - return x -} - -func (d *Decbuf) Byte() byte { - if d.E != nil { - return 0 - } - if len(d.B) < 1 { - d.E = ErrInvalidSize - return 0 - } - x := d.B[0] - d.B = d.B[1:] - return x -} - -func (d *Decbuf) Err() error { return d.E } -func (d *Decbuf) Len() int { return len(d.B) } -func (d *Decbuf) Get() []byte { return d.B } - -// ByteSlice abstracts a byte slice. -type ByteSlice interface { - Len() int - Range(start, end int) []byte -} diff --git a/vendor/github.com/prometheus/tsdb/encoding_helpers.go b/vendor/github.com/prometheus/tsdb/encoding_helpers.go new file mode 100644 index 000000000..6dd6e7c2e --- /dev/null +++ b/vendor/github.com/prometheus/tsdb/encoding_helpers.go @@ -0,0 +1,196 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tsdb + +import ( + "encoding/binary" + "hash" + "hash/crc32" + "unsafe" + + "github.com/pkg/errors" +) + +var errInvalidSize = errors.New("invalid size") + +// encbuf is a helper type to populate a byte slice with various types. +type encbuf struct { + b []byte + c [binary.MaxVarintLen64]byte +} + +func (e *encbuf) reset() { e.b = e.b[:0] } +func (e *encbuf) get() []byte { return e.b } +func (e *encbuf) len() int { return len(e.b) } + +func (e *encbuf) putString(s string) { e.b = append(e.b, s...) } +func (e *encbuf) putBytes(b []byte) { e.b = append(e.b, b...) } +func (e *encbuf) putByte(c byte) { e.b = append(e.b, c) } + +func (e *encbuf) putBE32int(x int) { e.putBE32(uint32(x)) } +func (e *encbuf) putBE64int(x int) { e.putBE64(uint64(x)) } +func (e *encbuf) putBE64int64(x int64) { e.putBE64(uint64(x)) } +func (e *encbuf) putUvarint32(x uint32) { e.putUvarint64(uint64(x)) } +func (e *encbuf) putUvarint(x int) { e.putUvarint64(uint64(x)) } + +func (e *encbuf) putBE32(x uint32) { + binary.BigEndian.PutUint32(e.c[:], x) + e.b = append(e.b, e.c[:4]...) +} + +func (e *encbuf) putBE64(x uint64) { + binary.BigEndian.PutUint64(e.c[:], x) + e.b = append(e.b, e.c[:8]...) +} + +func (e *encbuf) putUvarint64(x uint64) { + n := binary.PutUvarint(e.c[:], x) + e.b = append(e.b, e.c[:n]...) +} + +func (e *encbuf) putVarint64(x int64) { + n := binary.PutVarint(e.c[:], x) + e.b = append(e.b, e.c[:n]...) +} + +// putVarintStr writes a string to the buffer prefixed by its varint length (in bytes!). +func (e *encbuf) putUvarintStr(s string) { + b := *(*[]byte)(unsafe.Pointer(&s)) + e.putUvarint(len(b)) + e.putString(s) +} + +// putHash appends a hash over the buffers current contents to the buffer. +func (e *encbuf) putHash(h hash.Hash) { + h.Reset() + _, err := h.Write(e.b) + if err != nil { + panic(err) // The CRC32 implementation does not error + } + e.b = h.Sum(e.b) +} + +// decbuf provides safe methods to extract data from a byte slice. It does all +// necessary bounds checking and advancing of the byte slice. +// Several datums can be extracted without checking for errors. However, before using +// any datum, the err() method must be checked. +type decbuf struct { + b []byte + e error +} + +func (d *decbuf) uvarint() int { return int(d.uvarint64()) } +func (d *decbuf) uvarint32() uint32 { return uint32(d.uvarint64()) } +func (d *decbuf) be32int() int { return int(d.be32()) } +func (d *decbuf) be64int64() int64 { return int64(d.be64()) } + +// crc32 returns a CRC32 checksum over the remaining bytes. +func (d *decbuf) crc32() uint32 { + return crc32.Checksum(d.b, castagnoliTable) +} + +func (d *decbuf) uvarintStr() string { + l := d.uvarint64() + if d.e != nil { + return "" + } + if len(d.b) < int(l) { + d.e = errInvalidSize + return "" + } + s := string(d.b[:l]) + d.b = d.b[l:] + return s +} + +func (d *decbuf) varint64() int64 { + if d.e != nil { + return 0 + } + x, n := binary.Varint(d.b) + if n < 1 { + d.e = errInvalidSize + return 0 + } + d.b = d.b[n:] + return x +} + +func (d *decbuf) uvarint64() uint64 { + if d.e != nil { + return 0 + } + x, n := binary.Uvarint(d.b) + if n < 1 { + d.e = errInvalidSize + return 0 + } + d.b = d.b[n:] + return x +} + +func (d *decbuf) be64() uint64 { + if d.e != nil { + return 0 + } + if len(d.b) < 4 { + d.e = errInvalidSize + return 0 + } + x := binary.BigEndian.Uint64(d.b) + d.b = d.b[8:] + return x +} + +func (d *decbuf) be32() uint32 { + if d.e != nil { + return 0 + } + if len(d.b) < 4 { + d.e = errInvalidSize + return 0 + } + x := binary.BigEndian.Uint32(d.b) + d.b = d.b[4:] + return x +} + +func (d *decbuf) byte() byte { + if d.e != nil { + return 0 + } + if len(d.b) < 1 { + d.e = errInvalidSize + return 0 + } + x := d.b[0] + d.b = d.b[1:] + return x +} + +func (d *decbuf) decbuf(l int) decbuf { + if d.e != nil { + return decbuf{e: d.e} + } + if l > len(d.b) { + return decbuf{e: errInvalidSize} + } + r := decbuf{b: d.b[:l]} + d.b = d.b[l:] + return r +} + +func (d *decbuf) err() error { return d.e } +func (d *decbuf) len() int { return len(d.b) } +func (d *decbuf) get() []byte { return d.b } diff --git a/vendor/github.com/prometheus/tsdb/fileutil/fileutil.go b/vendor/github.com/prometheus/tsdb/fileutil/fileutil.go index 154fa1844..677df8c09 100644 --- a/vendor/github.com/prometheus/tsdb/fileutil/fileutil.go +++ b/vendor/github.com/prometheus/tsdb/fileutil/fileutil.go @@ -77,8 +77,9 @@ func copyFile(src, dest string) error { // returns relative paths to all files and empty directories. func readDirs(src string) ([]string, error) { var files []string + var err error - err := filepath.Walk(src, func(path string, f os.FileInfo, err error) error { + err = filepath.Walk(src, func(path string, f os.FileInfo, err error) error { relativePath := strings.TrimPrefix(path, src) if len(relativePath) > 0 { files = append(files, relativePath) diff --git a/vendor/github.com/prometheus/tsdb/fileutil/flock_test.go b/vendor/github.com/prometheus/tsdb/fileutil/flock_test.go deleted file mode 100644 index d30d20b21..000000000 --- a/vendor/github.com/prometheus/tsdb/fileutil/flock_test.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2016 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package fileutil - -import ( - "os" - "path/filepath" - "testing" - - "github.com/prometheus/tsdb/testutil" -) - -func TestLocking(t *testing.T) { - dir := testutil.NewTemporaryDirectory("test_flock", t) - defer dir.Close() - - fileName := filepath.Join(dir.Path(), "LOCK") - - if _, err := os.Stat(fileName); err == nil { - t.Fatalf("File %q unexpectedly exists.", fileName) - } - - lock, existed, err := Flock(fileName) - if err != nil { - t.Fatalf("Error locking file %q: %s", fileName, err) - } - if existed { - t.Errorf("File %q reported as existing during locking.", fileName) - } - - // File must now exist. - if _, err = os.Stat(fileName); err != nil { - t.Errorf("Could not stat file %q expected to exist: %s", fileName, err) - } - - // Try to lock again. - lockedAgain, existed, err := Flock(fileName) - if err == nil { - t.Fatalf("File %q locked twice.", fileName) - } - if lockedAgain != nil { - t.Error("Unsuccessful locking did not return nil.") - } - if !existed { - t.Errorf("Existing file %q not recognized.", fileName) - } - - if err := lock.Release(); err != nil { - t.Errorf("Error releasing lock for file %q: %s", fileName, err) - } - - // File must still exist. - if _, err = os.Stat(fileName); err != nil { - t.Errorf("Could not stat file %q expected to exist: %s", fileName, err) - } - - // Lock existing file. - lock, existed, err = Flock(fileName) - if err != nil { - t.Fatalf("Error locking file %q: %s", fileName, err) - } - if !existed { - t.Errorf("Existing file %q not recognized.", fileName) - } - - if err := lock.Release(); err != nil { - t.Errorf("Error releasing lock for file %q: %s", fileName, err) - } -} diff --git a/vendor/github.com/prometheus/tsdb/head.go b/vendor/github.com/prometheus/tsdb/head.go index fe2089754..cbc8661f8 100644 --- a/vendor/github.com/prometheus/tsdb/head.go +++ b/vendor/github.com/prometheus/tsdb/head.go @@ -28,7 +28,6 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/tsdb/chunkenc" "github.com/prometheus/tsdb/chunks" - "github.com/prometheus/tsdb/encoding" "github.com/prometheus/tsdb/index" "github.com/prometheus/tsdb/labels" "github.com/prometheus/tsdb/wal" @@ -49,10 +48,6 @@ var ( // ErrOutOfBounds is returned if an appended sample is out of the // writable time range. ErrOutOfBounds = errors.New("out of bounds") - - // emptyTombstoneReader is a no-op Tombstone Reader. - // This is used by head to satisfy the Tombstones() function call. - emptyTombstoneReader = newMemTombstones() ) // Head handles reads and writes of time series data within a time window. @@ -76,6 +71,8 @@ type Head struct { values map[string]stringset // label names to possible values postings *index.MemPostings // postings lists for terms + + tombstones *memTombstones } type headMetrics struct { @@ -234,6 +231,7 @@ func NewHead(r prometheus.Registerer, l log.Logger, wal *wal.WAL, chunkRange int values: map[string]stringset{}, symbols: map[string]struct{}{}, postings: index.NewUnorderedMemPostings(), + tombstones: newMemTombstones(), } h.metrics = newHeadMetrics(h, r) @@ -336,14 +334,12 @@ func (h *Head) loadWAL(r *wal.Reader) error { } var ( - dec RecordDecoder - series []RefSeries - samples []RefSample - tstones []Stone - allStones = newMemTombstones() - err error + dec RecordDecoder + series []RefSeries + samples []RefSample + tstones []Stone + err error ) - defer allStones.Close() for r.Next() { series, samples, tstones = series[:0], samples[:0], tstones[:0] rec := r.Record() @@ -417,7 +413,7 @@ func (h *Head) loadWAL(r *wal.Reader) error { if itv.Maxt < h.minValidTime { continue } - allStones.addInterval(s.ref, itv) + h.tombstones.addInterval(s.ref, itv) } } default: @@ -440,12 +436,6 @@ func (h *Head) loadWAL(r *wal.Reader) error { } wg.Wait() - if err := allStones.Iter(func(ref uint64, dranges Intervals) error { - return h.chunkRewrite(ref, dranges) - }); err != nil { - return errors.Wrap(r.Err(), "deleting samples from tombstones") - } - if unknownRefs > 0 { level.Warn(h.logger).Log("msg", "unknown series references", "count", unknownRefs) } @@ -614,15 +604,7 @@ func (h *rangeHead) Chunks() (ChunkReader, error) { } func (h *rangeHead) Tombstones() (TombstoneReader, error) { - return emptyTombstoneReader, nil -} - -func (h *rangeHead) MinTime() int64 { - return h.mint -} - -func (h *rangeHead) MaxTime() int64 { - return h.maxt + return h.head.tombstones, nil } // initAppender is a helper to initialize the time bounds of the head @@ -867,7 +849,7 @@ func (h *Head) Delete(mint, maxt int64, ms ...labels.Matcher) error { } var stones []Stone - dirty := false + for p.Next() { series := h.series.getByID(p.At()) @@ -877,61 +859,22 @@ func (h *Head) Delete(mint, maxt int64, ms ...labels.Matcher) error { } // Delete only until the current values and not beyond. t0, t1 = clampInterval(mint, maxt, t0, t1) - if h.wal != nil { - stones = append(stones, Stone{p.At(), Intervals{{t0, t1}}}) - } - if err := h.chunkRewrite(p.At(), Intervals{{t0, t1}}); err != nil { - return errors.Wrap(err, "delete samples") - } - dirty = true + stones = append(stones, Stone{p.At(), Intervals{{t0, t1}}}) } + if p.Err() != nil { return p.Err() } var enc RecordEncoder + if h.wal != nil { - // Although we don't store the stones in the head - // we need to write them to the WAL to mark these as deleted - // after a restart while loeading the WAL. if err := h.wal.Log(enc.Tombstones(stones, nil)); err != nil { return err } } - if dirty { - h.gc() - } - - return nil -} - -// chunkRewrite re-writes the chunks which overlaps with deleted ranges -// and removes the samples in the deleted ranges. -// Chunks is deleted if no samples are left at the end. -func (h *Head) chunkRewrite(ref uint64, dranges Intervals) (err error) { - if len(dranges) == 0 { - return nil - } - - ms := h.series.getByID(ref) - ms.Lock() - defer ms.Unlock() - if len(ms.chunks) == 0 { - return nil - } - - metas := ms.chunksMetas() - mint, maxt := metas[0].MinTime, metas[len(metas)-1].MaxTime - it := newChunkSeriesIterator(metas, dranges, mint, maxt) - - ms.reset() - for it.Next() { - t, v := it.At() - ok, _ := ms.append(t, v) - if !ok { - level.Warn(h.logger).Log("msg", "failed to add sample during delete") - } + for _, s := range stones { + h.tombstones.addInterval(s.ref, s.intervals[0]) } - return nil } @@ -983,7 +926,7 @@ func (h *Head) gc() { // Tombstones returns a new reader over the head's tombstones func (h *Head) Tombstones() (TombstoneReader, error) { - return emptyTombstoneReader, nil + return h.tombstones, nil } // Index returns an IndexReader against the block. @@ -1118,7 +1061,7 @@ func (h *headIndexReader) Symbols() (map[string]struct{}, error) { // LabelValues returns the possible label values func (h *headIndexReader) LabelValues(names ...string) (index.StringTuples, error) { if len(names) != 1 { - return nil, encoding.ErrInvalidSize + return nil, errInvalidSize } h.head.symMtx.RLock() @@ -1463,16 +1406,6 @@ type memSeries struct { app chunkenc.Appender // Current appender for the chunk. } -func newMemSeries(lset labels.Labels, id uint64, chunkRange int64) *memSeries { - s := &memSeries{ - lset: lset, - ref: id, - chunkRange: chunkRange, - nextAt: math.MinInt64, - } - return s -} - func (s *memSeries) minTime() int64 { if len(s.chunks) == 0 { return math.MinInt64 @@ -1509,24 +1442,14 @@ func (s *memSeries) cut(mint int64) *memChunk { return c } -func (s *memSeries) chunksMetas() []chunks.Meta { - metas := make([]chunks.Meta, 0, len(s.chunks)) - for _, chk := range s.chunks { - metas = append(metas, chunks.Meta{Chunk: chk.chunk, MinTime: chk.minTime, MaxTime: chk.maxTime}) +func newMemSeries(lset labels.Labels, id uint64, chunkRange int64) *memSeries { + s := &memSeries{ + lset: lset, + ref: id, + chunkRange: chunkRange, + nextAt: math.MinInt64, } - return metas -} - -// reset re-initialises all the variable in the memSeries except 'lset', 'ref', -// and 'chunkRange', like how it would appear after 'newMemSeries(...)'. -func (s *memSeries) reset() { - s.chunks = nil - s.headChunk = nil - s.firstChunkID = 0 - s.nextAt = math.MinInt64 - s.sampleBuf = [4]sample{} - s.pendingCommit = false - s.app = nil + return s } // appendable checks whether the given sample is valid for appending to the series. @@ -1705,6 +1628,11 @@ func (ss stringset) set(s string) { ss[s] = struct{}{} } +func (ss stringset) has(s string) bool { + _, ok := ss[s] + return ok +} + func (ss stringset) String() string { return strings.Join(ss.slice(), ",") } diff --git a/vendor/github.com/prometheus/tsdb/head_bench_test.go b/vendor/github.com/prometheus/tsdb/head_bench_test.go deleted file mode 100644 index ebae304d7..000000000 --- a/vendor/github.com/prometheus/tsdb/head_bench_test.go +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tsdb - -import ( - "strconv" - "sync/atomic" - "testing" - - "github.com/prometheus/tsdb/labels" - "github.com/prometheus/tsdb/testutil" -) - -func BenchmarkHeadStripeSeriesCreate(b *testing.B) { - // Put a series, select it. GC it and then access it. - h, err := NewHead(nil, nil, nil, 1000) - testutil.Ok(b, err) - defer h.Close() - - for i := 0; i < b.N; i++ { - h.getOrCreate(uint64(i), labels.FromStrings("a", strconv.Itoa(i))) - } -} - -func BenchmarkHeadStripeSeriesCreateParallel(b *testing.B) { - // Put a series, select it. GC it and then access it. - h, err := NewHead(nil, nil, nil, 1000) - testutil.Ok(b, err) - defer h.Close() - - var count int64 - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - i := atomic.AddInt64(&count, 1) - h.getOrCreate(uint64(i), labels.FromStrings("a", strconv.Itoa(int(i)))) - } - }) -} - -// TODO: generalize benchmark and pass all postings for matchers here -func BenchmarkHeadPostingForMatchers(b *testing.B) { - // Put a series, select it. GC it and then access it. - h, err := NewHead(nil, nil, nil, 1000) - testutil.Ok(b, err) - defer func() { - testutil.Ok(b, h.Close()) - }() - - var hash uint64 - for n := 0; n < 10; n++ { - for i := 0; i < 100000; i++ { - h.getOrCreate(hash, labels.FromStrings("i", strconv.Itoa(i), "n", strconv.Itoa(i), "j", "foo")) - hash++ - // Have some series that won't be matched, to properly test inverted matches. - h.getOrCreate(hash, labels.FromStrings("i", strconv.Itoa(i), "n", strconv.Itoa(i), "j", "bar")) - hash++ - } - } - - n1 := labels.NewEqualMatcher("n", "1") - - jFoo := labels.NewEqualMatcher("j", "foo") - jNotFoo := labels.Not(jFoo) - - iStar := labels.NewMustRegexpMatcher("i", "^.*$") - iPlus := labels.NewMustRegexpMatcher("i", "^.+$") - i1Plus := labels.NewMustRegexpMatcher("i", "^1.+$") - iEmptyRe := labels.NewMustRegexpMatcher("i", "^$") - iNotEmpty := labels.Not(labels.NewEqualMatcher("i", "")) - iNot2 := labels.Not(labels.NewEqualMatcher("n", "2")) - iNot2Star := labels.Not(labels.NewMustRegexpMatcher("i", "^2.*$")) - - cases := []struct { - name string - matchers []labels.Matcher - }{ - {`n="1"`, []labels.Matcher{n1}}, - {`n="1",j="foo"`, []labels.Matcher{n1, jFoo}}, - {`j="foo",n="1"`, []labels.Matcher{jFoo, n1}}, - {`n="1",j!="foo"`, []labels.Matcher{n1, jNotFoo}}, - {`i=~".*"`, []labels.Matcher{iStar}}, - {`i=~".+"`, []labels.Matcher{iPlus}}, - {`i=~""`, []labels.Matcher{iEmptyRe}}, - {`i!=""`, []labels.Matcher{iNotEmpty}}, - {`n="1",i=~".*",j="foo"`, []labels.Matcher{n1, iStar, jFoo}}, - {`n="1",i=~".*",i!="2",j="foo"`, []labels.Matcher{n1, iStar, iNot2, jFoo}}, - {`n="1",i!="",j="foo"`, []labels.Matcher{n1, iNotEmpty, jFoo}}, - {`n="1",i=~".+",j="foo"`, []labels.Matcher{n1, iPlus, jFoo}}, - {`n="1",i=~"1.+",j="foo"`, []labels.Matcher{n1, i1Plus, jFoo}}, - {`n="1",i=~".+",i!="2",j="foo"`, []labels.Matcher{n1, iPlus, iNot2, jFoo}}, - {`n="1",i=~".+",i!~"2.*",j="foo"`, []labels.Matcher{n1, iPlus, iNot2Star, jFoo}}, - } - - for _, c := range cases { - b.Run(c.name, func(b *testing.B) { - for i := 0; i < b.N; i++ { - _, err := PostingsForMatchers(h.indexRange(0, 1000), c.matchers...) - testutil.Ok(b, err) - } - }) - } -} diff --git a/vendor/github.com/prometheus/tsdb/head_test.go b/vendor/github.com/prometheus/tsdb/head_test.go deleted file mode 100644 index 679e8c832..000000000 --- a/vendor/github.com/prometheus/tsdb/head_test.go +++ /dev/null @@ -1,1012 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tsdb - -import ( - "io/ioutil" - "math" - "math/rand" - "os" - "path" - "path/filepath" - "sort" - "testing" - - prom_testutil "github.com/prometheus/client_golang/prometheus/testutil" - "github.com/prometheus/tsdb/chunkenc" - "github.com/prometheus/tsdb/chunks" - "github.com/prometheus/tsdb/index" - "github.com/prometheus/tsdb/labels" - "github.com/prometheus/tsdb/testutil" - "github.com/prometheus/tsdb/tsdbutil" - "github.com/prometheus/tsdb/wal" -) - -func BenchmarkCreateSeries(b *testing.B) { - lbls, err := labels.ReadLabels(filepath.Join("testdata", "20kseries.json"), b.N) - testutil.Ok(b, err) - - h, err := NewHead(nil, nil, nil, 10000) - testutil.Ok(b, err) - defer h.Close() - - b.ReportAllocs() - b.ResetTimer() - - for _, l := range lbls { - h.getOrCreate(l.Hash(), l) - } -} - -func populateTestWAL(t testing.TB, w *wal.WAL, recs []interface{}) { - var enc RecordEncoder - for _, r := range recs { - switch v := r.(type) { - case []RefSeries: - testutil.Ok(t, w.Log(enc.Series(v, nil))) - case []RefSample: - testutil.Ok(t, w.Log(enc.Samples(v, nil))) - case []Stone: - testutil.Ok(t, w.Log(enc.Tombstones(v, nil))) - } - } -} - -func readTestWAL(t testing.TB, dir string) (recs []interface{}) { - sr, err := wal.NewSegmentsReader(dir) - testutil.Ok(t, err) - defer sr.Close() - - var dec RecordDecoder - r := wal.NewReader(sr) - - for r.Next() { - rec := r.Record() - - switch dec.Type(rec) { - case RecordSeries: - series, err := dec.Series(rec, nil) - testutil.Ok(t, err) - recs = append(recs, series) - case RecordSamples: - samples, err := dec.Samples(rec, nil) - testutil.Ok(t, err) - recs = append(recs, samples) - case RecordTombstones: - tstones, err := dec.Tombstones(rec, nil) - testutil.Ok(t, err) - recs = append(recs, tstones) - default: - t.Fatalf("unknown record type") - } - } - testutil.Ok(t, r.Err()) - return recs -} - -func TestHead_ReadWAL(t *testing.T) { - entries := []interface{}{ - []RefSeries{ - {Ref: 10, Labels: labels.FromStrings("a", "1")}, - {Ref: 11, Labels: labels.FromStrings("a", "2")}, - {Ref: 100, Labels: labels.FromStrings("a", "3")}, - }, - []RefSample{ - {Ref: 0, T: 99, V: 1}, - {Ref: 10, T: 100, V: 2}, - {Ref: 100, T: 100, V: 3}, - }, - []RefSeries{ - {Ref: 50, Labels: labels.FromStrings("a", "4")}, - }, - []RefSample{ - {Ref: 10, T: 101, V: 5}, - {Ref: 50, T: 101, V: 6}, - }, - } - dir, err := ioutil.TempDir("", "test_read_wal") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - w, err := wal.New(nil, nil, dir) - testutil.Ok(t, err) - defer w.Close() - populateTestWAL(t, w, entries) - - head, err := NewHead(nil, nil, w, 1000) - testutil.Ok(t, err) - - testutil.Ok(t, head.Init(math.MinInt64)) - testutil.Equals(t, uint64(100), head.lastSeriesID) - - s10 := head.series.getByID(10) - s11 := head.series.getByID(11) - s50 := head.series.getByID(50) - s100 := head.series.getByID(100) - - testutil.Equals(t, labels.FromStrings("a", "1"), s10.lset) - testutil.Equals(t, (*memSeries)(nil), s11) // Series without samples should be garbage colected at head.Init(). - testutil.Equals(t, labels.FromStrings("a", "4"), s50.lset) - testutil.Equals(t, labels.FromStrings("a", "3"), s100.lset) - - expandChunk := func(c chunkenc.Iterator) (x []sample) { - for c.Next() { - t, v := c.At() - x = append(x, sample{t: t, v: v}) - } - testutil.Ok(t, c.Err()) - return x - } - - testutil.Equals(t, []sample{{100, 2}, {101, 5}}, expandChunk(s10.iterator(0))) - testutil.Equals(t, []sample{{101, 6}}, expandChunk(s50.iterator(0))) - testutil.Equals(t, []sample{{100, 3}}, expandChunk(s100.iterator(0))) -} - -func TestHead_Truncate(t *testing.T) { - h, err := NewHead(nil, nil, nil, 1000) - testutil.Ok(t, err) - defer h.Close() - - h.initTime(0) - - s1, _ := h.getOrCreate(1, labels.FromStrings("a", "1", "b", "1")) - s2, _ := h.getOrCreate(2, labels.FromStrings("a", "2", "b", "1")) - s3, _ := h.getOrCreate(3, labels.FromStrings("a", "1", "b", "2")) - s4, _ := h.getOrCreate(4, labels.FromStrings("a", "2", "b", "2", "c", "1")) - - s1.chunks = []*memChunk{ - {minTime: 0, maxTime: 999}, - {minTime: 1000, maxTime: 1999}, - {minTime: 2000, maxTime: 2999}, - } - s2.chunks = []*memChunk{ - {minTime: 1000, maxTime: 1999}, - {minTime: 2000, maxTime: 2999}, - {minTime: 3000, maxTime: 3999}, - } - s3.chunks = []*memChunk{ - {minTime: 0, maxTime: 999}, - {minTime: 1000, maxTime: 1999}, - } - s4.chunks = []*memChunk{} - - // Truncation need not be aligned. - testutil.Ok(t, h.Truncate(1)) - - testutil.Ok(t, h.Truncate(2000)) - - testutil.Equals(t, []*memChunk{ - {minTime: 2000, maxTime: 2999}, - }, h.series.getByID(s1.ref).chunks) - - testutil.Equals(t, []*memChunk{ - {minTime: 2000, maxTime: 2999}, - {minTime: 3000, maxTime: 3999}, - }, h.series.getByID(s2.ref).chunks) - - testutil.Assert(t, h.series.getByID(s3.ref) == nil, "") - testutil.Assert(t, h.series.getByID(s4.ref) == nil, "") - - postingsA1, _ := index.ExpandPostings(h.postings.Get("a", "1")) - postingsA2, _ := index.ExpandPostings(h.postings.Get("a", "2")) - postingsB1, _ := index.ExpandPostings(h.postings.Get("b", "1")) - postingsB2, _ := index.ExpandPostings(h.postings.Get("b", "2")) - postingsC1, _ := index.ExpandPostings(h.postings.Get("c", "1")) - postingsAll, _ := index.ExpandPostings(h.postings.Get("", "")) - - testutil.Equals(t, []uint64{s1.ref}, postingsA1) - testutil.Equals(t, []uint64{s2.ref}, postingsA2) - testutil.Equals(t, []uint64{s1.ref, s2.ref}, postingsB1) - testutil.Equals(t, []uint64{s1.ref, s2.ref}, postingsAll) - testutil.Assert(t, postingsB2 == nil, "") - testutil.Assert(t, postingsC1 == nil, "") - - testutil.Equals(t, map[string]struct{}{ - "": {}, // from 'all' postings list - "a": {}, - "b": {}, - "1": {}, - "2": {}, - }, h.symbols) - - testutil.Equals(t, map[string]stringset{ - "a": {"1": struct{}{}, "2": struct{}{}}, - "b": {"1": struct{}{}}, - "": {"": struct{}{}}, - }, h.values) -} - -// Validate various behaviors brought on by firstChunkID accounting for -// garbage collected chunks. -func TestMemSeries_truncateChunks(t *testing.T) { - s := newMemSeries(labels.FromStrings("a", "b"), 1, 2000) - - for i := 0; i < 4000; i += 5 { - ok, _ := s.append(int64(i), float64(i)) - testutil.Assert(t, ok == true, "sample append failed") - } - - // Check that truncate removes half of the chunks and afterwards - // that the ID of the last chunk still gives us the same chunk afterwards. - countBefore := len(s.chunks) - lastID := s.chunkID(countBefore - 1) - lastChunk := s.chunk(lastID) - - testutil.Assert(t, s.chunk(0) != nil, "") - testutil.Assert(t, lastChunk != nil, "") - - s.truncateChunksBefore(2000) - - testutil.Equals(t, int64(2000), s.chunks[0].minTime) - testutil.Assert(t, s.chunk(0) == nil, "first chunks not gone") - testutil.Equals(t, countBefore/2, len(s.chunks)) - testutil.Equals(t, lastChunk, s.chunk(lastID)) - - // Validate that the series' sample buffer is applied correctly to the last chunk - // after truncation. - it1 := s.iterator(s.chunkID(len(s.chunks) - 1)) - _, ok := it1.(*memSafeIterator) - testutil.Assert(t, ok == true, "") - - it2 := s.iterator(s.chunkID(len(s.chunks) - 2)) - _, ok = it2.(*memSafeIterator) - testutil.Assert(t, ok == false, "non-last chunk incorrectly wrapped with sample buffer") -} - -func TestHeadDeleteSeriesWithoutSamples(t *testing.T) { - entries := []interface{}{ - []RefSeries{ - {Ref: 10, Labels: labels.FromStrings("a", "1")}, - }, - []RefSample{}, - []RefSeries{ - {Ref: 50, Labels: labels.FromStrings("a", "2")}, - }, - []RefSample{ - {Ref: 50, T: 80, V: 1}, - {Ref: 50, T: 90, V: 1}, - }, - } - dir, err := ioutil.TempDir("", "test_delete_series") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - w, err := wal.New(nil, nil, dir) - testutil.Ok(t, err) - defer w.Close() - populateTestWAL(t, w, entries) - - head, err := NewHead(nil, nil, w, 1000) - testutil.Ok(t, err) - - testutil.Ok(t, head.Init(math.MinInt64)) - - testutil.Ok(t, head.Delete(0, 100, labels.NewEqualMatcher("a", "1"))) -} - -func TestHeadDeleteSimple(t *testing.T) { - buildSmpls := func(s []int64) []sample { - ss := make([]sample, 0, len(s)) - for _, t := range s { - ss = append(ss, sample{t: t, v: float64(t)}) - } - return ss - } - smplsAll := buildSmpls([]int64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) - lblDefault := labels.Label{"a", "b"} - - cases := []struct { - dranges Intervals - smplsExp []sample - }{ - { - dranges: Intervals{{0, 3}}, - smplsExp: buildSmpls([]int64{4, 5, 6, 7, 8, 9}), - }, - { - dranges: Intervals{{1, 3}}, - smplsExp: buildSmpls([]int64{0, 4, 5, 6, 7, 8, 9}), - }, - { - dranges: Intervals{{1, 3}, {4, 7}}, - smplsExp: buildSmpls([]int64{0, 8, 9}), - }, - { - dranges: Intervals{{1, 3}, {4, 700}}, - smplsExp: buildSmpls([]int64{0}), - }, - { // This case is to ensure that labels and symbols are deleted. - dranges: Intervals{{0, 9}}, - smplsExp: buildSmpls([]int64{}), - }, - } - -Outer: - for _, c := range cases { - dir, err := ioutil.TempDir("", "test_wal_reload") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - w, err := wal.New(nil, nil, path.Join(dir, "wal")) - testutil.Ok(t, err) - - head, err := NewHead(nil, nil, w, 1000) - testutil.Ok(t, err) - - app := head.Appender() - for _, smpl := range smplsAll { - _, err = app.Add(labels.Labels{lblDefault}, smpl.t, smpl.v) - testutil.Ok(t, err) - - } - testutil.Ok(t, app.Commit()) - - // Delete the ranges. - for _, r := range c.dranges { - testutil.Ok(t, head.Delete(r.Mint, r.Maxt, labels.NewEqualMatcher(lblDefault.Name, lblDefault.Value))) - } - - // Compare the samples for both heads - before and after the reload. - reloadedW, err := wal.New(nil, nil, w.Dir()) // Use a new wal to ensure deleted samples are gone even after a reload. - testutil.Ok(t, err) - reloadedHead, err := NewHead(nil, nil, reloadedW, 1000) - testutil.Ok(t, err) - testutil.Ok(t, reloadedHead.Init(0)) - for _, h := range []*Head{head, reloadedHead} { - indexr, err := h.Index() - testutil.Ok(t, err) - // Use an emptyTombstoneReader explicitly to get all the samples. - css, err := LookupChunkSeries(indexr, emptyTombstoneReader, labels.NewEqualMatcher(lblDefault.Name, lblDefault.Value)) - testutil.Ok(t, err) - - // Getting the actual samples. - actSamples := make([]sample, 0) - for css.Next() { - lblsAct, chkMetas, intv := css.At() - testutil.Equals(t, labels.Labels{lblDefault}, lblsAct) - testutil.Equals(t, 0, len(intv)) - - chunkr, err := h.Chunks() - testutil.Ok(t, err) - for _, meta := range chkMetas { - chk, err := chunkr.Chunk(meta.Ref) - testutil.Ok(t, err) - ii := chk.Iterator() - for ii.Next() { - t, v := ii.At() - actSamples = append(actSamples, sample{t: t, v: v}) - } - } - } - - testutil.Ok(t, css.Err()) - testutil.Equals(t, c.smplsExp, actSamples) - } - - // Compare the query results for both heads - before and after the reload. - expSeriesSet := newMockSeriesSet([]Series{ - newSeries(map[string]string{lblDefault.Name: lblDefault.Value}, func() []tsdbutil.Sample { - ss := make([]tsdbutil.Sample, 0, len(c.smplsExp)) - for _, s := range c.smplsExp { - ss = append(ss, s) - } - return ss - }(), - ), - }) - for _, h := range []*Head{head, reloadedHead} { - q, err := NewBlockQuerier(h, h.MinTime(), h.MaxTime()) - testutil.Ok(t, err) - actSeriesSet, err := q.Select(labels.NewEqualMatcher(lblDefault.Name, lblDefault.Value)) - testutil.Ok(t, err) - - lns, err := q.LabelNames() - testutil.Ok(t, err) - lvs, err := q.LabelValues(lblDefault.Name) - testutil.Ok(t, err) - // When all samples are deleted we expect that no labels should exist either. - if len(c.smplsExp) == 0 { - testutil.Equals(t, 0, len(lns)) - testutil.Equals(t, 0, len(lvs)) - testutil.Assert(t, actSeriesSet.Next() == false, "") - testutil.Ok(t, h.Close()) - continue - } else { - testutil.Equals(t, 1, len(lns)) - testutil.Equals(t, 1, len(lvs)) - testutil.Equals(t, lblDefault.Name, lns[0]) - testutil.Equals(t, lblDefault.Value, lvs[0]) - } - - for { - eok, rok := expSeriesSet.Next(), actSeriesSet.Next() - testutil.Equals(t, eok, rok) - - if !eok { - testutil.Ok(t, h.Close()) - continue Outer - } - expSeries := expSeriesSet.At() - actSeries := actSeriesSet.At() - - testutil.Equals(t, expSeries.Labels(), actSeries.Labels()) - - smplExp, errExp := expandSeriesIterator(expSeries.Iterator()) - smplRes, errRes := expandSeriesIterator(actSeries.Iterator()) - - testutil.Equals(t, errExp, errRes) - testutil.Equals(t, smplExp, smplRes) - } - } - } -} - -func TestDeleteUntilCurMax(t *testing.T) { - numSamples := int64(10) - hb, err := NewHead(nil, nil, nil, 1000000) - testutil.Ok(t, err) - defer hb.Close() - app := hb.Appender() - smpls := make([]float64, numSamples) - for i := int64(0); i < numSamples; i++ { - smpls[i] = rand.Float64() - _, err := app.Add(labels.Labels{{"a", "b"}}, i, smpls[i]) - testutil.Ok(t, err) - } - testutil.Ok(t, app.Commit()) - testutil.Ok(t, hb.Delete(0, 10000, labels.NewEqualMatcher("a", "b"))) - - // Test the series have been deleted. - q, err := NewBlockQuerier(hb, 0, 100000) - testutil.Ok(t, err) - res, err := q.Select(labels.NewEqualMatcher("a", "b")) - testutil.Ok(t, err) - testutil.Assert(t, !res.Next(), "series didn't get deleted") - - // Add again and test for presence. - app = hb.Appender() - _, err = app.Add(labels.Labels{{"a", "b"}}, 11, 1) - testutil.Ok(t, err) - testutil.Ok(t, app.Commit()) - q, err = NewBlockQuerier(hb, 0, 100000) - testutil.Ok(t, err) - res, err = q.Select(labels.NewEqualMatcher("a", "b")) - testutil.Ok(t, err) - testutil.Assert(t, res.Next(), "series don't exist") - exps := res.At() - it := exps.Iterator() - ressmpls, err := expandSeriesIterator(it) - testutil.Ok(t, err) - testutil.Equals(t, []tsdbutil.Sample{sample{11, 1}}, ressmpls) -} -func TestDelete_e2e(t *testing.T) { - numDatapoints := 1000 - numRanges := 1000 - timeInterval := int64(2) - // Create 8 series with 1000 data-points of different ranges, delete and run queries. - lbls := [][]labels.Label{ - { - {"a", "b"}, - {"instance", "localhost:9090"}, - {"job", "prometheus"}, - }, - { - {"a", "b"}, - {"instance", "127.0.0.1:9090"}, - {"job", "prometheus"}, - }, - { - {"a", "b"}, - {"instance", "127.0.0.1:9090"}, - {"job", "prom-k8s"}, - }, - { - {"a", "b"}, - {"instance", "localhost:9090"}, - {"job", "prom-k8s"}, - }, - { - {"a", "c"}, - {"instance", "localhost:9090"}, - {"job", "prometheus"}, - }, - { - {"a", "c"}, - {"instance", "127.0.0.1:9090"}, - {"job", "prometheus"}, - }, - { - {"a", "c"}, - {"instance", "127.0.0.1:9090"}, - {"job", "prom-k8s"}, - }, - { - {"a", "c"}, - {"instance", "localhost:9090"}, - {"job", "prom-k8s"}, - }, - } - seriesMap := map[string][]tsdbutil.Sample{} - for _, l := range lbls { - seriesMap[labels.New(l...).String()] = []tsdbutil.Sample{} - } - dir, _ := ioutil.TempDir("", "test") - defer os.RemoveAll(dir) - hb, err := NewHead(nil, nil, nil, 100000) - testutil.Ok(t, err) - defer hb.Close() - app := hb.Appender() - for _, l := range lbls { - ls := labels.New(l...) - series := []tsdbutil.Sample{} - ts := rand.Int63n(300) - for i := 0; i < numDatapoints; i++ { - v := rand.Float64() - _, err := app.Add(ls, ts, v) - testutil.Ok(t, err) - series = append(series, sample{ts, v}) - ts += rand.Int63n(timeInterval) + 1 - } - seriesMap[labels.New(l...).String()] = series - } - testutil.Ok(t, app.Commit()) - // Delete a time-range from each-selector. - dels := []struct { - ms []labels.Matcher - drange Intervals - }{ - { - ms: []labels.Matcher{labels.NewEqualMatcher("a", "b")}, - drange: Intervals{{300, 500}, {600, 670}}, - }, - { - ms: []labels.Matcher{ - labels.NewEqualMatcher("a", "b"), - labels.NewEqualMatcher("job", "prom-k8s"), - }, - drange: Intervals{{300, 500}, {100, 670}}, - }, - { - ms: []labels.Matcher{ - labels.NewEqualMatcher("a", "c"), - labels.NewEqualMatcher("instance", "localhost:9090"), - labels.NewEqualMatcher("job", "prometheus"), - }, - drange: Intervals{{300, 400}, {100, 6700}}, - }, - // TODO: Add Regexp Matchers. - } - for _, del := range dels { - for _, r := range del.drange { - testutil.Ok(t, hb.Delete(r.Mint, r.Maxt, del.ms...)) - } - matched := labels.Slice{} - for _, ls := range lbls { - s := labels.Selector(del.ms) - if s.Matches(ls) { - matched = append(matched, ls) - } - } - sort.Sort(matched) - for i := 0; i < numRanges; i++ { - q, err := NewBlockQuerier(hb, 0, 100000) - testutil.Ok(t, err) - defer q.Close() - ss, err := q.Select(del.ms...) - testutil.Ok(t, err) - // Build the mockSeriesSet. - matchedSeries := make([]Series, 0, len(matched)) - for _, m := range matched { - smpls := seriesMap[m.String()] - smpls = deletedSamples(smpls, del.drange) - // Only append those series for which samples exist as mockSeriesSet - // doesn't skip series with no samples. - // TODO: But sometimes SeriesSet returns an empty SeriesIterator - if len(smpls) > 0 { - matchedSeries = append(matchedSeries, newSeries( - m.Map(), - smpls, - )) - } - } - expSs := newMockSeriesSet(matchedSeries) - // Compare both SeriesSets. - for { - eok, rok := expSs.Next(), ss.Next() - // Skip a series if iterator is empty. - if rok { - for !ss.At().Iterator().Next() { - rok = ss.Next() - if !rok { - break - } - } - } - testutil.Equals(t, eok, rok) - if !eok { - break - } - sexp := expSs.At() - sres := ss.At() - testutil.Equals(t, sexp.Labels(), sres.Labels()) - smplExp, errExp := expandSeriesIterator(sexp.Iterator()) - smplRes, errRes := expandSeriesIterator(sres.Iterator()) - testutil.Equals(t, errExp, errRes) - testutil.Equals(t, smplExp, smplRes) - } - } - } -} - -func boundedSamples(full []tsdbutil.Sample, mint, maxt int64) []tsdbutil.Sample { - for len(full) > 0 { - if full[0].T() >= mint { - break - } - full = full[1:] - } - for i, s := range full { - // labels.Labelinate on the first sample larger than maxt. - if s.T() > maxt { - return full[:i] - } - } - // maxt is after highest sample. - return full -} - -func deletedSamples(full []tsdbutil.Sample, dranges Intervals) []tsdbutil.Sample { - ds := make([]tsdbutil.Sample, 0, len(full)) -Outer: - for _, s := range full { - for _, r := range dranges { - if r.inBounds(s.T()) { - continue Outer - } - } - ds = append(ds, s) - } - - return ds -} - -func TestComputeChunkEndTime(t *testing.T) { - cases := []struct { - start, cur, max int64 - res int64 - }{ - { - start: 0, - cur: 250, - max: 1000, - res: 1000, - }, - { - start: 100, - cur: 200, - max: 1000, - res: 550, - }, - // Case where we fit floored 0 chunks. Must catch division by 0 - // and default to maximum time. - { - start: 0, - cur: 500, - max: 1000, - res: 1000, - }, - // Catch division by zero for cur == start. Strictly not a possible case. - { - start: 100, - cur: 100, - max: 1000, - res: 104, - }, - } - - for _, c := range cases { - got := computeChunkEndTime(c.start, c.cur, c.max) - if got != c.res { - t.Errorf("expected %d for (start: %d, cur: %d, max: %d), got %d", c.res, c.start, c.cur, c.max, got) - } - } -} - -func TestMemSeries_append(t *testing.T) { - s := newMemSeries(labels.Labels{}, 1, 500) - - // Add first two samples at the very end of a chunk range and the next two - // on and after it. - // New chunk must correctly be cut at 1000. - ok, chunkCreated := s.append(998, 1) - testutil.Assert(t, ok, "append failed") - testutil.Assert(t, chunkCreated, "first sample created chunk") - - ok, chunkCreated = s.append(999, 2) - testutil.Assert(t, ok, "append failed") - testutil.Assert(t, !chunkCreated, "second sample should use same chunk") - - ok, chunkCreated = s.append(1000, 3) - testutil.Assert(t, ok, "append failed") - testutil.Assert(t, chunkCreated, "expected new chunk on boundary") - - ok, chunkCreated = s.append(1001, 4) - testutil.Assert(t, ok, "append failed") - testutil.Assert(t, !chunkCreated, "second sample should use same chunk") - - testutil.Assert(t, s.chunks[0].minTime == 998 && s.chunks[0].maxTime == 999, "wrong chunk range") - testutil.Assert(t, s.chunks[1].minTime == 1000 && s.chunks[1].maxTime == 1001, "wrong chunk range") - - // Fill the range [1000,2000) with many samples. Intermediate chunks should be cut - // at approximately 120 samples per chunk. - for i := 1; i < 1000; i++ { - ok, _ := s.append(1001+int64(i), float64(i)) - testutil.Assert(t, ok, "append failed") - } - - testutil.Assert(t, len(s.chunks) > 7, "expected intermediate chunks") - - // All chunks but the first and last should now be moderately full. - for i, c := range s.chunks[1 : len(s.chunks)-1] { - testutil.Assert(t, c.chunk.NumSamples() > 100, "unexpected small chunk %d of length %d", i, c.chunk.NumSamples()) - } -} - -func TestGCChunkAccess(t *testing.T) { - // Put a chunk, select it. GC it and then access it. - h, err := NewHead(nil, nil, nil, 1000) - testutil.Ok(t, err) - defer h.Close() - - h.initTime(0) - - s, _ := h.getOrCreate(1, labels.FromStrings("a", "1")) - s.chunks = []*memChunk{ - {minTime: 0, maxTime: 999}, - {minTime: 1000, maxTime: 1999}, - } - - idx := h.indexRange(0, 1500) - var ( - lset labels.Labels - chunks []chunks.Meta - ) - testutil.Ok(t, idx.Series(1, &lset, &chunks)) - - testutil.Equals(t, labels.Labels{{ - Name: "a", Value: "1", - }}, lset) - testutil.Equals(t, 2, len(chunks)) - - cr := h.chunksRange(0, 1500) - _, err = cr.Chunk(chunks[0].Ref) - testutil.Ok(t, err) - _, err = cr.Chunk(chunks[1].Ref) - testutil.Ok(t, err) - - h.Truncate(1500) // Remove a chunk. - - _, err = cr.Chunk(chunks[0].Ref) - testutil.Equals(t, ErrNotFound, err) - _, err = cr.Chunk(chunks[1].Ref) - testutil.Ok(t, err) -} - -func TestGCSeriesAccess(t *testing.T) { - // Put a series, select it. GC it and then access it. - h, err := NewHead(nil, nil, nil, 1000) - testutil.Ok(t, err) - defer h.Close() - - h.initTime(0) - - s, _ := h.getOrCreate(1, labels.FromStrings("a", "1")) - s.chunks = []*memChunk{ - {minTime: 0, maxTime: 999}, - {minTime: 1000, maxTime: 1999}, - } - - idx := h.indexRange(0, 2000) - var ( - lset labels.Labels - chunks []chunks.Meta - ) - testutil.Ok(t, idx.Series(1, &lset, &chunks)) - - testutil.Equals(t, labels.Labels{{ - Name: "a", Value: "1", - }}, lset) - testutil.Equals(t, 2, len(chunks)) - - cr := h.chunksRange(0, 2000) - _, err = cr.Chunk(chunks[0].Ref) - testutil.Ok(t, err) - _, err = cr.Chunk(chunks[1].Ref) - testutil.Ok(t, err) - - h.Truncate(2000) // Remove the series. - - testutil.Equals(t, (*memSeries)(nil), h.series.getByID(1)) - - _, err = cr.Chunk(chunks[0].Ref) - testutil.Equals(t, ErrNotFound, err) - _, err = cr.Chunk(chunks[1].Ref) - testutil.Equals(t, ErrNotFound, err) -} - -func TestUncommittedSamplesNotLostOnTruncate(t *testing.T) { - h, err := NewHead(nil, nil, nil, 1000) - testutil.Ok(t, err) - defer h.Close() - - h.initTime(0) - - app := h.appender() - lset := labels.FromStrings("a", "1") - _, err = app.Add(lset, 2100, 1) - testutil.Ok(t, err) - - testutil.Ok(t, h.Truncate(2000)) - testutil.Assert(t, nil != h.series.getByHash(lset.Hash(), lset), "series should not have been garbage collected") - - testutil.Ok(t, app.Commit()) - - q, err := NewBlockQuerier(h, 1500, 2500) - testutil.Ok(t, err) - defer q.Close() - - ss, err := q.Select(labels.NewEqualMatcher("a", "1")) - testutil.Ok(t, err) - - testutil.Equals(t, true, ss.Next()) -} - -func TestRemoveSeriesAfterRollbackAndTruncate(t *testing.T) { - h, err := NewHead(nil, nil, nil, 1000) - testutil.Ok(t, err) - defer h.Close() - - h.initTime(0) - - app := h.appender() - lset := labels.FromStrings("a", "1") - _, err = app.Add(lset, 2100, 1) - testutil.Ok(t, err) - - testutil.Ok(t, h.Truncate(2000)) - testutil.Assert(t, nil != h.series.getByHash(lset.Hash(), lset), "series should not have been garbage collected") - - testutil.Ok(t, app.Rollback()) - - q, err := NewBlockQuerier(h, 1500, 2500) - testutil.Ok(t, err) - defer q.Close() - - ss, err := q.Select(labels.NewEqualMatcher("a", "1")) - testutil.Ok(t, err) - - testutil.Equals(t, false, ss.Next()) - - // Truncate again, this time the series should be deleted - testutil.Ok(t, h.Truncate(2050)) - testutil.Equals(t, (*memSeries)(nil), h.series.getByHash(lset.Hash(), lset)) -} - -func TestHead_LogRollback(t *testing.T) { - dir, err := ioutil.TempDir("", "wal_rollback") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - w, err := wal.New(nil, nil, dir) - testutil.Ok(t, err) - defer w.Close() - h, err := NewHead(nil, nil, w, 1000) - testutil.Ok(t, err) - - app := h.Appender() - _, err = app.Add(labels.FromStrings("a", "b"), 1, 2) - testutil.Ok(t, err) - - testutil.Ok(t, app.Rollback()) - recs := readTestWAL(t, w.Dir()) - - testutil.Equals(t, 1, len(recs)) - - series, ok := recs[0].([]RefSeries) - testutil.Assert(t, ok, "expected series record but got %+v", recs[0]) - testutil.Equals(t, []RefSeries{{Ref: 1, Labels: labels.FromStrings("a", "b")}}, series) -} - -func TestWalRepair(t *testing.T) { - var enc RecordEncoder - for name, test := range map[string]struct { - corrFunc func(rec []byte) []byte // Func that applies the corruption to a record. - rec []byte - totalRecs int - expRecs int - }{ - "invalid_record": { - func(rec []byte) []byte { - rec[0] = byte(RecordInvalid) - return rec - }, - enc.Series([]RefSeries{{Ref: 1, Labels: labels.FromStrings("a", "b")}}, []byte{}), - 9, - 5, - }, - "decode_series": { - func(rec []byte) []byte { - return rec[:3] - }, - enc.Series([]RefSeries{{Ref: 1, Labels: labels.FromStrings("a", "b")}}, []byte{}), - 9, - 5, - }, - "decode_samples": { - func(rec []byte) []byte { - return rec[:3] - }, - enc.Samples([]RefSample{{Ref: 0, T: 99, V: 1}}, []byte{}), - 9, - 5, - }, - "decode_tombstone": { - func(rec []byte) []byte { - return rec[:3] - }, - enc.Tombstones([]Stone{{ref: 1, intervals: Intervals{}}}, []byte{}), - 9, - 5, - }, - } { - t.Run(name, func(t *testing.T) { - dir, err := ioutil.TempDir("", "wal_head_repair") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - w, err := wal.New(nil, nil, dir) - testutil.Ok(t, err) - defer w.Close() - - for i := 1; i <= test.totalRecs; i++ { - // At this point insert a corrupted record. - if i-1 == test.expRecs { - testutil.Ok(t, w.Log(test.corrFunc(test.rec))) - continue - } - testutil.Ok(t, w.Log(test.rec)) - } - - h, err := NewHead(nil, nil, w, 1) - testutil.Ok(t, err) - testutil.Equals(t, 0.0, prom_testutil.ToFloat64(h.metrics.walCorruptionsTotal)) - testutil.Ok(t, h.Init(math.MinInt64)) - testutil.Equals(t, 1.0, prom_testutil.ToFloat64(h.metrics.walCorruptionsTotal)) - - sr, err := wal.NewSegmentsReader(dir) - testutil.Ok(t, err) - defer sr.Close() - r := wal.NewReader(sr) - - var actRec int - for r.Next() { - actRec++ - } - testutil.Ok(t, r.Err()) - testutil.Equals(t, test.expRecs, actRec, "Wrong number of intact records") - }) - } - -} diff --git a/vendor/github.com/prometheus/tsdb/index/encoding_helpers.go b/vendor/github.com/prometheus/tsdb/index/encoding_helpers.go new file mode 100644 index 000000000..9104f1cb5 --- /dev/null +++ b/vendor/github.com/prometheus/tsdb/index/encoding_helpers.go @@ -0,0 +1,248 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package index + +import ( + "encoding/binary" + "hash" + "hash/crc32" + "unsafe" + + "github.com/pkg/errors" +) + +// enbuf is a helper type to populate a byte slice with various types. +type encbuf struct { + b []byte + c [binary.MaxVarintLen64]byte +} + +func (e *encbuf) reset() { e.b = e.b[:0] } +func (e *encbuf) get() []byte { return e.b } +func (e *encbuf) len() int { return len(e.b) } + +func (e *encbuf) putString(s string) { e.b = append(e.b, s...) } +func (e *encbuf) putBytes(b []byte) { e.b = append(e.b, b...) } +func (e *encbuf) putByte(c byte) { e.b = append(e.b, c) } + +func (e *encbuf) putBE32int(x int) { e.putBE32(uint32(x)) } +func (e *encbuf) putBE64int(x int) { e.putBE64(uint64(x)) } +func (e *encbuf) putBE64int64(x int64) { e.putBE64(uint64(x)) } +func (e *encbuf) putUvarint32(x uint32) { e.putUvarint64(uint64(x)) } +func (e *encbuf) putUvarint(x int) { e.putUvarint64(uint64(x)) } + +func (e *encbuf) putBE32(x uint32) { + binary.BigEndian.PutUint32(e.c[:], x) + e.b = append(e.b, e.c[:4]...) +} + +func (e *encbuf) putBE64(x uint64) { + binary.BigEndian.PutUint64(e.c[:], x) + e.b = append(e.b, e.c[:8]...) +} + +func (e *encbuf) putUvarint64(x uint64) { + n := binary.PutUvarint(e.c[:], x) + e.b = append(e.b, e.c[:n]...) +} + +func (e *encbuf) putVarint64(x int64) { + n := binary.PutVarint(e.c[:], x) + e.b = append(e.b, e.c[:n]...) +} + +// putVarintStr writes a string to the buffer prefixed by its varint length (in bytes!). +func (e *encbuf) putUvarintStr(s string) { + b := *(*[]byte)(unsafe.Pointer(&s)) + e.putUvarint(len(b)) + e.putString(s) +} + +// putHash appends a hash over the buffers current contents to the buffer. +func (e *encbuf) putHash(h hash.Hash) { + h.Reset() + _, err := h.Write(e.b) + if err != nil { + panic(err) // The CRC32 implementation does not error + } + e.b = h.Sum(e.b) +} + +// decbuf provides safe methods to extract data from a byte slice. It does all +// necessary bounds checking and advancing of the byte slice. +// Several datums can be extracted without checking for errors. However, before using +// any datum, the err() method must be checked. +type decbuf struct { + b []byte + e error +} + +// newDecbufAt returns a new decoding buffer. It expects the first 4 bytes +// after offset to hold the big endian encoded content length, followed by the contents and the expected +// checksum. +func newDecbufAt(bs ByteSlice, off int) decbuf { + if bs.Len() < off+4 { + return decbuf{e: errInvalidSize} + } + b := bs.Range(off, off+4) + l := int(binary.BigEndian.Uint32(b)) + + if bs.Len() < off+4+l+4 { + return decbuf{e: errInvalidSize} + } + + // Load bytes holding the contents plus a CRC32 checksum. + b = bs.Range(off+4, off+4+l+4) + dec := decbuf{b: b[:len(b)-4]} + + if exp := binary.BigEndian.Uint32(b[len(b)-4:]); dec.crc32() != exp { + return decbuf{e: errInvalidChecksum} + } + return dec +} + +// decbufUvarintAt returns a new decoding buffer. It expects the first bytes +// after offset to hold the uvarint-encoded buffers length, followed by the contents and the expected +// checksum. +func newDecbufUvarintAt(bs ByteSlice, off int) decbuf { + // We never have to access this method at the far end of the byte slice. Thus just checking + // against the MaxVarintLen32 is sufficient. + if bs.Len() < off+binary.MaxVarintLen32 { + return decbuf{e: errInvalidSize} + } + b := bs.Range(off, off+binary.MaxVarintLen32) + + l, n := binary.Uvarint(b) + if n <= 0 || n > binary.MaxVarintLen32 { + return decbuf{e: errors.Errorf("invalid uvarint %d", n)} + } + + if bs.Len() < off+n+int(l)+4 { + return decbuf{e: errInvalidSize} + } + + // Load bytes holding the contents plus a CRC32 checksum. + b = bs.Range(off+n, off+n+int(l)+4) + dec := decbuf{b: b[:len(b)-4]} + + if dec.crc32() != binary.BigEndian.Uint32(b[len(b)-4:]) { + return decbuf{e: errInvalidChecksum} + } + return dec +} + +func (d *decbuf) uvarint() int { return int(d.uvarint64()) } +func (d *decbuf) uvarint32() uint32 { return uint32(d.uvarint64()) } +func (d *decbuf) be32int() int { return int(d.be32()) } +func (d *decbuf) be64int64() int64 { return int64(d.be64()) } + +// crc32 returns a CRC32 checksum over the remaining bytes. +func (d *decbuf) crc32() uint32 { + return crc32.Checksum(d.b, castagnoliTable) +} + +func (d *decbuf) uvarintStr() string { + l := d.uvarint64() + if d.e != nil { + return "" + } + if len(d.b) < int(l) { + d.e = errInvalidSize + return "" + } + s := string(d.b[:l]) + d.b = d.b[l:] + return s +} + +func (d *decbuf) varint64() int64 { + if d.e != nil { + return 0 + } + x, n := binary.Varint(d.b) + if n < 1 { + d.e = errInvalidSize + return 0 + } + d.b = d.b[n:] + return x +} + +func (d *decbuf) uvarint64() uint64 { + if d.e != nil { + return 0 + } + x, n := binary.Uvarint(d.b) + if n < 1 { + d.e = errInvalidSize + return 0 + } + d.b = d.b[n:] + return x +} + +func (d *decbuf) be64() uint64 { + if d.e != nil { + return 0 + } + if len(d.b) < 4 { + d.e = errInvalidSize + return 0 + } + x := binary.BigEndian.Uint64(d.b) + d.b = d.b[8:] + return x +} + +func (d *decbuf) be32() uint32 { + if d.e != nil { + return 0 + } + if len(d.b) < 4 { + d.e = errInvalidSize + return 0 + } + x := binary.BigEndian.Uint32(d.b) + d.b = d.b[4:] + return x +} + +func (d *decbuf) byte() byte { + if d.e != nil { + return 0 + } + if len(d.b) < 1 { + d.e = errInvalidSize + return 0 + } + x := d.b[0] + d.b = d.b[1:] + return x +} + +func (d *decbuf) decbuf(l int) decbuf { + if d.e != nil { + return decbuf{e: d.e} + } + if l > len(d.b) { + return decbuf{e: errInvalidSize} + } + r := decbuf{b: d.b[:l]} + d.b = d.b[l:] + return r +} + +func (d *decbuf) err() error { return d.e } +func (d *decbuf) len() int { return len(d.b) } +func (d *decbuf) get() []byte { return d.b } diff --git a/vendor/github.com/prometheus/tsdb/index/index.go b/vendor/github.com/prometheus/tsdb/index/index.go index 580291a71..74e08d465 100644 --- a/vendor/github.com/prometheus/tsdb/index/index.go +++ b/vendor/github.com/prometheus/tsdb/index/index.go @@ -16,6 +16,7 @@ package index import ( "bufio" "encoding/binary" + "fmt" "hash" "hash/crc32" "io" @@ -28,7 +29,6 @@ import ( "github.com/pkg/errors" "github.com/prometheus/tsdb/chunks" - "github.com/prometheus/tsdb/encoding" "github.com/prometheus/tsdb/fileutil" "github.com/prometheus/tsdb/labels" ) @@ -45,8 +45,6 @@ const ( FormatV2 = 2 labelNameSeperator = "\xff" - - indexFilename = "index" ) type indexWriterSeries struct { @@ -119,8 +117,8 @@ type Writer struct { stage indexWriterStage // Reusable memory. - buf1 encoding.Encbuf - buf2 encoding.Encbuf + buf1 encbuf + buf2 encbuf uint32s []uint32 symbols map[string]uint32 // symbol offsets @@ -149,28 +147,28 @@ type TOC struct { // NewTOCFromByteSlice return parsed TOC from given index byte slice. func NewTOCFromByteSlice(bs ByteSlice) (*TOC, error) { if bs.Len() < indexTOCLen { - return nil, encoding.ErrInvalidSize + return nil, errInvalidSize } b := bs.Range(bs.Len()-indexTOCLen, bs.Len()) expCRC := binary.BigEndian.Uint32(b[len(b)-4:]) - d := encoding.Decbuf{B: b[:len(b)-4]} + d := decbuf{b: b[:len(b)-4]} - if d.Crc32(castagnoliTable) != expCRC { - return nil, errors.Wrap(encoding.ErrInvalidChecksum, "read TOC") + if d.crc32() != expCRC { + return nil, errors.Wrap(errInvalidChecksum, "read TOC") } - if err := d.Err(); err != nil { + if err := d.err(); err != nil { return nil, err } return &TOC{ - Symbols: d.Be64(), - Series: d.Be64(), - LabelIndices: d.Be64(), - LabelIndicesTable: d.Be64(), - Postings: d.Be64(), - PostingsTable: d.Be64(), + Symbols: d.be64(), + Series: d.be64(), + LabelIndices: d.be64(), + LabelIndicesTable: d.be64(), + Postings: d.be64(), + PostingsTable: d.be64(), }, nil } @@ -203,8 +201,8 @@ func NewWriter(fn string) (*Writer, error) { stage: idxStageNone, // Reusable memory. - buf1: encoding.Encbuf{B: make([]byte, 0, 1<<22)}, - buf2: encoding.Encbuf{B: make([]byte, 0, 1<<22)}, + buf1: encbuf{b: make([]byte, 0, 1<<22)}, + buf2: encbuf{b: make([]byte, 0, 1<<22)}, uint32s: make([]uint32, 0, 1<<15), // Caches. @@ -288,11 +286,11 @@ func (w *Writer) ensureStage(s indexWriterStage) error { } func (w *Writer) writeMeta() error { - w.buf1.Reset() - w.buf1.PutBE32(MagicIndex) - w.buf1.PutByte(FormatV2) + w.buf1.reset() + w.buf1.putBE32(MagicIndex) + w.buf1.putByte(FormatV2) - return w.write(w.buf1.Get()) + return w.write(w.buf1.get()) } // AddSeries adds the series one at a time along with its chunks. @@ -318,8 +316,8 @@ func (w *Writer) AddSeries(ref uint64, lset labels.Labels, chunks ...chunks.Meta } w.seriesOffsets[ref] = w.pos / 16 - w.buf2.Reset() - w.buf2.PutUvarint(len(lset)) + w.buf2.reset() + w.buf2.putUvarint(len(lset)) for _, l := range lset { // here we have an index for the symbol file if v2, otherwise it's an offset @@ -327,41 +325,41 @@ func (w *Writer) AddSeries(ref uint64, lset labels.Labels, chunks ...chunks.Meta if !ok { return errors.Errorf("symbol entry for %q does not exist", l.Name) } - w.buf2.PutUvarint32(index) + w.buf2.putUvarint32(index) index, ok = w.symbols[l.Value] if !ok { return errors.Errorf("symbol entry for %q does not exist", l.Value) } - w.buf2.PutUvarint32(index) + w.buf2.putUvarint32(index) } - w.buf2.PutUvarint(len(chunks)) + w.buf2.putUvarint(len(chunks)) if len(chunks) > 0 { c := chunks[0] - w.buf2.PutVarint64(c.MinTime) - w.buf2.PutUvarint64(uint64(c.MaxTime - c.MinTime)) - w.buf2.PutUvarint64(c.Ref) + w.buf2.putVarint64(c.MinTime) + w.buf2.putUvarint64(uint64(c.MaxTime - c.MinTime)) + w.buf2.putUvarint64(c.Ref) t0 := c.MaxTime ref0 := int64(c.Ref) for _, c := range chunks[1:] { - w.buf2.PutUvarint64(uint64(c.MinTime - t0)) - w.buf2.PutUvarint64(uint64(c.MaxTime - c.MinTime)) + w.buf2.putUvarint64(uint64(c.MinTime - t0)) + w.buf2.putUvarint64(uint64(c.MaxTime - c.MinTime)) t0 = c.MaxTime - w.buf2.PutVarint64(int64(c.Ref) - ref0) + w.buf2.putVarint64(int64(c.Ref) - ref0) ref0 = int64(c.Ref) } } - w.buf1.Reset() - w.buf1.PutUvarint(w.buf2.Len()) + w.buf1.reset() + w.buf1.putUvarint(w.buf2.len()) - w.buf2.PutHash(w.crc32) + w.buf2.putHash(w.crc32) - if err := w.write(w.buf1.Get(), w.buf2.Get()); err != nil { + if err := w.write(w.buf1.get(), w.buf2.get()); err != nil { return errors.Wrap(err, "write series data") } @@ -382,22 +380,22 @@ func (w *Writer) AddSymbols(sym map[string]struct{}) error { } sort.Strings(symbols) - w.buf1.Reset() - w.buf2.Reset() + w.buf1.reset() + w.buf2.reset() - w.buf2.PutBE32int(len(symbols)) + w.buf2.putBE32int(len(symbols)) w.symbols = make(map[string]uint32, len(symbols)) for index, s := range symbols { w.symbols[s] = uint32(index) - w.buf2.PutUvarintStr(s) + w.buf2.putUvarintStr(s) } - w.buf1.PutBE32int(w.buf2.Len()) - w.buf2.PutHash(w.crc32) + w.buf1.putBE32int(w.buf2.len()) + w.buf2.putHash(w.crc32) - err := w.write(w.buf1.Get(), w.buf2.Get()) + err := w.write(w.buf1.get(), w.buf2.get()) return errors.Wrap(err, "write symbols") } @@ -425,9 +423,9 @@ func (w *Writer) WriteLabelIndex(names []string, values []string) error { offset: w.pos, }) - w.buf2.Reset() - w.buf2.PutBE32int(len(names)) - w.buf2.PutBE32int(valt.Len()) + w.buf2.reset() + w.buf2.putBE32int(len(names)) + w.buf2.putBE32int(valt.Len()) // here we have an index for the symbol file if v2, otherwise it's an offset for _, v := range valt.entries { @@ -435,53 +433,53 @@ func (w *Writer) WriteLabelIndex(names []string, values []string) error { if !ok { return errors.Errorf("symbol entry for %q does not exist", v) } - w.buf2.PutBE32(index) + w.buf2.putBE32(index) } - w.buf1.Reset() - w.buf1.PutBE32int(w.buf2.Len()) + w.buf1.reset() + w.buf1.putBE32int(w.buf2.len()) - w.buf2.PutHash(w.crc32) + w.buf2.putHash(w.crc32) - err = w.write(w.buf1.Get(), w.buf2.Get()) + err = w.write(w.buf1.get(), w.buf2.get()) return errors.Wrap(err, "write label index") } // writeOffsetTable writes a sequence of readable hash entries. func (w *Writer) writeOffsetTable(entries []hashEntry) error { - w.buf2.Reset() - w.buf2.PutBE32int(len(entries)) + w.buf2.reset() + w.buf2.putBE32int(len(entries)) for _, e := range entries { - w.buf2.PutUvarint(len(e.keys)) + w.buf2.putUvarint(len(e.keys)) for _, k := range e.keys { - w.buf2.PutUvarintStr(k) + w.buf2.putUvarintStr(k) } - w.buf2.PutUvarint64(e.offset) + w.buf2.putUvarint64(e.offset) } - w.buf1.Reset() - w.buf1.PutBE32int(w.buf2.Len()) - w.buf2.PutHash(w.crc32) + w.buf1.reset() + w.buf1.putBE32int(w.buf2.len()) + w.buf2.putHash(w.crc32) - return w.write(w.buf1.Get(), w.buf2.Get()) + return w.write(w.buf1.get(), w.buf2.get()) } const indexTOCLen = 6*8 + 4 func (w *Writer) writeTOC() error { - w.buf1.Reset() + w.buf1.reset() - w.buf1.PutBE64(w.toc.Symbols) - w.buf1.PutBE64(w.toc.Series) - w.buf1.PutBE64(w.toc.LabelIndices) - w.buf1.PutBE64(w.toc.LabelIndicesTable) - w.buf1.PutBE64(w.toc.Postings) - w.buf1.PutBE64(w.toc.PostingsTable) + w.buf1.putBE64(w.toc.Symbols) + w.buf1.putBE64(w.toc.Series) + w.buf1.putBE64(w.toc.LabelIndices) + w.buf1.putBE64(w.toc.LabelIndicesTable) + w.buf1.putBE64(w.toc.Postings) + w.buf1.putBE64(w.toc.PostingsTable) - w.buf1.PutHash(w.crc32) + w.buf1.putHash(w.crc32) - return w.write(w.buf1.Get()) + return w.write(w.buf1.get()) } func (w *Writer) WritePostings(name, value string, it Postings) error { @@ -519,20 +517,20 @@ func (w *Writer) WritePostings(name, value string, it Postings) error { } sort.Sort(uint32slice(refs)) - w.buf2.Reset() - w.buf2.PutBE32int(len(refs)) + w.buf2.reset() + w.buf2.putBE32int(len(refs)) for _, r := range refs { - w.buf2.PutBE32(r) + w.buf2.putBE32(r) } w.uint32s = refs - w.buf1.Reset() - w.buf1.PutBE32int(w.buf2.Len()) + w.buf1.reset() + w.buf1.putBE32int(w.buf2.len()) - w.buf2.PutHash(w.crc32) + w.buf2.putHash(w.crc32) - err := w.write(w.buf1.Get(), w.buf2.Get()) + err := w.write(w.buf1.get(), w.buf2.get()) return errors.Wrap(err, "write postings") } @@ -593,6 +591,11 @@ type Reader struct { version int } +var ( + errInvalidSize = fmt.Errorf("invalid size") + errInvalidChecksum = fmt.Errorf("invalid checksum") +) + // ByteSlice abstracts a byte slice. type ByteSlice interface { Len() int @@ -638,7 +641,7 @@ func newReader(b ByteSlice, c io.Closer) (*Reader, error) { // Verify header. if r.b.Len() < HeaderLen { - return nil, errors.Wrap(encoding.ErrInvalidSize, "index header") + return nil, errors.Wrap(errInvalidSize, "index header") } if m := binary.BigEndian.Uint32(r.b.Range(0, 4)); m != MagicIndex { return nil, errors.Errorf("invalid magic number %x", m) @@ -719,13 +722,13 @@ func (r *Reader) PostingsRanges() (map[labels.Label]Range, error) { for k, e := range r.postings { for v, start := range e { - d := encoding.NewDecbufAt(r.b, int(start), castagnoliTable) - if d.Err() != nil { - return nil, d.Err() + d := newDecbufAt(r.b, int(start)) + if d.err() != nil { + return nil, d.err() } m[labels.Label{Name: k, Value: v}] = Range{ Start: int64(start) + 4, - End: int64(start) + 4 + int64(d.Len()), + End: int64(start) + 4 + int64(d.len()), } } } @@ -739,49 +742,49 @@ func ReadSymbols(bs ByteSlice, version int, off int) ([]string, map[uint32]strin if off == 0 { return nil, nil, nil } - d := encoding.NewDecbufAt(bs, off, castagnoliTable) + d := newDecbufAt(bs, off) var ( - origLen = d.Len() - cnt = d.Be32int() + origLen = d.len() + cnt = d.be32int() basePos = uint32(off) + 4 - nextPos = basePos + uint32(origLen-d.Len()) + nextPos = basePos + uint32(origLen-d.len()) symbolSlice []string symbols = map[uint32]string{} ) - if version == FormatV2 { + if version == 2 { symbolSlice = make([]string, 0, cnt) } - for d.Err() == nil && d.Len() > 0 && cnt > 0 { - s := d.UvarintStr() + for d.err() == nil && d.len() > 0 && cnt > 0 { + s := d.uvarintStr() if version == FormatV2 { symbolSlice = append(symbolSlice, s) } else { symbols[nextPos] = s - nextPos = basePos + uint32(origLen-d.Len()) + nextPos = basePos + uint32(origLen-d.len()) } cnt-- } - return symbolSlice, symbols, errors.Wrap(d.Err(), "read symbols") + return symbolSlice, symbols, errors.Wrap(d.err(), "read symbols") } // ReadOffsetTable reads an offset table and at the given position calls f for each // found entry. If f returns an error it stops decoding and returns the received error. func ReadOffsetTable(bs ByteSlice, off uint64, f func([]string, uint64) error) error { - d := encoding.NewDecbufAt(bs, int(off), castagnoliTable) - cnt := d.Be32() + d := newDecbufAt(bs, int(off)) + cnt := d.be32() - for d.Err() == nil && d.Len() > 0 && cnt > 0 { - keyCount := d.Uvarint() + for d.err() == nil && d.len() > 0 && cnt > 0 { + keyCount := d.uvarint() keys := make([]string, 0, keyCount) for i := 0; i < keyCount; i++ { - keys = append(keys, d.UvarintStr()) + keys = append(keys, d.uvarintStr()) } - o := d.Uvarint64() - if d.Err() != nil { + o := d.uvarint64() + if d.err() != nil { break } if err := f(keys, o); err != nil { @@ -789,7 +792,7 @@ func ReadOffsetTable(bs ByteSlice, off uint64, f func([]string, uint64) error) e } cnt-- } - return d.Err() + return d.err() } // Close the reader and its underlying resources. @@ -838,17 +841,17 @@ func (r *Reader) LabelValues(names ...string) (StringTuples, error) { //return nil, fmt.Errorf("label index doesn't exist") } - d := encoding.NewDecbufAt(r.b, int(off), castagnoliTable) + d := newDecbufAt(r.b, int(off)) - nc := d.Be32int() - d.Be32() // consume unused value entry count. + nc := d.be32int() + d.be32() // consume unused value entry count. - if d.Err() != nil { - return nil, errors.Wrap(d.Err(), "read label value index") + if d.err() != nil { + return nil, errors.Wrap(d.err(), "read label value index") } st := &serializedStringTuples{ idsCount: nc, - idsBytes: d.Get(), + idsBytes: d.get(), lookup: r.lookupSymbol, } return st, nil @@ -877,11 +880,11 @@ func (r *Reader) Series(id uint64, lbls *labels.Labels, chks *[]chunks.Meta) err if r.version == FormatV2 { offset = id * 16 } - d := encoding.NewDecbufUvarintAt(r.b, int(offset), castagnoliTable) - if d.Err() != nil { - return d.Err() + d := newDecbufUvarintAt(r.b, int(offset)) + if d.err() != nil { + return d.err() } - return errors.Wrap(r.dec.Series(d.Get(), lbls, chks), "read series") + return errors.Wrap(r.dec.Series(d.get(), lbls, chks), "read series") } // Postings returns a postings list for the given label pair. @@ -894,11 +897,11 @@ func (r *Reader) Postings(name, value string) (Postings, error) { if !ok { return EmptyPostings(), nil } - d := encoding.NewDecbufAt(r.b, int(off), castagnoliTable) - if d.Err() != nil { - return nil, errors.Wrap(d.Err(), "get postings entry") + d := newDecbufAt(r.b, int(off)) + if d.err() != nil { + return nil, errors.Wrap(d.err(), "get postings entry") } - _, p, err := r.dec.Postings(d.Get()) + _, p, err := r.dec.Postings(d.get()) if err != nil { return nil, errors.Wrap(err, "decode postings") } @@ -947,7 +950,7 @@ type stringTuples struct { func NewStringTuples(entries []string, length int) (*stringTuples, error) { if len(entries)%length != 0 { - return nil, errors.Wrap(encoding.ErrInvalidSize, "string tuple list") + return nil, errors.Wrap(errInvalidSize, "string tuple list") } return &stringTuples{entries: entries, length: length}, nil } @@ -991,7 +994,7 @@ func (t *serializedStringTuples) Len() int { func (t *serializedStringTuples) At(i int) ([]string, error) { if len(t.idsBytes) < (i+t.idsCount)*4 { - return nil, encoding.ErrInvalidSize + return nil, errInvalidSize } res := make([]string, 0, t.idsCount) @@ -1018,10 +1021,10 @@ type Decoder struct { // Postings returns a postings list for b and its number of elements. func (dec *Decoder) Postings(b []byte) (int, Postings, error) { - d := encoding.Decbuf{B: b} - n := d.Be32int() - l := d.Get() - return n, newBigEndianPostings(l), d.Err() + d := decbuf{b: b} + n := d.be32int() + l := d.get() + return n, newBigEndianPostings(l), d.err() } // Series decodes a series entry from the given byte slice into lset and chks. @@ -1029,16 +1032,16 @@ func (dec *Decoder) Series(b []byte, lbls *labels.Labels, chks *[]chunks.Meta) e *lbls = (*lbls)[:0] *chks = (*chks)[:0] - d := encoding.Decbuf{B: b} + d := decbuf{b: b} - k := d.Uvarint() + k := d.uvarint() for i := 0; i < k; i++ { - lno := uint32(d.Uvarint()) - lvo := uint32(d.Uvarint()) + lno := uint32(d.uvarint()) + lvo := uint32(d.uvarint()) - if d.Err() != nil { - return errors.Wrap(d.Err(), "read series label offsets") + if d.err() != nil { + return errors.Wrap(d.err(), "read series label offsets") } ln, err := dec.LookupSymbol(lno) @@ -1054,15 +1057,15 @@ func (dec *Decoder) Series(b []byte, lbls *labels.Labels, chks *[]chunks.Meta) e } // Read the chunks meta data. - k = d.Uvarint() + k = d.uvarint() if k == 0 { return nil } - t0 := d.Varint64() - maxt := int64(d.Uvarint64()) + t0 - ref0 := int64(d.Uvarint64()) + t0 := d.varint64() + maxt := int64(d.uvarint64()) + t0 + ref0 := int64(d.uvarint64()) *chks = append(*chks, chunks.Meta{ Ref: uint64(ref0), @@ -1072,14 +1075,14 @@ func (dec *Decoder) Series(b []byte, lbls *labels.Labels, chks *[]chunks.Meta) e t0 = maxt for i := 1; i < k; i++ { - mint := int64(d.Uvarint64()) + t0 - maxt := int64(d.Uvarint64()) + mint + mint := int64(d.uvarint64()) + t0 + maxt := int64(d.uvarint64()) + mint - ref0 += d.Varint64() + ref0 += d.varint64() t0 = maxt - if d.Err() != nil { - return errors.Wrapf(d.Err(), "read meta for chunk %d", i) + if d.err() != nil { + return errors.Wrapf(d.err(), "read meta for chunk %d", i) } *chks = append(*chks, chunks.Meta{ @@ -1088,5 +1091,5 @@ func (dec *Decoder) Series(b []byte, lbls *labels.Labels, chks *[]chunks.Meta) e MaxTime: maxt, }) } - return d.Err() + return d.err() } diff --git a/vendor/github.com/prometheus/tsdb/index/index_test.go b/vendor/github.com/prometheus/tsdb/index/index_test.go deleted file mode 100644 index 1395a34a5..000000000 --- a/vendor/github.com/prometheus/tsdb/index/index_test.go +++ /dev/null @@ -1,408 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package index - -import ( - "io/ioutil" - "math/rand" - "os" - "path/filepath" - "sort" - "testing" - - "github.com/pkg/errors" - "github.com/prometheus/tsdb/chunkenc" - "github.com/prometheus/tsdb/chunks" - "github.com/prometheus/tsdb/encoding" - "github.com/prometheus/tsdb/labels" - "github.com/prometheus/tsdb/testutil" -) - -type series struct { - l labels.Labels - chunks []chunks.Meta -} - -type mockIndex struct { - series map[uint64]series - labelIndex map[string][]string - postings map[labels.Label][]uint64 - symbols map[string]struct{} -} - -func newMockIndex() mockIndex { - ix := mockIndex{ - series: make(map[uint64]series), - labelIndex: make(map[string][]string), - postings: make(map[labels.Label][]uint64), - symbols: make(map[string]struct{}), - } - return ix -} - -func (m mockIndex) Symbols() (map[string]struct{}, error) { - return m.symbols, nil -} - -func (m mockIndex) AddSeries(ref uint64, l labels.Labels, chunks ...chunks.Meta) error { - if _, ok := m.series[ref]; ok { - return errors.Errorf("series with reference %d already added", ref) - } - for _, lbl := range l { - m.symbols[lbl.Name] = struct{}{} - m.symbols[lbl.Value] = struct{}{} - } - - s := series{l: l} - // Actual chunk data is not stored in the index. - for _, c := range chunks { - c.Chunk = nil - s.chunks = append(s.chunks, c) - } - m.series[ref] = s - - return nil -} - -func (m mockIndex) WriteLabelIndex(names []string, values []string) error { - // TODO support composite indexes - if len(names) != 1 { - return errors.New("composite indexes not supported yet") - } - sort.Strings(values) - m.labelIndex[names[0]] = values - return nil -} - -func (m mockIndex) WritePostings(name, value string, it Postings) error { - l := labels.Label{Name: name, Value: value} - if _, ok := m.postings[l]; ok { - return errors.Errorf("postings for %s already added", l) - } - ep, err := ExpandPostings(it) - if err != nil { - return err - } - m.postings[l] = ep - return nil -} - -func (m mockIndex) Close() error { - return nil -} - -func (m mockIndex) LabelValues(names ...string) (StringTuples, error) { - // TODO support composite indexes - if len(names) != 1 { - return nil, errors.New("composite indexes not supported yet") - } - - return NewStringTuples(m.labelIndex[names[0]], 1) -} - -func (m mockIndex) Postings(name, value string) (Postings, error) { - l := labels.Label{Name: name, Value: value} - return NewListPostings(m.postings[l]), nil -} - -func (m mockIndex) SortedPostings(p Postings) Postings { - ep, err := ExpandPostings(p) - if err != nil { - return ErrPostings(errors.Wrap(err, "expand postings")) - } - - sort.Slice(ep, func(i, j int) bool { - return labels.Compare(m.series[ep[i]].l, m.series[ep[j]].l) < 0 - }) - return NewListPostings(ep) -} - -func (m mockIndex) Series(ref uint64, lset *labels.Labels, chks *[]chunks.Meta) error { - s, ok := m.series[ref] - if !ok { - return errors.New("not found") - } - *lset = append((*lset)[:0], s.l...) - *chks = append((*chks)[:0], s.chunks...) - - return nil -} - -func (m mockIndex) LabelIndices() ([][]string, error) { - res := make([][]string, 0, len(m.labelIndex)) - for k := range m.labelIndex { - res = append(res, []string{k}) - } - return res, nil -} - -func TestIndexRW_Create_Open(t *testing.T) { - dir, err := ioutil.TempDir("", "test_index_create") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - fn := filepath.Join(dir, indexFilename) - - // An empty index must still result in a readable file. - iw, err := NewWriter(fn) - testutil.Ok(t, err) - testutil.Ok(t, iw.Close()) - - ir, err := NewFileReader(fn) - testutil.Ok(t, err) - testutil.Ok(t, ir.Close()) - - // Modify magic header must cause open to fail. - f, err := os.OpenFile(fn, os.O_WRONLY, 0666) - testutil.Ok(t, err) - _, err = f.WriteAt([]byte{0, 0}, 0) - testutil.Ok(t, err) - - _, err = NewFileReader(dir) - testutil.NotOk(t, err) -} - -func TestIndexRW_Postings(t *testing.T) { - dir, err := ioutil.TempDir("", "test_index_postings") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - fn := filepath.Join(dir, indexFilename) - - iw, err := NewWriter(fn) - testutil.Ok(t, err) - - series := []labels.Labels{ - labels.FromStrings("a", "1", "b", "1"), - labels.FromStrings("a", "1", "b", "2"), - labels.FromStrings("a", "1", "b", "3"), - labels.FromStrings("a", "1", "b", "4"), - } - - err = iw.AddSymbols(map[string]struct{}{ - "a": {}, - "b": {}, - "1": {}, - "2": {}, - "3": {}, - "4": {}, - }) - testutil.Ok(t, err) - - // Postings lists are only written if a series with the respective - // reference was added before. - testutil.Ok(t, iw.AddSeries(1, series[0])) - testutil.Ok(t, iw.AddSeries(2, series[1])) - testutil.Ok(t, iw.AddSeries(3, series[2])) - testutil.Ok(t, iw.AddSeries(4, series[3])) - - err = iw.WritePostings("a", "1", newListPostings([]uint64{1, 2, 3, 4})) - testutil.Ok(t, err) - - testutil.Ok(t, iw.Close()) - - ir, err := NewFileReader(fn) - testutil.Ok(t, err) - - p, err := ir.Postings("a", "1") - testutil.Ok(t, err) - - var l labels.Labels - var c []chunks.Meta - - for i := 0; p.Next(); i++ { - err := ir.Series(p.At(), &l, &c) - - testutil.Ok(t, err) - testutil.Equals(t, 0, len(c)) - testutil.Equals(t, series[i], l) - } - testutil.Ok(t, p.Err()) - - testutil.Ok(t, ir.Close()) -} - -func TestPersistence_index_e2e(t *testing.T) { - dir, err := ioutil.TempDir("", "test_persistence_e2e") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - lbls, err := labels.ReadLabels(filepath.Join("..", "testdata", "20kseries.json"), 20000) - testutil.Ok(t, err) - - // Sort labels as the index writer expects series in sorted order. - sort.Sort(labels.Slice(lbls)) - - symbols := map[string]struct{}{} - for _, lset := range lbls { - for _, l := range lset { - symbols[l.Name] = struct{}{} - symbols[l.Value] = struct{}{} - } - } - - var input indexWriterSeriesSlice - - // Generate ChunkMetas for every label set. - for i, lset := range lbls { - var metas []chunks.Meta - - for j := 0; j <= (i % 20); j++ { - metas = append(metas, chunks.Meta{ - MinTime: int64(j * 10000), - MaxTime: int64((j + 1) * 10000), - Ref: rand.Uint64(), - Chunk: chunkenc.NewXORChunk(), - }) - } - input = append(input, &indexWriterSeries{ - labels: lset, - chunks: metas, - }) - } - - iw, err := NewWriter(filepath.Join(dir, indexFilename)) - testutil.Ok(t, err) - - testutil.Ok(t, iw.AddSymbols(symbols)) - - // Population procedure as done by compaction. - var ( - postings = NewMemPostings() - values = map[string]map[string]struct{}{} - ) - - mi := newMockIndex() - - for i, s := range input { - err = iw.AddSeries(uint64(i), s.labels, s.chunks...) - testutil.Ok(t, err) - mi.AddSeries(uint64(i), s.labels, s.chunks...) - - for _, l := range s.labels { - valset, ok := values[l.Name] - if !ok { - valset = map[string]struct{}{} - values[l.Name] = valset - } - valset[l.Value] = struct{}{} - } - postings.Add(uint64(i), s.labels) - i++ - } - - for k, v := range values { - var vals []string - for e := range v { - vals = append(vals, e) - } - sort.Strings(vals) - - testutil.Ok(t, iw.WriteLabelIndex([]string{k}, vals)) - testutil.Ok(t, mi.WriteLabelIndex([]string{k}, vals)) - } - - all := make([]uint64, len(lbls)) - for i := range all { - all[i] = uint64(i) - } - err = iw.WritePostings("", "", newListPostings(all)) - testutil.Ok(t, err) - mi.WritePostings("", "", newListPostings(all)) - - for n, e := range postings.m { - for v := range e { - err = iw.WritePostings(n, v, postings.Get(n, v)) - testutil.Ok(t, err) - mi.WritePostings(n, v, postings.Get(n, v)) - } - } - - err = iw.Close() - testutil.Ok(t, err) - - ir, err := NewFileReader(filepath.Join(dir, indexFilename)) - testutil.Ok(t, err) - - for p := range mi.postings { - gotp, err := ir.Postings(p.Name, p.Value) - testutil.Ok(t, err) - - expp, err := mi.Postings(p.Name, p.Value) - testutil.Ok(t, err) - - var lset, explset labels.Labels - var chks, expchks []chunks.Meta - - for gotp.Next() { - testutil.Assert(t, expp.Next() == true, "") - - ref := gotp.At() - - err := ir.Series(ref, &lset, &chks) - testutil.Ok(t, err) - - err = mi.Series(expp.At(), &explset, &expchks) - testutil.Ok(t, err) - testutil.Equals(t, explset, lset) - testutil.Equals(t, expchks, chks) - } - testutil.Assert(t, expp.Next() == false, "") - testutil.Ok(t, gotp.Err()) - } - - for k, v := range mi.labelIndex { - tplsExp, err := NewStringTuples(v, 1) - testutil.Ok(t, err) - - tplsRes, err := ir.LabelValues(k) - testutil.Ok(t, err) - - testutil.Equals(t, tplsExp.Len(), tplsRes.Len()) - for i := 0; i < tplsExp.Len(); i++ { - strsExp, err := tplsExp.At(i) - testutil.Ok(t, err) - - strsRes, err := tplsRes.At(i) - testutil.Ok(t, err) - - testutil.Equals(t, strsExp, strsRes) - } - } - - gotSymbols, err := ir.Symbols() - testutil.Ok(t, err) - - testutil.Equals(t, len(mi.symbols), len(gotSymbols)) - for s := range mi.symbols { - _, ok := gotSymbols[s] - testutil.Assert(t, ok, "") - } - - testutil.Ok(t, ir.Close()) -} - -func TestDecbufUvariantWithInvalidBuffer(t *testing.T) { - b := realByteSlice([]byte{0x81, 0x81, 0x81, 0x81, 0x81, 0x81}) - - db := encoding.NewDecbufUvarintAt(b, 0, castagnoliTable) - testutil.NotOk(t, db.Err()) -} - -func TestReaderWithInvalidBuffer(t *testing.T) { - b := realByteSlice([]byte{0x81, 0x81, 0x81, 0x81, 0x81, 0x81}) - - _, err := NewReader(b) - testutil.NotOk(t, err) -} diff --git a/vendor/github.com/prometheus/tsdb/index/postings.go b/vendor/github.com/prometheus/tsdb/index/postings.go index cbad5b74d..13df1c69a 100644 --- a/vendor/github.com/prometheus/tsdb/index/postings.go +++ b/vendor/github.com/prometheus/tsdb/index/postings.go @@ -14,7 +14,6 @@ package index import ( - "container/heap" "encoding/binary" "runtime" "sort" @@ -306,8 +305,9 @@ func Intersect(its ...Postings) Postings { } type intersectPostings struct { - a, b Postings - cur uint64 + a, b Postings + aok, bok bool + cur uint64 } func newIntersectPostings(a, b Postings) *intersectPostings { @@ -366,132 +366,25 @@ func Merge(its ...Postings) Postings { if len(its) == 1 { return its[0] } - return newMergedPostings(its) -} - -type postingsHeap []Postings - -func (h postingsHeap) Len() int { return len(h) } -func (h postingsHeap) Less(i, j int) bool { return h[i].At() < h[j].At() } -func (h *postingsHeap) Swap(i, j int) { (*h)[i], (*h)[j] = (*h)[j], (*h)[i] } - -func (h *postingsHeap) Push(x interface{}) { - *h = append(*h, x.(Postings)) -} - -func (h *postingsHeap) Pop() interface{} { - old := *h - n := len(old) - x := old[n-1] - *h = old[0 : n-1] - return x -} - -type mergedPostings struct { - h postingsHeap - initilized bool - heaped bool - cur uint64 - err error -} - -func newMergedPostings(p []Postings) *mergedPostings { - ph := make(postingsHeap, 0, len(p)) - for _, it := range p { - if it.Next() { - ph = append(ph, it) - } else { - if it.Err() != nil { - return &mergedPostings{err: it.Err()} - } + // All the uses of this function immediately expand it, so + // collect everything in a map. This is more efficient + // when there's 100ks of postings, compared to + // having a tree of merge objects. + pm := make(map[uint64]struct{}, len(its)) + for _, it := range its { + for it.Next() { + pm[it.At()] = struct{}{} } - } - return &mergedPostings{h: ph} -} - -func (it *mergedPostings) Next() bool { - if it.h.Len() == 0 || it.err != nil { - return false - } - - if !it.heaped { - heap.Init(&it.h) - it.heaped = true - } - // The user must issue an initial Next. - if !it.initilized { - it.cur = it.h[0].At() - it.initilized = true - return true - } - - for { - cur := it.h[0] - if !cur.Next() { - heap.Pop(&it.h) - if cur.Err() != nil { - it.err = cur.Err() - return false - } - if it.h.Len() == 0 { - return false - } - } else { - // Value of top of heap has changed, re-heapify. - heap.Fix(&it.h, 0) - } - - if it.h[0].At() != it.cur { - it.cur = it.h[0].At() - return true - } - } -} - -func (it *mergedPostings) Seek(id uint64) bool { - if it.h.Len() == 0 || it.err != nil { - return false - } - if !it.initilized { - if !it.Next() { - return false + if it.Err() != nil { + return ErrPostings(it.Err()) } } - if it.cur >= id { - return true + pl := make([]uint64, 0, len(pm)) + for p := range pm { + pl = append(pl, p) } - // Heapifying when there is lots of Seeks is inefficient, - // mark to be re-heapified on the Next() call. - it.heaped = false - newH := make(postingsHeap, 0, len(it.h)) - lowest := ^uint64(0) - for _, i := range it.h { - if i.Seek(id) { - newH = append(newH, i) - if i.At() < lowest { - lowest = i.At() - } - } else { - if i.Err() != nil { - it.err = i.Err() - return false - } - } - } - it.h = newH - if len(it.h) == 0 { - return false - } - it.cur = lowest - return true -} - -func (it mergedPostings) At() uint64 { - return it.cur -} - -func (it mergedPostings) Err() error { - return it.err + sort.Slice(pl, func(i, j int) bool { return pl[i] < pl[j] }) + return newListPostings(pl) } // Without returns a new postings list that contains all elements from the full list that @@ -606,9 +499,6 @@ func (it *listPostings) Seek(x uint64) bool { if it.cur >= x { return true } - if len(it.list) == 0 { - return false - } // Do binary search between current position and end. i := sort.Search(len(it.list), func(i int) bool { diff --git a/vendor/github.com/prometheus/tsdb/index/postings_test.go b/vendor/github.com/prometheus/tsdb/index/postings_test.go deleted file mode 100644 index 668ec3609..000000000 --- a/vendor/github.com/prometheus/tsdb/index/postings_test.go +++ /dev/null @@ -1,543 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package index - -import ( - "encoding/binary" - "fmt" - "math/rand" - "sort" - "testing" - - "github.com/prometheus/tsdb/testutil" -) - -func TestMemPostings_addFor(t *testing.T) { - p := NewMemPostings() - p.m[allPostingsKey.Name] = map[string][]uint64{} - p.m[allPostingsKey.Name][allPostingsKey.Value] = []uint64{1, 2, 3, 4, 6, 7, 8} - - p.addFor(5, allPostingsKey) - - testutil.Equals(t, []uint64{1, 2, 3, 4, 5, 6, 7, 8}, p.m[allPostingsKey.Name][allPostingsKey.Value]) -} - -func TestMemPostings_ensureOrder(t *testing.T) { - p := NewUnorderedMemPostings() - p.m["a"] = map[string][]uint64{} - - for i := 0; i < 100; i++ { - l := make([]uint64, 100) - for j := range l { - l[j] = rand.Uint64() - } - v := fmt.Sprintf("%d", i) - - p.m["a"][v] = l - } - - p.EnsureOrder() - - for _, e := range p.m { - for _, l := range e { - ok := sort.SliceIsSorted(l, func(i, j int) bool { - return l[i] < l[j] - }) - if !ok { - t.Fatalf("postings list %v is not sorted", l) - } - } - } -} - -func TestIntersect(t *testing.T) { - var cases = []struct { - a, b []uint64 - res []uint64 - }{ - { - a: []uint64{1, 2, 3, 4, 5}, - b: []uint64{6, 7, 8, 9, 10}, - res: nil, - }, - { - a: []uint64{1, 2, 3, 4, 5}, - b: []uint64{4, 5, 6, 7, 8}, - res: []uint64{4, 5}, - }, - { - a: []uint64{1, 2, 3, 4, 9, 10}, - b: []uint64{1, 4, 5, 6, 7, 8, 10, 11}, - res: []uint64{1, 4, 10}, - }, { - a: []uint64{1}, - b: []uint64{0, 1}, - res: []uint64{1}, - }, - } - - for _, c := range cases { - a := newListPostings(c.a) - b := newListPostings(c.b) - - res, err := ExpandPostings(Intersect(a, b)) - testutil.Ok(t, err) - testutil.Equals(t, c.res, res) - } -} - -func TestMultiIntersect(t *testing.T) { - var cases = []struct { - p [][]uint64 - res []uint64 - }{ - { - p: [][]uint64{ - {1, 2, 3, 4, 5, 6, 1000, 1001}, - {2, 4, 5, 6, 7, 8, 999, 1001}, - {1, 2, 5, 6, 7, 8, 1001, 1200}, - }, - res: []uint64{2, 5, 6, 1001}, - }, - // One of the reproduceable cases for: - // https://github.com/prometheus/prometheus/issues/2616 - // The initialisation of intersectPostings was moving the iterator forward - // prematurely making us miss some postings. - { - p: [][]uint64{ - {1, 2}, - {1, 2}, - {1, 2}, - {2}, - }, - res: []uint64{2}, - }, - } - - for _, c := range cases { - ps := make([]Postings, 0, len(c.p)) - for _, postings := range c.p { - ps = append(ps, newListPostings(postings)) - } - - res, err := ExpandPostings(Intersect(ps...)) - - testutil.Ok(t, err) - testutil.Equals(t, c.res, res) - } -} - -func BenchmarkIntersect(t *testing.B) { - var a, b, c, d []uint64 - - for i := 0; i < 10000000; i += 2 { - a = append(a, uint64(i)) - } - for i := 5000000; i < 5000100; i += 4 { - b = append(b, uint64(i)) - } - for i := 5090000; i < 5090600; i += 4 { - b = append(b, uint64(i)) - } - for i := 4990000; i < 5100000; i++ { - c = append(c, uint64(i)) - } - for i := 4000000; i < 6000000; i++ { - d = append(d, uint64(i)) - } - - i1 := newListPostings(a) - i2 := newListPostings(b) - i3 := newListPostings(c) - i4 := newListPostings(d) - - t.ResetTimer() - - for i := 0; i < t.N; i++ { - if _, err := ExpandPostings(Intersect(i1, i2, i3, i4)); err != nil { - t.Fatal(err) - } - } -} - -func TestMultiMerge(t *testing.T) { - var cases = []struct { - a, b, c []uint64 - res []uint64 - }{ - { - a: []uint64{1, 2, 3, 4, 5, 6, 1000, 1001}, - b: []uint64{2, 4, 5, 6, 7, 8, 999, 1001}, - c: []uint64{1, 2, 5, 6, 7, 8, 1001, 1200}, - res: []uint64{1, 2, 3, 4, 5, 6, 7, 8, 999, 1000, 1001, 1200}, - }, - } - - for _, c := range cases { - i1 := newListPostings(c.a) - i2 := newListPostings(c.b) - i3 := newListPostings(c.c) - - res, err := ExpandPostings(Merge(i1, i2, i3)) - testutil.Ok(t, err) - testutil.Equals(t, c.res, res) - } -} - -func TestMergedPostings(t *testing.T) { - var cases = []struct { - a, b []uint64 - res []uint64 - }{ - { - a: []uint64{1, 2, 3, 4, 5}, - b: []uint64{6, 7, 8, 9, 10}, - res: []uint64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, - }, - { - a: []uint64{1, 2, 3, 4, 5}, - b: []uint64{4, 5, 6, 7, 8}, - res: []uint64{1, 2, 3, 4, 5, 6, 7, 8}, - }, - { - a: []uint64{1, 2, 3, 4, 9, 10}, - b: []uint64{1, 4, 5, 6, 7, 8, 10, 11}, - res: []uint64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, - }, - } - - for _, c := range cases { - a := newListPostings(c.a) - b := newListPostings(c.b) - - res, err := ExpandPostings(Merge(a, b)) - testutil.Ok(t, err) - testutil.Equals(t, c.res, res) - } - -} - -func TestMergedPostingsSeek(t *testing.T) { - var cases = []struct { - a, b []uint64 - - seek uint64 - success bool - res []uint64 - }{ - { - a: []uint64{2, 3, 4, 5}, - b: []uint64{6, 7, 8, 9, 10}, - - seek: 1, - success: true, - res: []uint64{2, 3, 4, 5, 6, 7, 8, 9, 10}, - }, - { - a: []uint64{1, 2, 3, 4, 5}, - b: []uint64{6, 7, 8, 9, 10}, - - seek: 2, - success: true, - res: []uint64{2, 3, 4, 5, 6, 7, 8, 9, 10}, - }, - { - a: []uint64{1, 2, 3, 4, 5}, - b: []uint64{4, 5, 6, 7, 8}, - - seek: 9, - success: false, - res: nil, - }, - { - a: []uint64{1, 2, 3, 4, 9, 10}, - b: []uint64{1, 4, 5, 6, 7, 8, 10, 11}, - - seek: 10, - success: true, - res: []uint64{10, 11}, - }, - } - - for _, c := range cases { - a := newListPostings(c.a) - b := newListPostings(c.b) - - p := Merge(a, b) - - testutil.Equals(t, c.success, p.Seek(c.seek)) - - // After Seek(), At() should be called. - if c.success { - start := p.At() - lst, err := ExpandPostings(p) - testutil.Ok(t, err) - - lst = append([]uint64{start}, lst...) - testutil.Equals(t, c.res, lst) - } - } -} - -func TestRemovedPostings(t *testing.T) { - var cases = []struct { - a, b []uint64 - res []uint64 - }{ - { - a: nil, - b: nil, - res: []uint64(nil), - }, - { - a: []uint64{1, 2, 3, 4}, - b: nil, - res: []uint64{1, 2, 3, 4}, - }, - { - a: nil, - b: []uint64{1, 2, 3, 4}, - res: []uint64(nil), - }, - { - a: []uint64{1, 2, 3, 4, 5}, - b: []uint64{6, 7, 8, 9, 10}, - res: []uint64{1, 2, 3, 4, 5}, - }, - { - a: []uint64{1, 2, 3, 4, 5}, - b: []uint64{4, 5, 6, 7, 8}, - res: []uint64{1, 2, 3}, - }, - { - a: []uint64{1, 2, 3, 4, 9, 10}, - b: []uint64{1, 4, 5, 6, 7, 8, 10, 11}, - res: []uint64{2, 3, 9}, - }, - { - a: []uint64{1, 2, 3, 4, 9, 10}, - b: []uint64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, - res: []uint64(nil), - }, - } - - for _, c := range cases { - a := newListPostings(c.a) - b := newListPostings(c.b) - - res, err := ExpandPostings(newRemovedPostings(a, b)) - testutil.Ok(t, err) - testutil.Equals(t, c.res, res) - } - -} - -func TestRemovedNextStackoverflow(t *testing.T) { - var full []uint64 - var remove []uint64 - - var i uint64 - for i = 0; i < 1e7; i++ { - full = append(full, i) - remove = append(remove, i) - } - - flp := newListPostings(full) - rlp := newListPostings(remove) - rp := newRemovedPostings(flp, rlp) - gotElem := false - for rp.Next() { - gotElem = true - } - - testutil.Ok(t, rp.Err()) - testutil.Assert(t, !gotElem, "") -} - -func TestRemovedPostingsSeek(t *testing.T) { - var cases = []struct { - a, b []uint64 - - seek uint64 - success bool - res []uint64 - }{ - { - a: []uint64{2, 3, 4, 5}, - b: []uint64{6, 7, 8, 9, 10}, - - seek: 1, - success: true, - res: []uint64{2, 3, 4, 5}, - }, - { - a: []uint64{1, 2, 3, 4, 5}, - b: []uint64{6, 7, 8, 9, 10}, - - seek: 2, - success: true, - res: []uint64{2, 3, 4, 5}, - }, - { - a: []uint64{1, 2, 3, 4, 5}, - b: []uint64{4, 5, 6, 7, 8}, - - seek: 9, - success: false, - res: nil, - }, - { - a: []uint64{1, 2, 3, 4, 9, 10}, - b: []uint64{1, 4, 5, 6, 7, 8, 10, 11}, - - seek: 10, - success: false, - res: nil, - }, - { - a: []uint64{1, 2, 3, 4, 9, 10}, - b: []uint64{1, 4, 5, 6, 7, 8, 11}, - - seek: 4, - success: true, - res: []uint64{9, 10}, - }, - { - a: []uint64{1, 2, 3, 4, 9, 10}, - b: []uint64{1, 4, 5, 6, 7, 8, 11}, - - seek: 5, - success: true, - res: []uint64{9, 10}, - }, - { - a: []uint64{1, 2, 3, 4, 9, 10}, - b: []uint64{1, 4, 5, 6, 7, 8, 11}, - - seek: 10, - success: true, - res: []uint64{10}, - }, - } - - for _, c := range cases { - a := newListPostings(c.a) - b := newListPostings(c.b) - - p := newRemovedPostings(a, b) - - testutil.Equals(t, c.success, p.Seek(c.seek)) - - // After Seek(), At() should be called. - if c.success { - start := p.At() - lst, err := ExpandPostings(p) - testutil.Ok(t, err) - - lst = append([]uint64{start}, lst...) - testutil.Equals(t, c.res, lst) - } - } -} - -func TestBigEndian(t *testing.T) { - num := 1000 - // mock a list as postings - ls := make([]uint32, num) - ls[0] = 2 - for i := 1; i < num; i++ { - ls[i] = ls[i-1] + uint32(rand.Int31n(25)) + 2 - } - - beLst := make([]byte, num*4) - for i := 0; i < num; i++ { - b := beLst[i*4 : i*4+4] - binary.BigEndian.PutUint32(b, ls[i]) - } - - t.Run("Iteration", func(t *testing.T) { - bep := newBigEndianPostings(beLst) - for i := 0; i < num; i++ { - testutil.Assert(t, bep.Next() == true, "") - testutil.Equals(t, uint64(ls[i]), bep.At()) - } - - testutil.Assert(t, bep.Next() == false, "") - testutil.Assert(t, bep.Err() == nil, "") - }) - - t.Run("Seek", func(t *testing.T) { - table := []struct { - seek uint32 - val uint32 - found bool - }{ - { - ls[0] - 1, ls[0], true, - }, - { - ls[4], ls[4], true, - }, - { - ls[500] - 1, ls[500], true, - }, - { - ls[600] + 1, ls[601], true, - }, - { - ls[600] + 1, ls[601], true, - }, - { - ls[600] + 1, ls[601], true, - }, - { - ls[0], ls[601], true, - }, - { - ls[600], ls[601], true, - }, - { - ls[999], ls[999], true, - }, - { - ls[999] + 10, ls[999], false, - }, - } - - bep := newBigEndianPostings(beLst) - - for _, v := range table { - testutil.Equals(t, v.found, bep.Seek(uint64(v.seek))) - testutil.Equals(t, uint64(v.val), bep.At()) - testutil.Assert(t, bep.Err() == nil, "") - } - }) -} - -func TestIntersectWithMerge(t *testing.T) { - // One of the reproduceable cases for: - // https://github.com/prometheus/prometheus/issues/2616 - a := newListPostings([]uint64{21, 22, 23, 24, 25, 30}) - - b := Merge( - newListPostings([]uint64{10, 20, 30}), - newListPostings([]uint64{15, 26, 30}), - ) - - p := Intersect(a, b) - res, err := ExpandPostings(p) - - testutil.Ok(t, err) - testutil.Equals(t, []uint64{30}, res) -} diff --git a/vendor/github.com/prometheus/tsdb/labels/labels_test.go b/vendor/github.com/prometheus/tsdb/labels/labels_test.go deleted file mode 100644 index c49f66edf..000000000 --- a/vendor/github.com/prometheus/tsdb/labels/labels_test.go +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package labels - -import ( - "fmt" - "math/rand" - "path/filepath" - "sort" - "testing" - - "github.com/prometheus/tsdb/testutil" -) - -func TestCompareAndEquals(t *testing.T) { - cases := []struct { - a, b []Label - res int - }{ - { - a: []Label{}, - b: []Label{}, - res: 0, - }, - { - a: []Label{{"a", ""}}, - b: []Label{{"a", ""}, {"b", ""}}, - res: -1, - }, - { - a: []Label{{"a", ""}}, - b: []Label{{"a", ""}}, - res: 0, - }, - { - a: []Label{{"aa", ""}, {"aa", ""}}, - b: []Label{{"aa", ""}, {"ab", ""}}, - res: -1, - }, - { - a: []Label{{"aa", ""}, {"abb", ""}}, - b: []Label{{"aa", ""}, {"ab", ""}}, - res: 1, - }, - { - a: []Label{ - {"__name__", "go_gc_duration_seconds"}, - {"job", "prometheus"}, - {"quantile", "0.75"}, - }, - b: []Label{ - {"__name__", "go_gc_duration_seconds"}, - {"job", "prometheus"}, - {"quantile", "1"}, - }, - res: -1, - }, - { - a: []Label{ - {"handler", "prometheus"}, - {"instance", "localhost:9090"}, - }, - b: []Label{ - {"handler", "query"}, - {"instance", "localhost:9090"}, - }, - res: -1, - }, - } - for _, c := range cases { - // Use constructor to ensure sortedness. - a, b := New(c.a...), New(c.b...) - - testutil.Equals(t, c.res, Compare(a, b)) - testutil.Equals(t, c.res == 0, a.Equals(b)) - } -} - -func BenchmarkSliceSort(b *testing.B) { - lbls, err := ReadLabels(filepath.Join("..", "testdata", "20kseries.json"), 20000) - testutil.Ok(b, err) - - for len(lbls) < 20e6 { - lbls = append(lbls, lbls...) - } - for i := range lbls { - j := rand.Intn(i + 1) - lbls[i], lbls[j] = lbls[j], lbls[i] - } - - for _, k := range []int{ - 100, 5000, 50000, 300000, 900000, 5e6, 20e6, - } { - b.Run(fmt.Sprintf("%d", k), func(b *testing.B) { - b.ReportAllocs() - - for a := 0; a < b.N; a++ { - b.StopTimer() - cl := make(Slice, k) - copy(cl, Slice(lbls[:k])) - b.StartTimer() - - sort.Sort(cl) - } - }) - } -} - -func BenchmarkLabelSetFromMap(b *testing.B) { - m := map[string]string{ - "job": "node", - "instance": "123.123.1.211:9090", - "path": "/api/v1/namespaces//deployments/", - "method": "GET", - "namespace": "system", - "status": "500", - } - var ls Labels - b.ReportAllocs() - - for i := 0; i < b.N; i++ { - ls = FromMap(m) - } - _ = ls -} - -func BenchmarkMapFromLabels(b *testing.B) { - m := map[string]string{ - "job": "node", - "instance": "123.123.1.211:9090", - "path": "/api/v1/namespaces//deployments/", - "method": "GET", - "namespace": "system", - "status": "500", - } - ls := FromMap(m) - - b.ResetTimer() - b.ReportAllocs() - - for i := 0; i < b.N; i++ { - _ = ls.Map() - } -} - -func BenchmarkLabelSetEquals(b *testing.B) { - // The vast majority of comparisons will be against a matching label set. - m := map[string]string{ - "job": "node", - "instance": "123.123.1.211:9090", - "path": "/api/v1/namespaces//deployments/", - "method": "GET", - "namespace": "system", - "status": "500", - } - ls := FromMap(m) - var res bool - - b.ResetTimer() - b.ReportAllocs() - - for i := 0; i < b.N; i++ { - res = ls.Equals(ls) - } - _ = res -} - -func BenchmarkLabelSetHash(b *testing.B) { - // The vast majority of comparisons will be against a matching label set. - m := map[string]string{ - "job": "node", - "instance": "123.123.1.211:9090", - "path": "/api/v1/namespaces//deployments/", - "method": "GET", - "namespace": "system", - "status": "500", - } - ls := FromMap(m) - var res uint64 - - b.ResetTimer() - b.ReportAllocs() - - for i := 0; i < b.N; i++ { - res += ls.Hash() - } - fmt.Println(res) -} diff --git a/vendor/github.com/prometheus/tsdb/mocks_test.go b/vendor/github.com/prometheus/tsdb/mocks_test.go deleted file mode 100644 index 243d5cf14..000000000 --- a/vendor/github.com/prometheus/tsdb/mocks_test.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tsdb - -import ( - "github.com/prometheus/tsdb/chunks" - "github.com/prometheus/tsdb/index" - "github.com/prometheus/tsdb/labels" -) - -type mockIndexWriter struct { - series []seriesSamples -} - -func (mockIndexWriter) AddSymbols(sym map[string]struct{}) error { return nil } -func (m *mockIndexWriter) AddSeries(ref uint64, l labels.Labels, chunks ...chunks.Meta) error { - i := -1 - for j, s := range m.series { - if !labels.FromMap(s.lset).Equals(l) { - continue - } - i = j - break - } - if i == -1 { - m.series = append(m.series, seriesSamples{ - lset: l.Map(), - }) - i = len(m.series) - 1 - } - - for _, chk := range chunks { - samples := make([]sample, 0, chk.Chunk.NumSamples()) - - iter := chk.Chunk.Iterator() - for iter.Next() { - s := sample{} - s.t, s.v = iter.At() - - samples = append(samples, s) - } - if err := iter.Err(); err != nil { - return err - } - - m.series[i].chunks = append(m.series[i].chunks, samples) - } - return nil -} - -func (mockIndexWriter) WriteLabelIndex(names []string, values []string) error { return nil } -func (mockIndexWriter) WritePostings(name, value string, it index.Postings) error { return nil } -func (mockIndexWriter) Close() error { return nil } - -type mockBReader struct { - ir IndexReader - cr ChunkReader - mint int64 - maxt int64 -} - -func (r *mockBReader) Index() (IndexReader, error) { return r.ir, nil } -func (r *mockBReader) Chunks() (ChunkReader, error) { return r.cr, nil } -func (r *mockBReader) Tombstones() (TombstoneReader, error) { return newMemTombstones(), nil } -func (r *mockBReader) MinTime() int64 { return r.mint } -func (r *mockBReader) MaxTime() int64 { return r.maxt } diff --git a/vendor/github.com/prometheus/tsdb/querier.go b/vendor/github.com/prometheus/tsdb/querier.go index 3e8cd77ca..4a5a40636 100644 --- a/vendor/github.com/prometheus/tsdb/querier.go +++ b/vendor/github.com/prometheus/tsdb/querier.go @@ -111,6 +111,7 @@ func (q *querier) LabelValuesFor(string, labels.Label) ([]string, error) { func (q *querier) Select(ms ...labels.Matcher) (SeriesSet, error) { return q.sel(q.blocks, ms) + } func (q *querier) sel(qs []Querier, ms []labels.Matcher) (SeriesSet, error) { @@ -142,36 +143,6 @@ func (q *querier) Close() error { return merr.Err() } -// verticalQuerier aggregates querying results from time blocks within -// a single partition. The block time ranges can be overlapping. -type verticalQuerier struct { - querier -} - -func (q *verticalQuerier) Select(ms ...labels.Matcher) (SeriesSet, error) { - return q.sel(q.blocks, ms) -} - -func (q *verticalQuerier) sel(qs []Querier, ms []labels.Matcher) (SeriesSet, error) { - if len(qs) == 0 { - return EmptySeriesSet(), nil - } - if len(qs) == 1 { - return qs[0].Select(ms...) - } - l := len(qs) / 2 - - a, err := q.sel(qs[:l], ms) - if err != nil { - return nil, err - } - b, err := q.sel(qs[l:], ms) - if err != nil { - return nil, err - } - return newMergedVerticalSeriesSet(a, b), nil -} - // NewBlockQuerier returns a querier against the reader. func NewBlockQuerier(b BlockReader, mint, maxt int64) (Querier, error) { indexr, err := b.Index() @@ -354,23 +325,11 @@ func postingsForUnsetLabelMatcher(ix IndexReader, m labels.Matcher) (index.Posti rit = append(rit, it) } - merged := index.Merge(rit...) - // With many many postings, it's best to pre-calculate - // the merged list via next rather than have a ton of seeks - // in Without/Intersection. - if len(rit) > 100 { - pl, err := index.ExpandPostings(merged) - if err != nil { - return nil, err - } - merged = index.NewListPostings(pl) - } - allPostings, err := ix.Postings(index.AllPostingsKey()) if err != nil { return nil, err } - return index.Without(allPostings, merged), nil + return index.Without(allPostings, index.Merge(rit...)), nil } func mergeStrings(a, b []string) []string { @@ -485,72 +444,6 @@ func (s *mergedSeriesSet) Next() bool { return true } -type mergedVerticalSeriesSet struct { - a, b SeriesSet - cur Series - adone, bdone bool -} - -// NewMergedVerticalSeriesSet takes two series sets as a single series set. -// The input series sets must be sorted and -// the time ranges of the series can be overlapping. -func NewMergedVerticalSeriesSet(a, b SeriesSet) SeriesSet { - return newMergedVerticalSeriesSet(a, b) -} - -func newMergedVerticalSeriesSet(a, b SeriesSet) *mergedVerticalSeriesSet { - s := &mergedVerticalSeriesSet{a: a, b: b} - // Initialize first elements of both sets as Next() needs - // one element look-ahead. - s.adone = !s.a.Next() - s.bdone = !s.b.Next() - - return s -} - -func (s *mergedVerticalSeriesSet) At() Series { - return s.cur -} - -func (s *mergedVerticalSeriesSet) Err() error { - if s.a.Err() != nil { - return s.a.Err() - } - return s.b.Err() -} - -func (s *mergedVerticalSeriesSet) compare() int { - if s.adone { - return 1 - } - if s.bdone { - return -1 - } - return labels.Compare(s.a.At().Labels(), s.b.At().Labels()) -} - -func (s *mergedVerticalSeriesSet) Next() bool { - if s.adone && s.bdone || s.Err() != nil { - return false - } - - d := s.compare() - - // Both sets contain the current series. Chain them into a single one. - if d > 0 { - s.cur = s.b.At() - s.bdone = !s.b.Next() - } else if d < 0 { - s.cur = s.a.At() - s.adone = !s.a.Next() - } else { - s.cur = &verticalChainedSeries{series: []Series{s.a.At(), s.b.At()}} - s.adone = !s.a.Next() - s.bdone = !s.b.Next() - } - return true -} - // ChunkSeriesSet exposes the chunks and intervals of a series instead of the // actual series itself. type ChunkSeriesSet interface { @@ -846,100 +739,6 @@ func (it *chainedSeriesIterator) Err() error { return it.cur.Err() } -// verticalChainedSeries implements a series for a list of time-sorted, time-overlapping series. -// They all must have the same labels. -type verticalChainedSeries struct { - series []Series -} - -func (s *verticalChainedSeries) Labels() labels.Labels { - return s.series[0].Labels() -} - -func (s *verticalChainedSeries) Iterator() SeriesIterator { - return newVerticalMergeSeriesIterator(s.series...) -} - -// verticalMergeSeriesIterator implements a series iterater over a list -// of time-sorted, time-overlapping iterators. -type verticalMergeSeriesIterator struct { - a, b SeriesIterator - aok, bok, initialized bool - - curT int64 - curV float64 -} - -func newVerticalMergeSeriesIterator(s ...Series) SeriesIterator { - if len(s) == 1 { - return s[0].Iterator() - } else if len(s) == 2 { - return &verticalMergeSeriesIterator{ - a: s[0].Iterator(), - b: s[1].Iterator(), - } - } - return &verticalMergeSeriesIterator{ - a: s[0].Iterator(), - b: newVerticalMergeSeriesIterator(s[1:]...), - } -} - -func (it *verticalMergeSeriesIterator) Seek(t int64) bool { - it.aok, it.bok = it.a.Seek(t), it.b.Seek(t) - it.initialized = true - return it.Next() -} - -func (it *verticalMergeSeriesIterator) Next() bool { - if !it.initialized { - it.aok = it.a.Next() - it.bok = it.b.Next() - it.initialized = true - } - - if !it.aok && !it.bok { - return false - } - - if !it.aok { - it.curT, it.curV = it.b.At() - it.bok = it.b.Next() - return true - } - if !it.bok { - it.curT, it.curV = it.a.At() - it.aok = it.a.Next() - return true - } - - acurT, acurV := it.a.At() - bcurT, bcurV := it.b.At() - if acurT < bcurT { - it.curT, it.curV = acurT, acurV - it.aok = it.a.Next() - } else if acurT > bcurT { - it.curT, it.curV = bcurT, bcurV - it.bok = it.b.Next() - } else { - it.curT, it.curV = bcurT, bcurV - it.aok = it.a.Next() - it.bok = it.b.Next() - } - return true -} - -func (it *verticalMergeSeriesIterator) At() (t int64, v float64) { - return it.curT, it.curV -} - -func (it *verticalMergeSeriesIterator) Err() error { - if it.a.Err() != nil { - return it.a.Err() - } - return it.b.Err() -} - // chunkSeriesIterator implements a series iterator on top // of a list of time-sorted, non-overlapping chunks. type chunkSeriesIterator struct { diff --git a/vendor/github.com/prometheus/tsdb/querier_test.go b/vendor/github.com/prometheus/tsdb/querier_test.go deleted file mode 100644 index ee426d044..000000000 --- a/vendor/github.com/prometheus/tsdb/querier_test.go +++ /dev/null @@ -1,1691 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tsdb - -import ( - "fmt" - "io/ioutil" - "math" - "math/rand" - "os" - "path/filepath" - "sort" - "testing" - - "github.com/pkg/errors" - "github.com/prometheus/tsdb/chunkenc" - "github.com/prometheus/tsdb/chunks" - "github.com/prometheus/tsdb/index" - "github.com/prometheus/tsdb/labels" - "github.com/prometheus/tsdb/testutil" - "github.com/prometheus/tsdb/tsdbutil" -) - -type mockSeriesSet struct { - next func() bool - series func() Series - err func() error -} - -func (m *mockSeriesSet) Next() bool { return m.next() } -func (m *mockSeriesSet) At() Series { return m.series() } -func (m *mockSeriesSet) Err() error { return m.err() } - -func newMockSeriesSet(list []Series) *mockSeriesSet { - i := -1 - return &mockSeriesSet{ - next: func() bool { - i++ - return i < len(list) - }, - series: func() Series { - return list[i] - }, - err: func() error { return nil }, - } -} - -func TestMergedSeriesSet(t *testing.T) { - - cases := []struct { - // The input sets in order (samples in series in b are strictly - // after those in a). - a, b SeriesSet - // The composition of a and b in the partition series set must yield - // results equivalent to the result series set. - exp SeriesSet - }{ - { - a: newMockSeriesSet([]Series{ - newSeries(map[string]string{ - "a": "a", - }, []tsdbutil.Sample{ - sample{t: 1, v: 1}, - }), - }), - b: newMockSeriesSet([]Series{ - newSeries(map[string]string{ - "a": "a", - }, []tsdbutil.Sample{ - sample{t: 2, v: 2}, - }), - newSeries(map[string]string{ - "b": "b", - }, []tsdbutil.Sample{ - sample{t: 1, v: 1}, - }), - }), - exp: newMockSeriesSet([]Series{ - newSeries(map[string]string{ - "a": "a", - }, []tsdbutil.Sample{ - sample{t: 1, v: 1}, - sample{t: 2, v: 2}, - }), - newSeries(map[string]string{ - "b": "b", - }, []tsdbutil.Sample{ - sample{t: 1, v: 1}, - }), - }), - }, - { - a: newMockSeriesSet([]Series{ - newSeries(map[string]string{ - "handler": "prometheus", - "instance": "127.0.0.1:9090", - }, []tsdbutil.Sample{ - sample{t: 1, v: 1}, - }), - newSeries(map[string]string{ - "handler": "prometheus", - "instance": "localhost:9090", - }, []tsdbutil.Sample{ - sample{t: 1, v: 2}, - }), - }), - b: newMockSeriesSet([]Series{ - newSeries(map[string]string{ - "handler": "prometheus", - "instance": "127.0.0.1:9090", - }, []tsdbutil.Sample{ - sample{t: 2, v: 1}, - }), - newSeries(map[string]string{ - "handler": "query", - "instance": "localhost:9090", - }, []tsdbutil.Sample{ - sample{t: 2, v: 2}, - }), - }), - exp: newMockSeriesSet([]Series{ - newSeries(map[string]string{ - "handler": "prometheus", - "instance": "127.0.0.1:9090", - }, []tsdbutil.Sample{ - sample{t: 1, v: 1}, - sample{t: 2, v: 1}, - }), - newSeries(map[string]string{ - "handler": "prometheus", - "instance": "localhost:9090", - }, []tsdbutil.Sample{ - sample{t: 1, v: 2}, - }), - newSeries(map[string]string{ - "handler": "query", - "instance": "localhost:9090", - }, []tsdbutil.Sample{ - sample{t: 2, v: 2}, - }), - }), - }, - } - -Outer: - for _, c := range cases { - res := newMergedSeriesSet(c.a, c.b) - - for { - eok, rok := c.exp.Next(), res.Next() - testutil.Equals(t, eok, rok) - - if !eok { - continue Outer - } - sexp := c.exp.At() - sres := res.At() - - testutil.Equals(t, sexp.Labels(), sres.Labels()) - - smplExp, errExp := expandSeriesIterator(sexp.Iterator()) - smplRes, errRes := expandSeriesIterator(sres.Iterator()) - - testutil.Equals(t, errExp, errRes) - testutil.Equals(t, smplExp, smplRes) - } - } -} - -func expandSeriesIterator(it SeriesIterator) (r []tsdbutil.Sample, err error) { - for it.Next() { - t, v := it.At() - r = append(r, sample{t: t, v: v}) - } - - return r, it.Err() -} - -type seriesSamples struct { - lset map[string]string - chunks [][]sample -} - -// Index: labels -> postings -> chunkMetas -> chunkRef -// ChunkReader: ref -> vals -func createIdxChkReaders(tc []seriesSamples) (IndexReader, ChunkReader, int64, int64) { - sort.Slice(tc, func(i, j int) bool { - return labels.Compare(labels.FromMap(tc[i].lset), labels.FromMap(tc[i].lset)) < 0 - }) - - postings := index.NewMemPostings() - chkReader := mockChunkReader(make(map[uint64]chunkenc.Chunk)) - lblIdx := make(map[string]stringset) - mi := newMockIndex() - blockMint := int64(math.MaxInt64) - blockMaxt := int64(math.MinInt64) - - for i, s := range tc { - i = i + 1 // 0 is not a valid posting. - metas := make([]chunks.Meta, 0, len(s.chunks)) - for _, chk := range s.chunks { - // Collisions can be there, but for tests, its fine. - ref := rand.Uint64() - - if chk[0].t < blockMint { - blockMint = chk[0].t - } - if chk[len(chk)-1].t > blockMaxt { - blockMaxt = chk[len(chk)-1].t - } - - metas = append(metas, chunks.Meta{ - MinTime: chk[0].t, - MaxTime: chk[len(chk)-1].t, - Ref: ref, - }) - - chunk := chunkenc.NewXORChunk() - app, _ := chunk.Appender() - for _, smpl := range chk { - app.Append(smpl.t, smpl.v) - } - chkReader[ref] = chunk - } - - ls := labels.FromMap(s.lset) - mi.AddSeries(uint64(i), ls, metas...) - - postings.Add(uint64(i), ls) - - for _, l := range ls { - vs, present := lblIdx[l.Name] - if !present { - vs = stringset{} - lblIdx[l.Name] = vs - } - vs.set(l.Value) - } - } - - for l, vs := range lblIdx { - mi.WriteLabelIndex([]string{l}, vs.slice()) - } - - postings.Iter(func(l labels.Label, p index.Postings) error { - return mi.WritePostings(l.Name, l.Value, p) - }) - - return mi, chkReader, blockMint, blockMaxt -} - -func TestBlockQuerier(t *testing.T) { - newSeries := func(l map[string]string, s []tsdbutil.Sample) Series { - return &mockSeries{ - labels: func() labels.Labels { return labels.FromMap(l) }, - iterator: func() SeriesIterator { return newListSeriesIterator(s) }, - } - } - - type query struct { - mint, maxt int64 - ms []labels.Matcher - exp SeriesSet - } - - cases := struct { - data []seriesSamples - - queries []query - }{ - data: []seriesSamples{ - { - lset: map[string]string{ - "a": "a", - }, - chunks: [][]sample{ - { - {1, 2}, {2, 3}, {3, 4}, - }, - { - {5, 2}, {6, 3}, {7, 4}, - }, - }, - }, - { - lset: map[string]string{ - "a": "a", - "b": "b", - }, - chunks: [][]sample{ - { - {1, 1}, {2, 2}, {3, 3}, - }, - { - {5, 3}, {6, 6}, - }, - }, - }, - { - lset: map[string]string{ - "b": "b", - }, - chunks: [][]sample{ - { - {1, 3}, {2, 2}, {3, 6}, - }, - { - {5, 1}, {6, 7}, {7, 2}, - }, - }, - }, - }, - - queries: []query{ - { - mint: 0, - maxt: 0, - ms: []labels.Matcher{}, - exp: newMockSeriesSet([]Series{}), - }, - { - mint: 0, - maxt: 0, - ms: []labels.Matcher{labels.NewEqualMatcher("a", "a")}, - exp: newMockSeriesSet([]Series{}), - }, - { - mint: 1, - maxt: 0, - ms: []labels.Matcher{labels.NewEqualMatcher("a", "a")}, - exp: newMockSeriesSet([]Series{}), - }, - { - mint: 2, - maxt: 6, - ms: []labels.Matcher{labels.NewEqualMatcher("a", "a")}, - exp: newMockSeriesSet([]Series{ - newSeries(map[string]string{ - "a": "a", - }, - []tsdbutil.Sample{sample{2, 3}, sample{3, 4}, sample{5, 2}, sample{6, 3}}, - ), - newSeries(map[string]string{ - "a": "a", - "b": "b", - }, - []tsdbutil.Sample{sample{2, 2}, sample{3, 3}, sample{5, 3}, sample{6, 6}}, - ), - }), - }, - }, - } - -Outer: - for _, c := range cases.queries { - ir, cr, _, _ := createIdxChkReaders(cases.data) - querier := &blockQuerier{ - index: ir, - chunks: cr, - tombstones: newMemTombstones(), - - mint: c.mint, - maxt: c.maxt, - } - - res, err := querier.Select(c.ms...) - testutil.Ok(t, err) - - for { - eok, rok := c.exp.Next(), res.Next() - testutil.Equals(t, eok, rok) - - if !eok { - continue Outer - } - sexp := c.exp.At() - sres := res.At() - - testutil.Equals(t, sexp.Labels(), sres.Labels()) - - smplExp, errExp := expandSeriesIterator(sexp.Iterator()) - smplRes, errRes := expandSeriesIterator(sres.Iterator()) - - testutil.Equals(t, errExp, errRes) - testutil.Equals(t, smplExp, smplRes) - } - } -} - -func TestBlockQuerierDelete(t *testing.T) { - newSeries := func(l map[string]string, s []tsdbutil.Sample) Series { - return &mockSeries{ - labels: func() labels.Labels { return labels.FromMap(l) }, - iterator: func() SeriesIterator { return newListSeriesIterator(s) }, - } - } - - type query struct { - mint, maxt int64 - ms []labels.Matcher - exp SeriesSet - } - - cases := struct { - data []seriesSamples - - tombstones TombstoneReader - queries []query - }{ - data: []seriesSamples{ - { - lset: map[string]string{ - "a": "a", - }, - chunks: [][]sample{ - { - {1, 2}, {2, 3}, {3, 4}, - }, - { - {5, 2}, {6, 3}, {7, 4}, - }, - }, - }, - { - lset: map[string]string{ - "a": "a", - "b": "b", - }, - chunks: [][]sample{ - { - {1, 1}, {2, 2}, {3, 3}, - }, - { - {4, 15}, {5, 3}, {6, 6}, - }, - }, - }, - { - lset: map[string]string{ - "b": "b", - }, - chunks: [][]sample{ - { - {1, 3}, {2, 2}, {3, 6}, - }, - { - {5, 1}, {6, 7}, {7, 2}, - }, - }, - }, - }, - tombstones: &memTombstones{intvlGroups: map[uint64]Intervals{ - 1: Intervals{{1, 3}}, - 2: Intervals{{1, 3}, {6, 10}}, - 3: Intervals{{6, 10}}, - }}, - queries: []query{ - { - mint: 2, - maxt: 7, - ms: []labels.Matcher{labels.NewEqualMatcher("a", "a")}, - exp: newMockSeriesSet([]Series{ - newSeries(map[string]string{ - "a": "a", - }, - []tsdbutil.Sample{sample{5, 2}, sample{6, 3}, sample{7, 4}}, - ), - newSeries(map[string]string{ - "a": "a", - "b": "b", - }, - []tsdbutil.Sample{sample{4, 15}, sample{5, 3}}, - ), - }), - }, - { - mint: 2, - maxt: 7, - ms: []labels.Matcher{labels.NewEqualMatcher("b", "b")}, - exp: newMockSeriesSet([]Series{ - newSeries(map[string]string{ - "a": "a", - "b": "b", - }, - []tsdbutil.Sample{sample{4, 15}, sample{5, 3}}, - ), - newSeries(map[string]string{ - "b": "b", - }, - []tsdbutil.Sample{sample{2, 2}, sample{3, 6}, sample{5, 1}}, - ), - }), - }, - { - mint: 1, - maxt: 4, - ms: []labels.Matcher{labels.NewEqualMatcher("a", "a")}, - exp: newMockSeriesSet([]Series{ - newSeries(map[string]string{ - "a": "a", - "b": "b", - }, - []tsdbutil.Sample{sample{4, 15}}, - ), - }), - }, - { - mint: 1, - maxt: 3, - ms: []labels.Matcher{labels.NewEqualMatcher("a", "a")}, - exp: newMockSeriesSet([]Series{}), - }, - }, - } - -Outer: - for _, c := range cases.queries { - ir, cr, _, _ := createIdxChkReaders(cases.data) - querier := &blockQuerier{ - index: ir, - chunks: cr, - tombstones: cases.tombstones, - - mint: c.mint, - maxt: c.maxt, - } - - res, err := querier.Select(c.ms...) - testutil.Ok(t, err) - - for { - eok, rok := c.exp.Next(), res.Next() - testutil.Equals(t, eok, rok) - - if !eok { - continue Outer - } - sexp := c.exp.At() - sres := res.At() - - testutil.Equals(t, sexp.Labels(), sres.Labels()) - - smplExp, errExp := expandSeriesIterator(sexp.Iterator()) - smplRes, errRes := expandSeriesIterator(sres.Iterator()) - - testutil.Equals(t, errExp, errRes) - testutil.Equals(t, smplExp, smplRes) - } - } -} - -func TestBaseChunkSeries(t *testing.T) { - type refdSeries struct { - lset labels.Labels - chunks []chunks.Meta - - ref uint64 - } - - cases := []struct { - series []refdSeries - // Postings should be in the sorted order of the the series - postings []uint64 - - expIdxs []int - }{ - { - series: []refdSeries{ - { - lset: labels.New([]labels.Label{{"a", "a"}}...), - chunks: []chunks.Meta{ - {Ref: 29}, {Ref: 45}, {Ref: 245}, {Ref: 123}, {Ref: 4232}, {Ref: 5344}, - {Ref: 121}, - }, - ref: 12, - }, - { - lset: labels.New([]labels.Label{{"a", "a"}, {"b", "b"}}...), - chunks: []chunks.Meta{ - {Ref: 82}, {Ref: 23}, {Ref: 234}, {Ref: 65}, {Ref: 26}, - }, - ref: 10, - }, - { - lset: labels.New([]labels.Label{{"b", "c"}}...), - chunks: []chunks.Meta{{Ref: 8282}}, - ref: 1, - }, - { - lset: labels.New([]labels.Label{{"b", "b"}}...), - chunks: []chunks.Meta{ - {Ref: 829}, {Ref: 239}, {Ref: 2349}, {Ref: 659}, {Ref: 269}, - }, - ref: 108, - }, - }, - postings: []uint64{12, 13, 10, 108}, // 13 doesn't exist and should just be skipped over. - expIdxs: []int{0, 1, 3}, - }, - { - series: []refdSeries{ - { - lset: labels.New([]labels.Label{{"a", "a"}, {"b", "b"}}...), - chunks: []chunks.Meta{ - {Ref: 82}, {Ref: 23}, {Ref: 234}, {Ref: 65}, {Ref: 26}, - }, - ref: 10, - }, - { - lset: labels.New([]labels.Label{{"b", "c"}}...), - chunks: []chunks.Meta{{Ref: 8282}}, - ref: 3, - }, - }, - postings: []uint64{}, - expIdxs: []int{}, - }, - } - - for _, tc := range cases { - mi := newMockIndex() - for _, s := range tc.series { - mi.AddSeries(s.ref, s.lset, s.chunks...) - } - - bcs := &baseChunkSeries{ - p: index.NewListPostings(tc.postings), - index: mi, - tombstones: newMemTombstones(), - } - - i := 0 - for bcs.Next() { - lset, chks, _ := bcs.At() - - idx := tc.expIdxs[i] - - testutil.Equals(t, tc.series[idx].lset, lset) - testutil.Equals(t, tc.series[idx].chunks, chks) - - i++ - } - testutil.Equals(t, len(tc.expIdxs), i) - testutil.Ok(t, bcs.Err()) - } -} - -// TODO: Remove after simpleSeries is merged -type itSeries struct { - si SeriesIterator -} - -func (s itSeries) Iterator() SeriesIterator { return s.si } -func (s itSeries) Labels() labels.Labels { return labels.Labels{} } - -func TestSeriesIterator(t *testing.T) { - itcases := []struct { - a, b, c []tsdbutil.Sample - exp []tsdbutil.Sample - - mint, maxt int64 - }{ - { - a: []tsdbutil.Sample{}, - b: []tsdbutil.Sample{}, - c: []tsdbutil.Sample{}, - - exp: []tsdbutil.Sample{}, - - mint: math.MinInt64, - maxt: math.MaxInt64, - }, - { - a: []tsdbutil.Sample{ - sample{1, 2}, - sample{2, 3}, - sample{3, 5}, - sample{6, 1}, - }, - b: []tsdbutil.Sample{}, - c: []tsdbutil.Sample{ - sample{7, 89}, sample{9, 8}, - }, - - exp: []tsdbutil.Sample{ - sample{1, 2}, sample{2, 3}, sample{3, 5}, sample{6, 1}, sample{7, 89}, sample{9, 8}, - }, - mint: math.MinInt64, - maxt: math.MaxInt64, - }, - { - a: []tsdbutil.Sample{}, - b: []tsdbutil.Sample{ - sample{1, 2}, sample{2, 3}, sample{3, 5}, sample{6, 1}, - }, - c: []tsdbutil.Sample{ - sample{7, 89}, sample{9, 8}, - }, - - exp: []tsdbutil.Sample{ - sample{1, 2}, sample{2, 3}, sample{3, 5}, sample{6, 1}, sample{7, 89}, sample{9, 8}, - }, - mint: 2, - maxt: 8, - }, - { - a: []tsdbutil.Sample{ - sample{1, 2}, sample{2, 3}, sample{3, 5}, sample{6, 1}, - }, - b: []tsdbutil.Sample{ - sample{7, 89}, sample{9, 8}, - }, - c: []tsdbutil.Sample{ - sample{10, 22}, sample{203, 3493}, - }, - - exp: []tsdbutil.Sample{ - sample{1, 2}, sample{2, 3}, sample{3, 5}, sample{6, 1}, sample{7, 89}, sample{9, 8}, sample{10, 22}, sample{203, 3493}, - }, - mint: 6, - maxt: 10, - }, - } - - seekcases := []struct { - a, b, c []tsdbutil.Sample - - seek int64 - success bool - exp []tsdbutil.Sample - - mint, maxt int64 - }{ - { - a: []tsdbutil.Sample{}, - b: []tsdbutil.Sample{}, - c: []tsdbutil.Sample{}, - - seek: 0, - success: false, - exp: nil, - }, - { - a: []tsdbutil.Sample{ - sample{2, 3}, - }, - b: []tsdbutil.Sample{}, - c: []tsdbutil.Sample{ - sample{7, 89}, sample{9, 8}, - }, - - seek: 10, - success: false, - exp: nil, - mint: math.MinInt64, - maxt: math.MaxInt64, - }, - { - a: []tsdbutil.Sample{}, - b: []tsdbutil.Sample{ - sample{1, 2}, sample{3, 5}, sample{6, 1}, - }, - c: []tsdbutil.Sample{ - sample{7, 89}, sample{9, 8}, - }, - - seek: 2, - success: true, - exp: []tsdbutil.Sample{ - sample{3, 5}, sample{6, 1}, sample{7, 89}, sample{9, 8}, - }, - mint: 5, - maxt: 8, - }, - { - a: []tsdbutil.Sample{ - sample{6, 1}, - }, - b: []tsdbutil.Sample{ - sample{9, 8}, - }, - c: []tsdbutil.Sample{ - sample{10, 22}, sample{203, 3493}, - }, - - seek: 10, - success: true, - exp: []tsdbutil.Sample{ - sample{10, 22}, sample{203, 3493}, - }, - mint: 10, - maxt: 203, - }, - { - a: []tsdbutil.Sample{ - sample{6, 1}, - }, - b: []tsdbutil.Sample{ - sample{9, 8}, - }, - c: []tsdbutil.Sample{ - sample{10, 22}, sample{203, 3493}, - }, - - seek: 203, - success: true, - exp: []tsdbutil.Sample{ - sample{203, 3493}, - }, - mint: 7, - maxt: 203, - }, - } - - t.Run("Chunk", func(t *testing.T) { - for _, tc := range itcases { - chkMetas := []chunks.Meta{ - tsdbutil.ChunkFromSamples(tc.a), - tsdbutil.ChunkFromSamples(tc.b), - tsdbutil.ChunkFromSamples(tc.c), - } - res := newChunkSeriesIterator(chkMetas, nil, tc.mint, tc.maxt) - - smplValid := make([]tsdbutil.Sample, 0) - for _, s := range tc.exp { - if s.T() >= tc.mint && s.T() <= tc.maxt { - smplValid = append(smplValid, tsdbutil.Sample(s)) - } - } - exp := newListSeriesIterator(smplValid) - - smplExp, errExp := expandSeriesIterator(exp) - smplRes, errRes := expandSeriesIterator(res) - - testutil.Equals(t, errExp, errRes) - testutil.Equals(t, smplExp, smplRes) - } - - t.Run("Seek", func(t *testing.T) { - extra := []struct { - a, b, c []tsdbutil.Sample - - seek int64 - success bool - exp []tsdbutil.Sample - - mint, maxt int64 - }{ - { - a: []tsdbutil.Sample{ - sample{6, 1}, - }, - b: []tsdbutil.Sample{ - sample{9, 8}, - }, - c: []tsdbutil.Sample{ - sample{10, 22}, sample{203, 3493}, - }, - - seek: 203, - success: false, - exp: nil, - mint: 2, - maxt: 202, - }, - { - a: []tsdbutil.Sample{ - sample{6, 1}, - }, - b: []tsdbutil.Sample{ - sample{9, 8}, - }, - c: []tsdbutil.Sample{ - sample{10, 22}, sample{203, 3493}, - }, - - seek: 5, - success: true, - exp: []tsdbutil.Sample{sample{10, 22}}, - mint: 10, - maxt: 202, - }, - } - - seekcases2 := append(seekcases, extra...) - - for _, tc := range seekcases2 { - chkMetas := []chunks.Meta{ - tsdbutil.ChunkFromSamples(tc.a), - tsdbutil.ChunkFromSamples(tc.b), - tsdbutil.ChunkFromSamples(tc.c), - } - res := newChunkSeriesIterator(chkMetas, nil, tc.mint, tc.maxt) - - smplValid := make([]tsdbutil.Sample, 0) - for _, s := range tc.exp { - if s.T() >= tc.mint && s.T() <= tc.maxt { - smplValid = append(smplValid, tsdbutil.Sample(s)) - } - } - exp := newListSeriesIterator(smplValid) - - testutil.Equals(t, tc.success, res.Seek(tc.seek)) - - if tc.success { - // Init the list and then proceed to check. - remaining := exp.Next() - testutil.Assert(t, remaining == true, "") - - for remaining { - sExp, eExp := exp.At() - sRes, eRes := res.At() - testutil.Equals(t, eExp, eRes) - testutil.Equals(t, sExp, sRes) - - remaining = exp.Next() - testutil.Equals(t, remaining, res.Next()) - } - } - } - }) - }) - - t.Run("Chain", func(t *testing.T) { - // Extra cases for overlapping series. - itcasesExtra := []struct { - a, b, c []tsdbutil.Sample - exp []tsdbutil.Sample - mint, maxt int64 - }{ - { - a: []tsdbutil.Sample{ - sample{1, 2}, sample{2, 3}, sample{3, 5}, sample{6, 1}, - }, - b: []tsdbutil.Sample{ - sample{5, 49}, sample{7, 89}, sample{9, 8}, - }, - c: []tsdbutil.Sample{ - sample{2, 33}, sample{4, 44}, sample{10, 3}, - }, - - exp: []tsdbutil.Sample{ - sample{1, 2}, sample{2, 33}, sample{3, 5}, sample{4, 44}, sample{5, 49}, sample{6, 1}, sample{7, 89}, sample{9, 8}, sample{10, 3}, - }, - mint: math.MinInt64, - maxt: math.MaxInt64, - }, - { - a: []tsdbutil.Sample{ - sample{1, 2}, sample{2, 3}, sample{9, 5}, sample{13, 1}, - }, - b: []tsdbutil.Sample{}, - c: []tsdbutil.Sample{ - sample{1, 23}, sample{2, 342}, sample{3, 25}, sample{6, 11}, - }, - - exp: []tsdbutil.Sample{ - sample{1, 23}, sample{2, 342}, sample{3, 25}, sample{6, 11}, sample{9, 5}, sample{13, 1}, - }, - mint: math.MinInt64, - maxt: math.MaxInt64, - }, - } - - for _, tc := range itcases { - a, b, c := itSeries{newListSeriesIterator(tc.a)}, - itSeries{newListSeriesIterator(tc.b)}, - itSeries{newListSeriesIterator(tc.c)} - - res := newChainedSeriesIterator(a, b, c) - exp := newListSeriesIterator([]tsdbutil.Sample(tc.exp)) - - smplExp, errExp := expandSeriesIterator(exp) - smplRes, errRes := expandSeriesIterator(res) - - testutil.Equals(t, errExp, errRes) - testutil.Equals(t, smplExp, smplRes) - } - - for _, tc := range append(itcases, itcasesExtra...) { - a, b, c := itSeries{newListSeriesIterator(tc.a)}, - itSeries{newListSeriesIterator(tc.b)}, - itSeries{newListSeriesIterator(tc.c)} - - res := newVerticalMergeSeriesIterator(a, b, c) - exp := newListSeriesIterator([]tsdbutil.Sample(tc.exp)) - - smplExp, errExp := expandSeriesIterator(exp) - smplRes, errRes := expandSeriesIterator(res) - - testutil.Equals(t, errExp, errRes) - testutil.Equals(t, smplExp, smplRes) - } - - t.Run("Seek", func(t *testing.T) { - for _, tc := range seekcases { - ress := []SeriesIterator{ - newChainedSeriesIterator( - itSeries{newListSeriesIterator(tc.a)}, - itSeries{newListSeriesIterator(tc.b)}, - itSeries{newListSeriesIterator(tc.c)}, - ), - newVerticalMergeSeriesIterator( - itSeries{newListSeriesIterator(tc.a)}, - itSeries{newListSeriesIterator(tc.b)}, - itSeries{newListSeriesIterator(tc.c)}, - ), - } - - for _, res := range ress { - exp := newListSeriesIterator(tc.exp) - - testutil.Equals(t, tc.success, res.Seek(tc.seek)) - - if tc.success { - // Init the list and then proceed to check. - remaining := exp.Next() - testutil.Assert(t, remaining == true, "") - - for remaining { - sExp, eExp := exp.At() - sRes, eRes := res.At() - testutil.Equals(t, eExp, eRes) - testutil.Equals(t, sExp, sRes) - - remaining = exp.Next() - testutil.Equals(t, remaining, res.Next()) - } - } - } - } - }) - }) -} - -// Regression for: https://github.com/prometheus/tsdb/pull/97 -func TestChunkSeriesIterator_DoubleSeek(t *testing.T) { - chkMetas := []chunks.Meta{ - tsdbutil.ChunkFromSamples([]tsdbutil.Sample{}), - tsdbutil.ChunkFromSamples([]tsdbutil.Sample{sample{1, 1}, sample{2, 2}, sample{3, 3}}), - tsdbutil.ChunkFromSamples([]tsdbutil.Sample{sample{4, 4}, sample{5, 5}}), - } - - res := newChunkSeriesIterator(chkMetas, nil, 2, 8) - testutil.Assert(t, res.Seek(1) == true, "") - testutil.Assert(t, res.Seek(2) == true, "") - ts, v := res.At() - testutil.Equals(t, int64(2), ts) - testutil.Equals(t, float64(2), v) -} - -// Regression when seeked chunks were still found via binary search and we always -// skipped to the end when seeking a value in the current chunk. -func TestChunkSeriesIterator_SeekInCurrentChunk(t *testing.T) { - metas := []chunks.Meta{ - tsdbutil.ChunkFromSamples([]tsdbutil.Sample{}), - tsdbutil.ChunkFromSamples([]tsdbutil.Sample{sample{1, 2}, sample{3, 4}, sample{5, 6}, sample{7, 8}}), - tsdbutil.ChunkFromSamples([]tsdbutil.Sample{}), - } - - it := newChunkSeriesIterator(metas, nil, 1, 7) - - testutil.Assert(t, it.Next() == true, "") - ts, v := it.At() - testutil.Equals(t, int64(1), ts) - testutil.Equals(t, float64(2), v) - - testutil.Assert(t, it.Seek(4) == true, "") - ts, v = it.At() - testutil.Equals(t, int64(5), ts) - testutil.Equals(t, float64(6), v) -} - -// Regression when calling Next() with a time bounded to fit within two samples. -// Seek gets called and advances beyond the max time, which was just accepted as a valid sample. -func TestChunkSeriesIterator_NextWithMinTime(t *testing.T) { - metas := []chunks.Meta{ - tsdbutil.ChunkFromSamples([]tsdbutil.Sample{sample{1, 6}, sample{5, 6}, sample{7, 8}}), - } - - it := newChunkSeriesIterator(metas, nil, 2, 4) - testutil.Assert(t, it.Next() == false, "") -} - -func TestPopulatedCSReturnsValidChunkSlice(t *testing.T) { - lbls := []labels.Labels{labels.New(labels.Label{"a", "b"})} - chunkMetas := [][]chunks.Meta{ - { - {MinTime: 1, MaxTime: 2, Ref: 1}, - {MinTime: 3, MaxTime: 4, Ref: 2}, - {MinTime: 10, MaxTime: 12, Ref: 3}, - }, - } - - cr := mockChunkReader( - map[uint64]chunkenc.Chunk{ - 1: chunkenc.NewXORChunk(), - 2: chunkenc.NewXORChunk(), - 3: chunkenc.NewXORChunk(), - }, - ) - - m := &mockChunkSeriesSet{l: lbls, cm: chunkMetas, i: -1} - p := &populatedChunkSeries{ - set: m, - chunks: cr, - - mint: 0, - maxt: 0, - } - - testutil.Assert(t, p.Next() == false, "") - - p.mint = 6 - p.maxt = 9 - testutil.Assert(t, p.Next() == false, "") - - // Test the case where 1 chunk could cause an unpopulated chunk to be returned. - chunkMetas = [][]chunks.Meta{ - { - {MinTime: 1, MaxTime: 2, Ref: 1}, - }, - } - - m = &mockChunkSeriesSet{l: lbls, cm: chunkMetas, i: -1} - p = &populatedChunkSeries{ - set: m, - chunks: cr, - - mint: 10, - maxt: 15, - } - testutil.Assert(t, p.Next() == false, "") -} - -type mockChunkSeriesSet struct { - l []labels.Labels - cm [][]chunks.Meta - - i int -} - -func (m *mockChunkSeriesSet) Next() bool { - if len(m.l) != len(m.cm) { - return false - } - m.i++ - return m.i < len(m.l) -} - -func (m *mockChunkSeriesSet) At() (labels.Labels, []chunks.Meta, Intervals) { - return m.l[m.i], m.cm[m.i], nil -} - -func (m *mockChunkSeriesSet) Err() error { - return nil -} - -// Test the cost of merging series sets for different number of merged sets and their size. -// The subset are all equivalent so this does not capture merging of partial or non-overlapping sets well. -func BenchmarkMergedSeriesSet(b *testing.B) { - var sel func(sets []SeriesSet) SeriesSet - - sel = func(sets []SeriesSet) SeriesSet { - if len(sets) == 0 { - return EmptySeriesSet() - } - if len(sets) == 1 { - return sets[0] - } - l := len(sets) / 2 - return newMergedSeriesSet(sel(sets[:l]), sel(sets[l:])) - } - - for _, k := range []int{ - 100, - 1000, - 10000, - 20000, - } { - for _, j := range []int{1, 2, 4, 8, 16, 32} { - b.Run(fmt.Sprintf("series=%d,blocks=%d", k, j), func(b *testing.B) { - lbls, err := labels.ReadLabels(filepath.Join("testdata", "20kseries.json"), k) - testutil.Ok(b, err) - - sort.Sort(labels.Slice(lbls)) - - in := make([][]Series, j) - - for _, l := range lbls { - l2 := l - for j := range in { - in[j] = append(in[j], &mockSeries{labels: func() labels.Labels { return l2 }}) - } - } - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - var sets []SeriesSet - for _, s := range in { - sets = append(sets, newMockSeriesSet(s)) - } - ms := sel(sets) - - i := 0 - for ms.Next() { - i++ - } - testutil.Ok(b, ms.Err()) - testutil.Equals(b, len(lbls), i) - } - }) - } - } -} - -func BenchmarkPersistedQueries(b *testing.B) { - for _, nSeries := range []int{10, 100} { - for _, nSamples := range []int64{1000, 10000, 100000} { - b.Run(fmt.Sprintf("series=%d,samplesPerSeries=%d", nSeries, nSamples), func(b *testing.B) { - dir, err := ioutil.TempDir("", "bench_persisted") - testutil.Ok(b, err) - defer os.RemoveAll(dir) - - block, err := OpenBlock(nil, createBlock(b, dir, genSeries(nSeries, 10, 1, int64(nSamples))), nil) - testutil.Ok(b, err) - defer block.Close() - - q, err := NewBlockQuerier(block, block.Meta().MinTime, block.Meta().MaxTime) - testutil.Ok(b, err) - defer q.Close() - - b.ResetTimer() - b.ReportAllocs() - - for i := 0; i < b.N; i++ { - ss, err := q.Select(labels.NewMustRegexpMatcher("__name__", ".+")) - for ss.Next() { - s := ss.At() - s.Labels() - it := s.Iterator() - for it.Next() { - } - testutil.Ok(b, it.Err()) - } - testutil.Ok(b, ss.Err()) - testutil.Ok(b, err) - } - }) - } - } -} - -type mockChunkReader map[uint64]chunkenc.Chunk - -func (cr mockChunkReader) Chunk(id uint64) (chunkenc.Chunk, error) { - chk, ok := cr[id] - if ok { - return chk, nil - } - - return nil, errors.New("Chunk with ref not found") -} - -func (cr mockChunkReader) Close() error { - return nil -} - -func TestDeletedIterator(t *testing.T) { - chk := chunkenc.NewXORChunk() - app, err := chk.Appender() - testutil.Ok(t, err) - // Insert random stuff from (0, 1000). - act := make([]sample, 1000) - for i := 0; i < 1000; i++ { - act[i].t = int64(i) - act[i].v = rand.Float64() - app.Append(act[i].t, act[i].v) - } - - cases := []struct { - r Intervals - }{ - {r: Intervals{{1, 20}}}, - {r: Intervals{{1, 10}, {12, 20}, {21, 23}, {25, 30}}}, - {r: Intervals{{1, 10}, {12, 20}, {20, 30}}}, - {r: Intervals{{1, 10}, {12, 23}, {25, 30}}}, - {r: Intervals{{1, 23}, {12, 20}, {25, 30}}}, - {r: Intervals{{1, 23}, {12, 20}, {25, 3000}}}, - {r: Intervals{{0, 2000}}}, - {r: Intervals{{500, 2000}}}, - {r: Intervals{{0, 200}}}, - {r: Intervals{{1000, 20000}}}, - } - - for _, c := range cases { - i := int64(-1) - it := &deletedIterator{it: chk.Iterator(), intervals: c.r[:]} - ranges := c.r[:] - for it.Next() { - i++ - for _, tr := range ranges { - if tr.inBounds(i) { - i = tr.Maxt + 1 - ranges = ranges[1:] - } - } - - testutil.Assert(t, i < 1000, "") - - ts, v := it.At() - testutil.Equals(t, act[i].t, ts) - testutil.Equals(t, act[i].v, v) - } - // There has been an extra call to Next(). - i++ - for _, tr := range ranges { - if tr.inBounds(i) { - i = tr.Maxt + 1 - ranges = ranges[1:] - } - } - - testutil.Assert(t, i >= 1000, "") - testutil.Ok(t, it.Err()) - } -} - -type series struct { - l labels.Labels - chunks []chunks.Meta -} - -type mockIndex struct { - series map[uint64]series - labelIndex map[string][]string - postings map[labels.Label][]uint64 - symbols map[string]struct{} -} - -func newMockIndex() mockIndex { - ix := mockIndex{ - series: make(map[uint64]series), - labelIndex: make(map[string][]string), - postings: make(map[labels.Label][]uint64), - symbols: make(map[string]struct{}), - } - return ix -} - -func (m mockIndex) Symbols() (map[string]struct{}, error) { - return m.symbols, nil -} - -func (m mockIndex) AddSeries(ref uint64, l labels.Labels, chunks ...chunks.Meta) error { - if _, ok := m.series[ref]; ok { - return errors.Errorf("series with reference %d already added", ref) - } - for _, lbl := range l { - m.symbols[lbl.Name] = struct{}{} - m.symbols[lbl.Value] = struct{}{} - } - - s := series{l: l} - // Actual chunk data is not stored in the index. - for _, c := range chunks { - c.Chunk = nil - s.chunks = append(s.chunks, c) - } - m.series[ref] = s - - return nil -} - -func (m mockIndex) WriteLabelIndex(names []string, values []string) error { - // TODO support composite indexes - if len(names) != 1 { - return errors.New("composite indexes not supported yet") - } - sort.Strings(values) - m.labelIndex[names[0]] = values - return nil -} - -func (m mockIndex) WritePostings(name, value string, it index.Postings) error { - l := labels.Label{Name: name, Value: value} - if _, ok := m.postings[l]; ok { - return errors.Errorf("postings for %s already added", l) - } - ep, err := index.ExpandPostings(it) - if err != nil { - return err - } - m.postings[l] = ep - return nil -} - -func (m mockIndex) Close() error { - return nil -} - -func (m mockIndex) LabelValues(names ...string) (index.StringTuples, error) { - // TODO support composite indexes - if len(names) != 1 { - return nil, errors.New("composite indexes not supported yet") - } - - return index.NewStringTuples(m.labelIndex[names[0]], 1) -} - -func (m mockIndex) Postings(name, value string) (index.Postings, error) { - l := labels.Label{Name: name, Value: value} - return index.NewListPostings(m.postings[l]), nil -} - -func (m mockIndex) SortedPostings(p index.Postings) index.Postings { - ep, err := index.ExpandPostings(p) - if err != nil { - return index.ErrPostings(errors.Wrap(err, "expand postings")) - } - - sort.Slice(ep, func(i, j int) bool { - return labels.Compare(m.series[ep[i]].l, m.series[ep[j]].l) < 0 - }) - return index.NewListPostings(ep) -} - -func (m mockIndex) Series(ref uint64, lset *labels.Labels, chks *[]chunks.Meta) error { - s, ok := m.series[ref] - if !ok { - return ErrNotFound - } - *lset = append((*lset)[:0], s.l...) - *chks = append((*chks)[:0], s.chunks...) - - return nil -} - -func (m mockIndex) LabelIndices() ([][]string, error) { - res := make([][]string, 0, len(m.labelIndex)) - for k := range m.labelIndex { - res = append(res, []string{k}) - } - return res, nil -} - -func (m mockIndex) LabelNames() ([]string, error) { - labelNames := make([]string, 0, len(m.labelIndex)) - for name := range m.labelIndex { - labelNames = append(labelNames, name) - } - sort.Strings(labelNames) - return labelNames, nil -} - -type mockSeries struct { - labels func() labels.Labels - iterator func() SeriesIterator -} - -func newSeries(l map[string]string, s []tsdbutil.Sample) Series { - return &mockSeries{ - labels: func() labels.Labels { return labels.FromMap(l) }, - iterator: func() SeriesIterator { return newListSeriesIterator(s) }, - } -} -func (m *mockSeries) Labels() labels.Labels { return m.labels() } -func (m *mockSeries) Iterator() SeriesIterator { return m.iterator() } - -type listSeriesIterator struct { - list []tsdbutil.Sample - idx int -} - -func newListSeriesIterator(list []tsdbutil.Sample) *listSeriesIterator { - return &listSeriesIterator{list: list, idx: -1} -} - -func (it *listSeriesIterator) At() (int64, float64) { - s := it.list[it.idx] - return s.T(), s.V() -} - -func (it *listSeriesIterator) Next() bool { - it.idx++ - return it.idx < len(it.list) -} - -func (it *listSeriesIterator) Seek(t int64) bool { - if it.idx == -1 { - it.idx = 0 - } - // Do binary search between current position and end. - it.idx = sort.Search(len(it.list)-it.idx, func(i int) bool { - s := it.list[i+it.idx] - return s.T() >= t - }) - - return it.idx < len(it.list) -} - -func (it *listSeriesIterator) Err() error { - return nil -} - -func BenchmarkQueryIterator(b *testing.B) { - cases := []struct { - numBlocks int - numSeries int - numSamplesPerSeriesPerBlock int - overlapPercentages []int // >=0, <=100, this is w.r.t. the previous block. - }{ - { - numBlocks: 20, - numSeries: 1000, - numSamplesPerSeriesPerBlock: 20000, - overlapPercentages: []int{0, 10, 30}, - }, - } - - for _, c := range cases { - for _, overlapPercentage := range c.overlapPercentages { - benchMsg := fmt.Sprintf("nBlocks=%d,nSeries=%d,numSamplesPerSeriesPerBlock=%d,overlap=%d%%", - c.numBlocks, c.numSeries, c.numSamplesPerSeriesPerBlock, overlapPercentage) - - b.Run(benchMsg, func(b *testing.B) { - dir, err := ioutil.TempDir("", "bench_query_iterator") - testutil.Ok(b, err) - defer func() { - testutil.Ok(b, os.RemoveAll(dir)) - }() - - var ( - blocks []*Block - overlapDelta = int64(overlapPercentage * c.numSamplesPerSeriesPerBlock / 100) - prefilledLabels []map[string]string - generatedSeries []Series - ) - for i := int64(0); i < int64(c.numBlocks); i++ { - offset := i * overlapDelta - mint := i*int64(c.numSamplesPerSeriesPerBlock) - offset - maxt := mint + int64(c.numSamplesPerSeriesPerBlock) - 1 - if len(prefilledLabels) == 0 { - generatedSeries = genSeries(c.numSeries, 10, mint, maxt) - for _, s := range generatedSeries { - prefilledLabels = append(prefilledLabels, s.Labels().Map()) - } - } else { - generatedSeries = populateSeries(prefilledLabels, mint, maxt) - } - block, err := OpenBlock(nil, createBlock(b, dir, generatedSeries), nil) - testutil.Ok(b, err) - blocks = append(blocks, block) - defer block.Close() - } - - que := &querier{ - blocks: make([]Querier, 0, len(blocks)), - } - for _, blk := range blocks { - q, err := NewBlockQuerier(blk, math.MinInt64, math.MaxInt64) - testutil.Ok(b, err) - que.blocks = append(que.blocks, q) - } - - var sq Querier = que - if overlapPercentage > 0 { - sq = &verticalQuerier{ - querier: *que, - } - } - defer sq.Close() - - b.ResetTimer() - b.ReportAllocs() - - ss, err := sq.Select(labels.NewMustRegexpMatcher("__name__", ".*")) - testutil.Ok(b, err) - for ss.Next() { - it := ss.At().Iterator() - for it.Next() { - } - testutil.Ok(b, it.Err()) - } - testutil.Ok(b, ss.Err()) - testutil.Ok(b, err) - }) - } - } -} - -func BenchmarkQuerySeek(b *testing.B) { - cases := []struct { - numBlocks int - numSeries int - numSamplesPerSeriesPerBlock int - overlapPercentages []int // >=0, <=100, this is w.r.t. the previous block. - }{ - { - numBlocks: 20, - numSeries: 100, - numSamplesPerSeriesPerBlock: 2000, - overlapPercentages: []int{0, 10, 30, 50}, - }, - } - - for _, c := range cases { - for _, overlapPercentage := range c.overlapPercentages { - benchMsg := fmt.Sprintf("nBlocks=%d,nSeries=%d,numSamplesPerSeriesPerBlock=%d,overlap=%d%%", - c.numBlocks, c.numSeries, c.numSamplesPerSeriesPerBlock, overlapPercentage) - - b.Run(benchMsg, func(b *testing.B) { - dir, err := ioutil.TempDir("", "bench_query_iterator") - testutil.Ok(b, err) - defer func() { - testutil.Ok(b, os.RemoveAll(dir)) - }() - - var ( - blocks []*Block - overlapDelta = int64(overlapPercentage * c.numSamplesPerSeriesPerBlock / 100) - prefilledLabels []map[string]string - generatedSeries []Series - ) - for i := int64(0); i < int64(c.numBlocks); i++ { - offset := i * overlapDelta - mint := i*int64(c.numSamplesPerSeriesPerBlock) - offset - maxt := mint + int64(c.numSamplesPerSeriesPerBlock) - 1 - if len(prefilledLabels) == 0 { - generatedSeries = genSeries(c.numSeries, 10, mint, maxt) - for _, s := range generatedSeries { - prefilledLabels = append(prefilledLabels, s.Labels().Map()) - } - } else { - generatedSeries = populateSeries(prefilledLabels, mint, maxt) - } - block, err := OpenBlock(nil, createBlock(b, dir, generatedSeries), nil) - testutil.Ok(b, err) - blocks = append(blocks, block) - defer block.Close() - } - - que := &querier{ - blocks: make([]Querier, 0, len(blocks)), - } - for _, blk := range blocks { - q, err := NewBlockQuerier(blk, math.MinInt64, math.MaxInt64) - testutil.Ok(b, err) - que.blocks = append(que.blocks, q) - } - - var sq Querier = que - if overlapPercentage > 0 { - sq = &verticalQuerier{ - querier: *que, - } - } - defer sq.Close() - - mint := blocks[0].meta.MinTime - maxt := blocks[len(blocks)-1].meta.MaxTime - - b.ResetTimer() - b.ReportAllocs() - - ss, err := sq.Select(labels.NewMustRegexpMatcher("__name__", ".*")) - for ss.Next() { - it := ss.At().Iterator() - for t := mint; t <= maxt; t++ { - it.Seek(t) - } - testutil.Ok(b, it.Err()) - } - testutil.Ok(b, ss.Err()) - testutil.Ok(b, err) - }) - } - } -} diff --git a/vendor/github.com/prometheus/tsdb/record.go b/vendor/github.com/prometheus/tsdb/record.go index 8d9c5751d..364e8144d 100644 --- a/vendor/github.com/prometheus/tsdb/record.go +++ b/vendor/github.com/prometheus/tsdb/record.go @@ -19,7 +19,6 @@ import ( "sort" "github.com/pkg/errors" - "github.com/prometheus/tsdb/encoding" "github.com/prometheus/tsdb/labels" ) @@ -57,19 +56,19 @@ func (d *RecordDecoder) Type(rec []byte) RecordType { // Series appends series in rec to the given slice. func (d *RecordDecoder) Series(rec []byte, series []RefSeries) ([]RefSeries, error) { - dec := encoding.Decbuf{B: rec} + dec := decbuf{b: rec} - if RecordType(dec.Byte()) != RecordSeries { + if RecordType(dec.byte()) != RecordSeries { return nil, errors.New("invalid record type") } - for len(dec.B) > 0 && dec.Err() == nil { - ref := dec.Be64() + for len(dec.b) > 0 && dec.err() == nil { + ref := dec.be64() - lset := make(labels.Labels, dec.Uvarint()) + lset := make(labels.Labels, dec.uvarint()) for i := range lset { - lset[i].Name = dec.UvarintStr() - lset[i].Value = dec.UvarintStr() + lset[i].Name = dec.uvarintStr() + lset[i].Value = dec.uvarintStr() } sort.Sort(lset) @@ -78,33 +77,33 @@ func (d *RecordDecoder) Series(rec []byte, series []RefSeries) ([]RefSeries, err Labels: lset, }) } - if dec.Err() != nil { - return nil, dec.Err() + if dec.err() != nil { + return nil, dec.err() } - if len(dec.B) > 0 { - return nil, errors.Errorf("unexpected %d bytes left in entry", len(dec.B)) + if len(dec.b) > 0 { + return nil, errors.Errorf("unexpected %d bytes left in entry", len(dec.b)) } return series, nil } // Samples appends samples in rec to the given slice. func (d *RecordDecoder) Samples(rec []byte, samples []RefSample) ([]RefSample, error) { - dec := encoding.Decbuf{B: rec} + dec := decbuf{b: rec} - if RecordType(dec.Byte()) != RecordSamples { + if RecordType(dec.byte()) != RecordSamples { return nil, errors.New("invalid record type") } - if dec.Len() == 0 { + if dec.len() == 0 { return samples, nil } var ( - baseRef = dec.Be64() - baseTime = dec.Be64int64() + baseRef = dec.be64() + baseTime = dec.be64int64() ) - for len(dec.B) > 0 && dec.Err() == nil { - dref := dec.Varint64() - dtime := dec.Varint64() - val := dec.Be64() + for len(dec.b) > 0 && dec.err() == nil { + dref := dec.varint64() + dtime := dec.varint64() + val := dec.be64() samples = append(samples, RefSample{ Ref: uint64(int64(baseRef) + dref), @@ -113,35 +112,35 @@ func (d *RecordDecoder) Samples(rec []byte, samples []RefSample) ([]RefSample, e }) } - if dec.Err() != nil { - return nil, errors.Wrapf(dec.Err(), "decode error after %d samples", len(samples)) + if dec.err() != nil { + return nil, errors.Wrapf(dec.err(), "decode error after %d samples", len(samples)) } - if len(dec.B) > 0 { - return nil, errors.Errorf("unexpected %d bytes left in entry", len(dec.B)) + if len(dec.b) > 0 { + return nil, errors.Errorf("unexpected %d bytes left in entry", len(dec.b)) } return samples, nil } // Tombstones appends tombstones in rec to the given slice. func (d *RecordDecoder) Tombstones(rec []byte, tstones []Stone) ([]Stone, error) { - dec := encoding.Decbuf{B: rec} + dec := decbuf{b: rec} - if RecordType(dec.Byte()) != RecordTombstones { + if RecordType(dec.byte()) != RecordTombstones { return nil, errors.New("invalid record type") } - for dec.Len() > 0 && dec.Err() == nil { + for dec.len() > 0 && dec.err() == nil { tstones = append(tstones, Stone{ - ref: dec.Be64(), + ref: dec.be64(), intervals: Intervals{ - {Mint: dec.Varint64(), Maxt: dec.Varint64()}, + {Mint: dec.varint64(), Maxt: dec.varint64()}, }, }) } - if dec.Err() != nil { - return nil, dec.Err() + if dec.err() != nil { + return nil, dec.err() } - if len(dec.B) > 0 { - return nil, errors.Errorf("unexpected %d bytes left in entry", len(dec.B)) + if len(dec.b) > 0 { + return nil, errors.Errorf("unexpected %d bytes left in entry", len(dec.b)) } return tstones, nil } @@ -153,56 +152,56 @@ type RecordEncoder struct { // Series appends the encoded series to b and returns the resulting slice. func (e *RecordEncoder) Series(series []RefSeries, b []byte) []byte { - buf := encoding.Encbuf{B: b} - buf.PutByte(byte(RecordSeries)) + buf := encbuf{b: b} + buf.putByte(byte(RecordSeries)) for _, s := range series { - buf.PutBE64(s.Ref) - buf.PutUvarint(len(s.Labels)) + buf.putBE64(s.Ref) + buf.putUvarint(len(s.Labels)) for _, l := range s.Labels { - buf.PutUvarintStr(l.Name) - buf.PutUvarintStr(l.Value) + buf.putUvarintStr(l.Name) + buf.putUvarintStr(l.Value) } } - return buf.Get() + return buf.get() } // Samples appends the encoded samples to b and returns the resulting slice. func (e *RecordEncoder) Samples(samples []RefSample, b []byte) []byte { - buf := encoding.Encbuf{B: b} - buf.PutByte(byte(RecordSamples)) + buf := encbuf{b: b} + buf.putByte(byte(RecordSamples)) if len(samples) == 0 { - return buf.Get() + return buf.get() } // Store base timestamp and base reference number of first sample. // All samples encode their timestamp and ref as delta to those. first := samples[0] - buf.PutBE64(first.Ref) - buf.PutBE64int64(first.T) + buf.putBE64(first.Ref) + buf.putBE64int64(first.T) for _, s := range samples { - buf.PutVarint64(int64(s.Ref) - int64(first.Ref)) - buf.PutVarint64(s.T - first.T) - buf.PutBE64(math.Float64bits(s.V)) + buf.putVarint64(int64(s.Ref) - int64(first.Ref)) + buf.putVarint64(s.T - first.T) + buf.putBE64(math.Float64bits(s.V)) } - return buf.Get() + return buf.get() } // Tombstones appends the encoded tombstones to b and returns the resulting slice. func (e *RecordEncoder) Tombstones(tstones []Stone, b []byte) []byte { - buf := encoding.Encbuf{B: b} - buf.PutByte(byte(RecordTombstones)) + buf := encbuf{b: b} + buf.putByte(byte(RecordTombstones)) for _, s := range tstones { for _, iv := range s.intervals { - buf.PutBE64(s.ref) - buf.PutVarint64(iv.Mint) - buf.PutVarint64(iv.Maxt) + buf.putBE64(s.ref) + buf.putVarint64(iv.Mint) + buf.putVarint64(iv.Maxt) } } - return buf.Get() + return buf.get() } diff --git a/vendor/github.com/prometheus/tsdb/record_test.go b/vendor/github.com/prometheus/tsdb/record_test.go deleted file mode 100644 index 8316ccf3a..000000000 --- a/vendor/github.com/prometheus/tsdb/record_test.go +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2018 The Prometheus Authors - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tsdb - -import ( - "testing" - - "github.com/pkg/errors" - "github.com/prometheus/tsdb/encoding" - "github.com/prometheus/tsdb/labels" - "github.com/prometheus/tsdb/testutil" -) - -func TestRecord_EncodeDecode(t *testing.T) { - var enc RecordEncoder - var dec RecordDecoder - - series := []RefSeries{ - { - Ref: 100, - Labels: labels.FromStrings("abc", "def", "123", "456"), - }, { - Ref: 1, - Labels: labels.FromStrings("abc", "def2", "1234", "4567"), - }, { - Ref: 435245, - Labels: labels.FromStrings("xyz", "def", "foo", "bar"), - }, - } - decSeries, err := dec.Series(enc.Series(series, nil), nil) - testutil.Ok(t, err) - testutil.Equals(t, series, decSeries) - - samples := []RefSample{ - {Ref: 0, T: 12423423, V: 1.2345}, - {Ref: 123, T: -1231, V: -123}, - {Ref: 2, T: 0, V: 99999}, - } - decSamples, err := dec.Samples(enc.Samples(samples, nil), nil) - testutil.Ok(t, err) - testutil.Equals(t, samples, decSamples) - - // Intervals get split up into single entries. So we don't get back exactly - // what we put in. - tstones := []Stone{ - {ref: 123, intervals: Intervals{ - {Mint: -1000, Maxt: 1231231}, - {Mint: 5000, Maxt: 0}, - }}, - {ref: 13, intervals: Intervals{ - {Mint: -1000, Maxt: -11}, - {Mint: 5000, Maxt: 1000}, - }}, - } - decTstones, err := dec.Tombstones(enc.Tombstones(tstones, nil), nil) - testutil.Ok(t, err) - testutil.Equals(t, []Stone{ - {ref: 123, intervals: Intervals{{Mint: -1000, Maxt: 1231231}}}, - {ref: 123, intervals: Intervals{{Mint: 5000, Maxt: 0}}}, - {ref: 13, intervals: Intervals{{Mint: -1000, Maxt: -11}}}, - {ref: 13, intervals: Intervals{{Mint: 5000, Maxt: 1000}}}, - }, decTstones) -} - -// TestRecord_Corruputed ensures that corrupted records return the correct error. -// Bugfix check for pull/521 and pull/523. -func TestRecord_Corruputed(t *testing.T) { - var enc RecordEncoder - var dec RecordDecoder - - t.Run("Test corrupted series record", func(t *testing.T) { - series := []RefSeries{ - { - Ref: 100, - Labels: labels.FromStrings("abc", "def", "123", "456"), - }, - } - - corrupted := enc.Series(series, nil)[:8] - _, err := dec.Series(corrupted, nil) - testutil.Equals(t, err, encoding.ErrInvalidSize) - }) - - t.Run("Test corrupted sample record", func(t *testing.T) { - samples := []RefSample{ - {Ref: 0, T: 12423423, V: 1.2345}, - } - - corrupted := enc.Samples(samples, nil)[:8] - _, err := dec.Samples(corrupted, nil) - testutil.Equals(t, errors.Cause(err), encoding.ErrInvalidSize) - }) - - t.Run("Test corrupted tombstone record", func(t *testing.T) { - tstones := []Stone{ - {ref: 123, intervals: Intervals{ - {Mint: -1000, Maxt: 1231231}, - {Mint: 5000, Maxt: 0}, - }}, - } - - corrupted := enc.Tombstones(tstones, nil)[:8] - _, err := dec.Tombstones(corrupted, nil) - testutil.Equals(t, err, encoding.ErrInvalidSize) - }) -} diff --git a/vendor/github.com/prometheus/tsdb/repair.go b/vendor/github.com/prometheus/tsdb/repair.go index 4aeffb554..15f79d5f7 100644 --- a/vendor/github.com/prometheus/tsdb/repair.go +++ b/vendor/github.com/prometheus/tsdb/repair.go @@ -64,7 +64,7 @@ func repairBadIndexVersion(logger log.Logger, dir string) error { if err != nil { return wrapErr(err, d) } - broken, err := os.Open(filepath.Join(d, indexFilename)) + broken, err := os.Open(filepath.Join(d, "index")) if err != nil { return wrapErr(err, d) } diff --git a/vendor/github.com/prometheus/tsdb/repair_test.go b/vendor/github.com/prometheus/tsdb/repair_test.go deleted file mode 100644 index cbe21691e..000000000 --- a/vendor/github.com/prometheus/tsdb/repair_test.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2018 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tsdb - -import ( - "os" - "path/filepath" - "testing" - - "github.com/prometheus/tsdb/chunks" - "github.com/prometheus/tsdb/fileutil" - "github.com/prometheus/tsdb/index" - "github.com/prometheus/tsdb/labels" - "github.com/prometheus/tsdb/testutil" -) - -func TestRepairBadIndexVersion(t *testing.T) { - // The broken index used in this test was written by the following script - // at a broken revision. - // - // func main() { - // w, err := index.NewWriter(indexFilename) - // if err != nil { - // panic(err) - // } - // err = w.AddSymbols(map[string]struct{}{ - // "a": struct{}{}, - // "b": struct{}{}, - // "1": struct{}{}, - // "2": struct{}{}, - // }) - // if err != nil { - // panic(err) - // } - // err = w.AddSeries(1, labels.FromStrings("a", "1", "b", "1")) - // if err != nil { - // panic(err) - // } - // err = w.AddSeries(2, labels.FromStrings("a", "2", "b", "1")) - // if err != nil { - // panic(err) - // } - // err = w.WritePostings("b", "1", index.NewListPostings([]uint64{1, 2})) - // if err != nil { - // panic(err) - // } - // if err := w.Close(); err != nil { - // panic(err) - // } - // } - dbDir := filepath.Join("testdata", "repair_index_version", "01BZJ9WJQPWHGNC2W4J9TA62KC") - tmpDir := filepath.Join("testdata", "repair_index_version", "copy") - tmpDbDir := filepath.Join(tmpDir, "3MCNSQ8S31EHGJYWK5E1GPJWJZ") - - // Check the current db. - // In its current state, lookups should fail with the fixed code. - _, err := readMetaFile(dbDir) - testutil.NotOk(t, err) - - // Touch chunks dir in block. - os.MkdirAll(filepath.Join(dbDir, "chunks"), 0777) - defer os.RemoveAll(filepath.Join(dbDir, "chunks")) - - r, err := index.NewFileReader(filepath.Join(dbDir, indexFilename)) - testutil.Ok(t, err) - p, err := r.Postings("b", "1") - testutil.Ok(t, err) - for p.Next() { - t.Logf("next ID %d", p.At()) - - var lset labels.Labels - testutil.NotOk(t, r.Series(p.At(), &lset, nil)) - } - testutil.Ok(t, p.Err()) - testutil.Ok(t, r.Close()) - - // Create a copy DB to run test against. - if err = fileutil.CopyDirs(dbDir, tmpDbDir); err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpDir) - // On DB opening all blocks in the base dir should be repaired. - db, err := Open(tmpDir, nil, nil, nil) - testutil.Ok(t, err) - db.Close() - - r, err = index.NewFileReader(filepath.Join(tmpDbDir, indexFilename)) - testutil.Ok(t, err) - p, err = r.Postings("b", "1") - testutil.Ok(t, err) - res := []labels.Labels{} - - for p.Next() { - t.Logf("next ID %d", p.At()) - - var lset labels.Labels - var chks []chunks.Meta - testutil.Ok(t, r.Series(p.At(), &lset, &chks)) - res = append(res, lset) - } - - testutil.Ok(t, p.Err()) - testutil.Equals(t, []labels.Labels{ - {{"a", "1"}, {"b", "1"}}, - {{"a", "2"}, {"b", "1"}}, - }, res) - - meta, err := readMetaFile(tmpDbDir) - testutil.Ok(t, err) - testutil.Assert(t, meta.Version == 1, "unexpected meta version %d", meta.Version) -} diff --git a/vendor/github.com/prometheus/tsdb/staticcheck.conf b/vendor/github.com/prometheus/tsdb/staticcheck.conf new file mode 100644 index 000000000..3266a2e29 --- /dev/null +++ b/vendor/github.com/prometheus/tsdb/staticcheck.conf @@ -0,0 +1,2 @@ +# Enable only "legacy" staticcheck verifications. +checks = [ "SA*" ] diff --git a/vendor/github.com/prometheus/tsdb/tombstones.go b/vendor/github.com/prometheus/tsdb/tombstones.go index 4c36c7b2a..078140406 100644 --- a/vendor/github.com/prometheus/tsdb/tombstones.go +++ b/vendor/github.com/prometheus/tsdb/tombstones.go @@ -23,7 +23,6 @@ import ( "sync" "github.com/pkg/errors" - "github.com/prometheus/tsdb/encoding" ) const tombstoneFilename = "tombstones" @@ -65,12 +64,12 @@ func writeTombstoneFile(dir string, tr TombstoneReader) error { } }() - buf := encoding.Encbuf{B: make([]byte, 3*binary.MaxVarintLen64)} - buf.Reset() + buf := encbuf{b: make([]byte, 3*binary.MaxVarintLen64)} + buf.reset() // Write the meta. - buf.PutBE32(MagicTombstone) - buf.PutByte(tombstoneFormatV1) - _, err = f.Write(buf.Get()) + buf.putBE32(MagicTombstone) + buf.putByte(tombstoneFormatV1) + _, err = f.Write(buf.get()) if err != nil { return err } @@ -79,13 +78,13 @@ func writeTombstoneFile(dir string, tr TombstoneReader) error { if err := tr.Iter(func(ref uint64, ivs Intervals) error { for _, iv := range ivs { - buf.Reset() + buf.reset() - buf.PutUvarint64(ref) - buf.PutVarint64(iv.Mint) - buf.PutVarint64(iv.Maxt) + buf.putUvarint64(ref) + buf.putVarint64(iv.Mint) + buf.putVarint64(iv.Maxt) - _, err = mw.Write(buf.Get()) + _, err = mw.Write(buf.get()) if err != nil { return err } @@ -127,24 +126,24 @@ func readTombstones(dir string) (TombstoneReader, SizeReader, error) { } if len(b) < 5 { - return nil, sr, errors.Wrap(encoding.ErrInvalidSize, "tombstones header") + return nil, sr, errors.Wrap(errInvalidSize, "tombstones header") } - d := &encoding.Decbuf{B: b[:len(b)-4]} // 4 for the checksum. - if mg := d.Be32(); mg != MagicTombstone { + d := &decbuf{b: b[:len(b)-4]} // 4 for the checksum. + if mg := d.be32(); mg != MagicTombstone { return nil, sr, fmt.Errorf("invalid magic number %x", mg) } - if flag := d.Byte(); flag != tombstoneFormatV1 { + if flag := d.byte(); flag != tombstoneFormatV1 { return nil, sr, fmt.Errorf("invalid tombstone format %x", flag) } - if d.Err() != nil { - return nil, sr, d.Err() + if d.err() != nil { + return nil, sr, d.err() } // Verify checksum. hash := newCRC32() - if _, err := hash.Write(d.Get()); err != nil { + if _, err := hash.Write(d.get()); err != nil { return nil, sr, errors.Wrap(err, "write to hash") } if binary.BigEndian.Uint32(b[len(b)-4:]) != hash.Sum32() { @@ -153,12 +152,12 @@ func readTombstones(dir string) (TombstoneReader, SizeReader, error) { stonesMap := newMemTombstones() - for d.Len() > 0 { - k := d.Uvarint64() - mint := d.Varint64() - maxt := d.Varint64() - if d.Err() != nil { - return nil, sr, d.Err() + for d.len() > 0 { + k := d.uvarint64() + mint := d.varint64() + maxt := d.varint64() + if d.err() != nil { + return nil, sr, d.err() } stonesMap.addInterval(k, Interval{mint, maxt}) diff --git a/vendor/github.com/prometheus/tsdb/tombstones_test.go b/vendor/github.com/prometheus/tsdb/tombstones_test.go deleted file mode 100644 index 95ef42f8f..000000000 --- a/vendor/github.com/prometheus/tsdb/tombstones_test.go +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tsdb - -import ( - "io/ioutil" - "math/rand" - "os" - "sync" - "testing" - "time" - - "github.com/prometheus/tsdb/testutil" -) - -func TestWriteAndReadbackTombStones(t *testing.T) { - tmpdir, _ := ioutil.TempDir("", "test") - defer os.RemoveAll(tmpdir) - - ref := uint64(0) - - stones := newMemTombstones() - // Generate the tombstones. - for i := 0; i < 100; i++ { - ref += uint64(rand.Int31n(10)) + 1 - numRanges := rand.Intn(5) + 1 - dranges := make(Intervals, 0, numRanges) - mint := rand.Int63n(time.Now().UnixNano()) - for j := 0; j < numRanges; j++ { - dranges = dranges.add(Interval{mint, mint + rand.Int63n(1000)}) - mint += rand.Int63n(1000) + 1 - } - stones.addInterval(ref, dranges...) - } - - testutil.Ok(t, writeTombstoneFile(tmpdir, stones)) - - restr, _, err := readTombstones(tmpdir) - testutil.Ok(t, err) - - // Compare the two readers. - testutil.Equals(t, stones, restr) -} - -func TestAddingNewIntervals(t *testing.T) { - cases := []struct { - exist Intervals - new Interval - - exp Intervals - }{ - { - new: Interval{1, 2}, - exp: Intervals{{1, 2}}, - }, - { - exist: Intervals{{1, 2}}, - new: Interval{1, 2}, - exp: Intervals{{1, 2}}, - }, - { - exist: Intervals{{1, 4}, {6, 6}}, - new: Interval{5, 6}, - exp: Intervals{{1, 6}}, - }, - { - exist: Intervals{{1, 10}, {12, 20}, {25, 30}}, - new: Interval{21, 23}, - exp: Intervals{{1, 10}, {12, 23}, {25, 30}}, - }, - { - exist: Intervals{{1, 2}, {3, 5}, {7, 7}}, - new: Interval{6, 7}, - exp: Intervals{{1, 2}, {3, 7}}, - }, - { - exist: Intervals{{1, 10}, {12, 20}, {25, 30}}, - new: Interval{21, 25}, - exp: Intervals{{1, 10}, {12, 30}}, - }, - { - exist: Intervals{{1, 10}, {12, 20}, {25, 30}}, - new: Interval{18, 23}, - exp: Intervals{{1, 10}, {12, 23}, {25, 30}}, - }, - { - exist: Intervals{{1, 10}, {12, 20}, {25, 30}}, - new: Interval{9, 23}, - exp: Intervals{{1, 23}, {25, 30}}, - }, - { - exist: Intervals{{1, 10}, {12, 20}, {25, 30}}, - new: Interval{9, 230}, - exp: Intervals{{1, 230}}, - }, - { - exist: Intervals{{5, 10}, {12, 20}, {25, 30}}, - new: Interval{1, 4}, - exp: Intervals{{1, 10}, {12, 20}, {25, 30}}, - }, - { - exist: Intervals{{5, 10}, {12, 20}, {25, 30}}, - new: Interval{11, 14}, - exp: Intervals{{5, 20}, {25, 30}}, - }, - } - - for _, c := range cases { - - testutil.Equals(t, c.exp, c.exist.add(c.new)) - } -} - -// TestMemTombstonesConcurrency to make sure they are safe to access from different goroutines. -func TestMemTombstonesConcurrency(t *testing.T) { - tomb := newMemTombstones() - totalRuns := 100 - var wg sync.WaitGroup - wg.Add(2) - - go func() { - for x := 0; x < totalRuns; x++ { - tomb.addInterval(uint64(x), Interval{int64(x), int64(x)}) - } - wg.Done() - }() - go func() { - for x := 0; x < totalRuns; x++ { - tomb.Get(uint64(x)) - } - wg.Done() - }() - wg.Wait() -} diff --git a/vendor/github.com/prometheus/tsdb/wal.go b/vendor/github.com/prometheus/tsdb/wal.go index d7ffe0c1e..60e1c5807 100644 --- a/vendor/github.com/prometheus/tsdb/wal.go +++ b/vendor/github.com/prometheus/tsdb/wal.go @@ -31,7 +31,6 @@ import ( "github.com/go-kit/kit/log/level" "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/tsdb/encoding" "github.com/prometheus/tsdb/fileutil" "github.com/prometheus/tsdb/labels" "github.com/prometheus/tsdb/wal" @@ -288,16 +287,16 @@ func (w *SegmentWAL) Reader() WALReader { } } -func (w *SegmentWAL) getBuffer() *encoding.Encbuf { +func (w *SegmentWAL) getBuffer() *encbuf { b := w.buffers.Get() if b == nil { - return &encoding.Encbuf{B: make([]byte, 0, 64*1024)} + return &encbuf{b: make([]byte, 0, 64*1024)} } - return b.(*encoding.Encbuf) + return b.(*encbuf) } -func (w *SegmentWAL) putBuffer(b *encoding.Encbuf) { - b.Reset() +func (w *SegmentWAL) putBuffer(b *encbuf) { + b.reset() w.buffers.Put(b) } @@ -367,7 +366,7 @@ func (w *SegmentWAL) Truncate(mint int64, keep func(uint64) bool) error { buf := w.getBuffer() flag = w.encodeSeries(buf, activeSeries) - _, err = w.writeTo(csf, crc32, WALEntrySeries, flag, buf.Get()) + _, err = w.writeTo(csf, crc32, WALEntrySeries, flag, buf.get()) w.putBuffer(buf) if err != nil { @@ -428,7 +427,7 @@ func (w *SegmentWAL) LogSeries(series []RefSeries) error { w.mtx.Lock() defer w.mtx.Unlock() - err := w.write(WALEntrySeries, flag, buf.Get()) + err := w.write(WALEntrySeries, flag, buf.get()) w.putBuffer(buf) @@ -455,7 +454,7 @@ func (w *SegmentWAL) LogSamples(samples []RefSample) error { w.mtx.Lock() defer w.mtx.Unlock() - err := w.write(WALEntrySamples, flag, buf.Get()) + err := w.write(WALEntrySamples, flag, buf.get()) w.putBuffer(buf) @@ -481,7 +480,7 @@ func (w *SegmentWAL) LogDeletes(stones []Stone) error { w.mtx.Lock() defer w.mtx.Unlock() - err := w.write(WALEntryDeletes, flag, buf.Get()) + err := w.write(WALEntryDeletes, flag, buf.get()) w.putBuffer(buf) @@ -784,20 +783,20 @@ const ( walDeletesSimple = 1 ) -func (w *SegmentWAL) encodeSeries(buf *encoding.Encbuf, series []RefSeries) uint8 { +func (w *SegmentWAL) encodeSeries(buf *encbuf, series []RefSeries) uint8 { for _, s := range series { - buf.PutBE64(s.Ref) - buf.PutUvarint(len(s.Labels)) + buf.putBE64(s.Ref) + buf.putUvarint(len(s.Labels)) for _, l := range s.Labels { - buf.PutUvarintStr(l.Name) - buf.PutUvarintStr(l.Value) + buf.putUvarintStr(l.Name) + buf.putUvarintStr(l.Value) } } return walSeriesSimple } -func (w *SegmentWAL) encodeSamples(buf *encoding.Encbuf, samples []RefSample) uint8 { +func (w *SegmentWAL) encodeSamples(buf *encbuf, samples []RefSample) uint8 { if len(samples) == 0 { return walSamplesSimple } @@ -807,23 +806,23 @@ func (w *SegmentWAL) encodeSamples(buf *encoding.Encbuf, samples []RefSample) ui // TODO(fabxc): optimize for all samples having the same timestamp. first := samples[0] - buf.PutBE64(first.Ref) - buf.PutBE64int64(first.T) + buf.putBE64(first.Ref) + buf.putBE64int64(first.T) for _, s := range samples { - buf.PutVarint64(int64(s.Ref) - int64(first.Ref)) - buf.PutVarint64(s.T - first.T) - buf.PutBE64(math.Float64bits(s.V)) + buf.putVarint64(int64(s.Ref) - int64(first.Ref)) + buf.putVarint64(s.T - first.T) + buf.putBE64(math.Float64bits(s.V)) } return walSamplesSimple } -func (w *SegmentWAL) encodeDeletes(buf *encoding.Encbuf, stones []Stone) uint8 { +func (w *SegmentWAL) encodeDeletes(buf *encbuf, stones []Stone) uint8 { for _, s := range stones { for _, iv := range s.intervals { - buf.PutBE64(s.ref) - buf.PutVarint64(iv.Mint) - buf.PutVarint64(iv.Maxt) + buf.putBE64(s.ref) + buf.putVarint64(iv.Mint) + buf.putVarint64(iv.Maxt) } } return walDeletesSimple @@ -1116,16 +1115,16 @@ func (r *walReader) entry(cr io.Reader) (WALEntryType, byte, []byte, error) { } func (r *walReader) decodeSeries(flag byte, b []byte, res *[]RefSeries) error { - dec := encoding.Decbuf{B: b} + dec := decbuf{b: b} - for len(dec.B) > 0 && dec.Err() == nil { - ref := dec.Be64() + for len(dec.b) > 0 && dec.err() == nil { + ref := dec.be64() - lset := make(labels.Labels, dec.Uvarint()) + lset := make(labels.Labels, dec.uvarint()) for i := range lset { - lset[i].Name = dec.UvarintStr() - lset[i].Value = dec.UvarintStr() + lset[i].Name = dec.uvarintStr() + lset[i].Value = dec.uvarintStr() } sort.Sort(lset) @@ -1134,11 +1133,11 @@ func (r *walReader) decodeSeries(flag byte, b []byte, res *[]RefSeries) error { Labels: lset, }) } - if dec.Err() != nil { - return dec.Err() + if dec.err() != nil { + return dec.err() } - if len(dec.B) > 0 { - return errors.Errorf("unexpected %d bytes left in entry", len(dec.B)) + if len(dec.b) > 0 { + return errors.Errorf("unexpected %d bytes left in entry", len(dec.b)) } return nil } @@ -1147,17 +1146,17 @@ func (r *walReader) decodeSamples(flag byte, b []byte, res *[]RefSample) error { if len(b) == 0 { return nil } - dec := encoding.Decbuf{B: b} + dec := decbuf{b: b} var ( - baseRef = dec.Be64() - baseTime = dec.Be64int64() + baseRef = dec.be64() + baseTime = dec.be64int64() ) - for len(dec.B) > 0 && dec.Err() == nil { - dref := dec.Varint64() - dtime := dec.Varint64() - val := dec.Be64() + for len(dec.b) > 0 && dec.err() == nil { + dref := dec.varint64() + dtime := dec.varint64() + val := dec.be64() *res = append(*res, RefSample{ Ref: uint64(int64(baseRef) + dref), @@ -1166,31 +1165,31 @@ func (r *walReader) decodeSamples(flag byte, b []byte, res *[]RefSample) error { }) } - if dec.Err() != nil { - return errors.Wrapf(dec.Err(), "decode error after %d samples", len(*res)) + if dec.err() != nil { + return errors.Wrapf(dec.err(), "decode error after %d samples", len(*res)) } - if len(dec.B) > 0 { - return errors.Errorf("unexpected %d bytes left in entry", len(dec.B)) + if len(dec.b) > 0 { + return errors.Errorf("unexpected %d bytes left in entry", len(dec.b)) } return nil } func (r *walReader) decodeDeletes(flag byte, b []byte, res *[]Stone) error { - dec := &encoding.Decbuf{B: b} + dec := &decbuf{b: b} - for dec.Len() > 0 && dec.Err() == nil { + for dec.len() > 0 && dec.err() == nil { *res = append(*res, Stone{ - ref: dec.Be64(), + ref: dec.be64(), intervals: Intervals{ - {Mint: dec.Varint64(), Maxt: dec.Varint64()}, + {Mint: dec.varint64(), Maxt: dec.varint64()}, }, }) } - if dec.Err() != nil { - return dec.Err() + if dec.err() != nil { + return dec.err() } - if len(dec.B) > 0 { - return errors.Errorf("unexpected %d bytes left in entry", len(dec.B)) + if len(dec.b) > 0 { + return errors.Errorf("unexpected %d bytes left in entry", len(dec.b)) } return nil } diff --git a/vendor/github.com/prometheus/tsdb/wal/live_reader.go b/vendor/github.com/prometheus/tsdb/wal/live_reader.go deleted file mode 100644 index 8394bfd08..000000000 --- a/vendor/github.com/prometheus/tsdb/wal/live_reader.go +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright 2019 The Prometheus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package wal - -import ( - "encoding/binary" - "fmt" - "hash/crc32" - "io" - - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/log/level" - "github.com/pkg/errors" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" -) - -var ( - readerCorruptionErrors = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "prometheus_tsdb_wal_reader_corruption_errors", - Help: "Errors encountered when reading the WAL.", - }, []string{"error"}) -) - -// NewLiveReader returns a new live reader. -func NewLiveReader(logger log.Logger, r io.Reader) *LiveReader { - return &LiveReader{ - logger: logger, - rdr: r, - - // Until we understand how they come about, make readers permissive - // to records spanning pages. - permissive: true, - } -} - -// LiveReader reads WAL records from an io.Reader. It allows reading of WALs -// that are still in the process of being written, and returns records as soon -// as they can be read. -type LiveReader struct { - logger log.Logger - rdr io.Reader - err error - rec []byte - hdr [recordHeaderSize]byte - buf [pageSize]byte - readIndex int // Index in buf to start at for next read. - writeIndex int // Index in buf to start at for next write. - total int64 // Total bytes processed during reading in calls to Next(). - index int // Used to track partial records, should be 0 at the start of every new record. - - // For testing, we can treat EOF as a non-error. - eofNonErr bool - - // We sometime see records span page boundaries. Should never happen, but it - // does. Until we track down why, set permissive to true to tolerate it. - // NB the non-ive Reader implementation allows for this. - permissive bool -} - -// Err returns any errors encountered reading the WAL. io.EOFs are not terminal -// and Next can be tried again. Non-EOFs are terminal, and the reader should -// not be used again. It is up to the user to decide when to stop trying should -// io.EOF be returned. -func (r *LiveReader) Err() error { - if r.eofNonErr && r.err == io.EOF { - return nil - } - return r.err -} - -// Offset returns the number of bytes consumed from this segment. -func (r *LiveReader) Offset() int64 { - return r.total -} - -func (r *LiveReader) fillBuffer() (int, error) { - n, err := r.rdr.Read(r.buf[r.writeIndex:len(r.buf)]) - r.writeIndex += n - return n, err -} - -// Next returns true if Record() will contain a full record. -// If Next returns false, you should always checked the contents of Error(). -// Return false guarantees there are no more records if the segment is closed -// and not corrupt, otherwise if Err() == io.EOF you should try again when more -// data has been written. -func (r *LiveReader) Next() bool { - for { - // If buildRecord returns a non-EOF error, its game up - the segment is - // corrupt. If buildRecord returns an EOF, we try and read more in - // fillBuffer later on. If that fails to read anything (n=0 && err=EOF), - // we return EOF and the user can try again later. If we have a full - // page, buildRecord is guaranteed to return a record or a non-EOF; it - // has checks the records fit in pages. - if ok, err := r.buildRecord(); ok { - return true - } else if err != nil && err != io.EOF { - r.err = err - return false - } - - // If we've filled the page and not found a record, this - // means records have started to span pages. Shouldn't happen - // but does and until we found out why, we need to deal with this. - if r.permissive && r.writeIndex == pageSize && r.readIndex > 0 { - copy(r.buf[:], r.buf[r.readIndex:]) - r.writeIndex -= r.readIndex - r.readIndex = 0 - continue - } - - if r.readIndex == pageSize { - r.writeIndex = 0 - r.readIndex = 0 - } - - if r.writeIndex != pageSize { - n, err := r.fillBuffer() - if n == 0 || (err != nil && err != io.EOF) { - r.err = err - return false - } - } - } -} - -// Record returns the current record. -// The returned byte slice is only valid until the next call to Next. -func (r *LiveReader) Record() []byte { - return r.rec -} - -// Rebuild a full record from potentially partial records. Returns false -// if there was an error or if we weren't able to read a record for any reason. -// Returns true if we read a full record. Any record data is appended to -// LiveReader.rec -func (r *LiveReader) buildRecord() (bool, error) { - for { - // Check that we have data in the internal buffer to read. - if r.writeIndex <= r.readIndex { - return false, nil - } - - // Attempt to read a record, partial or otherwise. - temp, n, err := r.readRecord() - if err != nil { - return false, err - } - - r.readIndex += n - r.total += int64(n) - if temp == nil { - return false, nil - } - - rt := recType(r.hdr[0]) - if rt == recFirst || rt == recFull { - r.rec = r.rec[:0] - } - r.rec = append(r.rec, temp...) - - if err := validateRecord(rt, r.index); err != nil { - r.index = 0 - return false, err - } - if rt == recLast || rt == recFull { - r.index = 0 - return true, nil - } - // Only increment i for non-zero records since we use it - // to determine valid content record sequences. - r.index++ - } -} - -// Returns an error if the recType and i indicate an invalid record sequence. -// As an example, if i is > 0 because we've read some amount of a partial record -// (recFirst, recMiddle, etc. but not recLast) and then we get another recFirst or recFull -// instead of a recLast or recMiddle we would have an invalid record. -func validateRecord(typ recType, i int) error { - switch typ { - case recFull: - if i != 0 { - return errors.New("unexpected full record") - } - return nil - case recFirst: - if i != 0 { - return errors.New("unexpected first record, dropping buffer") - } - return nil - case recMiddle: - if i == 0 { - return errors.New("unexpected middle record, dropping buffer") - } - return nil - case recLast: - if i == 0 { - return errors.New("unexpected last record, dropping buffer") - } - return nil - default: - return errors.Errorf("unexpected record type %d", typ) - } -} - -// Read a sub-record (see recType) from the buffer. It could potentially -// be a full record (recFull) if the record fits within the bounds of a single page. -// Returns a byte slice of the record data read, the number of bytes read, and an error -// if there's a non-zero byte in a page term record or the record checksum fails. -// This is a non-method function to make it clear it does not mutate the reader. -func (r *LiveReader) readRecord() ([]byte, int, error) { - // Special case: for recPageTerm, check that are all zeros to end of page, - // consume them but don't return them. - if r.buf[r.readIndex] == byte(recPageTerm) { - // End of page won't necessarily be end of buffer, as we may have - // got misaligned by records spanning page boundaries. - // r.total % pageSize is the offset into the current page - // that r.readIndex points to in buf. Therefore - // pageSize - (r.total % pageSize) is the amount left to read of - // the current page. - remaining := int(pageSize - (r.total % pageSize)) - if r.readIndex+remaining > r.writeIndex { - return nil, 0, io.EOF - } - - for i := r.readIndex; i < r.readIndex+remaining; i++ { - if r.buf[i] != 0 { - return nil, 0, errors.New("unexpected non-zero byte in page term bytes") - } - } - - return nil, remaining, nil - } - - // Not a recPageTerm; read the record and check the checksum. - if r.writeIndex-r.readIndex < recordHeaderSize { - return nil, 0, io.EOF - } - - copy(r.hdr[:], r.buf[r.readIndex:r.readIndex+recordHeaderSize]) - length := int(binary.BigEndian.Uint16(r.hdr[1:])) - crc := binary.BigEndian.Uint32(r.hdr[3:]) - if r.readIndex+recordHeaderSize+length > pageSize { - if !r.permissive { - return nil, 0, fmt.Errorf("record would overflow current page: %d > %d", r.readIndex+recordHeaderSize+length, pageSize) - } - readerCorruptionErrors.WithLabelValues("record_span_page").Inc() - level.Warn(r.logger).Log("msg", "record spans page boundaries", "start", r.readIndex, "end", recordHeaderSize+length, "pageSize", pageSize) - } - if recordHeaderSize+length > pageSize { - return nil, 0, fmt.Errorf("record length greater than a single page: %d > %d", recordHeaderSize+length, pageSize) - } - if r.readIndex+recordHeaderSize+length > r.writeIndex { - return nil, 0, io.EOF - } - - rec := r.buf[r.readIndex+recordHeaderSize : r.readIndex+recordHeaderSize+length] - if c := crc32.Checksum(rec, castagnoliTable); c != crc { - return nil, 0, errors.Errorf("unexpected checksum %x, expected %x", c, crc) - } - - return rec, length + recordHeaderSize, nil -} - -func min(i, j int) int { - if i < j { - return i - } - return j -} diff --git a/vendor/github.com/prometheus/tsdb/wal/reader.go b/vendor/github.com/prometheus/tsdb/wal/reader.go deleted file mode 100644 index 297463b00..000000000 --- a/vendor/github.com/prometheus/tsdb/wal/reader.go +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2019 The Prometheus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package wal - -import ( - "encoding/binary" - "hash/crc32" - "io" - - "github.com/pkg/errors" -) - -// Reader reads WAL records from an io.Reader. -type Reader struct { - rdr io.Reader - err error - rec []byte - buf [pageSize]byte - total int64 // Total bytes processed. - curRecTyp recType // Used for checking that the last record is not torn. -} - -// NewReader returns a new reader. -func NewReader(r io.Reader) *Reader { - return &Reader{rdr: r} -} - -// Next advances the reader to the next records and returns true if it exists. -// It must not be called again after it returned false. -func (r *Reader) Next() bool { - err := r.next() - if errors.Cause(err) == io.EOF { - // The last WAL segment record shouldn't be torn(should be full or last). - // The last record would be torn after a crash just before - // the last record part could be persisted to disk. - if recType(r.curRecTyp) == recFirst || recType(r.curRecTyp) == recMiddle { - r.err = errors.New("last record is torn") - } - return false - } - r.err = err - return r.err == nil -} - -func (r *Reader) next() (err error) { - // We have to use r.buf since allocating byte arrays here fails escape - // analysis and ends up on the heap, even though it seemingly should not. - hdr := r.buf[:recordHeaderSize] - buf := r.buf[recordHeaderSize:] - - r.rec = r.rec[:0] - - i := 0 - for { - if _, err = io.ReadFull(r.rdr, hdr[:1]); err != nil { - return errors.Wrap(err, "read first header byte") - } - r.total++ - r.curRecTyp = recType(hdr[0]) - - // Gobble up zero bytes. - if r.curRecTyp == recPageTerm { - // recPageTerm is a single byte that indicates the rest of the page is padded. - // If it's the first byte in a page, buf is too small and - // needs to be resized to fit pageSize-1 bytes. - buf = r.buf[1:] - - // We are pedantic and check whether the zeros are actually up - // to a page boundary. - // It's not strictly necessary but may catch sketchy state early. - k := pageSize - (r.total % pageSize) - if k == pageSize { - continue // Initial 0 byte was last page byte. - } - n, err := io.ReadFull(r.rdr, buf[:k]) - if err != nil { - return errors.Wrap(err, "read remaining zeros") - } - r.total += int64(n) - - for _, c := range buf[:k] { - if c != 0 { - return errors.New("unexpected non-zero byte in padded page") - } - } - continue - } - n, err := io.ReadFull(r.rdr, hdr[1:]) - if err != nil { - return errors.Wrap(err, "read remaining header") - } - r.total += int64(n) - - var ( - length = binary.BigEndian.Uint16(hdr[1:]) - crc = binary.BigEndian.Uint32(hdr[3:]) - ) - - if length > pageSize-recordHeaderSize { - return errors.Errorf("invalid record size %d", length) - } - n, err = io.ReadFull(r.rdr, buf[:length]) - if err != nil { - return err - } - r.total += int64(n) - - if n != int(length) { - return errors.Errorf("invalid size: expected %d, got %d", length, n) - } - if c := crc32.Checksum(buf[:length], castagnoliTable); c != crc { - return errors.Errorf("unexpected checksum %x, expected %x", c, crc) - } - r.rec = append(r.rec, buf[:length]...) - - if err := validateRecord(r.curRecTyp, i); err != nil { - return err - } - if r.curRecTyp == recLast || r.curRecTyp == recFull { - return nil - } - - // Only increment i for non-zero records since we use it - // to determine valid content record sequences. - i++ - } -} - -// Err returns the last encountered error wrapped in a corruption error. -// If the reader does not allow to infer a segment index and offset, a total -// offset in the reader stream will be provided. -func (r *Reader) Err() error { - if r.err == nil { - return nil - } - if b, ok := r.rdr.(*segmentBufReader); ok { - return &CorruptionErr{ - Err: r.err, - Dir: b.segs[b.cur].Dir(), - Segment: b.segs[b.cur].Index(), - Offset: int64(b.off), - } - } - return &CorruptionErr{ - Err: r.err, - Segment: -1, - Offset: r.total, - } -} - -// Record returns the current record. The returned byte slice is only -// valid until the next call to Next. -func (r *Reader) Record() []byte { - return r.rec -} - -// Segment returns the current segment being read. -func (r *Reader) Segment() int { - if b, ok := r.rdr.(*segmentBufReader); ok { - return b.segs[b.cur].Index() - } - return -1 -} - -// Offset returns the current position of the segment being read. -func (r *Reader) Offset() int64 { - if b, ok := r.rdr.(*segmentBufReader); ok { - return int64(b.off) - } - return r.total -} diff --git a/vendor/github.com/prometheus/tsdb/wal/reader_test.go b/vendor/github.com/prometheus/tsdb/wal/reader_test.go deleted file mode 100644 index d782ae804..000000000 --- a/vendor/github.com/prometheus/tsdb/wal/reader_test.go +++ /dev/null @@ -1,506 +0,0 @@ -// Copyright 2019 The Prometheus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package wal - -import ( - "bytes" - "encoding/binary" - "fmt" - "hash/crc32" - "io" - "io/ioutil" - "math/rand" - "os" - "path/filepath" - "runtime" - "strconv" - "testing" - "time" - - "github.com/go-kit/kit/log" - "github.com/prometheus/tsdb/testutil" -) - -type reader interface { - Next() bool - Err() error - Record() []byte - Offset() int64 -} - -type record struct { - t recType - b []byte -} - -var readerConstructors = map[string]func(io.Reader) reader{ - "Reader": func(r io.Reader) reader { - return NewReader(r) - }, - "LiveReader": func(r io.Reader) reader { - lr := NewLiveReader(log.NewNopLogger(), r) - lr.eofNonErr = true - return lr - }, -} - -var data = make([]byte, 100000) -var testReaderCases = []struct { - t []record - exp [][]byte - fail bool -}{ - // Sequence of valid records. - { - t: []record{ - {recFull, data[0:200]}, - {recFirst, data[200:300]}, - {recLast, data[300:400]}, - {recFirst, data[400:800]}, - {recMiddle, data[800:900]}, - {recPageTerm, make([]byte, pageSize-900-recordHeaderSize*5-1)}, // exactly lines up with page boundary. - {recLast, data[900:900]}, - {recFirst, data[900:1000]}, - {recMiddle, data[1000:1200]}, - {recMiddle, data[1200:30000]}, - {recMiddle, data[30000:30001]}, - {recMiddle, data[30001:30001]}, - {recLast, data[30001:32000]}, - }, - exp: [][]byte{ - data[0:200], - data[200:400], - data[400:900], - data[900:32000], - }, - }, - // Exactly at the limit of one page minus the header size - { - t: []record{ - {recFull, data[0 : pageSize-recordHeaderSize]}, - }, - exp: [][]byte{ - data[:pageSize-recordHeaderSize], - }, - }, - // More than a full page, this exceeds our buffer and can never happen - // when written by the WAL. - { - t: []record{ - {recFull, data[0 : pageSize+1]}, - }, - fail: true, - }, - // Two records the together are too big for a page. - // NB currently the non-live reader succeeds on this. I think this is a bug. - // but we've seen it in production. - { - t: []record{ - {recFull, data[:pageSize/2]}, - {recFull, data[:pageSize/2]}, - }, - exp: [][]byte{ - data[:pageSize/2], - data[:pageSize/2], - }, - }, - // Invalid orders of record types. - { - t: []record{{recMiddle, data[:200]}}, - fail: true, - }, - { - t: []record{{recLast, data[:200]}}, - fail: true, - }, - { - t: []record{ - {recFirst, data[:200]}, - {recFull, data[200:400]}, - }, - fail: true, - }, - { - t: []record{ - {recFirst, data[:100]}, - {recMiddle, data[100:200]}, - {recFull, data[200:400]}, - }, - fail: true, - }, - // Non-zero data after page termination. - { - t: []record{ - {recFull, data[:100]}, - {recPageTerm, append(make([]byte, pageSize-recordHeaderSize-102), 1)}, - }, - exp: [][]byte{data[:100]}, - fail: true, - }, -} - -func encodedRecord(t recType, b []byte) []byte { - if t == recPageTerm { - return append([]byte{0}, b...) - } - r := make([]byte, recordHeaderSize) - r[0] = byte(t) - binary.BigEndian.PutUint16(r[1:], uint16(len(b))) - binary.BigEndian.PutUint32(r[3:], crc32.Checksum(b, castagnoliTable)) - return append(r, b...) -} - -// TestReader feeds the reader a stream of encoded records with different types. -func TestReader(t *testing.T) { - for name, fn := range readerConstructors { - for i, c := range testReaderCases { - t.Run(fmt.Sprintf("%s/%d", name, i), func(t *testing.T) { - var buf []byte - for _, r := range c.t { - buf = append(buf, encodedRecord(r.t, r.b)...) - } - r := fn(bytes.NewReader(buf)) - - for j := 0; r.Next(); j++ { - t.Logf("record %d", j) - rec := r.Record() - - if j >= len(c.exp) { - t.Fatal("received more records than expected") - } - testutil.Equals(t, c.exp[j], rec, "Bytes within record did not match expected Bytes") - } - if !c.fail && r.Err() != nil { - t.Fatalf("unexpected error: %s", r.Err()) - } - if c.fail && r.Err() == nil { - t.Fatalf("expected error but got none") - } - }) - } - } -} - -func TestReader_Live(t *testing.T) { - logger := testutil.NewLogger(t) - - for i := range testReaderCases { - t.Run(strconv.Itoa(i), func(t *testing.T) { - writeFd, err := ioutil.TempFile("", "TestReader_Live") - testutil.Ok(t, err) - defer os.Remove(writeFd.Name()) - - go func(i int) { - for _, rec := range testReaderCases[i].t { - rec := encodedRecord(rec.t, rec.b) - _, err := writeFd.Write(rec) - testutil.Ok(t, err) - runtime.Gosched() - } - writeFd.Close() - }(i) - - // Read from a second FD on the same file. - readFd, err := os.Open(writeFd.Name()) - testutil.Ok(t, err) - reader := NewLiveReader(logger, readFd) - for _, exp := range testReaderCases[i].exp { - for !reader.Next() { - testutil.Assert(t, reader.Err() == io.EOF, "expect EOF, got: %v", reader.Err()) - runtime.Gosched() - } - - actual := reader.Record() - testutil.Equals(t, exp, actual, "read wrong record") - } - - testutil.Assert(t, !reader.Next(), "unexpected record") - if testReaderCases[i].fail { - testutil.Assert(t, reader.Err() != nil, "expected error") - } - }) - } -} - -const fuzzLen = 500 - -func generateRandomEntries(w *WAL, records chan []byte) error { - var recs [][]byte - for i := 0; i < fuzzLen; i++ { - var sz int64 - switch i % 5 { - case 0, 1: - sz = 50 - case 2, 3: - sz = pageSize - default: - sz = pageSize * 8 - } - - rec := make([]byte, rand.Int63n(sz)) - if _, err := rand.Read(rec); err != nil { - return err - } - - records <- rec - - // Randomly batch up records. - recs = append(recs, rec) - if rand.Intn(4) < 3 { - if err := w.Log(recs...); err != nil { - return err - } - recs = recs[:0] - } - } - return w.Log(recs...) -} - -func allSegments(dir string) (io.Reader, error) { - seg, err := listSegments(dir) - if err != nil { - return nil, err - } - - var readers []io.Reader - for _, r := range seg { - f, err := os.Open(filepath.Join(dir, r.name)) - if err != nil { - return nil, err - } - readers = append(readers, f) - } - return io.MultiReader(readers...), nil -} - -func TestReaderFuzz(t *testing.T) { - for name, fn := range readerConstructors { - t.Run(name, func(t *testing.T) { - dir, err := ioutil.TempDir("", "wal_fuzz_live") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - w, err := NewSize(nil, nil, dir, 128*pageSize) - testutil.Ok(t, err) - - // Buffering required as we're not reading concurrently. - input := make(chan []byte, fuzzLen) - err = generateRandomEntries(w, input) - testutil.Ok(t, err) - close(input) - - err = w.Close() - testutil.Ok(t, err) - - sr, err := allSegments(w.Dir()) - testutil.Ok(t, err) - - reader := fn(sr) - for expected := range input { - testutil.Assert(t, reader.Next(), "expected record: %v", reader.Err()) - testutil.Equals(t, expected, reader.Record(), "read wrong record") - } - testutil.Assert(t, !reader.Next(), "unexpected record") - }) - } -} - -func TestReaderFuzz_Live(t *testing.T) { - logger := testutil.NewLogger(t) - dir, err := ioutil.TempDir("", "wal_fuzz_live") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - w, err := NewSize(nil, nil, dir, 128*pageSize) - testutil.Ok(t, err) - - // In the background, generate a stream of random records and write them - // to the WAL. - input := make(chan []byte, fuzzLen/10) // buffering required as we sometimes batch WAL writes. - done := make(chan struct{}) - go func() { - err := generateRandomEntries(w, input) - testutil.Ok(t, err) - time.Sleep(100 * time.Millisecond) - close(done) - }() - - // Tail the WAL and compare the results. - m, _, err := w.Segments() - testutil.Ok(t, err) - - seg, err := OpenReadSegment(SegmentName(dir, m)) - testutil.Ok(t, err) - - r := NewLiveReader(logger, seg) - segmentTicker := time.NewTicker(100 * time.Millisecond) - readTicker := time.NewTicker(10 * time.Millisecond) - - readSegment := func(r *LiveReader) bool { - for r.Next() { - rec := r.Record() - expected, ok := <-input - testutil.Assert(t, ok, "unexpected record") - testutil.Equals(t, expected, rec, "record does not match expected") - } - testutil.Assert(t, r.Err() == io.EOF, "expected EOF, got: %v", r.Err()) - return true - } - -outer: - for { - select { - case <-segmentTicker.C: - // check if new segments exist - _, last, err := w.Segments() - testutil.Ok(t, err) - if last <= seg.i { - continue - } - - // read to end of segment. - readSegment(r) - - fi, err := os.Stat(SegmentName(dir, seg.i)) - testutil.Ok(t, err) - testutil.Assert(t, r.Offset() == fi.Size(), "expected to have read whole segment, but read %d of %d", r.Offset(), fi.Size()) - - seg, err = OpenReadSegment(SegmentName(dir, seg.i+1)) - testutil.Ok(t, err) - r = NewLiveReader(logger, seg) - - case <-readTicker.C: - readSegment(r) - - case <-done: - readSegment(r) - break outer - } - } - - testutil.Assert(t, r.Err() == io.EOF, "expected EOF") -} - -func TestLiveReaderCorrupt_ShortFile(t *testing.T) { - // Write a corrupt WAL segment, there is one record of pageSize in length, - // but the segment is only half written. - logger := testutil.NewLogger(t) - dir, err := ioutil.TempDir("", "wal_live_corrupt") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - w, err := NewSize(nil, nil, dir, pageSize) - testutil.Ok(t, err) - - rec := make([]byte, pageSize-recordHeaderSize) - _, err = rand.Read(rec) - testutil.Ok(t, err) - - err = w.Log(rec) - testutil.Ok(t, err) - - err = w.Close() - testutil.Ok(t, err) - - segmentFile, err := os.OpenFile(filepath.Join(dir, "00000000"), os.O_RDWR, 0666) - testutil.Ok(t, err) - - err = segmentFile.Truncate(pageSize / 2) - testutil.Ok(t, err) - - err = segmentFile.Close() - testutil.Ok(t, err) - - // Try and LiveReader it. - m, _, err := w.Segments() - testutil.Ok(t, err) - - seg, err := OpenReadSegment(SegmentName(dir, m)) - testutil.Ok(t, err) - - r := NewLiveReader(logger, seg) - testutil.Assert(t, r.Next() == false, "expected no records") - testutil.Assert(t, r.Err() == io.EOF, "expected error, got: %v", r.Err()) -} - -func TestLiveReaderCorrupt_RecordTooLongAndShort(t *testing.T) { - // Write a corrupt WAL segment, when record len > page size. - logger := testutil.NewLogger(t) - dir, err := ioutil.TempDir("", "wal_live_corrupt") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - w, err := NewSize(nil, nil, dir, pageSize*2) - testutil.Ok(t, err) - - rec := make([]byte, pageSize-recordHeaderSize) - _, err = rand.Read(rec) - testutil.Ok(t, err) - - err = w.Log(rec) - testutil.Ok(t, err) - - err = w.Close() - testutil.Ok(t, err) - - segmentFile, err := os.OpenFile(filepath.Join(dir, "00000000"), os.O_RDWR, 0666) - testutil.Ok(t, err) - - // Override the record length - buf := make([]byte, 3) - buf[0] = byte(recFull) - binary.BigEndian.PutUint16(buf[1:], 0xFFFF) - _, err = segmentFile.WriteAt(buf, 0) - testutil.Ok(t, err) - - err = segmentFile.Close() - testutil.Ok(t, err) - - // Try and LiveReader it. - m, _, err := w.Segments() - testutil.Ok(t, err) - - seg, err := OpenReadSegment(SegmentName(dir, m)) - testutil.Ok(t, err) - - r := NewLiveReader(logger, seg) - testutil.Assert(t, r.Next() == false, "expected no records") - testutil.Assert(t, r.Err().Error() == "record length greater than a single page: 65542 > 32768", "expected error, got: %v", r.Err()) -} - -func TestReaderData(t *testing.T) { - dir := os.Getenv("WALDIR") - if dir == "" { - return - } - - for name, fn := range readerConstructors { - t.Run(name, func(t *testing.T) { - w, err := New(nil, nil, dir) - testutil.Ok(t, err) - - sr, err := allSegments(dir) - testutil.Ok(t, err) - - reader := fn(sr) - for reader.Next() { - } - testutil.Ok(t, reader.Err()) - - err = w.Repair(reader.Err()) - testutil.Ok(t, err) - }) - } -} diff --git a/vendor/github.com/prometheus/tsdb/wal/wal.go b/vendor/github.com/prometheus/tsdb/wal/wal.go index b37032604..fd90eb90e 100644 --- a/vendor/github.com/prometheus/tsdb/wal/wal.go +++ b/vendor/github.com/prometheus/tsdb/wal/wal.go @@ -228,23 +228,19 @@ func NewSize(logger log.Logger, reg prometheus.Registerer, dir string, segmentSi } // Fresh dir, no segments yet. if j == -1 { - segment, err := CreateSegment(w.dir, 0) - if err != nil { - return nil, err - } - - if err := w.setSegment(segment); err != nil { + if w.segment, err = CreateSegment(w.dir, 0); err != nil { return nil, err } } else { - segment, err := OpenWriteSegment(logger, w.dir, j) - if err != nil { + if w.segment, err = OpenWriteSegment(logger, w.dir, j); err != nil { return nil, err } - - if err := w.setSegment(segment); err != nil { + // Correctly initialize donePages. + stat, err := w.segment.Stat() + if err != nil { return nil, err } + w.donePages = int(stat.Size() / pageSize) } go w.run() @@ -300,7 +296,7 @@ func (w *WAL) Repair(origErr error) error { if err != nil { return errors.Wrap(err, "list segments") } - level.Warn(w.logger).Log("msg", "deleting all segments newer than corrupted segment", "segment", cerr.Segment) + level.Warn(w.logger).Log("msg", "deleting all segments behind corruption", "segment", cerr.Segment) for _, s := range segs { if w.segment.i == s.index { @@ -335,9 +331,7 @@ func (w *WAL) Repair(origErr error) error { if err != nil { return err } - if err := w.setSegment(s); err != nil { - return err - } + w.segment = s f, err := os.Open(tmpfn) if err != nil { @@ -388,9 +382,8 @@ func (w *WAL) nextSegment() error { return errors.Wrap(err, "create new segment file") } prev := w.segment - if err := w.setSegment(next); err != nil { - return err - } + w.segment = next + w.donePages = 0 // Don't block further writes by fsyncing the last segment. w.actorc <- func() { @@ -404,19 +397,6 @@ func (w *WAL) nextSegment() error { return nil } -func (w *WAL) setSegment(segment *Segment) error { - w.segment = segment - - // Correctly initialize donePages. - stat, err := segment.Stat() - if err != nil { - return err - } - w.donePages = int(stat.Size() / pageSize) - - return nil -} - // flushPage writes the new contents of the page to disk. If no more records will fit into // the page, the remaining bytes will be set to zero and a new page will be started. // If clear is true, this is enforced regardless of how many bytes are left in the page. @@ -701,20 +681,20 @@ func NewSegmentsRangeReader(sr ...SegmentRange) (io.ReadCloser, error) { // segmentBufReader is a buffered reader that reads in multiples of pages. // The main purpose is that we are able to track segment and offset for -// corruption reporting. We have to be careful not to increment curr too -// early, as it is used by Reader.Err() to tell Repair which segment is corrupt. -// As such we pad the end of non-page align segments with zeros. +// corruption reporting. type segmentBufReader struct { buf *bufio.Reader segs []*Segment - cur int // Index into segs. - off int // Offset of read data into current segment. + cur int + off int + more bool } func newSegmentBufReader(segs ...*Segment) *segmentBufReader { return &segmentBufReader{ - buf: bufio.NewReaderSize(segs[0], 16*pageSize), + buf: bufio.NewReaderSize(nil, 16*pageSize), segs: segs, + cur: -1, } } @@ -727,38 +707,411 @@ func (r *segmentBufReader) Close() (err error) { return err } -// Read implements io.Reader. func (r *segmentBufReader) Read(b []byte) (n int, err error) { + if !r.more { + if r.cur+1 >= len(r.segs) { + return 0, io.EOF + } + r.cur++ + r.off = 0 + r.more = true + r.buf.Reset(r.segs[r.cur]) + } n, err = r.buf.Read(b) r.off += n - - // If we succeeded, or hit a non-EOF, we can stop. - if err == nil || err != io.EOF { + if err != io.EOF { return n, err } + // Just return what we read so far, but don't signal EOF. + // Only unset more so we don't invalidate the current segment and + // offset before the next read. + r.more = false + return n, nil +} + +// Reader reads WAL records from an io.Reader. +type Reader struct { + rdr io.Reader + err error + rec []byte + buf [pageSize]byte + total int64 // Total bytes processed. + curRecTyp recType // Used for checking that the last record is not torn. +} + +// NewReader returns a new reader. +func NewReader(r io.Reader) *Reader { + return &Reader{rdr: r} +} - // We hit EOF; fake out zero padding at the end of short segments, so we - // don't increment curr too early and report the wrong segment as corrupt. - if r.off%pageSize != 0 { - i := 0 - for ; n+i < len(b) && (r.off+i)%pageSize != 0; i++ { - b[n+i] = 0 +// Next advances the reader to the next records and returns true if it exists. +// It must not be called again after it returned false. +func (r *Reader) Next() bool { + err := r.next() + if errors.Cause(err) == io.EOF { + // The last WAL segment record shouldn't be torn(should be full or last). + // The last record would be torn after a crash just before + // the last record part could be persisted to disk. + if recType(r.curRecTyp) == recFirst || recType(r.curRecTyp) == recMiddle { + r.err = errors.New("last record is torn") } + return false + } + r.err = err + return r.err == nil +} + +func (r *Reader) next() (err error) { + // We have to use r.buf since allocating byte arrays here fails escape + // analysis and ends up on the heap, even though it seemingly should not. + hdr := r.buf[:recordHeaderSize] + buf := r.buf[recordHeaderSize:] - // Return early, even if we didn't fill b. - r.off += i - return n + i, nil + r.rec = r.rec[:0] + + i := 0 + for { + if _, err = io.ReadFull(r.rdr, hdr[:1]); err != nil { + return errors.Wrap(err, "read first header byte") + } + r.total++ + r.curRecTyp = recType(hdr[0]) + + // Gobble up zero bytes. + if r.curRecTyp == recPageTerm { + // recPageTerm is a single byte that indicates the rest of the page is padded. + // If it's the first byte in a page, buf is too small and + // needs to be resized to fit pageSize-1 bytes. + buf = r.buf[1:] + + // We are pedantic and check whether the zeros are actually up + // to a page boundary. + // It's not strictly necessary but may catch sketchy state early. + k := pageSize - (r.total % pageSize) + if k == pageSize { + continue // Initial 0 byte was last page byte. + } + n, err := io.ReadFull(r.rdr, buf[:k]) + if err != nil { + return errors.Wrap(err, "read remaining zeros") + } + r.total += int64(n) + + for _, c := range buf[:k] { + if c != 0 { + return errors.New("unexpected non-zero byte in padded page") + } + } + continue + } + n, err := io.ReadFull(r.rdr, hdr[1:]) + if err != nil { + return errors.Wrap(err, "read remaining header") + } + r.total += int64(n) + + var ( + length = binary.BigEndian.Uint16(hdr[1:]) + crc = binary.BigEndian.Uint32(hdr[3:]) + ) + + if length > pageSize-recordHeaderSize { + return errors.Errorf("invalid record size %d", length) + } + n, err = io.ReadFull(r.rdr, buf[:length]) + if err != nil { + return err + } + r.total += int64(n) + + if n != int(length) { + return errors.Errorf("invalid size: expected %d, got %d", length, n) + } + if c := crc32.Checksum(buf[:length], castagnoliTable); c != crc { + return errors.Errorf("unexpected checksum %x, expected %x", c, crc) + } + r.rec = append(r.rec, buf[:length]...) + + if err := validateRecord(r.curRecTyp, i); err != nil { + return err + } + if r.curRecTyp == recLast || r.curRecTyp == recFull { + return nil + } + + // Only increment i for non-zero records since we use it + // to determine valid content record sequences. + i++ + } +} + +// Err returns the last encountered error wrapped in a corruption error. +// If the reader does not allow to infer a segment index and offset, a total +// offset in the reader stream will be provided. +func (r *Reader) Err() error { + if r.err == nil { + return nil + } + if b, ok := r.rdr.(*segmentBufReader); ok { + return &CorruptionErr{ + Err: r.err, + Dir: b.segs[b.cur].Dir(), + Segment: b.segs[b.cur].Index(), + Offset: int64(b.off), + } + } + return &CorruptionErr{ + Err: r.err, + Segment: -1, + Offset: r.total, } +} + +// Record returns the current record. The returned byte slice is only +// valid until the next call to Next. +func (r *Reader) Record() []byte { + return r.rec +} - // There is no more deta left in the curr segment and there are no more - // segments left. Return EOF. - if r.cur+1 >= len(r.segs) { - return n, io.EOF +// Segment returns the current segment being read. +func (r *Reader) Segment() int { + if b, ok := r.rdr.(*segmentBufReader); ok { + return b.segs[b.cur].Index() } + return -1 +} - // Move to next segment. - r.cur++ - r.off = 0 - r.buf.Reset(r.segs[r.cur]) - return n, nil +// Offset returns the current position of the segment being read. +func (r *Reader) Offset() int64 { + if b, ok := r.rdr.(*segmentBufReader); ok { + return int64(b.off) + } + return r.total +} + +// NewLiveReader returns a new live reader. +func NewLiveReader(r io.Reader) *LiveReader { + return &LiveReader{rdr: r} +} + +// Reader reads WAL records from an io.Reader. It buffers partial record data for +// the next read. +type LiveReader struct { + rdr io.Reader + err error + rec []byte + hdr [recordHeaderSize]byte + buf [pageSize]byte + readIndex int // Index in buf to start at for next read. + writeIndex int // Index in buf to start at for next write. + total int64 // Total bytes processed during reading in calls to Next(). + index int // Used to track partial records, should be 0 at the start of every new record. +} + +func (r *LiveReader) Err() error { + return r.err +} + +func (r *LiveReader) TotalRead() int64 { + return r.total +} + +func (r *LiveReader) fillBuffer() error { + n, err := r.rdr.Read(r.buf[r.writeIndex:len(r.buf)]) + r.writeIndex += n + return err +} + +// Shift the buffer up to the read index. +func (r *LiveReader) shiftBuffer() { + copied := copy(r.buf[0:], r.buf[r.readIndex:r.writeIndex]) + r.readIndex = 0 + r.writeIndex = copied +} + +// Next returns true if r.rec will contain a full record. +// False does not indicate that there will never be more data to +// read for the current io.Reader. +func (r *LiveReader) Next() bool { + for { + if r.buildRecord() { + return true + } + if r.err != nil && r.err != io.EOF { + return false + } + if r.readIndex == pageSize { + r.shiftBuffer() + } + if r.writeIndex != pageSize { + if err := r.fillBuffer(); err != nil { + // We expect to get EOF, since we're reading the segment file as it's being written. + if err != io.EOF { + r.err = err + } + return false + } + } + } +} + +// Record returns the current record. +// The returned byte slice is only valid until the next call to Next. +func (r *LiveReader) Record() []byte { + return r.rec +} + +// Rebuild a full record from potentially partial records. Returns false +// if there was an error or if we weren't able to read a record for any reason. +// Returns true if we read a full record. Any record data is appeneded to +// LiveReader.rec +func (r *LiveReader) buildRecord() bool { + for { + // Check that we have data in the internal buffer to read. + if r.writeIndex <= r.readIndex { + return false + } + + // Attempt to read a record, partial or otherwise. + temp, n, err := readRecord(r.buf[r.readIndex:r.writeIndex], r.hdr[:], r.total) + r.readIndex += n + r.total += int64(n) + if err != nil { + r.err = err + return false + } + + if temp == nil { + return false + } + + rt := recType(r.hdr[0]) + + if rt == recFirst || rt == recFull { + r.rec = r.rec[:0] + } + r.rec = append(r.rec, temp...) + + if err := validateRecord(rt, r.index); err != nil { + r.err = err + r.index = 0 + return false + } + if rt == recLast || rt == recFull { + r.index = 0 + return true + } + // Only increment i for non-zero records since we use it + // to determine valid content record sequences. + r.index++ + } +} + +// Returns an error if the recType and i indicate an invalid record sequence. +// As an example, if i is > 0 because we've read some amount of a partial record +// (recFirst, recMiddle, etc. but not recLast) and then we get another recFirst or recFull +// instead of a recLast or recMiddle we would have an invalid record. +func validateRecord(typ recType, i int) error { + switch typ { + case recFull: + if i != 0 { + return errors.New("unexpected full record") + } + return nil + case recFirst: + if i != 0 { + return errors.New("unexpected first record, dropping buffer") + } + return nil + case recMiddle: + if i == 0 { + return errors.New("unexpected middle record, dropping buffer") + } + return nil + case recLast: + if i == 0 { + return errors.New("unexpected last record, dropping buffer") + } + return nil + default: + return errors.Errorf("unexpected record type %d", typ) + } +} + +// Read a sub-record (see recType) from the buffer. It could potentially +// be a full record (recFull) if the record fits within the bounds of a single page. +// Returns a byte slice of the record data read, the number of bytes read, and an error +// if there's a non-zero byte in a page term record or the record checksum fails. +// TODO(callum) the EOF errors we're returning from this function should theoretically +// never happen, add a metric for them. +func readRecord(buf []byte, header []byte, total int64) ([]byte, int, error) { + readIndex := 0 + header[0] = buf[0] + readIndex++ + total++ + + // The rest of this function is mostly from Reader.Next(). + typ := recType(header[0]) + // Gobble up zero bytes. + if typ == recPageTerm { + // We are pedantic and check whether the zeros are actually up to a page boundary. + // It's not strictly necessary but may catch sketchy state early. + k := pageSize - (total % pageSize) + if k == pageSize { + return nil, 1, nil // Initial 0 byte was last page byte. + } + + if k <= int64(len(buf)-readIndex) { + for _, v := range buf[readIndex : int64(readIndex)+k] { + readIndex++ + if v != 0 { + return nil, readIndex, errors.New("unexpected non-zero byte in page term bytes") + } + } + return nil, readIndex, nil + } + // Not enough bytes to read the rest of the page term rec. + // This theoretically should never happen, since we're only shifting the + // internal buffer of the live reader when we read to the end of page. + // Treat this the same as an EOF, it's an error we would expect to see. + return nil, 0, io.EOF + } + + if readIndex+recordHeaderSize-1 > len(buf) { + // Treat this the same as an EOF, it's an error we would expect to see. + return nil, 0, io.EOF + } + + copy(header[1:], buf[readIndex:readIndex+len(header[1:])]) + readIndex += recordHeaderSize - 1 + total += int64(recordHeaderSize - 1) + var ( + length = binary.BigEndian.Uint16(header[1:]) + crc = binary.BigEndian.Uint32(header[3:]) + ) + readTo := int(length) + readIndex + if readTo > len(buf) { + if (readTo - readIndex) > pageSize { + return nil, 0, errors.Errorf("invalid record, record size would be larger than max page size: %d", int(length)) + } + // Not enough data to read all of the record data. + // Treat this the same as an EOF, it's an error we would expect to see. + return nil, 0, io.EOF + } + recData := buf[readIndex:readTo] + readIndex += int(length) + total += int64(length) + + // TODO(callum) what should we do here, throw out the record? We should add a metric at least. + if c := crc32.Checksum(recData, castagnoliTable); c != crc { + return recData, readIndex, errors.Errorf("unexpected checksum %x, expected %x", c, crc) + } + return recData, readIndex, nil +} + +func min(i, j int) int { + if i < j { + return i + } + return j } diff --git a/vendor/github.com/prometheus/tsdb/wal/wal_test.go b/vendor/github.com/prometheus/tsdb/wal/wal_test.go deleted file mode 100644 index 16d277539..000000000 --- a/vendor/github.com/prometheus/tsdb/wal/wal_test.go +++ /dev/null @@ -1,349 +0,0 @@ -// Copyright 2017 The Prometheus Authors - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package wal - -import ( - "bytes" - "fmt" - "io/ioutil" - "math/rand" - "os" - "path/filepath" - "testing" - - "github.com/prometheus/tsdb/testutil" -) - -func TestWAL_Repair(t *testing.T) { - for name, test := range map[string]struct { - corrSgm int // Which segment to corrupt. - corrFunc func(f *os.File) // Func that applies the corruption. - intactRecs int // Total expected records left after the repair. - }{ - "torn_last_record": { - 2, - func(f *os.File) { - _, err := f.Seek(pageSize*2, 0) - testutil.Ok(t, err) - _, err = f.Write([]byte{byte(recFirst)}) - testutil.Ok(t, err) - }, - 8, - }, - // Ensures that the page buffer is big enough to fit - // an entire page size without panicing. - // https://github.com/prometheus/tsdb/pull/414 - "bad_header": { - 1, - func(f *os.File) { - _, err := f.Seek(pageSize, 0) - testutil.Ok(t, err) - _, err = f.Write([]byte{byte(recPageTerm)}) - testutil.Ok(t, err) - }, - 4, - }, - "bad_fragment_sequence": { - 1, - func(f *os.File) { - _, err := f.Seek(pageSize, 0) - testutil.Ok(t, err) - _, err = f.Write([]byte{byte(recLast)}) - testutil.Ok(t, err) - }, - 4, - }, - "bad_fragment_flag": { - 1, - func(f *os.File) { - _, err := f.Seek(pageSize, 0) - testutil.Ok(t, err) - _, err = f.Write([]byte{123}) - testutil.Ok(t, err) - }, - 4, - }, - "bad_checksum": { - 1, - func(f *os.File) { - _, err := f.Seek(pageSize+4, 0) - testutil.Ok(t, err) - _, err = f.Write([]byte{0}) - testutil.Ok(t, err) - }, - 4, - }, - "bad_length": { - 1, - func(f *os.File) { - _, err := f.Seek(pageSize+2, 0) - testutil.Ok(t, err) - _, err = f.Write([]byte{0}) - testutil.Ok(t, err) - }, - 4, - }, - "bad_content": { - 1, - func(f *os.File) { - _, err := f.Seek(pageSize+100, 0) - testutil.Ok(t, err) - _, err = f.Write([]byte("beef")) - testutil.Ok(t, err) - }, - 4, - }, - } { - t.Run(name, func(t *testing.T) { - dir, err := ioutil.TempDir("", "wal_repair") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - // We create 3 segments with 3 records each and - // then corrupt a given record in a given segment. - // As a result we want a repaired WAL with given intact records. - segSize := 3 * pageSize - w, err := NewSize(nil, nil, dir, segSize) - testutil.Ok(t, err) - - var records [][]byte - - for i := 1; i <= 9; i++ { - b := make([]byte, pageSize-recordHeaderSize) - b[0] = byte(i) - records = append(records, b) - testutil.Ok(t, w.Log(b)) - } - testutil.Ok(t, w.Close()) - - f, err := os.OpenFile(SegmentName(dir, test.corrSgm), os.O_RDWR, 0666) - testutil.Ok(t, err) - - // Apply corruption function. - test.corrFunc(f) - - testutil.Ok(t, f.Close()) - - w, err = NewSize(nil, nil, dir, segSize) - testutil.Ok(t, err) - - sr, err := NewSegmentsReader(dir) - testutil.Ok(t, err) - r := NewReader(sr) - - for r.Next() { - } - testutil.NotOk(t, r.Err()) - testutil.Ok(t, sr.Close()) - - testutil.Ok(t, w.Repair(r.Err())) - sr, err = NewSegmentsReader(dir) - testutil.Ok(t, err) - r = NewReader(sr) - - var result [][]byte - for r.Next() { - var b []byte - result = append(result, append(b, r.Record()...)) - } - testutil.Ok(t, r.Err()) - testutil.Equals(t, test.intactRecs, len(result), "Wrong number of intact records") - - for i, r := range result { - if !bytes.Equal(records[i], r) { - t.Fatalf("record %d diverges: want %x, got %x", i, records[i][:10], r[:10]) - } - } - - // Make sure the last segment is the corrupt segment. - _, last, err := w.Segments() - testutil.Ok(t, err) - testutil.Equals(t, test.corrSgm, last) - }) - } -} - -// TestCorruptAndCarryOn writes a multi-segment WAL; corrupts the first segment and -// ensures that an error during reading that segment are correctly repaired before -// moving to write more records to the WAL. -func TestCorruptAndCarryOn(t *testing.T) { - dir, err := ioutil.TempDir("", "wal_repair") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - var ( - logger = testutil.NewLogger(t) - segmentSize = pageSize * 3 - recordSize = (pageSize / 3) - recordHeaderSize - ) - - // Produce a WAL with a two segments of 3 pages with 3 records each, - // so when we truncate the file we're guaranteed to split a record. - { - w, err := NewSize(logger, nil, dir, segmentSize) - testutil.Ok(t, err) - - for i := 0; i < 18; i++ { - buf := make([]byte, recordSize) - _, err := rand.Read(buf) - testutil.Ok(t, err) - - err = w.Log(buf) - testutil.Ok(t, err) - } - - err = w.Close() - testutil.Ok(t, err) - } - - // Check all the segments are the correct size. - { - segments, err := listSegments(dir) - testutil.Ok(t, err) - for _, segment := range segments { - f, err := os.OpenFile(filepath.Join(dir, fmt.Sprintf("%08d", segment.index)), os.O_RDONLY, 0666) - testutil.Ok(t, err) - - fi, err := f.Stat() - testutil.Ok(t, err) - - t.Log("segment", segment.index, "size", fi.Size()) - testutil.Equals(t, int64(segmentSize), fi.Size()) - - err = f.Close() - testutil.Ok(t, err) - } - } - - // Truncate the first file, splitting the middle record in the second - // page in half, leaving 4 valid records. - { - f, err := os.OpenFile(filepath.Join(dir, fmt.Sprintf("%08d", 0)), os.O_RDWR, 0666) - testutil.Ok(t, err) - - fi, err := f.Stat() - testutil.Ok(t, err) - testutil.Equals(t, int64(segmentSize), fi.Size()) - - err = f.Truncate(int64(segmentSize / 2)) - testutil.Ok(t, err) - - err = f.Close() - testutil.Ok(t, err) - } - - // Now try and repair this WAL, and write 5 more records to it. - { - sr, err := NewSegmentsReader(dir) - testutil.Ok(t, err) - - reader := NewReader(sr) - i := 0 - for ; i < 4 && reader.Next(); i++ { - testutil.Equals(t, recordSize, len(reader.Record())) - } - testutil.Equals(t, 4, i, "not enough records") - testutil.Assert(t, !reader.Next(), "unexpected record") - - corruptionErr := reader.Err() - testutil.Assert(t, corruptionErr != nil, "expected error") - - err = sr.Close() - testutil.Ok(t, err) - - w, err := NewSize(logger, nil, dir, segmentSize) - testutil.Ok(t, err) - - err = w.Repair(corruptionErr) - testutil.Ok(t, err) - - for i := 0; i < 5; i++ { - buf := make([]byte, recordSize) - _, err := rand.Read(buf) - testutil.Ok(t, err) - - err = w.Log(buf) - testutil.Ok(t, err) - } - - err = w.Close() - testutil.Ok(t, err) - } - - // Replay the WAL. Should get 9 records. - { - sr, err := NewSegmentsReader(dir) - testutil.Ok(t, err) - - reader := NewReader(sr) - i := 0 - for ; i < 9 && reader.Next(); i++ { - testutil.Equals(t, recordSize, len(reader.Record())) - } - testutil.Equals(t, 9, i, "wrong number of records") - testutil.Assert(t, !reader.Next(), "unexpected record") - testutil.Equals(t, nil, reader.Err()) - } -} - -func BenchmarkWAL_LogBatched(b *testing.B) { - dir, err := ioutil.TempDir("", "bench_logbatch") - testutil.Ok(b, err) - defer os.RemoveAll(dir) - - w, err := New(nil, nil, "testdir") - testutil.Ok(b, err) - defer w.Close() - - var buf [2048]byte - var recs [][]byte - b.SetBytes(2048) - - for i := 0; i < b.N; i++ { - recs = append(recs, buf[:]) - if len(recs) < 1000 { - continue - } - err := w.Log(recs...) - testutil.Ok(b, err) - recs = recs[:0] - } - // Stop timer to not count fsync time on close. - // If it's counted batched vs. single benchmarks are very similar but - // do not show burst throughput well. - b.StopTimer() -} - -func BenchmarkWAL_Log(b *testing.B) { - dir, err := ioutil.TempDir("", "bench_logsingle") - testutil.Ok(b, err) - defer os.RemoveAll(dir) - - w, err := New(nil, nil, "testdir") - testutil.Ok(b, err) - defer w.Close() - - var buf [2048]byte - b.SetBytes(2048) - - for i := 0; i < b.N; i++ { - err := w.Log(buf[:]) - testutil.Ok(b, err) - } - // Stop timer to not count fsync time on close. - // If it's counted batched vs. single benchmarks are very similar but - // do not show burst throughput well. - b.StopTimer() -} diff --git a/vendor/github.com/prometheus/tsdb/wal_test.go b/vendor/github.com/prometheus/tsdb/wal_test.go deleted file mode 100644 index fcda65b41..000000000 --- a/vendor/github.com/prometheus/tsdb/wal_test.go +++ /dev/null @@ -1,552 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// +build !windows - -package tsdb - -import ( - "encoding/binary" - "io" - "io/ioutil" - "math/rand" - "os" - "path" - "path/filepath" - "testing" - "time" - - "github.com/go-kit/kit/log" - "github.com/prometheus/tsdb/fileutil" - "github.com/prometheus/tsdb/labels" - "github.com/prometheus/tsdb/testutil" - "github.com/prometheus/tsdb/wal" -) - -func TestSegmentWAL_cut(t *testing.T) { - tmpdir, err := ioutil.TempDir("", "test_wal_cut") - testutil.Ok(t, err) - defer os.RemoveAll(tmpdir) - - // This calls cut() implicitly the first time without a previous tail. - w, err := OpenSegmentWAL(tmpdir, nil, 0, nil) - testutil.Ok(t, err) - - testutil.Ok(t, w.write(WALEntrySeries, 1, []byte("Hello World!!"))) - - testutil.Ok(t, w.cut()) - - // Cutting creates a new file. - testutil.Equals(t, 2, len(w.files)) - - testutil.Ok(t, w.write(WALEntrySeries, 1, []byte("Hello World!!"))) - - testutil.Ok(t, w.Close()) - - for _, of := range w.files { - f, err := os.Open(of.Name()) - testutil.Ok(t, err) - - // Verify header data. - metab := make([]byte, 8) - _, err = f.Read(metab) - testutil.Ok(t, err) - testutil.Equals(t, WALMagic, binary.BigEndian.Uint32(metab[:4])) - testutil.Equals(t, WALFormatDefault, metab[4]) - - // We cannot actually check for correct pre-allocation as it is - // optional per filesystem and handled transparently. - et, flag, b, err := newWALReader(nil, nil).entry(f) - testutil.Ok(t, err) - testutil.Equals(t, WALEntrySeries, et) - testutil.Equals(t, byte(walSeriesSimple), flag) - testutil.Equals(t, []byte("Hello World!!"), b) - } -} - -func TestSegmentWAL_Truncate(t *testing.T) { - const ( - numMetrics = 20000 - batch = 100 - ) - series, err := labels.ReadLabels(filepath.Join("testdata", "20kseries.json"), numMetrics) - testutil.Ok(t, err) - - dir, err := ioutil.TempDir("", "test_wal_log_truncate") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - w, err := OpenSegmentWAL(dir, nil, 0, nil) - testutil.Ok(t, err) - w.segmentSize = 10000 - - for i := 0; i < numMetrics; i += batch { - var rs []RefSeries - - for j, s := range series[i : i+batch] { - rs = append(rs, RefSeries{Labels: s, Ref: uint64(i+j) + 1}) - } - err := w.LogSeries(rs) - testutil.Ok(t, err) - } - - // We mark the 2nd half of the files with a min timestamp that should discard - // them from the selection of compactable files. - for i, f := range w.files[len(w.files)/2:] { - f.maxTime = int64(1000 + i) - } - // All series in those files must be preserved regarding of the provided postings list. - boundarySeries := w.files[len(w.files)/2].minSeries - - // We truncate while keeping every 2nd series. - keep := map[uint64]struct{}{} - for i := 1; i <= numMetrics; i += 2 { - keep[uint64(i)] = struct{}{} - } - keepf := func(id uint64) bool { - _, ok := keep[id] - return ok - } - - err = w.Truncate(1000, keepf) - testutil.Ok(t, err) - - var expected []RefSeries - - for i := 1; i <= numMetrics; i++ { - if i%2 == 1 || uint64(i) >= boundarySeries { - expected = append(expected, RefSeries{Ref: uint64(i), Labels: series[i-1]}) - } - } - - // Call Truncate once again to see whether we can read the written file without - // creating a new WAL. - err = w.Truncate(1000, keepf) - testutil.Ok(t, err) - testutil.Ok(t, w.Close()) - - // The same again with a new WAL. - w, err = OpenSegmentWAL(dir, nil, 0, nil) - testutil.Ok(t, err) - - var readSeries []RefSeries - r := w.Reader() - - r.Read(func(s []RefSeries) { - readSeries = append(readSeries, s...) - }, nil, nil) - - testutil.Equals(t, expected, readSeries) -} - -// Symmetrical test of reading and writing to the WAL via its main interface. -func TestSegmentWAL_Log_Restore(t *testing.T) { - const ( - numMetrics = 50 - iterations = 5 - stepSize = 5 - ) - // Generate testing data. It does not make semantical sense but - // for the purpose of this test. - series, err := labels.ReadLabels(filepath.Join("testdata", "20kseries.json"), numMetrics) - testutil.Ok(t, err) - - dir, err := ioutil.TempDir("", "test_wal_log_restore") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - var ( - recordedSeries [][]RefSeries - recordedSamples [][]RefSample - recordedDeletes [][]Stone - ) - var totalSamples int - - // Open WAL a bunch of times, validate all previous data can be read, - // write more data to it, close it. - for k := 0; k < numMetrics; k += numMetrics / iterations { - w, err := OpenSegmentWAL(dir, nil, 0, nil) - testutil.Ok(t, err) - - // Set smaller segment size so we can actually write several files. - w.segmentSize = 1000 * 1000 - - r := w.Reader() - - var ( - resultSeries [][]RefSeries - resultSamples [][]RefSample - resultDeletes [][]Stone - ) - - serf := func(series []RefSeries) { - if len(series) > 0 { - clsets := make([]RefSeries, len(series)) - copy(clsets, series) - resultSeries = append(resultSeries, clsets) - } - } - smplf := func(smpls []RefSample) { - if len(smpls) > 0 { - csmpls := make([]RefSample, len(smpls)) - copy(csmpls, smpls) - resultSamples = append(resultSamples, csmpls) - } - } - - delf := func(stones []Stone) { - if len(stones) > 0 { - cst := make([]Stone, len(stones)) - copy(cst, stones) - resultDeletes = append(resultDeletes, cst) - } - } - - testutil.Ok(t, r.Read(serf, smplf, delf)) - - testutil.Equals(t, recordedSamples, resultSamples) - testutil.Equals(t, recordedSeries, resultSeries) - testutil.Equals(t, recordedDeletes, resultDeletes) - - series := series[k : k+(numMetrics/iterations)] - - // Insert in batches and generate different amounts of samples for each. - for i := 0; i < len(series); i += stepSize { - var samples []RefSample - var stones []Stone - - for j := 0; j < i*10; j++ { - samples = append(samples, RefSample{ - Ref: uint64(j % 10000), - T: int64(j * 2), - V: rand.Float64(), - }) - } - - for j := 0; j < i*20; j++ { - ts := rand.Int63() - stones = append(stones, Stone{rand.Uint64(), Intervals{{ts, ts + rand.Int63n(10000)}}}) - } - - lbls := series[i : i+stepSize] - series := make([]RefSeries, 0, len(series)) - for j, l := range lbls { - series = append(series, RefSeries{ - Ref: uint64(i + j), - Labels: l, - }) - } - - testutil.Ok(t, w.LogSeries(series)) - testutil.Ok(t, w.LogSamples(samples)) - testutil.Ok(t, w.LogDeletes(stones)) - - if len(lbls) > 0 { - recordedSeries = append(recordedSeries, series) - } - if len(samples) > 0 { - recordedSamples = append(recordedSamples, samples) - totalSamples += len(samples) - } - if len(stones) > 0 { - recordedDeletes = append(recordedDeletes, stones) - } - } - - testutil.Ok(t, w.Close()) - } -} - -func TestWALRestoreCorrupted_invalidSegment(t *testing.T) { - dir, err := ioutil.TempDir("", "test_wal_log_restore") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - wal, err := OpenSegmentWAL(dir, nil, 0, nil) - testutil.Ok(t, err) - - _, err = wal.createSegmentFile(filepath.Join(dir, "000000")) - testutil.Ok(t, err) - f, err := wal.createSegmentFile(filepath.Join(dir, "000001")) - testutil.Ok(t, err) - f2, err := wal.createSegmentFile(filepath.Join(dir, "000002")) - testutil.Ok(t, err) - testutil.Ok(t, f2.Close()) - - // Make header of second segment invalid. - _, err = f.WriteAt([]byte{1, 2, 3, 4}, 0) - testutil.Ok(t, err) - testutil.Ok(t, f.Close()) - - testutil.Ok(t, wal.Close()) - - _, err = OpenSegmentWAL(dir, log.NewLogfmtLogger(os.Stderr), 0, nil) - testutil.Ok(t, err) - - fns, err := fileutil.ReadDir(dir) - testutil.Ok(t, err) - testutil.Equals(t, []string{"000000"}, fns) -} - -// Test reading from a WAL that has been corrupted through various means. -func TestWALRestoreCorrupted(t *testing.T) { - cases := []struct { - name string - f func(*testing.T, *SegmentWAL) - }{ - { - name: "truncate_checksum", - f: func(t *testing.T, w *SegmentWAL) { - f, err := os.OpenFile(w.files[0].Name(), os.O_WRONLY, 0666) - testutil.Ok(t, err) - defer f.Close() - - off, err := f.Seek(0, io.SeekEnd) - testutil.Ok(t, err) - - testutil.Ok(t, f.Truncate(off-1)) - }, - }, - { - name: "truncate_body", - f: func(t *testing.T, w *SegmentWAL) { - f, err := os.OpenFile(w.files[0].Name(), os.O_WRONLY, 0666) - testutil.Ok(t, err) - defer f.Close() - - off, err := f.Seek(0, io.SeekEnd) - testutil.Ok(t, err) - - testutil.Ok(t, f.Truncate(off-8)) - }, - }, - { - name: "body_content", - f: func(t *testing.T, w *SegmentWAL) { - f, err := os.OpenFile(w.files[0].Name(), os.O_WRONLY, 0666) - testutil.Ok(t, err) - defer f.Close() - - off, err := f.Seek(0, io.SeekEnd) - testutil.Ok(t, err) - - // Write junk before checksum starts. - _, err = f.WriteAt([]byte{1, 2, 3, 4}, off-8) - testutil.Ok(t, err) - }, - }, - { - name: "checksum", - f: func(t *testing.T, w *SegmentWAL) { - f, err := os.OpenFile(w.files[0].Name(), os.O_WRONLY, 0666) - testutil.Ok(t, err) - defer f.Close() - - off, err := f.Seek(0, io.SeekEnd) - testutil.Ok(t, err) - - // Write junk into checksum - _, err = f.WriteAt([]byte{1, 2, 3, 4}, off-4) - testutil.Ok(t, err) - }, - }, - } - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - // Generate testing data. It does not make semantical sense but - // for the purpose of this test. - dir, err := ioutil.TempDir("", "test_corrupted") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - w, err := OpenSegmentWAL(dir, nil, 0, nil) - testutil.Ok(t, err) - - testutil.Ok(t, w.LogSamples([]RefSample{{T: 1, V: 2}})) - testutil.Ok(t, w.LogSamples([]RefSample{{T: 2, V: 3}})) - - testutil.Ok(t, w.cut()) - - // Sleep 2 seconds to avoid error where cut and test "cases" function may write or - // truncate the file out of orders as "cases" are not synchronized with cut. - // Hopefully cut will complete by 2 seconds. - time.Sleep(2 * time.Second) - - testutil.Ok(t, w.LogSamples([]RefSample{{T: 3, V: 4}})) - testutil.Ok(t, w.LogSamples([]RefSample{{T: 5, V: 6}})) - - testutil.Ok(t, w.Close()) - - // cut() truncates and fsyncs the first segment async. If it happens after - // the corruption we apply below, the corruption will be overwritten again. - // Fire and forget a sync to avoid flakyness. - w.files[0].Sync() - // Corrupt the second entry in the first file. - // After re-opening we must be able to read the first entry - // and the rest, including the second file, must be truncated for clean further - // writes. - c.f(t, w) - - logger := log.NewLogfmtLogger(os.Stderr) - - w2, err := OpenSegmentWAL(dir, logger, 0, nil) - testutil.Ok(t, err) - - r := w2.Reader() - - serf := func(l []RefSeries) { - testutil.Equals(t, 0, len(l)) - } - - // Weird hack to check order of reads. - i := 0 - samplf := func(s []RefSample) { - if i == 0 { - testutil.Equals(t, []RefSample{{T: 1, V: 2}}, s) - i++ - } else { - testutil.Equals(t, []RefSample{{T: 99, V: 100}}, s) - } - } - - testutil.Ok(t, r.Read(serf, samplf, nil)) - - testutil.Ok(t, w2.LogSamples([]RefSample{{T: 99, V: 100}})) - testutil.Ok(t, w2.Close()) - - // We should see the first valid entry and the new one, everything after - // is truncated. - w3, err := OpenSegmentWAL(dir, logger, 0, nil) - testutil.Ok(t, err) - - r = w3.Reader() - - i = 0 - testutil.Ok(t, r.Read(serf, samplf, nil)) - }) - } -} - -func TestMigrateWAL_Empty(t *testing.T) { - // The migration proecedure must properly deal with a zero-length segment, - // which is valid in the new format. - dir, err := ioutil.TempDir("", "walmigrate") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - wdir := path.Join(dir, "wal") - - // Initialize empty WAL. - w, err := wal.New(nil, nil, wdir) - testutil.Ok(t, err) - testutil.Ok(t, w.Close()) - - testutil.Ok(t, MigrateWAL(nil, wdir)) -} - -func TestMigrateWAL_Fuzz(t *testing.T) { - dir, err := ioutil.TempDir("", "walmigrate") - testutil.Ok(t, err) - defer os.RemoveAll(dir) - - wdir := path.Join(dir, "wal") - - // Should pass if no WAL exists yet. - testutil.Ok(t, MigrateWAL(nil, wdir)) - - oldWAL, err := OpenSegmentWAL(wdir, nil, time.Minute, nil) - testutil.Ok(t, err) - - // Write some data. - testutil.Ok(t, oldWAL.LogSeries([]RefSeries{ - {Ref: 100, Labels: labels.FromStrings("abc", "def", "123", "456")}, - {Ref: 1, Labels: labels.FromStrings("abc", "def2", "1234", "4567")}, - })) - testutil.Ok(t, oldWAL.LogSamples([]RefSample{ - {Ref: 1, T: 100, V: 200}, - {Ref: 2, T: 300, V: 400}, - })) - testutil.Ok(t, oldWAL.LogSeries([]RefSeries{ - {Ref: 200, Labels: labels.FromStrings("xyz", "def", "foo", "bar")}, - })) - testutil.Ok(t, oldWAL.LogSamples([]RefSample{ - {Ref: 3, T: 100, V: 200}, - {Ref: 4, T: 300, V: 400}, - })) - testutil.Ok(t, oldWAL.LogDeletes([]Stone{ - {ref: 1, intervals: []Interval{{100, 200}}}, - })) - - testutil.Ok(t, oldWAL.Close()) - - // Perform migration. - testutil.Ok(t, MigrateWAL(nil, wdir)) - - w, err := wal.New(nil, nil, wdir) - testutil.Ok(t, err) - - // We can properly write some new data after migration. - var enc RecordEncoder - testutil.Ok(t, w.Log(enc.Samples([]RefSample{ - {Ref: 500, T: 1, V: 1}, - }, nil))) - - testutil.Ok(t, w.Close()) - - // Read back all data. - sr, err := wal.NewSegmentsReader(wdir) - testutil.Ok(t, err) - - r := wal.NewReader(sr) - var res []interface{} - var dec RecordDecoder - - for r.Next() { - rec := r.Record() - - switch dec.Type(rec) { - case RecordSeries: - s, err := dec.Series(rec, nil) - testutil.Ok(t, err) - res = append(res, s) - case RecordSamples: - s, err := dec.Samples(rec, nil) - testutil.Ok(t, err) - res = append(res, s) - case RecordTombstones: - s, err := dec.Tombstones(rec, nil) - testutil.Ok(t, err) - res = append(res, s) - default: - t.Fatalf("unknown record type %d", dec.Type(rec)) - } - } - testutil.Ok(t, r.Err()) - - testutil.Equals(t, []interface{}{ - []RefSeries{ - {Ref: 100, Labels: labels.FromStrings("abc", "def", "123", "456")}, - {Ref: 1, Labels: labels.FromStrings("abc", "def2", "1234", "4567")}, - }, - []RefSample{{Ref: 1, T: 100, V: 200}, {Ref: 2, T: 300, V: 400}}, - []RefSeries{ - {Ref: 200, Labels: labels.FromStrings("xyz", "def", "foo", "bar")}, - }, - []RefSample{{Ref: 3, T: 100, V: 200}, {Ref: 4, T: 300, V: 400}}, - []Stone{{ref: 1, intervals: []Interval{{100, 200}}}}, - []RefSample{{Ref: 500, T: 1, V: 1}}, - }, res) - - // Migrating an already migrated WAL shouldn't do anything. - testutil.Ok(t, MigrateWAL(nil, wdir)) -} diff --git a/vendor/github.com/satori/go.uuid/codec_test.go b/vendor/github.com/satori/go.uuid/codec_test.go deleted file mode 100644 index 7158c095a..000000000 --- a/vendor/github.com/satori/go.uuid/codec_test.go +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright (C) 2013-2018 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package uuid - -import ( - "bytes" - - . "gopkg.in/check.v1" -) - -type codecTestSuite struct{} - -var _ = Suite(&codecTestSuite{}) - -func (s *codecTestSuite) TestFromBytes(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - u1, err := FromBytes(b1) - c.Assert(err, IsNil) - c.Assert(u1, Equals, u) - - b2 := []byte{} - _, err = FromBytes(b2) - c.Assert(err, NotNil) -} - -func (s *codecTestSuite) BenchmarkFromBytes(c *C) { - bytes := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - for i := 0; i < c.N; i++ { - FromBytes(bytes) - } -} - -func (s *codecTestSuite) TestMarshalBinary(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - b2, err := u.MarshalBinary() - c.Assert(err, IsNil) - c.Assert(bytes.Equal(b1, b2), Equals, true) -} - -func (s *codecTestSuite) BenchmarkMarshalBinary(c *C) { - u, err := NewV4() - c.Assert(err, IsNil) - for i := 0; i < c.N; i++ { - u.MarshalBinary() - } -} - -func (s *codecTestSuite) TestUnmarshalBinary(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - u1 := UUID{} - err := u1.UnmarshalBinary(b1) - c.Assert(err, IsNil) - c.Assert(u1, Equals, u) - - b2 := []byte{} - u2 := UUID{} - err = u2.UnmarshalBinary(b2) - c.Assert(err, NotNil) -} - -func (s *codecTestSuite) TestFromString(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" - s2 := "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" - s3 := "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" - s4 := "6ba7b8109dad11d180b400c04fd430c8" - s5 := "urn:uuid:6ba7b8109dad11d180b400c04fd430c8" - - _, err := FromString("") - c.Assert(err, NotNil) - - u1, err := FromString(s1) - c.Assert(err, IsNil) - c.Assert(u1, Equals, u) - - u2, err := FromString(s2) - c.Assert(err, IsNil) - c.Assert(u2, Equals, u) - - u3, err := FromString(s3) - c.Assert(err, IsNil) - c.Assert(u3, Equals, u) - - u4, err := FromString(s4) - c.Assert(err, IsNil) - c.Assert(u4, Equals, u) - - u5, err := FromString(s5) - c.Assert(err, IsNil) - c.Assert(u5, Equals, u) -} - -func (s *codecTestSuite) BenchmarkFromString(c *C) { - str := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" - for i := 0; i < c.N; i++ { - FromString(str) - } -} - -func (s *codecTestSuite) BenchmarkFromStringUrn(c *C) { - str := "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" - for i := 0; i < c.N; i++ { - FromString(str) - } -} - -func (s *codecTestSuite) BenchmarkFromStringWithBrackets(c *C) { - str := "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" - for i := 0; i < c.N; i++ { - FromString(str) - } -} - -func (s *codecTestSuite) TestFromStringShort(c *C) { - // Invalid 35-character UUID string - s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c" - - for i := len(s1); i >= 0; i-- { - _, err := FromString(s1[:i]) - c.Assert(err, NotNil) - } -} - -func (s *codecTestSuite) TestFromStringLong(c *C) { - // Invalid 37+ character UUID string - strings := []string{ - "6ba7b810-9dad-11d1-80b4-00c04fd430c8=", - "6ba7b810-9dad-11d1-80b4-00c04fd430c8}", - "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}f", - "6ba7b810-9dad-11d1-80b4-00c04fd430c800c04fd430c8", - } - - for _, str := range strings { - _, err := FromString(str) - c.Assert(err, NotNil) - } -} - -func (s *codecTestSuite) TestFromStringInvalid(c *C) { - // Invalid UUID string formats - strings := []string{ - "6ba7b8109dad11d180b400c04fd430c86ba7b8109dad11d180b400c04fd430c8", - "urn:uuid:{6ba7b810-9dad-11d1-80b4-00c04fd430c8}", - "uuid:urn:6ba7b810-9dad-11d1-80b4-00c04fd430c8", - "uuid:urn:6ba7b8109dad11d180b400c04fd430c8", - "6ba7b8109-dad-11d1-80b4-00c04fd430c8", - "6ba7b810-9dad1-1d1-80b4-00c04fd430c8", - "6ba7b810-9dad-11d18-0b4-00c04fd430c8", - "6ba7b810-9dad-11d1-80b40-0c04fd430c8", - "6ba7b810+9dad+11d1+80b4+00c04fd430c8", - "(6ba7b810-9dad-11d1-80b4-00c04fd430c8}", - "{6ba7b810-9dad-11d1-80b4-00c04fd430c8>", - "zba7b810-9dad-11d1-80b4-00c04fd430c8", - "6ba7b810-9dad11d180b400c04fd430c8", - "6ba7b8109dad-11d180b400c04fd430c8", - "6ba7b8109dad11d1-80b400c04fd430c8", - "6ba7b8109dad11d180b4-00c04fd430c8", - } - - for _, str := range strings { - _, err := FromString(str) - c.Assert(err, NotNil) - } -} - -func (s *codecTestSuite) TestFromStringOrNil(c *C) { - u := FromStringOrNil("") - c.Assert(u, Equals, Nil) -} - -func (s *codecTestSuite) TestFromBytesOrNil(c *C) { - b := []byte{} - u := FromBytesOrNil(b) - c.Assert(u, Equals, Nil) -} - -func (s *codecTestSuite) TestMarshalText(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - - b2, err := u.MarshalText() - c.Assert(err, IsNil) - c.Assert(bytes.Equal(b1, b2), Equals, true) -} - -func (s *codecTestSuite) BenchmarkMarshalText(c *C) { - u, err := NewV4() - c.Assert(err, IsNil) - for i := 0; i < c.N; i++ { - u.MarshalText() - } -} - -func (s *codecTestSuite) TestUnmarshalText(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - - u1 := UUID{} - err := u1.UnmarshalText(b1) - c.Assert(err, IsNil) - c.Assert(u1, Equals, u) - - b2 := []byte("") - u2 := UUID{} - err = u2.UnmarshalText(b2) - c.Assert(err, NotNil) -} - -func (s *codecTestSuite) BenchmarkUnmarshalText(c *C) { - bytes := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - u := UUID{} - for i := 0; i < c.N; i++ { - u.UnmarshalText(bytes) - } -} - -var sink string - -func (s *codecTestSuite) BenchmarkMarshalToString(c *C) { - u, err := NewV4() - c.Assert(err, IsNil) - for i := 0; i < c.N; i++ { - sink = u.String() - } -} diff --git a/vendor/github.com/satori/go.uuid/generator_test.go b/vendor/github.com/satori/go.uuid/generator_test.go deleted file mode 100644 index a445fb0c7..000000000 --- a/vendor/github.com/satori/go.uuid/generator_test.go +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright (C) 2013-2018 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package uuid - -import ( - "bytes" - "crypto/rand" - "fmt" - "net" - "testing/iotest" - "time" - - . "gopkg.in/check.v1" -) - -type faultyReader struct { - callsNum int - readToFail int // Read call number to fail -} - -func (r *faultyReader) Read(dest []byte) (int, error) { - r.callsNum++ - if (r.callsNum - 1) == r.readToFail { - return 0, fmt.Errorf("io: reader is faulty") - } - return rand.Read(dest) -} - -type genTestSuite struct{} - -var _ = Suite(&genTestSuite{}) - -func (s *genTestSuite) TestNewV1(c *C) { - u1, err := NewV1() - c.Assert(err, IsNil) - c.Assert(u1.Version(), Equals, V1) - c.Assert(u1.Variant(), Equals, VariantRFC4122) - - u2, err := NewV1() - c.Assert(err, IsNil) - c.Assert(u1, Not(Equals), u2) -} - -func (s *genTestSuite) TestNewV1EpochStale(c *C) { - g := &rfc4122Generator{ - epochFunc: func() time.Time { - return time.Unix(0, 0) - }, - hwAddrFunc: defaultHWAddrFunc, - rand: rand.Reader, - } - u1, err := g.NewV1() - c.Assert(err, IsNil) - u2, err := g.NewV1() - c.Assert(err, IsNil) - c.Assert(u1, Not(Equals), u2) -} - -func (s *genTestSuite) TestNewV1FaultyRand(c *C) { - g := &rfc4122Generator{ - epochFunc: time.Now, - hwAddrFunc: defaultHWAddrFunc, - rand: &faultyReader{}, - } - u1, err := g.NewV1() - c.Assert(err, NotNil) - c.Assert(u1, Equals, Nil) -} - -func (s *genTestSuite) TestNewV1MissingNetworkInterfaces(c *C) { - g := &rfc4122Generator{ - epochFunc: time.Now, - hwAddrFunc: func() (net.HardwareAddr, error) { - return []byte{}, fmt.Errorf("uuid: no hw address found") - }, - rand: rand.Reader, - } - _, err := g.NewV1() - c.Assert(err, IsNil) -} - -func (s *genTestSuite) TestNewV1MissingNetInterfacesAndFaultyRand(c *C) { - g := &rfc4122Generator{ - epochFunc: time.Now, - hwAddrFunc: func() (net.HardwareAddr, error) { - return []byte{}, fmt.Errorf("uuid: no hw address found") - }, - rand: &faultyReader{ - readToFail: 1, - }, - } - u1, err := g.NewV1() - c.Assert(err, NotNil) - c.Assert(u1, Equals, Nil) -} - -func (s *genTestSuite) BenchmarkNewV1(c *C) { - for i := 0; i < c.N; i++ { - NewV1() - } -} - -func (s *genTestSuite) TestNewV2(c *C) { - u1, err := NewV2(DomainPerson) - c.Assert(err, IsNil) - c.Assert(u1.Version(), Equals, V2) - c.Assert(u1.Variant(), Equals, VariantRFC4122) - - u2, err := NewV2(DomainGroup) - c.Assert(err, IsNil) - c.Assert(u2.Version(), Equals, V2) - c.Assert(u2.Variant(), Equals, VariantRFC4122) - - u3, err := NewV2(DomainOrg) - c.Assert(err, IsNil) - c.Assert(u3.Version(), Equals, V2) - c.Assert(u3.Variant(), Equals, VariantRFC4122) -} - -func (s *genTestSuite) TestNewV2FaultyRand(c *C) { - g := &rfc4122Generator{ - epochFunc: time.Now, - hwAddrFunc: defaultHWAddrFunc, - rand: &faultyReader{}, - } - u1, err := g.NewV2(DomainPerson) - c.Assert(err, NotNil) - c.Assert(u1, Equals, Nil) -} - -func (s *genTestSuite) BenchmarkNewV2(c *C) { - for i := 0; i < c.N; i++ { - NewV2(DomainPerson) - } -} - -func (s *genTestSuite) TestNewV3(c *C) { - u1 := NewV3(NamespaceDNS, "www.example.com") - c.Assert(u1.Version(), Equals, V3) - c.Assert(u1.Variant(), Equals, VariantRFC4122) - c.Assert(u1.String(), Equals, "5df41881-3aed-3515-88a7-2f4a814cf09e") - - u2 := NewV3(NamespaceDNS, "example.com") - c.Assert(u2, Not(Equals), u1) - - u3 := NewV3(NamespaceDNS, "example.com") - c.Assert(u3, Equals, u2) - - u4 := NewV3(NamespaceURL, "example.com") - c.Assert(u4, Not(Equals), u3) -} - -func (s *genTestSuite) BenchmarkNewV3(c *C) { - for i := 0; i < c.N; i++ { - NewV3(NamespaceDNS, "www.example.com") - } -} - -func (s *genTestSuite) TestNewV4(c *C) { - u1, err := NewV4() - c.Assert(err, IsNil) - c.Assert(u1.Version(), Equals, V4) - c.Assert(u1.Variant(), Equals, VariantRFC4122) - - u2, err := NewV4() - c.Assert(err, IsNil) - c.Assert(u1, Not(Equals), u2) -} - -func (s *genTestSuite) TestNewV4FaultyRand(c *C) { - g := &rfc4122Generator{ - epochFunc: time.Now, - hwAddrFunc: defaultHWAddrFunc, - rand: &faultyReader{}, - } - u1, err := g.NewV4() - c.Assert(err, NotNil) - c.Assert(u1, Equals, Nil) -} - -func (s *genTestSuite) TestNewV4PartialRead(c *C) { - g := &rfc4122Generator{ - epochFunc: time.Now, - hwAddrFunc: defaultHWAddrFunc, - rand: iotest.OneByteReader(rand.Reader), - } - u1, err := g.NewV4() - zeros := bytes.Count(u1.Bytes(), []byte{0}) - mostlyZeros := zeros >= 10 - - c.Assert(err, IsNil) - c.Assert(mostlyZeros, Equals, false) -} - -func (s *genTestSuite) BenchmarkNewV4(c *C) { - for i := 0; i < c.N; i++ { - NewV4() - } -} - -func (s *genTestSuite) TestNewV5(c *C) { - u1 := NewV5(NamespaceDNS, "www.example.com") - c.Assert(u1.Version(), Equals, V5) - c.Assert(u1.Variant(), Equals, VariantRFC4122) - c.Assert(u1.String(), Equals, "2ed6657d-e927-568b-95e1-2665a8aea6a2") - - u2 := NewV5(NamespaceDNS, "example.com") - c.Assert(u2, Not(Equals), u1) - - u3 := NewV5(NamespaceDNS, "example.com") - c.Assert(u3, Equals, u2) - - u4 := NewV5(NamespaceURL, "example.com") - c.Assert(u4, Not(Equals), u3) -} - -func (s *genTestSuite) BenchmarkNewV5(c *C) { - for i := 0; i < c.N; i++ { - NewV5(NamespaceDNS, "www.example.com") - } -} diff --git a/vendor/github.com/satori/go.uuid/sql_test.go b/vendor/github.com/satori/go.uuid/sql_test.go deleted file mode 100644 index 74255f50d..000000000 --- a/vendor/github.com/satori/go.uuid/sql_test.go +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (C) 2013-2018 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package uuid - -import ( - . "gopkg.in/check.v1" -) - -type sqlTestSuite struct{} - -var _ = Suite(&sqlTestSuite{}) - -func (s *sqlTestSuite) TestValue(c *C) { - u, err := FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - c.Assert(err, IsNil) - - val, err := u.Value() - c.Assert(err, IsNil) - c.Assert(val, Equals, u.String()) -} - -func (s *sqlTestSuite) TestValueNil(c *C) { - u := UUID{} - - val, err := u.Value() - c.Assert(err, IsNil) - c.Assert(val, Equals, Nil.String()) -} - -func (s *sqlTestSuite) TestNullUUIDValueNil(c *C) { - u := NullUUID{} - - val, err := u.Value() - c.Assert(err, IsNil) - c.Assert(val, IsNil) -} - -func (s *sqlTestSuite) TestScanBinary(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - u1 := UUID{} - err := u1.Scan(b1) - c.Assert(err, IsNil) - c.Assert(u, Equals, u1) - - b2 := []byte{} - u2 := UUID{} - - err = u2.Scan(b2) - c.Assert(err, NotNil) -} - -func (s *sqlTestSuite) TestScanString(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" - - u1 := UUID{} - err := u1.Scan(s1) - c.Assert(err, IsNil) - c.Assert(u, Equals, u1) - - s2 := "" - u2 := UUID{} - - err = u2.Scan(s2) - c.Assert(err, NotNil) -} - -func (s *sqlTestSuite) TestScanText(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - - u1 := UUID{} - err := u1.Scan(b1) - c.Assert(err, IsNil) - c.Assert(u, Equals, u1) - - b2 := []byte("") - u2 := UUID{} - err = u2.Scan(b2) - c.Assert(err, NotNil) -} - -func (s *sqlTestSuite) TestScanUnsupported(c *C) { - u := UUID{} - - err := u.Scan(true) - c.Assert(err, NotNil) -} - -func (s *sqlTestSuite) TestScanNil(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - err := u.Scan(nil) - c.Assert(err, NotNil) -} - -func (s *sqlTestSuite) TestNullUUIDScanValid(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" - - u1 := NullUUID{} - err := u1.Scan(s1) - c.Assert(err, IsNil) - c.Assert(u1.Valid, Equals, true) - c.Assert(u1.UUID, Equals, u) -} - -func (s *sqlTestSuite) TestNullUUIDScanNil(c *C) { - u := NullUUID{UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}, true} - - err := u.Scan(nil) - c.Assert(err, IsNil) - c.Assert(u.Valid, Equals, false) - c.Assert(u.UUID, Equals, Nil) -} diff --git a/vendor/github.com/satori/go.uuid/uuid_test.go b/vendor/github.com/satori/go.uuid/uuid_test.go deleted file mode 100644 index fa40280a2..000000000 --- a/vendor/github.com/satori/go.uuid/uuid_test.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (C) 2013-2018 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package uuid - -import ( - "bytes" - "fmt" - "testing" - - . "gopkg.in/check.v1" -) - -// Hook up gocheck into the "go test" runner. -func TestUUID(t *testing.T) { TestingT(t) } - -type testSuite struct{} - -var _ = Suite(&testSuite{}) - -func (s *testSuite) TestBytes(c *C) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - bytes1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - c.Assert(bytes.Equal(u.Bytes(), bytes1), Equals, true) -} - -func (s *testSuite) TestString(c *C) { - c.Assert(NamespaceDNS.String(), Equals, "6ba7b810-9dad-11d1-80b4-00c04fd430c8") -} - -func (s *testSuite) TestEqual(c *C) { - c.Assert(Equal(NamespaceDNS, NamespaceDNS), Equals, true) - c.Assert(Equal(NamespaceDNS, NamespaceURL), Equals, false) -} - -func (s *testSuite) TestVersion(c *C) { - u := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - c.Assert(u.Version(), Equals, V1) -} - -func (s *testSuite) TestSetVersion(c *C) { - u := UUID{} - u.SetVersion(4) - c.Assert(u.Version(), Equals, V4) -} - -func (s *testSuite) TestVariant(c *C) { - u1 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - c.Assert(u1.Variant(), Equals, VariantNCS) - - u2 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - c.Assert(u2.Variant(), Equals, VariantRFC4122) - - u3 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - c.Assert(u3.Variant(), Equals, VariantMicrosoft) - - u4 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - c.Assert(u4.Variant(), Equals, VariantFuture) -} - -func (s *testSuite) TestSetVariant(c *C) { - u := UUID{} - u.SetVariant(VariantNCS) - c.Assert(u.Variant(), Equals, VariantNCS) - u.SetVariant(VariantRFC4122) - c.Assert(u.Variant(), Equals, VariantRFC4122) - u.SetVariant(VariantMicrosoft) - c.Assert(u.Variant(), Equals, VariantMicrosoft) - u.SetVariant(VariantFuture) - c.Assert(u.Variant(), Equals, VariantFuture) -} - -func (s *testSuite) TestMust(c *C) { - defer func() { - c.Assert(recover(), NotNil) - }() - Must(func() (UUID, error) { - return Nil, fmt.Errorf("uuid: expected error") - }()) -} diff --git a/vendor/github.com/sean-/seed/init_test.go b/vendor/github.com/sean-/seed/init_test.go deleted file mode 100644 index 4736061f7..000000000 --- a/vendor/github.com/sean-/seed/init_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package seed_test - -import ( - "testing" - - "github.com/sean-/seed" -) - -func TestInit(t *testing.T) { - secure, err := seed.Init() - if !secure { - t.Fatalf("Failed to securely seed: %v", err) - } -} - -func TestMustInit(t *testing.T) { - seed.MustInit() - - if !seed.Seeded() { - t.Fatalf("MustInit() failed to seed") - } - - if !seed.Secure() { - t.Fatalf("MustInit() failed to securely seed") - } -} diff --git a/vendor/github.com/serialx/hashring/hashring_test.go b/vendor/github.com/serialx/hashring/hashring_test.go deleted file mode 100644 index c673ba7f3..000000000 --- a/vendor/github.com/serialx/hashring/hashring_test.go +++ /dev/null @@ -1,521 +0,0 @@ -package hashring - -import ( - "reflect" - "testing" -) - -func expectNode(t *testing.T, hashRing *HashRing, key string, expectedNode string) { - node, ok := hashRing.GetNode(key) - if !ok || node != expectedNode { - t.Error("GetNode(", key, ") expected", expectedNode, "but got", node) - } -} - -func expectNodes(t *testing.T, hashRing *HashRing, key string, expectedNodes []string) { - nodes, ok := hashRing.GetNodes(key, 2) - sliceEquality := reflect.DeepEqual(nodes, expectedNodes) - if !ok || !sliceEquality { - t.Error("GetNodes(", key, ") expected", expectedNodes, "but got", nodes) - } -} - -func expectWeights(t *testing.T, hashRing *HashRing, expectedWeights map[string]int) { - weightsEquality := reflect.DeepEqual(hashRing.weights, expectedWeights) - if !weightsEquality { - t.Error("Weights expected", expectedWeights, "but got", hashRing.weights) - } -} - -func expectNodesABC(t *testing.T, hashRing *HashRing) { - // Python hash_ring module test case - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test1", "b") - expectNode(t, hashRing, "test2", "b") - expectNode(t, hashRing, "test3", "c") - expectNode(t, hashRing, "test4", "c") - expectNode(t, hashRing, "test5", "a") - expectNode(t, hashRing, "aaaa", "b") - expectNode(t, hashRing, "bbbb", "a") -} - -func expectNodeRangesABC(t *testing.T, hashRing *HashRing) { - expectNodes(t, hashRing, "test", []string{"a", "b"}) - expectNodes(t, hashRing, "test", []string{"a", "b"}) - expectNodes(t, hashRing, "test1", []string{"b", "c"}) - expectNodes(t, hashRing, "test2", []string{"b", "a"}) - expectNodes(t, hashRing, "test3", []string{"c", "a"}) - expectNodes(t, hashRing, "test4", []string{"c", "b"}) - expectNodes(t, hashRing, "test5", []string{"a", "c"}) - expectNodes(t, hashRing, "aaaa", []string{"b", "a"}) - expectNodes(t, hashRing, "bbbb", []string{"a", "b"}) -} - -func expectNodesABCD(t *testing.T, hashRing *HashRing) { - // Somehow adding d does not load balance these keys... - expectNodesABC(t, hashRing) -} - -func TestNew(t *testing.T) { - nodes := []string{"a", "b", "c"} - hashRing := New(nodes) - - expectNodesABC(t, hashRing) - expectNodeRangesABC(t, hashRing) -} - -func TestNewEmpty(t *testing.T) { - nodes := []string{} - hashRing := New(nodes) - - node, ok := hashRing.GetNode("test") - if ok || node != "" { - t.Error("GetNode(test) expected (\"\", false) but got (", node, ",", ok, ")") - } - - nodes, rok := hashRing.GetNodes("test", 2) - if rok || !(len(nodes) == 0) { - t.Error("GetNode(test) expected ( [], false ) but got (", nodes, ",", rok, ")") - } -} - -func TestForMoreNodes(t *testing.T) { - nodes := []string{"a", "b", "c"} - hashRing := New(nodes) - - nodes, ok := hashRing.GetNodes("test", 5) - if ok || !(len(nodes) == 0) { - t.Error("GetNode(test) expected ( [], false ) but got (", nodes, ",", ok, ")") - } -} - -func TestForEqualNodes(t *testing.T) { - nodes := []string{"a", "b", "c"} - hashRing := New(nodes) - - nodes, ok := hashRing.GetNodes("test", 3) - if !ok && (len(nodes) == 3) { - t.Error("GetNode(test) expected ( [a b c], true ) but got (", nodes, ",", ok, ")") - } -} - -func TestNewSingle(t *testing.T) { - nodes := []string{"a"} - hashRing := New(nodes) - - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test1", "a") - expectNode(t, hashRing, "test2", "a") - expectNode(t, hashRing, "test3", "a") - - // This triggers the edge case where sortedKey search resulting in not found - expectNode(t, hashRing, "test14", "a") - - expectNode(t, hashRing, "test15", "a") - expectNode(t, hashRing, "test16", "a") - expectNode(t, hashRing, "test17", "a") - expectNode(t, hashRing, "test18", "a") - expectNode(t, hashRing, "test19", "a") - expectNode(t, hashRing, "test20", "a") -} - -func TestNewWeighted(t *testing.T) { - weights := make(map[string]int) - weights["a"] = 1 - weights["b"] = 2 - weights["c"] = 1 - hashRing := NewWithWeights(weights) - - expectNode(t, hashRing, "test", "b") - expectNode(t, hashRing, "test", "b") - expectNode(t, hashRing, "test1", "b") - expectNode(t, hashRing, "test2", "b") - expectNode(t, hashRing, "test3", "c") - expectNode(t, hashRing, "test4", "b") - expectNode(t, hashRing, "test5", "b") - expectNode(t, hashRing, "aaaa", "b") - expectNode(t, hashRing, "bbbb", "a") - - expectNodes(t, hashRing, "test", []string{"b", "a"}) -} - -func TestRemoveNode(t *testing.T) { - nodes := []string{"a", "b", "c"} - hashRing := New(nodes) - hashRing = hashRing.RemoveNode("b") - - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test1", "c") // Migrated to c from b - expectNode(t, hashRing, "test2", "a") // Migrated to a from b - expectNode(t, hashRing, "test3", "c") - expectNode(t, hashRing, "test4", "c") - expectNode(t, hashRing, "test5", "a") - expectNode(t, hashRing, "aaaa", "a") // Migrated to a from b - expectNode(t, hashRing, "bbbb", "a") - - expectNodes(t, hashRing, "test", []string{"a", "c"}) -} - -func TestAddNode(t *testing.T) { - nodes := []string{"a", "c"} - hashRing := New(nodes) - hashRing = hashRing.AddNode("b") - - expectNodesABC(t, hashRing) - - defaultWeights := map[string]int{ - "a": 1, - "b": 1, - "c": 1, - } - expectWeights(t, hashRing, defaultWeights) -} - -func TestAddNode2(t *testing.T) { - nodes := []string{"a", "c"} - hashRing := New(nodes) - hashRing = hashRing.AddNode("b") - hashRing = hashRing.AddNode("b") - - expectNodesABC(t, hashRing) - expectNodeRangesABC(t, hashRing) -} - -func TestAddNode3(t *testing.T) { - nodes := []string{"a", "b", "c"} - hashRing := New(nodes) - hashRing = hashRing.AddNode("d") - - // Somehow adding d does not load balance these keys... - expectNodesABCD(t, hashRing) - - hashRing = hashRing.AddNode("e") - - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test1", "b") - expectNode(t, hashRing, "test2", "b") - expectNode(t, hashRing, "test3", "c") - expectNode(t, hashRing, "test4", "c") - expectNode(t, hashRing, "test5", "a") - expectNode(t, hashRing, "aaaa", "b") - expectNode(t, hashRing, "bbbb", "e") // Migrated to e from a - - expectNodes(t, hashRing, "test", []string{"a", "b"}) - - hashRing = hashRing.AddNode("f") - - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test1", "b") - expectNode(t, hashRing, "test2", "f") // Migrated to f from b - expectNode(t, hashRing, "test3", "f") // Migrated to f from c - expectNode(t, hashRing, "test4", "c") - expectNode(t, hashRing, "test5", "f") // Migrated to f from a - expectNode(t, hashRing, "aaaa", "b") - expectNode(t, hashRing, "bbbb", "e") - - expectNodes(t, hashRing, "test", []string{"a", "b"}) -} - -func TestDuplicateNodes(t *testing.T) { - nodes := []string{"a", "a", "a", "a", "b"} - hashRing := New(nodes) - - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test1", "b") - expectNode(t, hashRing, "test2", "b") - expectNode(t, hashRing, "test3", "a") - expectNode(t, hashRing, "test4", "b") - expectNode(t, hashRing, "test5", "a") - expectNode(t, hashRing, "aaaa", "b") - expectNode(t, hashRing, "bbbb", "a") -} - -func TestAddWeightedNode(t *testing.T) { - nodes := []string{"a", "c"} - hashRing := New(nodes) - hashRing = hashRing.AddWeightedNode("b", 0) - hashRing = hashRing.AddWeightedNode("b", 2) - hashRing = hashRing.AddWeightedNode("b", 2) - - expectNode(t, hashRing, "test", "b") - expectNode(t, hashRing, "test", "b") - expectNode(t, hashRing, "test1", "b") - expectNode(t, hashRing, "test2", "b") - expectNode(t, hashRing, "test3", "c") - expectNode(t, hashRing, "test4", "b") - expectNode(t, hashRing, "test5", "b") - expectNode(t, hashRing, "aaaa", "b") - expectNode(t, hashRing, "bbbb", "a") - - expectNodes(t, hashRing, "test", []string{"b", "a"}) -} - -func TestUpdateWeightedNode(t *testing.T) { - nodes := []string{"a", "c"} - hashRing := New(nodes) - hashRing = hashRing.AddWeightedNode("b", 1) - hashRing = hashRing.UpdateWeightedNode("b", 2) - hashRing = hashRing.UpdateWeightedNode("b", 2) - hashRing = hashRing.UpdateWeightedNode("b", 0) - hashRing = hashRing.UpdateWeightedNode("d", 2) - - expectNode(t, hashRing, "test", "b") - expectNode(t, hashRing, "test", "b") - expectNode(t, hashRing, "test1", "b") - expectNode(t, hashRing, "test2", "b") - expectNode(t, hashRing, "test3", "c") - expectNode(t, hashRing, "test4", "b") - expectNode(t, hashRing, "test5", "b") - expectNode(t, hashRing, "aaaa", "b") - expectNode(t, hashRing, "bbbb", "a") - - expectNodes(t, hashRing, "test", []string{"b", "a"}) -} - -func TestRemoveAddNode(t *testing.T) { - nodes := []string{"a", "b", "c"} - hashRing := New(nodes) - - expectNodesABC(t, hashRing) - expectNodeRangesABC(t, hashRing) - - hashRing = hashRing.RemoveNode("b") - - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test1", "c") // Migrated to c from b - expectNode(t, hashRing, "test2", "a") // Migrated to a from b - expectNode(t, hashRing, "test3", "c") - expectNode(t, hashRing, "test4", "c") - expectNode(t, hashRing, "test5", "a") - expectNode(t, hashRing, "aaaa", "a") // Migrated to a from b - expectNode(t, hashRing, "bbbb", "a") - - expectNodes(t, hashRing, "test", []string{"a", "c"}) - expectNodes(t, hashRing, "test", []string{"a", "c"}) - expectNodes(t, hashRing, "test1", []string{"c", "a"}) - expectNodes(t, hashRing, "test2", []string{"a", "c"}) - expectNodes(t, hashRing, "test3", []string{"c", "a"}) - expectNodes(t, hashRing, "test4", []string{"c", "a"}) - expectNodes(t, hashRing, "test5", []string{"a", "c"}) - expectNodes(t, hashRing, "aaaa", []string{"a", "c"}) - expectNodes(t, hashRing, "bbbb", []string{"a", "c"}) - - hashRing = hashRing.AddNode("b") - - expectNodesABC(t, hashRing) - expectNodeRangesABC(t, hashRing) -} - -func TestRemoveAddWeightedNode(t *testing.T) { - weights := make(map[string]int) - weights["a"] = 1 - weights["b"] = 2 - weights["c"] = 1 - hashRing := NewWithWeights(weights) - - expectWeights(t, hashRing, weights) - - expectNode(t, hashRing, "test", "b") - expectNode(t, hashRing, "test", "b") - expectNode(t, hashRing, "test1", "b") - expectNode(t, hashRing, "test2", "b") - expectNode(t, hashRing, "test3", "c") - expectNode(t, hashRing, "test4", "b") - expectNode(t, hashRing, "test5", "b") - expectNode(t, hashRing, "aaaa", "b") - expectNode(t, hashRing, "bbbb", "a") - - expectNodes(t, hashRing, "test", []string{"b", "a"}) - expectNodes(t, hashRing, "test", []string{"b", "a"}) - expectNodes(t, hashRing, "test1", []string{"b", "c"}) - expectNodes(t, hashRing, "test2", []string{"b", "a"}) - expectNodes(t, hashRing, "test3", []string{"c", "b"}) - expectNodes(t, hashRing, "test4", []string{"b", "a"}) - expectNodes(t, hashRing, "test5", []string{"b", "a"}) - expectNodes(t, hashRing, "aaaa", []string{"b", "a"}) - expectNodes(t, hashRing, "bbbb", []string{"a", "b"}) - - hashRing = hashRing.RemoveNode("c") - - delete(weights, "c") - expectWeights(t, hashRing, weights) - - expectNode(t, hashRing, "test", "b") - expectNode(t, hashRing, "test", "b") - expectNode(t, hashRing, "test1", "b") - expectNode(t, hashRing, "test2", "b") - expectNode(t, hashRing, "test3", "b") // Migrated to b from c - expectNode(t, hashRing, "test4", "b") - expectNode(t, hashRing, "test5", "b") - expectNode(t, hashRing, "aaaa", "b") - expectNode(t, hashRing, "bbbb", "a") - - expectNodes(t, hashRing, "test", []string{"b", "a"}) - expectNodes(t, hashRing, "test", []string{"b", "a"}) - expectNodes(t, hashRing, "test1", []string{"b", "a"}) - expectNodes(t, hashRing, "test2", []string{"b", "a"}) - expectNodes(t, hashRing, "test3", []string{"b", "a"}) - expectNodes(t, hashRing, "test4", []string{"b", "a"}) - expectNodes(t, hashRing, "test5", []string{"b", "a"}) - expectNodes(t, hashRing, "aaaa", []string{"b", "a"}) - expectNodes(t, hashRing, "bbbb", []string{"a", "b"}) -} - -func TestAddRemoveNode(t *testing.T) { - nodes := []string{"a", "b", "c"} - hashRing := New(nodes) - hashRing = hashRing.AddNode("d") - - // Somehow adding d does not load balance these keys... - expectNodesABCD(t, hashRing) - - expectNodes(t, hashRing, "test", []string{"a", "b"}) - expectNodes(t, hashRing, "test", []string{"a", "b"}) - expectNodes(t, hashRing, "test1", []string{"b", "d"}) - expectNodes(t, hashRing, "test2", []string{"b", "d"}) - expectNodes(t, hashRing, "test3", []string{"c", "d"}) - expectNodes(t, hashRing, "test4", []string{"c", "b"}) - expectNodes(t, hashRing, "test5", []string{"a", "d"}) - expectNodes(t, hashRing, "aaaa", []string{"b", "a"}) - expectNodes(t, hashRing, "bbbb", []string{"a", "b"}) - - hashRing = hashRing.AddNode("e") - - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test1", "b") - expectNode(t, hashRing, "test2", "b") - expectNode(t, hashRing, "test3", "c") - expectNode(t, hashRing, "test4", "c") - expectNode(t, hashRing, "test5", "a") - expectNode(t, hashRing, "aaaa", "b") - expectNode(t, hashRing, "bbbb", "e") // Migrated to e from a - - expectNodes(t, hashRing, "test", []string{"a", "b"}) - expectNodes(t, hashRing, "test", []string{"a", "b"}) - expectNodes(t, hashRing, "test1", []string{"b", "d"}) - expectNodes(t, hashRing, "test2", []string{"b", "d"}) - expectNodes(t, hashRing, "test3", []string{"c", "e"}) - expectNodes(t, hashRing, "test4", []string{"c", "b"}) - expectNodes(t, hashRing, "test5", []string{"a", "e"}) - expectNodes(t, hashRing, "aaaa", []string{"b", "e"}) - expectNodes(t, hashRing, "bbbb", []string{"e", "a"}) - - hashRing = hashRing.AddNode("f") - - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test1", "b") - expectNode(t, hashRing, "test2", "f") // Migrated to f from b - expectNode(t, hashRing, "test3", "f") // Migrated to f from c - expectNode(t, hashRing, "test4", "c") - expectNode(t, hashRing, "test5", "f") // Migrated to f from a - expectNode(t, hashRing, "aaaa", "b") - expectNode(t, hashRing, "bbbb", "e") - - expectNodes(t, hashRing, "test", []string{"a", "b"}) - expectNodes(t, hashRing, "test", []string{"a", "b"}) - expectNodes(t, hashRing, "test1", []string{"b", "d"}) - expectNodes(t, hashRing, "test2", []string{"f", "b"}) - expectNodes(t, hashRing, "test3", []string{"f", "c"}) - expectNodes(t, hashRing, "test4", []string{"c", "b"}) - expectNodes(t, hashRing, "test5", []string{"f", "a"}) - expectNodes(t, hashRing, "aaaa", []string{"b", "e"}) - expectNodes(t, hashRing, "bbbb", []string{"e", "f"}) - - hashRing = hashRing.RemoveNode("e") - - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test", "a") - expectNode(t, hashRing, "test1", "b") - expectNode(t, hashRing, "test2", "f") - expectNode(t, hashRing, "test3", "f") - expectNode(t, hashRing, "test4", "c") - expectNode(t, hashRing, "test5", "f") - expectNode(t, hashRing, "aaaa", "b") - expectNode(t, hashRing, "bbbb", "f") // Migrated to f from e - - expectNodes(t, hashRing, "test", []string{"a", "b"}) - expectNodes(t, hashRing, "test", []string{"a", "b"}) - expectNodes(t, hashRing, "test1", []string{"b", "d"}) - expectNodes(t, hashRing, "test2", []string{"f", "b"}) - expectNodes(t, hashRing, "test3", []string{"f", "c"}) - expectNodes(t, hashRing, "test4", []string{"c", "b"}) - expectNodes(t, hashRing, "test5", []string{"f", "a"}) - expectNodes(t, hashRing, "aaaa", []string{"b", "a"}) - expectNodes(t, hashRing, "bbbb", []string{"f", "a"}) - - hashRing = hashRing.RemoveNode("f") - - expectNodesABCD(t, hashRing) - - expectNodes(t, hashRing, "test", []string{"a", "b"}) - expectNodes(t, hashRing, "test", []string{"a", "b"}) - expectNodes(t, hashRing, "test1", []string{"b", "d"}) - expectNodes(t, hashRing, "test2", []string{"b", "d"}) - expectNodes(t, hashRing, "test3", []string{"c", "d"}) - expectNodes(t, hashRing, "test4", []string{"c", "b"}) - expectNodes(t, hashRing, "test5", []string{"a", "d"}) - expectNodes(t, hashRing, "aaaa", []string{"b", "a"}) - expectNodes(t, hashRing, "bbbb", []string{"a", "b"}) - - hashRing = hashRing.RemoveNode("d") - - expectNodesABC(t, hashRing) - expectNodeRangesABC(t, hashRing) -} - -func BenchmarkHashes(b *testing.B) { - nodes := []string{"a", "b", "c", "d", "e", "f", "g"} - hashRing := New(nodes) - tt := []struct { - key string - nodes []string - }{ - {"test", []string{"a", "b"}}, - {"test", []string{"a", "b"}}, - {"test1", []string{"b", "d"}}, - {"test2", []string{"f", "b"}}, - {"test3", []string{"f", "c"}}, - {"test4", []string{"c", "b"}}, - {"test5", []string{"f", "a"}}, - {"aaaa", []string{"b", "a"}}, - {"bbbb", []string{"f", "a"}}, - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - o := tt[i%len(tt)] - hashRing.GetNodes(o.key, 2) - } -} - -func BenchmarkHashesSingle(b *testing.B) { - nodes := []string{"a", "b", "c", "d", "e", "f", "g"} - hashRing := New(nodes) - tt := []struct { - key string - nodes []string - }{ - {"test", []string{"a", "b"}}, - {"test", []string{"a", "b"}}, - {"test1", []string{"b", "d"}}, - {"test2", []string{"f", "b"}}, - {"test3", []string{"f", "c"}}, - {"test4", []string{"c", "b"}}, - {"test5", []string{"f", "a"}}, - {"aaaa", []string{"b", "a"}}, - {"bbbb", []string{"f", "a"}}, - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - o := tt[i%len(tt)] - hashRing.GetNode(o.key) - } -} diff --git a/vendor/github.com/spf13/cobra/args_test.go b/vendor/github.com/spf13/cobra/args_test.go deleted file mode 100644 index d797b6f58..000000000 --- a/vendor/github.com/spf13/cobra/args_test.go +++ /dev/null @@ -1,241 +0,0 @@ -package cobra - -import ( - "strings" - "testing" -) - -func TestNoArgs(t *testing.T) { - c := &Command{Use: "c", Args: NoArgs, Run: emptyRun} - - output, err := executeCommand(c) - if output != "" { - t.Errorf("Unexpected string: %v", output) - } - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } -} - -func TestNoArgsWithArgs(t *testing.T) { - c := &Command{Use: "c", Args: NoArgs, Run: emptyRun} - - _, err := executeCommand(c, "illegal") - if err == nil { - t.Fatal("Expected an error") - } - - got := err.Error() - expected := `unknown command "illegal" for "c"` - if got != expected { - t.Errorf("Expected: %q, got: %q", expected, got) - } -} - -func TestOnlyValidArgs(t *testing.T) { - c := &Command{ - Use: "c", - Args: OnlyValidArgs, - ValidArgs: []string{"one", "two"}, - Run: emptyRun, - } - - output, err := executeCommand(c, "one", "two") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } -} - -func TestOnlyValidArgsWithInvalidArgs(t *testing.T) { - c := &Command{ - Use: "c", - Args: OnlyValidArgs, - ValidArgs: []string{"one", "two"}, - Run: emptyRun, - } - - _, err := executeCommand(c, "three") - if err == nil { - t.Fatal("Expected an error") - } - - got := err.Error() - expected := `invalid argument "three" for "c"` - if got != expected { - t.Errorf("Expected: %q, got: %q", expected, got) - } -} - -func TestArbitraryArgs(t *testing.T) { - c := &Command{Use: "c", Args: ArbitraryArgs, Run: emptyRun} - output, err := executeCommand(c, "a", "b") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } -} - -func TestMinimumNArgs(t *testing.T) { - c := &Command{Use: "c", Args: MinimumNArgs(2), Run: emptyRun} - output, err := executeCommand(c, "a", "b", "c") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } -} - -func TestMinimumNArgsWithLessArgs(t *testing.T) { - c := &Command{Use: "c", Args: MinimumNArgs(2), Run: emptyRun} - _, err := executeCommand(c, "a") - - if err == nil { - t.Fatal("Expected an error") - } - - got := err.Error() - expected := "requires at least 2 arg(s), only received 1" - if got != expected { - t.Fatalf("Expected %q, got %q", expected, got) - } -} - -func TestMaximumNArgs(t *testing.T) { - c := &Command{Use: "c", Args: MaximumNArgs(3), Run: emptyRun} - output, err := executeCommand(c, "a", "b") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } -} - -func TestMaximumNArgsWithMoreArgs(t *testing.T) { - c := &Command{Use: "c", Args: MaximumNArgs(2), Run: emptyRun} - _, err := executeCommand(c, "a", "b", "c") - - if err == nil { - t.Fatal("Expected an error") - } - - got := err.Error() - expected := "accepts at most 2 arg(s), received 3" - if got != expected { - t.Fatalf("Expected %q, got %q", expected, got) - } -} - -func TestExactArgs(t *testing.T) { - c := &Command{Use: "c", Args: ExactArgs(3), Run: emptyRun} - output, err := executeCommand(c, "a", "b", "c") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } -} - -func TestExactArgsWithInvalidCount(t *testing.T) { - c := &Command{Use: "c", Args: ExactArgs(2), Run: emptyRun} - _, err := executeCommand(c, "a", "b", "c") - - if err == nil { - t.Fatal("Expected an error") - } - - got := err.Error() - expected := "accepts 2 arg(s), received 3" - if got != expected { - t.Fatalf("Expected %q, got %q", expected, got) - } -} - -func TestRangeArgs(t *testing.T) { - c := &Command{Use: "c", Args: RangeArgs(2, 4), Run: emptyRun} - output, err := executeCommand(c, "a", "b", "c") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } -} - -func TestRangeArgsWithInvalidCount(t *testing.T) { - c := &Command{Use: "c", Args: RangeArgs(2, 4), Run: emptyRun} - _, err := executeCommand(c, "a") - - if err == nil { - t.Fatal("Expected an error") - } - - got := err.Error() - expected := "accepts between 2 and 4 arg(s), received 1" - if got != expected { - t.Fatalf("Expected %q, got %q", expected, got) - } -} - -func TestRootTakesNoArgs(t *testing.T) { - rootCmd := &Command{Use: "root", Run: emptyRun} - childCmd := &Command{Use: "child", Run: emptyRun} - rootCmd.AddCommand(childCmd) - - _, err := executeCommand(rootCmd, "illegal", "args") - if err == nil { - t.Fatal("Expected an error") - } - - got := err.Error() - expected := `unknown command "illegal" for "root"` - if !strings.Contains(got, expected) { - t.Errorf("expected %q, got %q", expected, got) - } -} - -func TestRootTakesArgs(t *testing.T) { - rootCmd := &Command{Use: "root", Args: ArbitraryArgs, Run: emptyRun} - childCmd := &Command{Use: "child", Run: emptyRun} - rootCmd.AddCommand(childCmd) - - _, err := executeCommand(rootCmd, "legal", "args") - if err != nil { - t.Errorf("Unexpected error: %v", err) - } -} - -func TestChildTakesNoArgs(t *testing.T) { - rootCmd := &Command{Use: "root", Run: emptyRun} - childCmd := &Command{Use: "child", Args: NoArgs, Run: emptyRun} - rootCmd.AddCommand(childCmd) - - _, err := executeCommand(rootCmd, "child", "illegal", "args") - if err == nil { - t.Fatal("Expected an error") - } - - got := err.Error() - expected := `unknown command "illegal" for "root child"` - if !strings.Contains(got, expected) { - t.Errorf("expected %q, got %q", expected, got) - } -} - -func TestChildTakesArgs(t *testing.T) { - rootCmd := &Command{Use: "root", Run: emptyRun} - childCmd := &Command{Use: "child", Args: ArbitraryArgs, Run: emptyRun} - rootCmd.AddCommand(childCmd) - - _, err := executeCommand(rootCmd, "child", "legal", "args") - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } -} diff --git a/vendor/github.com/spf13/cobra/bash_completions_test.go b/vendor/github.com/spf13/cobra/bash_completions_test.go deleted file mode 100644 index 02a4f15ba..000000000 --- a/vendor/github.com/spf13/cobra/bash_completions_test.go +++ /dev/null @@ -1,217 +0,0 @@ -package cobra - -import ( - "bytes" - "fmt" - "os" - "os/exec" - "regexp" - "strings" - "testing" -) - -func checkOmit(t *testing.T, found, unexpected string) { - if strings.Contains(found, unexpected) { - t.Errorf("Got: %q\nBut should not have!\n", unexpected) - } -} - -func check(t *testing.T, found, expected string) { - if !strings.Contains(found, expected) { - t.Errorf("Expecting to contain: \n %q\nGot:\n %q\n", expected, found) - } -} - -func checkRegex(t *testing.T, found, pattern string) { - matched, err := regexp.MatchString(pattern, found) - if err != nil { - t.Errorf("Error thrown performing MatchString: \n %s\n", err) - } - if !matched { - t.Errorf("Expecting to match: \n %q\nGot:\n %q\n", pattern, found) - } -} - -func runShellCheck(s string) error { - excluded := []string{ - "SC2034", // PREFIX appears unused. Verify it or export it. - } - cmd := exec.Command("shellcheck", "-s", "bash", "-", "-e", strings.Join(excluded, ",")) - cmd.Stderr = os.Stderr - cmd.Stdout = os.Stdout - - stdin, err := cmd.StdinPipe() - if err != nil { - return err - } - go func() { - stdin.Write([]byte(s)) - stdin.Close() - }() - - return cmd.Run() -} - -// World worst custom function, just keep telling you to enter hello! -const bashCompletionFunc = `__custom_func() { - COMPREPLY=( "hello" ) -} -` - -func TestBashCompletions(t *testing.T) { - rootCmd := &Command{ - Use: "root", - ArgAliases: []string{"pods", "nodes", "services", "replicationcontrollers", "po", "no", "svc", "rc"}, - ValidArgs: []string{"pod", "node", "service", "replicationcontroller"}, - BashCompletionFunction: bashCompletionFunc, - Run: emptyRun, - } - rootCmd.Flags().IntP("introot", "i", -1, "help message for flag introot") - rootCmd.MarkFlagRequired("introot") - - // Filename. - rootCmd.Flags().String("filename", "", "Enter a filename") - rootCmd.MarkFlagFilename("filename", "json", "yaml", "yml") - - // Persistent filename. - rootCmd.PersistentFlags().String("persistent-filename", "", "Enter a filename") - rootCmd.MarkPersistentFlagFilename("persistent-filename") - rootCmd.MarkPersistentFlagRequired("persistent-filename") - - // Filename extensions. - rootCmd.Flags().String("filename-ext", "", "Enter a filename (extension limited)") - rootCmd.MarkFlagFilename("filename-ext") - rootCmd.Flags().String("custom", "", "Enter a filename (extension limited)") - rootCmd.MarkFlagCustom("custom", "__complete_custom") - - // Subdirectories in a given directory. - rootCmd.Flags().String("theme", "", "theme to use (located in /themes/THEMENAME/)") - rootCmd.Flags().SetAnnotation("theme", BashCompSubdirsInDir, []string{"themes"}) - - echoCmd := &Command{ - Use: "echo [string to echo]", - Aliases: []string{"say"}, - Short: "Echo anything to the screen", - Long: "an utterly useless command for testing.", - Example: "Just run cobra-test echo", - Run: emptyRun, - } - - echoCmd.Flags().String("filename", "", "Enter a filename") - echoCmd.MarkFlagFilename("filename", "json", "yaml", "yml") - echoCmd.Flags().String("config", "", "config to use (located in /config/PROFILE/)") - echoCmd.Flags().SetAnnotation("config", BashCompSubdirsInDir, []string{"config"}) - - printCmd := &Command{ - Use: "print [string to print]", - Args: MinimumNArgs(1), - Short: "Print anything to the screen", - Long: "an absolutely utterly useless command for testing.", - Run: emptyRun, - } - - deprecatedCmd := &Command{ - Use: "deprecated [can't do anything here]", - Args: NoArgs, - Short: "A command which is deprecated", - Long: "an absolutely utterly useless command for testing deprecation!.", - Deprecated: "Please use echo instead", - Run: emptyRun, - } - - colonCmd := &Command{ - Use: "cmd:colon", - Run: emptyRun, - } - - timesCmd := &Command{ - Use: "times [# times] [string to echo]", - SuggestFor: []string{"counts"}, - Args: OnlyValidArgs, - ValidArgs: []string{"one", "two", "three", "four"}, - Short: "Echo anything to the screen more times", - Long: "a slightly useless command for testing.", - Run: emptyRun, - } - - echoCmd.AddCommand(timesCmd) - rootCmd.AddCommand(echoCmd, printCmd, deprecatedCmd, colonCmd) - - buf := new(bytes.Buffer) - rootCmd.GenBashCompletion(buf) - output := buf.String() - - check(t, output, "_root") - check(t, output, "_root_echo") - check(t, output, "_root_echo_times") - check(t, output, "_root_print") - check(t, output, "_root_cmd__colon") - - // check for required flags - check(t, output, `must_have_one_flag+=("--introot=")`) - check(t, output, `must_have_one_flag+=("--persistent-filename=")`) - // check for custom completion function - check(t, output, `COMPREPLY=( "hello" )`) - // check for required nouns - check(t, output, `must_have_one_noun+=("pod")`) - // check for noun aliases - check(t, output, `noun_aliases+=("pods")`) - check(t, output, `noun_aliases+=("rc")`) - checkOmit(t, output, `must_have_one_noun+=("pods")`) - // check for filename extension flags - check(t, output, `flags_completion+=("_filedir")`) - // check for filename extension flags - check(t, output, `must_have_one_noun+=("three")`) - // check for filename extension flags - check(t, output, fmt.Sprintf(`flags_completion+=("__%s_handle_filename_extension_flag json|yaml|yml")`, rootCmd.Name())) - // check for filename extension flags in a subcommand - checkRegex(t, output, fmt.Sprintf(`_root_echo\(\)\n{[^}]*flags_completion\+=\("__%s_handle_filename_extension_flag json\|yaml\|yml"\)`, rootCmd.Name())) - // check for custom flags - check(t, output, `flags_completion+=("__complete_custom")`) - // check for subdirs_in_dir flags - check(t, output, fmt.Sprintf(`flags_completion+=("__%s_handle_subdirs_in_dir_flag themes")`, rootCmd.Name())) - // check for subdirs_in_dir flags in a subcommand - checkRegex(t, output, fmt.Sprintf(`_root_echo\(\)\n{[^}]*flags_completion\+=\("__%s_handle_subdirs_in_dir_flag config"\)`, rootCmd.Name())) - - checkOmit(t, output, deprecatedCmd.Name()) - - // If available, run shellcheck against the script. - if err := exec.Command("which", "shellcheck").Run(); err != nil { - return - } - if err := runShellCheck(output); err != nil { - t.Fatalf("shellcheck failed: %v", err) - } -} - -func TestBashCompletionHiddenFlag(t *testing.T) { - c := &Command{Use: "c", Run: emptyRun} - - const flagName = "hiddenFlag" - c.Flags().Bool(flagName, false, "") - c.Flags().MarkHidden(flagName) - - buf := new(bytes.Buffer) - c.GenBashCompletion(buf) - output := buf.String() - - if strings.Contains(output, flagName) { - t.Errorf("Expected completion to not include %q flag: Got %v", flagName, output) - } -} - -func TestBashCompletionDeprecatedFlag(t *testing.T) { - c := &Command{Use: "c", Run: emptyRun} - - const flagName = "deprecated-flag" - c.Flags().Bool(flagName, false, "") - c.Flags().MarkDeprecated(flagName, "use --not-deprecated instead") - - buf := new(bytes.Buffer) - c.GenBashCompletion(buf) - output := buf.String() - - if strings.Contains(output, flagName) { - t.Errorf("expected completion to not include %q flag: Got %v", flagName, output) - } -} diff --git a/vendor/github.com/spf13/cobra/cobra_test.go b/vendor/github.com/spf13/cobra/cobra_test.go deleted file mode 100644 index 0d1755bdb..000000000 --- a/vendor/github.com/spf13/cobra/cobra_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package cobra - -import ( - "testing" - "text/template" -) - -func TestAddTemplateFunctions(t *testing.T) { - AddTemplateFunc("t", func() bool { return true }) - AddTemplateFuncs(template.FuncMap{ - "f": func() bool { return false }, - "h": func() string { return "Hello," }, - "w": func() string { return "world." }}) - - c := &Command{} - c.SetUsageTemplate(`{{if t}}{{h}}{{end}}{{if f}}{{h}}{{end}} {{w}}`) - - const expected = "Hello, world." - if got := c.UsageString(); got != expected { - t.Errorf("Expected UsageString: %v\nGot: %v", expected, got) - } -} diff --git a/vendor/github.com/spf13/cobra/command_test.go b/vendor/github.com/spf13/cobra/command_test.go deleted file mode 100644 index ccee031de..000000000 --- a/vendor/github.com/spf13/cobra/command_test.go +++ /dev/null @@ -1,1733 +0,0 @@ -package cobra - -import ( - "bytes" - "fmt" - "os" - "reflect" - "strings" - "testing" - - "github.com/spf13/pflag" -) - -func emptyRun(*Command, []string) {} - -func executeCommand(root *Command, args ...string) (output string, err error) { - _, output, err = executeCommandC(root, args...) - return output, err -} - -func executeCommandC(root *Command, args ...string) (c *Command, output string, err error) { - buf := new(bytes.Buffer) - root.SetOutput(buf) - root.SetArgs(args) - - c, err = root.ExecuteC() - - return c, buf.String(), err -} - -func resetCommandLineFlagSet() { - pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError) -} - -func checkStringContains(t *testing.T, got, expected string) { - if !strings.Contains(got, expected) { - t.Errorf("Expected to contain: \n %v\nGot:\n %v\n", expected, got) - } -} - -func checkStringOmits(t *testing.T, got, expected string) { - if strings.Contains(got, expected) { - t.Errorf("Expected to not contain: \n %v\nGot: %v", expected, got) - } -} - -func TestSingleCommand(t *testing.T) { - var rootCmdArgs []string - rootCmd := &Command{ - Use: "root", - Args: ExactArgs(2), - Run: func(_ *Command, args []string) { rootCmdArgs = args }, - } - aCmd := &Command{Use: "a", Args: NoArgs, Run: emptyRun} - bCmd := &Command{Use: "b", Args: NoArgs, Run: emptyRun} - rootCmd.AddCommand(aCmd, bCmd) - - output, err := executeCommand(rootCmd, "one", "two") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - got := strings.Join(rootCmdArgs, " ") - expected := "one two" - if got != expected { - t.Errorf("rootCmdArgs expected: %q, got: %q", expected, got) - } -} - -func TestChildCommand(t *testing.T) { - var child1CmdArgs []string - rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} - child1Cmd := &Command{ - Use: "child1", - Args: ExactArgs(2), - Run: func(_ *Command, args []string) { child1CmdArgs = args }, - } - child2Cmd := &Command{Use: "child2", Args: NoArgs, Run: emptyRun} - rootCmd.AddCommand(child1Cmd, child2Cmd) - - output, err := executeCommand(rootCmd, "child1", "one", "two") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - got := strings.Join(child1CmdArgs, " ") - expected := "one two" - if got != expected { - t.Errorf("child1CmdArgs expected: %q, got: %q", expected, got) - } -} - -func TestCallCommandWithoutSubcommands(t *testing.T) { - rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} - _, err := executeCommand(rootCmd) - if err != nil { - t.Errorf("Calling command without subcommands should not have error: %v", err) - } -} - -func TestRootExecuteUnknownCommand(t *testing.T) { - rootCmd := &Command{Use: "root", Run: emptyRun} - rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun}) - - output, _ := executeCommand(rootCmd, "unknown") - - expected := "Error: unknown command \"unknown\" for \"root\"\nRun 'root --help' for usage.\n" - - if output != expected { - t.Errorf("Expected:\n %q\nGot:\n %q\n", expected, output) - } -} - -func TestSubcommandExecuteC(t *testing.T) { - rootCmd := &Command{Use: "root", Run: emptyRun} - childCmd := &Command{Use: "child", Run: emptyRun} - rootCmd.AddCommand(childCmd) - - c, output, err := executeCommandC(rootCmd, "child") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - if c.Name() != "child" { - t.Errorf(`invalid command returned from ExecuteC: expected "child"', got %q`, c.Name()) - } -} - -func TestRootUnknownCommandSilenced(t *testing.T) { - rootCmd := &Command{Use: "root", Run: emptyRun} - rootCmd.SilenceErrors = true - rootCmd.SilenceUsage = true - rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun}) - - output, _ := executeCommand(rootCmd, "unknown") - if output != "" { - t.Errorf("Expected blank output, because of silenced usage.\nGot:\n %q\n", output) - } -} - -func TestCommandAlias(t *testing.T) { - var timesCmdArgs []string - rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} - echoCmd := &Command{ - Use: "echo", - Aliases: []string{"say", "tell"}, - Args: NoArgs, - Run: emptyRun, - } - timesCmd := &Command{ - Use: "times", - Args: ExactArgs(2), - Run: func(_ *Command, args []string) { timesCmdArgs = args }, - } - echoCmd.AddCommand(timesCmd) - rootCmd.AddCommand(echoCmd) - - output, err := executeCommand(rootCmd, "tell", "times", "one", "two") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - got := strings.Join(timesCmdArgs, " ") - expected := "one two" - if got != expected { - t.Errorf("timesCmdArgs expected: %v, got: %v", expected, got) - } -} - -func TestEnablePrefixMatching(t *testing.T) { - EnablePrefixMatching = true - - var aCmdArgs []string - rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} - aCmd := &Command{ - Use: "aCmd", - Args: ExactArgs(2), - Run: func(_ *Command, args []string) { aCmdArgs = args }, - } - bCmd := &Command{Use: "bCmd", Args: NoArgs, Run: emptyRun} - rootCmd.AddCommand(aCmd, bCmd) - - output, err := executeCommand(rootCmd, "a", "one", "two") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - got := strings.Join(aCmdArgs, " ") - expected := "one two" - if got != expected { - t.Errorf("aCmdArgs expected: %q, got: %q", expected, got) - } - - EnablePrefixMatching = false -} - -func TestAliasPrefixMatching(t *testing.T) { - EnablePrefixMatching = true - - var timesCmdArgs []string - rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} - echoCmd := &Command{ - Use: "echo", - Aliases: []string{"say", "tell"}, - Args: NoArgs, - Run: emptyRun, - } - timesCmd := &Command{ - Use: "times", - Args: ExactArgs(2), - Run: func(_ *Command, args []string) { timesCmdArgs = args }, - } - echoCmd.AddCommand(timesCmd) - rootCmd.AddCommand(echoCmd) - - output, err := executeCommand(rootCmd, "sa", "times", "one", "two") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - got := strings.Join(timesCmdArgs, " ") - expected := "one two" - if got != expected { - t.Errorf("timesCmdArgs expected: %v, got: %v", expected, got) - } - - EnablePrefixMatching = false -} - -// TestChildSameName checks the correct behaviour of cobra in cases, -// when an application with name "foo" and with subcommand "foo" -// is executed with args "foo foo". -func TestChildSameName(t *testing.T) { - var fooCmdArgs []string - rootCmd := &Command{Use: "foo", Args: NoArgs, Run: emptyRun} - fooCmd := &Command{ - Use: "foo", - Args: ExactArgs(2), - Run: func(_ *Command, args []string) { fooCmdArgs = args }, - } - barCmd := &Command{Use: "bar", Args: NoArgs, Run: emptyRun} - rootCmd.AddCommand(fooCmd, barCmd) - - output, err := executeCommand(rootCmd, "foo", "one", "two") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - got := strings.Join(fooCmdArgs, " ") - expected := "one two" - if got != expected { - t.Errorf("fooCmdArgs expected: %v, got: %v", expected, got) - } -} - -// TestGrandChildSameName checks the correct behaviour of cobra in cases, -// when user has a root command and a grand child -// with the same name. -func TestGrandChildSameName(t *testing.T) { - var fooCmdArgs []string - rootCmd := &Command{Use: "foo", Args: NoArgs, Run: emptyRun} - barCmd := &Command{Use: "bar", Args: NoArgs, Run: emptyRun} - fooCmd := &Command{ - Use: "foo", - Args: ExactArgs(2), - Run: func(_ *Command, args []string) { fooCmdArgs = args }, - } - barCmd.AddCommand(fooCmd) - rootCmd.AddCommand(barCmd) - - output, err := executeCommand(rootCmd, "bar", "foo", "one", "two") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - got := strings.Join(fooCmdArgs, " ") - expected := "one two" - if got != expected { - t.Errorf("fooCmdArgs expected: %v, got: %v", expected, got) - } -} - -func TestFlagLong(t *testing.T) { - var cArgs []string - c := &Command{ - Use: "c", - Args: ArbitraryArgs, - Run: func(_ *Command, args []string) { cArgs = args }, - } - - var intFlagValue int - var stringFlagValue string - c.Flags().IntVar(&intFlagValue, "intf", -1, "") - c.Flags().StringVar(&stringFlagValue, "sf", "", "") - - output, err := executeCommand(c, "--intf=7", "--sf=abc", "one", "--", "two") - if output != "" { - t.Errorf("Unexpected output: %v", err) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - if c.ArgsLenAtDash() != 1 { - t.Errorf("Expected ArgsLenAtDash: %v but got %v", 1, c.ArgsLenAtDash()) - } - if intFlagValue != 7 { - t.Errorf("Expected intFlagValue: %v, got %v", 7, intFlagValue) - } - if stringFlagValue != "abc" { - t.Errorf("Expected stringFlagValue: %q, got %q", "abc", stringFlagValue) - } - - got := strings.Join(cArgs, " ") - expected := "one two" - if got != expected { - t.Errorf("Expected arguments: %q, got %q", expected, got) - } -} - -func TestFlagShort(t *testing.T) { - var cArgs []string - c := &Command{ - Use: "c", - Args: ArbitraryArgs, - Run: func(_ *Command, args []string) { cArgs = args }, - } - - var intFlagValue int - var stringFlagValue string - c.Flags().IntVarP(&intFlagValue, "intf", "i", -1, "") - c.Flags().StringVarP(&stringFlagValue, "sf", "s", "", "") - - output, err := executeCommand(c, "-i", "7", "-sabc", "one", "two") - if output != "" { - t.Errorf("Unexpected output: %v", err) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - if intFlagValue != 7 { - t.Errorf("Expected flag value: %v, got %v", 7, intFlagValue) - } - if stringFlagValue != "abc" { - t.Errorf("Expected stringFlagValue: %q, got %q", "abc", stringFlagValue) - } - - got := strings.Join(cArgs, " ") - expected := "one two" - if got != expected { - t.Errorf("Expected arguments: %q, got %q", expected, got) - } -} - -func TestChildFlag(t *testing.T) { - rootCmd := &Command{Use: "root", Run: emptyRun} - childCmd := &Command{Use: "child", Run: emptyRun} - rootCmd.AddCommand(childCmd) - - var intFlagValue int - childCmd.Flags().IntVarP(&intFlagValue, "intf", "i", -1, "") - - output, err := executeCommand(rootCmd, "child", "-i7") - if output != "" { - t.Errorf("Unexpected output: %v", err) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - if intFlagValue != 7 { - t.Errorf("Expected flag value: %v, got %v", 7, intFlagValue) - } -} - -func TestChildFlagWithParentLocalFlag(t *testing.T) { - rootCmd := &Command{Use: "root", Run: emptyRun} - childCmd := &Command{Use: "child", Run: emptyRun} - rootCmd.AddCommand(childCmd) - - var intFlagValue int - rootCmd.Flags().StringP("sf", "s", "", "") - childCmd.Flags().IntVarP(&intFlagValue, "intf", "i", -1, "") - - _, err := executeCommand(rootCmd, "child", "-i7", "-sabc") - if err == nil { - t.Errorf("Invalid flag should generate error") - } - - checkStringContains(t, err.Error(), "unknown shorthand") - - if intFlagValue != 7 { - t.Errorf("Expected flag value: %v, got %v", 7, intFlagValue) - } -} - -func TestFlagInvalidInput(t *testing.T) { - rootCmd := &Command{Use: "root", Run: emptyRun} - rootCmd.Flags().IntP("intf", "i", -1, "") - - _, err := executeCommand(rootCmd, "-iabc") - if err == nil { - t.Errorf("Invalid flag value should generate error") - } - - checkStringContains(t, err.Error(), "invalid syntax") -} - -func TestFlagBeforeCommand(t *testing.T) { - rootCmd := &Command{Use: "root", Run: emptyRun} - childCmd := &Command{Use: "child", Run: emptyRun} - rootCmd.AddCommand(childCmd) - - var flagValue int - childCmd.Flags().IntVarP(&flagValue, "intf", "i", -1, "") - - // With short flag. - _, err := executeCommand(rootCmd, "-i7", "child") - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - if flagValue != 7 { - t.Errorf("Expected flag value: %v, got %v", 7, flagValue) - } - - // With long flag. - _, err = executeCommand(rootCmd, "--intf=8", "child") - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - if flagValue != 8 { - t.Errorf("Expected flag value: %v, got %v", 9, flagValue) - } -} - -func TestStripFlags(t *testing.T) { - tests := []struct { - input []string - output []string - }{ - { - []string{"foo", "bar"}, - []string{"foo", "bar"}, - }, - { - []string{"foo", "--str", "-s"}, - []string{"foo"}, - }, - { - []string{"-s", "foo", "--str", "bar"}, - []string{}, - }, - { - []string{"-i10", "echo"}, - []string{"echo"}, - }, - { - []string{"-i=10", "echo"}, - []string{"echo"}, - }, - { - []string{"--int=100", "echo"}, - []string{"echo"}, - }, - { - []string{"-ib", "echo", "-sfoo", "baz"}, - []string{"echo", "baz"}, - }, - { - []string{"-i=baz", "bar", "-i", "foo", "blah"}, - []string{"bar", "blah"}, - }, - { - []string{"--int=baz", "-sbar", "-i", "foo", "blah"}, - []string{"blah"}, - }, - { - []string{"--bool", "bar", "-i", "foo", "blah"}, - []string{"bar", "blah"}, - }, - { - []string{"-b", "bar", "-i", "foo", "blah"}, - []string{"bar", "blah"}, - }, - { - []string{"--persist", "bar"}, - []string{"bar"}, - }, - { - []string{"-p", "bar"}, - []string{"bar"}, - }, - } - - c := &Command{Use: "c", Run: emptyRun} - c.PersistentFlags().BoolP("persist", "p", false, "") - c.Flags().IntP("int", "i", -1, "") - c.Flags().StringP("str", "s", "", "") - c.Flags().BoolP("bool", "b", false, "") - - for i, test := range tests { - got := stripFlags(test.input, c) - if !reflect.DeepEqual(test.output, got) { - t.Errorf("(%v) Expected: %v, got: %v", i, test.output, got) - } - } -} - -func TestDisableFlagParsing(t *testing.T) { - var cArgs []string - c := &Command{ - Use: "c", - DisableFlagParsing: true, - Run: func(_ *Command, args []string) { - cArgs = args - }, - } - - args := []string{"cmd", "-v", "-race", "-file", "foo.go"} - output, err := executeCommand(c, args...) - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - if !reflect.DeepEqual(args, cArgs) { - t.Errorf("Expected: %v, got: %v", args, cArgs) - } -} - -func TestPersistentFlagsOnSameCommand(t *testing.T) { - var rootCmdArgs []string - rootCmd := &Command{ - Use: "root", - Args: ArbitraryArgs, - Run: func(_ *Command, args []string) { rootCmdArgs = args }, - } - - var flagValue int - rootCmd.PersistentFlags().IntVarP(&flagValue, "intf", "i", -1, "") - - output, err := executeCommand(rootCmd, "-i7", "one", "two") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - got := strings.Join(rootCmdArgs, " ") - expected := "one two" - if got != expected { - t.Errorf("rootCmdArgs expected: %q, got %q", expected, got) - } - if flagValue != 7 { - t.Errorf("flagValue expected: %v, got %v", 7, flagValue) - } -} - -// TestEmptyInputs checks, -// if flags correctly parsed with blank strings in args. -func TestEmptyInputs(t *testing.T) { - c := &Command{Use: "c", Run: emptyRun} - - var flagValue int - c.Flags().IntVarP(&flagValue, "intf", "i", -1, "") - - output, err := executeCommand(c, "", "-i7", "") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - if flagValue != 7 { - t.Errorf("flagValue expected: %v, got %v", 7, flagValue) - } -} - -func TestOverwrittenFlag(t *testing.T) { - // TODO: This test fails, but should work. - t.Skip() - - parent := &Command{Use: "parent", Run: emptyRun} - child := &Command{Use: "child", Run: emptyRun} - - parent.PersistentFlags().Bool("boolf", false, "") - parent.PersistentFlags().Int("intf", -1, "") - child.Flags().String("strf", "", "") - child.Flags().Int("intf", -1, "") - - parent.AddCommand(child) - - childInherited := child.InheritedFlags() - childLocal := child.LocalFlags() - - if childLocal.Lookup("strf") == nil { - t.Error(`LocalFlags expected to contain "strf", got "nil"`) - } - if childInherited.Lookup("boolf") == nil { - t.Error(`InheritedFlags expected to contain "boolf", got "nil"`) - } - - if childInherited.Lookup("intf") != nil { - t.Errorf(`InheritedFlags should not contain overwritten flag "intf"`) - } - if childLocal.Lookup("intf") == nil { - t.Error(`LocalFlags expected to contain "intf", got "nil"`) - } -} - -func TestPersistentFlagsOnChild(t *testing.T) { - var childCmdArgs []string - rootCmd := &Command{Use: "root", Run: emptyRun} - childCmd := &Command{ - Use: "child", - Args: ArbitraryArgs, - Run: func(_ *Command, args []string) { childCmdArgs = args }, - } - rootCmd.AddCommand(childCmd) - - var parentFlagValue int - var childFlagValue int - rootCmd.PersistentFlags().IntVarP(&parentFlagValue, "parentf", "p", -1, "") - childCmd.Flags().IntVarP(&childFlagValue, "childf", "c", -1, "") - - output, err := executeCommand(rootCmd, "child", "-c7", "-p8", "one", "two") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - got := strings.Join(childCmdArgs, " ") - expected := "one two" - if got != expected { - t.Errorf("childCmdArgs expected: %q, got %q", expected, got) - } - if parentFlagValue != 8 { - t.Errorf("parentFlagValue expected: %v, got %v", 8, parentFlagValue) - } - if childFlagValue != 7 { - t.Errorf("childFlagValue expected: %v, got %v", 7, childFlagValue) - } -} - -func TestRequiredFlags(t *testing.T) { - c := &Command{Use: "c", Run: emptyRun} - c.Flags().String("foo1", "", "") - c.MarkFlagRequired("foo1") - c.Flags().String("foo2", "", "") - c.MarkFlagRequired("foo2") - c.Flags().String("bar", "", "") - - expected := fmt.Sprintf("required flag(s) %q, %q not set", "foo1", "foo2") - - _, err := executeCommand(c) - got := err.Error() - - if got != expected { - t.Errorf("Expected error: %q, got: %q", expected, got) - } -} - -func TestPersistentRequiredFlags(t *testing.T) { - parent := &Command{Use: "parent", Run: emptyRun} - parent.PersistentFlags().String("foo1", "", "") - parent.MarkPersistentFlagRequired("foo1") - parent.PersistentFlags().String("foo2", "", "") - parent.MarkPersistentFlagRequired("foo2") - parent.Flags().String("foo3", "", "") - - child := &Command{Use: "child", Run: emptyRun} - child.Flags().String("bar1", "", "") - child.MarkFlagRequired("bar1") - child.Flags().String("bar2", "", "") - child.MarkFlagRequired("bar2") - child.Flags().String("bar3", "", "") - - parent.AddCommand(child) - - expected := fmt.Sprintf("required flag(s) %q, %q, %q, %q not set", "bar1", "bar2", "foo1", "foo2") - - _, err := executeCommand(parent, "child") - if err.Error() != expected { - t.Errorf("Expected %q, got %q", expected, err.Error()) - } -} - -func TestInitHelpFlagMergesFlags(t *testing.T) { - usage := "custom flag" - rootCmd := &Command{Use: "root"} - rootCmd.PersistentFlags().Bool("help", false, "custom flag") - childCmd := &Command{Use: "child"} - rootCmd.AddCommand(childCmd) - - childCmd.InitDefaultHelpFlag() - got := childCmd.Flags().Lookup("help").Usage - if got != usage { - t.Errorf("Expected the help flag from the root command with usage: %v\nGot the default with usage: %v", usage, got) - } -} - -func TestHelpCommandExecuted(t *testing.T) { - rootCmd := &Command{Use: "root", Long: "Long description", Run: emptyRun} - rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun}) - - output, err := executeCommand(rootCmd, "help") - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - checkStringContains(t, output, rootCmd.Long) -} - -func TestHelpCommandExecutedOnChild(t *testing.T) { - rootCmd := &Command{Use: "root", Run: emptyRun} - childCmd := &Command{Use: "child", Long: "Long description", Run: emptyRun} - rootCmd.AddCommand(childCmd) - - output, err := executeCommand(rootCmd, "help", "child") - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - checkStringContains(t, output, childCmd.Long) -} - -func TestSetHelpCommand(t *testing.T) { - c := &Command{Use: "c", Run: emptyRun} - c.AddCommand(&Command{Use: "empty", Run: emptyRun}) - - expected := "WORKS" - c.SetHelpCommand(&Command{ - Use: "help [command]", - Short: "Help about any command", - Long: `Help provides help for any command in the application. - Simply type ` + c.Name() + ` help [path to command] for full details.`, - Run: func(c *Command, _ []string) { c.Print(expected) }, - }) - - got, err := executeCommand(c, "help") - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - if got != expected { - t.Errorf("Expected to contain %q, got %q", expected, got) - } -} - -func TestHelpFlagExecuted(t *testing.T) { - rootCmd := &Command{Use: "root", Long: "Long description", Run: emptyRun} - - output, err := executeCommand(rootCmd, "--help") - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - checkStringContains(t, output, rootCmd.Long) -} - -func TestHelpFlagExecutedOnChild(t *testing.T) { - rootCmd := &Command{Use: "root", Run: emptyRun} - childCmd := &Command{Use: "child", Long: "Long description", Run: emptyRun} - rootCmd.AddCommand(childCmd) - - output, err := executeCommand(rootCmd, "child", "--help") - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - checkStringContains(t, output, childCmd.Long) -} - -// TestHelpFlagInHelp checks, -// if '--help' flag is shown in help for child (executing `parent help child`), -// that has no other flags. -// Related to https://github.com/spf13/cobra/issues/302. -func TestHelpFlagInHelp(t *testing.T) { - parentCmd := &Command{Use: "parent", Run: func(*Command, []string) {}} - - childCmd := &Command{Use: "child", Run: func(*Command, []string) {}} - parentCmd.AddCommand(childCmd) - - output, err := executeCommand(parentCmd, "help", "child") - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - checkStringContains(t, output, "[flags]") -} - -func TestFlagsInUsage(t *testing.T) { - rootCmd := &Command{Use: "root", Args: NoArgs, Run: func(*Command, []string) {}} - output, err := executeCommand(rootCmd, "--help") - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - checkStringContains(t, output, "[flags]") -} - -func TestHelpExecutedOnNonRunnableChild(t *testing.T) { - rootCmd := &Command{Use: "root", Run: emptyRun} - childCmd := &Command{Use: "child", Long: "Long description"} - rootCmd.AddCommand(childCmd) - - output, err := executeCommand(rootCmd, "child") - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - checkStringContains(t, output, childCmd.Long) -} - -func TestVersionFlagExecuted(t *testing.T) { - rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun} - - output, err := executeCommand(rootCmd, "--version", "arg1") - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - checkStringContains(t, output, "root version 1.0.0") -} - -func TestVersionTemplate(t *testing.T) { - rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun} - rootCmd.SetVersionTemplate(`customized version: {{.Version}}`) - - output, err := executeCommand(rootCmd, "--version", "arg1") - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - checkStringContains(t, output, "customized version: 1.0.0") -} - -func TestVersionFlagExecutedOnSubcommand(t *testing.T) { - rootCmd := &Command{Use: "root", Version: "1.0.0"} - rootCmd.AddCommand(&Command{Use: "sub", Run: emptyRun}) - - output, err := executeCommand(rootCmd, "--version", "sub") - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - checkStringContains(t, output, "root version 1.0.0") -} - -func TestVersionFlagOnlyAddedToRoot(t *testing.T) { - rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun} - rootCmd.AddCommand(&Command{Use: "sub", Run: emptyRun}) - - _, err := executeCommand(rootCmd, "sub", "--version") - if err == nil { - t.Errorf("Expected error") - } - - checkStringContains(t, err.Error(), "unknown flag: --version") -} - -func TestVersionFlagOnlyExistsIfVersionNonEmpty(t *testing.T) { - rootCmd := &Command{Use: "root", Run: emptyRun} - - _, err := executeCommand(rootCmd, "--version") - if err == nil { - t.Errorf("Expected error") - } - checkStringContains(t, err.Error(), "unknown flag: --version") -} - -func TestUsageIsNotPrintedTwice(t *testing.T) { - var cmd = &Command{Use: "root"} - var sub = &Command{Use: "sub"} - cmd.AddCommand(sub) - - output, _ := executeCommand(cmd, "") - if strings.Count(output, "Usage:") != 1 { - t.Error("Usage output is not printed exactly once") - } -} - -func TestVisitParents(t *testing.T) { - c := &Command{Use: "app"} - sub := &Command{Use: "sub"} - dsub := &Command{Use: "dsub"} - sub.AddCommand(dsub) - c.AddCommand(sub) - - total := 0 - add := func(x *Command) { - total++ - } - sub.VisitParents(add) - if total != 1 { - t.Errorf("Should have visited 1 parent but visited %d", total) - } - - total = 0 - dsub.VisitParents(add) - if total != 2 { - t.Errorf("Should have visited 2 parents but visited %d", total) - } - - total = 0 - c.VisitParents(add) - if total != 0 { - t.Errorf("Should have visited no parents but visited %d", total) - } -} - -func TestSuggestions(t *testing.T) { - rootCmd := &Command{Use: "root", Run: emptyRun} - timesCmd := &Command{ - Use: "times", - SuggestFor: []string{"counts"}, - Run: emptyRun, - } - rootCmd.AddCommand(timesCmd) - - templateWithSuggestions := "Error: unknown command \"%s\" for \"root\"\n\nDid you mean this?\n\t%s\n\nRun 'root --help' for usage.\n" - templateWithoutSuggestions := "Error: unknown command \"%s\" for \"root\"\nRun 'root --help' for usage.\n" - - tests := map[string]string{ - "time": "times", - "tiems": "times", - "tims": "times", - "timeS": "times", - "rimes": "times", - "ti": "times", - "t": "times", - "timely": "times", - "ri": "", - "timezone": "", - "foo": "", - "counts": "times", - } - - for typo, suggestion := range tests { - for _, suggestionsDisabled := range []bool{true, false} { - rootCmd.DisableSuggestions = suggestionsDisabled - - var expected string - output, _ := executeCommand(rootCmd, typo) - - if suggestion == "" || suggestionsDisabled { - expected = fmt.Sprintf(templateWithoutSuggestions, typo) - } else { - expected = fmt.Sprintf(templateWithSuggestions, typo, suggestion) - } - - if output != expected { - t.Errorf("Unexpected response.\nExpected:\n %q\nGot:\n %q\n", expected, output) - } - } - } -} - -func TestRemoveCommand(t *testing.T) { - rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} - childCmd := &Command{Use: "child", Run: emptyRun} - rootCmd.AddCommand(childCmd) - rootCmd.RemoveCommand(childCmd) - - _, err := executeCommand(rootCmd, "child") - if err == nil { - t.Error("Expected error on calling removed command. Got nil.") - } -} - -func TestReplaceCommandWithRemove(t *testing.T) { - childUsed := 0 - rootCmd := &Command{Use: "root", Run: emptyRun} - child1Cmd := &Command{ - Use: "child", - Run: func(*Command, []string) { childUsed = 1 }, - } - child2Cmd := &Command{ - Use: "child", - Run: func(*Command, []string) { childUsed = 2 }, - } - rootCmd.AddCommand(child1Cmd) - rootCmd.RemoveCommand(child1Cmd) - rootCmd.AddCommand(child2Cmd) - - output, err := executeCommand(rootCmd, "child") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - if childUsed == 1 { - t.Error("Removed command shouldn't be called") - } - if childUsed != 2 { - t.Error("Replacing command should have been called but didn't") - } -} - -func TestDeprecatedCommand(t *testing.T) { - rootCmd := &Command{Use: "root", Run: emptyRun} - deprecatedCmd := &Command{ - Use: "deprecated", - Deprecated: "This command is deprecated", - Run: emptyRun, - } - rootCmd.AddCommand(deprecatedCmd) - - output, err := executeCommand(rootCmd, "deprecated") - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - checkStringContains(t, output, deprecatedCmd.Deprecated) -} - -func TestHooks(t *testing.T) { - var ( - persPreArgs string - preArgs string - runArgs string - postArgs string - persPostArgs string - ) - - c := &Command{ - Use: "c", - PersistentPreRun: func(_ *Command, args []string) { - persPreArgs = strings.Join(args, " ") - }, - PreRun: func(_ *Command, args []string) { - preArgs = strings.Join(args, " ") - }, - Run: func(_ *Command, args []string) { - runArgs = strings.Join(args, " ") - }, - PostRun: func(_ *Command, args []string) { - postArgs = strings.Join(args, " ") - }, - PersistentPostRun: func(_ *Command, args []string) { - persPostArgs = strings.Join(args, " ") - }, - } - - output, err := executeCommand(c, "one", "two") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - if persPreArgs != "one two" { - t.Errorf("Expected persPreArgs %q, got %q", "one two", persPreArgs) - } - if preArgs != "one two" { - t.Errorf("Expected preArgs %q, got %q", "one two", preArgs) - } - if runArgs != "one two" { - t.Errorf("Expected runArgs %q, got %q", "one two", runArgs) - } - if postArgs != "one two" { - t.Errorf("Expected postArgs %q, got %q", "one two", postArgs) - } - if persPostArgs != "one two" { - t.Errorf("Expected persPostArgs %q, got %q", "one two", persPostArgs) - } -} - -func TestPersistentHooks(t *testing.T) { - var ( - parentPersPreArgs string - parentPreArgs string - parentRunArgs string - parentPostArgs string - parentPersPostArgs string - ) - - var ( - childPersPreArgs string - childPreArgs string - childRunArgs string - childPostArgs string - childPersPostArgs string - ) - - parentCmd := &Command{ - Use: "parent", - PersistentPreRun: func(_ *Command, args []string) { - parentPersPreArgs = strings.Join(args, " ") - }, - PreRun: func(_ *Command, args []string) { - parentPreArgs = strings.Join(args, " ") - }, - Run: func(_ *Command, args []string) { - parentRunArgs = strings.Join(args, " ") - }, - PostRun: func(_ *Command, args []string) { - parentPostArgs = strings.Join(args, " ") - }, - PersistentPostRun: func(_ *Command, args []string) { - parentPersPostArgs = strings.Join(args, " ") - }, - } - - childCmd := &Command{ - Use: "child", - PersistentPreRun: func(_ *Command, args []string) { - childPersPreArgs = strings.Join(args, " ") - }, - PreRun: func(_ *Command, args []string) { - childPreArgs = strings.Join(args, " ") - }, - Run: func(_ *Command, args []string) { - childRunArgs = strings.Join(args, " ") - }, - PostRun: func(_ *Command, args []string) { - childPostArgs = strings.Join(args, " ") - }, - PersistentPostRun: func(_ *Command, args []string) { - childPersPostArgs = strings.Join(args, " ") - }, - } - parentCmd.AddCommand(childCmd) - - output, err := executeCommand(parentCmd, "child", "one", "two") - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - // TODO: This test fails, but should not. - // Related to https://github.com/spf13/cobra/issues/252. - // - // if parentPersPreArgs != "one two" { - // t.Errorf("Expected parentPersPreArgs %q, got %q", "one two", parentPersPreArgs) - // } - if parentPreArgs != "" { - t.Errorf("Expected blank parentPreArgs, got %q", parentPreArgs) - } - if parentRunArgs != "" { - t.Errorf("Expected blank parentRunArgs, got %q", parentRunArgs) - } - if parentPostArgs != "" { - t.Errorf("Expected blank parentPostArgs, got %q", parentPostArgs) - } - // TODO: This test fails, but should not. - // Related to https://github.com/spf13/cobra/issues/252. - // - // if parentPersPostArgs != "one two" { - // t.Errorf("Expected parentPersPostArgs %q, got %q", "one two", parentPersPostArgs) - // } - - if childPersPreArgs != "one two" { - t.Errorf("Expected childPersPreArgs %q, got %q", "one two", childPersPreArgs) - } - if childPreArgs != "one two" { - t.Errorf("Expected childPreArgs %q, got %q", "one two", childPreArgs) - } - if childRunArgs != "one two" { - t.Errorf("Expected childRunArgs %q, got %q", "one two", childRunArgs) - } - if childPostArgs != "one two" { - t.Errorf("Expected childPostArgs %q, got %q", "one two", childPostArgs) - } - if childPersPostArgs != "one two" { - t.Errorf("Expected childPersPostArgs %q, got %q", "one two", childPersPostArgs) - } -} - -// Related to https://github.com/spf13/cobra/issues/521. -func TestGlobalNormFuncPropagation(t *testing.T) { - normFunc := func(f *pflag.FlagSet, name string) pflag.NormalizedName { - return pflag.NormalizedName(name) - } - - rootCmd := &Command{Use: "root", Run: emptyRun} - childCmd := &Command{Use: "child", Run: emptyRun} - rootCmd.AddCommand(childCmd) - - rootCmd.SetGlobalNormalizationFunc(normFunc) - if reflect.ValueOf(normFunc).Pointer() != reflect.ValueOf(rootCmd.GlobalNormalizationFunc()).Pointer() { - t.Error("rootCmd seems to have a wrong normalization function") - } - - if reflect.ValueOf(normFunc).Pointer() != reflect.ValueOf(childCmd.GlobalNormalizationFunc()).Pointer() { - t.Error("childCmd should have had the normalization function of rootCmd") - } -} - -// Related to https://github.com/spf13/cobra/issues/521. -func TestNormPassedOnLocal(t *testing.T) { - toUpper := func(f *pflag.FlagSet, name string) pflag.NormalizedName { - return pflag.NormalizedName(strings.ToUpper(name)) - } - - c := &Command{} - c.Flags().Bool("flagname", true, "this is a dummy flag") - c.SetGlobalNormalizationFunc(toUpper) - if c.LocalFlags().Lookup("flagname") != c.LocalFlags().Lookup("FLAGNAME") { - t.Error("Normalization function should be passed on to Local flag set") - } -} - -// Related to https://github.com/spf13/cobra/issues/521. -func TestNormPassedOnInherited(t *testing.T) { - toUpper := func(f *pflag.FlagSet, name string) pflag.NormalizedName { - return pflag.NormalizedName(strings.ToUpper(name)) - } - - c := &Command{} - c.SetGlobalNormalizationFunc(toUpper) - - child1 := &Command{} - c.AddCommand(child1) - - c.PersistentFlags().Bool("flagname", true, "") - - child2 := &Command{} - c.AddCommand(child2) - - inherited := child1.InheritedFlags() - if inherited.Lookup("flagname") == nil || inherited.Lookup("flagname") != inherited.Lookup("FLAGNAME") { - t.Error("Normalization function should be passed on to inherited flag set in command added before flag") - } - - inherited = child2.InheritedFlags() - if inherited.Lookup("flagname") == nil || inherited.Lookup("flagname") != inherited.Lookup("FLAGNAME") { - t.Error("Normalization function should be passed on to inherited flag set in command added after flag") - } -} - -// Related to https://github.com/spf13/cobra/issues/521. -func TestConsistentNormalizedName(t *testing.T) { - toUpper := func(f *pflag.FlagSet, name string) pflag.NormalizedName { - return pflag.NormalizedName(strings.ToUpper(name)) - } - n := func(f *pflag.FlagSet, name string) pflag.NormalizedName { - return pflag.NormalizedName(name) - } - - c := &Command{} - c.Flags().Bool("flagname", true, "") - c.SetGlobalNormalizationFunc(toUpper) - c.SetGlobalNormalizationFunc(n) - - if c.LocalFlags().Lookup("flagname") == c.LocalFlags().Lookup("FLAGNAME") { - t.Error("Normalizing flag names should not result in duplicate flags") - } -} - -func TestFlagOnPflagCommandLine(t *testing.T) { - flagName := "flagOnCommandLine" - pflag.String(flagName, "", "about my flag") - - c := &Command{Use: "c", Run: emptyRun} - c.AddCommand(&Command{Use: "child", Run: emptyRun}) - - output, _ := executeCommand(c, "--help") - checkStringContains(t, output, flagName) - - resetCommandLineFlagSet() -} - -// TestHiddenCommandExecutes checks, -// if hidden commands run as intended. -func TestHiddenCommandExecutes(t *testing.T) { - executed := false - c := &Command{ - Use: "c", - Hidden: true, - Run: func(*Command, []string) { executed = true }, - } - - output, err := executeCommand(c) - if output != "" { - t.Errorf("Unexpected output: %v", output) - } - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - if !executed { - t.Error("Hidden command should have been executed") - } -} - -// test to ensure hidden commands do not show up in usage/help text -func TestHiddenCommandIsHidden(t *testing.T) { - c := &Command{Use: "c", Hidden: true, Run: emptyRun} - if c.IsAvailableCommand() { - t.Errorf("Hidden command should be unavailable") - } -} - -func TestCommandsAreSorted(t *testing.T) { - EnableCommandSorting = true - - originalNames := []string{"middle", "zlast", "afirst"} - expectedNames := []string{"afirst", "middle", "zlast"} - - var rootCmd = &Command{Use: "root"} - - for _, name := range originalNames { - rootCmd.AddCommand(&Command{Use: name}) - } - - for i, c := range rootCmd.Commands() { - got := c.Name() - if expectedNames[i] != got { - t.Errorf("Expected: %s, got: %s", expectedNames[i], got) - } - } - - EnableCommandSorting = true -} - -func TestEnableCommandSortingIsDisabled(t *testing.T) { - EnableCommandSorting = false - - originalNames := []string{"middle", "zlast", "afirst"} - - var rootCmd = &Command{Use: "root"} - - for _, name := range originalNames { - rootCmd.AddCommand(&Command{Use: name}) - } - - for i, c := range rootCmd.Commands() { - got := c.Name() - if originalNames[i] != got { - t.Errorf("expected: %s, got: %s", originalNames[i], got) - } - } - - EnableCommandSorting = true -} - -func TestSetOutput(t *testing.T) { - c := &Command{} - c.SetOutput(nil) - if out := c.OutOrStdout(); out != os.Stdout { - t.Errorf("Expected setting output to nil to revert back to stdout") - } -} - -func TestFlagErrorFunc(t *testing.T) { - c := &Command{Use: "c", Run: emptyRun} - - expectedFmt := "This is expected: %v" - c.SetFlagErrorFunc(func(_ *Command, err error) error { - return fmt.Errorf(expectedFmt, err) - }) - - _, err := executeCommand(c, "--unknown-flag") - - got := err.Error() - expected := fmt.Sprintf(expectedFmt, "unknown flag: --unknown-flag") - if got != expected { - t.Errorf("Expected %v, got %v", expected, got) - } -} - -// TestSortedFlags checks, -// if cmd.LocalFlags() is unsorted when cmd.Flags().SortFlags set to false. -// Related to https://github.com/spf13/cobra/issues/404. -func TestSortedFlags(t *testing.T) { - c := &Command{} - c.Flags().SortFlags = false - names := []string{"C", "B", "A", "D"} - for _, name := range names { - c.Flags().Bool(name, false, "") - } - - i := 0 - c.LocalFlags().VisitAll(func(f *pflag.Flag) { - if i == len(names) { - return - } - if stringInSlice(f.Name, names) { - if names[i] != f.Name { - t.Errorf("Incorrect order. Expected %v, got %v", names[i], f.Name) - } - i++ - } - }) -} - -// TestMergeCommandLineToFlags checks, -// if pflag.CommandLine is correctly merged to c.Flags() after first call -// of c.mergePersistentFlags. -// Related to https://github.com/spf13/cobra/issues/443. -func TestMergeCommandLineToFlags(t *testing.T) { - pflag.Bool("boolflag", false, "") - c := &Command{Use: "c", Run: emptyRun} - c.mergePersistentFlags() - if c.Flags().Lookup("boolflag") == nil { - t.Fatal("Expecting to have flag from CommandLine in c.Flags()") - } - - resetCommandLineFlagSet() -} - -// TestUseDeprecatedFlags checks, -// if cobra.Execute() prints a message, if a deprecated flag is used. -// Related to https://github.com/spf13/cobra/issues/463. -func TestUseDeprecatedFlags(t *testing.T) { - c := &Command{Use: "c", Run: emptyRun} - c.Flags().BoolP("deprecated", "d", false, "deprecated flag") - c.Flags().MarkDeprecated("deprecated", "This flag is deprecated") - - output, err := executeCommand(c, "c", "-d") - if err != nil { - t.Error("Unexpected error:", err) - } - checkStringContains(t, output, "This flag is deprecated") -} - -func TestTraverseWithParentFlags(t *testing.T) { - rootCmd := &Command{Use: "root", TraverseChildren: true} - rootCmd.Flags().String("str", "", "") - rootCmd.Flags().BoolP("bool", "b", false, "") - - childCmd := &Command{Use: "child"} - childCmd.Flags().Int("int", -1, "") - - rootCmd.AddCommand(childCmd) - - c, args, err := rootCmd.Traverse([]string{"-b", "--str", "ok", "child", "--int"}) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - if len(args) != 1 && args[0] != "--add" { - t.Errorf("Wrong args: %v", args) - } - if c.Name() != childCmd.Name() { - t.Errorf("Expected command: %q, got: %q", childCmd.Name(), c.Name()) - } -} - -func TestTraverseNoParentFlags(t *testing.T) { - rootCmd := &Command{Use: "root", TraverseChildren: true} - rootCmd.Flags().String("foo", "", "foo things") - - childCmd := &Command{Use: "child"} - childCmd.Flags().String("str", "", "") - rootCmd.AddCommand(childCmd) - - c, args, err := rootCmd.Traverse([]string{"child"}) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - if len(args) != 0 { - t.Errorf("Wrong args %v", args) - } - if c.Name() != childCmd.Name() { - t.Errorf("Expected command: %q, got: %q", childCmd.Name(), c.Name()) - } -} - -func TestTraverseWithBadParentFlags(t *testing.T) { - rootCmd := &Command{Use: "root", TraverseChildren: true} - - childCmd := &Command{Use: "child"} - childCmd.Flags().String("str", "", "") - rootCmd.AddCommand(childCmd) - - expected := "unknown flag: --str" - - c, _, err := rootCmd.Traverse([]string{"--str", "ok", "child"}) - if err == nil || !strings.Contains(err.Error(), expected) { - t.Errorf("Expected error, %q, got %q", expected, err) - } - if c != nil { - t.Errorf("Expected nil command") - } -} - -func TestTraverseWithBadChildFlag(t *testing.T) { - rootCmd := &Command{Use: "root", TraverseChildren: true} - rootCmd.Flags().String("str", "", "") - - childCmd := &Command{Use: "child"} - rootCmd.AddCommand(childCmd) - - // Expect no error because the last commands args shouldn't be parsed in - // Traverse. - c, args, err := rootCmd.Traverse([]string{"child", "--str"}) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - if len(args) != 1 && args[0] != "--str" { - t.Errorf("Wrong args: %v", args) - } - if c.Name() != childCmd.Name() { - t.Errorf("Expected command %q, got: %q", childCmd.Name(), c.Name()) - } -} - -func TestTraverseWithTwoSubcommands(t *testing.T) { - rootCmd := &Command{Use: "root", TraverseChildren: true} - - subCmd := &Command{Use: "sub", TraverseChildren: true} - rootCmd.AddCommand(subCmd) - - subsubCmd := &Command{ - Use: "subsub", - } - subCmd.AddCommand(subsubCmd) - - c, _, err := rootCmd.Traverse([]string{"sub", "subsub"}) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if c.Name() != subsubCmd.Name() { - t.Fatalf("Expected command: %q, got %q", subsubCmd.Name(), c.Name()) - } -} - -// TestUpdateName checks if c.Name() updates on changed c.Use. -// Related to https://github.com/spf13/cobra/pull/422#discussion_r143918343. -func TestUpdateName(t *testing.T) { - c := &Command{Use: "name xyz"} - originalName := c.Name() - - c.Use = "changedName abc" - if originalName == c.Name() || c.Name() != "changedName" { - t.Error("c.Name() should be updated on changed c.Use") - } -} - -type calledAsTestcase struct { - args []string - call string - want string - epm bool - tc bool -} - -func (tc *calledAsTestcase) test(t *testing.T) { - defer func(ov bool) { EnablePrefixMatching = ov }(EnablePrefixMatching) - EnablePrefixMatching = tc.epm - - var called *Command - run := func(c *Command, _ []string) { t.Logf("called: %q", c.Name()); called = c } - - parent := &Command{Use: "parent", Run: run} - child1 := &Command{Use: "child1", Run: run, Aliases: []string{"this"}} - child2 := &Command{Use: "child2", Run: run, Aliases: []string{"that"}} - - parent.AddCommand(child1) - parent.AddCommand(child2) - parent.SetArgs(tc.args) - - output := new(bytes.Buffer) - parent.SetOutput(output) - - parent.Execute() - - if called == nil { - if tc.call != "" { - t.Errorf("missing expected call to command: %s", tc.call) - } - return - } - - if called.Name() != tc.call { - t.Errorf("called command == %q; Wanted %q", called.Name(), tc.call) - } else if got := called.CalledAs(); got != tc.want { - t.Errorf("%s.CalledAs() == %q; Wanted: %q", tc.call, got, tc.want) - } -} - -func TestCalledAs(t *testing.T) { - tests := map[string]calledAsTestcase{ - "find/no-args": {nil, "parent", "parent", false, false}, - "find/real-name": {[]string{"child1"}, "child1", "child1", false, false}, - "find/full-alias": {[]string{"that"}, "child2", "that", false, false}, - "find/part-no-prefix": {[]string{"thi"}, "", "", false, false}, - "find/part-alias": {[]string{"thi"}, "child1", "this", true, false}, - "find/conflict": {[]string{"th"}, "", "", true, false}, - "traverse/no-args": {nil, "parent", "parent", false, true}, - "traverse/real-name": {[]string{"child1"}, "child1", "child1", false, true}, - "traverse/full-alias": {[]string{"that"}, "child2", "that", false, true}, - "traverse/part-no-prefix": {[]string{"thi"}, "", "", false, true}, - "traverse/part-alias": {[]string{"thi"}, "child1", "this", true, true}, - "traverse/conflict": {[]string{"th"}, "", "", true, true}, - } - - for name, tc := range tests { - t.Run(name, tc.test) - } -} - -func TestFParseErrWhitelistBackwardCompatibility(t *testing.T) { - c := &Command{Use: "c", Run: emptyRun} - c.Flags().BoolP("boola", "a", false, "a boolean flag") - - output, err := executeCommand(c, "c", "-a", "--unknown", "flag") - if err == nil { - t.Error("expected unknown flag error") - } - checkStringContains(t, output, "unknown flag: --unknown") -} - -func TestFParseErrWhitelistSameCommand(t *testing.T) { - c := &Command{ - Use: "c", - Run: emptyRun, - FParseErrWhitelist: FParseErrWhitelist{ - UnknownFlags: true, - }, - } - c.Flags().BoolP("boola", "a", false, "a boolean flag") - - _, err := executeCommand(c, "c", "-a", "--unknown", "flag") - if err != nil { - t.Error("unexpected error: ", err) - } -} - -func TestFParseErrWhitelistParentCommand(t *testing.T) { - root := &Command{ - Use: "root", - Run: emptyRun, - FParseErrWhitelist: FParseErrWhitelist{ - UnknownFlags: true, - }, - } - - c := &Command{ - Use: "child", - Run: emptyRun, - } - c.Flags().BoolP("boola", "a", false, "a boolean flag") - - root.AddCommand(c) - - output, err := executeCommand(root, "child", "-a", "--unknown", "flag") - if err == nil { - t.Error("expected unknown flag error") - } - checkStringContains(t, output, "unknown flag: --unknown") -} - -func TestFParseErrWhitelistChildCommand(t *testing.T) { - root := &Command{ - Use: "root", - Run: emptyRun, - } - - c := &Command{ - Use: "child", - Run: emptyRun, - FParseErrWhitelist: FParseErrWhitelist{ - UnknownFlags: true, - }, - } - c.Flags().BoolP("boola", "a", false, "a boolean flag") - - root.AddCommand(c) - - _, err := executeCommand(root, "child", "-a", "--unknown", "flag") - if err != nil { - t.Error("unexpected error: ", err.Error()) - } -} - -func TestFParseErrWhitelistSiblingCommand(t *testing.T) { - root := &Command{ - Use: "root", - Run: emptyRun, - } - - c := &Command{ - Use: "child", - Run: emptyRun, - FParseErrWhitelist: FParseErrWhitelist{ - UnknownFlags: true, - }, - } - c.Flags().BoolP("boola", "a", false, "a boolean flag") - - s := &Command{ - Use: "sibling", - Run: emptyRun, - } - s.Flags().BoolP("boolb", "b", false, "a boolean flag") - - root.AddCommand(c) - root.AddCommand(s) - - output, err := executeCommand(root, "sibling", "-b", "--unknown", "flag") - if err == nil { - t.Error("expected unknown flag error") - } - checkStringContains(t, output, "unknown flag: --unknown") -} diff --git a/vendor/github.com/spf13/cobra/zsh_completions_test.go b/vendor/github.com/spf13/cobra/zsh_completions_test.go deleted file mode 100644 index 34e69496f..000000000 --- a/vendor/github.com/spf13/cobra/zsh_completions_test.go +++ /dev/null @@ -1,89 +0,0 @@ -package cobra - -import ( - "bytes" - "strings" - "testing" -) - -func TestZshCompletion(t *testing.T) { - tcs := []struct { - name string - root *Command - expectedExpressions []string - }{ - { - name: "trivial", - root: &Command{Use: "trivialapp"}, - expectedExpressions: []string{"#compdef trivial"}, - }, - { - name: "linear", - root: func() *Command { - r := &Command{Use: "linear"} - - sub1 := &Command{Use: "sub1"} - r.AddCommand(sub1) - - sub2 := &Command{Use: "sub2"} - sub1.AddCommand(sub2) - - sub3 := &Command{Use: "sub3"} - sub2.AddCommand(sub3) - return r - }(), - expectedExpressions: []string{"sub1", "sub2", "sub3"}, - }, - { - name: "flat", - root: func() *Command { - r := &Command{Use: "flat"} - r.AddCommand(&Command{Use: "c1"}) - r.AddCommand(&Command{Use: "c2"}) - return r - }(), - expectedExpressions: []string{"(c1 c2)"}, - }, - { - name: "tree", - root: func() *Command { - r := &Command{Use: "tree"} - - sub1 := &Command{Use: "sub1"} - r.AddCommand(sub1) - - sub11 := &Command{Use: "sub11"} - sub12 := &Command{Use: "sub12"} - - sub1.AddCommand(sub11) - sub1.AddCommand(sub12) - - sub2 := &Command{Use: "sub2"} - r.AddCommand(sub2) - - sub21 := &Command{Use: "sub21"} - sub22 := &Command{Use: "sub22"} - - sub2.AddCommand(sub21) - sub2.AddCommand(sub22) - - return r - }(), - expectedExpressions: []string{"(sub11 sub12)", "(sub21 sub22)"}, - }, - } - - for _, tc := range tcs { - t.Run(tc.name, func(t *testing.T) { - buf := new(bytes.Buffer) - tc.root.GenZshCompletion(buf) - output := buf.String() - - for _, expectedExpression := range tc.expectedExpressions { - if !strings.Contains(output, expectedExpression) { - t.Errorf("Expected completion to contain %q somewhere; got %q", expectedExpression, output) - } - } - }) - } -} diff --git a/vendor/github.com/spf13/pflag/bool_slice_test.go b/vendor/github.com/spf13/pflag/bool_slice_test.go deleted file mode 100644 index b617dd237..000000000 --- a/vendor/github.com/spf13/pflag/bool_slice_test.go +++ /dev/null @@ -1,215 +0,0 @@ -package pflag - -import ( - "fmt" - "strconv" - "strings" - "testing" -) - -func setUpBSFlagSet(bsp *[]bool) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.BoolSliceVar(bsp, "bs", []bool{}, "Command separated list!") - return f -} - -func setUpBSFlagSetWithDefault(bsp *[]bool) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.BoolSliceVar(bsp, "bs", []bool{false, true}, "Command separated list!") - return f -} - -func TestEmptyBS(t *testing.T) { - var bs []bool - f := setUpBSFlagSet(&bs) - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - getBS, err := f.GetBoolSlice("bs") - if err != nil { - t.Fatal("got an error from GetBoolSlice():", err) - } - if len(getBS) != 0 { - t.Fatalf("got bs %v with len=%d but expected length=0", getBS, len(getBS)) - } -} - -func TestBS(t *testing.T) { - var bs []bool - f := setUpBSFlagSet(&bs) - - vals := []string{"1", "F", "TRUE", "0"} - arg := fmt.Sprintf("--bs=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range bs { - b, err := strconv.ParseBool(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if b != v { - t.Fatalf("expected is[%d] to be %s but got: %t", i, vals[i], v) - } - } - getBS, err := f.GetBoolSlice("bs") - if err != nil { - t.Fatalf("got error: %v", err) - } - for i, v := range getBS { - b, err := strconv.ParseBool(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if b != v { - t.Fatalf("expected bs[%d] to be %s but got: %t from GetBoolSlice", i, vals[i], v) - } - } -} - -func TestBSDefault(t *testing.T) { - var bs []bool - f := setUpBSFlagSetWithDefault(&bs) - - vals := []string{"false", "T"} - - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range bs { - b, err := strconv.ParseBool(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if b != v { - t.Fatalf("expected bs[%d] to be %t from GetBoolSlice but got: %t", i, b, v) - } - } - - getBS, err := f.GetBoolSlice("bs") - if err != nil { - t.Fatal("got an error from GetBoolSlice():", err) - } - for i, v := range getBS { - b, err := strconv.ParseBool(vals[i]) - if err != nil { - t.Fatal("got an error from GetBoolSlice():", err) - } - if b != v { - t.Fatalf("expected bs[%d] to be %t from GetBoolSlice but got: %t", i, b, v) - } - } -} - -func TestBSWithDefault(t *testing.T) { - var bs []bool - f := setUpBSFlagSetWithDefault(&bs) - - vals := []string{"FALSE", "1"} - arg := fmt.Sprintf("--bs=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range bs { - b, err := strconv.ParseBool(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if b != v { - t.Fatalf("expected bs[%d] to be %t but got: %t", i, b, v) - } - } - - getBS, err := f.GetBoolSlice("bs") - if err != nil { - t.Fatal("got an error from GetBoolSlice():", err) - } - for i, v := range getBS { - b, err := strconv.ParseBool(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if b != v { - t.Fatalf("expected bs[%d] to be %t from GetBoolSlice but got: %t", i, b, v) - } - } -} - -func TestBSCalledTwice(t *testing.T) { - var bs []bool - f := setUpBSFlagSet(&bs) - - in := []string{"T,F", "T"} - expected := []bool{true, false, true} - argfmt := "--bs=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range bs { - if expected[i] != v { - t.Fatalf("expected bs[%d] to be %t but got %t", i, expected[i], v) - } - } -} - -func TestBSBadQuoting(t *testing.T) { - - tests := []struct { - Want []bool - FlagArg []string - }{ - { - Want: []bool{true, false, true}, - FlagArg: []string{"1", "0", "true"}, - }, - { - Want: []bool{true, false}, - FlagArg: []string{"True", "F"}, - }, - { - Want: []bool{true, false}, - FlagArg: []string{"T", "0"}, - }, - { - Want: []bool{true, false}, - FlagArg: []string{"1", "0"}, - }, - { - Want: []bool{true, false, false}, - FlagArg: []string{"true,false", "false"}, - }, - { - Want: []bool{true, false, false, true, false, true, false}, - FlagArg: []string{`"true,false,false,1,0, T"`, " false "}, - }, - { - Want: []bool{false, false, true, false, true, false, true}, - FlagArg: []string{`"0, False, T,false , true,F"`, "true"}, - }, - } - - for i, test := range tests { - - var bs []bool - f := setUpBSFlagSet(&bs) - - if err := f.Parse([]string{fmt.Sprintf("--bs=%s", strings.Join(test.FlagArg, ","))}); err != nil { - t.Fatalf("flag parsing failed with error: %s\nparsing:\t%#v\nwant:\t\t%#v", - err, test.FlagArg, test.Want[i]) - } - - for j, b := range bs { - if b != test.Want[j] { - t.Fatalf("bad value parsed for test %d on bool %d:\nwant:\t%t\ngot:\t%t", i, j, test.Want[j], b) - } - } - } -} diff --git a/vendor/github.com/spf13/pflag/bool_test.go b/vendor/github.com/spf13/pflag/bool_test.go deleted file mode 100644 index a4319e79f..000000000 --- a/vendor/github.com/spf13/pflag/bool_test.go +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - "bytes" - "strconv" - "testing" -) - -// This value can be a boolean ("true", "false") or "maybe" -type triStateValue int - -const ( - triStateFalse triStateValue = 0 - triStateTrue triStateValue = 1 - triStateMaybe triStateValue = 2 -) - -const strTriStateMaybe = "maybe" - -func (v *triStateValue) IsBoolFlag() bool { - return true -} - -func (v *triStateValue) Get() interface{} { - return triStateValue(*v) -} - -func (v *triStateValue) Set(s string) error { - if s == strTriStateMaybe { - *v = triStateMaybe - return nil - } - boolVal, err := strconv.ParseBool(s) - if boolVal { - *v = triStateTrue - } else { - *v = triStateFalse - } - return err -} - -func (v *triStateValue) String() string { - if *v == triStateMaybe { - return strTriStateMaybe - } - return strconv.FormatBool(*v == triStateTrue) -} - -// The type of the flag as required by the pflag.Value interface -func (v *triStateValue) Type() string { - return "version" -} - -func setUpFlagSet(tristate *triStateValue) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - *tristate = triStateFalse - flag := f.VarPF(tristate, "tristate", "t", "tristate value (true, maybe or false)") - flag.NoOptDefVal = "true" - return f -} - -func TestExplicitTrue(t *testing.T) { - var tristate triStateValue - f := setUpFlagSet(&tristate) - err := f.Parse([]string{"--tristate=true"}) - if err != nil { - t.Fatal("expected no error; got", err) - } - if tristate != triStateTrue { - t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead") - } -} - -func TestImplicitTrue(t *testing.T) { - var tristate triStateValue - f := setUpFlagSet(&tristate) - err := f.Parse([]string{"--tristate"}) - if err != nil { - t.Fatal("expected no error; got", err) - } - if tristate != triStateTrue { - t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead") - } -} - -func TestShortFlag(t *testing.T) { - var tristate triStateValue - f := setUpFlagSet(&tristate) - err := f.Parse([]string{"-t"}) - if err != nil { - t.Fatal("expected no error; got", err) - } - if tristate != triStateTrue { - t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead") - } -} - -func TestShortFlagExtraArgument(t *testing.T) { - var tristate triStateValue - f := setUpFlagSet(&tristate) - // The"maybe"turns into an arg, since short boolean options will only do true/false - err := f.Parse([]string{"-t", "maybe"}) - if err != nil { - t.Fatal("expected no error; got", err) - } - if tristate != triStateTrue { - t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead") - } - args := f.Args() - if len(args) != 1 || args[0] != "maybe" { - t.Fatal("expected an extra 'maybe' argument to stick around") - } -} - -func TestExplicitMaybe(t *testing.T) { - var tristate triStateValue - f := setUpFlagSet(&tristate) - err := f.Parse([]string{"--tristate=maybe"}) - if err != nil { - t.Fatal("expected no error; got", err) - } - if tristate != triStateMaybe { - t.Fatal("expected", triStateMaybe, "(triStateMaybe) but got", tristate, "instead") - } -} - -func TestExplicitFalse(t *testing.T) { - var tristate triStateValue - f := setUpFlagSet(&tristate) - err := f.Parse([]string{"--tristate=false"}) - if err != nil { - t.Fatal("expected no error; got", err) - } - if tristate != triStateFalse { - t.Fatal("expected", triStateFalse, "(triStateFalse) but got", tristate, "instead") - } -} - -func TestImplicitFalse(t *testing.T) { - var tristate triStateValue - f := setUpFlagSet(&tristate) - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - if tristate != triStateFalse { - t.Fatal("expected", triStateFalse, "(triStateFalse) but got", tristate, "instead") - } -} - -func TestInvalidValue(t *testing.T) { - var tristate triStateValue - f := setUpFlagSet(&tristate) - var buf bytes.Buffer - f.SetOutput(&buf) - err := f.Parse([]string{"--tristate=invalid"}) - if err == nil { - t.Fatal("expected an error but did not get any, tristate has value", tristate) - } -} - -func TestBoolP(t *testing.T) { - b := BoolP("bool", "b", false, "bool value in CommandLine") - c := BoolP("c", "c", false, "other bool value") - args := []string{"--bool"} - if err := CommandLine.Parse(args); err != nil { - t.Error("expected no error, got ", err) - } - if *b != true { - t.Errorf("expected b=true got b=%v", *b) - } - if *c != false { - t.Errorf("expect c=false got c=%v", *c) - } -} diff --git a/vendor/github.com/spf13/pflag/bytes_test.go b/vendor/github.com/spf13/pflag/bytes_test.go deleted file mode 100644 index 5251f347c..000000000 --- a/vendor/github.com/spf13/pflag/bytes_test.go +++ /dev/null @@ -1,134 +0,0 @@ -package pflag - -import ( - "encoding/base64" - "fmt" - "os" - "testing" -) - -func setUpBytesHex(bytesHex *[]byte) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.BytesHexVar(bytesHex, "bytes", []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, "Some bytes in HEX") - f.BytesHexVarP(bytesHex, "bytes2", "B", []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, "Some bytes in HEX") - return f -} - -func TestBytesHex(t *testing.T) { - testCases := []struct { - input string - success bool - expected string - }{ - /// Positive cases - {"", true, ""}, // Is empty string OK ? - {"01", true, "01"}, - {"0101", true, "0101"}, - {"1234567890abcdef", true, "1234567890ABCDEF"}, - {"1234567890ABCDEF", true, "1234567890ABCDEF"}, - - // Negative cases - {"0", false, ""}, // Short string - {"000", false, ""}, /// Odd-length string - {"qq", false, ""}, /// non-hex character - } - - devnull, _ := os.Open(os.DevNull) - os.Stderr = devnull - - for i := range testCases { - var bytesHex []byte - f := setUpBytesHex(&bytesHex) - - tc := &testCases[i] - - // --bytes - args := []string{ - fmt.Sprintf("--bytes=%s", tc.input), - fmt.Sprintf("-B %s", tc.input), - fmt.Sprintf("--bytes2=%s", tc.input), - } - - for _, arg := range args { - err := f.Parse([]string{arg}) - - if err != nil && tc.success == true { - t.Errorf("expected success, got %q", err) - continue - } else if err == nil && tc.success == false { - // bytesHex, err := f.GetBytesHex("bytes") - t.Errorf("expected failure while processing %q", tc.input) - continue - } else if tc.success { - bytesHex, err := f.GetBytesHex("bytes") - if err != nil { - t.Errorf("Got error trying to fetch the 'bytes' flag: %v", err) - } - if fmt.Sprintf("%X", bytesHex) != tc.expected { - t.Errorf("expected %q, got '%X'", tc.expected, bytesHex) - } - } - } - } -} - -func setUpBytesBase64(bytesBase64 *[]byte) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.BytesBase64Var(bytesBase64, "bytes", []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, "Some bytes in Base64") - f.BytesBase64VarP(bytesBase64, "bytes2", "B", []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, "Some bytes in Base64") - return f -} - -func TestBytesBase64(t *testing.T) { - testCases := []struct { - input string - success bool - expected string - }{ - /// Positive cases - {"", true, ""}, // Is empty string OK ? - {"AQ==", true, "AQ=="}, - - // Negative cases - {"AQ", false, ""}, // Padding removed - {"ï", false, ""}, // non-base64 characters - } - - devnull, _ := os.Open(os.DevNull) - os.Stderr = devnull - - for i := range testCases { - var bytesBase64 []byte - f := setUpBytesBase64(&bytesBase64) - - tc := &testCases[i] - - // --bytes - args := []string{ - fmt.Sprintf("--bytes=%s", tc.input), - fmt.Sprintf("-B %s", tc.input), - fmt.Sprintf("--bytes2=%s", tc.input), - } - - for _, arg := range args { - err := f.Parse([]string{arg}) - - if err != nil && tc.success == true { - t.Errorf("expected success, got %q", err) - continue - } else if err == nil && tc.success == false { - // bytesBase64, err := f.GetBytesBase64("bytes") - t.Errorf("expected failure while processing %q", tc.input) - continue - } else if tc.success { - bytesBase64, err := f.GetBytesBase64("bytes") - if err != nil { - t.Errorf("Got error trying to fetch the 'bytes' flag: %v", err) - } - if base64.StdEncoding.EncodeToString(bytesBase64) != tc.expected { - t.Errorf("expected %q, got '%X'", tc.expected, bytesBase64) - } - } - } - } -} diff --git a/vendor/github.com/spf13/pflag/count_test.go b/vendor/github.com/spf13/pflag/count_test.go deleted file mode 100644 index 3785d375a..000000000 --- a/vendor/github.com/spf13/pflag/count_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package pflag - -import ( - "os" - "testing" -) - -func setUpCount(c *int) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.CountVarP(c, "verbose", "v", "a counter") - return f -} - -func TestCount(t *testing.T) { - testCases := []struct { - input []string - success bool - expected int - }{ - {[]string{}, true, 0}, - {[]string{"-v"}, true, 1}, - {[]string{"-vvv"}, true, 3}, - {[]string{"-v", "-v", "-v"}, true, 3}, - {[]string{"-v", "--verbose", "-v"}, true, 3}, - {[]string{"-v=3", "-v"}, true, 4}, - {[]string{"--verbose=0"}, true, 0}, - {[]string{"-v=0"}, true, 0}, - {[]string{"-v=a"}, false, 0}, - } - - devnull, _ := os.Open(os.DevNull) - os.Stderr = devnull - for i := range testCases { - var count int - f := setUpCount(&count) - - tc := &testCases[i] - - err := f.Parse(tc.input) - if err != nil && tc.success == true { - t.Errorf("expected success, got %q", err) - continue - } else if err == nil && tc.success == false { - t.Errorf("expected failure, got success") - continue - } else if tc.success { - c, err := f.GetCount("verbose") - if err != nil { - t.Errorf("Got error trying to fetch the counter flag") - } - if c != tc.expected { - t.Errorf("expected %d, got %d", tc.expected, c) - } - } - } -} diff --git a/vendor/github.com/spf13/pflag/duration_slice_test.go b/vendor/github.com/spf13/pflag/duration_slice_test.go deleted file mode 100644 index 489b012ff..000000000 --- a/vendor/github.com/spf13/pflag/duration_slice_test.go +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code ds governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - "fmt" - "strings" - "testing" - "time" -) - -func setUpDSFlagSet(dsp *[]time.Duration) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.DurationSliceVar(dsp, "ds", []time.Duration{}, "Command separated list!") - return f -} - -func setUpDSFlagSetWithDefault(dsp *[]time.Duration) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.DurationSliceVar(dsp, "ds", []time.Duration{0, 1}, "Command separated list!") - return f -} - -func TestEmptyDS(t *testing.T) { - var ds []time.Duration - f := setUpDSFlagSet(&ds) - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - getDS, err := f.GetDurationSlice("ds") - if err != nil { - t.Fatal("got an error from GetDurationSlice():", err) - } - if len(getDS) != 0 { - t.Fatalf("got ds %v with len=%d but expected length=0", getDS, len(getDS)) - } -} - -func TestDS(t *testing.T) { - var ds []time.Duration - f := setUpDSFlagSet(&ds) - - vals := []string{"1ns", "2ms", "3m", "4h"} - arg := fmt.Sprintf("--ds=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range ds { - d, err := time.ParseDuration(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected ds[%d] to be %s but got: %d", i, vals[i], v) - } - } - getDS, err := f.GetDurationSlice("ds") - if err != nil { - t.Fatalf("got error: %v", err) - } - for i, v := range getDS { - d, err := time.ParseDuration(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected ds[%d] to be %s but got: %d from GetDurationSlice", i, vals[i], v) - } - } -} - -func TestDSDefault(t *testing.T) { - var ds []time.Duration - f := setUpDSFlagSetWithDefault(&ds) - - vals := []string{"0s", "1ns"} - - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range ds { - d, err := time.ParseDuration(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected ds[%d] to be %d but got: %d", i, d, v) - } - } - - getDS, err := f.GetDurationSlice("ds") - if err != nil { - t.Fatal("got an error from GetDurationSlice():", err) - } - for i, v := range getDS { - d, err := time.ParseDuration(vals[i]) - if err != nil { - t.Fatal("got an error from GetDurationSlice():", err) - } - if d != v { - t.Fatalf("expected ds[%d] to be %d from GetDurationSlice but got: %d", i, d, v) - } - } -} - -func TestDSWithDefault(t *testing.T) { - var ds []time.Duration - f := setUpDSFlagSetWithDefault(&ds) - - vals := []string{"1ns", "2ns"} - arg := fmt.Sprintf("--ds=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range ds { - d, err := time.ParseDuration(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected ds[%d] to be %d but got: %d", i, d, v) - } - } - - getDS, err := f.GetDurationSlice("ds") - if err != nil { - t.Fatal("got an error from GetDurationSlice():", err) - } - for i, v := range getDS { - d, err := time.ParseDuration(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected ds[%d] to be %d from GetDurationSlice but got: %d", i, d, v) - } - } -} - -func TestDSCalledTwice(t *testing.T) { - var ds []time.Duration - f := setUpDSFlagSet(&ds) - - in := []string{"1ns,2ns", "3ns"} - expected := []time.Duration{1, 2, 3} - argfmt := "--ds=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range ds { - if expected[i] != v { - t.Fatalf("expected ds[%d] to be %d but got: %d", i, expected[i], v) - } - } -} diff --git a/vendor/github.com/spf13/pflag/example_test.go b/vendor/github.com/spf13/pflag/example_test.go deleted file mode 100644 index abd7806fa..000000000 --- a/vendor/github.com/spf13/pflag/example_test.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag_test - -import ( - "fmt" - - "github.com/spf13/pflag" -) - -func ExampleShorthandLookup() { - name := "verbose" - short := name[:1] - - pflag.BoolP(name, short, false, "verbose output") - - // len(short) must be == 1 - flag := pflag.ShorthandLookup(short) - - fmt.Println(flag.Name) -} - -func ExampleFlagSet_ShorthandLookup() { - name := "verbose" - short := name[:1] - - fs := pflag.NewFlagSet("Example", pflag.ContinueOnError) - fs.BoolP(name, short, false, "verbose output") - - // len(short) must be == 1 - flag := fs.ShorthandLookup(short) - - fmt.Println(flag.Name) -} diff --git a/vendor/github.com/spf13/pflag/export_test.go b/vendor/github.com/spf13/pflag/export_test.go deleted file mode 100644 index 9318fee00..000000000 --- a/vendor/github.com/spf13/pflag/export_test.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - "io/ioutil" - "os" -) - -// Additional routines compiled into the package only during testing. - -// ResetForTesting clears all flag state and sets the usage function as directed. -// After calling ResetForTesting, parse errors in flag handling will not -// exit the program. -func ResetForTesting(usage func()) { - CommandLine = &FlagSet{ - name: os.Args[0], - errorHandling: ContinueOnError, - output: ioutil.Discard, - } - Usage = usage -} - -// GetCommandLine returns the default FlagSet. -func GetCommandLine() *FlagSet { - return CommandLine -} diff --git a/vendor/github.com/spf13/pflag/flag.go b/vendor/github.com/spf13/pflag/flag.go index 5cc710ccd..9beeda8ec 100644 --- a/vendor/github.com/spf13/pflag/flag.go +++ b/vendor/github.com/spf13/pflag/flag.go @@ -925,13 +925,16 @@ func stripUnknownFlagValue(args []string) []string { } first := args[0] - if first[0] == '-' { + if len(first) > 0 && first[0] == '-' { //--unknown --next-flag ... return args } //--unknown arg ... (args will be arg ...) - return args[1:] + if len(args) > 1 { + return args[1:] + } + return nil } func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) { diff --git a/vendor/github.com/spf13/pflag/flag_test.go b/vendor/github.com/spf13/pflag/flag_test.go deleted file mode 100644 index f600f0aeb..000000000 --- a/vendor/github.com/spf13/pflag/flag_test.go +++ /dev/null @@ -1,1259 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - "bytes" - "fmt" - "io" - "io/ioutil" - "net" - "os" - "reflect" - "sort" - "strconv" - "strings" - "testing" - "time" -) - -var ( - testBool = Bool("test_bool", false, "bool value") - testInt = Int("test_int", 0, "int value") - testInt64 = Int64("test_int64", 0, "int64 value") - testUint = Uint("test_uint", 0, "uint value") - testUint64 = Uint64("test_uint64", 0, "uint64 value") - testString = String("test_string", "0", "string value") - testFloat = Float64("test_float64", 0, "float64 value") - testDuration = Duration("test_duration", 0, "time.Duration value") - testOptionalInt = Int("test_optional_int", 0, "optional int value") - normalizeFlagNameInvocations = 0 -) - -func boolString(s string) string { - if s == "0" { - return "false" - } - return "true" -} - -func TestEverything(t *testing.T) { - m := make(map[string]*Flag) - desired := "0" - visitor := func(f *Flag) { - if len(f.Name) > 5 && f.Name[0:5] == "test_" { - m[f.Name] = f - ok := false - switch { - case f.Value.String() == desired: - ok = true - case f.Name == "test_bool" && f.Value.String() == boolString(desired): - ok = true - case f.Name == "test_duration" && f.Value.String() == desired+"s": - ok = true - } - if !ok { - t.Error("Visit: bad value", f.Value.String(), "for", f.Name) - } - } - } - VisitAll(visitor) - if len(m) != 9 { - t.Error("VisitAll misses some flags") - for k, v := range m { - t.Log(k, *v) - } - } - m = make(map[string]*Flag) - Visit(visitor) - if len(m) != 0 { - t.Errorf("Visit sees unset flags") - for k, v := range m { - t.Log(k, *v) - } - } - // Now set all flags - Set("test_bool", "true") - Set("test_int", "1") - Set("test_int64", "1") - Set("test_uint", "1") - Set("test_uint64", "1") - Set("test_string", "1") - Set("test_float64", "1") - Set("test_duration", "1s") - Set("test_optional_int", "1") - desired = "1" - Visit(visitor) - if len(m) != 9 { - t.Error("Visit fails after set") - for k, v := range m { - t.Log(k, *v) - } - } - // Now test they're visited in sort order. - var flagNames []string - Visit(func(f *Flag) { flagNames = append(flagNames, f.Name) }) - if !sort.StringsAreSorted(flagNames) { - t.Errorf("flag names not sorted: %v", flagNames) - } -} - -func TestUsage(t *testing.T) { - called := false - ResetForTesting(func() { called = true }) - if GetCommandLine().Parse([]string{"--x"}) == nil { - t.Error("parse did not fail for unknown flag") - } - if called { - t.Error("did call Usage while using ContinueOnError") - } -} - -func TestAddFlagSet(t *testing.T) { - oldSet := NewFlagSet("old", ContinueOnError) - newSet := NewFlagSet("new", ContinueOnError) - - oldSet.String("flag1", "flag1", "flag1") - oldSet.String("flag2", "flag2", "flag2") - - newSet.String("flag2", "flag2", "flag2") - newSet.String("flag3", "flag3", "flag3") - - oldSet.AddFlagSet(newSet) - - if len(oldSet.formal) != 3 { - t.Errorf("Unexpected result adding a FlagSet to a FlagSet %v", oldSet) - } -} - -func TestAnnotation(t *testing.T) { - f := NewFlagSet("shorthand", ContinueOnError) - - if err := f.SetAnnotation("missing-flag", "key", nil); err == nil { - t.Errorf("Expected error setting annotation on non-existent flag") - } - - f.StringP("stringa", "a", "", "string value") - if err := f.SetAnnotation("stringa", "key", nil); err != nil { - t.Errorf("Unexpected error setting new nil annotation: %v", err) - } - if annotation := f.Lookup("stringa").Annotations["key"]; annotation != nil { - t.Errorf("Unexpected annotation: %v", annotation) - } - - f.StringP("stringb", "b", "", "string2 value") - if err := f.SetAnnotation("stringb", "key", []string{"value1"}); err != nil { - t.Errorf("Unexpected error setting new annotation: %v", err) - } - if annotation := f.Lookup("stringb").Annotations["key"]; !reflect.DeepEqual(annotation, []string{"value1"}) { - t.Errorf("Unexpected annotation: %v", annotation) - } - - if err := f.SetAnnotation("stringb", "key", []string{"value2"}); err != nil { - t.Errorf("Unexpected error updating annotation: %v", err) - } - if annotation := f.Lookup("stringb").Annotations["key"]; !reflect.DeepEqual(annotation, []string{"value2"}) { - t.Errorf("Unexpected annotation: %v", annotation) - } -} - -func testParse(f *FlagSet, t *testing.T) { - if f.Parsed() { - t.Error("f.Parse() = true before Parse") - } - boolFlag := f.Bool("bool", false, "bool value") - bool2Flag := f.Bool("bool2", false, "bool2 value") - bool3Flag := f.Bool("bool3", false, "bool3 value") - intFlag := f.Int("int", 0, "int value") - int8Flag := f.Int8("int8", 0, "int value") - int16Flag := f.Int16("int16", 0, "int value") - int32Flag := f.Int32("int32", 0, "int value") - int64Flag := f.Int64("int64", 0, "int64 value") - uintFlag := f.Uint("uint", 0, "uint value") - uint8Flag := f.Uint8("uint8", 0, "uint value") - uint16Flag := f.Uint16("uint16", 0, "uint value") - uint32Flag := f.Uint32("uint32", 0, "uint value") - uint64Flag := f.Uint64("uint64", 0, "uint64 value") - stringFlag := f.String("string", "0", "string value") - float32Flag := f.Float32("float32", 0, "float32 value") - float64Flag := f.Float64("float64", 0, "float64 value") - ipFlag := f.IP("ip", net.ParseIP("127.0.0.1"), "ip value") - maskFlag := f.IPMask("mask", ParseIPv4Mask("0.0.0.0"), "mask value") - durationFlag := f.Duration("duration", 5*time.Second, "time.Duration value") - optionalIntNoValueFlag := f.Int("optional-int-no-value", 0, "int value") - f.Lookup("optional-int-no-value").NoOptDefVal = "9" - optionalIntWithValueFlag := f.Int("optional-int-with-value", 0, "int value") - f.Lookup("optional-int-no-value").NoOptDefVal = "9" - extra := "one-extra-argument" - args := []string{ - "--bool", - "--bool2=true", - "--bool3=false", - "--int=22", - "--int8=-8", - "--int16=-16", - "--int32=-32", - "--int64=0x23", - "--uint", "24", - "--uint8=8", - "--uint16=16", - "--uint32=32", - "--uint64=25", - "--string=hello", - "--float32=-172e12", - "--float64=2718e28", - "--ip=10.11.12.13", - "--mask=255.255.255.0", - "--duration=2m", - "--optional-int-no-value", - "--optional-int-with-value=42", - extra, - } - if err := f.Parse(args); err != nil { - t.Fatal(err) - } - if !f.Parsed() { - t.Error("f.Parse() = false after Parse") - } - if *boolFlag != true { - t.Error("bool flag should be true, is ", *boolFlag) - } - if v, err := f.GetBool("bool"); err != nil || v != *boolFlag { - t.Error("GetBool does not work.") - } - if *bool2Flag != true { - t.Error("bool2 flag should be true, is ", *bool2Flag) - } - if *bool3Flag != false { - t.Error("bool3 flag should be false, is ", *bool2Flag) - } - if *intFlag != 22 { - t.Error("int flag should be 22, is ", *intFlag) - } - if v, err := f.GetInt("int"); err != nil || v != *intFlag { - t.Error("GetInt does not work.") - } - if *int8Flag != -8 { - t.Error("int8 flag should be 0x23, is ", *int8Flag) - } - if *int16Flag != -16 { - t.Error("int16 flag should be -16, is ", *int16Flag) - } - if v, err := f.GetInt8("int8"); err != nil || v != *int8Flag { - t.Error("GetInt8 does not work.") - } - if v, err := f.GetInt16("int16"); err != nil || v != *int16Flag { - t.Error("GetInt16 does not work.") - } - if *int32Flag != -32 { - t.Error("int32 flag should be 0x23, is ", *int32Flag) - } - if v, err := f.GetInt32("int32"); err != nil || v != *int32Flag { - t.Error("GetInt32 does not work.") - } - if *int64Flag != 0x23 { - t.Error("int64 flag should be 0x23, is ", *int64Flag) - } - if v, err := f.GetInt64("int64"); err != nil || v != *int64Flag { - t.Error("GetInt64 does not work.") - } - if *uintFlag != 24 { - t.Error("uint flag should be 24, is ", *uintFlag) - } - if v, err := f.GetUint("uint"); err != nil || v != *uintFlag { - t.Error("GetUint does not work.") - } - if *uint8Flag != 8 { - t.Error("uint8 flag should be 8, is ", *uint8Flag) - } - if v, err := f.GetUint8("uint8"); err != nil || v != *uint8Flag { - t.Error("GetUint8 does not work.") - } - if *uint16Flag != 16 { - t.Error("uint16 flag should be 16, is ", *uint16Flag) - } - if v, err := f.GetUint16("uint16"); err != nil || v != *uint16Flag { - t.Error("GetUint16 does not work.") - } - if *uint32Flag != 32 { - t.Error("uint32 flag should be 32, is ", *uint32Flag) - } - if v, err := f.GetUint32("uint32"); err != nil || v != *uint32Flag { - t.Error("GetUint32 does not work.") - } - if *uint64Flag != 25 { - t.Error("uint64 flag should be 25, is ", *uint64Flag) - } - if v, err := f.GetUint64("uint64"); err != nil || v != *uint64Flag { - t.Error("GetUint64 does not work.") - } - if *stringFlag != "hello" { - t.Error("string flag should be `hello`, is ", *stringFlag) - } - if v, err := f.GetString("string"); err != nil || v != *stringFlag { - t.Error("GetString does not work.") - } - if *float32Flag != -172e12 { - t.Error("float32 flag should be -172e12, is ", *float32Flag) - } - if v, err := f.GetFloat32("float32"); err != nil || v != *float32Flag { - t.Errorf("GetFloat32 returned %v but float32Flag was %v", v, *float32Flag) - } - if *float64Flag != 2718e28 { - t.Error("float64 flag should be 2718e28, is ", *float64Flag) - } - if v, err := f.GetFloat64("float64"); err != nil || v != *float64Flag { - t.Errorf("GetFloat64 returned %v but float64Flag was %v", v, *float64Flag) - } - if !(*ipFlag).Equal(net.ParseIP("10.11.12.13")) { - t.Error("ip flag should be 10.11.12.13, is ", *ipFlag) - } - if v, err := f.GetIP("ip"); err != nil || !v.Equal(*ipFlag) { - t.Errorf("GetIP returned %v but ipFlag was %v", v, *ipFlag) - } - if (*maskFlag).String() != ParseIPv4Mask("255.255.255.0").String() { - t.Error("mask flag should be 255.255.255.0, is ", (*maskFlag).String()) - } - if v, err := f.GetIPv4Mask("mask"); err != nil || v.String() != (*maskFlag).String() { - t.Errorf("GetIP returned %v maskFlag was %v error was %v", v, *maskFlag, err) - } - if *durationFlag != 2*time.Minute { - t.Error("duration flag should be 2m, is ", *durationFlag) - } - if v, err := f.GetDuration("duration"); err != nil || v != *durationFlag { - t.Error("GetDuration does not work.") - } - if _, err := f.GetInt("duration"); err == nil { - t.Error("GetInt parsed a time.Duration?!?!") - } - if *optionalIntNoValueFlag != 9 { - t.Error("optional int flag should be the default value, is ", *optionalIntNoValueFlag) - } - if *optionalIntWithValueFlag != 42 { - t.Error("optional int flag should be 42, is ", *optionalIntWithValueFlag) - } - if len(f.Args()) != 1 { - t.Error("expected one argument, got", len(f.Args())) - } else if f.Args()[0] != extra { - t.Errorf("expected argument %q got %q", extra, f.Args()[0]) - } -} - -func testParseAll(f *FlagSet, t *testing.T) { - if f.Parsed() { - t.Error("f.Parse() = true before Parse") - } - f.BoolP("boola", "a", false, "bool value") - f.BoolP("boolb", "b", false, "bool2 value") - f.BoolP("boolc", "c", false, "bool3 value") - f.BoolP("boold", "d", false, "bool4 value") - f.StringP("stringa", "s", "0", "string value") - f.StringP("stringz", "z", "0", "string value") - f.StringP("stringx", "x", "0", "string value") - f.StringP("stringy", "y", "0", "string value") - f.Lookup("stringx").NoOptDefVal = "1" - args := []string{ - "-ab", - "-cs=xx", - "--stringz=something", - "-d=true", - "-x", - "-y", - "ee", - } - want := []string{ - "boola", "true", - "boolb", "true", - "boolc", "true", - "stringa", "xx", - "stringz", "something", - "boold", "true", - "stringx", "1", - "stringy", "ee", - } - got := []string{} - store := func(flag *Flag, value string) error { - got = append(got, flag.Name) - if len(value) > 0 { - got = append(got, value) - } - return nil - } - if err := f.ParseAll(args, store); err != nil { - t.Errorf("expected no error, got %s", err) - } - if !f.Parsed() { - t.Errorf("f.Parse() = false after Parse") - } - if !reflect.DeepEqual(got, want) { - t.Errorf("f.ParseAll() fail to restore the args") - t.Errorf("Got: %v", got) - t.Errorf("Want: %v", want) - } -} - -func testParseWithUnknownFlags(f *FlagSet, t *testing.T) { - if f.Parsed() { - t.Error("f.Parse() = true before Parse") - } - f.ParseErrorsWhitelist.UnknownFlags = true - - f.BoolP("boola", "a", false, "bool value") - f.BoolP("boolb", "b", false, "bool2 value") - f.BoolP("boolc", "c", false, "bool3 value") - f.BoolP("boold", "d", false, "bool4 value") - f.BoolP("boole", "e", false, "bool4 value") - f.StringP("stringa", "s", "0", "string value") - f.StringP("stringz", "z", "0", "string value") - f.StringP("stringx", "x", "0", "string value") - f.StringP("stringy", "y", "0", "string value") - f.StringP("stringo", "o", "0", "string value") - f.Lookup("stringx").NoOptDefVal = "1" - args := []string{ - "-ab", - "-cs=xx", - "--stringz=something", - "--unknown1", - "unknown1Value", - "-d=true", - "-x", - "--unknown2=unknown2Value", - "-u=unknown3Value", - "-p", - "unknown4Value", - "-q", //another unknown with bool value - "-y", - "ee", - "--unknown7=unknown7value", - "--stringo=ovalue", - "--unknown8=unknown8value", - "--boole", - "--unknown6", - } - want := []string{ - "boola", "true", - "boolb", "true", - "boolc", "true", - "stringa", "xx", - "stringz", "something", - "boold", "true", - "stringx", "1", - "stringy", "ee", - "stringo", "ovalue", - "boole", "true", - } - got := []string{} - store := func(flag *Flag, value string) error { - got = append(got, flag.Name) - if len(value) > 0 { - got = append(got, value) - } - return nil - } - if err := f.ParseAll(args, store); err != nil { - t.Errorf("expected no error, got %s", err) - } - if !f.Parsed() { - t.Errorf("f.Parse() = false after Parse") - } - if !reflect.DeepEqual(got, want) { - t.Errorf("f.ParseAll() fail to restore the args") - t.Errorf("Got: %v", got) - t.Errorf("Want: %v", want) - } -} - -func TestShorthand(t *testing.T) { - f := NewFlagSet("shorthand", ContinueOnError) - if f.Parsed() { - t.Error("f.Parse() = true before Parse") - } - boolaFlag := f.BoolP("boola", "a", false, "bool value") - boolbFlag := f.BoolP("boolb", "b", false, "bool2 value") - boolcFlag := f.BoolP("boolc", "c", false, "bool3 value") - booldFlag := f.BoolP("boold", "d", false, "bool4 value") - stringaFlag := f.StringP("stringa", "s", "0", "string value") - stringzFlag := f.StringP("stringz", "z", "0", "string value") - extra := "interspersed-argument" - notaflag := "--i-look-like-a-flag" - args := []string{ - "-ab", - extra, - "-cs", - "hello", - "-z=something", - "-d=true", - "--", - notaflag, - } - f.SetOutput(ioutil.Discard) - if err := f.Parse(args); err != nil { - t.Error("expected no error, got ", err) - } - if !f.Parsed() { - t.Error("f.Parse() = false after Parse") - } - if *boolaFlag != true { - t.Error("boola flag should be true, is ", *boolaFlag) - } - if *boolbFlag != true { - t.Error("boolb flag should be true, is ", *boolbFlag) - } - if *boolcFlag != true { - t.Error("boolc flag should be true, is ", *boolcFlag) - } - if *booldFlag != true { - t.Error("boold flag should be true, is ", *booldFlag) - } - if *stringaFlag != "hello" { - t.Error("stringa flag should be `hello`, is ", *stringaFlag) - } - if *stringzFlag != "something" { - t.Error("stringz flag should be `something`, is ", *stringzFlag) - } - if len(f.Args()) != 2 { - t.Error("expected one argument, got", len(f.Args())) - } else if f.Args()[0] != extra { - t.Errorf("expected argument %q got %q", extra, f.Args()[0]) - } else if f.Args()[1] != notaflag { - t.Errorf("expected argument %q got %q", notaflag, f.Args()[1]) - } - if f.ArgsLenAtDash() != 1 { - t.Errorf("expected argsLenAtDash %d got %d", f.ArgsLenAtDash(), 1) - } -} - -func TestShorthandLookup(t *testing.T) { - f := NewFlagSet("shorthand", ContinueOnError) - if f.Parsed() { - t.Error("f.Parse() = true before Parse") - } - f.BoolP("boola", "a", false, "bool value") - f.BoolP("boolb", "b", false, "bool2 value") - args := []string{ - "-ab", - } - f.SetOutput(ioutil.Discard) - if err := f.Parse(args); err != nil { - t.Error("expected no error, got ", err) - } - if !f.Parsed() { - t.Error("f.Parse() = false after Parse") - } - flag := f.ShorthandLookup("a") - if flag == nil { - t.Errorf("f.ShorthandLookup(\"a\") returned nil") - } - if flag.Name != "boola" { - t.Errorf("f.ShorthandLookup(\"a\") found %q instead of \"boola\"", flag.Name) - } - flag = f.ShorthandLookup("") - if flag != nil { - t.Errorf("f.ShorthandLookup(\"\") did not return nil") - } - defer func() { - recover() - }() - flag = f.ShorthandLookup("ab") - // should NEVER get here. lookup should panic. defer'd func should recover it. - t.Errorf("f.ShorthandLookup(\"ab\") did not panic") -} - -func TestParse(t *testing.T) { - ResetForTesting(func() { t.Error("bad parse") }) - testParse(GetCommandLine(), t) -} - -func TestParseAll(t *testing.T) { - ResetForTesting(func() { t.Error("bad parse") }) - testParseAll(GetCommandLine(), t) -} - -func TestIgnoreUnknownFlags(t *testing.T) { - ResetForTesting(func() { t.Error("bad parse") }) - testParseWithUnknownFlags(GetCommandLine(), t) -} - -func TestFlagSetParse(t *testing.T) { - testParse(NewFlagSet("test", ContinueOnError), t) -} - -func TestChangedHelper(t *testing.T) { - f := NewFlagSet("changedtest", ContinueOnError) - f.Bool("changed", false, "changed bool") - f.Bool("settrue", true, "true to true") - f.Bool("setfalse", false, "false to false") - f.Bool("unchanged", false, "unchanged bool") - - args := []string{"--changed", "--settrue", "--setfalse=false"} - if err := f.Parse(args); err != nil { - t.Error("f.Parse() = false after Parse") - } - if !f.Changed("changed") { - t.Errorf("--changed wasn't changed!") - } - if !f.Changed("settrue") { - t.Errorf("--settrue wasn't changed!") - } - if !f.Changed("setfalse") { - t.Errorf("--setfalse wasn't changed!") - } - if f.Changed("unchanged") { - t.Errorf("--unchanged was changed!") - } - if f.Changed("invalid") { - t.Errorf("--invalid was changed!") - } - if f.ArgsLenAtDash() != -1 { - t.Errorf("Expected argsLenAtDash: %d but got %d", -1, f.ArgsLenAtDash()) - } -} - -func replaceSeparators(name string, from []string, to string) string { - result := name - for _, sep := range from { - result = strings.Replace(result, sep, to, -1) - } - // Type convert to indicate normalization has been done. - return result -} - -func wordSepNormalizeFunc(f *FlagSet, name string) NormalizedName { - seps := []string{"-", "_"} - name = replaceSeparators(name, seps, ".") - normalizeFlagNameInvocations++ - - return NormalizedName(name) -} - -func testWordSepNormalizedNames(args []string, t *testing.T) { - f := NewFlagSet("normalized", ContinueOnError) - if f.Parsed() { - t.Error("f.Parse() = true before Parse") - } - withDashFlag := f.Bool("with-dash-flag", false, "bool value") - // Set this after some flags have been added and before others. - f.SetNormalizeFunc(wordSepNormalizeFunc) - withUnderFlag := f.Bool("with_under_flag", false, "bool value") - withBothFlag := f.Bool("with-both_flag", false, "bool value") - if err := f.Parse(args); err != nil { - t.Fatal(err) - } - if !f.Parsed() { - t.Error("f.Parse() = false after Parse") - } - if *withDashFlag != true { - t.Error("withDashFlag flag should be true, is ", *withDashFlag) - } - if *withUnderFlag != true { - t.Error("withUnderFlag flag should be true, is ", *withUnderFlag) - } - if *withBothFlag != true { - t.Error("withBothFlag flag should be true, is ", *withBothFlag) - } -} - -func TestWordSepNormalizedNames(t *testing.T) { - args := []string{ - "--with-dash-flag", - "--with-under-flag", - "--with-both-flag", - } - testWordSepNormalizedNames(args, t) - - args = []string{ - "--with_dash_flag", - "--with_under_flag", - "--with_both_flag", - } - testWordSepNormalizedNames(args, t) - - args = []string{ - "--with-dash_flag", - "--with-under_flag", - "--with-both_flag", - } - testWordSepNormalizedNames(args, t) -} - -func aliasAndWordSepFlagNames(f *FlagSet, name string) NormalizedName { - seps := []string{"-", "_"} - - oldName := replaceSeparators("old-valid_flag", seps, ".") - newName := replaceSeparators("valid-flag", seps, ".") - - name = replaceSeparators(name, seps, ".") - switch name { - case oldName: - name = newName - } - - return NormalizedName(name) -} - -func TestCustomNormalizedNames(t *testing.T) { - f := NewFlagSet("normalized", ContinueOnError) - if f.Parsed() { - t.Error("f.Parse() = true before Parse") - } - - validFlag := f.Bool("valid-flag", false, "bool value") - f.SetNormalizeFunc(aliasAndWordSepFlagNames) - someOtherFlag := f.Bool("some-other-flag", false, "bool value") - - args := []string{"--old_valid_flag", "--some-other_flag"} - if err := f.Parse(args); err != nil { - t.Fatal(err) - } - - if *validFlag != true { - t.Errorf("validFlag is %v even though we set the alias --old_valid_falg", *validFlag) - } - if *someOtherFlag != true { - t.Error("someOtherFlag should be true, is ", *someOtherFlag) - } -} - -// Every flag we add, the name (displayed also in usage) should normalized -func TestNormalizationFuncShouldChangeFlagName(t *testing.T) { - // Test normalization after addition - f := NewFlagSet("normalized", ContinueOnError) - - f.Bool("valid_flag", false, "bool value") - if f.Lookup("valid_flag").Name != "valid_flag" { - t.Error("The new flag should have the name 'valid_flag' instead of ", f.Lookup("valid_flag").Name) - } - - f.SetNormalizeFunc(wordSepNormalizeFunc) - if f.Lookup("valid_flag").Name != "valid.flag" { - t.Error("The new flag should have the name 'valid.flag' instead of ", f.Lookup("valid_flag").Name) - } - - // Test normalization before addition - f = NewFlagSet("normalized", ContinueOnError) - f.SetNormalizeFunc(wordSepNormalizeFunc) - - f.Bool("valid_flag", false, "bool value") - if f.Lookup("valid_flag").Name != "valid.flag" { - t.Error("The new flag should have the name 'valid.flag' instead of ", f.Lookup("valid_flag").Name) - } -} - -// Related to https://github.com/spf13/cobra/issues/521. -func TestNormalizationSharedFlags(t *testing.T) { - f := NewFlagSet("set f", ContinueOnError) - g := NewFlagSet("set g", ContinueOnError) - nfunc := wordSepNormalizeFunc - testName := "valid_flag" - normName := nfunc(nil, testName) - if testName == string(normName) { - t.Error("TestNormalizationSharedFlags meaningless: the original and normalized flag names are identical:", testName) - } - - f.Bool(testName, false, "bool value") - g.AddFlagSet(f) - - f.SetNormalizeFunc(nfunc) - g.SetNormalizeFunc(nfunc) - - if len(f.formal) != 1 { - t.Error("Normalizing flags should not result in duplications in the flag set:", f.formal) - } - if f.orderedFormal[0].Name != string(normName) { - t.Error("Flag name not normalized") - } - for k := range f.formal { - if k != "valid.flag" { - t.Errorf("The key in the flag map should have been normalized: wanted \"%s\", got \"%s\" instead", normName, k) - } - } - - if !reflect.DeepEqual(f.formal, g.formal) || !reflect.DeepEqual(f.orderedFormal, g.orderedFormal) { - t.Error("Two flag sets sharing the same flags should stay consistent after being normalized. Original set:", f.formal, "Duplicate set:", g.formal) - } -} - -func TestNormalizationSetFlags(t *testing.T) { - f := NewFlagSet("normalized", ContinueOnError) - nfunc := wordSepNormalizeFunc - testName := "valid_flag" - normName := nfunc(nil, testName) - if testName == string(normName) { - t.Error("TestNormalizationSetFlags meaningless: the original and normalized flag names are identical:", testName) - } - - f.Bool(testName, false, "bool value") - f.Set(testName, "true") - f.SetNormalizeFunc(nfunc) - - if len(f.formal) != 1 { - t.Error("Normalizing flags should not result in duplications in the flag set:", f.formal) - } - if f.orderedFormal[0].Name != string(normName) { - t.Error("Flag name not normalized") - } - for k := range f.formal { - if k != "valid.flag" { - t.Errorf("The key in the flag map should have been normalized: wanted \"%s\", got \"%s\" instead", normName, k) - } - } - - if !reflect.DeepEqual(f.formal, f.actual) { - t.Error("The map of set flags should get normalized. Formal:", f.formal, "Actual:", f.actual) - } -} - -// Declare a user-defined flag type. -type flagVar []string - -func (f *flagVar) String() string { - return fmt.Sprint([]string(*f)) -} - -func (f *flagVar) Set(value string) error { - *f = append(*f, value) - return nil -} - -func (f *flagVar) Type() string { - return "flagVar" -} - -func TestUserDefined(t *testing.T) { - var flags FlagSet - flags.Init("test", ContinueOnError) - var v flagVar - flags.VarP(&v, "v", "v", "usage") - if err := flags.Parse([]string{"--v=1", "-v2", "-v", "3"}); err != nil { - t.Error(err) - } - if len(v) != 3 { - t.Fatal("expected 3 args; got ", len(v)) - } - expect := "[1 2 3]" - if v.String() != expect { - t.Errorf("expected value %q got %q", expect, v.String()) - } -} - -func TestSetOutput(t *testing.T) { - var flags FlagSet - var buf bytes.Buffer - flags.SetOutput(&buf) - flags.Init("test", ContinueOnError) - flags.Parse([]string{"--unknown"}) - if out := buf.String(); !strings.Contains(out, "--unknown") { - t.Logf("expected output mentioning unknown; got %q", out) - } -} - -// This tests that one can reset the flags. This still works but not well, and is -// superseded by FlagSet. -func TestChangingArgs(t *testing.T) { - ResetForTesting(func() { t.Fatal("bad parse") }) - oldArgs := os.Args - defer func() { os.Args = oldArgs }() - os.Args = []string{"cmd", "--before", "subcmd"} - before := Bool("before", false, "") - if err := GetCommandLine().Parse(os.Args[1:]); err != nil { - t.Fatal(err) - } - cmd := Arg(0) - os.Args = []string{"subcmd", "--after", "args"} - after := Bool("after", false, "") - Parse() - args := Args() - - if !*before || cmd != "subcmd" || !*after || len(args) != 1 || args[0] != "args" { - t.Fatalf("expected true subcmd true [args] got %v %v %v %v", *before, cmd, *after, args) - } -} - -// Test that -help invokes the usage message and returns ErrHelp. -func TestHelp(t *testing.T) { - var helpCalled = false - fs := NewFlagSet("help test", ContinueOnError) - fs.Usage = func() { helpCalled = true } - var flag bool - fs.BoolVar(&flag, "flag", false, "regular flag") - // Regular flag invocation should work - err := fs.Parse([]string{"--flag=true"}) - if err != nil { - t.Fatal("expected no error; got ", err) - } - if !flag { - t.Error("flag was not set by --flag") - } - if helpCalled { - t.Error("help called for regular flag") - helpCalled = false // reset for next test - } - // Help flag should work as expected. - err = fs.Parse([]string{"--help"}) - if err == nil { - t.Fatal("error expected") - } - if err != ErrHelp { - t.Fatal("expected ErrHelp; got ", err) - } - if !helpCalled { - t.Fatal("help was not called") - } - // If we define a help flag, that should override. - var help bool - fs.BoolVar(&help, "help", false, "help flag") - helpCalled = false - err = fs.Parse([]string{"--help"}) - if err != nil { - t.Fatal("expected no error for defined --help; got ", err) - } - if helpCalled { - t.Fatal("help was called; should not have been for defined help flag") - } -} - -func TestNoInterspersed(t *testing.T) { - f := NewFlagSet("test", ContinueOnError) - f.SetInterspersed(false) - f.Bool("true", true, "always true") - f.Bool("false", false, "always false") - err := f.Parse([]string{"--true", "break", "--false"}) - if err != nil { - t.Fatal("expected no error; got ", err) - } - args := f.Args() - if len(args) != 2 || args[0] != "break" || args[1] != "--false" { - t.Fatal("expected interspersed options/non-options to fail") - } -} - -func TestTermination(t *testing.T) { - f := NewFlagSet("termination", ContinueOnError) - boolFlag := f.BoolP("bool", "l", false, "bool value") - if f.Parsed() { - t.Error("f.Parse() = true before Parse") - } - arg1 := "ls" - arg2 := "-l" - args := []string{ - "--", - arg1, - arg2, - } - f.SetOutput(ioutil.Discard) - if err := f.Parse(args); err != nil { - t.Fatal("expected no error; got ", err) - } - if !f.Parsed() { - t.Error("f.Parse() = false after Parse") - } - if *boolFlag { - t.Error("expected boolFlag=false, got true") - } - if len(f.Args()) != 2 { - t.Errorf("expected 2 arguments, got %d: %v", len(f.Args()), f.Args()) - } - if f.Args()[0] != arg1 { - t.Errorf("expected argument %q got %q", arg1, f.Args()[0]) - } - if f.Args()[1] != arg2 { - t.Errorf("expected argument %q got %q", arg2, f.Args()[1]) - } - if f.ArgsLenAtDash() != 0 { - t.Errorf("expected argsLenAtDash %d got %d", 0, f.ArgsLenAtDash()) - } -} - -func getDeprecatedFlagSet() *FlagSet { - f := NewFlagSet("bob", ContinueOnError) - f.Bool("badflag", true, "always true") - f.MarkDeprecated("badflag", "use --good-flag instead") - return f -} -func TestDeprecatedFlagInDocs(t *testing.T) { - f := getDeprecatedFlagSet() - - out := new(bytes.Buffer) - f.SetOutput(out) - f.PrintDefaults() - - if strings.Contains(out.String(), "badflag") { - t.Errorf("found deprecated flag in usage!") - } -} - -func TestUnHiddenDeprecatedFlagInDocs(t *testing.T) { - f := getDeprecatedFlagSet() - flg := f.Lookup("badflag") - if flg == nil { - t.Fatalf("Unable to lookup 'bob' in TestUnHiddenDeprecatedFlagInDocs") - } - flg.Hidden = false - - out := new(bytes.Buffer) - f.SetOutput(out) - f.PrintDefaults() - - defaults := out.String() - if !strings.Contains(defaults, "badflag") { - t.Errorf("Did not find deprecated flag in usage!") - } - if !strings.Contains(defaults, "use --good-flag instead") { - t.Errorf("Did not find 'use --good-flag instead' in defaults") - } -} - -func TestDeprecatedFlagShorthandInDocs(t *testing.T) { - f := NewFlagSet("bob", ContinueOnError) - name := "noshorthandflag" - f.BoolP(name, "n", true, "always true") - f.MarkShorthandDeprecated("noshorthandflag", fmt.Sprintf("use --%s instead", name)) - - out := new(bytes.Buffer) - f.SetOutput(out) - f.PrintDefaults() - - if strings.Contains(out.String(), "-n,") { - t.Errorf("found deprecated flag shorthand in usage!") - } -} - -func parseReturnStderr(t *testing.T, f *FlagSet, args []string) (string, error) { - oldStderr := os.Stderr - r, w, _ := os.Pipe() - os.Stderr = w - - err := f.Parse(args) - - outC := make(chan string) - // copy the output in a separate goroutine so printing can't block indefinitely - go func() { - var buf bytes.Buffer - io.Copy(&buf, r) - outC <- buf.String() - }() - - w.Close() - os.Stderr = oldStderr - out := <-outC - - return out, err -} - -func TestDeprecatedFlagUsage(t *testing.T) { - f := NewFlagSet("bob", ContinueOnError) - f.Bool("badflag", true, "always true") - usageMsg := "use --good-flag instead" - f.MarkDeprecated("badflag", usageMsg) - - args := []string{"--badflag"} - out, err := parseReturnStderr(t, f, args) - if err != nil { - t.Fatal("expected no error; got ", err) - } - - if !strings.Contains(out, usageMsg) { - t.Errorf("usageMsg not printed when using a deprecated flag!") - } -} - -func TestDeprecatedFlagShorthandUsage(t *testing.T) { - f := NewFlagSet("bob", ContinueOnError) - name := "noshorthandflag" - f.BoolP(name, "n", true, "always true") - usageMsg := fmt.Sprintf("use --%s instead", name) - f.MarkShorthandDeprecated(name, usageMsg) - - args := []string{"-n"} - out, err := parseReturnStderr(t, f, args) - if err != nil { - t.Fatal("expected no error; got ", err) - } - - if !strings.Contains(out, usageMsg) { - t.Errorf("usageMsg not printed when using a deprecated flag!") - } -} - -func TestDeprecatedFlagUsageNormalized(t *testing.T) { - f := NewFlagSet("bob", ContinueOnError) - f.Bool("bad-double_flag", true, "always true") - f.SetNormalizeFunc(wordSepNormalizeFunc) - usageMsg := "use --good-flag instead" - f.MarkDeprecated("bad_double-flag", usageMsg) - - args := []string{"--bad_double_flag"} - out, err := parseReturnStderr(t, f, args) - if err != nil { - t.Fatal("expected no error; got ", err) - } - - if !strings.Contains(out, usageMsg) { - t.Errorf("usageMsg not printed when using a deprecated flag!") - } -} - -// Name normalization function should be called only once on flag addition -func TestMultipleNormalizeFlagNameInvocations(t *testing.T) { - normalizeFlagNameInvocations = 0 - - f := NewFlagSet("normalized", ContinueOnError) - f.SetNormalizeFunc(wordSepNormalizeFunc) - f.Bool("with_under_flag", false, "bool value") - - if normalizeFlagNameInvocations != 1 { - t.Fatal("Expected normalizeFlagNameInvocations to be 1; got ", normalizeFlagNameInvocations) - } -} - -// -func TestHiddenFlagInUsage(t *testing.T) { - f := NewFlagSet("bob", ContinueOnError) - f.Bool("secretFlag", true, "shhh") - f.MarkHidden("secretFlag") - - out := new(bytes.Buffer) - f.SetOutput(out) - f.PrintDefaults() - - if strings.Contains(out.String(), "secretFlag") { - t.Errorf("found hidden flag in usage!") - } -} - -// -func TestHiddenFlagUsage(t *testing.T) { - f := NewFlagSet("bob", ContinueOnError) - f.Bool("secretFlag", true, "shhh") - f.MarkHidden("secretFlag") - - args := []string{"--secretFlag"} - out, err := parseReturnStderr(t, f, args) - if err != nil { - t.Fatal("expected no error; got ", err) - } - - if strings.Contains(out, "shhh") { - t.Errorf("usage message printed when using a hidden flag!") - } -} - -const defaultOutput = ` --A for bootstrapping, allow 'any' type - --Alongflagname disable bounds checking - -C, --CCC a boolean defaulting to true (default true) - --D path set relative path for local imports - -E, --EEE num[=1234] a num with NoOptDefVal (default 4321) - --F number a non-zero number (default 2.7) - --G float a float that defaults to zero - --IP ip IP address with no default - --IPMask ipMask Netmask address with no default - --IPNet ipNet IP network with no default - --Ints ints int slice with zero default - --N int a non-zero int (default 27) - --ND1 string[="bar"] a string with NoOptDefVal (default "foo") - --ND2 num[=4321] a num with NoOptDefVal (default 1234) - --StringArray stringArray string array with zero default - --StringSlice strings string slice with zero default - --Z int an int that defaults to zero - --custom custom custom Value implementation - --customP custom a VarP with default (default 10) - --maxT timeout set timeout for dial - -v, --verbose count verbosity -` - -// Custom value that satisfies the Value interface. -type customValue int - -func (cv *customValue) String() string { return fmt.Sprintf("%v", *cv) } - -func (cv *customValue) Set(s string) error { - v, err := strconv.ParseInt(s, 0, 64) - *cv = customValue(v) - return err -} - -func (cv *customValue) Type() string { return "custom" } - -func TestPrintDefaults(t *testing.T) { - fs := NewFlagSet("print defaults test", ContinueOnError) - var buf bytes.Buffer - fs.SetOutput(&buf) - fs.Bool("A", false, "for bootstrapping, allow 'any' type") - fs.Bool("Alongflagname", false, "disable bounds checking") - fs.BoolP("CCC", "C", true, "a boolean defaulting to true") - fs.String("D", "", "set relative `path` for local imports") - fs.Float64("F", 2.7, "a non-zero `number`") - fs.Float64("G", 0, "a float that defaults to zero") - fs.Int("N", 27, "a non-zero int") - fs.IntSlice("Ints", []int{}, "int slice with zero default") - fs.IP("IP", nil, "IP address with no default") - fs.IPMask("IPMask", nil, "Netmask address with no default") - fs.IPNet("IPNet", net.IPNet{}, "IP network with no default") - fs.Int("Z", 0, "an int that defaults to zero") - fs.Duration("maxT", 0, "set `timeout` for dial") - fs.String("ND1", "foo", "a string with NoOptDefVal") - fs.Lookup("ND1").NoOptDefVal = "bar" - fs.Int("ND2", 1234, "a `num` with NoOptDefVal") - fs.Lookup("ND2").NoOptDefVal = "4321" - fs.IntP("EEE", "E", 4321, "a `num` with NoOptDefVal") - fs.ShorthandLookup("E").NoOptDefVal = "1234" - fs.StringSlice("StringSlice", []string{}, "string slice with zero default") - fs.StringArray("StringArray", []string{}, "string array with zero default") - fs.CountP("verbose", "v", "verbosity") - - var cv customValue - fs.Var(&cv, "custom", "custom Value implementation") - - cv2 := customValue(10) - fs.VarP(&cv2, "customP", "", "a VarP with default") - - fs.PrintDefaults() - got := buf.String() - if got != defaultOutput { - fmt.Println("\n" + got) - fmt.Println("\n" + defaultOutput) - t.Errorf("got %q want %q\n", got, defaultOutput) - } -} - -func TestVisitAllFlagOrder(t *testing.T) { - fs := NewFlagSet("TestVisitAllFlagOrder", ContinueOnError) - fs.SortFlags = false - // https://github.com/spf13/pflag/issues/120 - fs.SetNormalizeFunc(func(f *FlagSet, name string) NormalizedName { - return NormalizedName(name) - }) - - names := []string{"C", "B", "A", "D"} - for _, name := range names { - fs.Bool(name, false, "") - } - - i := 0 - fs.VisitAll(func(f *Flag) { - if names[i] != f.Name { - t.Errorf("Incorrect order. Expected %v, got %v", names[i], f.Name) - } - i++ - }) -} - -func TestVisitFlagOrder(t *testing.T) { - fs := NewFlagSet("TestVisitFlagOrder", ContinueOnError) - fs.SortFlags = false - names := []string{"C", "B", "A", "D"} - for _, name := range names { - fs.Bool(name, false, "") - fs.Set(name, "true") - } - - i := 0 - fs.Visit(func(f *Flag) { - if names[i] != f.Name { - t.Errorf("Incorrect order. Expected %v, got %v", names[i], f.Name) - } - i++ - }) -} diff --git a/vendor/github.com/spf13/pflag/golangflag_test.go b/vendor/github.com/spf13/pflag/golangflag_test.go deleted file mode 100644 index 5bd831bf9..000000000 --- a/vendor/github.com/spf13/pflag/golangflag_test.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - goflag "flag" - "testing" -) - -func TestGoflags(t *testing.T) { - goflag.String("stringFlag", "stringFlag", "stringFlag") - goflag.Bool("boolFlag", false, "boolFlag") - - f := NewFlagSet("test", ContinueOnError) - - f.AddGoFlagSet(goflag.CommandLine) - err := f.Parse([]string{"--stringFlag=bob", "--boolFlag"}) - if err != nil { - t.Fatal("expected no error; get", err) - } - - getString, err := f.GetString("stringFlag") - if err != nil { - t.Fatal("expected no error; get", err) - } - if getString != "bob" { - t.Fatalf("expected getString=bob but got getString=%s", getString) - } - - getBool, err := f.GetBool("boolFlag") - if err != nil { - t.Fatal("expected no error; get", err) - } - if getBool != true { - t.Fatalf("expected getBool=true but got getBool=%v", getBool) - } - if !f.Parsed() { - t.Fatal("f.Parsed() return false after f.Parse() called") - } - - // in fact it is useless. because `go test` called flag.Parse() - if !goflag.CommandLine.Parsed() { - t.Fatal("goflag.CommandLine.Parsed() return false after f.Parse() called") - } -} diff --git a/vendor/github.com/spf13/pflag/int_slice_test.go b/vendor/github.com/spf13/pflag/int_slice_test.go deleted file mode 100644 index 745aecb95..000000000 --- a/vendor/github.com/spf13/pflag/int_slice_test.go +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - "fmt" - "strconv" - "strings" - "testing" -) - -func setUpISFlagSet(isp *[]int) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.IntSliceVar(isp, "is", []int{}, "Command separated list!") - return f -} - -func setUpISFlagSetWithDefault(isp *[]int) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.IntSliceVar(isp, "is", []int{0, 1}, "Command separated list!") - return f -} - -func TestEmptyIS(t *testing.T) { - var is []int - f := setUpISFlagSet(&is) - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - getIS, err := f.GetIntSlice("is") - if err != nil { - t.Fatal("got an error from GetIntSlice():", err) - } - if len(getIS) != 0 { - t.Fatalf("got is %v with len=%d but expected length=0", getIS, len(getIS)) - } -} - -func TestIS(t *testing.T) { - var is []int - f := setUpISFlagSet(&is) - - vals := []string{"1", "2", "4", "3"} - arg := fmt.Sprintf("--is=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range is { - d, err := strconv.Atoi(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected is[%d] to be %s but got: %d", i, vals[i], v) - } - } - getIS, err := f.GetIntSlice("is") - if err != nil { - t.Fatalf("got error: %v", err) - } - for i, v := range getIS { - d, err := strconv.Atoi(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected is[%d] to be %s but got: %d from GetIntSlice", i, vals[i], v) - } - } -} - -func TestISDefault(t *testing.T) { - var is []int - f := setUpISFlagSetWithDefault(&is) - - vals := []string{"0", "1"} - - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range is { - d, err := strconv.Atoi(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected is[%d] to be %d but got: %d", i, d, v) - } - } - - getIS, err := f.GetIntSlice("is") - if err != nil { - t.Fatal("got an error from GetIntSlice():", err) - } - for i, v := range getIS { - d, err := strconv.Atoi(vals[i]) - if err != nil { - t.Fatal("got an error from GetIntSlice():", err) - } - if d != v { - t.Fatalf("expected is[%d] to be %d from GetIntSlice but got: %d", i, d, v) - } - } -} - -func TestISWithDefault(t *testing.T) { - var is []int - f := setUpISFlagSetWithDefault(&is) - - vals := []string{"1", "2"} - arg := fmt.Sprintf("--is=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range is { - d, err := strconv.Atoi(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected is[%d] to be %d but got: %d", i, d, v) - } - } - - getIS, err := f.GetIntSlice("is") - if err != nil { - t.Fatal("got an error from GetIntSlice():", err) - } - for i, v := range getIS { - d, err := strconv.Atoi(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected is[%d] to be %d from GetIntSlice but got: %d", i, d, v) - } - } -} - -func TestISCalledTwice(t *testing.T) { - var is []int - f := setUpISFlagSet(&is) - - in := []string{"1,2", "3"} - expected := []int{1, 2, 3} - argfmt := "--is=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range is { - if expected[i] != v { - t.Fatalf("expected is[%d] to be %d but got: %d", i, expected[i], v) - } - } -} diff --git a/vendor/github.com/spf13/pflag/ip_slice_test.go b/vendor/github.com/spf13/pflag/ip_slice_test.go deleted file mode 100644 index b0c681c5b..000000000 --- a/vendor/github.com/spf13/pflag/ip_slice_test.go +++ /dev/null @@ -1,222 +0,0 @@ -package pflag - -import ( - "fmt" - "net" - "strings" - "testing" -) - -func setUpIPSFlagSet(ipsp *[]net.IP) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.IPSliceVar(ipsp, "ips", []net.IP{}, "Command separated list!") - return f -} - -func setUpIPSFlagSetWithDefault(ipsp *[]net.IP) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.IPSliceVar(ipsp, "ips", - []net.IP{ - net.ParseIP("192.168.1.1"), - net.ParseIP("0:0:0:0:0:0:0:1"), - }, - "Command separated list!") - return f -} - -func TestEmptyIP(t *testing.T) { - var ips []net.IP - f := setUpIPSFlagSet(&ips) - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - getIPS, err := f.GetIPSlice("ips") - if err != nil { - t.Fatal("got an error from GetIPSlice():", err) - } - if len(getIPS) != 0 { - t.Fatalf("got ips %v with len=%d but expected length=0", getIPS, len(getIPS)) - } -} - -func TestIPS(t *testing.T) { - var ips []net.IP - f := setUpIPSFlagSet(&ips) - - vals := []string{"192.168.1.1", "10.0.0.1", "0:0:0:0:0:0:0:2"} - arg := fmt.Sprintf("--ips=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range ips { - if ip := net.ParseIP(vals[i]); ip == nil { - t.Fatalf("invalid string being converted to IP address: %s", vals[i]) - } else if !ip.Equal(v) { - t.Fatalf("expected ips[%d] to be %s but got: %s from GetIPSlice", i, vals[i], v) - } - } -} - -func TestIPSDefault(t *testing.T) { - var ips []net.IP - f := setUpIPSFlagSetWithDefault(&ips) - - vals := []string{"192.168.1.1", "0:0:0:0:0:0:0:1"} - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range ips { - if ip := net.ParseIP(vals[i]); ip == nil { - t.Fatalf("invalid string being converted to IP address: %s", vals[i]) - } else if !ip.Equal(v) { - t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v) - } - } - - getIPS, err := f.GetIPSlice("ips") - if err != nil { - t.Fatal("got an error from GetIPSlice") - } - for i, v := range getIPS { - if ip := net.ParseIP(vals[i]); ip == nil { - t.Fatalf("invalid string being converted to IP address: %s", vals[i]) - } else if !ip.Equal(v) { - t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v) - } - } -} - -func TestIPSWithDefault(t *testing.T) { - var ips []net.IP - f := setUpIPSFlagSetWithDefault(&ips) - - vals := []string{"192.168.1.1", "0:0:0:0:0:0:0:1"} - arg := fmt.Sprintf("--ips=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range ips { - if ip := net.ParseIP(vals[i]); ip == nil { - t.Fatalf("invalid string being converted to IP address: %s", vals[i]) - } else if !ip.Equal(v) { - t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v) - } - } - - getIPS, err := f.GetIPSlice("ips") - if err != nil { - t.Fatal("got an error from GetIPSlice") - } - for i, v := range getIPS { - if ip := net.ParseIP(vals[i]); ip == nil { - t.Fatalf("invalid string being converted to IP address: %s", vals[i]) - } else if !ip.Equal(v) { - t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v) - } - } -} - -func TestIPSCalledTwice(t *testing.T) { - var ips []net.IP - f := setUpIPSFlagSet(&ips) - - in := []string{"192.168.1.2,0:0:0:0:0:0:0:1", "10.0.0.1"} - expected := []net.IP{net.ParseIP("192.168.1.2"), net.ParseIP("0:0:0:0:0:0:0:1"), net.ParseIP("10.0.0.1")} - argfmt := "ips=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range ips { - if !expected[i].Equal(v) { - t.Fatalf("expected ips[%d] to be %s but got: %s", i, expected[i], v) - } - } -} - -func TestIPSBadQuoting(t *testing.T) { - - tests := []struct { - Want []net.IP - FlagArg []string - }{ - { - Want: []net.IP{ - net.ParseIP("a4ab:61d:f03e:5d7d:fad7:d4c2:a1a5:568"), - net.ParseIP("203.107.49.208"), - net.ParseIP("14.57.204.90"), - }, - FlagArg: []string{ - "a4ab:61d:f03e:5d7d:fad7:d4c2:a1a5:568", - "203.107.49.208", - "14.57.204.90", - }, - }, - { - Want: []net.IP{ - net.ParseIP("204.228.73.195"), - net.ParseIP("86.141.15.94"), - }, - FlagArg: []string{ - "204.228.73.195", - "86.141.15.94", - }, - }, - { - Want: []net.IP{ - net.ParseIP("c70c:db36:3001:890f:c6ea:3f9b:7a39:cc3f"), - net.ParseIP("4d17:1d6e:e699:bd7a:88c5:5e7e:ac6a:4472"), - }, - FlagArg: []string{ - "c70c:db36:3001:890f:c6ea:3f9b:7a39:cc3f", - "4d17:1d6e:e699:bd7a:88c5:5e7e:ac6a:4472", - }, - }, - { - Want: []net.IP{ - net.ParseIP("5170:f971:cfac:7be3:512a:af37:952c:bc33"), - net.ParseIP("93.21.145.140"), - net.ParseIP("2cac:61d3:c5ff:6caf:73e0:1b1a:c336:c1ca"), - }, - FlagArg: []string{ - " 5170:f971:cfac:7be3:512a:af37:952c:bc33 , 93.21.145.140 ", - "2cac:61d3:c5ff:6caf:73e0:1b1a:c336:c1ca", - }, - }, - { - Want: []net.IP{ - net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"), - net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"), - net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"), - net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"), - }, - FlagArg: []string{ - `"2e5e:66b2:6441:848:5b74:76ea:574c:3a7b, 2e5e:66b2:6441:848:5b74:76ea:574c:3a7b,2e5e:66b2:6441:848:5b74:76ea:574c:3a7b "`, - " 2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"}, - }, - } - - for i, test := range tests { - - var ips []net.IP - f := setUpIPSFlagSet(&ips) - - if err := f.Parse([]string{fmt.Sprintf("--ips=%s", strings.Join(test.FlagArg, ","))}); err != nil { - t.Fatalf("flag parsing failed with error: %s\nparsing:\t%#v\nwant:\t\t%s", - err, test.FlagArg, test.Want[i]) - } - - for j, b := range ips { - if !b.Equal(test.Want[j]) { - t.Fatalf("bad value parsed for test %d on net.IP %d:\nwant:\t%s\ngot:\t%s", i, j, test.Want[j], b) - } - } - } -} diff --git a/vendor/github.com/spf13/pflag/ip_test.go b/vendor/github.com/spf13/pflag/ip_test.go deleted file mode 100644 index 1fec50e42..000000000 --- a/vendor/github.com/spf13/pflag/ip_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package pflag - -import ( - "fmt" - "net" - "os" - "testing" -) - -func setUpIP(ip *net.IP) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.IPVar(ip, "address", net.ParseIP("0.0.0.0"), "IP Address") - return f -} - -func TestIP(t *testing.T) { - testCases := []struct { - input string - success bool - expected string - }{ - {"0.0.0.0", true, "0.0.0.0"}, - {" 0.0.0.0 ", true, "0.0.0.0"}, - {"1.2.3.4", true, "1.2.3.4"}, - {"127.0.0.1", true, "127.0.0.1"}, - {"255.255.255.255", true, "255.255.255.255"}, - {"", false, ""}, - {"0", false, ""}, - {"localhost", false, ""}, - {"0.0.0", false, ""}, - {"0.0.0.", false, ""}, - {"0.0.0.0.", false, ""}, - {"0.0.0.256", false, ""}, - {"0 . 0 . 0 . 0", false, ""}, - } - - devnull, _ := os.Open(os.DevNull) - os.Stderr = devnull - for i := range testCases { - var addr net.IP - f := setUpIP(&addr) - - tc := &testCases[i] - - arg := fmt.Sprintf("--address=%s", tc.input) - err := f.Parse([]string{arg}) - if err != nil && tc.success == true { - t.Errorf("expected success, got %q", err) - continue - } else if err == nil && tc.success == false { - t.Errorf("expected failure") - continue - } else if tc.success { - ip, err := f.GetIP("address") - if err != nil { - t.Errorf("Got error trying to fetch the IP flag: %v", err) - } - if ip.String() != tc.expected { - t.Errorf("expected %q, got %q", tc.expected, ip.String()) - } - } - } -} diff --git a/vendor/github.com/spf13/pflag/ipnet_test.go b/vendor/github.com/spf13/pflag/ipnet_test.go deleted file mode 100644 index 335b6fa15..000000000 --- a/vendor/github.com/spf13/pflag/ipnet_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package pflag - -import ( - "fmt" - "net" - "os" - "testing" -) - -func setUpIPNet(ip *net.IPNet) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - _, def, _ := net.ParseCIDR("0.0.0.0/0") - f.IPNetVar(ip, "address", *def, "IP Address") - return f -} - -func TestIPNet(t *testing.T) { - testCases := []struct { - input string - success bool - expected string - }{ - {"0.0.0.0/0", true, "0.0.0.0/0"}, - {" 0.0.0.0/0 ", true, "0.0.0.0/0"}, - {"1.2.3.4/8", true, "1.0.0.0/8"}, - {"127.0.0.1/16", true, "127.0.0.0/16"}, - {"255.255.255.255/19", true, "255.255.224.0/19"}, - {"255.255.255.255/32", true, "255.255.255.255/32"}, - {"", false, ""}, - {"/0", false, ""}, - {"0", false, ""}, - {"0/0", false, ""}, - {"localhost/0", false, ""}, - {"0.0.0/4", false, ""}, - {"0.0.0./8", false, ""}, - {"0.0.0.0./12", false, ""}, - {"0.0.0.256/16", false, ""}, - {"0.0.0.0 /20", false, ""}, - {"0.0.0.0/ 24", false, ""}, - {"0 . 0 . 0 . 0 / 28", false, ""}, - {"0.0.0.0/33", false, ""}, - } - - devnull, _ := os.Open(os.DevNull) - os.Stderr = devnull - for i := range testCases { - var addr net.IPNet - f := setUpIPNet(&addr) - - tc := &testCases[i] - - arg := fmt.Sprintf("--address=%s", tc.input) - err := f.Parse([]string{arg}) - if err != nil && tc.success == true { - t.Errorf("expected success, got %q", err) - continue - } else if err == nil && tc.success == false { - t.Errorf("expected failure") - continue - } else if tc.success { - ip, err := f.GetIPNet("address") - if err != nil { - t.Errorf("Got error trying to fetch the IP flag: %v", err) - } - if ip.String() != tc.expected { - t.Errorf("expected %q, got %q", tc.expected, ip.String()) - } - } - } -} diff --git a/vendor/github.com/spf13/pflag/printusage_test.go b/vendor/github.com/spf13/pflag/printusage_test.go deleted file mode 100644 index df982aab4..000000000 --- a/vendor/github.com/spf13/pflag/printusage_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package pflag - -import ( - "bytes" - "io" - "testing" -) - -const expectedOutput = ` --long-form Some description - --long-form2 Some description - with multiline - -s, --long-name Some description - -t, --long-name2 Some description with - multiline -` - -func setUpPFlagSet(buf io.Writer) *FlagSet { - f := NewFlagSet("test", ExitOnError) - f.Bool("long-form", false, "Some description") - f.Bool("long-form2", false, "Some description\n with multiline") - f.BoolP("long-name", "s", false, "Some description") - f.BoolP("long-name2", "t", false, "Some description with\n multiline") - f.SetOutput(buf) - return f -} - -func TestPrintUsage(t *testing.T) { - buf := bytes.Buffer{} - f := setUpPFlagSet(&buf) - f.PrintDefaults() - res := buf.String() - if res != expectedOutput { - t.Errorf("Expected \n%s \nActual \n%s", expectedOutput, res) - } -} - -func setUpPFlagSet2(buf io.Writer) *FlagSet { - f := NewFlagSet("test", ExitOnError) - f.Bool("long-form", false, "Some description") - f.Bool("long-form2", false, "Some description\n with multiline") - f.BoolP("long-name", "s", false, "Some description") - f.BoolP("long-name2", "t", false, "Some description with\n multiline") - f.StringP("some-very-long-arg", "l", "test", "Some very long description having break the limit") - f.StringP("other-very-long-arg", "o", "long-default-value", "Some very long description having break the limit") - f.String("some-very-long-arg2", "very long default value", "Some very long description\nwith line break\nmultiple") - f.SetOutput(buf) - return f -} - -const expectedOutput2 = ` --long-form Some description - --long-form2 Some description - with multiline - -s, --long-name Some description - -t, --long-name2 Some description with - multiline - -o, --other-very-long-arg string Some very long description having - break the limit (default - "long-default-value") - -l, --some-very-long-arg string Some very long description having - break the limit (default "test") - --some-very-long-arg2 string Some very long description - with line break - multiple (default "very long default - value") -` - -func TestPrintUsage_2(t *testing.T) { - buf := bytes.Buffer{} - f := setUpPFlagSet2(&buf) - res := f.FlagUsagesWrapped(80) - if res != expectedOutput2 { - t.Errorf("Expected \n%q \nActual \n%q", expectedOutput2, res) - } -} diff --git a/vendor/github.com/spf13/pflag/string_array_test.go b/vendor/github.com/spf13/pflag/string_array_test.go deleted file mode 100644 index 1ceac8c6c..000000000 --- a/vendor/github.com/spf13/pflag/string_array_test.go +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - "fmt" - "testing" -) - -func setUpSAFlagSet(sap *[]string) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.StringArrayVar(sap, "sa", []string{}, "Command separated list!") - return f -} - -func setUpSAFlagSetWithDefault(sap *[]string) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.StringArrayVar(sap, "sa", []string{"default", "values"}, "Command separated list!") - return f -} - -func TestEmptySA(t *testing.T) { - var sa []string - f := setUpSAFlagSet(&sa) - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - getSA, err := f.GetStringArray("sa") - if err != nil { - t.Fatal("got an error from GetStringArray():", err) - } - if len(getSA) != 0 { - t.Fatalf("got sa %v with len=%d but expected length=0", getSA, len(getSA)) - } -} - -func TestEmptySAValue(t *testing.T) { - var sa []string - f := setUpSAFlagSet(&sa) - err := f.Parse([]string{"--sa="}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - getSA, err := f.GetStringArray("sa") - if err != nil { - t.Fatal("got an error from GetStringArray():", err) - } - if len(getSA) != 0 { - t.Fatalf("got sa %v with len=%d but expected length=0", getSA, len(getSA)) - } -} - -func TestSADefault(t *testing.T) { - var sa []string - f := setUpSAFlagSetWithDefault(&sa) - - vals := []string{"default", "values"} - - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range sa { - if vals[i] != v { - t.Fatalf("expected sa[%d] to be %s but got: %s", i, vals[i], v) - } - } - - getSA, err := f.GetStringArray("sa") - if err != nil { - t.Fatal("got an error from GetStringArray():", err) - } - for i, v := range getSA { - if vals[i] != v { - t.Fatalf("expected sa[%d] to be %s from GetStringArray but got: %s", i, vals[i], v) - } - } -} - -func TestSAWithDefault(t *testing.T) { - var sa []string - f := setUpSAFlagSetWithDefault(&sa) - - val := "one" - arg := fmt.Sprintf("--sa=%s", val) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - if len(sa) != 1 { - t.Fatalf("expected number of values to be %d but %d", 1, len(sa)) - } - - if sa[0] != val { - t.Fatalf("expected value to be %s but got: %s", sa[0], val) - } - - getSA, err := f.GetStringArray("sa") - if err != nil { - t.Fatal("got an error from GetStringArray():", err) - } - - if len(getSA) != 1 { - t.Fatalf("expected number of values to be %d but %d", 1, len(getSA)) - } - - if getSA[0] != val { - t.Fatalf("expected value to be %s but got: %s", getSA[0], val) - } -} - -func TestSACalledTwice(t *testing.T) { - var sa []string - f := setUpSAFlagSet(&sa) - - in := []string{"one", "two"} - expected := []string{"one", "two"} - argfmt := "--sa=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - if len(expected) != len(sa) { - t.Fatalf("expected number of sa to be %d but got: %d", len(expected), len(sa)) - } - for i, v := range sa { - if expected[i] != v { - t.Fatalf("expected sa[%d] to be %s but got: %s", i, expected[i], v) - } - } - - values, err := f.GetStringArray("sa") - if err != nil { - t.Fatal("expected no error; got", err) - } - - if len(expected) != len(values) { - t.Fatalf("expected number of values to be %d but got: %d", len(expected), len(sa)) - } - for i, v := range values { - if expected[i] != v { - t.Fatalf("expected got sa[%d] to be %s but got: %s", i, expected[i], v) - } - } -} - -func TestSAWithSpecialChar(t *testing.T) { - var sa []string - f := setUpSAFlagSet(&sa) - - in := []string{"one,two", `"three"`, `"four,five",six`, "seven eight"} - expected := []string{"one,two", `"three"`, `"four,five",six`, "seven eight"} - argfmt := "--sa=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - arg3 := fmt.Sprintf(argfmt, in[2]) - arg4 := fmt.Sprintf(argfmt, in[3]) - err := f.Parse([]string{arg1, arg2, arg3, arg4}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - if len(expected) != len(sa) { - t.Fatalf("expected number of sa to be %d but got: %d", len(expected), len(sa)) - } - for i, v := range sa { - if expected[i] != v { - t.Fatalf("expected sa[%d] to be %s but got: %s", i, expected[i], v) - } - } - - values, err := f.GetStringArray("sa") - if err != nil { - t.Fatal("expected no error; got", err) - } - - if len(expected) != len(values) { - t.Fatalf("expected number of values to be %d but got: %d", len(expected), len(values)) - } - for i, v := range values { - if expected[i] != v { - t.Fatalf("expected got sa[%d] to be %s but got: %s", i, expected[i], v) - } - } -} - -func TestSAWithSquareBrackets(t *testing.T) { - var sa []string - f := setUpSAFlagSet(&sa) - - in := []string{"][]-[", "[a-z]", "[a-z]+"} - expected := []string{"][]-[", "[a-z]", "[a-z]+"} - argfmt := "--sa=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - arg3 := fmt.Sprintf(argfmt, in[2]) - err := f.Parse([]string{arg1, arg2, arg3}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - if len(expected) != len(sa) { - t.Fatalf("expected number of sa to be %d but got: %d", len(expected), len(sa)) - } - for i, v := range sa { - if expected[i] != v { - t.Fatalf("expected sa[%d] to be %s but got: %s", i, expected[i], v) - } - } - - values, err := f.GetStringArray("sa") - if err != nil { - t.Fatal("expected no error; got", err) - } - - if len(expected) != len(values) { - t.Fatalf("expected number of values to be %d but got: %d", len(expected), len(values)) - } - for i, v := range values { - if expected[i] != v { - t.Fatalf("expected got sa[%d] to be %s but got: %s", i, expected[i], v) - } - } -} diff --git a/vendor/github.com/spf13/pflag/string_slice_test.go b/vendor/github.com/spf13/pflag/string_slice_test.go deleted file mode 100644 index c41f3bd66..000000000 --- a/vendor/github.com/spf13/pflag/string_slice_test.go +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - "fmt" - "strings" - "testing" -) - -func setUpSSFlagSet(ssp *[]string) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.StringSliceVar(ssp, "ss", []string{}, "Command separated list!") - return f -} - -func setUpSSFlagSetWithDefault(ssp *[]string) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.StringSliceVar(ssp, "ss", []string{"default", "values"}, "Command separated list!") - return f -} - -func TestEmptySS(t *testing.T) { - var ss []string - f := setUpSSFlagSet(&ss) - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - getSS, err := f.GetStringSlice("ss") - if err != nil { - t.Fatal("got an error from GetStringSlice():", err) - } - if len(getSS) != 0 { - t.Fatalf("got ss %v with len=%d but expected length=0", getSS, len(getSS)) - } -} - -func TestEmptySSValue(t *testing.T) { - var ss []string - f := setUpSSFlagSet(&ss) - err := f.Parse([]string{"--ss="}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - getSS, err := f.GetStringSlice("ss") - if err != nil { - t.Fatal("got an error from GetStringSlice():", err) - } - if len(getSS) != 0 { - t.Fatalf("got ss %v with len=%d but expected length=0", getSS, len(getSS)) - } -} - -func TestSS(t *testing.T) { - var ss []string - f := setUpSSFlagSet(&ss) - - vals := []string{"one", "two", "4", "3"} - arg := fmt.Sprintf("--ss=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range ss { - if vals[i] != v { - t.Fatalf("expected ss[%d] to be %s but got: %s", i, vals[i], v) - } - } - - getSS, err := f.GetStringSlice("ss") - if err != nil { - t.Fatal("got an error from GetStringSlice():", err) - } - for i, v := range getSS { - if vals[i] != v { - t.Fatalf("expected ss[%d] to be %s from GetStringSlice but got: %s", i, vals[i], v) - } - } -} - -func TestSSDefault(t *testing.T) { - var ss []string - f := setUpSSFlagSetWithDefault(&ss) - - vals := []string{"default", "values"} - - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range ss { - if vals[i] != v { - t.Fatalf("expected ss[%d] to be %s but got: %s", i, vals[i], v) - } - } - - getSS, err := f.GetStringSlice("ss") - if err != nil { - t.Fatal("got an error from GetStringSlice():", err) - } - for i, v := range getSS { - if vals[i] != v { - t.Fatalf("expected ss[%d] to be %s from GetStringSlice but got: %s", i, vals[i], v) - } - } -} - -func TestSSWithDefault(t *testing.T) { - var ss []string - f := setUpSSFlagSetWithDefault(&ss) - - vals := []string{"one", "two", "4", "3"} - arg := fmt.Sprintf("--ss=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range ss { - if vals[i] != v { - t.Fatalf("expected ss[%d] to be %s but got: %s", i, vals[i], v) - } - } - - getSS, err := f.GetStringSlice("ss") - if err != nil { - t.Fatal("got an error from GetStringSlice():", err) - } - for i, v := range getSS { - if vals[i] != v { - t.Fatalf("expected ss[%d] to be %s from GetStringSlice but got: %s", i, vals[i], v) - } - } -} - -func TestSSCalledTwice(t *testing.T) { - var ss []string - f := setUpSSFlagSet(&ss) - - in := []string{"one,two", "three"} - expected := []string{"one", "two", "three"} - argfmt := "--ss=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - if len(expected) != len(ss) { - t.Fatalf("expected number of ss to be %d but got: %d", len(expected), len(ss)) - } - for i, v := range ss { - if expected[i] != v { - t.Fatalf("expected ss[%d] to be %s but got: %s", i, expected[i], v) - } - } - - values, err := f.GetStringSlice("ss") - if err != nil { - t.Fatal("expected no error; got", err) - } - - if len(expected) != len(values) { - t.Fatalf("expected number of values to be %d but got: %d", len(expected), len(ss)) - } - for i, v := range values { - if expected[i] != v { - t.Fatalf("expected got ss[%d] to be %s but got: %s", i, expected[i], v) - } - } -} - -func TestSSWithComma(t *testing.T) { - var ss []string - f := setUpSSFlagSet(&ss) - - in := []string{`"one,two"`, `"three"`, `"four,five",six`} - expected := []string{"one,two", "three", "four,five", "six"} - argfmt := "--ss=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - arg3 := fmt.Sprintf(argfmt, in[2]) - err := f.Parse([]string{arg1, arg2, arg3}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - if len(expected) != len(ss) { - t.Fatalf("expected number of ss to be %d but got: %d", len(expected), len(ss)) - } - for i, v := range ss { - if expected[i] != v { - t.Fatalf("expected ss[%d] to be %s but got: %s", i, expected[i], v) - } - } - - values, err := f.GetStringSlice("ss") - if err != nil { - t.Fatal("expected no error; got", err) - } - - if len(expected) != len(values) { - t.Fatalf("expected number of values to be %d but got: %d", len(expected), len(values)) - } - for i, v := range values { - if expected[i] != v { - t.Fatalf("expected got ss[%d] to be %s but got: %s", i, expected[i], v) - } - } -} - -func TestSSWithSquareBrackets(t *testing.T) { - var ss []string - f := setUpSSFlagSet(&ss) - - in := []string{`"[a-z]"`, `"[a-z]+"`} - expected := []string{"[a-z]", "[a-z]+"} - argfmt := "--ss=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - if len(expected) != len(ss) { - t.Fatalf("expected number of ss to be %d but got: %d", len(expected), len(ss)) - } - for i, v := range ss { - if expected[i] != v { - t.Fatalf("expected ss[%d] to be %s but got: %s", i, expected[i], v) - } - } - - values, err := f.GetStringSlice("ss") - if err != nil { - t.Fatal("expected no error; got", err) - } - - if len(expected) != len(values) { - t.Fatalf("expected number of values to be %d but got: %d", len(expected), len(values)) - } - for i, v := range values { - if expected[i] != v { - t.Fatalf("expected got ss[%d] to be %s but got: %s", i, expected[i], v) - } - } -} diff --git a/vendor/github.com/spf13/pflag/string_to_int.go b/vendor/github.com/spf13/pflag/string_to_int.go new file mode 100644 index 000000000..5ceda3965 --- /dev/null +++ b/vendor/github.com/spf13/pflag/string_to_int.go @@ -0,0 +1,149 @@ +package pflag + +import ( + "bytes" + "fmt" + "strconv" + "strings" +) + +// -- stringToInt Value +type stringToIntValue struct { + value *map[string]int + changed bool +} + +func newStringToIntValue(val map[string]int, p *map[string]int) *stringToIntValue { + ssv := new(stringToIntValue) + ssv.value = p + *ssv.value = val + return ssv +} + +// Format: a=1,b=2 +func (s *stringToIntValue) Set(val string) error { + ss := strings.Split(val, ",") + out := make(map[string]int, len(ss)) + for _, pair := range ss { + kv := strings.SplitN(pair, "=", 2) + if len(kv) != 2 { + return fmt.Errorf("%s must be formatted as key=value", pair) + } + var err error + out[kv[0]], err = strconv.Atoi(kv[1]) + if err != nil { + return err + } + } + if !s.changed { + *s.value = out + } else { + for k, v := range out { + (*s.value)[k] = v + } + } + s.changed = true + return nil +} + +func (s *stringToIntValue) Type() string { + return "stringToInt" +} + +func (s *stringToIntValue) String() string { + var buf bytes.Buffer + i := 0 + for k, v := range *s.value { + if i > 0 { + buf.WriteRune(',') + } + buf.WriteString(k) + buf.WriteRune('=') + buf.WriteString(strconv.Itoa(v)) + i++ + } + return "[" + buf.String() + "]" +} + +func stringToIntConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // An empty string would cause an empty map + if len(val) == 0 { + return map[string]int{}, nil + } + ss := strings.Split(val, ",") + out := make(map[string]int, len(ss)) + for _, pair := range ss { + kv := strings.SplitN(pair, "=", 2) + if len(kv) != 2 { + return nil, fmt.Errorf("%s must be formatted as key=value", pair) + } + var err error + out[kv[0]], err = strconv.Atoi(kv[1]) + if err != nil { + return nil, err + } + } + return out, nil +} + +// GetStringToInt return the map[string]int value of a flag with the given name +func (f *FlagSet) GetStringToInt(name string) (map[string]int, error) { + val, err := f.getFlagType(name, "stringToInt", stringToIntConv) + if err != nil { + return map[string]int{}, err + } + return val.(map[string]int), nil +} + +// StringToIntVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a map[string]int variable in which to store the values of the multiple flags. +// The value of each argument will not try to be separated by comma +func (f *FlagSet) StringToIntVar(p *map[string]int, name string, value map[string]int, usage string) { + f.VarP(newStringToIntValue(value, p), name, "", usage) +} + +// StringToIntVarP is like StringToIntVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringToIntVarP(p *map[string]int, name, shorthand string, value map[string]int, usage string) { + f.VarP(newStringToIntValue(value, p), name, shorthand, usage) +} + +// StringToIntVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a map[string]int variable in which to store the value of the flag. +// The value of each argument will not try to be separated by comma +func StringToIntVar(p *map[string]int, name string, value map[string]int, usage string) { + CommandLine.VarP(newStringToIntValue(value, p), name, "", usage) +} + +// StringToIntVarP is like StringToIntVar, but accepts a shorthand letter that can be used after a single dash. +func StringToIntVarP(p *map[string]int, name, shorthand string, value map[string]int, usage string) { + CommandLine.VarP(newStringToIntValue(value, p), name, shorthand, usage) +} + +// StringToInt defines a string flag with specified name, default value, and usage string. +// The return value is the address of a map[string]int variable that stores the value of the flag. +// The value of each argument will not try to be separated by comma +func (f *FlagSet) StringToInt(name string, value map[string]int, usage string) *map[string]int { + p := map[string]int{} + f.StringToIntVarP(&p, name, "", value, usage) + return &p +} + +// StringToIntP is like StringToInt, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringToIntP(name, shorthand string, value map[string]int, usage string) *map[string]int { + p := map[string]int{} + f.StringToIntVarP(&p, name, shorthand, value, usage) + return &p +} + +// StringToInt defines a string flag with specified name, default value, and usage string. +// The return value is the address of a map[string]int variable that stores the value of the flag. +// The value of each argument will not try to be separated by comma +func StringToInt(name string, value map[string]int, usage string) *map[string]int { + return CommandLine.StringToIntP(name, "", value, usage) +} + +// StringToIntP is like StringToInt, but accepts a shorthand letter that can be used after a single dash. +func StringToIntP(name, shorthand string, value map[string]int, usage string) *map[string]int { + return CommandLine.StringToIntP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/string_to_string.go b/vendor/github.com/spf13/pflag/string_to_string.go new file mode 100644 index 000000000..890a01afc --- /dev/null +++ b/vendor/github.com/spf13/pflag/string_to_string.go @@ -0,0 +1,160 @@ +package pflag + +import ( + "bytes" + "encoding/csv" + "fmt" + "strings" +) + +// -- stringToString Value +type stringToStringValue struct { + value *map[string]string + changed bool +} + +func newStringToStringValue(val map[string]string, p *map[string]string) *stringToStringValue { + ssv := new(stringToStringValue) + ssv.value = p + *ssv.value = val + return ssv +} + +// Format: a=1,b=2 +func (s *stringToStringValue) Set(val string) error { + var ss []string + n := strings.Count(val, "=") + switch n { + case 0: + return fmt.Errorf("%s must be formatted as key=value", val) + case 1: + ss = append(ss, strings.Trim(val, `"`)) + default: + r := csv.NewReader(strings.NewReader(val)) + var err error + ss, err = r.Read() + if err != nil { + return err + } + } + + out := make(map[string]string, len(ss)) + for _, pair := range ss { + kv := strings.SplitN(pair, "=", 2) + if len(kv) != 2 { + return fmt.Errorf("%s must be formatted as key=value", pair) + } + out[kv[0]] = kv[1] + } + if !s.changed { + *s.value = out + } else { + for k, v := range out { + (*s.value)[k] = v + } + } + s.changed = true + return nil +} + +func (s *stringToStringValue) Type() string { + return "stringToString" +} + +func (s *stringToStringValue) String() string { + records := make([]string, 0, len(*s.value)>>1) + for k, v := range *s.value { + records = append(records, k+"="+v) + } + + var buf bytes.Buffer + w := csv.NewWriter(&buf) + if err := w.Write(records); err != nil { + panic(err) + } + w.Flush() + return "[" + strings.TrimSpace(buf.String()) + "]" +} + +func stringToStringConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // An empty string would cause an empty map + if len(val) == 0 { + return map[string]string{}, nil + } + r := csv.NewReader(strings.NewReader(val)) + ss, err := r.Read() + if err != nil { + return nil, err + } + out := make(map[string]string, len(ss)) + for _, pair := range ss { + kv := strings.SplitN(pair, "=", 2) + if len(kv) != 2 { + return nil, fmt.Errorf("%s must be formatted as key=value", pair) + } + out[kv[0]] = kv[1] + } + return out, nil +} + +// GetStringToString return the map[string]string value of a flag with the given name +func (f *FlagSet) GetStringToString(name string) (map[string]string, error) { + val, err := f.getFlagType(name, "stringToString", stringToStringConv) + if err != nil { + return map[string]string{}, err + } + return val.(map[string]string), nil +} + +// StringToStringVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a map[string]string variable in which to store the values of the multiple flags. +// The value of each argument will not try to be separated by comma +func (f *FlagSet) StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) { + f.VarP(newStringToStringValue(value, p), name, "", usage) +} + +// StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) { + f.VarP(newStringToStringValue(value, p), name, shorthand, usage) +} + +// StringToStringVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a map[string]string variable in which to store the value of the flag. +// The value of each argument will not try to be separated by comma +func StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) { + CommandLine.VarP(newStringToStringValue(value, p), name, "", usage) +} + +// StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash. +func StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) { + CommandLine.VarP(newStringToStringValue(value, p), name, shorthand, usage) +} + +// StringToString defines a string flag with specified name, default value, and usage string. +// The return value is the address of a map[string]string variable that stores the value of the flag. +// The value of each argument will not try to be separated by comma +func (f *FlagSet) StringToString(name string, value map[string]string, usage string) *map[string]string { + p := map[string]string{} + f.StringToStringVarP(&p, name, "", value, usage) + return &p +} + +// StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string { + p := map[string]string{} + f.StringToStringVarP(&p, name, shorthand, value, usage) + return &p +} + +// StringToString defines a string flag with specified name, default value, and usage string. +// The return value is the address of a map[string]string variable that stores the value of the flag. +// The value of each argument will not try to be separated by comma +func StringToString(name string, value map[string]string, usage string) *map[string]string { + return CommandLine.StringToStringP(name, "", value, usage) +} + +// StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash. +func StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string { + return CommandLine.StringToStringP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/uint_slice_test.go b/vendor/github.com/spf13/pflag/uint_slice_test.go deleted file mode 100644 index db1a19dc2..000000000 --- a/vendor/github.com/spf13/pflag/uint_slice_test.go +++ /dev/null @@ -1,161 +0,0 @@ -package pflag - -import ( - "fmt" - "strconv" - "strings" - "testing" -) - -func setUpUISFlagSet(uisp *[]uint) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.UintSliceVar(uisp, "uis", []uint{}, "Command separated list!") - return f -} - -func setUpUISFlagSetWithDefault(uisp *[]uint) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.UintSliceVar(uisp, "uis", []uint{0, 1}, "Command separated list!") - return f -} - -func TestEmptyUIS(t *testing.T) { - var uis []uint - f := setUpUISFlagSet(&uis) - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - getUIS, err := f.GetUintSlice("uis") - if err != nil { - t.Fatal("got an error from GetUintSlice():", err) - } - if len(getUIS) != 0 { - t.Fatalf("got is %v with len=%d but expected length=0", getUIS, len(getUIS)) - } -} - -func TestUIS(t *testing.T) { - var uis []uint - f := setUpUISFlagSet(&uis) - - vals := []string{"1", "2", "4", "3"} - arg := fmt.Sprintf("--uis=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range uis { - u, err := strconv.ParseUint(vals[i], 10, 0) - if err != nil { - t.Fatalf("got error: %v", err) - } - if uint(u) != v { - t.Fatalf("expected uis[%d] to be %s but got %d", i, vals[i], v) - } - } - getUIS, err := f.GetUintSlice("uis") - if err != nil { - t.Fatalf("got error: %v", err) - } - for i, v := range getUIS { - u, err := strconv.ParseUint(vals[i], 10, 0) - if err != nil { - t.Fatalf("got error: %v", err) - } - if uint(u) != v { - t.Fatalf("expected uis[%d] to be %s but got: %d from GetUintSlice", i, vals[i], v) - } - } -} - -func TestUISDefault(t *testing.T) { - var uis []uint - f := setUpUISFlagSetWithDefault(&uis) - - vals := []string{"0", "1"} - - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range uis { - u, err := strconv.ParseUint(vals[i], 10, 0) - if err != nil { - t.Fatalf("got error: %v", err) - } - if uint(u) != v { - t.Fatalf("expect uis[%d] to be %d but got: %d", i, u, v) - } - } - - getUIS, err := f.GetUintSlice("uis") - if err != nil { - t.Fatal("got an error from GetUintSlice():", err) - } - for i, v := range getUIS { - u, err := strconv.ParseUint(vals[i], 10, 0) - if err != nil { - t.Fatal("got an error from GetIntSlice():", err) - } - if uint(u) != v { - t.Fatalf("expected uis[%d] to be %d from GetUintSlice but got: %d", i, u, v) - } - } -} - -func TestUISWithDefault(t *testing.T) { - var uis []uint - f := setUpUISFlagSetWithDefault(&uis) - - vals := []string{"1", "2"} - arg := fmt.Sprintf("--uis=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range uis { - u, err := strconv.ParseUint(vals[i], 10, 0) - if err != nil { - t.Fatalf("got error: %v", err) - } - if uint(u) != v { - t.Fatalf("expected uis[%d] to be %d from GetUintSlice but got: %d", i, u, v) - } - } - - getUIS, err := f.GetUintSlice("uis") - if err != nil { - t.Fatal("got an error from GetUintSlice():", err) - } - for i, v := range getUIS { - u, err := strconv.ParseUint(vals[i], 10, 0) - if err != nil { - t.Fatalf("got error: %v", err) - } - if uint(u) != v { - t.Fatalf("expected uis[%d] to be %d from GetUintSlice but got: %d", i, u, v) - } - } -} - -func TestUISCalledTwice(t *testing.T) { - var uis []uint - f := setUpUISFlagSet(&uis) - - in := []string{"1,2", "3"} - expected := []int{1, 2, 3} - argfmt := "--uis=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range uis { - if uint(expected[i]) != v { - t.Fatalf("expected uis[%d] to be %d but got: %d", i, expected[i], v) - } - } -} diff --git a/vendor/golang.org/x/crypto/AUTHORS b/vendor/golang.org/x/crypto/AUTHORS new file mode 100644 index 000000000..2b00ddba0 --- /dev/null +++ b/vendor/golang.org/x/crypto/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at https://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/crypto/CONTRIBUTORS b/vendor/golang.org/x/crypto/CONTRIBUTORS new file mode 100644 index 000000000..1fbd3e976 --- /dev/null +++ b/vendor/golang.org/x/crypto/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at https://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519_test.go b/vendor/golang.org/x/crypto/ed25519/ed25519_test.go deleted file mode 100644 index 80946036d..000000000 --- a/vendor/golang.org/x/crypto/ed25519/ed25519_test.go +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ed25519 - -import ( - "bufio" - "bytes" - "compress/gzip" - "crypto" - "crypto/rand" - "encoding/hex" - "os" - "strings" - "testing" - - "golang.org/x/crypto/ed25519/internal/edwards25519" -) - -type zeroReader struct{} - -func (zeroReader) Read(buf []byte) (int, error) { - for i := range buf { - buf[i] = 0 - } - return len(buf), nil -} - -func TestUnmarshalMarshal(t *testing.T) { - pub, _, _ := GenerateKey(rand.Reader) - - var A edwards25519.ExtendedGroupElement - var pubBytes [32]byte - copy(pubBytes[:], pub) - if !A.FromBytes(&pubBytes) { - t.Fatalf("ExtendedGroupElement.FromBytes failed") - } - - var pub2 [32]byte - A.ToBytes(&pub2) - - if pubBytes != pub2 { - t.Errorf("FromBytes(%v)->ToBytes does not round-trip, got %x\n", pubBytes, pub2) - } -} - -func TestSignVerify(t *testing.T) { - var zero zeroReader - public, private, _ := GenerateKey(zero) - - message := []byte("test message") - sig := Sign(private, message) - if !Verify(public, message, sig) { - t.Errorf("valid signature rejected") - } - - wrongMessage := []byte("wrong message") - if Verify(public, wrongMessage, sig) { - t.Errorf("signature of different message accepted") - } -} - -func TestCryptoSigner(t *testing.T) { - var zero zeroReader - public, private, _ := GenerateKey(zero) - - signer := crypto.Signer(private) - - publicInterface := signer.Public() - public2, ok := publicInterface.(PublicKey) - if !ok { - t.Fatalf("expected PublicKey from Public() but got %T", publicInterface) - } - - if !bytes.Equal(public, public2) { - t.Errorf("public keys do not match: original:%x vs Public():%x", public, public2) - } - - message := []byte("message") - var noHash crypto.Hash - signature, err := signer.Sign(zero, message, noHash) - if err != nil { - t.Fatalf("error from Sign(): %s", err) - } - - if !Verify(public, message, signature) { - t.Errorf("Verify failed on signature from Sign()") - } -} - -func TestGolden(t *testing.T) { - // sign.input.gz is a selection of test cases from - // https://ed25519.cr.yp.to/python/sign.input - testDataZ, err := os.Open("testdata/sign.input.gz") - if err != nil { - t.Fatal(err) - } - defer testDataZ.Close() - testData, err := gzip.NewReader(testDataZ) - if err != nil { - t.Fatal(err) - } - defer testData.Close() - - scanner := bufio.NewScanner(testData) - lineNo := 0 - - for scanner.Scan() { - lineNo++ - - line := scanner.Text() - parts := strings.Split(line, ":") - if len(parts) != 5 { - t.Fatalf("bad number of parts on line %d", lineNo) - } - - privBytes, _ := hex.DecodeString(parts[0]) - pubKey, _ := hex.DecodeString(parts[1]) - msg, _ := hex.DecodeString(parts[2]) - sig, _ := hex.DecodeString(parts[3]) - // The signatures in the test vectors also include the message - // at the end, but we just want R and S. - sig = sig[:SignatureSize] - - if l := len(pubKey); l != PublicKeySize { - t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l) - } - - var priv [PrivateKeySize]byte - copy(priv[:], privBytes) - copy(priv[32:], pubKey) - - sig2 := Sign(priv[:], msg) - if !bytes.Equal(sig, sig2[:]) { - t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2) - } - - if !Verify(pubKey, msg, sig2) { - t.Errorf("signature failed to verify on line %d", lineNo) - } - - priv2 := NewKeyFromSeed(priv[:32]) - if !bytes.Equal(priv[:], priv2) { - t.Errorf("recreating key pair gave different private key on line %d: %x vs %x", lineNo, priv[:], priv2) - } - - if pubKey2 := priv2.Public().(PublicKey); !bytes.Equal(pubKey, pubKey2) { - t.Errorf("recreating key pair gave different public key on line %d: %x vs %x", lineNo, pubKey, pubKey2) - } - - if seed := priv2.Seed(); !bytes.Equal(priv[:32], seed) { - t.Errorf("recreating key pair gave different seed on line %d: %x vs %x", lineNo, priv[:32], seed) - } - } - - if err := scanner.Err(); err != nil { - t.Fatalf("error reading test data: %s", err) - } -} - -func TestMalleability(t *testing.T) { - // https://tools.ietf.org/html/rfc8032#section-5.1.7 adds an additional test - // that s be in [0, order). This prevents someone from adding a multiple of - // order to s and obtaining a second valid signature for the same message. - msg := []byte{0x54, 0x65, 0x73, 0x74} - sig := []byte{ - 0x7c, 0x38, 0xe0, 0x26, 0xf2, 0x9e, 0x14, 0xaa, 0xbd, 0x05, 0x9a, - 0x0f, 0x2d, 0xb8, 0xb0, 0xcd, 0x78, 0x30, 0x40, 0x60, 0x9a, 0x8b, - 0xe6, 0x84, 0xdb, 0x12, 0xf8, 0x2a, 0x27, 0x77, 0x4a, 0xb0, 0x67, - 0x65, 0x4b, 0xce, 0x38, 0x32, 0xc2, 0xd7, 0x6f, 0x8f, 0x6f, 0x5d, - 0xaf, 0xc0, 0x8d, 0x93, 0x39, 0xd4, 0xee, 0xf6, 0x76, 0x57, 0x33, - 0x36, 0xa5, 0xc5, 0x1e, 0xb6, 0xf9, 0x46, 0xb3, 0x1d, - } - publicKey := []byte{ - 0x7d, 0x4d, 0x0e, 0x7f, 0x61, 0x53, 0xa6, 0x9b, 0x62, 0x42, 0xb5, - 0x22, 0xab, 0xbe, 0xe6, 0x85, 0xfd, 0xa4, 0x42, 0x0f, 0x88, 0x34, - 0xb1, 0x08, 0xc3, 0xbd, 0xae, 0x36, 0x9e, 0xf5, 0x49, 0xfa, - } - - if Verify(publicKey, msg, sig) { - t.Fatal("non-canonical signature accepted") - } -} - -func BenchmarkKeyGeneration(b *testing.B) { - var zero zeroReader - for i := 0; i < b.N; i++ { - if _, _, err := GenerateKey(zero); err != nil { - b.Fatal(err) - } - } -} - -func BenchmarkSigning(b *testing.B) { - var zero zeroReader - _, priv, err := GenerateKey(zero) - if err != nil { - b.Fatal(err) - } - message := []byte("Hello, world!") - b.ResetTimer() - for i := 0; i < b.N; i++ { - Sign(priv, message) - } -} - -func BenchmarkVerification(b *testing.B) { - var zero zeroReader - pub, priv, err := GenerateKey(zero) - if err != nil { - b.Fatal(err) - } - message := []byte("Hello, world!") - signature := Sign(priv, message) - b.ResetTimer() - for i := 0; i < b.N; i++ { - Verify(pub, message, signature) - } -} diff --git a/vendor/golang.org/x/net/AUTHORS b/vendor/golang.org/x/net/AUTHORS new file mode 100644 index 000000000..15167cd74 --- /dev/null +++ b/vendor/golang.org/x/net/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/net/CONTRIBUTORS b/vendor/golang.org/x/net/CONTRIBUTORS new file mode 100644 index 000000000..1c4577e96 --- /dev/null +++ b/vendor/golang.org/x/net/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/net/bpf/constants.go b/vendor/golang.org/x/net/bpf/constants.go index b89ca3523..12f3ee835 100644 --- a/vendor/golang.org/x/net/bpf/constants.go +++ b/vendor/golang.org/x/net/bpf/constants.go @@ -38,6 +38,7 @@ const ( type JumpTest uint16 // Supported operators for conditional jumps. +// K can be RegX for JumpIfX const ( // K == A JumpEqual JumpTest = iota @@ -134,12 +135,9 @@ const ( opMaskLoadDest = 0x01 opMaskLoadWidth = 0x18 opMaskLoadMode = 0xe0 - // opClsALU - opMaskOperandSrc = 0x08 - opMaskOperator = 0xf0 - // opClsJump - opMaskJumpConst = 0x0f - opMaskJumpCond = 0xf0 + // opClsALU & opClsJump + opMaskOperand = 0x08 + opMaskOperator = 0xf0 ) const ( @@ -192,15 +190,21 @@ const ( opLoadWidth1 ) -// Operator defined by ALUOp* +// Operand for ALU and Jump instructions +type opOperand uint16 +// Supported operand sources. const ( - opALUSrcConstant uint16 = iota << 3 - opALUSrcX + opOperandConstant opOperand = iota << 3 + opOperandX ) +// An jumpOp is a conditional jump condition. +type jumpOp uint16 + +// Supported jump conditions. const ( - opJumpAlways = iota << 4 + opJumpAlways jumpOp = iota << 4 opJumpEqual opJumpGT opJumpGE diff --git a/vendor/golang.org/x/net/bpf/instructions.go b/vendor/golang.org/x/net/bpf/instructions.go index 3b4fd0891..3cffcaa01 100644 --- a/vendor/golang.org/x/net/bpf/instructions.go +++ b/vendor/golang.org/x/net/bpf/instructions.go @@ -89,10 +89,14 @@ func (ri RawInstruction) Disassemble() Instruction { case opClsALU: switch op := ALUOp(ri.Op & opMaskOperator); op { case ALUOpAdd, ALUOpSub, ALUOpMul, ALUOpDiv, ALUOpOr, ALUOpAnd, ALUOpShiftLeft, ALUOpShiftRight, ALUOpMod, ALUOpXor: - if ri.Op&opMaskOperandSrc != 0 { + switch operand := opOperand(ri.Op & opMaskOperand); operand { + case opOperandX: return ALUOpX{Op: op} + case opOperandConstant: + return ALUOpConstant{Op: op, Val: ri.K} + default: + return ri } - return ALUOpConstant{Op: op, Val: ri.K} case aluOpNeg: return NegateA{} default: @@ -100,63 +104,18 @@ func (ri RawInstruction) Disassemble() Instruction { } case opClsJump: - if ri.Op&opMaskJumpConst != opClsJump { - return ri - } - switch ri.Op & opMaskJumpCond { + switch op := jumpOp(ri.Op & opMaskOperator); op { case opJumpAlways: return Jump{Skip: ri.K} - case opJumpEqual: - if ri.Jt == 0 { - return JumpIf{ - Cond: JumpNotEqual, - Val: ri.K, - SkipTrue: ri.Jf, - SkipFalse: 0, - } - } - return JumpIf{ - Cond: JumpEqual, - Val: ri.K, - SkipTrue: ri.Jt, - SkipFalse: ri.Jf, - } - case opJumpGT: - if ri.Jt == 0 { - return JumpIf{ - Cond: JumpLessOrEqual, - Val: ri.K, - SkipTrue: ri.Jf, - SkipFalse: 0, - } - } - return JumpIf{ - Cond: JumpGreaterThan, - Val: ri.K, - SkipTrue: ri.Jt, - SkipFalse: ri.Jf, - } - case opJumpGE: - if ri.Jt == 0 { - return JumpIf{ - Cond: JumpLessThan, - Val: ri.K, - SkipTrue: ri.Jf, - SkipFalse: 0, - } - } - return JumpIf{ - Cond: JumpGreaterOrEqual, - Val: ri.K, - SkipTrue: ri.Jt, - SkipFalse: ri.Jf, - } - case opJumpSet: - return JumpIf{ - Cond: JumpBitsSet, - Val: ri.K, - SkipTrue: ri.Jt, - SkipFalse: ri.Jf, + case opJumpEqual, opJumpGT, opJumpGE, opJumpSet: + cond, skipTrue, skipFalse := jumpOpToTest(op, ri.Jt, ri.Jf) + switch operand := opOperand(ri.Op & opMaskOperand); operand { + case opOperandX: + return JumpIfX{Cond: cond, SkipTrue: skipTrue, SkipFalse: skipFalse} + case opOperandConstant: + return JumpIf{Cond: cond, Val: ri.K, SkipTrue: skipTrue, SkipFalse: skipFalse} + default: + return ri } default: return ri @@ -187,6 +146,41 @@ func (ri RawInstruction) Disassemble() Instruction { } } +func jumpOpToTest(op jumpOp, skipTrue uint8, skipFalse uint8) (JumpTest, uint8, uint8) { + var test JumpTest + + // Decode "fake" jump conditions that don't appear in machine code + // Ensures the Assemble -> Disassemble stage recreates the same instructions + // See https://github.com/golang/go/issues/18470 + if skipTrue == 0 { + switch op { + case opJumpEqual: + test = JumpNotEqual + case opJumpGT: + test = JumpLessOrEqual + case opJumpGE: + test = JumpLessThan + case opJumpSet: + test = JumpBitsNotSet + } + + return test, skipFalse, 0 + } + + switch op { + case opJumpEqual: + test = JumpEqual + case opJumpGT: + test = JumpGreaterThan + case opJumpGE: + test = JumpGreaterOrEqual + case opJumpSet: + test = JumpBitsSet + } + + return test, skipTrue, skipFalse +} + // LoadConstant loads Val into register Dst. type LoadConstant struct { Dst Register @@ -198,7 +192,7 @@ func (a LoadConstant) Assemble() (RawInstruction, error) { return assembleLoad(a.Dst, 4, opAddrModeImmediate, a.Val) } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a LoadConstant) String() string { switch a.Dst { case RegA: @@ -224,7 +218,7 @@ func (a LoadScratch) Assemble() (RawInstruction, error) { return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N)) } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a LoadScratch) String() string { switch a.Dst { case RegA: @@ -248,7 +242,7 @@ func (a LoadAbsolute) Assemble() (RawInstruction, error) { return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off) } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a LoadAbsolute) String() string { switch a.Size { case 1: // byte @@ -277,7 +271,7 @@ func (a LoadIndirect) Assemble() (RawInstruction, error) { return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off) } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a LoadIndirect) String() string { switch a.Size { case 1: // byte @@ -306,7 +300,7 @@ func (a LoadMemShift) Assemble() (RawInstruction, error) { return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off) } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a LoadMemShift) String() string { return fmt.Sprintf("ldx 4*([%d]&0xf)", a.Off) } @@ -325,7 +319,7 @@ func (a LoadExtension) Assemble() (RawInstruction, error) { return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(extOffset+a.Num)) } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a LoadExtension) String() string { switch a.Num { case ExtLen: @@ -392,7 +386,7 @@ func (a StoreScratch) Assemble() (RawInstruction, error) { }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a StoreScratch) String() string { switch a.Src { case RegA: @@ -413,12 +407,12 @@ type ALUOpConstant struct { // Assemble implements the Instruction Assemble method. func (a ALUOpConstant) Assemble() (RawInstruction, error) { return RawInstruction{ - Op: opClsALU | opALUSrcConstant | uint16(a.Op), + Op: opClsALU | uint16(opOperandConstant) | uint16(a.Op), K: a.Val, }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a ALUOpConstant) String() string { switch a.Op { case ALUOpAdd: @@ -454,11 +448,11 @@ type ALUOpX struct { // Assemble implements the Instruction Assemble method. func (a ALUOpX) Assemble() (RawInstruction, error) { return RawInstruction{ - Op: opClsALU | opALUSrcX | uint16(a.Op), + Op: opClsALU | uint16(opOperandX) | uint16(a.Op), }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a ALUOpX) String() string { switch a.Op { case ALUOpAdd: @@ -496,7 +490,7 @@ func (a NegateA) Assemble() (RawInstruction, error) { }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a NegateA) String() string { return fmt.Sprintf("neg") } @@ -509,12 +503,12 @@ type Jump struct { // Assemble implements the Instruction Assemble method. func (a Jump) Assemble() (RawInstruction, error) { return RawInstruction{ - Op: opClsJump | opJumpAlways, + Op: opClsJump | uint16(opJumpAlways), K: a.Skip, }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a Jump) String() string { return fmt.Sprintf("ja %d", a.Skip) } @@ -530,11 +524,39 @@ type JumpIf struct { // Assemble implements the Instruction Assemble method. func (a JumpIf) Assemble() (RawInstruction, error) { + return jumpToRaw(a.Cond, opOperandConstant, a.Val, a.SkipTrue, a.SkipFalse) +} + +// String returns the instruction in assembler notation. +func (a JumpIf) String() string { + return jumpToString(a.Cond, fmt.Sprintf("#%d", a.Val), a.SkipTrue, a.SkipFalse) +} + +// JumpIfX skips the following Skip instructions in the program if A +// X is true. +type JumpIfX struct { + Cond JumpTest + SkipTrue uint8 + SkipFalse uint8 +} + +// Assemble implements the Instruction Assemble method. +func (a JumpIfX) Assemble() (RawInstruction, error) { + return jumpToRaw(a.Cond, opOperandX, 0, a.SkipTrue, a.SkipFalse) +} + +// String returns the instruction in assembler notation. +func (a JumpIfX) String() string { + return jumpToString(a.Cond, "x", a.SkipTrue, a.SkipFalse) +} + +// jumpToRaw assembles a jump instruction into a RawInstruction +func jumpToRaw(test JumpTest, operand opOperand, k uint32, skipTrue, skipFalse uint8) (RawInstruction, error) { var ( - cond uint16 + cond jumpOp flip bool ) - switch a.Cond { + switch test { case JumpEqual: cond = opJumpEqual case JumpNotEqual: @@ -552,63 +574,63 @@ func (a JumpIf) Assemble() (RawInstruction, error) { case JumpBitsNotSet: cond, flip = opJumpSet, true default: - return RawInstruction{}, fmt.Errorf("unknown JumpTest %v", a.Cond) + return RawInstruction{}, fmt.Errorf("unknown JumpTest %v", test) } - jt, jf := a.SkipTrue, a.SkipFalse + jt, jf := skipTrue, skipFalse if flip { jt, jf = jf, jt } return RawInstruction{ - Op: opClsJump | cond, + Op: opClsJump | uint16(cond) | uint16(operand), Jt: jt, Jf: jf, - K: a.Val, + K: k, }, nil } -// String returns the the instruction in assembler notation. -func (a JumpIf) String() string { - switch a.Cond { +// jumpToString converts a jump instruction to assembler notation +func jumpToString(cond JumpTest, operand string, skipTrue, skipFalse uint8) string { + switch cond { // K == A case JumpEqual: - return conditionalJump(a, "jeq", "jneq") + return conditionalJump(operand, skipTrue, skipFalse, "jeq", "jneq") // K != A case JumpNotEqual: - return fmt.Sprintf("jneq #%d,%d", a.Val, a.SkipTrue) + return fmt.Sprintf("jneq %s,%d", operand, skipTrue) // K > A case JumpGreaterThan: - return conditionalJump(a, "jgt", "jle") + return conditionalJump(operand, skipTrue, skipFalse, "jgt", "jle") // K < A case JumpLessThan: - return fmt.Sprintf("jlt #%d,%d", a.Val, a.SkipTrue) + return fmt.Sprintf("jlt %s,%d", operand, skipTrue) // K >= A case JumpGreaterOrEqual: - return conditionalJump(a, "jge", "jlt") + return conditionalJump(operand, skipTrue, skipFalse, "jge", "jlt") // K <= A case JumpLessOrEqual: - return fmt.Sprintf("jle #%d,%d", a.Val, a.SkipTrue) + return fmt.Sprintf("jle %s,%d", operand, skipTrue) // K & A != 0 case JumpBitsSet: - if a.SkipFalse > 0 { - return fmt.Sprintf("jset #%d,%d,%d", a.Val, a.SkipTrue, a.SkipFalse) + if skipFalse > 0 { + return fmt.Sprintf("jset %s,%d,%d", operand, skipTrue, skipFalse) } - return fmt.Sprintf("jset #%d,%d", a.Val, a.SkipTrue) + return fmt.Sprintf("jset %s,%d", operand, skipTrue) // K & A == 0, there is no assembler instruction for JumpBitNotSet, use JumpBitSet and invert skips case JumpBitsNotSet: - return JumpIf{Cond: JumpBitsSet, SkipTrue: a.SkipFalse, SkipFalse: a.SkipTrue, Val: a.Val}.String() + return jumpToString(JumpBitsSet, operand, skipFalse, skipTrue) default: - return fmt.Sprintf("unknown instruction: %#v", a) + return fmt.Sprintf("unknown JumpTest %#v", cond) } } -func conditionalJump(inst JumpIf, positiveJump, negativeJump string) string { - if inst.SkipTrue > 0 { - if inst.SkipFalse > 0 { - return fmt.Sprintf("%s #%d,%d,%d", positiveJump, inst.Val, inst.SkipTrue, inst.SkipFalse) +func conditionalJump(operand string, skipTrue, skipFalse uint8, positiveJump, negativeJump string) string { + if skipTrue > 0 { + if skipFalse > 0 { + return fmt.Sprintf("%s %s,%d,%d", positiveJump, operand, skipTrue, skipFalse) } - return fmt.Sprintf("%s #%d,%d", positiveJump, inst.Val, inst.SkipTrue) + return fmt.Sprintf("%s %s,%d", positiveJump, operand, skipTrue) } - return fmt.Sprintf("%s #%d,%d", negativeJump, inst.Val, inst.SkipFalse) + return fmt.Sprintf("%s %s,%d", negativeJump, operand, skipFalse) } // RetA exits the BPF program, returning the value of register A. @@ -621,7 +643,7 @@ func (a RetA) Assemble() (RawInstruction, error) { }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a RetA) String() string { return fmt.Sprintf("ret a") } @@ -639,7 +661,7 @@ func (a RetConstant) Assemble() (RawInstruction, error) { }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a RetConstant) String() string { return fmt.Sprintf("ret #%d", a.Val) } @@ -654,7 +676,7 @@ func (a TXA) Assemble() (RawInstruction, error) { }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a TXA) String() string { return fmt.Sprintf("txa") } @@ -669,7 +691,7 @@ func (a TAX) Assemble() (RawInstruction, error) { }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a TAX) String() string { return fmt.Sprintf("tax") } diff --git a/vendor/golang.org/x/net/bpf/instructions_test.go b/vendor/golang.org/x/net/bpf/instructions_test.go deleted file mode 100644 index dde474aba..000000000 --- a/vendor/golang.org/x/net/bpf/instructions_test.go +++ /dev/null @@ -1,525 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bpf - -import ( - "fmt" - "io/ioutil" - "reflect" - "strconv" - "strings" - "testing" -) - -// This is a direct translation of the program in -// testdata/all_instructions.txt. -var allInstructions = []Instruction{ - LoadConstant{Dst: RegA, Val: 42}, - LoadConstant{Dst: RegX, Val: 42}, - - LoadScratch{Dst: RegA, N: 3}, - LoadScratch{Dst: RegX, N: 3}, - - LoadAbsolute{Off: 42, Size: 1}, - LoadAbsolute{Off: 42, Size: 2}, - LoadAbsolute{Off: 42, Size: 4}, - - LoadIndirect{Off: 42, Size: 1}, - LoadIndirect{Off: 42, Size: 2}, - LoadIndirect{Off: 42, Size: 4}, - - LoadMemShift{Off: 42}, - - LoadExtension{Num: ExtLen}, - LoadExtension{Num: ExtProto}, - LoadExtension{Num: ExtType}, - LoadExtension{Num: ExtRand}, - - StoreScratch{Src: RegA, N: 3}, - StoreScratch{Src: RegX, N: 3}, - - ALUOpConstant{Op: ALUOpAdd, Val: 42}, - ALUOpConstant{Op: ALUOpSub, Val: 42}, - ALUOpConstant{Op: ALUOpMul, Val: 42}, - ALUOpConstant{Op: ALUOpDiv, Val: 42}, - ALUOpConstant{Op: ALUOpOr, Val: 42}, - ALUOpConstant{Op: ALUOpAnd, Val: 42}, - ALUOpConstant{Op: ALUOpShiftLeft, Val: 42}, - ALUOpConstant{Op: ALUOpShiftRight, Val: 42}, - ALUOpConstant{Op: ALUOpMod, Val: 42}, - ALUOpConstant{Op: ALUOpXor, Val: 42}, - - ALUOpX{Op: ALUOpAdd}, - ALUOpX{Op: ALUOpSub}, - ALUOpX{Op: ALUOpMul}, - ALUOpX{Op: ALUOpDiv}, - ALUOpX{Op: ALUOpOr}, - ALUOpX{Op: ALUOpAnd}, - ALUOpX{Op: ALUOpShiftLeft}, - ALUOpX{Op: ALUOpShiftRight}, - ALUOpX{Op: ALUOpMod}, - ALUOpX{Op: ALUOpXor}, - - NegateA{}, - - Jump{Skip: 10}, - JumpIf{Cond: JumpEqual, Val: 42, SkipTrue: 8, SkipFalse: 9}, - JumpIf{Cond: JumpNotEqual, Val: 42, SkipTrue: 8}, - JumpIf{Cond: JumpLessThan, Val: 42, SkipTrue: 7}, - JumpIf{Cond: JumpLessOrEqual, Val: 42, SkipTrue: 6}, - JumpIf{Cond: JumpGreaterThan, Val: 42, SkipTrue: 4, SkipFalse: 5}, - JumpIf{Cond: JumpGreaterOrEqual, Val: 42, SkipTrue: 3, SkipFalse: 4}, - JumpIf{Cond: JumpBitsSet, Val: 42, SkipTrue: 2, SkipFalse: 3}, - - TAX{}, - TXA{}, - - RetA{}, - RetConstant{Val: 42}, -} -var allInstructionsExpected = "testdata/all_instructions.bpf" - -// Check that we produce the same output as the canonical bpf_asm -// linux kernel tool. -func TestInterop(t *testing.T) { - out, err := Assemble(allInstructions) - if err != nil { - t.Fatalf("assembly of allInstructions program failed: %s", err) - } - t.Logf("Assembled program is %d instructions long", len(out)) - - bs, err := ioutil.ReadFile(allInstructionsExpected) - if err != nil { - t.Fatalf("reading %s: %s", allInstructionsExpected, err) - } - // First statement is the number of statements, last statement is - // empty. We just ignore both and rely on slice length. - stmts := strings.Split(string(bs), ",") - if len(stmts)-2 != len(out) { - t.Fatalf("test program lengths don't match: %s has %d, Go implementation has %d", allInstructionsExpected, len(stmts)-2, len(allInstructions)) - } - - for i, stmt := range stmts[1 : len(stmts)-2] { - nums := strings.Split(stmt, " ") - if len(nums) != 4 { - t.Fatalf("malformed instruction %d in %s: %s", i+1, allInstructionsExpected, stmt) - } - - actual := out[i] - - op, err := strconv.ParseUint(nums[0], 10, 16) - if err != nil { - t.Fatalf("malformed opcode %s in instruction %d of %s", nums[0], i+1, allInstructionsExpected) - } - if actual.Op != uint16(op) { - t.Errorf("opcode mismatch on instruction %d (%#v): got 0x%02x, want 0x%02x", i+1, allInstructions[i], actual.Op, op) - } - - jt, err := strconv.ParseUint(nums[1], 10, 8) - if err != nil { - t.Fatalf("malformed jt offset %s in instruction %d of %s", nums[1], i+1, allInstructionsExpected) - } - if actual.Jt != uint8(jt) { - t.Errorf("jt mismatch on instruction %d (%#v): got %d, want %d", i+1, allInstructions[i], actual.Jt, jt) - } - - jf, err := strconv.ParseUint(nums[2], 10, 8) - if err != nil { - t.Fatalf("malformed jf offset %s in instruction %d of %s", nums[2], i+1, allInstructionsExpected) - } - if actual.Jf != uint8(jf) { - t.Errorf("jf mismatch on instruction %d (%#v): got %d, want %d", i+1, allInstructions[i], actual.Jf, jf) - } - - k, err := strconv.ParseUint(nums[3], 10, 32) - if err != nil { - t.Fatalf("malformed constant %s in instruction %d of %s", nums[3], i+1, allInstructionsExpected) - } - if actual.K != uint32(k) { - t.Errorf("constant mismatch on instruction %d (%#v): got %d, want %d", i+1, allInstructions[i], actual.K, k) - } - } -} - -// Check that assembly and disassembly match each other. -func TestAsmDisasm(t *testing.T) { - prog1, err := Assemble(allInstructions) - if err != nil { - t.Fatalf("assembly of allInstructions program failed: %s", err) - } - t.Logf("Assembled program is %d instructions long", len(prog1)) - - got, allDecoded := Disassemble(prog1) - if !allDecoded { - t.Errorf("Disassemble(Assemble(allInstructions)) produced unrecognized instructions:") - for i, inst := range got { - if r, ok := inst.(RawInstruction); ok { - t.Logf(" insn %d, %#v --> %#v", i+1, allInstructions[i], r) - } - } - } - - if len(allInstructions) != len(got) { - t.Fatalf("disassembly changed program size: %d insns before, %d insns after", len(allInstructions), len(got)) - } - if !reflect.DeepEqual(allInstructions, got) { - t.Errorf("program mutated by disassembly:") - for i := range got { - if !reflect.DeepEqual(allInstructions[i], got[i]) { - t.Logf(" insn %d, s: %#v, p1: %#v, got: %#v", i+1, allInstructions[i], prog1[i], got[i]) - } - } - } -} - -type InvalidInstruction struct{} - -func (a InvalidInstruction) Assemble() (RawInstruction, error) { - return RawInstruction{}, fmt.Errorf("Invalid Instruction") -} - -func (a InvalidInstruction) String() string { - return fmt.Sprintf("unknown instruction: %#v", a) -} - -func TestString(t *testing.T) { - testCases := []struct { - instruction Instruction - assembler string - }{ - { - instruction: LoadConstant{Dst: RegA, Val: 42}, - assembler: "ld #42", - }, - { - instruction: LoadConstant{Dst: RegX, Val: 42}, - assembler: "ldx #42", - }, - { - instruction: LoadConstant{Dst: 0xffff, Val: 42}, - assembler: "unknown instruction: bpf.LoadConstant{Dst:0xffff, Val:0x2a}", - }, - { - instruction: LoadScratch{Dst: RegA, N: 3}, - assembler: "ld M[3]", - }, - { - instruction: LoadScratch{Dst: RegX, N: 3}, - assembler: "ldx M[3]", - }, - { - instruction: LoadScratch{Dst: 0xffff, N: 3}, - assembler: "unknown instruction: bpf.LoadScratch{Dst:0xffff, N:3}", - }, - { - instruction: LoadAbsolute{Off: 42, Size: 1}, - assembler: "ldb [42]", - }, - { - instruction: LoadAbsolute{Off: 42, Size: 2}, - assembler: "ldh [42]", - }, - { - instruction: LoadAbsolute{Off: 42, Size: 4}, - assembler: "ld [42]", - }, - { - instruction: LoadAbsolute{Off: 42, Size: -1}, - assembler: "unknown instruction: bpf.LoadAbsolute{Off:0x2a, Size:-1}", - }, - { - instruction: LoadIndirect{Off: 42, Size: 1}, - assembler: "ldb [x + 42]", - }, - { - instruction: LoadIndirect{Off: 42, Size: 2}, - assembler: "ldh [x + 42]", - }, - { - instruction: LoadIndirect{Off: 42, Size: 4}, - assembler: "ld [x + 42]", - }, - { - instruction: LoadIndirect{Off: 42, Size: -1}, - assembler: "unknown instruction: bpf.LoadIndirect{Off:0x2a, Size:-1}", - }, - { - instruction: LoadMemShift{Off: 42}, - assembler: "ldx 4*([42]&0xf)", - }, - { - instruction: LoadExtension{Num: ExtLen}, - assembler: "ld #len", - }, - { - instruction: LoadExtension{Num: ExtProto}, - assembler: "ld #proto", - }, - { - instruction: LoadExtension{Num: ExtType}, - assembler: "ld #type", - }, - { - instruction: LoadExtension{Num: ExtPayloadOffset}, - assembler: "ld #poff", - }, - { - instruction: LoadExtension{Num: ExtInterfaceIndex}, - assembler: "ld #ifidx", - }, - { - instruction: LoadExtension{Num: ExtNetlinkAttr}, - assembler: "ld #nla", - }, - { - instruction: LoadExtension{Num: ExtNetlinkAttrNested}, - assembler: "ld #nlan", - }, - { - instruction: LoadExtension{Num: ExtMark}, - assembler: "ld #mark", - }, - { - instruction: LoadExtension{Num: ExtQueue}, - assembler: "ld #queue", - }, - { - instruction: LoadExtension{Num: ExtLinkLayerType}, - assembler: "ld #hatype", - }, - { - instruction: LoadExtension{Num: ExtRXHash}, - assembler: "ld #rxhash", - }, - { - instruction: LoadExtension{Num: ExtCPUID}, - assembler: "ld #cpu", - }, - { - instruction: LoadExtension{Num: ExtVLANTag}, - assembler: "ld #vlan_tci", - }, - { - instruction: LoadExtension{Num: ExtVLANTagPresent}, - assembler: "ld #vlan_avail", - }, - { - instruction: LoadExtension{Num: ExtVLANProto}, - assembler: "ld #vlan_tpid", - }, - { - instruction: LoadExtension{Num: ExtRand}, - assembler: "ld #rand", - }, - { - instruction: LoadAbsolute{Off: 0xfffff038, Size: 4}, - assembler: "ld #rand", - }, - { - instruction: LoadExtension{Num: 0xfff}, - assembler: "unknown instruction: bpf.LoadExtension{Num:4095}", - }, - { - instruction: StoreScratch{Src: RegA, N: 3}, - assembler: "st M[3]", - }, - { - instruction: StoreScratch{Src: RegX, N: 3}, - assembler: "stx M[3]", - }, - { - instruction: StoreScratch{Src: 0xffff, N: 3}, - assembler: "unknown instruction: bpf.StoreScratch{Src:0xffff, N:3}", - }, - { - instruction: ALUOpConstant{Op: ALUOpAdd, Val: 42}, - assembler: "add #42", - }, - { - instruction: ALUOpConstant{Op: ALUOpSub, Val: 42}, - assembler: "sub #42", - }, - { - instruction: ALUOpConstant{Op: ALUOpMul, Val: 42}, - assembler: "mul #42", - }, - { - instruction: ALUOpConstant{Op: ALUOpDiv, Val: 42}, - assembler: "div #42", - }, - { - instruction: ALUOpConstant{Op: ALUOpOr, Val: 42}, - assembler: "or #42", - }, - { - instruction: ALUOpConstant{Op: ALUOpAnd, Val: 42}, - assembler: "and #42", - }, - { - instruction: ALUOpConstant{Op: ALUOpShiftLeft, Val: 42}, - assembler: "lsh #42", - }, - { - instruction: ALUOpConstant{Op: ALUOpShiftRight, Val: 42}, - assembler: "rsh #42", - }, - { - instruction: ALUOpConstant{Op: ALUOpMod, Val: 42}, - assembler: "mod #42", - }, - { - instruction: ALUOpConstant{Op: ALUOpXor, Val: 42}, - assembler: "xor #42", - }, - { - instruction: ALUOpConstant{Op: 0xffff, Val: 42}, - assembler: "unknown instruction: bpf.ALUOpConstant{Op:0xffff, Val:0x2a}", - }, - { - instruction: ALUOpX{Op: ALUOpAdd}, - assembler: "add x", - }, - { - instruction: ALUOpX{Op: ALUOpSub}, - assembler: "sub x", - }, - { - instruction: ALUOpX{Op: ALUOpMul}, - assembler: "mul x", - }, - { - instruction: ALUOpX{Op: ALUOpDiv}, - assembler: "div x", - }, - { - instruction: ALUOpX{Op: ALUOpOr}, - assembler: "or x", - }, - { - instruction: ALUOpX{Op: ALUOpAnd}, - assembler: "and x", - }, - { - instruction: ALUOpX{Op: ALUOpShiftLeft}, - assembler: "lsh x", - }, - { - instruction: ALUOpX{Op: ALUOpShiftRight}, - assembler: "rsh x", - }, - { - instruction: ALUOpX{Op: ALUOpMod}, - assembler: "mod x", - }, - { - instruction: ALUOpX{Op: ALUOpXor}, - assembler: "xor x", - }, - { - instruction: ALUOpX{Op: 0xffff}, - assembler: "unknown instruction: bpf.ALUOpX{Op:0xffff}", - }, - { - instruction: NegateA{}, - assembler: "neg", - }, - { - instruction: Jump{Skip: 10}, - assembler: "ja 10", - }, - { - instruction: JumpIf{Cond: JumpEqual, Val: 42, SkipTrue: 8, SkipFalse: 9}, - assembler: "jeq #42,8,9", - }, - { - instruction: JumpIf{Cond: JumpEqual, Val: 42, SkipTrue: 8}, - assembler: "jeq #42,8", - }, - { - instruction: JumpIf{Cond: JumpEqual, Val: 42, SkipFalse: 8}, - assembler: "jneq #42,8", - }, - { - instruction: JumpIf{Cond: JumpNotEqual, Val: 42, SkipTrue: 8}, - assembler: "jneq #42,8", - }, - { - instruction: JumpIf{Cond: JumpLessThan, Val: 42, SkipTrue: 7}, - assembler: "jlt #42,7", - }, - { - instruction: JumpIf{Cond: JumpLessOrEqual, Val: 42, SkipTrue: 6}, - assembler: "jle #42,6", - }, - { - instruction: JumpIf{Cond: JumpGreaterThan, Val: 42, SkipTrue: 4, SkipFalse: 5}, - assembler: "jgt #42,4,5", - }, - { - instruction: JumpIf{Cond: JumpGreaterThan, Val: 42, SkipTrue: 4}, - assembler: "jgt #42,4", - }, - { - instruction: JumpIf{Cond: JumpGreaterOrEqual, Val: 42, SkipTrue: 3, SkipFalse: 4}, - assembler: "jge #42,3,4", - }, - { - instruction: JumpIf{Cond: JumpGreaterOrEqual, Val: 42, SkipTrue: 3}, - assembler: "jge #42,3", - }, - { - instruction: JumpIf{Cond: JumpBitsSet, Val: 42, SkipTrue: 2, SkipFalse: 3}, - assembler: "jset #42,2,3", - }, - { - instruction: JumpIf{Cond: JumpBitsSet, Val: 42, SkipTrue: 2}, - assembler: "jset #42,2", - }, - { - instruction: JumpIf{Cond: JumpBitsNotSet, Val: 42, SkipTrue: 2, SkipFalse: 3}, - assembler: "jset #42,3,2", - }, - { - instruction: JumpIf{Cond: JumpBitsNotSet, Val: 42, SkipTrue: 2}, - assembler: "jset #42,0,2", - }, - { - instruction: JumpIf{Cond: 0xffff, Val: 42, SkipTrue: 1, SkipFalse: 2}, - assembler: "unknown instruction: bpf.JumpIf{Cond:0xffff, Val:0x2a, SkipTrue:0x1, SkipFalse:0x2}", - }, - { - instruction: TAX{}, - assembler: "tax", - }, - { - instruction: TXA{}, - assembler: "txa", - }, - { - instruction: RetA{}, - assembler: "ret a", - }, - { - instruction: RetConstant{Val: 42}, - assembler: "ret #42", - }, - // Invalid instruction - { - instruction: InvalidInstruction{}, - assembler: "unknown instruction: bpf.InvalidInstruction{}", - }, - } - - for _, testCase := range testCases { - if input, ok := testCase.instruction.(fmt.Stringer); ok { - got := input.String() - if got != testCase.assembler { - t.Errorf("String did not return expected assembler notation, expected: %s, got: %s", testCase.assembler, got) - } - } else { - t.Errorf("Instruction %#v is not a fmt.Stringer", testCase.instruction) - } - } -} diff --git a/vendor/golang.org/x/net/bpf/vm.go b/vendor/golang.org/x/net/bpf/vm.go index 4c656f1e1..73f57f1f7 100644 --- a/vendor/golang.org/x/net/bpf/vm.go +++ b/vendor/golang.org/x/net/bpf/vm.go @@ -35,6 +35,13 @@ func NewVM(filter []Instruction) (*VM, error) { if check <= int(ins.SkipFalse) { return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse) } + case JumpIfX: + if check <= int(ins.SkipTrue) { + return nil, fmt.Errorf("cannot jump %d instructions in true case; jumping past program bounds", ins.SkipTrue) + } + if check <= int(ins.SkipFalse) { + return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse) + } // Check for division or modulus by zero case ALUOpConstant: if ins.Val != 0 { @@ -109,6 +116,9 @@ func (v *VM) Run(in []byte) (int, error) { case JumpIf: jump := jumpIf(ins, regA) i += jump + case JumpIfX: + jump := jumpIfX(ins, regA, regX) + i += jump case LoadAbsolute: regA, ok = loadAbsolute(ins, in) case LoadConstant: diff --git a/vendor/golang.org/x/net/bpf/vm_aluop_test.go b/vendor/golang.org/x/net/bpf/vm_aluop_test.go deleted file mode 100644 index 16678244a..000000000 --- a/vendor/golang.org/x/net/bpf/vm_aluop_test.go +++ /dev/null @@ -1,512 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bpf_test - -import ( - "testing" - - "golang.org/x/net/bpf" -) - -func TestVMALUOpAdd(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 1, - }, - bpf.ALUOpConstant{ - Op: bpf.ALUOpAdd, - Val: 3, - }, - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 8, 2, 3, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 3, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMALUOpSub(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 1, - }, - bpf.TAX{}, - bpf.ALUOpX{ - Op: bpf.ALUOpSub, - }, - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 1, 2, 3, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 0, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMALUOpMul(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 1, - }, - bpf.ALUOpConstant{ - Op: bpf.ALUOpMul, - Val: 2, - }, - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 6, 2, 3, 4, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 4, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMALUOpDiv(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 1, - }, - bpf.ALUOpConstant{ - Op: bpf.ALUOpDiv, - Val: 2, - }, - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 20, 2, 3, 4, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 2, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMALUOpDivByZeroALUOpConstant(t *testing.T) { - _, _, err := testVM(t, []bpf.Instruction{ - bpf.ALUOpConstant{ - Op: bpf.ALUOpDiv, - Val: 0, - }, - bpf.RetA{}, - }) - if errStr(err) != "cannot divide by zero using ALUOpConstant" { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestVMALUOpDivByZeroALUOpX(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - // Load byte 0 into X - bpf.LoadAbsolute{ - Off: 8, - Size: 1, - }, - bpf.TAX{}, - // Load byte 1 into A - bpf.LoadAbsolute{ - Off: 9, - Size: 1, - }, - // Attempt to perform 1/0 - bpf.ALUOpX{ - Op: bpf.ALUOpDiv, - }, - // Return 4 bytes if program does not terminate - bpf.LoadConstant{ - Val: 12, - }, - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, 1, 3, 4, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 0, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMALUOpOr(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 2, - }, - bpf.ALUOpConstant{ - Op: bpf.ALUOpOr, - Val: 0x01, - }, - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0x00, 0x10, 0x03, 0x04, - 0x05, 0x06, 0x07, 0x08, - 0x09, 0xff, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 9, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMALUOpAnd(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 2, - }, - bpf.ALUOpConstant{ - Op: bpf.ALUOpAnd, - Val: 0x0019, - }, - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0xaa, 0x09, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 1, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMALUOpShiftLeft(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 1, - }, - bpf.ALUOpConstant{ - Op: bpf.ALUOpShiftLeft, - Val: 0x01, - }, - bpf.JumpIf{ - Cond: bpf.JumpEqual, - Val: 0x02, - SkipTrue: 1, - }, - bpf.RetConstant{ - Val: 0, - }, - bpf.RetConstant{ - Val: 9, - }, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0x01, 0xaa, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 1, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMALUOpShiftRight(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 1, - }, - bpf.ALUOpConstant{ - Op: bpf.ALUOpShiftRight, - Val: 0x01, - }, - bpf.JumpIf{ - Cond: bpf.JumpEqual, - Val: 0x04, - SkipTrue: 1, - }, - bpf.RetConstant{ - Val: 0, - }, - bpf.RetConstant{ - Val: 9, - }, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0x08, 0xff, 0xff, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 1, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMALUOpMod(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 1, - }, - bpf.ALUOpConstant{ - Op: bpf.ALUOpMod, - Val: 20, - }, - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 30, 0, 0, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 2, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMALUOpModByZeroALUOpConstant(t *testing.T) { - _, _, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 1, - }, - bpf.ALUOpConstant{ - Op: bpf.ALUOpMod, - Val: 0, - }, - bpf.RetA{}, - }) - if errStr(err) != "cannot divide by zero using ALUOpConstant" { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestVMALUOpModByZeroALUOpX(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - // Load byte 0 into X - bpf.LoadAbsolute{ - Off: 8, - Size: 1, - }, - bpf.TAX{}, - // Load byte 1 into A - bpf.LoadAbsolute{ - Off: 9, - Size: 1, - }, - // Attempt to perform 1%0 - bpf.ALUOpX{ - Op: bpf.ALUOpMod, - }, - // Return 4 bytes if program does not terminate - bpf.LoadConstant{ - Val: 12, - }, - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, 1, 3, 4, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 0, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMALUOpXor(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 1, - }, - bpf.ALUOpConstant{ - Op: bpf.ALUOpXor, - Val: 0x0a, - }, - bpf.JumpIf{ - Cond: bpf.JumpEqual, - Val: 0x01, - SkipTrue: 1, - }, - bpf.RetConstant{ - Val: 0, - }, - bpf.RetConstant{ - Val: 9, - }, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0x0b, 0x00, 0x00, 0x00, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 1, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMALUOpUnknown(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 1, - }, - bpf.ALUOpConstant{ - Op: bpf.ALUOpAdd, - Val: 1, - }, - // Verify that an unknown operation is a no-op - bpf.ALUOpConstant{ - Op: 100, - }, - bpf.JumpIf{ - Cond: bpf.JumpEqual, - Val: 0x02, - SkipTrue: 1, - }, - bpf.RetConstant{ - Val: 0, - }, - bpf.RetConstant{ - Val: 9, - }, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 1, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 1, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} diff --git a/vendor/golang.org/x/net/bpf/vm_bpf_test.go b/vendor/golang.org/x/net/bpf/vm_bpf_test.go deleted file mode 100644 index 77fa8fe4a..000000000 --- a/vendor/golang.org/x/net/bpf/vm_bpf_test.go +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bpf_test - -import ( - "net" - "runtime" - "testing" - "time" - - "golang.org/x/net/bpf" - "golang.org/x/net/ipv4" -) - -// A virtualMachine is a BPF virtual machine which can process an -// input packet against a BPF program and render a verdict. -type virtualMachine interface { - Run(in []byte) (int, error) -} - -// canUseOSVM indicates if the OS BPF VM is available on this platform. -func canUseOSVM() bool { - // OS BPF VM can only be used on platforms where x/net/ipv4 supports - // attaching a BPF program to a socket. - switch runtime.GOOS { - case "linux": - return true - } - - return false -} - -// All BPF tests against both the Go VM and OS VM are assumed to -// be used with a UDP socket. As a result, the entire contents -// of a UDP datagram is sent through the BPF program, but only -// the body after the UDP header will ever be returned in output. - -// testVM sets up a Go BPF VM, and if available, a native OS BPF VM -// for integration testing. -func testVM(t *testing.T, filter []bpf.Instruction) (virtualMachine, func(), error) { - goVM, err := bpf.NewVM(filter) - if err != nil { - // Some tests expect an error, so this error must be returned - // instead of fatally exiting the test - return nil, nil, err - } - - mvm := &multiVirtualMachine{ - goVM: goVM, - - t: t, - } - - // If available, add the OS VM for tests which verify that both the Go - // VM and OS VM have exactly the same output for the same input program - // and packet. - done := func() {} - if canUseOSVM() { - osVM, osVMDone := testOSVM(t, filter) - done = func() { osVMDone() } - mvm.osVM = osVM - } - - return mvm, done, nil -} - -// udpHeaderLen is the length of a UDP header. -const udpHeaderLen = 8 - -// A multiVirtualMachine is a virtualMachine which can call out to both the Go VM -// and the native OS VM, if the OS VM is available. -type multiVirtualMachine struct { - goVM virtualMachine - osVM virtualMachine - - t *testing.T -} - -func (mvm *multiVirtualMachine) Run(in []byte) (int, error) { - if len(in) < udpHeaderLen { - mvm.t.Fatalf("input must be at least length of UDP header (%d), got: %d", - udpHeaderLen, len(in)) - } - - // All tests have a UDP header as part of input, because the OS VM - // packets always will. For the Go VM, this output is trimmed before - // being sent back to tests. - goOut, goErr := mvm.goVM.Run(in) - if goOut >= udpHeaderLen { - goOut -= udpHeaderLen - } - - // If Go output is larger than the size of the packet, packet filtering - // interop tests must trim the output bytes to the length of the packet. - // The BPF VM should not do this on its own, as other uses of it do - // not trim the output byte count. - trim := len(in) - udpHeaderLen - if goOut > trim { - goOut = trim - } - - // When the OS VM is not available, process using the Go VM alone - if mvm.osVM == nil { - return goOut, goErr - } - - // The OS VM will apply its own UDP header, so remove the pseudo header - // that the Go VM needs. - osOut, err := mvm.osVM.Run(in[udpHeaderLen:]) - if err != nil { - mvm.t.Fatalf("error while running OS VM: %v", err) - } - - // Verify both VMs return same number of bytes - var mismatch bool - if goOut != osOut { - mismatch = true - mvm.t.Logf("output byte count does not match:\n- go: %v\n- os: %v", goOut, osOut) - } - - if mismatch { - mvm.t.Fatal("Go BPF and OS BPF packet outputs do not match") - } - - return goOut, goErr -} - -// An osVirtualMachine is a virtualMachine which uses the OS's BPF VM for -// processing BPF programs. -type osVirtualMachine struct { - l net.PacketConn - s net.Conn -} - -// testOSVM creates a virtualMachine which uses the OS's BPF VM by injecting -// packets into a UDP listener with a BPF program attached to it. -func testOSVM(t *testing.T, filter []bpf.Instruction) (virtualMachine, func()) { - l, err := net.ListenPacket("udp4", "127.0.0.1:0") - if err != nil { - t.Fatalf("failed to open OS VM UDP listener: %v", err) - } - - prog, err := bpf.Assemble(filter) - if err != nil { - t.Fatalf("failed to compile BPF program: %v", err) - } - - p := ipv4.NewPacketConn(l) - if err = p.SetBPF(prog); err != nil { - t.Fatalf("failed to attach BPF program to listener: %v", err) - } - - s, err := net.Dial("udp4", l.LocalAddr().String()) - if err != nil { - t.Fatalf("failed to dial connection to listener: %v", err) - } - - done := func() { - _ = s.Close() - _ = l.Close() - } - - return &osVirtualMachine{ - l: l, - s: s, - }, done -} - -// Run sends the input bytes into the OS's BPF VM and returns its verdict. -func (vm *osVirtualMachine) Run(in []byte) (int, error) { - go func() { - _, _ = vm.s.Write(in) - }() - - vm.l.SetDeadline(time.Now().Add(50 * time.Millisecond)) - - var b [512]byte - n, _, err := vm.l.ReadFrom(b[:]) - if err != nil { - // A timeout indicates that BPF filtered out the packet, and thus, - // no input should be returned. - if nerr, ok := err.(net.Error); ok && nerr.Timeout() { - return n, nil - } - - return n, err - } - - return n, nil -} diff --git a/vendor/golang.org/x/net/bpf/vm_extension_test.go b/vendor/golang.org/x/net/bpf/vm_extension_test.go deleted file mode 100644 index 7a48c82f3..000000000 --- a/vendor/golang.org/x/net/bpf/vm_extension_test.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bpf_test - -import ( - "testing" - - "golang.org/x/net/bpf" -) - -func TestVMLoadExtensionNotImplemented(t *testing.T) { - _, _, err := testVM(t, []bpf.Instruction{ - bpf.LoadExtension{ - Num: 100, - }, - bpf.RetA{}, - }) - if errStr(err) != "extension 100 not implemented" { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestVMLoadExtensionExtLen(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadExtension{ - Num: bpf.ExtLen, - }, - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, 1, 2, 3, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 4, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} diff --git a/vendor/golang.org/x/net/bpf/vm_instructions.go b/vendor/golang.org/x/net/bpf/vm_instructions.go index 516f9462b..f0d2e55bd 100644 --- a/vendor/golang.org/x/net/bpf/vm_instructions.go +++ b/vendor/golang.org/x/net/bpf/vm_instructions.go @@ -55,34 +55,41 @@ func aluOpCommon(op ALUOp, regA uint32, value uint32) uint32 { } } -func jumpIf(ins JumpIf, value uint32) int { +func jumpIf(ins JumpIf, regA uint32) int { + return jumpIfCommon(ins.Cond, ins.SkipTrue, ins.SkipFalse, regA, ins.Val) +} + +func jumpIfX(ins JumpIfX, regA uint32, regX uint32) int { + return jumpIfCommon(ins.Cond, ins.SkipTrue, ins.SkipFalse, regA, regX) +} + +func jumpIfCommon(cond JumpTest, skipTrue, skipFalse uint8, regA uint32, value uint32) int { var ok bool - inV := uint32(ins.Val) - switch ins.Cond { + switch cond { case JumpEqual: - ok = value == inV + ok = regA == value case JumpNotEqual: - ok = value != inV + ok = regA != value case JumpGreaterThan: - ok = value > inV + ok = regA > value case JumpLessThan: - ok = value < inV + ok = regA < value case JumpGreaterOrEqual: - ok = value >= inV + ok = regA >= value case JumpLessOrEqual: - ok = value <= inV + ok = regA <= value case JumpBitsSet: - ok = (value & inV) != 0 + ok = (regA & value) != 0 case JumpBitsNotSet: - ok = (value & inV) == 0 + ok = (regA & value) == 0 } if ok { - return int(ins.SkipTrue) + return int(skipTrue) } - return int(ins.SkipFalse) + return int(skipFalse) } func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) { diff --git a/vendor/golang.org/x/net/bpf/vm_jump_test.go b/vendor/golang.org/x/net/bpf/vm_jump_test.go deleted file mode 100644 index e0a3a988b..000000000 --- a/vendor/golang.org/x/net/bpf/vm_jump_test.go +++ /dev/null @@ -1,380 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bpf_test - -import ( - "testing" - - "golang.org/x/net/bpf" -) - -func TestVMJumpOne(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 1, - }, - bpf.Jump{ - Skip: 1, - }, - bpf.RetConstant{ - Val: 0, - }, - bpf.RetConstant{ - Val: 9, - }, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 1, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 1, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMJumpOutOfProgram(t *testing.T) { - _, _, err := testVM(t, []bpf.Instruction{ - bpf.Jump{ - Skip: 1, - }, - bpf.RetA{}, - }) - if errStr(err) != "cannot jump 1 instructions; jumping past program bounds" { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestVMJumpIfTrueOutOfProgram(t *testing.T) { - _, _, err := testVM(t, []bpf.Instruction{ - bpf.JumpIf{ - Cond: bpf.JumpEqual, - SkipTrue: 2, - }, - bpf.RetA{}, - }) - if errStr(err) != "cannot jump 2 instructions in true case; jumping past program bounds" { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestVMJumpIfFalseOutOfProgram(t *testing.T) { - _, _, err := testVM(t, []bpf.Instruction{ - bpf.JumpIf{ - Cond: bpf.JumpEqual, - SkipFalse: 3, - }, - bpf.RetA{}, - }) - if errStr(err) != "cannot jump 3 instructions in false case; jumping past program bounds" { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestVMJumpIfEqual(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 1, - }, - bpf.JumpIf{ - Cond: bpf.JumpEqual, - Val: 1, - SkipTrue: 1, - }, - bpf.RetConstant{ - Val: 0, - }, - bpf.RetConstant{ - Val: 9, - }, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 1, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 1, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMJumpIfNotEqual(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 1, - }, - bpf.JumpIf{ - Cond: bpf.JumpNotEqual, - Val: 1, - SkipFalse: 1, - }, - bpf.RetConstant{ - Val: 0, - }, - bpf.RetConstant{ - Val: 9, - }, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 1, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 1, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMJumpIfGreaterThan(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 4, - }, - bpf.JumpIf{ - Cond: bpf.JumpGreaterThan, - Val: 0x00010202, - SkipTrue: 1, - }, - bpf.RetConstant{ - Val: 0, - }, - bpf.RetConstant{ - Val: 12, - }, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, 1, 2, 3, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 4, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMJumpIfLessThan(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 4, - }, - bpf.JumpIf{ - Cond: bpf.JumpLessThan, - Val: 0xff010203, - SkipTrue: 1, - }, - bpf.RetConstant{ - Val: 0, - }, - bpf.RetConstant{ - Val: 12, - }, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, 1, 2, 3, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 4, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMJumpIfGreaterOrEqual(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 4, - }, - bpf.JumpIf{ - Cond: bpf.JumpGreaterOrEqual, - Val: 0x00010203, - SkipTrue: 1, - }, - bpf.RetConstant{ - Val: 0, - }, - bpf.RetConstant{ - Val: 12, - }, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, 1, 2, 3, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 4, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMJumpIfLessOrEqual(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 4, - }, - bpf.JumpIf{ - Cond: bpf.JumpLessOrEqual, - Val: 0xff010203, - SkipTrue: 1, - }, - bpf.RetConstant{ - Val: 0, - }, - bpf.RetConstant{ - Val: 12, - }, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, 1, 2, 3, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 4, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMJumpIfBitsSet(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 2, - }, - bpf.JumpIf{ - Cond: bpf.JumpBitsSet, - Val: 0x1122, - SkipTrue: 1, - }, - bpf.RetConstant{ - Val: 0, - }, - bpf.RetConstant{ - Val: 10, - }, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0x01, 0x02, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 2, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMJumpIfBitsNotSet(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 2, - }, - bpf.JumpIf{ - Cond: bpf.JumpBitsNotSet, - Val: 0x1221, - SkipTrue: 1, - }, - bpf.RetConstant{ - Val: 0, - }, - bpf.RetConstant{ - Val: 10, - }, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0x01, 0x02, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 2, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} diff --git a/vendor/golang.org/x/net/bpf/vm_load_test.go b/vendor/golang.org/x/net/bpf/vm_load_test.go deleted file mode 100644 index 04578b66b..000000000 --- a/vendor/golang.org/x/net/bpf/vm_load_test.go +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bpf_test - -import ( - "net" - "testing" - - "golang.org/x/net/bpf" - "golang.org/x/net/ipv4" -) - -func TestVMLoadAbsoluteOffsetOutOfBounds(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 100, - Size: 2, - }, - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, 1, 2, 3, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 0, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMLoadAbsoluteOffsetPlusSizeOutOfBounds(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 2, - }, - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 0, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMLoadAbsoluteBadInstructionSize(t *testing.T) { - _, _, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Size: 5, - }, - bpf.RetA{}, - }) - if errStr(err) != "assembling instruction 1: invalid load byte length 0" { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestVMLoadConstantOK(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadConstant{ - Dst: bpf.RegX, - Val: 9, - }, - bpf.TXA{}, - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 1, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMLoadIndirectOutOfBounds(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadIndirect{ - Off: 100, - Size: 1, - }, - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 0, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMLoadMemShiftOutOfBounds(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadMemShift{ - Off: 100, - }, - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 0, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -const ( - dhcp4Port = 53 -) - -func TestVMLoadMemShiftLoadIndirectNoResult(t *testing.T) { - vm, in, done := testDHCPv4(t) - defer done() - - // Append mostly empty UDP header with incorrect DHCPv4 port - in = append(in, []byte{ - 0, 0, - 0, dhcp4Port + 1, - 0, 0, - 0, 0, - }...) - - out, err := vm.Run(in) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 0, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMLoadMemShiftLoadIndirectOK(t *testing.T) { - vm, in, done := testDHCPv4(t) - defer done() - - // Append mostly empty UDP header with correct DHCPv4 port - in = append(in, []byte{ - 0, 0, - 0, dhcp4Port, - 0, 0, - 0, 0, - }...) - - out, err := vm.Run(in) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := len(in)-8, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func testDHCPv4(t *testing.T) (virtualMachine, []byte, func()) { - // DHCPv4 test data courtesy of David Anderson: - // https://github.com/google/netboot/blob/master/dhcp4/conn_linux.go#L59-L70 - vm, done, err := testVM(t, []bpf.Instruction{ - // Load IPv4 packet length - bpf.LoadMemShift{Off: 8}, - // Get UDP dport - bpf.LoadIndirect{Off: 8 + 2, Size: 2}, - // Correct dport? - bpf.JumpIf{Cond: bpf.JumpEqual, Val: dhcp4Port, SkipFalse: 1}, - // Accept - bpf.RetConstant{Val: 1500}, - // Ignore - bpf.RetConstant{Val: 0}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - - // Minimal requirements to make a valid IPv4 header - h := &ipv4.Header{ - Len: ipv4.HeaderLen, - Src: net.IPv4(192, 168, 1, 1), - Dst: net.IPv4(192, 168, 1, 2), - } - hb, err := h.Marshal() - if err != nil { - t.Fatalf("failed to marshal IPv4 header: %v", err) - } - - hb = append([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - }, hb...) - - return vm, hb, done -} diff --git a/vendor/golang.org/x/net/bpf/vm_ret_test.go b/vendor/golang.org/x/net/bpf/vm_ret_test.go deleted file mode 100644 index 2d86eae3e..000000000 --- a/vendor/golang.org/x/net/bpf/vm_ret_test.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bpf_test - -import ( - "testing" - - "golang.org/x/net/bpf" -) - -func TestVMRetA(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 1, - }, - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 9, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 1, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMRetALargerThanInput(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadAbsolute{ - Off: 8, - Size: 2, - }, - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, 255, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 2, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMRetConstant(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.RetConstant{ - Val: 9, - }, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, 1, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 1, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMRetConstantLargerThanInput(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.RetConstant{ - Val: 16, - }, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, 1, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 2, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} diff --git a/vendor/golang.org/x/net/bpf/vm_scratch_test.go b/vendor/golang.org/x/net/bpf/vm_scratch_test.go deleted file mode 100644 index e600e3c28..000000000 --- a/vendor/golang.org/x/net/bpf/vm_scratch_test.go +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bpf_test - -import ( - "testing" - - "golang.org/x/net/bpf" -) - -func TestVMStoreScratchInvalidScratchRegisterTooSmall(t *testing.T) { - _, _, err := testVM(t, []bpf.Instruction{ - bpf.StoreScratch{ - Src: bpf.RegA, - N: -1, - }, - bpf.RetA{}, - }) - if errStr(err) != "assembling instruction 1: invalid scratch slot -1" { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestVMStoreScratchInvalidScratchRegisterTooLarge(t *testing.T) { - _, _, err := testVM(t, []bpf.Instruction{ - bpf.StoreScratch{ - Src: bpf.RegA, - N: 16, - }, - bpf.RetA{}, - }) - if errStr(err) != "assembling instruction 1: invalid scratch slot 16" { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestVMStoreScratchUnknownSourceRegister(t *testing.T) { - _, _, err := testVM(t, []bpf.Instruction{ - bpf.StoreScratch{ - Src: 100, - N: 0, - }, - bpf.RetA{}, - }) - if errStr(err) != "assembling instruction 1: invalid source register 100" { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestVMLoadScratchInvalidScratchRegisterTooSmall(t *testing.T) { - _, _, err := testVM(t, []bpf.Instruction{ - bpf.LoadScratch{ - Dst: bpf.RegX, - N: -1, - }, - bpf.RetA{}, - }) - if errStr(err) != "assembling instruction 1: invalid scratch slot -1" { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestVMLoadScratchInvalidScratchRegisterTooLarge(t *testing.T) { - _, _, err := testVM(t, []bpf.Instruction{ - bpf.LoadScratch{ - Dst: bpf.RegX, - N: 16, - }, - bpf.RetA{}, - }) - if errStr(err) != "assembling instruction 1: invalid scratch slot 16" { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestVMLoadScratchUnknownDestinationRegister(t *testing.T) { - _, _, err := testVM(t, []bpf.Instruction{ - bpf.LoadScratch{ - Dst: 100, - N: 0, - }, - bpf.RetA{}, - }) - if errStr(err) != "assembling instruction 1: invalid target register 100" { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestVMStoreScratchLoadScratchOneValue(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - // Load byte 255 - bpf.LoadAbsolute{ - Off: 8, - Size: 1, - }, - // Copy to X and store in scratch[0] - bpf.TAX{}, - bpf.StoreScratch{ - Src: bpf.RegX, - N: 0, - }, - // Load byte 1 - bpf.LoadAbsolute{ - Off: 9, - Size: 1, - }, - // Overwrite 1 with 255 from scratch[0] - bpf.LoadScratch{ - Dst: bpf.RegA, - N: 0, - }, - // Return 255 - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 255, 1, 2, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 3, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} - -func TestVMStoreScratchLoadScratchMultipleValues(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - // Load byte 10 - bpf.LoadAbsolute{ - Off: 8, - Size: 1, - }, - // Store in scratch[0] - bpf.StoreScratch{ - Src: bpf.RegA, - N: 0, - }, - // Load byte 20 - bpf.LoadAbsolute{ - Off: 9, - Size: 1, - }, - // Store in scratch[1] - bpf.StoreScratch{ - Src: bpf.RegA, - N: 1, - }, - // Load byte 30 - bpf.LoadAbsolute{ - Off: 10, - Size: 1, - }, - // Store in scratch[2] - bpf.StoreScratch{ - Src: bpf.RegA, - N: 2, - }, - // Load byte 1 - bpf.LoadAbsolute{ - Off: 11, - Size: 1, - }, - // Store in scratch[3] - bpf.StoreScratch{ - Src: bpf.RegA, - N: 3, - }, - // Load in byte 10 to X - bpf.LoadScratch{ - Dst: bpf.RegX, - N: 0, - }, - // Copy X -> A - bpf.TXA{}, - // Verify value is 10 - bpf.JumpIf{ - Cond: bpf.JumpEqual, - Val: 10, - SkipTrue: 1, - }, - // Fail test if incorrect - bpf.RetConstant{ - Val: 0, - }, - // Load in byte 20 to A - bpf.LoadScratch{ - Dst: bpf.RegA, - N: 1, - }, - // Verify value is 20 - bpf.JumpIf{ - Cond: bpf.JumpEqual, - Val: 20, - SkipTrue: 1, - }, - // Fail test if incorrect - bpf.RetConstant{ - Val: 0, - }, - // Load in byte 30 to A - bpf.LoadScratch{ - Dst: bpf.RegA, - N: 2, - }, - // Verify value is 30 - bpf.JumpIf{ - Cond: bpf.JumpEqual, - Val: 30, - SkipTrue: 1, - }, - // Fail test if incorrect - bpf.RetConstant{ - Val: 0, - }, - // Return first two bytes on success - bpf.RetConstant{ - Val: 10, - }, - }) - if err != nil { - t.Fatalf("failed to load BPF program: %v", err) - } - defer done() - - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 10, 20, 30, 1, - }) - if err != nil { - t.Fatalf("unexpected error while running program: %v", err) - } - if want, got := 2, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", - want, got) - } -} diff --git a/vendor/golang.org/x/net/bpf/vm_test.go b/vendor/golang.org/x/net/bpf/vm_test.go deleted file mode 100644 index 6bd4dd5c3..000000000 --- a/vendor/golang.org/x/net/bpf/vm_test.go +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bpf_test - -import ( - "fmt" - "testing" - - "golang.org/x/net/bpf" -) - -var _ bpf.Instruction = unknown{} - -type unknown struct{} - -func (unknown) Assemble() (bpf.RawInstruction, error) { - return bpf.RawInstruction{}, nil -} - -func TestVMUnknownInstruction(t *testing.T) { - vm, done, err := testVM(t, []bpf.Instruction{ - bpf.LoadConstant{ - Dst: bpf.RegA, - Val: 100, - }, - // Should terminate the program with an error immediately - unknown{}, - bpf.RetA{}, - }) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - defer done() - - _, err = vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, - }) - if errStr(err) != "unknown Instruction at index 1: bpf_test.unknown" { - t.Fatalf("unexpected error while running program: %v", err) - } -} - -func TestVMNoReturnInstruction(t *testing.T) { - _, _, err := testVM(t, []bpf.Instruction{ - bpf.LoadConstant{ - Dst: bpf.RegA, - Val: 1, - }, - }) - if errStr(err) != "BPF program must end with RetA or RetConstant" { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestVMNoInputInstructions(t *testing.T) { - _, _, err := testVM(t, []bpf.Instruction{}) - if errStr(err) != "one or more Instructions must be specified" { - t.Fatalf("unexpected error: %v", err) - } -} - -// ExampleNewVM demonstrates usage of a VM, using an Ethernet frame -// as input and checking its EtherType to determine if it should be accepted. -func ExampleNewVM() { - // Offset | Length | Comment - // ------------------------- - // 00 | 06 | Ethernet destination MAC address - // 06 | 06 | Ethernet source MAC address - // 12 | 02 | Ethernet EtherType - const ( - etOff = 12 - etLen = 2 - - etARP = 0x0806 - ) - - // Set up a VM to filter traffic based on if its EtherType - // matches the ARP EtherType. - vm, err := bpf.NewVM([]bpf.Instruction{ - // Load EtherType value from Ethernet header - bpf.LoadAbsolute{ - Off: etOff, - Size: etLen, - }, - // If EtherType is equal to the ARP EtherType, jump to allow - // packet to be accepted - bpf.JumpIf{ - Cond: bpf.JumpEqual, - Val: etARP, - SkipTrue: 1, - }, - // EtherType does not match the ARP EtherType - bpf.RetConstant{ - Val: 0, - }, - // EtherType matches the ARP EtherType, accept up to 1500 - // bytes of packet - bpf.RetConstant{ - Val: 1500, - }, - }) - if err != nil { - panic(fmt.Sprintf("failed to load BPF program: %v", err)) - } - - // Create an Ethernet frame with the ARP EtherType for testing - frame := []byte{ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, - 0x08, 0x06, - // Payload omitted for brevity - } - - // Run our VM's BPF program using the Ethernet frame as input - out, err := vm.Run(frame) - if err != nil { - panic(fmt.Sprintf("failed to accept Ethernet frame: %v", err)) - } - - // BPF VM can return a byte count greater than the number of input - // bytes, so trim the output to match the input byte length - if out > len(frame) { - out = len(frame) - } - - fmt.Printf("out: %d bytes", out) - - // Output: - // out: 14 bytes -} - -// errStr returns the string representation of an error, or -// "" if it is nil. -func errStr(err error) string { - if err == nil { - return "" - } - - return err.Error() -} diff --git a/vendor/golang.org/x/net/context/context_test.go b/vendor/golang.org/x/net/context/context_test.go deleted file mode 100644 index 62844131b..000000000 --- a/vendor/golang.org/x/net/context/context_test.go +++ /dev/null @@ -1,583 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !go1.7 - -package context - -import ( - "fmt" - "math/rand" - "runtime" - "strings" - "sync" - "testing" - "time" -) - -// otherContext is a Context that's not one of the types defined in context.go. -// This lets us test code paths that differ based on the underlying type of the -// Context. -type otherContext struct { - Context -} - -func TestBackground(t *testing.T) { - c := Background() - if c == nil { - t.Fatalf("Background returned nil") - } - select { - case x := <-c.Done(): - t.Errorf("<-c.Done() == %v want nothing (it should block)", x) - default: - } - if got, want := fmt.Sprint(c), "context.Background"; got != want { - t.Errorf("Background().String() = %q want %q", got, want) - } -} - -func TestTODO(t *testing.T) { - c := TODO() - if c == nil { - t.Fatalf("TODO returned nil") - } - select { - case x := <-c.Done(): - t.Errorf("<-c.Done() == %v want nothing (it should block)", x) - default: - } - if got, want := fmt.Sprint(c), "context.TODO"; got != want { - t.Errorf("TODO().String() = %q want %q", got, want) - } -} - -func TestWithCancel(t *testing.T) { - c1, cancel := WithCancel(Background()) - - if got, want := fmt.Sprint(c1), "context.Background.WithCancel"; got != want { - t.Errorf("c1.String() = %q want %q", got, want) - } - - o := otherContext{c1} - c2, _ := WithCancel(o) - contexts := []Context{c1, o, c2} - - for i, c := range contexts { - if d := c.Done(); d == nil { - t.Errorf("c[%d].Done() == %v want non-nil", i, d) - } - if e := c.Err(); e != nil { - t.Errorf("c[%d].Err() == %v want nil", i, e) - } - - select { - case x := <-c.Done(): - t.Errorf("<-c.Done() == %v want nothing (it should block)", x) - default: - } - } - - cancel() - time.Sleep(100 * time.Millisecond) // let cancelation propagate - - for i, c := range contexts { - select { - case <-c.Done(): - default: - t.Errorf("<-c[%d].Done() blocked, but shouldn't have", i) - } - if e := c.Err(); e != Canceled { - t.Errorf("c[%d].Err() == %v want %v", i, e, Canceled) - } - } -} - -func TestParentFinishesChild(t *testing.T) { - // Context tree: - // parent -> cancelChild - // parent -> valueChild -> timerChild - parent, cancel := WithCancel(Background()) - cancelChild, stop := WithCancel(parent) - defer stop() - valueChild := WithValue(parent, "key", "value") - timerChild, stop := WithTimeout(valueChild, 10000*time.Hour) - defer stop() - - select { - case x := <-parent.Done(): - t.Errorf("<-parent.Done() == %v want nothing (it should block)", x) - case x := <-cancelChild.Done(): - t.Errorf("<-cancelChild.Done() == %v want nothing (it should block)", x) - case x := <-timerChild.Done(): - t.Errorf("<-timerChild.Done() == %v want nothing (it should block)", x) - case x := <-valueChild.Done(): - t.Errorf("<-valueChild.Done() == %v want nothing (it should block)", x) - default: - } - - // The parent's children should contain the two cancelable children. - pc := parent.(*cancelCtx) - cc := cancelChild.(*cancelCtx) - tc := timerChild.(*timerCtx) - pc.mu.Lock() - if len(pc.children) != 2 || !pc.children[cc] || !pc.children[tc] { - t.Errorf("bad linkage: pc.children = %v, want %v and %v", - pc.children, cc, tc) - } - pc.mu.Unlock() - - if p, ok := parentCancelCtx(cc.Context); !ok || p != pc { - t.Errorf("bad linkage: parentCancelCtx(cancelChild.Context) = %v, %v want %v, true", p, ok, pc) - } - if p, ok := parentCancelCtx(tc.Context); !ok || p != pc { - t.Errorf("bad linkage: parentCancelCtx(timerChild.Context) = %v, %v want %v, true", p, ok, pc) - } - - cancel() - - pc.mu.Lock() - if len(pc.children) != 0 { - t.Errorf("pc.cancel didn't clear pc.children = %v", pc.children) - } - pc.mu.Unlock() - - // parent and children should all be finished. - check := func(ctx Context, name string) { - select { - case <-ctx.Done(): - default: - t.Errorf("<-%s.Done() blocked, but shouldn't have", name) - } - if e := ctx.Err(); e != Canceled { - t.Errorf("%s.Err() == %v want %v", name, e, Canceled) - } - } - check(parent, "parent") - check(cancelChild, "cancelChild") - check(valueChild, "valueChild") - check(timerChild, "timerChild") - - // WithCancel should return a canceled context on a canceled parent. - precanceledChild := WithValue(parent, "key", "value") - select { - case <-precanceledChild.Done(): - default: - t.Errorf("<-precanceledChild.Done() blocked, but shouldn't have") - } - if e := precanceledChild.Err(); e != Canceled { - t.Errorf("precanceledChild.Err() == %v want %v", e, Canceled) - } -} - -func TestChildFinishesFirst(t *testing.T) { - cancelable, stop := WithCancel(Background()) - defer stop() - for _, parent := range []Context{Background(), cancelable} { - child, cancel := WithCancel(parent) - - select { - case x := <-parent.Done(): - t.Errorf("<-parent.Done() == %v want nothing (it should block)", x) - case x := <-child.Done(): - t.Errorf("<-child.Done() == %v want nothing (it should block)", x) - default: - } - - cc := child.(*cancelCtx) - pc, pcok := parent.(*cancelCtx) // pcok == false when parent == Background() - if p, ok := parentCancelCtx(cc.Context); ok != pcok || (ok && pc != p) { - t.Errorf("bad linkage: parentCancelCtx(cc.Context) = %v, %v want %v, %v", p, ok, pc, pcok) - } - - if pcok { - pc.mu.Lock() - if len(pc.children) != 1 || !pc.children[cc] { - t.Errorf("bad linkage: pc.children = %v, cc = %v", pc.children, cc) - } - pc.mu.Unlock() - } - - cancel() - - if pcok { - pc.mu.Lock() - if len(pc.children) != 0 { - t.Errorf("child's cancel didn't remove self from pc.children = %v", pc.children) - } - pc.mu.Unlock() - } - - // child should be finished. - select { - case <-child.Done(): - default: - t.Errorf("<-child.Done() blocked, but shouldn't have") - } - if e := child.Err(); e != Canceled { - t.Errorf("child.Err() == %v want %v", e, Canceled) - } - - // parent should not be finished. - select { - case x := <-parent.Done(): - t.Errorf("<-parent.Done() == %v want nothing (it should block)", x) - default: - } - if e := parent.Err(); e != nil { - t.Errorf("parent.Err() == %v want nil", e) - } - } -} - -func testDeadline(c Context, wait time.Duration, t *testing.T) { - select { - case <-time.After(wait): - t.Fatalf("context should have timed out") - case <-c.Done(): - } - if e := c.Err(); e != DeadlineExceeded { - t.Errorf("c.Err() == %v want %v", e, DeadlineExceeded) - } -} - -func TestDeadline(t *testing.T) { - t.Parallel() - const timeUnit = 500 * time.Millisecond - c, _ := WithDeadline(Background(), time.Now().Add(1*timeUnit)) - if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) { - t.Errorf("c.String() = %q want prefix %q", got, prefix) - } - testDeadline(c, 2*timeUnit, t) - - c, _ = WithDeadline(Background(), time.Now().Add(1*timeUnit)) - o := otherContext{c} - testDeadline(o, 2*timeUnit, t) - - c, _ = WithDeadline(Background(), time.Now().Add(1*timeUnit)) - o = otherContext{c} - c, _ = WithDeadline(o, time.Now().Add(3*timeUnit)) - testDeadline(c, 2*timeUnit, t) -} - -func TestTimeout(t *testing.T) { - t.Parallel() - const timeUnit = 500 * time.Millisecond - c, _ := WithTimeout(Background(), 1*timeUnit) - if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) { - t.Errorf("c.String() = %q want prefix %q", got, prefix) - } - testDeadline(c, 2*timeUnit, t) - - c, _ = WithTimeout(Background(), 1*timeUnit) - o := otherContext{c} - testDeadline(o, 2*timeUnit, t) - - c, _ = WithTimeout(Background(), 1*timeUnit) - o = otherContext{c} - c, _ = WithTimeout(o, 3*timeUnit) - testDeadline(c, 2*timeUnit, t) -} - -func TestCanceledTimeout(t *testing.T) { - t.Parallel() - const timeUnit = 500 * time.Millisecond - c, _ := WithTimeout(Background(), 2*timeUnit) - o := otherContext{c} - c, cancel := WithTimeout(o, 4*timeUnit) - cancel() - time.Sleep(1 * timeUnit) // let cancelation propagate - select { - case <-c.Done(): - default: - t.Errorf("<-c.Done() blocked, but shouldn't have") - } - if e := c.Err(); e != Canceled { - t.Errorf("c.Err() == %v want %v", e, Canceled) - } -} - -type key1 int -type key2 int - -var k1 = key1(1) -var k2 = key2(1) // same int as k1, different type -var k3 = key2(3) // same type as k2, different int - -func TestValues(t *testing.T) { - check := func(c Context, nm, v1, v2, v3 string) { - if v, ok := c.Value(k1).(string); ok == (len(v1) == 0) || v != v1 { - t.Errorf(`%s.Value(k1).(string) = %q, %t want %q, %t`, nm, v, ok, v1, len(v1) != 0) - } - if v, ok := c.Value(k2).(string); ok == (len(v2) == 0) || v != v2 { - t.Errorf(`%s.Value(k2).(string) = %q, %t want %q, %t`, nm, v, ok, v2, len(v2) != 0) - } - if v, ok := c.Value(k3).(string); ok == (len(v3) == 0) || v != v3 { - t.Errorf(`%s.Value(k3).(string) = %q, %t want %q, %t`, nm, v, ok, v3, len(v3) != 0) - } - } - - c0 := Background() - check(c0, "c0", "", "", "") - - c1 := WithValue(Background(), k1, "c1k1") - check(c1, "c1", "c1k1", "", "") - - if got, want := fmt.Sprint(c1), `context.Background.WithValue(1, "c1k1")`; got != want { - t.Errorf("c.String() = %q want %q", got, want) - } - - c2 := WithValue(c1, k2, "c2k2") - check(c2, "c2", "c1k1", "c2k2", "") - - c3 := WithValue(c2, k3, "c3k3") - check(c3, "c2", "c1k1", "c2k2", "c3k3") - - c4 := WithValue(c3, k1, nil) - check(c4, "c4", "", "c2k2", "c3k3") - - o0 := otherContext{Background()} - check(o0, "o0", "", "", "") - - o1 := otherContext{WithValue(Background(), k1, "c1k1")} - check(o1, "o1", "c1k1", "", "") - - o2 := WithValue(o1, k2, "o2k2") - check(o2, "o2", "c1k1", "o2k2", "") - - o3 := otherContext{c4} - check(o3, "o3", "", "c2k2", "c3k3") - - o4 := WithValue(o3, k3, nil) - check(o4, "o4", "", "c2k2", "") -} - -func TestAllocs(t *testing.T) { - bg := Background() - for _, test := range []struct { - desc string - f func() - limit float64 - gccgoLimit float64 - }{ - { - desc: "Background()", - f: func() { Background() }, - limit: 0, - gccgoLimit: 0, - }, - { - desc: fmt.Sprintf("WithValue(bg, %v, nil)", k1), - f: func() { - c := WithValue(bg, k1, nil) - c.Value(k1) - }, - limit: 3, - gccgoLimit: 3, - }, - { - desc: "WithTimeout(bg, 15*time.Millisecond)", - f: func() { - c, _ := WithTimeout(bg, 15*time.Millisecond) - <-c.Done() - }, - limit: 8, - gccgoLimit: 16, - }, - { - desc: "WithCancel(bg)", - f: func() { - c, cancel := WithCancel(bg) - cancel() - <-c.Done() - }, - limit: 5, - gccgoLimit: 8, - }, - { - desc: "WithTimeout(bg, 100*time.Millisecond)", - f: func() { - c, cancel := WithTimeout(bg, 100*time.Millisecond) - cancel() - <-c.Done() - }, - limit: 8, - gccgoLimit: 25, - }, - } { - limit := test.limit - if runtime.Compiler == "gccgo" { - // gccgo does not yet do escape analysis. - // TODO(iant): Remove this when gccgo does do escape analysis. - limit = test.gccgoLimit - } - if n := testing.AllocsPerRun(100, test.f); n > limit { - t.Errorf("%s allocs = %f want %d", test.desc, n, int(limit)) - } - } -} - -func TestSimultaneousCancels(t *testing.T) { - root, cancel := WithCancel(Background()) - m := map[Context]CancelFunc{root: cancel} - q := []Context{root} - // Create a tree of contexts. - for len(q) != 0 && len(m) < 100 { - parent := q[0] - q = q[1:] - for i := 0; i < 4; i++ { - ctx, cancel := WithCancel(parent) - m[ctx] = cancel - q = append(q, ctx) - } - } - // Start all the cancels in a random order. - var wg sync.WaitGroup - wg.Add(len(m)) - for _, cancel := range m { - go func(cancel CancelFunc) { - cancel() - wg.Done() - }(cancel) - } - // Wait on all the contexts in a random order. - for ctx := range m { - select { - case <-ctx.Done(): - case <-time.After(1 * time.Second): - buf := make([]byte, 10<<10) - n := runtime.Stack(buf, true) - t.Fatalf("timed out waiting for <-ctx.Done(); stacks:\n%s", buf[:n]) - } - } - // Wait for all the cancel functions to return. - done := make(chan struct{}) - go func() { - wg.Wait() - close(done) - }() - select { - case <-done: - case <-time.After(1 * time.Second): - buf := make([]byte, 10<<10) - n := runtime.Stack(buf, true) - t.Fatalf("timed out waiting for cancel functions; stacks:\n%s", buf[:n]) - } -} - -func TestInterlockedCancels(t *testing.T) { - parent, cancelParent := WithCancel(Background()) - child, cancelChild := WithCancel(parent) - go func() { - parent.Done() - cancelChild() - }() - cancelParent() - select { - case <-child.Done(): - case <-time.After(1 * time.Second): - buf := make([]byte, 10<<10) - n := runtime.Stack(buf, true) - t.Fatalf("timed out waiting for child.Done(); stacks:\n%s", buf[:n]) - } -} - -func TestLayersCancel(t *testing.T) { - testLayers(t, time.Now().UnixNano(), false) -} - -func TestLayersTimeout(t *testing.T) { - testLayers(t, time.Now().UnixNano(), true) -} - -func testLayers(t *testing.T, seed int64, testTimeout bool) { - rand.Seed(seed) - errorf := func(format string, a ...interface{}) { - t.Errorf(fmt.Sprintf("seed=%d: %s", seed, format), a...) - } - const ( - timeout = 200 * time.Millisecond - minLayers = 30 - ) - type value int - var ( - vals []*value - cancels []CancelFunc - numTimers int - ctx = Background() - ) - for i := 0; i < minLayers || numTimers == 0 || len(cancels) == 0 || len(vals) == 0; i++ { - switch rand.Intn(3) { - case 0: - v := new(value) - ctx = WithValue(ctx, v, v) - vals = append(vals, v) - case 1: - var cancel CancelFunc - ctx, cancel = WithCancel(ctx) - cancels = append(cancels, cancel) - case 2: - var cancel CancelFunc - ctx, cancel = WithTimeout(ctx, timeout) - cancels = append(cancels, cancel) - numTimers++ - } - } - checkValues := func(when string) { - for _, key := range vals { - if val := ctx.Value(key).(*value); key != val { - errorf("%s: ctx.Value(%p) = %p want %p", when, key, val, key) - } - } - } - select { - case <-ctx.Done(): - errorf("ctx should not be canceled yet") - default: - } - if s, prefix := fmt.Sprint(ctx), "context.Background."; !strings.HasPrefix(s, prefix) { - t.Errorf("ctx.String() = %q want prefix %q", s, prefix) - } - t.Log(ctx) - checkValues("before cancel") - if testTimeout { - select { - case <-ctx.Done(): - case <-time.After(timeout + 100*time.Millisecond): - errorf("ctx should have timed out") - } - checkValues("after timeout") - } else { - cancel := cancels[rand.Intn(len(cancels))] - cancel() - select { - case <-ctx.Done(): - default: - errorf("ctx should be canceled") - } - checkValues("after cancel") - } -} - -func TestCancelRemoves(t *testing.T) { - checkChildren := func(when string, ctx Context, want int) { - if got := len(ctx.(*cancelCtx).children); got != want { - t.Errorf("%s: context has %d children, want %d", when, got, want) - } - } - - ctx, _ := WithCancel(Background()) - checkChildren("after creation", ctx, 0) - _, cancel := WithCancel(ctx) - checkChildren("with WithCancel child ", ctx, 1) - cancel() - checkChildren("after cancelling WithCancel child", ctx, 0) - - ctx, _ = WithCancel(Background()) - checkChildren("after creation", ctx, 0) - _, cancel = WithTimeout(ctx, 60*time.Minute) - checkChildren("with WithTimeout child ", ctx, 1) - cancel() - checkChildren("after cancelling WithTimeout child", ctx, 0) -} diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go new file mode 100644 index 000000000..37dc0cfdb --- /dev/null +++ b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go @@ -0,0 +1,71 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package ctxhttp provides helper functions for performing context-aware HTTP requests. +package ctxhttp // import "golang.org/x/net/context/ctxhttp" + +import ( + "context" + "io" + "net/http" + "net/url" + "strings" +) + +// Do sends an HTTP request with the provided http.Client and returns +// an HTTP response. +// +// If the client is nil, http.DefaultClient is used. +// +// The provided ctx must be non-nil. If it is canceled or times out, +// ctx.Err() will be returned. +func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) { + if client == nil { + client = http.DefaultClient + } + resp, err := client.Do(req.WithContext(ctx)) + // If we got an error, and the context has been canceled, + // the context's error is probably more useful. + if err != nil { + select { + case <-ctx.Done(): + err = ctx.Err() + default: + } + } + return resp, err +} + +// Get issues a GET request via the Do function. +func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) { + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + return Do(ctx, client, req) +} + +// Head issues a HEAD request via the Do function. +func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) { + req, err := http.NewRequest("HEAD", url, nil) + if err != nil { + return nil, err + } + return Do(ctx, client, req) +} + +// Post issues a POST request via the Do function. +func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) { + req, err := http.NewRequest("POST", url, body) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", bodyType) + return Do(ctx, client, req) +} + +// PostForm issues a POST request via the Do function. +func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) { + return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) +} diff --git a/vendor/golang.org/x/net/context/withtimeout_test.go b/vendor/golang.org/x/net/context/withtimeout_test.go deleted file mode 100644 index e6f56691d..000000000 --- a/vendor/golang.org/x/net/context/withtimeout_test.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package context_test - -import ( - "fmt" - "time" - - "golang.org/x/net/context" -) - -// This example passes a context with a timeout to tell a blocking function that -// it should abandon its work after the timeout elapses. -func ExampleWithTimeout() { - // Pass a context with a timeout to tell a blocking function that it - // should abandon its work after the timeout elapses. - ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond) - defer cancel() - - select { - case <-time.After(1 * time.Second): - fmt.Println("overslept") - case <-ctx.Done(): - fmt.Println(ctx.Err()) // prints "context deadline exceeded" - } - - // Output: - // context deadline exceeded -} diff --git a/vendor/golang.org/x/net/internal/iana/const.go b/vendor/golang.org/x/net/internal/iana/const.go index c9df24d95..cea712fac 100644 --- a/vendor/golang.org/x/net/internal/iana/const.go +++ b/vendor/golang.org/x/net/internal/iana/const.go @@ -1,44 +1,40 @@ // go generate gen.go -// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT +// Code generated by the command above; DO NOT EDIT. // Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA). package iana // import "golang.org/x/net/internal/iana" -// Differentiated Services Field Codepoints (DSCP), Updated: 2017-05-12 +// Differentiated Services Field Codepoints (DSCP), Updated: 2018-05-04 const ( - DiffServCS0 = 0x0 // CS0 - DiffServCS1 = 0x20 // CS1 - DiffServCS2 = 0x40 // CS2 - DiffServCS3 = 0x60 // CS3 - DiffServCS4 = 0x80 // CS4 - DiffServCS5 = 0xa0 // CS5 - DiffServCS6 = 0xc0 // CS6 - DiffServCS7 = 0xe0 // CS7 - DiffServAF11 = 0x28 // AF11 - DiffServAF12 = 0x30 // AF12 - DiffServAF13 = 0x38 // AF13 - DiffServAF21 = 0x48 // AF21 - DiffServAF22 = 0x50 // AF22 - DiffServAF23 = 0x58 // AF23 - DiffServAF31 = 0x68 // AF31 - DiffServAF32 = 0x70 // AF32 - DiffServAF33 = 0x78 // AF33 - DiffServAF41 = 0x88 // AF41 - DiffServAF42 = 0x90 // AF42 - DiffServAF43 = 0x98 // AF43 - DiffServEF = 0xb8 // EF - DiffServVOICEADMIT = 0xb0 // VOICE-ADMIT + DiffServCS0 = 0x00 // CS0 + DiffServCS1 = 0x20 // CS1 + DiffServCS2 = 0x40 // CS2 + DiffServCS3 = 0x60 // CS3 + DiffServCS4 = 0x80 // CS4 + DiffServCS5 = 0xa0 // CS5 + DiffServCS6 = 0xc0 // CS6 + DiffServCS7 = 0xe0 // CS7 + DiffServAF11 = 0x28 // AF11 + DiffServAF12 = 0x30 // AF12 + DiffServAF13 = 0x38 // AF13 + DiffServAF21 = 0x48 // AF21 + DiffServAF22 = 0x50 // AF22 + DiffServAF23 = 0x58 // AF23 + DiffServAF31 = 0x68 // AF31 + DiffServAF32 = 0x70 // AF32 + DiffServAF33 = 0x78 // AF33 + DiffServAF41 = 0x88 // AF41 + DiffServAF42 = 0x90 // AF42 + DiffServAF43 = 0x98 // AF43 + DiffServEF = 0xb8 // EF + DiffServVOICEADMIT = 0xb0 // VOICE-ADMIT + NotECNTransport = 0x00 // Not-ECT (Not ECN-Capable Transport) + ECNTransport1 = 0x01 // ECT(1) (ECN-Capable Transport(1)) + ECNTransport0 = 0x02 // ECT(0) (ECN-Capable Transport(0)) + CongestionExperienced = 0x03 // CE (Congestion Experienced) ) -// IPv4 TOS Byte and IPv6 Traffic Class Octet, Updated: 2001-09-06 -const ( - NotECNTransport = 0x0 // Not-ECT (Not ECN-Capable Transport) - ECNTransport1 = 0x1 // ECT(1) (ECN-Capable Transport(1)) - ECNTransport0 = 0x2 // ECT(0) (ECN-Capable Transport(0)) - CongestionExperienced = 0x3 // CE (Congestion Experienced) -) - -// Protocol Numbers, Updated: 2016-06-22 +// Protocol Numbers, Updated: 2017-10-13 const ( ProtocolIP = 0 // IPv4 encapsulation, pseudo protocol number ProtocolHOPOPT = 0 // IPv6 Hop-by-Hop Option @@ -178,3 +174,50 @@ const ( ProtocolROHC = 142 // Robust Header Compression ProtocolReserved = 255 // Reserved ) + +// Address Family Numbers, Updated: 2018-04-02 +const ( + AddrFamilyIPv4 = 1 // IP (IP version 4) + AddrFamilyIPv6 = 2 // IP6 (IP version 6) + AddrFamilyNSAP = 3 // NSAP + AddrFamilyHDLC = 4 // HDLC (8-bit multidrop) + AddrFamilyBBN1822 = 5 // BBN 1822 + AddrFamily802 = 6 // 802 (includes all 802 media plus Ethernet "canonical format") + AddrFamilyE163 = 7 // E.163 + AddrFamilyE164 = 8 // E.164 (SMDS, Frame Relay, ATM) + AddrFamilyF69 = 9 // F.69 (Telex) + AddrFamilyX121 = 10 // X.121 (X.25, Frame Relay) + AddrFamilyIPX = 11 // IPX + AddrFamilyAppletalk = 12 // Appletalk + AddrFamilyDecnetIV = 13 // Decnet IV + AddrFamilyBanyanVines = 14 // Banyan Vines + AddrFamilyE164withSubaddress = 15 // E.164 with NSAP format subaddress + AddrFamilyDNS = 16 // DNS (Domain Name System) + AddrFamilyDistinguishedName = 17 // Distinguished Name + AddrFamilyASNumber = 18 // AS Number + AddrFamilyXTPoverIPv4 = 19 // XTP over IP version 4 + AddrFamilyXTPoverIPv6 = 20 // XTP over IP version 6 + AddrFamilyXTPnativemodeXTP = 21 // XTP native mode XTP + AddrFamilyFibreChannelWorldWidePortName = 22 // Fibre Channel World-Wide Port Name + AddrFamilyFibreChannelWorldWideNodeName = 23 // Fibre Channel World-Wide Node Name + AddrFamilyGWID = 24 // GWID + AddrFamilyL2VPN = 25 // AFI for L2VPN information + AddrFamilyMPLSTPSectionEndpointID = 26 // MPLS-TP Section Endpoint Identifier + AddrFamilyMPLSTPLSPEndpointID = 27 // MPLS-TP LSP Endpoint Identifier + AddrFamilyMPLSTPPseudowireEndpointID = 28 // MPLS-TP Pseudowire Endpoint Identifier + AddrFamilyMTIPv4 = 29 // MT IP: Multi-Topology IP version 4 + AddrFamilyMTIPv6 = 30 // MT IPv6: Multi-Topology IP version 6 + AddrFamilyEIGRPCommonServiceFamily = 16384 // EIGRP Common Service Family + AddrFamilyEIGRPIPv4ServiceFamily = 16385 // EIGRP IPv4 Service Family + AddrFamilyEIGRPIPv6ServiceFamily = 16386 // EIGRP IPv6 Service Family + AddrFamilyLISPCanonicalAddressFormat = 16387 // LISP Canonical Address Format (LCAF) + AddrFamilyBGPLS = 16388 // BGP-LS + AddrFamily48bitMAC = 16389 // 48-bit MAC + AddrFamily64bitMAC = 16390 // 64-bit MAC + AddrFamilyOUI = 16391 // OUI + AddrFamilyMACFinal24bits = 16392 // MAC/24 + AddrFamilyMACFinal40bits = 16393 // MAC/40 + AddrFamilyIPv6Initial64bits = 16394 // IPv6/64 + AddrFamilyRBridgePortID = 16395 // RBridge Port ID + AddrFamilyTRILLNickname = 16396 // TRILL Nickname +) diff --git a/vendor/golang.org/x/net/internal/iana/gen.go b/vendor/golang.org/x/net/internal/iana/gen.go index 2a5c310c2..2a7661c27 100644 --- a/vendor/golang.org/x/net/internal/iana/gen.go +++ b/vendor/golang.org/x/net/internal/iana/gen.go @@ -31,20 +31,20 @@ var registries = []struct { "https://www.iana.org/assignments/dscp-registry/dscp-registry.xml", parseDSCPRegistry, }, - { - "https://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml", - parseTOSTCByte, - }, { "https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml", parseProtocolNumbers, }, + { + "https://www.iana.org/assignments/address-family-numbers/address-family-numbers.xml", + parseAddrFamilyNumbers, + }, } func main() { var bb bytes.Buffer fmt.Fprintf(&bb, "// go generate gen.go\n") - fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n") + fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n") fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n") fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n") for _, r := range registries { @@ -81,31 +81,39 @@ func parseDSCPRegistry(w io.Writer, r io.Reader) error { if err := dec.Decode(&dr); err != nil { return err } - drs := dr.escape() fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated) fmt.Fprintf(w, "const (\n") - for _, dr := range drs { - fmt.Fprintf(w, "DiffServ%s = %#x", dr.Name, dr.Value) + for _, dr := range dr.escapeDSCP() { + fmt.Fprintf(w, "DiffServ%s = %#02x", dr.Name, dr.Value) fmt.Fprintf(w, "// %s\n", dr.OrigName) } + for _, er := range dr.escapeECN() { + fmt.Fprintf(w, "%s = %#02x", er.Descr, er.Value) + fmt.Fprintf(w, "// %s\n", er.OrigDescr) + } fmt.Fprintf(w, ")\n") return nil } type dscpRegistry struct { - XMLName xml.Name `xml:"registry"` - Title string `xml:"title"` - Updated string `xml:"updated"` - Note string `xml:"note"` - RegTitle string `xml:"registry>title"` - PoolRecords []struct { - Name string `xml:"name"` - Space string `xml:"space"` - } `xml:"registry>record"` - Records []struct { - Name string `xml:"name"` - Space string `xml:"space"` - } `xml:"registry>registry>record"` + XMLName xml.Name `xml:"registry"` + Title string `xml:"title"` + Updated string `xml:"updated"` + Note string `xml:"note"` + Registries []struct { + Title string `xml:"title"` + Registries []struct { + Title string `xml:"title"` + Records []struct { + Name string `xml:"name"` + Space string `xml:"space"` + } `xml:"record"` + } `xml:"registry"` + Records []struct { + Value string `xml:"value"` + Descr string `xml:"description"` + } `xml:"record"` + } `xml:"registry"` } type canonDSCPRecord struct { @@ -114,92 +122,84 @@ type canonDSCPRecord struct { Value int } -func (drr *dscpRegistry) escape() []canonDSCPRecord { - drs := make([]canonDSCPRecord, len(drr.Records)) - sr := strings.NewReplacer( - "+", "", - "-", "", - "/", "", - ".", "", - " ", "", - ) - for i, dr := range drr.Records { - s := strings.TrimSpace(dr.Name) - drs[i].OrigName = s - drs[i].Name = sr.Replace(s) - n, err := strconv.ParseUint(dr.Space, 2, 8) - if err != nil { +func (drr *dscpRegistry) escapeDSCP() []canonDSCPRecord { + var drs []canonDSCPRecord + for _, preg := range drr.Registries { + if !strings.Contains(preg.Title, "Differentiated Services Field Codepoints") { continue } - drs[i].Value = int(n) << 2 + for _, reg := range preg.Registries { + if !strings.Contains(reg.Title, "Pool 1 Codepoints") { + continue + } + drs = make([]canonDSCPRecord, len(reg.Records)) + sr := strings.NewReplacer( + "+", "", + "-", "", + "/", "", + ".", "", + " ", "", + ) + for i, dr := range reg.Records { + s := strings.TrimSpace(dr.Name) + drs[i].OrigName = s + drs[i].Name = sr.Replace(s) + n, err := strconv.ParseUint(dr.Space, 2, 8) + if err != nil { + continue + } + drs[i].Value = int(n) << 2 + } + } } return drs } -func parseTOSTCByte(w io.Writer, r io.Reader) error { - dec := xml.NewDecoder(r) - var ttb tosTCByte - if err := dec.Decode(&ttb); err != nil { - return err - } - trs := ttb.escape() - fmt.Fprintf(w, "// %s, Updated: %s\n", ttb.Title, ttb.Updated) - fmt.Fprintf(w, "const (\n") - for _, tr := range trs { - fmt.Fprintf(w, "%s = %#x", tr.Keyword, tr.Value) - fmt.Fprintf(w, "// %s\n", tr.OrigKeyword) - } - fmt.Fprintf(w, ")\n") - return nil -} - -type tosTCByte struct { - XMLName xml.Name `xml:"registry"` - Title string `xml:"title"` - Updated string `xml:"updated"` - Note string `xml:"note"` - RegTitle string `xml:"registry>title"` - Records []struct { - Binary string `xml:"binary"` - Keyword string `xml:"keyword"` - } `xml:"registry>record"` +type canonECNRecord struct { + OrigDescr string + Descr string + Value int } -type canonTOSTCByteRecord struct { - OrigKeyword string - Keyword string - Value int -} - -func (ttb *tosTCByte) escape() []canonTOSTCByteRecord { - trs := make([]canonTOSTCByteRecord, len(ttb.Records)) - sr := strings.NewReplacer( - "Capable", "", - "(", "", - ")", "", - "+", "", - "-", "", - "/", "", - ".", "", - " ", "", - ) - for i, tr := range ttb.Records { - s := strings.TrimSpace(tr.Keyword) - trs[i].OrigKeyword = s - ss := strings.Split(s, " ") - if len(ss) > 1 { - trs[i].Keyword = strings.Join(ss[1:], " ") - } else { - trs[i].Keyword = ss[0] - } - trs[i].Keyword = sr.Replace(trs[i].Keyword) - n, err := strconv.ParseUint(tr.Binary, 2, 8) - if err != nil { +func (drr *dscpRegistry) escapeECN() []canonECNRecord { + var ers []canonECNRecord + for _, reg := range drr.Registries { + if !strings.Contains(reg.Title, "ECN Field") { continue } - trs[i].Value = int(n) + ers = make([]canonECNRecord, len(reg.Records)) + sr := strings.NewReplacer( + "Capable", "", + "Not-ECT", "", + "ECT(1)", "", + "ECT(0)", "", + "CE", "", + "(", "", + ")", "", + "+", "", + "-", "", + "/", "", + ".", "", + " ", "", + ) + for i, er := range reg.Records { + s := strings.TrimSpace(er.Descr) + ers[i].OrigDescr = s + ss := strings.Split(s, " ") + if len(ss) > 1 { + ers[i].Descr = strings.Join(ss[1:], " ") + } else { + ers[i].Descr = ss[0] + } + ers[i].Descr = sr.Replace(er.Descr) + n, err := strconv.ParseUint(er.Value, 2, 8) + if err != nil { + continue + } + ers[i].Value = int(n) + } } - return trs + return ers } func parseProtocolNumbers(w io.Writer, r io.Reader) error { @@ -291,3 +291,93 @@ func (pn *protocolNumbers) escape() []canonProtocolRecord { } return prs } + +func parseAddrFamilyNumbers(w io.Writer, r io.Reader) error { + dec := xml.NewDecoder(r) + var afn addrFamilylNumbers + if err := dec.Decode(&afn); err != nil { + return err + } + afrs := afn.escape() + fmt.Fprintf(w, "// %s, Updated: %s\n", afn.Title, afn.Updated) + fmt.Fprintf(w, "const (\n") + for _, afr := range afrs { + if afr.Name == "" { + continue + } + fmt.Fprintf(w, "AddrFamily%s = %d", afr.Name, afr.Value) + fmt.Fprintf(w, "// %s\n", afr.Descr) + } + fmt.Fprintf(w, ")\n") + return nil +} + +type addrFamilylNumbers struct { + XMLName xml.Name `xml:"registry"` + Title string `xml:"title"` + Updated string `xml:"updated"` + RegTitle string `xml:"registry>title"` + Note string `xml:"registry>note"` + Records []struct { + Value string `xml:"value"` + Descr string `xml:"description"` + } `xml:"registry>record"` +} + +type canonAddrFamilyRecord struct { + Name string + Descr string + Value int +} + +func (afn *addrFamilylNumbers) escape() []canonAddrFamilyRecord { + afrs := make([]canonAddrFamilyRecord, len(afn.Records)) + sr := strings.NewReplacer( + "IP version 4", "IPv4", + "IP version 6", "IPv6", + "Identifier", "ID", + "-", "", + "-", "", + "/", "", + ".", "", + " ", "", + ) + for i, afr := range afn.Records { + if strings.Contains(afr.Descr, "Unassigned") || + strings.Contains(afr.Descr, "Reserved") { + continue + } + afrs[i].Descr = afr.Descr + s := strings.TrimSpace(afr.Descr) + switch s { + case "IP (IP version 4)": + afrs[i].Name = "IPv4" + case "IP6 (IP version 6)": + afrs[i].Name = "IPv6" + case "AFI for L2VPN information": + afrs[i].Name = "L2VPN" + case "E.164 with NSAP format subaddress": + afrs[i].Name = "E164withSubaddress" + case "MT IP: Multi-Topology IP version 4": + afrs[i].Name = "MTIPv4" + case "MAC/24": + afrs[i].Name = "MACFinal24bits" + case "MAC/40": + afrs[i].Name = "MACFinal40bits" + case "IPv6/64": + afrs[i].Name = "IPv6Initial64bits" + default: + n := strings.Index(s, "(") + if n > 0 { + s = s[:n] + } + n = strings.Index(s, ":") + if n > 0 { + s = s[:n] + } + afrs[i].Name = sr.Replace(s) + } + afrs[i].Value, _ = strconv.Atoi(afr.Value) + } + return afrs +} diff --git a/vendor/golang.org/x/net/internal/socket/empty.s b/vendor/golang.org/x/net/internal/socket/empty.s new file mode 100644 index 000000000..bff0231c7 --- /dev/null +++ b/vendor/golang.org/x/net/internal/socket/empty.s @@ -0,0 +1,7 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin,go1.12 + +// This exists solely so we can linkname in symbols from syscall. diff --git a/vendor/golang.org/x/net/internal/socket/socket_go1_9_test.go b/vendor/golang.org/x/net/internal/socket/socket_go1_9_test.go deleted file mode 100644 index c4edd4a8d..000000000 --- a/vendor/golang.org/x/net/internal/socket/socket_go1_9_test.go +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.9 -// +build darwin dragonfly freebsd linux netbsd openbsd solaris - -package socket_test - -import ( - "bytes" - "fmt" - "net" - "runtime" - "testing" - - "golang.org/x/net/internal/nettest" - "golang.org/x/net/internal/socket" -) - -type mockControl struct { - Level int - Type int - Data []byte -} - -func TestControlMessage(t *testing.T) { - for _, tt := range []struct { - cs []mockControl - }{ - { - []mockControl{ - {Level: 1, Type: 1}, - }, - }, - { - []mockControl{ - {Level: 2, Type: 2, Data: []byte{0xfe}}, - }, - }, - { - []mockControl{ - {Level: 3, Type: 3, Data: []byte{0xfe, 0xff, 0xff, 0xfe}}, - }, - }, - { - []mockControl{ - {Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}}, - }, - }, - { - []mockControl{ - {Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}}, - {Level: 2, Type: 2, Data: []byte{0xfe}}, - }, - }, - } { - var w []byte - var tailPadLen int - mm := socket.NewControlMessage([]int{0}) - for i, c := range tt.cs { - m := socket.NewControlMessage([]int{len(c.Data)}) - l := len(m) - len(mm) - if i == len(tt.cs)-1 && l > len(c.Data) { - tailPadLen = l - len(c.Data) - } - w = append(w, m...) - } - - var err error - ww := make([]byte, len(w)) - copy(ww, w) - m := socket.ControlMessage(ww) - for _, c := range tt.cs { - if err = m.MarshalHeader(c.Level, c.Type, len(c.Data)); err != nil { - t.Fatalf("(%v).MarshalHeader() = %v", tt.cs, err) - } - copy(m.Data(len(c.Data)), c.Data) - m = m.Next(len(c.Data)) - } - m = socket.ControlMessage(w) - for _, c := range tt.cs { - m, err = m.Marshal(c.Level, c.Type, c.Data) - if err != nil { - t.Fatalf("(%v).Marshal() = %v", tt.cs, err) - } - } - if !bytes.Equal(ww, w) { - t.Fatalf("got %#v; want %#v", ww, w) - } - - ws := [][]byte{w} - if tailPadLen > 0 { - // Test a message with no tail padding. - nopad := w[:len(w)-tailPadLen] - ws = append(ws, [][]byte{nopad}...) - } - for _, w := range ws { - ms, err := socket.ControlMessage(w).Parse() - if err != nil { - t.Fatalf("(%v).Parse() = %v", tt.cs, err) - } - for i, m := range ms { - lvl, typ, dataLen, err := m.ParseHeader() - if err != nil { - t.Fatalf("(%v).ParseHeader() = %v", tt.cs, err) - } - if lvl != tt.cs[i].Level || typ != tt.cs[i].Type || dataLen != len(tt.cs[i].Data) { - t.Fatalf("%v: got %d, %d, %d; want %d, %d, %d", tt.cs[i], lvl, typ, dataLen, tt.cs[i].Level, tt.cs[i].Type, len(tt.cs[i].Data)) - } - } - } - } -} - -func TestUDP(t *testing.T) { - c, err := nettest.NewLocalPacketListener("udp") - if err != nil { - t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - cc, err := socket.NewConn(c.(net.Conn)) - if err != nil { - t.Fatal(err) - } - - t.Run("Message", func(t *testing.T) { - data := []byte("HELLO-R-U-THERE") - wm := socket.Message{ - Buffers: bytes.SplitAfter(data, []byte("-")), - Addr: c.LocalAddr(), - } - if err := cc.SendMsg(&wm, 0); err != nil { - t.Fatal(err) - } - b := make([]byte, 32) - rm := socket.Message{ - Buffers: [][]byte{b[:1], b[1:3], b[3:7], b[7:11], b[11:]}, - } - if err := cc.RecvMsg(&rm, 0); err != nil { - t.Fatal(err) - } - if !bytes.Equal(b[:rm.N], data) { - t.Fatalf("got %#v; want %#v", b[:rm.N], data) - } - }) - switch runtime.GOOS { - case "android", "linux": - t.Run("Messages", func(t *testing.T) { - data := []byte("HELLO-R-U-THERE") - wmbs := bytes.SplitAfter(data, []byte("-")) - wms := []socket.Message{ - {Buffers: wmbs[:1], Addr: c.LocalAddr()}, - {Buffers: wmbs[1:], Addr: c.LocalAddr()}, - } - n, err := cc.SendMsgs(wms, 0) - if err != nil { - t.Fatal(err) - } - if n != len(wms) { - t.Fatalf("got %d; want %d", n, len(wms)) - } - b := make([]byte, 32) - rmbs := [][][]byte{{b[:len(wmbs[0])]}, {b[len(wmbs[0]):]}} - rms := []socket.Message{ - {Buffers: rmbs[0]}, - {Buffers: rmbs[1]}, - } - n, err = cc.RecvMsgs(rms, 0) - if err != nil { - t.Fatal(err) - } - if n != len(rms) { - t.Fatalf("got %d; want %d", n, len(rms)) - } - nn := 0 - for i := 0; i < n; i++ { - nn += rms[i].N - } - if !bytes.Equal(b[:nn], data) { - t.Fatalf("got %#v; want %#v", b[:nn], data) - } - }) - } - - // The behavior of transmission for zero byte paylaod depends - // on each platform implementation. Some may transmit only - // protocol header and options, other may transmit nothing. - // We test only that SendMsg and SendMsgs will not crash with - // empty buffers. - wm := socket.Message{ - Buffers: [][]byte{{}}, - Addr: c.LocalAddr(), - } - cc.SendMsg(&wm, 0) - wms := []socket.Message{ - {Buffers: [][]byte{{}}, Addr: c.LocalAddr()}, - } - cc.SendMsgs(wms, 0) -} - -func BenchmarkUDP(b *testing.B) { - c, err := nettest.NewLocalPacketListener("udp") - if err != nil { - b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - cc, err := socket.NewConn(c.(net.Conn)) - if err != nil { - b.Fatal(err) - } - data := []byte("HELLO-R-U-THERE") - wm := socket.Message{ - Buffers: [][]byte{data}, - Addr: c.LocalAddr(), - } - rm := socket.Message{ - Buffers: [][]byte{make([]byte, 128)}, - OOB: make([]byte, 128), - } - - for M := 1; M <= 1<<9; M = M << 1 { - b.Run(fmt.Sprintf("Iter-%d", M), func(b *testing.B) { - for i := 0; i < b.N; i++ { - for j := 0; j < M; j++ { - if err := cc.SendMsg(&wm, 0); err != nil { - b.Fatal(err) - } - if err := cc.RecvMsg(&rm, 0); err != nil { - b.Fatal(err) - } - } - } - }) - switch runtime.GOOS { - case "android", "linux": - wms := make([]socket.Message, M) - for i := range wms { - wms[i].Buffers = [][]byte{data} - wms[i].Addr = c.LocalAddr() - } - rms := make([]socket.Message, M) - for i := range rms { - rms[i].Buffers = [][]byte{make([]byte, 128)} - rms[i].OOB = make([]byte, 128) - } - b.Run(fmt.Sprintf("Batch-%d", M), func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := cc.SendMsgs(wms, 0); err != nil { - b.Fatal(err) - } - if _, err := cc.RecvMsgs(rms, 0); err != nil { - b.Fatal(err) - } - } - }) - } - } -} diff --git a/vendor/golang.org/x/net/internal/socket/socket_test.go b/vendor/golang.org/x/net/internal/socket/socket_test.go deleted file mode 100644 index bf3751b5e..000000000 --- a/vendor/golang.org/x/net/internal/socket/socket_test.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows - -package socket_test - -import ( - "net" - "runtime" - "syscall" - "testing" - - "golang.org/x/net/internal/nettest" - "golang.org/x/net/internal/socket" -) - -func TestSocket(t *testing.T) { - t.Run("Option", func(t *testing.T) { - testSocketOption(t, &socket.Option{Level: syscall.SOL_SOCKET, Name: syscall.SO_RCVBUF, Len: 4}) - }) -} - -func testSocketOption(t *testing.T, so *socket.Option) { - c, err := nettest.NewLocalPacketListener("udp") - if err != nil { - t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - cc, err := socket.NewConn(c.(net.Conn)) - if err != nil { - t.Fatal(err) - } - const N = 2048 - if err := so.SetInt(cc, N); err != nil { - t.Fatal(err) - } - n, err := so.GetInt(cc) - if err != nil { - t.Fatal(err) - } - if n < N { - t.Fatalf("got %d; want greater than or equal to %d", n, N) - } -} diff --git a/vendor/golang.org/x/net/internal/socket/sys_go1_11_darwin.go b/vendor/golang.org/x/net/internal/socket/sys_go1_11_darwin.go new file mode 100644 index 000000000..02d2b3cc8 --- /dev/null +++ b/vendor/golang.org/x/net/internal/socket/sys_go1_11_darwin.go @@ -0,0 +1,33 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !go1.12 + +package socket + +import ( + "syscall" + "unsafe" +) + +func getsockopt(s uintptr, level, name int, b []byte) (int, error) { + l := uint32(len(b)) + _, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(unsafe.Pointer(&l)), 0) + return int(l), errnoErr(errno) +} + +func setsockopt(s uintptr, level, name int, b []byte) error { + _, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), 0) + return errnoErr(errno) +} + +func recvmsg(s uintptr, h *msghdr, flags int) (int, error) { + n, _, errno := syscall.Syscall(syscall.SYS_RECVMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags)) + return int(n), errnoErr(errno) +} + +func sendmsg(s uintptr, h *msghdr, flags int) (int, error) { + n, _, errno := syscall.Syscall(syscall.SYS_SENDMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags)) + return int(n), errnoErr(errno) +} diff --git a/vendor/golang.org/x/net/internal/socket/sys_go1_12_darwin.go b/vendor/golang.org/x/net/internal/socket/sys_go1_12_darwin.go new file mode 100644 index 000000000..0999a19fb --- /dev/null +++ b/vendor/golang.org/x/net/internal/socket/sys_go1_12_darwin.go @@ -0,0 +1,42 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.12 + +package socket + +import ( + "syscall" + "unsafe" +) + +//go:linkname syscall_getsockopt syscall.getsockopt +func syscall_getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *uint32) error + +func getsockopt(s uintptr, level, name int, b []byte) (int, error) { + l := uint32(len(b)) + err := syscall_getsockopt(int(s), level, name, unsafe.Pointer(&b[0]), &l) + return int(l), err +} + +//go:linkname syscall_setsockopt syscall.setsockopt +func syscall_setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) error + +func setsockopt(s uintptr, level, name int, b []byte) error { + return syscall_setsockopt(int(s), level, name, unsafe.Pointer(&b[0]), uintptr(len(b))) +} + +//go:linkname syscall_recvmsg syscall.recvmsg +func syscall_recvmsg(s int, msg *syscall.Msghdr, flags int) (n int, err error) + +func recvmsg(s uintptr, h *msghdr, flags int) (int, error) { + return syscall_recvmsg(int(s), (*syscall.Msghdr)(unsafe.Pointer(h)), flags) +} + +//go:linkname syscall_sendmsg syscall.sendmsg +func syscall_sendmsg(s int, msg *syscall.Msghdr, flags int) (n int, err error) + +func sendmsg(s uintptr, h *msghdr, flags int) (int, error) { + return syscall_sendmsg(int(s), (*syscall.Msghdr)(unsafe.Pointer(h)), flags) +} diff --git a/vendor/golang.org/x/net/internal/socket/sys_posix.go b/vendor/golang.org/x/net/internal/socket/sys_posix.go index dc130c27e..9a9bc4762 100644 --- a/vendor/golang.org/x/net/internal/socket/sys_posix.go +++ b/vendor/golang.org/x/net/internal/socket/sys_posix.go @@ -121,18 +121,21 @@ var zoneCache = ipv6ZoneCache{ toName: make(map[int]string), } -func (zc *ipv6ZoneCache) update(ift []net.Interface) { +// update refreshes the network interface information if the cache was last +// updated more than 1 minute ago, or if force is set. It returns whether the +// cache was updated. +func (zc *ipv6ZoneCache) update(ift []net.Interface, force bool) (updated bool) { zc.Lock() defer zc.Unlock() now := time.Now() - if zc.lastFetched.After(now.Add(-60 * time.Second)) { - return + if !force && zc.lastFetched.After(now.Add(-60*time.Second)) { + return false } zc.lastFetched = now if len(ift) == 0 { var err error if ift, err = net.Interfaces(); err != nil { - return + return false } } zc.toIndex = make(map[string]int, len(ift)) @@ -143,25 +146,38 @@ func (zc *ipv6ZoneCache) update(ift []net.Interface) { zc.toName[ifi.Index] = ifi.Name } } + return true } func (zc *ipv6ZoneCache) name(zone int) string { - zoneCache.update(nil) + updated := zoneCache.update(nil, false) zoneCache.RLock() - defer zoneCache.RUnlock() name, ok := zoneCache.toName[zone] - if !ok { + zoneCache.RUnlock() + if !ok && !updated { + zoneCache.update(nil, true) + zoneCache.RLock() + name, ok = zoneCache.toName[zone] + zoneCache.RUnlock() + } + if !ok { // last resort name = strconv.Itoa(zone) } return name } func (zc *ipv6ZoneCache) index(zone string) int { - zoneCache.update(nil) + updated := zoneCache.update(nil, false) zoneCache.RLock() - defer zoneCache.RUnlock() index, ok := zoneCache.toIndex[zone] - if !ok { + zoneCache.RUnlock() + if !ok && !updated { + zoneCache.update(nil, true) + zoneCache.RLock() + index, ok = zoneCache.toIndex[zone] + zoneCache.RUnlock() + } + if !ok { // last resort index, _ = strconv.Atoi(zone) } return index diff --git a/vendor/golang.org/x/net/internal/socket/sys_unix.go b/vendor/golang.org/x/net/internal/socket/sys_unix.go index 18eba3085..0eb71283f 100644 --- a/vendor/golang.org/x/net/internal/socket/sys_unix.go +++ b/vendor/golang.org/x/net/internal/socket/sys_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin dragonfly freebsd linux,!s390x,!386 netbsd openbsd +// +build dragonfly freebsd linux,!s390x,!386 netbsd openbsd package socket diff --git a/vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm.go b/vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm.go index 206ea2d11..db60491fe 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm.go @@ -26,6 +26,11 @@ type msghdr struct { Flags int32 } +type mmsghdr struct { + Hdr msghdr + Len uint32 +} + type cmsghdr struct { Len uint32 Level int32 @@ -52,6 +57,7 @@ type sockaddrInet6 struct { const ( sizeofIovec = 0x8 sizeofMsghdr = 0x1c + sizeofMmsghdr = 0x20 sizeofCmsghdr = 0xc sizeofSockaddrInet = 0x10 diff --git a/vendor/golang.org/x/net/ipv4/batch.go b/vendor/golang.org/x/net/ipv4/batch.go index b44549928..5ce9b3583 100644 --- a/vendor/golang.org/x/net/ipv4/batch.go +++ b/vendor/golang.org/x/net/ipv4/batch.go @@ -9,7 +9,6 @@ package ipv4 import ( "net" "runtime" - "syscall" "golang.org/x/net/internal/socket" ) @@ -76,7 +75,7 @@ type Message = socket.Message // headers. func (c *payloadHandler) ReadBatch(ms []Message, flags int) (int, error) { if !c.ok() { - return 0, syscall.EINVAL + return 0, errInvalidConn } switch runtime.GOOS { case "linux": @@ -107,7 +106,7 @@ func (c *payloadHandler) ReadBatch(ms []Message, flags int) (int, error) { // On other platforms, this method will write only a single message. func (c *payloadHandler) WriteBatch(ms []Message, flags int) (int, error) { if !c.ok() { - return 0, syscall.EINVAL + return 0, errInvalidConn } switch runtime.GOOS { case "linux": @@ -139,7 +138,7 @@ func (c *payloadHandler) WriteBatch(ms []Message, flags int) (int, error) { // On other platforms, this method will read only a single message. func (c *packetHandler) ReadBatch(ms []Message, flags int) (int, error) { if !c.ok() { - return 0, syscall.EINVAL + return 0, errInvalidConn } switch runtime.GOOS { case "linux": @@ -170,7 +169,7 @@ func (c *packetHandler) ReadBatch(ms []Message, flags int) (int, error) { // On other platforms, this method will write only a single message. func (c *packetHandler) WriteBatch(ms []Message, flags int) (int, error) { if !c.ok() { - return 0, syscall.EINVAL + return 0, errInvalidConn } switch runtime.GOOS { case "linux": diff --git a/vendor/golang.org/x/net/ipv4/bpf_test.go b/vendor/golang.org/x/net/ipv4/bpf_test.go deleted file mode 100644 index b44da9054..000000000 --- a/vendor/golang.org/x/net/ipv4/bpf_test.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv4_test - -import ( - "net" - "runtime" - "testing" - "time" - - "golang.org/x/net/bpf" - "golang.org/x/net/ipv4" -) - -func TestBPF(t *testing.T) { - if runtime.GOOS != "linux" { - t.Skipf("not supported on %s", runtime.GOOS) - } - - l, err := net.ListenPacket("udp4", "127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - defer l.Close() - - p := ipv4.NewPacketConn(l) - - // This filter accepts UDP packets whose first payload byte is - // even. - prog, err := bpf.Assemble([]bpf.Instruction{ - // Load the first byte of the payload (skipping UDP header). - bpf.LoadAbsolute{Off: 8, Size: 1}, - // Select LSB of the byte. - bpf.ALUOpConstant{Op: bpf.ALUOpAnd, Val: 1}, - // Byte is even? - bpf.JumpIf{Cond: bpf.JumpEqual, Val: 0, SkipFalse: 1}, - // Accept. - bpf.RetConstant{Val: 4096}, - // Ignore. - bpf.RetConstant{Val: 0}, - }) - if err != nil { - t.Fatalf("compiling BPF: %s", err) - } - - if err = p.SetBPF(prog); err != nil { - t.Fatalf("attaching filter to Conn: %s", err) - } - - s, err := net.Dial("udp4", l.LocalAddr().String()) - if err != nil { - t.Fatal(err) - } - defer s.Close() - go func() { - for i := byte(0); i < 10; i++ { - s.Write([]byte{i}) - } - }() - - l.SetDeadline(time.Now().Add(2 * time.Second)) - seen := make([]bool, 5) - for { - var b [512]byte - n, _, err := l.ReadFrom(b[:]) - if err != nil { - t.Fatalf("reading from listener: %s", err) - } - if n != 1 { - t.Fatalf("unexpected packet length, want 1, got %d", n) - } - if b[0] >= 10 { - t.Fatalf("unexpected byte, want 0-9, got %d", b[0]) - } - if b[0]%2 != 0 { - t.Fatalf("got odd byte %d, wanted only even bytes", b[0]) - } - seen[b[0]/2] = true - - seenAll := true - for _, v := range seen { - if !v { - seenAll = false - break - } - } - if seenAll { - break - } - } -} diff --git a/vendor/golang.org/x/net/ipv4/control_test.go b/vendor/golang.org/x/net/ipv4/control_test.go deleted file mode 100644 index f87fe124b..000000000 --- a/vendor/golang.org/x/net/ipv4/control_test.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv4_test - -import ( - "testing" - - "golang.org/x/net/ipv4" -) - -func TestControlMessageParseWithFuzz(t *testing.T) { - var cm ipv4.ControlMessage - for _, fuzz := range []string{ - "\f\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00", - "\f\x00\x00\x00\x00\x00\x00\x00\x1a\x00\x00\x00", - } { - cm.Parse([]byte(fuzz)) - } -} diff --git a/vendor/golang.org/x/net/ipv4/dgramopt.go b/vendor/golang.org/x/net/ipv4/dgramopt.go index 54d77d5fe..36764492d 100644 --- a/vendor/golang.org/x/net/ipv4/dgramopt.go +++ b/vendor/golang.org/x/net/ipv4/dgramopt.go @@ -6,7 +6,6 @@ package ipv4 import ( "net" - "syscall" "golang.org/x/net/bpf" ) @@ -15,7 +14,7 @@ import ( // multicast packets. func (c *dgramOpt) MulticastTTL() (int, error) { if !c.ok() { - return 0, syscall.EINVAL + return 0, errInvalidConn } so, ok := sockOpts[ssoMulticastTTL] if !ok { @@ -28,7 +27,7 @@ func (c *dgramOpt) MulticastTTL() (int, error) { // outgoing multicast packets. func (c *dgramOpt) SetMulticastTTL(ttl int) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoMulticastTTL] if !ok { @@ -41,7 +40,7 @@ func (c *dgramOpt) SetMulticastTTL(ttl int) error { // packet transmissions. func (c *dgramOpt) MulticastInterface() (*net.Interface, error) { if !c.ok() { - return nil, syscall.EINVAL + return nil, errInvalidConn } so, ok := sockOpts[ssoMulticastInterface] if !ok { @@ -54,7 +53,7 @@ func (c *dgramOpt) MulticastInterface() (*net.Interface, error) { // multicast packet transmissions. func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoMulticastInterface] if !ok { @@ -67,7 +66,7 @@ func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error { // should be copied and send back to the originator. func (c *dgramOpt) MulticastLoopback() (bool, error) { if !c.ok() { - return false, syscall.EINVAL + return false, errInvalidConn } so, ok := sockOpts[ssoMulticastLoopback] if !ok { @@ -84,7 +83,7 @@ func (c *dgramOpt) MulticastLoopback() (bool, error) { // should be copied and send back to the originator. func (c *dgramOpt) SetMulticastLoopback(on bool) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoMulticastLoopback] if !ok { @@ -104,7 +103,7 @@ func (c *dgramOpt) SetMulticastLoopback(on bool) error { // configuration. func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoJoinGroup] if !ok { @@ -122,7 +121,7 @@ func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error { // source-specific group. func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoLeaveGroup] if !ok { @@ -143,7 +142,7 @@ func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error { // routing configuration. func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoJoinSourceGroup] if !ok { @@ -164,7 +163,7 @@ func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net // interface ifi. func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoLeaveSourceGroup] if !ok { @@ -186,7 +185,7 @@ func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source ne // ifi. func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoBlockSourceGroup] if !ok { @@ -207,7 +206,7 @@ func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source // group by ExcludeSourceSpecificGroup again on the interface ifi. func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoUnblockSourceGroup] if !ok { @@ -228,7 +227,7 @@ func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source // Currently only Linux supports this. func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) { if !c.ok() { - return nil, syscall.EINVAL + return nil, errInvalidConn } so, ok := sockOpts[ssoICMPFilter] if !ok { @@ -241,7 +240,7 @@ func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) { // Currently only Linux supports this. func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoICMPFilter] if !ok { @@ -255,7 +254,7 @@ func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error { // Only supported on Linux. func (c *dgramOpt) SetBPF(filter []bpf.RawInstruction) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoAttachFilter] if !ok { diff --git a/vendor/golang.org/x/net/ipv4/doc.go b/vendor/golang.org/x/net/ipv4/doc.go index b43935a5a..863d55b8d 100644 --- a/vendor/golang.org/x/net/ipv4/doc.go +++ b/vendor/golang.org/x/net/ipv4/doc.go @@ -55,7 +55,7 @@ // Multicasting // // The options for multicasting are available for net.UDPConn and -// net.IPconn which are created as network connections that use the +// net.IPConn which are created as network connections that use the // IPv4 transport. A few network facilities must be prepared before // you begin multicasting, at a minimum joining network interfaces and // multicast groups. @@ -241,4 +241,5 @@ // IncludeSourceSpecificGroup may return an error. package ipv4 // import "golang.org/x/net/ipv4" -// BUG(mikio): This package is not implemented on NaCl and Plan 9. +// BUG(mikio): This package is not implemented on AIX, JS, NaCl and +// Plan 9. diff --git a/vendor/golang.org/x/net/ipv4/endpoint.go b/vendor/golang.org/x/net/ipv4/endpoint.go index 2ab877363..500946378 100644 --- a/vendor/golang.org/x/net/ipv4/endpoint.go +++ b/vendor/golang.org/x/net/ipv4/endpoint.go @@ -6,7 +6,6 @@ package ipv4 import ( "net" - "syscall" "time" "golang.org/x/net/internal/socket" @@ -58,7 +57,7 @@ func (c *dgramOpt) ok() bool { return c != nil && c.Conn != nil } // SetControlMessage sets the per packet IP-level socket options. func (c *PacketConn) SetControlMessage(cf ControlFlags, on bool) error { if !c.payloadHandler.ok() { - return syscall.EINVAL + return errInvalidConn } return setControlMessage(c.dgramOpt.Conn, &c.payloadHandler.rawOpt, cf, on) } @@ -67,7 +66,7 @@ func (c *PacketConn) SetControlMessage(cf ControlFlags, on bool) error { // endpoint. func (c *PacketConn) SetDeadline(t time.Time) error { if !c.payloadHandler.ok() { - return syscall.EINVAL + return errInvalidConn } return c.payloadHandler.PacketConn.SetDeadline(t) } @@ -76,7 +75,7 @@ func (c *PacketConn) SetDeadline(t time.Time) error { // endpoint. func (c *PacketConn) SetReadDeadline(t time.Time) error { if !c.payloadHandler.ok() { - return syscall.EINVAL + return errInvalidConn } return c.payloadHandler.PacketConn.SetReadDeadline(t) } @@ -85,7 +84,7 @@ func (c *PacketConn) SetReadDeadline(t time.Time) error { // endpoint. func (c *PacketConn) SetWriteDeadline(t time.Time) error { if !c.payloadHandler.ok() { - return syscall.EINVAL + return errInvalidConn } return c.payloadHandler.PacketConn.SetWriteDeadline(t) } @@ -93,7 +92,7 @@ func (c *PacketConn) SetWriteDeadline(t time.Time) error { // Close closes the endpoint. func (c *PacketConn) Close() error { if !c.payloadHandler.ok() { - return syscall.EINVAL + return errInvalidConn } return c.payloadHandler.PacketConn.Close() } @@ -124,7 +123,7 @@ type RawConn struct { // SetControlMessage sets the per packet IP-level socket options. func (c *RawConn) SetControlMessage(cf ControlFlags, on bool) error { if !c.packetHandler.ok() { - return syscall.EINVAL + return errInvalidConn } return setControlMessage(c.dgramOpt.Conn, &c.packetHandler.rawOpt, cf, on) } @@ -133,7 +132,7 @@ func (c *RawConn) SetControlMessage(cf ControlFlags, on bool) error { // endpoint. func (c *RawConn) SetDeadline(t time.Time) error { if !c.packetHandler.ok() { - return syscall.EINVAL + return errInvalidConn } return c.packetHandler.IPConn.SetDeadline(t) } @@ -142,7 +141,7 @@ func (c *RawConn) SetDeadline(t time.Time) error { // endpoint. func (c *RawConn) SetReadDeadline(t time.Time) error { if !c.packetHandler.ok() { - return syscall.EINVAL + return errInvalidConn } return c.packetHandler.IPConn.SetReadDeadline(t) } @@ -151,7 +150,7 @@ func (c *RawConn) SetReadDeadline(t time.Time) error { // endpoint. func (c *RawConn) SetWriteDeadline(t time.Time) error { if !c.packetHandler.ok() { - return syscall.EINVAL + return errInvalidConn } return c.packetHandler.IPConn.SetWriteDeadline(t) } @@ -159,7 +158,7 @@ func (c *RawConn) SetWriteDeadline(t time.Time) error { // Close closes the endpoint. func (c *RawConn) Close() error { if !c.packetHandler.ok() { - return syscall.EINVAL + return errInvalidConn } return c.packetHandler.IPConn.Close() } diff --git a/vendor/golang.org/x/net/ipv4/example_test.go b/vendor/golang.org/x/net/ipv4/example_test.go deleted file mode 100644 index ddc7577e8..000000000 --- a/vendor/golang.org/x/net/ipv4/example_test.go +++ /dev/null @@ -1,224 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv4_test - -import ( - "fmt" - "log" - "net" - "os" - "runtime" - "time" - - "golang.org/x/net/icmp" - "golang.org/x/net/ipv4" -) - -func ExampleConn_markingTCP() { - ln, err := net.Listen("tcp", "0.0.0.0:1024") - if err != nil { - log.Fatal(err) - } - defer ln.Close() - - for { - c, err := ln.Accept() - if err != nil { - log.Fatal(err) - } - go func(c net.Conn) { - defer c.Close() - if c.RemoteAddr().(*net.TCPAddr).IP.To4() != nil { - p := ipv4.NewConn(c) - if err := p.SetTOS(0x28); err != nil { // DSCP AF11 - log.Fatal(err) - } - if err := p.SetTTL(128); err != nil { - log.Fatal(err) - } - } - if _, err := c.Write([]byte("HELLO-R-U-THERE-ACK")); err != nil { - log.Fatal(err) - } - }(c) - } -} - -func ExamplePacketConn_servingOneShotMulticastDNS() { - c, err := net.ListenPacket("udp4", "0.0.0.0:5353") // mDNS over UDP - if err != nil { - log.Fatal(err) - } - defer c.Close() - p := ipv4.NewPacketConn(c) - - en0, err := net.InterfaceByName("en0") - if err != nil { - log.Fatal(err) - } - mDNSLinkLocal := net.UDPAddr{IP: net.IPv4(224, 0, 0, 251)} - if err := p.JoinGroup(en0, &mDNSLinkLocal); err != nil { - log.Fatal(err) - } - defer p.LeaveGroup(en0, &mDNSLinkLocal) - if err := p.SetControlMessage(ipv4.FlagDst, true); err != nil { - log.Fatal(err) - } - - b := make([]byte, 1500) - for { - _, cm, peer, err := p.ReadFrom(b) - if err != nil { - log.Fatal(err) - } - if !cm.Dst.IsMulticast() || !cm.Dst.Equal(mDNSLinkLocal.IP) { - continue - } - answers := []byte("FAKE-MDNS-ANSWERS") // fake mDNS answers, you need to implement this - if _, err := p.WriteTo(answers, nil, peer); err != nil { - log.Fatal(err) - } - } -} - -func ExamplePacketConn_tracingIPPacketRoute() { - // Tracing an IP packet route to www.google.com. - - const host = "www.google.com" - ips, err := net.LookupIP(host) - if err != nil { - log.Fatal(err) - } - var dst net.IPAddr - for _, ip := range ips { - if ip.To4() != nil { - dst.IP = ip - fmt.Printf("using %v for tracing an IP packet route to %s\n", dst.IP, host) - break - } - } - if dst.IP == nil { - log.Fatal("no A record found") - } - - c, err := net.ListenPacket("ip4:1", "0.0.0.0") // ICMP for IPv4 - if err != nil { - log.Fatal(err) - } - defer c.Close() - p := ipv4.NewPacketConn(c) - - if err := p.SetControlMessage(ipv4.FlagTTL|ipv4.FlagSrc|ipv4.FlagDst|ipv4.FlagInterface, true); err != nil { - log.Fatal(err) - } - wm := icmp.Message{ - Type: ipv4.ICMPTypeEcho, Code: 0, - Body: &icmp.Echo{ - ID: os.Getpid() & 0xffff, - Data: []byte("HELLO-R-U-THERE"), - }, - } - - rb := make([]byte, 1500) - for i := 1; i <= 64; i++ { // up to 64 hops - wm.Body.(*icmp.Echo).Seq = i - wb, err := wm.Marshal(nil) - if err != nil { - log.Fatal(err) - } - if err := p.SetTTL(i); err != nil { - log.Fatal(err) - } - - // In the real world usually there are several - // multiple traffic-engineered paths for each hop. - // You may need to probe a few times to each hop. - begin := time.Now() - if _, err := p.WriteTo(wb, nil, &dst); err != nil { - log.Fatal(err) - } - if err := p.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil { - log.Fatal(err) - } - n, cm, peer, err := p.ReadFrom(rb) - if err != nil { - if err, ok := err.(net.Error); ok && err.Timeout() { - fmt.Printf("%v\t*\n", i) - continue - } - log.Fatal(err) - } - rm, err := icmp.ParseMessage(1, rb[:n]) - if err != nil { - log.Fatal(err) - } - rtt := time.Since(begin) - - // In the real world you need to determine whether the - // received message is yours using ControlMessage.Src, - // ControlMessage.Dst, icmp.Echo.ID and icmp.Echo.Seq. - switch rm.Type { - case ipv4.ICMPTypeTimeExceeded: - names, _ := net.LookupAddr(peer.String()) - fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, cm) - case ipv4.ICMPTypeEchoReply: - names, _ := net.LookupAddr(peer.String()) - fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, cm) - return - default: - log.Printf("unknown ICMP message: %+v\n", rm) - } - } -} - -func ExampleRawConn_advertisingOSPFHello() { - c, err := net.ListenPacket("ip4:89", "0.0.0.0") // OSPF for IPv4 - if err != nil { - log.Fatal(err) - } - defer c.Close() - r, err := ipv4.NewRawConn(c) - if err != nil { - log.Fatal(err) - } - - en0, err := net.InterfaceByName("en0") - if err != nil { - log.Fatal(err) - } - allSPFRouters := net.IPAddr{IP: net.IPv4(224, 0, 0, 5)} - if err := r.JoinGroup(en0, &allSPFRouters); err != nil { - log.Fatal(err) - } - defer r.LeaveGroup(en0, &allSPFRouters) - - hello := make([]byte, 24) // fake hello data, you need to implement this - ospf := make([]byte, 24) // fake ospf header, you need to implement this - ospf[0] = 2 // version 2 - ospf[1] = 1 // hello packet - ospf = append(ospf, hello...) - iph := &ipv4.Header{ - Version: ipv4.Version, - Len: ipv4.HeaderLen, - TOS: 0xc0, // DSCP CS6 - TotalLen: ipv4.HeaderLen + len(ospf), - TTL: 1, - Protocol: 89, - Dst: allSPFRouters.IP.To4(), - } - - var cm *ipv4.ControlMessage - switch runtime.GOOS { - case "darwin", "linux": - cm = &ipv4.ControlMessage{IfIndex: en0.Index} - default: - if err := r.SetMulticastInterface(en0); err != nil { - log.Fatal(err) - } - } - if err := r.WriteTo(iph, ospf, cm); err != nil { - log.Fatal(err) - } -} diff --git a/vendor/golang.org/x/net/ipv4/gen.go b/vendor/golang.org/x/net/ipv4/gen.go index 9d490fac9..1bb1737f6 100644 --- a/vendor/golang.org/x/net/ipv4/gen.go +++ b/vendor/golang.org/x/net/ipv4/gen.go @@ -80,7 +80,7 @@ var registries = []struct { func geniana() error { var bb bytes.Buffer fmt.Fprintf(&bb, "// go generate gen.go\n") - fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n") + fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n") fmt.Fprintf(&bb, "package ipv4\n\n") for _, r := range registries { resp, err := http.Get(r.url) diff --git a/vendor/golang.org/x/net/ipv4/genericopt.go b/vendor/golang.org/x/net/ipv4/genericopt.go index 119bf841b..587ae4a19 100644 --- a/vendor/golang.org/x/net/ipv4/genericopt.go +++ b/vendor/golang.org/x/net/ipv4/genericopt.go @@ -4,12 +4,10 @@ package ipv4 -import "syscall" - // TOS returns the type-of-service field value for outgoing packets. func (c *genericOpt) TOS() (int, error) { if !c.ok() { - return 0, syscall.EINVAL + return 0, errInvalidConn } so, ok := sockOpts[ssoTOS] if !ok { @@ -22,7 +20,7 @@ func (c *genericOpt) TOS() (int, error) { // packets. func (c *genericOpt) SetTOS(tos int) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoTOS] if !ok { @@ -34,7 +32,7 @@ func (c *genericOpt) SetTOS(tos int) error { // TTL returns the time-to-live field value for outgoing packets. func (c *genericOpt) TTL() (int, error) { if !c.ok() { - return 0, syscall.EINVAL + return 0, errInvalidConn } so, ok := sockOpts[ssoTTL] if !ok { @@ -47,7 +45,7 @@ func (c *genericOpt) TTL() (int, error) { // packets. func (c *genericOpt) SetTTL(ttl int) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoTTL] if !ok { diff --git a/vendor/golang.org/x/net/ipv4/header.go b/vendor/golang.org/x/net/ipv4/header.go index 8bb0f0f4d..a8c8f7a6c 100644 --- a/vendor/golang.org/x/net/ipv4/header.go +++ b/vendor/golang.org/x/net/ipv4/header.go @@ -9,7 +9,6 @@ import ( "fmt" "net" "runtime" - "syscall" "golang.org/x/net/internal/socket" ) @@ -52,9 +51,13 @@ func (h *Header) String() string { } // Marshal returns the binary encoding of h. +// +// The returned slice is in the format used by a raw IP socket on the +// local system. +// This may differ from the wire format, depending on the system. func (h *Header) Marshal() ([]byte, error) { if h == nil { - return nil, syscall.EINVAL + return nil, errInvalidConn } if h.Len < HeaderLen { return nil, errHeaderTooShort @@ -98,7 +101,11 @@ func (h *Header) Marshal() ([]byte, error) { return b, nil } -// Parse parses b as an IPv4 header and sotres the result in h. +// Parse parses b as an IPv4 header and stores the result in h. +// +// The provided b must be in the format used by a raw IP socket on the +// local system. +// This may differ from the wire format, depending on the system. func (h *Header) Parse(b []byte) error { if h == nil || len(b) < HeaderLen { return errHeaderTooShort @@ -150,6 +157,10 @@ func (h *Header) Parse(b []byte) error { } // ParseHeader parses b as an IPv4 header. +// +// The provided b must be in the format used by a raw IP socket on the +// local system. +// This may differ from the wire format, depending on the system. func ParseHeader(b []byte) (*Header, error) { h := new(Header) if err := h.Parse(b); err != nil { diff --git a/vendor/golang.org/x/net/ipv4/header_test.go b/vendor/golang.org/x/net/ipv4/header_test.go deleted file mode 100644 index a246aeea1..000000000 --- a/vendor/golang.org/x/net/ipv4/header_test.go +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv4 - -import ( - "bytes" - "encoding/binary" - "net" - "reflect" - "runtime" - "strings" - "testing" - - "golang.org/x/net/internal/socket" -) - -type headerTest struct { - wireHeaderFromKernel []byte - wireHeaderToKernel []byte - wireHeaderFromTradBSDKernel []byte - wireHeaderToTradBSDKernel []byte - wireHeaderFromFreeBSD10Kernel []byte - wireHeaderToFreeBSD10Kernel []byte - *Header -} - -var headerLittleEndianTests = []headerTest{ - // TODO(mikio): Add platform dependent wire header formats when - // we support new platforms. - { - wireHeaderFromKernel: []byte{ - 0x45, 0x01, 0xbe, 0xef, - 0xca, 0xfe, 0x45, 0xdc, - 0xff, 0x01, 0xde, 0xad, - 172, 16, 254, 254, - 192, 168, 0, 1, - }, - wireHeaderToKernel: []byte{ - 0x45, 0x01, 0xbe, 0xef, - 0xca, 0xfe, 0x45, 0xdc, - 0xff, 0x01, 0xde, 0xad, - 172, 16, 254, 254, - 192, 168, 0, 1, - }, - wireHeaderFromTradBSDKernel: []byte{ - 0x45, 0x01, 0xdb, 0xbe, - 0xca, 0xfe, 0xdc, 0x45, - 0xff, 0x01, 0xde, 0xad, - 172, 16, 254, 254, - 192, 168, 0, 1, - }, - wireHeaderToTradBSDKernel: []byte{ - 0x45, 0x01, 0xef, 0xbe, - 0xca, 0xfe, 0xdc, 0x45, - 0xff, 0x01, 0xde, 0xad, - 172, 16, 254, 254, - 192, 168, 0, 1, - }, - wireHeaderFromFreeBSD10Kernel: []byte{ - 0x45, 0x01, 0xef, 0xbe, - 0xca, 0xfe, 0xdc, 0x45, - 0xff, 0x01, 0xde, 0xad, - 172, 16, 254, 254, - 192, 168, 0, 1, - }, - wireHeaderToFreeBSD10Kernel: []byte{ - 0x45, 0x01, 0xef, 0xbe, - 0xca, 0xfe, 0xdc, 0x45, - 0xff, 0x01, 0xde, 0xad, - 172, 16, 254, 254, - 192, 168, 0, 1, - }, - Header: &Header{ - Version: Version, - Len: HeaderLen, - TOS: 1, - TotalLen: 0xbeef, - ID: 0xcafe, - Flags: DontFragment, - FragOff: 1500, - TTL: 255, - Protocol: 1, - Checksum: 0xdead, - Src: net.IPv4(172, 16, 254, 254), - Dst: net.IPv4(192, 168, 0, 1), - }, - }, - - // with option headers - { - wireHeaderFromKernel: []byte{ - 0x46, 0x01, 0xbe, 0xf3, - 0xca, 0xfe, 0x45, 0xdc, - 0xff, 0x01, 0xde, 0xad, - 172, 16, 254, 254, - 192, 168, 0, 1, - 0xff, 0xfe, 0xfe, 0xff, - }, - wireHeaderToKernel: []byte{ - 0x46, 0x01, 0xbe, 0xf3, - 0xca, 0xfe, 0x45, 0xdc, - 0xff, 0x01, 0xde, 0xad, - 172, 16, 254, 254, - 192, 168, 0, 1, - 0xff, 0xfe, 0xfe, 0xff, - }, - wireHeaderFromTradBSDKernel: []byte{ - 0x46, 0x01, 0xdb, 0xbe, - 0xca, 0xfe, 0xdc, 0x45, - 0xff, 0x01, 0xde, 0xad, - 172, 16, 254, 254, - 192, 168, 0, 1, - 0xff, 0xfe, 0xfe, 0xff, - }, - wireHeaderToTradBSDKernel: []byte{ - 0x46, 0x01, 0xf3, 0xbe, - 0xca, 0xfe, 0xdc, 0x45, - 0xff, 0x01, 0xde, 0xad, - 172, 16, 254, 254, - 192, 168, 0, 1, - 0xff, 0xfe, 0xfe, 0xff, - }, - wireHeaderFromFreeBSD10Kernel: []byte{ - 0x46, 0x01, 0xf3, 0xbe, - 0xca, 0xfe, 0xdc, 0x45, - 0xff, 0x01, 0xde, 0xad, - 172, 16, 254, 254, - 192, 168, 0, 1, - 0xff, 0xfe, 0xfe, 0xff, - }, - wireHeaderToFreeBSD10Kernel: []byte{ - 0x46, 0x01, 0xf3, 0xbe, - 0xca, 0xfe, 0xdc, 0x45, - 0xff, 0x01, 0xde, 0xad, - 172, 16, 254, 254, - 192, 168, 0, 1, - 0xff, 0xfe, 0xfe, 0xff, - }, - Header: &Header{ - Version: Version, - Len: HeaderLen + 4, - TOS: 1, - TotalLen: 0xbef3, - ID: 0xcafe, - Flags: DontFragment, - FragOff: 1500, - TTL: 255, - Protocol: 1, - Checksum: 0xdead, - Src: net.IPv4(172, 16, 254, 254), - Dst: net.IPv4(192, 168, 0, 1), - Options: []byte{0xff, 0xfe, 0xfe, 0xff}, - }, - }, -} - -func TestMarshalHeader(t *testing.T) { - if socket.NativeEndian != binary.LittleEndian { - t.Skip("no test for non-little endian machine yet") - } - - for _, tt := range headerLittleEndianTests { - b, err := tt.Header.Marshal() - if err != nil { - t.Fatal(err) - } - var wh []byte - switch runtime.GOOS { - case "darwin", "dragonfly", "netbsd": - wh = tt.wireHeaderToTradBSDKernel - case "freebsd": - switch { - case freebsdVersion < 1000000: - wh = tt.wireHeaderToTradBSDKernel - case 1000000 <= freebsdVersion && freebsdVersion < 1100000: - wh = tt.wireHeaderToFreeBSD10Kernel - default: - wh = tt.wireHeaderToKernel - } - default: - wh = tt.wireHeaderToKernel - } - if !bytes.Equal(b, wh) { - t.Fatalf("got %#v; want %#v", b, wh) - } - } -} - -func TestParseHeader(t *testing.T) { - if socket.NativeEndian != binary.LittleEndian { - t.Skip("no test for big endian machine yet") - } - - for _, tt := range headerLittleEndianTests { - var wh []byte - switch runtime.GOOS { - case "darwin", "dragonfly", "netbsd": - wh = tt.wireHeaderFromTradBSDKernel - case "freebsd": - switch { - case freebsdVersion < 1000000: - wh = tt.wireHeaderFromTradBSDKernel - case 1000000 <= freebsdVersion && freebsdVersion < 1100000: - wh = tt.wireHeaderFromFreeBSD10Kernel - default: - wh = tt.wireHeaderFromKernel - } - default: - wh = tt.wireHeaderFromKernel - } - h, err := ParseHeader(wh) - if err != nil { - t.Fatal(err) - } - if err := h.Parse(wh); err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(h, tt.Header) { - t.Fatalf("got %#v; want %#v", h, tt.Header) - } - s := h.String() - if strings.Contains(s, ",") { - t.Fatalf("should be space-separated values: %s", s) - } - } -} diff --git a/vendor/golang.org/x/net/ipv4/helper.go b/vendor/golang.org/x/net/ipv4/helper.go index a5052e324..8d8ff98e9 100644 --- a/vendor/golang.org/x/net/ipv4/helper.go +++ b/vendor/golang.org/x/net/ipv4/helper.go @@ -10,6 +10,7 @@ import ( ) var ( + errInvalidConn = errors.New("invalid connection") errMissingAddress = errors.New("missing address") errMissingHeader = errors.New("missing header") errHeaderTooShort = errors.New("header too short") diff --git a/vendor/golang.org/x/net/ipv4/iana.go b/vendor/golang.org/x/net/ipv4/iana.go index be10c9488..4375b4099 100644 --- a/vendor/golang.org/x/net/ipv4/iana.go +++ b/vendor/golang.org/x/net/ipv4/iana.go @@ -1,9 +1,9 @@ // go generate gen.go -// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT +// Code generated by the command above; DO NOT EDIT. package ipv4 -// Internet Control Message Protocol (ICMP) Parameters, Updated: 2013-04-19 +// Internet Control Message Protocol (ICMP) Parameters, Updated: 2018-02-26 const ( ICMPTypeEchoReply ICMPType = 0 // Echo Reply ICMPTypeDestinationUnreachable ICMPType = 3 // Destination Unreachable @@ -16,9 +16,11 @@ const ( ICMPTypeTimestamp ICMPType = 13 // Timestamp ICMPTypeTimestampReply ICMPType = 14 // Timestamp Reply ICMPTypePhoturis ICMPType = 40 // Photuris + ICMPTypeExtendedEchoRequest ICMPType = 42 // Extended Echo Request + ICMPTypeExtendedEchoReply ICMPType = 43 // Extended Echo Reply ) -// Internet Control Message Protocol (ICMP) Parameters, Updated: 2013-04-19 +// Internet Control Message Protocol (ICMP) Parameters, Updated: 2018-02-26 var icmpTypes = map[ICMPType]string{ 0: "echo reply", 3: "destination unreachable", @@ -31,4 +33,6 @@ var icmpTypes = map[ICMPType]string{ 13: "timestamp", 14: "timestamp reply", 40: "photuris", + 42: "extended echo request", + 43: "extended echo reply", } diff --git a/vendor/golang.org/x/net/ipv4/icmp_test.go b/vendor/golang.org/x/net/ipv4/icmp_test.go deleted file mode 100644 index 3324b54df..000000000 --- a/vendor/golang.org/x/net/ipv4/icmp_test.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv4_test - -import ( - "net" - "reflect" - "runtime" - "testing" - - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv4" -) - -var icmpStringTests = []struct { - in ipv4.ICMPType - out string -}{ - {ipv4.ICMPTypeDestinationUnreachable, "destination unreachable"}, - - {256, ""}, -} - -func TestICMPString(t *testing.T) { - for _, tt := range icmpStringTests { - s := tt.in.String() - if s != tt.out { - t.Errorf("got %s; want %s", s, tt.out) - } - } -} - -func TestICMPFilter(t *testing.T) { - switch runtime.GOOS { - case "linux": - default: - t.Skipf("not supported on %s", runtime.GOOS) - } - - var f ipv4.ICMPFilter - for _, toggle := range []bool{false, true} { - f.SetAll(toggle) - for _, typ := range []ipv4.ICMPType{ - ipv4.ICMPTypeDestinationUnreachable, - ipv4.ICMPTypeEchoReply, - ipv4.ICMPTypeTimeExceeded, - ipv4.ICMPTypeParameterProblem, - } { - f.Accept(typ) - if f.WillBlock(typ) { - t.Errorf("ipv4.ICMPFilter.Set(%v, false) failed", typ) - } - f.Block(typ) - if !f.WillBlock(typ) { - t.Errorf("ipv4.ICMPFilter.Set(%v, true) failed", typ) - } - } - } -} - -func TestSetICMPFilter(t *testing.T) { - switch runtime.GOOS { - case "linux": - default: - t.Skipf("not supported on %s", runtime.GOOS) - } - if m, ok := nettest.SupportsRawIPSocket(); !ok { - t.Skip(m) - } - - c, err := net.ListenPacket("ip4:icmp", "127.0.0.1") - if err != nil { - t.Fatal(err) - } - defer c.Close() - - p := ipv4.NewPacketConn(c) - - var f ipv4.ICMPFilter - f.SetAll(true) - f.Accept(ipv4.ICMPTypeEcho) - f.Accept(ipv4.ICMPTypeEchoReply) - if err := p.SetICMPFilter(&f); err != nil { - t.Fatal(err) - } - kf, err := p.ICMPFilter() - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(kf, &f) { - t.Fatalf("got %#v; want %#v", kf, f) - } -} diff --git a/vendor/golang.org/x/net/ipv4/multicast_test.go b/vendor/golang.org/x/net/ipv4/multicast_test.go deleted file mode 100644 index bcf49736b..000000000 --- a/vendor/golang.org/x/net/ipv4/multicast_test.go +++ /dev/null @@ -1,334 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv4_test - -import ( - "bytes" - "net" - "os" - "runtime" - "testing" - "time" - - "golang.org/x/net/icmp" - "golang.org/x/net/internal/iana" - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv4" -) - -var packetConnReadWriteMulticastUDPTests = []struct { - addr string - grp, src *net.UDPAddr -}{ - {"224.0.0.0:0", &net.UDPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727 - - {"232.0.1.0:0", &net.UDPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771 -} - -func TestPacketConnReadWriteMulticastUDP(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "solaris", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) - if ifi == nil { - t.Skipf("not available on %s", runtime.GOOS) - } - - for _, tt := range packetConnReadWriteMulticastUDPTests { - c, err := net.ListenPacket("udp4", tt.addr) - if err != nil { - t.Fatal(err) - } - defer c.Close() - - grp := *tt.grp - grp.Port = c.LocalAddr().(*net.UDPAddr).Port - p := ipv4.NewPacketConn(c) - defer p.Close() - if tt.src == nil { - if err := p.JoinGroup(ifi, &grp); err != nil { - t.Fatal(err) - } - defer p.LeaveGroup(ifi, &grp) - } else { - if err := p.JoinSourceSpecificGroup(ifi, &grp, tt.src); err != nil { - switch runtime.GOOS { - case "freebsd", "linux": - default: // platforms that don't support IGMPv2/3 fail here - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } - defer p.LeaveSourceSpecificGroup(ifi, &grp, tt.src) - } - if err := p.SetMulticastInterface(ifi); err != nil { - t.Fatal(err) - } - if _, err := p.MulticastInterface(); err != nil { - t.Fatal(err) - } - if err := p.SetMulticastLoopback(true); err != nil { - t.Fatal(err) - } - if _, err := p.MulticastLoopback(); err != nil { - t.Fatal(err) - } - cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface - wb := []byte("HELLO-R-U-THERE") - - for i, toggle := range []bool{true, false, true} { - if err := p.SetControlMessage(cf, toggle); err != nil { - if nettest.ProtocolNotSupported(err) { - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } - if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil { - t.Fatal(err) - } - p.SetMulticastTTL(i + 1) - if n, err := p.WriteTo(wb, nil, &grp); err != nil { - t.Fatal(err) - } else if n != len(wb) { - t.Fatalf("got %v; want %v", n, len(wb)) - } - rb := make([]byte, 128) - if n, _, _, err := p.ReadFrom(rb); err != nil { - t.Fatal(err) - } else if !bytes.Equal(rb[:n], wb) { - t.Fatalf("got %v; want %v", rb[:n], wb) - } - } - } -} - -var packetConnReadWriteMulticastICMPTests = []struct { - grp, src *net.IPAddr -}{ - {&net.IPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727 - - {&net.IPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771 -} - -func TestPacketConnReadWriteMulticastICMP(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "solaris", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if m, ok := nettest.SupportsRawIPSocket(); !ok { - t.Skip(m) - } - ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) - if ifi == nil { - t.Skipf("not available on %s", runtime.GOOS) - } - - for _, tt := range packetConnReadWriteMulticastICMPTests { - c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") - if err != nil { - t.Fatal(err) - } - defer c.Close() - - p := ipv4.NewPacketConn(c) - defer p.Close() - if tt.src == nil { - if err := p.JoinGroup(ifi, tt.grp); err != nil { - t.Fatal(err) - } - defer p.LeaveGroup(ifi, tt.grp) - } else { - if err := p.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil { - switch runtime.GOOS { - case "freebsd", "linux": - default: // platforms that don't support IGMPv2/3 fail here - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } - defer p.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src) - } - if err := p.SetMulticastInterface(ifi); err != nil { - t.Fatal(err) - } - if _, err := p.MulticastInterface(); err != nil { - t.Fatal(err) - } - if err := p.SetMulticastLoopback(true); err != nil { - t.Fatal(err) - } - if _, err := p.MulticastLoopback(); err != nil { - t.Fatal(err) - } - cf := ipv4.FlagDst | ipv4.FlagInterface - if runtime.GOOS != "solaris" { - // Solaris never allows to modify ICMP properties. - cf |= ipv4.FlagTTL - } - - for i, toggle := range []bool{true, false, true} { - wb, err := (&icmp.Message{ - Type: ipv4.ICMPTypeEcho, Code: 0, - Body: &icmp.Echo{ - ID: os.Getpid() & 0xffff, Seq: i + 1, - Data: []byte("HELLO-R-U-THERE"), - }, - }).Marshal(nil) - if err != nil { - t.Fatal(err) - } - if err := p.SetControlMessage(cf, toggle); err != nil { - if nettest.ProtocolNotSupported(err) { - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } - if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil { - t.Fatal(err) - } - p.SetMulticastTTL(i + 1) - if n, err := p.WriteTo(wb, nil, tt.grp); err != nil { - t.Fatal(err) - } else if n != len(wb) { - t.Fatalf("got %v; want %v", n, len(wb)) - } - rb := make([]byte, 128) - if n, _, _, err := p.ReadFrom(rb); err != nil { - t.Fatal(err) - } else { - m, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n]) - if err != nil { - t.Fatal(err) - } - switch { - case m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1 - case m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0 - default: - t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0) - } - } - } - } -} - -var rawConnReadWriteMulticastICMPTests = []struct { - grp, src *net.IPAddr -}{ - {&net.IPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727 - - {&net.IPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771 -} - -func TestRawConnReadWriteMulticastICMP(t *testing.T) { - if testing.Short() { - t.Skip("to avoid external network") - } - if m, ok := nettest.SupportsRawIPSocket(); !ok { - t.Skip(m) - } - ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) - if ifi == nil { - t.Skipf("not available on %s", runtime.GOOS) - } - - for _, tt := range rawConnReadWriteMulticastICMPTests { - c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") - if err != nil { - t.Fatal(err) - } - defer c.Close() - - r, err := ipv4.NewRawConn(c) - if err != nil { - t.Fatal(err) - } - defer r.Close() - if tt.src == nil { - if err := r.JoinGroup(ifi, tt.grp); err != nil { - t.Fatal(err) - } - defer r.LeaveGroup(ifi, tt.grp) - } else { - if err := r.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil { - switch runtime.GOOS { - case "freebsd", "linux": - default: // platforms that don't support IGMPv2/3 fail here - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } - defer r.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src) - } - if err := r.SetMulticastInterface(ifi); err != nil { - t.Fatal(err) - } - if _, err := r.MulticastInterface(); err != nil { - t.Fatal(err) - } - if err := r.SetMulticastLoopback(true); err != nil { - t.Fatal(err) - } - if _, err := r.MulticastLoopback(); err != nil { - t.Fatal(err) - } - cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface - - for i, toggle := range []bool{true, false, true} { - wb, err := (&icmp.Message{ - Type: ipv4.ICMPTypeEcho, Code: 0, - Body: &icmp.Echo{ - ID: os.Getpid() & 0xffff, Seq: i + 1, - Data: []byte("HELLO-R-U-THERE"), - }, - }).Marshal(nil) - if err != nil { - t.Fatal(err) - } - wh := &ipv4.Header{ - Version: ipv4.Version, - Len: ipv4.HeaderLen, - TOS: i + 1, - TotalLen: ipv4.HeaderLen + len(wb), - Protocol: 1, - Dst: tt.grp.IP, - } - if err := r.SetControlMessage(cf, toggle); err != nil { - if nettest.ProtocolNotSupported(err) { - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } - if err := r.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil { - t.Fatal(err) - } - r.SetMulticastTTL(i + 1) - if err := r.WriteTo(wh, wb, nil); err != nil { - t.Fatal(err) - } - rb := make([]byte, ipv4.HeaderLen+128) - if rh, b, _, err := r.ReadFrom(rb); err != nil { - t.Fatal(err) - } else { - m, err := icmp.ParseMessage(iana.ProtocolICMP, b) - if err != nil { - t.Fatal(err) - } - switch { - case (rh.Dst.IsLoopback() || rh.Dst.IsLinkLocalUnicast() || rh.Dst.IsGlobalUnicast()) && m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1 - case rh.Dst.IsMulticast() && m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0 - default: - t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0) - } - } - } - } -} diff --git a/vendor/golang.org/x/net/ipv4/multicastlistener_test.go b/vendor/golang.org/x/net/ipv4/multicastlistener_test.go deleted file mode 100644 index e43fbbe08..000000000 --- a/vendor/golang.org/x/net/ipv4/multicastlistener_test.go +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv4_test - -import ( - "net" - "runtime" - "testing" - - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv4" -) - -var udpMultipleGroupListenerTests = []net.Addr{ - &net.UDPAddr{IP: net.IPv4(224, 0, 0, 249)}, // see RFC 4727 - &net.UDPAddr{IP: net.IPv4(224, 0, 0, 250)}, - &net.UDPAddr{IP: net.IPv4(224, 0, 0, 254)}, -} - -func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if testing.Short() { - t.Skip("to avoid external network") - } - - for _, gaddr := range udpMultipleGroupListenerTests { - c, err := net.ListenPacket("udp4", "0.0.0.0:0") // wildcard address with no reusable port - if err != nil { - t.Fatal(err) - } - defer c.Close() - - p := ipv4.NewPacketConn(c) - var mift []*net.Interface - - ift, err := net.Interfaces() - if err != nil { - t.Fatal(err) - } - for i, ifi := range ift { - if _, ok := nettest.IsMulticastCapable("ip4", &ifi); !ok { - continue - } - if err := p.JoinGroup(&ifi, gaddr); err != nil { - t.Fatal(err) - } - mift = append(mift, &ift[i]) - } - for _, ifi := range mift { - if err := p.LeaveGroup(ifi, gaddr); err != nil { - t.Fatal(err) - } - } - } -} - -func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if testing.Short() { - t.Skip("to avoid external network") - } - - for _, gaddr := range udpMultipleGroupListenerTests { - c1, err := net.ListenPacket("udp4", "224.0.0.0:0") // wildcard address with reusable port - if err != nil { - t.Fatal(err) - } - defer c1.Close() - _, port, err := net.SplitHostPort(c1.LocalAddr().String()) - if err != nil { - t.Fatal(err) - } - c2, err := net.ListenPacket("udp4", net.JoinHostPort("224.0.0.0", port)) // wildcard address with reusable port - if err != nil { - t.Fatal(err) - } - defer c2.Close() - - var ps [2]*ipv4.PacketConn - ps[0] = ipv4.NewPacketConn(c1) - ps[1] = ipv4.NewPacketConn(c2) - var mift []*net.Interface - - ift, err := net.Interfaces() - if err != nil { - t.Fatal(err) - } - for i, ifi := range ift { - if _, ok := nettest.IsMulticastCapable("ip4", &ifi); !ok { - continue - } - for _, p := range ps { - if err := p.JoinGroup(&ifi, gaddr); err != nil { - t.Fatal(err) - } - } - mift = append(mift, &ift[i]) - } - for _, ifi := range mift { - for _, p := range ps { - if err := p.LeaveGroup(ifi, gaddr); err != nil { - t.Fatal(err) - } - } - } - } -} - -func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if testing.Short() { - t.Skip("to avoid external network") - } - - gaddr := net.IPAddr{IP: net.IPv4(224, 0, 0, 254)} // see RFC 4727 - type ml struct { - c *ipv4.PacketConn - ifi *net.Interface - } - var mlt []*ml - - ift, err := net.Interfaces() - if err != nil { - t.Fatal(err) - } - port := "0" - for i, ifi := range ift { - ip, ok := nettest.IsMulticastCapable("ip4", &ifi) - if !ok { - continue - } - c, err := net.ListenPacket("udp4", net.JoinHostPort(ip.String(), port)) // unicast address with non-reusable port - if err != nil { - // The listen may fail when the serivce is - // already in use, but it's fine because the - // purpose of this is not to test the - // bookkeeping of IP control block inside the - // kernel. - t.Log(err) - continue - } - defer c.Close() - if port == "0" { - _, port, err = net.SplitHostPort(c.LocalAddr().String()) - if err != nil { - t.Fatal(err) - } - } - p := ipv4.NewPacketConn(c) - if err := p.JoinGroup(&ifi, &gaddr); err != nil { - t.Fatal(err) - } - mlt = append(mlt, &ml{p, &ift[i]}) - } - for _, m := range mlt { - if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil { - t.Fatal(err) - } - } -} - -func TestIPSingleRawConnWithSingleGroupListener(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if testing.Short() { - t.Skip("to avoid external network") - } - if m, ok := nettest.SupportsRawIPSocket(); !ok { - t.Skip(m) - } - - c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") // wildcard address - if err != nil { - t.Fatal(err) - } - defer c.Close() - - r, err := ipv4.NewRawConn(c) - if err != nil { - t.Fatal(err) - } - gaddr := net.IPAddr{IP: net.IPv4(224, 0, 0, 254)} // see RFC 4727 - var mift []*net.Interface - - ift, err := net.Interfaces() - if err != nil { - t.Fatal(err) - } - for i, ifi := range ift { - if _, ok := nettest.IsMulticastCapable("ip4", &ifi); !ok { - continue - } - if err := r.JoinGroup(&ifi, &gaddr); err != nil { - t.Fatal(err) - } - mift = append(mift, &ift[i]) - } - for _, ifi := range mift { - if err := r.LeaveGroup(ifi, &gaddr); err != nil { - t.Fatal(err) - } - } -} - -func TestIPPerInterfaceSingleRawConnWithSingleGroupListener(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if testing.Short() { - t.Skip("to avoid external network") - } - if m, ok := nettest.SupportsRawIPSocket(); !ok { - t.Skip(m) - } - - gaddr := net.IPAddr{IP: net.IPv4(224, 0, 0, 254)} // see RFC 4727 - type ml struct { - c *ipv4.RawConn - ifi *net.Interface - } - var mlt []*ml - - ift, err := net.Interfaces() - if err != nil { - t.Fatal(err) - } - for i, ifi := range ift { - ip, ok := nettest.IsMulticastCapable("ip4", &ifi) - if !ok { - continue - } - c, err := net.ListenPacket("ip4:253", ip.String()) // unicast address - if err != nil { - t.Fatal(err) - } - defer c.Close() - r, err := ipv4.NewRawConn(c) - if err != nil { - t.Fatal(err) - } - if err := r.JoinGroup(&ifi, &gaddr); err != nil { - t.Fatal(err) - } - mlt = append(mlt, &ml{r, &ift[i]}) - } - for _, m := range mlt { - if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil { - t.Fatal(err) - } - } -} diff --git a/vendor/golang.org/x/net/ipv4/multicastsockopt_test.go b/vendor/golang.org/x/net/ipv4/multicastsockopt_test.go deleted file mode 100644 index f7efac24c..000000000 --- a/vendor/golang.org/x/net/ipv4/multicastsockopt_test.go +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv4_test - -import ( - "net" - "runtime" - "testing" - - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv4" -) - -var packetConnMulticastSocketOptionTests = []struct { - net, proto, addr string - grp, src net.Addr -}{ - {"udp4", "", "224.0.0.0:0", &net.UDPAddr{IP: net.IPv4(224, 0, 0, 249)}, nil}, // see RFC 4727 - {"ip4", ":icmp", "0.0.0.0", &net.IPAddr{IP: net.IPv4(224, 0, 0, 250)}, nil}, // see RFC 4727 - - {"udp4", "", "232.0.0.0:0", &net.UDPAddr{IP: net.IPv4(232, 0, 1, 249)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771 - {"ip4", ":icmp", "0.0.0.0", &net.IPAddr{IP: net.IPv4(232, 0, 1, 250)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771 -} - -func TestPacketConnMulticastSocketOptions(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9": - t.Skipf("not supported on %s", runtime.GOOS) - } - ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) - if ifi == nil { - t.Skipf("not available on %s", runtime.GOOS) - } - - m, ok := nettest.SupportsRawIPSocket() - for _, tt := range packetConnMulticastSocketOptionTests { - if tt.net == "ip4" && !ok { - t.Log(m) - continue - } - c, err := net.ListenPacket(tt.net+tt.proto, tt.addr) - if err != nil { - t.Fatal(err) - } - defer c.Close() - p := ipv4.NewPacketConn(c) - defer p.Close() - - if tt.src == nil { - testMulticastSocketOptions(t, p, ifi, tt.grp) - } else { - testSourceSpecificMulticastSocketOptions(t, p, ifi, tt.grp, tt.src) - } - } -} - -var rawConnMulticastSocketOptionTests = []struct { - grp, src net.Addr -}{ - {&net.IPAddr{IP: net.IPv4(224, 0, 0, 250)}, nil}, // see RFC 4727 - - {&net.IPAddr{IP: net.IPv4(232, 0, 1, 250)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771 -} - -func TestRawConnMulticastSocketOptions(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9": - t.Skipf("not supported on %s", runtime.GOOS) - } - if m, ok := nettest.SupportsRawIPSocket(); !ok { - t.Skip(m) - } - ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) - if ifi == nil { - t.Skipf("not available on %s", runtime.GOOS) - } - - for _, tt := range rawConnMulticastSocketOptionTests { - c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") - if err != nil { - t.Fatal(err) - } - defer c.Close() - r, err := ipv4.NewRawConn(c) - if err != nil { - t.Fatal(err) - } - defer r.Close() - - if tt.src == nil { - testMulticastSocketOptions(t, r, ifi, tt.grp) - } else { - testSourceSpecificMulticastSocketOptions(t, r, ifi, tt.grp, tt.src) - } - } -} - -type testIPv4MulticastConn interface { - MulticastTTL() (int, error) - SetMulticastTTL(ttl int) error - MulticastLoopback() (bool, error) - SetMulticastLoopback(bool) error - JoinGroup(*net.Interface, net.Addr) error - LeaveGroup(*net.Interface, net.Addr) error - JoinSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error - LeaveSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error - ExcludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error - IncludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error -} - -func testMulticastSocketOptions(t *testing.T, c testIPv4MulticastConn, ifi *net.Interface, grp net.Addr) { - const ttl = 255 - if err := c.SetMulticastTTL(ttl); err != nil { - t.Error(err) - return - } - if v, err := c.MulticastTTL(); err != nil { - t.Error(err) - return - } else if v != ttl { - t.Errorf("got %v; want %v", v, ttl) - return - } - - for _, toggle := range []bool{true, false} { - if err := c.SetMulticastLoopback(toggle); err != nil { - t.Error(err) - return - } - if v, err := c.MulticastLoopback(); err != nil { - t.Error(err) - return - } else if v != toggle { - t.Errorf("got %v; want %v", v, toggle) - return - } - } - - if err := c.JoinGroup(ifi, grp); err != nil { - t.Error(err) - return - } - if err := c.LeaveGroup(ifi, grp); err != nil { - t.Error(err) - return - } -} - -func testSourceSpecificMulticastSocketOptions(t *testing.T, c testIPv4MulticastConn, ifi *net.Interface, grp, src net.Addr) { - // MCAST_JOIN_GROUP -> MCAST_BLOCK_SOURCE -> MCAST_UNBLOCK_SOURCE -> MCAST_LEAVE_GROUP - if err := c.JoinGroup(ifi, grp); err != nil { - t.Error(err) - return - } - if err := c.ExcludeSourceSpecificGroup(ifi, grp, src); err != nil { - switch runtime.GOOS { - case "freebsd", "linux": - default: // platforms that don't support IGMPv2/3 fail here - t.Logf("not supported on %s", runtime.GOOS) - return - } - t.Error(err) - return - } - if err := c.IncludeSourceSpecificGroup(ifi, grp, src); err != nil { - t.Error(err) - return - } - if err := c.LeaveGroup(ifi, grp); err != nil { - t.Error(err) - return - } - - // MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_SOURCE_GROUP - if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil { - t.Error(err) - return - } - if err := c.LeaveSourceSpecificGroup(ifi, grp, src); err != nil { - t.Error(err) - return - } - - // MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_GROUP - if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil { - t.Error(err) - return - } - if err := c.LeaveGroup(ifi, grp); err != nil { - t.Error(err) - return - } -} diff --git a/vendor/golang.org/x/net/ipv4/packet.go b/vendor/golang.org/x/net/ipv4/packet.go index f00f5b052..966bb776f 100644 --- a/vendor/golang.org/x/net/ipv4/packet.go +++ b/vendor/golang.org/x/net/ipv4/packet.go @@ -6,7 +6,6 @@ package ipv4 import ( "net" - "syscall" "golang.org/x/net/internal/socket" ) @@ -28,7 +27,7 @@ func (c *packetHandler) ok() bool { return c != nil && c.IPConn != nil && c.Conn // header h, the payload p and the control message cm. func (c *packetHandler) ReadFrom(b []byte) (h *Header, p []byte, cm *ControlMessage, err error) { if !c.ok() { - return nil, nil, nil, syscall.EINVAL + return nil, nil, nil, errInvalidConn } return c.readFrom(b) } @@ -63,7 +62,7 @@ func slicePacket(b []byte) (h, p []byte, err error) { // Options = optional func (c *packetHandler) WriteTo(h *Header, p []byte, cm *ControlMessage) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } return c.writeTo(h, p, cm) } diff --git a/vendor/golang.org/x/net/ipv4/payload_cmsg.go b/vendor/golang.org/x/net/ipv4/payload_cmsg.go index 3f06d7606..a7c892dc4 100644 --- a/vendor/golang.org/x/net/ipv4/payload_cmsg.go +++ b/vendor/golang.org/x/net/ipv4/payload_cmsg.go @@ -2,14 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !nacl,!plan9,!windows +// +build darwin dragonfly freebsd linux netbsd openbsd solaris package ipv4 -import ( - "net" - "syscall" -) +import "net" // ReadFrom reads a payload of the received IPv4 datagram, from the // endpoint c, copying the payload into b. It returns the number of @@ -17,7 +14,7 @@ import ( // src of the received datagram. func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) { if !c.ok() { - return 0, nil, nil, syscall.EINVAL + return 0, nil, nil, errInvalidConn } return c.readFrom(b) } @@ -30,7 +27,7 @@ func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net. // control of the outgoing datagram is not required. func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) { if !c.ok() { - return 0, syscall.EINVAL + return 0, errInvalidConn } return c.writeTo(b, cm, dst) } diff --git a/vendor/golang.org/x/net/ipv4/payload_cmsg_go1_8.go b/vendor/golang.org/x/net/ipv4/payload_cmsg_go1_8.go index d26ccd90c..15a27b7a0 100644 --- a/vendor/golang.org/x/net/ipv4/payload_cmsg_go1_8.go +++ b/vendor/golang.org/x/net/ipv4/payload_cmsg_go1_8.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // +build !go1.9 -// +build !nacl,!plan9,!windows +// +build darwin dragonfly freebsd linux netbsd openbsd solaris package ipv4 diff --git a/vendor/golang.org/x/net/ipv4/payload_cmsg_go1_9.go b/vendor/golang.org/x/net/ipv4/payload_cmsg_go1_9.go index 2f1931183..aab3b224e 100644 --- a/vendor/golang.org/x/net/ipv4/payload_cmsg_go1_9.go +++ b/vendor/golang.org/x/net/ipv4/payload_cmsg_go1_9.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // +build go1.9 -// +build !nacl,!plan9,!windows +// +build darwin dragonfly freebsd linux netbsd openbsd solaris package ipv4 diff --git a/vendor/golang.org/x/net/ipv4/payload_nocmsg.go b/vendor/golang.org/x/net/ipv4/payload_nocmsg.go index 3926de70b..d57f05c10 100644 --- a/vendor/golang.org/x/net/ipv4/payload_nocmsg.go +++ b/vendor/golang.org/x/net/ipv4/payload_nocmsg.go @@ -2,14 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build nacl plan9 windows +// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris package ipv4 -import ( - "net" - "syscall" -) +import "net" // ReadFrom reads a payload of the received IPv4 datagram, from the // endpoint c, copying the payload into b. It returns the number of @@ -17,7 +14,7 @@ import ( // src of the received datagram. func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) { if !c.ok() { - return 0, nil, nil, syscall.EINVAL + return 0, nil, nil, errInvalidConn } if n, src, err = c.PacketConn.ReadFrom(b); err != nil { return 0, nil, nil, err @@ -33,7 +30,7 @@ func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net. // control of the outgoing datagram is not required. func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) { if !c.ok() { - return 0, syscall.EINVAL + return 0, errInvalidConn } if dst == nil { return 0, errMissingAddress diff --git a/vendor/golang.org/x/net/ipv4/readwrite_go1_8_test.go b/vendor/golang.org/x/net/ipv4/readwrite_go1_8_test.go deleted file mode 100644 index 1cd926e7f..000000000 --- a/vendor/golang.org/x/net/ipv4/readwrite_go1_8_test.go +++ /dev/null @@ -1,248 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !go1.9 - -package ipv4_test - -import ( - "bytes" - "fmt" - "net" - "runtime" - "strings" - "sync" - "testing" - - "golang.org/x/net/internal/iana" - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv4" -) - -func BenchmarkPacketConnReadWriteUnicast(b *testing.B) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - b.Skipf("not supported on %s", runtime.GOOS) - } - - payload := []byte("HELLO-R-U-THERE") - iph, err := (&ipv4.Header{ - Version: ipv4.Version, - Len: ipv4.HeaderLen, - TotalLen: ipv4.HeaderLen + len(payload), - TTL: 1, - Protocol: iana.ProtocolReserved, - Src: net.IPv4(192, 0, 2, 1), - Dst: net.IPv4(192, 0, 2, 254), - }).Marshal() - if err != nil { - b.Fatal(err) - } - greh := []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00} - datagram := append(greh, append(iph, payload...)...) - bb := make([]byte, 128) - cm := ipv4.ControlMessage{ - Src: net.IPv4(127, 0, 0, 1), - } - if ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); ifi != nil { - cm.IfIndex = ifi.Index - } - - b.Run("UDP", func(b *testing.B) { - c, err := nettest.NewLocalPacketListener("udp4") - if err != nil { - b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - p := ipv4.NewPacketConn(c) - dst := c.LocalAddr() - cf := ipv4.FlagTTL | ipv4.FlagInterface - if err := p.SetControlMessage(cf, true); err != nil { - b.Fatal(err) - } - b.Run("Net", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := c.WriteTo(payload, dst); err != nil { - b.Fatal(err) - } - if _, _, err := c.ReadFrom(bb); err != nil { - b.Fatal(err) - } - } - }) - b.Run("ToFrom", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := p.WriteTo(payload, &cm, dst); err != nil { - b.Fatal(err) - } - if _, _, _, err := p.ReadFrom(bb); err != nil { - b.Fatal(err) - } - } - }) - }) - b.Run("IP", func(b *testing.B) { - switch runtime.GOOS { - case "netbsd": - b.Skip("need to configure gre on netbsd") - case "openbsd": - b.Skip("net.inet.gre.allow=0 by default on openbsd") - } - - c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolGRE), "127.0.0.1") - if err != nil { - b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - p := ipv4.NewPacketConn(c) - dst := c.LocalAddr() - cf := ipv4.FlagTTL | ipv4.FlagInterface - if err := p.SetControlMessage(cf, true); err != nil { - b.Fatal(err) - } - b.Run("Net", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := c.WriteTo(datagram, dst); err != nil { - b.Fatal(err) - } - if _, _, err := c.ReadFrom(bb); err != nil { - b.Fatal(err) - } - } - }) - b.Run("ToFrom", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := p.WriteTo(datagram, &cm, dst); err != nil { - b.Fatal(err) - } - if _, _, _, err := p.ReadFrom(bb); err != nil { - b.Fatal(err) - } - } - }) - }) -} - -func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - - payload := []byte("HELLO-R-U-THERE") - iph, err := (&ipv4.Header{ - Version: ipv4.Version, - Len: ipv4.HeaderLen, - TotalLen: ipv4.HeaderLen + len(payload), - TTL: 1, - Protocol: iana.ProtocolReserved, - Src: net.IPv4(192, 0, 2, 1), - Dst: net.IPv4(192, 0, 2, 254), - }).Marshal() - if err != nil { - t.Fatal(err) - } - greh := []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00} - datagram := append(greh, append(iph, payload...)...) - - t.Run("UDP", func(t *testing.T) { - c, err := nettest.NewLocalPacketListener("udp4") - if err != nil { - t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - p := ipv4.NewPacketConn(c) - t.Run("ToFrom", func(t *testing.T) { - testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr()) - }) - }) - t.Run("IP", func(t *testing.T) { - switch runtime.GOOS { - case "netbsd": - t.Skip("need to configure gre on netbsd") - case "openbsd": - t.Skip("net.inet.gre.allow=0 by default on openbsd") - } - - c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolGRE), "127.0.0.1") - if err != nil { - t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - p := ipv4.NewPacketConn(c) - t.Run("ToFrom", func(t *testing.T) { - testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr()) - }) - }) -} - -func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv4.PacketConn, data []byte, dst net.Addr) { - ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback) - cf := ipv4.FlagTTL | ipv4.FlagSrc | ipv4.FlagDst | ipv4.FlagInterface - - if err := p.SetControlMessage(cf, true); err != nil { // probe before test - if nettest.ProtocolNotSupported(err) { - t.Skipf("not supported on %s", runtime.GOOS) - } - t.Fatal(err) - } - - var wg sync.WaitGroup - reader := func() { - defer wg.Done() - b := make([]byte, 128) - n, cm, _, err := p.ReadFrom(b) - if err != nil { - t.Error(err) - return - } - if !bytes.Equal(b[:n], data) { - t.Errorf("got %#v; want %#v", b[:n], data) - return - } - s := cm.String() - if strings.Contains(s, ",") { - t.Errorf("should be space-separated values: %s", s) - return - } - } - writer := func(toggle bool) { - defer wg.Done() - cm := ipv4.ControlMessage{ - Src: net.IPv4(127, 0, 0, 1), - } - if ifi != nil { - cm.IfIndex = ifi.Index - } - if err := p.SetControlMessage(cf, toggle); err != nil { - t.Error(err) - return - } - n, err := p.WriteTo(data, &cm, dst) - if err != nil { - t.Error(err) - return - } - if n != len(data) { - t.Errorf("got %d; want %d", n, len(data)) - return - } - } - - const N = 10 - wg.Add(N) - for i := 0; i < N; i++ { - go reader() - } - wg.Add(2 * N) - for i := 0; i < 2*N; i++ { - go writer(i%2 != 0) - - } - wg.Add(N) - for i := 0; i < N; i++ { - go reader() - } - wg.Wait() -} diff --git a/vendor/golang.org/x/net/ipv4/readwrite_go1_9_test.go b/vendor/golang.org/x/net/ipv4/readwrite_go1_9_test.go deleted file mode 100644 index 365de022a..000000000 --- a/vendor/golang.org/x/net/ipv4/readwrite_go1_9_test.go +++ /dev/null @@ -1,388 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.9 - -package ipv4_test - -import ( - "bytes" - "fmt" - "net" - "runtime" - "strings" - "sync" - "testing" - - "golang.org/x/net/internal/iana" - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv4" -) - -func BenchmarkPacketConnReadWriteUnicast(b *testing.B) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - b.Skipf("not supported on %s", runtime.GOOS) - } - - payload := []byte("HELLO-R-U-THERE") - iph, err := (&ipv4.Header{ - Version: ipv4.Version, - Len: ipv4.HeaderLen, - TotalLen: ipv4.HeaderLen + len(payload), - TTL: 1, - Protocol: iana.ProtocolReserved, - Src: net.IPv4(192, 0, 2, 1), - Dst: net.IPv4(192, 0, 2, 254), - }).Marshal() - if err != nil { - b.Fatal(err) - } - greh := []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00} - datagram := append(greh, append(iph, payload...)...) - bb := make([]byte, 128) - cm := ipv4.ControlMessage{ - Src: net.IPv4(127, 0, 0, 1), - } - if ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); ifi != nil { - cm.IfIndex = ifi.Index - } - - b.Run("UDP", func(b *testing.B) { - c, err := nettest.NewLocalPacketListener("udp4") - if err != nil { - b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - p := ipv4.NewPacketConn(c) - dst := c.LocalAddr() - cf := ipv4.FlagTTL | ipv4.FlagInterface - if err := p.SetControlMessage(cf, true); err != nil { - b.Fatal(err) - } - wms := []ipv4.Message{ - { - Buffers: [][]byte{payload}, - Addr: dst, - OOB: cm.Marshal(), - }, - } - rms := []ipv4.Message{ - { - Buffers: [][]byte{bb}, - OOB: ipv4.NewControlMessage(cf), - }, - } - b.Run("Net", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := c.WriteTo(payload, dst); err != nil { - b.Fatal(err) - } - if _, _, err := c.ReadFrom(bb); err != nil { - b.Fatal(err) - } - } - }) - b.Run("ToFrom", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := p.WriteTo(payload, &cm, dst); err != nil { - b.Fatal(err) - } - if _, _, _, err := p.ReadFrom(bb); err != nil { - b.Fatal(err) - } - } - }) - b.Run("Batch", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := p.WriteBatch(wms, 0); err != nil { - b.Fatal(err) - } - if _, err := p.ReadBatch(rms, 0); err != nil { - b.Fatal(err) - } - } - }) - }) - b.Run("IP", func(b *testing.B) { - switch runtime.GOOS { - case "netbsd": - b.Skip("need to configure gre on netbsd") - case "openbsd": - b.Skip("net.inet.gre.allow=0 by default on openbsd") - } - - c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolGRE), "127.0.0.1") - if err != nil { - b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - p := ipv4.NewPacketConn(c) - dst := c.LocalAddr() - cf := ipv4.FlagTTL | ipv4.FlagInterface - if err := p.SetControlMessage(cf, true); err != nil { - b.Fatal(err) - } - wms := []ipv4.Message{ - { - Buffers: [][]byte{datagram}, - Addr: dst, - OOB: cm.Marshal(), - }, - } - rms := []ipv4.Message{ - { - Buffers: [][]byte{bb}, - OOB: ipv4.NewControlMessage(cf), - }, - } - b.Run("Net", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := c.WriteTo(datagram, dst); err != nil { - b.Fatal(err) - } - if _, _, err := c.ReadFrom(bb); err != nil { - b.Fatal(err) - } - } - }) - b.Run("ToFrom", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := p.WriteTo(datagram, &cm, dst); err != nil { - b.Fatal(err) - } - if _, _, _, err := p.ReadFrom(bb); err != nil { - b.Fatal(err) - } - } - }) - b.Run("Batch", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := p.WriteBatch(wms, 0); err != nil { - b.Fatal(err) - } - if _, err := p.ReadBatch(rms, 0); err != nil { - b.Fatal(err) - } - } - }) - }) -} - -func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - - payload := []byte("HELLO-R-U-THERE") - iph, err := (&ipv4.Header{ - Version: ipv4.Version, - Len: ipv4.HeaderLen, - TotalLen: ipv4.HeaderLen + len(payload), - TTL: 1, - Protocol: iana.ProtocolReserved, - Src: net.IPv4(192, 0, 2, 1), - Dst: net.IPv4(192, 0, 2, 254), - }).Marshal() - if err != nil { - t.Fatal(err) - } - greh := []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00} - datagram := append(greh, append(iph, payload...)...) - - t.Run("UDP", func(t *testing.T) { - c, err := nettest.NewLocalPacketListener("udp4") - if err != nil { - t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - p := ipv4.NewPacketConn(c) - t.Run("ToFrom", func(t *testing.T) { - testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr(), false) - }) - t.Run("Batch", func(t *testing.T) { - testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr(), true) - }) - }) - t.Run("IP", func(t *testing.T) { - switch runtime.GOOS { - case "netbsd": - t.Skip("need to configure gre on netbsd") - case "openbsd": - t.Skip("net.inet.gre.allow=0 by default on openbsd") - } - - c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolGRE), "127.0.0.1") - if err != nil { - t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - p := ipv4.NewPacketConn(c) - t.Run("ToFrom", func(t *testing.T) { - testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr(), false) - }) - t.Run("Batch", func(t *testing.T) { - testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr(), true) - }) - }) -} - -func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv4.PacketConn, data []byte, dst net.Addr, batch bool) { - ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback) - cf := ipv4.FlagTTL | ipv4.FlagSrc | ipv4.FlagDst | ipv4.FlagInterface - - if err := p.SetControlMessage(cf, true); err != nil { // probe before test - if nettest.ProtocolNotSupported(err) { - t.Skipf("not supported on %s", runtime.GOOS) - } - t.Fatal(err) - } - - var wg sync.WaitGroup - reader := func() { - defer wg.Done() - b := make([]byte, 128) - n, cm, _, err := p.ReadFrom(b) - if err != nil { - t.Error(err) - return - } - if !bytes.Equal(b[:n], data) { - t.Errorf("got %#v; want %#v", b[:n], data) - return - } - s := cm.String() - if strings.Contains(s, ",") { - t.Errorf("should be space-separated values: %s", s) - return - } - } - batchReader := func() { - defer wg.Done() - ms := []ipv4.Message{ - { - Buffers: [][]byte{make([]byte, 128)}, - OOB: ipv4.NewControlMessage(cf), - }, - } - n, err := p.ReadBatch(ms, 0) - if err != nil { - t.Error(err) - return - } - if n != len(ms) { - t.Errorf("got %d; want %d", n, len(ms)) - return - } - var cm ipv4.ControlMessage - if err := cm.Parse(ms[0].OOB[:ms[0].NN]); err != nil { - t.Error(err) - return - } - var b []byte - if _, ok := dst.(*net.IPAddr); ok { - var h ipv4.Header - if err := h.Parse(ms[0].Buffers[0][:ms[0].N]); err != nil { - t.Error(err) - return - } - b = ms[0].Buffers[0][h.Len:ms[0].N] - } else { - b = ms[0].Buffers[0][:ms[0].N] - } - if !bytes.Equal(b, data) { - t.Errorf("got %#v; want %#v", b, data) - return - } - s := cm.String() - if strings.Contains(s, ",") { - t.Errorf("should be space-separated values: %s", s) - return - } - } - writer := func(toggle bool) { - defer wg.Done() - cm := ipv4.ControlMessage{ - Src: net.IPv4(127, 0, 0, 1), - } - if ifi != nil { - cm.IfIndex = ifi.Index - } - if err := p.SetControlMessage(cf, toggle); err != nil { - t.Error(err) - return - } - n, err := p.WriteTo(data, &cm, dst) - if err != nil { - t.Error(err) - return - } - if n != len(data) { - t.Errorf("got %d; want %d", n, len(data)) - return - } - } - batchWriter := func(toggle bool) { - defer wg.Done() - cm := ipv4.ControlMessage{ - Src: net.IPv4(127, 0, 0, 1), - } - if ifi != nil { - cm.IfIndex = ifi.Index - } - if err := p.SetControlMessage(cf, toggle); err != nil { - t.Error(err) - return - } - ms := []ipv4.Message{ - { - Buffers: [][]byte{data}, - OOB: cm.Marshal(), - Addr: dst, - }, - } - n, err := p.WriteBatch(ms, 0) - if err != nil { - t.Error(err) - return - } - if n != len(ms) { - t.Errorf("got %d; want %d", n, len(ms)) - return - } - if ms[0].N != len(data) { - t.Errorf("got %d; want %d", ms[0].N, len(data)) - return - } - } - - const N = 10 - wg.Add(N) - for i := 0; i < N; i++ { - if batch { - go batchReader() - } else { - go reader() - } - } - wg.Add(2 * N) - for i := 0; i < 2*N; i++ { - if batch { - go batchWriter(i%2 != 0) - } else { - go writer(i%2 != 0) - } - - } - wg.Add(N) - for i := 0; i < N; i++ { - if batch { - go batchReader() - } else { - go reader() - } - } - wg.Wait() -} diff --git a/vendor/golang.org/x/net/ipv4/readwrite_test.go b/vendor/golang.org/x/net/ipv4/readwrite_test.go deleted file mode 100644 index 3896a8ae4..000000000 --- a/vendor/golang.org/x/net/ipv4/readwrite_test.go +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv4_test - -import ( - "bytes" - "net" - "runtime" - "strings" - "sync" - "testing" - - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv4" -) - -func BenchmarkReadWriteUnicast(b *testing.B) { - c, err := nettest.NewLocalPacketListener("udp4") - if err != nil { - b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - - dst := c.LocalAddr() - wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128) - - b.Run("NetUDP", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := c.WriteTo(wb, dst); err != nil { - b.Fatal(err) - } - if _, _, err := c.ReadFrom(rb); err != nil { - b.Fatal(err) - } - } - }) - b.Run("IPv4UDP", func(b *testing.B) { - p := ipv4.NewPacketConn(c) - cf := ipv4.FlagTTL | ipv4.FlagInterface - if err := p.SetControlMessage(cf, true); err != nil { - b.Fatal(err) - } - cm := ipv4.ControlMessage{TTL: 1} - ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback) - if ifi != nil { - cm.IfIndex = ifi.Index - } - - for i := 0; i < b.N; i++ { - if _, err := p.WriteTo(wb, &cm, dst); err != nil { - b.Fatal(err) - } - if _, _, _, err := p.ReadFrom(rb); err != nil { - b.Fatal(err) - } - } - }) -} - -func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - - c, err := nettest.NewLocalPacketListener("udp4") - if err != nil { - t.Fatal(err) - } - defer c.Close() - p := ipv4.NewPacketConn(c) - defer p.Close() - - dst := c.LocalAddr() - ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback) - cf := ipv4.FlagTTL | ipv4.FlagSrc | ipv4.FlagDst | ipv4.FlagInterface - wb := []byte("HELLO-R-U-THERE") - - if err := p.SetControlMessage(cf, true); err != nil { // probe before test - if nettest.ProtocolNotSupported(err) { - t.Skipf("not supported on %s", runtime.GOOS) - } - t.Fatal(err) - } - - var wg sync.WaitGroup - reader := func() { - defer wg.Done() - rb := make([]byte, 128) - if n, cm, _, err := p.ReadFrom(rb); err != nil { - t.Error(err) - return - } else if !bytes.Equal(rb[:n], wb) { - t.Errorf("got %v; want %v", rb[:n], wb) - return - } else { - s := cm.String() - if strings.Contains(s, ",") { - t.Errorf("should be space-separated values: %s", s) - } - } - } - writer := func(toggle bool) { - defer wg.Done() - cm := ipv4.ControlMessage{ - Src: net.IPv4(127, 0, 0, 1), - } - if ifi != nil { - cm.IfIndex = ifi.Index - } - if err := p.SetControlMessage(cf, toggle); err != nil { - t.Error(err) - return - } - if n, err := p.WriteTo(wb, &cm, dst); err != nil { - t.Error(err) - return - } else if n != len(wb) { - t.Errorf("got %d; want %d", n, len(wb)) - return - } - } - - const N = 10 - wg.Add(N) - for i := 0; i < N; i++ { - go reader() - } - wg.Add(2 * N) - for i := 0; i < 2*N; i++ { - go writer(i%2 != 0) - } - wg.Add(N) - for i := 0; i < N; i++ { - go reader() - } - wg.Wait() -} diff --git a/vendor/golang.org/x/net/ipv4/unicast_test.go b/vendor/golang.org/x/net/ipv4/unicast_test.go deleted file mode 100644 index 02c089f00..000000000 --- a/vendor/golang.org/x/net/ipv4/unicast_test.go +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv4_test - -import ( - "bytes" - "net" - "os" - "runtime" - "testing" - "time" - - "golang.org/x/net/icmp" - "golang.org/x/net/internal/iana" - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv4" -) - -func TestPacketConnReadWriteUnicastUDP(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback) - if ifi == nil { - t.Skipf("not available on %s", runtime.GOOS) - } - - c, err := nettest.NewLocalPacketListener("udp4") - if err != nil { - t.Fatal(err) - } - defer c.Close() - p := ipv4.NewPacketConn(c) - defer p.Close() - - dst := c.LocalAddr() - cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface - wb := []byte("HELLO-R-U-THERE") - - for i, toggle := range []bool{true, false, true} { - if err := p.SetControlMessage(cf, toggle); err != nil { - if nettest.ProtocolNotSupported(err) { - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } - p.SetTTL(i + 1) - if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { - t.Fatal(err) - } - if n, err := p.WriteTo(wb, nil, dst); err != nil { - t.Fatal(err) - } else if n != len(wb) { - t.Fatalf("got %v; want %v", n, len(wb)) - } - rb := make([]byte, 128) - if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { - t.Fatal(err) - } - if n, _, _, err := p.ReadFrom(rb); err != nil { - t.Fatal(err) - } else if !bytes.Equal(rb[:n], wb) { - t.Fatalf("got %v; want %v", rb[:n], wb) - } - } -} - -func TestPacketConnReadWriteUnicastICMP(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if m, ok := nettest.SupportsRawIPSocket(); !ok { - t.Skip(m) - } - ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback) - if ifi == nil { - t.Skipf("not available on %s", runtime.GOOS) - } - - c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") - if err != nil { - t.Fatal(err) - } - defer c.Close() - - dst, err := net.ResolveIPAddr("ip4", "127.0.0.1") - if err != nil { - t.Fatal(err) - } - p := ipv4.NewPacketConn(c) - defer p.Close() - cf := ipv4.FlagDst | ipv4.FlagInterface - if runtime.GOOS != "solaris" { - // Solaris never allows to modify ICMP properties. - cf |= ipv4.FlagTTL - } - - for i, toggle := range []bool{true, false, true} { - wb, err := (&icmp.Message{ - Type: ipv4.ICMPTypeEcho, Code: 0, - Body: &icmp.Echo{ - ID: os.Getpid() & 0xffff, Seq: i + 1, - Data: []byte("HELLO-R-U-THERE"), - }, - }).Marshal(nil) - if err != nil { - t.Fatal(err) - } - if err := p.SetControlMessage(cf, toggle); err != nil { - if nettest.ProtocolNotSupported(err) { - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } - p.SetTTL(i + 1) - if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { - t.Fatal(err) - } - if n, err := p.WriteTo(wb, nil, dst); err != nil { - t.Fatal(err) - } else if n != len(wb) { - t.Fatalf("got %v; want %v", n, len(wb)) - } - rb := make([]byte, 128) - loop: - if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { - t.Fatal(err) - } - if n, _, _, err := p.ReadFrom(rb); err != nil { - switch runtime.GOOS { - case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } else { - m, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n]) - if err != nil { - t.Fatal(err) - } - if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEcho { - // On Linux we must handle own sent packets. - goto loop - } - if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 { - t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0) - } - } - } -} - -func TestRawConnReadWriteUnicastICMP(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if m, ok := nettest.SupportsRawIPSocket(); !ok { - t.Skip(m) - } - ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback) - if ifi == nil { - t.Skipf("not available on %s", runtime.GOOS) - } - - c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") - if err != nil { - t.Fatal(err) - } - defer c.Close() - - dst, err := net.ResolveIPAddr("ip4", "127.0.0.1") - if err != nil { - t.Fatal(err) - } - r, err := ipv4.NewRawConn(c) - if err != nil { - t.Fatal(err) - } - defer r.Close() - cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface - - for i, toggle := range []bool{true, false, true} { - wb, err := (&icmp.Message{ - Type: ipv4.ICMPTypeEcho, Code: 0, - Body: &icmp.Echo{ - ID: os.Getpid() & 0xffff, Seq: i + 1, - Data: []byte("HELLO-R-U-THERE"), - }, - }).Marshal(nil) - if err != nil { - t.Fatal(err) - } - wh := &ipv4.Header{ - Version: ipv4.Version, - Len: ipv4.HeaderLen, - TOS: i + 1, - TotalLen: ipv4.HeaderLen + len(wb), - TTL: i + 1, - Protocol: 1, - Dst: dst.IP, - } - if err := r.SetControlMessage(cf, toggle); err != nil { - if nettest.ProtocolNotSupported(err) { - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } - if err := r.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { - t.Fatal(err) - } - if err := r.WriteTo(wh, wb, nil); err != nil { - t.Fatal(err) - } - rb := make([]byte, ipv4.HeaderLen+128) - loop: - if err := r.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { - t.Fatal(err) - } - if _, b, _, err := r.ReadFrom(rb); err != nil { - switch runtime.GOOS { - case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } else { - m, err := icmp.ParseMessage(iana.ProtocolICMP, b) - if err != nil { - t.Fatal(err) - } - if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEcho { - // On Linux we must handle own sent packets. - goto loop - } - if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 { - t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0) - } - } - } -} diff --git a/vendor/golang.org/x/net/ipv4/unicastsockopt_test.go b/vendor/golang.org/x/net/ipv4/unicastsockopt_test.go deleted file mode 100644 index db5213b91..000000000 --- a/vendor/golang.org/x/net/ipv4/unicastsockopt_test.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv4_test - -import ( - "net" - "runtime" - "testing" - - "golang.org/x/net/internal/iana" - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv4" -) - -func TestConnUnicastSocketOptions(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback) - if ifi == nil { - t.Skipf("not available on %s", runtime.GOOS) - } - - ln, err := net.Listen("tcp4", "127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - defer ln.Close() - - errc := make(chan error, 1) - go func() { - c, err := ln.Accept() - if err != nil { - errc <- err - return - } - errc <- c.Close() - }() - - c, err := net.Dial("tcp4", ln.Addr().String()) - if err != nil { - t.Fatal(err) - } - defer c.Close() - - testUnicastSocketOptions(t, ipv4.NewConn(c)) - - if err := <-errc; err != nil { - t.Errorf("server: %v", err) - } -} - -var packetConnUnicastSocketOptionTests = []struct { - net, proto, addr string -}{ - {"udp4", "", "127.0.0.1:0"}, - {"ip4", ":icmp", "127.0.0.1"}, -} - -func TestPacketConnUnicastSocketOptions(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback) - if ifi == nil { - t.Skipf("not available on %s", runtime.GOOS) - } - - m, ok := nettest.SupportsRawIPSocket() - for _, tt := range packetConnUnicastSocketOptionTests { - if tt.net == "ip4" && !ok { - t.Log(m) - continue - } - c, err := net.ListenPacket(tt.net+tt.proto, tt.addr) - if err != nil { - t.Fatal(err) - } - defer c.Close() - - testUnicastSocketOptions(t, ipv4.NewPacketConn(c)) - } -} - -func TestRawConnUnicastSocketOptions(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if m, ok := nettest.SupportsRawIPSocket(); !ok { - t.Skip(m) - } - ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback) - if ifi == nil { - t.Skipf("not available on %s", runtime.GOOS) - } - - c, err := net.ListenPacket("ip4:icmp", "127.0.0.1") - if err != nil { - t.Fatal(err) - } - defer c.Close() - - r, err := ipv4.NewRawConn(c) - if err != nil { - t.Fatal(err) - } - - testUnicastSocketOptions(t, r) -} - -type testIPv4UnicastConn interface { - TOS() (int, error) - SetTOS(int) error - TTL() (int, error) - SetTTL(int) error -} - -func testUnicastSocketOptions(t *testing.T, c testIPv4UnicastConn) { - tos := iana.DiffServCS0 | iana.NotECNTransport - switch runtime.GOOS { - case "windows": - // IP_TOS option is supported on Windows 8 and beyond. - t.Skipf("not supported on %s", runtime.GOOS) - } - - if err := c.SetTOS(tos); err != nil { - t.Fatal(err) - } - if v, err := c.TOS(); err != nil { - t.Fatal(err) - } else if v != tos { - t.Fatalf("got %v; want %v", v, tos) - } - const ttl = 255 - if err := c.SetTTL(ttl); err != nil { - t.Fatal(err) - } - if v, err := c.TTL(); err != nil { - t.Fatal(err) - } else if v != ttl { - t.Fatalf("got %v; want %v", v, ttl) - } -} diff --git a/vendor/golang.org/x/net/ipv6/batch.go b/vendor/golang.org/x/net/ipv6/batch.go index 4f5fe683d..10d649245 100644 --- a/vendor/golang.org/x/net/ipv6/batch.go +++ b/vendor/golang.org/x/net/ipv6/batch.go @@ -9,7 +9,6 @@ package ipv6 import ( "net" "runtime" - "syscall" "golang.org/x/net/internal/socket" ) @@ -67,7 +66,7 @@ type Message = socket.Message // On other platforms, this method will read only a single message. func (c *payloadHandler) ReadBatch(ms []Message, flags int) (int, error) { if !c.ok() { - return 0, syscall.EINVAL + return 0, errInvalidConn } switch runtime.GOOS { case "linux": @@ -98,7 +97,7 @@ func (c *payloadHandler) ReadBatch(ms []Message, flags int) (int, error) { // On other platforms, this method will write only a single message. func (c *payloadHandler) WriteBatch(ms []Message, flags int) (int, error) { if !c.ok() { - return 0, syscall.EINVAL + return 0, errInvalidConn } switch runtime.GOOS { case "linux": diff --git a/vendor/golang.org/x/net/ipv6/bpf_test.go b/vendor/golang.org/x/net/ipv6/bpf_test.go deleted file mode 100644 index 8253e1f42..000000000 --- a/vendor/golang.org/x/net/ipv6/bpf_test.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv6_test - -import ( - "net" - "runtime" - "testing" - "time" - - "golang.org/x/net/bpf" - "golang.org/x/net/ipv6" -) - -func TestBPF(t *testing.T) { - if runtime.GOOS != "linux" { - t.Skipf("not supported on %s", runtime.GOOS) - } - if !supportsIPv6 { - t.Skip("ipv6 is not supported") - } - - l, err := net.ListenPacket("udp6", "[::1]:0") - if err != nil { - t.Fatal(err) - } - defer l.Close() - - p := ipv6.NewPacketConn(l) - - // This filter accepts UDP packets whose first payload byte is - // even. - prog, err := bpf.Assemble([]bpf.Instruction{ - // Load the first byte of the payload (skipping UDP header). - bpf.LoadAbsolute{Off: 8, Size: 1}, - // Select LSB of the byte. - bpf.ALUOpConstant{Op: bpf.ALUOpAnd, Val: 1}, - // Byte is even? - bpf.JumpIf{Cond: bpf.JumpEqual, Val: 0, SkipFalse: 1}, - // Accept. - bpf.RetConstant{Val: 4096}, - // Ignore. - bpf.RetConstant{Val: 0}, - }) - if err != nil { - t.Fatalf("compiling BPF: %s", err) - } - - if err = p.SetBPF(prog); err != nil { - t.Fatalf("attaching filter to Conn: %s", err) - } - - s, err := net.Dial("udp6", l.LocalAddr().String()) - if err != nil { - t.Fatal(err) - } - defer s.Close() - go func() { - for i := byte(0); i < 10; i++ { - s.Write([]byte{i}) - } - }() - - l.SetDeadline(time.Now().Add(2 * time.Second)) - seen := make([]bool, 5) - for { - var b [512]byte - n, _, err := l.ReadFrom(b[:]) - if err != nil { - t.Fatalf("reading from listener: %s", err) - } - if n != 1 { - t.Fatalf("unexpected packet length, want 1, got %d", n) - } - if b[0] >= 10 { - t.Fatalf("unexpected byte, want 0-9, got %d", b[0]) - } - if b[0]%2 != 0 { - t.Fatalf("got odd byte %d, wanted only even bytes", b[0]) - } - seen[b[0]/2] = true - - seenAll := true - for _, v := range seen { - if !v { - seenAll = false - break - } - } - if seenAll { - break - } - } -} diff --git a/vendor/golang.org/x/net/ipv6/control_test.go b/vendor/golang.org/x/net/ipv6/control_test.go deleted file mode 100644 index c186ca99f..000000000 --- a/vendor/golang.org/x/net/ipv6/control_test.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv6_test - -import ( - "testing" - - "golang.org/x/net/ipv6" -) - -func TestControlMessageParseWithFuzz(t *testing.T) { - var cm ipv6.ControlMessage - for _, fuzz := range []string{ - "\f\x00\x00\x00)\x00\x00\x00.\x00\x00\x00", - "\f\x00\x00\x00)\x00\x00\x00,\x00\x00\x00", - } { - cm.Parse([]byte(fuzz)) - } -} diff --git a/vendor/golang.org/x/net/ipv6/dgramopt.go b/vendor/golang.org/x/net/ipv6/dgramopt.go index 703dafe84..eea4fde25 100644 --- a/vendor/golang.org/x/net/ipv6/dgramopt.go +++ b/vendor/golang.org/x/net/ipv6/dgramopt.go @@ -6,7 +6,6 @@ package ipv6 import ( "net" - "syscall" "golang.org/x/net/bpf" ) @@ -15,7 +14,7 @@ import ( // multicast packets. func (c *dgramOpt) MulticastHopLimit() (int, error) { if !c.ok() { - return 0, syscall.EINVAL + return 0, errInvalidConn } so, ok := sockOpts[ssoMulticastHopLimit] if !ok { @@ -28,7 +27,7 @@ func (c *dgramOpt) MulticastHopLimit() (int, error) { // outgoing multicast packets. func (c *dgramOpt) SetMulticastHopLimit(hoplim int) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoMulticastHopLimit] if !ok { @@ -41,7 +40,7 @@ func (c *dgramOpt) SetMulticastHopLimit(hoplim int) error { // packet transmissions. func (c *dgramOpt) MulticastInterface() (*net.Interface, error) { if !c.ok() { - return nil, syscall.EINVAL + return nil, errInvalidConn } so, ok := sockOpts[ssoMulticastInterface] if !ok { @@ -54,7 +53,7 @@ func (c *dgramOpt) MulticastInterface() (*net.Interface, error) { // multicast packet transmissions. func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoMulticastInterface] if !ok { @@ -67,7 +66,7 @@ func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error { // should be copied and send back to the originator. func (c *dgramOpt) MulticastLoopback() (bool, error) { if !c.ok() { - return false, syscall.EINVAL + return false, errInvalidConn } so, ok := sockOpts[ssoMulticastLoopback] if !ok { @@ -84,7 +83,7 @@ func (c *dgramOpt) MulticastLoopback() (bool, error) { // should be copied and send back to the originator. func (c *dgramOpt) SetMulticastLoopback(on bool) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoMulticastLoopback] if !ok { @@ -104,7 +103,7 @@ func (c *dgramOpt) SetMulticastLoopback(on bool) error { // configuration. func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoJoinGroup] if !ok { @@ -122,7 +121,7 @@ func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error { // source-specific group. func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoLeaveGroup] if !ok { @@ -143,7 +142,7 @@ func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error { // routing configuration. func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoJoinSourceGroup] if !ok { @@ -164,7 +163,7 @@ func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net // interface ifi. func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoLeaveSourceGroup] if !ok { @@ -186,7 +185,7 @@ func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source ne // ifi. func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoBlockSourceGroup] if !ok { @@ -207,7 +206,7 @@ func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source // group by ExcludeSourceSpecificGroup again on the interface ifi. func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoUnblockSourceGroup] if !ok { @@ -230,7 +229,7 @@ func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source // field is located. func (c *dgramOpt) Checksum() (on bool, offset int, err error) { if !c.ok() { - return false, 0, syscall.EINVAL + return false, 0, errInvalidConn } so, ok := sockOpts[ssoChecksum] if !ok { @@ -251,7 +250,7 @@ func (c *dgramOpt) Checksum() (on bool, offset int, err error) { // checksum field is located. func (c *dgramOpt) SetChecksum(on bool, offset int) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoChecksum] if !ok { @@ -266,7 +265,7 @@ func (c *dgramOpt) SetChecksum(on bool, offset int) error { // ICMPFilter returns an ICMP filter. func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) { if !c.ok() { - return nil, syscall.EINVAL + return nil, errInvalidConn } so, ok := sockOpts[ssoICMPFilter] if !ok { @@ -278,7 +277,7 @@ func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) { // SetICMPFilter deploys the ICMP filter. func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoICMPFilter] if !ok { @@ -292,7 +291,7 @@ func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error { // Only supported on Linux. func (c *dgramOpt) SetBPF(filter []bpf.RawInstruction) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoAttachFilter] if !ok { diff --git a/vendor/golang.org/x/net/ipv6/doc.go b/vendor/golang.org/x/net/ipv6/doc.go index 664a97dea..d38ea0da6 100644 --- a/vendor/golang.org/x/net/ipv6/doc.go +++ b/vendor/golang.org/x/net/ipv6/doc.go @@ -56,7 +56,7 @@ // Multicasting // // The options for multicasting are available for net.UDPConn and -// net.IPconn which are created as network connections that use the +// net.IPConn which are created as network connections that use the // IPv6 transport. A few network facilities must be prepared before // you begin multicasting, at a minimum joining network interfaces and // multicast groups. @@ -240,4 +240,5 @@ // IncludeSourceSpecificGroup may return an error. package ipv6 // import "golang.org/x/net/ipv6" -// BUG(mikio): This package is not implemented on NaCl and Plan 9. +// BUG(mikio): This package is not implemented on AIX, JS, NaCl and +// Plan 9. diff --git a/vendor/golang.org/x/net/ipv6/endpoint.go b/vendor/golang.org/x/net/ipv6/endpoint.go index 0624c1740..932575639 100644 --- a/vendor/golang.org/x/net/ipv6/endpoint.go +++ b/vendor/golang.org/x/net/ipv6/endpoint.go @@ -6,7 +6,6 @@ package ipv6 import ( "net" - "syscall" "time" "golang.org/x/net/internal/socket" @@ -34,7 +33,7 @@ func (c *genericOpt) ok() bool { return c != nil && c.Conn != nil } // with the endpoint. func (c *Conn) PathMTU() (int, error) { if !c.ok() { - return 0, syscall.EINVAL + return 0, errInvalidConn } so, ok := sockOpts[ssoPathMTU] if !ok { @@ -76,7 +75,7 @@ func (c *dgramOpt) ok() bool { return c != nil && c.Conn != nil } // socket options. func (c *PacketConn) SetControlMessage(cf ControlFlags, on bool) error { if !c.payloadHandler.ok() { - return syscall.EINVAL + return errInvalidConn } return setControlMessage(c.dgramOpt.Conn, &c.payloadHandler.rawOpt, cf, on) } @@ -85,7 +84,7 @@ func (c *PacketConn) SetControlMessage(cf ControlFlags, on bool) error { // endpoint. func (c *PacketConn) SetDeadline(t time.Time) error { if !c.payloadHandler.ok() { - return syscall.EINVAL + return errInvalidConn } return c.payloadHandler.SetDeadline(t) } @@ -94,7 +93,7 @@ func (c *PacketConn) SetDeadline(t time.Time) error { // endpoint. func (c *PacketConn) SetReadDeadline(t time.Time) error { if !c.payloadHandler.ok() { - return syscall.EINVAL + return errInvalidConn } return c.payloadHandler.SetReadDeadline(t) } @@ -103,7 +102,7 @@ func (c *PacketConn) SetReadDeadline(t time.Time) error { // endpoint. func (c *PacketConn) SetWriteDeadline(t time.Time) error { if !c.payloadHandler.ok() { - return syscall.EINVAL + return errInvalidConn } return c.payloadHandler.SetWriteDeadline(t) } @@ -111,7 +110,7 @@ func (c *PacketConn) SetWriteDeadline(t time.Time) error { // Close closes the endpoint. func (c *PacketConn) Close() error { if !c.payloadHandler.ok() { - return syscall.EINVAL + return errInvalidConn } return c.payloadHandler.Close() } diff --git a/vendor/golang.org/x/net/ipv6/example_test.go b/vendor/golang.org/x/net/ipv6/example_test.go deleted file mode 100644 index e761aa2a1..000000000 --- a/vendor/golang.org/x/net/ipv6/example_test.go +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv6_test - -import ( - "fmt" - "log" - "net" - "os" - "time" - - "golang.org/x/net/icmp" - "golang.org/x/net/ipv6" -) - -func ExampleConn_markingTCP() { - ln, err := net.Listen("tcp", "[::]:1024") - if err != nil { - log.Fatal(err) - } - defer ln.Close() - - for { - c, err := ln.Accept() - if err != nil { - log.Fatal(err) - } - go func(c net.Conn) { - defer c.Close() - if c.RemoteAddr().(*net.TCPAddr).IP.To16() != nil && c.RemoteAddr().(*net.TCPAddr).IP.To4() == nil { - p := ipv6.NewConn(c) - if err := p.SetTrafficClass(0x28); err != nil { // DSCP AF11 - log.Fatal(err) - } - if err := p.SetHopLimit(128); err != nil { - log.Fatal(err) - } - } - if _, err := c.Write([]byte("HELLO-R-U-THERE-ACK")); err != nil { - log.Fatal(err) - } - }(c) - } -} - -func ExamplePacketConn_servingOneShotMulticastDNS() { - c, err := net.ListenPacket("udp6", "[::]:5353") // mDNS over UDP - if err != nil { - log.Fatal(err) - } - defer c.Close() - p := ipv6.NewPacketConn(c) - - en0, err := net.InterfaceByName("en0") - if err != nil { - log.Fatal(err) - } - mDNSLinkLocal := net.UDPAddr{IP: net.ParseIP("ff02::fb")} - if err := p.JoinGroup(en0, &mDNSLinkLocal); err != nil { - log.Fatal(err) - } - defer p.LeaveGroup(en0, &mDNSLinkLocal) - if err := p.SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true); err != nil { - log.Fatal(err) - } - - var wcm ipv6.ControlMessage - b := make([]byte, 1500) - for { - _, rcm, peer, err := p.ReadFrom(b) - if err != nil { - log.Fatal(err) - } - if !rcm.Dst.IsMulticast() || !rcm.Dst.Equal(mDNSLinkLocal.IP) { - continue - } - wcm.IfIndex = rcm.IfIndex - answers := []byte("FAKE-MDNS-ANSWERS") // fake mDNS answers, you need to implement this - if _, err := p.WriteTo(answers, &wcm, peer); err != nil { - log.Fatal(err) - } - } -} - -func ExamplePacketConn_tracingIPPacketRoute() { - // Tracing an IP packet route to www.google.com. - - const host = "www.google.com" - ips, err := net.LookupIP(host) - if err != nil { - log.Fatal(err) - } - var dst net.IPAddr - for _, ip := range ips { - if ip.To16() != nil && ip.To4() == nil { - dst.IP = ip - fmt.Printf("using %v for tracing an IP packet route to %s\n", dst.IP, host) - break - } - } - if dst.IP == nil { - log.Fatal("no AAAA record found") - } - - c, err := net.ListenPacket("ip6:58", "::") // ICMP for IPv6 - if err != nil { - log.Fatal(err) - } - defer c.Close() - p := ipv6.NewPacketConn(c) - - if err := p.SetControlMessage(ipv6.FlagHopLimit|ipv6.FlagSrc|ipv6.FlagDst|ipv6.FlagInterface, true); err != nil { - log.Fatal(err) - } - wm := icmp.Message{ - Type: ipv6.ICMPTypeEchoRequest, Code: 0, - Body: &icmp.Echo{ - ID: os.Getpid() & 0xffff, - Data: []byte("HELLO-R-U-THERE"), - }, - } - var f ipv6.ICMPFilter - f.SetAll(true) - f.Accept(ipv6.ICMPTypeTimeExceeded) - f.Accept(ipv6.ICMPTypeEchoReply) - if err := p.SetICMPFilter(&f); err != nil { - log.Fatal(err) - } - - var wcm ipv6.ControlMessage - rb := make([]byte, 1500) - for i := 1; i <= 64; i++ { // up to 64 hops - wm.Body.(*icmp.Echo).Seq = i - wb, err := wm.Marshal(nil) - if err != nil { - log.Fatal(err) - } - - // In the real world usually there are several - // multiple traffic-engineered paths for each hop. - // You may need to probe a few times to each hop. - begin := time.Now() - wcm.HopLimit = i - if _, err := p.WriteTo(wb, &wcm, &dst); err != nil { - log.Fatal(err) - } - if err := p.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil { - log.Fatal(err) - } - n, rcm, peer, err := p.ReadFrom(rb) - if err != nil { - if err, ok := err.(net.Error); ok && err.Timeout() { - fmt.Printf("%v\t*\n", i) - continue - } - log.Fatal(err) - } - rm, err := icmp.ParseMessage(58, rb[:n]) - if err != nil { - log.Fatal(err) - } - rtt := time.Since(begin) - - // In the real world you need to determine whether the - // received message is yours using ControlMessage.Src, - // ControlMesage.Dst, icmp.Echo.ID and icmp.Echo.Seq. - switch rm.Type { - case ipv6.ICMPTypeTimeExceeded: - names, _ := net.LookupAddr(peer.String()) - fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, rcm) - case ipv6.ICMPTypeEchoReply: - names, _ := net.LookupAddr(peer.String()) - fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, rcm) - return - } - } -} - -func ExamplePacketConn_advertisingOSPFHello() { - c, err := net.ListenPacket("ip6:89", "::") // OSPF for IPv6 - if err != nil { - log.Fatal(err) - } - defer c.Close() - p := ipv6.NewPacketConn(c) - - en0, err := net.InterfaceByName("en0") - if err != nil { - log.Fatal(err) - } - allSPFRouters := net.IPAddr{IP: net.ParseIP("ff02::5")} - if err := p.JoinGroup(en0, &allSPFRouters); err != nil { - log.Fatal(err) - } - defer p.LeaveGroup(en0, &allSPFRouters) - - hello := make([]byte, 24) // fake hello data, you need to implement this - ospf := make([]byte, 16) // fake ospf header, you need to implement this - ospf[0] = 3 // version 3 - ospf[1] = 1 // hello packet - ospf = append(ospf, hello...) - if err := p.SetChecksum(true, 12); err != nil { - log.Fatal(err) - } - - cm := ipv6.ControlMessage{ - TrafficClass: 0xc0, // DSCP CS6 - HopLimit: 1, - IfIndex: en0.Index, - } - if _, err := p.WriteTo(ospf, &cm, &allSPFRouters); err != nil { - log.Fatal(err) - } -} diff --git a/vendor/golang.org/x/net/ipv6/gen.go b/vendor/golang.org/x/net/ipv6/gen.go index 47b7e9f0a..5885664fb 100644 --- a/vendor/golang.org/x/net/ipv6/gen.go +++ b/vendor/golang.org/x/net/ipv6/gen.go @@ -80,7 +80,7 @@ var registries = []struct { func geniana() error { var bb bytes.Buffer fmt.Fprintf(&bb, "// go generate gen.go\n") - fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n") + fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n") fmt.Fprintf(&bb, "package ipv6\n\n") for _, r := range registries { resp, err := http.Get(r.url) diff --git a/vendor/golang.org/x/net/ipv6/genericopt.go b/vendor/golang.org/x/net/ipv6/genericopt.go index e9dbc2e18..1a18f7549 100644 --- a/vendor/golang.org/x/net/ipv6/genericopt.go +++ b/vendor/golang.org/x/net/ipv6/genericopt.go @@ -4,13 +4,11 @@ package ipv6 -import "syscall" - // TrafficClass returns the traffic class field value for outgoing // packets. func (c *genericOpt) TrafficClass() (int, error) { if !c.ok() { - return 0, syscall.EINVAL + return 0, errInvalidConn } so, ok := sockOpts[ssoTrafficClass] if !ok { @@ -23,7 +21,7 @@ func (c *genericOpt) TrafficClass() (int, error) { // outgoing packets. func (c *genericOpt) SetTrafficClass(tclass int) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoTrafficClass] if !ok { @@ -35,7 +33,7 @@ func (c *genericOpt) SetTrafficClass(tclass int) error { // HopLimit returns the hop limit field value for outgoing packets. func (c *genericOpt) HopLimit() (int, error) { if !c.ok() { - return 0, syscall.EINVAL + return 0, errInvalidConn } so, ok := sockOpts[ssoHopLimit] if !ok { @@ -48,7 +46,7 @@ func (c *genericOpt) HopLimit() (int, error) { // packets. func (c *genericOpt) SetHopLimit(hoplim int) error { if !c.ok() { - return syscall.EINVAL + return errInvalidConn } so, ok := sockOpts[ssoHopLimit] if !ok { diff --git a/vendor/golang.org/x/net/ipv6/header_test.go b/vendor/golang.org/x/net/ipv6/header_test.go deleted file mode 100644 index ca11dc23d..000000000 --- a/vendor/golang.org/x/net/ipv6/header_test.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv6_test - -import ( - "net" - "reflect" - "strings" - "testing" - - "golang.org/x/net/internal/iana" - "golang.org/x/net/ipv6" -) - -var ( - wireHeaderFromKernel = [ipv6.HeaderLen]byte{ - 0x69, 0x8b, 0xee, 0xf1, - 0xca, 0xfe, 0x2c, 0x01, - 0x20, 0x01, 0x0d, 0xb8, - 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - 0x20, 0x01, 0x0d, 0xb8, - 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - } - - testHeader = &ipv6.Header{ - Version: ipv6.Version, - TrafficClass: iana.DiffServAF43, - FlowLabel: 0xbeef1, - PayloadLen: 0xcafe, - NextHeader: iana.ProtocolIPv6Frag, - HopLimit: 1, - Src: net.ParseIP("2001:db8:1::1"), - Dst: net.ParseIP("2001:db8:2::1"), - } -) - -func TestParseHeader(t *testing.T) { - h, err := ipv6.ParseHeader(wireHeaderFromKernel[:]) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(h, testHeader) { - t.Fatalf("got %#v; want %#v", h, testHeader) - } - s := h.String() - if strings.Contains(s, ",") { - t.Fatalf("should be space-separated values: %s", s) - } -} diff --git a/vendor/golang.org/x/net/ipv6/helper.go b/vendor/golang.org/x/net/ipv6/helper.go index 259740132..7ac535229 100644 --- a/vendor/golang.org/x/net/ipv6/helper.go +++ b/vendor/golang.org/x/net/ipv6/helper.go @@ -10,6 +10,7 @@ import ( ) var ( + errInvalidConn = errors.New("invalid connection") errMissingAddress = errors.New("missing address") errHeaderTooShort = errors.New("header too short") errInvalidConnType = errors.New("invalid conn type") diff --git a/vendor/golang.org/x/net/ipv6/iana.go b/vendor/golang.org/x/net/ipv6/iana.go index 3c6214fb6..32db1aa94 100644 --- a/vendor/golang.org/x/net/ipv6/iana.go +++ b/vendor/golang.org/x/net/ipv6/iana.go @@ -1,9 +1,9 @@ // go generate gen.go -// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT +// Code generated by the command above; DO NOT EDIT. package ipv6 -// Internet Control Message Protocol version 6 (ICMPv6) Parameters, Updated: 2015-07-07 +// Internet Control Message Protocol version 6 (ICMPv6) Parameters, Updated: 2018-03-09 const ( ICMPTypeDestinationUnreachable ICMPType = 1 // Destination Unreachable ICMPTypePacketTooBig ICMPType = 2 // Packet Too Big @@ -40,9 +40,11 @@ const ( ICMPTypeDuplicateAddressRequest ICMPType = 157 // Duplicate Address Request ICMPTypeDuplicateAddressConfirmation ICMPType = 158 // Duplicate Address Confirmation ICMPTypeMPLControl ICMPType = 159 // MPL Control Message + ICMPTypeExtendedEchoRequest ICMPType = 160 // Extended Echo Request + ICMPTypeExtendedEchoReply ICMPType = 161 // Extended Echo Reply ) -// Internet Control Message Protocol version 6 (ICMPv6) Parameters, Updated: 2015-07-07 +// Internet Control Message Protocol version 6 (ICMPv6) Parameters, Updated: 2018-03-09 var icmpTypes = map[ICMPType]string{ 1: "destination unreachable", 2: "packet too big", @@ -79,4 +81,6 @@ var icmpTypes = map[ICMPType]string{ 157: "duplicate address request", 158: "duplicate address confirmation", 159: "mpl control message", + 160: "extended echo request", + 161: "extended echo reply", } diff --git a/vendor/golang.org/x/net/ipv6/icmp_test.go b/vendor/golang.org/x/net/ipv6/icmp_test.go deleted file mode 100644 index d8e9675dc..000000000 --- a/vendor/golang.org/x/net/ipv6/icmp_test.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv6_test - -import ( - "net" - "reflect" - "runtime" - "testing" - - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv6" -) - -var icmpStringTests = []struct { - in ipv6.ICMPType - out string -}{ - {ipv6.ICMPTypeDestinationUnreachable, "destination unreachable"}, - - {256, ""}, -} - -func TestICMPString(t *testing.T) { - for _, tt := range icmpStringTests { - s := tt.in.String() - if s != tt.out { - t.Errorf("got %s; want %s", s, tt.out) - } - } -} - -func TestICMPFilter(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - - var f ipv6.ICMPFilter - for _, toggle := range []bool{false, true} { - f.SetAll(toggle) - for _, typ := range []ipv6.ICMPType{ - ipv6.ICMPTypeDestinationUnreachable, - ipv6.ICMPTypeEchoReply, - ipv6.ICMPTypeNeighborSolicitation, - ipv6.ICMPTypeDuplicateAddressConfirmation, - } { - f.Accept(typ) - if f.WillBlock(typ) { - t.Errorf("ipv6.ICMPFilter.Set(%v, false) failed", typ) - } - f.Block(typ) - if !f.WillBlock(typ) { - t.Errorf("ipv6.ICMPFilter.Set(%v, true) failed", typ) - } - } - } -} - -func TestSetICMPFilter(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if !supportsIPv6 { - t.Skip("ipv6 is not supported") - } - if m, ok := nettest.SupportsRawIPSocket(); !ok { - t.Skip(m) - } - - c, err := net.ListenPacket("ip6:ipv6-icmp", "::1") - if err != nil { - t.Fatal(err) - } - defer c.Close() - - p := ipv6.NewPacketConn(c) - - var f ipv6.ICMPFilter - f.SetAll(true) - f.Accept(ipv6.ICMPTypeEchoRequest) - f.Accept(ipv6.ICMPTypeEchoReply) - if err := p.SetICMPFilter(&f); err != nil { - t.Fatal(err) - } - kf, err := p.ICMPFilter() - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(kf, &f) { - t.Fatalf("got %#v; want %#v", kf, f) - } -} diff --git a/vendor/golang.org/x/net/ipv6/mocktransponder_test.go b/vendor/golang.org/x/net/ipv6/mocktransponder_test.go deleted file mode 100644 index 6efe56c68..000000000 --- a/vendor/golang.org/x/net/ipv6/mocktransponder_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv6_test - -import ( - "net" - "testing" -) - -func connector(t *testing.T, network, addr string, done chan<- bool) { - defer func() { done <- true }() - - c, err := net.Dial(network, addr) - if err != nil { - t.Error(err) - return - } - c.Close() -} - -func acceptor(t *testing.T, ln net.Listener, done chan<- bool) { - defer func() { done <- true }() - - c, err := ln.Accept() - if err != nil { - t.Error(err) - return - } - c.Close() -} diff --git a/vendor/golang.org/x/net/ipv6/multicast_test.go b/vendor/golang.org/x/net/ipv6/multicast_test.go deleted file mode 100644 index 69a21cd38..000000000 --- a/vendor/golang.org/x/net/ipv6/multicast_test.go +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv6_test - -import ( - "bytes" - "net" - "os" - "runtime" - "testing" - "time" - - "golang.org/x/net/icmp" - "golang.org/x/net/internal/iana" - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv6" -) - -var packetConnReadWriteMulticastUDPTests = []struct { - addr string - grp, src *net.UDPAddr -}{ - {"[ff02::]:0", &net.UDPAddr{IP: net.ParseIP("ff02::114")}, nil}, // see RFC 4727 - - {"[ff30::8000:0]:0", &net.UDPAddr{IP: net.ParseIP("ff30::8000:1")}, &net.UDPAddr{IP: net.IPv6loopback}}, // see RFC 5771 -} - -func TestPacketConnReadWriteMulticastUDP(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if !supportsIPv6 { - t.Skip("ipv6 is not supported") - } - if !nettest.SupportsIPv6MulticastDeliveryOnLoopback() { - t.Skipf("multicast delivery doesn't work correctly on %s", runtime.GOOS) - } - ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagMulticast|net.FlagLoopback) - if ifi == nil { - t.Skipf("not available on %s", runtime.GOOS) - } - - for _, tt := range packetConnReadWriteMulticastUDPTests { - c, err := net.ListenPacket("udp6", tt.addr) - if err != nil { - t.Fatal(err) - } - defer c.Close() - - grp := *tt.grp - grp.Port = c.LocalAddr().(*net.UDPAddr).Port - p := ipv6.NewPacketConn(c) - defer p.Close() - if tt.src == nil { - if err := p.JoinGroup(ifi, &grp); err != nil { - t.Fatal(err) - } - defer p.LeaveGroup(ifi, &grp) - } else { - if err := p.JoinSourceSpecificGroup(ifi, &grp, tt.src); err != nil { - switch runtime.GOOS { - case "freebsd", "linux": - default: // platforms that don't support MLDv2 fail here - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } - defer p.LeaveSourceSpecificGroup(ifi, &grp, tt.src) - } - if err := p.SetMulticastInterface(ifi); err != nil { - t.Fatal(err) - } - if _, err := p.MulticastInterface(); err != nil { - t.Fatal(err) - } - if err := p.SetMulticastLoopback(true); err != nil { - t.Fatal(err) - } - if _, err := p.MulticastLoopback(); err != nil { - t.Fatal(err) - } - - cm := ipv6.ControlMessage{ - TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, - Src: net.IPv6loopback, - IfIndex: ifi.Index, - } - cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU - wb := []byte("HELLO-R-U-THERE") - - for i, toggle := range []bool{true, false, true} { - if err := p.SetControlMessage(cf, toggle); err != nil { - if nettest.ProtocolNotSupported(err) { - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } - if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil { - t.Fatal(err) - } - cm.HopLimit = i + 1 - if n, err := p.WriteTo(wb, &cm, &grp); err != nil { - t.Fatal(err) - } else if n != len(wb) { - t.Fatal(err) - } - rb := make([]byte, 128) - if n, _, _, err := p.ReadFrom(rb); err != nil { - t.Fatal(err) - } else if !bytes.Equal(rb[:n], wb) { - t.Fatalf("got %v; want %v", rb[:n], wb) - } - } - } -} - -var packetConnReadWriteMulticastICMPTests = []struct { - grp, src *net.IPAddr -}{ - {&net.IPAddr{IP: net.ParseIP("ff02::114")}, nil}, // see RFC 4727 - - {&net.IPAddr{IP: net.ParseIP("ff30::8000:1")}, &net.IPAddr{IP: net.IPv6loopback}}, // see RFC 5771 -} - -func TestPacketConnReadWriteMulticastICMP(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if !supportsIPv6 { - t.Skip("ipv6 is not supported") - } - if !nettest.SupportsIPv6MulticastDeliveryOnLoopback() { - t.Skipf("multicast delivery doesn't work correctly on %s", runtime.GOOS) - } - if m, ok := nettest.SupportsRawIPSocket(); !ok { - t.Skip(m) - } - ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagMulticast|net.FlagLoopback) - if ifi == nil { - t.Skipf("not available on %s", runtime.GOOS) - } - - for _, tt := range packetConnReadWriteMulticastICMPTests { - c, err := net.ListenPacket("ip6:ipv6-icmp", "::") - if err != nil { - t.Fatal(err) - } - defer c.Close() - - pshicmp := icmp.IPv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, tt.grp.IP) - p := ipv6.NewPacketConn(c) - defer p.Close() - if tt.src == nil { - if err := p.JoinGroup(ifi, tt.grp); err != nil { - t.Fatal(err) - } - defer p.LeaveGroup(ifi, tt.grp) - } else { - if err := p.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil { - switch runtime.GOOS { - case "freebsd", "linux": - default: // platforms that don't support MLDv2 fail here - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } - defer p.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src) - } - if err := p.SetMulticastInterface(ifi); err != nil { - t.Fatal(err) - } - if _, err := p.MulticastInterface(); err != nil { - t.Fatal(err) - } - if err := p.SetMulticastLoopback(true); err != nil { - t.Fatal(err) - } - if _, err := p.MulticastLoopback(); err != nil { - t.Fatal(err) - } - - cm := ipv6.ControlMessage{ - TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, - Src: net.IPv6loopback, - IfIndex: ifi.Index, - } - cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU - - var f ipv6.ICMPFilter - f.SetAll(true) - f.Accept(ipv6.ICMPTypeEchoReply) - if err := p.SetICMPFilter(&f); err != nil { - t.Fatal(err) - } - - var psh []byte - for i, toggle := range []bool{true, false, true} { - if toggle { - psh = nil - if err := p.SetChecksum(true, 2); err != nil { - // Solaris never allows to - // modify ICMP properties. - if runtime.GOOS != "solaris" { - t.Fatal(err) - } - } - } else { - psh = pshicmp - // Some platforms never allow to - // disable the kernel checksum - // processing. - p.SetChecksum(false, -1) - } - wb, err := (&icmp.Message{ - Type: ipv6.ICMPTypeEchoRequest, Code: 0, - Body: &icmp.Echo{ - ID: os.Getpid() & 0xffff, Seq: i + 1, - Data: []byte("HELLO-R-U-THERE"), - }, - }).Marshal(psh) - if err != nil { - t.Fatal(err) - } - if err := p.SetControlMessage(cf, toggle); err != nil { - if nettest.ProtocolNotSupported(err) { - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } - if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil { - t.Fatal(err) - } - cm.HopLimit = i + 1 - if n, err := p.WriteTo(wb, &cm, tt.grp); err != nil { - t.Fatal(err) - } else if n != len(wb) { - t.Fatalf("got %v; want %v", n, len(wb)) - } - rb := make([]byte, 128) - if n, _, _, err := p.ReadFrom(rb); err != nil { - switch runtime.GOOS { - case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } else { - if m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, rb[:n]); err != nil { - t.Fatal(err) - } else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 { - t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0) - } - } - } - } -} diff --git a/vendor/golang.org/x/net/ipv6/multicastlistener_test.go b/vendor/golang.org/x/net/ipv6/multicastlistener_test.go deleted file mode 100644 index b27713e2f..000000000 --- a/vendor/golang.org/x/net/ipv6/multicastlistener_test.go +++ /dev/null @@ -1,261 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv6_test - -import ( - "net" - "runtime" - "testing" - - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv6" -) - -var udpMultipleGroupListenerTests = []net.Addr{ - &net.UDPAddr{IP: net.ParseIP("ff02::114")}, // see RFC 4727 - &net.UDPAddr{IP: net.ParseIP("ff02::1:114")}, - &net.UDPAddr{IP: net.ParseIP("ff02::2:114")}, -} - -func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if !supportsIPv6 { - t.Skip("ipv6 is not supported") - } - - for _, gaddr := range udpMultipleGroupListenerTests { - c, err := net.ListenPacket("udp6", "[::]:0") // wildcard address with non-reusable port - if err != nil { - t.Fatal(err) - } - defer c.Close() - - p := ipv6.NewPacketConn(c) - var mift []*net.Interface - - ift, err := net.Interfaces() - if err != nil { - t.Fatal(err) - } - for i, ifi := range ift { - if _, ok := nettest.IsMulticastCapable("ip6", &ifi); !ok { - continue - } - if err := p.JoinGroup(&ifi, gaddr); err != nil { - t.Fatal(err) - } - mift = append(mift, &ift[i]) - } - for _, ifi := range mift { - if err := p.LeaveGroup(ifi, gaddr); err != nil { - t.Fatal(err) - } - } - } -} - -func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if !supportsIPv6 { - t.Skip("ipv6 is not supported") - } - - for _, gaddr := range udpMultipleGroupListenerTests { - c1, err := net.ListenPacket("udp6", "[ff02::]:0") // wildcard address with reusable port - if err != nil { - t.Fatal(err) - } - defer c1.Close() - _, port, err := net.SplitHostPort(c1.LocalAddr().String()) - if err != nil { - t.Fatal(err) - } - c2, err := net.ListenPacket("udp6", net.JoinHostPort("ff02::", port)) // wildcard address with reusable port - if err != nil { - t.Fatal(err) - } - defer c2.Close() - - var ps [2]*ipv6.PacketConn - ps[0] = ipv6.NewPacketConn(c1) - ps[1] = ipv6.NewPacketConn(c2) - var mift []*net.Interface - - ift, err := net.Interfaces() - if err != nil { - t.Fatal(err) - } - for i, ifi := range ift { - if _, ok := nettest.IsMulticastCapable("ip6", &ifi); !ok { - continue - } - for _, p := range ps { - if err := p.JoinGroup(&ifi, gaddr); err != nil { - t.Fatal(err) - } - } - mift = append(mift, &ift[i]) - } - for _, ifi := range mift { - for _, p := range ps { - if err := p.LeaveGroup(ifi, gaddr); err != nil { - t.Fatal(err) - } - } - } - } -} - -func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if !supportsIPv6 { - t.Skip("ipv6 is not supported") - } - - gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727 - type ml struct { - c *ipv6.PacketConn - ifi *net.Interface - } - var mlt []*ml - - ift, err := net.Interfaces() - if err != nil { - t.Fatal(err) - } - port := "0" - for i, ifi := range ift { - ip, ok := nettest.IsMulticastCapable("ip6", &ifi) - if !ok { - continue - } - c, err := net.ListenPacket("udp6", net.JoinHostPort(ip.String()+"%"+ifi.Name, port)) // unicast address with non-reusable port - if err != nil { - // The listen may fail when the serivce is - // already in use, but it's fine because the - // purpose of this is not to test the - // bookkeeping of IP control block inside the - // kernel. - t.Log(err) - continue - } - defer c.Close() - if port == "0" { - _, port, err = net.SplitHostPort(c.LocalAddr().String()) - if err != nil { - t.Fatal(err) - } - } - p := ipv6.NewPacketConn(c) - if err := p.JoinGroup(&ifi, &gaddr); err != nil { - t.Fatal(err) - } - mlt = append(mlt, &ml{p, &ift[i]}) - } - for _, m := range mlt { - if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil { - t.Fatal(err) - } - } -} - -func TestIPSinglePacketConnWithSingleGroupListener(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if !supportsIPv6 { - t.Skip("ipv6 is not supported") - } - if m, ok := nettest.SupportsRawIPSocket(); !ok { - t.Skip(m) - } - - c, err := net.ListenPacket("ip6:ipv6-icmp", "::") // wildcard address - if err != nil { - t.Fatal(err) - } - defer c.Close() - - p := ipv6.NewPacketConn(c) - gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727 - var mift []*net.Interface - - ift, err := net.Interfaces() - if err != nil { - t.Fatal(err) - } - for i, ifi := range ift { - if _, ok := nettest.IsMulticastCapable("ip6", &ifi); !ok { - continue - } - if err := p.JoinGroup(&ifi, &gaddr); err != nil { - t.Fatal(err) - } - mift = append(mift, &ift[i]) - } - for _, ifi := range mift { - if err := p.LeaveGroup(ifi, &gaddr); err != nil { - t.Fatal(err) - } - } -} - -func TestIPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) { - switch runtime.GOOS { - case "darwin", "dragonfly", "openbsd": // platforms that return fe80::1%lo0: bind: can't assign requested address - t.Skipf("not supported on %s", runtime.GOOS) - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if !supportsIPv6 { - t.Skip("ipv6 is not supported") - } - if m, ok := nettest.SupportsRawIPSocket(); !ok { - t.Skip(m) - } - - gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727 - type ml struct { - c *ipv6.PacketConn - ifi *net.Interface - } - var mlt []*ml - - ift, err := net.Interfaces() - if err != nil { - t.Fatal(err) - } - for i, ifi := range ift { - ip, ok := nettest.IsMulticastCapable("ip6", &ifi) - if !ok { - continue - } - c, err := net.ListenPacket("ip6:ipv6-icmp", ip.String()+"%"+ifi.Name) // unicast address - if err != nil { - t.Fatal(err) - } - defer c.Close() - p := ipv6.NewPacketConn(c) - if err := p.JoinGroup(&ifi, &gaddr); err != nil { - t.Fatal(err) - } - mlt = append(mlt, &ml{p, &ift[i]}) - } - for _, m := range mlt { - if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil { - t.Fatal(err) - } - } -} diff --git a/vendor/golang.org/x/net/ipv6/multicastsockopt_test.go b/vendor/golang.org/x/net/ipv6/multicastsockopt_test.go deleted file mode 100644 index 9e6b902d7..000000000 --- a/vendor/golang.org/x/net/ipv6/multicastsockopt_test.go +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv6_test - -import ( - "net" - "runtime" - "testing" - - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv6" -) - -var packetConnMulticastSocketOptionTests = []struct { - net, proto, addr string - grp, src net.Addr -}{ - {"udp6", "", "[ff02::]:0", &net.UDPAddr{IP: net.ParseIP("ff02::114")}, nil}, // see RFC 4727 - {"ip6", ":ipv6-icmp", "::", &net.IPAddr{IP: net.ParseIP("ff02::115")}, nil}, // see RFC 4727 - - {"udp6", "", "[ff30::8000:0]:0", &net.UDPAddr{IP: net.ParseIP("ff30::8000:1")}, &net.UDPAddr{IP: net.IPv6loopback}}, // see RFC 5771 - {"ip6", ":ipv6-icmp", "::", &net.IPAddr{IP: net.ParseIP("ff30::8000:2")}, &net.IPAddr{IP: net.IPv6loopback}}, // see RFC 5771 -} - -func TestPacketConnMulticastSocketOptions(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if !supportsIPv6 { - t.Skip("ipv6 is not supported") - } - ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagMulticast|net.FlagLoopback) - if ifi == nil { - t.Skipf("not available on %s", runtime.GOOS) - } - - m, ok := nettest.SupportsRawIPSocket() - for _, tt := range packetConnMulticastSocketOptionTests { - if tt.net == "ip6" && !ok { - t.Log(m) - continue - } - c, err := net.ListenPacket(tt.net+tt.proto, tt.addr) - if err != nil { - t.Fatal(err) - } - defer c.Close() - p := ipv6.NewPacketConn(c) - defer p.Close() - - if tt.src == nil { - testMulticastSocketOptions(t, p, ifi, tt.grp) - } else { - testSourceSpecificMulticastSocketOptions(t, p, ifi, tt.grp, tt.src) - } - } -} - -type testIPv6MulticastConn interface { - MulticastHopLimit() (int, error) - SetMulticastHopLimit(ttl int) error - MulticastLoopback() (bool, error) - SetMulticastLoopback(bool) error - JoinGroup(*net.Interface, net.Addr) error - LeaveGroup(*net.Interface, net.Addr) error - JoinSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error - LeaveSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error - ExcludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error - IncludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error -} - -func testMulticastSocketOptions(t *testing.T, c testIPv6MulticastConn, ifi *net.Interface, grp net.Addr) { - const hoplim = 255 - if err := c.SetMulticastHopLimit(hoplim); err != nil { - t.Error(err) - return - } - if v, err := c.MulticastHopLimit(); err != nil { - t.Error(err) - return - } else if v != hoplim { - t.Errorf("got %v; want %v", v, hoplim) - return - } - - for _, toggle := range []bool{true, false} { - if err := c.SetMulticastLoopback(toggle); err != nil { - t.Error(err) - return - } - if v, err := c.MulticastLoopback(); err != nil { - t.Error(err) - return - } else if v != toggle { - t.Errorf("got %v; want %v", v, toggle) - return - } - } - - if err := c.JoinGroup(ifi, grp); err != nil { - t.Error(err) - return - } - if err := c.LeaveGroup(ifi, grp); err != nil { - t.Error(err) - return - } -} - -func testSourceSpecificMulticastSocketOptions(t *testing.T, c testIPv6MulticastConn, ifi *net.Interface, grp, src net.Addr) { - // MCAST_JOIN_GROUP -> MCAST_BLOCK_SOURCE -> MCAST_UNBLOCK_SOURCE -> MCAST_LEAVE_GROUP - if err := c.JoinGroup(ifi, grp); err != nil { - t.Error(err) - return - } - if err := c.ExcludeSourceSpecificGroup(ifi, grp, src); err != nil { - switch runtime.GOOS { - case "freebsd", "linux": - default: // platforms that don't support MLDv2 fail here - t.Logf("not supported on %s", runtime.GOOS) - return - } - t.Error(err) - return - } - if err := c.IncludeSourceSpecificGroup(ifi, grp, src); err != nil { - t.Error(err) - return - } - if err := c.LeaveGroup(ifi, grp); err != nil { - t.Error(err) - return - } - - // MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_SOURCE_GROUP - if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil { - t.Error(err) - return - } - if err := c.LeaveSourceSpecificGroup(ifi, grp, src); err != nil { - t.Error(err) - return - } - - // MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_GROUP - if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil { - t.Error(err) - return - } - if err := c.LeaveGroup(ifi, grp); err != nil { - t.Error(err) - return - } -} diff --git a/vendor/golang.org/x/net/ipv6/payload_cmsg.go b/vendor/golang.org/x/net/ipv6/payload_cmsg.go index 4ee4b062c..e17847d0b 100644 --- a/vendor/golang.org/x/net/ipv6/payload_cmsg.go +++ b/vendor/golang.org/x/net/ipv6/payload_cmsg.go @@ -2,14 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !nacl,!plan9,!windows +// +build darwin dragonfly freebsd linux netbsd openbsd solaris package ipv6 -import ( - "net" - "syscall" -) +import "net" // ReadFrom reads a payload of the received IPv6 datagram, from the // endpoint c, copying the payload into b. It returns the number of @@ -17,7 +14,7 @@ import ( // src of the received datagram. func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) { if !c.ok() { - return 0, nil, nil, syscall.EINVAL + return 0, nil, nil, errInvalidConn } return c.readFrom(b) } @@ -29,7 +26,7 @@ func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net. // cm may be nil if control of the outgoing datagram is not required. func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) { if !c.ok() { - return 0, syscall.EINVAL + return 0, errInvalidConn } return c.writeTo(b, cm, dst) } diff --git a/vendor/golang.org/x/net/ipv6/payload_cmsg_go1_8.go b/vendor/golang.org/x/net/ipv6/payload_cmsg_go1_8.go index fdc6c3994..a48a6ed64 100644 --- a/vendor/golang.org/x/net/ipv6/payload_cmsg_go1_8.go +++ b/vendor/golang.org/x/net/ipv6/payload_cmsg_go1_8.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // +build !go1.9 -// +build !nacl,!plan9,!windows +// +build darwin dragonfly freebsd linux netbsd openbsd solaris package ipv6 diff --git a/vendor/golang.org/x/net/ipv6/payload_cmsg_go1_9.go b/vendor/golang.org/x/net/ipv6/payload_cmsg_go1_9.go index 8f6d02e2f..fb196ed80 100644 --- a/vendor/golang.org/x/net/ipv6/payload_cmsg_go1_9.go +++ b/vendor/golang.org/x/net/ipv6/payload_cmsg_go1_9.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // +build go1.9 -// +build !nacl,!plan9,!windows +// +build darwin dragonfly freebsd linux netbsd openbsd solaris package ipv6 diff --git a/vendor/golang.org/x/net/ipv6/payload_nocmsg.go b/vendor/golang.org/x/net/ipv6/payload_nocmsg.go index 99a43542b..bfb544784 100644 --- a/vendor/golang.org/x/net/ipv6/payload_nocmsg.go +++ b/vendor/golang.org/x/net/ipv6/payload_nocmsg.go @@ -2,14 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build nacl plan9 windows +// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris package ipv6 -import ( - "net" - "syscall" -) +import "net" // ReadFrom reads a payload of the received IPv6 datagram, from the // endpoint c, copying the payload into b. It returns the number of @@ -17,7 +14,7 @@ import ( // src of the received datagram. func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) { if !c.ok() { - return 0, nil, nil, syscall.EINVAL + return 0, nil, nil, errInvalidConn } if n, src, err = c.PacketConn.ReadFrom(b); err != nil { return 0, nil, nil, err @@ -32,7 +29,7 @@ func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net. // cm may be nil if control of the outgoing datagram is not required. func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) { if !c.ok() { - return 0, syscall.EINVAL + return 0, errInvalidConn } if dst == nil { return 0, errMissingAddress diff --git a/vendor/golang.org/x/net/ipv6/readwrite_go1_8_test.go b/vendor/golang.org/x/net/ipv6/readwrite_go1_8_test.go deleted file mode 100644 index c11d92ae9..000000000 --- a/vendor/golang.org/x/net/ipv6/readwrite_go1_8_test.go +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !go1.9 - -package ipv6_test - -import ( - "bytes" - "fmt" - "net" - "runtime" - "strings" - "sync" - "testing" - - "golang.org/x/net/internal/iana" - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv6" -) - -func BenchmarkPacketConnReadWriteUnicast(b *testing.B) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - b.Skipf("not supported on %s", runtime.GOOS) - } - - payload := []byte("HELLO-R-U-THERE") - iph := []byte{ - 0x69, 0x8b, 0xee, 0xf1, 0xca, 0xfe, 0xff, 0x01, - 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - } - greh := []byte{0x00, 0x00, 0x86, 0xdd, 0x00, 0x00, 0x00, 0x00} - datagram := append(greh, append(iph, payload...)...) - bb := make([]byte, 128) - cm := ipv6.ControlMessage{ - TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, - HopLimit: 1, - Src: net.IPv6loopback, - } - if ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); ifi != nil { - cm.IfIndex = ifi.Index - } - - b.Run("UDP", func(b *testing.B) { - c, err := nettest.NewLocalPacketListener("udp6") - if err != nil { - b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - p := ipv6.NewPacketConn(c) - dst := c.LocalAddr() - cf := ipv6.FlagHopLimit | ipv6.FlagInterface - if err := p.SetControlMessage(cf, true); err != nil { - b.Fatal(err) - } - b.Run("Net", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := c.WriteTo(payload, dst); err != nil { - b.Fatal(err) - } - if _, _, err := c.ReadFrom(bb); err != nil { - b.Fatal(err) - } - } - }) - b.Run("ToFrom", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := p.WriteTo(payload, &cm, dst); err != nil { - b.Fatal(err) - } - if _, _, _, err := p.ReadFrom(bb); err != nil { - b.Fatal(err) - } - } - }) - }) - b.Run("IP", func(b *testing.B) { - switch runtime.GOOS { - case "netbsd": - b.Skip("need to configure gre on netbsd") - case "openbsd": - b.Skip("net.inet.gre.allow=0 by default on openbsd") - } - - c, err := net.ListenPacket(fmt.Sprintf("ip6:%d", iana.ProtocolGRE), "::1") - if err != nil { - b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - p := ipv6.NewPacketConn(c) - dst := c.LocalAddr() - cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU - if err := p.SetControlMessage(cf, true); err != nil { - b.Fatal(err) - } - b.Run("Net", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := c.WriteTo(datagram, dst); err != nil { - b.Fatal(err) - } - if _, _, err := c.ReadFrom(bb); err != nil { - b.Fatal(err) - } - } - }) - b.Run("ToFrom", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := p.WriteTo(datagram, &cm, dst); err != nil { - b.Fatal(err) - } - if _, _, _, err := p.ReadFrom(bb); err != nil { - b.Fatal(err) - } - } - }) - }) -} - -func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - - payload := []byte("HELLO-R-U-THERE") - iph := []byte{ - 0x69, 0x8b, 0xee, 0xf1, 0xca, 0xfe, 0xff, 0x01, - 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - } - greh := []byte{0x00, 0x00, 0x86, 0xdd, 0x00, 0x00, 0x00, 0x00} - datagram := append(greh, append(iph, payload...)...) - - t.Run("UDP", func(t *testing.T) { - c, err := nettest.NewLocalPacketListener("udp6") - if err != nil { - t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - p := ipv6.NewPacketConn(c) - t.Run("ToFrom", func(t *testing.T) { - testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr()) - }) - }) - t.Run("IP", func(t *testing.T) { - switch runtime.GOOS { - case "netbsd": - t.Skip("need to configure gre on netbsd") - case "openbsd": - t.Skip("net.inet.gre.allow=0 by default on openbsd") - } - - c, err := net.ListenPacket(fmt.Sprintf("ip6:%d", iana.ProtocolGRE), "::1") - if err != nil { - t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - p := ipv6.NewPacketConn(c) - t.Run("ToFrom", func(t *testing.T) { - testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr()) - }) - }) -} - -func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv6.PacketConn, data []byte, dst net.Addr) { - ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback) - cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU - - if err := p.SetControlMessage(cf, true); err != nil { // probe before test - if nettest.ProtocolNotSupported(err) { - t.Skipf("not supported on %s", runtime.GOOS) - } - t.Fatal(err) - } - - var wg sync.WaitGroup - reader := func() { - defer wg.Done() - b := make([]byte, 128) - n, cm, _, err := p.ReadFrom(b) - if err != nil { - t.Error(err) - return - } - if !bytes.Equal(b[:n], data) { - t.Errorf("got %#v; want %#v", b[:n], data) - return - } - s := cm.String() - if strings.Contains(s, ",") { - t.Errorf("should be space-separated values: %s", s) - return - } - } - writer := func(toggle bool) { - defer wg.Done() - cm := ipv6.ControlMessage{ - TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, - HopLimit: 1, - Src: net.IPv6loopback, - } - if ifi != nil { - cm.IfIndex = ifi.Index - } - if err := p.SetControlMessage(cf, toggle); err != nil { - t.Error(err) - return - } - n, err := p.WriteTo(data, &cm, dst) - if err != nil { - t.Error(err) - return - } - if n != len(data) { - t.Errorf("got %d; want %d", n, len(data)) - return - } - } - - const N = 10 - wg.Add(N) - for i := 0; i < N; i++ { - go reader() - } - wg.Add(2 * N) - for i := 0; i < 2*N; i++ { - go writer(i%2 != 0) - - } - wg.Add(N) - for i := 0; i < N; i++ { - go reader() - } - wg.Wait() -} diff --git a/vendor/golang.org/x/net/ipv6/readwrite_go1_9_test.go b/vendor/golang.org/x/net/ipv6/readwrite_go1_9_test.go deleted file mode 100644 index e2fd73370..000000000 --- a/vendor/golang.org/x/net/ipv6/readwrite_go1_9_test.go +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.9 - -package ipv6_test - -import ( - "bytes" - "fmt" - "net" - "runtime" - "strings" - "sync" - "testing" - - "golang.org/x/net/internal/iana" - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv6" -) - -func BenchmarkPacketConnReadWriteUnicast(b *testing.B) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - b.Skipf("not supported on %s", runtime.GOOS) - } - - payload := []byte("HELLO-R-U-THERE") - iph := []byte{ - 0x69, 0x8b, 0xee, 0xf1, 0xca, 0xfe, 0xff, 0x01, - 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - } - greh := []byte{0x00, 0x00, 0x86, 0xdd, 0x00, 0x00, 0x00, 0x00} - datagram := append(greh, append(iph, payload...)...) - bb := make([]byte, 128) - cm := ipv6.ControlMessage{ - TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, - HopLimit: 1, - Src: net.IPv6loopback, - } - if ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); ifi != nil { - cm.IfIndex = ifi.Index - } - - b.Run("UDP", func(b *testing.B) { - c, err := nettest.NewLocalPacketListener("udp6") - if err != nil { - b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - p := ipv6.NewPacketConn(c) - dst := c.LocalAddr() - cf := ipv6.FlagHopLimit | ipv6.FlagInterface - if err := p.SetControlMessage(cf, true); err != nil { - b.Fatal(err) - } - wms := []ipv6.Message{ - { - Buffers: [][]byte{payload}, - Addr: dst, - OOB: cm.Marshal(), - }, - } - rms := []ipv6.Message{ - { - Buffers: [][]byte{bb}, - OOB: ipv6.NewControlMessage(cf), - }, - } - b.Run("Net", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := c.WriteTo(payload, dst); err != nil { - b.Fatal(err) - } - if _, _, err := c.ReadFrom(bb); err != nil { - b.Fatal(err) - } - } - }) - b.Run("ToFrom", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := p.WriteTo(payload, &cm, dst); err != nil { - b.Fatal(err) - } - if _, _, _, err := p.ReadFrom(bb); err != nil { - b.Fatal(err) - } - } - }) - b.Run("Batch", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := p.WriteBatch(wms, 0); err != nil { - b.Fatal(err) - } - if _, err := p.ReadBatch(rms, 0); err != nil { - b.Fatal(err) - } - } - }) - }) - b.Run("IP", func(b *testing.B) { - switch runtime.GOOS { - case "netbsd": - b.Skip("need to configure gre on netbsd") - case "openbsd": - b.Skip("net.inet.gre.allow=0 by default on openbsd") - } - - c, err := net.ListenPacket(fmt.Sprintf("ip6:%d", iana.ProtocolGRE), "::1") - if err != nil { - b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - p := ipv6.NewPacketConn(c) - dst := c.LocalAddr() - cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU - if err := p.SetControlMessage(cf, true); err != nil { - b.Fatal(err) - } - wms := []ipv6.Message{ - { - Buffers: [][]byte{datagram}, - Addr: dst, - OOB: cm.Marshal(), - }, - } - rms := []ipv6.Message{ - { - Buffers: [][]byte{bb}, - OOB: ipv6.NewControlMessage(cf), - }, - } - b.Run("Net", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := c.WriteTo(datagram, dst); err != nil { - b.Fatal(err) - } - if _, _, err := c.ReadFrom(bb); err != nil { - b.Fatal(err) - } - } - }) - b.Run("ToFrom", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := p.WriteTo(datagram, &cm, dst); err != nil { - b.Fatal(err) - } - if _, _, _, err := p.ReadFrom(bb); err != nil { - b.Fatal(err) - } - } - }) - b.Run("Batch", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := p.WriteBatch(wms, 0); err != nil { - b.Fatal(err) - } - if _, err := p.ReadBatch(rms, 0); err != nil { - b.Fatal(err) - } - } - }) - }) -} - -func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - - payload := []byte("HELLO-R-U-THERE") - iph := []byte{ - 0x69, 0x8b, 0xee, 0xf1, 0xca, 0xfe, 0xff, 0x01, - 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - } - greh := []byte{0x00, 0x00, 0x86, 0xdd, 0x00, 0x00, 0x00, 0x00} - datagram := append(greh, append(iph, payload...)...) - - t.Run("UDP", func(t *testing.T) { - c, err := nettest.NewLocalPacketListener("udp6") - if err != nil { - t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - p := ipv6.NewPacketConn(c) - t.Run("ToFrom", func(t *testing.T) { - testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr(), false) - }) - t.Run("Batch", func(t *testing.T) { - testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr(), true) - }) - }) - t.Run("IP", func(t *testing.T) { - switch runtime.GOOS { - case "netbsd": - t.Skip("need to configure gre on netbsd") - case "openbsd": - t.Skip("net.inet.gre.allow=0 by default on openbsd") - } - - c, err := net.ListenPacket(fmt.Sprintf("ip6:%d", iana.ProtocolGRE), "::1") - if err != nil { - t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - p := ipv6.NewPacketConn(c) - t.Run("ToFrom", func(t *testing.T) { - testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr(), false) - }) - t.Run("Batch", func(t *testing.T) { - testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr(), true) - }) - }) -} - -func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv6.PacketConn, data []byte, dst net.Addr, batch bool) { - ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback) - cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU - - if err := p.SetControlMessage(cf, true); err != nil { // probe before test - if nettest.ProtocolNotSupported(err) { - t.Skipf("not supported on %s", runtime.GOOS) - } - t.Fatal(err) - } - - var wg sync.WaitGroup - reader := func() { - defer wg.Done() - b := make([]byte, 128) - n, cm, _, err := p.ReadFrom(b) - if err != nil { - t.Error(err) - return - } - if !bytes.Equal(b[:n], data) { - t.Errorf("got %#v; want %#v", b[:n], data) - return - } - s := cm.String() - if strings.Contains(s, ",") { - t.Errorf("should be space-separated values: %s", s) - return - } - } - batchReader := func() { - defer wg.Done() - ms := []ipv6.Message{ - { - Buffers: [][]byte{make([]byte, 128)}, - OOB: ipv6.NewControlMessage(cf), - }, - } - n, err := p.ReadBatch(ms, 0) - if err != nil { - t.Error(err) - return - } - if n != len(ms) { - t.Errorf("got %d; want %d", n, len(ms)) - return - } - var cm ipv6.ControlMessage - if err := cm.Parse(ms[0].OOB[:ms[0].NN]); err != nil { - t.Error(err) - return - } - b := ms[0].Buffers[0][:ms[0].N] - if !bytes.Equal(b, data) { - t.Errorf("got %#v; want %#v", b, data) - return - } - s := cm.String() - if strings.Contains(s, ",") { - t.Errorf("should be space-separated values: %s", s) - return - } - } - writer := func(toggle bool) { - defer wg.Done() - cm := ipv6.ControlMessage{ - TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, - HopLimit: 1, - Src: net.IPv6loopback, - } - if ifi != nil { - cm.IfIndex = ifi.Index - } - if err := p.SetControlMessage(cf, toggle); err != nil { - t.Error(err) - return - } - n, err := p.WriteTo(data, &cm, dst) - if err != nil { - t.Error(err) - return - } - if n != len(data) { - t.Errorf("got %d; want %d", n, len(data)) - return - } - } - batchWriter := func(toggle bool) { - defer wg.Done() - cm := ipv6.ControlMessage{ - TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, - HopLimit: 1, - Src: net.IPv6loopback, - } - if ifi != nil { - cm.IfIndex = ifi.Index - } - if err := p.SetControlMessage(cf, toggle); err != nil { - t.Error(err) - return - } - ms := []ipv6.Message{ - { - Buffers: [][]byte{data}, - OOB: cm.Marshal(), - Addr: dst, - }, - } - n, err := p.WriteBatch(ms, 0) - if err != nil { - t.Error(err) - return - } - if n != len(ms) { - t.Errorf("got %d; want %d", n, len(ms)) - return - } - if ms[0].N != len(data) { - t.Errorf("got %d; want %d", ms[0].N, len(data)) - return - } - } - - const N = 10 - wg.Add(N) - for i := 0; i < N; i++ { - if batch { - go batchReader() - } else { - go reader() - } - } - wg.Add(2 * N) - for i := 0; i < 2*N; i++ { - if batch { - go batchWriter(i%2 != 0) - } else { - go writer(i%2 != 0) - } - } - wg.Add(N) - for i := 0; i < N; i++ { - if batch { - go batchReader() - } else { - go reader() - } - } - wg.Wait() -} diff --git a/vendor/golang.org/x/net/ipv6/readwrite_test.go b/vendor/golang.org/x/net/ipv6/readwrite_test.go deleted file mode 100644 index 206b915ce..000000000 --- a/vendor/golang.org/x/net/ipv6/readwrite_test.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv6_test - -import ( - "bytes" - "net" - "runtime" - "strings" - "sync" - "testing" - - "golang.org/x/net/internal/iana" - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv6" -) - -func BenchmarkReadWriteUnicast(b *testing.B) { - c, err := nettest.NewLocalPacketListener("udp6") - if err != nil { - b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err) - } - defer c.Close() - - dst := c.LocalAddr() - wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128) - - b.Run("NetUDP", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := c.WriteTo(wb, dst); err != nil { - b.Fatal(err) - } - if _, _, err := c.ReadFrom(rb); err != nil { - b.Fatal(err) - } - } - }) - b.Run("IPv6UDP", func(b *testing.B) { - p := ipv6.NewPacketConn(c) - cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU - if err := p.SetControlMessage(cf, true); err != nil { - b.Fatal(err) - } - cm := ipv6.ControlMessage{ - TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, - HopLimit: 1, - } - ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback) - if ifi != nil { - cm.IfIndex = ifi.Index - } - - for i := 0; i < b.N; i++ { - if _, err := p.WriteTo(wb, &cm, dst); err != nil { - b.Fatal(err) - } - if _, _, _, err := p.ReadFrom(rb); err != nil { - b.Fatal(err) - } - } - }) -} - -func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if !supportsIPv6 { - t.Skip("ipv6 is not supported") - } - - c, err := nettest.NewLocalPacketListener("udp6") - if err != nil { - t.Fatal(err) - } - defer c.Close() - p := ipv6.NewPacketConn(c) - defer p.Close() - - dst := c.LocalAddr() - ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback) - cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU - wb := []byte("HELLO-R-U-THERE") - - if err := p.SetControlMessage(cf, true); err != nil { // probe before test - if nettest.ProtocolNotSupported(err) { - t.Skipf("not supported on %s", runtime.GOOS) - } - t.Fatal(err) - } - - var wg sync.WaitGroup - reader := func() { - defer wg.Done() - rb := make([]byte, 128) - if n, cm, _, err := p.ReadFrom(rb); err != nil { - t.Error(err) - return - } else if !bytes.Equal(rb[:n], wb) { - t.Errorf("got %v; want %v", rb[:n], wb) - return - } else { - s := cm.String() - if strings.Contains(s, ",") { - t.Errorf("should be space-separated values: %s", s) - } - } - } - writer := func(toggle bool) { - defer wg.Done() - cm := ipv6.ControlMessage{ - TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, - Src: net.IPv6loopback, - } - if ifi != nil { - cm.IfIndex = ifi.Index - } - if err := p.SetControlMessage(cf, toggle); err != nil { - t.Error(err) - return - } - if n, err := p.WriteTo(wb, &cm, dst); err != nil { - t.Error(err) - return - } else if n != len(wb) { - t.Errorf("got %d; want %d", n, len(wb)) - return - } - } - - const N = 10 - wg.Add(N) - for i := 0; i < N; i++ { - go reader() - } - wg.Add(2 * N) - for i := 0; i < 2*N; i++ { - go writer(i%2 != 0) - } - wg.Add(N) - for i := 0; i < N; i++ { - go reader() - } - wg.Wait() -} diff --git a/vendor/golang.org/x/net/ipv6/sockopt_test.go b/vendor/golang.org/x/net/ipv6/sockopt_test.go deleted file mode 100644 index 774338dbf..000000000 --- a/vendor/golang.org/x/net/ipv6/sockopt_test.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv6_test - -import ( - "fmt" - "net" - "runtime" - "testing" - - "golang.org/x/net/internal/iana" - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv6" -) - -var supportsIPv6 bool = nettest.SupportsIPv6() - -func TestConnInitiatorPathMTU(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if !supportsIPv6 { - t.Skip("ipv6 is not supported") - } - - ln, err := net.Listen("tcp6", "[::1]:0") - if err != nil { - t.Fatal(err) - } - defer ln.Close() - - done := make(chan bool) - go acceptor(t, ln, done) - - c, err := net.Dial("tcp6", ln.Addr().String()) - if err != nil { - t.Fatal(err) - } - defer c.Close() - - if pmtu, err := ipv6.NewConn(c).PathMTU(); err != nil { - switch runtime.GOOS { - case "darwin": // older darwin kernels don't support IPV6_PATHMTU option - t.Logf("not supported on %s", runtime.GOOS) - default: - t.Fatal(err) - } - } else { - t.Logf("path mtu for %v: %v", c.RemoteAddr(), pmtu) - } - - <-done -} - -func TestConnResponderPathMTU(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if !supportsIPv6 { - t.Skip("ipv6 is not supported") - } - - ln, err := net.Listen("tcp6", "[::1]:0") - if err != nil { - t.Fatal(err) - } - defer ln.Close() - - done := make(chan bool) - go connector(t, "tcp6", ln.Addr().String(), done) - - c, err := ln.Accept() - if err != nil { - t.Fatal(err) - } - defer c.Close() - - if pmtu, err := ipv6.NewConn(c).PathMTU(); err != nil { - switch runtime.GOOS { - case "darwin": // older darwin kernels don't support IPV6_PATHMTU option - t.Logf("not supported on %s", runtime.GOOS) - default: - t.Fatal(err) - } - } else { - t.Logf("path mtu for %v: %v", c.RemoteAddr(), pmtu) - } - - <-done -} - -func TestPacketConnChecksum(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if !supportsIPv6 { - t.Skip("ipv6 is not supported") - } - if m, ok := nettest.SupportsRawIPSocket(); !ok { - t.Skip(m) - } - - c, err := net.ListenPacket(fmt.Sprintf("ip6:%d", iana.ProtocolOSPFIGP), "::") // OSPF for IPv6 - if err != nil { - t.Fatal(err) - } - defer c.Close() - - p := ipv6.NewPacketConn(c) - offset := 12 // see RFC 5340 - - for _, toggle := range []bool{false, true} { - if err := p.SetChecksum(toggle, offset); err != nil { - if toggle { - t.Fatalf("ipv6.PacketConn.SetChecksum(%v, %v) failed: %v", toggle, offset, err) - } else { - // Some platforms never allow to disable the kernel - // checksum processing. - t.Logf("ipv6.PacketConn.SetChecksum(%v, %v) failed: %v", toggle, offset, err) - } - } - if on, offset, err := p.Checksum(); err != nil { - t.Fatal(err) - } else { - t.Logf("kernel checksum processing enabled=%v, offset=%v", on, offset) - } - } -} diff --git a/vendor/golang.org/x/net/ipv6/unicast_test.go b/vendor/golang.org/x/net/ipv6/unicast_test.go deleted file mode 100644 index a0b7d9550..000000000 --- a/vendor/golang.org/x/net/ipv6/unicast_test.go +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv6_test - -import ( - "bytes" - "net" - "os" - "runtime" - "testing" - "time" - - "golang.org/x/net/icmp" - "golang.org/x/net/internal/iana" - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv6" -) - -func TestPacketConnReadWriteUnicastUDP(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if !supportsIPv6 { - t.Skip("ipv6 is not supported") - } - - c, err := nettest.NewLocalPacketListener("udp6") - if err != nil { - t.Fatal(err) - } - defer c.Close() - p := ipv6.NewPacketConn(c) - defer p.Close() - - dst := c.LocalAddr() - cm := ipv6.ControlMessage{ - TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, - Src: net.IPv6loopback, - } - cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU - ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback) - if ifi != nil { - cm.IfIndex = ifi.Index - } - wb := []byte("HELLO-R-U-THERE") - - for i, toggle := range []bool{true, false, true} { - if err := p.SetControlMessage(cf, toggle); err != nil { - if nettest.ProtocolNotSupported(err) { - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } - cm.HopLimit = i + 1 - if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { - t.Fatal(err) - } - if n, err := p.WriteTo(wb, &cm, dst); err != nil { - t.Fatal(err) - } else if n != len(wb) { - t.Fatalf("got %v; want %v", n, len(wb)) - } - rb := make([]byte, 128) - if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { - t.Fatal(err) - } - if n, _, _, err := p.ReadFrom(rb); err != nil { - t.Fatal(err) - } else if !bytes.Equal(rb[:n], wb) { - t.Fatalf("got %v; want %v", rb[:n], wb) - } - } -} - -func TestPacketConnReadWriteUnicastICMP(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if !supportsIPv6 { - t.Skip("ipv6 is not supported") - } - if m, ok := nettest.SupportsRawIPSocket(); !ok { - t.Skip(m) - } - - c, err := net.ListenPacket("ip6:ipv6-icmp", "::1") - if err != nil { - t.Fatal(err) - } - defer c.Close() - p := ipv6.NewPacketConn(c) - defer p.Close() - - dst, err := net.ResolveIPAddr("ip6", "::1") - if err != nil { - t.Fatal(err) - } - - pshicmp := icmp.IPv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, dst.IP) - cm := ipv6.ControlMessage{ - TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, - Src: net.IPv6loopback, - } - cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU - ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback) - if ifi != nil { - cm.IfIndex = ifi.Index - } - - var f ipv6.ICMPFilter - f.SetAll(true) - f.Accept(ipv6.ICMPTypeEchoReply) - if err := p.SetICMPFilter(&f); err != nil { - t.Fatal(err) - } - - var psh []byte - for i, toggle := range []bool{true, false, true} { - if toggle { - psh = nil - if err := p.SetChecksum(true, 2); err != nil { - // Solaris never allows to modify - // ICMP properties. - if runtime.GOOS != "solaris" { - t.Fatal(err) - } - } - } else { - psh = pshicmp - // Some platforms never allow to disable the - // kernel checksum processing. - p.SetChecksum(false, -1) - } - wb, err := (&icmp.Message{ - Type: ipv6.ICMPTypeEchoRequest, Code: 0, - Body: &icmp.Echo{ - ID: os.Getpid() & 0xffff, Seq: i + 1, - Data: []byte("HELLO-R-U-THERE"), - }, - }).Marshal(psh) - if err != nil { - t.Fatal(err) - } - if err := p.SetControlMessage(cf, toggle); err != nil { - if nettest.ProtocolNotSupported(err) { - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } - cm.HopLimit = i + 1 - if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { - t.Fatal(err) - } - if n, err := p.WriteTo(wb, &cm, dst); err != nil { - t.Fatal(err) - } else if n != len(wb) { - t.Fatalf("got %v; want %v", n, len(wb)) - } - rb := make([]byte, 128) - if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { - t.Fatal(err) - } - if n, _, _, err := p.ReadFrom(rb); err != nil { - switch runtime.GOOS { - case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket - t.Logf("not supported on %s", runtime.GOOS) - continue - } - t.Fatal(err) - } else { - if m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, rb[:n]); err != nil { - t.Fatal(err) - } else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 { - t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0) - } - } - } -} diff --git a/vendor/golang.org/x/net/ipv6/unicastsockopt_test.go b/vendor/golang.org/x/net/ipv6/unicastsockopt_test.go deleted file mode 100644 index e175dccf5..000000000 --- a/vendor/golang.org/x/net/ipv6/unicastsockopt_test.go +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipv6_test - -import ( - "net" - "runtime" - "testing" - - "golang.org/x/net/internal/iana" - "golang.org/x/net/internal/nettest" - "golang.org/x/net/ipv6" -) - -func TestConnUnicastSocketOptions(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if !supportsIPv6 { - t.Skip("ipv6 is not supported") - } - - ln, err := net.Listen("tcp6", "[::1]:0") - if err != nil { - t.Fatal(err) - } - defer ln.Close() - - errc := make(chan error, 1) - go func() { - c, err := ln.Accept() - if err != nil { - errc <- err - return - } - errc <- c.Close() - }() - - c, err := net.Dial("tcp6", ln.Addr().String()) - if err != nil { - t.Fatal(err) - } - defer c.Close() - - testUnicastSocketOptions(t, ipv6.NewConn(c)) - - if err := <-errc; err != nil { - t.Errorf("server: %v", err) - } -} - -var packetConnUnicastSocketOptionTests = []struct { - net, proto, addr string -}{ - {"udp6", "", "[::1]:0"}, - {"ip6", ":ipv6-icmp", "::1"}, -} - -func TestPacketConnUnicastSocketOptions(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } - if !supportsIPv6 { - t.Skip("ipv6 is not supported") - } - - m, ok := nettest.SupportsRawIPSocket() - for _, tt := range packetConnUnicastSocketOptionTests { - if tt.net == "ip6" && !ok { - t.Log(m) - continue - } - c, err := net.ListenPacket(tt.net+tt.proto, tt.addr) - if err != nil { - t.Fatal(err) - } - defer c.Close() - - testUnicastSocketOptions(t, ipv6.NewPacketConn(c)) - } -} - -type testIPv6UnicastConn interface { - TrafficClass() (int, error) - SetTrafficClass(int) error - HopLimit() (int, error) - SetHopLimit(int) error -} - -func testUnicastSocketOptions(t *testing.T, c testIPv6UnicastConn) { - tclass := iana.DiffServCS0 | iana.NotECNTransport - if err := c.SetTrafficClass(tclass); err != nil { - switch runtime.GOOS { - case "darwin": // older darwin kernels don't support IPV6_TCLASS option - t.Logf("not supported on %s", runtime.GOOS) - goto next - } - t.Fatal(err) - } - if v, err := c.TrafficClass(); err != nil { - t.Fatal(err) - } else if v != tclass { - t.Fatalf("got %v; want %v", v, tclass) - } - -next: - hoplim := 255 - if err := c.SetHopLimit(hoplim); err != nil { - t.Fatal(err) - } - if v, err := c.HopLimit(); err != nil { - t.Fatal(err) - } else if v != hoplim { - t.Fatalf("got %v; want %v", v, hoplim) - } -} diff --git a/vendor/golang.org/x/oauth2/CONTRIBUTING.md b/vendor/golang.org/x/oauth2/CONTRIBUTING.md index 46aa2b12d..dfbed62cf 100644 --- a/vendor/golang.org/x/oauth2/CONTRIBUTING.md +++ b/vendor/golang.org/x/oauth2/CONTRIBUTING.md @@ -4,16 +4,15 @@ Go is an open source project. It is the work of hundreds of contributors. We appreciate your help! - ## Filing issues When [filing an issue](https://github.com/golang/oauth2/issues), make sure to answer these five questions: -1. What version of Go are you using (`go version`)? -2. What operating system and processor architecture are you using? -3. What did you do? -4. What did you expect to see? -5. What did you see instead? +1. What version of Go are you using (`go version`)? +2. What operating system and processor architecture are you using? +3. What did you do? +4. What did you expect to see? +5. What did you see instead? General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. The gophers there will answer or ask you to file an issue if you've tripped over a bug. @@ -23,9 +22,5 @@ The gophers there will answer or ask you to file an issue if you've tripped over Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) before sending patches. -**We do not accept GitHub pull requests** -(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review). - Unless otherwise noted, the Go source files are distributed under the BSD-style license found in the LICENSE file. - diff --git a/vendor/golang.org/x/oauth2/LICENSE b/vendor/golang.org/x/oauth2/LICENSE index d02f24fd5..6a66aea5e 100644 --- a/vendor/golang.org/x/oauth2/LICENSE +++ b/vendor/golang.org/x/oauth2/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009 The oauth2 Authors. All rights reserved. +Copyright (c) 2009 The Go Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/vendor/golang.org/x/oauth2/README.md b/vendor/golang.org/x/oauth2/README.md index b0ddf3c10..eb8dcee17 100644 --- a/vendor/golang.org/x/oauth2/README.md +++ b/vendor/golang.org/x/oauth2/README.md @@ -11,6 +11,9 @@ oauth2 package contains a client implementation for OAuth 2.0 spec. go get golang.org/x/oauth2 ~~~~ +Or you can manually git clone the repository to +`$(go env GOPATH)/src/golang.org/x/oauth2`. + See godoc for further documentation and examples. * [godoc.org/golang.org/x/oauth2](http://godoc.org/golang.org/x/oauth2) @@ -19,11 +22,11 @@ See godoc for further documentation and examples. ## App Engine -In change 96e89be (March 2015) we removed the `oauth2.Context2` type in favor +In change 96e89be (March 2015), we removed the `oauth2.Context2` type in favor of the [`context.Context`](https://golang.org/x/net/context#Context) type from the `golang.org/x/net/context` package -This means its no longer possible to use the "Classic App Engine" +This means it's no longer possible to use the "Classic App Engine" `appengine.Context` type with the `oauth2` package. (You're using Classic App Engine if you import the package `"appengine"`.) @@ -39,36 +42,36 @@ If you don't want to update your entire app to use the new App Engine packages, you may use both sets of packages in parallel, using only the new packages with the `oauth2` package. - import ( - "golang.org/x/net/context" - "golang.org/x/oauth2" - "golang.org/x/oauth2/google" - newappengine "google.golang.org/appengine" - newurlfetch "google.golang.org/appengine/urlfetch" - - "appengine" - ) - - func handler(w http.ResponseWriter, r *http.Request) { - var c appengine.Context = appengine.NewContext(r) - c.Infof("Logging a message with the old package") - - var ctx context.Context = newappengine.NewContext(r) - client := &http.Client{ - Transport: &oauth2.Transport{ - Source: google.AppEngineTokenSource(ctx, "scope"), - Base: &newurlfetch.Transport{Context: ctx}, - }, - } - client.Get("...") +```go +import ( + "golang.org/x/net/context" + "golang.org/x/oauth2" + "golang.org/x/oauth2/google" + newappengine "google.golang.org/appengine" + newurlfetch "google.golang.org/appengine/urlfetch" + + "appengine" +) + +func handler(w http.ResponseWriter, r *http.Request) { + var c appengine.Context = appengine.NewContext(r) + c.Infof("Logging a message with the old package") + + var ctx context.Context = newappengine.NewContext(r) + client := &http.Client{ + Transport: &oauth2.Transport{ + Source: google.AppEngineTokenSource(ctx, "scope"), + Base: &newurlfetch.Transport{Context: ctx}, + }, } + client.Get("...") +} +``` -## Contributing - -We appreciate your help! +## Report Issues / Send Patches -To contribute, please read the contribution guidelines: - https://golang.org/doc/contribute.html +This repository uses Gerrit for code changes. To learn how to submit changes to +this repository, see https://golang.org/doc/contribute.html. -Note that the Go project does not use GitHub pull requests but -uses Gerrit for code reviews. See the contribution guide for details. +The main issue tracker for the oauth2 repository is located at +https://github.com/golang/oauth2/issues. diff --git a/vendor/golang.org/x/oauth2/client_appengine.go b/vendor/golang.org/x/oauth2/client_appengine.go deleted file mode 100644 index 8962c49d1..000000000 --- a/vendor/golang.org/x/oauth2/client_appengine.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build appengine - -// App Engine hooks. - -package oauth2 - -import ( - "net/http" - - "golang.org/x/net/context" - "golang.org/x/oauth2/internal" - "google.golang.org/appengine/urlfetch" -) - -func init() { - internal.RegisterContextClientFunc(contextClientAppEngine) -} - -func contextClientAppEngine(ctx context.Context) (*http.Client, error) { - return urlfetch.Client(ctx), nil -} diff --git a/vendor/golang.org/x/oauth2/example_test.go b/vendor/golang.org/x/oauth2/example_test.go deleted file mode 100644 index 378c70dc1..000000000 --- a/vendor/golang.org/x/oauth2/example_test.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package oauth2_test - -import ( - "context" - "fmt" - "log" - "net/http" - "time" - - "golang.org/x/oauth2" -) - -func ExampleConfig() { - ctx := context.Background() - conf := &oauth2.Config{ - ClientID: "YOUR_CLIENT_ID", - ClientSecret: "YOUR_CLIENT_SECRET", - Scopes: []string{"SCOPE1", "SCOPE2"}, - Endpoint: oauth2.Endpoint{ - AuthURL: "https://provider.com/o/oauth2/auth", - TokenURL: "https://provider.com/o/oauth2/token", - }, - } - - // Redirect user to consent page to ask for permission - // for the scopes specified above. - url := conf.AuthCodeURL("state", oauth2.AccessTypeOffline) - fmt.Printf("Visit the URL for the auth dialog: %v", url) - - // Use the authorization code that is pushed to the redirect - // URL. Exchange will do the handshake to retrieve the - // initial access token. The HTTP Client returned by - // conf.Client will refresh the token as necessary. - var code string - if _, err := fmt.Scan(&code); err != nil { - log.Fatal(err) - } - tok, err := conf.Exchange(ctx, code) - if err != nil { - log.Fatal(err) - } - - client := conf.Client(ctx, tok) - client.Get("...") -} - -func ExampleHTTPClient() { - hc := &http.Client{Timeout: 2 * time.Second} - ctx := context.WithValue(context.Background(), oauth2.HTTPClient, hc) - - conf := &oauth2.Config{ - ClientID: "YOUR_CLIENT_ID", - ClientSecret: "YOUR_CLIENT_SECRET", - Scopes: []string{"SCOPE1", "SCOPE2"}, - Endpoint: oauth2.Endpoint{ - AuthURL: "https://provider.com/o/oauth2/auth", - TokenURL: "https://provider.com/o/oauth2/token", - }, - } - - // Exchange request will be made by the custom - // HTTP client, hc. - _, err := conf.Exchange(ctx, "foo") - if err != nil { - log.Fatal(err) - } -} diff --git a/vendor/golang.org/x/oauth2/internal/client_appengine.go b/vendor/golang.org/x/oauth2/internal/client_appengine.go new file mode 100644 index 000000000..743487188 --- /dev/null +++ b/vendor/golang.org/x/oauth2/internal/client_appengine.go @@ -0,0 +1,13 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build appengine + +package internal + +import "google.golang.org/appengine/urlfetch" + +func init() { + appengineClientHook = urlfetch.Client +} diff --git a/vendor/golang.org/x/oauth2/internal/doc.go b/vendor/golang.org/x/oauth2/internal/doc.go new file mode 100644 index 000000000..03265e888 --- /dev/null +++ b/vendor/golang.org/x/oauth2/internal/doc.go @@ -0,0 +1,6 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package internal contains support packages for oauth2 package. +package internal diff --git a/vendor/golang.org/x/oauth2/internal/oauth2.go b/vendor/golang.org/x/oauth2/internal/oauth2.go index e31541b39..fc63fcab3 100644 --- a/vendor/golang.org/x/oauth2/internal/oauth2.go +++ b/vendor/golang.org/x/oauth2/internal/oauth2.go @@ -2,18 +2,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package internal contains support packages for oauth2 package. package internal import ( - "bufio" "crypto/rsa" "crypto/x509" "encoding/pem" "errors" "fmt" - "io" - "strings" ) // ParseKey converts the binary contents of a private key file @@ -39,38 +35,3 @@ func ParseKey(key []byte) (*rsa.PrivateKey, error) { } return parsed, nil } - -func ParseINI(ini io.Reader) (map[string]map[string]string, error) { - result := map[string]map[string]string{ - "": {}, // root section - } - scanner := bufio.NewScanner(ini) - currentSection := "" - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if strings.HasPrefix(line, ";") { - // comment. - continue - } - if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { - currentSection = strings.TrimSpace(line[1 : len(line)-1]) - result[currentSection] = map[string]string{} - continue - } - parts := strings.SplitN(line, "=", 2) - if len(parts) == 2 && parts[0] != "" { - result[currentSection][strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) - } - } - if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("error scanning ini: %v", err) - } - return result, nil -} - -func CondVal(v string) []string { - if v == "" { - return nil - } - return []string{v} -} diff --git a/vendor/golang.org/x/oauth2/internal/oauth2_test.go b/vendor/golang.org/x/oauth2/internal/oauth2_test.go deleted file mode 100644 index 0aafc7f43..000000000 --- a/vendor/golang.org/x/oauth2/internal/oauth2_test.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package internal contains support packages for oauth2 package. -package internal - -import ( - "reflect" - "strings" - "testing" -) - -func TestParseINI(t *testing.T) { - tests := []struct { - ini string - want map[string]map[string]string - }{ - { - `root = toor -[foo] -bar = hop -ini = nin -`, - map[string]map[string]string{ - "": {"root": "toor"}, - "foo": {"bar": "hop", "ini": "nin"}, - }, - }, - { - `[empty] -[section] -empty= -`, - map[string]map[string]string{ - "": {}, - "empty": {}, - "section": {"empty": ""}, - }, - }, - { - `ignore -[invalid -=stuff -;comment=true -`, - map[string]map[string]string{ - "": {}, - }, - }, - } - for _, tt := range tests { - result, err := ParseINI(strings.NewReader(tt.ini)) - if err != nil { - t.Errorf("ParseINI(%q) error %v, want: no error", tt.ini, err) - continue - } - if !reflect.DeepEqual(result, tt.want) { - t.Errorf("ParseINI(%q) = %#v, want: %#v", tt.ini, result, tt.want) - } - } -} diff --git a/vendor/golang.org/x/oauth2/internal/token.go b/vendor/golang.org/x/oauth2/internal/token.go index 018b58ad1..5c5451ad8 100644 --- a/vendor/golang.org/x/oauth2/internal/token.go +++ b/vendor/golang.org/x/oauth2/internal/token.go @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package internal contains support packages for oauth2 package. package internal import ( "encoding/json" + "errors" "fmt" "io" "io/ioutil" @@ -18,9 +18,10 @@ import ( "time" "golang.org/x/net/context" + "golang.org/x/net/context/ctxhttp" ) -// Token represents the crendentials used to authorize +// Token represents the credentials used to authorize // the requests to access protected resources on the OAuth 2.0 // provider's backend. // @@ -100,11 +101,15 @@ var brokenAuthHeaderProviders = []string{ "https://api.pushbullet.com/", "https://api.soundcloud.com/", "https://api.twitch.tv/", + "https://id.twitch.tv/", "https://app.box.com/", + "https://api.box.com/", "https://connect.stripe.com/", - "https://graph.facebook.com", // see https://github.com/golang/oauth2/issues/214 + "https://login.mailchimp.com/", "https://login.microsoftonline.com/", "https://login.salesforce.com/", + "https://login.windows.net", + "https://login.live.com/", "https://oauth.sandbox.trainingpeaks.com/", "https://oauth.trainingpeaks.com/", "https://oauth.vk.com/", @@ -120,11 +125,20 @@ var brokenAuthHeaderProviders = []string{ "https://www.wunderlist.com/oauth/", "https://api.patreon.com/", "https://sandbox.codeswholesale.com/oauth/token", + "https://api.sipgate.com/v1/authorization/oauth", + "https://api.medium.com/v1/tokens", + "https://log.finalsurge.com/oauth/token", + "https://multisport.todaysplan.com.au/rest/oauth/access_token", + "https://whats.todaysplan.com.au/rest/oauth/access_token", + "https://stackoverflow.com/oauth/access_token", + "https://account.health.nokia.com", } // brokenAuthHeaderDomains lists broken providers that issue dynamic endpoints. var brokenAuthHeaderDomains = []string{ + ".auth0.com", ".force.com", + ".myshopify.com", ".okta.com", ".oktapreview.com", } @@ -165,10 +179,6 @@ func providerAuthHeaderWorks(tokenURL string) bool { } func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values) (*Token, error) { - hc, err := ContextClient(ctx) - if err != nil { - return nil, err - } bustedAuth := !providerAuthHeaderWorks(tokenURL) if bustedAuth { if clientID != "" { @@ -184,9 +194,9 @@ func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, } req.Header.Set("Content-Type", "application/x-www-form-urlencoded") if !bustedAuth { - req.SetBasicAuth(clientID, clientSecret) + req.SetBasicAuth(url.QueryEscape(clientID), url.QueryEscape(clientSecret)) } - r, err := hc.Do(req) + r, err := ctxhttp.Do(ctx, ContextClient(ctx), req) if err != nil { return nil, err } @@ -196,7 +206,10 @@ func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err) } if code := r.StatusCode; code < 200 || code > 299 { - return nil, fmt.Errorf("oauth2: cannot fetch token: %v\nResponse: %s", r.Status, body) + return nil, &RetrieveError{ + Response: r, + Body: body, + } } var token *Token @@ -243,5 +256,17 @@ func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, if token.RefreshToken == "" { token.RefreshToken = v.Get("refresh_token") } + if token.AccessToken == "" { + return token, errors.New("oauth2: server response missing access_token") + } return token, nil } + +type RetrieveError struct { + Response *http.Response + Body []byte +} + +func (r *RetrieveError) Error() string { + return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body) +} diff --git a/vendor/golang.org/x/oauth2/internal/token_test.go b/vendor/golang.org/x/oauth2/internal/token_test.go deleted file mode 100644 index 882de1128..000000000 --- a/vendor/golang.org/x/oauth2/internal/token_test.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package internal contains support packages for oauth2 package. -package internal - -import ( - "fmt" - "net/http" - "net/http/httptest" - "net/url" - "testing" - - "golang.org/x/net/context" -) - -func TestRegisterBrokenAuthHeaderProvider(t *testing.T) { - RegisterBrokenAuthHeaderProvider("https://aaa.com/") - tokenURL := "https://aaa.com/token" - if providerAuthHeaderWorks(tokenURL) { - t.Errorf("got %q as unbroken; want broken", tokenURL) - } -} - -func TestRetrieveTokenBustedNoSecret(t *testing.T) { - const clientID = "client-id" - - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if got, want := r.FormValue("client_id"), clientID; got != want { - t.Errorf("client_id = %q; want %q", got, want) - } - if got, want := r.FormValue("client_secret"), ""; got != want { - t.Errorf("client_secret = %q; want empty", got) - } - })) - defer ts.Close() - - RegisterBrokenAuthHeaderProvider(ts.URL) - _, err := RetrieveToken(context.Background(), clientID, "", ts.URL, url.Values{}) - if err != nil { - t.Errorf("RetrieveToken = %v; want no error", err) - } -} - -func Test_providerAuthHeaderWorks(t *testing.T) { - for _, p := range brokenAuthHeaderProviders { - if providerAuthHeaderWorks(p) { - t.Errorf("got %q as unbroken; want broken", p) - } - p := fmt.Sprintf("%ssomesuffix", p) - if providerAuthHeaderWorks(p) { - t.Errorf("got %q as unbroken; want broken", p) - } - } - p := "https://api.not-in-the-list-example.com/" - if !providerAuthHeaderWorks(p) { - t.Errorf("got %q as unbroken; want broken", p) - } -} - -func TestProviderAuthHeaderWorksDomain(t *testing.T) { - tests := []struct { - tokenURL string - wantWorks bool - }{ - {"https://dev-12345.okta.com/token-url", false}, - {"https://dev-12345.oktapreview.com/token-url", false}, - {"https://dev-12345.okta.org/token-url", true}, - {"https://foo.bar.force.com/token-url", false}, - {"https://foo.force.com/token-url", false}, - {"https://force.com/token-url", true}, - } - - for _, test := range tests { - got := providerAuthHeaderWorks(test.tokenURL) - if got != test.wantWorks { - t.Errorf("providerAuthHeaderWorks(%q) = %v; want %v", test.tokenURL, got, test.wantWorks) - } - } -} diff --git a/vendor/golang.org/x/oauth2/internal/transport.go b/vendor/golang.org/x/oauth2/internal/transport.go index f1f173e34..d16f9ae1f 100644 --- a/vendor/golang.org/x/oauth2/internal/transport.go +++ b/vendor/golang.org/x/oauth2/internal/transport.go @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package internal contains support packages for oauth2 package. package internal import ( @@ -20,50 +19,16 @@ var HTTPClient ContextKey // because nobody else can create a ContextKey, being unexported. type ContextKey struct{} -// ContextClientFunc is a func which tries to return an *http.Client -// given a Context value. If it returns an error, the search stops -// with that error. If it returns (nil, nil), the search continues -// down the list of registered funcs. -type ContextClientFunc func(context.Context) (*http.Client, error) +var appengineClientHook func(context.Context) *http.Client -var contextClientFuncs []ContextClientFunc - -func RegisterContextClientFunc(fn ContextClientFunc) { - contextClientFuncs = append(contextClientFuncs, fn) -} - -func ContextClient(ctx context.Context) (*http.Client, error) { +func ContextClient(ctx context.Context) *http.Client { if ctx != nil { if hc, ok := ctx.Value(HTTPClient).(*http.Client); ok { - return hc, nil + return hc } } - for _, fn := range contextClientFuncs { - c, err := fn(ctx) - if err != nil { - return nil, err - } - if c != nil { - return c, nil - } + if appengineClientHook != nil { + return appengineClientHook(ctx) } - return http.DefaultClient, nil -} - -func ContextTransport(ctx context.Context) http.RoundTripper { - hc, err := ContextClient(ctx) - // This is a rare error case (somebody using nil on App Engine). - if err != nil { - return ErrorTransport{err} - } - return hc.Transport -} - -// ErrorTransport returns the specified error on RoundTrip. -// This RoundTripper should be used in rare error cases where -// error handling can be postponed to response handling time. -type ErrorTransport struct{ Err error } - -func (t ErrorTransport) RoundTrip(*http.Request) (*http.Response, error) { - return nil, t.Err + return http.DefaultClient } diff --git a/vendor/golang.org/x/oauth2/internal/transport_test.go b/vendor/golang.org/x/oauth2/internal/transport_test.go deleted file mode 100644 index 8772ec5c4..000000000 --- a/vendor/golang.org/x/oauth2/internal/transport_test.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -import ( - "net/http" - "testing" - - "golang.org/x/net/context" -) - -func TestContextClient(t *testing.T) { - rc := &http.Client{} - RegisterContextClientFunc(func(context.Context) (*http.Client, error) { - return rc, nil - }) - - c := &http.Client{} - ctx := context.WithValue(context.Background(), HTTPClient, c) - - hc, err := ContextClient(ctx) - if err != nil { - t.Fatalf("want valid client; got err = %v", err) - } - if hc != c { - t.Fatalf("want context client = %p; got = %p", c, hc) - } - - hc, err = ContextClient(context.TODO()) - if err != nil { - t.Fatalf("want valid client; got err = %v", err) - } - if hc != rc { - t.Fatalf("want registered client = %p; got = %p", c, hc) - } -} diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go index 3e4835d7e..16775d081 100644 --- a/vendor/golang.org/x/oauth2/oauth2.go +++ b/vendor/golang.org/x/oauth2/oauth2.go @@ -3,7 +3,8 @@ // license that can be found in the LICENSE file. // Package oauth2 provides support for making -// OAuth2 authorized and authenticated HTTP requests. +// OAuth2 authorized and authenticated HTTP requests, +// as specified in RFC 6749. // It can additionally grant authorization with Bearer JWT. package oauth2 // import "golang.org/x/oauth2" @@ -117,21 +118,30 @@ func SetAuthURLParam(key, value string) AuthCodeOption { // that asks for permissions for the required scopes explicitly. // // State is a token to protect the user from CSRF attacks. You must -// always provide a non-zero string and validate that it matches the +// always provide a non-empty string and validate that it matches the // the state query parameter on your redirect callback. // See http://tools.ietf.org/html/rfc6749#section-10.12 for more info. // // Opts may include AccessTypeOnline or AccessTypeOffline, as well // as ApprovalForce. +// It can also be used to pass the PKCE challange. +// See https://www.oauth.com/oauth2-servers/pkce/ for more info. func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string { var buf bytes.Buffer buf.WriteString(c.Endpoint.AuthURL) v := url.Values{ "response_type": {"code"}, "client_id": {c.ClientID}, - "redirect_uri": internal.CondVal(c.RedirectURL), - "scope": internal.CondVal(strings.Join(c.Scopes, " ")), - "state": internal.CondVal(state), + } + if c.RedirectURL != "" { + v.Set("redirect_uri", c.RedirectURL) + } + if len(c.Scopes) > 0 { + v.Set("scope", strings.Join(c.Scopes, " ")) + } + if state != "" { + // TODO(light): Docs say never to omit state; don't allow empty. + v.Set("state", state) } for _, opt := range opts { opt.setValue(v) @@ -157,12 +167,15 @@ func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string { // The HTTP client to use is derived from the context. // If nil, http.DefaultClient is used. func (c *Config) PasswordCredentialsToken(ctx context.Context, username, password string) (*Token, error) { - return retrieveToken(ctx, c, url.Values{ + v := url.Values{ "grant_type": {"password"}, "username": {username}, "password": {password}, - "scope": internal.CondVal(strings.Join(c.Scopes, " ")), - }) + } + if len(c.Scopes) > 0 { + v.Set("scope", strings.Join(c.Scopes, " ")) + } + return retrieveToken(ctx, c, v) } // Exchange converts an authorization code into a token. @@ -175,12 +188,21 @@ func (c *Config) PasswordCredentialsToken(ctx context.Context, username, passwor // // The code will be in the *http.Request.FormValue("code"). Before // calling Exchange, be sure to validate FormValue("state"). -func (c *Config) Exchange(ctx context.Context, code string) (*Token, error) { - return retrieveToken(ctx, c, url.Values{ - "grant_type": {"authorization_code"}, - "code": {code}, - "redirect_uri": internal.CondVal(c.RedirectURL), - }) +// +// Opts may include the PKCE verifier code if previously used in AuthCodeURL. +// See https://www.oauth.com/oauth2-servers/pkce/ for more info. +func (c *Config) Exchange(ctx context.Context, code string, opts ...AuthCodeOption) (*Token, error) { + v := url.Values{ + "grant_type": {"authorization_code"}, + "code": {code}, + } + if c.RedirectURL != "" { + v.Set("redirect_uri", c.RedirectURL) + } + for _, opt := range opts { + opt.setValue(v) + } + return retrieveToken(ctx, c, v) } // Client returns an HTTP client using the provided token. @@ -291,20 +313,20 @@ var HTTPClient internal.ContextKey // NewClient creates an *http.Client from a Context and TokenSource. // The returned client is not valid beyond the lifetime of the context. // +// Note that if a custom *http.Client is provided via the Context it +// is used only for token acquisition and is not used to configure the +// *http.Client returned from NewClient. +// // As a special case, if src is nil, a non-OAuth2 client is returned // using the provided context. This exists to support related OAuth2 // packages. func NewClient(ctx context.Context, src TokenSource) *http.Client { if src == nil { - c, err := internal.ContextClient(ctx) - if err != nil { - return &http.Client{Transport: internal.ErrorTransport{Err: err}} - } - return c + return internal.ContextClient(ctx) } return &http.Client{ Transport: &Transport{ - Base: internal.ContextTransport(ctx), + Base: internal.ContextClient(ctx).Transport, Source: ReuseTokenSource(nil, src), }, } diff --git a/vendor/golang.org/x/oauth2/oauth2_test.go b/vendor/golang.org/x/oauth2/oauth2_test.go deleted file mode 100644 index e757b0f10..000000000 --- a/vendor/golang.org/x/oauth2/oauth2_test.go +++ /dev/null @@ -1,448 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package oauth2 - -import ( - "errors" - "fmt" - "io/ioutil" - "net/http" - "net/http/httptest" - "net/url" - "testing" - "time" - - "golang.org/x/net/context" -) - -type mockTransport struct { - rt func(req *http.Request) (resp *http.Response, err error) -} - -func (t *mockTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) { - return t.rt(req) -} - -func newConf(url string) *Config { - return &Config{ - ClientID: "CLIENT_ID", - ClientSecret: "CLIENT_SECRET", - RedirectURL: "REDIRECT_URL", - Scopes: []string{"scope1", "scope2"}, - Endpoint: Endpoint{ - AuthURL: url + "/auth", - TokenURL: url + "/token", - }, - } -} - -func TestAuthCodeURL(t *testing.T) { - conf := newConf("server") - url := conf.AuthCodeURL("foo", AccessTypeOffline, ApprovalForce) - const want = "server/auth?access_type=offline&approval_prompt=force&client_id=CLIENT_ID&redirect_uri=REDIRECT_URL&response_type=code&scope=scope1+scope2&state=foo" - if got := url; got != want { - t.Errorf("got auth code URL = %q; want %q", got, want) - } -} - -func TestAuthCodeURL_CustomParam(t *testing.T) { - conf := newConf("server") - param := SetAuthURLParam("foo", "bar") - url := conf.AuthCodeURL("baz", param) - const want = "server/auth?client_id=CLIENT_ID&foo=bar&redirect_uri=REDIRECT_URL&response_type=code&scope=scope1+scope2&state=baz" - if got := url; got != want { - t.Errorf("got auth code = %q; want %q", got, want) - } -} - -func TestAuthCodeURL_Optional(t *testing.T) { - conf := &Config{ - ClientID: "CLIENT_ID", - Endpoint: Endpoint{ - AuthURL: "/auth-url", - TokenURL: "/token-url", - }, - } - url := conf.AuthCodeURL("") - const want = "/auth-url?client_id=CLIENT_ID&response_type=code" - if got := url; got != want { - t.Fatalf("got auth code = %q; want %q", got, want) - } -} - -func TestExchangeRequest(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.URL.String() != "/token" { - t.Errorf("Unexpected exchange request URL, %v is found.", r.URL) - } - headerAuth := r.Header.Get("Authorization") - if headerAuth != "Basic Q0xJRU5UX0lEOkNMSUVOVF9TRUNSRVQ=" { - t.Errorf("Unexpected authorization header, %v is found.", headerAuth) - } - headerContentType := r.Header.Get("Content-Type") - if headerContentType != "application/x-www-form-urlencoded" { - t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType) - } - body, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Errorf("Failed reading request body: %s.", err) - } - if string(body) != "code=exchange-code&grant_type=authorization_code&redirect_uri=REDIRECT_URL" { - t.Errorf("Unexpected exchange payload, %v is found.", string(body)) - } - w.Header().Set("Content-Type", "application/x-www-form-urlencoded") - w.Write([]byte("access_token=90d64460d14870c08c81352a05dedd3465940a7c&scope=user&token_type=bearer")) - })) - defer ts.Close() - conf := newConf(ts.URL) - tok, err := conf.Exchange(context.Background(), "exchange-code") - if err != nil { - t.Error(err) - } - if !tok.Valid() { - t.Fatalf("Token invalid. Got: %#v", tok) - } - if tok.AccessToken != "90d64460d14870c08c81352a05dedd3465940a7c" { - t.Errorf("Unexpected access token, %#v.", tok.AccessToken) - } - if tok.TokenType != "bearer" { - t.Errorf("Unexpected token type, %#v.", tok.TokenType) - } - scope := tok.Extra("scope") - if scope != "user" { - t.Errorf("Unexpected value for scope: %v", scope) - } -} - -func TestExchangeRequest_JSONResponse(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.URL.String() != "/token" { - t.Errorf("Unexpected exchange request URL, %v is found.", r.URL) - } - headerAuth := r.Header.Get("Authorization") - if headerAuth != "Basic Q0xJRU5UX0lEOkNMSUVOVF9TRUNSRVQ=" { - t.Errorf("Unexpected authorization header, %v is found.", headerAuth) - } - headerContentType := r.Header.Get("Content-Type") - if headerContentType != "application/x-www-form-urlencoded" { - t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType) - } - body, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Errorf("Failed reading request body: %s.", err) - } - if string(body) != "code=exchange-code&grant_type=authorization_code&redirect_uri=REDIRECT_URL" { - t.Errorf("Unexpected exchange payload, %v is found.", string(body)) - } - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(`{"access_token": "90d64460d14870c08c81352a05dedd3465940a7c", "scope": "user", "token_type": "bearer", "expires_in": 86400}`)) - })) - defer ts.Close() - conf := newConf(ts.URL) - tok, err := conf.Exchange(context.Background(), "exchange-code") - if err != nil { - t.Error(err) - } - if !tok.Valid() { - t.Fatalf("Token invalid. Got: %#v", tok) - } - if tok.AccessToken != "90d64460d14870c08c81352a05dedd3465940a7c" { - t.Errorf("Unexpected access token, %#v.", tok.AccessToken) - } - if tok.TokenType != "bearer" { - t.Errorf("Unexpected token type, %#v.", tok.TokenType) - } - scope := tok.Extra("scope") - if scope != "user" { - t.Errorf("Unexpected value for scope: %v", scope) - } - expiresIn := tok.Extra("expires_in") - if expiresIn != float64(86400) { - t.Errorf("Unexpected non-numeric value for expires_in: %v", expiresIn) - } -} - -func TestExtraValueRetrieval(t *testing.T) { - values := url.Values{} - kvmap := map[string]string{ - "scope": "user", "token_type": "bearer", "expires_in": "86400.92", - "server_time": "1443571905.5606415", "referer_ip": "10.0.0.1", - "etag": "\"afZYj912P4alikMz_P11982\"", "request_id": "86400", - "untrimmed": " untrimmed ", - } - for key, value := range kvmap { - values.Set(key, value) - } - - tok := Token{raw: values} - scope := tok.Extra("scope") - if got, want := scope, "user"; got != want { - t.Errorf("got scope = %q; want %q", got, want) - } - serverTime := tok.Extra("server_time") - if got, want := serverTime, 1443571905.5606415; got != want { - t.Errorf("got server_time value = %v; want %v", got, want) - } - refererIP := tok.Extra("referer_ip") - if got, want := refererIP, "10.0.0.1"; got != want { - t.Errorf("got referer_ip value = %v, want %v", got, want) - } - expiresIn := tok.Extra("expires_in") - if got, want := expiresIn, 86400.92; got != want { - t.Errorf("got expires_in value = %v, want %v", got, want) - } - requestID := tok.Extra("request_id") - if got, want := requestID, int64(86400); got != want { - t.Errorf("got request_id value = %v, want %v", got, want) - } - untrimmed := tok.Extra("untrimmed") - if got, want := untrimmed, " untrimmed "; got != want { - t.Errorf("got untrimmed = %q; want %q", got, want) - } -} - -const day = 24 * time.Hour - -func TestExchangeRequest_JSONResponse_Expiry(t *testing.T) { - seconds := int32(day.Seconds()) - for _, c := range []struct { - expires string - want bool - }{ - {fmt.Sprintf(`"expires_in": %d`, seconds), true}, - {fmt.Sprintf(`"expires_in": "%d"`, seconds), true}, // PayPal case - {fmt.Sprintf(`"expires": %d`, seconds), true}, // Facebook case - {`"expires": false`, false}, // wrong type - {`"expires": {}`, false}, // wrong type - {`"expires": "zzz"`, false}, // wrong value - } { - testExchangeRequest_JSONResponse_expiry(t, c.expires, c.want) - } -} - -func testExchangeRequest_JSONResponse_expiry(t *testing.T, exp string, want bool) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(fmt.Sprintf(`{"access_token": "90d", "scope": "user", "token_type": "bearer", %s}`, exp))) - })) - defer ts.Close() - conf := newConf(ts.URL) - t1 := time.Now().Add(day) - tok, err := conf.Exchange(context.Background(), "exchange-code") - t2 := time.Now().Add(day) - - if got := (err == nil); got != want { - if want { - t.Errorf("unexpected error: got %v", err) - } else { - t.Errorf("unexpected success") - } - } - if !want { - return - } - if !tok.Valid() { - t.Fatalf("Token invalid. Got: %#v", tok) - } - expiry := tok.Expiry - if expiry.Before(t1) || expiry.After(t2) { - t.Errorf("Unexpected value for Expiry: %v (shold be between %v and %v)", expiry, t1, t2) - } -} - -func TestExchangeRequest_BadResponse(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(`{"scope": "user", "token_type": "bearer"}`)) - })) - defer ts.Close() - conf := newConf(ts.URL) - tok, err := conf.Exchange(context.Background(), "code") - if err != nil { - t.Fatal(err) - } - if tok.AccessToken != "" { - t.Errorf("Unexpected access token, %#v.", tok.AccessToken) - } -} - -func TestExchangeRequest_BadResponseType(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(`{"access_token":123, "scope": "user", "token_type": "bearer"}`)) - })) - defer ts.Close() - conf := newConf(ts.URL) - _, err := conf.Exchange(context.Background(), "exchange-code") - if err == nil { - t.Error("expected error from invalid access_token type") - } -} - -func TestExchangeRequest_NonBasicAuth(t *testing.T) { - tr := &mockTransport{ - rt: func(r *http.Request) (w *http.Response, err error) { - headerAuth := r.Header.Get("Authorization") - if headerAuth != "" { - t.Errorf("Unexpected authorization header, %v is found.", headerAuth) - } - return nil, errors.New("no response") - }, - } - c := &http.Client{Transport: tr} - conf := &Config{ - ClientID: "CLIENT_ID", - Endpoint: Endpoint{ - AuthURL: "https://accounts.google.com/auth", - TokenURL: "https://accounts.google.com/token", - }, - } - - ctx := context.WithValue(context.Background(), HTTPClient, c) - conf.Exchange(ctx, "code") -} - -func TestPasswordCredentialsTokenRequest(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - defer r.Body.Close() - expected := "/token" - if r.URL.String() != expected { - t.Errorf("URL = %q; want %q", r.URL, expected) - } - headerAuth := r.Header.Get("Authorization") - expected = "Basic Q0xJRU5UX0lEOkNMSUVOVF9TRUNSRVQ=" - if headerAuth != expected { - t.Errorf("Authorization header = %q; want %q", headerAuth, expected) - } - headerContentType := r.Header.Get("Content-Type") - expected = "application/x-www-form-urlencoded" - if headerContentType != expected { - t.Errorf("Content-Type header = %q; want %q", headerContentType, expected) - } - body, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Errorf("Failed reading request body: %s.", err) - } - expected = "grant_type=password&password=password1&scope=scope1+scope2&username=user1" - if string(body) != expected { - t.Errorf("res.Body = %q; want %q", string(body), expected) - } - w.Header().Set("Content-Type", "application/x-www-form-urlencoded") - w.Write([]byte("access_token=90d64460d14870c08c81352a05dedd3465940a7c&scope=user&token_type=bearer")) - })) - defer ts.Close() - conf := newConf(ts.URL) - tok, err := conf.PasswordCredentialsToken(context.Background(), "user1", "password1") - if err != nil { - t.Error(err) - } - if !tok.Valid() { - t.Fatalf("Token invalid. Got: %#v", tok) - } - expected := "90d64460d14870c08c81352a05dedd3465940a7c" - if tok.AccessToken != expected { - t.Errorf("AccessToken = %q; want %q", tok.AccessToken, expected) - } - expected = "bearer" - if tok.TokenType != expected { - t.Errorf("TokenType = %q; want %q", tok.TokenType, expected) - } -} - -func TestTokenRefreshRequest(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.URL.String() == "/somethingelse" { - return - } - if r.URL.String() != "/token" { - t.Errorf("Unexpected token refresh request URL, %v is found.", r.URL) - } - headerContentType := r.Header.Get("Content-Type") - if headerContentType != "application/x-www-form-urlencoded" { - t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType) - } - body, _ := ioutil.ReadAll(r.Body) - if string(body) != "grant_type=refresh_token&refresh_token=REFRESH_TOKEN" { - t.Errorf("Unexpected refresh token payload, %v is found.", string(body)) - } - })) - defer ts.Close() - conf := newConf(ts.URL) - c := conf.Client(context.Background(), &Token{RefreshToken: "REFRESH_TOKEN"}) - c.Get(ts.URL + "/somethingelse") -} - -func TestFetchWithNoRefreshToken(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.URL.String() == "/somethingelse" { - return - } - if r.URL.String() != "/token" { - t.Errorf("Unexpected token refresh request URL, %v is found.", r.URL) - } - headerContentType := r.Header.Get("Content-Type") - if headerContentType != "application/x-www-form-urlencoded" { - t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType) - } - body, _ := ioutil.ReadAll(r.Body) - if string(body) != "client_id=CLIENT_ID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN" { - t.Errorf("Unexpected refresh token payload, %v is found.", string(body)) - } - })) - defer ts.Close() - conf := newConf(ts.URL) - c := conf.Client(context.Background(), nil) - _, err := c.Get(ts.URL + "/somethingelse") - if err == nil { - t.Errorf("Fetch should return an error if no refresh token is set") - } -} - -func TestRefreshToken_RefreshTokenReplacement(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(`{"access_token":"ACCESS TOKEN", "scope": "user", "token_type": "bearer", "refresh_token": "NEW REFRESH TOKEN"}`)) - return - })) - defer ts.Close() - conf := newConf(ts.URL) - tkr := tokenRefresher{ - conf: conf, - ctx: context.Background(), - refreshToken: "OLD REFRESH TOKEN", - } - tk, err := tkr.Token() - if err != nil { - t.Errorf("got err = %v; want none", err) - return - } - if tk.RefreshToken != tkr.refreshToken { - t.Errorf("tokenRefresher.refresh_token = %q; want %q", tkr.refreshToken, tk.RefreshToken) - } -} - -func TestConfigClientWithToken(t *testing.T) { - tok := &Token{ - AccessToken: "abc123", - } - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("Authorization"), fmt.Sprintf("Bearer %s", tok.AccessToken); got != want { - t.Errorf("Authorization header = %q; want %q", got, want) - } - return - })) - defer ts.Close() - conf := newConf(ts.URL) - - c := conf.Client(context.Background(), tok) - req, err := http.NewRequest("GET", ts.URL, nil) - if err != nil { - t.Error(err) - } - _, err = c.Do(req) - if err != nil { - t.Error(err) - } -} diff --git a/vendor/golang.org/x/oauth2/token.go b/vendor/golang.org/x/oauth2/token.go index 7a3167f15..34db8cdc8 100644 --- a/vendor/golang.org/x/oauth2/token.go +++ b/vendor/golang.org/x/oauth2/token.go @@ -5,6 +5,7 @@ package oauth2 import ( + "fmt" "net/http" "net/url" "strconv" @@ -20,7 +21,7 @@ import ( // expirations due to client-server time mismatches. const expiryDelta = 10 * time.Second -// Token represents the crendentials used to authorize +// Token represents the credentials used to authorize // the requests to access protected resources on the OAuth 2.0 // provider's backend. // @@ -123,7 +124,7 @@ func (t *Token) expired() bool { if t.Expiry.IsZero() { return false } - return t.Expiry.Add(-expiryDelta).Before(time.Now()) + return t.Expiry.Round(0).Add(-expiryDelta).Before(time.Now()) } // Valid reports whether t is non-nil, has an AccessToken, and is not expired. @@ -152,7 +153,23 @@ func tokenFromInternal(t *internal.Token) *Token { func retrieveToken(ctx context.Context, c *Config, v url.Values) (*Token, error) { tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v) if err != nil { + if rErr, ok := err.(*internal.RetrieveError); ok { + return nil, (*RetrieveError)(rErr) + } return nil, err } return tokenFromInternal(tk), nil } + +// RetrieveError is the error returned when the token endpoint returns a +// non-2XX HTTP status code. +type RetrieveError struct { + Response *http.Response + // Body is the body that was consumed by reading Response.Body. + // It may be truncated. + Body []byte +} + +func (r *RetrieveError) Error() string { + return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body) +} diff --git a/vendor/golang.org/x/oauth2/token_test.go b/vendor/golang.org/x/oauth2/token_test.go deleted file mode 100644 index 80db83c29..000000000 --- a/vendor/golang.org/x/oauth2/token_test.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package oauth2 - -import ( - "testing" - "time" -) - -func TestTokenExtra(t *testing.T) { - type testCase struct { - key string - val interface{} - want interface{} - } - const key = "extra-key" - cases := []testCase{ - {key: key, val: "abc", want: "abc"}, - {key: key, val: 123, want: 123}, - {key: key, val: "", want: ""}, - {key: "other-key", val: "def", want: nil}, - } - for _, tc := range cases { - extra := make(map[string]interface{}) - extra[tc.key] = tc.val - tok := &Token{raw: extra} - if got, want := tok.Extra(key), tc.want; got != want { - t.Errorf("Extra(%q) = %q; want %q", key, got, want) - } - } -} - -func TestTokenExpiry(t *testing.T) { - now := time.Now() - cases := []struct { - name string - tok *Token - want bool - }{ - {name: "12 seconds", tok: &Token{Expiry: now.Add(12 * time.Second)}, want: false}, - {name: "10 seconds", tok: &Token{Expiry: now.Add(expiryDelta)}, want: true}, - {name: "-1 hour", tok: &Token{Expiry: now.Add(-1 * time.Hour)}, want: true}, - } - for _, tc := range cases { - if got, want := tc.tok.expired(), tc.want; got != want { - t.Errorf("expired (%q) = %v; want %v", tc.name, got, want) - } - } -} - -func TestTokenTypeMethod(t *testing.T) { - cases := []struct { - name string - tok *Token - want string - }{ - {name: "bearer-mixed_case", tok: &Token{TokenType: "beAREr"}, want: "Bearer"}, - {name: "default-bearer", tok: &Token{}, want: "Bearer"}, - {name: "basic", tok: &Token{TokenType: "basic"}, want: "Basic"}, - {name: "basic-capitalized", tok: &Token{TokenType: "Basic"}, want: "Basic"}, - {name: "mac", tok: &Token{TokenType: "mac"}, want: "MAC"}, - {name: "mac-caps", tok: &Token{TokenType: "MAC"}, want: "MAC"}, - {name: "mac-mixed_case", tok: &Token{TokenType: "mAc"}, want: "MAC"}, - } - for _, tc := range cases { - if got, want := tc.tok.Type(), tc.want; got != want { - t.Errorf("TokenType(%q) = %v; want %v", tc.name, got, want) - } - } -} diff --git a/vendor/golang.org/x/oauth2/transport.go b/vendor/golang.org/x/oauth2/transport.go index 92ac7e253..aa0d34f1e 100644 --- a/vendor/golang.org/x/oauth2/transport.go +++ b/vendor/golang.org/x/oauth2/transport.go @@ -31,9 +31,17 @@ type Transport struct { } // RoundTrip authorizes and authenticates the request with an -// access token. If no token exists or token is expired, -// tries to refresh/fetch a new token. +// access token from Transport's Source. func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { + reqBodyClosed := false + if req.Body != nil { + defer func() { + if !reqBodyClosed { + req.Body.Close() + } + }() + } + if t.Source == nil { return nil, errors.New("oauth2: Transport's Source is nil") } @@ -46,6 +54,10 @@ func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { token.SetAuthHeader(req2) t.setModReq(req, req2) res, err := t.base().RoundTrip(req2) + + // req.Body is assumed to have been closed by the base RoundTripper. + reqBodyClosed = true + if err != nil { t.setModReq(req, nil) return nil, err diff --git a/vendor/golang.org/x/oauth2/transport_test.go b/vendor/golang.org/x/oauth2/transport_test.go deleted file mode 100644 index d6e8087d6..000000000 --- a/vendor/golang.org/x/oauth2/transport_test.go +++ /dev/null @@ -1,108 +0,0 @@ -package oauth2 - -import ( - "net/http" - "net/http/httptest" - "testing" - "time" -) - -type tokenSource struct{ token *Token } - -func (t *tokenSource) Token() (*Token, error) { - return t.token, nil -} - -func TestTransportNilTokenSource(t *testing.T) { - tr := &Transport{} - server := newMockServer(func(w http.ResponseWriter, r *http.Request) {}) - defer server.Close() - client := &http.Client{Transport: tr} - resp, err := client.Get(server.URL) - if err == nil { - t.Errorf("got no errors, want an error with nil token source") - } - if resp != nil { - t.Errorf("Response = %v; want nil", resp) - } -} - -func TestTransportTokenSource(t *testing.T) { - ts := &tokenSource{ - token: &Token{ - AccessToken: "abc", - }, - } - tr := &Transport{ - Source: ts, - } - server := newMockServer(func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("Authorization"), "Bearer abc"; got != want { - t.Errorf("Authorization header = %q; want %q", got, want) - } - }) - defer server.Close() - client := &http.Client{Transport: tr} - res, err := client.Get(server.URL) - if err != nil { - t.Fatal(err) - } - res.Body.Close() -} - -// Test for case-sensitive token types, per https://github.com/golang/oauth2/issues/113 -func TestTransportTokenSourceTypes(t *testing.T) { - const val = "abc" - tests := []struct { - key string - val string - want string - }{ - {key: "bearer", val: val, want: "Bearer abc"}, - {key: "mac", val: val, want: "MAC abc"}, - {key: "basic", val: val, want: "Basic abc"}, - } - for _, tc := range tests { - ts := &tokenSource{ - token: &Token{ - AccessToken: tc.val, - TokenType: tc.key, - }, - } - tr := &Transport{ - Source: ts, - } - server := newMockServer(func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("Authorization"), tc.want; got != want { - t.Errorf("Authorization header (%q) = %q; want %q", val, got, want) - } - }) - defer server.Close() - client := &http.Client{Transport: tr} - res, err := client.Get(server.URL) - if err != nil { - t.Fatal(err) - } - res.Body.Close() - } -} - -func TestTokenValidNoAccessToken(t *testing.T) { - token := &Token{} - if token.Valid() { - t.Errorf("got valid with no access token; want invalid") - } -} - -func TestExpiredWithExpiry(t *testing.T) { - token := &Token{ - Expiry: time.Now().Add(-5 * time.Hour), - } - if token.Valid() { - t.Errorf("got valid with expired token; want invalid") - } -} - -func newMockServer(handler func(w http.ResponseWriter, r *http.Request)) *httptest.Server { - return httptest.NewServer(http.HandlerFunc(handler)) -} diff --git a/vendor/golang.org/x/sync/AUTHORS b/vendor/golang.org/x/sync/AUTHORS new file mode 100644 index 000000000..15167cd74 --- /dev/null +++ b/vendor/golang.org/x/sync/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/sync/CONTRIBUTORS b/vendor/golang.org/x/sync/CONTRIBUTORS new file mode 100644 index 000000000..1c4577e96 --- /dev/null +++ b/vendor/golang.org/x/sync/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/sync/errgroup/errgroup.go b/vendor/golang.org/x/sync/errgroup/errgroup.go index 533438d91..9857fe53d 100644 --- a/vendor/golang.org/x/sync/errgroup/errgroup.go +++ b/vendor/golang.org/x/sync/errgroup/errgroup.go @@ -7,9 +7,8 @@ package errgroup import ( + "context" "sync" - - "golang.org/x/net/context" ) // A Group is a collection of goroutines working on subtasks that are part of diff --git a/vendor/golang.org/x/sync/errgroup/errgroup_example_md5all_test.go b/vendor/golang.org/x/sync/errgroup/errgroup_example_md5all_test.go deleted file mode 100644 index 714b5aea7..000000000 --- a/vendor/golang.org/x/sync/errgroup/errgroup_example_md5all_test.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package errgroup_test - -import ( - "crypto/md5" - "fmt" - "io/ioutil" - "log" - "os" - "path/filepath" - - "golang.org/x/net/context" - "golang.org/x/sync/errgroup" -) - -// Pipeline demonstrates the use of a Group to implement a multi-stage -// pipeline: a version of the MD5All function with bounded parallelism from -// https://blog.golang.org/pipelines. -func ExampleGroup_pipeline() { - m, err := MD5All(context.Background(), ".") - if err != nil { - log.Fatal(err) - } - - for k, sum := range m { - fmt.Printf("%s:\t%x\n", k, sum) - } -} - -type result struct { - path string - sum [md5.Size]byte -} - -// MD5All reads all the files in the file tree rooted at root and returns a map -// from file path to the MD5 sum of the file's contents. If the directory walk -// fails or any read operation fails, MD5All returns an error. -func MD5All(ctx context.Context, root string) (map[string][md5.Size]byte, error) { - // ctx is canceled when g.Wait() returns. When this version of MD5All returns - // - even in case of error! - we know that all of the goroutines have finished - // and the memory they were using can be garbage-collected. - g, ctx := errgroup.WithContext(ctx) - paths := make(chan string) - - g.Go(func() error { - defer close(paths) - return filepath.Walk(root, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if !info.Mode().IsRegular() { - return nil - } - select { - case paths <- path: - case <-ctx.Done(): - return ctx.Err() - } - return nil - }) - }) - - // Start a fixed number of goroutines to read and digest files. - c := make(chan result) - const numDigesters = 20 - for i := 0; i < numDigesters; i++ { - g.Go(func() error { - for path := range paths { - data, err := ioutil.ReadFile(path) - if err != nil { - return err - } - select { - case c <- result{path, md5.Sum(data)}: - case <-ctx.Done(): - return ctx.Err() - } - } - return nil - }) - } - go func() { - g.Wait() - close(c) - }() - - m := make(map[string][md5.Size]byte) - for r := range c { - m[r.path] = r.sum - } - // Check whether any of the goroutines failed. Since g is accumulating the - // errors, we don't need to send them (or check for them) in the individual - // results sent on the channel. - if err := g.Wait(); err != nil { - return nil, err - } - return m, nil -} diff --git a/vendor/golang.org/x/sync/errgroup/errgroup_test.go b/vendor/golang.org/x/sync/errgroup/errgroup_test.go deleted file mode 100644 index 6a9696efc..000000000 --- a/vendor/golang.org/x/sync/errgroup/errgroup_test.go +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package errgroup_test - -import ( - "errors" - "fmt" - "net/http" - "os" - "testing" - - "golang.org/x/net/context" - "golang.org/x/sync/errgroup" -) - -var ( - Web = fakeSearch("web") - Image = fakeSearch("image") - Video = fakeSearch("video") -) - -type Result string -type Search func(ctx context.Context, query string) (Result, error) - -func fakeSearch(kind string) Search { - return func(_ context.Context, query string) (Result, error) { - return Result(fmt.Sprintf("%s result for %q", kind, query)), nil - } -} - -// JustErrors illustrates the use of a Group in place of a sync.WaitGroup to -// simplify goroutine counting and error handling. This example is derived from -// the sync.WaitGroup example at https://golang.org/pkg/sync/#example_WaitGroup. -func ExampleGroup_justErrors() { - var g errgroup.Group - var urls = []string{ - "http://www.golang.org/", - "http://www.google.com/", - "http://www.somestupidname.com/", - } - for _, url := range urls { - // Launch a goroutine to fetch the URL. - url := url // https://golang.org/doc/faq#closures_and_goroutines - g.Go(func() error { - // Fetch the URL. - resp, err := http.Get(url) - if err == nil { - resp.Body.Close() - } - return err - }) - } - // Wait for all HTTP fetches to complete. - if err := g.Wait(); err == nil { - fmt.Println("Successfully fetched all URLs.") - } -} - -// Parallel illustrates the use of a Group for synchronizing a simple parallel -// task: the "Google Search 2.0" function from -// https://talks.golang.org/2012/concurrency.slide#46, augmented with a Context -// and error-handling. -func ExampleGroup_parallel() { - Google := func(ctx context.Context, query string) ([]Result, error) { - g, ctx := errgroup.WithContext(ctx) - - searches := []Search{Web, Image, Video} - results := make([]Result, len(searches)) - for i, search := range searches { - i, search := i, search // https://golang.org/doc/faq#closures_and_goroutines - g.Go(func() error { - result, err := search(ctx, query) - if err == nil { - results[i] = result - } - return err - }) - } - if err := g.Wait(); err != nil { - return nil, err - } - return results, nil - } - - results, err := Google(context.Background(), "golang") - if err != nil { - fmt.Fprintln(os.Stderr, err) - return - } - for _, result := range results { - fmt.Println(result) - } - - // Output: - // web result for "golang" - // image result for "golang" - // video result for "golang" -} - -func TestZeroGroup(t *testing.T) { - err1 := errors.New("errgroup_test: 1") - err2 := errors.New("errgroup_test: 2") - - cases := []struct { - errs []error - }{ - {errs: []error{}}, - {errs: []error{nil}}, - {errs: []error{err1}}, - {errs: []error{err1, nil}}, - {errs: []error{err1, nil, err2}}, - } - - for _, tc := range cases { - var g errgroup.Group - - var firstErr error - for i, err := range tc.errs { - err := err - g.Go(func() error { return err }) - - if firstErr == nil && err != nil { - firstErr = err - } - - if gErr := g.Wait(); gErr != firstErr { - t.Errorf("after %T.Go(func() error { return err }) for err in %v\n"+ - "g.Wait() = %v; want %v", - g, tc.errs[:i+1], err, firstErr) - } - } - } -} - -func TestWithContext(t *testing.T) { - errDoom := errors.New("group_test: doomed") - - cases := []struct { - errs []error - want error - }{ - {want: nil}, - {errs: []error{nil}, want: nil}, - {errs: []error{errDoom}, want: errDoom}, - {errs: []error{errDoom, nil}, want: errDoom}, - } - - for _, tc := range cases { - g, ctx := errgroup.WithContext(context.Background()) - - for _, err := range tc.errs { - err := err - g.Go(func() error { return err }) - } - - if err := g.Wait(); err != tc.want { - t.Errorf("after %T.Go(func() error { return err }) for err in %v\n"+ - "g.Wait() = %v; want %v", - g, tc.errs, err, tc.want) - } - - canceled := false - select { - case <-ctx.Done(): - canceled = true - default: - } - if !canceled { - t.Errorf("after %T.Go(func() error { return err }) for err in %v\n"+ - "ctx.Done() was not closed", - g, tc.errs) - } - } -} diff --git a/vendor/golang.org/x/sys/AUTHORS b/vendor/golang.org/x/sys/AUTHORS new file mode 100644 index 000000000..15167cd74 --- /dev/null +++ b/vendor/golang.org/x/sys/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/sys/CONTRIBUTORS b/vendor/golang.org/x/sys/CONTRIBUTORS new file mode 100644 index 000000000..1c4577e96 --- /dev/null +++ b/vendor/golang.org/x/sys/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/sys/unix/creds_test.go b/vendor/golang.org/x/sys/unix/creds_test.go deleted file mode 100644 index 1b5083196..000000000 --- a/vendor/golang.org/x/sys/unix/creds_test.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build linux - -package unix_test - -import ( - "bytes" - "go/build" - "net" - "os" - "testing" - - "golang.org/x/sys/unix" -) - -// TestSCMCredentials tests the sending and receiving of credentials -// (PID, UID, GID) in an ancillary message between two UNIX -// sockets. The SO_PASSCRED socket option is enabled on the sending -// socket for this to work. -func TestSCMCredentials(t *testing.T) { - socketTypeTests := []struct { - socketType int - dataLen int - }{ - { - unix.SOCK_STREAM, - 1, - }, { - unix.SOCK_DGRAM, - 0, - }, - } - - for _, tt := range socketTypeTests { - if tt.socketType == unix.SOCK_DGRAM && !atLeast1p10() { - t.Log("skipping DGRAM test on pre-1.10") - continue - } - - fds, err := unix.Socketpair(unix.AF_LOCAL, tt.socketType, 0) - if err != nil { - t.Fatalf("Socketpair: %v", err) - } - defer unix.Close(fds[0]) - defer unix.Close(fds[1]) - - err = unix.SetsockoptInt(fds[0], unix.SOL_SOCKET, unix.SO_PASSCRED, 1) - if err != nil { - t.Fatalf("SetsockoptInt: %v", err) - } - - srvFile := os.NewFile(uintptr(fds[0]), "server") - defer srvFile.Close() - srv, err := net.FileConn(srvFile) - if err != nil { - t.Errorf("FileConn: %v", err) - return - } - defer srv.Close() - - cliFile := os.NewFile(uintptr(fds[1]), "client") - defer cliFile.Close() - cli, err := net.FileConn(cliFile) - if err != nil { - t.Errorf("FileConn: %v", err) - return - } - defer cli.Close() - - var ucred unix.Ucred - ucred.Pid = int32(os.Getpid()) - ucred.Uid = uint32(os.Getuid()) - ucred.Gid = uint32(os.Getgid()) - oob := unix.UnixCredentials(&ucred) - - // On SOCK_STREAM, this is internally going to send a dummy byte - n, oobn, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil) - if err != nil { - t.Fatalf("WriteMsgUnix: %v", err) - } - if n != 0 { - t.Fatalf("WriteMsgUnix n = %d, want 0", n) - } - if oobn != len(oob) { - t.Fatalf("WriteMsgUnix oobn = %d, want %d", oobn, len(oob)) - } - - oob2 := make([]byte, 10*len(oob)) - n, oobn2, flags, _, err := srv.(*net.UnixConn).ReadMsgUnix(nil, oob2) - if err != nil { - t.Fatalf("ReadMsgUnix: %v", err) - } - if flags != 0 { - t.Fatalf("ReadMsgUnix flags = 0x%x, want 0", flags) - } - if n != tt.dataLen { - t.Fatalf("ReadMsgUnix n = %d, want %d", n, tt.dataLen) - } - if oobn2 != oobn { - // without SO_PASSCRED set on the socket, ReadMsgUnix will - // return zero oob bytes - t.Fatalf("ReadMsgUnix oobn = %d, want %d", oobn2, oobn) - } - oob2 = oob2[:oobn2] - if !bytes.Equal(oob, oob2) { - t.Fatal("ReadMsgUnix oob bytes don't match") - } - - scm, err := unix.ParseSocketControlMessage(oob2) - if err != nil { - t.Fatalf("ParseSocketControlMessage: %v", err) - } - newUcred, err := unix.ParseUnixCredentials(&scm[0]) - if err != nil { - t.Fatalf("ParseUnixCredentials: %v", err) - } - if *newUcred != ucred { - t.Fatalf("ParseUnixCredentials = %+v, want %+v", newUcred, ucred) - } - } -} - -// atLeast1p10 reports whether we are running on Go 1.10 or later. -func atLeast1p10() bool { - for _, ver := range build.Default.ReleaseTags { - if ver == "go1.10" { - return true - } - } - return false -} diff --git a/vendor/golang.org/x/sys/unix/darwin_test.go b/vendor/golang.org/x/sys/unix/darwin_test.go deleted file mode 100644 index 29af36f10..000000000 --- a/vendor/golang.org/x/sys/unix/darwin_test.go +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin,go1.12,amd64 darwin,go1.12,386 - -package unix - -import ( - "os" - "os/exec" - "strings" - "testing" -) - -type darwinTest struct { - name string - f func() -} - -// TODO(khr): decide whether to keep this test enabled permanently or -// only temporarily. -func TestDarwinLoader(t *testing.T) { - // Make sure the Darwin dynamic loader can actually resolve - // all the system calls into libSystem.dylib. Unfortunately - // there is no easy way to test this at compile time. So we - // implement a crazy hack here, calling into the syscall - // function with all its arguments set to junk, and see what - // error we get. We are happy with any error (or none) except - // an error from the dynamic loader. - // - // We have to run each test in a separate subprocess for fault isolation. - // - // Hopefully the junk args won't accidentally ask the system to do "rm -fr /". - // - // In an ideal world each syscall would have its own test, so this test - // would be unnecessary. Unfortunately, we do not live in that world. - for _, test := range darwinTests { - // Call the test binary recursively, giving it a magic argument - // (see init below) and the name of the test to run. - cmd := exec.Command(os.Args[0], "testDarwinLoader", test.name) - - // Run subprocess, collect results. Note that we expect the subprocess - // to fail somehow, so the error is irrelevant. - out, _ := cmd.CombinedOutput() - - if strings.Contains(string(out), "dyld: Symbol not found:") { - t.Errorf("can't resolve %s in libSystem.dylib", test.name) - } - if !strings.Contains(string(out), "success") { - // Not really an error. Might be a syscall that never returns, - // like exit, or one that segfaults, like gettimeofday. - t.Logf("test never finished: %s: %s", test.name, string(out)) - } - } -} - -func init() { - // The test binary execs itself with the "testDarwinLoader" argument. - // Run the test specified by os.Args[2], then panic. - if len(os.Args) >= 3 && os.Args[1] == "testDarwinLoader" { - for _, test := range darwinTests { - if test.name == os.Args[2] { - test.f() - } - } - // Panic with a "success" label, so the parent process can check it. - panic("success") - } -} - -// All the _trampoline functions in zsyscall_darwin_$ARCH.s -var darwinTests = [...]darwinTest{ - {"getgroups", libc_getgroups_trampoline}, - {"setgroups", libc_setgroups_trampoline}, - {"wait4", libc_wait4_trampoline}, - {"accept", libc_accept_trampoline}, - {"bind", libc_bind_trampoline}, - {"connect", libc_connect_trampoline}, - {"socket", libc_socket_trampoline}, - {"getsockopt", libc_getsockopt_trampoline}, - {"setsockopt", libc_setsockopt_trampoline}, - {"getpeername", libc_getpeername_trampoline}, - {"getsockname", libc_getsockname_trampoline}, - {"shutdown", libc_shutdown_trampoline}, - {"socketpair", libc_socketpair_trampoline}, - {"recvfrom", libc_recvfrom_trampoline}, - {"sendto", libc_sendto_trampoline}, - {"recvmsg", libc_recvmsg_trampoline}, - {"sendmsg", libc_sendmsg_trampoline}, - {"kevent", libc_kevent_trampoline}, - {"__sysctl", libc___sysctl_trampoline}, - {"utimes", libc_utimes_trampoline}, - {"futimes", libc_futimes_trampoline}, - {"fcntl", libc_fcntl_trampoline}, - {"poll", libc_poll_trampoline}, - {"madvise", libc_madvise_trampoline}, - {"mlock", libc_mlock_trampoline}, - {"mlockall", libc_mlockall_trampoline}, - {"mprotect", libc_mprotect_trampoline}, - {"msync", libc_msync_trampoline}, - {"munlock", libc_munlock_trampoline}, - {"munlockall", libc_munlockall_trampoline}, - {"ptrace", libc_ptrace_trampoline}, - {"pipe", libc_pipe_trampoline}, - {"getxattr", libc_getxattr_trampoline}, - {"fgetxattr", libc_fgetxattr_trampoline}, - {"setxattr", libc_setxattr_trampoline}, - {"fsetxattr", libc_fsetxattr_trampoline}, - {"removexattr", libc_removexattr_trampoline}, - {"fremovexattr", libc_fremovexattr_trampoline}, - {"listxattr", libc_listxattr_trampoline}, - {"flistxattr", libc_flistxattr_trampoline}, - {"kill", libc_kill_trampoline}, - {"ioctl", libc_ioctl_trampoline}, - {"access", libc_access_trampoline}, - {"adjtime", libc_adjtime_trampoline}, - {"chdir", libc_chdir_trampoline}, - {"chflags", libc_chflags_trampoline}, - {"chmod", libc_chmod_trampoline}, - {"chown", libc_chown_trampoline}, - {"chroot", libc_chroot_trampoline}, - {"close", libc_close_trampoline}, - {"dup", libc_dup_trampoline}, - {"dup2", libc_dup2_trampoline}, - {"exchangedata", libc_exchangedata_trampoline}, - {"exit", libc_exit_trampoline}, - {"faccessat", libc_faccessat_trampoline}, - {"fchdir", libc_fchdir_trampoline}, - {"fchflags", libc_fchflags_trampoline}, - {"fchmod", libc_fchmod_trampoline}, - {"fchmodat", libc_fchmodat_trampoline}, - {"fchown", libc_fchown_trampoline}, - {"fchownat", libc_fchownat_trampoline}, - {"flock", libc_flock_trampoline}, - {"fpathconf", libc_fpathconf_trampoline}, - {"fstat64", libc_fstat64_trampoline}, - {"fstatat64", libc_fstatat64_trampoline}, - {"fstatfs64", libc_fstatfs64_trampoline}, - {"fsync", libc_fsync_trampoline}, - {"ftruncate", libc_ftruncate_trampoline}, - {"__getdirentries64", libc___getdirentries64_trampoline}, - {"getdtablesize", libc_getdtablesize_trampoline}, - {"getegid", libc_getegid_trampoline}, - {"geteuid", libc_geteuid_trampoline}, - {"getgid", libc_getgid_trampoline}, - {"getpgid", libc_getpgid_trampoline}, - {"getpgrp", libc_getpgrp_trampoline}, - {"getpid", libc_getpid_trampoline}, - {"getppid", libc_getppid_trampoline}, - {"getpriority", libc_getpriority_trampoline}, - {"getrlimit", libc_getrlimit_trampoline}, - {"getrusage", libc_getrusage_trampoline}, - {"getsid", libc_getsid_trampoline}, - {"getuid", libc_getuid_trampoline}, - {"issetugid", libc_issetugid_trampoline}, - {"kqueue", libc_kqueue_trampoline}, - {"lchown", libc_lchown_trampoline}, - {"link", libc_link_trampoline}, - {"linkat", libc_linkat_trampoline}, - {"listen", libc_listen_trampoline}, - {"lstat64", libc_lstat64_trampoline}, - {"mkdir", libc_mkdir_trampoline}, - {"mkdirat", libc_mkdirat_trampoline}, - {"mkfifo", libc_mkfifo_trampoline}, - {"mknod", libc_mknod_trampoline}, - {"open", libc_open_trampoline}, - {"openat", libc_openat_trampoline}, - {"pathconf", libc_pathconf_trampoline}, - {"pread", libc_pread_trampoline}, - {"pwrite", libc_pwrite_trampoline}, - {"read", libc_read_trampoline}, - {"readlink", libc_readlink_trampoline}, - {"readlinkat", libc_readlinkat_trampoline}, - {"rename", libc_rename_trampoline}, - {"renameat", libc_renameat_trampoline}, - {"revoke", libc_revoke_trampoline}, - {"rmdir", libc_rmdir_trampoline}, - {"lseek", libc_lseek_trampoline}, - {"select", libc_select_trampoline}, - {"setegid", libc_setegid_trampoline}, - {"seteuid", libc_seteuid_trampoline}, - {"setgid", libc_setgid_trampoline}, - {"setlogin", libc_setlogin_trampoline}, - {"setpgid", libc_setpgid_trampoline}, - {"setpriority", libc_setpriority_trampoline}, - {"setprivexec", libc_setprivexec_trampoline}, - {"setregid", libc_setregid_trampoline}, - {"setreuid", libc_setreuid_trampoline}, - {"setrlimit", libc_setrlimit_trampoline}, - {"setsid", libc_setsid_trampoline}, - {"settimeofday", libc_settimeofday_trampoline}, - {"setuid", libc_setuid_trampoline}, - {"stat64", libc_stat64_trampoline}, - {"statfs64", libc_statfs64_trampoline}, - {"symlink", libc_symlink_trampoline}, - {"symlinkat", libc_symlinkat_trampoline}, - {"sync", libc_sync_trampoline}, - {"truncate", libc_truncate_trampoline}, - {"umask", libc_umask_trampoline}, - {"undelete", libc_undelete_trampoline}, - {"unlink", libc_unlink_trampoline}, - {"unlinkat", libc_unlinkat_trampoline}, - {"unmount", libc_unmount_trampoline}, - {"write", libc_write_trampoline}, - {"mmap", libc_mmap_trampoline}, - {"munmap", libc_munmap_trampoline}, - {"gettimeofday", libc_gettimeofday_trampoline}, - {"getfsstat64", libc_getfsstat64_trampoline}, -} diff --git a/vendor/golang.org/x/sys/unix/dev_linux_test.go b/vendor/golang.org/x/sys/unix/dev_linux_test.go deleted file mode 100644 index 51645289c..000000000 --- a/vendor/golang.org/x/sys/unix/dev_linux_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.7 - -package unix_test - -import ( - "fmt" - "testing" - - "golang.org/x/sys/unix" -) - -func TestDevices(t *testing.T) { - testCases := []struct { - path string - major uint32 - minor uint32 - }{ - // well known major/minor numbers according to - // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/admin-guide/devices.txt - {"/dev/null", 1, 3}, - {"/dev/zero", 1, 5}, - {"/dev/random", 1, 8}, - {"/dev/full", 1, 7}, - {"/dev/urandom", 1, 9}, - {"/dev/tty", 5, 0}, - } - for _, tc := range testCases { - t.Run(fmt.Sprintf("%s %v:%v", tc.path, tc.major, tc.minor), func(t *testing.T) { - var stat unix.Stat_t - err := unix.Stat(tc.path, &stat) - if err != nil { - if err == unix.EACCES { - t.Skip("no permission to stat device, skipping test") - } - t.Errorf("failed to stat device: %v", err) - return - } - - dev := uint64(stat.Rdev) - if unix.Major(dev) != tc.major { - t.Errorf("for %s Major(%#x) == %d, want %d", tc.path, dev, unix.Major(dev), tc.major) - } - if unix.Minor(dev) != tc.minor { - t.Errorf("for %s Minor(%#x) == %d, want %d", tc.path, dev, unix.Minor(dev), tc.minor) - } - if unix.Mkdev(tc.major, tc.minor) != dev { - t.Errorf("for %s Mkdev(%d, %d) == %#x, want %#x", tc.path, tc.major, tc.minor, unix.Mkdev(tc.major, tc.minor), dev) - } - }) - - } -} diff --git a/vendor/golang.org/x/sys/unix/example_exec_test.go b/vendor/golang.org/x/sys/unix/example_exec_test.go deleted file mode 100644 index bb4d3bf5d..000000000 --- a/vendor/golang.org/x/sys/unix/example_exec_test.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris - -package unix_test - -import ( - "log" - "os" - - "golang.org/x/sys/unix" -) - -func ExampleExec() { - err := unix.Exec("/bin/ls", []string{"ls", "-al"}, os.Environ()) - log.Fatal(err) -} diff --git a/vendor/golang.org/x/sys/unix/example_flock_test.go b/vendor/golang.org/x/sys/unix/example_flock_test.go deleted file mode 100644 index 6c9174859..000000000 --- a/vendor/golang.org/x/sys/unix/example_flock_test.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin dragonfly freebsd linux netbsd openbsd solaris - -package unix_test - -import ( - "log" - "os" - - "golang.org/x/sys/unix" -) - -func ExampleFlock() { - f, _ := os.Create("example.lock") - if err := unix.Flock(int(f.Fd()), unix.LOCK_EX); err != nil { - log.Fatal(err) - } - // Do work here that requires the lock. When finished, release the lock: - if err := unix.Flock(int(f.Fd()), unix.LOCK_UN); err != nil { - log.Fatal(err) - } -} diff --git a/vendor/golang.org/x/sys/unix/export_test.go b/vendor/golang.org/x/sys/unix/export_test.go deleted file mode 100644 index f8ae0e0e3..000000000 --- a/vendor/golang.org/x/sys/unix/export_test.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris - -package unix - -var Itoa = itoa diff --git a/vendor/golang.org/x/sys/unix/mkall.sh b/vendor/golang.org/x/sys/unix/mkall.sh old mode 100755 new mode 100644 diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh old mode 100755 new mode 100644 diff --git a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go old mode 100755 new mode 100644 diff --git a/vendor/golang.org/x/sys/unix/mksyscall_solaris.pl b/vendor/golang.org/x/sys/unix/mksyscall_solaris.pl old mode 100755 new mode 100644 diff --git a/vendor/golang.org/x/sys/unix/mksysctl_openbsd.pl b/vendor/golang.org/x/sys/unix/mksysctl_openbsd.pl old mode 100755 new mode 100644 diff --git a/vendor/golang.org/x/sys/unix/mmap_unix_test.go b/vendor/golang.org/x/sys/unix/mmap_unix_test.go deleted file mode 100644 index d4c4ef926..000000000 --- a/vendor/golang.org/x/sys/unix/mmap_unix_test.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris - -package unix_test - -import ( - "runtime" - "testing" - - "golang.org/x/sys/unix" -) - -func TestMmap(t *testing.T) { - b, err := unix.Mmap(-1, 0, unix.Getpagesize(), unix.PROT_NONE, unix.MAP_ANON|unix.MAP_PRIVATE) - if err != nil { - t.Fatalf("Mmap: %v", err) - } - if err := unix.Mprotect(b, unix.PROT_READ|unix.PROT_WRITE); err != nil { - t.Fatalf("Mprotect: %v", err) - } - - b[0] = 42 - - if runtime.GOOS == "aix" { - t.Skip("msync returns invalid argument for AIX, skipping msync test") - } else { - if err := unix.Msync(b, unix.MS_SYNC); err != nil { - t.Fatalf("Msync: %v", err) - } - } - - if err := unix.Madvise(b, unix.MADV_DONTNEED); err != nil { - t.Fatalf("Madvise: %v", err) - } - if err := unix.Munmap(b); err != nil { - t.Fatalf("Munmap: %v", err) - } -} diff --git a/vendor/golang.org/x/sys/unix/openbsd_test.go b/vendor/golang.org/x/sys/unix/openbsd_test.go deleted file mode 100644 index 3ded96071..000000000 --- a/vendor/golang.org/x/sys/unix/openbsd_test.go +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build openbsd - -// This, on the face of it, bizarre testing mechanism is necessary because -// the only reliable way to gauge whether or not a pledge(2) call has succeeded -// is that the program has been killed as a result of breaking its pledge. - -package unix_test - -import ( - "flag" - "fmt" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "testing" - - "golang.org/x/sys/unix" -) - -type testProc struct { - fn func() // should always exit instead of returning - cleanup func() error // for instance, delete coredumps from testing pledge - success bool // whether zero-exit means success or failure -} - -var ( - testProcs = map[string]testProc{} - procName = "" -) - -const ( - optName = "sys-unix-internal-procname" -) - -func init() { - flag.StringVar(&procName, optName, "", "internal use only") -} - -// testCmd generates a proper command that, when executed, runs the test -// corresponding to the given key. -func testCmd(procName string) (*exec.Cmd, error) { - exe, err := filepath.Abs(os.Args[0]) - if err != nil { - return nil, err - } - cmd := exec.Command(exe, "-"+optName+"="+procName) - cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr - return cmd, nil -} - -// ExitsCorrectly is a comprehensive, one-line-of-use wrapper for testing -// a testProc with a key. -func ExitsCorrectly(procName string, t *testing.T) { - s := testProcs[procName] - c, err := testCmd(procName) - defer func() { - if s.cleanup() != nil { - t.Fatalf("Failed to run cleanup for %s", procName) - } - }() - if err != nil { - t.Fatalf("Failed to construct command for %s", procName) - } - if (c.Run() == nil) != s.success { - result := "succeed" - if !s.success { - result = "fail" - } - t.Fatalf("Process did not %s when it was supposed to", result) - } -} - -func TestMain(m *testing.M) { - flag.Parse() - if procName != "" { - testProcs[procName].fn() - } - os.Exit(m.Run()) -} - -// For example, add a test for pledge. -func init() { - testProcs["pledge"] = testProc{ - func() { - fmt.Println(unix.Pledge("", "")) - os.Exit(0) - }, - func() error { - files, err := ioutil.ReadDir(".") - if err != nil { - return err - } - for _, file := range files { - if filepath.Ext(file.Name()) == ".core" { - if err := os.Remove(file.Name()); err != nil { - return err - } - } - } - return nil - }, - false, - } -} - -func TestPledge(t *testing.T) { - ExitsCorrectly("pledge", t) -} diff --git a/vendor/golang.org/x/sys/unix/sendfile_test.go b/vendor/golang.org/x/sys/unix/sendfile_test.go deleted file mode 100644 index d41fb93c8..000000000 --- a/vendor/golang.org/x/sys/unix/sendfile_test.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin,amd64 darwin,386 dragonfly freebsd linux solaris - -package unix_test - -import ( - "io/ioutil" - "net" - "os" - "path/filepath" - "testing" - - "golang.org/x/sys/unix" -) - -func TestSendfile(t *testing.T) { - // Set up source data file. - tempDir, err := ioutil.TempDir("", "TestSendfile") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tempDir) - name := filepath.Join(tempDir, "source") - const contents = "contents" - err = ioutil.WriteFile(name, []byte(contents), 0666) - if err != nil { - t.Fatal(err) - } - - done := make(chan bool) - - // Start server listening on a socket. - ln, err := net.Listen("tcp", "127.0.0.1:0") - if err != nil { - t.Skipf("listen failed: %s\n", err) - } - defer ln.Close() - go func() { - conn, err := ln.Accept() - if err != nil { - t.Fatal(err) - } - defer conn.Close() - b, err := ioutil.ReadAll(conn) - if string(b) != contents { - t.Errorf("contents not transmitted: got %s (len=%d), want %s", string(b), len(b), contents) - } - done <- true - }() - - // Open source file. - src, err := os.Open(name) - if err != nil { - t.Fatal(err) - } - - // Send source file to server. - conn, err := net.Dial("tcp", ln.Addr().String()) - if err != nil { - t.Fatal(err) - } - file, err := conn.(*net.TCPConn).File() - if err != nil { - t.Fatal(err) - } - var off int64 - n, err := unix.Sendfile(int(file.Fd()), int(src.Fd()), &off, len(contents)) - if err != nil { - t.Errorf("Sendfile failed %s\n", err) - } - if n != len(contents) { - t.Errorf("written count wrong: want %d, got %d", len(contents), n) - } - // Note: off is updated on some systems and not others. Oh well. - // Linux: increments off by the amount sent. - // Darwin: leaves off unchanged. - // It would be nice to fix Darwin if we can. - if off != 0 && off != int64(len(contents)) { - t.Errorf("offset wrong: god %d, want %d or %d", off, 0, len(contents)) - } - // The cursor position should be unchanged. - pos, err := src.Seek(0, 1) - if err != nil { - t.Errorf("can't get cursor position %s\n", err) - } - if pos != 0 { - t.Errorf("cursor position wrong: got %d, want 0", pos) - } - - file.Close() // Note: required to have the close below really send EOF to the server. - conn.Close() - - // Wait for server to close. - <-done -} diff --git a/vendor/golang.org/x/sys/unix/syscall_aix_test.go b/vendor/golang.org/x/sys/unix/syscall_aix_test.go deleted file mode 100644 index 6f55c07bd..000000000 --- a/vendor/golang.org/x/sys/unix/syscall_aix_test.go +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build aix - -package unix_test - -import ( - "os" - "runtime" - "testing" - "time" - - "golang.org/x/sys/unix" -) - -func TestIoctlGetInt(t *testing.T) { - f, err := os.Open("/dev/random") - if err != nil { - t.Fatalf("failed to open device: %v", err) - } - defer f.Close() - - v, err := unix.IoctlGetInt(int(f.Fd()), unix.RNDGETENTCNT) - if err != nil { - t.Fatalf("failed to perform ioctl: %v", err) - } - - t.Logf("%d bits of entropy available", v) -} - -func TestTime(t *testing.T) { - var ut unix.Time_t - ut2, err := unix.Time(&ut) - if err != nil { - t.Fatalf("Time: %v", err) - } - if ut != ut2 { - t.Errorf("Time: return value %v should be equal to argument %v", ut2, ut) - } - - var now time.Time - - for i := 0; i < 10; i++ { - ut, err = unix.Time(nil) - if err != nil { - t.Fatalf("Time: %v", err) - } - - now = time.Now() - - if int64(ut) == now.Unix() { - return - } - } - - t.Errorf("Time: return value %v should be nearly equal to time.Now().Unix() %v", ut, now.Unix()) -} - -func TestUtime(t *testing.T) { - defer chtmpdir(t)() - - touch(t, "file1") - - buf := &unix.Utimbuf{ - Modtime: 12345, - } - - err := unix.Utime("file1", buf) - if err != nil { - t.Fatalf("Utime: %v", err) - } - - fi, err := os.Stat("file1") - if err != nil { - t.Fatal(err) - } - - if fi.ModTime().Unix() != 12345 { - t.Errorf("Utime: failed to change modtime: expected %v, got %v", 12345, fi.ModTime().Unix()) - } -} - -func TestUtimesNanoAt(t *testing.T) { - defer chtmpdir(t)() - - symlink := "symlink1" - defer os.Remove(symlink) - err := os.Symlink("nonexisting", symlink) - if err != nil { - t.Fatal(err) - } - - ts := []unix.Timespec{ - {Sec: 1111, Nsec: 2222}, - {Sec: 3333, Nsec: 4444}, - } - err = unix.UtimesNanoAt(unix.AT_FDCWD, symlink, ts, unix.AT_SYMLINK_NOFOLLOW) - if err != nil { - t.Fatalf("UtimesNanoAt: %v", err) - } - - var st unix.Stat_t - err = unix.Lstat(symlink, &st) - if err != nil { - t.Fatalf("Lstat: %v", err) - } - if runtime.GOARCH == "ppc64" { - if int64(st.Atim.Sec) != int64(ts[0].Sec) || st.Atim.Nsec != int32(ts[0].Nsec) { - t.Errorf("UtimesNanoAt: wrong atime: %v", st.Atim) - } - if int64(st.Mtim.Sec) != int64(ts[1].Sec) || st.Mtim.Nsec != int32(ts[1].Nsec) { - t.Errorf("UtimesNanoAt: wrong mtime: %v", st.Mtim) - } - } else { - if int32(st.Atim.Sec) != int32(ts[0].Sec) || int32(st.Atim.Nsec) != int32(ts[0].Nsec) { - t.Errorf("UtimesNanoAt: wrong atime: %v", st.Atim) - } - if int32(st.Mtim.Sec) != int32(ts[1].Sec) || int32(st.Mtim.Nsec) != int32(ts[1].Nsec) { - t.Errorf("UtimesNanoAt: wrong mtime: %v", st.Mtim) - } - } -} - -func TestPselect(t *testing.T) { - if runtime.GOARCH == "ppc64" { - t.Skip("pselect issue with structure timespec on AIX 7.2 tl0, skipping test") - } - - _, err := unix.Pselect(0, nil, nil, nil, &unix.Timespec{Sec: 0, Nsec: 0}, nil) - if err != nil { - t.Fatalf("Pselect: %v", err) - } - - dur := 2500 * time.Microsecond - ts := unix.NsecToTimespec(int64(dur)) - start := time.Now() - _, err = unix.Pselect(0, nil, nil, nil, &ts, nil) - took := time.Since(start) - if err != nil { - t.Fatalf("Pselect: %v", err) - } - - if took < dur { - t.Errorf("Pselect: timeout should have been at least %v, got %v", dur, took) - } -} - -// stringsFromByteSlice converts a sequence of attributes to a []string. -// On Linux, each entry is a NULL-terminated string. -func stringsFromByteSlice(buf []byte) []string { - var result []string - off := 0 - for i, b := range buf { - if b == 0 { - result = append(result, string(buf[off:i])) - off = i + 1 - } - } - return result -} diff --git a/vendor/golang.org/x/sys/unix/syscall_bsd_test.go b/vendor/golang.org/x/sys/unix/syscall_bsd_test.go deleted file mode 100644 index 12924cb83..000000000 --- a/vendor/golang.org/x/sys/unix/syscall_bsd_test.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin dragonfly freebsd openbsd - -package unix_test - -import ( - "os/exec" - "runtime" - "testing" - "time" - - "golang.org/x/sys/unix" -) - -func TestGetfsstat(t *testing.T) { - n, err := unix.Getfsstat(nil, unix.MNT_NOWAIT) - if err != nil { - t.Fatal(err) - } - - data := make([]unix.Statfs_t, n) - n2, err := unix.Getfsstat(data, unix.MNT_NOWAIT) - if err != nil { - t.Fatal(err) - } - if n != n2 { - t.Errorf("Getfsstat(nil) = %d, but subsequent Getfsstat(slice) = %d", n, n2) - } - for i, stat := range data { - if stat == (unix.Statfs_t{}) { - t.Errorf("index %v is an empty Statfs_t struct", i) - } - } - if t.Failed() { - for i, stat := range data[:n2] { - t.Logf("data[%v] = %+v", i, stat) - } - mount, err := exec.Command("mount").CombinedOutput() - if err != nil { - t.Logf("mount: %v\n%s", err, mount) - } else { - t.Logf("mount: %s", mount) - } - } -} - -func TestSelect(t *testing.T) { - err := unix.Select(0, nil, nil, nil, &unix.Timeval{Sec: 0, Usec: 0}) - if err != nil { - t.Fatalf("Select: %v", err) - } - - dur := 250 * time.Millisecond - tv := unix.NsecToTimeval(int64(dur)) - start := time.Now() - err = unix.Select(0, nil, nil, nil, &tv) - took := time.Since(start) - if err != nil { - t.Fatalf("Select: %v", err) - } - - // On some BSDs the actual timeout might also be slightly less than the requested. - // Add an acceptable margin to avoid flaky tests. - if took < dur*2/3 { - t.Errorf("Select: timeout should have been at least %v, got %v", dur, took) - } -} - -func TestSysctlRaw(t *testing.T) { - if runtime.GOOS == "openbsd" { - t.Skip("kern.proc.pid does not exist on OpenBSD") - } - - _, err := unix.SysctlRaw("kern.proc.pid", unix.Getpid()) - if err != nil { - t.Fatal(err) - } -} - -func TestSysctlUint32(t *testing.T) { - maxproc, err := unix.SysctlUint32("kern.maxproc") - if err != nil { - t.Fatal(err) - } - t.Logf("kern.maxproc: %v", maxproc) -} diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_test.go b/vendor/golang.org/x/sys/unix/syscall_darwin_test.go deleted file mode 100644 index 7faa295fc..000000000 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_test.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package unix_test - -import ( - "os" - "testing" - - "golang.org/x/sys/unix" -) - -// stringsFromByteSlice converts a sequence of attributes to a []string. -// On Darwin, each entry is a NULL-terminated string. -func stringsFromByteSlice(buf []byte) []string { - var result []string - off := 0 - for i, b := range buf { - if b == 0 { - result = append(result, string(buf[off:i])) - off = i + 1 - } - } - return result -} - -func TestUtimesNanoAt(t *testing.T) { - defer chtmpdir(t)() - - symlink := "symlink1" - os.Remove(symlink) - err := os.Symlink("nonexisting", symlink) - if err != nil { - t.Fatal(err) - } - - ts := []unix.Timespec{ - {Sec: 1111, Nsec: 2222}, - {Sec: 3333, Nsec: 4444}, - } - err = unix.UtimesNanoAt(unix.AT_FDCWD, symlink, ts, unix.AT_SYMLINK_NOFOLLOW) - if err != nil { - t.Fatalf("UtimesNanoAt: %v", err) - } - - var st unix.Stat_t - err = unix.Lstat(symlink, &st) - if err != nil { - t.Fatalf("Lstat: %v", err) - } - - // Only check Mtimespec, Atimespec might not be supported by the underlying filesystem - expected := ts[1] - if st.Mtimespec.Nsec == 0 { - // Some filesystems only support 1-second time stamp resolution - // and will always set Nsec to 0. - expected.Nsec = 0 - } - if st.Mtimespec != expected { - t.Errorf("UtimesNanoAt: wrong mtime: got %v, expected %v", st.Mtimespec, expected) - } -} diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_test.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_test.go deleted file mode 100644 index 0fec1a827..000000000 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_test.go +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build freebsd - -package unix_test - -import ( - "flag" - "fmt" - "io/ioutil" - "os" - "os/exec" - "path" - "path/filepath" - "runtime" - "testing" - - "golang.org/x/sys/unix" -) - -func TestSysctlUint64(t *testing.T) { - _, err := unix.SysctlUint64("vm.swap_total") - if err != nil { - t.Fatal(err) - } -} - -// FIXME: Infrastructure for launching tests in subprocesses stolen from openbsd_test.go - refactor? -// testCmd generates a proper command that, when executed, runs the test -// corresponding to the given key. - -type testProc struct { - fn func() // should always exit instead of returning - arg func(t *testing.T) string // generate argument for test - cleanup func(arg string) error // for instance, delete coredumps from testing pledge - success bool // whether zero-exit means success or failure -} - -var ( - testProcs = map[string]testProc{} - procName = "" - procArg = "" -) - -const ( - optName = "sys-unix-internal-procname" - optArg = "sys-unix-internal-arg" -) - -func init() { - flag.StringVar(&procName, optName, "", "internal use only") - flag.StringVar(&procArg, optArg, "", "internal use only") - -} - -func testCmd(procName string, procArg string) (*exec.Cmd, error) { - exe, err := filepath.Abs(os.Args[0]) - if err != nil { - return nil, err - } - cmd := exec.Command(exe, "-"+optName+"="+procName, "-"+optArg+"="+procArg) - cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr - return cmd, nil -} - -// ExitsCorrectly is a comprehensive, one-line-of-use wrapper for testing -// a testProc with a key. -func ExitsCorrectly(t *testing.T, procName string) { - s := testProcs[procName] - arg := "-" - if s.arg != nil { - arg = s.arg(t) - } - c, err := testCmd(procName, arg) - defer func(arg string) { - if err := s.cleanup(arg); err != nil { - t.Fatalf("Failed to run cleanup for %s %s %#v", procName, err, err) - } - }(arg) - if err != nil { - t.Fatalf("Failed to construct command for %s", procName) - } - if (c.Run() == nil) != s.success { - result := "succeed" - if !s.success { - result = "fail" - } - t.Fatalf("Process did not %s when it was supposed to", result) - } -} - -func TestMain(m *testing.M) { - flag.Parse() - if procName != "" { - t := testProcs[procName] - t.fn() - os.Stderr.WriteString("test function did not exit\n") - if t.success { - os.Exit(1) - } else { - os.Exit(0) - } - } - os.Exit(m.Run()) -} - -// end of infrastructure - -const testfile = "gocapmodetest" -const testfile2 = testfile + "2" - -func CapEnterTest() { - _, err := os.OpenFile(path.Join(procArg, testfile), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) - if err != nil { - panic(fmt.Sprintf("OpenFile: %s", err)) - } - - err = unix.CapEnter() - if err != nil { - panic(fmt.Sprintf("CapEnter: %s", err)) - } - - _, err = os.OpenFile(path.Join(procArg, testfile2), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) - if err == nil { - panic("OpenFile works!") - } - if err.(*os.PathError).Err != unix.ECAPMODE { - panic(fmt.Sprintf("OpenFile failed wrong: %s %#v", err, err)) - } - os.Exit(0) -} - -func makeTempDir(t *testing.T) string { - d, err := ioutil.TempDir("", "go_openat_test") - if err != nil { - t.Fatalf("TempDir failed: %s", err) - } - return d -} - -func removeTempDir(arg string) error { - err := os.RemoveAll(arg) - if err != nil && err.(*os.PathError).Err == unix.ENOENT { - return nil - } - return err -} - -func init() { - testProcs["cap_enter"] = testProc{ - CapEnterTest, - makeTempDir, - removeTempDir, - true, - } -} - -func TestCapEnter(t *testing.T) { - if runtime.GOARCH != "amd64" { - t.Skipf("skipping test on %s", runtime.GOARCH) - } - ExitsCorrectly(t, "cap_enter") -} - -func OpenatTest() { - f, err := os.Open(procArg) - if err != nil { - panic(err) - } - - err = unix.CapEnter() - if err != nil { - panic(fmt.Sprintf("CapEnter: %s", err)) - } - - fxx, err := unix.Openat(int(f.Fd()), "xx", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) - if err != nil { - panic(err) - } - unix.Close(fxx) - - // The right to open BASE/xx is not ambient - _, err = os.OpenFile(procArg+"/xx", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) - if err == nil { - panic("OpenFile succeeded") - } - if err.(*os.PathError).Err != unix.ECAPMODE { - panic(fmt.Sprintf("OpenFile failed wrong: %s %#v", err, err)) - } - - // Can't make a new directory either - err = os.Mkdir(procArg+"2", 0777) - if err == nil { - panic("MKdir succeeded") - } - if err.(*os.PathError).Err != unix.ECAPMODE { - panic(fmt.Sprintf("Mkdir failed wrong: %s %#v", err, err)) - } - - // Remove all caps except read and lookup. - r, err := unix.CapRightsInit([]uint64{unix.CAP_READ, unix.CAP_LOOKUP}) - if err != nil { - panic(fmt.Sprintf("CapRightsInit failed: %s %#v", err, err)) - } - err = unix.CapRightsLimit(f.Fd(), r) - if err != nil { - panic(fmt.Sprintf("CapRightsLimit failed: %s %#v", err, err)) - } - - // Check we can get the rights back again - r, err = unix.CapRightsGet(f.Fd()) - if err != nil { - panic(fmt.Sprintf("CapRightsGet failed: %s %#v", err, err)) - } - b, err := unix.CapRightsIsSet(r, []uint64{unix.CAP_READ, unix.CAP_LOOKUP}) - if err != nil { - panic(fmt.Sprintf("CapRightsIsSet failed: %s %#v", err, err)) - } - if !b { - panic(fmt.Sprintf("Unexpected rights")) - } - b, err = unix.CapRightsIsSet(r, []uint64{unix.CAP_READ, unix.CAP_LOOKUP, unix.CAP_WRITE}) - if err != nil { - panic(fmt.Sprintf("CapRightsIsSet failed: %s %#v", err, err)) - } - if b { - panic(fmt.Sprintf("Unexpected rights (2)")) - } - - // Can no longer create a file - _, err = unix.Openat(int(f.Fd()), "xx2", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) - if err == nil { - panic("Openat succeeded") - } - if err != unix.ENOTCAPABLE { - panic(fmt.Sprintf("OpenFileAt failed wrong: %s %#v", err, err)) - } - - // But can read an existing one - _, err = unix.Openat(int(f.Fd()), "xx", os.O_RDONLY, 0666) - if err != nil { - panic(fmt.Sprintf("Openat failed: %s %#v", err, err)) - } - - os.Exit(0) -} - -func init() { - testProcs["openat"] = testProc{ - OpenatTest, - makeTempDir, - removeTempDir, - true, - } -} - -func TestOpenat(t *testing.T) { - if runtime.GOARCH != "amd64" { - t.Skipf("skipping test on %s", runtime.GOARCH) - } - ExitsCorrectly(t, "openat") -} - -func TestCapRightsSetAndClear(t *testing.T) { - r, err := unix.CapRightsInit([]uint64{unix.CAP_READ, unix.CAP_WRITE, unix.CAP_PDWAIT}) - if err != nil { - t.Fatalf("CapRightsInit failed: %s", err) - } - - err = unix.CapRightsSet(r, []uint64{unix.CAP_EVENT, unix.CAP_LISTEN}) - if err != nil { - t.Fatalf("CapRightsSet failed: %s", err) - } - - b, err := unix.CapRightsIsSet(r, []uint64{unix.CAP_READ, unix.CAP_WRITE, unix.CAP_PDWAIT, unix.CAP_EVENT, unix.CAP_LISTEN}) - if err != nil { - t.Fatalf("CapRightsIsSet failed: %s", err) - } - if !b { - t.Fatalf("Wrong rights set") - } - - err = unix.CapRightsClear(r, []uint64{unix.CAP_READ, unix.CAP_PDWAIT}) - if err != nil { - t.Fatalf("CapRightsClear failed: %s", err) - } - - b, err = unix.CapRightsIsSet(r, []uint64{unix.CAP_WRITE, unix.CAP_EVENT, unix.CAP_LISTEN}) - if err != nil { - t.Fatalf("CapRightsIsSet failed: %s", err) - } - if !b { - t.Fatalf("Wrong rights set") - } -} - -// stringsFromByteSlice converts a sequence of attributes to a []string. -// On FreeBSD, each entry consists of a single byte containing the length -// of the attribute name, followed by the attribute name. -// The name is _not_ NULL-terminated. -func stringsFromByteSlice(buf []byte) []string { - var result []string - i := 0 - for i < len(buf) { - next := i + 1 + int(buf[i]) - result = append(result, string(buf[i+1:next])) - i = next - } - return result -} diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_test.go b/vendor/golang.org/x/sys/unix/syscall_linux_test.go deleted file mode 100644 index c7c6c0584..000000000 --- a/vendor/golang.org/x/sys/unix/syscall_linux_test.go +++ /dev/null @@ -1,517 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build linux - -package unix_test - -import ( - "io/ioutil" - "os" - "runtime" - "runtime/debug" - "testing" - "time" - - "golang.org/x/sys/unix" -) - -func TestIoctlGetInt(t *testing.T) { - f, err := os.Open("/dev/random") - if err != nil { - t.Fatalf("failed to open device: %v", err) - } - defer f.Close() - - v, err := unix.IoctlGetInt(int(f.Fd()), unix.RNDGETENTCNT) - if err != nil { - t.Fatalf("failed to perform ioctl: %v", err) - } - - t.Logf("%d bits of entropy available", v) -} - -func TestPpoll(t *testing.T) { - if runtime.GOOS == "android" { - t.Skip("mkfifo syscall is not available on android, skipping test") - } - - f, cleanup := mktmpfifo(t) - defer cleanup() - - const timeout = 100 * time.Millisecond - - ok := make(chan bool, 1) - go func() { - select { - case <-time.After(10 * timeout): - t.Errorf("Ppoll: failed to timeout after %d", 10*timeout) - case <-ok: - } - }() - - fds := []unix.PollFd{{Fd: int32(f.Fd()), Events: unix.POLLIN}} - timeoutTs := unix.NsecToTimespec(int64(timeout)) - n, err := unix.Ppoll(fds, &timeoutTs, nil) - ok <- true - if err != nil { - t.Errorf("Ppoll: unexpected error: %v", err) - return - } - if n != 0 { - t.Errorf("Ppoll: wrong number of events: got %v, expected %v", n, 0) - return - } -} - -func TestTime(t *testing.T) { - var ut unix.Time_t - ut2, err := unix.Time(&ut) - if err != nil { - t.Fatalf("Time: %v", err) - } - if ut != ut2 { - t.Errorf("Time: return value %v should be equal to argument %v", ut2, ut) - } - - var now time.Time - - for i := 0; i < 10; i++ { - ut, err = unix.Time(nil) - if err != nil { - t.Fatalf("Time: %v", err) - } - - now = time.Now() - - if int64(ut) == now.Unix() { - return - } - } - - t.Errorf("Time: return value %v should be nearly equal to time.Now().Unix() %v", ut, now.Unix()) -} - -func TestUtime(t *testing.T) { - defer chtmpdir(t)() - - touch(t, "file1") - - buf := &unix.Utimbuf{ - Modtime: 12345, - } - - err := unix.Utime("file1", buf) - if err != nil { - t.Fatalf("Utime: %v", err) - } - - fi, err := os.Stat("file1") - if err != nil { - t.Fatal(err) - } - - if fi.ModTime().Unix() != 12345 { - t.Errorf("Utime: failed to change modtime: expected %v, got %v", 12345, fi.ModTime().Unix()) - } -} - -func TestUtimesNanoAt(t *testing.T) { - defer chtmpdir(t)() - - symlink := "symlink1" - os.Remove(symlink) - err := os.Symlink("nonexisting", symlink) - if err != nil { - t.Fatal(err) - } - - ts := []unix.Timespec{ - {Sec: 1111, Nsec: 2222}, - {Sec: 3333, Nsec: 4444}, - } - err = unix.UtimesNanoAt(unix.AT_FDCWD, symlink, ts, unix.AT_SYMLINK_NOFOLLOW) - if err != nil { - t.Fatalf("UtimesNanoAt: %v", err) - } - - var st unix.Stat_t - err = unix.Lstat(symlink, &st) - if err != nil { - t.Fatalf("Lstat: %v", err) - } - - // Only check Mtim, Atim might not be supported by the underlying filesystem - expected := ts[1] - if st.Mtim.Nsec == 0 { - // Some filesystems only support 1-second time stamp resolution - // and will always set Nsec to 0. - expected.Nsec = 0 - } - if st.Mtim != expected { - t.Errorf("UtimesNanoAt: wrong mtime: expected %v, got %v", expected, st.Mtim) - } -} - -func TestRlimitAs(t *testing.T) { - // disable GC during to avoid flaky test - defer debug.SetGCPercent(debug.SetGCPercent(-1)) - - var rlim unix.Rlimit - err := unix.Getrlimit(unix.RLIMIT_AS, &rlim) - if err != nil { - t.Fatalf("Getrlimit: %v", err) - } - var zero unix.Rlimit - if zero == rlim { - t.Fatalf("Getrlimit: got zero value %#v", rlim) - } - set := rlim - set.Cur = uint64(unix.Getpagesize()) - err = unix.Setrlimit(unix.RLIMIT_AS, &set) - if err != nil { - t.Fatalf("Setrlimit: set failed: %#v %v", set, err) - } - - // RLIMIT_AS was set to the page size, so mmap()'ing twice the page size - // should fail. See 'man 2 getrlimit'. - _, err = unix.Mmap(-1, 0, 2*unix.Getpagesize(), unix.PROT_NONE, unix.MAP_ANON|unix.MAP_PRIVATE) - if err == nil { - t.Fatal("Mmap: unexpectedly succeeded after setting RLIMIT_AS") - } - - err = unix.Setrlimit(unix.RLIMIT_AS, &rlim) - if err != nil { - t.Fatalf("Setrlimit: restore failed: %#v %v", rlim, err) - } - - b, err := unix.Mmap(-1, 0, 2*unix.Getpagesize(), unix.PROT_NONE, unix.MAP_ANON|unix.MAP_PRIVATE) - if err != nil { - t.Fatalf("Mmap: %v", err) - } - err = unix.Munmap(b) - if err != nil { - t.Fatalf("Munmap: %v", err) - } -} - -func TestSelect(t *testing.T) { - _, err := unix.Select(0, nil, nil, nil, &unix.Timeval{Sec: 0, Usec: 0}) - if err != nil { - t.Fatalf("Select: %v", err) - } - - dur := 150 * time.Millisecond - tv := unix.NsecToTimeval(int64(dur)) - start := time.Now() - _, err = unix.Select(0, nil, nil, nil, &tv) - took := time.Since(start) - if err != nil { - t.Fatalf("Select: %v", err) - } - - if took < dur { - t.Errorf("Select: timeout should have been at least %v, got %v", dur, took) - } -} - -func TestPselect(t *testing.T) { - _, err := unix.Pselect(0, nil, nil, nil, &unix.Timespec{Sec: 0, Nsec: 0}, nil) - if err != nil { - t.Fatalf("Pselect: %v", err) - } - - dur := 2500 * time.Microsecond - ts := unix.NsecToTimespec(int64(dur)) - start := time.Now() - _, err = unix.Pselect(0, nil, nil, nil, &ts, nil) - took := time.Since(start) - if err != nil { - t.Fatalf("Pselect: %v", err) - } - - if took < dur { - t.Errorf("Pselect: timeout should have been at least %v, got %v", dur, took) - } -} - -func TestSchedSetaffinity(t *testing.T) { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - var oldMask unix.CPUSet - err := unix.SchedGetaffinity(0, &oldMask) - if err != nil { - t.Fatalf("SchedGetaffinity: %v", err) - } - - var newMask unix.CPUSet - newMask.Zero() - if newMask.Count() != 0 { - t.Errorf("CpuZero: didn't zero CPU set: %v", newMask) - } - cpu := 1 - newMask.Set(cpu) - if newMask.Count() != 1 || !newMask.IsSet(cpu) { - t.Errorf("CpuSet: didn't set CPU %d in set: %v", cpu, newMask) - } - cpu = 5 - newMask.Set(cpu) - if newMask.Count() != 2 || !newMask.IsSet(cpu) { - t.Errorf("CpuSet: didn't set CPU %d in set: %v", cpu, newMask) - } - newMask.Clear(cpu) - if newMask.Count() != 1 || newMask.IsSet(cpu) { - t.Errorf("CpuClr: didn't clear CPU %d in set: %v", cpu, newMask) - } - - if runtime.NumCPU() < 2 { - t.Skip("skipping setaffinity tests on single CPU system") - } - if runtime.GOOS == "android" { - t.Skip("skipping setaffinity tests on android") - } - - // On a system like ppc64x where some cores can be disabled using ppc64_cpu, - // setaffinity should only be called with enabled cores. The valid cores - // are found from the oldMask, but if none are found then the setaffinity - // tests are skipped. Issue #27875. - if !oldMask.IsSet(cpu) { - newMask.Zero() - for i := 0; i < len(oldMask); i++ { - if oldMask.IsSet(i) { - newMask.Set(i) - break - } - } - if newMask.Count() == 0 { - t.Skip("skipping setaffinity tests if CPU not available") - } - } - - err = unix.SchedSetaffinity(0, &newMask) - if err != nil { - t.Fatalf("SchedSetaffinity: %v", err) - } - - var gotMask unix.CPUSet - err = unix.SchedGetaffinity(0, &gotMask) - if err != nil { - t.Fatalf("SchedGetaffinity: %v", err) - } - - if gotMask != newMask { - t.Errorf("SchedSetaffinity: returned affinity mask does not match set affinity mask") - } - - // Restore old mask so it doesn't affect successive tests - err = unix.SchedSetaffinity(0, &oldMask) - if err != nil { - t.Fatalf("SchedSetaffinity: %v", err) - } -} - -func TestStatx(t *testing.T) { - var stx unix.Statx_t - err := unix.Statx(unix.AT_FDCWD, ".", 0, 0, &stx) - if err == unix.ENOSYS || err == unix.EPERM { - t.Skip("statx syscall is not available, skipping test") - } else if err != nil { - t.Fatalf("Statx: %v", err) - } - - defer chtmpdir(t)() - touch(t, "file1") - - var st unix.Stat_t - err = unix.Stat("file1", &st) - if err != nil { - t.Fatalf("Stat: %v", err) - } - - flags := unix.AT_STATX_SYNC_AS_STAT - err = unix.Statx(unix.AT_FDCWD, "file1", flags, unix.STATX_ALL, &stx) - if err != nil { - t.Fatalf("Statx: %v", err) - } - - if uint32(stx.Mode) != st.Mode { - t.Errorf("Statx: returned stat mode does not match Stat") - } - - ctime := unix.StatxTimestamp{Sec: int64(st.Ctim.Sec), Nsec: uint32(st.Ctim.Nsec)} - mtime := unix.StatxTimestamp{Sec: int64(st.Mtim.Sec), Nsec: uint32(st.Mtim.Nsec)} - - if stx.Ctime != ctime { - t.Errorf("Statx: returned stat ctime does not match Stat") - } - if stx.Mtime != mtime { - t.Errorf("Statx: returned stat mtime does not match Stat") - } - - err = os.Symlink("file1", "symlink1") - if err != nil { - t.Fatal(err) - } - - err = unix.Lstat("symlink1", &st) - if err != nil { - t.Fatalf("Lstat: %v", err) - } - - err = unix.Statx(unix.AT_FDCWD, "symlink1", flags, unix.STATX_BASIC_STATS, &stx) - if err != nil { - t.Fatalf("Statx: %v", err) - } - - // follow symlink, expect a regulat file - if stx.Mode&unix.S_IFREG == 0 { - t.Errorf("Statx: didn't follow symlink") - } - - err = unix.Statx(unix.AT_FDCWD, "symlink1", flags|unix.AT_SYMLINK_NOFOLLOW, unix.STATX_ALL, &stx) - if err != nil { - t.Fatalf("Statx: %v", err) - } - - // follow symlink, expect a symlink - if stx.Mode&unix.S_IFLNK == 0 { - t.Errorf("Statx: unexpectedly followed symlink") - } - if uint32(stx.Mode) != st.Mode { - t.Errorf("Statx: returned stat mode does not match Lstat") - } - - ctime = unix.StatxTimestamp{Sec: int64(st.Ctim.Sec), Nsec: uint32(st.Ctim.Nsec)} - mtime = unix.StatxTimestamp{Sec: int64(st.Mtim.Sec), Nsec: uint32(st.Mtim.Nsec)} - - if stx.Ctime != ctime { - t.Errorf("Statx: returned stat ctime does not match Lstat") - } - if stx.Mtime != mtime { - t.Errorf("Statx: returned stat mtime does not match Lstat") - } -} - -// stringsFromByteSlice converts a sequence of attributes to a []string. -// On Linux, each entry is a NULL-terminated string. -func stringsFromByteSlice(buf []byte) []string { - var result []string - off := 0 - for i, b := range buf { - if b == 0 { - result = append(result, string(buf[off:i])) - off = i + 1 - } - } - return result -} - -func TestFaccessat(t *testing.T) { - defer chtmpdir(t)() - touch(t, "file1") - - err := unix.Faccessat(unix.AT_FDCWD, "file1", unix.R_OK, 0) - if err != nil { - t.Errorf("Faccessat: unexpected error: %v", err) - } - - err = unix.Faccessat(unix.AT_FDCWD, "file1", unix.R_OK, 2) - if err != unix.EINVAL { - t.Errorf("Faccessat: unexpected error: %v, want EINVAL", err) - } - - err = unix.Faccessat(unix.AT_FDCWD, "file1", unix.R_OK, unix.AT_EACCESS) - if err != nil { - t.Errorf("Faccessat: unexpected error: %v", err) - } - - err = os.Symlink("file1", "symlink1") - if err != nil { - t.Fatal(err) - } - - err = unix.Faccessat(unix.AT_FDCWD, "symlink1", unix.R_OK, unix.AT_SYMLINK_NOFOLLOW) - if err != nil { - t.Errorf("Faccessat SYMLINK_NOFOLLOW: unexpected error %v", err) - } - - // We can't really test AT_SYMLINK_NOFOLLOW, because there - // doesn't seem to be any way to change the mode of a symlink. - // We don't test AT_EACCESS because such tests are only - // meaningful if run as root. - - err = unix.Fchmodat(unix.AT_FDCWD, "file1", 0, 0) - if err != nil { - t.Errorf("Fchmodat: unexpected error %v", err) - } - - err = unix.Faccessat(unix.AT_FDCWD, "file1", unix.F_OK, unix.AT_SYMLINK_NOFOLLOW) - if err != nil { - t.Errorf("Faccessat: unexpected error: %v", err) - } - - err = unix.Faccessat(unix.AT_FDCWD, "file1", unix.R_OK, unix.AT_SYMLINK_NOFOLLOW) - if err != unix.EACCES { - if unix.Getuid() != 0 { - t.Errorf("Faccessat: unexpected error: %v, want EACCES", err) - } - } -} - -func TestSyncFileRange(t *testing.T) { - file, err := ioutil.TempFile("", "TestSyncFileRange") - if err != nil { - t.Fatal(err) - } - defer os.Remove(file.Name()) - defer file.Close() - - err = unix.SyncFileRange(int(file.Fd()), 0, 0, 0) - if err == unix.ENOSYS || err == unix.EPERM { - t.Skip("sync_file_range syscall is not available, skipping test") - } else if err != nil { - t.Fatalf("SyncFileRange: %v", err) - } - - // invalid flags - flags := 0xf00 - err = unix.SyncFileRange(int(file.Fd()), 0, 0, flags) - if err != unix.EINVAL { - t.Fatalf("SyncFileRange: unexpected error: %v, want EINVAL", err) - } -} - -func TestClockNanosleep(t *testing.T) { - delay := 100 * time.Millisecond - - // Relative timespec. - start := time.Now() - rel := unix.NsecToTimespec(delay.Nanoseconds()) - err := unix.ClockNanosleep(unix.CLOCK_MONOTONIC, 0, &rel, nil) - if err == unix.ENOSYS || err == unix.EPERM { - t.Skip("clock_nanosleep syscall is not available, skipping test") - } else if err != nil { - t.Errorf("ClockNanosleep(CLOCK_MONOTONIC, 0, %#v, nil) = %v", &rel, err) - } else if slept := time.Now().Sub(start); slept < delay { - t.Errorf("ClockNanosleep(CLOCK_MONOTONIC, 0, %#v, nil) slept only %v", &rel, slept) - } - - // Absolute timespec. - start = time.Now() - until := start.Add(delay) - abs := unix.NsecToTimespec(until.UnixNano()) - err = unix.ClockNanosleep(unix.CLOCK_REALTIME, unix.TIMER_ABSTIME, &abs, nil) - if err != nil { - t.Errorf("ClockNanosleep(CLOCK_REALTIME, TIMER_ABSTIME, %#v (=%v), nil) = %v", &abs, until, err) - } else if slept := time.Now().Sub(start); slept < delay { - t.Errorf("ClockNanosleep(CLOCK_REALTIME, TIMER_ABSTIME, %#v (=%v), nil) slept only %v", &abs, until, slept) - } - - // Invalid clock. clock_nanosleep(2) says EINVAL, but it’s actually EOPNOTSUPP. - err = unix.ClockNanosleep(unix.CLOCK_THREAD_CPUTIME_ID, 0, &rel, nil) - if err != unix.EINVAL && err != unix.EOPNOTSUPP { - t.Errorf("ClockNanosleep(CLOCK_THREAD_CPUTIME_ID, 0, %#v, nil) = %v, want EINVAL or EOPNOTSUPP", &rel, err) - } -} diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_test.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_test.go deleted file mode 100644 index 41141f96e..000000000 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_test.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package unix_test - -import ( - "bytes" - "testing" - - "golang.org/x/sys/unix" -) - -// stringsFromByteSlice converts a sequence of attributes to a []string. -// On NetBSD, each entry consists of a single byte containing the length -// of the attribute name, followed by the attribute name. -// The name is _not_ NULL-terminated. -func stringsFromByteSlice(buf []byte) []string { - var result []string - i := 0 - for i < len(buf) { - next := i + 1 + int(buf[i]) - result = append(result, string(buf[i+1:next])) - i = next - } - return result -} - -func TestSysctlClockinfo(t *testing.T) { - ci, err := unix.SysctlClockinfo("kern.clockrate") - if err != nil { - t.Fatal(err) - } - t.Logf("tick = %v, tickadj = %v, hz = %v, profhz = %v, stathz = %v", - ci.Tick, ci.Tickadj, ci.Hz, ci.Profhz, ci.Stathz) -} - -func TestIoctlPtmget(t *testing.T) { - fd, err := unix.Open("/dev/ptmx", unix.O_NOCTTY|unix.O_RDWR, 0666) - if err != nil { - t.Skip("failed to open /dev/ptmx, skipping test") - } - defer unix.Close(fd) - - ptm, err := unix.IoctlGetPtmget(fd, unix.TIOCPTSNAME) - if err != nil { - t.Fatalf("IoctlGetPtmget: %v\n", err) - } - - t.Logf("sfd = %v, ptsname = %v", ptm.Sfd, string(ptm.Sn[:bytes.IndexByte(ptm.Sn[:], 0)])) -} diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_test.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_test.go deleted file mode 100644 index b95f334e1..000000000 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_test.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package unix_test - -import ( - "testing" - "time" - - "golang.org/x/sys/unix" -) - -func TestPpoll(t *testing.T) { - f, cleanup := mktmpfifo(t) - defer cleanup() - - const timeout = 100 * time.Millisecond - - ok := make(chan bool, 1) - go func() { - select { - case <-time.After(10 * timeout): - t.Errorf("Ppoll: failed to timeout after %d", 10*timeout) - case <-ok: - } - }() - - fds := []unix.PollFd{{Fd: int32(f.Fd()), Events: unix.POLLIN}} - timeoutTs := unix.NsecToTimespec(int64(timeout)) - n, err := unix.Ppoll(fds, &timeoutTs, nil) - ok <- true - if err != nil { - t.Errorf("Ppoll: unexpected error: %v", err) - return - } - if n != 0 { - t.Errorf("Ppoll: wrong number of events: got %v, expected %v", n, 0) - return - } -} - -func TestSysctlUvmexp(t *testing.T) { - uvm, err := unix.SysctlUvmexp("vm.uvmexp") - if err != nil { - t.Fatal(err) - } - t.Logf("free = %v", uvm.Free) -} diff --git a/vendor/golang.org/x/sys/unix/syscall_solaris_test.go b/vendor/golang.org/x/sys/unix/syscall_solaris_test.go deleted file mode 100644 index 57dba8824..000000000 --- a/vendor/golang.org/x/sys/unix/syscall_solaris_test.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build solaris - -package unix_test - -import ( - "os/exec" - "testing" - "time" - - "golang.org/x/sys/unix" -) - -func TestSelect(t *testing.T) { - err := unix.Select(0, nil, nil, nil, &unix.Timeval{Sec: 0, Usec: 0}) - if err != nil { - t.Fatalf("Select: %v", err) - } - - dur := 150 * time.Millisecond - tv := unix.NsecToTimeval(int64(dur)) - start := time.Now() - err = unix.Select(0, nil, nil, nil, &tv) - took := time.Since(start) - if err != nil { - t.Fatalf("Select: %v", err) - } - - if took < dur { - t.Errorf("Select: timeout should have been at least %v, got %v", dur, took) - } -} - -func TestStatvfs(t *testing.T) { - if err := unix.Statvfs("", nil); err == nil { - t.Fatal(`Statvfs("") expected failure`) - } - - statvfs := unix.Statvfs_t{} - if err := unix.Statvfs("/", &statvfs); err != nil { - t.Errorf(`Statvfs("/") failed: %v`, err) - } - - if t.Failed() { - mount, err := exec.Command("mount").CombinedOutput() - if err != nil { - t.Logf("mount: %v\n%s", err, mount) - } else { - t.Logf("mount: %s", mount) - } - } -} diff --git a/vendor/golang.org/x/sys/unix/syscall_test.go b/vendor/golang.org/x/sys/unix/syscall_test.go deleted file mode 100644 index dc857840a..000000000 --- a/vendor/golang.org/x/sys/unix/syscall_test.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris - -package unix_test - -import ( - "fmt" - "testing" - - "golang.org/x/sys/unix" -) - -func testSetGetenv(t *testing.T, key, value string) { - err := unix.Setenv(key, value) - if err != nil { - t.Fatalf("Setenv failed to set %q: %v", value, err) - } - newvalue, found := unix.Getenv(key) - if !found { - t.Fatalf("Getenv failed to find %v variable (want value %q)", key, value) - } - if newvalue != value { - t.Fatalf("Getenv(%v) = %q; want %q", key, newvalue, value) - } -} - -func TestEnv(t *testing.T) { - testSetGetenv(t, "TESTENV", "AVALUE") - // make sure TESTENV gets set to "", not deleted - testSetGetenv(t, "TESTENV", "") -} - -func TestItoa(t *testing.T) { - // Make most negative integer: 0x8000... - i := 1 - for i<<1 != 0 { - i <<= 1 - } - if i >= 0 { - t.Fatal("bad math") - } - s := unix.Itoa(i) - f := fmt.Sprint(i) - if s != f { - t.Fatalf("itoa(%d) = %s, want %s", i, s, f) - } -} - -func TestUname(t *testing.T) { - var utsname unix.Utsname - err := unix.Uname(&utsname) - if err != nil { - t.Fatalf("Uname: %v", err) - } - - t.Logf("OS: %s/%s %s", utsname.Sysname[:], utsname.Machine[:], utsname.Release[:]) -} diff --git a/vendor/golang.org/x/sys/unix/syscall_unix_test.go b/vendor/golang.org/x/sys/unix/syscall_unix_test.go deleted file mode 100644 index c393f68d0..000000000 --- a/vendor/golang.org/x/sys/unix/syscall_unix_test.go +++ /dev/null @@ -1,700 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris - -package unix_test - -import ( - "flag" - "fmt" - "io/ioutil" - "net" - "os" - "os/exec" - "path/filepath" - "runtime" - "syscall" - "testing" - "time" - - "golang.org/x/sys/unix" -) - -// Tests that below functions, structures and constants are consistent -// on all Unix-like systems. -func _() { - // program scheduling priority functions and constants - var ( - _ func(int, int, int) error = unix.Setpriority - _ func(int, int) (int, error) = unix.Getpriority - ) - const ( - _ int = unix.PRIO_USER - _ int = unix.PRIO_PROCESS - _ int = unix.PRIO_PGRP - ) - - // termios constants - const ( - _ int = unix.TCIFLUSH - _ int = unix.TCIOFLUSH - _ int = unix.TCOFLUSH - ) - - // fcntl file locking structure and constants - var ( - _ = unix.Flock_t{ - Type: int16(0), - Whence: int16(0), - Start: int64(0), - Len: int64(0), - Pid: int32(0), - } - ) - const ( - _ = unix.F_GETLK - _ = unix.F_SETLK - _ = unix.F_SETLKW - ) -} - -func TestErrnoSignalName(t *testing.T) { - testErrors := []struct { - num syscall.Errno - name string - }{ - {syscall.EPERM, "EPERM"}, - {syscall.EINVAL, "EINVAL"}, - {syscall.ENOENT, "ENOENT"}, - } - - for _, te := range testErrors { - t.Run(fmt.Sprintf("%d/%s", te.num, te.name), func(t *testing.T) { - e := unix.ErrnoName(te.num) - if e != te.name { - t.Errorf("ErrnoName(%d) returned %s, want %s", te.num, e, te.name) - } - }) - } - - testSignals := []struct { - num syscall.Signal - name string - }{ - {syscall.SIGHUP, "SIGHUP"}, - {syscall.SIGPIPE, "SIGPIPE"}, - {syscall.SIGSEGV, "SIGSEGV"}, - } - - for _, ts := range testSignals { - t.Run(fmt.Sprintf("%d/%s", ts.num, ts.name), func(t *testing.T) { - s := unix.SignalName(ts.num) - if s != ts.name { - t.Errorf("SignalName(%d) returned %s, want %s", ts.num, s, ts.name) - } - }) - } -} - -func TestFcntlInt(t *testing.T) { - t.Parallel() - file, err := ioutil.TempFile("", "TestFnctlInt") - if err != nil { - t.Fatal(err) - } - defer os.Remove(file.Name()) - defer file.Close() - f := file.Fd() - flags, err := unix.FcntlInt(f, unix.F_GETFD, 0) - if err != nil { - t.Fatal(err) - } - if flags&unix.FD_CLOEXEC == 0 { - t.Errorf("flags %#x do not include FD_CLOEXEC", flags) - } -} - -// TestFcntlFlock tests whether the file locking structure matches -// the calling convention of each kernel. -func TestFcntlFlock(t *testing.T) { - name := filepath.Join(os.TempDir(), "TestFcntlFlock") - fd, err := unix.Open(name, unix.O_CREAT|unix.O_RDWR|unix.O_CLOEXEC, 0) - if err != nil { - t.Fatalf("Open failed: %v", err) - } - defer unix.Unlink(name) - defer unix.Close(fd) - flock := unix.Flock_t{ - Type: unix.F_RDLCK, - Start: 0, Len: 0, Whence: 1, - } - if err := unix.FcntlFlock(uintptr(fd), unix.F_GETLK, &flock); err != nil { - t.Fatalf("FcntlFlock failed: %v", err) - } -} - -// TestPassFD tests passing a file descriptor over a Unix socket. -// -// This test involved both a parent and child process. The parent -// process is invoked as a normal test, with "go test", which then -// runs the child process by running the current test binary with args -// "-test.run=^TestPassFD$" and an environment variable used to signal -// that the test should become the child process instead. -func TestPassFD(t *testing.T) { - if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") { - t.Skip("cannot exec subprocess on iOS, skipping test") - } - if runtime.GOOS == "aix" { - t.Skip("getsockname issue on AIX 7.2 tl1, skipping test") - } - - if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" { - passFDChild() - return - } - - tempDir, err := ioutil.TempDir("", "TestPassFD") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tempDir) - - fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM, 0) - if err != nil { - t.Fatalf("Socketpair: %v", err) - } - defer unix.Close(fds[0]) - defer unix.Close(fds[1]) - writeFile := os.NewFile(uintptr(fds[0]), "child-writes") - readFile := os.NewFile(uintptr(fds[1]), "parent-reads") - defer writeFile.Close() - defer readFile.Close() - - cmd := exec.Command(os.Args[0], "-test.run=^TestPassFD$", "--", tempDir) - cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"} - if lp := os.Getenv("LD_LIBRARY_PATH"); lp != "" { - cmd.Env = append(cmd.Env, "LD_LIBRARY_PATH="+lp) - } - cmd.ExtraFiles = []*os.File{writeFile} - - out, err := cmd.CombinedOutput() - if len(out) > 0 || err != nil { - t.Fatalf("child process: %q, %v", out, err) - } - - c, err := net.FileConn(readFile) - if err != nil { - t.Fatalf("FileConn: %v", err) - } - defer c.Close() - - uc, ok := c.(*net.UnixConn) - if !ok { - t.Fatalf("unexpected FileConn type; expected UnixConn, got %T", c) - } - - buf := make([]byte, 32) // expect 1 byte - oob := make([]byte, 32) // expect 24 bytes - closeUnix := time.AfterFunc(5*time.Second, func() { - t.Logf("timeout reading from unix socket") - uc.Close() - }) - _, oobn, _, _, err := uc.ReadMsgUnix(buf, oob) - if err != nil { - t.Fatalf("ReadMsgUnix: %v", err) - } - closeUnix.Stop() - - scms, err := unix.ParseSocketControlMessage(oob[:oobn]) - if err != nil { - t.Fatalf("ParseSocketControlMessage: %v", err) - } - if len(scms) != 1 { - t.Fatalf("expected 1 SocketControlMessage; got scms = %#v", scms) - } - scm := scms[0] - gotFds, err := unix.ParseUnixRights(&scm) - if err != nil { - t.Fatalf("unix.ParseUnixRights: %v", err) - } - if len(gotFds) != 1 { - t.Fatalf("wanted 1 fd; got %#v", gotFds) - } - - f := os.NewFile(uintptr(gotFds[0]), "fd-from-child") - defer f.Close() - - got, err := ioutil.ReadAll(f) - want := "Hello from child process!\n" - if string(got) != want { - t.Errorf("child process ReadAll: %q, %v; want %q", got, err, want) - } -} - -// passFDChild is the child process used by TestPassFD. -func passFDChild() { - defer os.Exit(0) - - // Look for our fd. It should be fd 3, but we work around an fd leak - // bug here (http://golang.org/issue/2603) to let it be elsewhere. - var uc *net.UnixConn - for fd := uintptr(3); fd <= 10; fd++ { - f := os.NewFile(fd, "unix-conn") - var ok bool - netc, _ := net.FileConn(f) - uc, ok = netc.(*net.UnixConn) - if ok { - break - } - } - if uc == nil { - fmt.Println("failed to find unix fd") - return - } - - // Make a file f to send to our parent process on uc. - // We make it in tempDir, which our parent will clean up. - flag.Parse() - tempDir := flag.Arg(0) - f, err := ioutil.TempFile(tempDir, "") - if err != nil { - fmt.Printf("TempFile: %v", err) - return - } - - f.Write([]byte("Hello from child process!\n")) - f.Seek(0, 0) - - rights := unix.UnixRights(int(f.Fd())) - dummyByte := []byte("x") - n, oobn, err := uc.WriteMsgUnix(dummyByte, rights, nil) - if err != nil { - fmt.Printf("WriteMsgUnix: %v", err) - return - } - if n != 1 || oobn != len(rights) { - fmt.Printf("WriteMsgUnix = %d, %d; want 1, %d", n, oobn, len(rights)) - return - } -} - -// TestUnixRightsRoundtrip tests that UnixRights, ParseSocketControlMessage, -// and ParseUnixRights are able to successfully round-trip lists of file descriptors. -func TestUnixRightsRoundtrip(t *testing.T) { - testCases := [...][][]int{ - {{42}}, - {{1, 2}}, - {{3, 4, 5}}, - {{}}, - {{1, 2}, {3, 4, 5}, {}, {7}}, - } - for _, testCase := range testCases { - b := []byte{} - var n int - for _, fds := range testCase { - // Last assignment to n wins - n = len(b) + unix.CmsgLen(4*len(fds)) - b = append(b, unix.UnixRights(fds...)...) - } - // Truncate b - b = b[:n] - - scms, err := unix.ParseSocketControlMessage(b) - if err != nil { - t.Fatalf("ParseSocketControlMessage: %v", err) - } - if len(scms) != len(testCase) { - t.Fatalf("expected %v SocketControlMessage; got scms = %#v", len(testCase), scms) - } - for i, scm := range scms { - gotFds, err := unix.ParseUnixRights(&scm) - if err != nil { - t.Fatalf("ParseUnixRights: %v", err) - } - wantFds := testCase[i] - if len(gotFds) != len(wantFds) { - t.Fatalf("expected %v fds, got %#v", len(wantFds), gotFds) - } - for j, fd := range gotFds { - if fd != wantFds[j] { - t.Fatalf("expected fd %v, got %v", wantFds[j], fd) - } - } - } - } -} - -func TestRlimit(t *testing.T) { - var rlimit, zero unix.Rlimit - err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit) - if err != nil { - t.Fatalf("Getrlimit: save failed: %v", err) - } - if zero == rlimit { - t.Fatalf("Getrlimit: save failed: got zero value %#v", rlimit) - } - set := rlimit - set.Cur = set.Max - 1 - if runtime.GOOS == "darwin" && set.Cur > 10240 { - // The max file limit is 10240, even though - // the max returned by Getrlimit is 1<<63-1. - // This is OPEN_MAX in sys/syslimits.h. - set.Cur = 10240 - } - err = unix.Setrlimit(unix.RLIMIT_NOFILE, &set) - if err != nil { - t.Fatalf("Setrlimit: set failed: %#v %v", set, err) - } - var get unix.Rlimit - err = unix.Getrlimit(unix.RLIMIT_NOFILE, &get) - if err != nil { - t.Fatalf("Getrlimit: get failed: %v", err) - } - set = rlimit - set.Cur = set.Max - 1 - if set != get { - // Seems like Darwin requires some privilege to - // increase the soft limit of rlimit sandbox, though - // Setrlimit never reports an error. - switch runtime.GOOS { - case "darwin": - default: - t.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get) - } - } - err = unix.Setrlimit(unix.RLIMIT_NOFILE, &rlimit) - if err != nil { - t.Fatalf("Setrlimit: restore failed: %#v %v", rlimit, err) - } -} - -func TestSeekFailure(t *testing.T) { - _, err := unix.Seek(-1, 0, 0) - if err == nil { - t.Fatalf("Seek(-1, 0, 0) did not fail") - } - str := err.Error() // used to crash on Linux - t.Logf("Seek: %v", str) - if str == "" { - t.Fatalf("Seek(-1, 0, 0) return error with empty message") - } -} - -func TestDup(t *testing.T) { - file, err := ioutil.TempFile("", "TestDup") - if err != nil { - t.Fatalf("Tempfile failed: %v", err) - } - defer os.Remove(file.Name()) - defer file.Close() - f := int(file.Fd()) - - newFd, err := unix.Dup(f) - if err != nil { - t.Fatalf("Dup: %v", err) - } - - err = unix.Dup2(newFd, newFd+1) - if err != nil { - t.Fatalf("Dup2: %v", err) - } - - b1 := []byte("Test123") - b2 := make([]byte, 7) - _, err = unix.Write(newFd+1, b1) - if err != nil { - t.Fatalf("Write to dup2 fd failed: %v", err) - } - _, err = unix.Seek(f, 0, 0) - if err != nil { - t.Fatalf("Seek failed: %v", err) - } - _, err = unix.Read(f, b2) - if err != nil { - t.Fatalf("Read back failed: %v", err) - } - if string(b1) != string(b2) { - t.Errorf("Dup: stdout write not in file, expected %v, got %v", string(b1), string(b2)) - } -} - -func TestPoll(t *testing.T) { - if runtime.GOOS == "android" || - (runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64")) { - t.Skip("mkfifo syscall is not available on android and iOS, skipping test") - } - - f, cleanup := mktmpfifo(t) - defer cleanup() - - const timeout = 100 - - ok := make(chan bool, 1) - go func() { - select { - case <-time.After(10 * timeout * time.Millisecond): - t.Errorf("Poll: failed to timeout after %d milliseconds", 10*timeout) - case <-ok: - } - }() - - fds := []unix.PollFd{{Fd: int32(f.Fd()), Events: unix.POLLIN}} - n, err := unix.Poll(fds, timeout) - ok <- true - if err != nil { - t.Errorf("Poll: unexpected error: %v", err) - return - } - if n != 0 { - t.Errorf("Poll: wrong number of events: got %v, expected %v", n, 0) - return - } -} - -func TestGetwd(t *testing.T) { - fd, err := os.Open(".") - if err != nil { - t.Fatalf("Open .: %s", err) - } - defer fd.Close() - // Directory list for test. Do not worry if any are symlinks or do not - // exist on some common unix desktop environments. That will be checked. - dirs := []string{"/", "/usr/bin", "/etc", "/var", "/opt"} - switch runtime.GOOS { - case "android": - dirs = []string{"/", "/system/bin"} - case "darwin": - switch runtime.GOARCH { - case "arm", "arm64": - d1, err := ioutil.TempDir("", "d1") - if err != nil { - t.Fatalf("TempDir: %v", err) - } - d2, err := ioutil.TempDir("", "d2") - if err != nil { - t.Fatalf("TempDir: %v", err) - } - dirs = []string{d1, d2} - } - } - oldwd := os.Getenv("PWD") - for _, d := range dirs { - // Check whether d exists, is a dir and that d's path does not contain a symlink - fi, err := os.Stat(d) - if err != nil || !fi.IsDir() { - t.Logf("Test dir %s stat error (%v) or not a directory, skipping", d, err) - continue - } - check, err := filepath.EvalSymlinks(d) - if err != nil || check != d { - t.Logf("Test dir %s (%s) is symlink or other error (%v), skipping", d, check, err) - continue - } - err = os.Chdir(d) - if err != nil { - t.Fatalf("Chdir: %v", err) - } - pwd, err := unix.Getwd() - if err != nil { - t.Fatalf("Getwd in %s: %s", d, err) - } - os.Setenv("PWD", oldwd) - err = fd.Chdir() - if err != nil { - // We changed the current directory and cannot go back. - // Don't let the tests continue; they'll scribble - // all over some other directory. - fmt.Fprintf(os.Stderr, "fchdir back to dot failed: %s\n", err) - os.Exit(1) - } - if pwd != d { - t.Fatalf("Getwd returned %q want %q", pwd, d) - } - } -} - -func TestFstatat(t *testing.T) { - defer chtmpdir(t)() - - touch(t, "file1") - - var st1 unix.Stat_t - err := unix.Stat("file1", &st1) - if err != nil { - t.Fatalf("Stat: %v", err) - } - - var st2 unix.Stat_t - err = unix.Fstatat(unix.AT_FDCWD, "file1", &st2, 0) - if err != nil { - t.Fatalf("Fstatat: %v", err) - } - - if st1 != st2 { - t.Errorf("Fstatat: returned stat does not match Stat") - } - - err = os.Symlink("file1", "symlink1") - if err != nil { - t.Fatal(err) - } - - err = unix.Lstat("symlink1", &st1) - if err != nil { - t.Fatalf("Lstat: %v", err) - } - - err = unix.Fstatat(unix.AT_FDCWD, "symlink1", &st2, unix.AT_SYMLINK_NOFOLLOW) - if err != nil { - t.Fatalf("Fstatat: %v", err) - } - - if st1 != st2 { - t.Errorf("Fstatat: returned stat does not match Lstat") - } -} - -func TestFchmodat(t *testing.T) { - defer chtmpdir(t)() - - touch(t, "file1") - err := os.Symlink("file1", "symlink1") - if err != nil { - t.Fatal(err) - } - - mode := os.FileMode(0444) - err = unix.Fchmodat(unix.AT_FDCWD, "symlink1", uint32(mode), 0) - if err != nil { - t.Fatalf("Fchmodat: unexpected error: %v", err) - } - - fi, err := os.Stat("file1") - if err != nil { - t.Fatal(err) - } - - if fi.Mode() != mode { - t.Errorf("Fchmodat: failed to change file mode: expected %v, got %v", mode, fi.Mode()) - } - - mode = os.FileMode(0644) - didChmodSymlink := true - err = unix.Fchmodat(unix.AT_FDCWD, "symlink1", uint32(mode), unix.AT_SYMLINK_NOFOLLOW) - if err != nil { - if (runtime.GOOS == "android" || runtime.GOOS == "linux" || runtime.GOOS == "solaris") && err == unix.EOPNOTSUPP { - // Linux and Illumos don't support flags != 0 - didChmodSymlink = false - } else { - t.Fatalf("Fchmodat: unexpected error: %v", err) - } - } - - if !didChmodSymlink { - // Didn't change mode of the symlink. On Linux, the permissions - // of a symbolic link are always 0777 according to symlink(7) - mode = os.FileMode(0777) - } - - var st unix.Stat_t - err = unix.Lstat("symlink1", &st) - if err != nil { - t.Fatal(err) - } - - got := os.FileMode(st.Mode & 0777) - if got != mode { - t.Errorf("Fchmodat: failed to change symlink mode: expected %v, got %v", mode, got) - } -} - -func TestMkdev(t *testing.T) { - major := uint32(42) - minor := uint32(7) - dev := unix.Mkdev(major, minor) - - if unix.Major(dev) != major { - t.Errorf("Major(%#x) == %d, want %d", dev, unix.Major(dev), major) - } - if unix.Minor(dev) != minor { - t.Errorf("Minor(%#x) == %d, want %d", dev, unix.Minor(dev), minor) - } -} - -func TestRenameat(t *testing.T) { - defer chtmpdir(t)() - - from, to := "renamefrom", "renameto" - - touch(t, from) - - err := unix.Renameat(unix.AT_FDCWD, from, unix.AT_FDCWD, to) - if err != nil { - t.Fatalf("Renameat: unexpected error: %v", err) - } - - _, err = os.Stat(to) - if err != nil { - t.Error(err) - } - - _, err = os.Stat(from) - if err == nil { - t.Errorf("Renameat: stat of renamed file %q unexpectedly suceeded", from) - } -} - -// mktmpfifo creates a temporary FIFO and provides a cleanup function. -func mktmpfifo(t *testing.T) (*os.File, func()) { - err := unix.Mkfifo("fifo", 0666) - if err != nil { - t.Fatalf("mktmpfifo: failed to create FIFO: %v", err) - } - - f, err := os.OpenFile("fifo", os.O_RDWR, 0666) - if err != nil { - os.Remove("fifo") - t.Fatalf("mktmpfifo: failed to open FIFO: %v", err) - } - - return f, func() { - f.Close() - os.Remove("fifo") - } -} - -// utilities taken from os/os_test.go - -func touch(t *testing.T, name string) { - f, err := os.Create(name) - if err != nil { - t.Fatal(err) - } - if err := f.Close(); err != nil { - t.Fatal(err) - } -} - -// chtmpdir changes the working directory to a new temporary directory and -// provides a cleanup function. Used when PWD is read-only. -func chtmpdir(t *testing.T) func() { - oldwd, err := os.Getwd() - if err != nil { - t.Fatalf("chtmpdir: %v", err) - } - d, err := ioutil.TempDir("", "test") - if err != nil { - t.Fatalf("chtmpdir: %v", err) - } - if err := os.Chdir(d); err != nil { - t.Fatalf("chtmpdir: %v", err) - } - return func() { - if err := os.Chdir(oldwd); err != nil { - t.Fatalf("chtmpdir: %v", err) - } - os.RemoveAll(d) - } -} diff --git a/vendor/golang.org/x/sys/unix/timestruct_test.go b/vendor/golang.org/x/sys/unix/timestruct_test.go deleted file mode 100644 index 1a72fdb36..000000000 --- a/vendor/golang.org/x/sys/unix/timestruct_test.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2017 The Go Authors. All right reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris - -package unix_test - -import ( - "testing" - "time" - "unsafe" - - "golang.org/x/sys/unix" -) - -func TestTimeToTimespec(t *testing.T) { - timeTests := []struct { - time time.Time - valid bool - }{ - {time.Unix(0, 0), true}, - {time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), true}, - {time.Date(2262, time.December, 31, 23, 0, 0, 0, time.UTC), false}, - {time.Unix(0x7FFFFFFF, 0), true}, - {time.Unix(0x80000000, 0), false}, - {time.Unix(0x7FFFFFFF, 1000000000), false}, - {time.Unix(0x7FFFFFFF, 999999999), true}, - {time.Unix(-0x80000000, 0), true}, - {time.Unix(-0x80000001, 0), false}, - {time.Date(2038, time.January, 19, 3, 14, 7, 0, time.UTC), true}, - {time.Date(2038, time.January, 19, 3, 14, 8, 0, time.UTC), false}, - {time.Date(1901, time.December, 13, 20, 45, 52, 0, time.UTC), true}, - {time.Date(1901, time.December, 13, 20, 45, 51, 0, time.UTC), false}, - } - - // Currently all targets have either int32 or int64 for Timespec.Sec. - // If there were a new target with unsigned or floating point type for - // it, this test must be adjusted. - have64BitTime := (unsafe.Sizeof(unix.Timespec{}.Sec) == 8) - for _, tt := range timeTests { - ts, err := unix.TimeToTimespec(tt.time) - tt.valid = tt.valid || have64BitTime - if tt.valid && err != nil { - t.Errorf("TimeToTimespec(%v): %v", tt.time, err) - } - if err == nil { - tstime := time.Unix(int64(ts.Sec), int64(ts.Nsec)) - if !tstime.Equal(tt.time) { - t.Errorf("TimeToTimespec(%v) is the time %v", tt.time, tstime) - } - } - } -} diff --git a/vendor/golang.org/x/sys/unix/xattr_test.go b/vendor/golang.org/x/sys/unix/xattr_test.go deleted file mode 100644 index 57fc84fb0..000000000 --- a/vendor/golang.org/x/sys/unix/xattr_test.go +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin freebsd linux netbsd - -package unix_test - -import ( - "io/ioutil" - "os" - "runtime" - "strings" - "testing" - - "golang.org/x/sys/unix" -) - -func TestXattr(t *testing.T) { - defer chtmpdir(t)() - - f := "xattr1" - touch(t, f) - - xattrName := "user.test" - xattrDataSet := "gopher" - - err := unix.Setxattr(f, xattrName, []byte{}, 0) - if err == unix.ENOTSUP || err == unix.EOPNOTSUPP { - t.Skip("filesystem does not support extended attributes, skipping test") - } else if err != nil { - t.Fatalf("Setxattr: %v", err) - } - - err = unix.Setxattr(f, xattrName, []byte(xattrDataSet), 0) - if err != nil { - t.Fatalf("Setxattr: %v", err) - } - - // find size - size, err := unix.Listxattr(f, nil) - if err != nil { - t.Fatalf("Listxattr: %v", err) - } - - if size <= 0 { - t.Fatalf("Listxattr returned an empty list of attributes") - } - - buf := make([]byte, size) - read, err := unix.Listxattr(f, buf) - if err != nil { - t.Fatalf("Listxattr: %v", err) - } - - xattrs := stringsFromByteSlice(buf[:read]) - - xattrWant := xattrName - if runtime.GOOS == "freebsd" { - // On FreeBSD, the namespace is stored separately from the xattr - // name and Listxattr doesn't return the namespace prefix. - xattrWant = strings.TrimPrefix(xattrWant, "user.") - } - found := false - for _, name := range xattrs { - if name == xattrWant { - found = true - } - } - - if !found { - t.Errorf("Listxattr did not return previously set attribute '%s'", xattrName) - } - - // find size - size, err = unix.Getxattr(f, xattrName, nil) - if err != nil { - t.Fatalf("Getxattr: %v", err) - } - - if size <= 0 { - t.Fatalf("Getxattr returned an empty attribute") - } - - xattrDataGet := make([]byte, size) - _, err = unix.Getxattr(f, xattrName, xattrDataGet) - if err != nil { - t.Fatalf("Getxattr: %v", err) - } - - got := string(xattrDataGet) - if got != xattrDataSet { - t.Errorf("Getxattr: expected attribute value %s, got %s", xattrDataSet, got) - } - - err = unix.Removexattr(f, xattrName) - if err != nil { - t.Fatalf("Removexattr: %v", err) - } - - n := "nonexistent" - err = unix.Lsetxattr(n, xattrName, []byte(xattrDataSet), 0) - if err != unix.ENOENT { - t.Errorf("Lsetxattr: expected %v on non-existent file, got %v", unix.ENOENT, err) - } - - _, err = unix.Lgetxattr(n, xattrName, nil) - if err != unix.ENOENT { - t.Errorf("Lgetxattr: %v", err) - } - - s := "symlink1" - err = os.Symlink(n, s) - if err != nil { - t.Fatal(err) - } - - err = unix.Lsetxattr(s, xattrName, []byte(xattrDataSet), 0) - if err != nil { - // Linux and Android doen't support xattrs on symlinks according - // to xattr(7), so just test that we get the proper error. - if (runtime.GOOS != "linux" && runtime.GOOS != "android") || err != unix.EPERM { - t.Fatalf("Lsetxattr: %v", err) - } - } -} - -func TestFdXattr(t *testing.T) { - file, err := ioutil.TempFile("", "TestFdXattr") - if err != nil { - t.Fatal(err) - } - defer os.Remove(file.Name()) - defer file.Close() - - fd := int(file.Fd()) - xattrName := "user.test" - xattrDataSet := "gopher" - - err = unix.Fsetxattr(fd, xattrName, []byte(xattrDataSet), 0) - if err == unix.ENOTSUP || err == unix.EOPNOTSUPP { - t.Skip("filesystem does not support extended attributes, skipping test") - } else if err != nil { - t.Fatalf("Fsetxattr: %v", err) - } - - // find size - size, err := unix.Flistxattr(fd, nil) - if err != nil { - t.Fatalf("Flistxattr: %v", err) - } - - if size <= 0 { - t.Fatalf("Flistxattr returned an empty list of attributes") - } - - buf := make([]byte, size) - read, err := unix.Flistxattr(fd, buf) - if err != nil { - t.Fatalf("Flistxattr: %v", err) - } - - xattrs := stringsFromByteSlice(buf[:read]) - - xattrWant := xattrName - if runtime.GOOS == "freebsd" { - // On FreeBSD, the namespace is stored separately from the xattr - // name and Listxattr doesn't return the namespace prefix. - xattrWant = strings.TrimPrefix(xattrWant, "user.") - } - found := false - for _, name := range xattrs { - if name == xattrWant { - found = true - } - } - - if !found { - t.Errorf("Flistxattr did not return previously set attribute '%s'", xattrName) - } - - // find size - size, err = unix.Fgetxattr(fd, xattrName, nil) - if err != nil { - t.Fatalf("Fgetxattr: %v", err) - } - - if size <= 0 { - t.Fatalf("Fgetxattr returned an empty attribute") - } - - xattrDataGet := make([]byte, size) - _, err = unix.Fgetxattr(fd, xattrName, xattrDataGet) - if err != nil { - t.Fatalf("Fgetxattr: %v", err) - } - - got := string(xattrDataGet) - if got != xattrDataSet { - t.Errorf("Fgetxattr: expected attribute value %s, got %s", xattrDataSet, got) - } - - err = unix.Fremovexattr(fd, xattrName) - if err != nil { - t.Fatalf("Fremovexattr: %v", err) - } -} diff --git a/vendor/golang.org/x/time/AUTHORS b/vendor/golang.org/x/time/AUTHORS new file mode 100644 index 000000000..15167cd74 --- /dev/null +++ b/vendor/golang.org/x/time/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/time/CONTRIBUTORS b/vendor/golang.org/x/time/CONTRIBUTORS new file mode 100644 index 000000000..1c4577e96 --- /dev/null +++ b/vendor/golang.org/x/time/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/time/rate/rate.go b/vendor/golang.org/x/time/rate/rate.go index 938feaffe..eabcd1147 100644 --- a/vendor/golang.org/x/time/rate/rate.go +++ b/vendor/golang.org/x/time/rate/rate.go @@ -10,8 +10,6 @@ import ( "math" "sync" "time" - - "golang.org/x/net/context" ) // Limit defines the maximum frequency of some events. @@ -214,8 +212,19 @@ func (lim *Limiter) ReserveN(now time.Time, n int) *Reservation { return &r } +// contextContext is a temporary(?) copy of the context.Context type +// to support both Go 1.6 using golang.org/x/net/context and Go 1.7+ +// with the built-in context package. If people ever stop using Go 1.6 +// we can remove this. +type contextContext interface { + Deadline() (deadline time.Time, ok bool) + Done() <-chan struct{} + Err() error + Value(key interface{}) interface{} +} + // Wait is shorthand for WaitN(ctx, 1). -func (lim *Limiter) Wait(ctx context.Context) (err error) { +func (lim *Limiter) wait(ctx contextContext) (err error) { return lim.WaitN(ctx, 1) } @@ -223,7 +232,7 @@ func (lim *Limiter) Wait(ctx context.Context) (err error) { // It returns an error if n exceeds the Limiter's burst size, the Context is // canceled, or the expected wait time exceeds the Context's Deadline. // The burst limit is ignored if the rate limit is Inf. -func (lim *Limiter) WaitN(ctx context.Context, n int) (err error) { +func (lim *Limiter) waitN(ctx contextContext, n int) (err error) { if n > lim.burst && lim.limit != Inf { return fmt.Errorf("rate: Wait(n=%d) exceeds limiter's burst %d", n, lim.burst) } diff --git a/vendor/golang.org/x/time/rate/rate_go16.go b/vendor/golang.org/x/time/rate/rate_go16.go new file mode 100644 index 000000000..6bab1850f --- /dev/null +++ b/vendor/golang.org/x/time/rate/rate_go16.go @@ -0,0 +1,21 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !go1.7 + +package rate + +import "golang.org/x/net/context" + +// Wait is shorthand for WaitN(ctx, 1). +func (lim *Limiter) Wait(ctx context.Context) (err error) { + return lim.waitN(ctx, 1) +} + +// WaitN blocks until lim permits n events to happen. +// It returns an error if n exceeds the Limiter's burst size, the Context is +// canceled, or the expected wait time exceeds the Context's Deadline. +func (lim *Limiter) WaitN(ctx context.Context, n int) (err error) { + return lim.waitN(ctx, n) +} diff --git a/vendor/golang.org/x/time/rate/rate_go17.go b/vendor/golang.org/x/time/rate/rate_go17.go new file mode 100644 index 000000000..f90d85f51 --- /dev/null +++ b/vendor/golang.org/x/time/rate/rate_go17.go @@ -0,0 +1,21 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7 + +package rate + +import "context" + +// Wait is shorthand for WaitN(ctx, 1). +func (lim *Limiter) Wait(ctx context.Context) (err error) { + return lim.waitN(ctx, 1) +} + +// WaitN blocks until lim permits n events to happen. +// It returns an error if n exceeds the Limiter's burst size, the Context is +// canceled, or the expected wait time exceeds the Context's Deadline. +func (lim *Limiter) WaitN(ctx context.Context, n int) (err error) { + return lim.waitN(ctx, n) +} diff --git a/vendor/golang.org/x/time/rate/rate_test.go b/vendor/golang.org/x/time/rate/rate_test.go deleted file mode 100644 index cf45d92ef..000000000 --- a/vendor/golang.org/x/time/rate/rate_test.go +++ /dev/null @@ -1,445 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package rate - -import ( - "math" - "runtime" - "sync" - "sync/atomic" - "testing" - "time" - - "golang.org/x/net/context" -) - -func TestLimit(t *testing.T) { - if Limit(10) == Inf { - t.Errorf("Limit(10) == Inf should be false") - } -} - -func closeEnough(a, b Limit) bool { - return (math.Abs(float64(a)/float64(b)) - 1.0) < 1e-9 -} - -func TestEvery(t *testing.T) { - cases := []struct { - interval time.Duration - lim Limit - }{ - {0, Inf}, - {-1, Inf}, - {1 * time.Nanosecond, Limit(1e9)}, - {1 * time.Microsecond, Limit(1e6)}, - {1 * time.Millisecond, Limit(1e3)}, - {10 * time.Millisecond, Limit(100)}, - {100 * time.Millisecond, Limit(10)}, - {1 * time.Second, Limit(1)}, - {2 * time.Second, Limit(0.5)}, - {time.Duration(2.5 * float64(time.Second)), Limit(0.4)}, - {4 * time.Second, Limit(0.25)}, - {10 * time.Second, Limit(0.1)}, - {time.Duration(math.MaxInt64), Limit(1e9 / float64(math.MaxInt64))}, - } - for _, tc := range cases { - lim := Every(tc.interval) - if !closeEnough(lim, tc.lim) { - t.Errorf("Every(%v) = %v want %v", tc.interval, lim, tc.lim) - } - } -} - -const ( - d = 100 * time.Millisecond -) - -var ( - t0 = time.Now() - t1 = t0.Add(time.Duration(1) * d) - t2 = t0.Add(time.Duration(2) * d) - t3 = t0.Add(time.Duration(3) * d) - t4 = t0.Add(time.Duration(4) * d) - t5 = t0.Add(time.Duration(5) * d) - t9 = t0.Add(time.Duration(9) * d) -) - -type allow struct { - t time.Time - n int - ok bool -} - -func run(t *testing.T, lim *Limiter, allows []allow) { - for i, allow := range allows { - ok := lim.AllowN(allow.t, allow.n) - if ok != allow.ok { - t.Errorf("step %d: lim.AllowN(%v, %v) = %v want %v", - i, allow.t, allow.n, ok, allow.ok) - } - } -} - -func TestLimiterBurst1(t *testing.T) { - run(t, NewLimiter(10, 1), []allow{ - {t0, 1, true}, - {t0, 1, false}, - {t0, 1, false}, - {t1, 1, true}, - {t1, 1, false}, - {t1, 1, false}, - {t2, 2, false}, // burst size is 1, so n=2 always fails - {t2, 1, true}, - {t2, 1, false}, - }) -} - -func TestLimiterBurst3(t *testing.T) { - run(t, NewLimiter(10, 3), []allow{ - {t0, 2, true}, - {t0, 2, false}, - {t0, 1, true}, - {t0, 1, false}, - {t1, 4, false}, - {t2, 1, true}, - {t3, 1, true}, - {t4, 1, true}, - {t4, 1, true}, - {t4, 1, false}, - {t4, 1, false}, - {t9, 3, true}, - {t9, 0, true}, - }) -} - -func TestLimiterJumpBackwards(t *testing.T) { - run(t, NewLimiter(10, 3), []allow{ - {t1, 1, true}, // start at t1 - {t0, 1, true}, // jump back to t0, two tokens remain - {t0, 1, true}, - {t0, 1, false}, - {t0, 1, false}, - {t1, 1, true}, // got a token - {t1, 1, false}, - {t1, 1, false}, - {t2, 1, true}, // got another token - {t2, 1, false}, - {t2, 1, false}, - }) -} - -func TestSimultaneousRequests(t *testing.T) { - const ( - limit = 1 - burst = 5 - numRequests = 15 - ) - var ( - wg sync.WaitGroup - numOK = uint32(0) - ) - - // Very slow replenishing bucket. - lim := NewLimiter(limit, burst) - - // Tries to take a token, atomically updates the counter and decreases the wait - // group counter. - f := func() { - defer wg.Done() - if ok := lim.Allow(); ok { - atomic.AddUint32(&numOK, 1) - } - } - - wg.Add(numRequests) - for i := 0; i < numRequests; i++ { - go f() - } - wg.Wait() - if numOK != burst { - t.Errorf("numOK = %d, want %d", numOK, burst) - } -} - -func TestLongRunningQPS(t *testing.T) { - if runtime.GOOS == "openbsd" { - t.Skip("low resolution time.Sleep invalidates test (golang.org/issue/14183)") - return - } - - // The test runs for a few seconds executing many requests and then checks - // that overall number of requests is reasonable. - const ( - limit = 100 - burst = 100 - ) - var numOK = int32(0) - - lim := NewLimiter(limit, burst) - - var wg sync.WaitGroup - f := func() { - if ok := lim.Allow(); ok { - atomic.AddInt32(&numOK, 1) - } - wg.Done() - } - - start := time.Now() - end := start.Add(5 * time.Second) - for time.Now().Before(end) { - wg.Add(1) - go f() - - // This will still offer ~500 requests per second, but won't consume - // outrageous amount of CPU. - time.Sleep(2 * time.Millisecond) - } - wg.Wait() - elapsed := time.Since(start) - ideal := burst + (limit * float64(elapsed) / float64(time.Second)) - - // We should never get more requests than allowed. - if want := int32(ideal + 1); numOK > want { - t.Errorf("numOK = %d, want %d (ideal %f)", numOK, want, ideal) - } - // We should get very close to the number of requests allowed. - if want := int32(0.999 * ideal); numOK < want { - t.Errorf("numOK = %d, want %d (ideal %f)", numOK, want, ideal) - } -} - -type request struct { - t time.Time - n int - act time.Time - ok bool -} - -// dFromDuration converts a duration to a multiple of the global constant d -func dFromDuration(dur time.Duration) int { - // Adding a millisecond to be swallowed by the integer division - // because we don't care about small inaccuracies - return int((dur + time.Millisecond) / d) -} - -// dSince returns multiples of d since t0 -func dSince(t time.Time) int { - return dFromDuration(t.Sub(t0)) -} - -func runReserve(t *testing.T, lim *Limiter, req request) *Reservation { - return runReserveMax(t, lim, req, InfDuration) -} - -func runReserveMax(t *testing.T, lim *Limiter, req request, maxReserve time.Duration) *Reservation { - r := lim.reserveN(req.t, req.n, maxReserve) - if r.ok && (dSince(r.timeToAct) != dSince(req.act)) || r.ok != req.ok { - t.Errorf("lim.reserveN(t%d, %v, %v) = (t%d, %v) want (t%d, %v)", - dSince(req.t), req.n, maxReserve, dSince(r.timeToAct), r.ok, dSince(req.act), req.ok) - } - return &r -} - -func TestSimpleReserve(t *testing.T) { - lim := NewLimiter(10, 2) - - runReserve(t, lim, request{t0, 2, t0, true}) - runReserve(t, lim, request{t0, 2, t2, true}) - runReserve(t, lim, request{t3, 2, t4, true}) -} - -func TestMix(t *testing.T) { - lim := NewLimiter(10, 2) - - runReserve(t, lim, request{t0, 3, t1, false}) // should return false because n > Burst - runReserve(t, lim, request{t0, 2, t0, true}) - run(t, lim, []allow{{t1, 2, false}}) // not enought tokens - don't allow - runReserve(t, lim, request{t1, 2, t2, true}) - run(t, lim, []allow{{t1, 1, false}}) // negative tokens - don't allow - run(t, lim, []allow{{t3, 1, true}}) -} - -func TestCancelInvalid(t *testing.T) { - lim := NewLimiter(10, 2) - - runReserve(t, lim, request{t0, 2, t0, true}) - r := runReserve(t, lim, request{t0, 3, t3, false}) - r.CancelAt(t0) // should have no effect - runReserve(t, lim, request{t0, 2, t2, true}) // did not get extra tokens -} - -func TestCancelLast(t *testing.T) { - lim := NewLimiter(10, 2) - - runReserve(t, lim, request{t0, 2, t0, true}) - r := runReserve(t, lim, request{t0, 2, t2, true}) - r.CancelAt(t1) // got 2 tokens back - runReserve(t, lim, request{t1, 2, t2, true}) -} - -func TestCancelTooLate(t *testing.T) { - lim := NewLimiter(10, 2) - - runReserve(t, lim, request{t0, 2, t0, true}) - r := runReserve(t, lim, request{t0, 2, t2, true}) - r.CancelAt(t3) // too late to cancel - should have no effect - runReserve(t, lim, request{t3, 2, t4, true}) -} - -func TestCancel0Tokens(t *testing.T) { - lim := NewLimiter(10, 2) - - runReserve(t, lim, request{t0, 2, t0, true}) - r := runReserve(t, lim, request{t0, 1, t1, true}) - runReserve(t, lim, request{t0, 1, t2, true}) - r.CancelAt(t0) // got 0 tokens back - runReserve(t, lim, request{t0, 1, t3, true}) -} - -func TestCancel1Token(t *testing.T) { - lim := NewLimiter(10, 2) - - runReserve(t, lim, request{t0, 2, t0, true}) - r := runReserve(t, lim, request{t0, 2, t2, true}) - runReserve(t, lim, request{t0, 1, t3, true}) - r.CancelAt(t2) // got 1 token back - runReserve(t, lim, request{t2, 2, t4, true}) -} - -func TestCancelMulti(t *testing.T) { - lim := NewLimiter(10, 4) - - runReserve(t, lim, request{t0, 4, t0, true}) - rA := runReserve(t, lim, request{t0, 3, t3, true}) - runReserve(t, lim, request{t0, 1, t4, true}) - rC := runReserve(t, lim, request{t0, 1, t5, true}) - rC.CancelAt(t1) // get 1 token back - rA.CancelAt(t1) // get 2 tokens back, as if C was never reserved - runReserve(t, lim, request{t1, 3, t5, true}) -} - -func TestReserveJumpBack(t *testing.T) { - lim := NewLimiter(10, 2) - - runReserve(t, lim, request{t1, 2, t1, true}) // start at t1 - runReserve(t, lim, request{t0, 1, t1, true}) // should violate Limit,Burst - runReserve(t, lim, request{t2, 2, t3, true}) -} - -func TestReserveJumpBackCancel(t *testing.T) { - lim := NewLimiter(10, 2) - - runReserve(t, lim, request{t1, 2, t1, true}) // start at t1 - r := runReserve(t, lim, request{t1, 2, t3, true}) - runReserve(t, lim, request{t1, 1, t4, true}) - r.CancelAt(t0) // cancel at t0, get 1 token back - runReserve(t, lim, request{t1, 2, t4, true}) // should violate Limit,Burst -} - -func TestReserveSetLimit(t *testing.T) { - lim := NewLimiter(5, 2) - - runReserve(t, lim, request{t0, 2, t0, true}) - runReserve(t, lim, request{t0, 2, t4, true}) - lim.SetLimitAt(t2, 10) - runReserve(t, lim, request{t2, 1, t4, true}) // violates Limit and Burst -} - -func TestReserveSetLimitCancel(t *testing.T) { - lim := NewLimiter(5, 2) - - runReserve(t, lim, request{t0, 2, t0, true}) - r := runReserve(t, lim, request{t0, 2, t4, true}) - lim.SetLimitAt(t2, 10) - r.CancelAt(t2) // 2 tokens back - runReserve(t, lim, request{t2, 2, t3, true}) -} - -func TestReserveMax(t *testing.T) { - lim := NewLimiter(10, 2) - maxT := d - - runReserveMax(t, lim, request{t0, 2, t0, true}, maxT) - runReserveMax(t, lim, request{t0, 1, t1, true}, maxT) // reserve for close future - runReserveMax(t, lim, request{t0, 1, t2, false}, maxT) // time to act too far in the future -} - -type wait struct { - name string - ctx context.Context - n int - delay int // in multiples of d - nilErr bool -} - -func runWait(t *testing.T, lim *Limiter, w wait) { - start := time.Now() - err := lim.WaitN(w.ctx, w.n) - delay := time.Now().Sub(start) - if (w.nilErr && err != nil) || (!w.nilErr && err == nil) || w.delay != dFromDuration(delay) { - errString := "" - if !w.nilErr { - errString = "" - } - t.Errorf("lim.WaitN(%v, lim, %v) = %v with delay %v ; want %v with delay %v", - w.name, w.n, err, delay, errString, d*time.Duration(w.delay)) - } -} - -func TestWaitSimple(t *testing.T) { - lim := NewLimiter(10, 3) - - ctx, cancel := context.WithCancel(context.Background()) - cancel() - runWait(t, lim, wait{"already-cancelled", ctx, 1, 0, false}) - - runWait(t, lim, wait{"exceed-burst-error", context.Background(), 4, 0, false}) - - runWait(t, lim, wait{"act-now", context.Background(), 2, 0, true}) - runWait(t, lim, wait{"act-later", context.Background(), 3, 2, true}) -} - -func TestWaitCancel(t *testing.T) { - lim := NewLimiter(10, 3) - - ctx, cancel := context.WithCancel(context.Background()) - runWait(t, lim, wait{"act-now", ctx, 2, 0, true}) // after this lim.tokens = 1 - go func() { - time.Sleep(d) - cancel() - }() - runWait(t, lim, wait{"will-cancel", ctx, 3, 1, false}) - // should get 3 tokens back, and have lim.tokens = 2 - t.Logf("tokens:%v last:%v lastEvent:%v", lim.tokens, lim.last, lim.lastEvent) - runWait(t, lim, wait{"act-now-after-cancel", context.Background(), 2, 0, true}) -} - -func TestWaitTimeout(t *testing.T) { - lim := NewLimiter(10, 3) - - ctx, cancel := context.WithTimeout(context.Background(), d) - defer cancel() - runWait(t, lim, wait{"act-now", ctx, 2, 0, true}) - runWait(t, lim, wait{"w-timeout-err", ctx, 3, 0, false}) -} - -func TestWaitInf(t *testing.T) { - lim := NewLimiter(Inf, 0) - - runWait(t, lim, wait{"exceed-burst-no-error", context.Background(), 3, 0, true}) -} - -func BenchmarkAllowN(b *testing.B) { - lim := NewLimiter(Every(1*time.Second), 1) - now := time.Now() - b.ReportAllocs() - b.ResetTimer() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - lim.AllowN(now, 1) - } - }) -} diff --git a/vendor/google.golang.org/appengine/internal/api.go b/vendor/google.golang.org/appengine/internal/api.go index aa139d4d5..16f87c5d3 100644 --- a/vendor/google.golang.org/appengine/internal/api.go +++ b/vendor/google.golang.org/appengine/internal/api.go @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. // +build !appengine +// +build go1.7 package internal @@ -32,7 +33,8 @@ import ( ) const ( - apiPath = "/rpc_http" + apiPath = "/rpc_http" + defaultTicketSuffix = "/default.20150612t184001.0" ) var ( @@ -60,6 +62,11 @@ var ( Dial: limitDial, }, } + + defaultTicketOnce sync.Once + defaultTicket string + backgroundContextOnce sync.Once + backgroundContext netcontext.Context ) func apiURL() *url.URL { @@ -83,16 +90,10 @@ func handleHTTP(w http.ResponseWriter, r *http.Request) { outHeader: w.Header(), apiURL: apiURL(), } - stopFlushing := make(chan int) + r = r.WithContext(withContext(r.Context(), c)) + c.req = r - ctxs.Lock() - ctxs.m[r] = c - ctxs.Unlock() - defer func() { - ctxs.Lock() - delete(ctxs.m, r) - ctxs.Unlock() - }() + stopFlushing := make(chan int) // Patch up RemoteAddr so it looks reasonable. if addr := r.Header.Get(userIPHeader); addr != "" { @@ -191,18 +192,6 @@ func renderPanic(x interface{}) string { return string(buf) } -var ctxs = struct { - sync.Mutex - m map[*http.Request]*context - bg *context // background context, lazily initialized - // dec is used by tests to decorate the netcontext.Context returned - // for a given request. This allows tests to add overrides (such as - // WithAppIDOverride) to the context. The map is nil outside tests. - dec map[*http.Request]func(netcontext.Context) netcontext.Context -}{ - m: make(map[*http.Request]*context), -} - // context represents the context of an in-flight HTTP request. // It implements the appengine.Context and http.ResponseWriter interfaces. type context struct { @@ -223,6 +212,34 @@ type context struct { var contextKey = "holds a *context" +// jointContext joins two contexts in a superficial way. +// It takes values and timeouts from a base context, and only values from another context. +type jointContext struct { + base netcontext.Context + valuesOnly netcontext.Context +} + +func (c jointContext) Deadline() (time.Time, bool) { + return c.base.Deadline() +} + +func (c jointContext) Done() <-chan struct{} { + return c.base.Done() +} + +func (c jointContext) Err() error { + return c.base.Err() +} + +func (c jointContext) Value(key interface{}) interface{} { + if val := c.base.Value(key); val != nil { + return val + } + return c.valuesOnly.Value(key) +} + +// fromContext returns the App Engine context or nil if ctx is not +// derived from an App Engine context. func fromContext(ctx netcontext.Context) *context { c, _ := ctx.Value(&contextKey).(*context) return c @@ -247,86 +264,70 @@ func IncomingHeaders(ctx netcontext.Context) http.Header { return nil } -func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context { - ctxs.Lock() - c := ctxs.m[req] - d := ctxs.dec[req] - ctxs.Unlock() +func ReqContext(req *http.Request) netcontext.Context { + return req.Context() +} - if d != nil { - parent = d(parent) +func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context { + return jointContext{ + base: parent, + valuesOnly: req.Context(), } +} - if c == nil { - // Someone passed in an http.Request that is not in-flight. - // We panic here rather than panicking at a later point - // so that stack traces will be more sensible. - log.Panic("appengine: NewContext passed an unknown http.Request") - } - return withContext(parent, c) +// DefaultTicket returns a ticket used for background context or dev_appserver. +func DefaultTicket() string { + defaultTicketOnce.Do(func() { + if IsDevAppServer() { + defaultTicket = "testapp" + defaultTicketSuffix + return + } + appID := partitionlessAppID() + escAppID := strings.Replace(strings.Replace(appID, ":", "_", -1), ".", "_", -1) + majVersion := VersionID(nil) + if i := strings.Index(majVersion, "."); i > 0 { + majVersion = majVersion[:i] + } + defaultTicket = fmt.Sprintf("%s/%s.%s.%s", escAppID, ModuleName(nil), majVersion, InstanceID()) + }) + return defaultTicket } func BackgroundContext() netcontext.Context { - ctxs.Lock() - defer ctxs.Unlock() - - if ctxs.bg != nil { - return toContext(ctxs.bg) - } - - // Compute background security ticket. - appID := partitionlessAppID() - escAppID := strings.Replace(strings.Replace(appID, ":", "_", -1), ".", "_", -1) - majVersion := VersionID(nil) - if i := strings.Index(majVersion, "."); i > 0 { - majVersion = majVersion[:i] - } - ticket := fmt.Sprintf("%s/%s.%s.%s", escAppID, ModuleName(nil), majVersion, InstanceID()) - - ctxs.bg = &context{ - req: &http.Request{ - Header: http.Header{ - ticketHeader: []string{ticket}, + backgroundContextOnce.Do(func() { + // Compute background security ticket. + ticket := DefaultTicket() + + c := &context{ + req: &http.Request{ + Header: http.Header{ + ticketHeader: []string{ticket}, + }, }, - }, - apiURL: apiURL(), - } + apiURL: apiURL(), + } + backgroundContext = toContext(c) - // TODO(dsymonds): Wire up the shutdown handler to do a final flush. - go ctxs.bg.logFlusher(make(chan int)) + // TODO(dsymonds): Wire up the shutdown handler to do a final flush. + go c.logFlusher(make(chan int)) + }) - return toContext(ctxs.bg) + return backgroundContext } // RegisterTestRequest registers the HTTP request req for testing, such that // any API calls are sent to the provided URL. It returns a closure to delete // the registration. // It should only be used by aetest package. -func RegisterTestRequest(req *http.Request, apiURL *url.URL, decorate func(netcontext.Context) netcontext.Context) func() { +func RegisterTestRequest(req *http.Request, apiURL *url.URL, decorate func(netcontext.Context) netcontext.Context) (*http.Request, func()) { c := &context{ req: req, apiURL: apiURL, } - ctxs.Lock() - defer ctxs.Unlock() - if _, ok := ctxs.m[req]; ok { - log.Panic("req already associated with context") - } - if _, ok := ctxs.dec[req]; ok { - log.Panic("req already associated with context") - } - if ctxs.dec == nil { - ctxs.dec = make(map[*http.Request]func(netcontext.Context) netcontext.Context) - } - ctxs.m[req] = c - ctxs.dec[req] = decorate - - return func() { - ctxs.Lock() - delete(ctxs.m, req) - delete(ctxs.dec, req) - ctxs.Unlock() - } + ctx := withContext(decorate(req.Context()), c) + req = req.WithContext(ctx) + c.req = req + return req, func() {} } var errTimeout = &CallError{ @@ -432,6 +433,12 @@ func (c *context) post(body []byte, timeout time.Duration) (b []byte, err error) } func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error { + if ns := NamespaceFromContext(ctx); ns != "" { + if fn, ok := NamespaceMods[service]; ok { + fn(in, ns) + } + } + if f, ctx, ok := callOverrideFromContext(ctx); ok { return f(ctx, service, method, in, out) } @@ -446,7 +453,7 @@ func Call(ctx netcontext.Context, service, method string, in, out proto.Message) c := fromContext(ctx) if c == nil { // Give a good error message rather than a panic lower down. - return errors.New("not an App Engine context") + return errNotAppEngineContext } // Apply transaction modifications if we're in a transaction. @@ -469,6 +476,16 @@ func Call(ctx netcontext.Context, service, method string, in, out proto.Message) } ticket := c.req.Header.Get(ticketHeader) + // Use a test ticket under test environment. + if ticket == "" { + if appid := ctx.Value(&appIDOverrideKey); appid != nil { + ticket = appid.(string) + defaultTicketSuffix + } + } + // Fall back to use background ticket when the request ticket is not available in Flex or dev_appserver. + if ticket == "" { + ticket = DefaultTicket() + } req := &remotepb.Request{ ServiceName: &service, Method: &method, @@ -544,6 +561,9 @@ var logLevelName = map[int64]string{ } func logf(c *context, level int64, format string, args ...interface{}) { + if c == nil { + panic("not an App Engine context") + } s := fmt.Sprintf(format, args...) s = strings.TrimRight(s, "\n") // Remove any trailing newline characters. c.addLogLine(&logpb.UserAppLogLine{ diff --git a/vendor/google.golang.org/appengine/internal/api_classic.go b/vendor/google.golang.org/appengine/internal/api_classic.go index 1c072e9db..f0f40b2e3 100644 --- a/vendor/google.golang.org/appengine/internal/api_classic.go +++ b/vendor/google.golang.org/appengine/internal/api_classic.go @@ -8,6 +8,7 @@ package internal import ( "errors" + "fmt" "net/http" "time" @@ -21,14 +22,20 @@ import ( var contextKey = "holds an appengine.Context" +// fromContext returns the App Engine context or nil if ctx is not +// derived from an App Engine context. func fromContext(ctx netcontext.Context) appengine.Context { c, _ := ctx.Value(&contextKey).(appengine.Context) return c } // This is only for classic App Engine adapters. -func ClassicContextFromContext(ctx netcontext.Context) appengine.Context { - return fromContext(ctx) +func ClassicContextFromContext(ctx netcontext.Context) (appengine.Context, error) { + c := fromContext(ctx) + if c == nil { + return nil, errNotAppEngineContext + } + return c, nil } func withContext(parent netcontext.Context, c appengine.Context) netcontext.Context { @@ -52,12 +59,41 @@ func IncomingHeaders(ctx netcontext.Context) http.Header { return nil } +func ReqContext(req *http.Request) netcontext.Context { + return WithContext(netcontext.Background(), req) +} + func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context { c := appengine.NewContext(req) return withContext(parent, c) } +type testingContext struct { + appengine.Context + + req *http.Request +} + +func (t *testingContext) FullyQualifiedAppID() string { return "dev~testcontext" } +func (t *testingContext) Call(service, method string, _, _ appengine_internal.ProtoMessage, _ *appengine_internal.CallOptions) error { + if service == "__go__" && method == "GetNamespace" { + return nil + } + return fmt.Errorf("testingContext: unsupported Call") +} +func (t *testingContext) Request() interface{} { return t.req } + +func ContextForTesting(req *http.Request) netcontext.Context { + return withContext(netcontext.Background(), &testingContext{req: req}) +} + func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error { + if ns := NamespaceFromContext(ctx); ns != "" { + if fn, ok := NamespaceMods[service]; ok { + fn(in, ns) + } + } + if f, ctx, ok := callOverrideFromContext(ctx); ok { return f(ctx, service, method, in, out) } @@ -72,7 +108,7 @@ func Call(ctx netcontext.Context, service, method string, in, out proto.Message) c := fromContext(ctx) if c == nil { // Give a good error message rather than a panic lower down. - return errors.New("not an App Engine context") + return errNotAppEngineContext } // Apply transaction modifications if we're in a transaction. diff --git a/vendor/google.golang.org/appengine/internal/api_common.go b/vendor/google.golang.org/appengine/internal/api_common.go index ec5383e66..e0c0b214b 100644 --- a/vendor/google.golang.org/appengine/internal/api_common.go +++ b/vendor/google.golang.org/appengine/internal/api_common.go @@ -5,10 +5,15 @@ package internal import ( + "errors" + "os" + "github.com/golang/protobuf/proto" netcontext "golang.org/x/net/context" ) +var errNotAppEngineContext = errors.New("not an App Engine context") + type CallOverrideFunc func(ctx netcontext.Context, service, method string, in, out proto.Message) error var callOverrideKey = "holds []CallOverrideFunc" @@ -77,25 +82,42 @@ func Logf(ctx netcontext.Context, level int64, format string, args ...interface{ f(level, format, args...) return } - logf(fromContext(ctx), level, format, args...) + c := fromContext(ctx) + if c == nil { + panic(errNotAppEngineContext) + } + logf(c, level, format, args...) } // NamespacedContext wraps a Context to support namespaces. func NamespacedContext(ctx netcontext.Context, namespace string) netcontext.Context { - n := &namespacedContext{ - namespace: namespace, - } - return withNamespace(WithCallOverride(ctx, n.call), namespace) + return withNamespace(ctx, namespace) } -type namespacedContext struct { - namespace string -} +// SetTestEnv sets the env variables for testing background ticket in Flex. +func SetTestEnv() func() { + var environ = []struct { + key, value string + }{ + {"GAE_LONG_APP_ID", "my-app-id"}, + {"GAE_MINOR_VERSION", "067924799508853122"}, + {"GAE_MODULE_INSTANCE", "0"}, + {"GAE_MODULE_NAME", "default"}, + {"GAE_MODULE_VERSION", "20150612t184001"}, + } -func (n *namespacedContext) call(ctx netcontext.Context, service, method string, in, out proto.Message) error { - // Apply any namespace mods. - if mod, ok := NamespaceMods[service]; ok { - mod(in, n.namespace) + for _, v := range environ { + old := os.Getenv(v.key) + os.Setenv(v.key, v.value) + v.value = old + } + return func() { // Restore old environment after the test completes. + for _, v := range environ { + if v.value == "" { + os.Unsetenv(v.key) + continue + } + os.Setenv(v.key, v.value) + } } - return Call(ctx, service, method, in, out) } diff --git a/vendor/google.golang.org/appengine/internal/api_pre17.go b/vendor/google.golang.org/appengine/internal/api_pre17.go new file mode 100644 index 000000000..028b4f056 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/api_pre17.go @@ -0,0 +1,682 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// +build !appengine +// +build !go1.7 + +package internal + +import ( + "bytes" + "errors" + "fmt" + "io/ioutil" + "log" + "net" + "net/http" + "net/url" + "os" + "runtime" + "strconv" + "strings" + "sync" + "sync/atomic" + "time" + + "github.com/golang/protobuf/proto" + netcontext "golang.org/x/net/context" + + basepb "google.golang.org/appengine/internal/base" + logpb "google.golang.org/appengine/internal/log" + remotepb "google.golang.org/appengine/internal/remote_api" +) + +const ( + apiPath = "/rpc_http" + defaultTicketSuffix = "/default.20150612t184001.0" +) + +var ( + // Incoming headers. + ticketHeader = http.CanonicalHeaderKey("X-AppEngine-API-Ticket") + dapperHeader = http.CanonicalHeaderKey("X-Google-DapperTraceInfo") + traceHeader = http.CanonicalHeaderKey("X-Cloud-Trace-Context") + curNamespaceHeader = http.CanonicalHeaderKey("X-AppEngine-Current-Namespace") + userIPHeader = http.CanonicalHeaderKey("X-AppEngine-User-IP") + remoteAddrHeader = http.CanonicalHeaderKey("X-AppEngine-Remote-Addr") + + // Outgoing headers. + apiEndpointHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Endpoint") + apiEndpointHeaderValue = []string{"app-engine-apis"} + apiMethodHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Method") + apiMethodHeaderValue = []string{"/VMRemoteAPI.CallRemoteAPI"} + apiDeadlineHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Deadline") + apiContentType = http.CanonicalHeaderKey("Content-Type") + apiContentTypeValue = []string{"application/octet-stream"} + logFlushHeader = http.CanonicalHeaderKey("X-AppEngine-Log-Flush-Count") + + apiHTTPClient = &http.Client{ + Transport: &http.Transport{ + Proxy: http.ProxyFromEnvironment, + Dial: limitDial, + }, + } + + defaultTicketOnce sync.Once + defaultTicket string +) + +func apiURL() *url.URL { + host, port := "appengine.googleapis.internal", "10001" + if h := os.Getenv("API_HOST"); h != "" { + host = h + } + if p := os.Getenv("API_PORT"); p != "" { + port = p + } + return &url.URL{ + Scheme: "http", + Host: host + ":" + port, + Path: apiPath, + } +} + +func handleHTTP(w http.ResponseWriter, r *http.Request) { + c := &context{ + req: r, + outHeader: w.Header(), + apiURL: apiURL(), + } + stopFlushing := make(chan int) + + ctxs.Lock() + ctxs.m[r] = c + ctxs.Unlock() + defer func() { + ctxs.Lock() + delete(ctxs.m, r) + ctxs.Unlock() + }() + + // Patch up RemoteAddr so it looks reasonable. + if addr := r.Header.Get(userIPHeader); addr != "" { + r.RemoteAddr = addr + } else if addr = r.Header.Get(remoteAddrHeader); addr != "" { + r.RemoteAddr = addr + } else { + // Should not normally reach here, but pick a sensible default anyway. + r.RemoteAddr = "127.0.0.1" + } + // The address in the headers will most likely be of these forms: + // 123.123.123.123 + // 2001:db8::1 + // net/http.Request.RemoteAddr is specified to be in "IP:port" form. + if _, _, err := net.SplitHostPort(r.RemoteAddr); err != nil { + // Assume the remote address is only a host; add a default port. + r.RemoteAddr = net.JoinHostPort(r.RemoteAddr, "80") + } + + // Start goroutine responsible for flushing app logs. + // This is done after adding c to ctx.m (and stopped before removing it) + // because flushing logs requires making an API call. + go c.logFlusher(stopFlushing) + + executeRequestSafely(c, r) + c.outHeader = nil // make sure header changes aren't respected any more + + stopFlushing <- 1 // any logging beyond this point will be dropped + + // Flush any pending logs asynchronously. + c.pendingLogs.Lock() + flushes := c.pendingLogs.flushes + if len(c.pendingLogs.lines) > 0 { + flushes++ + } + c.pendingLogs.Unlock() + go c.flushLog(false) + w.Header().Set(logFlushHeader, strconv.Itoa(flushes)) + + // Avoid nil Write call if c.Write is never called. + if c.outCode != 0 { + w.WriteHeader(c.outCode) + } + if c.outBody != nil { + w.Write(c.outBody) + } +} + +func executeRequestSafely(c *context, r *http.Request) { + defer func() { + if x := recover(); x != nil { + logf(c, 4, "%s", renderPanic(x)) // 4 == critical + c.outCode = 500 + } + }() + + http.DefaultServeMux.ServeHTTP(c, r) +} + +func renderPanic(x interface{}) string { + buf := make([]byte, 16<<10) // 16 KB should be plenty + buf = buf[:runtime.Stack(buf, false)] + + // Remove the first few stack frames: + // this func + // the recover closure in the caller + // That will root the stack trace at the site of the panic. + const ( + skipStart = "internal.renderPanic" + skipFrames = 2 + ) + start := bytes.Index(buf, []byte(skipStart)) + p := start + for i := 0; i < skipFrames*2 && p+1 < len(buf); i++ { + p = bytes.IndexByte(buf[p+1:], '\n') + p + 1 + if p < 0 { + break + } + } + if p >= 0 { + // buf[start:p+1] is the block to remove. + // Copy buf[p+1:] over buf[start:] and shrink buf. + copy(buf[start:], buf[p+1:]) + buf = buf[:len(buf)-(p+1-start)] + } + + // Add panic heading. + head := fmt.Sprintf("panic: %v\n\n", x) + if len(head) > len(buf) { + // Extremely unlikely to happen. + return head + } + copy(buf[len(head):], buf) + copy(buf, head) + + return string(buf) +} + +var ctxs = struct { + sync.Mutex + m map[*http.Request]*context + bg *context // background context, lazily initialized + // dec is used by tests to decorate the netcontext.Context returned + // for a given request. This allows tests to add overrides (such as + // WithAppIDOverride) to the context. The map is nil outside tests. + dec map[*http.Request]func(netcontext.Context) netcontext.Context +}{ + m: make(map[*http.Request]*context), +} + +// context represents the context of an in-flight HTTP request. +// It implements the appengine.Context and http.ResponseWriter interfaces. +type context struct { + req *http.Request + + outCode int + outHeader http.Header + outBody []byte + + pendingLogs struct { + sync.Mutex + lines []*logpb.UserAppLogLine + flushes int + } + + apiURL *url.URL +} + +var contextKey = "holds a *context" + +// fromContext returns the App Engine context or nil if ctx is not +// derived from an App Engine context. +func fromContext(ctx netcontext.Context) *context { + c, _ := ctx.Value(&contextKey).(*context) + return c +} + +func withContext(parent netcontext.Context, c *context) netcontext.Context { + ctx := netcontext.WithValue(parent, &contextKey, c) + if ns := c.req.Header.Get(curNamespaceHeader); ns != "" { + ctx = withNamespace(ctx, ns) + } + return ctx +} + +func toContext(c *context) netcontext.Context { + return withContext(netcontext.Background(), c) +} + +func IncomingHeaders(ctx netcontext.Context) http.Header { + if c := fromContext(ctx); c != nil { + return c.req.Header + } + return nil +} + +func ReqContext(req *http.Request) netcontext.Context { + return WithContext(netcontext.Background(), req) +} + +func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context { + ctxs.Lock() + c := ctxs.m[req] + d := ctxs.dec[req] + ctxs.Unlock() + + if d != nil { + parent = d(parent) + } + + if c == nil { + // Someone passed in an http.Request that is not in-flight. + // We panic here rather than panicking at a later point + // so that stack traces will be more sensible. + log.Panic("appengine: NewContext passed an unknown http.Request") + } + return withContext(parent, c) +} + +// DefaultTicket returns a ticket used for background context or dev_appserver. +func DefaultTicket() string { + defaultTicketOnce.Do(func() { + if IsDevAppServer() { + defaultTicket = "testapp" + defaultTicketSuffix + return + } + appID := partitionlessAppID() + escAppID := strings.Replace(strings.Replace(appID, ":", "_", -1), ".", "_", -1) + majVersion := VersionID(nil) + if i := strings.Index(majVersion, "."); i > 0 { + majVersion = majVersion[:i] + } + defaultTicket = fmt.Sprintf("%s/%s.%s.%s", escAppID, ModuleName(nil), majVersion, InstanceID()) + }) + return defaultTicket +} + +func BackgroundContext() netcontext.Context { + ctxs.Lock() + defer ctxs.Unlock() + + if ctxs.bg != nil { + return toContext(ctxs.bg) + } + + // Compute background security ticket. + ticket := DefaultTicket() + + ctxs.bg = &context{ + req: &http.Request{ + Header: http.Header{ + ticketHeader: []string{ticket}, + }, + }, + apiURL: apiURL(), + } + + // TODO(dsymonds): Wire up the shutdown handler to do a final flush. + go ctxs.bg.logFlusher(make(chan int)) + + return toContext(ctxs.bg) +} + +// RegisterTestRequest registers the HTTP request req for testing, such that +// any API calls are sent to the provided URL. It returns a closure to delete +// the registration. +// It should only be used by aetest package. +func RegisterTestRequest(req *http.Request, apiURL *url.URL, decorate func(netcontext.Context) netcontext.Context) (*http.Request, func()) { + c := &context{ + req: req, + apiURL: apiURL, + } + ctxs.Lock() + defer ctxs.Unlock() + if _, ok := ctxs.m[req]; ok { + log.Panic("req already associated with context") + } + if _, ok := ctxs.dec[req]; ok { + log.Panic("req already associated with context") + } + if ctxs.dec == nil { + ctxs.dec = make(map[*http.Request]func(netcontext.Context) netcontext.Context) + } + ctxs.m[req] = c + ctxs.dec[req] = decorate + + return req, func() { + ctxs.Lock() + delete(ctxs.m, req) + delete(ctxs.dec, req) + ctxs.Unlock() + } +} + +var errTimeout = &CallError{ + Detail: "Deadline exceeded", + Code: int32(remotepb.RpcError_CANCELLED), + Timeout: true, +} + +func (c *context) Header() http.Header { return c.outHeader } + +// Copied from $GOROOT/src/pkg/net/http/transfer.go. Some response status +// codes do not permit a response body (nor response entity headers such as +// Content-Length, Content-Type, etc). +func bodyAllowedForStatus(status int) bool { + switch { + case status >= 100 && status <= 199: + return false + case status == 204: + return false + case status == 304: + return false + } + return true +} + +func (c *context) Write(b []byte) (int, error) { + if c.outCode == 0 { + c.WriteHeader(http.StatusOK) + } + if len(b) > 0 && !bodyAllowedForStatus(c.outCode) { + return 0, http.ErrBodyNotAllowed + } + c.outBody = append(c.outBody, b...) + return len(b), nil +} + +func (c *context) WriteHeader(code int) { + if c.outCode != 0 { + logf(c, 3, "WriteHeader called multiple times on request.") // error level + return + } + c.outCode = code +} + +func (c *context) post(body []byte, timeout time.Duration) (b []byte, err error) { + hreq := &http.Request{ + Method: "POST", + URL: c.apiURL, + Header: http.Header{ + apiEndpointHeader: apiEndpointHeaderValue, + apiMethodHeader: apiMethodHeaderValue, + apiContentType: apiContentTypeValue, + apiDeadlineHeader: []string{strconv.FormatFloat(timeout.Seconds(), 'f', -1, 64)}, + }, + Body: ioutil.NopCloser(bytes.NewReader(body)), + ContentLength: int64(len(body)), + Host: c.apiURL.Host, + } + if info := c.req.Header.Get(dapperHeader); info != "" { + hreq.Header.Set(dapperHeader, info) + } + if info := c.req.Header.Get(traceHeader); info != "" { + hreq.Header.Set(traceHeader, info) + } + + tr := apiHTTPClient.Transport.(*http.Transport) + + var timedOut int32 // atomic; set to 1 if timed out + t := time.AfterFunc(timeout, func() { + atomic.StoreInt32(&timedOut, 1) + tr.CancelRequest(hreq) + }) + defer t.Stop() + defer func() { + // Check if timeout was exceeded. + if atomic.LoadInt32(&timedOut) != 0 { + err = errTimeout + } + }() + + hresp, err := apiHTTPClient.Do(hreq) + if err != nil { + return nil, &CallError{ + Detail: fmt.Sprintf("service bridge HTTP failed: %v", err), + Code: int32(remotepb.RpcError_UNKNOWN), + } + } + defer hresp.Body.Close() + hrespBody, err := ioutil.ReadAll(hresp.Body) + if hresp.StatusCode != 200 { + return nil, &CallError{ + Detail: fmt.Sprintf("service bridge returned HTTP %d (%q)", hresp.StatusCode, hrespBody), + Code: int32(remotepb.RpcError_UNKNOWN), + } + } + if err != nil { + return nil, &CallError{ + Detail: fmt.Sprintf("service bridge response bad: %v", err), + Code: int32(remotepb.RpcError_UNKNOWN), + } + } + return hrespBody, nil +} + +func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error { + if ns := NamespaceFromContext(ctx); ns != "" { + if fn, ok := NamespaceMods[service]; ok { + fn(in, ns) + } + } + + if f, ctx, ok := callOverrideFromContext(ctx); ok { + return f(ctx, service, method, in, out) + } + + // Handle already-done contexts quickly. + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + c := fromContext(ctx) + if c == nil { + // Give a good error message rather than a panic lower down. + return errNotAppEngineContext + } + + // Apply transaction modifications if we're in a transaction. + if t := transactionFromContext(ctx); t != nil { + if t.finished { + return errors.New("transaction context has expired") + } + applyTransaction(in, &t.transaction) + } + + // Default RPC timeout is 60s. + timeout := 60 * time.Second + if deadline, ok := ctx.Deadline(); ok { + timeout = deadline.Sub(time.Now()) + } + + data, err := proto.Marshal(in) + if err != nil { + return err + } + + ticket := c.req.Header.Get(ticketHeader) + // Use a test ticket under test environment. + if ticket == "" { + if appid := ctx.Value(&appIDOverrideKey); appid != nil { + ticket = appid.(string) + defaultTicketSuffix + } + } + // Fall back to use background ticket when the request ticket is not available in Flex or dev_appserver. + if ticket == "" { + ticket = DefaultTicket() + } + req := &remotepb.Request{ + ServiceName: &service, + Method: &method, + Request: data, + RequestId: &ticket, + } + hreqBody, err := proto.Marshal(req) + if err != nil { + return err + } + + hrespBody, err := c.post(hreqBody, timeout) + if err != nil { + return err + } + + res := &remotepb.Response{} + if err := proto.Unmarshal(hrespBody, res); err != nil { + return err + } + if res.RpcError != nil { + ce := &CallError{ + Detail: res.RpcError.GetDetail(), + Code: *res.RpcError.Code, + } + switch remotepb.RpcError_ErrorCode(ce.Code) { + case remotepb.RpcError_CANCELLED, remotepb.RpcError_DEADLINE_EXCEEDED: + ce.Timeout = true + } + return ce + } + if res.ApplicationError != nil { + return &APIError{ + Service: *req.ServiceName, + Detail: res.ApplicationError.GetDetail(), + Code: *res.ApplicationError.Code, + } + } + if res.Exception != nil || res.JavaException != nil { + // This shouldn't happen, but let's be defensive. + return &CallError{ + Detail: "service bridge returned exception", + Code: int32(remotepb.RpcError_UNKNOWN), + } + } + return proto.Unmarshal(res.Response, out) +} + +func (c *context) Request() *http.Request { + return c.req +} + +func (c *context) addLogLine(ll *logpb.UserAppLogLine) { + // Truncate long log lines. + // TODO(dsymonds): Check if this is still necessary. + const lim = 8 << 10 + if len(*ll.Message) > lim { + suffix := fmt.Sprintf("...(length %d)", len(*ll.Message)) + ll.Message = proto.String((*ll.Message)[:lim-len(suffix)] + suffix) + } + + c.pendingLogs.Lock() + c.pendingLogs.lines = append(c.pendingLogs.lines, ll) + c.pendingLogs.Unlock() +} + +var logLevelName = map[int64]string{ + 0: "DEBUG", + 1: "INFO", + 2: "WARNING", + 3: "ERROR", + 4: "CRITICAL", +} + +func logf(c *context, level int64, format string, args ...interface{}) { + if c == nil { + panic("not an App Engine context") + } + s := fmt.Sprintf(format, args...) + s = strings.TrimRight(s, "\n") // Remove any trailing newline characters. + c.addLogLine(&logpb.UserAppLogLine{ + TimestampUsec: proto.Int64(time.Now().UnixNano() / 1e3), + Level: &level, + Message: &s, + }) + log.Print(logLevelName[level] + ": " + s) +} + +// flushLog attempts to flush any pending logs to the appserver. +// It should not be called concurrently. +func (c *context) flushLog(force bool) (flushed bool) { + c.pendingLogs.Lock() + // Grab up to 30 MB. We can get away with up to 32 MB, but let's be cautious. + n, rem := 0, 30<<20 + for ; n < len(c.pendingLogs.lines); n++ { + ll := c.pendingLogs.lines[n] + // Each log line will require about 3 bytes of overhead. + nb := proto.Size(ll) + 3 + if nb > rem { + break + } + rem -= nb + } + lines := c.pendingLogs.lines[:n] + c.pendingLogs.lines = c.pendingLogs.lines[n:] + c.pendingLogs.Unlock() + + if len(lines) == 0 && !force { + // Nothing to flush. + return false + } + + rescueLogs := false + defer func() { + if rescueLogs { + c.pendingLogs.Lock() + c.pendingLogs.lines = append(lines, c.pendingLogs.lines...) + c.pendingLogs.Unlock() + } + }() + + buf, err := proto.Marshal(&logpb.UserAppLogGroup{ + LogLine: lines, + }) + if err != nil { + log.Printf("internal.flushLog: marshaling UserAppLogGroup: %v", err) + rescueLogs = true + return false + } + + req := &logpb.FlushRequest{ + Logs: buf, + } + res := &basepb.VoidProto{} + c.pendingLogs.Lock() + c.pendingLogs.flushes++ + c.pendingLogs.Unlock() + if err := Call(toContext(c), "logservice", "Flush", req, res); err != nil { + log.Printf("internal.flushLog: Flush RPC: %v", err) + rescueLogs = true + return false + } + return true +} + +const ( + // Log flushing parameters. + flushInterval = 1 * time.Second + forceFlushInterval = 60 * time.Second +) + +func (c *context) logFlusher(stop <-chan int) { + lastFlush := time.Now() + tick := time.NewTicker(flushInterval) + for { + select { + case <-stop: + // Request finished. + tick.Stop() + return + case <-tick.C: + force := time.Now().Sub(lastFlush) > forceFlushInterval + if c.flushLog(force) { + lastFlush = time.Now() + } + } + } +} + +func ContextForTesting(req *http.Request) netcontext.Context { + return toContext(&context{req: req}) +} diff --git a/vendor/google.golang.org/appengine/internal/api_race_test.go b/vendor/google.golang.org/appengine/internal/api_race_test.go deleted file mode 100644 index 6cfe90649..000000000 --- a/vendor/google.golang.org/appengine/internal/api_race_test.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2014 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -// +build race - -package internal - -func init() { raceDetector = true } diff --git a/vendor/google.golang.org/appengine/internal/api_test.go b/vendor/google.golang.org/appengine/internal/api_test.go deleted file mode 100644 index 386d7f6cf..000000000 --- a/vendor/google.golang.org/appengine/internal/api_test.go +++ /dev/null @@ -1,467 +0,0 @@ -// Copyright 2014 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -// +build !appengine - -package internal - -import ( - "bufio" - "bytes" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/http/httptest" - "net/url" - "os" - "os/exec" - "strings" - "sync/atomic" - "testing" - "time" - - "github.com/golang/protobuf/proto" - netcontext "golang.org/x/net/context" - - basepb "google.golang.org/appengine/internal/base" - remotepb "google.golang.org/appengine/internal/remote_api" -) - -const testTicketHeader = "X-Magic-Ticket-Header" - -func init() { - ticketHeader = testTicketHeader -} - -type fakeAPIHandler struct { - hang chan int // used for RunSlowly RPC - - LogFlushes int32 // atomic -} - -func (f *fakeAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - writeResponse := func(res *remotepb.Response) { - hresBody, err := proto.Marshal(res) - if err != nil { - http.Error(w, fmt.Sprintf("Failed encoding API response: %v", err), 500) - return - } - w.Write(hresBody) - } - - if r.URL.Path != "/rpc_http" { - http.NotFound(w, r) - return - } - hreqBody, err := ioutil.ReadAll(r.Body) - if err != nil { - http.Error(w, fmt.Sprintf("Bad body: %v", err), 500) - return - } - apiReq := &remotepb.Request{} - if err := proto.Unmarshal(hreqBody, apiReq); err != nil { - http.Error(w, fmt.Sprintf("Bad encoded API request: %v", err), 500) - return - } - if *apiReq.RequestId != "s3cr3t" { - writeResponse(&remotepb.Response{ - RpcError: &remotepb.RpcError{ - Code: proto.Int32(int32(remotepb.RpcError_SECURITY_VIOLATION)), - Detail: proto.String("bad security ticket"), - }, - }) - return - } - if got, want := r.Header.Get(dapperHeader), "trace-001"; got != want { - writeResponse(&remotepb.Response{ - RpcError: &remotepb.RpcError{ - Code: proto.Int32(int32(remotepb.RpcError_BAD_REQUEST)), - Detail: proto.String(fmt.Sprintf("trace info = %q, want %q", got, want)), - }, - }) - return - } - - service, method := *apiReq.ServiceName, *apiReq.Method - var resOut proto.Message - if service == "actordb" && method == "LookupActor" { - req := &basepb.StringProto{} - res := &basepb.StringProto{} - if err := proto.Unmarshal(apiReq.Request, req); err != nil { - http.Error(w, fmt.Sprintf("Bad encoded request: %v", err), 500) - return - } - if *req.Value == "Doctor Who" { - res.Value = proto.String("David Tennant") - } - resOut = res - } - if service == "errors" { - switch method { - case "Non200": - http.Error(w, "I'm a little teapot.", 418) - return - case "ShortResponse": - w.Header().Set("Content-Length", "100") - w.Write([]byte("way too short")) - return - case "OverQuota": - writeResponse(&remotepb.Response{ - RpcError: &remotepb.RpcError{ - Code: proto.Int32(int32(remotepb.RpcError_OVER_QUOTA)), - Detail: proto.String("you are hogging the resources!"), - }, - }) - return - case "RunSlowly": - // TestAPICallRPCFailure creates f.hang, but does not strobe it - // until Call returns with remotepb.RpcError_CANCELLED. - // This is here to force a happens-before relationship between - // the httptest server handler and shutdown. - <-f.hang - resOut = &basepb.VoidProto{} - } - } - if service == "logservice" && method == "Flush" { - // Pretend log flushing is slow. - time.Sleep(50 * time.Millisecond) - atomic.AddInt32(&f.LogFlushes, 1) - resOut = &basepb.VoidProto{} - } - - encOut, err := proto.Marshal(resOut) - if err != nil { - http.Error(w, fmt.Sprintf("Failed encoding response: %v", err), 500) - return - } - writeResponse(&remotepb.Response{ - Response: encOut, - }) -} - -func setup() (f *fakeAPIHandler, c *context, cleanup func()) { - f = &fakeAPIHandler{} - srv := httptest.NewServer(f) - u, err := url.Parse(srv.URL + apiPath) - if err != nil { - panic(fmt.Sprintf("url.Parse(%q): %v", srv.URL+apiPath, err)) - } - return f, &context{ - req: &http.Request{ - Header: http.Header{ - ticketHeader: []string{"s3cr3t"}, - dapperHeader: []string{"trace-001"}, - }, - }, - apiURL: u, - }, srv.Close -} - -func TestAPICall(t *testing.T) { - _, c, cleanup := setup() - defer cleanup() - - req := &basepb.StringProto{ - Value: proto.String("Doctor Who"), - } - res := &basepb.StringProto{} - err := Call(toContext(c), "actordb", "LookupActor", req, res) - if err != nil { - t.Fatalf("API call failed: %v", err) - } - if got, want := *res.Value, "David Tennant"; got != want { - t.Errorf("Response is %q, want %q", got, want) - } -} - -func TestAPICallRPCFailure(t *testing.T) { - f, c, cleanup := setup() - defer cleanup() - - testCases := []struct { - method string - code remotepb.RpcError_ErrorCode - }{ - {"Non200", remotepb.RpcError_UNKNOWN}, - {"ShortResponse", remotepb.RpcError_UNKNOWN}, - {"OverQuota", remotepb.RpcError_OVER_QUOTA}, - {"RunSlowly", remotepb.RpcError_CANCELLED}, - } - f.hang = make(chan int) // only for RunSlowly - for _, tc := range testCases { - ctx, _ := netcontext.WithTimeout(toContext(c), 100*time.Millisecond) - err := Call(ctx, "errors", tc.method, &basepb.VoidProto{}, &basepb.VoidProto{}) - ce, ok := err.(*CallError) - if !ok { - t.Errorf("%s: API call error is %T (%v), want *CallError", tc.method, err, err) - continue - } - if ce.Code != int32(tc.code) { - t.Errorf("%s: ce.Code = %d, want %d", tc.method, ce.Code, tc.code) - } - if tc.method == "RunSlowly" { - f.hang <- 1 // release the HTTP handler - } - } -} - -func TestAPICallDialFailure(t *testing.T) { - // See what happens if the API host is unresponsive. - // This should time out quickly, not hang forever. - _, c, cleanup := setup() - defer cleanup() - // Reset the URL to the production address so that dialing fails. - c.apiURL = apiURL() - - start := time.Now() - err := Call(toContext(c), "foo", "bar", &basepb.VoidProto{}, &basepb.VoidProto{}) - const max = 1 * time.Second - if taken := time.Since(start); taken > max { - t.Errorf("Dial hang took too long: %v > %v", taken, max) - } - if err == nil { - t.Error("Call did not fail") - } -} - -func TestDelayedLogFlushing(t *testing.T) { - f, c, cleanup := setup() - defer cleanup() - - http.HandleFunc("/quick_log", func(w http.ResponseWriter, r *http.Request) { - logC := WithContext(netcontext.Background(), r) - fromContext(logC).apiURL = c.apiURL // Otherwise it will try to use the default URL. - Logf(logC, 1, "It's a lovely day.") - w.WriteHeader(200) - w.Write(make([]byte, 100<<10)) // write 100 KB to force HTTP flush - }) - - r := &http.Request{ - Method: "GET", - URL: &url.URL{ - Scheme: "http", - Path: "/quick_log", - }, - Header: c.req.Header, - Body: ioutil.NopCloser(bytes.NewReader(nil)), - } - w := httptest.NewRecorder() - - // Check that log flushing does not hold up the HTTP response. - start := time.Now() - handleHTTP(w, r) - if d := time.Since(start); d > 10*time.Millisecond { - t.Errorf("handleHTTP took %v, want under 10ms", d) - } - const hdr = "X-AppEngine-Log-Flush-Count" - if h := w.HeaderMap.Get(hdr); h != "1" { - t.Errorf("%s header = %q, want %q", hdr, h, "1") - } - if f := atomic.LoadInt32(&f.LogFlushes); f != 0 { - t.Errorf("After HTTP response: f.LogFlushes = %d, want 0", f) - } - - // Check that the log flush eventually comes in. - time.Sleep(100 * time.Millisecond) - if f := atomic.LoadInt32(&f.LogFlushes); f != 1 { - t.Errorf("After 100ms: f.LogFlushes = %d, want 1", f) - } -} - -func TestRemoteAddr(t *testing.T) { - var addr string - http.HandleFunc("/remote_addr", func(w http.ResponseWriter, r *http.Request) { - addr = r.RemoteAddr - }) - - testCases := []struct { - headers http.Header - addr string - }{ - {http.Header{"X-Appengine-User-Ip": []string{"10.5.2.1"}}, "10.5.2.1:80"}, - {http.Header{"X-Appengine-Remote-Addr": []string{"1.2.3.4"}}, "1.2.3.4:80"}, - {http.Header{"X-Appengine-Remote-Addr": []string{"1.2.3.4:8080"}}, "1.2.3.4:8080"}, - { - http.Header{"X-Appengine-Remote-Addr": []string{"2401:fa00:9:1:7646:a0ff:fe90:ca66"}}, - "[2401:fa00:9:1:7646:a0ff:fe90:ca66]:80", - }, - { - http.Header{"X-Appengine-Remote-Addr": []string{"[::1]:http"}}, - "[::1]:http", - }, - {http.Header{}, "127.0.0.1:80"}, - } - - for _, tc := range testCases { - r := &http.Request{ - Method: "GET", - URL: &url.URL{Scheme: "http", Path: "/remote_addr"}, - Header: tc.headers, - Body: ioutil.NopCloser(bytes.NewReader(nil)), - } - handleHTTP(httptest.NewRecorder(), r) - if addr != tc.addr { - t.Errorf("Header %v, got %q, want %q", tc.headers, addr, tc.addr) - } - } -} - -func TestPanickingHandler(t *testing.T) { - http.HandleFunc("/panic", func(http.ResponseWriter, *http.Request) { - panic("whoops!") - }) - r := &http.Request{ - Method: "GET", - URL: &url.URL{Scheme: "http", Path: "/panic"}, - Body: ioutil.NopCloser(bytes.NewReader(nil)), - } - rec := httptest.NewRecorder() - handleHTTP(rec, r) - if rec.Code != 500 { - t.Errorf("Panicking handler returned HTTP %d, want HTTP %d", rec.Code, 500) - } -} - -var raceDetector = false - -func TestAPICallAllocations(t *testing.T) { - if raceDetector { - t.Skip("not running under race detector") - } - - // Run the test API server in a subprocess so we aren't counting its allocations. - u, cleanup := launchHelperProcess(t) - defer cleanup() - c := &context{ - req: &http.Request{ - Header: http.Header{ - ticketHeader: []string{"s3cr3t"}, - dapperHeader: []string{"trace-001"}, - }, - }, - apiURL: u, - } - - req := &basepb.StringProto{ - Value: proto.String("Doctor Who"), - } - res := &basepb.StringProto{} - var apiErr error - avg := testing.AllocsPerRun(100, func() { - ctx, _ := netcontext.WithTimeout(toContext(c), 100*time.Millisecond) - if err := Call(ctx, "actordb", "LookupActor", req, res); err != nil && apiErr == nil { - apiErr = err // get the first error only - } - }) - if apiErr != nil { - t.Errorf("API call failed: %v", apiErr) - } - - // Lots of room for improvement... - // TODO(djd): Reduce maximum to 85 once the App Engine SDK is based on 1.6. - const min, max float64 = 70, 90 - if avg < min || max < avg { - t.Errorf("Allocations per API call = %g, want in [%g,%g]", avg, min, max) - } -} - -func launchHelperProcess(t *testing.T) (apiURL *url.URL, cleanup func()) { - cmd := exec.Command(os.Args[0], "-test.run=TestHelperProcess") - cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"} - stdin, err := cmd.StdinPipe() - if err != nil { - t.Fatalf("StdinPipe: %v", err) - } - stdout, err := cmd.StdoutPipe() - if err != nil { - t.Fatalf("StdoutPipe: %v", err) - } - if err := cmd.Start(); err != nil { - t.Fatalf("Starting helper process: %v", err) - } - - scan := bufio.NewScanner(stdout) - var u *url.URL - for scan.Scan() { - line := scan.Text() - if hp := strings.TrimPrefix(line, helperProcessMagic); hp != line { - var err error - u, err = url.Parse(hp) - if err != nil { - t.Fatalf("Failed to parse %q: %v", hp, err) - } - break - } - } - if err := scan.Err(); err != nil { - t.Fatalf("Scanning helper process stdout: %v", err) - } - if u == nil { - t.Fatal("Helper process never reported") - } - - return u, func() { - stdin.Close() - if err := cmd.Wait(); err != nil { - t.Errorf("Helper process did not exit cleanly: %v", err) - } - } -} - -const helperProcessMagic = "A lovely helper process is listening at " - -// This isn't a real test. It's used as a helper process. -func TestHelperProcess(*testing.T) { - if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" { - return - } - defer os.Exit(0) - - f := &fakeAPIHandler{} - srv := httptest.NewServer(f) - defer srv.Close() - fmt.Println(helperProcessMagic + srv.URL + apiPath) - - // Wait for stdin to be closed. - io.Copy(ioutil.Discard, os.Stdin) -} - -func TestBackgroundContext(t *testing.T) { - environ := []struct { - key, value string - }{ - {"GAE_LONG_APP_ID", "my-app-id"}, - {"GAE_MINOR_VERSION", "067924799508853122"}, - {"GAE_MODULE_INSTANCE", "0"}, - {"GAE_MODULE_NAME", "default"}, - {"GAE_MODULE_VERSION", "20150612t184001"}, - } - for _, v := range environ { - old := os.Getenv(v.key) - os.Setenv(v.key, v.value) - v.value = old - } - defer func() { // Restore old environment after the test completes. - for _, v := range environ { - if v.value == "" { - os.Unsetenv(v.key) - continue - } - os.Setenv(v.key, v.value) - } - }() - - ctx, key := fromContext(BackgroundContext()), "X-Magic-Ticket-Header" - if g, w := ctx.req.Header.Get(key), "my-app-id/default.20150612t184001.0"; g != w { - t.Errorf("%v = %q, want %q", key, g, w) - } - - // Check that using the background context doesn't panic. - req := &basepb.StringProto{ - Value: proto.String("Doctor Who"), - } - res := &basepb.StringProto{} - Call(BackgroundContext(), "actordb", "LookupActor", req, res) // expected to fail -} diff --git a/vendor/google.golang.org/appengine/internal/app_id_test.go b/vendor/google.golang.org/appengine/internal/app_id_test.go deleted file mode 100644 index e69195cd4..000000000 --- a/vendor/google.golang.org/appengine/internal/app_id_test.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -package internal - -import ( - "testing" -) - -func TestAppIDParsing(t *testing.T) { - testCases := []struct { - in string - partition, domain, displayID string - }{ - {"simple-app-id", "", "", "simple-app-id"}, - {"domain.com:domain-app-id", "", "domain.com", "domain-app-id"}, - {"part~partition-app-id", "part", "", "partition-app-id"}, - {"part~domain.com:display", "part", "domain.com", "display"}, - } - - for _, tc := range testCases { - part, dom, dis := parseFullAppID(tc.in) - if part != tc.partition { - t.Errorf("partition of %q: got %q, want %q", tc.in, part, tc.partition) - } - if dom != tc.domain { - t.Errorf("domain of %q: got %q, want %q", tc.in, dom, tc.domain) - } - if dis != tc.displayID { - t.Errorf("displayID of %q: got %q, want %q", tc.in, dis, tc.displayID) - } - } -} diff --git a/vendor/google.golang.org/appengine/internal/base/api_base.pb.go b/vendor/google.golang.org/appengine/internal/base/api_base.pb.go index 36a195650..6205a7aee 100644 --- a/vendor/google.golang.org/appengine/internal/base/api_base.pb.go +++ b/vendor/google.golang.org/appengine/internal/base/api_base.pb.go @@ -1,6 +1,5 @@ -// Code generated by protoc-gen-go. +// Code generated by protoc-gen-go. DO NOT EDIT. // source: google.golang.org/appengine/internal/base/api_base.proto -// DO NOT EDIT! /* Package base is a generated protocol buffer package. @@ -28,14 +27,21 @@ var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + type StringProto struct { Value *string `protobuf:"bytes,1,req,name=value" json:"value,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *StringProto) Reset() { *m = StringProto{} } -func (m *StringProto) String() string { return proto.CompactTextString(m) } -func (*StringProto) ProtoMessage() {} +func (m *StringProto) Reset() { *m = StringProto{} } +func (m *StringProto) String() string { return proto.CompactTextString(m) } +func (*StringProto) ProtoMessage() {} +func (*StringProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } func (m *StringProto) GetValue() string { if m != nil && m.Value != nil { @@ -49,9 +55,10 @@ type Integer32Proto struct { XXX_unrecognized []byte `json:"-"` } -func (m *Integer32Proto) Reset() { *m = Integer32Proto{} } -func (m *Integer32Proto) String() string { return proto.CompactTextString(m) } -func (*Integer32Proto) ProtoMessage() {} +func (m *Integer32Proto) Reset() { *m = Integer32Proto{} } +func (m *Integer32Proto) String() string { return proto.CompactTextString(m) } +func (*Integer32Proto) ProtoMessage() {} +func (*Integer32Proto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } func (m *Integer32Proto) GetValue() int32 { if m != nil && m.Value != nil { @@ -65,9 +72,10 @@ type Integer64Proto struct { XXX_unrecognized []byte `json:"-"` } -func (m *Integer64Proto) Reset() { *m = Integer64Proto{} } -func (m *Integer64Proto) String() string { return proto.CompactTextString(m) } -func (*Integer64Proto) ProtoMessage() {} +func (m *Integer64Proto) Reset() { *m = Integer64Proto{} } +func (m *Integer64Proto) String() string { return proto.CompactTextString(m) } +func (*Integer64Proto) ProtoMessage() {} +func (*Integer64Proto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } func (m *Integer64Proto) GetValue() int64 { if m != nil && m.Value != nil { @@ -81,9 +89,10 @@ type BoolProto struct { XXX_unrecognized []byte `json:"-"` } -func (m *BoolProto) Reset() { *m = BoolProto{} } -func (m *BoolProto) String() string { return proto.CompactTextString(m) } -func (*BoolProto) ProtoMessage() {} +func (m *BoolProto) Reset() { *m = BoolProto{} } +func (m *BoolProto) String() string { return proto.CompactTextString(m) } +func (*BoolProto) ProtoMessage() {} +func (*BoolProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } func (m *BoolProto) GetValue() bool { if m != nil && m.Value != nil { @@ -97,9 +106,10 @@ type DoubleProto struct { XXX_unrecognized []byte `json:"-"` } -func (m *DoubleProto) Reset() { *m = DoubleProto{} } -func (m *DoubleProto) String() string { return proto.CompactTextString(m) } -func (*DoubleProto) ProtoMessage() {} +func (m *DoubleProto) Reset() { *m = DoubleProto{} } +func (m *DoubleProto) String() string { return proto.CompactTextString(m) } +func (*DoubleProto) ProtoMessage() {} +func (*DoubleProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } func (m *DoubleProto) GetValue() float64 { if m != nil && m.Value != nil { @@ -113,9 +123,10 @@ type BytesProto struct { XXX_unrecognized []byte `json:"-"` } -func (m *BytesProto) Reset() { *m = BytesProto{} } -func (m *BytesProto) String() string { return proto.CompactTextString(m) } -func (*BytesProto) ProtoMessage() {} +func (m *BytesProto) Reset() { *m = BytesProto{} } +func (m *BytesProto) String() string { return proto.CompactTextString(m) } +func (*BytesProto) ProtoMessage() {} +func (*BytesProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } func (m *BytesProto) GetValue() []byte { if m != nil { @@ -128,6 +139,38 @@ type VoidProto struct { XXX_unrecognized []byte `json:"-"` } -func (m *VoidProto) Reset() { *m = VoidProto{} } -func (m *VoidProto) String() string { return proto.CompactTextString(m) } -func (*VoidProto) ProtoMessage() {} +func (m *VoidProto) Reset() { *m = VoidProto{} } +func (m *VoidProto) String() string { return proto.CompactTextString(m) } +func (*VoidProto) ProtoMessage() {} +func (*VoidProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +func init() { + proto.RegisterType((*StringProto)(nil), "appengine.base.StringProto") + proto.RegisterType((*Integer32Proto)(nil), "appengine.base.Integer32Proto") + proto.RegisterType((*Integer64Proto)(nil), "appengine.base.Integer64Proto") + proto.RegisterType((*BoolProto)(nil), "appengine.base.BoolProto") + proto.RegisterType((*DoubleProto)(nil), "appengine.base.DoubleProto") + proto.RegisterType((*BytesProto)(nil), "appengine.base.BytesProto") + proto.RegisterType((*VoidProto)(nil), "appengine.base.VoidProto") +} + +func init() { + proto.RegisterFile("google.golang.org/appengine/internal/base/api_base.proto", fileDescriptor0) +} + +var fileDescriptor0 = []byte{ + // 199 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0xcf, 0x3f, 0x4b, 0xc6, 0x30, + 0x10, 0x06, 0x70, 0x5a, 0xad, 0xb4, 0x57, 0xe9, 0x20, 0x0e, 0x1d, 0xb5, 0x05, 0x71, 0x4a, 0x40, + 0x45, 0x9c, 0x83, 0x8b, 0x9b, 0x28, 0x38, 0xb8, 0x48, 0x8a, 0xc7, 0x11, 0x08, 0xb9, 0x90, 0xa6, + 0x82, 0xdf, 0x5e, 0xda, 0xd2, 0xfa, 0xc2, 0x9b, 0xed, 0xfe, 0xfc, 0xe0, 0xe1, 0x81, 0x27, 0x62, + 0x26, 0x8b, 0x82, 0xd8, 0x6a, 0x47, 0x82, 0x03, 0x49, 0xed, 0x3d, 0x3a, 0x32, 0x0e, 0xa5, 0x71, + 0x11, 0x83, 0xd3, 0x56, 0x0e, 0x7a, 0x44, 0xa9, 0xbd, 0xf9, 0x9a, 0x07, 0xe1, 0x03, 0x47, 0xbe, + 0x68, 0x76, 0x27, 0xe6, 0x6b, 0xd7, 0x43, 0xfd, 0x1e, 0x83, 0x71, 0xf4, 0xba, 0xbc, 0x2f, 0xa1, + 0xf8, 0xd1, 0x76, 0xc2, 0x36, 0xbb, 0xca, 0x6f, 0xab, 0xb7, 0x75, 0xe9, 0x6e, 0xa0, 0x79, 0x71, + 0x11, 0x09, 0xc3, 0xfd, 0x5d, 0xc2, 0x15, 0xc7, 0xee, 0xf1, 0x21, 0xe1, 0x4e, 0x36, 0x77, 0x0d, + 0x95, 0x62, 0xb6, 0x09, 0x52, 0x6e, 0xa4, 0x87, 0xfa, 0x99, 0xa7, 0xc1, 0x62, 0x02, 0x65, 0xff, + 0x79, 0xa0, 0x7e, 0x23, 0x8e, 0xab, 0x69, 0x0f, 0xcd, 0xb9, 0xca, 0xcb, 0xdd, 0xd5, 0x50, 0x7d, + 0xb0, 0xf9, 0x5e, 0x98, 0x3a, 0xfb, 0x3c, 0x9d, 0x9b, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xba, + 0x37, 0x25, 0xea, 0x44, 0x01, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.pb.go b/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.pb.go index 8613cb731..393342c13 100644 --- a/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.pb.go +++ b/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.pb.go @@ -1,6 +1,5 @@ -// Code generated by protoc-gen-go. +// Code generated by protoc-gen-go. DO NOT EDIT. // source: google.golang.org/appengine/internal/datastore/datastore_v3.proto -// DO NOT EDIT! /* Package datastore is a generated protocol buffer package. @@ -59,6 +58,12 @@ var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + type Property_Meaning int32 const ( @@ -145,6 +150,7 @@ func (x *Property_Meaning) UnmarshalJSON(data []byte) error { *x = Property_Meaning(value) return nil } +func (Property_Meaning) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} } type Property_FtsTokenizationOption int32 @@ -178,6 +184,9 @@ func (x *Property_FtsTokenizationOption) UnmarshalJSON(data []byte) error { *x = Property_FtsTokenizationOption(value) return nil } +func (Property_FtsTokenizationOption) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{2, 1} +} type EntityProto_Kind int32 @@ -214,6 +223,7 @@ func (x *EntityProto_Kind) UnmarshalJSON(data []byte) error { *x = EntityProto_Kind(value) return nil } +func (EntityProto_Kind) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{6, 0} } type Index_Property_Direction int32 @@ -247,6 +257,9 @@ func (x *Index_Property_Direction) UnmarshalJSON(data []byte) error { *x = Index_Property_Direction(value) return nil } +func (Index_Property_Direction) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{8, 0, 0} +} type CompositeIndex_State int32 @@ -286,6 +299,7 @@ func (x *CompositeIndex_State) UnmarshalJSON(data []byte) error { *x = CompositeIndex_State(value) return nil } +func (CompositeIndex_State) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{9, 0} } type Snapshot_Status int32 @@ -319,6 +333,7 @@ func (x *Snapshot_Status) UnmarshalJSON(data []byte) error { *x = Snapshot_Status(value) return nil } +func (Snapshot_Status) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{12, 0} } type Query_Hint int32 @@ -355,6 +370,7 @@ func (x *Query_Hint) UnmarshalJSON(data []byte) error { *x = Query_Hint(value) return nil } +func (Query_Hint) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{15, 0} } type Query_Filter_Operator int32 @@ -403,6 +419,7 @@ func (x *Query_Filter_Operator) UnmarshalJSON(data []byte) error { *x = Query_Filter_Operator(value) return nil } +func (Query_Filter_Operator) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{15, 0, 0} } type Query_Order_Direction int32 @@ -436,6 +453,7 @@ func (x *Query_Order_Direction) UnmarshalJSON(data []byte) error { *x = Query_Order_Direction(value) return nil } +func (Query_Order_Direction) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{15, 1, 0} } type Error_ErrorCode int32 @@ -496,6 +514,7 @@ func (x *Error_ErrorCode) UnmarshalJSON(data []byte) error { *x = Error_ErrorCode(value) return nil } +func (Error_ErrorCode) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{19, 0} } type PutRequest_AutoIdPolicy int32 @@ -529,29 +548,71 @@ func (x *PutRequest_AutoIdPolicy) UnmarshalJSON(data []byte) error { *x = PutRequest_AutoIdPolicy(value) return nil } +func (PutRequest_AutoIdPolicy) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{23, 0} } + +type BeginTransactionRequest_TransactionMode int32 + +const ( + BeginTransactionRequest_UNKNOWN BeginTransactionRequest_TransactionMode = 0 + BeginTransactionRequest_READ_ONLY BeginTransactionRequest_TransactionMode = 1 + BeginTransactionRequest_READ_WRITE BeginTransactionRequest_TransactionMode = 2 +) + +var BeginTransactionRequest_TransactionMode_name = map[int32]string{ + 0: "UNKNOWN", + 1: "READ_ONLY", + 2: "READ_WRITE", +} +var BeginTransactionRequest_TransactionMode_value = map[string]int32{ + "UNKNOWN": 0, + "READ_ONLY": 1, + "READ_WRITE": 2, +} + +func (x BeginTransactionRequest_TransactionMode) Enum() *BeginTransactionRequest_TransactionMode { + p := new(BeginTransactionRequest_TransactionMode) + *p = x + return p +} +func (x BeginTransactionRequest_TransactionMode) String() string { + return proto.EnumName(BeginTransactionRequest_TransactionMode_name, int32(x)) +} +func (x *BeginTransactionRequest_TransactionMode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(BeginTransactionRequest_TransactionMode_value, data, "BeginTransactionRequest_TransactionMode") + if err != nil { + return err + } + *x = BeginTransactionRequest_TransactionMode(value) + return nil +} +func (BeginTransactionRequest_TransactionMode) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{36, 0} +} type Action struct { XXX_unrecognized []byte `json:"-"` } -func (m *Action) Reset() { *m = Action{} } -func (m *Action) String() string { return proto.CompactTextString(m) } -func (*Action) ProtoMessage() {} +func (m *Action) Reset() { *m = Action{} } +func (m *Action) String() string { return proto.CompactTextString(m) } +func (*Action) ProtoMessage() {} +func (*Action) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } type PropertyValue struct { Int64Value *int64 `protobuf:"varint,1,opt,name=int64Value" json:"int64Value,omitempty"` BooleanValue *bool `protobuf:"varint,2,opt,name=booleanValue" json:"booleanValue,omitempty"` StringValue *string `protobuf:"bytes,3,opt,name=stringValue" json:"stringValue,omitempty"` DoubleValue *float64 `protobuf:"fixed64,4,opt,name=doubleValue" json:"doubleValue,omitempty"` - Pointvalue *PropertyValue_PointValue `protobuf:"group,5,opt,name=PointValue" json:"pointvalue,omitempty"` - Uservalue *PropertyValue_UserValue `protobuf:"group,8,opt,name=UserValue" json:"uservalue,omitempty"` - Referencevalue *PropertyValue_ReferenceValue `protobuf:"group,12,opt,name=ReferenceValue" json:"referencevalue,omitempty"` + Pointvalue *PropertyValue_PointValue `protobuf:"group,5,opt,name=PointValue,json=pointvalue" json:"pointvalue,omitempty"` + Uservalue *PropertyValue_UserValue `protobuf:"group,8,opt,name=UserValue,json=uservalue" json:"uservalue,omitempty"` + Referencevalue *PropertyValue_ReferenceValue `protobuf:"group,12,opt,name=ReferenceValue,json=referencevalue" json:"referencevalue,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *PropertyValue) Reset() { *m = PropertyValue{} } -func (m *PropertyValue) String() string { return proto.CompactTextString(m) } -func (*PropertyValue) ProtoMessage() {} +func (m *PropertyValue) Reset() { *m = PropertyValue{} } +func (m *PropertyValue) String() string { return proto.CompactTextString(m) } +func (*PropertyValue) ProtoMessage() {} +func (*PropertyValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } func (m *PropertyValue) GetInt64Value() int64 { if m != nil && m.Int64Value != nil { @@ -608,9 +669,10 @@ type PropertyValue_PointValue struct { XXX_unrecognized []byte `json:"-"` } -func (m *PropertyValue_PointValue) Reset() { *m = PropertyValue_PointValue{} } -func (m *PropertyValue_PointValue) String() string { return proto.CompactTextString(m) } -func (*PropertyValue_PointValue) ProtoMessage() {} +func (m *PropertyValue_PointValue) Reset() { *m = PropertyValue_PointValue{} } +func (m *PropertyValue_PointValue) String() string { return proto.CompactTextString(m) } +func (*PropertyValue_PointValue) ProtoMessage() {} +func (*PropertyValue_PointValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1, 0} } func (m *PropertyValue_PointValue) GetX() float64 { if m != nil && m.X != nil { @@ -628,16 +690,17 @@ func (m *PropertyValue_PointValue) GetY() float64 { type PropertyValue_UserValue struct { Email *string `protobuf:"bytes,9,req,name=email" json:"email,omitempty"` - AuthDomain *string `protobuf:"bytes,10,req,name=auth_domain" json:"auth_domain,omitempty"` + AuthDomain *string `protobuf:"bytes,10,req,name=auth_domain,json=authDomain" json:"auth_domain,omitempty"` Nickname *string `protobuf:"bytes,11,opt,name=nickname" json:"nickname,omitempty"` - FederatedIdentity *string `protobuf:"bytes,21,opt,name=federated_identity" json:"federated_identity,omitempty"` - FederatedProvider *string `protobuf:"bytes,22,opt,name=federated_provider" json:"federated_provider,omitempty"` + FederatedIdentity *string `protobuf:"bytes,21,opt,name=federated_identity,json=federatedIdentity" json:"federated_identity,omitempty"` + FederatedProvider *string `protobuf:"bytes,22,opt,name=federated_provider,json=federatedProvider" json:"federated_provider,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *PropertyValue_UserValue) Reset() { *m = PropertyValue_UserValue{} } -func (m *PropertyValue_UserValue) String() string { return proto.CompactTextString(m) } -func (*PropertyValue_UserValue) ProtoMessage() {} +func (m *PropertyValue_UserValue) Reset() { *m = PropertyValue_UserValue{} } +func (m *PropertyValue_UserValue) String() string { return proto.CompactTextString(m) } +func (*PropertyValue_UserValue) ProtoMessage() {} +func (*PropertyValue_UserValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1, 1} } func (m *PropertyValue_UserValue) GetEmail() string { if m != nil && m.Email != nil { @@ -676,14 +739,15 @@ func (m *PropertyValue_UserValue) GetFederatedProvider() string { type PropertyValue_ReferenceValue struct { App *string `protobuf:"bytes,13,req,name=app" json:"app,omitempty"` - NameSpace *string `protobuf:"bytes,20,opt,name=name_space" json:"name_space,omitempty"` - Pathelement []*PropertyValue_ReferenceValue_PathElement `protobuf:"group,14,rep,name=PathElement" json:"pathelement,omitempty"` + NameSpace *string `protobuf:"bytes,20,opt,name=name_space,json=nameSpace" json:"name_space,omitempty"` + Pathelement []*PropertyValue_ReferenceValue_PathElement `protobuf:"group,14,rep,name=PathElement,json=pathelement" json:"pathelement,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *PropertyValue_ReferenceValue) Reset() { *m = PropertyValue_ReferenceValue{} } -func (m *PropertyValue_ReferenceValue) String() string { return proto.CompactTextString(m) } -func (*PropertyValue_ReferenceValue) ProtoMessage() {} +func (m *PropertyValue_ReferenceValue) Reset() { *m = PropertyValue_ReferenceValue{} } +func (m *PropertyValue_ReferenceValue) String() string { return proto.CompactTextString(m) } +func (*PropertyValue_ReferenceValue) ProtoMessage() {} +func (*PropertyValue_ReferenceValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1, 2} } func (m *PropertyValue_ReferenceValue) GetApp() string { if m != nil && m.App != nil { @@ -718,6 +782,9 @@ func (m *PropertyValue_ReferenceValue_PathElement) Reset() { } func (m *PropertyValue_ReferenceValue_PathElement) String() string { return proto.CompactTextString(m) } func (*PropertyValue_ReferenceValue_PathElement) ProtoMessage() {} +func (*PropertyValue_ReferenceValue_PathElement) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{1, 2, 0} +} func (m *PropertyValue_ReferenceValue_PathElement) GetType() string { if m != nil && m.Type != nil { @@ -742,19 +809,20 @@ func (m *PropertyValue_ReferenceValue_PathElement) GetName() string { type Property struct { Meaning *Property_Meaning `protobuf:"varint,1,opt,name=meaning,enum=appengine.Property_Meaning,def=0" json:"meaning,omitempty"` - MeaningUri *string `protobuf:"bytes,2,opt,name=meaning_uri" json:"meaning_uri,omitempty"` + MeaningUri *string `protobuf:"bytes,2,opt,name=meaning_uri,json=meaningUri" json:"meaning_uri,omitempty"` Name *string `protobuf:"bytes,3,req,name=name" json:"name,omitempty"` Value *PropertyValue `protobuf:"bytes,5,req,name=value" json:"value,omitempty"` Multiple *bool `protobuf:"varint,4,req,name=multiple" json:"multiple,omitempty"` Searchable *bool `protobuf:"varint,6,opt,name=searchable,def=0" json:"searchable,omitempty"` - FtsTokenizationOption *Property_FtsTokenizationOption `protobuf:"varint,8,opt,name=fts_tokenization_option,enum=appengine.Property_FtsTokenizationOption" json:"fts_tokenization_option,omitempty"` + FtsTokenizationOption *Property_FtsTokenizationOption `protobuf:"varint,8,opt,name=fts_tokenization_option,json=ftsTokenizationOption,enum=appengine.Property_FtsTokenizationOption" json:"fts_tokenization_option,omitempty"` Locale *string `protobuf:"bytes,9,opt,name=locale,def=en" json:"locale,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *Property) Reset() { *m = Property{} } -func (m *Property) String() string { return proto.CompactTextString(m) } -func (*Property) ProtoMessage() {} +func (m *Property) Reset() { *m = Property{} } +func (m *Property) String() string { return proto.CompactTextString(m) } +func (*Property) ProtoMessage() {} +func (*Property) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } const Default_Property_Meaning Property_Meaning = Property_NO_MEANING const Default_Property_Searchable bool = false @@ -817,13 +885,14 @@ func (m *Property) GetLocale() string { } type Path struct { - Element []*Path_Element `protobuf:"group,1,rep,name=Element" json:"element,omitempty"` + Element []*Path_Element `protobuf:"group,1,rep,name=Element,json=element" json:"element,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *Path) Reset() { *m = Path{} } -func (m *Path) String() string { return proto.CompactTextString(m) } -func (*Path) ProtoMessage() {} +func (m *Path) Reset() { *m = Path{} } +func (m *Path) String() string { return proto.CompactTextString(m) } +func (*Path) ProtoMessage() {} +func (*Path) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } func (m *Path) GetElement() []*Path_Element { if m != nil { @@ -839,9 +908,10 @@ type Path_Element struct { XXX_unrecognized []byte `json:"-"` } -func (m *Path_Element) Reset() { *m = Path_Element{} } -func (m *Path_Element) String() string { return proto.CompactTextString(m) } -func (*Path_Element) ProtoMessage() {} +func (m *Path_Element) Reset() { *m = Path_Element{} } +func (m *Path_Element) String() string { return proto.CompactTextString(m) } +func (*Path_Element) ProtoMessage() {} +func (*Path_Element) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3, 0} } func (m *Path_Element) GetType() string { if m != nil && m.Type != nil { @@ -866,14 +936,15 @@ func (m *Path_Element) GetName() string { type Reference struct { App *string `protobuf:"bytes,13,req,name=app" json:"app,omitempty"` - NameSpace *string `protobuf:"bytes,20,opt,name=name_space" json:"name_space,omitempty"` + NameSpace *string `protobuf:"bytes,20,opt,name=name_space,json=nameSpace" json:"name_space,omitempty"` Path *Path `protobuf:"bytes,14,req,name=path" json:"path,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *Reference) Reset() { *m = Reference{} } -func (m *Reference) String() string { return proto.CompactTextString(m) } -func (*Reference) ProtoMessage() {} +func (m *Reference) Reset() { *m = Reference{} } +func (m *Reference) String() string { return proto.CompactTextString(m) } +func (*Reference) ProtoMessage() {} +func (*Reference) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } func (m *Reference) GetApp() string { if m != nil && m.App != nil { @@ -898,16 +969,17 @@ func (m *Reference) GetPath() *Path { type User struct { Email *string `protobuf:"bytes,1,req,name=email" json:"email,omitempty"` - AuthDomain *string `protobuf:"bytes,2,req,name=auth_domain" json:"auth_domain,omitempty"` + AuthDomain *string `protobuf:"bytes,2,req,name=auth_domain,json=authDomain" json:"auth_domain,omitempty"` Nickname *string `protobuf:"bytes,3,opt,name=nickname" json:"nickname,omitempty"` - FederatedIdentity *string `protobuf:"bytes,6,opt,name=federated_identity" json:"federated_identity,omitempty"` - FederatedProvider *string `protobuf:"bytes,7,opt,name=federated_provider" json:"federated_provider,omitempty"` + FederatedIdentity *string `protobuf:"bytes,6,opt,name=federated_identity,json=federatedIdentity" json:"federated_identity,omitempty"` + FederatedProvider *string `protobuf:"bytes,7,opt,name=federated_provider,json=federatedProvider" json:"federated_provider,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *User) Reset() { *m = User{} } -func (m *User) String() string { return proto.CompactTextString(m) } -func (*User) ProtoMessage() {} +func (m *User) Reset() { *m = User{} } +func (m *User) String() string { return proto.CompactTextString(m) } +func (*User) ProtoMessage() {} +func (*User) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } func (m *User) GetEmail() string { if m != nil && m.Email != nil { @@ -946,19 +1018,20 @@ func (m *User) GetFederatedProvider() string { type EntityProto struct { Key *Reference `protobuf:"bytes,13,req,name=key" json:"key,omitempty"` - EntityGroup *Path `protobuf:"bytes,16,req,name=entity_group" json:"entity_group,omitempty"` + EntityGroup *Path `protobuf:"bytes,16,req,name=entity_group,json=entityGroup" json:"entity_group,omitempty"` Owner *User `protobuf:"bytes,17,opt,name=owner" json:"owner,omitempty"` Kind *EntityProto_Kind `protobuf:"varint,4,opt,name=kind,enum=appengine.EntityProto_Kind" json:"kind,omitempty"` - KindUri *string `protobuf:"bytes,5,opt,name=kind_uri" json:"kind_uri,omitempty"` + KindUri *string `protobuf:"bytes,5,opt,name=kind_uri,json=kindUri" json:"kind_uri,omitempty"` Property []*Property `protobuf:"bytes,14,rep,name=property" json:"property,omitempty"` - RawProperty []*Property `protobuf:"bytes,15,rep,name=raw_property" json:"raw_property,omitempty"` + RawProperty []*Property `protobuf:"bytes,15,rep,name=raw_property,json=rawProperty" json:"raw_property,omitempty"` Rank *int32 `protobuf:"varint,18,opt,name=rank" json:"rank,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *EntityProto) Reset() { *m = EntityProto{} } -func (m *EntityProto) String() string { return proto.CompactTextString(m) } -func (*EntityProto) ProtoMessage() {} +func (m *EntityProto) Reset() { *m = EntityProto{} } +func (m *EntityProto) String() string { return proto.CompactTextString(m) } +func (*EntityProto) ProtoMessage() {} +func (*EntityProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } func (m *EntityProto) GetKey() *Reference { if m != nil { @@ -1017,14 +1090,15 @@ func (m *EntityProto) GetRank() int32 { } type CompositeProperty struct { - IndexId *int64 `protobuf:"varint,1,req,name=index_id" json:"index_id,omitempty"` + IndexId *int64 `protobuf:"varint,1,req,name=index_id,json=indexId" json:"index_id,omitempty"` Value []string `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *CompositeProperty) Reset() { *m = CompositeProperty{} } -func (m *CompositeProperty) String() string { return proto.CompactTextString(m) } -func (*CompositeProperty) ProtoMessage() {} +func (m *CompositeProperty) Reset() { *m = CompositeProperty{} } +func (m *CompositeProperty) String() string { return proto.CompactTextString(m) } +func (*CompositeProperty) ProtoMessage() {} +func (*CompositeProperty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } func (m *CompositeProperty) GetIndexId() int64 { if m != nil && m.IndexId != nil { @@ -1041,15 +1115,16 @@ func (m *CompositeProperty) GetValue() []string { } type Index struct { - EntityType *string `protobuf:"bytes,1,req,name=entity_type" json:"entity_type,omitempty"` + EntityType *string `protobuf:"bytes,1,req,name=entity_type,json=entityType" json:"entity_type,omitempty"` Ancestor *bool `protobuf:"varint,5,req,name=ancestor" json:"ancestor,omitempty"` - Property []*Index_Property `protobuf:"group,2,rep,name=Property" json:"property,omitempty"` + Property []*Index_Property `protobuf:"group,2,rep,name=Property,json=property" json:"property,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *Index) Reset() { *m = Index{} } -func (m *Index) String() string { return proto.CompactTextString(m) } -func (*Index) ProtoMessage() {} +func (m *Index) Reset() { *m = Index{} } +func (m *Index) String() string { return proto.CompactTextString(m) } +func (*Index) ProtoMessage() {} +func (*Index) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } func (m *Index) GetEntityType() string { if m != nil && m.EntityType != nil { @@ -1078,9 +1153,10 @@ type Index_Property struct { XXX_unrecognized []byte `json:"-"` } -func (m *Index_Property) Reset() { *m = Index_Property{} } -func (m *Index_Property) String() string { return proto.CompactTextString(m) } -func (*Index_Property) ProtoMessage() {} +func (m *Index_Property) Reset() { *m = Index_Property{} } +func (m *Index_Property) String() string { return proto.CompactTextString(m) } +func (*Index_Property) ProtoMessage() {} +func (*Index_Property) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8, 0} } const Default_Index_Property_Direction Index_Property_Direction = Index_Property_ASCENDING @@ -1099,17 +1175,18 @@ func (m *Index_Property) GetDirection() Index_Property_Direction { } type CompositeIndex struct { - AppId *string `protobuf:"bytes,1,req,name=app_id" json:"app_id,omitempty"` + AppId *string `protobuf:"bytes,1,req,name=app_id,json=appId" json:"app_id,omitempty"` Id *int64 `protobuf:"varint,2,req,name=id" json:"id,omitempty"` Definition *Index `protobuf:"bytes,3,req,name=definition" json:"definition,omitempty"` State *CompositeIndex_State `protobuf:"varint,4,req,name=state,enum=appengine.CompositeIndex_State" json:"state,omitempty"` - OnlyUseIfRequired *bool `protobuf:"varint,6,opt,name=only_use_if_required,def=0" json:"only_use_if_required,omitempty"` + OnlyUseIfRequired *bool `protobuf:"varint,6,opt,name=only_use_if_required,json=onlyUseIfRequired,def=0" json:"only_use_if_required,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *CompositeIndex) Reset() { *m = CompositeIndex{} } -func (m *CompositeIndex) String() string { return proto.CompactTextString(m) } -func (*CompositeIndex) ProtoMessage() {} +func (m *CompositeIndex) Reset() { *m = CompositeIndex{} } +func (m *CompositeIndex) String() string { return proto.CompactTextString(m) } +func (*CompositeIndex) ProtoMessage() {} +func (*CompositeIndex) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } const Default_CompositeIndex_OnlyUseIfRequired bool = false @@ -1149,15 +1226,16 @@ func (m *CompositeIndex) GetOnlyUseIfRequired() bool { } type IndexPostfix struct { - IndexValue []*IndexPostfix_IndexValue `protobuf:"bytes,1,rep,name=index_value" json:"index_value,omitempty"` + IndexValue []*IndexPostfix_IndexValue `protobuf:"bytes,1,rep,name=index_value,json=indexValue" json:"index_value,omitempty"` Key *Reference `protobuf:"bytes,2,opt,name=key" json:"key,omitempty"` Before *bool `protobuf:"varint,3,opt,name=before,def=1" json:"before,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *IndexPostfix) Reset() { *m = IndexPostfix{} } -func (m *IndexPostfix) String() string { return proto.CompactTextString(m) } -func (*IndexPostfix) ProtoMessage() {} +func (m *IndexPostfix) Reset() { *m = IndexPostfix{} } +func (m *IndexPostfix) String() string { return proto.CompactTextString(m) } +func (*IndexPostfix) ProtoMessage() {} +func (*IndexPostfix) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } const Default_IndexPostfix_Before bool = true @@ -1183,14 +1261,15 @@ func (m *IndexPostfix) GetBefore() bool { } type IndexPostfix_IndexValue struct { - PropertyName *string `protobuf:"bytes,1,req,name=property_name" json:"property_name,omitempty"` + PropertyName *string `protobuf:"bytes,1,req,name=property_name,json=propertyName" json:"property_name,omitempty"` Value *PropertyValue `protobuf:"bytes,2,req,name=value" json:"value,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *IndexPostfix_IndexValue) Reset() { *m = IndexPostfix_IndexValue{} } -func (m *IndexPostfix_IndexValue) String() string { return proto.CompactTextString(m) } -func (*IndexPostfix_IndexValue) ProtoMessage() {} +func (m *IndexPostfix_IndexValue) Reset() { *m = IndexPostfix_IndexValue{} } +func (m *IndexPostfix_IndexValue) String() string { return proto.CompactTextString(m) } +func (*IndexPostfix_IndexValue) ProtoMessage() {} +func (*IndexPostfix_IndexValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10, 0} } func (m *IndexPostfix_IndexValue) GetPropertyName() string { if m != nil && m.PropertyName != nil { @@ -1212,9 +1291,10 @@ type IndexPosition struct { XXX_unrecognized []byte `json:"-"` } -func (m *IndexPosition) Reset() { *m = IndexPosition{} } -func (m *IndexPosition) String() string { return proto.CompactTextString(m) } -func (*IndexPosition) ProtoMessage() {} +func (m *IndexPosition) Reset() { *m = IndexPosition{} } +func (m *IndexPosition) String() string { return proto.CompactTextString(m) } +func (*IndexPosition) ProtoMessage() {} +func (*IndexPosition) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } const Default_IndexPosition_Before bool = true @@ -1237,9 +1317,10 @@ type Snapshot struct { XXX_unrecognized []byte `json:"-"` } -func (m *Snapshot) Reset() { *m = Snapshot{} } -func (m *Snapshot) String() string { return proto.CompactTextString(m) } -func (*Snapshot) ProtoMessage() {} +func (m *Snapshot) Reset() { *m = Snapshot{} } +func (m *Snapshot) String() string { return proto.CompactTextString(m) } +func (*Snapshot) ProtoMessage() {} +func (*Snapshot) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } func (m *Snapshot) GetTs() int64 { if m != nil && m.Ts != nil { @@ -1253,9 +1334,10 @@ type InternalHeader struct { XXX_unrecognized []byte `json:"-"` } -func (m *InternalHeader) Reset() { *m = InternalHeader{} } -func (m *InternalHeader) String() string { return proto.CompactTextString(m) } -func (*InternalHeader) ProtoMessage() {} +func (m *InternalHeader) Reset() { *m = InternalHeader{} } +func (m *InternalHeader) String() string { return proto.CompactTextString(m) } +func (*InternalHeader) ProtoMessage() {} +func (*InternalHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } func (m *InternalHeader) GetQos() string { if m != nil && m.Qos != nil { @@ -1268,13 +1350,14 @@ type Transaction struct { Header *InternalHeader `protobuf:"bytes,4,opt,name=header" json:"header,omitempty"` Handle *uint64 `protobuf:"fixed64,1,req,name=handle" json:"handle,omitempty"` App *string `protobuf:"bytes,2,req,name=app" json:"app,omitempty"` - MarkChanges *bool `protobuf:"varint,3,opt,name=mark_changes,def=0" json:"mark_changes,omitempty"` + MarkChanges *bool `protobuf:"varint,3,opt,name=mark_changes,json=markChanges,def=0" json:"mark_changes,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *Transaction) Reset() { *m = Transaction{} } -func (m *Transaction) String() string { return proto.CompactTextString(m) } -func (*Transaction) ProtoMessage() {} +func (m *Transaction) Reset() { *m = Transaction{} } +func (m *Transaction) String() string { return proto.CompactTextString(m) } +func (*Transaction) ProtoMessage() {} +func (*Transaction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } const Default_Transaction_MarkChanges bool = false @@ -1309,37 +1392,38 @@ func (m *Transaction) GetMarkChanges() bool { type Query struct { Header *InternalHeader `protobuf:"bytes,39,opt,name=header" json:"header,omitempty"` App *string `protobuf:"bytes,1,req,name=app" json:"app,omitempty"` - NameSpace *string `protobuf:"bytes,29,opt,name=name_space" json:"name_space,omitempty"` + NameSpace *string `protobuf:"bytes,29,opt,name=name_space,json=nameSpace" json:"name_space,omitempty"` Kind *string `protobuf:"bytes,3,opt,name=kind" json:"kind,omitempty"` Ancestor *Reference `protobuf:"bytes,17,opt,name=ancestor" json:"ancestor,omitempty"` - Filter []*Query_Filter `protobuf:"group,4,rep,name=Filter" json:"filter,omitempty"` - SearchQuery *string `protobuf:"bytes,8,opt,name=search_query" json:"search_query,omitempty"` - Order []*Query_Order `protobuf:"group,9,rep,name=Order" json:"order,omitempty"` + Filter []*Query_Filter `protobuf:"group,4,rep,name=Filter,json=filter" json:"filter,omitempty"` + SearchQuery *string `protobuf:"bytes,8,opt,name=search_query,json=searchQuery" json:"search_query,omitempty"` + Order []*Query_Order `protobuf:"group,9,rep,name=Order,json=order" json:"order,omitempty"` Hint *Query_Hint `protobuf:"varint,18,opt,name=hint,enum=appengine.Query_Hint" json:"hint,omitempty"` Count *int32 `protobuf:"varint,23,opt,name=count" json:"count,omitempty"` Offset *int32 `protobuf:"varint,12,opt,name=offset,def=0" json:"offset,omitempty"` Limit *int32 `protobuf:"varint,16,opt,name=limit" json:"limit,omitempty"` - CompiledCursor *CompiledCursor `protobuf:"bytes,30,opt,name=compiled_cursor" json:"compiled_cursor,omitempty"` - EndCompiledCursor *CompiledCursor `protobuf:"bytes,31,opt,name=end_compiled_cursor" json:"end_compiled_cursor,omitempty"` - CompositeIndex []*CompositeIndex `protobuf:"bytes,19,rep,name=composite_index" json:"composite_index,omitempty"` - RequirePerfectPlan *bool `protobuf:"varint,20,opt,name=require_perfect_plan,def=0" json:"require_perfect_plan,omitempty"` - KeysOnly *bool `protobuf:"varint,21,opt,name=keys_only,def=0" json:"keys_only,omitempty"` + CompiledCursor *CompiledCursor `protobuf:"bytes,30,opt,name=compiled_cursor,json=compiledCursor" json:"compiled_cursor,omitempty"` + EndCompiledCursor *CompiledCursor `protobuf:"bytes,31,opt,name=end_compiled_cursor,json=endCompiledCursor" json:"end_compiled_cursor,omitempty"` + CompositeIndex []*CompositeIndex `protobuf:"bytes,19,rep,name=composite_index,json=compositeIndex" json:"composite_index,omitempty"` + RequirePerfectPlan *bool `protobuf:"varint,20,opt,name=require_perfect_plan,json=requirePerfectPlan,def=0" json:"require_perfect_plan,omitempty"` + KeysOnly *bool `protobuf:"varint,21,opt,name=keys_only,json=keysOnly,def=0" json:"keys_only,omitempty"` Transaction *Transaction `protobuf:"bytes,22,opt,name=transaction" json:"transaction,omitempty"` Compile *bool `protobuf:"varint,25,opt,name=compile,def=0" json:"compile,omitempty"` - FailoverMs *int64 `protobuf:"varint,26,opt,name=failover_ms" json:"failover_ms,omitempty"` + FailoverMs *int64 `protobuf:"varint,26,opt,name=failover_ms,json=failoverMs" json:"failover_ms,omitempty"` Strong *bool `protobuf:"varint,32,opt,name=strong" json:"strong,omitempty"` - PropertyName []string `protobuf:"bytes,33,rep,name=property_name" json:"property_name,omitempty"` - GroupByPropertyName []string `protobuf:"bytes,34,rep,name=group_by_property_name" json:"group_by_property_name,omitempty"` + PropertyName []string `protobuf:"bytes,33,rep,name=property_name,json=propertyName" json:"property_name,omitempty"` + GroupByPropertyName []string `protobuf:"bytes,34,rep,name=group_by_property_name,json=groupByPropertyName" json:"group_by_property_name,omitempty"` Distinct *bool `protobuf:"varint,24,opt,name=distinct" json:"distinct,omitempty"` - MinSafeTimeSeconds *int64 `protobuf:"varint,35,opt,name=min_safe_time_seconds" json:"min_safe_time_seconds,omitempty"` - SafeReplicaName []string `protobuf:"bytes,36,rep,name=safe_replica_name" json:"safe_replica_name,omitempty"` - PersistOffset *bool `protobuf:"varint,37,opt,name=persist_offset,def=0" json:"persist_offset,omitempty"` + MinSafeTimeSeconds *int64 `protobuf:"varint,35,opt,name=min_safe_time_seconds,json=minSafeTimeSeconds" json:"min_safe_time_seconds,omitempty"` + SafeReplicaName []string `protobuf:"bytes,36,rep,name=safe_replica_name,json=safeReplicaName" json:"safe_replica_name,omitempty"` + PersistOffset *bool `protobuf:"varint,37,opt,name=persist_offset,json=persistOffset,def=0" json:"persist_offset,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *Query) Reset() { *m = Query{} } -func (m *Query) String() string { return proto.CompactTextString(m) } -func (*Query) ProtoMessage() {} +func (m *Query) Reset() { *m = Query{} } +func (m *Query) String() string { return proto.CompactTextString(m) } +func (*Query) ProtoMessage() {} +func (*Query) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } const Default_Query_Offset int32 = 0 const Default_Query_RequirePerfectPlan bool = false @@ -1542,9 +1626,10 @@ type Query_Filter struct { XXX_unrecognized []byte `json:"-"` } -func (m *Query_Filter) Reset() { *m = Query_Filter{} } -func (m *Query_Filter) String() string { return proto.CompactTextString(m) } -func (*Query_Filter) ProtoMessage() {} +func (m *Query_Filter) Reset() { *m = Query_Filter{} } +func (m *Query_Filter) String() string { return proto.CompactTextString(m) } +func (*Query_Filter) ProtoMessage() {} +func (*Query_Filter) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15, 0} } func (m *Query_Filter) GetOp() Query_Filter_Operator { if m != nil && m.Op != nil { @@ -1566,9 +1651,10 @@ type Query_Order struct { XXX_unrecognized []byte `json:"-"` } -func (m *Query_Order) Reset() { *m = Query_Order{} } -func (m *Query_Order) String() string { return proto.CompactTextString(m) } -func (*Query_Order) ProtoMessage() {} +func (m *Query_Order) Reset() { *m = Query_Order{} } +func (m *Query_Order) String() string { return proto.CompactTextString(m) } +func (*Query_Order) ProtoMessage() {} +func (*Query_Order) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15, 1} } const Default_Query_Order_Direction Query_Order_Direction = Query_Order_ASCENDING @@ -1587,21 +1673,22 @@ func (m *Query_Order) GetDirection() Query_Order_Direction { } type CompiledQuery struct { - Primaryscan *CompiledQuery_PrimaryScan `protobuf:"group,1,req,name=PrimaryScan" json:"primaryscan,omitempty"` - Mergejoinscan []*CompiledQuery_MergeJoinScan `protobuf:"group,7,rep,name=MergeJoinScan" json:"mergejoinscan,omitempty"` - IndexDef *Index `protobuf:"bytes,21,opt,name=index_def" json:"index_def,omitempty"` + Primaryscan *CompiledQuery_PrimaryScan `protobuf:"group,1,req,name=PrimaryScan,json=primaryscan" json:"primaryscan,omitempty"` + Mergejoinscan []*CompiledQuery_MergeJoinScan `protobuf:"group,7,rep,name=MergeJoinScan,json=mergejoinscan" json:"mergejoinscan,omitempty"` + IndexDef *Index `protobuf:"bytes,21,opt,name=index_def,json=indexDef" json:"index_def,omitempty"` Offset *int32 `protobuf:"varint,10,opt,name=offset,def=0" json:"offset,omitempty"` Limit *int32 `protobuf:"varint,11,opt,name=limit" json:"limit,omitempty"` - KeysOnly *bool `protobuf:"varint,12,req,name=keys_only" json:"keys_only,omitempty"` - PropertyName []string `protobuf:"bytes,24,rep,name=property_name" json:"property_name,omitempty"` - DistinctInfixSize *int32 `protobuf:"varint,25,opt,name=distinct_infix_size" json:"distinct_infix_size,omitempty"` - Entityfilter *CompiledQuery_EntityFilter `protobuf:"group,13,opt,name=EntityFilter" json:"entityfilter,omitempty"` + KeysOnly *bool `protobuf:"varint,12,req,name=keys_only,json=keysOnly" json:"keys_only,omitempty"` + PropertyName []string `protobuf:"bytes,24,rep,name=property_name,json=propertyName" json:"property_name,omitempty"` + DistinctInfixSize *int32 `protobuf:"varint,25,opt,name=distinct_infix_size,json=distinctInfixSize" json:"distinct_infix_size,omitempty"` + Entityfilter *CompiledQuery_EntityFilter `protobuf:"group,13,opt,name=EntityFilter,json=entityfilter" json:"entityfilter,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *CompiledQuery) Reset() { *m = CompiledQuery{} } -func (m *CompiledQuery) String() string { return proto.CompactTextString(m) } -func (*CompiledQuery) ProtoMessage() {} +func (m *CompiledQuery) Reset() { *m = CompiledQuery{} } +func (m *CompiledQuery) String() string { return proto.CompactTextString(m) } +func (*CompiledQuery) ProtoMessage() {} +func (*CompiledQuery) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } const Default_CompiledQuery_Offset int32 = 0 @@ -1669,20 +1756,21 @@ func (m *CompiledQuery) GetEntityfilter() *CompiledQuery_EntityFilter { } type CompiledQuery_PrimaryScan struct { - IndexName *string `protobuf:"bytes,2,opt,name=index_name" json:"index_name,omitempty"` - StartKey *string `protobuf:"bytes,3,opt,name=start_key" json:"start_key,omitempty"` - StartInclusive *bool `protobuf:"varint,4,opt,name=start_inclusive" json:"start_inclusive,omitempty"` - EndKey *string `protobuf:"bytes,5,opt,name=end_key" json:"end_key,omitempty"` - EndInclusive *bool `protobuf:"varint,6,opt,name=end_inclusive" json:"end_inclusive,omitempty"` - StartPostfixValue []string `protobuf:"bytes,22,rep,name=start_postfix_value" json:"start_postfix_value,omitempty"` - EndPostfixValue []string `protobuf:"bytes,23,rep,name=end_postfix_value" json:"end_postfix_value,omitempty"` - EndUnappliedLogTimestampUs *int64 `protobuf:"varint,19,opt,name=end_unapplied_log_timestamp_us" json:"end_unapplied_log_timestamp_us,omitempty"` + IndexName *string `protobuf:"bytes,2,opt,name=index_name,json=indexName" json:"index_name,omitempty"` + StartKey *string `protobuf:"bytes,3,opt,name=start_key,json=startKey" json:"start_key,omitempty"` + StartInclusive *bool `protobuf:"varint,4,opt,name=start_inclusive,json=startInclusive" json:"start_inclusive,omitempty"` + EndKey *string `protobuf:"bytes,5,opt,name=end_key,json=endKey" json:"end_key,omitempty"` + EndInclusive *bool `protobuf:"varint,6,opt,name=end_inclusive,json=endInclusive" json:"end_inclusive,omitempty"` + StartPostfixValue []string `protobuf:"bytes,22,rep,name=start_postfix_value,json=startPostfixValue" json:"start_postfix_value,omitempty"` + EndPostfixValue []string `protobuf:"bytes,23,rep,name=end_postfix_value,json=endPostfixValue" json:"end_postfix_value,omitempty"` + EndUnappliedLogTimestampUs *int64 `protobuf:"varint,19,opt,name=end_unapplied_log_timestamp_us,json=endUnappliedLogTimestampUs" json:"end_unapplied_log_timestamp_us,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *CompiledQuery_PrimaryScan) Reset() { *m = CompiledQuery_PrimaryScan{} } -func (m *CompiledQuery_PrimaryScan) String() string { return proto.CompactTextString(m) } -func (*CompiledQuery_PrimaryScan) ProtoMessage() {} +func (m *CompiledQuery_PrimaryScan) Reset() { *m = CompiledQuery_PrimaryScan{} } +func (m *CompiledQuery_PrimaryScan) String() string { return proto.CompactTextString(m) } +func (*CompiledQuery_PrimaryScan) ProtoMessage() {} +func (*CompiledQuery_PrimaryScan) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16, 0} } func (m *CompiledQuery_PrimaryScan) GetIndexName() string { if m != nil && m.IndexName != nil { @@ -1741,15 +1829,16 @@ func (m *CompiledQuery_PrimaryScan) GetEndUnappliedLogTimestampUs() int64 { } type CompiledQuery_MergeJoinScan struct { - IndexName *string `protobuf:"bytes,8,req,name=index_name" json:"index_name,omitempty"` - PrefixValue []string `protobuf:"bytes,9,rep,name=prefix_value" json:"prefix_value,omitempty"` - ValuePrefix *bool `protobuf:"varint,20,opt,name=value_prefix,def=0" json:"value_prefix,omitempty"` + IndexName *string `protobuf:"bytes,8,req,name=index_name,json=indexName" json:"index_name,omitempty"` + PrefixValue []string `protobuf:"bytes,9,rep,name=prefix_value,json=prefixValue" json:"prefix_value,omitempty"` + ValuePrefix *bool `protobuf:"varint,20,opt,name=value_prefix,json=valuePrefix,def=0" json:"value_prefix,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *CompiledQuery_MergeJoinScan) Reset() { *m = CompiledQuery_MergeJoinScan{} } -func (m *CompiledQuery_MergeJoinScan) String() string { return proto.CompactTextString(m) } -func (*CompiledQuery_MergeJoinScan) ProtoMessage() {} +func (m *CompiledQuery_MergeJoinScan) Reset() { *m = CompiledQuery_MergeJoinScan{} } +func (m *CompiledQuery_MergeJoinScan) String() string { return proto.CompactTextString(m) } +func (*CompiledQuery_MergeJoinScan) ProtoMessage() {} +func (*CompiledQuery_MergeJoinScan) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16, 1} } const Default_CompiledQuery_MergeJoinScan_ValuePrefix bool = false @@ -1781,9 +1870,10 @@ type CompiledQuery_EntityFilter struct { XXX_unrecognized []byte `json:"-"` } -func (m *CompiledQuery_EntityFilter) Reset() { *m = CompiledQuery_EntityFilter{} } -func (m *CompiledQuery_EntityFilter) String() string { return proto.CompactTextString(m) } -func (*CompiledQuery_EntityFilter) ProtoMessage() {} +func (m *CompiledQuery_EntityFilter) Reset() { *m = CompiledQuery_EntityFilter{} } +func (m *CompiledQuery_EntityFilter) String() string { return proto.CompactTextString(m) } +func (*CompiledQuery_EntityFilter) ProtoMessage() {} +func (*CompiledQuery_EntityFilter) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16, 2} } const Default_CompiledQuery_EntityFilter_Distinct bool = false @@ -1809,13 +1899,14 @@ func (m *CompiledQuery_EntityFilter) GetAncestor() *Reference { } type CompiledCursor struct { - Position *CompiledCursor_Position `protobuf:"group,2,opt,name=Position" json:"position,omitempty"` + Position *CompiledCursor_Position `protobuf:"group,2,opt,name=Position,json=position" json:"position,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *CompiledCursor) Reset() { *m = CompiledCursor{} } -func (m *CompiledCursor) String() string { return proto.CompactTextString(m) } -func (*CompiledCursor) ProtoMessage() {} +func (m *CompiledCursor) Reset() { *m = CompiledCursor{} } +func (m *CompiledCursor) String() string { return proto.CompactTextString(m) } +func (*CompiledCursor) ProtoMessage() {} +func (*CompiledCursor) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } func (m *CompiledCursor) GetPosition() *CompiledCursor_Position { if m != nil { @@ -1825,16 +1916,17 @@ func (m *CompiledCursor) GetPosition() *CompiledCursor_Position { } type CompiledCursor_Position struct { - StartKey *string `protobuf:"bytes,27,opt,name=start_key" json:"start_key,omitempty"` - Indexvalue []*CompiledCursor_Position_IndexValue `protobuf:"group,29,rep,name=IndexValue" json:"indexvalue,omitempty"` + StartKey *string `protobuf:"bytes,27,opt,name=start_key,json=startKey" json:"start_key,omitempty"` + Indexvalue []*CompiledCursor_Position_IndexValue `protobuf:"group,29,rep,name=IndexValue,json=indexvalue" json:"indexvalue,omitempty"` Key *Reference `protobuf:"bytes,32,opt,name=key" json:"key,omitempty"` - StartInclusive *bool `protobuf:"varint,28,opt,name=start_inclusive,def=1" json:"start_inclusive,omitempty"` + StartInclusive *bool `protobuf:"varint,28,opt,name=start_inclusive,json=startInclusive,def=1" json:"start_inclusive,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *CompiledCursor_Position) Reset() { *m = CompiledCursor_Position{} } -func (m *CompiledCursor_Position) String() string { return proto.CompactTextString(m) } -func (*CompiledCursor_Position) ProtoMessage() {} +func (m *CompiledCursor_Position) Reset() { *m = CompiledCursor_Position{} } +func (m *CompiledCursor_Position) String() string { return proto.CompactTextString(m) } +func (*CompiledCursor_Position) ProtoMessage() {} +func (*CompiledCursor_Position) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17, 0} } const Default_CompiledCursor_Position_StartInclusive bool = true @@ -1875,6 +1967,9 @@ type CompiledCursor_Position_IndexValue struct { func (m *CompiledCursor_Position_IndexValue) Reset() { *m = CompiledCursor_Position_IndexValue{} } func (m *CompiledCursor_Position_IndexValue) String() string { return proto.CompactTextString(m) } func (*CompiledCursor_Position_IndexValue) ProtoMessage() {} +func (*CompiledCursor_Position_IndexValue) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{17, 0, 0} +} func (m *CompiledCursor_Position_IndexValue) GetProperty() string { if m != nil && m.Property != nil { @@ -1896,9 +1991,10 @@ type Cursor struct { XXX_unrecognized []byte `json:"-"` } -func (m *Cursor) Reset() { *m = Cursor{} } -func (m *Cursor) String() string { return proto.CompactTextString(m) } -func (*Cursor) ProtoMessage() {} +func (m *Cursor) Reset() { *m = Cursor{} } +func (m *Cursor) String() string { return proto.CompactTextString(m) } +func (*Cursor) ProtoMessage() {} +func (*Cursor) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } func (m *Cursor) GetCursor() uint64 { if m != nil && m.Cursor != nil { @@ -1918,24 +2014,26 @@ type Error struct { XXX_unrecognized []byte `json:"-"` } -func (m *Error) Reset() { *m = Error{} } -func (m *Error) String() string { return proto.CompactTextString(m) } -func (*Error) ProtoMessage() {} +func (m *Error) Reset() { *m = Error{} } +func (m *Error) String() string { return proto.CompactTextString(m) } +func (*Error) ProtoMessage() {} +func (*Error) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } type Cost struct { - IndexWrites *int32 `protobuf:"varint,1,opt,name=index_writes" json:"index_writes,omitempty"` - IndexWriteBytes *int32 `protobuf:"varint,2,opt,name=index_write_bytes" json:"index_write_bytes,omitempty"` - EntityWrites *int32 `protobuf:"varint,3,opt,name=entity_writes" json:"entity_writes,omitempty"` - EntityWriteBytes *int32 `protobuf:"varint,4,opt,name=entity_write_bytes" json:"entity_write_bytes,omitempty"` - Commitcost *Cost_CommitCost `protobuf:"group,5,opt,name=CommitCost" json:"commitcost,omitempty"` - ApproximateStorageDelta *int32 `protobuf:"varint,8,opt,name=approximate_storage_delta" json:"approximate_storage_delta,omitempty"` - IdSequenceUpdates *int32 `protobuf:"varint,9,opt,name=id_sequence_updates" json:"id_sequence_updates,omitempty"` + IndexWrites *int32 `protobuf:"varint,1,opt,name=index_writes,json=indexWrites" json:"index_writes,omitempty"` + IndexWriteBytes *int32 `protobuf:"varint,2,opt,name=index_write_bytes,json=indexWriteBytes" json:"index_write_bytes,omitempty"` + EntityWrites *int32 `protobuf:"varint,3,opt,name=entity_writes,json=entityWrites" json:"entity_writes,omitempty"` + EntityWriteBytes *int32 `protobuf:"varint,4,opt,name=entity_write_bytes,json=entityWriteBytes" json:"entity_write_bytes,omitempty"` + Commitcost *Cost_CommitCost `protobuf:"group,5,opt,name=CommitCost,json=commitcost" json:"commitcost,omitempty"` + ApproximateStorageDelta *int32 `protobuf:"varint,8,opt,name=approximate_storage_delta,json=approximateStorageDelta" json:"approximate_storage_delta,omitempty"` + IdSequenceUpdates *int32 `protobuf:"varint,9,opt,name=id_sequence_updates,json=idSequenceUpdates" json:"id_sequence_updates,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *Cost) Reset() { *m = Cost{} } -func (m *Cost) String() string { return proto.CompactTextString(m) } -func (*Cost) ProtoMessage() {} +func (m *Cost) Reset() { *m = Cost{} } +func (m *Cost) String() string { return proto.CompactTextString(m) } +func (*Cost) ProtoMessage() {} +func (*Cost) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } func (m *Cost) GetIndexWrites() int32 { if m != nil && m.IndexWrites != nil { @@ -1987,14 +2085,15 @@ func (m *Cost) GetIdSequenceUpdates() int32 { } type Cost_CommitCost struct { - RequestedEntityPuts *int32 `protobuf:"varint,6,opt,name=requested_entity_puts" json:"requested_entity_puts,omitempty"` - RequestedEntityDeletes *int32 `protobuf:"varint,7,opt,name=requested_entity_deletes" json:"requested_entity_deletes,omitempty"` + RequestedEntityPuts *int32 `protobuf:"varint,6,opt,name=requested_entity_puts,json=requestedEntityPuts" json:"requested_entity_puts,omitempty"` + RequestedEntityDeletes *int32 `protobuf:"varint,7,opt,name=requested_entity_deletes,json=requestedEntityDeletes" json:"requested_entity_deletes,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *Cost_CommitCost) Reset() { *m = Cost_CommitCost{} } -func (m *Cost_CommitCost) String() string { return proto.CompactTextString(m) } -func (*Cost_CommitCost) ProtoMessage() {} +func (m *Cost_CommitCost) Reset() { *m = Cost_CommitCost{} } +func (m *Cost_CommitCost) String() string { return proto.CompactTextString(m) } +func (*Cost_CommitCost) ProtoMessage() {} +func (*Cost_CommitCost) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20, 0} } func (m *Cost_CommitCost) GetRequestedEntityPuts() int32 { if m != nil && m.RequestedEntityPuts != nil { @@ -2014,15 +2113,16 @@ type GetRequest struct { Header *InternalHeader `protobuf:"bytes,6,opt,name=header" json:"header,omitempty"` Key []*Reference `protobuf:"bytes,1,rep,name=key" json:"key,omitempty"` Transaction *Transaction `protobuf:"bytes,2,opt,name=transaction" json:"transaction,omitempty"` - FailoverMs *int64 `protobuf:"varint,3,opt,name=failover_ms" json:"failover_ms,omitempty"` + FailoverMs *int64 `protobuf:"varint,3,opt,name=failover_ms,json=failoverMs" json:"failover_ms,omitempty"` Strong *bool `protobuf:"varint,4,opt,name=strong" json:"strong,omitempty"` - AllowDeferred *bool `protobuf:"varint,5,opt,name=allow_deferred,def=0" json:"allow_deferred,omitempty"` + AllowDeferred *bool `protobuf:"varint,5,opt,name=allow_deferred,json=allowDeferred,def=0" json:"allow_deferred,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *GetRequest) Reset() { *m = GetRequest{} } -func (m *GetRequest) String() string { return proto.CompactTextString(m) } -func (*GetRequest) ProtoMessage() {} +func (m *GetRequest) Reset() { *m = GetRequest{} } +func (m *GetRequest) String() string { return proto.CompactTextString(m) } +func (*GetRequest) ProtoMessage() {} +func (*GetRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } const Default_GetRequest_AllowDeferred bool = false @@ -2069,15 +2169,16 @@ func (m *GetRequest) GetAllowDeferred() bool { } type GetResponse struct { - Entity []*GetResponse_Entity `protobuf:"group,1,rep,name=Entity" json:"entity,omitempty"` + Entity []*GetResponse_Entity `protobuf:"group,1,rep,name=Entity,json=entity" json:"entity,omitempty"` Deferred []*Reference `protobuf:"bytes,5,rep,name=deferred" json:"deferred,omitempty"` - InOrder *bool `protobuf:"varint,6,opt,name=in_order,def=1" json:"in_order,omitempty"` + InOrder *bool `protobuf:"varint,6,opt,name=in_order,json=inOrder,def=1" json:"in_order,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *GetResponse) Reset() { *m = GetResponse{} } -func (m *GetResponse) String() string { return proto.CompactTextString(m) } -func (*GetResponse) ProtoMessage() {} +func (m *GetResponse) Reset() { *m = GetResponse{} } +func (m *GetResponse) String() string { return proto.CompactTextString(m) } +func (*GetResponse) ProtoMessage() {} +func (*GetResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } const Default_GetResponse_InOrder bool = true @@ -2109,9 +2210,10 @@ type GetResponse_Entity struct { XXX_unrecognized []byte `json:"-"` } -func (m *GetResponse_Entity) Reset() { *m = GetResponse_Entity{} } -func (m *GetResponse_Entity) String() string { return proto.CompactTextString(m) } -func (*GetResponse_Entity) ProtoMessage() {} +func (m *GetResponse_Entity) Reset() { *m = GetResponse_Entity{} } +func (m *GetResponse_Entity) String() string { return proto.CompactTextString(m) } +func (*GetResponse_Entity) ProtoMessage() {} +func (*GetResponse_Entity) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22, 0} } func (m *GetResponse_Entity) GetEntity() *EntityProto { if m != nil { @@ -2138,18 +2240,19 @@ type PutRequest struct { Header *InternalHeader `protobuf:"bytes,11,opt,name=header" json:"header,omitempty"` Entity []*EntityProto `protobuf:"bytes,1,rep,name=entity" json:"entity,omitempty"` Transaction *Transaction `protobuf:"bytes,2,opt,name=transaction" json:"transaction,omitempty"` - CompositeIndex []*CompositeIndex `protobuf:"bytes,3,rep,name=composite_index" json:"composite_index,omitempty"` + CompositeIndex []*CompositeIndex `protobuf:"bytes,3,rep,name=composite_index,json=compositeIndex" json:"composite_index,omitempty"` Trusted *bool `protobuf:"varint,4,opt,name=trusted,def=0" json:"trusted,omitempty"` Force *bool `protobuf:"varint,7,opt,name=force,def=0" json:"force,omitempty"` - MarkChanges *bool `protobuf:"varint,8,opt,name=mark_changes,def=0" json:"mark_changes,omitempty"` + MarkChanges *bool `protobuf:"varint,8,opt,name=mark_changes,json=markChanges,def=0" json:"mark_changes,omitempty"` Snapshot []*Snapshot `protobuf:"bytes,9,rep,name=snapshot" json:"snapshot,omitempty"` - AutoIdPolicy *PutRequest_AutoIdPolicy `protobuf:"varint,10,opt,name=auto_id_policy,enum=appengine.PutRequest_AutoIdPolicy,def=0" json:"auto_id_policy,omitempty"` + AutoIdPolicy *PutRequest_AutoIdPolicy `protobuf:"varint,10,opt,name=auto_id_policy,json=autoIdPolicy,enum=appengine.PutRequest_AutoIdPolicy,def=0" json:"auto_id_policy,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *PutRequest) Reset() { *m = PutRequest{} } -func (m *PutRequest) String() string { return proto.CompactTextString(m) } -func (*PutRequest) ProtoMessage() {} +func (m *PutRequest) Reset() { *m = PutRequest{} } +func (m *PutRequest) String() string { return proto.CompactTextString(m) } +func (*PutRequest) ProtoMessage() {} +func (*PutRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } const Default_PutRequest_Trusted bool = false const Default_PutRequest_Force bool = false @@ -2226,9 +2329,10 @@ type PutResponse struct { XXX_unrecognized []byte `json:"-"` } -func (m *PutResponse) Reset() { *m = PutResponse{} } -func (m *PutResponse) String() string { return proto.CompactTextString(m) } -func (*PutResponse) ProtoMessage() {} +func (m *PutResponse) Reset() { *m = PutResponse{} } +func (m *PutResponse) String() string { return proto.CompactTextString(m) } +func (*PutResponse) ProtoMessage() {} +func (*PutResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } func (m *PutResponse) GetKey() []*Reference { if m != nil { @@ -2254,15 +2358,16 @@ func (m *PutResponse) GetVersion() []int64 { type TouchRequest struct { Header *InternalHeader `protobuf:"bytes,10,opt,name=header" json:"header,omitempty"` Key []*Reference `protobuf:"bytes,1,rep,name=key" json:"key,omitempty"` - CompositeIndex []*CompositeIndex `protobuf:"bytes,2,rep,name=composite_index" json:"composite_index,omitempty"` + CompositeIndex []*CompositeIndex `protobuf:"bytes,2,rep,name=composite_index,json=compositeIndex" json:"composite_index,omitempty"` Force *bool `protobuf:"varint,3,opt,name=force,def=0" json:"force,omitempty"` Snapshot []*Snapshot `protobuf:"bytes,9,rep,name=snapshot" json:"snapshot,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *TouchRequest) Reset() { *m = TouchRequest{} } -func (m *TouchRequest) String() string { return proto.CompactTextString(m) } -func (*TouchRequest) ProtoMessage() {} +func (m *TouchRequest) Reset() { *m = TouchRequest{} } +func (m *TouchRequest) String() string { return proto.CompactTextString(m) } +func (*TouchRequest) ProtoMessage() {} +func (*TouchRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } const Default_TouchRequest_Force bool = false @@ -2306,9 +2411,10 @@ type TouchResponse struct { XXX_unrecognized []byte `json:"-"` } -func (m *TouchResponse) Reset() { *m = TouchResponse{} } -func (m *TouchResponse) String() string { return proto.CompactTextString(m) } -func (*TouchResponse) ProtoMessage() {} +func (m *TouchResponse) Reset() { *m = TouchResponse{} } +func (m *TouchResponse) String() string { return proto.CompactTextString(m) } +func (*TouchResponse) ProtoMessage() {} +func (*TouchResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } func (m *TouchResponse) GetCost() *Cost { if m != nil { @@ -2323,14 +2429,15 @@ type DeleteRequest struct { Transaction *Transaction `protobuf:"bytes,5,opt,name=transaction" json:"transaction,omitempty"` Trusted *bool `protobuf:"varint,4,opt,name=trusted,def=0" json:"trusted,omitempty"` Force *bool `protobuf:"varint,7,opt,name=force,def=0" json:"force,omitempty"` - MarkChanges *bool `protobuf:"varint,8,opt,name=mark_changes,def=0" json:"mark_changes,omitempty"` + MarkChanges *bool `protobuf:"varint,8,opt,name=mark_changes,json=markChanges,def=0" json:"mark_changes,omitempty"` Snapshot []*Snapshot `protobuf:"bytes,9,rep,name=snapshot" json:"snapshot,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *DeleteRequest) Reset() { *m = DeleteRequest{} } -func (m *DeleteRequest) String() string { return proto.CompactTextString(m) } -func (*DeleteRequest) ProtoMessage() {} +func (m *DeleteRequest) Reset() { *m = DeleteRequest{} } +func (m *DeleteRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteRequest) ProtoMessage() {} +func (*DeleteRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } const Default_DeleteRequest_Trusted bool = false const Default_DeleteRequest_Force bool = false @@ -2391,9 +2498,10 @@ type DeleteResponse struct { XXX_unrecognized []byte `json:"-"` } -func (m *DeleteResponse) Reset() { *m = DeleteResponse{} } -func (m *DeleteResponse) String() string { return proto.CompactTextString(m) } -func (*DeleteResponse) ProtoMessage() {} +func (m *DeleteResponse) Reset() { *m = DeleteResponse{} } +func (m *DeleteResponse) String() string { return proto.CompactTextString(m) } +func (*DeleteResponse) ProtoMessage() {} +func (*DeleteResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } func (m *DeleteResponse) GetCost() *Cost { if m != nil { @@ -2418,9 +2526,10 @@ type NextRequest struct { XXX_unrecognized []byte `json:"-"` } -func (m *NextRequest) Reset() { *m = NextRequest{} } -func (m *NextRequest) String() string { return proto.CompactTextString(m) } -func (*NextRequest) ProtoMessage() {} +func (m *NextRequest) Reset() { *m = NextRequest{} } +func (m *NextRequest) String() string { return proto.CompactTextString(m) } +func (*NextRequest) ProtoMessage() {} +func (*NextRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } const Default_NextRequest_Offset int32 = 0 const Default_NextRequest_Compile bool = false @@ -2463,21 +2572,22 @@ func (m *NextRequest) GetCompile() bool { type QueryResult struct { Cursor *Cursor `protobuf:"bytes,1,opt,name=cursor" json:"cursor,omitempty"` Result []*EntityProto `protobuf:"bytes,2,rep,name=result" json:"result,omitempty"` - SkippedResults *int32 `protobuf:"varint,7,opt,name=skipped_results" json:"skipped_results,omitempty"` - MoreResults *bool `protobuf:"varint,3,req,name=more_results" json:"more_results,omitempty"` - KeysOnly *bool `protobuf:"varint,4,opt,name=keys_only" json:"keys_only,omitempty"` - IndexOnly *bool `protobuf:"varint,9,opt,name=index_only" json:"index_only,omitempty"` - SmallOps *bool `protobuf:"varint,10,opt,name=small_ops" json:"small_ops,omitempty"` - CompiledQuery *CompiledQuery `protobuf:"bytes,5,opt,name=compiled_query" json:"compiled_query,omitempty"` - CompiledCursor *CompiledCursor `protobuf:"bytes,6,opt,name=compiled_cursor" json:"compiled_cursor,omitempty"` + SkippedResults *int32 `protobuf:"varint,7,opt,name=skipped_results,json=skippedResults" json:"skipped_results,omitempty"` + MoreResults *bool `protobuf:"varint,3,req,name=more_results,json=moreResults" json:"more_results,omitempty"` + KeysOnly *bool `protobuf:"varint,4,opt,name=keys_only,json=keysOnly" json:"keys_only,omitempty"` + IndexOnly *bool `protobuf:"varint,9,opt,name=index_only,json=indexOnly" json:"index_only,omitempty"` + SmallOps *bool `protobuf:"varint,10,opt,name=small_ops,json=smallOps" json:"small_ops,omitempty"` + CompiledQuery *CompiledQuery `protobuf:"bytes,5,opt,name=compiled_query,json=compiledQuery" json:"compiled_query,omitempty"` + CompiledCursor *CompiledCursor `protobuf:"bytes,6,opt,name=compiled_cursor,json=compiledCursor" json:"compiled_cursor,omitempty"` Index []*CompositeIndex `protobuf:"bytes,8,rep,name=index" json:"index,omitempty"` Version []int64 `protobuf:"varint,11,rep,name=version" json:"version,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *QueryResult) Reset() { *m = QueryResult{} } -func (m *QueryResult) String() string { return proto.CompactTextString(m) } -func (*QueryResult) ProtoMessage() {} +func (m *QueryResult) Reset() { *m = QueryResult{} } +func (m *QueryResult) String() string { return proto.CompactTextString(m) } +func (*QueryResult) ProtoMessage() {} +func (*QueryResult) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } func (m *QueryResult) GetCursor() *Cursor { if m != nil { @@ -2558,16 +2668,17 @@ func (m *QueryResult) GetVersion() []int64 { type AllocateIdsRequest struct { Header *InternalHeader `protobuf:"bytes,4,opt,name=header" json:"header,omitempty"` - ModelKey *Reference `protobuf:"bytes,1,opt,name=model_key" json:"model_key,omitempty"` + ModelKey *Reference `protobuf:"bytes,1,opt,name=model_key,json=modelKey" json:"model_key,omitempty"` Size *int64 `protobuf:"varint,2,opt,name=size" json:"size,omitempty"` Max *int64 `protobuf:"varint,3,opt,name=max" json:"max,omitempty"` Reserve []*Reference `protobuf:"bytes,5,rep,name=reserve" json:"reserve,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *AllocateIdsRequest) Reset() { *m = AllocateIdsRequest{} } -func (m *AllocateIdsRequest) String() string { return proto.CompactTextString(m) } -func (*AllocateIdsRequest) ProtoMessage() {} +func (m *AllocateIdsRequest) Reset() { *m = AllocateIdsRequest{} } +func (m *AllocateIdsRequest) String() string { return proto.CompactTextString(m) } +func (*AllocateIdsRequest) ProtoMessage() {} +func (*AllocateIdsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{31} } func (m *AllocateIdsRequest) GetHeader() *InternalHeader { if m != nil { @@ -2611,9 +2722,10 @@ type AllocateIdsResponse struct { XXX_unrecognized []byte `json:"-"` } -func (m *AllocateIdsResponse) Reset() { *m = AllocateIdsResponse{} } -func (m *AllocateIdsResponse) String() string { return proto.CompactTextString(m) } -func (*AllocateIdsResponse) ProtoMessage() {} +func (m *AllocateIdsResponse) Reset() { *m = AllocateIdsResponse{} } +func (m *AllocateIdsResponse) String() string { return proto.CompactTextString(m) } +func (*AllocateIdsResponse) ProtoMessage() {} +func (*AllocateIdsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{32} } func (m *AllocateIdsResponse) GetStart() int64 { if m != nil && m.Start != nil { @@ -2641,9 +2753,10 @@ type CompositeIndices struct { XXX_unrecognized []byte `json:"-"` } -func (m *CompositeIndices) Reset() { *m = CompositeIndices{} } -func (m *CompositeIndices) String() string { return proto.CompactTextString(m) } -func (*CompositeIndices) ProtoMessage() {} +func (m *CompositeIndices) Reset() { *m = CompositeIndices{} } +func (m *CompositeIndices) String() string { return proto.CompactTextString(m) } +func (*CompositeIndices) ProtoMessage() {} +func (*CompositeIndices) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{33} } func (m *CompositeIndices) GetIndex() []*CompositeIndex { if m != nil { @@ -2659,9 +2772,10 @@ type AddActionsRequest struct { XXX_unrecognized []byte `json:"-"` } -func (m *AddActionsRequest) Reset() { *m = AddActionsRequest{} } -func (m *AddActionsRequest) String() string { return proto.CompactTextString(m) } -func (*AddActionsRequest) ProtoMessage() {} +func (m *AddActionsRequest) Reset() { *m = AddActionsRequest{} } +func (m *AddActionsRequest) String() string { return proto.CompactTextString(m) } +func (*AddActionsRequest) ProtoMessage() {} +func (*AddActionsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{34} } func (m *AddActionsRequest) GetHeader() *InternalHeader { if m != nil { @@ -2688,22 +2802,28 @@ type AddActionsResponse struct { XXX_unrecognized []byte `json:"-"` } -func (m *AddActionsResponse) Reset() { *m = AddActionsResponse{} } -func (m *AddActionsResponse) String() string { return proto.CompactTextString(m) } -func (*AddActionsResponse) ProtoMessage() {} +func (m *AddActionsResponse) Reset() { *m = AddActionsResponse{} } +func (m *AddActionsResponse) String() string { return proto.CompactTextString(m) } +func (*AddActionsResponse) ProtoMessage() {} +func (*AddActionsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{35} } type BeginTransactionRequest struct { - Header *InternalHeader `protobuf:"bytes,3,opt,name=header" json:"header,omitempty"` - App *string `protobuf:"bytes,1,req,name=app" json:"app,omitempty"` - AllowMultipleEg *bool `protobuf:"varint,2,opt,name=allow_multiple_eg,def=0" json:"allow_multiple_eg,omitempty"` - XXX_unrecognized []byte `json:"-"` + Header *InternalHeader `protobuf:"bytes,3,opt,name=header" json:"header,omitempty"` + App *string `protobuf:"bytes,1,req,name=app" json:"app,omitempty"` + AllowMultipleEg *bool `protobuf:"varint,2,opt,name=allow_multiple_eg,json=allowMultipleEg,def=0" json:"allow_multiple_eg,omitempty"` + DatabaseId *string `protobuf:"bytes,4,opt,name=database_id,json=databaseId" json:"database_id,omitempty"` + Mode *BeginTransactionRequest_TransactionMode `protobuf:"varint,5,opt,name=mode,enum=appengine.BeginTransactionRequest_TransactionMode,def=0" json:"mode,omitempty"` + PreviousTransaction *Transaction `protobuf:"bytes,7,opt,name=previous_transaction,json=previousTransaction" json:"previous_transaction,omitempty"` + XXX_unrecognized []byte `json:"-"` } -func (m *BeginTransactionRequest) Reset() { *m = BeginTransactionRequest{} } -func (m *BeginTransactionRequest) String() string { return proto.CompactTextString(m) } -func (*BeginTransactionRequest) ProtoMessage() {} +func (m *BeginTransactionRequest) Reset() { *m = BeginTransactionRequest{} } +func (m *BeginTransactionRequest) String() string { return proto.CompactTextString(m) } +func (*BeginTransactionRequest) ProtoMessage() {} +func (*BeginTransactionRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{36} } const Default_BeginTransactionRequest_AllowMultipleEg bool = false +const Default_BeginTransactionRequest_Mode BeginTransactionRequest_TransactionMode = BeginTransactionRequest_UNKNOWN func (m *BeginTransactionRequest) GetHeader() *InternalHeader { if m != nil { @@ -2726,15 +2846,37 @@ func (m *BeginTransactionRequest) GetAllowMultipleEg() bool { return Default_BeginTransactionRequest_AllowMultipleEg } +func (m *BeginTransactionRequest) GetDatabaseId() string { + if m != nil && m.DatabaseId != nil { + return *m.DatabaseId + } + return "" +} + +func (m *BeginTransactionRequest) GetMode() BeginTransactionRequest_TransactionMode { + if m != nil && m.Mode != nil { + return *m.Mode + } + return Default_BeginTransactionRequest_Mode +} + +func (m *BeginTransactionRequest) GetPreviousTransaction() *Transaction { + if m != nil { + return m.PreviousTransaction + } + return nil +} + type CommitResponse struct { Cost *Cost `protobuf:"bytes,1,opt,name=cost" json:"cost,omitempty"` - Version []*CommitResponse_Version `protobuf:"group,3,rep,name=Version" json:"version,omitempty"` + Version []*CommitResponse_Version `protobuf:"group,3,rep,name=Version,json=version" json:"version,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *CommitResponse) Reset() { *m = CommitResponse{} } -func (m *CommitResponse) String() string { return proto.CompactTextString(m) } -func (*CommitResponse) ProtoMessage() {} +func (m *CommitResponse) Reset() { *m = CommitResponse{} } +func (m *CommitResponse) String() string { return proto.CompactTextString(m) } +func (*CommitResponse) ProtoMessage() {} +func (*CommitResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{37} } func (m *CommitResponse) GetCost() *Cost { if m != nil { @@ -2751,14 +2893,15 @@ func (m *CommitResponse) GetVersion() []*CommitResponse_Version { } type CommitResponse_Version struct { - RootEntityKey *Reference `protobuf:"bytes,4,req,name=root_entity_key" json:"root_entity_key,omitempty"` + RootEntityKey *Reference `protobuf:"bytes,4,req,name=root_entity_key,json=rootEntityKey" json:"root_entity_key,omitempty"` Version *int64 `protobuf:"varint,5,req,name=version" json:"version,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *CommitResponse_Version) Reset() { *m = CommitResponse_Version{} } -func (m *CommitResponse_Version) String() string { return proto.CompactTextString(m) } -func (*CommitResponse_Version) ProtoMessage() {} +func (m *CommitResponse_Version) Reset() { *m = CommitResponse_Version{} } +func (m *CommitResponse_Version) String() string { return proto.CompactTextString(m) } +func (*CommitResponse_Version) ProtoMessage() {} +func (*CommitResponse_Version) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{37, 0} } func (m *CommitResponse_Version) GetRootEntityKey() *Reference { if m != nil { @@ -2775,4 +2918,327 @@ func (m *CommitResponse_Version) GetVersion() int64 { } func init() { + proto.RegisterType((*Action)(nil), "appengine.Action") + proto.RegisterType((*PropertyValue)(nil), "appengine.PropertyValue") + proto.RegisterType((*PropertyValue_PointValue)(nil), "appengine.PropertyValue.PointValue") + proto.RegisterType((*PropertyValue_UserValue)(nil), "appengine.PropertyValue.UserValue") + proto.RegisterType((*PropertyValue_ReferenceValue)(nil), "appengine.PropertyValue.ReferenceValue") + proto.RegisterType((*PropertyValue_ReferenceValue_PathElement)(nil), "appengine.PropertyValue.ReferenceValue.PathElement") + proto.RegisterType((*Property)(nil), "appengine.Property") + proto.RegisterType((*Path)(nil), "appengine.Path") + proto.RegisterType((*Path_Element)(nil), "appengine.Path.Element") + proto.RegisterType((*Reference)(nil), "appengine.Reference") + proto.RegisterType((*User)(nil), "appengine.User") + proto.RegisterType((*EntityProto)(nil), "appengine.EntityProto") + proto.RegisterType((*CompositeProperty)(nil), "appengine.CompositeProperty") + proto.RegisterType((*Index)(nil), "appengine.Index") + proto.RegisterType((*Index_Property)(nil), "appengine.Index.Property") + proto.RegisterType((*CompositeIndex)(nil), "appengine.CompositeIndex") + proto.RegisterType((*IndexPostfix)(nil), "appengine.IndexPostfix") + proto.RegisterType((*IndexPostfix_IndexValue)(nil), "appengine.IndexPostfix.IndexValue") + proto.RegisterType((*IndexPosition)(nil), "appengine.IndexPosition") + proto.RegisterType((*Snapshot)(nil), "appengine.Snapshot") + proto.RegisterType((*InternalHeader)(nil), "appengine.InternalHeader") + proto.RegisterType((*Transaction)(nil), "appengine.Transaction") + proto.RegisterType((*Query)(nil), "appengine.Query") + proto.RegisterType((*Query_Filter)(nil), "appengine.Query.Filter") + proto.RegisterType((*Query_Order)(nil), "appengine.Query.Order") + proto.RegisterType((*CompiledQuery)(nil), "appengine.CompiledQuery") + proto.RegisterType((*CompiledQuery_PrimaryScan)(nil), "appengine.CompiledQuery.PrimaryScan") + proto.RegisterType((*CompiledQuery_MergeJoinScan)(nil), "appengine.CompiledQuery.MergeJoinScan") + proto.RegisterType((*CompiledQuery_EntityFilter)(nil), "appengine.CompiledQuery.EntityFilter") + proto.RegisterType((*CompiledCursor)(nil), "appengine.CompiledCursor") + proto.RegisterType((*CompiledCursor_Position)(nil), "appengine.CompiledCursor.Position") + proto.RegisterType((*CompiledCursor_Position_IndexValue)(nil), "appengine.CompiledCursor.Position.IndexValue") + proto.RegisterType((*Cursor)(nil), "appengine.Cursor") + proto.RegisterType((*Error)(nil), "appengine.Error") + proto.RegisterType((*Cost)(nil), "appengine.Cost") + proto.RegisterType((*Cost_CommitCost)(nil), "appengine.Cost.CommitCost") + proto.RegisterType((*GetRequest)(nil), "appengine.GetRequest") + proto.RegisterType((*GetResponse)(nil), "appengine.GetResponse") + proto.RegisterType((*GetResponse_Entity)(nil), "appengine.GetResponse.Entity") + proto.RegisterType((*PutRequest)(nil), "appengine.PutRequest") + proto.RegisterType((*PutResponse)(nil), "appengine.PutResponse") + proto.RegisterType((*TouchRequest)(nil), "appengine.TouchRequest") + proto.RegisterType((*TouchResponse)(nil), "appengine.TouchResponse") + proto.RegisterType((*DeleteRequest)(nil), "appengine.DeleteRequest") + proto.RegisterType((*DeleteResponse)(nil), "appengine.DeleteResponse") + proto.RegisterType((*NextRequest)(nil), "appengine.NextRequest") + proto.RegisterType((*QueryResult)(nil), "appengine.QueryResult") + proto.RegisterType((*AllocateIdsRequest)(nil), "appengine.AllocateIdsRequest") + proto.RegisterType((*AllocateIdsResponse)(nil), "appengine.AllocateIdsResponse") + proto.RegisterType((*CompositeIndices)(nil), "appengine.CompositeIndices") + proto.RegisterType((*AddActionsRequest)(nil), "appengine.AddActionsRequest") + proto.RegisterType((*AddActionsResponse)(nil), "appengine.AddActionsResponse") + proto.RegisterType((*BeginTransactionRequest)(nil), "appengine.BeginTransactionRequest") + proto.RegisterType((*CommitResponse)(nil), "appengine.CommitResponse") + proto.RegisterType((*CommitResponse_Version)(nil), "appengine.CommitResponse.Version") +} + +func init() { + proto.RegisterFile("google.golang.org/appengine/internal/datastore/datastore_v3.proto", fileDescriptor0) +} + +var fileDescriptor0 = []byte{ + // 4156 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x5a, 0xcd, 0x73, 0xe3, 0x46, + 0x76, 0x37, 0xc1, 0xef, 0x47, 0x89, 0x82, 0x5a, 0xf3, 0xc1, 0xa1, 0x3f, 0x46, 0xc6, 0xac, 0x6d, + 0xd9, 0x6b, 0x73, 0x6c, 0xf9, 0x23, 0x5b, 0x4a, 0x76, 0x1d, 0x4a, 0xc4, 0x68, 0x90, 0xa1, 0x48, + 0xb9, 0x09, 0xd9, 0x9e, 0x5c, 0x50, 0x18, 0xa2, 0x29, 0x21, 0x43, 0x02, 0x30, 0x00, 0x6a, 0x46, + 0x93, 0xe4, 0x90, 0x4b, 0x2a, 0x55, 0x5b, 0xa9, 0x1c, 0x92, 0x4a, 0x25, 0xf9, 0x07, 0x72, 0xc8, + 0x39, 0x95, 0xaa, 0x54, 0xf6, 0x98, 0x5b, 0x0e, 0x7b, 0xc9, 0x31, 0x95, 0x73, 0xf2, 0x27, 0x24, + 0x39, 0xa4, 0xfa, 0x75, 0x03, 0x02, 0x28, 0x4a, 0x23, 0x6d, 0xf6, 0x90, 0x13, 0xd1, 0xef, 0xfd, + 0xba, 0xf1, 0xfa, 0xf5, 0xfb, 0x6c, 0x10, 0xba, 0xc7, 0xbe, 0x7f, 0x3c, 0x65, 0x9d, 0x63, 0x7f, + 0x6a, 0x7b, 0xc7, 0x1d, 0x3f, 0x3c, 0x7e, 0x68, 0x07, 0x01, 0xf3, 0x8e, 0x5d, 0x8f, 0x3d, 0x74, + 0xbd, 0x98, 0x85, 0x9e, 0x3d, 0x7d, 0xe8, 0xd8, 0xb1, 0x1d, 0xc5, 0x7e, 0xc8, 0xce, 0x9f, 0xac, + 0xd3, 0xcf, 0x3b, 0x41, 0xe8, 0xc7, 0x3e, 0xa9, 0xa7, 0x13, 0xb4, 0x1a, 0x54, 0xba, 0xe3, 0xd8, + 0xf5, 0x3d, 0xed, 0x1f, 0x2b, 0xb0, 0x7a, 0x18, 0xfa, 0x01, 0x0b, 0xe3, 0xb3, 0x6f, 0xed, 0xe9, + 0x9c, 0x91, 0x77, 0x00, 0x5c, 0x2f, 0xfe, 0xea, 0x0b, 0x1c, 0xb5, 0x0a, 0x9b, 0x85, 0xad, 0x22, + 0xcd, 0x50, 0x88, 0x06, 0x2b, 0xcf, 0x7c, 0x7f, 0xca, 0x6c, 0x4f, 0x20, 0x94, 0xcd, 0xc2, 0x56, + 0x8d, 0xe6, 0x68, 0x64, 0x13, 0x1a, 0x51, 0x1c, 0xba, 0xde, 0xb1, 0x80, 0x14, 0x37, 0x0b, 0x5b, + 0x75, 0x9a, 0x25, 0x71, 0x84, 0xe3, 0xcf, 0x9f, 0x4d, 0x99, 0x40, 0x94, 0x36, 0x0b, 0x5b, 0x05, + 0x9a, 0x25, 0x91, 0x3d, 0x80, 0xc0, 0x77, 0xbd, 0xf8, 0x14, 0x01, 0xe5, 0xcd, 0xc2, 0x16, 0x6c, + 0x3f, 0xe8, 0xa4, 0x7b, 0xe8, 0xe4, 0xa4, 0xee, 0x1c, 0x72, 0x28, 0x3e, 0xd2, 0xcc, 0x34, 0xf2, + 0xdb, 0x50, 0x9f, 0x47, 0x2c, 0x14, 0x6b, 0xd4, 0x70, 0x0d, 0xed, 0xd2, 0x35, 0x8e, 0x22, 0x16, + 0x8a, 0x25, 0xce, 0x27, 0x91, 0x21, 0x34, 0x43, 0x36, 0x61, 0x21, 0xf3, 0xc6, 0x4c, 0x2c, 0xb3, + 0x82, 0xcb, 0x7c, 0x70, 0xe9, 0x32, 0x34, 0x81, 0x8b, 0xb5, 0x16, 0xa6, 0xb7, 0xb7, 0x00, 0xce, + 0x85, 0x25, 0x2b, 0x50, 0x78, 0xd9, 0xaa, 0x6c, 0x2a, 0x5b, 0x05, 0x5a, 0x78, 0xc9, 0x47, 0x67, + 0xad, 0xaa, 0x18, 0x9d, 0xb5, 0xff, 0xa9, 0x00, 0xf5, 0x54, 0x26, 0x72, 0x0b, 0xca, 0x6c, 0x66, + 0xbb, 0xd3, 0x56, 0x7d, 0x53, 0xd9, 0xaa, 0x53, 0x31, 0x20, 0xf7, 0xa1, 0x61, 0xcf, 0xe3, 0x13, + 0xcb, 0xf1, 0x67, 0xb6, 0xeb, 0xb5, 0x00, 0x79, 0xc0, 0x49, 0x3d, 0xa4, 0x90, 0x36, 0xd4, 0x3c, + 0x77, 0xfc, 0xdc, 0xb3, 0x67, 0xac, 0xd5, 0xc0, 0x73, 0x48, 0xc7, 0xe4, 0x13, 0x20, 0x13, 0xe6, + 0xb0, 0xd0, 0x8e, 0x99, 0x63, 0xb9, 0x0e, 0xf3, 0x62, 0x37, 0x3e, 0x6b, 0xdd, 0x46, 0xd4, 0x7a, + 0xca, 0x31, 0x24, 0x23, 0x0f, 0x0f, 0x42, 0xff, 0xd4, 0x75, 0x58, 0xd8, 0xba, 0xb3, 0x00, 0x3f, + 0x94, 0x8c, 0xf6, 0xbf, 0x17, 0xa0, 0x99, 0xd7, 0x05, 0x51, 0xa1, 0x68, 0x07, 0x41, 0x6b, 0x15, + 0xa5, 0xe4, 0x8f, 0xe4, 0x6d, 0x00, 0x2e, 0x8a, 0x15, 0x05, 0xf6, 0x98, 0xb5, 0x6e, 0xe1, 0x5a, + 0x75, 0x4e, 0x19, 0x71, 0x02, 0x39, 0x82, 0x46, 0x60, 0xc7, 0x27, 0x6c, 0xca, 0x66, 0xcc, 0x8b, + 0x5b, 0xcd, 0xcd, 0xe2, 0x16, 0x6c, 0x7f, 0x7e, 0x4d, 0xd5, 0x77, 0x0e, 0xed, 0xf8, 0x44, 0x17, + 0x53, 0x69, 0x76, 0x9d, 0xb6, 0x0e, 0x8d, 0x0c, 0x8f, 0x10, 0x28, 0xc5, 0x67, 0x01, 0x6b, 0xad, + 0xa1, 0x5c, 0xf8, 0x4c, 0x9a, 0xa0, 0xb8, 0x4e, 0x4b, 0x45, 0xf3, 0x57, 0x5c, 0x87, 0x63, 0x50, + 0x87, 0xeb, 0x28, 0x22, 0x3e, 0x6b, 0xff, 0x51, 0x86, 0x5a, 0x22, 0x00, 0xe9, 0x42, 0x75, 0xc6, + 0x6c, 0xcf, 0xf5, 0x8e, 0xd1, 0x69, 0x9a, 0xdb, 0x6f, 0x2e, 0x11, 0xb3, 0x73, 0x20, 0x20, 0x3b, + 0x30, 0x18, 0x5a, 0x07, 0x7a, 0x77, 0x60, 0x0c, 0xf6, 0x69, 0x32, 0x8f, 0x1f, 0xa6, 0x7c, 0xb4, + 0xe6, 0xa1, 0x8b, 0x9e, 0x55, 0xa7, 0x20, 0x49, 0x47, 0xa1, 0x9b, 0x0a, 0x51, 0x14, 0x82, 0xe2, + 0x21, 0x76, 0xa0, 0x9c, 0xb8, 0x88, 0xb2, 0xd5, 0xd8, 0x6e, 0x5d, 0xa6, 0x1c, 0x2a, 0x60, 0xdc, + 0x20, 0x66, 0xf3, 0x69, 0xec, 0x06, 0x53, 0xee, 0x76, 0xca, 0x56, 0x8d, 0xa6, 0x63, 0xf2, 0x1e, + 0x40, 0xc4, 0xec, 0x70, 0x7c, 0x62, 0x3f, 0x9b, 0xb2, 0x56, 0x85, 0x7b, 0xf6, 0x4e, 0x79, 0x62, + 0x4f, 0x23, 0x46, 0x33, 0x0c, 0x62, 0xc3, 0xdd, 0x49, 0x1c, 0x59, 0xb1, 0xff, 0x9c, 0x79, 0xee, + 0x2b, 0x9b, 0x07, 0x12, 0xcb, 0x0f, 0xf8, 0x0f, 0xfa, 0x58, 0x73, 0xfb, 0xc3, 0x65, 0x5b, 0x7f, + 0x14, 0x47, 0x66, 0x66, 0xc6, 0x10, 0x27, 0xd0, 0xdb, 0x93, 0x65, 0x64, 0xd2, 0x86, 0xca, 0xd4, + 0x1f, 0xdb, 0x53, 0xd6, 0xaa, 0x73, 0x2d, 0xec, 0x28, 0xcc, 0xa3, 0x92, 0xa2, 0xfd, 0xb3, 0x02, + 0x55, 0xa9, 0x47, 0xd2, 0x84, 0x8c, 0x26, 0xd5, 0x37, 0x48, 0x0d, 0x4a, 0xbb, 0xfd, 0xe1, 0xae, + 0xda, 0xe4, 0x4f, 0xa6, 0xfe, 0xbd, 0xa9, 0xae, 0x71, 0xcc, 0xee, 0x53, 0x53, 0x1f, 0x99, 0x94, + 0x63, 0x54, 0xb2, 0x0e, 0xab, 0x5d, 0x73, 0x78, 0x60, 0xed, 0x75, 0x4d, 0x7d, 0x7f, 0x48, 0x9f, + 0xaa, 0x05, 0xb2, 0x0a, 0x75, 0x24, 0xf5, 0x8d, 0xc1, 0x13, 0x55, 0xe1, 0x33, 0x70, 0x68, 0x1a, + 0x66, 0x5f, 0x57, 0x8b, 0x44, 0x85, 0x15, 0x31, 0x63, 0x38, 0x30, 0xf5, 0x81, 0xa9, 0x96, 0x52, + 0xca, 0xe8, 0xe8, 0xe0, 0xa0, 0x4b, 0x9f, 0xaa, 0x65, 0xb2, 0x06, 0x0d, 0xa4, 0x74, 0x8f, 0xcc, + 0xc7, 0x43, 0xaa, 0x56, 0x48, 0x03, 0xaa, 0xfb, 0x3d, 0xeb, 0xbb, 0xc7, 0xfa, 0x40, 0xad, 0x92, + 0x15, 0xa8, 0xed, 0xf7, 0x2c, 0xfd, 0xa0, 0x6b, 0xf4, 0xd5, 0x1a, 0x9f, 0xbd, 0xaf, 0x0f, 0xe9, + 0x68, 0x64, 0x1d, 0x0e, 0x8d, 0x81, 0xa9, 0xd6, 0x49, 0x1d, 0xca, 0xfb, 0x3d, 0xcb, 0x38, 0x50, + 0x81, 0x10, 0x68, 0xee, 0xf7, 0xac, 0xc3, 0xc7, 0xc3, 0x81, 0x3e, 0x38, 0x3a, 0xd8, 0xd5, 0xa9, + 0xda, 0x20, 0xb7, 0x40, 0xe5, 0xb4, 0xe1, 0xc8, 0xec, 0xf6, 0xbb, 0xbd, 0x1e, 0xd5, 0x47, 0x23, + 0x75, 0x85, 0x4b, 0xbd, 0xdf, 0xb3, 0x68, 0xd7, 0xe4, 0xfb, 0x5a, 0xe5, 0x2f, 0xe4, 0x7b, 0x7f, + 0xa2, 0x3f, 0x55, 0xd7, 0xf9, 0x2b, 0xf4, 0x81, 0x69, 0x98, 0x4f, 0xad, 0x43, 0x3a, 0x34, 0x87, + 0xea, 0x06, 0x17, 0xd0, 0x18, 0xf4, 0xf4, 0xef, 0xad, 0x6f, 0xbb, 0xfd, 0x23, 0x5d, 0x25, 0xda, + 0x8f, 0xe1, 0xf6, 0xd2, 0x33, 0xe1, 0xaa, 0x7b, 0x6c, 0x1e, 0xf4, 0xd5, 0x02, 0x7f, 0xe2, 0x9b, + 0x52, 0x15, 0xed, 0x0f, 0xa0, 0xc4, 0x5d, 0x86, 0x7c, 0x06, 0xd5, 0xc4, 0x1b, 0x0b, 0xe8, 0x8d, + 0x77, 0xb3, 0x67, 0x6d, 0xc7, 0x27, 0x9d, 0xc4, 0xe3, 0x12, 0x5c, 0xbb, 0x0b, 0xd5, 0x45, 0x4f, + 0x53, 0x2e, 0x78, 0x5a, 0xf1, 0x82, 0xa7, 0x95, 0x32, 0x9e, 0x66, 0x43, 0x3d, 0xf5, 0xed, 0x9b, + 0x47, 0x91, 0x07, 0x50, 0xe2, 0xde, 0xdf, 0x6a, 0xa2, 0x87, 0xac, 0x2d, 0x08, 0x4c, 0x91, 0xa9, + 0xfd, 0x43, 0x01, 0x4a, 0x3c, 0xda, 0x9e, 0x07, 0xda, 0xc2, 0x15, 0x81, 0x56, 0xb9, 0x32, 0xd0, + 0x16, 0xaf, 0x15, 0x68, 0x2b, 0x37, 0x0b, 0xb4, 0xd5, 0x4b, 0x02, 0xad, 0xf6, 0x67, 0x45, 0x68, + 0xe8, 0x38, 0xf3, 0x10, 0x13, 0xfd, 0xfb, 0x50, 0x7c, 0xce, 0xce, 0x50, 0x3f, 0x8d, 0xed, 0x5b, + 0x99, 0xdd, 0xa6, 0x2a, 0xa4, 0x1c, 0x40, 0xb6, 0x61, 0x45, 0xbc, 0xd0, 0x3a, 0x0e, 0xfd, 0x79, + 0xd0, 0x52, 0x97, 0xab, 0xa7, 0x21, 0x40, 0xfb, 0x1c, 0x43, 0xde, 0x83, 0xb2, 0xff, 0xc2, 0x63, + 0x21, 0xc6, 0xc1, 0x3c, 0x98, 0x2b, 0x8f, 0x0a, 0x2e, 0x79, 0x08, 0xa5, 0xe7, 0xae, 0xe7, 0xe0, + 0x19, 0xe6, 0x23, 0x61, 0x46, 0xd0, 0xce, 0x13, 0xd7, 0x73, 0x28, 0x02, 0xc9, 0x3d, 0xa8, 0xf1, + 0x5f, 0x8c, 0x7b, 0x65, 0xdc, 0x68, 0x95, 0x8f, 0x79, 0xd0, 0x7b, 0x08, 0xb5, 0x40, 0xc6, 0x10, + 0x4c, 0x00, 0x8d, 0xed, 0x8d, 0x25, 0xe1, 0x85, 0xa6, 0x20, 0xf2, 0x15, 0xac, 0x84, 0xf6, 0x0b, + 0x2b, 0x9d, 0xb4, 0x76, 0xf9, 0xa4, 0x46, 0x68, 0xbf, 0x48, 0x23, 0x38, 0x81, 0x52, 0x68, 0x7b, + 0xcf, 0x5b, 0x64, 0xb3, 0xb0, 0x55, 0xa6, 0xf8, 0xac, 0x7d, 0x01, 0x25, 0x2e, 0x25, 0x8f, 0x08, + 0xfb, 0x3d, 0xf4, 0xff, 0xee, 0x9e, 0xa9, 0x16, 0x12, 0x7f, 0xfe, 0x96, 0x47, 0x03, 0x45, 0x72, + 0x0f, 0xf4, 0xd1, 0xa8, 0xbb, 0xaf, 0xab, 0x45, 0xad, 0x07, 0xeb, 0x7b, 0xfe, 0x2c, 0xf0, 0x23, + 0x37, 0x66, 0xe9, 0xf2, 0xf7, 0xa0, 0xe6, 0x7a, 0x0e, 0x7b, 0x69, 0xb9, 0x0e, 0x9a, 0x56, 0x91, + 0x56, 0x71, 0x6c, 0x38, 0xdc, 0xe4, 0x4e, 0x65, 0x31, 0x55, 0xe4, 0x26, 0x87, 0x03, 0xed, 0x2f, + 0x15, 0x28, 0x1b, 0x1c, 0xc1, 0x8d, 0x4f, 0x9e, 0x14, 0x7a, 0x8f, 0x30, 0x4c, 0x10, 0x24, 0x93, + 0xfb, 0x50, 0x1b, 0x6a, 0xb6, 0x37, 0x66, 0xbc, 0xe2, 0xc3, 0x3c, 0x50, 0xa3, 0xe9, 0x98, 0x7c, + 0x99, 0xd1, 0x9f, 0x82, 0x2e, 0x7b, 0x2f, 0xa3, 0x0a, 0x7c, 0xc1, 0x12, 0x2d, 0xb6, 0xff, 0xaa, + 0x90, 0x49, 0x6e, 0xcb, 0x12, 0x4f, 0x1f, 0xea, 0x8e, 0x1b, 0x32, 0xac, 0x23, 0xe5, 0x41, 0x3f, + 0xb8, 0x74, 0xe1, 0x4e, 0x2f, 0x81, 0xee, 0xd4, 0xbb, 0xa3, 0x3d, 0x7d, 0xd0, 0xe3, 0x99, 0xef, + 0x7c, 0x01, 0xed, 0x23, 0xa8, 0xa7, 0x10, 0x0c, 0xc7, 0x09, 0x48, 0x2d, 0x70, 0xf5, 0xf6, 0xf4, + 0x74, 0xac, 0x68, 0x7f, 0xad, 0x40, 0x33, 0xd5, 0xaf, 0xd0, 0xd0, 0x6d, 0xa8, 0xd8, 0x41, 0x90, + 0xa8, 0xb6, 0x4e, 0xcb, 0x76, 0x10, 0x18, 0x8e, 0x8c, 0x2d, 0x0a, 0x6a, 0x9b, 0xc7, 0x96, 0x4f, + 0x01, 0x1c, 0x36, 0x71, 0x3d, 0x17, 0x85, 0x2e, 0xa2, 0xc1, 0xab, 0x8b, 0x42, 0xd3, 0x0c, 0x86, + 0x7c, 0x09, 0xe5, 0x28, 0xb6, 0x63, 0x91, 0x2b, 0x9b, 0xdb, 0xf7, 0x33, 0xe0, 0xbc, 0x08, 0x9d, + 0x11, 0x87, 0x51, 0x81, 0x26, 0x5f, 0xc1, 0x2d, 0xdf, 0x9b, 0x9e, 0x59, 0xf3, 0x88, 0x59, 0xee, + 0xc4, 0x0a, 0xd9, 0x0f, 0x73, 0x37, 0x64, 0x4e, 0x3e, 0xa7, 0xae, 0x73, 0xc8, 0x51, 0xc4, 0x8c, + 0x09, 0x95, 0x7c, 0xed, 0x6b, 0x28, 0xe3, 0x3a, 0x7c, 0xcf, 0xdf, 0x51, 0xc3, 0xd4, 0xad, 0xe1, + 0xa0, 0xff, 0x54, 0xe8, 0x80, 0xea, 0xdd, 0x9e, 0x85, 0x44, 0x55, 0xe1, 0xc1, 0xbe, 0xa7, 0xf7, + 0x75, 0x53, 0xef, 0xa9, 0x45, 0x9e, 0x3d, 0x74, 0x4a, 0x87, 0x54, 0x2d, 0x69, 0xff, 0x53, 0x80, + 0x15, 0x94, 0xe7, 0xd0, 0x8f, 0xe2, 0x89, 0xfb, 0x92, 0xec, 0x41, 0x43, 0x98, 0xdd, 0xa9, 0x2c, + 0xe8, 0xb9, 0x33, 0x68, 0x8b, 0x7b, 0x96, 0x68, 0x31, 0x90, 0x75, 0xb4, 0x9b, 0x3e, 0x27, 0x21, + 0x45, 0x41, 0xa7, 0xbf, 0x22, 0xa4, 0xbc, 0x05, 0x95, 0x67, 0x6c, 0xe2, 0x87, 0x22, 0x04, 0xd6, + 0x76, 0x4a, 0x71, 0x38, 0x67, 0x54, 0xd2, 0xda, 0x36, 0xc0, 0xf9, 0xfa, 0xe4, 0x01, 0xac, 0x26, + 0xc6, 0x66, 0xa1, 0x71, 0x89, 0x93, 0x5b, 0x49, 0x88, 0x83, 0x5c, 0x75, 0xa3, 0x5c, 0xab, 0xba, + 0xd1, 0xbe, 0x86, 0xd5, 0x64, 0x3f, 0xe2, 0xfc, 0x54, 0x21, 0x79, 0x01, 0x63, 0xca, 0x82, 0x8c, + 0xca, 0x45, 0x19, 0xb5, 0x9f, 0x41, 0x6d, 0xe4, 0xd9, 0x41, 0x74, 0xe2, 0xc7, 0xdc, 0x7a, 0xe2, + 0x48, 0xfa, 0xaa, 0x12, 0x47, 0x9a, 0x06, 0x15, 0x7e, 0x38, 0xf3, 0x88, 0xbb, 0xbf, 0x31, 0xe8, + 0xee, 0x99, 0xc6, 0xb7, 0xba, 0xfa, 0x06, 0x01, 0xa8, 0xc8, 0xe7, 0x82, 0xa6, 0x41, 0xd3, 0x90, + 0xed, 0xd8, 0x63, 0x66, 0x3b, 0x2c, 0xe4, 0x12, 0xfc, 0xe0, 0x47, 0x89, 0x04, 0x3f, 0xf8, 0x91, + 0xf6, 0x17, 0x05, 0x68, 0x98, 0xa1, 0xed, 0x45, 0xb6, 0x30, 0xf7, 0xcf, 0xa0, 0x72, 0x82, 0x58, + 0x74, 0xa3, 0xc6, 0x82, 0x7f, 0x66, 0x17, 0xa3, 0x12, 0x48, 0xee, 0x40, 0xe5, 0xc4, 0xf6, 0x9c, + 0xa9, 0xd0, 0x5a, 0x85, 0xca, 0x51, 0x92, 0x1b, 0x95, 0xf3, 0xdc, 0xb8, 0x05, 0x2b, 0x33, 0x3b, + 0x7c, 0x6e, 0x8d, 0x4f, 0x6c, 0xef, 0x98, 0x45, 0xf2, 0x60, 0xa4, 0x05, 0x36, 0x38, 0x6b, 0x4f, + 0x70, 0xb4, 0xbf, 0x5f, 0x81, 0xf2, 0x37, 0x73, 0x16, 0x9e, 0x65, 0x04, 0xfa, 0xe0, 0xba, 0x02, + 0xc9, 0x17, 0x17, 0x2e, 0x4b, 0xca, 0x6f, 0x2f, 0x26, 0x65, 0x22, 0x53, 0x84, 0xc8, 0x95, 0x22, + 0x0b, 0x7c, 0x9a, 0x09, 0x63, 0xeb, 0x57, 0xd8, 0xda, 0x79, 0x70, 0x7b, 0x08, 0x95, 0x89, 0x3b, + 0x8d, 0x51, 0x75, 0x8b, 0xd5, 0x08, 0xee, 0xa5, 0xf3, 0x08, 0xd9, 0x54, 0xc2, 0xc8, 0xbb, 0xb0, + 0x22, 0x2a, 0x59, 0xeb, 0x07, 0xce, 0xc6, 0x82, 0x95, 0xf7, 0xa6, 0x48, 0x13, 0xbb, 0xff, 0x18, + 0xca, 0x7e, 0xc8, 0x37, 0x5f, 0xc7, 0x25, 0xef, 0x5c, 0x58, 0x72, 0xc8, 0xb9, 0x54, 0x80, 0xc8, + 0x87, 0x50, 0x3a, 0x71, 0xbd, 0x18, 0xb3, 0x46, 0x73, 0xfb, 0xf6, 0x05, 0xf0, 0x63, 0xd7, 0x8b, + 0x29, 0x42, 0x78, 0x98, 0x1f, 0xfb, 0x73, 0x2f, 0x6e, 0xdd, 0xc5, 0x0c, 0x23, 0x06, 0xe4, 0x1e, + 0x54, 0xfc, 0xc9, 0x24, 0x62, 0x31, 0x76, 0x96, 0xe5, 0x9d, 0xc2, 0xa7, 0x54, 0x12, 0xf8, 0x84, + 0xa9, 0x3b, 0x73, 0x63, 0xec, 0x43, 0xca, 0x54, 0x0c, 0xc8, 0x2e, 0xac, 0x8d, 0xfd, 0x59, 0xe0, + 0x4e, 0x99, 0x63, 0x8d, 0xe7, 0x61, 0xe4, 0x87, 0xad, 0x77, 0x2e, 0x1c, 0xd3, 0x9e, 0x44, 0xec, + 0x21, 0x80, 0x36, 0xc7, 0xb9, 0x31, 0x31, 0x60, 0x83, 0x79, 0x8e, 0xb5, 0xb8, 0xce, 0xfd, 0xd7, + 0xad, 0xb3, 0xce, 0x3c, 0x27, 0x4f, 0x4a, 0xc4, 0xc1, 0x48, 0x68, 0x61, 0xcc, 0x68, 0x6d, 0x60, + 0x90, 0xb9, 0x77, 0x69, 0xac, 0x14, 0xe2, 0x64, 0xc2, 0xf7, 0x6f, 0xc0, 0x2d, 0x19, 0x22, 0xad, + 0x80, 0x85, 0x13, 0x36, 0x8e, 0xad, 0x60, 0x6a, 0x7b, 0x58, 0xca, 0xa5, 0xc6, 0x4a, 0x24, 0xe4, + 0x50, 0x20, 0x0e, 0xa7, 0xb6, 0x47, 0x34, 0xa8, 0x3f, 0x67, 0x67, 0x91, 0xc5, 0x23, 0x29, 0x76, + 0xae, 0x29, 0xba, 0xc6, 0xe9, 0x43, 0x6f, 0x7a, 0x46, 0x7e, 0x02, 0x8d, 0xf8, 0xdc, 0xdb, 0xb0, + 0x61, 0x6d, 0xe4, 0x4e, 0x35, 0xe3, 0x8b, 0x34, 0x0b, 0x25, 0xf7, 0xa1, 0x2a, 0x35, 0xd4, 0xba, + 0x97, 0x5d, 0x3b, 0xa1, 0xf2, 0xc4, 0x3c, 0xb1, 0xdd, 0xa9, 0x7f, 0xca, 0x42, 0x6b, 0x16, 0xb5, + 0xda, 0xe2, 0xb6, 0x24, 0x21, 0x1d, 0x44, 0xdc, 0x4f, 0xa3, 0x38, 0xf4, 0xbd, 0xe3, 0xd6, 0x26, + 0xde, 0x93, 0xc8, 0xd1, 0xc5, 0xe0, 0xf7, 0x2e, 0x66, 0xfe, 0x7c, 0xf0, 0xfb, 0x1c, 0xee, 0x60, + 0x65, 0x66, 0x3d, 0x3b, 0xb3, 0xf2, 0x68, 0x0d, 0xd1, 0x1b, 0xc8, 0xdd, 0x3d, 0x3b, 0xcc, 0x4e, + 0x6a, 0x43, 0xcd, 0x71, 0xa3, 0xd8, 0xf5, 0xc6, 0x71, 0xab, 0x85, 0xef, 0x4c, 0xc7, 0xe4, 0x33, + 0xb8, 0x3d, 0x73, 0x3d, 0x2b, 0xb2, 0x27, 0xcc, 0x8a, 0x5d, 0xee, 0x9b, 0x6c, 0xec, 0x7b, 0x4e, + 0xd4, 0x7a, 0x80, 0x82, 0x93, 0x99, 0xeb, 0x8d, 0xec, 0x09, 0x33, 0xdd, 0x19, 0x1b, 0x09, 0x0e, + 0xf9, 0x08, 0xd6, 0x11, 0x1e, 0xb2, 0x60, 0xea, 0x8e, 0x6d, 0xf1, 0xfa, 0x1f, 0xe1, 0xeb, 0xd7, + 0x38, 0x83, 0x0a, 0x3a, 0xbe, 0xfa, 0x63, 0x68, 0x06, 0x2c, 0x8c, 0xdc, 0x28, 0xb6, 0xa4, 0x45, + 0xbf, 0x97, 0xd5, 0xda, 0xaa, 0x64, 0x0e, 0x91, 0xd7, 0xfe, 0xcf, 0x02, 0x54, 0x84, 0x73, 0x92, + 0x4f, 0x41, 0xf1, 0x03, 0xbc, 0x06, 0x69, 0x6e, 0x6f, 0x5e, 0xe2, 0xc1, 0x9d, 0x61, 0xc0, 0xeb, + 0x5e, 0x3f, 0xa4, 0x8a, 0x1f, 0xdc, 0xb8, 0x28, 0xd4, 0xfe, 0x10, 0x6a, 0xc9, 0x02, 0xbc, 0xbc, + 0xe8, 0xeb, 0xa3, 0x91, 0x65, 0x3e, 0xee, 0x0e, 0xd4, 0x02, 0xb9, 0x03, 0x24, 0x1d, 0x5a, 0x43, + 0x6a, 0xe9, 0xdf, 0x1c, 0x75, 0xfb, 0xaa, 0x82, 0x5d, 0x1a, 0xd5, 0xbb, 0xa6, 0x4e, 0x05, 0xb2, + 0x48, 0xee, 0xc1, 0xed, 0x2c, 0xe5, 0x1c, 0x5c, 0xc2, 0x14, 0x8c, 0x8f, 0x65, 0x52, 0x01, 0xc5, + 0x18, 0xa8, 0x15, 0x9e, 0x16, 0xf4, 0xef, 0x8d, 0x91, 0x39, 0x52, 0xab, 0xed, 0xbf, 0x29, 0x40, + 0x19, 0xc3, 0x06, 0x3f, 0x9f, 0x54, 0x72, 0x71, 0x5d, 0x73, 0x5e, 0xb9, 0x1a, 0xd9, 0x92, 0xaa, + 0x81, 0x01, 0x65, 0x73, 0x79, 0xf4, 0xf9, 0xb5, 0xd6, 0x53, 0x3f, 0x85, 0x12, 0x8f, 0x52, 0xbc, + 0x43, 0x1c, 0xd2, 0x9e, 0x4e, 0xad, 0x47, 0x06, 0x1d, 0xf1, 0x2a, 0x97, 0x40, 0xb3, 0x3b, 0xd8, + 0xd3, 0x47, 0xe6, 0x30, 0xa1, 0xa1, 0x56, 0x1e, 0x19, 0x7d, 0x33, 0x45, 0x15, 0xb5, 0x9f, 0xd7, + 0x60, 0x35, 0x89, 0x09, 0x22, 0x82, 0x3e, 0x82, 0x46, 0x10, 0xba, 0x33, 0x3b, 0x3c, 0x8b, 0xc6, + 0xb6, 0x87, 0x49, 0x01, 0xb6, 0x7f, 0xb4, 0x24, 0xaa, 0x88, 0x1d, 0x1d, 0x0a, 0xec, 0x68, 0x6c, + 0x7b, 0x34, 0x3b, 0x91, 0xf4, 0x61, 0x75, 0xc6, 0xc2, 0x63, 0xf6, 0x7b, 0xbe, 0xeb, 0xe1, 0x4a, + 0x55, 0x8c, 0xc8, 0xef, 0x5f, 0xba, 0xd2, 0x01, 0x47, 0xff, 0x8e, 0xef, 0x7a, 0xb8, 0x56, 0x7e, + 0x32, 0xf9, 0x04, 0xea, 0xa2, 0x12, 0x72, 0xd8, 0x04, 0x63, 0xc5, 0xb2, 0xda, 0x4f, 0xd4, 0xe8, + 0x3d, 0x36, 0xc9, 0xc4, 0x65, 0xb8, 0x34, 0x2e, 0x37, 0xb2, 0x71, 0xf9, 0xcd, 0x6c, 0x2c, 0x5a, + 0x11, 0x55, 0x78, 0x1a, 0x84, 0x2e, 0x38, 0x7c, 0x6b, 0x89, 0xc3, 0x77, 0x60, 0x23, 0xf1, 0x55, + 0xcb, 0xf5, 0x26, 0xee, 0x4b, 0x2b, 0x72, 0x5f, 0x89, 0xd8, 0x53, 0xa6, 0xeb, 0x09, 0xcb, 0xe0, + 0x9c, 0x91, 0xfb, 0x8a, 0x11, 0x23, 0xe9, 0xe0, 0x64, 0x0e, 0x5c, 0xc5, 0xab, 0xc9, 0xf7, 0x2e, + 0x55, 0x8f, 0x68, 0xbe, 0x64, 0x46, 0xcc, 0x4d, 0x6d, 0xff, 0x52, 0x81, 0x46, 0xe6, 0x1c, 0x78, + 0xf6, 0x16, 0xca, 0x42, 0x61, 0xc5, 0x55, 0x94, 0x50, 0x1f, 0x4a, 0xfa, 0x26, 0xd4, 0xa3, 0xd8, + 0x0e, 0x63, 0x8b, 0x17, 0x57, 0xb2, 0xdd, 0x45, 0xc2, 0x13, 0x76, 0x46, 0x3e, 0x80, 0x35, 0xc1, + 0x74, 0xbd, 0xf1, 0x74, 0x1e, 0xb9, 0xa7, 0xa2, 0x99, 0xaf, 0xd1, 0x26, 0x92, 0x8d, 0x84, 0x4a, + 0xee, 0x42, 0x95, 0x67, 0x21, 0xbe, 0x86, 0x68, 0xfa, 0x2a, 0xcc, 0x73, 0xf8, 0x0a, 0x0f, 0x60, + 0x95, 0x33, 0xce, 0xe7, 0x57, 0xc4, 0x2d, 0x33, 0xf3, 0x9c, 0xf3, 0xd9, 0x1d, 0xd8, 0x10, 0xaf, + 0x09, 0x44, 0xf1, 0x2a, 0x2b, 0xdc, 0x3b, 0xa8, 0xd8, 0x75, 0x64, 0xc9, 0xb2, 0x56, 0x14, 0x9c, + 0x1f, 0x01, 0xcf, 0x5e, 0x0b, 0xe8, 0xbb, 0x22, 0x94, 0x31, 0xcf, 0xc9, 0x61, 0x77, 0xe1, 0x1d, + 0x8e, 0x9d, 0x7b, 0x76, 0x10, 0x4c, 0x5d, 0xe6, 0x58, 0x53, 0xff, 0x18, 0x43, 0x66, 0x14, 0xdb, + 0xb3, 0xc0, 0x9a, 0x47, 0xad, 0x0d, 0x0c, 0x99, 0x6d, 0xe6, 0x39, 0x47, 0x09, 0xa8, 0xef, 0x1f, + 0x9b, 0x09, 0xe4, 0x28, 0x6a, 0xff, 0x3e, 0xac, 0xe6, 0xec, 0x71, 0x41, 0xa7, 0x35, 0x74, 0xfe, + 0x8c, 0x4e, 0xdf, 0x85, 0x95, 0x20, 0x64, 0xe7, 0xa2, 0xd5, 0x51, 0xb4, 0x86, 0xa0, 0x09, 0xb1, + 0xb6, 0x60, 0x05, 0x79, 0x96, 0x20, 0xe6, 0xf3, 0x63, 0x03, 0x59, 0x87, 0xc8, 0x69, 0xbf, 0x80, + 0x95, 0xec, 0x69, 0x93, 0x77, 0x33, 0x69, 0xa1, 0x99, 0xcb, 0x93, 0x69, 0x76, 0x48, 0x2a, 0xb2, + 0xf5, 0x4b, 0x2a, 0x32, 0x72, 0x9d, 0x8a, 0x4c, 0xfb, 0x2f, 0xd9, 0x9c, 0x65, 0x2a, 0x84, 0x9f, + 0x41, 0x2d, 0x90, 0xf5, 0x38, 0x5a, 0x52, 0xfe, 0x12, 0x3e, 0x0f, 0xee, 0x24, 0x95, 0x3b, 0x4d, + 0xe7, 0xb4, 0xff, 0x56, 0x81, 0x5a, 0x5a, 0xd0, 0xe7, 0x2c, 0xef, 0xcd, 0x05, 0xcb, 0x3b, 0x90, + 0x1a, 0x16, 0x0a, 0x7c, 0x1b, 0xa3, 0xc5, 0x27, 0xaf, 0x7f, 0xd7, 0xc5, 0xb6, 0xe7, 0x34, 0xdb, + 0xf6, 0x6c, 0xbe, 0xae, 0xed, 0xf9, 0xe4, 0xa2, 0xc1, 0xbf, 0x95, 0xe9, 0x2d, 0x16, 0xcc, 0xbe, + 0xfd, 0x7d, 0xae, 0x0f, 0xca, 0x26, 0x84, 0x77, 0xc4, 0x7e, 0xd2, 0x84, 0x90, 0xb6, 0x3f, 0xf7, + 0xaf, 0xd7, 0xfe, 0x6c, 0x43, 0x45, 0xea, 0xfc, 0x0e, 0x54, 0x64, 0x4d, 0x27, 0x1b, 0x04, 0x31, + 0x3a, 0x6f, 0x10, 0x0a, 0xb2, 0x4e, 0xd7, 0x7e, 0xae, 0x40, 0x59, 0x0f, 0x43, 0x3f, 0xd4, 0xfe, + 0x48, 0x81, 0x3a, 0x3e, 0xed, 0xf9, 0x0e, 0xe3, 0xd9, 0x60, 0xb7, 0xdb, 0xb3, 0xa8, 0xfe, 0xcd, + 0x91, 0x8e, 0xd9, 0xa0, 0x0d, 0x77, 0xf6, 0x86, 0x83, 0xbd, 0x23, 0x4a, 0xf5, 0x81, 0x69, 0x99, + 0xb4, 0x3b, 0x18, 0xf1, 0xb6, 0x67, 0x38, 0x50, 0x15, 0x9e, 0x29, 0x8c, 0x81, 0xa9, 0xd3, 0x41, + 0xb7, 0x6f, 0x89, 0x56, 0xb4, 0x88, 0x77, 0xb3, 0xba, 0xde, 0xb3, 0xf0, 0xd6, 0x51, 0x2d, 0xf1, + 0x96, 0xd5, 0x34, 0x0e, 0xf4, 0xe1, 0x91, 0xa9, 0x96, 0xc9, 0x6d, 0x58, 0x3f, 0xd4, 0xe9, 0x81, + 0x31, 0x1a, 0x19, 0xc3, 0x81, 0xd5, 0xd3, 0x07, 0x86, 0xde, 0x53, 0x2b, 0x7c, 0x9d, 0x5d, 0x63, + 0xdf, 0xec, 0xee, 0xf6, 0x75, 0xb9, 0x4e, 0x95, 0x6c, 0xc2, 0x5b, 0x7b, 0xc3, 0x83, 0x03, 0xc3, + 0x34, 0xf5, 0x9e, 0xb5, 0x7b, 0x64, 0x5a, 0x23, 0xd3, 0xe8, 0xf7, 0xad, 0xee, 0xe1, 0x61, 0xff, + 0x29, 0x4f, 0x60, 0x35, 0x72, 0x17, 0x36, 0xf6, 0xba, 0x87, 0xdd, 0x5d, 0xa3, 0x6f, 0x98, 0x4f, + 0xad, 0x9e, 0x31, 0xe2, 0xf3, 0x7b, 0x6a, 0x9d, 0x27, 0x6c, 0x93, 0x3e, 0xb5, 0xba, 0x7d, 0x14, + 0xcd, 0xd4, 0xad, 0xdd, 0xee, 0xde, 0x13, 0x7d, 0xd0, 0x53, 0x81, 0x0b, 0x30, 0xea, 0x3e, 0xd2, + 0x2d, 0x2e, 0x92, 0x65, 0x0e, 0x87, 0xd6, 0xb0, 0xdf, 0x53, 0x1b, 0xda, 0xbf, 0x14, 0xa1, 0xb4, + 0xe7, 0x47, 0x31, 0xf7, 0x46, 0xe1, 0xac, 0x2f, 0x42, 0x37, 0x66, 0xa2, 0x7f, 0x2b, 0x53, 0xd1, + 0x4b, 0x7f, 0x87, 0x24, 0x1e, 0x50, 0x32, 0x10, 0xeb, 0xd9, 0x19, 0xc7, 0x29, 0x88, 0x5b, 0x3b, + 0xc7, 0xed, 0x72, 0xb2, 0x88, 0x68, 0x78, 0x85, 0x23, 0xd7, 0x2b, 0x22, 0x4e, 0x06, 0x61, 0xb9, + 0xe0, 0xc7, 0x40, 0xb2, 0x20, 0xb9, 0x62, 0x09, 0x91, 0x6a, 0x06, 0x29, 0x96, 0xdc, 0x01, 0x18, + 0xfb, 0xb3, 0x99, 0x1b, 0x8f, 0xfd, 0x28, 0x96, 0x5f, 0xc8, 0xda, 0x39, 0x63, 0x8f, 0x62, 0x6e, + 0xf1, 0x33, 0x37, 0xe6, 0x8f, 0x34, 0x83, 0x26, 0x3b, 0x70, 0xcf, 0x0e, 0x82, 0xd0, 0x7f, 0xe9, + 0xce, 0xec, 0x98, 0x59, 0xdc, 0x73, 0xed, 0x63, 0x66, 0x39, 0x6c, 0x1a, 0xdb, 0xd8, 0x13, 0x95, + 0xe9, 0xdd, 0x0c, 0x60, 0x24, 0xf8, 0x3d, 0xce, 0xe6, 0x71, 0xd7, 0x75, 0xac, 0x88, 0xfd, 0x30, + 0xe7, 0x1e, 0x60, 0xcd, 0x03, 0xc7, 0xe6, 0x62, 0xd6, 0x45, 0x96, 0x72, 0x9d, 0x91, 0xe4, 0x1c, + 0x09, 0x46, 0xfb, 0x15, 0xc0, 0xb9, 0x14, 0x64, 0x1b, 0x6e, 0xf3, 0x3a, 0x9e, 0x45, 0x31, 0x73, + 0x2c, 0xb9, 0xdb, 0x60, 0x1e, 0x47, 0x18, 0xe2, 0xcb, 0x74, 0x23, 0x65, 0xca, 0x9b, 0xc2, 0x79, + 0x1c, 0x91, 0x9f, 0x40, 0xeb, 0xc2, 0x1c, 0x87, 0x4d, 0x19, 0x7f, 0x6d, 0x15, 0xa7, 0xdd, 0x59, + 0x98, 0xd6, 0x13, 0x5c, 0xed, 0x4f, 0x14, 0x80, 0x7d, 0x16, 0x53, 0xc1, 0xcd, 0x34, 0xb6, 0x95, + 0xeb, 0x36, 0xb6, 0xef, 0x27, 0x17, 0x08, 0xc5, 0xab, 0x63, 0xc0, 0x42, 0x97, 0xa1, 0xdc, 0xa4, + 0xcb, 0xc8, 0x35, 0x11, 0xc5, 0x2b, 0x9a, 0x88, 0x52, 0xae, 0x89, 0xf8, 0x18, 0x9a, 0xf6, 0x74, + 0xea, 0xbf, 0xe0, 0x05, 0x0d, 0x0b, 0x43, 0xe6, 0xa0, 0x11, 0x9c, 0xd7, 0xdb, 0xc8, 0xec, 0x49, + 0x9e, 0xf6, 0xe7, 0x0a, 0x34, 0x50, 0x15, 0x51, 0xe0, 0x7b, 0x11, 0x23, 0x5f, 0x42, 0x45, 0x5e, + 0x44, 0x8b, 0x8b, 0xfc, 0xb7, 0x33, 0xb2, 0x66, 0x70, 0xb2, 0x68, 0xa0, 0x12, 0xcc, 0x33, 0x42, + 0xe6, 0x75, 0x97, 0x2b, 0x25, 0x45, 0x91, 0xfb, 0x50, 0x73, 0x3d, 0x4b, 0xb4, 0xd4, 0x95, 0x4c, + 0x58, 0xac, 0xba, 0x1e, 0xd6, 0xb2, 0xed, 0x57, 0x50, 0x11, 0x2f, 0x21, 0x9d, 0x54, 0xa6, 0x8b, + 0xfa, 0xcb, 0xdc, 0x1c, 0xa7, 0xc2, 0xc8, 0xc3, 0x29, 0xbd, 0x2e, 0x40, 0xb7, 0xa0, 0x7a, 0xca, + 0x9b, 0x0f, 0xbc, 0xf4, 0xe3, 0xea, 0x4d, 0x86, 0xda, 0x1f, 0x97, 0x00, 0x0e, 0xe7, 0x4b, 0x0c, + 0xa4, 0x71, 0x5d, 0x03, 0xe9, 0xe4, 0xf4, 0xf8, 0x7a, 0x99, 0x7f, 0x75, 0x43, 0x59, 0xd2, 0x69, + 0x17, 0x6f, 0xda, 0x69, 0xdf, 0x87, 0x6a, 0x1c, 0xce, 0xb9, 0xa3, 0x08, 0x63, 0x4a, 0x5b, 0x5a, + 0x49, 0x25, 0x6f, 0x42, 0x79, 0xe2, 0x87, 0x63, 0x86, 0x8e, 0x95, 0xb2, 0x05, 0xed, 0xc2, 0x65, + 0x52, 0xed, 0xb2, 0xcb, 0x24, 0xde, 0xa0, 0x45, 0xf2, 0x1e, 0x0d, 0x0b, 0x99, 0x7c, 0x83, 0x96, + 0x5c, 0xb1, 0xd1, 0x14, 0x44, 0xbe, 0x81, 0xa6, 0x3d, 0x8f, 0x7d, 0xcb, 0xe5, 0x15, 0xda, 0xd4, + 0x1d, 0x9f, 0x61, 0xd9, 0xdd, 0xcc, 0x7f, 0xaf, 0x4f, 0x0f, 0xaa, 0xd3, 0x9d, 0xc7, 0xbe, 0xe1, + 0x1c, 0x22, 0x72, 0xa7, 0x2a, 0x93, 0x12, 0x5d, 0xb1, 0x33, 0x64, 0xed, 0xc7, 0xb0, 0x92, 0x85, + 0xf1, 0x04, 0x24, 0x81, 0xea, 0x1b, 0x3c, 0x3b, 0x8d, 0x78, 0x6a, 0x1b, 0x98, 0x46, 0xb7, 0xaf, + 0x16, 0xb4, 0x18, 0x1a, 0xb8, 0xbc, 0xf4, 0x8e, 0xeb, 0xba, 0xfd, 0x03, 0x28, 0x61, 0xf8, 0x55, + 0x2e, 0x7c, 0x0f, 0xc1, 0x98, 0x8b, 0xcc, 0xbc, 0xf9, 0x15, 0xb3, 0xe6, 0xf7, 0xdf, 0x05, 0x58, + 0x31, 0xfd, 0xf9, 0xf8, 0xe4, 0xa2, 0x01, 0xc2, 0xaf, 0x3b, 0x42, 0x2d, 0x31, 0x1f, 0xe5, 0xa6, + 0xe6, 0x93, 0x5a, 0x47, 0x71, 0x89, 0x75, 0xdc, 0xf4, 0xcc, 0xb5, 0x2f, 0x60, 0x55, 0x6e, 0x5e, + 0x6a, 0x3d, 0xd1, 0x66, 0xe1, 0x0a, 0x6d, 0x6a, 0xbf, 0x50, 0x60, 0x55, 0xc4, 0xf7, 0xff, 0xbb, + 0xd2, 0x2a, 0x37, 0x0c, 0xeb, 0xe5, 0x1b, 0x5d, 0x1e, 0xfd, 0xbf, 0xf4, 0x34, 0x6d, 0x08, 0xcd, + 0x44, 0x7d, 0x37, 0x50, 0xfb, 0x15, 0x46, 0xfc, 0x8b, 0x02, 0x34, 0x06, 0xec, 0xe5, 0x92, 0x20, + 0x5a, 0xbe, 0xee, 0x71, 0x7c, 0x98, 0x2b, 0x57, 0x1b, 0xdb, 0xeb, 0x59, 0x19, 0xc4, 0xd5, 0x63, + 0x52, 0xc1, 0xa6, 0xb7, 0xa8, 0xca, 0xf2, 0x5b, 0xd4, 0xd2, 0x62, 0xb7, 0x9e, 0xb9, 0xc5, 0x2b, + 0x2e, 0xbb, 0xc5, 0xd3, 0xfe, 0xad, 0x08, 0x0d, 0x6c, 0x90, 0x29, 0x8b, 0xe6, 0xd3, 0x38, 0x27, + 0x4c, 0xe1, 0x6a, 0x61, 0x3a, 0x50, 0x09, 0x71, 0x92, 0x74, 0xa5, 0x4b, 0x83, 0xbf, 0x40, 0x61, + 0x6b, 0xfc, 0xdc, 0x0d, 0x02, 0xe6, 0x58, 0x82, 0x92, 0x14, 0x30, 0x4d, 0x49, 0x16, 0x22, 0x44, + 0xbc, 0xfc, 0x9c, 0xf9, 0x21, 0x4b, 0x51, 0x45, 0xbc, 0x4f, 0x68, 0x70, 0x5a, 0x02, 0xc9, 0xdd, + 0x37, 0x88, 0xca, 0xe0, 0xfc, 0xbe, 0x21, 0xed, 0x35, 0x91, 0x5b, 0x47, 0xae, 0xe8, 0x35, 0x91, + 0xcd, 0xbb, 0xa8, 0x99, 0x3d, 0x9d, 0x5a, 0x7e, 0x10, 0xa1, 0xd3, 0xd4, 0x68, 0x0d, 0x09, 0xc3, + 0x20, 0x22, 0x5f, 0x43, 0x7a, 0x5d, 0x2c, 0x6f, 0xc9, 0xc5, 0x39, 0xb6, 0x2e, 0xbb, 0x58, 0xa0, + 0xab, 0xe3, 0xdc, 0xfd, 0xcf, 0x92, 0x1b, 0xea, 0xca, 0x4d, 0x6f, 0xa8, 0x1f, 0x42, 0x59, 0xc4, + 0xa8, 0xda, 0xeb, 0x62, 0x94, 0xc0, 0x65, 0xed, 0xb3, 0x91, 0xb7, 0xcf, 0x5f, 0x16, 0x80, 0x74, + 0xa7, 0x53, 0x7f, 0x6c, 0xc7, 0xcc, 0x70, 0xa2, 0x8b, 0x66, 0x7a, 0xed, 0xcf, 0x2e, 0x9f, 0x41, + 0x7d, 0xe6, 0x3b, 0x6c, 0x6a, 0x25, 0xdf, 0x94, 0x2e, 0xad, 0x7e, 0x10, 0xc6, 0x5b, 0x52, 0x02, + 0x25, 0xbc, 0xc4, 0x51, 0xb0, 0xee, 0xc0, 0x67, 0xde, 0x84, 0xcd, 0xec, 0x97, 0xb2, 0x14, 0xe1, + 0x8f, 0xa4, 0x03, 0xd5, 0x90, 0x45, 0x2c, 0x3c, 0x65, 0x57, 0x16, 0x55, 0x09, 0x48, 0x7b, 0x06, + 0x1b, 0xb9, 0x1d, 0x49, 0x47, 0xbe, 0x85, 0x5f, 0x2b, 0xc3, 0x58, 0x7e, 0xb4, 0x12, 0x03, 0xfe, + 0x3a, 0xe6, 0x25, 0x9f, 0x41, 0xf9, 0x63, 0xea, 0xf0, 0xc5, 0xab, 0xe2, 0xec, 0x1e, 0xa8, 0x59, + 0x4d, 0xbb, 0x63, 0x0c, 0x36, 0xf2, 0x54, 0x0a, 0xd7, 0x3b, 0x15, 0xed, 0xef, 0x0a, 0xb0, 0xde, + 0x75, 0x1c, 0xf1, 0x77, 0xc3, 0x25, 0xaa, 0x2f, 0x5e, 0x57, 0xf5, 0x0b, 0x81, 0x58, 0x84, 0x89, + 0x6b, 0x05, 0xe2, 0x0f, 0xa1, 0x92, 0xd6, 0x5a, 0xc5, 0x05, 0x77, 0x16, 0x72, 0x51, 0x09, 0xd0, + 0x6e, 0x01, 0xc9, 0x0a, 0x2b, 0xb4, 0xaa, 0xfd, 0x69, 0x11, 0xee, 0xee, 0xb2, 0x63, 0xd7, 0xcb, + 0xbe, 0xe2, 0x57, 0xdf, 0xc9, 0xc5, 0x4f, 0x65, 0x9f, 0xc1, 0xba, 0x28, 0xe4, 0x93, 0x7f, 0x62, + 0x59, 0xec, 0x58, 0x7e, 0x9d, 0x94, 0xb1, 0x6a, 0x0d, 0xf9, 0x07, 0x92, 0xad, 0xe3, 0x7f, 0xc5, + 0x1c, 0x3b, 0xb6, 0x9f, 0xd9, 0x11, 0xb3, 0x5c, 0x47, 0xfe, 0x59, 0x06, 0x12, 0x92, 0xe1, 0x90, + 0x21, 0x94, 0xb8, 0x0d, 0xa2, 0xeb, 0x36, 0xb7, 0xb7, 0x33, 0x62, 0x5d, 0xb2, 0x95, 0xac, 0x02, + 0x0f, 0x7c, 0x87, 0xed, 0x54, 0x8f, 0x06, 0x4f, 0x06, 0xc3, 0xef, 0x06, 0x14, 0x17, 0x22, 0x06, + 0xdc, 0x0a, 0x42, 0x76, 0xea, 0xfa, 0xf3, 0xc8, 0xca, 0x9e, 0x44, 0xf5, 0xca, 0x94, 0xb8, 0x91, + 0xcc, 0xc9, 0x10, 0xb5, 0x9f, 0xc2, 0xda, 0xc2, 0xcb, 0x78, 0x6d, 0x26, 0x5f, 0xa7, 0xbe, 0x41, + 0x56, 0xa1, 0x8e, 0x1f, 0xbb, 0x97, 0x7f, 0xfb, 0xd6, 0xfe, 0xb5, 0x80, 0x57, 0x4c, 0x33, 0x37, + 0xbe, 0x59, 0x06, 0xfb, 0xcd, 0x7c, 0x06, 0x83, 0xed, 0x77, 0xf3, 0xe6, 0x9b, 0x59, 0xb0, 0xf3, + 0xad, 0x00, 0xa6, 0x41, 0xa4, 0x6d, 0x43, 0x55, 0xd2, 0xc8, 0x6f, 0xc1, 0x5a, 0xe8, 0xfb, 0x71, + 0xd2, 0x89, 0x8a, 0x0e, 0xe4, 0xf2, 0x3f, 0xdb, 0xac, 0x72, 0xb0, 0x48, 0x06, 0x4f, 0xf2, 0xbd, + 0x48, 0x59, 0xfc, 0x0d, 0x44, 0x0e, 0x77, 0x1b, 0xbf, 0x5b, 0x4f, 0xff, 0xb7, 0xfb, 0xbf, 0x01, + 0x00, 0x00, 0xff, 0xff, 0x35, 0x9f, 0x30, 0x98, 0xf2, 0x2b, 0x00, 0x00, } diff --git a/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto b/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto old mode 100755 new mode 100644 index e76f126ff..497b4d9a9 --- a/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto +++ b/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto @@ -529,6 +529,16 @@ message BeginTransactionRequest { required string app = 1; optional bool allow_multiple_eg = 2 [default = false]; + optional string database_id = 4; + + enum TransactionMode { + UNKNOWN = 0; + READ_ONLY = 1; + READ_WRITE = 2; + } + optional TransactionMode mode = 5 [default = UNKNOWN]; + + optional Transaction previous_transaction = 7; } message CommitResponse { diff --git a/vendor/google.golang.org/appengine/internal/identity_classic.go b/vendor/google.golang.org/appengine/internal/identity_classic.go index e6b9227c5..b59603f13 100644 --- a/vendor/google.golang.org/appengine/internal/identity_classic.go +++ b/vendor/google.golang.org/appengine/internal/identity_classic.go @@ -13,15 +13,45 @@ import ( ) func DefaultVersionHostname(ctx netcontext.Context) string { - return appengine.DefaultVersionHostname(fromContext(ctx)) + c := fromContext(ctx) + if c == nil { + panic(errNotAppEngineContext) + } + return appengine.DefaultVersionHostname(c) } -func RequestID(ctx netcontext.Context) string { return appengine.RequestID(fromContext(ctx)) } -func Datacenter(_ netcontext.Context) string { return appengine.Datacenter() } -func ServerSoftware() string { return appengine.ServerSoftware() } -func ModuleName(ctx netcontext.Context) string { return appengine.ModuleName(fromContext(ctx)) } -func VersionID(ctx netcontext.Context) string { return appengine.VersionID(fromContext(ctx)) } -func InstanceID() string { return appengine.InstanceID() } -func IsDevAppServer() bool { return appengine.IsDevAppServer() } +func Datacenter(_ netcontext.Context) string { return appengine.Datacenter() } +func ServerSoftware() string { return appengine.ServerSoftware() } +func InstanceID() string { return appengine.InstanceID() } +func IsDevAppServer() bool { return appengine.IsDevAppServer() } -func fullyQualifiedAppID(ctx netcontext.Context) string { return fromContext(ctx).FullyQualifiedAppID() } +func RequestID(ctx netcontext.Context) string { + c := fromContext(ctx) + if c == nil { + panic(errNotAppEngineContext) + } + return appengine.RequestID(c) +} + +func ModuleName(ctx netcontext.Context) string { + c := fromContext(ctx) + if c == nil { + panic(errNotAppEngineContext) + } + return appengine.ModuleName(c) +} +func VersionID(ctx netcontext.Context) string { + c := fromContext(ctx) + if c == nil { + panic(errNotAppEngineContext) + } + return appengine.VersionID(c) +} + +func fullyQualifiedAppID(ctx netcontext.Context) string { + c := fromContext(ctx) + if c == nil { + panic(errNotAppEngineContext) + } + return c.FullyQualifiedAppID() +} diff --git a/vendor/google.golang.org/appengine/internal/identity_vm.go b/vendor/google.golang.org/appengine/internal/identity_vm.go index ebe68b785..d5fa75be7 100644 --- a/vendor/google.golang.org/appengine/internal/identity_vm.go +++ b/vendor/google.golang.org/appengine/internal/identity_vm.go @@ -23,7 +23,11 @@ const ( ) func ctxHeaders(ctx netcontext.Context) http.Header { - return fromContext(ctx).Request().Header + c := fromContext(ctx) + if c == nil { + return nil + } + return c.Request().Header } func DefaultVersionHostname(ctx netcontext.Context) string { diff --git a/vendor/google.golang.org/appengine/internal/internal.go b/vendor/google.golang.org/appengine/internal/internal.go index 66e8d7686..051ea3980 100644 --- a/vendor/google.golang.org/appengine/internal/internal.go +++ b/vendor/google.golang.org/appengine/internal/internal.go @@ -10,11 +10,6 @@ package internal import ( "fmt" - "io" - "log" - "net/http" - "net/url" - "os" "github.com/golang/protobuf/proto" @@ -109,35 +104,6 @@ func (e *CallError) IsTimeout() bool { return e.Timeout } -func Main() { - installHealthChecker(http.DefaultServeMux) - - port := "8080" - if s := os.Getenv("PORT"); s != "" { - port = s - } - - if err := http.ListenAndServe(":"+port, http.HandlerFunc(handleHTTP)); err != nil { - log.Fatalf("http.ListenAndServe: %v", err) - } -} - -func installHealthChecker(mux *http.ServeMux) { - // If no health check handler has been installed by this point, add a trivial one. - const healthPath = "/_ah/health" - hreq := &http.Request{ - Method: "GET", - URL: &url.URL{ - Path: healthPath, - }, - } - if _, pat := mux.Handler(hreq); pat != healthPath { - mux.HandleFunc(healthPath, func(w http.ResponseWriter, r *http.Request) { - io.WriteString(w, "ok") - }) - } -} - // NamespaceMods is a map from API service to a function that will mutate an RPC request to attach a namespace. // The function should be prepared to be called on the same message more than once; it should only modify the // RPC request the first time. diff --git a/vendor/google.golang.org/appengine/internal/internal_test.go b/vendor/google.golang.org/appengine/internal/internal_test.go deleted file mode 100644 index dc684f50b..000000000 --- a/vendor/google.golang.org/appengine/internal/internal_test.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2014 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -package internal - -import ( - "io" - "io/ioutil" - "net/http" - "net/http/httptest" - "testing" -) - -func TestInstallingHealthChecker(t *testing.T) { - try := func(desc string, mux *http.ServeMux, wantCode int, wantBody string) { - installHealthChecker(mux) - srv := httptest.NewServer(mux) - defer srv.Close() - - resp, err := http.Get(srv.URL + "/_ah/health") - if err != nil { - t.Errorf("%s: http.Get: %v", desc, err) - return - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Errorf("%s: reading body: %v", desc, err) - return - } - - if resp.StatusCode != wantCode { - t.Errorf("%s: got HTTP %d, want %d", desc, resp.StatusCode, wantCode) - return - } - if wantBody != "" && string(body) != wantBody { - t.Errorf("%s: got HTTP body %q, want %q", desc, body, wantBody) - return - } - } - - // If there's no handlers, or only a root handler, a health checker should be installed. - try("empty mux", http.NewServeMux(), 200, "ok") - mux := http.NewServeMux() - mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - io.WriteString(w, "root handler") - }) - try("mux with root handler", mux, 200, "ok") - - // If there's a custom health check handler, one should not be installed. - mux = http.NewServeMux() - mux.HandleFunc("/_ah/health", func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(418) - io.WriteString(w, "I'm short and stout!") - }) - try("mux with custom health checker", mux, 418, "I'm short and stout!") -} diff --git a/vendor/google.golang.org/appengine/internal/log/log_service.pb.go b/vendor/google.golang.org/appengine/internal/log/log_service.pb.go index 20c595be3..5549605ad 100644 --- a/vendor/google.golang.org/appengine/internal/log/log_service.pb.go +++ b/vendor/google.golang.org/appengine/internal/log/log_service.pb.go @@ -1,6 +1,5 @@ -// Code generated by protoc-gen-go. +// Code generated by protoc-gen-go. DO NOT EDIT. // source: google.golang.org/appengine/internal/log/log_service.proto -// DO NOT EDIT! /* Package log is a generated protocol buffer package. @@ -35,6 +34,12 @@ var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + type LogServiceError_ErrorCode int32 const ( @@ -70,25 +75,28 @@ func (x *LogServiceError_ErrorCode) UnmarshalJSON(data []byte) error { *x = LogServiceError_ErrorCode(value) return nil } +func (LogServiceError_ErrorCode) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} } type LogServiceError struct { XXX_unrecognized []byte `json:"-"` } -func (m *LogServiceError) Reset() { *m = LogServiceError{} } -func (m *LogServiceError) String() string { return proto.CompactTextString(m) } -func (*LogServiceError) ProtoMessage() {} +func (m *LogServiceError) Reset() { *m = LogServiceError{} } +func (m *LogServiceError) String() string { return proto.CompactTextString(m) } +func (*LogServiceError) ProtoMessage() {} +func (*LogServiceError) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } type UserAppLogLine struct { - TimestampUsec *int64 `protobuf:"varint,1,req,name=timestamp_usec" json:"timestamp_usec,omitempty"` + TimestampUsec *int64 `protobuf:"varint,1,req,name=timestamp_usec,json=timestampUsec" json:"timestamp_usec,omitempty"` Level *int64 `protobuf:"varint,2,req,name=level" json:"level,omitempty"` Message *string `protobuf:"bytes,3,req,name=message" json:"message,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *UserAppLogLine) Reset() { *m = UserAppLogLine{} } -func (m *UserAppLogLine) String() string { return proto.CompactTextString(m) } -func (*UserAppLogLine) ProtoMessage() {} +func (m *UserAppLogLine) Reset() { *m = UserAppLogLine{} } +func (m *UserAppLogLine) String() string { return proto.CompactTextString(m) } +func (*UserAppLogLine) ProtoMessage() {} +func (*UserAppLogLine) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } func (m *UserAppLogLine) GetTimestampUsec() int64 { if m != nil && m.TimestampUsec != nil { @@ -112,13 +120,14 @@ func (m *UserAppLogLine) GetMessage() string { } type UserAppLogGroup struct { - LogLine []*UserAppLogLine `protobuf:"bytes,2,rep,name=log_line" json:"log_line,omitempty"` + LogLine []*UserAppLogLine `protobuf:"bytes,2,rep,name=log_line,json=logLine" json:"log_line,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *UserAppLogGroup) Reset() { *m = UserAppLogGroup{} } -func (m *UserAppLogGroup) String() string { return proto.CompactTextString(m) } -func (*UserAppLogGroup) ProtoMessage() {} +func (m *UserAppLogGroup) Reset() { *m = UserAppLogGroup{} } +func (m *UserAppLogGroup) String() string { return proto.CompactTextString(m) } +func (*UserAppLogGroup) ProtoMessage() {} +func (*UserAppLogGroup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } func (m *UserAppLogGroup) GetLogLine() []*UserAppLogLine { if m != nil { @@ -132,9 +141,10 @@ type FlushRequest struct { XXX_unrecognized []byte `json:"-"` } -func (m *FlushRequest) Reset() { *m = FlushRequest{} } -func (m *FlushRequest) String() string { return proto.CompactTextString(m) } -func (*FlushRequest) ProtoMessage() {} +func (m *FlushRequest) Reset() { *m = FlushRequest{} } +func (m *FlushRequest) String() string { return proto.CompactTextString(m) } +func (*FlushRequest) ProtoMessage() {} +func (*FlushRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } func (m *FlushRequest) GetLogs() []byte { if m != nil { @@ -148,9 +158,10 @@ type SetStatusRequest struct { XXX_unrecognized []byte `json:"-"` } -func (m *SetStatusRequest) Reset() { *m = SetStatusRequest{} } -func (m *SetStatusRequest) String() string { return proto.CompactTextString(m) } -func (*SetStatusRequest) ProtoMessage() {} +func (m *SetStatusRequest) Reset() { *m = SetStatusRequest{} } +func (m *SetStatusRequest) String() string { return proto.CompactTextString(m) } +func (*SetStatusRequest) ProtoMessage() {} +func (*SetStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } func (m *SetStatusRequest) GetStatus() string { if m != nil && m.Status != nil { @@ -160,13 +171,14 @@ func (m *SetStatusRequest) GetStatus() string { } type LogOffset struct { - RequestId []byte `protobuf:"bytes,1,opt,name=request_id" json:"request_id,omitempty"` + RequestId []byte `protobuf:"bytes,1,opt,name=request_id,json=requestId" json:"request_id,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *LogOffset) Reset() { *m = LogOffset{} } -func (m *LogOffset) String() string { return proto.CompactTextString(m) } -func (*LogOffset) ProtoMessage() {} +func (m *LogOffset) Reset() { *m = LogOffset{} } +func (m *LogOffset) String() string { return proto.CompactTextString(m) } +func (*LogOffset) ProtoMessage() {} +func (*LogOffset) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } func (m *LogOffset) GetRequestId() []byte { if m != nil { @@ -178,13 +190,14 @@ func (m *LogOffset) GetRequestId() []byte { type LogLine struct { Time *int64 `protobuf:"varint,1,req,name=time" json:"time,omitempty"` Level *int32 `protobuf:"varint,2,req,name=level" json:"level,omitempty"` - LogMessage *string `protobuf:"bytes,3,req,name=log_message" json:"log_message,omitempty"` + LogMessage *string `protobuf:"bytes,3,req,name=log_message,json=logMessage" json:"log_message,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *LogLine) Reset() { *m = LogLine{} } -func (m *LogLine) String() string { return proto.CompactTextString(m) } -func (*LogLine) ProtoMessage() {} +func (m *LogLine) Reset() { *m = LogLine{} } +func (m *LogLine) String() string { return proto.CompactTextString(m) } +func (*LogLine) ProtoMessage() {} +func (*LogLine) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } func (m *LogLine) GetTime() int64 { if m != nil && m.Time != nil { @@ -208,50 +221,51 @@ func (m *LogLine) GetLogMessage() string { } type RequestLog struct { - AppId *string `protobuf:"bytes,1,req,name=app_id" json:"app_id,omitempty"` - ModuleId *string `protobuf:"bytes,37,opt,name=module_id,def=default" json:"module_id,omitempty"` - VersionId *string `protobuf:"bytes,2,req,name=version_id" json:"version_id,omitempty"` - RequestId []byte `protobuf:"bytes,3,req,name=request_id" json:"request_id,omitempty"` + AppId *string `protobuf:"bytes,1,req,name=app_id,json=appId" json:"app_id,omitempty"` + ModuleId *string `protobuf:"bytes,37,opt,name=module_id,json=moduleId,def=default" json:"module_id,omitempty"` + VersionId *string `protobuf:"bytes,2,req,name=version_id,json=versionId" json:"version_id,omitempty"` + RequestId []byte `protobuf:"bytes,3,req,name=request_id,json=requestId" json:"request_id,omitempty"` Offset *LogOffset `protobuf:"bytes,35,opt,name=offset" json:"offset,omitempty"` Ip *string `protobuf:"bytes,4,req,name=ip" json:"ip,omitempty"` Nickname *string `protobuf:"bytes,5,opt,name=nickname" json:"nickname,omitempty"` - StartTime *int64 `protobuf:"varint,6,req,name=start_time" json:"start_time,omitempty"` - EndTime *int64 `protobuf:"varint,7,req,name=end_time" json:"end_time,omitempty"` + StartTime *int64 `protobuf:"varint,6,req,name=start_time,json=startTime" json:"start_time,omitempty"` + EndTime *int64 `protobuf:"varint,7,req,name=end_time,json=endTime" json:"end_time,omitempty"` Latency *int64 `protobuf:"varint,8,req,name=latency" json:"latency,omitempty"` Mcycles *int64 `protobuf:"varint,9,req,name=mcycles" json:"mcycles,omitempty"` Method *string `protobuf:"bytes,10,req,name=method" json:"method,omitempty"` Resource *string `protobuf:"bytes,11,req,name=resource" json:"resource,omitempty"` - HttpVersion *string `protobuf:"bytes,12,req,name=http_version" json:"http_version,omitempty"` + HttpVersion *string `protobuf:"bytes,12,req,name=http_version,json=httpVersion" json:"http_version,omitempty"` Status *int32 `protobuf:"varint,13,req,name=status" json:"status,omitempty"` - ResponseSize *int64 `protobuf:"varint,14,req,name=response_size" json:"response_size,omitempty"` + ResponseSize *int64 `protobuf:"varint,14,req,name=response_size,json=responseSize" json:"response_size,omitempty"` Referrer *string `protobuf:"bytes,15,opt,name=referrer" json:"referrer,omitempty"` - UserAgent *string `protobuf:"bytes,16,opt,name=user_agent" json:"user_agent,omitempty"` - UrlMapEntry *string `protobuf:"bytes,17,req,name=url_map_entry" json:"url_map_entry,omitempty"` + UserAgent *string `protobuf:"bytes,16,opt,name=user_agent,json=userAgent" json:"user_agent,omitempty"` + UrlMapEntry *string `protobuf:"bytes,17,req,name=url_map_entry,json=urlMapEntry" json:"url_map_entry,omitempty"` Combined *string `protobuf:"bytes,18,req,name=combined" json:"combined,omitempty"` - ApiMcycles *int64 `protobuf:"varint,19,opt,name=api_mcycles" json:"api_mcycles,omitempty"` + ApiMcycles *int64 `protobuf:"varint,19,opt,name=api_mcycles,json=apiMcycles" json:"api_mcycles,omitempty"` Host *string `protobuf:"bytes,20,opt,name=host" json:"host,omitempty"` Cost *float64 `protobuf:"fixed64,21,opt,name=cost" json:"cost,omitempty"` - TaskQueueName *string `protobuf:"bytes,22,opt,name=task_queue_name" json:"task_queue_name,omitempty"` - TaskName *string `protobuf:"bytes,23,opt,name=task_name" json:"task_name,omitempty"` - WasLoadingRequest *bool `protobuf:"varint,24,opt,name=was_loading_request" json:"was_loading_request,omitempty"` - PendingTime *int64 `protobuf:"varint,25,opt,name=pending_time" json:"pending_time,omitempty"` - ReplicaIndex *int32 `protobuf:"varint,26,opt,name=replica_index,def=-1" json:"replica_index,omitempty"` + TaskQueueName *string `protobuf:"bytes,22,opt,name=task_queue_name,json=taskQueueName" json:"task_queue_name,omitempty"` + TaskName *string `protobuf:"bytes,23,opt,name=task_name,json=taskName" json:"task_name,omitempty"` + WasLoadingRequest *bool `protobuf:"varint,24,opt,name=was_loading_request,json=wasLoadingRequest" json:"was_loading_request,omitempty"` + PendingTime *int64 `protobuf:"varint,25,opt,name=pending_time,json=pendingTime" json:"pending_time,omitempty"` + ReplicaIndex *int32 `protobuf:"varint,26,opt,name=replica_index,json=replicaIndex,def=-1" json:"replica_index,omitempty"` Finished *bool `protobuf:"varint,27,opt,name=finished,def=1" json:"finished,omitempty"` - CloneKey []byte `protobuf:"bytes,28,opt,name=clone_key" json:"clone_key,omitempty"` + CloneKey []byte `protobuf:"bytes,28,opt,name=clone_key,json=cloneKey" json:"clone_key,omitempty"` Line []*LogLine `protobuf:"bytes,29,rep,name=line" json:"line,omitempty"` - LinesIncomplete *bool `protobuf:"varint,36,opt,name=lines_incomplete" json:"lines_incomplete,omitempty"` - AppEngineRelease []byte `protobuf:"bytes,38,opt,name=app_engine_release" json:"app_engine_release,omitempty"` - ExitReason *int32 `protobuf:"varint,30,opt,name=exit_reason" json:"exit_reason,omitempty"` - WasThrottledForTime *bool `protobuf:"varint,31,opt,name=was_throttled_for_time" json:"was_throttled_for_time,omitempty"` - WasThrottledForRequests *bool `protobuf:"varint,32,opt,name=was_throttled_for_requests" json:"was_throttled_for_requests,omitempty"` - ThrottledTime *int64 `protobuf:"varint,33,opt,name=throttled_time" json:"throttled_time,omitempty"` - ServerName []byte `protobuf:"bytes,34,opt,name=server_name" json:"server_name,omitempty"` + LinesIncomplete *bool `protobuf:"varint,36,opt,name=lines_incomplete,json=linesIncomplete" json:"lines_incomplete,omitempty"` + AppEngineRelease []byte `protobuf:"bytes,38,opt,name=app_engine_release,json=appEngineRelease" json:"app_engine_release,omitempty"` + ExitReason *int32 `protobuf:"varint,30,opt,name=exit_reason,json=exitReason" json:"exit_reason,omitempty"` + WasThrottledForTime *bool `protobuf:"varint,31,opt,name=was_throttled_for_time,json=wasThrottledForTime" json:"was_throttled_for_time,omitempty"` + WasThrottledForRequests *bool `protobuf:"varint,32,opt,name=was_throttled_for_requests,json=wasThrottledForRequests" json:"was_throttled_for_requests,omitempty"` + ThrottledTime *int64 `protobuf:"varint,33,opt,name=throttled_time,json=throttledTime" json:"throttled_time,omitempty"` + ServerName []byte `protobuf:"bytes,34,opt,name=server_name,json=serverName" json:"server_name,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *RequestLog) Reset() { *m = RequestLog{} } -func (m *RequestLog) String() string { return proto.CompactTextString(m) } -func (*RequestLog) ProtoMessage() {} +func (m *RequestLog) Reset() { *m = RequestLog{} } +func (m *RequestLog) String() string { return proto.CompactTextString(m) } +func (*RequestLog) ProtoMessage() {} +func (*RequestLog) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } const Default_RequestLog_ModuleId string = "default" const Default_RequestLog_ReplicaIndex int32 = -1 @@ -524,14 +538,15 @@ func (m *RequestLog) GetServerName() []byte { } type LogModuleVersion struct { - ModuleId *string `protobuf:"bytes,1,opt,name=module_id,def=default" json:"module_id,omitempty"` - VersionId *string `protobuf:"bytes,2,opt,name=version_id" json:"version_id,omitempty"` + ModuleId *string `protobuf:"bytes,1,opt,name=module_id,json=moduleId,def=default" json:"module_id,omitempty"` + VersionId *string `protobuf:"bytes,2,opt,name=version_id,json=versionId" json:"version_id,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *LogModuleVersion) Reset() { *m = LogModuleVersion{} } -func (m *LogModuleVersion) String() string { return proto.CompactTextString(m) } -func (*LogModuleVersion) ProtoMessage() {} +func (m *LogModuleVersion) Reset() { *m = LogModuleVersion{} } +func (m *LogModuleVersion) String() string { return proto.CompactTextString(m) } +func (*LogModuleVersion) ProtoMessage() {} +func (*LogModuleVersion) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } const Default_LogModuleVersion_ModuleId string = "default" @@ -550,31 +565,32 @@ func (m *LogModuleVersion) GetVersionId() string { } type LogReadRequest struct { - AppId *string `protobuf:"bytes,1,req,name=app_id" json:"app_id,omitempty"` - VersionId []string `protobuf:"bytes,2,rep,name=version_id" json:"version_id,omitempty"` - ModuleVersion []*LogModuleVersion `protobuf:"bytes,19,rep,name=module_version" json:"module_version,omitempty"` - StartTime *int64 `protobuf:"varint,3,opt,name=start_time" json:"start_time,omitempty"` - EndTime *int64 `protobuf:"varint,4,opt,name=end_time" json:"end_time,omitempty"` + AppId *string `protobuf:"bytes,1,req,name=app_id,json=appId" json:"app_id,omitempty"` + VersionId []string `protobuf:"bytes,2,rep,name=version_id,json=versionId" json:"version_id,omitempty"` + ModuleVersion []*LogModuleVersion `protobuf:"bytes,19,rep,name=module_version,json=moduleVersion" json:"module_version,omitempty"` + StartTime *int64 `protobuf:"varint,3,opt,name=start_time,json=startTime" json:"start_time,omitempty"` + EndTime *int64 `protobuf:"varint,4,opt,name=end_time,json=endTime" json:"end_time,omitempty"` Offset *LogOffset `protobuf:"bytes,5,opt,name=offset" json:"offset,omitempty"` - RequestId [][]byte `protobuf:"bytes,6,rep,name=request_id" json:"request_id,omitempty"` - MinimumLogLevel *int32 `protobuf:"varint,7,opt,name=minimum_log_level" json:"minimum_log_level,omitempty"` - IncludeIncomplete *bool `protobuf:"varint,8,opt,name=include_incomplete" json:"include_incomplete,omitempty"` + RequestId [][]byte `protobuf:"bytes,6,rep,name=request_id,json=requestId" json:"request_id,omitempty"` + MinimumLogLevel *int32 `protobuf:"varint,7,opt,name=minimum_log_level,json=minimumLogLevel" json:"minimum_log_level,omitempty"` + IncludeIncomplete *bool `protobuf:"varint,8,opt,name=include_incomplete,json=includeIncomplete" json:"include_incomplete,omitempty"` Count *int64 `protobuf:"varint,9,opt,name=count" json:"count,omitempty"` - CombinedLogRegex *string `protobuf:"bytes,14,opt,name=combined_log_regex" json:"combined_log_regex,omitempty"` - HostRegex *string `protobuf:"bytes,15,opt,name=host_regex" json:"host_regex,omitempty"` - ReplicaIndex *int32 `protobuf:"varint,16,opt,name=replica_index" json:"replica_index,omitempty"` - IncludeAppLogs *bool `protobuf:"varint,10,opt,name=include_app_logs" json:"include_app_logs,omitempty"` - AppLogsPerRequest *int32 `protobuf:"varint,17,opt,name=app_logs_per_request" json:"app_logs_per_request,omitempty"` - IncludeHost *bool `protobuf:"varint,11,opt,name=include_host" json:"include_host,omitempty"` - IncludeAll *bool `protobuf:"varint,12,opt,name=include_all" json:"include_all,omitempty"` - CacheIterator *bool `protobuf:"varint,13,opt,name=cache_iterator" json:"cache_iterator,omitempty"` - NumShards *int32 `protobuf:"varint,18,opt,name=num_shards" json:"num_shards,omitempty"` + CombinedLogRegex *string `protobuf:"bytes,14,opt,name=combined_log_regex,json=combinedLogRegex" json:"combined_log_regex,omitempty"` + HostRegex *string `protobuf:"bytes,15,opt,name=host_regex,json=hostRegex" json:"host_regex,omitempty"` + ReplicaIndex *int32 `protobuf:"varint,16,opt,name=replica_index,json=replicaIndex" json:"replica_index,omitempty"` + IncludeAppLogs *bool `protobuf:"varint,10,opt,name=include_app_logs,json=includeAppLogs" json:"include_app_logs,omitempty"` + AppLogsPerRequest *int32 `protobuf:"varint,17,opt,name=app_logs_per_request,json=appLogsPerRequest" json:"app_logs_per_request,omitempty"` + IncludeHost *bool `protobuf:"varint,11,opt,name=include_host,json=includeHost" json:"include_host,omitempty"` + IncludeAll *bool `protobuf:"varint,12,opt,name=include_all,json=includeAll" json:"include_all,omitempty"` + CacheIterator *bool `protobuf:"varint,13,opt,name=cache_iterator,json=cacheIterator" json:"cache_iterator,omitempty"` + NumShards *int32 `protobuf:"varint,18,opt,name=num_shards,json=numShards" json:"num_shards,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *LogReadRequest) Reset() { *m = LogReadRequest{} } -func (m *LogReadRequest) String() string { return proto.CompactTextString(m) } -func (*LogReadRequest) ProtoMessage() {} +func (m *LogReadRequest) Reset() { *m = LogReadRequest{} } +func (m *LogReadRequest) String() string { return proto.CompactTextString(m) } +func (*LogReadRequest) ProtoMessage() {} +func (*LogReadRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } func (m *LogReadRequest) GetAppId() string { if m != nil && m.AppId != nil { @@ -712,13 +728,14 @@ func (m *LogReadRequest) GetNumShards() int32 { type LogReadResponse struct { Log []*RequestLog `protobuf:"bytes,1,rep,name=log" json:"log,omitempty"` Offset *LogOffset `protobuf:"bytes,2,opt,name=offset" json:"offset,omitempty"` - LastEndTime *int64 `protobuf:"varint,3,opt,name=last_end_time" json:"last_end_time,omitempty"` + LastEndTime *int64 `protobuf:"varint,3,opt,name=last_end_time,json=lastEndTime" json:"last_end_time,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *LogReadResponse) Reset() { *m = LogReadResponse{} } -func (m *LogReadResponse) String() string { return proto.CompactTextString(m) } -func (*LogReadResponse) ProtoMessage() {} +func (m *LogReadResponse) Reset() { *m = LogReadResponse{} } +func (m *LogReadResponse) String() string { return proto.CompactTextString(m) } +func (*LogReadResponse) ProtoMessage() {} +func (*LogReadResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } func (m *LogReadResponse) GetLog() []*RequestLog { if m != nil { @@ -742,18 +759,19 @@ func (m *LogReadResponse) GetLastEndTime() int64 { } type LogUsageRecord struct { - VersionId *string `protobuf:"bytes,1,opt,name=version_id" json:"version_id,omitempty"` - StartTime *int32 `protobuf:"varint,2,opt,name=start_time" json:"start_time,omitempty"` - EndTime *int32 `protobuf:"varint,3,opt,name=end_time" json:"end_time,omitempty"` + VersionId *string `protobuf:"bytes,1,opt,name=version_id,json=versionId" json:"version_id,omitempty"` + StartTime *int32 `protobuf:"varint,2,opt,name=start_time,json=startTime" json:"start_time,omitempty"` + EndTime *int32 `protobuf:"varint,3,opt,name=end_time,json=endTime" json:"end_time,omitempty"` Count *int64 `protobuf:"varint,4,opt,name=count" json:"count,omitempty"` - TotalSize *int64 `protobuf:"varint,5,opt,name=total_size" json:"total_size,omitempty"` + TotalSize *int64 `protobuf:"varint,5,opt,name=total_size,json=totalSize" json:"total_size,omitempty"` Records *int32 `protobuf:"varint,6,opt,name=records" json:"records,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *LogUsageRecord) Reset() { *m = LogUsageRecord{} } -func (m *LogUsageRecord) String() string { return proto.CompactTextString(m) } -func (*LogUsageRecord) ProtoMessage() {} +func (m *LogUsageRecord) Reset() { *m = LogUsageRecord{} } +func (m *LogUsageRecord) String() string { return proto.CompactTextString(m) } +func (*LogUsageRecord) ProtoMessage() {} +func (*LogUsageRecord) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } func (m *LogUsageRecord) GetVersionId() string { if m != nil && m.VersionId != nil { @@ -798,20 +816,21 @@ func (m *LogUsageRecord) GetRecords() int32 { } type LogUsageRequest struct { - AppId *string `protobuf:"bytes,1,req,name=app_id" json:"app_id,omitempty"` - VersionId []string `protobuf:"bytes,2,rep,name=version_id" json:"version_id,omitempty"` - StartTime *int32 `protobuf:"varint,3,opt,name=start_time" json:"start_time,omitempty"` - EndTime *int32 `protobuf:"varint,4,opt,name=end_time" json:"end_time,omitempty"` - ResolutionHours *uint32 `protobuf:"varint,5,opt,name=resolution_hours,def=1" json:"resolution_hours,omitempty"` - CombineVersions *bool `protobuf:"varint,6,opt,name=combine_versions" json:"combine_versions,omitempty"` - UsageVersion *int32 `protobuf:"varint,7,opt,name=usage_version" json:"usage_version,omitempty"` - VersionsOnly *bool `protobuf:"varint,8,opt,name=versions_only" json:"versions_only,omitempty"` + AppId *string `protobuf:"bytes,1,req,name=app_id,json=appId" json:"app_id,omitempty"` + VersionId []string `protobuf:"bytes,2,rep,name=version_id,json=versionId" json:"version_id,omitempty"` + StartTime *int32 `protobuf:"varint,3,opt,name=start_time,json=startTime" json:"start_time,omitempty"` + EndTime *int32 `protobuf:"varint,4,opt,name=end_time,json=endTime" json:"end_time,omitempty"` + ResolutionHours *uint32 `protobuf:"varint,5,opt,name=resolution_hours,json=resolutionHours,def=1" json:"resolution_hours,omitempty"` + CombineVersions *bool `protobuf:"varint,6,opt,name=combine_versions,json=combineVersions" json:"combine_versions,omitempty"` + UsageVersion *int32 `protobuf:"varint,7,opt,name=usage_version,json=usageVersion" json:"usage_version,omitempty"` + VersionsOnly *bool `protobuf:"varint,8,opt,name=versions_only,json=versionsOnly" json:"versions_only,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *LogUsageRequest) Reset() { *m = LogUsageRequest{} } -func (m *LogUsageRequest) String() string { return proto.CompactTextString(m) } -func (*LogUsageRequest) ProtoMessage() {} +func (m *LogUsageRequest) Reset() { *m = LogUsageRequest{} } +func (m *LogUsageRequest) String() string { return proto.CompactTextString(m) } +func (*LogUsageRequest) ProtoMessage() {} +func (*LogUsageRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } const Default_LogUsageRequest_ResolutionHours uint32 = 1 @@ -877,9 +896,10 @@ type LogUsageResponse struct { XXX_unrecognized []byte `json:"-"` } -func (m *LogUsageResponse) Reset() { *m = LogUsageResponse{} } -func (m *LogUsageResponse) String() string { return proto.CompactTextString(m) } -func (*LogUsageResponse) ProtoMessage() {} +func (m *LogUsageResponse) Reset() { *m = LogUsageResponse{} } +func (m *LogUsageResponse) String() string { return proto.CompactTextString(m) } +func (*LogUsageResponse) ProtoMessage() {} +func (*LogUsageResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } func (m *LogUsageResponse) GetUsage() []*LogUsageRecord { if m != nil { @@ -896,4 +916,124 @@ func (m *LogUsageResponse) GetSummary() *LogUsageRecord { } func init() { + proto.RegisterType((*LogServiceError)(nil), "appengine.LogServiceError") + proto.RegisterType((*UserAppLogLine)(nil), "appengine.UserAppLogLine") + proto.RegisterType((*UserAppLogGroup)(nil), "appengine.UserAppLogGroup") + proto.RegisterType((*FlushRequest)(nil), "appengine.FlushRequest") + proto.RegisterType((*SetStatusRequest)(nil), "appengine.SetStatusRequest") + proto.RegisterType((*LogOffset)(nil), "appengine.LogOffset") + proto.RegisterType((*LogLine)(nil), "appengine.LogLine") + proto.RegisterType((*RequestLog)(nil), "appengine.RequestLog") + proto.RegisterType((*LogModuleVersion)(nil), "appengine.LogModuleVersion") + proto.RegisterType((*LogReadRequest)(nil), "appengine.LogReadRequest") + proto.RegisterType((*LogReadResponse)(nil), "appengine.LogReadResponse") + proto.RegisterType((*LogUsageRecord)(nil), "appengine.LogUsageRecord") + proto.RegisterType((*LogUsageRequest)(nil), "appengine.LogUsageRequest") + proto.RegisterType((*LogUsageResponse)(nil), "appengine.LogUsageResponse") +} + +func init() { + proto.RegisterFile("google.golang.org/appengine/internal/log/log_service.proto", fileDescriptor0) +} + +var fileDescriptor0 = []byte{ + // 1553 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xdd, 0x72, 0xdb, 0xc6, + 0x15, 0x2e, 0x48, 0x51, 0x24, 0x0f, 0x49, 0x91, 0x5a, 0xcb, 0xce, 0xda, 0xae, 0x6b, 0x1a, 0x4e, + 0x1c, 0xd6, 0x93, 0x48, 0x93, 0xa4, 0x57, 0xca, 0x95, 0xd3, 0x2a, 0x8e, 0x26, 0xb4, 0xd5, 0x40, + 0x72, 0x3a, 0xd3, 0x1b, 0x0c, 0x0a, 0x1c, 0x81, 0x18, 0x2f, 0xb1, 0xc8, 0xee, 0xc2, 0x91, 0x72, + 0xdb, 0xdb, 0x3e, 0x46, 0x1f, 0xa2, 0xaf, 0xd2, 0xb7, 0xe9, 0xec, 0xd9, 0x05, 0x44, 0x2a, 0x4d, + 0xc6, 0x33, 0xb9, 0xe0, 0x10, 0xfb, 0x9d, 0x83, 0xdd, 0xf3, 0xf3, 0x9d, 0x6f, 0x01, 0xc7, 0xb9, + 0x94, 0xb9, 0xc0, 0xc3, 0x5c, 0x8a, 0xa4, 0xcc, 0x0f, 0xa5, 0xca, 0x8f, 0x92, 0xaa, 0xc2, 0x32, + 0x2f, 0x4a, 0x3c, 0x2a, 0x4a, 0x83, 0xaa, 0x4c, 0xc4, 0x91, 0x90, 0xb9, 0xfd, 0xc5, 0x1a, 0xd5, + 0xbb, 0x22, 0xc5, 0xc3, 0x4a, 0x49, 0x23, 0xd9, 0xb0, 0xf5, 0x0c, 0x5f, 0xc3, 0x74, 0x29, 0xf3, + 0x73, 0x67, 0x3e, 0x51, 0x4a, 0xaa, 0xf0, 0x4b, 0x18, 0xd2, 0xc3, 0x9f, 0x65, 0x86, 0x6c, 0x17, + 0x3a, 0x67, 0xdf, 0xce, 0x7e, 0xc7, 0xee, 0xc0, 0xf4, 0xf4, 0xf5, 0xf7, 0x2f, 0x96, 0xa7, 0x7f, + 0x89, 0xa3, 0x93, 0xef, 0xde, 0x9c, 0x9c, 0x5f, 0xcc, 0x02, 0xb6, 0x0f, 0x93, 0xf3, 0x8b, 0xb3, + 0xe8, 0xc5, 0xcb, 0x93, 0xf8, 0x24, 0x8a, 0xce, 0xa2, 0x59, 0x27, 0xcc, 0x61, 0xef, 0x8d, 0x46, + 0xf5, 0xa2, 0xaa, 0x96, 0x32, 0x5f, 0x16, 0x25, 0xb2, 0x8f, 0x60, 0xcf, 0x14, 0x6b, 0xd4, 0x26, + 0x59, 0x57, 0x71, 0xad, 0x31, 0xe5, 0xc1, 0xbc, 0xb3, 0xe8, 0x46, 0x93, 0x16, 0x7d, 0xa3, 0x31, + 0x65, 0x07, 0xd0, 0x13, 0xf8, 0x0e, 0x05, 0xef, 0x90, 0xd5, 0x2d, 0x18, 0x87, 0xfe, 0x1a, 0xb5, + 0x4e, 0x72, 0xe4, 0xdd, 0x79, 0x67, 0x31, 0x8c, 0x9a, 0x65, 0xf8, 0x12, 0xa6, 0x37, 0x07, 0xbd, + 0x54, 0xb2, 0xae, 0xd8, 0x9f, 0x60, 0x60, 0x73, 0x15, 0x45, 0x89, 0xbc, 0x33, 0xef, 0x2e, 0x46, + 0x9f, 0xdf, 0x3f, 0x6c, 0x33, 0x3d, 0xdc, 0x0e, 0x2b, 0xea, 0x0b, 0xf7, 0x10, 0x86, 0x30, 0xfe, + 0x5a, 0xd4, 0x7a, 0x15, 0xe1, 0x0f, 0x35, 0x6a, 0xc3, 0x18, 0xec, 0x08, 0x99, 0x6b, 0x1e, 0xcc, + 0x83, 0xc5, 0x38, 0xa2, 0xe7, 0xf0, 0x39, 0xcc, 0xce, 0xd1, 0x9c, 0x9b, 0xc4, 0xd4, 0xba, 0xf1, + 0xbb, 0x07, 0xbb, 0x9a, 0x00, 0xca, 0x67, 0x18, 0xf9, 0x55, 0xf8, 0x1c, 0x86, 0x4b, 0x99, 0x9f, + 0x5d, 0x5e, 0x6a, 0x34, 0xec, 0x11, 0x80, 0x72, 0xfe, 0x71, 0x91, 0xf9, 0x2d, 0x87, 0x1e, 0x39, + 0xcd, 0xc2, 0x0b, 0xe8, 0x37, 0x65, 0x62, 0xb0, 0x63, 0x0b, 0xe2, 0x8b, 0x43, 0xcf, 0xdb, 0x35, + 0xe9, 0x35, 0x35, 0x79, 0x0c, 0x23, 0x9b, 0xe6, 0x76, 0x5d, 0x40, 0xc8, 0xfc, 0x95, 0x2f, 0xcd, + 0x3f, 0x01, 0xc0, 0x47, 0xb9, 0x94, 0x39, 0xbb, 0x0b, 0xbb, 0x49, 0x55, 0xb9, 0xf3, 0xad, 0x6b, + 0x2f, 0xa9, 0xaa, 0xd3, 0x8c, 0x7d, 0x08, 0xc3, 0xb5, 0xcc, 0x6a, 0x81, 0xd6, 0xf2, 0xd1, 0x3c, + 0x58, 0x0c, 0x8f, 0xfb, 0x19, 0x5e, 0x26, 0xb5, 0x30, 0xd1, 0xc0, 0x59, 0x4e, 0x33, 0x9b, 0xc0, + 0x3b, 0x54, 0xba, 0x90, 0xa5, 0x75, 0xeb, 0xd0, 0x06, 0x43, 0x8f, 0x38, 0xf3, 0x46, 0x7e, 0x36, + 0x94, 0xcd, 0xfc, 0xd8, 0x27, 0xb0, 0x2b, 0xa9, 0x10, 0xfc, 0xe9, 0x3c, 0x58, 0x8c, 0x3e, 0x3f, + 0xd8, 0xe8, 0x47, 0x5b, 0xa4, 0xc8, 0xfb, 0xb0, 0x3d, 0xe8, 0x14, 0x15, 0xdf, 0xa1, 0x33, 0x3a, + 0x45, 0xc5, 0x1e, 0xc0, 0xa0, 0x2c, 0xd2, 0xb7, 0x65, 0xb2, 0x46, 0xde, 0xb3, 0x01, 0x46, 0xed, + 0xda, 0x1e, 0xac, 0x4d, 0xa2, 0x4c, 0x4c, 0x45, 0xdb, 0xa5, 0xa2, 0x0d, 0x09, 0xb9, 0xb0, 0x95, + 0xbb, 0x0f, 0x03, 0x2c, 0x33, 0x67, 0xec, 0x93, 0xb1, 0x8f, 0x65, 0x46, 0x26, 0x0e, 0x7d, 0x91, + 0x18, 0x2c, 0xd3, 0x6b, 0x3e, 0x70, 0x16, 0xbf, 0x24, 0xb2, 0xa5, 0xd7, 0xa9, 0x40, 0xcd, 0x87, + 0xce, 0xe2, 0x97, 0xb6, 0xd7, 0x6b, 0x34, 0x2b, 0x99, 0x71, 0x70, 0xbd, 0x76, 0x2b, 0x1b, 0xa1, + 0x42, 0x2d, 0x6b, 0x95, 0x22, 0x1f, 0x91, 0xa5, 0x5d, 0xb3, 0x27, 0x30, 0x5e, 0x19, 0x53, 0xc5, + 0xbe, 0x58, 0x7c, 0x4c, 0xf6, 0x91, 0xc5, 0xbe, 0x77, 0xd0, 0x06, 0x85, 0x26, 0xd4, 0x60, 0xbf, + 0x62, 0x4f, 0x61, 0xa2, 0x50, 0x57, 0xb2, 0xd4, 0x18, 0xeb, 0xe2, 0x27, 0xe4, 0x7b, 0x14, 0xce, + 0xb8, 0x01, 0xcf, 0x8b, 0x9f, 0xd0, 0x9d, 0x7d, 0x89, 0x4a, 0xa1, 0xe2, 0x53, 0x57, 0x9d, 0x66, + 0x6d, 0xab, 0x53, 0x6b, 0x54, 0x71, 0x92, 0x63, 0x69, 0xf8, 0x8c, 0xac, 0x43, 0x8b, 0xbc, 0xb0, + 0x00, 0x0b, 0x61, 0x52, 0x2b, 0x11, 0xaf, 0x93, 0x2a, 0xc6, 0xd2, 0xa8, 0x6b, 0xbe, 0xef, 0x62, + 0xab, 0x95, 0x78, 0x95, 0x54, 0x27, 0x16, 0xb2, 0xdb, 0xa7, 0x72, 0xfd, 0x8f, 0xa2, 0xc4, 0x8c, + 0x33, 0x97, 0x5a, 0xb3, 0xb6, 0x0c, 0x4c, 0xaa, 0x22, 0x6e, 0x8a, 0x75, 0x67, 0x1e, 0x2c, 0xba, + 0x11, 0x24, 0x55, 0xf1, 0xca, 0xd7, 0x8b, 0xc1, 0xce, 0x4a, 0x6a, 0xc3, 0x0f, 0xe8, 0x64, 0x7a, + 0xb6, 0x58, 0x6a, 0xb1, 0xbb, 0xf3, 0x60, 0x11, 0x44, 0xf4, 0xcc, 0x9e, 0xc1, 0xd4, 0x24, 0xfa, + 0x6d, 0xfc, 0x43, 0x8d, 0x35, 0xc6, 0xd4, 0xe8, 0x7b, 0xf4, 0xca, 0xc4, 0xc2, 0xdf, 0x59, 0xf4, + 0xb5, 0xed, 0xf6, 0x43, 0x18, 0x92, 0x1f, 0x79, 0x7c, 0xe0, 0x92, 0xb5, 0x00, 0x19, 0x0f, 0xe1, + 0xce, 0x8f, 0x89, 0x8e, 0x85, 0x4c, 0xb2, 0xa2, 0xcc, 0x63, 0xcf, 0x3e, 0xce, 0xe7, 0xc1, 0x62, + 0x10, 0xed, 0xff, 0x98, 0xe8, 0xa5, 0xb3, 0x34, 0x83, 0xfb, 0x04, 0xc6, 0x15, 0x96, 0xe4, 0x4b, + 0xfc, 0xb8, 0x4f, 0xe1, 0x8f, 0x3c, 0x46, 0x1c, 0xf9, 0xd8, 0x36, 0xa0, 0x12, 0x45, 0x9a, 0xc4, + 0x45, 0x99, 0xe1, 0x15, 0x7f, 0x30, 0x0f, 0x16, 0xbd, 0xe3, 0xce, 0xa7, 0x9f, 0xd9, 0x26, 0x90, + 0xe1, 0xd4, 0xe2, 0x6c, 0x0e, 0x83, 0xcb, 0xa2, 0x2c, 0xf4, 0x0a, 0x33, 0xfe, 0xd0, 0x1e, 0x78, + 0xbc, 0x63, 0x54, 0x8d, 0x51, 0x8b, 0xda, 0xd0, 0x53, 0x21, 0x4b, 0x8c, 0xdf, 0xe2, 0x35, 0xff, + 0x3d, 0x09, 0xc0, 0x80, 0x80, 0x6f, 0xf1, 0x9a, 0x3d, 0x83, 0x1d, 0x52, 0xab, 0x47, 0xa4, 0x56, + 0x6c, 0x7b, 0x3a, 0x48, 0xa6, 0xc8, 0xce, 0xfe, 0x08, 0x33, 0xfb, 0xaf, 0xe3, 0xa2, 0x4c, 0xe5, + 0xba, 0x12, 0x68, 0x90, 0x7f, 0x48, 0xf9, 0x4d, 0x09, 0x3f, 0x6d, 0x61, 0xf6, 0x09, 0x30, 0x3b, + 0xed, 0x6e, 0x9b, 0x58, 0xa1, 0xc0, 0x44, 0x23, 0x7f, 0x46, 0x07, 0xcf, 0x92, 0xaa, 0x3a, 0x21, + 0x43, 0xe4, 0x70, 0xdb, 0x49, 0xbc, 0x2a, 0x4c, 0xac, 0x30, 0xd1, 0xb2, 0xe4, 0x7f, 0xb0, 0x69, + 0x46, 0x60, 0xa1, 0x88, 0x10, 0xf6, 0x05, 0xdc, 0xb3, 0xc5, 0x35, 0x2b, 0x25, 0x8d, 0x11, 0x98, + 0xc5, 0x97, 0x52, 0xb9, 0xb2, 0x3d, 0xa6, 0xf3, 0x6d, 0xe9, 0x2f, 0x1a, 0xe3, 0xd7, 0x52, 0x51, + 0xf9, 0xbe, 0x84, 0x07, 0x3f, 0x7f, 0xc9, 0xf7, 0x45, 0xf3, 0x39, 0xbd, 0xf8, 0xc1, 0xad, 0x17, + 0x7d, 0x77, 0x34, 0xdd, 0x17, 0xed, 0x8b, 0x74, 0xd2, 0x13, 0x6a, 0xd0, 0xa4, 0x45, 0xe9, 0x8c, + 0xc7, 0x30, 0xb2, 0x97, 0x1a, 0x2a, 0x47, 0x8a, 0x90, 0x12, 0x04, 0x07, 0x59, 0x5a, 0x84, 0x7f, + 0x83, 0xd9, 0x52, 0xe6, 0xaf, 0x48, 0xc8, 0x9a, 0x81, 0xdb, 0xd2, 0xbc, 0xe0, 0x7d, 0x35, 0x2f, + 0xd8, 0xd2, 0xbc, 0xf0, 0xbf, 0x3d, 0xd8, 0x5b, 0xca, 0x3c, 0xc2, 0x24, 0x6b, 0x28, 0xf5, 0x0b, + 0x12, 0x7b, 0x7b, 0xa3, 0xee, 0xb6, 0x78, 0x7e, 0x05, 0x7b, 0x3e, 0x9a, 0x46, 0x23, 0xee, 0x10, + 0x0f, 0x1e, 0x6e, 0xf3, 0x60, 0x2b, 0x85, 0x68, 0xb2, 0xde, 0xca, 0x68, 0x5b, 0x07, 0xbb, 0x54, + 0xa9, 0x5f, 0xd0, 0xc1, 0x1d, 0x32, 0xb6, 0x3a, 0x78, 0xa3, 0xcd, 0xbd, 0xf7, 0xd0, 0xe6, 0x6d, + 0xa1, 0xdf, 0x9d, 0x77, 0xb7, 0x85, 0xfe, 0x39, 0xec, 0xaf, 0x8b, 0xb2, 0x58, 0xd7, 0xeb, 0x98, + 0xae, 0x60, 0xba, 0xb5, 0xfa, 0xc4, 0xa6, 0xa9, 0x37, 0x58, 0x46, 0xd3, 0xfd, 0xf5, 0x29, 0xb0, + 0xa2, 0x4c, 0x45, 0x9d, 0xe1, 0x26, 0x9d, 0x07, 0x6e, 0x5c, 0xbd, 0x65, 0x83, 0xd0, 0x07, 0xd0, + 0x4b, 0x65, 0x5d, 0x1a, 0x3e, 0xa4, 0xf8, 0xdd, 0xc2, 0xd2, 0xbc, 0x91, 0x23, 0x3a, 0x51, 0x61, + 0x8e, 0x57, 0x7c, 0x8f, 0x7a, 0x35, 0x6b, 0x2c, 0xd4, 0xa5, 0x1c, 0xaf, 0x6c, 0xf4, 0x56, 0x83, + 0xbc, 0x97, 0x53, 0xcb, 0xa1, 0x45, 0x9c, 0xf9, 0xe9, 0xed, 0x71, 0x9f, 0x51, 0xe4, 0xdb, 0xa3, + 0xbe, 0x80, 0x59, 0x13, 0xb6, 0xed, 0x35, 0x7d, 0x23, 0x00, 0x05, 0xbd, 0xe7, 0x71, 0xf7, 0x75, + 0xa1, 0xd9, 0x11, 0x1c, 0x34, 0x1e, 0x71, 0x85, 0x2d, 0xf3, 0xf9, 0x3e, 0xed, 0xba, 0x9f, 0x38, + 0xb7, 0xbf, 0xa2, 0xda, 0x50, 0xa4, 0x66, 0x6b, 0x92, 0xcd, 0x11, 0x6d, 0x3b, 0xf2, 0xd8, 0x37, + 0x56, 0x29, 0x1f, 0xc3, 0xa8, 0x3d, 0x5d, 0x08, 0x3e, 0x26, 0x0f, 0x68, 0x0e, 0x16, 0xc2, 0x8e, + 0x4d, 0x9a, 0xa4, 0x2b, 0x8c, 0x0b, 0x83, 0x2a, 0x31, 0x52, 0xf1, 0x09, 0xf9, 0x4c, 0x08, 0x3d, + 0xf5, 0xa0, 0xad, 0x44, 0x59, 0xaf, 0x63, 0xbd, 0x4a, 0x54, 0xa6, 0x39, 0xa3, 0x88, 0x86, 0x65, + 0xbd, 0x3e, 0x27, 0x20, 0xfc, 0x57, 0x40, 0xdf, 0x83, 0x8e, 0xdb, 0xee, 0xb2, 0x61, 0x1f, 0x43, + 0x57, 0xc8, 0x9c, 0x07, 0xc4, 0xcd, 0xbb, 0x1b, 0x2c, 0xb9, 0xf9, 0xc6, 0x88, 0xac, 0xc7, 0x06, + 0xa3, 0x3a, 0xef, 0xc1, 0xa8, 0x10, 0x26, 0x22, 0xd1, 0x26, 0x6e, 0xf9, 0xe9, 0xc8, 0x3b, 0xb2, + 0xe0, 0x89, 0xe3, 0x68, 0xf8, 0x9f, 0x80, 0x46, 0xed, 0x8d, 0xfd, 0xac, 0x89, 0x30, 0x95, 0xea, + 0xf6, 0x4c, 0x05, 0xb7, 0x86, 0xf3, 0xd6, 0x3c, 0x74, 0x5c, 0x7e, 0xff, 0x7f, 0x1e, 0xba, 0x64, + 0x6c, 0xe7, 0xa1, 0xe5, 0xd9, 0xce, 0x26, 0xcf, 0x1e, 0x01, 0x18, 0x69, 0x12, 0xe1, 0xee, 0xe1, + 0x9e, 0x9b, 0x2f, 0x42, 0xe8, 0x12, 0xe6, 0xd0, 0x57, 0x14, 0x97, 0xe6, 0xbb, 0x6e, 0x3b, 0xbf, + 0x0c, 0xff, 0xdd, 0xa1, 0x4a, 0xfa, 0xd0, 0x7f, 0x8b, 0x4c, 0xfc, 0x7c, 0xc4, 0x7b, 0xbf, 0x36, + 0xe2, 0xbd, 0xcd, 0x11, 0x9f, 0xd9, 0xcf, 0x11, 0x51, 0x1b, 0xbb, 0xf7, 0x4a, 0xd6, 0x4a, 0x53, + 0x0a, 0x93, 0xe3, 0xe0, 0xb3, 0x68, 0x7a, 0x63, 0xfa, 0xc6, 0x5a, 0xec, 0x25, 0xe3, 0x07, 0xa7, + 0xd1, 0x23, 0x97, 0xd4, 0x20, 0x9a, 0x7a, 0xdc, 0x8b, 0x0e, 0x7d, 0xa0, 0xd4, 0x36, 0xb1, 0x56, + 0xb8, 0xdc, 0xa8, 0x8f, 0x09, 0x6c, 0xa4, 0xe9, 0x29, 0x4c, 0x9a, 0x7d, 0x62, 0x59, 0x8a, 0x6b, + 0x3f, 0xe2, 0xe3, 0x06, 0x3c, 0x2b, 0xc5, 0x75, 0x78, 0x45, 0x2a, 0xed, 0xab, 0xe4, 0x09, 0x77, + 0x04, 0x3d, 0xda, 0xc8, 0x53, 0xee, 0xfe, 0x36, 0x8d, 0x36, 0xc8, 0x10, 0x39, 0x3f, 0xf6, 0x05, + 0xf4, 0x75, 0xbd, 0x5e, 0x27, 0xea, 0xda, 0x33, 0xef, 0x57, 0x5e, 0x69, 0x3c, 0xbf, 0xea, 0xfd, + 0xdd, 0x92, 0xf6, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x70, 0xd9, 0xa0, 0xf8, 0x48, 0x0d, 0x00, + 0x00, } diff --git a/vendor/google.golang.org/appengine/internal/main.go b/vendor/google.golang.org/appengine/internal/main.go new file mode 100644 index 000000000..49036163c --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/main.go @@ -0,0 +1,15 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// +build appengine + +package internal + +import ( + "appengine_internal" +) + +func Main() { + appengine_internal.Main() +} diff --git a/vendor/google.golang.org/appengine/internal/main_vm.go b/vendor/google.golang.org/appengine/internal/main_vm.go new file mode 100644 index 000000000..822e784a4 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/main_vm.go @@ -0,0 +1,48 @@ +// Copyright 2011 Google Inc. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +// +build !appengine + +package internal + +import ( + "io" + "log" + "net/http" + "net/url" + "os" +) + +func Main() { + installHealthChecker(http.DefaultServeMux) + + port := "8080" + if s := os.Getenv("PORT"); s != "" { + port = s + } + + host := "" + if IsDevAppServer() { + host = "127.0.0.1" + } + if err := http.ListenAndServe(host+":"+port, http.HandlerFunc(handleHTTP)); err != nil { + log.Fatalf("http.ListenAndServe: %v", err) + } +} + +func installHealthChecker(mux *http.ServeMux) { + // If no health check handler has been installed by this point, add a trivial one. + const healthPath = "/_ah/health" + hreq := &http.Request{ + Method: "GET", + URL: &url.URL{ + Path: healthPath, + }, + } + if _, pat := mux.Handler(hreq); pat != healthPath { + mux.HandleFunc(healthPath, func(w http.ResponseWriter, r *http.Request) { + io.WriteString(w, "ok") + }) + } +} diff --git a/vendor/google.golang.org/appengine/internal/net_test.go b/vendor/google.golang.org/appengine/internal/net_test.go deleted file mode 100644 index 24da8bb2b..000000000 --- a/vendor/google.golang.org/appengine/internal/net_test.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2014 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -// +build !appengine - -package internal - -import ( - "sync" - "testing" - "time" - - netcontext "golang.org/x/net/context" - - basepb "google.golang.org/appengine/internal/base" -) - -func TestDialLimit(t *testing.T) { - // Fill up semaphore with false acquisitions to permit only two TCP connections at a time. - // We don't replace limitSem because that results in a data race when net/http lazily closes connections. - nFake := cap(limitSem) - 2 - for i := 0; i < nFake; i++ { - limitSem <- 1 - } - defer func() { - for i := 0; i < nFake; i++ { - <-limitSem - } - }() - - f, c, cleanup := setup() // setup is in api_test.go - defer cleanup() - f.hang = make(chan int) - - // If we make two RunSlowly RPCs (which will wait for f.hang to be strobed), - // then the simple Non200 RPC should hang. - var wg sync.WaitGroup - wg.Add(2) - for i := 0; i < 2; i++ { - go func() { - defer wg.Done() - Call(toContext(c), "errors", "RunSlowly", &basepb.VoidProto{}, &basepb.VoidProto{}) - }() - } - time.Sleep(50 * time.Millisecond) // let those two RPCs start - - ctx, _ := netcontext.WithTimeout(toContext(c), 50*time.Millisecond) - err := Call(ctx, "errors", "Non200", &basepb.VoidProto{}, &basepb.VoidProto{}) - if err != errTimeout { - t.Errorf("Non200 RPC returned with err %v, want errTimeout", err) - } - - // Drain the two RunSlowly calls. - f.hang <- 1 - f.hang <- 1 - wg.Wait() -} diff --git a/vendor/google.golang.org/appengine/internal/regen.sh b/vendor/google.golang.org/appengine/internal/regen.sh old mode 100755 new mode 100644 diff --git a/vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go b/vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go index 526bd39e6..172aebe8e 100644 --- a/vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go +++ b/vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go @@ -1,6 +1,5 @@ -// Code generated by protoc-gen-go. +// Code generated by protoc-gen-go. DO NOT EDIT. // source: google.golang.org/appengine/internal/remote_api/remote_api.proto -// DO NOT EDIT! /* Package remote_api is a generated protocol buffer package. @@ -25,6 +24,12 @@ var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + type RpcError_ErrorCode int32 const ( @@ -90,18 +95,20 @@ func (x *RpcError_ErrorCode) UnmarshalJSON(data []byte) error { *x = RpcError_ErrorCode(value) return nil } +func (RpcError_ErrorCode) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} } type Request struct { - ServiceName *string `protobuf:"bytes,2,req,name=service_name" json:"service_name,omitempty"` + ServiceName *string `protobuf:"bytes,2,req,name=service_name,json=serviceName" json:"service_name,omitempty"` Method *string `protobuf:"bytes,3,req,name=method" json:"method,omitempty"` Request []byte `protobuf:"bytes,4,req,name=request" json:"request,omitempty"` - RequestId *string `protobuf:"bytes,5,opt,name=request_id" json:"request_id,omitempty"` + RequestId *string `protobuf:"bytes,5,opt,name=request_id,json=requestId" json:"request_id,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *Request) Reset() { *m = Request{} } -func (m *Request) String() string { return proto.CompactTextString(m) } -func (*Request) ProtoMessage() {} +func (m *Request) Reset() { *m = Request{} } +func (m *Request) String() string { return proto.CompactTextString(m) } +func (*Request) ProtoMessage() {} +func (*Request) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } func (m *Request) GetServiceName() string { if m != nil && m.ServiceName != nil { @@ -137,9 +144,10 @@ type ApplicationError struct { XXX_unrecognized []byte `json:"-"` } -func (m *ApplicationError) Reset() { *m = ApplicationError{} } -func (m *ApplicationError) String() string { return proto.CompactTextString(m) } -func (*ApplicationError) ProtoMessage() {} +func (m *ApplicationError) Reset() { *m = ApplicationError{} } +func (m *ApplicationError) String() string { return proto.CompactTextString(m) } +func (*ApplicationError) ProtoMessage() {} +func (*ApplicationError) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } func (m *ApplicationError) GetCode() int32 { if m != nil && m.Code != nil { @@ -161,9 +169,10 @@ type RpcError struct { XXX_unrecognized []byte `json:"-"` } -func (m *RpcError) Reset() { *m = RpcError{} } -func (m *RpcError) String() string { return proto.CompactTextString(m) } -func (*RpcError) ProtoMessage() {} +func (m *RpcError) Reset() { *m = RpcError{} } +func (m *RpcError) String() string { return proto.CompactTextString(m) } +func (*RpcError) ProtoMessage() {} +func (*RpcError) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } func (m *RpcError) GetCode() int32 { if m != nil && m.Code != nil { @@ -182,15 +191,16 @@ func (m *RpcError) GetDetail() string { type Response struct { Response []byte `protobuf:"bytes,1,opt,name=response" json:"response,omitempty"` Exception []byte `protobuf:"bytes,2,opt,name=exception" json:"exception,omitempty"` - ApplicationError *ApplicationError `protobuf:"bytes,3,opt,name=application_error" json:"application_error,omitempty"` - JavaException []byte `protobuf:"bytes,4,opt,name=java_exception" json:"java_exception,omitempty"` - RpcError *RpcError `protobuf:"bytes,5,opt,name=rpc_error" json:"rpc_error,omitempty"` + ApplicationError *ApplicationError `protobuf:"bytes,3,opt,name=application_error,json=applicationError" json:"application_error,omitempty"` + JavaException []byte `protobuf:"bytes,4,opt,name=java_exception,json=javaException" json:"java_exception,omitempty"` + RpcError *RpcError `protobuf:"bytes,5,opt,name=rpc_error,json=rpcError" json:"rpc_error,omitempty"` XXX_unrecognized []byte `json:"-"` } -func (m *Response) Reset() { *m = Response{} } -func (m *Response) String() string { return proto.CompactTextString(m) } -func (*Response) ProtoMessage() {} +func (m *Response) Reset() { *m = Response{} } +func (m *Response) String() string { return proto.CompactTextString(m) } +func (*Response) ProtoMessage() {} +func (*Response) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } func (m *Response) GetResponse() []byte { if m != nil { @@ -228,4 +238,50 @@ func (m *Response) GetRpcError() *RpcError { } func init() { + proto.RegisterType((*Request)(nil), "remote_api.Request") + proto.RegisterType((*ApplicationError)(nil), "remote_api.ApplicationError") + proto.RegisterType((*RpcError)(nil), "remote_api.RpcError") + proto.RegisterType((*Response)(nil), "remote_api.Response") +} + +func init() { + proto.RegisterFile("google.golang.org/appengine/internal/remote_api/remote_api.proto", fileDescriptor0) +} + +var fileDescriptor0 = []byte{ + // 531 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0x51, 0x6e, 0xd3, 0x40, + 0x10, 0x86, 0xb1, 0x9b, 0x34, 0xf1, 0xc4, 0x2d, 0xdb, 0xa5, 0x14, 0x0b, 0x15, 0x29, 0x44, 0x42, + 0xca, 0x53, 0x2a, 0x38, 0x00, 0x62, 0x63, 0x6f, 0x91, 0x85, 0x65, 0xa7, 0x6b, 0xbb, 0x50, 0x5e, + 0x56, 0x2b, 0x67, 0x65, 0x8c, 0x12, 0xaf, 0xd9, 0x98, 0x8a, 0x17, 0x6e, 0xc0, 0xb5, 0x38, 0x0c, + 0xb7, 0x40, 0x36, 0x6e, 0x63, 0xf5, 0x89, 0xb7, 0x7f, 0x7e, 0x7b, 0xe6, 0x1b, 0xcd, 0xcc, 0xc2, + 0xbb, 0x5c, 0xa9, 0x7c, 0x23, 0x17, 0xb9, 0xda, 0x88, 0x32, 0x5f, 0x28, 0x9d, 0x5f, 0x88, 0xaa, + 0x92, 0x65, 0x5e, 0x94, 0xf2, 0xa2, 0x28, 0x6b, 0xa9, 0x4b, 0xb1, 0xb9, 0xd0, 0x72, 0xab, 0x6a, + 0xc9, 0x45, 0x55, 0xf4, 0xe4, 0xa2, 0xd2, 0xaa, 0x56, 0x18, 0xf6, 0xce, 0xec, 0x27, 0x8c, 0x98, + 0xfc, 0xf6, 0x5d, 0xee, 0x6a, 0xfc, 0x12, 0xec, 0x9d, 0xd4, 0xb7, 0x45, 0x26, 0x79, 0x29, 0xb6, + 0xd2, 0x31, 0xa7, 0xe6, 0xdc, 0x62, 0x93, 0xce, 0x0b, 0xc5, 0x56, 0xe2, 0x33, 0x38, 0xdc, 0xca, + 0xfa, 0x8b, 0x5a, 0x3b, 0x07, 0xed, 0xc7, 0x2e, 0xc2, 0x0e, 0x8c, 0xf4, 0xbf, 0x2a, 0xce, 0x60, + 0x6a, 0xce, 0x6d, 0x76, 0x17, 0xe2, 0x17, 0x00, 0x9d, 0xe4, 0xc5, 0xda, 0x19, 0x4e, 0x8d, 0xb9, + 0xc5, 0xac, 0xce, 0xf1, 0xd7, 0xb3, 0xb7, 0x80, 0x48, 0x55, 0x6d, 0x8a, 0x4c, 0xd4, 0x85, 0x2a, + 0xa9, 0xd6, 0x4a, 0x63, 0x0c, 0x83, 0x4c, 0xad, 0xa5, 0x63, 0x4c, 0xcd, 0xf9, 0x90, 0xb5, 0xba, + 0x01, 0xaf, 0x65, 0x2d, 0x8a, 0x4d, 0xd7, 0x55, 0x17, 0xcd, 0x7e, 0x9b, 0x30, 0x66, 0x55, 0xf6, + 0x7f, 0x89, 0x46, 0x2f, 0xf1, 0x97, 0x09, 0x56, 0x9b, 0xe5, 0x36, 0x7f, 0x4d, 0x60, 0x94, 0x86, + 0x1f, 0xc2, 0xe8, 0x63, 0x88, 0x1e, 0x61, 0x0c, 0xc7, 0x2e, 0x09, 0x02, 0x1e, 0x46, 0x09, 0xbf, + 0x8c, 0xd2, 0xd0, 0x43, 0x06, 0x7e, 0x0c, 0x93, 0x15, 0x61, 0x31, 0xe5, 0x94, 0xb1, 0x88, 0x21, + 0x13, 0x9f, 0x01, 0x8e, 0xa9, 0x9b, 0x32, 0x3f, 0xb9, 0xe1, 0xd7, 0x7e, 0x14, 0x90, 0xc4, 0x8f, + 0x42, 0x74, 0x80, 0x8f, 0x01, 0xa2, 0x6b, 0xca, 0xf8, 0x55, 0x1a, 0x25, 0x04, 0x0d, 0xf0, 0x53, + 0x38, 0x61, 0xf4, 0x2a, 0xa5, 0x71, 0xc2, 0x93, 0x28, 0xe2, 0x01, 0x61, 0xef, 0x29, 0x1a, 0xe2, + 0x67, 0xf0, 0xc4, 0x25, 0x2b, 0xb2, 0xf4, 0x83, 0xa6, 0x80, 0xe7, 0xc7, 0x64, 0x19, 0x50, 0x0f, + 0x1d, 0xe2, 0x53, 0x40, 0x97, 0x94, 0x24, 0x29, 0xa3, 0x7b, 0x77, 0xd4, 0xe0, 0x97, 0xc4, 0xe3, + 0x5d, 0x25, 0x34, 0x6e, 0xf0, 0x8c, 0xc6, 0xab, 0x28, 0x8c, 0x69, 0xaf, 0xae, 0x85, 0x8f, 0xc0, + 0x72, 0x49, 0xe8, 0xd2, 0xa0, 0xc9, 0x03, 0x8c, 0xc0, 0x66, 0x74, 0x15, 0x90, 0x9b, 0xae, 0xef, + 0x49, 0xd3, 0x8f, 0x47, 0x89, 0x17, 0xf8, 0x21, 0xe5, 0xf4, 0x93, 0x4b, 0xa9, 0x47, 0x3d, 0x64, + 0xcf, 0xfe, 0x18, 0x30, 0x66, 0x72, 0x57, 0xa9, 0x72, 0x27, 0xf1, 0x73, 0x18, 0xeb, 0x4e, 0x3b, + 0xc6, 0xd4, 0x98, 0xdb, 0xec, 0x3e, 0xc6, 0xe7, 0x60, 0xc9, 0x1f, 0x99, 0xac, 0x9a, 0x75, 0xb5, + 0x23, 0xb5, 0xd9, 0xde, 0xc0, 0x3e, 0x9c, 0x88, 0xfd, 0x3a, 0xb9, 0x6c, 0x06, 0xec, 0x1c, 0x4c, + 0x8d, 0xf9, 0xe4, 0xcd, 0xf9, 0xa2, 0x77, 0x87, 0x0f, 0x77, 0xce, 0x90, 0x78, 0x78, 0x05, 0xaf, + 0xe0, 0xf8, 0xab, 0xb8, 0x15, 0x7c, 0x4f, 0x1b, 0xb4, 0xb4, 0xa3, 0xc6, 0xa5, 0xf7, 0xc4, 0xd7, + 0x60, 0xe9, 0x2a, 0xeb, 0x48, 0xc3, 0x96, 0x74, 0xda, 0x27, 0xdd, 0x1d, 0x07, 0x1b, 0xeb, 0x4e, + 0x2d, 0xed, 0xcf, 0xbd, 0x07, 0xf0, 0x37, 0x00, 0x00, 0xff, 0xff, 0x38, 0xd1, 0x0f, 0x22, 0x4f, + 0x03, 0x00, 0x00, } diff --git a/vendor/google.golang.org/appengine/internal/transaction.go b/vendor/google.golang.org/appengine/internal/transaction.go index 28a6d1812..9006ae653 100644 --- a/vendor/google.golang.org/appengine/internal/transaction.go +++ b/vendor/google.golang.org/appengine/internal/transaction.go @@ -54,9 +54,9 @@ type transaction struct { var ErrConcurrentTransaction = errors.New("internal: concurrent transaction") -func RunTransactionOnce(c netcontext.Context, f func(netcontext.Context) error, xg bool) error { +func RunTransactionOnce(c netcontext.Context, f func(netcontext.Context) error, xg bool, readOnly bool, previousTransaction *pb.Transaction) (*pb.Transaction, error) { if transactionFromContext(c) != nil { - return errors.New("nested transactions are not supported") + return nil, errors.New("nested transactions are not supported") } // Begin the transaction. @@ -67,8 +67,16 @@ func RunTransactionOnce(c netcontext.Context, f func(netcontext.Context) error, if xg { req.AllowMultipleEg = proto.Bool(true) } + if previousTransaction != nil { + req.PreviousTransaction = previousTransaction + } + if readOnly { + req.Mode = pb.BeginTransactionRequest_READ_ONLY.Enum() + } else { + req.Mode = pb.BeginTransactionRequest_READ_WRITE.Enum() + } if err := Call(c, "datastore_v3", "BeginTransaction", req, &t.transaction); err != nil { - return err + return nil, err } // Call f, rolling back the transaction if f returns a non-nil error, or panics. @@ -83,7 +91,7 @@ func RunTransactionOnce(c netcontext.Context, f func(netcontext.Context) error, Call(c, "datastore_v3", "Rollback", &t.transaction, &basepb.VoidProto{}) }() if err := f(withTransaction(c, t)); err != nil { - return err + return &t.transaction, err } t.finished = true @@ -97,11 +105,11 @@ func RunTransactionOnce(c netcontext.Context, f func(netcontext.Context) error, // The Python Dev AppServer raises an ApplicationError with error code 2 (which is // Error.CONCURRENT_TRANSACTION) and message "Concurrency exception.". if ae.Code == int32(pb.Error_BAD_REQUEST) && ae.Detail == "ApplicationError: 2 Concurrency exception." { - return ErrConcurrentTransaction + return &t.transaction, ErrConcurrentTransaction } if ae.Code == int32(pb.Error_CONCURRENT_TRANSACTION) { - return ErrConcurrentTransaction + return &t.transaction, ErrConcurrentTransaction } } - return err + return &t.transaction, err } diff --git a/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.pb.go b/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.pb.go index af463fbb2..7c96c9d40 100644 --- a/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.pb.go +++ b/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.pb.go @@ -1,6 +1,5 @@ -// Code generated by protoc-gen-go. +// Code generated by protoc-gen-go. DO NOT EDIT. // source: google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto -// DO NOT EDIT! /* Package urlfetch is a generated protocol buffer package. @@ -24,6 +23,12 @@ var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + type URLFetchServiceError_ErrorCode int32 const ( @@ -89,6 +94,9 @@ func (x *URLFetchServiceError_ErrorCode) UnmarshalJSON(data []byte) error { *x = URLFetchServiceError_ErrorCode(value) return nil } +func (URLFetchServiceError_ErrorCode) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{0, 0} +} type URLFetchRequest_RequestMethod int32 @@ -134,19 +142,23 @@ func (x *URLFetchRequest_RequestMethod) UnmarshalJSON(data []byte) error { *x = URLFetchRequest_RequestMethod(value) return nil } +func (URLFetchRequest_RequestMethod) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{1, 0} +} type URLFetchServiceError struct { XXX_unrecognized []byte `json:"-"` } -func (m *URLFetchServiceError) Reset() { *m = URLFetchServiceError{} } -func (m *URLFetchServiceError) String() string { return proto.CompactTextString(m) } -func (*URLFetchServiceError) ProtoMessage() {} +func (m *URLFetchServiceError) Reset() { *m = URLFetchServiceError{} } +func (m *URLFetchServiceError) String() string { return proto.CompactTextString(m) } +func (*URLFetchServiceError) ProtoMessage() {} +func (*URLFetchServiceError) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } type URLFetchRequest struct { Method *URLFetchRequest_RequestMethod `protobuf:"varint,1,req,name=Method,enum=appengine.URLFetchRequest_RequestMethod" json:"Method,omitempty"` Url *string `protobuf:"bytes,2,req,name=Url" json:"Url,omitempty"` - Header []*URLFetchRequest_Header `protobuf:"group,3,rep,name=Header" json:"header,omitempty"` + Header []*URLFetchRequest_Header `protobuf:"group,3,rep,name=Header,json=header" json:"header,omitempty"` Payload []byte `protobuf:"bytes,6,opt,name=Payload" json:"Payload,omitempty"` FollowRedirects *bool `protobuf:"varint,7,opt,name=FollowRedirects,def=1" json:"FollowRedirects,omitempty"` Deadline *float64 `protobuf:"fixed64,8,opt,name=Deadline" json:"Deadline,omitempty"` @@ -154,9 +166,10 @@ type URLFetchRequest struct { XXX_unrecognized []byte `json:"-"` } -func (m *URLFetchRequest) Reset() { *m = URLFetchRequest{} } -func (m *URLFetchRequest) String() string { return proto.CompactTextString(m) } -func (*URLFetchRequest) ProtoMessage() {} +func (m *URLFetchRequest) Reset() { *m = URLFetchRequest{} } +func (m *URLFetchRequest) String() string { return proto.CompactTextString(m) } +func (*URLFetchRequest) ProtoMessage() {} +func (*URLFetchRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } const Default_URLFetchRequest_FollowRedirects bool = true const Default_URLFetchRequest_MustValidateServerCertificate bool = true @@ -216,9 +229,10 @@ type URLFetchRequest_Header struct { XXX_unrecognized []byte `json:"-"` } -func (m *URLFetchRequest_Header) Reset() { *m = URLFetchRequest_Header{} } -func (m *URLFetchRequest_Header) String() string { return proto.CompactTextString(m) } -func (*URLFetchRequest_Header) ProtoMessage() {} +func (m *URLFetchRequest_Header) Reset() { *m = URLFetchRequest_Header{} } +func (m *URLFetchRequest_Header) String() string { return proto.CompactTextString(m) } +func (*URLFetchRequest_Header) ProtoMessage() {} +func (*URLFetchRequest_Header) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1, 0} } func (m *URLFetchRequest_Header) GetKey() string { if m != nil && m.Key != nil { @@ -237,7 +251,7 @@ func (m *URLFetchRequest_Header) GetValue() string { type URLFetchResponse struct { Content []byte `protobuf:"bytes,1,opt,name=Content" json:"Content,omitempty"` StatusCode *int32 `protobuf:"varint,2,req,name=StatusCode" json:"StatusCode,omitempty"` - Header []*URLFetchResponse_Header `protobuf:"group,3,rep,name=Header" json:"header,omitempty"` + Header []*URLFetchResponse_Header `protobuf:"group,3,rep,name=Header,json=header" json:"header,omitempty"` ContentWasTruncated *bool `protobuf:"varint,6,opt,name=ContentWasTruncated,def=0" json:"ContentWasTruncated,omitempty"` ExternalBytesSent *int64 `protobuf:"varint,7,opt,name=ExternalBytesSent" json:"ExternalBytesSent,omitempty"` ExternalBytesReceived *int64 `protobuf:"varint,8,opt,name=ExternalBytesReceived" json:"ExternalBytesReceived,omitempty"` @@ -248,9 +262,10 @@ type URLFetchResponse struct { XXX_unrecognized []byte `json:"-"` } -func (m *URLFetchResponse) Reset() { *m = URLFetchResponse{} } -func (m *URLFetchResponse) String() string { return proto.CompactTextString(m) } -func (*URLFetchResponse) ProtoMessage() {} +func (m *URLFetchResponse) Reset() { *m = URLFetchResponse{} } +func (m *URLFetchResponse) String() string { return proto.CompactTextString(m) } +func (*URLFetchResponse) ProtoMessage() {} +func (*URLFetchResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } const Default_URLFetchResponse_ContentWasTruncated bool = false const Default_URLFetchResponse_ApiCpuMilliseconds int64 = 0 @@ -333,9 +348,10 @@ type URLFetchResponse_Header struct { XXX_unrecognized []byte `json:"-"` } -func (m *URLFetchResponse_Header) Reset() { *m = URLFetchResponse_Header{} } -func (m *URLFetchResponse_Header) String() string { return proto.CompactTextString(m) } -func (*URLFetchResponse_Header) ProtoMessage() {} +func (m *URLFetchResponse_Header) Reset() { *m = URLFetchResponse_Header{} } +func (m *URLFetchResponse_Header) String() string { return proto.CompactTextString(m) } +func (*URLFetchResponse_Header) ProtoMessage() {} +func (*URLFetchResponse_Header) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} } func (m *URLFetchResponse_Header) GetKey() string { if m != nil && m.Key != nil { @@ -352,4 +368,66 @@ func (m *URLFetchResponse_Header) GetValue() string { } func init() { + proto.RegisterType((*URLFetchServiceError)(nil), "appengine.URLFetchServiceError") + proto.RegisterType((*URLFetchRequest)(nil), "appengine.URLFetchRequest") + proto.RegisterType((*URLFetchRequest_Header)(nil), "appengine.URLFetchRequest.Header") + proto.RegisterType((*URLFetchResponse)(nil), "appengine.URLFetchResponse") + proto.RegisterType((*URLFetchResponse_Header)(nil), "appengine.URLFetchResponse.Header") +} + +func init() { + proto.RegisterFile("google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto", fileDescriptor0) +} + +var fileDescriptor0 = []byte{ + // 770 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0xdd, 0x6e, 0xe3, 0x54, + 0x10, 0xc6, 0x76, 0x7e, 0xa7, 0x5d, 0x7a, 0x76, 0xb6, 0x45, 0x66, 0xb5, 0xa0, 0x10, 0x09, 0x29, + 0x17, 0x90, 0x2e, 0x2b, 0x24, 0x44, 0xaf, 0x70, 0xed, 0x93, 0xad, 0xa9, 0x63, 0x47, 0xc7, 0x4e, + 0x61, 0xb9, 0xb1, 0xac, 0x78, 0x9a, 0x5a, 0xb2, 0xec, 0x60, 0x9f, 0x2c, 0xf4, 0x35, 0x78, 0x0d, + 0xde, 0x87, 0xa7, 0xe1, 0x02, 0x9d, 0xc4, 0xc9, 0x6e, 0xbb, 0xd1, 0x4a, 0x5c, 0x65, 0xe6, 0x9b, + 0xef, 0xcc, 0x99, 0x7c, 0xdf, 0xf8, 0x80, 0xb3, 0x2c, 0xcb, 0x65, 0x4e, 0xe3, 0x65, 0x99, 0x27, + 0xc5, 0x72, 0x5c, 0x56, 0xcb, 0xf3, 0x64, 0xb5, 0xa2, 0x62, 0x99, 0x15, 0x74, 0x9e, 0x15, 0x92, + 0xaa, 0x22, 0xc9, 0xcf, 0xd7, 0x55, 0x7e, 0x4b, 0x72, 0x71, 0xb7, 0x0f, 0xe2, 0x9a, 0xaa, 0xb7, + 0xd9, 0x82, 0xc6, 0xab, 0xaa, 0x94, 0x25, 0xf6, 0xf7, 0x67, 0x86, 0x7f, 0xeb, 0x70, 0x3a, 0x17, + 0xde, 0x44, 0xb1, 0xc2, 0x2d, 0x89, 0x57, 0x55, 0x59, 0x0d, 0xff, 0xd2, 0xa1, 0xbf, 0x89, 0xec, + 0x32, 0x25, 0xec, 0x80, 0x1e, 0x5c, 0xb3, 0x4f, 0xf0, 0x04, 0x8e, 0x5c, 0xff, 0xc6, 0xf2, 0x5c, + 0x27, 0x9e, 0x0b, 0x8f, 0x69, 0x0a, 0x98, 0xf0, 0xc8, 0xbe, 0x8a, 0xb9, 0x10, 0x81, 0x60, 0x3a, + 0x9e, 0xc1, 0xd3, 0xb9, 0x1f, 0xce, 0xb8, 0xed, 0x4e, 0x5c, 0xee, 0x34, 0xb0, 0x81, 0x9f, 0x01, + 0x0a, 0x1e, 0xce, 0x02, 0x3f, 0xe4, 0x71, 0x14, 0x04, 0xb1, 0x67, 0x89, 0xd7, 0x9c, 0xb5, 0x14, + 0xdd, 0xe1, 0x96, 0xe3, 0xb9, 0x3e, 0x8f, 0xf9, 0xaf, 0x36, 0xe7, 0x0e, 0x77, 0x58, 0x1b, 0x3f, + 0x87, 0xb3, 0x30, 0xf4, 0x62, 0x9b, 0x8b, 0xc8, 0x9d, 0xb8, 0xb6, 0x15, 0xf1, 0xa6, 0x53, 0x07, + 0x9f, 0x40, 0xdf, 0xf1, 0xc3, 0x26, 0xed, 0x22, 0x40, 0xc7, 0xf6, 0x82, 0x90, 0x3b, 0xac, 0x87, + 0x2f, 0xc0, 0x74, 0xfd, 0x88, 0x0b, 0xdf, 0xf2, 0xe2, 0x48, 0x58, 0x7e, 0xe8, 0x72, 0x3f, 0x6a, + 0x98, 0x7d, 0x35, 0x82, 0xba, 0x79, 0x6a, 0xf9, 0x6f, 0x62, 0xc1, 0x1d, 0x57, 0x70, 0x3b, 0x0a, + 0x19, 0xe0, 0x33, 0x38, 0x99, 0x5a, 0xde, 0x24, 0x10, 0x53, 0xee, 0xc4, 0x82, 0xcf, 0xbc, 0x37, + 0xec, 0x08, 0x4f, 0x81, 0xd9, 0x81, 0xef, 0x73, 0x3b, 0x72, 0x03, 0xbf, 0x69, 0x71, 0x3c, 0xfc, + 0xc7, 0x80, 0x93, 0x9d, 0x5a, 0x82, 0x7e, 0x5f, 0x53, 0x2d, 0xf1, 0x27, 0xe8, 0x4c, 0x49, 0xde, + 0x95, 0xa9, 0xa9, 0x0d, 0xf4, 0xd1, 0xa7, 0xaf, 0x46, 0xe3, 0xbd, 0xba, 0xe3, 0x47, 0xdc, 0x71, + 0xf3, 0xbb, 0xe5, 0x8b, 0xe6, 0x1c, 0x32, 0x30, 0xe6, 0x55, 0x6e, 0xea, 0x03, 0x7d, 0xd4, 0x17, + 0x2a, 0xc4, 0x1f, 0xa1, 0x73, 0x47, 0x49, 0x4a, 0x95, 0x69, 0x0c, 0x8c, 0x11, 0xbc, 0xfa, 0xea, + 0x23, 0x3d, 0xaf, 0x36, 0x44, 0xd1, 0x1c, 0xc0, 0x17, 0xd0, 0x9d, 0x25, 0xf7, 0x79, 0x99, 0xa4, + 0x66, 0x67, 0xa0, 0x8d, 0x8e, 0x2f, 0xf5, 0x9e, 0x26, 0x76, 0x10, 0x8e, 0xe1, 0x64, 0x52, 0xe6, + 0x79, 0xf9, 0x87, 0xa0, 0x34, 0xab, 0x68, 0x21, 0x6b, 0xb3, 0x3b, 0xd0, 0x46, 0xbd, 0x8b, 0x96, + 0xac, 0xd6, 0x24, 0x1e, 0x17, 0xf1, 0x39, 0xf4, 0x1c, 0x4a, 0xd2, 0x3c, 0x2b, 0xc8, 0xec, 0x0d, + 0xb4, 0x91, 0x26, 0xf6, 0x39, 0xfe, 0x0c, 0x5f, 0x4c, 0xd7, 0xb5, 0xbc, 0x49, 0xf2, 0x2c, 0x4d, + 0x24, 0xa9, 0xed, 0xa1, 0xca, 0xa6, 0x4a, 0x66, 0xb7, 0xd9, 0x22, 0x91, 0x64, 0xf6, 0xdf, 0xeb, + 0xfc, 0x71, 0xea, 0xf3, 0x97, 0xd0, 0xd9, 0xfe, 0x0f, 0x25, 0xc6, 0x35, 0xdd, 0x9b, 0xad, 0xad, + 0x18, 0xd7, 0x74, 0x8f, 0xa7, 0xd0, 0xbe, 0x49, 0xf2, 0x35, 0x99, 0xed, 0x0d, 0xb6, 0x4d, 0x86, + 0x1e, 0x3c, 0x79, 0xa0, 0x26, 0x76, 0xc1, 0x78, 0xcd, 0x23, 0xa6, 0x61, 0x0f, 0x5a, 0xb3, 0x20, + 0x8c, 0x98, 0xae, 0xa2, 0x2b, 0x6e, 0x39, 0xcc, 0x50, 0xc5, 0xd9, 0x3c, 0x62, 0x2d, 0xb5, 0x2e, + 0x0e, 0xf7, 0x78, 0xc4, 0x59, 0x1b, 0xfb, 0xd0, 0x9e, 0x59, 0x91, 0x7d, 0xc5, 0x3a, 0xc3, 0x7f, + 0x0d, 0x60, 0xef, 0x84, 0xad, 0x57, 0x65, 0x51, 0x13, 0x9a, 0xd0, 0xb5, 0xcb, 0x42, 0x52, 0x21, + 0x4d, 0x4d, 0x49, 0x29, 0x76, 0x29, 0x7e, 0x09, 0x10, 0xca, 0x44, 0xae, 0x6b, 0xf5, 0x71, 0x6c, + 0x8c, 0x6b, 0x8b, 0xf7, 0x10, 0xbc, 0x78, 0xe4, 0xdf, 0xf0, 0xa0, 0x7f, 0xdb, 0x6b, 0x1e, 0x1b, + 0xf8, 0x03, 0x3c, 0x6b, 0xae, 0xf9, 0x25, 0xa9, 0xa3, 0x6a, 0x5d, 0x28, 0x81, 0xb6, 0x66, 0xf6, + 0x2e, 0xda, 0xb7, 0x49, 0x5e, 0x93, 0x38, 0xc4, 0xc0, 0x6f, 0xe0, 0x29, 0xff, 0x73, 0xfb, 0x02, + 0x5c, 0xde, 0x4b, 0xaa, 0x43, 0x35, 0xb8, 0x72, 0xd7, 0x10, 0x1f, 0x16, 0xf0, 0x7b, 0x38, 0x7b, + 0x00, 0x0a, 0x5a, 0x50, 0xf6, 0x96, 0xd2, 0x8d, 0xcd, 0x86, 0x38, 0x5c, 0x54, 0xfb, 0x30, 0xc9, + 0x8a, 0x24, 0x57, 0xfb, 0xaa, 0xec, 0xed, 0x8b, 0x7d, 0x8e, 0xdf, 0x01, 0x5a, 0xab, 0xcc, 0x5e, + 0xad, 0xa7, 0x59, 0x9e, 0x67, 0x35, 0x2d, 0xca, 0x22, 0xad, 0x4d, 0x50, 0xed, 0x2e, 0xb4, 0x97, + 0xe2, 0x40, 0x11, 0xbf, 0x86, 0x63, 0x6b, 0x95, 0xbd, 0x9b, 0xf6, 0x68, 0x47, 0x7e, 0x00, 0xe3, + 0xb7, 0xc0, 0x76, 0xf9, 0x7e, 0xcc, 0xe3, 0x1d, 0xf5, 0x83, 0xd2, 0xff, 0x5f, 0xa6, 0x4b, 0xf8, + 0xad, 0xb7, 0x7b, 0x2a, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x1d, 0x9f, 0x6d, 0x24, 0x63, 0x05, + 0x00, 0x00, } diff --git a/vendor/gopkg.in/square/go-jose.v2/asymmetric_test.go b/vendor/gopkg.in/square/go-jose.v2/asymmetric_test.go deleted file mode 100644 index 66aea365c..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/asymmetric_test.go +++ /dev/null @@ -1,504 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jose - -import ( - "bytes" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "crypto/rsa" - "errors" - "io" - "math/big" - "testing" -) - -func TestVectorsRSA(t *testing.T) { - // Sources: - // http://www.emc.com/emc-plus/rsa-labs/standards-initiatives/pkcs-rsa-cryptography-standard.htm - // ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15crypt-vectors.txt - priv := &rsa.PrivateKey{ - PublicKey: rsa.PublicKey{ - N: fromHexInt(` - a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8 - ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0c - bc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bd - bf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93 - ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb`), - E: 65537, - }, - D: fromHexInt(` - 53339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf1195 - 17ef4f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d - 4ac4d1812b8b9fa5af0e7f55fe7304df41570926f3311f15c4d6 - 5a732c483116ee3d3d2d0af3549ad9bf7cbfb78ad884f84d5beb - 04724dc7369b31def37d0cf539e9cfcdd3de653729ead5d1`), - Primes: []*big.Int{ - fromHexInt(` - d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262 - 864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c - 2f26a471dcad212eac7ca39d`), - fromHexInt(` - cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb3 - 3d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af - 72bfe9a030e860b0288b5d77`), - }, - } - - input := fromHexBytes( - "6628194e12073db03ba94cda9ef9532397d50dba79b987004afefe34") - - expectedPKCS := fromHexBytes(` - 50b4c14136bd198c2f3c3ed243fce036e168d56517984a263cd66492b808 - 04f169d210f2b9bdfb48b12f9ea05009c77da257cc600ccefe3a6283789d - 8ea0e607ac58e2690ec4ebc10146e8cbaa5ed4d5cce6fe7b0ff9efc1eabb - 564dbf498285f449ee61dd7b42ee5b5892cb90601f30cda07bf26489310b - cd23b528ceab3c31`) - - expectedOAEP := fromHexBytes(` - 354fe67b4a126d5d35fe36c777791a3f7ba13def484e2d3908aff722fad4 - 68fb21696de95d0be911c2d3174f8afcc201035f7b6d8e69402de5451618 - c21a535fa9d7bfc5b8dd9fc243f8cf927db31322d6e881eaa91a996170e6 - 57a05a266426d98c88003f8477c1227094a0d9fa1e8c4024309ce1ecccb5 - 210035d47ac72e8a`) - - // Mock random reader - randReader = bytes.NewReader(fromHexBytes(` - 017341ae3875d5f87101f8cc4fa9b9bc156bb04628fccdb2f4f11e905bd3 - a155d376f593bd7304210874eba08a5e22bcccb4c9d3882a93a54db022f5 - 03d16338b6b7ce16dc7f4bbf9a96b59772d6606e9747c7649bf9e083db98 - 1884a954ab3c6f18b776ea21069d69776a33e96bad48e1dda0a5ef`)) - defer resetRandReader() - - // RSA-PKCS1v1.5 encrypt - enc := new(rsaEncrypterVerifier) - enc.publicKey = &priv.PublicKey - encryptedPKCS, err := enc.encrypt(input, RSA1_5) - if err != nil { - t.Error("Encryption failed:", err) - return - } - - if bytes.Compare(encryptedPKCS, expectedPKCS) != 0 { - t.Error("Output does not match expected value (PKCS1v1.5)") - } - - // RSA-OAEP encrypt - encryptedOAEP, err := enc.encrypt(input, RSA_OAEP) - if err != nil { - t.Error("Encryption failed:", err) - return - } - - if bytes.Compare(encryptedOAEP, expectedOAEP) != 0 { - t.Error("Output does not match expected value (OAEP)") - } - - // Need fake cipher for PKCS1v1.5 decrypt - resetRandReader() - aes := newAESGCM(len(input)) - - keygen := randomKeyGenerator{ - size: aes.keySize(), - } - - // RSA-PKCS1v1.5 decrypt - dec := new(rsaDecrypterSigner) - dec.privateKey = priv - decryptedPKCS, err := dec.decrypt(encryptedPKCS, RSA1_5, keygen) - if err != nil { - t.Error("Decryption failed:", err) - return - } - - if bytes.Compare(input, decryptedPKCS) != 0 { - t.Error("Output does not match expected value (PKCS1v1.5)") - } - - // RSA-OAEP decrypt - decryptedOAEP, err := dec.decrypt(encryptedOAEP, RSA_OAEP, keygen) - if err != nil { - t.Error("decryption failed:", err) - return - } - - if bytes.Compare(input, decryptedOAEP) != 0 { - t.Error("output does not match expected value (OAEP)") - } -} - -func TestEd25519(t *testing.T) { - _, err := newEd25519Signer("XYZ", nil) - if err != ErrUnsupportedAlgorithm { - t.Error("should return error on invalid algorithm") - } - - enc := new(edEncrypterVerifier) - enc.publicKey = ed25519PublicKey - err = enc.verifyPayload([]byte{}, []byte{}, "XYZ") - if err != ErrUnsupportedAlgorithm { - t.Error("should return error on invalid algorithm") - } - - dec := new(edDecrypterSigner) - dec.privateKey = ed25519PrivateKey - _, err = dec.signPayload([]byte{}, "XYZ") - if err != ErrUnsupportedAlgorithm { - t.Error("should return error on invalid algorithm") - } - - sig, err := dec.signPayload([]byte("This is a test"), "EdDSA") - if err != nil { - t.Error("should not error trying to sign payload") - } - if sig.Signature == nil { - t.Error("Check the signature") - } - err = enc.verifyPayload([]byte("This is a test"), sig.Signature, "EdDSA") - if err != nil { - t.Error("should not error trying to verify payload") - } - - err = enc.verifyPayload([]byte("This is test number 2"), sig.Signature, "EdDSA") - if err == nil { - t.Error("should not error trying to verify payload") - } -} - -func TestInvalidAlgorithmsRSA(t *testing.T) { - _, err := newRSARecipient("XYZ", nil) - if err != ErrUnsupportedAlgorithm { - t.Error("should return error on invalid algorithm") - } - - _, err = newRSASigner("XYZ", nil) - if err != ErrUnsupportedAlgorithm { - t.Error("should return error on invalid algorithm") - } - - enc := new(rsaEncrypterVerifier) - enc.publicKey = &rsaTestKey.PublicKey - _, err = enc.encryptKey([]byte{}, "XYZ") - if err != ErrUnsupportedAlgorithm { - t.Error("should return error on invalid algorithm") - } - - err = enc.verifyPayload([]byte{}, []byte{}, "XYZ") - if err != ErrUnsupportedAlgorithm { - t.Error("should return error on invalid algorithm") - } - - dec := new(rsaDecrypterSigner) - dec.privateKey = rsaTestKey - _, err = dec.decrypt(make([]byte, 256), "XYZ", randomKeyGenerator{size: 16}) - if err != ErrUnsupportedAlgorithm { - t.Error("should return error on invalid algorithm") - } - - _, err = dec.signPayload([]byte{}, "XYZ") - if err != ErrUnsupportedAlgorithm { - t.Error("should return error on invalid algorithm") - } -} - -type failingKeyGenerator struct{} - -func (ctx failingKeyGenerator) keySize() int { - return 0 -} - -func (ctx failingKeyGenerator) genKey() ([]byte, rawHeader, error) { - return nil, rawHeader{}, errors.New("failed to generate key") -} - -func TestPKCSKeyGeneratorFailure(t *testing.T) { - dec := new(rsaDecrypterSigner) - dec.privateKey = rsaTestKey - generator := failingKeyGenerator{} - _, err := dec.decrypt(make([]byte, 256), RSA1_5, generator) - if err != ErrCryptoFailure { - t.Error("should return error on invalid algorithm") - } -} - -func TestInvalidAlgorithmsEC(t *testing.T) { - _, err := newECDHRecipient("XYZ", nil) - if err != ErrUnsupportedAlgorithm { - t.Error("should return error on invalid algorithm") - } - - _, err = newECDSASigner("XYZ", nil) - if err != ErrUnsupportedAlgorithm { - t.Error("should return error on invalid algorithm") - } - - enc := new(ecEncrypterVerifier) - enc.publicKey = &ecTestKey256.PublicKey - _, err = enc.encryptKey([]byte{}, "XYZ") - if err != ErrUnsupportedAlgorithm { - t.Error("should return error on invalid algorithm") - } -} - -func TestInvalidECKeyGen(t *testing.T) { - gen := ecKeyGenerator{ - size: 16, - algID: "A128GCM", - publicKey: &ecTestKey256.PublicKey, - } - - if gen.keySize() != 16 { - t.Error("ec key generator reported incorrect key size") - } - - _, _, err := gen.genKey() - if err != nil { - t.Error("ec key generator failed to generate key", err) - } -} - -func TestInvalidECDecrypt(t *testing.T) { - dec := ecDecrypterSigner{ - privateKey: ecTestKey256, - } - - generator := randomKeyGenerator{size: 16} - - // Missing epk header - headers := rawHeader{} - headers.set(headerAlgorithm, ECDH_ES) - - _, err := dec.decryptKey(headers, nil, generator) - if err == nil { - t.Error("ec decrypter accepted object with missing epk header") - } - - // Invalid epk header - headers.set(headerEPK, &JSONWebKey{}) - - _, err = dec.decryptKey(headers, nil, generator) - if err == nil { - t.Error("ec decrypter accepted object with invalid epk header") - } -} - -func TestDecryptWithIncorrectSize(t *testing.T) { - priv, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - t.Error(err) - return - } - - dec := new(rsaDecrypterSigner) - dec.privateKey = priv - aes := newAESGCM(16) - - keygen := randomKeyGenerator{ - size: aes.keySize(), - } - - payload := make([]byte, 254) - _, err = dec.decrypt(payload, RSA1_5, keygen) - if err == nil { - t.Error("Invalid payload size should return error") - } - - payload = make([]byte, 257) - _, err = dec.decrypt(payload, RSA1_5, keygen) - if err == nil { - t.Error("Invalid payload size should return error") - } -} - -func TestPKCSDecryptNeverFails(t *testing.T) { - // We don't want RSA-PKCS1 v1.5 decryption to ever fail, in order to prevent - // side-channel timing attacks (Bleichenbacher attack in particular). - priv, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - t.Error(err) - return - } - - dec := new(rsaDecrypterSigner) - dec.privateKey = priv - aes := newAESGCM(16) - - keygen := randomKeyGenerator{ - size: aes.keySize(), - } - - for i := 1; i < 50; i++ { - payload := make([]byte, 256) - _, err := io.ReadFull(rand.Reader, payload) - if err != nil { - t.Error("Unable to get random data:", err) - return - } - _, err = dec.decrypt(payload, RSA1_5, keygen) - if err != nil { - t.Error("PKCS1v1.5 decrypt should never fail:", err) - return - } - } -} - -func BenchmarkPKCSDecryptWithValidPayloads(b *testing.B) { - priv, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - panic(err) - } - - enc := new(rsaEncrypterVerifier) - enc.publicKey = &priv.PublicKey - dec := new(rsaDecrypterSigner) - dec.privateKey = priv - aes := newAESGCM(32) - - b.StopTimer() - b.ResetTimer() - for i := 0; i < b.N; i++ { - plaintext := make([]byte, 32) - _, err = io.ReadFull(rand.Reader, plaintext) - if err != nil { - panic(err) - } - - ciphertext, err := enc.encrypt(plaintext, RSA1_5) - if err != nil { - panic(err) - } - - keygen := randomKeyGenerator{ - size: aes.keySize(), - } - - b.StartTimer() - _, err = dec.decrypt(ciphertext, RSA1_5, keygen) - b.StopTimer() - if err != nil { - panic(err) - } - } -} - -func BenchmarkPKCSDecryptWithInvalidPayloads(b *testing.B) { - priv, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - panic(err) - } - - enc := new(rsaEncrypterVerifier) - enc.publicKey = &priv.PublicKey - dec := new(rsaDecrypterSigner) - dec.privateKey = priv - aes := newAESGCM(16) - - keygen := randomKeyGenerator{ - size: aes.keySize(), - } - - b.StopTimer() - b.ResetTimer() - for i := 0; i < b.N; i++ { - plaintext := make([]byte, 16) - _, err = io.ReadFull(rand.Reader, plaintext) - if err != nil { - panic(err) - } - - ciphertext, err := enc.encrypt(plaintext, RSA1_5) - if err != nil { - panic(err) - } - - // Do some simple scrambling - ciphertext[128] ^= 0xFF - - b.StartTimer() - _, err = dec.decrypt(ciphertext, RSA1_5, keygen) - b.StopTimer() - if err != nil { - panic(err) - } - } -} - -func TestInvalidEllipticCurve(t *testing.T) { - signer256 := ecDecrypterSigner{privateKey: ecTestKey256} - signer384 := ecDecrypterSigner{privateKey: ecTestKey384} - signer521 := ecDecrypterSigner{privateKey: ecTestKey521} - - _, err := signer256.signPayload([]byte{}, ES384) - if err == nil { - t.Error("should not generate ES384 signature with P-256 key") - } - _, err = signer256.signPayload([]byte{}, ES512) - if err == nil { - t.Error("should not generate ES512 signature with P-256 key") - } - _, err = signer384.signPayload([]byte{}, ES256) - if err == nil { - t.Error("should not generate ES256 signature with P-384 key") - } - _, err = signer384.signPayload([]byte{}, ES512) - if err == nil { - t.Error("should not generate ES512 signature with P-384 key") - } - _, err = signer521.signPayload([]byte{}, ES256) - if err == nil { - t.Error("should not generate ES256 signature with P-521 key") - } - _, err = signer521.signPayload([]byte{}, ES384) - if err == nil { - t.Error("should not generate ES384 signature with P-521 key") - } -} - -func estInvalidECPublicKey(t *testing.T) { - // Invalid key - invalid := &ecdsa.PrivateKey{ - PublicKey: ecdsa.PublicKey{ - Curve: elliptic.P256(), - X: fromBase64Int("MTEx"), - Y: fromBase64Int("MTEx"), - }, - D: fromBase64Int("0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo"), - } - - headers := rawHeader{} - headers.set(headerAlgorithm, ECDH_ES) - headers.set(headerEPK, &JSONWebKey{ - Key: &invalid.PublicKey, - }) - - dec := ecDecrypterSigner{ - privateKey: ecTestKey256, - } - - _, err := dec.decryptKey(headers, nil, randomKeyGenerator{size: 16}) - if err == nil { - t.Fatal("decrypter accepted JWS with invalid ECDH public key") - } -} - -func TestInvalidAlgorithmEC(t *testing.T) { - err := ecEncrypterVerifier{publicKey: &ecTestKey256.PublicKey}.verifyPayload([]byte{}, []byte{}, "XYZ") - if err != ErrUnsupportedAlgorithm { - t.Fatal("should not accept invalid/unsupported algorithm") - } -} diff --git a/vendor/gopkg.in/square/go-jose.v2/cipher/cbc_hmac_test.go b/vendor/gopkg.in/square/go-jose.v2/cipher/cbc_hmac_test.go deleted file mode 100644 index 40bcb20fa..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/cipher/cbc_hmac_test.go +++ /dev/null @@ -1,498 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package josecipher - -import ( - "bytes" - "crypto/aes" - "crypto/cipher" - "crypto/rand" - "io" - "strings" - "testing" -) - -func TestInvalidInputs(t *testing.T) { - key := []byte{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - } - - nonce := []byte{ - 92, 80, 104, 49, 133, 25, 161, 215, 173, 101, 219, 211, 136, 91, 210, 145} - - aead, _ := NewCBCHMAC(key, aes.NewCipher) - ciphertext := aead.Seal(nil, nonce, []byte("plaintext"), []byte("aad")) - - // Changed AAD, must fail - _, err := aead.Open(nil, nonce, ciphertext, []byte("INVALID")) - if err == nil { - t.Error("must detect invalid aad") - } - - // Empty ciphertext, must fail - _, err = aead.Open(nil, nonce, []byte{}, []byte("aad")) - if err == nil { - t.Error("must detect invalid/empty ciphertext") - } - - // Corrupt ciphertext, must fail - corrupt := make([]byte, len(ciphertext)) - copy(corrupt, ciphertext) - corrupt[0] ^= 0xFF - - _, err = aead.Open(nil, nonce, corrupt, []byte("aad")) - if err == nil { - t.Error("must detect corrupt ciphertext") - } - - // Corrupt authtag, must fail - copy(corrupt, ciphertext) - corrupt[len(ciphertext)-1] ^= 0xFF - - _, err = aead.Open(nil, nonce, corrupt, []byte("aad")) - if err == nil { - t.Error("must detect corrupt authtag") - } - - // Truncated data, must fail - _, err = aead.Open(nil, nonce, ciphertext[:10], []byte("aad")) - if err == nil { - t.Error("must detect corrupt authtag") - } -} - -func TestVectorsAESCBC128(t *testing.T) { - // Source: http://tools.ietf.org/html/draft-ietf-jose-json-web-encryption-29#appendix-A.2 - plaintext := []byte{ - 76, 105, 118, 101, 32, 108, 111, 110, 103, 32, 97, 110, 100, 32, - 112, 114, 111, 115, 112, 101, 114, 46} - - aad := []byte{ - 101, 121, 74, 104, 98, 71, 99, 105, 79, 105, 74, 83, 85, 48, 69, - 120, 88, 122, 85, 105, 76, 67, 74, 108, 98, 109, 77, 105, 79, 105, - 74, 66, 77, 84, 73, 52, 81, 48, 74, 68, 76, 85, 104, 84, 77, 106, 85, - 50, 73, 110, 48} - - expectedCiphertext := []byte{ - 40, 57, 83, 181, 119, 33, 133, 148, 198, 185, 243, 24, 152, 230, 6, - 75, 129, 223, 127, 19, 210, 82, 183, 230, 168, 33, 215, 104, 143, - 112, 56, 102} - - expectedAuthtag := []byte{ - 246, 17, 244, 190, 4, 95, 98, 3, 231, 0, 115, 157, 242, 203, 100, - 191} - - key := []byte{ - 4, 211, 31, 197, 84, 157, 252, 254, 11, 100, 157, 250, 63, 170, 106, 206, - 107, 124, 212, 45, 111, 107, 9, 219, 200, 177, 0, 240, 143, 156, 44, 207} - - nonce := []byte{ - 3, 22, 60, 12, 43, 67, 104, 105, 108, 108, 105, 99, 111, 116, 104, 101} - - enc, err := NewCBCHMAC(key, aes.NewCipher) - out := enc.Seal(nil, nonce, plaintext, aad) - if err != nil { - t.Error("Unable to encrypt:", err) - return - } - - if bytes.Compare(out[:len(out)-16], expectedCiphertext) != 0 { - t.Error("Ciphertext did not match") - } - if bytes.Compare(out[len(out)-16:], expectedAuthtag) != 0 { - t.Error("Auth tag did not match") - } -} - -func TestVectorsAESCBC256(t *testing.T) { - // Source: https://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha2-05#section-5.4 - plaintext := []byte{ - 0x41, 0x20, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, - 0x6d, 0x75, 0x73, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x73, 0x65, 0x63, 0x72, 0x65, - 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, - 0x65, 0x20, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x61, 0x6c, 0x6c, 0x20, 0x69, - 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x6f, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x65, 0x6d, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, - 0x75, 0x74, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x6e, 0x69, 0x65, 0x6e, 0x63, 0x65} - - aad := []byte{ - 0x54, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x63, - 0x69, 0x70, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x65, 0x20, - 0x4b, 0x65, 0x72, 0x63, 0x6b, 0x68, 0x6f, 0x66, 0x66, 0x73} - - expectedCiphertext := []byte{ - 0x4a, 0xff, 0xaa, 0xad, 0xb7, 0x8c, 0x31, 0xc5, 0xda, 0x4b, 0x1b, 0x59, 0x0d, 0x10, 0xff, 0xbd, - 0x3d, 0xd8, 0xd5, 0xd3, 0x02, 0x42, 0x35, 0x26, 0x91, 0x2d, 0xa0, 0x37, 0xec, 0xbc, 0xc7, 0xbd, - 0x82, 0x2c, 0x30, 0x1d, 0xd6, 0x7c, 0x37, 0x3b, 0xcc, 0xb5, 0x84, 0xad, 0x3e, 0x92, 0x79, 0xc2, - 0xe6, 0xd1, 0x2a, 0x13, 0x74, 0xb7, 0x7f, 0x07, 0x75, 0x53, 0xdf, 0x82, 0x94, 0x10, 0x44, 0x6b, - 0x36, 0xeb, 0xd9, 0x70, 0x66, 0x29, 0x6a, 0xe6, 0x42, 0x7e, 0xa7, 0x5c, 0x2e, 0x08, 0x46, 0xa1, - 0x1a, 0x09, 0xcc, 0xf5, 0x37, 0x0d, 0xc8, 0x0b, 0xfe, 0xcb, 0xad, 0x28, 0xc7, 0x3f, 0x09, 0xb3, - 0xa3, 0xb7, 0x5e, 0x66, 0x2a, 0x25, 0x94, 0x41, 0x0a, 0xe4, 0x96, 0xb2, 0xe2, 0xe6, 0x60, 0x9e, - 0x31, 0xe6, 0xe0, 0x2c, 0xc8, 0x37, 0xf0, 0x53, 0xd2, 0x1f, 0x37, 0xff, 0x4f, 0x51, 0x95, 0x0b, - 0xbe, 0x26, 0x38, 0xd0, 0x9d, 0xd7, 0xa4, 0x93, 0x09, 0x30, 0x80, 0x6d, 0x07, 0x03, 0xb1, 0xf6} - - expectedAuthtag := []byte{ - 0x4d, 0xd3, 0xb4, 0xc0, 0x88, 0xa7, 0xf4, 0x5c, 0x21, 0x68, 0x39, 0x64, 0x5b, 0x20, 0x12, 0xbf, - 0x2e, 0x62, 0x69, 0xa8, 0xc5, 0x6a, 0x81, 0x6d, 0xbc, 0x1b, 0x26, 0x77, 0x61, 0x95, 0x5b, 0xc5} - - key := []byte{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f} - - nonce := []byte{ - 0x1a, 0xf3, 0x8c, 0x2d, 0xc2, 0xb9, 0x6f, 0xfd, 0xd8, 0x66, 0x94, 0x09, 0x23, 0x41, 0xbc, 0x04} - - enc, err := NewCBCHMAC(key, aes.NewCipher) - out := enc.Seal(nil, nonce, plaintext, aad) - if err != nil { - t.Error("Unable to encrypt:", err) - return - } - - if bytes.Compare(out[:len(out)-32], expectedCiphertext) != 0 { - t.Error("Ciphertext did not match, got", out[:len(out)-32], "wanted", expectedCiphertext) - } - if bytes.Compare(out[len(out)-32:], expectedAuthtag) != 0 { - t.Error("Auth tag did not match, got", out[len(out)-32:], "wanted", expectedAuthtag) - } -} - -func TestAESCBCRoundtrip(t *testing.T) { - key128 := []byte{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} - - key192 := []byte{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7} - - key256 := []byte{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} - - nonce := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} - - RunRoundtrip(t, key128, nonce) - RunRoundtrip(t, key192, nonce) - RunRoundtrip(t, key256, nonce) -} - -func RunRoundtrip(t *testing.T, key, nonce []byte) { - aead, err := NewCBCHMAC(key, aes.NewCipher) - if err != nil { - panic(err) - } - - if aead.NonceSize() != len(nonce) { - panic("invalid nonce") - } - - // Test pre-existing data in dst buffer - dst := []byte{15, 15, 15, 15} - plaintext := []byte{0, 0, 0, 0} - aad := []byte{4, 3, 2, 1} - - result := aead.Seal(dst, nonce, plaintext, aad) - if bytes.Compare(dst, result[:4]) != 0 { - t.Error("Existing data in dst not preserved") - } - - // Test pre-existing (empty) dst buffer with sufficient capacity - dst = make([]byte, 256)[:0] - result, err = aead.Open(dst, nonce, result[4:], aad) - if err != nil { - panic(err) - } - - if bytes.Compare(result, plaintext) != 0 { - t.Error("Plaintext does not match output") - } -} - -func TestAESCBCOverhead(t *testing.T) { - aead, err := NewCBCHMAC(make([]byte, 32), aes.NewCipher) - if err != nil { - panic(err) - } - - if aead.Overhead() != 32 { - t.Error("CBC-HMAC reports incorrect overhead value") - } -} - -func TestPadding(t *testing.T) { - for i := 0; i < 256; i++ { - slice := make([]byte, i) - padded := padBuffer(slice, 16) - if len(padded)%16 != 0 { - t.Error("failed to pad slice properly", i) - return - } - unpadded, err := unpadBuffer(padded, 16) - if err != nil || len(unpadded) != i { - t.Error("failed to unpad slice properly", i) - return - } - } -} - -func TestInvalidKey(t *testing.T) { - key := make([]byte, 30) - _, err := NewCBCHMAC(key, aes.NewCipher) - if err == nil { - t.Error("should not be able to instantiate CBC-HMAC with invalid key") - } -} - -func TestTruncatedCiphertext(t *testing.T) { - key := make([]byte, 32) - nonce := make([]byte, 16) - data := make([]byte, 32) - - io.ReadFull(rand.Reader, key) - io.ReadFull(rand.Reader, nonce) - - aead, err := NewCBCHMAC(key, aes.NewCipher) - if err != nil { - panic(err) - } - - ctx := aead.(*cbcAEAD) - ct := aead.Seal(nil, nonce, data, nil) - - // Truncated ciphertext, but with correct auth tag - truncated, tail := resize(ct[:len(ct)-ctx.authtagBytes-2], uint64(len(ct))-2) - copy(tail, ctx.computeAuthTag(nil, nonce, truncated[:len(truncated)-ctx.authtagBytes])) - - // Open should fail - _, err = aead.Open(nil, nonce, truncated, nil) - if err == nil { - t.Error("open on truncated ciphertext should fail") - } -} - -func TestInvalidPaddingOpen(t *testing.T) { - key := make([]byte, 32) - nonce := make([]byte, 16) - - // Plaintext with invalid padding - plaintext := padBuffer(make([]byte, 28), aes.BlockSize) - plaintext[len(plaintext)-1] = 0xFF - - io.ReadFull(rand.Reader, key) - io.ReadFull(rand.Reader, nonce) - - block, _ := aes.NewCipher(key) - cbc := cipher.NewCBCEncrypter(block, nonce) - buffer := append([]byte{}, plaintext...) - cbc.CryptBlocks(buffer, buffer) - - aead, _ := NewCBCHMAC(key, aes.NewCipher) - ctx := aead.(*cbcAEAD) - - // Mutated ciphertext, but with correct auth tag - size := uint64(len(buffer)) - ciphertext, tail := resize(buffer, size+(uint64(len(key))/2)) - copy(tail, ctx.computeAuthTag(nil, nonce, ciphertext[:size])) - - // Open should fail (b/c of invalid padding, even though tag matches) - _, err := aead.Open(nil, nonce, ciphertext, nil) - if err == nil || !strings.Contains(err.Error(), "invalid padding") { - t.Error("no or unexpected error on open with invalid padding:", err) - } -} - -func TestInvalidPadding(t *testing.T) { - for i := 0; i < 256; i++ { - slice := make([]byte, i) - padded := padBuffer(slice, 16) - if len(padded)%16 != 0 { - t.Error("failed to pad slice properly", i) - return - } - - paddingBytes := 16 - (i % 16) - - // Mutate padding for testing - for j := 1; j <= paddingBytes; j++ { - mutated := make([]byte, len(padded)) - copy(mutated, padded) - mutated[len(mutated)-j] ^= 0xFF - - _, err := unpadBuffer(mutated, 16) - if err == nil { - t.Error("unpad on invalid padding should fail", i) - return - } - } - - // Test truncated padding - _, err := unpadBuffer(padded[:len(padded)-1], 16) - if err == nil { - t.Error("unpad on truncated padding should fail", i) - return - } - } -} - -func TestZeroLengthPadding(t *testing.T) { - data := make([]byte, 16) - data, err := unpadBuffer(data, 16) - if err == nil { - t.Error("padding with 0x00 should never be valid") - } -} - -func benchEncryptCBCHMAC(b *testing.B, keySize, chunkSize int) { - key := make([]byte, keySize*2) - nonce := make([]byte, 16) - - io.ReadFull(rand.Reader, key) - io.ReadFull(rand.Reader, nonce) - - chunk := make([]byte, chunkSize) - - aead, err := NewCBCHMAC(key, aes.NewCipher) - if err != nil { - panic(err) - } - - b.SetBytes(int64(chunkSize)) - b.ResetTimer() - for i := 0; i < b.N; i++ { - aead.Seal(nil, nonce, chunk, nil) - } -} - -func benchDecryptCBCHMAC(b *testing.B, keySize, chunkSize int) { - key := make([]byte, keySize*2) - nonce := make([]byte, 16) - - io.ReadFull(rand.Reader, key) - io.ReadFull(rand.Reader, nonce) - - chunk := make([]byte, chunkSize) - - aead, err := NewCBCHMAC(key, aes.NewCipher) - if err != nil { - panic(err) - } - - out := aead.Seal(nil, nonce, chunk, nil) - - b.SetBytes(int64(chunkSize)) - b.ResetTimer() - for i := 0; i < b.N; i++ { - aead.Open(nil, nonce, out, nil) - } -} - -func BenchmarkEncryptAES128_CBCHMAC_1k(b *testing.B) { - benchEncryptCBCHMAC(b, 16, 1024) -} - -func BenchmarkEncryptAES128_CBCHMAC_64k(b *testing.B) { - benchEncryptCBCHMAC(b, 16, 65536) -} - -func BenchmarkEncryptAES128_CBCHMAC_1MB(b *testing.B) { - benchEncryptCBCHMAC(b, 16, 1048576) -} - -func BenchmarkEncryptAES128_CBCHMAC_64MB(b *testing.B) { - benchEncryptCBCHMAC(b, 16, 67108864) -} - -func BenchmarkDecryptAES128_CBCHMAC_1k(b *testing.B) { - benchDecryptCBCHMAC(b, 16, 1024) -} - -func BenchmarkDecryptAES128_CBCHMAC_64k(b *testing.B) { - benchDecryptCBCHMAC(b, 16, 65536) -} - -func BenchmarkDecryptAES128_CBCHMAC_1MB(b *testing.B) { - benchDecryptCBCHMAC(b, 16, 1048576) -} - -func BenchmarkDecryptAES128_CBCHMAC_64MB(b *testing.B) { - benchDecryptCBCHMAC(b, 16, 67108864) -} - -func BenchmarkEncryptAES192_CBCHMAC_64k(b *testing.B) { - benchEncryptCBCHMAC(b, 24, 65536) -} - -func BenchmarkEncryptAES192_CBCHMAC_1MB(b *testing.B) { - benchEncryptCBCHMAC(b, 24, 1048576) -} - -func BenchmarkEncryptAES192_CBCHMAC_64MB(b *testing.B) { - benchEncryptCBCHMAC(b, 24, 67108864) -} - -func BenchmarkDecryptAES192_CBCHMAC_1k(b *testing.B) { - benchDecryptCBCHMAC(b, 24, 1024) -} - -func BenchmarkDecryptAES192_CBCHMAC_64k(b *testing.B) { - benchDecryptCBCHMAC(b, 24, 65536) -} - -func BenchmarkDecryptAES192_CBCHMAC_1MB(b *testing.B) { - benchDecryptCBCHMAC(b, 24, 1048576) -} - -func BenchmarkDecryptAES192_CBCHMAC_64MB(b *testing.B) { - benchDecryptCBCHMAC(b, 24, 67108864) -} - -func BenchmarkEncryptAES256_CBCHMAC_64k(b *testing.B) { - benchEncryptCBCHMAC(b, 32, 65536) -} - -func BenchmarkEncryptAES256_CBCHMAC_1MB(b *testing.B) { - benchEncryptCBCHMAC(b, 32, 1048576) -} - -func BenchmarkEncryptAES256_CBCHMAC_64MB(b *testing.B) { - benchEncryptCBCHMAC(b, 32, 67108864) -} - -func BenchmarkDecryptAES256_CBCHMAC_1k(b *testing.B) { - benchDecryptCBCHMAC(b, 32, 1032) -} - -func BenchmarkDecryptAES256_CBCHMAC_64k(b *testing.B) { - benchDecryptCBCHMAC(b, 32, 65536) -} - -func BenchmarkDecryptAES256_CBCHMAC_1MB(b *testing.B) { - benchDecryptCBCHMAC(b, 32, 1048576) -} - -func BenchmarkDecryptAES256_CBCHMAC_64MB(b *testing.B) { - benchDecryptCBCHMAC(b, 32, 67108864) -} diff --git a/vendor/gopkg.in/square/go-jose.v2/cipher/concat_kdf_test.go b/vendor/gopkg.in/square/go-jose.v2/cipher/concat_kdf_test.go deleted file mode 100644 index 48219b3e1..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/cipher/concat_kdf_test.go +++ /dev/null @@ -1,150 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package josecipher - -import ( - "bytes" - "crypto" - "testing" -) - -// Taken from: https://tools.ietf.org/id/draft-ietf-jose-json-web-algorithms-38.txt -func TestVectorConcatKDF(t *testing.T) { - z := []byte{ - 158, 86, 217, 29, 129, 113, 53, 211, 114, 131, 66, 131, 191, 132, - 38, 156, 251, 49, 110, 163, 218, 128, 106, 72, 246, 218, 167, 121, - 140, 254, 144, 196} - - algID := []byte{0, 0, 0, 7, 65, 49, 50, 56, 71, 67, 77} - - ptyUInfo := []byte{0, 0, 0, 5, 65, 108, 105, 99, 101} - ptyVInfo := []byte{0, 0, 0, 3, 66, 111, 98} - - supPubInfo := []byte{0, 0, 0, 128} - supPrivInfo := []byte{} - - expected := []byte{ - 86, 170, 141, 234, 248, 35, 109, 32, 92, 34, 40, 205, 113, 167, 16, 26} - - ckdf := NewConcatKDF(crypto.SHA256, z, algID, ptyUInfo, ptyVInfo, supPubInfo, supPrivInfo) - - out0 := make([]byte, 9) - out1 := make([]byte, 7) - - read0, err := ckdf.Read(out0) - if err != nil { - t.Error("error when reading from concat kdf reader", err) - return - } - - read1, err := ckdf.Read(out1) - if err != nil { - t.Error("error when reading from concat kdf reader", err) - return - } - - if read0+read1 != len(out0)+len(out1) { - t.Error("did not receive enough bytes from concat kdf reader") - return - } - - out := []byte{} - out = append(out, out0...) - out = append(out, out1...) - - if bytes.Compare(out, expected) != 0 { - t.Error("did not receive expected output from concat kdf reader") - return - } -} - -func TestCache(t *testing.T) { - z := []byte{ - 158, 86, 217, 29, 129, 113, 53, 211, 114, 131, 66, 131, 191, 132, - 38, 156, 251, 49, 110, 163, 218, 128, 106, 72, 246, 218, 167, 121, - 140, 254, 144, 196} - - algID := []byte{1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4} - - ptyUInfo := []byte{1, 2, 3, 4} - ptyVInfo := []byte{4, 3, 2, 1} - - supPubInfo := []byte{} - supPrivInfo := []byte{} - - outputs := [][]byte{} - - // Read the same amount of data in different chunk sizes - chunkSizes := []int{1, 2, 4, 8, 16, 32, 64, 128, 256, 512} - - for _, c := range chunkSizes { - out := make([]byte, 1024) - reader := NewConcatKDF(crypto.SHA256, z, algID, ptyUInfo, ptyVInfo, supPubInfo, supPrivInfo) - - for i := 0; i < 1024; i += c { - _, _ = reader.Read(out[i : i+c]) - } - - outputs = append(outputs, out) - } - - for i := range outputs { - if bytes.Compare(outputs[i], outputs[(i+1)%len(outputs)]) != 0 { - t.Error("not all outputs from KDF matched") - } - } -} - -func benchmarkKDF(b *testing.B, total int) { - z := []byte{ - 158, 86, 217, 29, 129, 113, 53, 211, 114, 131, 66, 131, 191, 132, - 38, 156, 251, 49, 110, 163, 218, 128, 106, 72, 246, 218, 167, 121, - 140, 254, 144, 196} - - algID := []byte{1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4} - - ptyUInfo := []byte{1, 2, 3, 4} - ptyVInfo := []byte{4, 3, 2, 1} - - supPubInfo := []byte{} - supPrivInfo := []byte{} - - out := make([]byte, total) - reader := NewConcatKDF(crypto.SHA256, z, algID, ptyUInfo, ptyVInfo, supPubInfo, supPrivInfo) - - b.ResetTimer() - b.SetBytes(int64(total)) - for i := 0; i < b.N; i++ { - _, _ = reader.Read(out) - } -} - -func BenchmarkConcatKDF_1k(b *testing.B) { - benchmarkKDF(b, 1024) -} - -func BenchmarkConcatKDF_64k(b *testing.B) { - benchmarkKDF(b, 65536) -} - -func BenchmarkConcatKDF_1MB(b *testing.B) { - benchmarkKDF(b, 1048576) -} - -func BenchmarkConcatKDF_64MB(b *testing.B) { - benchmarkKDF(b, 67108864) -} diff --git a/vendor/gopkg.in/square/go-jose.v2/cipher/ecdh_es_test.go b/vendor/gopkg.in/square/go-jose.v2/cipher/ecdh_es_test.go deleted file mode 100644 index 58fb4c67b..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/cipher/ecdh_es_test.go +++ /dev/null @@ -1,115 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package josecipher - -import ( - "bytes" - "crypto/ecdsa" - "crypto/elliptic" - "encoding/base64" - "math/big" - "testing" -) - -// Example keys from JWA, Appendix C -var aliceKey = &ecdsa.PrivateKey{ - PublicKey: ecdsa.PublicKey{ - Curve: elliptic.P256(), - X: fromBase64Int("gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0="), - Y: fromBase64Int("SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps="), - }, - D: fromBase64Int("0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo="), -} - -var bobKey = &ecdsa.PrivateKey{ - PublicKey: ecdsa.PublicKey{ - Curve: elliptic.P256(), - X: fromBase64Int("weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ="), - Y: fromBase64Int("e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck="), - }, - D: fromBase64Int("VEmDZpDXXK8p8N0Cndsxs924q6nS1RXFASRl6BfUqdw="), -} - -// Build big int from base64-encoded string. Strips whitespace (for testing). -func fromBase64Int(data string) *big.Int { - val, err := base64.URLEncoding.DecodeString(data) - if err != nil { - panic("Invalid test data: " + err.Error()) - } - return new(big.Int).SetBytes(val) -} - -func TestVectorECDHES(t *testing.T) { - apuData := []byte("Alice") - apvData := []byte("Bob") - - expected := []byte{ - 86, 170, 141, 234, 248, 35, 109, 32, 92, 34, 40, 205, 113, 167, 16, 26} - - output := DeriveECDHES("A128GCM", apuData, apvData, bobKey, &aliceKey.PublicKey, 16) - - if bytes.Compare(output, expected) != 0 { - t.Error("output did not match what we expect, got", output, "wanted", expected) - } -} - -func TestInvalidECPublicKey(t *testing.T) { - defer func() { recover() }() - - // Invalid key - invalid := &ecdsa.PrivateKey{ - PublicKey: ecdsa.PublicKey{ - Curve: elliptic.P256(), - X: fromBase64Int("MTEx"), - Y: fromBase64Int("MTEx"), - }, - D: fromBase64Int("0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo="), - } - - DeriveECDHES("A128GCM", []byte{}, []byte{}, bobKey, &invalid.PublicKey, 16) - t.Fatal("should panic if public key was invalid") -} - -func BenchmarkECDHES_128(b *testing.B) { - apuData := []byte("APU") - apvData := []byte("APV") - - b.ResetTimer() - for i := 0; i < b.N; i++ { - DeriveECDHES("ID", apuData, apvData, bobKey, &aliceKey.PublicKey, 16) - } -} - -func BenchmarkECDHES_192(b *testing.B) { - apuData := []byte("APU") - apvData := []byte("APV") - - b.ResetTimer() - for i := 0; i < b.N; i++ { - DeriveECDHES("ID", apuData, apvData, bobKey, &aliceKey.PublicKey, 24) - } -} - -func BenchmarkECDHES_256(b *testing.B) { - apuData := []byte("APU") - apvData := []byte("APV") - - b.ResetTimer() - for i := 0; i < b.N; i++ { - DeriveECDHES("ID", apuData, apvData, bobKey, &aliceKey.PublicKey, 32) - } -} diff --git a/vendor/gopkg.in/square/go-jose.v2/cipher/key_wrap_test.go b/vendor/gopkg.in/square/go-jose.v2/cipher/key_wrap_test.go deleted file mode 100644 index ceecf812b..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/cipher/key_wrap_test.go +++ /dev/null @@ -1,133 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package josecipher - -import ( - "bytes" - "crypto/aes" - "encoding/hex" - "testing" -) - -func TestAesKeyWrap(t *testing.T) { - // Test vectors from: http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf - kek0, _ := hex.DecodeString("000102030405060708090A0B0C0D0E0F") - cek0, _ := hex.DecodeString("00112233445566778899AABBCCDDEEFF") - - expected0, _ := hex.DecodeString("1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5") - - kek1, _ := hex.DecodeString("000102030405060708090A0B0C0D0E0F1011121314151617") - cek1, _ := hex.DecodeString("00112233445566778899AABBCCDDEEFF") - - expected1, _ := hex.DecodeString("96778B25AE6CA435F92B5B97C050AED2468AB8A17AD84E5D") - - kek2, _ := hex.DecodeString("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F") - cek2, _ := hex.DecodeString("00112233445566778899AABBCCDDEEFF0001020304050607") - - expected2, _ := hex.DecodeString("A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB8958CD5D17D6B254DA1") - - block0, _ := aes.NewCipher(kek0) - block1, _ := aes.NewCipher(kek1) - block2, _ := aes.NewCipher(kek2) - - out0, _ := KeyWrap(block0, cek0) - out1, _ := KeyWrap(block1, cek1) - out2, _ := KeyWrap(block2, cek2) - - if bytes.Compare(out0, expected0) != 0 { - t.Error("output 0 not as expected, got", out0, "wanted", expected0) - } - - if bytes.Compare(out1, expected1) != 0 { - t.Error("output 1 not as expected, got", out1, "wanted", expected1) - } - - if bytes.Compare(out2, expected2) != 0 { - t.Error("output 2 not as expected, got", out2, "wanted", expected2) - } - - unwrap0, _ := KeyUnwrap(block0, out0) - unwrap1, _ := KeyUnwrap(block1, out1) - unwrap2, _ := KeyUnwrap(block2, out2) - - if bytes.Compare(unwrap0, cek0) != 0 { - t.Error("key unwrap did not return original input, got", unwrap0, "wanted", cek0) - } - - if bytes.Compare(unwrap1, cek1) != 0 { - t.Error("key unwrap did not return original input, got", unwrap1, "wanted", cek1) - } - - if bytes.Compare(unwrap2, cek2) != 0 { - t.Error("key unwrap did not return original input, got", unwrap2, "wanted", cek2) - } -} - -func TestAesKeyWrapInvalid(t *testing.T) { - kek, _ := hex.DecodeString("000102030405060708090A0B0C0D0E0F") - - // Invalid unwrap input (bit flipped) - input0, _ := hex.DecodeString("1EA68C1A8112B447AEF34BD8FB5A7B828D3E862371D2CFE5") - - block, _ := aes.NewCipher(kek) - - _, err := KeyUnwrap(block, input0) - if err == nil { - t.Error("key unwrap failed to detect invalid input") - } - - // Invalid unwrap input (truncated) - input1, _ := hex.DecodeString("1EA68C1A8112B447AEF34BD8FB5A7B828D3E862371D2CF") - - _, err = KeyUnwrap(block, input1) - if err == nil { - t.Error("key unwrap failed to detect truncated input") - } - - // Invalid wrap input (not multiple of 8) - input2, _ := hex.DecodeString("0123456789ABCD") - - _, err = KeyWrap(block, input2) - if err == nil { - t.Error("key wrap accepted invalid input") - } - -} - -func BenchmarkAesKeyWrap(b *testing.B) { - kek, _ := hex.DecodeString("000102030405060708090A0B0C0D0E0F") - key, _ := hex.DecodeString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") - - block, _ := aes.NewCipher(kek) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - KeyWrap(block, key) - } -} - -func BenchmarkAesKeyUnwrap(b *testing.B) { - kek, _ := hex.DecodeString("000102030405060708090A0B0C0D0E0F") - input, _ := hex.DecodeString("1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5") - - block, _ := aes.NewCipher(kek) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - KeyUnwrap(block, input) - } -} diff --git a/vendor/gopkg.in/square/go-jose.v2/crypter_test.go b/vendor/gopkg.in/square/go-jose.v2/crypter_test.go deleted file mode 100644 index 57eff1c37..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/crypter_test.go +++ /dev/null @@ -1,838 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jose - -import ( - "bytes" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "crypto/rsa" - "fmt" - "io" - "reflect" - "testing" - - "golang.org/x/crypto/ed25519" -) - -// We generate only a single RSA and EC key for testing, speeds up tests. -var rsaTestKey, _ = rsa.GenerateKey(rand.Reader, 2048) - -var ecTestKey256, _ = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -var ecTestKey384, _ = ecdsa.GenerateKey(elliptic.P384(), rand.Reader) -var ecTestKey521, _ = ecdsa.GenerateKey(elliptic.P521(), rand.Reader) - -var ed25519PublicKey, ed25519PrivateKey, _ = ed25519.GenerateKey(rand.Reader) - -func RoundtripJWE(keyAlg KeyAlgorithm, encAlg ContentEncryption, compressionAlg CompressionAlgorithm, serializer func(*JSONWebEncryption) (string, error), corrupter func(*JSONWebEncryption) bool, aad []byte, encryptionKey interface{}, decryptionKey interface{}) error { - enc, err := NewEncrypter(encAlg, Recipient{Algorithm: keyAlg, Key: encryptionKey}, &EncrypterOptions{Compression: compressionAlg}) - if err != nil { - return fmt.Errorf("error on new encrypter: %s", err) - } - - input := []byte("Lorem ipsum dolor sit amet") - obj, err := enc.EncryptWithAuthData(input, aad) - if err != nil { - return fmt.Errorf("error in encrypt: %s", err) - } - - msg, err := serializer(obj) - if err != nil { - return fmt.Errorf("error in serializer: %s", err) - } - - parsed, err := ParseEncrypted(msg) - if err != nil { - return fmt.Errorf("error in parse: %s, on msg '%s'", err, msg) - } - - // (Maybe) mangle object - skip := corrupter(parsed) - if skip { - return fmt.Errorf("corrupter indicated message should be skipped") - } - - if bytes.Compare(parsed.GetAuthData(), aad) != 0 { - return fmt.Errorf("auth data in parsed object does not match") - } - - output, err := parsed.Decrypt(decryptionKey) - if err != nil { - return fmt.Errorf("error on decrypt: %s", err) - } - - if bytes.Compare(input, output) != 0 { - return fmt.Errorf("Decrypted output does not match input, got '%s' but wanted '%s'", output, input) - } - - return nil -} - -func TestRoundtripsJWE(t *testing.T) { - // Test matrix - keyAlgs := []KeyAlgorithm{ - DIRECT, ECDH_ES, ECDH_ES_A128KW, ECDH_ES_A192KW, ECDH_ES_A256KW, A128KW, A192KW, A256KW, - RSA1_5, RSA_OAEP, RSA_OAEP_256, A128GCMKW, A192GCMKW, A256GCMKW} - encAlgs := []ContentEncryption{A128GCM, A192GCM, A256GCM, A128CBC_HS256, A192CBC_HS384, A256CBC_HS512} - zipAlgs := []CompressionAlgorithm{NONE, DEFLATE} - - serializers := []func(*JSONWebEncryption) (string, error){ - func(obj *JSONWebEncryption) (string, error) { return obj.CompactSerialize() }, - func(obj *JSONWebEncryption) (string, error) { return obj.FullSerialize(), nil }, - } - - corrupter := func(obj *JSONWebEncryption) bool { return false } - - // Note: can't use AAD with compact serialization - aads := [][]byte{ - nil, - []byte("Ut enim ad minim veniam"), - } - - // Test all different configurations - for _, alg := range keyAlgs { - for _, enc := range encAlgs { - for _, key := range generateTestKeys(alg, enc) { - for _, zip := range zipAlgs { - for i, serializer := range serializers { - err := RoundtripJWE(alg, enc, zip, serializer, corrupter, aads[i], key.enc, key.dec) - if err != nil { - t.Error(err, alg, enc, zip, i) - } - } - } - } - } - } -} - -func TestRoundtripsJWECorrupted(t *testing.T) { - // Test matrix - keyAlgs := []KeyAlgorithm{DIRECT, ECDH_ES, ECDH_ES_A128KW, A128KW, RSA1_5, RSA_OAEP, RSA_OAEP_256, A128GCMKW} - encAlgs := []ContentEncryption{A128GCM, A192GCM, A256GCM, A128CBC_HS256, A192CBC_HS384, A256CBC_HS512} - zipAlgs := []CompressionAlgorithm{NONE, DEFLATE} - - serializers := []func(*JSONWebEncryption) (string, error){ - func(obj *JSONWebEncryption) (string, error) { return obj.CompactSerialize() }, - func(obj *JSONWebEncryption) (string, error) { return obj.FullSerialize(), nil }, - } - - bitflip := func(slice []byte) bool { - if len(slice) > 0 { - slice[0] ^= 0xFF - return false - } - return true - } - - corrupters := []func(*JSONWebEncryption) bool{ - func(obj *JSONWebEncryption) bool { - // Set invalid ciphertext - return bitflip(obj.ciphertext) - }, - func(obj *JSONWebEncryption) bool { - // Set invalid auth tag - return bitflip(obj.tag) - }, - func(obj *JSONWebEncryption) bool { - // Set invalid AAD - return bitflip(obj.aad) - }, - func(obj *JSONWebEncryption) bool { - // Mess with encrypted key - return bitflip(obj.recipients[0].encryptedKey) - }, - func(obj *JSONWebEncryption) bool { - // Mess with GCM-KW auth tag - tag, _ := obj.protected.getTag() - skip := bitflip(tag.bytes()) - if skip { - return true - } - obj.protected.set(headerTag, tag) - return false - }, - } - - // Note: can't use AAD with compact serialization - aads := [][]byte{ - nil, - []byte("Ut enim ad minim veniam"), - } - - // Test all different configurations - for _, alg := range keyAlgs { - for _, enc := range encAlgs { - for _, key := range generateTestKeys(alg, enc) { - for _, zip := range zipAlgs { - for i, serializer := range serializers { - for j, corrupter := range corrupters { - err := RoundtripJWE(alg, enc, zip, serializer, corrupter, aads[i], key.enc, key.dec) - if err == nil { - t.Error("failed to detect corrupt data", err, alg, enc, zip, i, j) - } - } - } - } - } - } - } -} - -func TestEncrypterWithJWKAndKeyID(t *testing.T) { - enc, err := NewEncrypter(A128GCM, Recipient{Algorithm: A128KW, Key: &JSONWebKey{ - KeyID: "test-id", - Key: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - }}, nil) - if err != nil { - t.Error(err) - } - - ciphertext, _ := enc.Encrypt([]byte("Lorem ipsum dolor sit amet")) - - serialized1, _ := ciphertext.CompactSerialize() - serialized2 := ciphertext.FullSerialize() - - parsed1, _ := ParseEncrypted(serialized1) - parsed2, _ := ParseEncrypted(serialized2) - - if parsed1.Header.KeyID != "test-id" { - t.Errorf("expected message to have key id from JWK, but found '%s' instead", parsed1.Header.KeyID) - } - if parsed2.Header.KeyID != "test-id" { - t.Errorf("expected message to have key id from JWK, but found '%s' instead", parsed2.Header.KeyID) - } -} - -func TestEncrypterWithBrokenRand(t *testing.T) { - keyAlgs := []KeyAlgorithm{ECDH_ES_A128KW, A128KW, RSA1_5, RSA_OAEP, RSA_OAEP_256, A128GCMKW} - encAlgs := []ContentEncryption{A128GCM, A192GCM, A256GCM, A128CBC_HS256, A192CBC_HS384, A256CBC_HS512} - - serializer := func(obj *JSONWebEncryption) (string, error) { return obj.CompactSerialize() } - corrupter := func(obj *JSONWebEncryption) bool { return false } - - // Break rand reader - readers := []func() io.Reader{ - // Totally broken - func() io.Reader { return bytes.NewReader([]byte{}) }, - // Not enough bytes - func() io.Reader { return io.LimitReader(rand.Reader, 20) }, - } - - defer resetRandReader() - - for _, alg := range keyAlgs { - for _, enc := range encAlgs { - for _, key := range generateTestKeys(alg, enc) { - for i, getReader := range readers { - randReader = getReader() - err := RoundtripJWE(alg, enc, NONE, serializer, corrupter, nil, key.enc, key.dec) - if err == nil { - t.Error("encrypter should fail if rand is broken", i) - } - } - } - } - } -} - -func TestNewEncrypterErrors(t *testing.T) { - _, err := NewEncrypter("XYZ", Recipient{}, nil) - if err == nil { - t.Error("was able to instantiate encrypter with invalid cipher") - } - - _, err = NewMultiEncrypter("XYZ", []Recipient{}, nil) - if err == nil { - t.Error("was able to instantiate multi-encrypter with invalid cipher") - } - - _, err = NewEncrypter(A128GCM, Recipient{Algorithm: DIRECT, Key: nil}, nil) - if err == nil { - t.Error("was able to instantiate encrypter with invalid direct key") - } - - _, err = NewEncrypter(A128GCM, Recipient{Algorithm: ECDH_ES, Key: nil}, nil) - if err == nil { - t.Error("was able to instantiate encrypter with invalid EC key") - } -} - -func TestMultiRecipientJWE(t *testing.T) { - sharedKey := []byte{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - } - - enc, err := NewMultiEncrypter(A128GCM, []Recipient{ - {Algorithm: RSA_OAEP, Key: &rsaTestKey.PublicKey}, - {Algorithm: A256GCMKW, Key: sharedKey}, - }, nil) - if err != nil { - panic(err) - } - - input := []byte("Lorem ipsum dolor sit amet") - obj, err := enc.Encrypt(input) - if err != nil { - t.Fatal("error in encrypt: ", err) - } - - msg := obj.FullSerialize() - - parsed, err := ParseEncrypted(msg) - if err != nil { - t.Fatal("error in parse: ", err) - } - - i, _, output, err := parsed.DecryptMulti(rsaTestKey) - if err != nil { - t.Fatal("error on decrypt with RSA: ", err) - } - - if i != 0 { - t.Fatal("recipient index should be 0 for RSA key") - } - - if bytes.Compare(input, output) != 0 { - t.Fatal("Decrypted output does not match input: ", output, input) - } - - i, _, output, err = parsed.DecryptMulti(sharedKey) - if err != nil { - t.Fatal("error on decrypt with AES: ", err) - } - - if i != 1 { - t.Fatal("recipient index should be 1 for shared key") - } - - if bytes.Compare(input, output) != 0 { - t.Fatal("Decrypted output does not match input", output, input) - } -} - -func TestMultiRecipientErrors(t *testing.T) { - _, err := NewMultiEncrypter(A128GCM, []Recipient{}, nil) - if err == nil { - t.Error("should fail to instantiate with zero recipients") - } -} - -func TestEncrypterOptions(t *testing.T) { - sharedKey := []byte{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - } - - opts := &EncrypterOptions{ - Compression: DEFLATE, - } - opts.WithType("JWT") - opts.WithContentType("JWT") - enc, err := NewEncrypter(A256GCM, Recipient{Algorithm: A256GCMKW, Key: sharedKey}, opts) - if err != nil { - fmt.Println(err) - t.Error("Failed to create encrypter") - } - - if !reflect.DeepEqual(*opts, enc.Options()) { - t.Error("Encrypter options do not match") - } -} - -// Test that extra headers are generated and parsed in a round trip. -func TestEncrypterExtraHeaderInclusion(t *testing.T) { - sharedKey := []byte{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - } - - opts := &EncrypterOptions{ - Compression: DEFLATE, - } - opts.WithType("JWT") - opts.WithContentType("JWT") - opts.WithHeader(HeaderKey("myCustomHeader"), "xyz") - enc, err := NewEncrypter(A256GCM, Recipient{Algorithm: A256GCMKW, Key: sharedKey}, opts) - if err != nil { - fmt.Println(err) - t.Error("Failed to create encrypter") - } - - if !reflect.DeepEqual(*opts, enc.Options()) { - t.Error("Encrypter options do not match") - } - - input := []byte("Lorem ipsum dolor sit amet") - obj, err := enc.Encrypt(input) - if err != nil { - t.Fatal("error in encrypt: ", err) - } - - parsed, err := ParseEncrypted(obj.FullSerialize()) - if err != nil { - t.Fatal("error in parse: ", err) - } - - output, err := parsed.Decrypt(sharedKey) - if err != nil { - t.Fatal("error on decrypt: ", err) - } - - if bytes.Compare(input, output) != 0 { - t.Fatal("Decrypted output does not match input: ", output, input) - } - - if parsed.Header.ExtraHeaders[HeaderType] != "JWT" || - parsed.Header.ExtraHeaders[HeaderContentType] != "JWT" || - parsed.Header.ExtraHeaders[HeaderKey("myCustomHeader")] != "xyz" { - t.Fatalf("Mismatch in extra headers: %#v", parsed.Header.ExtraHeaders) - } -} - -type testKey struct { - enc, dec interface{} -} - -func symmetricTestKey(size int) []testKey { - key, _, _ := randomKeyGenerator{size: size}.genKey() - - return []testKey{ - { - enc: key, - dec: key, - }, - { - enc: &JSONWebKey{KeyID: "test", Key: key}, - dec: &JSONWebKey{KeyID: "test", Key: key}, - }, - } -} - -func generateTestKeys(keyAlg KeyAlgorithm, encAlg ContentEncryption) []testKey { - switch keyAlg { - case DIRECT: - return symmetricTestKey(getContentCipher(encAlg).keySize()) - case ECDH_ES, ECDH_ES_A128KW, ECDH_ES_A192KW, ECDH_ES_A256KW: - return []testKey{ - { - dec: ecTestKey256, - enc: &ecTestKey256.PublicKey, - }, - { - dec: ecTestKey384, - enc: &ecTestKey384.PublicKey, - }, - { - dec: ecTestKey521, - enc: &ecTestKey521.PublicKey, - }, - { - dec: &JSONWebKey{KeyID: "test", Key: ecTestKey256}, - enc: &JSONWebKey{KeyID: "test", Key: &ecTestKey256.PublicKey}, - }, - } - case A128GCMKW, A128KW: - return symmetricTestKey(16) - case A192GCMKW, A192KW: - return symmetricTestKey(24) - case A256GCMKW, A256KW: - return symmetricTestKey(32) - case RSA1_5, RSA_OAEP, RSA_OAEP_256: - return []testKey{{ - dec: rsaTestKey, - enc: &rsaTestKey.PublicKey, - }} - } - - panic("Must update test case") -} - -func RunRoundtripsJWE(b *testing.B, alg KeyAlgorithm, enc ContentEncryption, zip CompressionAlgorithm, priv, pub interface{}) { - serializer := func(obj *JSONWebEncryption) (string, error) { - return obj.CompactSerialize() - } - - corrupter := func(obj *JSONWebEncryption) bool { return false } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - err := RoundtripJWE(alg, enc, zip, serializer, corrupter, nil, pub, priv) - if err != nil { - b.Error(err) - } - } -} - -var ( - chunks = map[string][]byte{ - "1B": make([]byte, 1), - "64B": make([]byte, 64), - "1KB": make([]byte, 1024), - "64KB": make([]byte, 65536), - "1MB": make([]byte, 1048576), - "64MB": make([]byte, 67108864), - } - - symKey, _, _ = randomKeyGenerator{size: 32}.genKey() - - encrypters = map[string]Encrypter{ - "OAEPAndGCM": mustEncrypter(RSA_OAEP, A128GCM, &rsaTestKey.PublicKey), - "PKCSAndGCM": mustEncrypter(RSA1_5, A128GCM, &rsaTestKey.PublicKey), - "OAEPAndCBC": mustEncrypter(RSA_OAEP, A128CBC_HS256, &rsaTestKey.PublicKey), - "PKCSAndCBC": mustEncrypter(RSA1_5, A128CBC_HS256, &rsaTestKey.PublicKey), - "DirectGCM128": mustEncrypter(DIRECT, A128GCM, symKey), - "DirectCBC128": mustEncrypter(DIRECT, A128CBC_HS256, symKey), - "DirectGCM256": mustEncrypter(DIRECT, A256GCM, symKey), - "DirectCBC256": mustEncrypter(DIRECT, A256CBC_HS512, symKey), - "AESKWAndGCM128": mustEncrypter(A128KW, A128GCM, symKey), - "AESKWAndCBC256": mustEncrypter(A256KW, A256GCM, symKey), - "ECDHOnP256AndGCM128": mustEncrypter(ECDH_ES, A128GCM, &ecTestKey256.PublicKey), - "ECDHOnP384AndGCM128": mustEncrypter(ECDH_ES, A128GCM, &ecTestKey384.PublicKey), - "ECDHOnP521AndGCM128": mustEncrypter(ECDH_ES, A128GCM, &ecTestKey521.PublicKey), - } -) - -func BenchmarkEncrypt1BWithOAEPAndGCM(b *testing.B) { benchEncrypt("1B", "OAEPAndGCM", b) } -func BenchmarkEncrypt64BWithOAEPAndGCM(b *testing.B) { benchEncrypt("64B", "OAEPAndGCM", b) } -func BenchmarkEncrypt1KBWithOAEPAndGCM(b *testing.B) { benchEncrypt("1KB", "OAEPAndGCM", b) } -func BenchmarkEncrypt64KBWithOAEPAndGCM(b *testing.B) { benchEncrypt("64KB", "OAEPAndGCM", b) } -func BenchmarkEncrypt1MBWithOAEPAndGCM(b *testing.B) { benchEncrypt("1MB", "OAEPAndGCM", b) } -func BenchmarkEncrypt64MBWithOAEPAndGCM(b *testing.B) { benchEncrypt("64MB", "OAEPAndGCM", b) } - -func BenchmarkEncrypt1BWithPKCSAndGCM(b *testing.B) { benchEncrypt("1B", "PKCSAndGCM", b) } -func BenchmarkEncrypt64BWithPKCSAndGCM(b *testing.B) { benchEncrypt("64B", "PKCSAndGCM", b) } -func BenchmarkEncrypt1KBWithPKCSAndGCM(b *testing.B) { benchEncrypt("1KB", "PKCSAndGCM", b) } -func BenchmarkEncrypt64KBWithPKCSAndGCM(b *testing.B) { benchEncrypt("64KB", "PKCSAndGCM", b) } -func BenchmarkEncrypt1MBWithPKCSAndGCM(b *testing.B) { benchEncrypt("1MB", "PKCSAndGCM", b) } -func BenchmarkEncrypt64MBWithPKCSAndGCM(b *testing.B) { benchEncrypt("64MB", "PKCSAndGCM", b) } - -func BenchmarkEncrypt1BWithOAEPAndCBC(b *testing.B) { benchEncrypt("1B", "OAEPAndCBC", b) } -func BenchmarkEncrypt64BWithOAEPAndCBC(b *testing.B) { benchEncrypt("64B", "OAEPAndCBC", b) } -func BenchmarkEncrypt1KBWithOAEPAndCBC(b *testing.B) { benchEncrypt("1KB", "OAEPAndCBC", b) } -func BenchmarkEncrypt64KBWithOAEPAndCBC(b *testing.B) { benchEncrypt("64KB", "OAEPAndCBC", b) } -func BenchmarkEncrypt1MBWithOAEPAndCBC(b *testing.B) { benchEncrypt("1MB", "OAEPAndCBC", b) } -func BenchmarkEncrypt64MBWithOAEPAndCBC(b *testing.B) { benchEncrypt("64MB", "OAEPAndCBC", b) } - -func BenchmarkEncrypt1BWithPKCSAndCBC(b *testing.B) { benchEncrypt("1B", "PKCSAndCBC", b) } -func BenchmarkEncrypt64BWithPKCSAndCBC(b *testing.B) { benchEncrypt("64B", "PKCSAndCBC", b) } -func BenchmarkEncrypt1KBWithPKCSAndCBC(b *testing.B) { benchEncrypt("1KB", "PKCSAndCBC", b) } -func BenchmarkEncrypt64KBWithPKCSAndCBC(b *testing.B) { benchEncrypt("64KB", "PKCSAndCBC", b) } -func BenchmarkEncrypt1MBWithPKCSAndCBC(b *testing.B) { benchEncrypt("1MB", "PKCSAndCBC", b) } -func BenchmarkEncrypt64MBWithPKCSAndCBC(b *testing.B) { benchEncrypt("64MB", "PKCSAndCBC", b) } - -func BenchmarkEncrypt1BWithDirectGCM128(b *testing.B) { benchEncrypt("1B", "DirectGCM128", b) } -func BenchmarkEncrypt64BWithDirectGCM128(b *testing.B) { benchEncrypt("64B", "DirectGCM128", b) } -func BenchmarkEncrypt1KBWithDirectGCM128(b *testing.B) { benchEncrypt("1KB", "DirectGCM128", b) } -func BenchmarkEncrypt64KBWithDirectGCM128(b *testing.B) { benchEncrypt("64KB", "DirectGCM128", b) } -func BenchmarkEncrypt1MBWithDirectGCM128(b *testing.B) { benchEncrypt("1MB", "DirectGCM128", b) } -func BenchmarkEncrypt64MBWithDirectGCM128(b *testing.B) { benchEncrypt("64MB", "DirectGCM128", b) } - -func BenchmarkEncrypt1BWithDirectCBC128(b *testing.B) { benchEncrypt("1B", "DirectCBC128", b) } -func BenchmarkEncrypt64BWithDirectCBC128(b *testing.B) { benchEncrypt("64B", "DirectCBC128", b) } -func BenchmarkEncrypt1KBWithDirectCBC128(b *testing.B) { benchEncrypt("1KB", "DirectCBC128", b) } -func BenchmarkEncrypt64KBWithDirectCBC128(b *testing.B) { benchEncrypt("64KB", "DirectCBC128", b) } -func BenchmarkEncrypt1MBWithDirectCBC128(b *testing.B) { benchEncrypt("1MB", "DirectCBC128", b) } -func BenchmarkEncrypt64MBWithDirectCBC128(b *testing.B) { benchEncrypt("64MB", "DirectCBC128", b) } - -func BenchmarkEncrypt1BWithDirectGCM256(b *testing.B) { benchEncrypt("1B", "DirectGCM256", b) } -func BenchmarkEncrypt64BWithDirectGCM256(b *testing.B) { benchEncrypt("64B", "DirectGCM256", b) } -func BenchmarkEncrypt1KBWithDirectGCM256(b *testing.B) { benchEncrypt("1KB", "DirectGCM256", b) } -func BenchmarkEncrypt64KBWithDirectGCM256(b *testing.B) { benchEncrypt("64KB", "DirectGCM256", b) } -func BenchmarkEncrypt1MBWithDirectGCM256(b *testing.B) { benchEncrypt("1MB", "DirectGCM256", b) } -func BenchmarkEncrypt64MBWithDirectGCM256(b *testing.B) { benchEncrypt("64MB", "DirectGCM256", b) } - -func BenchmarkEncrypt1BWithDirectCBC256(b *testing.B) { benchEncrypt("1B", "DirectCBC256", b) } -func BenchmarkEncrypt64BWithDirectCBC256(b *testing.B) { benchEncrypt("64B", "DirectCBC256", b) } -func BenchmarkEncrypt1KBWithDirectCBC256(b *testing.B) { benchEncrypt("1KB", "DirectCBC256", b) } -func BenchmarkEncrypt64KBWithDirectCBC256(b *testing.B) { benchEncrypt("64KB", "DirectCBC256", b) } -func BenchmarkEncrypt1MBWithDirectCBC256(b *testing.B) { benchEncrypt("1MB", "DirectCBC256", b) } -func BenchmarkEncrypt64MBWithDirectCBC256(b *testing.B) { benchEncrypt("64MB", "DirectCBC256", b) } - -func BenchmarkEncrypt1BWithAESKWAndGCM128(b *testing.B) { benchEncrypt("1B", "AESKWAndGCM128", b) } -func BenchmarkEncrypt64BWithAESKWAndGCM128(b *testing.B) { benchEncrypt("64B", "AESKWAndGCM128", b) } -func BenchmarkEncrypt1KBWithAESKWAndGCM128(b *testing.B) { benchEncrypt("1KB", "AESKWAndGCM128", b) } -func BenchmarkEncrypt64KBWithAESKWAndGCM128(b *testing.B) { benchEncrypt("64KB", "AESKWAndGCM128", b) } -func BenchmarkEncrypt1MBWithAESKWAndGCM128(b *testing.B) { benchEncrypt("1MB", "AESKWAndGCM128", b) } -func BenchmarkEncrypt64MBWithAESKWAndGCM128(b *testing.B) { benchEncrypt("64MB", "AESKWAndGCM128", b) } - -func BenchmarkEncrypt1BWithAESKWAndCBC256(b *testing.B) { benchEncrypt("1B", "AESKWAndCBC256", b) } -func BenchmarkEncrypt64BWithAESKWAndCBC256(b *testing.B) { benchEncrypt("64B", "AESKWAndCBC256", b) } -func BenchmarkEncrypt1KBWithAESKWAndCBC256(b *testing.B) { benchEncrypt("1KB", "AESKWAndCBC256", b) } -func BenchmarkEncrypt64KBWithAESKWAndCBC256(b *testing.B) { benchEncrypt("64KB", "AESKWAndCBC256", b) } -func BenchmarkEncrypt1MBWithAESKWAndCBC256(b *testing.B) { benchEncrypt("1MB", "AESKWAndCBC256", b) } -func BenchmarkEncrypt64MBWithAESKWAndCBC256(b *testing.B) { benchEncrypt("64MB", "AESKWAndCBC256", b) } - -func BenchmarkEncrypt1BWithECDHOnP256AndGCM128(b *testing.B) { - benchEncrypt("1B", "ECDHOnP256AndGCM128", b) -} -func BenchmarkEncrypt64BWithECDHOnP256AndGCM128(b *testing.B) { - benchEncrypt("64B", "ECDHOnP256AndGCM128", b) -} -func BenchmarkEncrypt1KBWithECDHOnP256AndGCM128(b *testing.B) { - benchEncrypt("1KB", "ECDHOnP256AndGCM128", b) -} -func BenchmarkEncrypt64KBWithECDHOnP256AndGCM128(b *testing.B) { - benchEncrypt("64KB", "ECDHOnP256AndGCM128", b) -} -func BenchmarkEncrypt1MBWithECDHOnP256AndGCM128(b *testing.B) { - benchEncrypt("1MB", "ECDHOnP256AndGCM128", b) -} -func BenchmarkEncrypt64MBWithECDHOnP256AndGCM128(b *testing.B) { - benchEncrypt("64MB", "ECDHOnP256AndGCM128", b) -} - -func BenchmarkEncrypt1BWithECDHOnP384AndGCM128(b *testing.B) { - benchEncrypt("1B", "ECDHOnP384AndGCM128", b) -} -func BenchmarkEncrypt64BWithECDHOnP384AndGCM128(b *testing.B) { - benchEncrypt("64B", "ECDHOnP384AndGCM128", b) -} -func BenchmarkEncrypt1KBWithECDHOnP384AndGCM128(b *testing.B) { - benchEncrypt("1KB", "ECDHOnP384AndGCM128", b) -} -func BenchmarkEncrypt64KBWithECDHOnP384AndGCM128(b *testing.B) { - benchEncrypt("64KB", "ECDHOnP384AndGCM128", b) -} -func BenchmarkEncrypt1MBWithECDHOnP384AndGCM128(b *testing.B) { - benchEncrypt("1MB", "ECDHOnP384AndGCM128", b) -} -func BenchmarkEncrypt64MBWithECDHOnP384AndGCM128(b *testing.B) { - benchEncrypt("64MB", "ECDHOnP384AndGCM128", b) -} - -func BenchmarkEncrypt1BWithECDHOnP521AndGCM128(b *testing.B) { - benchEncrypt("1B", "ECDHOnP521AndGCM128", b) -} -func BenchmarkEncrypt64BWithECDHOnP521AndGCM128(b *testing.B) { - benchEncrypt("64B", "ECDHOnP521AndGCM128", b) -} -func BenchmarkEncrypt1KBWithECDHOnP521AndGCM128(b *testing.B) { - benchEncrypt("1KB", "ECDHOnP521AndGCM128", b) -} -func BenchmarkEncrypt64KBWithECDHOnP521AndGCM128(b *testing.B) { - benchEncrypt("64KB", "ECDHOnP521AndGCM128", b) -} -func BenchmarkEncrypt1MBWithECDHOnP521AndGCM128(b *testing.B) { - benchEncrypt("1MB", "ECDHOnP521AndGCM128", b) -} -func BenchmarkEncrypt64MBWithECDHOnP521AndGCM128(b *testing.B) { - benchEncrypt("64MB", "ECDHOnP521AndGCM128", b) -} - -func benchEncrypt(chunkKey, primKey string, b *testing.B) { - data, ok := chunks[chunkKey] - if !ok { - b.Fatalf("unknown chunk size %s", chunkKey) - } - - enc, ok := encrypters[primKey] - if !ok { - b.Fatalf("unknown encrypter %s", primKey) - } - - b.SetBytes(int64(len(data))) - for i := 0; i < b.N; i++ { - enc.Encrypt(data) - } -} - -var ( - decryptionKeys = map[string]interface{}{ - "OAEPAndGCM": rsaTestKey, - "PKCSAndGCM": rsaTestKey, - "OAEPAndCBC": rsaTestKey, - "PKCSAndCBC": rsaTestKey, - - "DirectGCM128": symKey, - "DirectCBC128": symKey, - "DirectGCM256": symKey, - "DirectCBC256": symKey, - - "AESKWAndGCM128": symKey, - "AESKWAndCBC256": symKey, - - "ECDHOnP256AndGCM128": ecTestKey256, - "ECDHOnP384AndGCM128": ecTestKey384, - "ECDHOnP521AndGCM128": ecTestKey521, - } -) - -func BenchmarkDecrypt1BWithOAEPAndGCM(b *testing.B) { benchDecrypt("1B", "OAEPAndGCM", b) } -func BenchmarkDecrypt64BWithOAEPAndGCM(b *testing.B) { benchDecrypt("64B", "OAEPAndGCM", b) } -func BenchmarkDecrypt1KBWithOAEPAndGCM(b *testing.B) { benchDecrypt("1KB", "OAEPAndGCM", b) } -func BenchmarkDecrypt64KBWithOAEPAndGCM(b *testing.B) { benchDecrypt("64KB", "OAEPAndGCM", b) } -func BenchmarkDecrypt1MBWithOAEPAndGCM(b *testing.B) { benchDecrypt("1MB", "OAEPAndGCM", b) } -func BenchmarkDecrypt64MBWithOAEPAndGCM(b *testing.B) { benchDecrypt("64MB", "OAEPAndGCM", b) } - -func BenchmarkDecrypt1BWithPKCSAndGCM(b *testing.B) { benchDecrypt("1B", "PKCSAndGCM", b) } -func BenchmarkDecrypt64BWithPKCSAndGCM(b *testing.B) { benchDecrypt("64B", "PKCSAndGCM", b) } -func BenchmarkDecrypt1KBWithPKCSAndGCM(b *testing.B) { benchDecrypt("1KB", "PKCSAndGCM", b) } -func BenchmarkDecrypt64KBWithPKCSAndGCM(b *testing.B) { benchDecrypt("64KB", "PKCSAndGCM", b) } -func BenchmarkDecrypt1MBWithPKCSAndGCM(b *testing.B) { benchDecrypt("1MB", "PKCSAndGCM", b) } -func BenchmarkDecrypt64MBWithPKCSAndGCM(b *testing.B) { benchDecrypt("64MB", "PKCSAndGCM", b) } - -func BenchmarkDecrypt1BWithOAEPAndCBC(b *testing.B) { benchDecrypt("1B", "OAEPAndCBC", b) } -func BenchmarkDecrypt64BWithOAEPAndCBC(b *testing.B) { benchDecrypt("64B", "OAEPAndCBC", b) } -func BenchmarkDecrypt1KBWithOAEPAndCBC(b *testing.B) { benchDecrypt("1KB", "OAEPAndCBC", b) } -func BenchmarkDecrypt64KBWithOAEPAndCBC(b *testing.B) { benchDecrypt("64KB", "OAEPAndCBC", b) } -func BenchmarkDecrypt1MBWithOAEPAndCBC(b *testing.B) { benchDecrypt("1MB", "OAEPAndCBC", b) } -func BenchmarkDecrypt64MBWithOAEPAndCBC(b *testing.B) { benchDecrypt("64MB", "OAEPAndCBC", b) } - -func BenchmarkDecrypt1BWithPKCSAndCBC(b *testing.B) { benchDecrypt("1B", "PKCSAndCBC", b) } -func BenchmarkDecrypt64BWithPKCSAndCBC(b *testing.B) { benchDecrypt("64B", "PKCSAndCBC", b) } -func BenchmarkDecrypt1KBWithPKCSAndCBC(b *testing.B) { benchDecrypt("1KB", "PKCSAndCBC", b) } -func BenchmarkDecrypt64KBWithPKCSAndCBC(b *testing.B) { benchDecrypt("64KB", "PKCSAndCBC", b) } -func BenchmarkDecrypt1MBWithPKCSAndCBC(b *testing.B) { benchDecrypt("1MB", "PKCSAndCBC", b) } -func BenchmarkDecrypt64MBWithPKCSAndCBC(b *testing.B) { benchDecrypt("64MB", "PKCSAndCBC", b) } - -func BenchmarkDecrypt1BWithDirectGCM128(b *testing.B) { benchDecrypt("1B", "DirectGCM128", b) } -func BenchmarkDecrypt64BWithDirectGCM128(b *testing.B) { benchDecrypt("64B", "DirectGCM128", b) } -func BenchmarkDecrypt1KBWithDirectGCM128(b *testing.B) { benchDecrypt("1KB", "DirectGCM128", b) } -func BenchmarkDecrypt64KBWithDirectGCM128(b *testing.B) { benchDecrypt("64KB", "DirectGCM128", b) } -func BenchmarkDecrypt1MBWithDirectGCM128(b *testing.B) { benchDecrypt("1MB", "DirectGCM128", b) } -func BenchmarkDecrypt64MBWithDirectGCM128(b *testing.B) { benchDecrypt("64MB", "DirectGCM128", b) } - -func BenchmarkDecrypt1BWithDirectCBC128(b *testing.B) { benchDecrypt("1B", "DirectCBC128", b) } -func BenchmarkDecrypt64BWithDirectCBC128(b *testing.B) { benchDecrypt("64B", "DirectCBC128", b) } -func BenchmarkDecrypt1KBWithDirectCBC128(b *testing.B) { benchDecrypt("1KB", "DirectCBC128", b) } -func BenchmarkDecrypt64KBWithDirectCBC128(b *testing.B) { benchDecrypt("64KB", "DirectCBC128", b) } -func BenchmarkDecrypt1MBWithDirectCBC128(b *testing.B) { benchDecrypt("1MB", "DirectCBC128", b) } -func BenchmarkDecrypt64MBWithDirectCBC128(b *testing.B) { benchDecrypt("64MB", "DirectCBC128", b) } - -func BenchmarkDecrypt1BWithDirectGCM256(b *testing.B) { benchDecrypt("1B", "DirectGCM256", b) } -func BenchmarkDecrypt64BWithDirectGCM256(b *testing.B) { benchDecrypt("64B", "DirectGCM256", b) } -func BenchmarkDecrypt1KBWithDirectGCM256(b *testing.B) { benchDecrypt("1KB", "DirectGCM256", b) } -func BenchmarkDecrypt64KBWithDirectGCM256(b *testing.B) { benchDecrypt("64KB", "DirectGCM256", b) } -func BenchmarkDecrypt1MBWithDirectGCM256(b *testing.B) { benchDecrypt("1MB", "DirectGCM256", b) } -func BenchmarkDecrypt64MBWithDirectGCM256(b *testing.B) { benchDecrypt("64MB", "DirectGCM256", b) } - -func BenchmarkDecrypt1BWithDirectCBC256(b *testing.B) { benchDecrypt("1B", "DirectCBC256", b) } -func BenchmarkDecrypt64BWithDirectCBC256(b *testing.B) { benchDecrypt("64B", "DirectCBC256", b) } -func BenchmarkDecrypt1KBWithDirectCBC256(b *testing.B) { benchDecrypt("1KB", "DirectCBC256", b) } -func BenchmarkDecrypt64KBWithDirectCBC256(b *testing.B) { benchDecrypt("64KB", "DirectCBC256", b) } -func BenchmarkDecrypt1MBWithDirectCBC256(b *testing.B) { benchDecrypt("1MB", "DirectCBC256", b) } -func BenchmarkDecrypt64MBWithDirectCBC256(b *testing.B) { benchDecrypt("64MB", "DirectCBC256", b) } - -func BenchmarkDecrypt1BWithAESKWAndGCM128(b *testing.B) { benchDecrypt("1B", "AESKWAndGCM128", b) } -func BenchmarkDecrypt64BWithAESKWAndGCM128(b *testing.B) { benchDecrypt("64B", "AESKWAndGCM128", b) } -func BenchmarkDecrypt1KBWithAESKWAndGCM128(b *testing.B) { benchDecrypt("1KB", "AESKWAndGCM128", b) } -func BenchmarkDecrypt64KBWithAESKWAndGCM128(b *testing.B) { benchDecrypt("64KB", "AESKWAndGCM128", b) } -func BenchmarkDecrypt1MBWithAESKWAndGCM128(b *testing.B) { benchDecrypt("1MB", "AESKWAndGCM128", b) } -func BenchmarkDecrypt64MBWithAESKWAndGCM128(b *testing.B) { benchDecrypt("64MB", "AESKWAndGCM128", b) } - -func BenchmarkDecrypt1BWithAESKWAndCBC256(b *testing.B) { benchDecrypt("1B", "AESKWAndCBC256", b) } -func BenchmarkDecrypt64BWithAESKWAndCBC256(b *testing.B) { benchDecrypt("64B", "AESKWAndCBC256", b) } -func BenchmarkDecrypt1KBWithAESKWAndCBC256(b *testing.B) { benchDecrypt("1KB", "AESKWAndCBC256", b) } -func BenchmarkDecrypt64KBWithAESKWAndCBC256(b *testing.B) { benchDecrypt("64KB", "AESKWAndCBC256", b) } -func BenchmarkDecrypt1MBWithAESKWAndCBC256(b *testing.B) { benchDecrypt("1MB", "AESKWAndCBC256", b) } -func BenchmarkDecrypt64MBWithAESKWAndCBC256(b *testing.B) { benchDecrypt("64MB", "AESKWAndCBC256", b) } - -func BenchmarkDecrypt1BWithECDHOnP256AndGCM128(b *testing.B) { - benchDecrypt("1B", "ECDHOnP256AndGCM128", b) -} -func BenchmarkDecrypt64BWithECDHOnP256AndGCM128(b *testing.B) { - benchDecrypt("64B", "ECDHOnP256AndGCM128", b) -} -func BenchmarkDecrypt1KBWithECDHOnP256AndGCM128(b *testing.B) { - benchDecrypt("1KB", "ECDHOnP256AndGCM128", b) -} -func BenchmarkDecrypt64KBWithECDHOnP256AndGCM128(b *testing.B) { - benchDecrypt("64KB", "ECDHOnP256AndGCM128", b) -} -func BenchmarkDecrypt1MBWithECDHOnP256AndGCM128(b *testing.B) { - benchDecrypt("1MB", "ECDHOnP256AndGCM128", b) -} -func BenchmarkDecrypt64MBWithECDHOnP256AndGCM128(b *testing.B) { - benchDecrypt("64MB", "ECDHOnP256AndGCM128", b) -} - -func BenchmarkDecrypt1BWithECDHOnP384AndGCM128(b *testing.B) { - benchDecrypt("1B", "ECDHOnP384AndGCM128", b) -} -func BenchmarkDecrypt64BWithECDHOnP384AndGCM128(b *testing.B) { - benchDecrypt("64B", "ECDHOnP384AndGCM128", b) -} -func BenchmarkDecrypt1KBWithECDHOnP384AndGCM128(b *testing.B) { - benchDecrypt("1KB", "ECDHOnP384AndGCM128", b) -} -func BenchmarkDecrypt64KBWithECDHOnP384AndGCM128(b *testing.B) { - benchDecrypt("64KB", "ECDHOnP384AndGCM128", b) -} -func BenchmarkDecrypt1MBWithECDHOnP384AndGCM128(b *testing.B) { - benchDecrypt("1MB", "ECDHOnP384AndGCM128", b) -} -func BenchmarkDecrypt64MBWithECDHOnP384AndGCM128(b *testing.B) { - benchDecrypt("64MB", "ECDHOnP384AndGCM128", b) -} - -func BenchmarkDecrypt1BWithECDHOnP521AndGCM128(b *testing.B) { - benchDecrypt("1B", "ECDHOnP521AndGCM128", b) -} -func BenchmarkDecrypt64BWithECDHOnP521AndGCM128(b *testing.B) { - benchDecrypt("64B", "ECDHOnP521AndGCM128", b) -} -func BenchmarkDecrypt1KBWithECDHOnP521AndGCM128(b *testing.B) { - benchDecrypt("1KB", "ECDHOnP521AndGCM128", b) -} -func BenchmarkDecrypt64KBWithECDHOnP521AndGCM128(b *testing.B) { - benchDecrypt("64KB", "ECDHOnP521AndGCM128", b) -} -func BenchmarkDecrypt1MBWithECDHOnP521AndGCM128(b *testing.B) { - benchDecrypt("1MB", "ECDHOnP521AndGCM128", b) -} -func BenchmarkDecrypt64MBWithECDHOnP521AndGCM128(b *testing.B) { - benchDecrypt("64MB", "ECDHOnP521AndGCM128", b) -} - -func benchDecrypt(chunkKey, primKey string, b *testing.B) { - chunk, ok := chunks[chunkKey] - if !ok { - b.Fatalf("unknown chunk size %s", chunkKey) - } - - enc, ok := encrypters[primKey] - if !ok { - b.Fatalf("unknown encrypter %s", primKey) - } - - dec, ok := decryptionKeys[primKey] - if !ok { - b.Fatalf("unknown decryption key %s", primKey) - } - - data, err := enc.Encrypt(chunk) - if err != nil { - b.Fatal(err) - } - - b.SetBytes(int64(len(chunk))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - data.Decrypt(dec) - } -} - -func mustEncrypter(keyAlg KeyAlgorithm, encAlg ContentEncryption, encryptionKey interface{}) Encrypter { - enc, err := NewEncrypter(encAlg, Recipient{Algorithm: keyAlg, Key: encryptionKey}, nil) - if err != nil { - panic(err) - } - return enc -} diff --git a/vendor/gopkg.in/square/go-jose.v2/doc_test.go b/vendor/gopkg.in/square/go-jose.v2/doc_test.go deleted file mode 100644 index 1ee1478bc..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/doc_test.go +++ /dev/null @@ -1,201 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jose - -import ( - "crypto/ecdsa" - "crypto/rand" - "crypto/rsa" - "fmt" -) - -// Dummy encrypter for use in examples -var encrypter Encrypter - -func Example_jWE() { - // Generate a public/private key pair to use for this example. - privateKey, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - panic(err) - } - - // Instantiate an encrypter using RSA-OAEP with AES128-GCM. An error would - // indicate that the selected algorithm(s) are not currently supported. - publicKey := &privateKey.PublicKey - encrypter, err := NewEncrypter(A128GCM, Recipient{Algorithm: RSA_OAEP, Key: publicKey}, nil) - if err != nil { - panic(err) - } - - // Encrypt a sample plaintext. Calling the encrypter returns an encrypted - // JWE object, which can then be serialized for output afterwards. An error - // would indicate a problem in an underlying cryptographic primitive. - var plaintext = []byte("Lorem ipsum dolor sit amet") - object, err := encrypter.Encrypt(plaintext) - if err != nil { - panic(err) - } - - // Serialize the encrypted object using the full serialization format. - // Alternatively you can also use the compact format here by calling - // object.CompactSerialize() instead. - serialized := object.FullSerialize() - - // Parse the serialized, encrypted JWE object. An error would indicate that - // the given input did not represent a valid message. - object, err = ParseEncrypted(serialized) - if err != nil { - panic(err) - } - - // Now we can decrypt and get back our original plaintext. An error here - // would indicate the the message failed to decrypt, e.g. because the auth - // tag was broken or the message was tampered with. - decrypted, err := object.Decrypt(privateKey) - if err != nil { - panic(err) - } - - fmt.Printf(string(decrypted)) - // output: Lorem ipsum dolor sit amet -} - -func Example_jWS() { - // Generate a public/private key pair to use for this example. - privateKey, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - panic(err) - } - - // Instantiate a signer using RSASSA-PSS (SHA512) with the given private key. - signer, err := NewSigner(SigningKey{Algorithm: PS512, Key: privateKey}, nil) - if err != nil { - panic(err) - } - - // Sign a sample payload. Calling the signer returns a protected JWS object, - // which can then be serialized for output afterwards. An error would - // indicate a problem in an underlying cryptographic primitive. - var payload = []byte("Lorem ipsum dolor sit amet") - object, err := signer.Sign(payload) - if err != nil { - panic(err) - } - - // Serialize the encrypted object using the full serialization format. - // Alternatively you can also use the compact format here by calling - // object.CompactSerialize() instead. - serialized := object.FullSerialize() - - // Parse the serialized, protected JWS object. An error would indicate that - // the given input did not represent a valid message. - object, err = ParseSigned(serialized) - if err != nil { - panic(err) - } - - // Now we can verify the signature on the payload. An error here would - // indicate the the message failed to verify, e.g. because the signature was - // broken or the message was tampered with. - output, err := object.Verify(&privateKey.PublicKey) - if err != nil { - panic(err) - } - - fmt.Printf(string(output)) - // output: Lorem ipsum dolor sit amet -} - -func ExampleNewEncrypter_publicKey() { - var publicKey *rsa.PublicKey - - // Instantiate an encrypter using RSA-OAEP with AES128-GCM. - NewEncrypter(A128GCM, Recipient{Algorithm: RSA_OAEP, Key: publicKey}, nil) - - // Instantiate an encrypter using RSA-PKCS1v1.5 with AES128-CBC+HMAC. - NewEncrypter(A128CBC_HS256, Recipient{Algorithm: RSA1_5, Key: publicKey}, nil) -} - -func ExampleNewEncrypter_symmetric() { - var sharedKey []byte - - // Instantiate an encrypter using AES128-GCM with AES-GCM key wrap. - NewEncrypter(A128GCM, Recipient{Algorithm: A128GCMKW, Key: sharedKey}, nil) - - // Instantiate an encrypter using AES128-GCM directly, w/o key wrapping. - NewEncrypter(A128GCM, Recipient{Algorithm: DIRECT, Key: sharedKey}, nil) -} - -func ExampleNewSigner_publicKey() { - var rsaPrivateKey *rsa.PrivateKey - var ecdsaPrivateKey *ecdsa.PrivateKey - - // Instantiate a signer using RSA-PKCS#1v1.5 with SHA-256. - NewSigner(SigningKey{Algorithm: RS256, Key: rsaPrivateKey}, nil) - - // Instantiate a signer using ECDSA with SHA-384. - NewSigner(SigningKey{Algorithm: ES384, Key: ecdsaPrivateKey}, nil) -} - -func ExampleNewSigner_symmetric() { - var sharedKey []byte - - // Instantiate an signer using HMAC-SHA256. - NewSigner(SigningKey{Algorithm: HS256, Key: sharedKey}, nil) - - // Instantiate an signer using HMAC-SHA512. - NewSigner(SigningKey{Algorithm: HS512, Key: sharedKey}, nil) -} - -func ExampleNewMultiEncrypter() { - var publicKey *rsa.PublicKey - var sharedKey []byte - - // Instantiate an encrypter using AES-GCM. - NewMultiEncrypter(A128GCM, []Recipient{ - {Algorithm: A128GCMKW, Key: sharedKey}, - {Algorithm: RSA_OAEP, Key: publicKey}, - }, nil) -} - -func ExampleNewMultiSigner() { - var privateKey *rsa.PrivateKey - var sharedKey []byte - - // Instantiate a signer for multiple recipients. - NewMultiSigner([]SigningKey{ - {Algorithm: HS256, Key: sharedKey}, - {Algorithm: PS384, Key: privateKey}, - }, nil) -} - -func ExampleEncrypter_encrypt() { - // Encrypt a plaintext in order to get an encrypted JWE object. - var plaintext = []byte("This is a secret message") - - encrypter.Encrypt(plaintext) -} - -func ExampleEncrypter_encryptWithAuthData() { - // Encrypt a plaintext in order to get an encrypted JWE object. Also attach - // some additional authenticated data (AAD) to the object. Note that objects - // with attached AAD can only be represented using full serialization. - var plaintext = []byte("This is a secret message") - var aad = []byte("This is authenticated, but public data") - - encrypter.EncryptWithAuthData(plaintext, aad) -} diff --git a/vendor/gopkg.in/square/go-jose.v2/encoding_test.go b/vendor/gopkg.in/square/go-jose.v2/encoding_test.go deleted file mode 100644 index c824e4c59..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/encoding_test.go +++ /dev/null @@ -1,122 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jose - -import ( - "bytes" - "strings" - "testing" -) - -func TestDeflateRoundtrip(t *testing.T) { - original := []byte("Lorem ipsum dolor sit amet") - - compressed, err := deflate(original) - if err != nil { - panic(err) - } - - output, err := inflate(compressed) - if err != nil { - panic(err) - } - - if bytes.Compare(output, original) != 0 { - t.Error("Input and output do not match") - } -} - -func TestInvalidCompression(t *testing.T) { - _, err := compress("XYZ", []byte{}) - if err == nil { - t.Error("should not accept invalid algorithm") - } - - _, err = decompress("XYZ", []byte{}) - if err == nil { - t.Error("should not accept invalid algorithm") - } - - _, err = decompress(DEFLATE, []byte{1, 2, 3, 4}) - if err == nil { - t.Error("should not accept invalid data") - } -} - -func TestByteBufferTrim(t *testing.T) { - buf := newBufferFromInt(1) - if !bytes.Equal(buf.data, []byte{1}) { - t.Error("Byte buffer for integer '1' should contain [0x01]") - } - - buf = newBufferFromInt(65537) - if !bytes.Equal(buf.data, []byte{1, 0, 1}) { - t.Error("Byte buffer for integer '65537' should contain [0x01, 0x00, 0x01]") - } -} - -func TestFixedSizeBuffer(t *testing.T) { - data0 := []byte{} - data1 := []byte{1} - data2 := []byte{1, 2} - data3 := []byte{1, 2, 3} - data4 := []byte{1, 2, 3, 4} - - buf0 := newFixedSizeBuffer(data0, 4) - buf1 := newFixedSizeBuffer(data1, 4) - buf2 := newFixedSizeBuffer(data2, 4) - buf3 := newFixedSizeBuffer(data3, 4) - buf4 := newFixedSizeBuffer(data4, 4) - - if !bytes.Equal(buf0.data, []byte{0, 0, 0, 0}) { - t.Error("Invalid padded buffer for buf0") - } - if !bytes.Equal(buf1.data, []byte{0, 0, 0, 1}) { - t.Error("Invalid padded buffer for buf1") - } - if !bytes.Equal(buf2.data, []byte{0, 0, 1, 2}) { - t.Error("Invalid padded buffer for buf2") - } - if !bytes.Equal(buf3.data, []byte{0, 1, 2, 3}) { - t.Error("Invalid padded buffer for buf3") - } - if !bytes.Equal(buf4.data, []byte{1, 2, 3, 4}) { - t.Error("Invalid padded buffer for buf4") - } -} - -func TestSerializeJSONRejectsNil(t *testing.T) { - defer func() { - r := recover() - if r == nil || !strings.Contains(r.(string), "nil pointer") { - t.Error("serialize function should not accept nil pointer") - } - }() - - mustSerializeJSON(nil) -} - -func TestFixedSizeBufferTooLarge(t *testing.T) { - defer func() { - r := recover() - if r == nil { - t.Error("should not be able to create fixed size buffer with oversized data") - } - }() - - newFixedSizeBuffer(make([]byte, 2), 1) -} diff --git a/vendor/gopkg.in/square/go-jose.v2/json/bench_test.go b/vendor/gopkg.in/square/go-jose.v2/json/bench_test.go deleted file mode 100644 index ed89d1156..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/json/bench_test.go +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Large data benchmark. -// The JSON data is a summary of agl's changes in the -// go, webkit, and chromium open source projects. -// We benchmark converting between the JSON form -// and in-memory data structures. - -package json - -import ( - "bytes" - "compress/gzip" - "io/ioutil" - "os" - "strings" - "testing" -) - -type codeResponse struct { - Tree *codeNode `json:"tree"` - Username string `json:"username"` -} - -type codeNode struct { - Name string `json:"name"` - Kids []*codeNode `json:"kids"` - CLWeight float64 `json:"cl_weight"` - Touches int `json:"touches"` - MinT int64 `json:"min_t"` - MaxT int64 `json:"max_t"` - MeanT int64 `json:"mean_t"` -} - -var codeJSON []byte -var codeStruct codeResponse - -func codeInit() { - f, err := os.Open("testdata/code.json.gz") - if err != nil { - panic(err) - } - defer f.Close() - gz, err := gzip.NewReader(f) - if err != nil { - panic(err) - } - data, err := ioutil.ReadAll(gz) - if err != nil { - panic(err) - } - - codeJSON = data - - if err := Unmarshal(codeJSON, &codeStruct); err != nil { - panic("unmarshal code.json: " + err.Error()) - } - - if data, err = Marshal(&codeStruct); err != nil { - panic("marshal code.json: " + err.Error()) - } - - if !bytes.Equal(data, codeJSON) { - println("different lengths", len(data), len(codeJSON)) - for i := 0; i < len(data) && i < len(codeJSON); i++ { - if data[i] != codeJSON[i] { - println("re-marshal: changed at byte", i) - println("orig: ", string(codeJSON[i-10:i+10])) - println("new: ", string(data[i-10:i+10])) - break - } - } - panic("re-marshal code.json: different result") - } -} - -func BenchmarkCodeEncoder(b *testing.B) { - if codeJSON == nil { - b.StopTimer() - codeInit() - b.StartTimer() - } - enc := NewEncoder(ioutil.Discard) - for i := 0; i < b.N; i++ { - if err := enc.Encode(&codeStruct); err != nil { - b.Fatal("Encode:", err) - } - } - b.SetBytes(int64(len(codeJSON))) -} - -func BenchmarkCodeMarshal(b *testing.B) { - if codeJSON == nil { - b.StopTimer() - codeInit() - b.StartTimer() - } - for i := 0; i < b.N; i++ { - if _, err := Marshal(&codeStruct); err != nil { - b.Fatal("Marshal:", err) - } - } - b.SetBytes(int64(len(codeJSON))) -} - -func BenchmarkCodeDecoder(b *testing.B) { - if codeJSON == nil { - b.StopTimer() - codeInit() - b.StartTimer() - } - var buf bytes.Buffer - dec := NewDecoder(&buf) - var r codeResponse - for i := 0; i < b.N; i++ { - buf.Write(codeJSON) - // hide EOF - buf.WriteByte('\n') - buf.WriteByte('\n') - buf.WriteByte('\n') - if err := dec.Decode(&r); err != nil { - b.Fatal("Decode:", err) - } - } - b.SetBytes(int64(len(codeJSON))) -} - -func BenchmarkDecoderStream(b *testing.B) { - b.StopTimer() - var buf bytes.Buffer - dec := NewDecoder(&buf) - buf.WriteString(`"` + strings.Repeat("x", 1000000) + `"` + "\n\n\n") - var x interface{} - if err := dec.Decode(&x); err != nil { - b.Fatal("Decode:", err) - } - ones := strings.Repeat(" 1\n", 300000) + "\n\n\n" - b.StartTimer() - for i := 0; i < b.N; i++ { - if i%300000 == 0 { - buf.WriteString(ones) - } - x = nil - if err := dec.Decode(&x); err != nil || x != 1.0 { - b.Fatalf("Decode: %v after %d", err, i) - } - } -} - -func BenchmarkCodeUnmarshal(b *testing.B) { - if codeJSON == nil { - b.StopTimer() - codeInit() - b.StartTimer() - } - for i := 0; i < b.N; i++ { - var r codeResponse - if err := Unmarshal(codeJSON, &r); err != nil { - b.Fatal("Unmmarshal:", err) - } - } - b.SetBytes(int64(len(codeJSON))) -} - -func BenchmarkCodeUnmarshalReuse(b *testing.B) { - if codeJSON == nil { - b.StopTimer() - codeInit() - b.StartTimer() - } - var r codeResponse - for i := 0; i < b.N; i++ { - if err := Unmarshal(codeJSON, &r); err != nil { - b.Fatal("Unmmarshal:", err) - } - } -} - -func BenchmarkUnmarshalString(b *testing.B) { - data := []byte(`"hello, world"`) - var s string - - for i := 0; i < b.N; i++ { - if err := Unmarshal(data, &s); err != nil { - b.Fatal("Unmarshal:", err) - } - } -} - -func BenchmarkUnmarshalFloat64(b *testing.B) { - var f float64 - data := []byte(`3.14`) - - for i := 0; i < b.N; i++ { - if err := Unmarshal(data, &f); err != nil { - b.Fatal("Unmarshal:", err) - } - } -} - -func BenchmarkUnmarshalInt64(b *testing.B) { - var x int64 - data := []byte(`3`) - - for i := 0; i < b.N; i++ { - if err := Unmarshal(data, &x); err != nil { - b.Fatal("Unmarshal:", err) - } - } -} - -func BenchmarkIssue10335(b *testing.B) { - b.ReportAllocs() - var s struct{} - j := []byte(`{"a":{ }}`) - for n := 0; n < b.N; n++ { - if err := Unmarshal(j, &s); err != nil { - b.Fatal(err) - } - } -} diff --git a/vendor/gopkg.in/square/go-jose.v2/json/decode_test.go b/vendor/gopkg.in/square/go-jose.v2/json/decode_test.go deleted file mode 100644 index 32394654e..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/json/decode_test.go +++ /dev/null @@ -1,1474 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "bytes" - "encoding" - "fmt" - "image" - "net" - "reflect" - "strings" - "testing" - "time" -) - -type T struct { - X string - Y int - Z int `json:"-"` -} - -type U struct { - Alphabet string `json:"alpha"` -} - -type V struct { - F1 interface{} - F2 int32 - F3 Number -} - -// ifaceNumAsFloat64/ifaceNumAsNumber are used to test unmarshaling with and -// without UseNumber -var ifaceNumAsFloat64 = map[string]interface{}{ - "k1": float64(1), - "k2": "s", - "k3": []interface{}{float64(1), float64(2.0), float64(3e-3)}, - "k4": map[string]interface{}{"kk1": "s", "kk2": float64(2)}, -} - -var ifaceNumAsNumber = map[string]interface{}{ - "k1": Number("1"), - "k2": "s", - "k3": []interface{}{Number("1"), Number("2.0"), Number("3e-3")}, - "k4": map[string]interface{}{"kk1": "s", "kk2": Number("2")}, -} - -type tx struct { - x int -} - -// A type that can unmarshal itself. - -type unmarshaler struct { - T bool -} - -func (u *unmarshaler) UnmarshalJSON(b []byte) error { - *u = unmarshaler{true} // All we need to see that UnmarshalJSON is called. - return nil -} - -type ustruct struct { - M unmarshaler -} - -type unmarshalerText struct { - T bool -} - -// needed for re-marshaling tests -func (u *unmarshalerText) MarshalText() ([]byte, error) { - return []byte(""), nil -} - -func (u *unmarshalerText) UnmarshalText(b []byte) error { - *u = unmarshalerText{true} // All we need to see that UnmarshalText is called. - return nil -} - -var _ encoding.TextUnmarshaler = (*unmarshalerText)(nil) - -type ustructText struct { - M unmarshalerText -} - -var ( - um0, um1 unmarshaler // target2 of unmarshaling - ump = &um1 - umtrue = unmarshaler{true} - umslice = []unmarshaler{{true}} - umslicep = new([]unmarshaler) - umstruct = ustruct{unmarshaler{true}} - - um0T, um1T unmarshalerText // target2 of unmarshaling - umpT = &um1T - umtrueT = unmarshalerText{true} - umsliceT = []unmarshalerText{{true}} - umslicepT = new([]unmarshalerText) - umstructT = ustructText{unmarshalerText{true}} -) - -// Test data structures for anonymous fields. - -type Point struct { - Z int -} - -type Top struct { - Level0 int - Embed0 - *Embed0a - *Embed0b `json:"e,omitempty"` // treated as named - Embed0c `json:"-"` // ignored - Loop - Embed0p // has Point with X, Y, used - Embed0q // has Point with Z, used - embed // contains exported field -} - -type Embed0 struct { - Level1a int // overridden by Embed0a's Level1a with json tag - Level1b int // used because Embed0a's Level1b is renamed - Level1c int // used because Embed0a's Level1c is ignored - Level1d int // annihilated by Embed0a's Level1d - Level1e int `json:"x"` // annihilated by Embed0a.Level1e -} - -type Embed0a struct { - Level1a int `json:"Level1a,omitempty"` - Level1b int `json:"LEVEL1B,omitempty"` - Level1c int `json:"-"` - Level1d int // annihilated by Embed0's Level1d - Level1f int `json:"x"` // annihilated by Embed0's Level1e -} - -type Embed0b Embed0 - -type Embed0c Embed0 - -type Embed0p struct { - image.Point -} - -type Embed0q struct { - Point -} - -type embed struct { - Q int -} - -type Loop struct { - Loop1 int `json:",omitempty"` - Loop2 int `json:",omitempty"` - *Loop -} - -// From reflect test: -// The X in S6 and S7 annihilate, but they also block the X in S8.S9. -type S5 struct { - S6 - S7 - S8 -} - -type S6 struct { - X int -} - -type S7 S6 - -type S8 struct { - S9 -} - -type S9 struct { - X int - Y int -} - -// From reflect test: -// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9. -type S10 struct { - S11 - S12 - S13 -} - -type S11 struct { - S6 -} - -type S12 struct { - S6 -} - -type S13 struct { - S8 -} - -type unmarshalTest struct { - in string - ptr interface{} - out interface{} - err error - useNumber bool -} - -type XYZ struct { - X interface{} - Y interface{} - Z interface{} -} - -func sliceAddr(x []int) *[]int { return &x } -func mapAddr(x map[string]int) *map[string]int { return &x } - -var unmarshalTests = []unmarshalTest{ - // basic types - {in: `true`, ptr: new(bool), out: true}, - {in: `1`, ptr: new(int), out: 1}, - {in: `1.2`, ptr: new(float64), out: 1.2}, - {in: `-5`, ptr: new(int16), out: int16(-5)}, - {in: `2`, ptr: new(Number), out: Number("2"), useNumber: true}, - {in: `2`, ptr: new(Number), out: Number("2")}, - {in: `2`, ptr: new(interface{}), out: float64(2.0)}, - {in: `2`, ptr: new(interface{}), out: Number("2"), useNumber: true}, - {in: `"a\u1234"`, ptr: new(string), out: "a\u1234"}, - {in: `"http:\/\/"`, ptr: new(string), out: "http://"}, - {in: `"g-clef: \uD834\uDD1E"`, ptr: new(string), out: "g-clef: \U0001D11E"}, - {in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"}, - {in: "null", ptr: new(interface{}), out: nil}, - {in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf(""), 7}}, - {in: `{"x": 1}`, ptr: new(tx), out: tx{}}, - {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}}, - {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: Number("1"), F2: int32(2), F3: Number("3")}, useNumber: true}, - {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsFloat64}, - {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsNumber, useNumber: true}, - - // raw values with whitespace - {in: "\n true ", ptr: new(bool), out: true}, - {in: "\t 1 ", ptr: new(int), out: 1}, - {in: "\r 1.2 ", ptr: new(float64), out: 1.2}, - {in: "\t -5 \n", ptr: new(int16), out: int16(-5)}, - {in: "\t \"a\\u1234\" \n", ptr: new(string), out: "a\u1234"}, - - // Z has a "-" tag. - {in: `{"Y": 1, "Z": 2}`, ptr: new(T), out: T{Y: 1}}, - - {in: `{"alpha": "abc", "alphabet": "xyz"}`, ptr: new(U), out: U{Alphabet: "abc"}}, - {in: `{"alpha": "abc"}`, ptr: new(U), out: U{Alphabet: "abc"}}, - {in: `{"alphabet": "xyz"}`, ptr: new(U), out: U{}}, - - // syntax errors - {in: `{"X": "foo", "Y"}`, err: &SyntaxError{"invalid character '}' after object key", 17}}, - {in: `[1, 2, 3+]`, err: &SyntaxError{"invalid character '+' after array element", 9}}, - {in: `{"X":12x}`, err: &SyntaxError{"invalid character 'x' after object key:value pair", 8}, useNumber: true}, - - // raw value errors - {in: "\x01 42", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}}, - {in: " 42 \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 5}}, - {in: "\x01 true", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}}, - {in: " false \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 8}}, - {in: "\x01 1.2", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}}, - {in: " 3.4 \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 6}}, - {in: "\x01 \"string\"", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}}, - {in: " \"string\" \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 11}}, - - // array tests - {in: `[1, 2, 3]`, ptr: new([3]int), out: [3]int{1, 2, 3}}, - {in: `[1, 2, 3]`, ptr: new([1]int), out: [1]int{1}}, - {in: `[1, 2, 3]`, ptr: new([5]int), out: [5]int{1, 2, 3, 0, 0}}, - - // empty array to interface test - {in: `[]`, ptr: new([]interface{}), out: []interface{}{}}, - {in: `null`, ptr: new([]interface{}), out: []interface{}(nil)}, - {in: `{"T":[]}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": []interface{}{}}}, - {in: `{"T":null}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": interface{}(nil)}}, - - // composite tests - {in: allValueIndent, ptr: new(All), out: allValue}, - {in: allValueCompact, ptr: new(All), out: allValue}, - {in: allValueIndent, ptr: new(*All), out: &allValue}, - {in: allValueCompact, ptr: new(*All), out: &allValue}, - {in: pallValueIndent, ptr: new(All), out: pallValue}, - {in: pallValueCompact, ptr: new(All), out: pallValue}, - {in: pallValueIndent, ptr: new(*All), out: &pallValue}, - {in: pallValueCompact, ptr: new(*All), out: &pallValue}, - - // unmarshal interface test - {in: `{"T":false}`, ptr: &um0, out: umtrue}, // use "false" so test will fail if custom unmarshaler is not called - {in: `{"T":false}`, ptr: &ump, out: &umtrue}, - {in: `[{"T":false}]`, ptr: &umslice, out: umslice}, - {in: `[{"T":false}]`, ptr: &umslicep, out: &umslice}, - {in: `{"M":{"T":false}}`, ptr: &umstruct, out: umstruct}, - - // UnmarshalText interface test - {in: `"X"`, ptr: &um0T, out: umtrueT}, // use "false" so test will fail if custom unmarshaler is not called - {in: `"X"`, ptr: &umpT, out: &umtrueT}, - {in: `["X"]`, ptr: &umsliceT, out: umsliceT}, - {in: `["X"]`, ptr: &umslicepT, out: &umsliceT}, - {in: `{"M":"X"}`, ptr: &umstructT, out: umstructT}, - - // Overwriting of data. - // This is different from package xml, but it's what we've always done. - // Now documented and tested. - {in: `[2]`, ptr: sliceAddr([]int{1}), out: []int{2}}, - {in: `{"key": 2}`, ptr: mapAddr(map[string]int{"old": 0, "key": 1}), out: map[string]int{"key": 2}}, - - { - in: `{ - "Level0": 1, - "Level1b": 2, - "Level1c": 3, - "x": 4, - "Level1a": 5, - "LEVEL1B": 6, - "e": { - "Level1a": 8, - "Level1b": 9, - "Level1c": 10, - "Level1d": 11, - "x": 12 - }, - "Loop1": 13, - "Loop2": 14, - "X": 15, - "Y": 16, - "Z": 17, - "Q": 18 - }`, - ptr: new(Top), - out: Top{ - Level0: 1, - Embed0: Embed0{ - Level1b: 2, - Level1c: 3, - }, - Embed0a: &Embed0a{ - Level1a: 5, - Level1b: 6, - }, - Embed0b: &Embed0b{ - Level1a: 8, - Level1b: 9, - Level1c: 10, - Level1d: 11, - Level1e: 12, - }, - Loop: Loop{ - Loop1: 13, - Loop2: 14, - }, - Embed0p: Embed0p{ - Point: image.Point{X: 15, Y: 16}, - }, - Embed0q: Embed0q{ - Point: Point{Z: 17}, - }, - embed: embed{ - Q: 18, - }, - }, - }, - { - in: `{"X": 1,"Y":2}`, - ptr: new(S5), - out: S5{S8: S8{S9: S9{Y: 2}}}, - }, - { - in: `{"X": 1,"Y":2}`, - ptr: new(S10), - out: S10{S13: S13{S8: S8{S9: S9{Y: 2}}}}, - }, - - // invalid UTF-8 is coerced to valid UTF-8. - { - in: "\"hello\xffworld\"", - ptr: new(string), - out: "hello\ufffdworld", - }, - { - in: "\"hello\xc2\xc2world\"", - ptr: new(string), - out: "hello\ufffd\ufffdworld", - }, - { - in: "\"hello\xc2\xffworld\"", - ptr: new(string), - out: "hello\ufffd\ufffdworld", - }, - { - in: "\"hello\\ud800world\"", - ptr: new(string), - out: "hello\ufffdworld", - }, - { - in: "\"hello\\ud800\\ud800world\"", - ptr: new(string), - out: "hello\ufffd\ufffdworld", - }, - { - in: "\"hello\\ud800\\ud800world\"", - ptr: new(string), - out: "hello\ufffd\ufffdworld", - }, - { - in: "\"hello\xed\xa0\x80\xed\xb0\x80world\"", - ptr: new(string), - out: "hello\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdworld", - }, - - // issue 8305 - { - in: `{"2009-11-10T23:00:00Z": "hello world"}`, - ptr: &map[time.Time]string{}, - err: &UnmarshalTypeError{"object", reflect.TypeOf(map[time.Time]string{}), 1}, - }, -} - -func TestMarshal(t *testing.T) { - b, err := Marshal(allValue) - if err != nil { - t.Fatalf("Marshal allValue: %v", err) - } - if string(b) != allValueCompact { - t.Errorf("Marshal allValueCompact") - diff(t, b, []byte(allValueCompact)) - return - } - - b, err = Marshal(pallValue) - if err != nil { - t.Fatalf("Marshal pallValue: %v", err) - } - if string(b) != pallValueCompact { - t.Errorf("Marshal pallValueCompact") - diff(t, b, []byte(pallValueCompact)) - return - } -} - -var badUTF8 = []struct { - in, out string -}{ - {"hello\xffworld", `"hello\ufffdworld"`}, - {"", `""`}, - {"\xff", `"\ufffd"`}, - {"\xff\xff", `"\ufffd\ufffd"`}, - {"a\xffb", `"a\ufffdb"`}, - {"\xe6\x97\xa5\xe6\x9c\xac\xff\xaa\x9e", `"日本\ufffd\ufffd\ufffd"`}, -} - -func TestMarshalBadUTF8(t *testing.T) { - for _, tt := range badUTF8 { - b, err := Marshal(tt.in) - if string(b) != tt.out || err != nil { - t.Errorf("Marshal(%q) = %#q, %v, want %#q, nil", tt.in, b, err, tt.out) - } - } -} - -func TestMarshalNumberZeroVal(t *testing.T) { - var n Number - out, err := Marshal(n) - if err != nil { - t.Fatal(err) - } - outStr := string(out) - if outStr != "0" { - t.Fatalf("Invalid zero val for Number: %q", outStr) - } -} - -func TestMarshalEmbeds(t *testing.T) { - top := &Top{ - Level0: 1, - Embed0: Embed0{ - Level1b: 2, - Level1c: 3, - }, - Embed0a: &Embed0a{ - Level1a: 5, - Level1b: 6, - }, - Embed0b: &Embed0b{ - Level1a: 8, - Level1b: 9, - Level1c: 10, - Level1d: 11, - Level1e: 12, - }, - Loop: Loop{ - Loop1: 13, - Loop2: 14, - }, - Embed0p: Embed0p{ - Point: image.Point{X: 15, Y: 16}, - }, - Embed0q: Embed0q{ - Point: Point{Z: 17}, - }, - embed: embed{ - Q: 18, - }, - } - b, err := Marshal(top) - if err != nil { - t.Fatal(err) - } - want := "{\"Level0\":1,\"Level1b\":2,\"Level1c\":3,\"Level1a\":5,\"LEVEL1B\":6,\"e\":{\"Level1a\":8,\"Level1b\":9,\"Level1c\":10,\"Level1d\":11,\"x\":12},\"Loop1\":13,\"Loop2\":14,\"X\":15,\"Y\":16,\"Z\":17,\"Q\":18}" - if string(b) != want { - t.Errorf("Wrong marshal result.\n got: %q\nwant: %q", b, want) - } -} - -func TestUnmarshal(t *testing.T) { - for i, tt := range unmarshalTests { - var scan scanner - in := []byte(tt.in) - if err := checkValid(in, &scan); err != nil { - if !reflect.DeepEqual(err, tt.err) { - t.Errorf("#%d: checkValid: %#v", i, err) - continue - } - } - if tt.ptr == nil { - continue - } - - // v = new(right-type) - v := reflect.New(reflect.TypeOf(tt.ptr).Elem()) - dec := NewDecoder(bytes.NewReader(in)) - if tt.useNumber { - dec.UseNumber() - } - if err := dec.Decode(v.Interface()); !reflect.DeepEqual(err, tt.err) { - t.Errorf("#%d: %v, want %v", i, err, tt.err) - continue - } else if err != nil { - continue - } - if !reflect.DeepEqual(v.Elem().Interface(), tt.out) { - t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), tt.out) - data, _ := Marshal(v.Elem().Interface()) - println(string(data)) - data, _ = Marshal(tt.out) - println(string(data)) - continue - } - - // Check round trip. - if tt.err == nil { - enc, err := Marshal(v.Interface()) - if err != nil { - t.Errorf("#%d: error re-marshaling: %v", i, err) - continue - } - vv := reflect.New(reflect.TypeOf(tt.ptr).Elem()) - dec = NewDecoder(bytes.NewReader(enc)) - if tt.useNumber { - dec.UseNumber() - } - if err := dec.Decode(vv.Interface()); err != nil { - t.Errorf("#%d: error re-unmarshaling %#q: %v", i, enc, err) - continue - } - if !reflect.DeepEqual(v.Elem().Interface(), vv.Elem().Interface()) { - t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), vv.Elem().Interface()) - t.Errorf(" In: %q", strings.Map(noSpace, string(in))) - t.Errorf("Marshal: %q", strings.Map(noSpace, string(enc))) - continue - } - } - } -} - -func TestUnmarshalMarshal(t *testing.T) { - initBig() - var v interface{} - if err := Unmarshal(jsonBig, &v); err != nil { - t.Fatalf("Unmarshal: %v", err) - } - b, err := Marshal(v) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - if !bytes.Equal(jsonBig, b) { - t.Errorf("Marshal jsonBig") - diff(t, b, jsonBig) - return - } -} - -var numberTests = []struct { - in string - i int64 - intErr string - f float64 - floatErr string -}{ - {in: "-1.23e1", intErr: "strconv.ParseInt: parsing \"-1.23e1\": invalid syntax", f: -1.23e1}, - {in: "-12", i: -12, f: -12.0}, - {in: "1e1000", intErr: "strconv.ParseInt: parsing \"1e1000\": invalid syntax", floatErr: "strconv.ParseFloat: parsing \"1e1000\": value out of range"}, -} - -// Independent of Decode, basic coverage of the accessors in Number -func TestNumberAccessors(t *testing.T) { - for _, tt := range numberTests { - n := Number(tt.in) - if s := n.String(); s != tt.in { - t.Errorf("Number(%q).String() is %q", tt.in, s) - } - if i, err := n.Int64(); err == nil && tt.intErr == "" && i != tt.i { - t.Errorf("Number(%q).Int64() is %d", tt.in, i) - } else if (err == nil && tt.intErr != "") || (err != nil && err.Error() != tt.intErr) { - t.Errorf("Number(%q).Int64() wanted error %q but got: %v", tt.in, tt.intErr, err) - } - if f, err := n.Float64(); err == nil && tt.floatErr == "" && f != tt.f { - t.Errorf("Number(%q).Float64() is %g", tt.in, f) - } else if (err == nil && tt.floatErr != "") || (err != nil && err.Error() != tt.floatErr) { - t.Errorf("Number(%q).Float64() wanted error %q but got: %v", tt.in, tt.floatErr, err) - } - } -} - -func TestLargeByteSlice(t *testing.T) { - s0 := make([]byte, 2000) - for i := range s0 { - s0[i] = byte(i) - } - b, err := Marshal(s0) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - var s1 []byte - if err := Unmarshal(b, &s1); err != nil { - t.Fatalf("Unmarshal: %v", err) - } - if !bytes.Equal(s0, s1) { - t.Errorf("Marshal large byte slice") - diff(t, s0, s1) - } -} - -type Xint struct { - X int -} - -func TestUnmarshalInterface(t *testing.T) { - var xint Xint - var i interface{} = &xint - if err := Unmarshal([]byte(`{"X":1}`), &i); err != nil { - t.Fatalf("Unmarshal: %v", err) - } - if xint.X != 1 { - t.Fatalf("Did not write to xint") - } -} - -func TestUnmarshalPtrPtr(t *testing.T) { - var xint Xint - pxint := &xint - if err := Unmarshal([]byte(`{"X":1}`), &pxint); err != nil { - t.Fatalf("Unmarshal: %v", err) - } - if xint.X != 1 { - t.Fatalf("Did not write to xint") - } -} - -func TestEscape(t *testing.T) { - const input = `"foobar"` + " [\u2028 \u2029]" - const expected = `"\"foobar\"\u003chtml\u003e [\u2028 \u2029]"` - b, err := Marshal(input) - if err != nil { - t.Fatalf("Marshal error: %v", err) - } - if s := string(b); s != expected { - t.Errorf("Encoding of [%s]:\n got [%s]\nwant [%s]", input, s, expected) - } -} - -// WrongString is a struct that's misusing the ,string modifier. -type WrongString struct { - Message string `json:"result,string"` -} - -type wrongStringTest struct { - in, err string -} - -var wrongStringTests = []wrongStringTest{ - {`{"result":"x"}`, `json: invalid use of ,string struct tag, trying to unmarshal "x" into string`}, - {`{"result":"foo"}`, `json: invalid use of ,string struct tag, trying to unmarshal "foo" into string`}, - {`{"result":"123"}`, `json: invalid use of ,string struct tag, trying to unmarshal "123" into string`}, - {`{"result":123}`, `json: invalid use of ,string struct tag, trying to unmarshal unquoted value into string`}, -} - -// If people misuse the ,string modifier, the error message should be -// helpful, telling the user that they're doing it wrong. -func TestErrorMessageFromMisusedString(t *testing.T) { - for n, tt := range wrongStringTests { - r := strings.NewReader(tt.in) - var s WrongString - err := NewDecoder(r).Decode(&s) - got := fmt.Sprintf("%v", err) - if got != tt.err { - t.Errorf("%d. got err = %q, want %q", n, got, tt.err) - } - } -} - -func noSpace(c rune) rune { - if isSpace(byte(c)) { //only used for ascii - return -1 - } - return c -} - -type All struct { - Bool bool - Int int - Int8 int8 - Int16 int16 - Int32 int32 - Int64 int64 - Uint uint - Uint8 uint8 - Uint16 uint16 - Uint32 uint32 - Uint64 uint64 - Uintptr uintptr - Float32 float32 - Float64 float64 - - Foo string `json:"bar"` - Foo2 string `json:"bar2,dummyopt"` - - IntStr int64 `json:",string"` - - PBool *bool - PInt *int - PInt8 *int8 - PInt16 *int16 - PInt32 *int32 - PInt64 *int64 - PUint *uint - PUint8 *uint8 - PUint16 *uint16 - PUint32 *uint32 - PUint64 *uint64 - PUintptr *uintptr - PFloat32 *float32 - PFloat64 *float64 - - String string - PString *string - - Map map[string]Small - MapP map[string]*Small - PMap *map[string]Small - PMapP *map[string]*Small - - EmptyMap map[string]Small - NilMap map[string]Small - - Slice []Small - SliceP []*Small - PSlice *[]Small - PSliceP *[]*Small - - EmptySlice []Small - NilSlice []Small - - StringSlice []string - ByteSlice []byte - - Small Small - PSmall *Small - PPSmall **Small - - Interface interface{} - PInterface *interface{} - - unexported int -} - -type Small struct { - Tag string -} - -var allValue = All{ - Bool: true, - Int: 2, - Int8: 3, - Int16: 4, - Int32: 5, - Int64: 6, - Uint: 7, - Uint8: 8, - Uint16: 9, - Uint32: 10, - Uint64: 11, - Uintptr: 12, - Float32: 14.1, - Float64: 15.1, - Foo: "foo", - Foo2: "foo2", - IntStr: 42, - String: "16", - Map: map[string]Small{ - "17": {Tag: "tag17"}, - "18": {Tag: "tag18"}, - }, - MapP: map[string]*Small{ - "19": {Tag: "tag19"}, - "20": nil, - }, - EmptyMap: map[string]Small{}, - Slice: []Small{{Tag: "tag20"}, {Tag: "tag21"}}, - SliceP: []*Small{{Tag: "tag22"}, nil, {Tag: "tag23"}}, - EmptySlice: []Small{}, - StringSlice: []string{"str24", "str25", "str26"}, - ByteSlice: []byte{27, 28, 29}, - Small: Small{Tag: "tag30"}, - PSmall: &Small{Tag: "tag31"}, - Interface: 5.2, -} - -var pallValue = All{ - PBool: &allValue.Bool, - PInt: &allValue.Int, - PInt8: &allValue.Int8, - PInt16: &allValue.Int16, - PInt32: &allValue.Int32, - PInt64: &allValue.Int64, - PUint: &allValue.Uint, - PUint8: &allValue.Uint8, - PUint16: &allValue.Uint16, - PUint32: &allValue.Uint32, - PUint64: &allValue.Uint64, - PUintptr: &allValue.Uintptr, - PFloat32: &allValue.Float32, - PFloat64: &allValue.Float64, - PString: &allValue.String, - PMap: &allValue.Map, - PMapP: &allValue.MapP, - PSlice: &allValue.Slice, - PSliceP: &allValue.SliceP, - PPSmall: &allValue.PSmall, - PInterface: &allValue.Interface, -} - -var allValueIndent = `{ - "Bool": true, - "Int": 2, - "Int8": 3, - "Int16": 4, - "Int32": 5, - "Int64": 6, - "Uint": 7, - "Uint8": 8, - "Uint16": 9, - "Uint32": 10, - "Uint64": 11, - "Uintptr": 12, - "Float32": 14.1, - "Float64": 15.1, - "bar": "foo", - "bar2": "foo2", - "IntStr": "42", - "PBool": null, - "PInt": null, - "PInt8": null, - "PInt16": null, - "PInt32": null, - "PInt64": null, - "PUint": null, - "PUint8": null, - "PUint16": null, - "PUint32": null, - "PUint64": null, - "PUintptr": null, - "PFloat32": null, - "PFloat64": null, - "String": "16", - "PString": null, - "Map": { - "17": { - "Tag": "tag17" - }, - "18": { - "Tag": "tag18" - } - }, - "MapP": { - "19": { - "Tag": "tag19" - }, - "20": null - }, - "PMap": null, - "PMapP": null, - "EmptyMap": {}, - "NilMap": null, - "Slice": [ - { - "Tag": "tag20" - }, - { - "Tag": "tag21" - } - ], - "SliceP": [ - { - "Tag": "tag22" - }, - null, - { - "Tag": "tag23" - } - ], - "PSlice": null, - "PSliceP": null, - "EmptySlice": [], - "NilSlice": null, - "StringSlice": [ - "str24", - "str25", - "str26" - ], - "ByteSlice": "Gxwd", - "Small": { - "Tag": "tag30" - }, - "PSmall": { - "Tag": "tag31" - }, - "PPSmall": null, - "Interface": 5.2, - "PInterface": null -}` - -var allValueCompact = strings.Map(noSpace, allValueIndent) - -var pallValueIndent = `{ - "Bool": false, - "Int": 0, - "Int8": 0, - "Int16": 0, - "Int32": 0, - "Int64": 0, - "Uint": 0, - "Uint8": 0, - "Uint16": 0, - "Uint32": 0, - "Uint64": 0, - "Uintptr": 0, - "Float32": 0, - "Float64": 0, - "bar": "", - "bar2": "", - "IntStr": "0", - "PBool": true, - "PInt": 2, - "PInt8": 3, - "PInt16": 4, - "PInt32": 5, - "PInt64": 6, - "PUint": 7, - "PUint8": 8, - "PUint16": 9, - "PUint32": 10, - "PUint64": 11, - "PUintptr": 12, - "PFloat32": 14.1, - "PFloat64": 15.1, - "String": "", - "PString": "16", - "Map": null, - "MapP": null, - "PMap": { - "17": { - "Tag": "tag17" - }, - "18": { - "Tag": "tag18" - } - }, - "PMapP": { - "19": { - "Tag": "tag19" - }, - "20": null - }, - "EmptyMap": null, - "NilMap": null, - "Slice": null, - "SliceP": null, - "PSlice": [ - { - "Tag": "tag20" - }, - { - "Tag": "tag21" - } - ], - "PSliceP": [ - { - "Tag": "tag22" - }, - null, - { - "Tag": "tag23" - } - ], - "EmptySlice": null, - "NilSlice": null, - "StringSlice": null, - "ByteSlice": null, - "Small": { - "Tag": "" - }, - "PSmall": null, - "PPSmall": { - "Tag": "tag31" - }, - "Interface": null, - "PInterface": 5.2 -}` - -var pallValueCompact = strings.Map(noSpace, pallValueIndent) - -func TestRefUnmarshal(t *testing.T) { - type S struct { - // Ref is defined in encode_test.go. - R0 Ref - R1 *Ref - R2 RefText - R3 *RefText - } - want := S{ - R0: 12, - R1: new(Ref), - R2: 13, - R3: new(RefText), - } - *want.R1 = 12 - *want.R3 = 13 - - var got S - if err := Unmarshal([]byte(`{"R0":"ref","R1":"ref","R2":"ref","R3":"ref"}`), &got); err != nil { - t.Fatalf("Unmarshal: %v", err) - } - if !reflect.DeepEqual(got, want) { - t.Errorf("got %+v, want %+v", got, want) - } -} - -// Test that the empty string doesn't panic decoding when ,string is specified -// Issue 3450 -func TestEmptyString(t *testing.T) { - type T2 struct { - Number1 int `json:",string"` - Number2 int `json:",string"` - } - data := `{"Number1":"1", "Number2":""}` - dec := NewDecoder(strings.NewReader(data)) - var t2 T2 - err := dec.Decode(&t2) - if err == nil { - t.Fatal("Decode: did not return error") - } - if t2.Number1 != 1 { - t.Fatal("Decode: did not set Number1") - } -} - -// Test that a null for ,string is not replaced with the previous quoted string (issue 7046). -// It should also not be an error (issue 2540, issue 8587). -func TestNullString(t *testing.T) { - type T struct { - A int `json:",string"` - B int `json:",string"` - C *int `json:",string"` - } - data := []byte(`{"A": "1", "B": null, "C": null}`) - var s T - s.B = 1 - s.C = new(int) - *s.C = 2 - err := Unmarshal(data, &s) - if err != nil { - t.Fatalf("Unmarshal: %v", err) - } - if s.B != 1 || s.C != nil { - t.Fatalf("after Unmarshal, s.B=%d, s.C=%p, want 1, nil", s.B, s.C) - } -} - -func intp(x int) *int { - p := new(int) - *p = x - return p -} - -func intpp(x *int) **int { - pp := new(*int) - *pp = x - return pp -} - -var interfaceSetTests = []struct { - pre interface{} - json string - post interface{} -}{ - {"foo", `"bar"`, "bar"}, - {"foo", `2`, 2.0}, - {"foo", `true`, true}, - {"foo", `null`, nil}, - - {nil, `null`, nil}, - {new(int), `null`, nil}, - {(*int)(nil), `null`, nil}, - {new(*int), `null`, new(*int)}, - {(**int)(nil), `null`, nil}, - {intp(1), `null`, nil}, - {intpp(nil), `null`, intpp(nil)}, - {intpp(intp(1)), `null`, intpp(nil)}, -} - -func TestInterfaceSet(t *testing.T) { - for _, tt := range interfaceSetTests { - b := struct{ X interface{} }{tt.pre} - blob := `{"X":` + tt.json + `}` - if err := Unmarshal([]byte(blob), &b); err != nil { - t.Errorf("Unmarshal %#q: %v", blob, err) - continue - } - if !reflect.DeepEqual(b.X, tt.post) { - t.Errorf("Unmarshal %#q into %#v: X=%#v, want %#v", blob, tt.pre, b.X, tt.post) - } - } -} - -// JSON null values should be ignored for primitives and string values instead of resulting in an error. -// Issue 2540 -func TestUnmarshalNulls(t *testing.T) { - jsonData := []byte(`{ - "Bool" : null, - "Int" : null, - "Int8" : null, - "Int16" : null, - "Int32" : null, - "Int64" : null, - "Uint" : null, - "Uint8" : null, - "Uint16" : null, - "Uint32" : null, - "Uint64" : null, - "Float32" : null, - "Float64" : null, - "String" : null}`) - - nulls := All{ - Bool: true, - Int: 2, - Int8: 3, - Int16: 4, - Int32: 5, - Int64: 6, - Uint: 7, - Uint8: 8, - Uint16: 9, - Uint32: 10, - Uint64: 11, - Float32: 12.1, - Float64: 13.1, - String: "14"} - - err := Unmarshal(jsonData, &nulls) - if err != nil { - t.Errorf("Unmarshal of null values failed: %v", err) - } - if !nulls.Bool || nulls.Int != 2 || nulls.Int8 != 3 || nulls.Int16 != 4 || nulls.Int32 != 5 || nulls.Int64 != 6 || - nulls.Uint != 7 || nulls.Uint8 != 8 || nulls.Uint16 != 9 || nulls.Uint32 != 10 || nulls.Uint64 != 11 || - nulls.Float32 != 12.1 || nulls.Float64 != 13.1 || nulls.String != "14" { - - t.Errorf("Unmarshal of null values affected primitives") - } -} - -func TestStringKind(t *testing.T) { - type stringKind string - - var m1, m2 map[stringKind]int - m1 = map[stringKind]int{ - "foo": 42, - } - - data, err := Marshal(m1) - if err != nil { - t.Errorf("Unexpected error marshaling: %v", err) - } - - err = Unmarshal(data, &m2) - if err != nil { - t.Errorf("Unexpected error unmarshaling: %v", err) - } - - if !reflect.DeepEqual(m1, m2) { - t.Error("Items should be equal after encoding and then decoding") - } -} - -// Custom types with []byte as underlying type could not be marshalled -// and then unmarshalled. -// Issue 8962. -func TestByteKind(t *testing.T) { - type byteKind []byte - - a := byteKind("hello") - - data, err := Marshal(a) - if err != nil { - t.Error(err) - } - var b byteKind - err = Unmarshal(data, &b) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(a, b) { - t.Errorf("expected %v == %v", a, b) - } -} - -// The fix for issue 8962 introduced a regression. -// Issue 12921. -func TestSliceOfCustomByte(t *testing.T) { - type Uint8 uint8 - - a := []Uint8("hello") - - data, err := Marshal(a) - if err != nil { - t.Fatal(err) - } - var b []Uint8 - err = Unmarshal(data, &b) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(a, b) { - t.Fatalf("expected %v == %v", a, b) - } -} - -var decodeTypeErrorTests = []struct { - dest interface{} - src string -}{ - {new(string), `{"user": "name"}`}, // issue 4628. - {new(error), `{}`}, // issue 4222 - {new(error), `[]`}, - {new(error), `""`}, - {new(error), `123`}, - {new(error), `true`}, -} - -func TestUnmarshalTypeError(t *testing.T) { - for _, item := range decodeTypeErrorTests { - err := Unmarshal([]byte(item.src), item.dest) - if _, ok := err.(*UnmarshalTypeError); !ok { - t.Errorf("expected type error for Unmarshal(%q, type %T): got %T", - item.src, item.dest, err) - } - } -} - -var unmarshalSyntaxTests = []string{ - "tru", - "fals", - "nul", - "123e", - `"hello`, - `[1,2,3`, - `{"key":1`, - `{"key":1,`, -} - -func TestUnmarshalSyntax(t *testing.T) { - var x interface{} - for _, src := range unmarshalSyntaxTests { - err := Unmarshal([]byte(src), &x) - if _, ok := err.(*SyntaxError); !ok { - t.Errorf("expected syntax error for Unmarshal(%q): got %T", src, err) - } - } -} - -// Test handling of unexported fields that should be ignored. -// Issue 4660 -type unexportedFields struct { - Name string - m map[string]interface{} `json:"-"` - m2 map[string]interface{} `json:"abcd"` -} - -func TestUnmarshalUnexported(t *testing.T) { - input := `{"Name": "Bob", "m": {"x": 123}, "m2": {"y": 456}, "abcd": {"z": 789}}` - want := &unexportedFields{Name: "Bob"} - - out := &unexportedFields{} - err := Unmarshal([]byte(input), out) - if err != nil { - t.Errorf("got error %v, expected nil", err) - } - if !reflect.DeepEqual(out, want) { - t.Errorf("got %q, want %q", out, want) - } -} - -// Time3339 is a time.Time which encodes to and from JSON -// as an RFC 3339 time in UTC. -type Time3339 time.Time - -func (t *Time3339) UnmarshalJSON(b []byte) error { - if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' { - return fmt.Errorf("types: failed to unmarshal non-string value %q as an RFC 3339 time", b) - } - tm, err := time.Parse(time.RFC3339, string(b[1:len(b)-1])) - if err != nil { - return err - } - *t = Time3339(tm) - return nil -} - -func TestUnmarshalJSONLiteralError(t *testing.T) { - var t3 Time3339 - err := Unmarshal([]byte(`"0000-00-00T00:00:00Z"`), &t3) - if err == nil { - t.Fatalf("expected error; got time %v", time.Time(t3)) - } - if !strings.Contains(err.Error(), "range") { - t.Errorf("got err = %v; want out of range error", err) - } -} - -// Test that extra object elements in an array do not result in a -// "data changing underfoot" error. -// Issue 3717 -func TestSkipArrayObjects(t *testing.T) { - json := `[{}]` - var dest [0]interface{} - - err := Unmarshal([]byte(json), &dest) - if err != nil { - t.Errorf("got error %q, want nil", err) - } -} - -// Test semantics of pre-filled struct fields and pre-filled map fields. -// Issue 4900. -func TestPrefilled(t *testing.T) { - ptrToMap := func(m map[string]interface{}) *map[string]interface{} { return &m } - - // Values here change, cannot reuse table across runs. - var prefillTests = []struct { - in string - ptr interface{} - out interface{} - }{ - { - in: `{"X": 1, "Y": 2}`, - ptr: &XYZ{X: float32(3), Y: int16(4), Z: 1.5}, - out: &XYZ{X: float64(1), Y: float64(2), Z: 1.5}, - }, - { - in: `{"X": 1, "Y": 2}`, - ptr: ptrToMap(map[string]interface{}{"X": float32(3), "Y": int16(4), "Z": 1.5}), - out: ptrToMap(map[string]interface{}{"X": float64(1), "Y": float64(2), "Z": 1.5}), - }, - } - - for _, tt := range prefillTests { - ptrstr := fmt.Sprintf("%v", tt.ptr) - err := Unmarshal([]byte(tt.in), tt.ptr) // tt.ptr edited here - if err != nil { - t.Errorf("Unmarshal: %v", err) - } - if !reflect.DeepEqual(tt.ptr, tt.out) { - t.Errorf("Unmarshal(%#q, %s): have %v, want %v", tt.in, ptrstr, tt.ptr, tt.out) - } - } -} - -var invalidUnmarshalTests = []struct { - v interface{} - want string -}{ - {nil, "json: Unmarshal(nil)"}, - {struct{}{}, "json: Unmarshal(non-pointer struct {})"}, - {(*int)(nil), "json: Unmarshal(nil *int)"}, -} - -func TestInvalidUnmarshal(t *testing.T) { - buf := []byte(`{"a":"1"}`) - for _, tt := range invalidUnmarshalTests { - err := Unmarshal(buf, tt.v) - if err == nil { - t.Errorf("Unmarshal expecting error, got nil") - continue - } - if got := err.Error(); got != tt.want { - t.Errorf("Unmarshal = %q; want %q", got, tt.want) - } - } -} - -var invalidUnmarshalTextTests = []struct { - v interface{} - want string -}{ - {nil, "json: Unmarshal(nil)"}, - {struct{}{}, "json: Unmarshal(non-pointer struct {})"}, - {(*int)(nil), "json: Unmarshal(nil *int)"}, - {new(net.IP), "json: cannot unmarshal string into Go value of type *net.IP"}, -} - -func TestInvalidUnmarshalText(t *testing.T) { - buf := []byte(`123`) - for _, tt := range invalidUnmarshalTextTests { - err := Unmarshal(buf, tt.v) - if err == nil { - t.Errorf("Unmarshal expecting error, got nil") - continue - } - if got := err.Error(); got != tt.want { - t.Errorf("Unmarshal = %q; want %q", got, tt.want) - } - } -} - -// Test that string option is ignored for invalid types. -// Issue 9812. -func TestInvalidStringOption(t *testing.T) { - num := 0 - item := struct { - T time.Time `json:",string"` - M map[string]string `json:",string"` - S []string `json:",string"` - A [1]string `json:",string"` - I interface{} `json:",string"` - P *int `json:",string"` - }{M: make(map[string]string), S: make([]string, 0), I: num, P: &num} - - data, err := Marshal(item) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - - err = Unmarshal(data, &item) - if err != nil { - t.Fatalf("Unmarshal: %v", err) - } -} diff --git a/vendor/gopkg.in/square/go-jose.v2/json/encode_test.go b/vendor/gopkg.in/square/go-jose.v2/json/encode_test.go deleted file mode 100644 index c00491e00..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/json/encode_test.go +++ /dev/null @@ -1,538 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "bytes" - "math" - "reflect" - "testing" - "unicode" -) - -type Optionals struct { - Sr string `json:"sr"` - So string `json:"so,omitempty"` - Sw string `json:"-"` - - Ir int `json:"omitempty"` // actually named omitempty, not an option - Io int `json:"io,omitempty"` - - Slr []string `json:"slr,random"` - Slo []string `json:"slo,omitempty"` - - Mr map[string]interface{} `json:"mr"` - Mo map[string]interface{} `json:",omitempty"` - - Fr float64 `json:"fr"` - Fo float64 `json:"fo,omitempty"` - - Br bool `json:"br"` - Bo bool `json:"bo,omitempty"` - - Ur uint `json:"ur"` - Uo uint `json:"uo,omitempty"` - - Str struct{} `json:"str"` - Sto struct{} `json:"sto,omitempty"` -} - -var optionalsExpected = `{ - "sr": "", - "omitempty": 0, - "slr": null, - "mr": {}, - "fr": 0, - "br": false, - "ur": 0, - "str": {}, - "sto": {} -}` - -func TestOmitEmpty(t *testing.T) { - var o Optionals - o.Sw = "something" - o.Mr = map[string]interface{}{} - o.Mo = map[string]interface{}{} - - got, err := MarshalIndent(&o, "", " ") - if err != nil { - t.Fatal(err) - } - if got := string(got); got != optionalsExpected { - t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected) - } -} - -type StringTag struct { - BoolStr bool `json:",string"` - IntStr int64 `json:",string"` - StrStr string `json:",string"` -} - -var stringTagExpected = `{ - "BoolStr": "true", - "IntStr": "42", - "StrStr": "\"xzbit\"" -}` - -func TestStringTag(t *testing.T) { - var s StringTag - s.BoolStr = true - s.IntStr = 42 - s.StrStr = "xzbit" - got, err := MarshalIndent(&s, "", " ") - if err != nil { - t.Fatal(err) - } - if got := string(got); got != stringTagExpected { - t.Fatalf(" got: %s\nwant: %s\n", got, stringTagExpected) - } - - // Verify that it round-trips. - var s2 StringTag - err = NewDecoder(bytes.NewReader(got)).Decode(&s2) - if err != nil { - t.Fatalf("Decode: %v", err) - } - if !reflect.DeepEqual(s, s2) { - t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", s, string(got), s2) - } -} - -// byte slices are special even if they're renamed types. -type renamedByte byte -type renamedByteSlice []byte -type renamedRenamedByteSlice []renamedByte - -func TestEncodeRenamedByteSlice(t *testing.T) { - s := renamedByteSlice("abc") - result, err := Marshal(s) - if err != nil { - t.Fatal(err) - } - expect := `"YWJj"` - if string(result) != expect { - t.Errorf(" got %s want %s", result, expect) - } - r := renamedRenamedByteSlice("abc") - result, err = Marshal(r) - if err != nil { - t.Fatal(err) - } - if string(result) != expect { - t.Errorf(" got %s want %s", result, expect) - } -} - -var unsupportedValues = []interface{}{ - math.NaN(), - math.Inf(-1), - math.Inf(1), -} - -func TestUnsupportedValues(t *testing.T) { - for _, v := range unsupportedValues { - if _, err := Marshal(v); err != nil { - if _, ok := err.(*UnsupportedValueError); !ok { - t.Errorf("for %v, got %T want UnsupportedValueError", v, err) - } - } else { - t.Errorf("for %v, expected error", v) - } - } -} - -// Ref has Marshaler and Unmarshaler methods with pointer receiver. -type Ref int - -func (*Ref) MarshalJSON() ([]byte, error) { - return []byte(`"ref"`), nil -} - -func (r *Ref) UnmarshalJSON([]byte) error { - *r = 12 - return nil -} - -// Val has Marshaler methods with value receiver. -type Val int - -func (Val) MarshalJSON() ([]byte, error) { - return []byte(`"val"`), nil -} - -// RefText has Marshaler and Unmarshaler methods with pointer receiver. -type RefText int - -func (*RefText) MarshalText() ([]byte, error) { - return []byte(`"ref"`), nil -} - -func (r *RefText) UnmarshalText([]byte) error { - *r = 13 - return nil -} - -// ValText has Marshaler methods with value receiver. -type ValText int - -func (ValText) MarshalText() ([]byte, error) { - return []byte(`"val"`), nil -} - -func TestRefValMarshal(t *testing.T) { - var s = struct { - R0 Ref - R1 *Ref - R2 RefText - R3 *RefText - V0 Val - V1 *Val - V2 ValText - V3 *ValText - }{ - R0: 12, - R1: new(Ref), - R2: 14, - R3: new(RefText), - V0: 13, - V1: new(Val), - V2: 15, - V3: new(ValText), - } - const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}` - b, err := Marshal(&s) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - if got := string(b); got != want { - t.Errorf("got %q, want %q", got, want) - } -} - -// C implements Marshaler and returns unescaped JSON. -type C int - -func (C) MarshalJSON() ([]byte, error) { - return []byte(`"<&>"`), nil -} - -// CText implements Marshaler and returns unescaped text. -type CText int - -func (CText) MarshalText() ([]byte, error) { - return []byte(`"<&>"`), nil -} - -func TestMarshalerEscaping(t *testing.T) { - var c C - want := `"\u003c\u0026\u003e"` - b, err := Marshal(c) - if err != nil { - t.Fatalf("Marshal(c): %v", err) - } - if got := string(b); got != want { - t.Errorf("Marshal(c) = %#q, want %#q", got, want) - } - - var ct CText - want = `"\"\u003c\u0026\u003e\""` - b, err = Marshal(ct) - if err != nil { - t.Fatalf("Marshal(ct): %v", err) - } - if got := string(b); got != want { - t.Errorf("Marshal(ct) = %#q, want %#q", got, want) - } -} - -type IntType int - -type MyStruct struct { - IntType -} - -func TestAnonymousNonstruct(t *testing.T) { - var i IntType = 11 - a := MyStruct{i} - const want = `{"IntType":11}` - - b, err := Marshal(a) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - if got := string(b); got != want { - t.Errorf("got %q, want %q", got, want) - } -} - -type BugA struct { - S string -} - -type BugB struct { - BugA - S string -} - -type BugC struct { - S string -} - -// Legal Go: We never use the repeated embedded field (S). -type BugX struct { - A int - BugA - BugB -} - -// Issue 5245. -func TestEmbeddedBug(t *testing.T) { - v := BugB{ - BugA{"A"}, - "B", - } - b, err := Marshal(v) - if err != nil { - t.Fatal("Marshal:", err) - } - want := `{"S":"B"}` - got := string(b) - if got != want { - t.Fatalf("Marshal: got %s want %s", got, want) - } - // Now check that the duplicate field, S, does not appear. - x := BugX{ - A: 23, - } - b, err = Marshal(x) - if err != nil { - t.Fatal("Marshal:", err) - } - want = `{"A":23}` - got = string(b) - if got != want { - t.Fatalf("Marshal: got %s want %s", got, want) - } -} - -type BugD struct { // Same as BugA after tagging. - XXX string `json:"S"` -} - -// BugD's tagged S field should dominate BugA's. -type BugY struct { - BugA - BugD -} - -// Test that a field with a tag dominates untagged fields. -func TestTaggedFieldDominates(t *testing.T) { - v := BugY{ - BugA{"BugA"}, - BugD{"BugD"}, - } - b, err := Marshal(v) - if err != nil { - t.Fatal("Marshal:", err) - } - want := `{"S":"BugD"}` - got := string(b) - if got != want { - t.Fatalf("Marshal: got %s want %s", got, want) - } -} - -// There are no tags here, so S should not appear. -type BugZ struct { - BugA - BugC - BugY // Contains a tagged S field through BugD; should not dominate. -} - -func TestDuplicatedFieldDisappears(t *testing.T) { - v := BugZ{ - BugA{"BugA"}, - BugC{"BugC"}, - BugY{ - BugA{"nested BugA"}, - BugD{"nested BugD"}, - }, - } - b, err := Marshal(v) - if err != nil { - t.Fatal("Marshal:", err) - } - want := `{}` - got := string(b) - if got != want { - t.Fatalf("Marshal: got %s want %s", got, want) - } -} - -func TestStringBytes(t *testing.T) { - // Test that encodeState.stringBytes and encodeState.string use the same encoding. - es := &encodeState{} - var r []rune - for i := '\u0000'; i <= unicode.MaxRune; i++ { - r = append(r, i) - } - s := string(r) + "\xff\xff\xffhello" // some invalid UTF-8 too - es.string(s) - - esBytes := &encodeState{} - esBytes.stringBytes([]byte(s)) - - enc := es.Buffer.String() - encBytes := esBytes.Buffer.String() - if enc != encBytes { - i := 0 - for i < len(enc) && i < len(encBytes) && enc[i] == encBytes[i] { - i++ - } - enc = enc[i:] - encBytes = encBytes[i:] - i = 0 - for i < len(enc) && i < len(encBytes) && enc[len(enc)-i-1] == encBytes[len(encBytes)-i-1] { - i++ - } - enc = enc[:len(enc)-i] - encBytes = encBytes[:len(encBytes)-i] - - if len(enc) > 20 { - enc = enc[:20] + "..." - } - if len(encBytes) > 20 { - encBytes = encBytes[:20] + "..." - } - - t.Errorf("encodings differ at %#q vs %#q", enc, encBytes) - } -} - -func TestIssue6458(t *testing.T) { - type Foo struct { - M RawMessage - } - x := Foo{RawMessage(`"foo"`)} - - b, err := Marshal(&x) - if err != nil { - t.Fatal(err) - } - if want := `{"M":"foo"}`; string(b) != want { - t.Errorf("Marshal(&x) = %#q; want %#q", b, want) - } - - b, err = Marshal(x) - if err != nil { - t.Fatal(err) - } - - if want := `{"M":"ImZvbyI="}`; string(b) != want { - t.Errorf("Marshal(x) = %#q; want %#q", b, want) - } -} - -func TestIssue10281(t *testing.T) { - type Foo struct { - N Number - } - x := Foo{Number(`invalid`)} - - b, err := Marshal(&x) - if err == nil { - t.Errorf("Marshal(&x) = %#q; want error", b) - } -} - -func TestHTMLEscape(t *testing.T) { - var b, want bytes.Buffer - m := `{"M":"foo &` + "\xe2\x80\xa8 \xe2\x80\xa9" + `"}` - want.Write([]byte(`{"M":"\u003chtml\u003efoo \u0026\u2028 \u2029\u003c/html\u003e"}`)) - HTMLEscape(&b, []byte(m)) - if !bytes.Equal(b.Bytes(), want.Bytes()) { - t.Errorf("HTMLEscape(&b, []byte(m)) = %s; want %s", b.Bytes(), want.Bytes()) - } -} - -// golang.org/issue/8582 -func TestEncodePointerString(t *testing.T) { - type stringPointer struct { - N *int64 `json:"n,string"` - } - var n int64 = 42 - b, err := Marshal(stringPointer{N: &n}) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - if got, want := string(b), `{"n":"42"}`; got != want { - t.Errorf("Marshal = %s, want %s", got, want) - } - var back stringPointer - err = Unmarshal(b, &back) - if err != nil { - t.Fatalf("Unmarshal: %v", err) - } - if back.N == nil { - t.Fatalf("Unmarshalled nil N field") - } - if *back.N != 42 { - t.Fatalf("*N = %d; want 42", *back.N) - } -} - -var encodeStringTests = []struct { - in string - out string -}{ - {"\x00", `"\u0000"`}, - {"\x01", `"\u0001"`}, - {"\x02", `"\u0002"`}, - {"\x03", `"\u0003"`}, - {"\x04", `"\u0004"`}, - {"\x05", `"\u0005"`}, - {"\x06", `"\u0006"`}, - {"\x07", `"\u0007"`}, - {"\x08", `"\u0008"`}, - {"\x09", `"\t"`}, - {"\x0a", `"\n"`}, - {"\x0b", `"\u000b"`}, - {"\x0c", `"\u000c"`}, - {"\x0d", `"\r"`}, - {"\x0e", `"\u000e"`}, - {"\x0f", `"\u000f"`}, - {"\x10", `"\u0010"`}, - {"\x11", `"\u0011"`}, - {"\x12", `"\u0012"`}, - {"\x13", `"\u0013"`}, - {"\x14", `"\u0014"`}, - {"\x15", `"\u0015"`}, - {"\x16", `"\u0016"`}, - {"\x17", `"\u0017"`}, - {"\x18", `"\u0018"`}, - {"\x19", `"\u0019"`}, - {"\x1a", `"\u001a"`}, - {"\x1b", `"\u001b"`}, - {"\x1c", `"\u001c"`}, - {"\x1d", `"\u001d"`}, - {"\x1e", `"\u001e"`}, - {"\x1f", `"\u001f"`}, -} - -func TestEncodeString(t *testing.T) { - for _, tt := range encodeStringTests { - b, err := Marshal(tt.in) - if err != nil { - t.Errorf("Marshal(%q): %v", tt.in, err) - continue - } - out := string(b) - if out != tt.out { - t.Errorf("Marshal(%q) = %#q, want %#q", tt.in, out, tt.out) - } - } -} diff --git a/vendor/gopkg.in/square/go-jose.v2/json/number_test.go b/vendor/gopkg.in/square/go-jose.v2/json/number_test.go deleted file mode 100644 index 4e63cf9c7..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/json/number_test.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "regexp" - "testing" -) - -func TestNumberIsValid(t *testing.T) { - // From: http://stackoverflow.com/a/13340826 - var jsonNumberRegexp = regexp.MustCompile(`^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$`) - - validTests := []string{ - "0", - "-0", - "1", - "-1", - "0.1", - "-0.1", - "1234", - "-1234", - "12.34", - "-12.34", - "12E0", - "12E1", - "12e34", - "12E-0", - "12e+1", - "12e-34", - "-12E0", - "-12E1", - "-12e34", - "-12E-0", - "-12e+1", - "-12e-34", - "1.2E0", - "1.2E1", - "1.2e34", - "1.2E-0", - "1.2e+1", - "1.2e-34", - "-1.2E0", - "-1.2E1", - "-1.2e34", - "-1.2E-0", - "-1.2e+1", - "-1.2e-34", - "0E0", - "0E1", - "0e34", - "0E-0", - "0e+1", - "0e-34", - "-0E0", - "-0E1", - "-0e34", - "-0E-0", - "-0e+1", - "-0e-34", - } - - for _, test := range validTests { - if !isValidNumber(test) { - t.Errorf("%s should be valid", test) - } - - var f float64 - if err := Unmarshal([]byte(test), &f); err != nil { - t.Errorf("%s should be valid but Unmarshal failed: %v", test, err) - } - - if !jsonNumberRegexp.MatchString(test) { - t.Errorf("%s should be valid but regexp does not match", test) - } - } - - invalidTests := []string{ - "", - "invalid", - "1.0.1", - "1..1", - "-1-2", - "012a42", - "01.2", - "012", - "12E12.12", - "1e2e3", - "1e+-2", - "1e--23", - "1e", - "e1", - "1e+", - "1ea", - "1a", - "1.a", - "1.", - "01", - "1.e1", - } - - for _, test := range invalidTests { - if isValidNumber(test) { - t.Errorf("%s should be invalid", test) - } - - var f float64 - if err := Unmarshal([]byte(test), &f); err == nil { - t.Errorf("%s should be invalid but unmarshal wrote %v", test, f) - } - - if jsonNumberRegexp.MatchString(test) { - t.Errorf("%s should be invalid but matches regexp", test) - } - } -} - -func BenchmarkNumberIsValid(b *testing.B) { - s := "-61657.61667E+61673" - for i := 0; i < b.N; i++ { - isValidNumber(s) - } -} - -func BenchmarkNumberIsValidRegexp(b *testing.B) { - var jsonNumberRegexp = regexp.MustCompile(`^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$`) - s := "-61657.61667E+61673" - for i := 0; i < b.N; i++ { - jsonNumberRegexp.MatchString(s) - } -} diff --git a/vendor/gopkg.in/square/go-jose.v2/json/scanner_test.go b/vendor/gopkg.in/square/go-jose.v2/json/scanner_test.go deleted file mode 100644 index 66383ef0e..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/json/scanner_test.go +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "bytes" - "math" - "math/rand" - "reflect" - "testing" -) - -// Tests of simple examples. - -type example struct { - compact string - indent string -} - -var examples = []example{ - {`1`, `1`}, - {`{}`, `{}`}, - {`[]`, `[]`}, - {`{"":2}`, "{\n\t\"\": 2\n}"}, - {`[3]`, "[\n\t3\n]"}, - {`[1,2,3]`, "[\n\t1,\n\t2,\n\t3\n]"}, - {`{"x":1}`, "{\n\t\"x\": 1\n}"}, - {ex1, ex1i}, -} - -var ex1 = `[true,false,null,"x",1,1.5,0,-5e+2]` - -var ex1i = `[ - true, - false, - null, - "x", - 1, - 1.5, - 0, - -5e+2 -]` - -func TestCompact(t *testing.T) { - var buf bytes.Buffer - for _, tt := range examples { - buf.Reset() - if err := Compact(&buf, []byte(tt.compact)); err != nil { - t.Errorf("Compact(%#q): %v", tt.compact, err) - } else if s := buf.String(); s != tt.compact { - t.Errorf("Compact(%#q) = %#q, want original", tt.compact, s) - } - - buf.Reset() - if err := Compact(&buf, []byte(tt.indent)); err != nil { - t.Errorf("Compact(%#q): %v", tt.indent, err) - continue - } else if s := buf.String(); s != tt.compact { - t.Errorf("Compact(%#q) = %#q, want %#q", tt.indent, s, tt.compact) - } - } -} - -func TestCompactSeparators(t *testing.T) { - // U+2028 and U+2029 should be escaped inside strings. - // They should not appear outside strings. - tests := []struct { - in, compact string - }{ - {"{\"\u2028\": 1}", `{"\u2028":1}`}, - {"{\"\u2029\" :2}", `{"\u2029":2}`}, - } - for _, tt := range tests { - var buf bytes.Buffer - if err := Compact(&buf, []byte(tt.in)); err != nil { - t.Errorf("Compact(%q): %v", tt.in, err) - } else if s := buf.String(); s != tt.compact { - t.Errorf("Compact(%q) = %q, want %q", tt.in, s, tt.compact) - } - } -} - -func TestIndent(t *testing.T) { - var buf bytes.Buffer - for _, tt := range examples { - buf.Reset() - if err := Indent(&buf, []byte(tt.indent), "", "\t"); err != nil { - t.Errorf("Indent(%#q): %v", tt.indent, err) - } else if s := buf.String(); s != tt.indent { - t.Errorf("Indent(%#q) = %#q, want original", tt.indent, s) - } - - buf.Reset() - if err := Indent(&buf, []byte(tt.compact), "", "\t"); err != nil { - t.Errorf("Indent(%#q): %v", tt.compact, err) - continue - } else if s := buf.String(); s != tt.indent { - t.Errorf("Indent(%#q) = %#q, want %#q", tt.compact, s, tt.indent) - } - } -} - -// Tests of a large random structure. - -func TestCompactBig(t *testing.T) { - initBig() - var buf bytes.Buffer - if err := Compact(&buf, jsonBig); err != nil { - t.Fatalf("Compact: %v", err) - } - b := buf.Bytes() - if !bytes.Equal(b, jsonBig) { - t.Error("Compact(jsonBig) != jsonBig") - diff(t, b, jsonBig) - return - } -} - -func TestIndentBig(t *testing.T) { - initBig() - var buf bytes.Buffer - if err := Indent(&buf, jsonBig, "", "\t"); err != nil { - t.Fatalf("Indent1: %v", err) - } - b := buf.Bytes() - if len(b) == len(jsonBig) { - // jsonBig is compact (no unnecessary spaces); - // indenting should make it bigger - t.Fatalf("Indent(jsonBig) did not get bigger") - } - - // should be idempotent - var buf1 bytes.Buffer - if err := Indent(&buf1, b, "", "\t"); err != nil { - t.Fatalf("Indent2: %v", err) - } - b1 := buf1.Bytes() - if !bytes.Equal(b1, b) { - t.Error("Indent(Indent(jsonBig)) != Indent(jsonBig)") - diff(t, b1, b) - return - } - - // should get back to original - buf1.Reset() - if err := Compact(&buf1, b); err != nil { - t.Fatalf("Compact: %v", err) - } - b1 = buf1.Bytes() - if !bytes.Equal(b1, jsonBig) { - t.Error("Compact(Indent(jsonBig)) != jsonBig") - diff(t, b1, jsonBig) - return - } -} - -type indentErrorTest struct { - in string - err error -} - -var indentErrorTests = []indentErrorTest{ - {`{"X": "foo", "Y"}`, &SyntaxError{"invalid character '}' after object key", 17}}, - {`{"X": "foo" "Y": "bar"}`, &SyntaxError{"invalid character '\"' after object key:value pair", 13}}, -} - -func TestIndentErrors(t *testing.T) { - for i, tt := range indentErrorTests { - slice := make([]uint8, 0) - buf := bytes.NewBuffer(slice) - if err := Indent(buf, []uint8(tt.in), "", ""); err != nil { - if !reflect.DeepEqual(err, tt.err) { - t.Errorf("#%d: Indent: %#v", i, err) - continue - } - } - } -} - -func TestNextValueBig(t *testing.T) { - initBig() - var scan scanner - item, rest, err := nextValue(jsonBig, &scan) - if err != nil { - t.Fatalf("nextValue: %s", err) - } - if len(item) != len(jsonBig) || &item[0] != &jsonBig[0] { - t.Errorf("invalid item: %d %d", len(item), len(jsonBig)) - } - if len(rest) != 0 { - t.Errorf("invalid rest: %d", len(rest)) - } - - item, rest, err = nextValue(append(jsonBig, "HELLO WORLD"...), &scan) - if err != nil { - t.Fatalf("nextValue extra: %s", err) - } - if len(item) != len(jsonBig) { - t.Errorf("invalid item: %d %d", len(item), len(jsonBig)) - } - if string(rest) != "HELLO WORLD" { - t.Errorf("invalid rest: %d", len(rest)) - } -} - -var benchScan scanner - -func BenchmarkSkipValue(b *testing.B) { - initBig() - b.ResetTimer() - for i := 0; i < b.N; i++ { - nextValue(jsonBig, &benchScan) - } - b.SetBytes(int64(len(jsonBig))) -} - -func diff(t *testing.T, a, b []byte) { - for i := 0; ; i++ { - if i >= len(a) || i >= len(b) || a[i] != b[i] { - j := i - 10 - if j < 0 { - j = 0 - } - t.Errorf("diverge at %d: «%s» vs «%s»", i, trim(a[j:]), trim(b[j:])) - return - } - } -} - -func trim(b []byte) []byte { - if len(b) > 20 { - return b[0:20] - } - return b -} - -// Generate a random JSON object. - -var jsonBig []byte - -func initBig() { - n := 10000 - if testing.Short() { - n = 100 - } - b, err := Marshal(genValue(n)) - if err != nil { - panic(err) - } - jsonBig = b -} - -func genValue(n int) interface{} { - if n > 1 { - switch rand.Intn(2) { - case 0: - return genArray(n) - case 1: - return genMap(n) - } - } - switch rand.Intn(3) { - case 0: - return rand.Intn(2) == 0 - case 1: - return rand.NormFloat64() - case 2: - return genString(30) - } - panic("unreachable") -} - -func genString(stddev float64) string { - n := int(math.Abs(rand.NormFloat64()*stddev + stddev/2)) - c := make([]rune, n) - for i := range c { - f := math.Abs(rand.NormFloat64()*64 + 32) - if f > 0x10ffff { - f = 0x10ffff - } - c[i] = rune(f) - } - return string(c) -} - -func genArray(n int) []interface{} { - f := int(math.Abs(rand.NormFloat64()) * math.Min(10, float64(n/2))) - if f > n { - f = n - } - if f < 1 { - f = 1 - } - x := make([]interface{}, f) - for i := range x { - x[i] = genValue(((i+1)*n)/f - (i*n)/f) - } - return x -} - -func genMap(n int) map[string]interface{} { - f := int(math.Abs(rand.NormFloat64()) * math.Min(10, float64(n/2))) - if f > n { - f = n - } - if n > 0 && f == 0 { - f = 1 - } - x := make(map[string]interface{}) - for i := 0; i < f; i++ { - x[genString(10)] = genValue(((i+1)*n)/f - (i*n)/f) - } - return x -} diff --git a/vendor/gopkg.in/square/go-jose.v2/json/stream_test.go b/vendor/gopkg.in/square/go-jose.v2/json/stream_test.go deleted file mode 100644 index eccf365b2..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/json/stream_test.go +++ /dev/null @@ -1,354 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "bytes" - "io" - "io/ioutil" - "log" - "net" - "net/http" - "net/http/httptest" - "reflect" - "strings" - "testing" -) - -// Test values for the stream test. -// One of each JSON kind. -var streamTest = []interface{}{ - 0.1, - "hello", - nil, - true, - false, - []interface{}{"a", "b", "c"}, - map[string]interface{}{"K": "Kelvin", "ß": "long s"}, - 3.14, // another value to make sure something can follow map -} - -var streamEncoded = `0.1 -"hello" -null -true -false -["a","b","c"] -{"ß":"long s","K":"Kelvin"} -3.14 -` - -func TestEncoder(t *testing.T) { - for i := 0; i <= len(streamTest); i++ { - var buf bytes.Buffer - enc := NewEncoder(&buf) - for j, v := range streamTest[0:i] { - if err := enc.Encode(v); err != nil { - t.Fatalf("encode #%d: %v", j, err) - } - } - if have, want := buf.String(), nlines(streamEncoded, i); have != want { - t.Errorf("encoding %d items: mismatch", i) - diff(t, []byte(have), []byte(want)) - break - } - } -} - -func TestDecoder(t *testing.T) { - for i := 0; i <= len(streamTest); i++ { - // Use stream without newlines as input, - // just to stress the decoder even more. - // Our test input does not include back-to-back numbers. - // Otherwise stripping the newlines would - // merge two adjacent JSON values. - var buf bytes.Buffer - for _, c := range nlines(streamEncoded, i) { - if c != '\n' { - buf.WriteRune(c) - } - } - out := make([]interface{}, i) - dec := NewDecoder(&buf) - for j := range out { - if err := dec.Decode(&out[j]); err != nil { - t.Fatalf("decode #%d/%d: %v", j, i, err) - } - } - if !reflect.DeepEqual(out, streamTest[0:i]) { - t.Errorf("decoding %d items: mismatch", i) - for j := range out { - if !reflect.DeepEqual(out[j], streamTest[j]) { - t.Errorf("#%d: have %v want %v", j, out[j], streamTest[j]) - } - } - break - } - } -} - -func TestDecoderBuffered(t *testing.T) { - r := strings.NewReader(`{"Name": "Gopher"} extra `) - var m struct { - Name string - } - d := NewDecoder(r) - err := d.Decode(&m) - if err != nil { - t.Fatal(err) - } - if m.Name != "Gopher" { - t.Errorf("Name = %q; want Gopher", m.Name) - } - rest, err := ioutil.ReadAll(d.Buffered()) - if err != nil { - t.Fatal(err) - } - if g, w := string(rest), " extra "; g != w { - t.Errorf("Remaining = %q; want %q", g, w) - } -} - -func nlines(s string, n int) string { - if n <= 0 { - return "" - } - for i, c := range s { - if c == '\n' { - if n--; n == 0 { - return s[0 : i+1] - } - } - } - return s -} - -func TestRawMessage(t *testing.T) { - // TODO(rsc): Should not need the * in *RawMessage - var data struct { - X float64 - Id *RawMessage - Y float32 - } - const raw = `["\u0056",null]` - const msg = `{"X":0.1,"Id":["\u0056",null],"Y":0.2}` - err := Unmarshal([]byte(msg), &data) - if err != nil { - t.Fatalf("Unmarshal: %v", err) - } - if string([]byte(*data.Id)) != raw { - t.Fatalf("Raw mismatch: have %#q want %#q", []byte(*data.Id), raw) - } - b, err := Marshal(&data) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - if string(b) != msg { - t.Fatalf("Marshal: have %#q want %#q", b, msg) - } -} - -func TestNullRawMessage(t *testing.T) { - // TODO(rsc): Should not need the * in *RawMessage - var data struct { - X float64 - Id *RawMessage - Y float32 - } - data.Id = new(RawMessage) - const msg = `{"X":0.1,"Id":null,"Y":0.2}` - err := Unmarshal([]byte(msg), &data) - if err != nil { - t.Fatalf("Unmarshal: %v", err) - } - if data.Id != nil { - t.Fatalf("Raw mismatch: have non-nil, want nil") - } - b, err := Marshal(&data) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - if string(b) != msg { - t.Fatalf("Marshal: have %#q want %#q", b, msg) - } -} - -var blockingTests = []string{ - `{"x": 1}`, - `[1, 2, 3]`, -} - -func TestBlocking(t *testing.T) { - for _, enc := range blockingTests { - r, w := net.Pipe() - go w.Write([]byte(enc)) - var val interface{} - - // If Decode reads beyond what w.Write writes above, - // it will block, and the test will deadlock. - if err := NewDecoder(r).Decode(&val); err != nil { - t.Errorf("decoding %s: %v", enc, err) - } - r.Close() - w.Close() - } -} - -func BenchmarkEncoderEncode(b *testing.B) { - b.ReportAllocs() - type T struct { - X, Y string - } - v := &T{"foo", "bar"} - for i := 0; i < b.N; i++ { - if err := NewEncoder(ioutil.Discard).Encode(v); err != nil { - b.Fatal(err) - } - } -} - -type tokenStreamCase struct { - json string - expTokens []interface{} -} - -type decodeThis struct { - v interface{} -} - -var tokenStreamCases []tokenStreamCase = []tokenStreamCase{ - // streaming token cases - {json: `10`, expTokens: []interface{}{float64(10)}}, - {json: ` [10] `, expTokens: []interface{}{ - Delim('['), float64(10), Delim(']')}}, - {json: ` [false,10,"b"] `, expTokens: []interface{}{ - Delim('['), false, float64(10), "b", Delim(']')}}, - {json: `{ "a": 1 }`, expTokens: []interface{}{ - Delim('{'), "a", float64(1), Delim('}')}}, - {json: `{"a": 1, "b":"3"}`, expTokens: []interface{}{ - Delim('{'), "a", float64(1), "b", "3", Delim('}')}}, - {json: ` [{"a": 1},{"a": 2}] `, expTokens: []interface{}{ - Delim('['), - Delim('{'), "a", float64(1), Delim('}'), - Delim('{'), "a", float64(2), Delim('}'), - Delim(']')}}, - {json: `{"obj": {"a": 1}}`, expTokens: []interface{}{ - Delim('{'), "obj", Delim('{'), "a", float64(1), Delim('}'), - Delim('}')}}, - {json: `{"obj": [{"a": 1}]}`, expTokens: []interface{}{ - Delim('{'), "obj", Delim('['), - Delim('{'), "a", float64(1), Delim('}'), - Delim(']'), Delim('}')}}, - - // streaming tokens with intermittent Decode() - {json: `{ "a": 1 }`, expTokens: []interface{}{ - Delim('{'), "a", - decodeThis{float64(1)}, - Delim('}')}}, - {json: ` [ { "a" : 1 } ] `, expTokens: []interface{}{ - Delim('['), - decodeThis{map[string]interface{}{"a": float64(1)}}, - Delim(']')}}, - {json: ` [{"a": 1},{"a": 2}] `, expTokens: []interface{}{ - Delim('['), - decodeThis{map[string]interface{}{"a": float64(1)}}, - decodeThis{map[string]interface{}{"a": float64(2)}}, - Delim(']')}}, - {json: `{ "obj" : [ { "a" : 1 } ] }`, expTokens: []interface{}{ - Delim('{'), "obj", Delim('['), - decodeThis{map[string]interface{}{"a": float64(1)}}, - Delim(']'), Delim('}')}}, - - {json: `{"obj": {"a": 1}}`, expTokens: []interface{}{ - Delim('{'), "obj", - decodeThis{map[string]interface{}{"a": float64(1)}}, - Delim('}')}}, - {json: `{"obj": [{"a": 1}]}`, expTokens: []interface{}{ - Delim('{'), "obj", - decodeThis{[]interface{}{ - map[string]interface{}{"a": float64(1)}, - }}, - Delim('}')}}, - {json: ` [{"a": 1} {"a": 2}] `, expTokens: []interface{}{ - Delim('['), - decodeThis{map[string]interface{}{"a": float64(1)}}, - decodeThis{&SyntaxError{"expected comma after array element", 0}}, - }}, - {json: `{ "a" 1 }`, expTokens: []interface{}{ - Delim('{'), "a", - decodeThis{&SyntaxError{"expected colon after object key", 0}}, - }}, -} - -func TestDecodeInStream(t *testing.T) { - - for ci, tcase := range tokenStreamCases { - - dec := NewDecoder(strings.NewReader(tcase.json)) - for i, etk := range tcase.expTokens { - - var tk interface{} - var err error - - if dt, ok := etk.(decodeThis); ok { - etk = dt.v - err = dec.Decode(&tk) - } else { - tk, err = dec.Token() - } - if experr, ok := etk.(error); ok { - if err == nil || err.Error() != experr.Error() { - t.Errorf("case %v: Expected error %v in %q, but was %v", ci, experr, tcase.json, err) - } - break - } else if err == io.EOF { - t.Errorf("case %v: Unexpected EOF in %q", ci, tcase.json) - break - } else if err != nil { - t.Errorf("case %v: Unexpected error '%v' in %q", ci, err, tcase.json) - break - } - if !reflect.DeepEqual(tk, etk) { - t.Errorf(`case %v: %q @ %v expected %T(%v) was %T(%v)`, ci, tcase.json, i, etk, etk, tk, tk) - break - } - } - } - -} - -// Test from golang.org/issue/11893 -func TestHTTPDecoding(t *testing.T) { - const raw = `{ "foo": "bar" }` - - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(raw)) - })) - defer ts.Close() - res, err := http.Get(ts.URL) - if err != nil { - log.Fatalf("GET failed: %v", err) - } - defer res.Body.Close() - - foo := struct { - Foo string `json:"foo"` - }{} - - d := NewDecoder(res.Body) - err = d.Decode(&foo) - if err != nil { - t.Fatalf("Decode: %v", err) - } - if foo.Foo != "bar" { - t.Errorf("decoded %q; want \"bar\"", foo.Foo) - } - - // make sure we get the EOF the second time - err = d.Decode(&foo) - if err != io.EOF { - t.Errorf("err = %v; want io.EOF", err) - } -} diff --git a/vendor/gopkg.in/square/go-jose.v2/json/tagkey_test.go b/vendor/gopkg.in/square/go-jose.v2/json/tagkey_test.go deleted file mode 100644 index 85bb4ba83..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/json/tagkey_test.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "testing" -) - -type basicLatin2xTag struct { - V string `json:"$%-/"` -} - -type basicLatin3xTag struct { - V string `json:"0123456789"` -} - -type basicLatin4xTag struct { - V string `json:"ABCDEFGHIJKLMO"` -} - -type basicLatin5xTag struct { - V string `json:"PQRSTUVWXYZ_"` -} - -type basicLatin6xTag struct { - V string `json:"abcdefghijklmno"` -} - -type basicLatin7xTag struct { - V string `json:"pqrstuvwxyz"` -} - -type miscPlaneTag struct { - V string `json:"色は匂へど"` -} - -type percentSlashTag struct { - V string `json:"text/html%"` // https://golang.org/issue/2718 -} - -type punctuationTag struct { - V string `json:"!#$%&()*+-./:<=>?@[]^_{|}~"` // https://golang.org/issue/3546 -} - -type emptyTag struct { - W string -} - -type misnamedTag struct { - X string `jsom:"Misnamed"` -} - -type badFormatTag struct { - Y string `:"BadFormat"` -} - -type badCodeTag struct { - Z string `json:" !\"#&'()*+,."` -} - -type spaceTag struct { - Q string `json:"With space"` -} - -type unicodeTag struct { - W string `json:"Ελλάδα"` -} - -var structTagObjectKeyTests = []struct { - raw interface{} - value string - key string -}{ - {basicLatin2xTag{"2x"}, "2x", "$%-/"}, - {basicLatin3xTag{"3x"}, "3x", "0123456789"}, - {basicLatin4xTag{"4x"}, "4x", "ABCDEFGHIJKLMO"}, - {basicLatin5xTag{"5x"}, "5x", "PQRSTUVWXYZ_"}, - {basicLatin6xTag{"6x"}, "6x", "abcdefghijklmno"}, - {basicLatin7xTag{"7x"}, "7x", "pqrstuvwxyz"}, - {miscPlaneTag{"いろはにほへと"}, "いろはにほへと", "色は匂へど"}, - {emptyTag{"Pour Moi"}, "Pour Moi", "W"}, - {misnamedTag{"Animal Kingdom"}, "Animal Kingdom", "X"}, - {badFormatTag{"Orfevre"}, "Orfevre", "Y"}, - {badCodeTag{"Reliable Man"}, "Reliable Man", "Z"}, - {percentSlashTag{"brut"}, "brut", "text/html%"}, - {punctuationTag{"Union Rags"}, "Union Rags", "!#$%&()*+-./:<=>?@[]^_{|}~"}, - {spaceTag{"Perreddu"}, "Perreddu", "With space"}, - {unicodeTag{"Loukanikos"}, "Loukanikos", "Ελλάδα"}, -} - -func TestStructTagObjectKey(t *testing.T) { - for _, tt := range structTagObjectKeyTests { - b, err := Marshal(tt.raw) - if err != nil { - t.Fatalf("Marshal(%#q) failed: %v", tt.raw, err) - } - var f interface{} - err = Unmarshal(b, &f) - if err != nil { - t.Fatalf("Unmarshal(%#q) failed: %v", b, err) - } - for i, v := range f.(map[string]interface{}) { - switch i { - case tt.key: - if s, ok := v.(string); !ok || s != tt.value { - t.Fatalf("Unexpected value: %#q, want %v", s, tt.value) - } - default: - t.Fatalf("Unexpected key: %#q, from %#q", i, b) - } - } - } -} diff --git a/vendor/gopkg.in/square/go-jose.v2/json/tags_test.go b/vendor/gopkg.in/square/go-jose.v2/json/tags_test.go deleted file mode 100644 index 91fb18831..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/json/tags_test.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package json - -import ( - "testing" -) - -func TestTagParsing(t *testing.T) { - name, opts := parseTag("field,foobar,foo") - if name != "field" { - t.Fatalf("name = %q, want field", name) - } - for _, tt := range []struct { - opt string - want bool - }{ - {"foobar", true}, - {"foo", true}, - {"bar", false}, - } { - if opts.Contains(tt.opt) != tt.want { - t.Errorf("Contains(%q) = %v", tt.opt, !tt.want) - } - } -} diff --git a/vendor/gopkg.in/square/go-jose.v2/jwe_test.go b/vendor/gopkg.in/square/go-jose.v2/jwe_test.go deleted file mode 100644 index dc772af67..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/jwe_test.go +++ /dev/null @@ -1,543 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jose - -import ( - "bytes" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rsa" - "crypto/x509" - "math/big" - "testing" -) - -func TestCompactParseJWE(t *testing.T) { - // Should parse - msg := "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.dGVzdA.dGVzdA.dGVzdA.dGVzdA" - _, err := ParseEncrypted(msg) - if err != nil { - t.Error("Unable to parse valid message:", err) - } - - // Messages that should fail to parse - failures := []string{ - // Too many parts - "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.dGVzdA.dGVzdA.dGVzdA.dGVzdA.dGVzdA", - // Not enough parts - "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.dGVzdA.dGVzdA.dGVzdA", - // Invalid encrypted key - "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.//////.dGVzdA.dGVzdA.dGVzdA", - // Invalid IV - "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.dGVzdA.//////.dGVzdA.dGVzdA", - // Invalid ciphertext - "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.dGVzdA.dGVzdA.//////.dGVzdA", - // Invalid tag - "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.dGVzdA.dGVzdA.dGVzdA.//////", - // Invalid header - "W10.dGVzdA.dGVzdA.dGVzdA.dGVzdA", - // Invalid header - "######.dGVzdA.dGVzdA.dGVzdA.dGVzdA", - // Missing alc/enc params - "e30.dGVzdA.dGVzdA.dGVzdA.dGVzdA", - } - - for _, msg := range failures { - _, err = ParseEncrypted(msg) - if err == nil { - t.Error("Able to parse invalid message", msg) - } - } -} - -func TestFullParseJWE(t *testing.T) { - // Messages that should succeed to parse - successes := []string{ - // Flattened serialization, single recipient - "{\"protected\":\"eyJhbGciOiJYWVoiLCJlbmMiOiJYWVoifQo\",\"encrypted_key\":\"QUJD\",\"iv\":\"QUJD\",\"ciphertext\":\"QUJD\",\"tag\":\"QUJD\"}", - // Unflattened serialization, single recipient - "{\"protected\":\"\",\"unprotected\":{\"enc\":\"XYZ\"},\"recipients\":[{\"header\":{\"alg\":\"XYZ\"},\"encrypted_key\":\"QUJD\"}],\"iv\":\"QUJD\",\"ciphertext\":\"QUJD\",\"tag\":\"QUJD\"}", - } - - for i := range successes { - _, err := ParseEncrypted(successes[i]) - if err != nil { - t.Error("Unble to parse valid message", err, successes[i]) - } - } - - // Messages that should fail to parse - failures := []string{ - // Empty - "{}", - // Invalid JSON - "{XX", - // Invalid protected header - "{\"protected\":\"###\"}", - // Invalid protected header - "{\"protected\":\"e1gK\"}", - // Invalid encrypted key - "{\"protected\":\"e30\",\"encrypted_key\":\"###\"}", - // Invalid IV - "{\"protected\":\"e30\",\"encrypted_key\":\"QUJD\",\"iv\":\"###\"}", - // Invalid ciphertext - "{\"protected\":\"e30\",\"encrypted_key\":\"QUJD\",\"iv\":\"QUJD\",\"ciphertext\":\"###\"}", - // Invalid tag - "{\"protected\":\"e30\",\"encrypted_key\":\"QUJD\",\"iv\":\"QUJD\",\"ciphertext\":\"QUJD\",\"tag\":\"###\"}", - // Invalid AAD - "{\"protected\":\"e30\",\"encrypted_key\":\"QUJD\",\"iv\":\"QUJD\",\"ciphertext\":\"QUJD\",\"tag\":\"QUJD\",\"aad\":\"###\"}", - // Missing alg/enc headers - "{\"protected\":\"e30\",\"encrypted_key\":\"QUJD\",\"iv\":\"QUJD\",\"ciphertext\":\"QUJD\",\"tag\":\"QUJD\"}", - // Missing enc header - "{\"protected\":\"eyJhbGciOiJYWVoifQ\",\"encrypted_key\":\"QUJD\",\"iv\":\"QUJD\",\"ciphertext\":\"QUJD\",\"tag\":\"QUJD\"}", - // Missing alg header - "{\"protected\":\"eyJlbmMiOiJYWVoifQ\",\"encrypted_key\":\"QUJD\",\"iv\":\"QUJD\",\"ciphertext\":\"QUJD\",\"tag\":\"QUJD\"}", - // Unflattened serialization, single recipient, invalid encrypted_key - "{\"protected\":\"\",\"recipients\":[{\"header\":{\"alg\":\"XYZ\", \"enc\":\"XYZ\"},\"encrypted_key\":\"###\"}],\"iv\":\"QUJD\",\"ciphertext\":\"QUJD\",\"tag\":\"QUJD\"}", - // Unflattened serialization, single recipient, missing alg - "{\"protected\":\"eyJhbGciOiJYWVoifQ\",\"recipients\":[{\"encrypted_key\":\"QUJD\"}],\"iv\":\"QUJD\",\"ciphertext\":\"QUJD\",\"tag\":\"QUJD\"}", - } - - for i := range failures { - _, err := ParseEncrypted(failures[i]) - if err == nil { - t.Error("Able to parse invalid message", err, failures[i]) - } - } -} - -func TestMissingInvalidHeaders(t *testing.T) { - protected := &rawHeader{} - protected.set(headerEncryption, A128GCM) - - obj := &JSONWebEncryption{ - protected: protected, - unprotected: &rawHeader{}, - recipients: []recipientInfo{ - {}, - }, - } - - _, err := obj.Decrypt(nil) - if err != ErrUnsupportedKeyType { - t.Error("should detect invalid key") - } - - obj.unprotected.set(headerCritical, []string{"1", "2"}) - - _, err = obj.Decrypt(nil) - if err == nil { - t.Error("should reject message with crit header") - } - - obj.unprotected.set(headerCritical, nil) - obj.protected = &rawHeader{} - obj.protected.set(headerAlgorithm, RSA1_5) - - _, err = obj.Decrypt(rsaTestKey) - if err == nil || err == ErrCryptoFailure { - t.Error("should detect missing enc header") - } -} - -func TestRejectUnprotectedJWENonce(t *testing.T) { - // No need to test compact, since that's always protected - - // Flattened JSON - input := `{ - "header": { - "alg": "XYZ", "enc": "XYZ", - "nonce": "should-cause-an-error" - }, - "encrypted_key": "does-not-matter", - "aad": "does-not-matter", - "iv": "does-not-matter", - "ciphertext": "does-not-matter", - "tag": "does-not-matter" - }` - _, err := ParseEncrypted(input) - if err == nil { - t.Error("JWE with an unprotected nonce parsed as valid.") - } else if err.Error() != "square/go-jose: Nonce parameter included in unprotected header" { - t.Errorf("Improper error for unprotected nonce: %v", err) - } - - input = `{ - "unprotected": { - "alg": "XYZ", "enc": "XYZ", - "nonce": "should-cause-an-error" - }, - "encrypted_key": "does-not-matter", - "aad": "does-not-matter", - "iv": "does-not-matter", - "ciphertext": "does-not-matter", - "tag": "does-not-matter" - }` - _, err = ParseEncrypted(input) - if err == nil { - t.Error("JWE with an unprotected nonce parsed as valid.") - } else if err.Error() != "square/go-jose: Nonce parameter included in unprotected header" { - t.Errorf("Improper error for unprotected nonce: %v", err) - } - - // Full JSON - input = `{ - "header": { "alg": "XYZ", "enc": "XYZ" }, - "aad": "does-not-matter", - "iv": "does-not-matter", - "ciphertext": "does-not-matter", - "tag": "does-not-matter", - "recipients": [{ - "header": { "nonce": "should-cause-an-error" }, - "encrypted_key": "does-not-matter" - }] - }` - _, err = ParseEncrypted(input) - if err == nil { - t.Error("JWS with an unprotected nonce parsed as valid.") - } else if err.Error() != "square/go-jose: Nonce parameter included in unprotected header" { - t.Errorf("Improper error for unprotected nonce: %v", err) - } -} - -func TestCompactSerialize(t *testing.T) { - // Compact serialization must fail if we have unprotected headers - obj := &JSONWebEncryption{ - unprotected: &rawHeader{}, - } - obj.unprotected.set(headerAlgorithm, "XYZ") - - _, err := obj.CompactSerialize() - if err == nil { - t.Error("Object with unprotected headers can't be compact serialized") - } -} - -func TestVectorsJWE(t *testing.T) { - plaintext := []byte("The true sign of intelligence is not knowledge but imagination.") - - publicKey := &rsa.PublicKey{ - N: fromBase64Int(` - oahUIoWw0K0usKNuOR6H4wkf4oBUXHTxRvgb48E-BVvxkeDNjbC4he8rUW - cJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3S - psk_ZkoFnilakGygTwpZ3uesH-PFABNIUYpOiN15dsQRkgr0vEhxN92i2a - sbOenSZeyaxziK72UwxrrKoExv6kc5twXTq4h-QChLOln0_mtUZwfsRaMS - tPs6mS6XrgxnxbWhojf663tuEQueGC-FCMfra36C9knDFGzKsNa7LZK2dj - YgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm-L5StowjzGy-_bq6Gw`), - E: 65537, - } - - expectedCompact := stripWhitespace(` - eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.ROQCfge4JPm_ - yACxv1C1NSXmwNbL6kvmCuyxBRGpW57DvlwByjyjsb6g8m7wtLMqKEyhFCn - tV7sjippEePIlKln6BvVnz5ZLXHNYQgmubuNq8MC0KTwcaGJ_C0z_T8j4PZ - a1nfpbhSe-ePYaALrf_nIsSRKu7cWsrwOSlaRPecRnYeDd_ytAxEQWYEKFi - Pszc70fP9geZOB_09y9jq0vaOF0jGmpIAmgk71lCcUpSdrhNokTKo5y8MH8 - 3NcbIvmuZ51cjXQj1f0_AwM9RW3oCh2Hu0z0C5l4BujZVsDuGgMsGZsjUhS - RZsAQSXHCAmlJ2NlnN60U7y4SPJhKv5tKYw.48V1_ALb6US04U3b.5eym8T - W_c8SuK0ltJ3rpYIzOeDQz7TALvtu6UG9oMo4vpzs9tX_EFShS8iB7j6jiS - diwkIr3ajwQzaBtQD_A.XFBoMYUZodetZdvTiFvSkQ`) - - expectedFull := stripWhitespace(` - { "protected":"eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ", - "encrypted_key": - "ROQCfge4JPm_yACxv1C1NSXmwNbL6kvmCuyxBRGpW57DvlwByjyjsb - 6g8m7wtLMqKEyhFCntV7sjippEePIlKln6BvVnz5ZLXHNYQgmubuNq - 8MC0KTwcaGJ_C0z_T8j4PZa1nfpbhSe-ePYaALrf_nIsSRKu7cWsrw - OSlaRPecRnYeDd_ytAxEQWYEKFiPszc70fP9geZOB_09y9jq0vaOF0 - jGmpIAmgk71lCcUpSdrhNokTKo5y8MH83NcbIvmuZ51cjXQj1f0_Aw - M9RW3oCh2Hu0z0C5l4BujZVsDuGgMsGZsjUhSRZsAQSXHCAmlJ2Nln - N60U7y4SPJhKv5tKYw", - "iv": "48V1_ALb6US04U3b", - "ciphertext": - "5eym8TW_c8SuK0ltJ3rpYIzOeDQz7TALvtu6UG9oMo4vpzs9tX_EFS - hS8iB7j6jiSdiwkIr3ajwQzaBtQD_A", - "tag":"XFBoMYUZodetZdvTiFvSkQ" }`) - - // Mock random reader - randReader = bytes.NewReader([]byte{ - // Encryption key - 177, 161, 244, 128, 84, 143, 225, 115, 63, 180, 3, 255, 107, 154, - 212, 246, 138, 7, 110, 91, 112, 46, 34, 105, 47, 130, 203, 46, 122, - 234, 64, 252, - // Randomness for RSA-OAEP - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - // Initialization vector - 227, 197, 117, 252, 2, 219, 233, 68, 180, 225, 77, 219}) - defer resetRandReader() - - // Encrypt with a dummy key - encrypter, err := NewEncrypter(A256GCM, Recipient{Algorithm: RSA_OAEP, Key: publicKey}, nil) - if err != nil { - panic(err) - } - - object, err := encrypter.Encrypt(plaintext) - if err != nil { - panic(err) - } - - serialized, err := object.CompactSerialize() - if serialized != expectedCompact { - t.Error("Compact serialization is not what we expected", serialized, expectedCompact) - } - - serialized = object.FullSerialize() - if serialized != expectedFull { - t.Error("Full serialization is not what we expected") - } -} - -func TestVectorsJWECorrupt(t *testing.T) { - priv := &rsa.PrivateKey{ - PublicKey: rsa.PublicKey{ - N: fromHexInt(` - a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8 - ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0c - bc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bd - bf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93 - ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb`), - E: 65537, - }, - D: fromHexInt(` - 53339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf1195 - 17ef4f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d - 4ac4d1812b8b9fa5af0e7f55fe7304df41570926f3311f15c4d6 - 5a732c483116ee3d3d2d0af3549ad9bf7cbfb78ad884f84d5beb - 04724dc7369b31def37d0cf539e9cfcdd3de653729ead5d1`), - Primes: []*big.Int{ - fromHexInt(` - d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262 - 864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c - 2f26a471dcad212eac7ca39d`), - fromHexInt(` - cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb3 - 3d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af - 72bfe9a030e860b0288b5d77`), - }, - } - - corruptCiphertext := stripWhitespace(` - eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.NFl09dehy - IR2Oh5iSsvEa82Ps7DLjRHeo0RnuTuSR45OsaIP6U8yu7vLlWaZKSZMy - B2qRBSujf-5XIRoNhtyIyjk81eJRXGa_Bxaor1XBCMyyhGchW2H2P71f - PhDO6ufSC7kV4bNqgHR-4ziS7KXwzN83_5kogXqxUpymUoJDNc.tk-GT - W_VVhiTIKFF.D_BE6ImZUl9F.52a-zFnRb3YQwIC7UrhVyQ`) - - corruptAuthtag := stripWhitespace(` - eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.NFl09dehy - IR2Oh5iSsvEa82Ps7DLjRHeo0RnuTuSR45OsaIP6U8yu7vLlWaZKSZMy - B2qRBSujf-5XIRoNhtyIyjk81eJRXGa_Bxaor1XBCMyyhGchW2H2P71f - PhDO6ufSC7kV4bNqgHR-4ziS7KNwzN83_5kogXqxUpymUoJDNc.tk-GT - W_VVhiTIKFF.D_BE6ImZUl9F.52a-zFnRb3YQwiC7UrhVyQ`) - - msg, _ := ParseEncrypted(corruptCiphertext) - _, err := msg.Decrypt(priv) - if err != ErrCryptoFailure { - t.Error("should detect corrupt ciphertext") - } - - msg, _ = ParseEncrypted(corruptAuthtag) - _, err = msg.Decrypt(priv) - if err != ErrCryptoFailure { - t.Error("should detect corrupt auth tag") - } -} - -// Test vectors generated with nimbus-jose-jwt -func TestSampleNimbusJWEMessagesRSA(t *testing.T) { - rsaPrivateKey, err := x509.ParsePKCS8PrivateKey(fromBase64Bytes(` - MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCNRCEmf5PlbXKuT4uwnb - wGKvFrtpi+bDYxOZxxqxdVkZM/bYATAnD1fg9pNvLMKeF+MWJ9kPIMmDgOh9RdnRdLvQGb - BzhLmxwhhcua2QYiHEZizXmiaXvNP12bzEBhebdX7ObW8izMVW0p0lqHPNzkK3K75B0Sxo - FMVKkZ7KtBHgepBT5yPhPPcNe5lXQeTne5bo3I60DRcN9jTBgMJOXdq0I9o4y6ZmoXdNTm - 0EyLzn9/EYiHqBxtKFh791EHR7wYgyi/t+nOKr4sO74NbEByP0mHDil+mPvZSzFW4l7fPx - OclRZvpRIKIub2TroZA9s2WsshGf79eqqXYbBB9NNRAgMBAAECggEAIExbZ/nzTplfhwsY - 3SCzRJW87OuqsJ79JPQPGM4NX7sQ94eJqM7+FKLl0yCFErjgnYGdCyiArvB+oJPdsimgke - h83X0hGeg03lVA3/6OsG3WifCAxulnLN44AM8KST8S9D9t5+cm5vEBLHazzAfWWTS13s+g - 9hH8rf8NSqgZ36EutjKlvLdHx1mWcKX7SREFVHT8FWPAbdhTLEHUjoWHrfSektnczaSHnt - q8fFJy6Ld13QkF1ZJRUhtA24XrD+qLTc+M36IuedjeZaLHFB+KyhYR3YvXEtrbCug7dCRd - uG6uTlDCSaSy7xHeTPolWtWo9F202jal54otxiAJFGUHgQKBgQDRAT0s6YQZUfwE0wluXV - k0JdhDdCo8sC1aMmKlRKWUkBAqrDl7BI3MF56VOr4ybr90buuscshFf9TtrtBOjHSGcfDI - tSKfhhkW5ewQKB0YqyHzoD6UKT0/XAshFY3esc3uCxuJ/6vOiXV0og9o7eFvr51O0TfDFh - mcTvW4wirKlQKBgQCtB7UAu8I9Nn8czkd6oXLDRyTWYviuiqFmxR+PM9klgZtsumkeSxO1 - lkfFoj9+G8nFaqYEBA9sPeNtJVTSROCvj/iQtoqpV2NiI/wWeVszpBwsswx2mlks4LJa8a - Yz9xrsfNoroKYVppefc/MCoSx4M+99RSm3FSpLGZQHAUGyzQKBgQDMQmq4JuuMF1y2lk0E - SESyuz21BqV0tDVOjilsHT+5hmXWXoS6nkO6L2czrrpM7YE82F6JJZBmo7zEIXHBInGLJ3 - XLoYLZ5qNEhqYDUEDHaBCBWZ1vDTKnZlwWFEuXVavNNZvPbUhKTHq25t8qjDki/r09Vykp - BsM2yNBKpbBOVQKBgCJyUVd3CaFUExQyAMrqD0XPCQdhJq7gzGcAQVsp8EXmOoH3zmuIeM - ECzQEMXuWFNLMHm0tbX5Kl83vMHcnKioyI9ewhWxOBYTitf0ceG8j5F97SOl32NmCXzwoJ - 55Oa0xJXfLuIvOe8hZzp4WwZmBfKBxiCR166aPQQgIawelrVAoGAEJsHomfCI4epxH4oMw - qYJMCGy95zloB+2+c86BZCOJAGwnfzbtc2eutWZw61/9sSO8sQCfzA8oX+5HwAgnFVzwW4 - lNMZohppYcpwN9EyjkPaCXuALC7p5rF2o63wY7JLvnjS2aYZliknh2yW6X6fSB0PK0Cpvd - lAIyRw6Kud0zI=`)) - if err != nil { - panic(err) - } - - rsaSampleMessages := []string{ - "eyJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiUlNBMV81In0.EW0KOhHeoAxTBnLjYhh2T6HjwI-srNs6RpcSdZvE-GJ5iww3EYWBCmeGGj1UVz6OcBfwW3wllZ6GPOHU-hxVQH5KYpVOjkmrFIYU6-8BHhxBP_PjSJEBCZzjOgsCm9Th4-zmlO7UWTdK_UtwE7nk4X-kkmEy-aZBCShA8nFe2MVvqD5F7nvEWNFBOHh8ae_juo-kvycoIzvxLV9g1B0Zn8K9FAlu8YF1KiL5NFekn76f3jvAwlExuRbFPUx4gJN6CeBDK_D57ABsY2aBVDSiQceuYZxvCIAajqSS6dMT382FNJzAiQhToOpo_1w5FnnBjzJLLEKDk_I-Eo2YCWxxsQ.5mCMuxJqLRuPXGAr.Ghe4INeBhP3MDWGvyNko7qanKdZIzKjfeiU.ja3UlVWJXKNFJ-rZsJWycw", - "eyJlbmMiOiJBMTkyR0NNIiwiYWxnIjoiUlNBMV81In0.JsJeYoP0St1bRYNUaAmA34DAA27usE7RNuC2grGikBRmh1xrwUOpnEIXXpwr7fjVmNi52zzWkNHC8JkkRTrLcCh2VXvnOnarpH8DCr9qM6440bSrahzbxIvDds8z8q0wT1W4kjVnq1mGwGxg8RQNBWTV6Sp2FLQkZyjzt_aXsgYzr3zEmLZxB-d41lBS81Mguk_hdFJIg_WO4ao54lozvxkCn_uMiIZ8eLb8qHy0h-N21tiHGCaiC2vV8KXomwoqbJ0SXrEH4r9_R2J844H80TBZdbvNBd8whvoQNHvOX659LNs9EQ9xxvHU2kqGZekXBu7sDXXTjctMkMITobGSzw.1v5govaDvanP3LGp.llwYNBDrD7MwVLaFHesljlratfmndWs4XPQ.ZGT1zk9_yIKi2GzW6CuAyA", - "eyJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBMV81In0.fBv3fA3TMS3ML8vlsCuvwdsKvB0ym8R30jJrlOiqkWKk7WVUkjDInFzr1zw3Owla6c5BqOJNoACXt4IWbkLbkoWV3tweXlWwpafuaWPkjLOUH_K31rS2fCX5x-MTj8_hScquVQXpbz3vk2EfulRmGXZc_8JU2NqQCAsYy3a28houqP3rDe5jEAvZS2SOFvJkKW--f5S-z39t1D7fNz1N8Btd9SmXWQzjbul5YNxI9ctqxhJpkKYpxOLlvrzdA6YdJjOlDx3n6S-HnSZGM6kQd_xKtAf8l1EGwhQmhbXhMhjVxMvGwE5BX7PAb8Ccde5bzOCJx-PVbVetuLb169ZYqQ._jiZbOPRR82FEWMZ.88j68LI-K2KT6FMBEdlz6amG5nvaJU8a-90.EnEbUTJsWNqJYKzfO0x4Yw", - "eyJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiUlNBMV81In0.bN6FN0qmGxhkESiVukrCaDVG3woL0xE-0bHN_Mu0WZXTQWbzzT-7jOvaN1xhGK8nzi8qpCSRgE5onONNB9i8OnJm3MMIxF7bUUEAXO9SUAFn2v--wNc4drPc5OjIu0RiJrDVDkkGjNrBDIuBaEQcke7A0v91PH58dXE7o4TLPzC8UJmRtXWhUSwjXVF3-UmYRMht2rjHJlvRbtm6Tu2LMBIopRL0zj6tlPP4Dm7I7sz9OEB3VahYAhpXnFR7D_f8RjLSXQmBvB1FiI5l_vMz2NFt2hYUmQF3EJMLIEdHvvPp3iHDGiXC1obJrDID_CCf3qs9UY7DMYL622KLvP2NIg.qb72oxECzxd_aNuHVR0aNg.Gwet9Ms8hB8rKEb0h4RGdFNRq97Qs2LQaJM0HWrCqoI.03ljVThOFvgXzMmQJ79VjQ", - "eyJlbmMiOiJBMTkyQ0JDLUhTMzg0IiwiYWxnIjoiUlNBMV81In0.ZbEOP6rqdiIP4g7Nl1PL5gwhgDwv9RinyiUQxZXPOmD7kwEZrZ093dJnhqI9kEd3QGFlHDpB7HgNz53d27z2zmEj1-27v6miizq6tH4sN2MoeZLwSyk16O1_n3bVdDmROawsTYYFJfHsuLwyVJxPd37duIYnbUCFO9J8lLIv-2VI50KJ1t47YfE4P-Wt9jVzxP2CVUQaJwTlcwfiDLJTagYmfyrDjf525WlQFlgfJGqsJKp8BX9gmKvAo-1iCBAM8VpEjS0u0_hW9VSye36yh8BthVV-VJkhJ-0tMpto3bbBmj7M25Xf4gbTrrVU7Nz6wb18YZuhHZWmj2Y2nHV6Jg.AjnS44blTrIIfFlqVw0_Mg.muCRgaEXNKKpW8rMfW7jf7Zpn3VwSYDz-JTRg16jZxY.qjc9OGlMaaWKDWQSIwVpR4K556Pp6SF9", - "eyJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiYWxnIjoiUlNBMV81In0.c7_F1lMlRHQQE3WbKmtHBYTosdZrG9hPfs-F9gNQYet61zKG8NXVkSy0Zf2UFHt0vhcO8hP2qrqOFsy7vmRj20xnGHQ2EE29HH6hwX5bx1Jj3uE5WT9Gvh0OewpvF9VubbwWTIObBpdEG7XdJsMAQlIxtXUmQYAtLTWcy2ZJipyJtVlWQLaPuE8BKfZH-XAsp2CpQNiRPI8Ftza3EAspiyRfVQbjKt7nF8nuZ2sESjt7Y50q4CSiiCuGT28T3diMN0_rWrH-I-xx7OQvJlrQaNGglGtu3jKUcrJDcvxW2e1OxriaTeuQ848ayuRvGUNeSv6WoVYmkiK1x_gNwUAAbw.7XtSqHJA7kjt6JrfxJMwiA.Yvi4qukAbdT-k-Fd2s4G8xzL4VFxaFC0ZIzgFDAI6n0.JSWPJ-HjOE3SK9Lm0yHclmjS7Z1ahtQga9FHGCWVRcc", - "eyJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.SYVxJbCnJ_tcR13LJpaqHQj-nGNkMxre4A1FmnUdxnvzeJwuvyrLiUdRsZR1IkP4fqLtDON2mumx39QeJQf0WIObPBYlIxycRLkwxDHRVlyTmPvdZHAxN26jPrk09wa5SgK1UF1W1VSQIPm-Tek8jNAmarF1Yxzxl-t54wZFlQiHP4TuaczugO5f-J4nlWenfla2mU1snDgdUMlEZGOAQ_gTEtwSgd1MqXmK_7LZBkoDqqoCujMZhziafJPXPDaUUqBLW3hHkkDA7GpVec3XcTtNUWQJqOpMyQhqo1KQMc8jg3fuirILp-hjvvNVtBnCRBvbrKUCPzu2_yH3HM_agA.2VsdijtonAxShNIW.QzzB3P9CxYP3foNKN0Ma1Z9tMwijAlkWo08.ZdQkIPDY_M-hxqi5fD4NGw", - "eyJlbmMiOiJBMTkyR0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.Z2oTJXXib1u-S38Vn3DRKE3JnhnwgUa92UhsefzY2Wpdn0dmxMfYt9iRoJGFfSAcA97MOfjyvXVRCKWXGrG5AZCMAXEqU8SNQwKPRjlcqojcVzQyMucXI0ikLC4mUgeRlfKTwsBicq6JZZylzRoLGGSNJQbni3_BLsf7H3Qor0BYg0FPCLG9Z2OVvrFzvjTLmZtV6gFlVrMHBxJub_aUet9gAkxiu1Wx_Kx46TlLX2tkumXIpTGlzX6pef6jLeZ5EIg_K-Uz4tkWgWQIEkLD7qmTyk5pAGmzukHa_08jIh5-U-Sd8XGZdx4J1pVPJ5CPg0qDJGZ_cfgkgpWbP_wB6A.4qgKfokK1EwYxz20._Md82bv_KH2Vru0Ue2Eb6oAqHP2xBBP5jF8.WFRojvQpD5VmZlOr_dN0rQ", - "eyJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.JzCUgJcBJmBgByp4PBAABUfhezPvndxBIVzaoZ96DAS0HPni0OjMbsOGsz6JwNsiTr1gSn_S6R1WpZM8GJc9R2z0EKKVP67TR62ZSG0MEWyLpHmG_4ug0fAp1HWWMa9bT4ApSaOLgwlpVAb_-BPZZgIu6c8cREuMon6UBHDqW1euTBbzk8zix3-FTZ6p5b_3soDL1wXfRiRBEsxxUGMnpryx1OFb8Od0JdyGF0GgfLt6OoaujDJpo-XtLRawu1Xlg6GqRs0NQwSHZ5jXgQ6-zgCufXonAmYTiIyBXY2no9XmECTexjwrS_05nA7H-UyIZEBOCp3Yhz2zxrt5j_0pvQ.SJR-ghhaUKP4zXtZ.muiuzLfZA0y0BDNsroGTw2r2-l73SLf9lK8.XFMH1oHr1G6ByP3dWSUUPA", - "eyJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiUlNBLU9BRVAifQ.U946MVfIm4Dpk_86HrnIA-QXyiUu0LZ67PL93CMLmEtJemMNDqmRd9fXyenCIhAC7jPIV1aaqW7gS194xyrrnUpBoJBdbegiPqOfquy493Iq_GQ8OXnFxFibPNQ6rU0l8BwIfh28ei_VIF2jqN6bhxFURCVW7fG6n6zkCCuEyc7IcxWafSHjH2FNttREuVj-jS-4LYDZsFzSKbpqoYF6mHt8H3btNEZDTSmy_6v0fV1foNtUKNfWopCp-iE4hNh4EzJfDuU8eXLhDb03aoOockrUiUCh-E0tQx9su4rOv-mDEOHHAQK7swm5etxoa7__9PC3Hg97_p4GM9gC9ykNgw.pnXwvoSPi0kMQP54of-HGg.RPJt1CMWs1nyotx1fOIfZ8760mYQ69HlyDp3XmdVsZ8.Yxw2iPVWaBROFE_FGbvodA", - "eyJlbmMiOiJBMTkyQ0JDLUhTMzg0IiwiYWxnIjoiUlNBLU9BRVAifQ.eKEOIJUJpXmO_ghH_nGCJmoEspqKyiy3D5l0P8lKutlo8AuYHPQlgOsaFYnDkypyUVWd9zi-JaQuCeo7dzoBiS1L71nAZo-SUoN0anQBkVuyuRjr-deJMhPPfq1H86tTk-4rKzPr1Ivd2RGXMtWsrUpNGk81r1v8DdMntLE7UxZQqT34ONuZg1IXnD_U6di7k07unI29zuU1ySeUr6w1YPw5aUDErMlpZcEJWrgOEYWaS2nuC8sWGlPGYEjqkACMFGn-y40UoS_JatNZO6gHK3SKZnXD7vN5NAaMo_mFNbh50e1t_zO8DaUdLtXPOBLcx_ULoteNd9H8HyDGWqwAPw.0xmtzJfeVMoIT1Cp68QrXA.841l1aA4c3uvSYfw6l180gn5JZQjL53WQ5fr8ejtvoI.lojzeWql_3gDq-AoaIbl_aGQRH_54w_f", - "eyJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiYWxnIjoiUlNBLU9BRVAifQ.D0QkvIXR1TL7dIHWuPNMybmmD8UPyQd1bRKjRDNbA2HmKGpamCtcJmpNB_EetNFe-LDmhe44BYI_XN2wIBbYURKgDK_WG9BH0LQw_nCVqQ-sKqjtj3yQeytXhLHYTDmiF0TO-uW-RFR7GbPAdARBfuf4zj82r_wDD9sD5WSCGx89iPfozDOYQ_OLwdL2WD99VvDyfwS3ZhxA-9IMSYv5pwqPkxj4C0JdjCqrN0YNrZn_1ORgjtsVmcWXsmusObTozUGA7n5GeVepfZdU1vrMulAwdRYqOYtlqKaOpFowe9xFN3ncBG7wb4f9pmzbS_Dgt-1_Ii_4SEB9GQ4NiuBZ0w.N4AZeCxMGUv52A0UVJsaZw.5eHOGbZdtahnp3l_PDY-YojYib4ft4SRmdsQ2kggrTs.WsmGH8ZDv4ctBFs7qsQvw2obe4dVToRcAQaZ3PYL34E", - "eyJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.fDTxO_ZzZ3Jdrdw-bxvg7u-xWB2q1tp3kI5zH6JfhLUm4h6rt9qDA_wZlRym8-GzEtkUjkTtQGs6HgQx_qlyy8ylCakY5GHsNhCG4m0UNhRiNfcasAs03JSXfON9-tfTJimWD9n4k5OHHhvcrsCW1G3jYeLsK9WHCGRIhNz5ULbo8HBrCTbmZ6bOEQ9mqhdssLpdV24HDpebotf3bgPJqoaTfWU6Uy7tLmPiNuuNRLQ-iTpLyNMTVvGqqZhpcV3lAEN5l77QabI5xLJYucvYjrXQhAEZ7YXO8oRYhGkdG2XXIRcwr87rBeRH-47HAyhZgF_PBPBhhrJNS9UNMqdfBw.FvU4_s7Md6vxnXWd.fw29Q4_gHt4f026DPPV-CNebQ8plJ6IVLX8._apBZrw7WsT8HOmxgCrTwA", - "eyJlbmMiOiJBMTkyR0NNIiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.bYuorK-rHMbO4c2CRWtvyOEaM1EN-o-wLRZ0wFWRX9mCXQ-iTNarZn7ksYM1XnGmZ4u3CSowX1Hpca9Rg72_VJCmKapqCT7r3YfasN4_oeLwuSKI_gT-uVOznod97tn3Gf_EDv0y1V4H0k9BEIFGbajAcG1znTD_ODY3j2KZJxisfrsBoslc6N-HI0kKZMC2hSGuHOcOf8HN1sTE-BLqZCtoj-zxQECJK8Wh14Ih4jzzdmmiu_qmSR780K6su-4PRt3j8uY7oCiLBfwpCsCmhJgp8rKd91zoedZmamfvX38mJIfE52j4fG6HmIYw9Ov814fk9OffV6tzixjcg54Q2g.yeVJz4aSh2s-GUr9.TBzzWP5llEiDdugpP2SmPf2U4MEGG9EoPWk.g25UoWpsBaOd45J__FX7mA", - "eyJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.h9tFtmh762JuffBxlSQbJujCyI4Zs9yc3IOb1yR8g65W4ZHosIvzVGHWbShj4EY9MNrz-RbKtHfqQGGzDeo3Xb4-HcQ2ZDHyWoUg7VfA8JafJ5zIKL1npz8eUExOVMLsAaRfHg8qNfczodg3egoSmX5Q-nrx4DeidDSXYZaZjV0C72stLTPcuQ7XPV7z1tvERAkqpvcsRmJn_PiRNxIbAgoyHMJ4Gijuzt1bWZwezlxYmw0TEuwCTVC2fl9NJTZyxOntS1Lcm-WQGlPkVYeVgYTOQXLlp7tF9t-aAvYpth2oWGT6Y-hbPrjx_19WaKD0XyWCR46V32DlXEVDP3Xl2A.NUgfnzQyEaJjzt9r.k2To43B2YVWMeR-w3n4Pr2b5wYq2o87giHk.X8_QYCg0IGnn1pJqe8p_KA", - "eyJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.EDq6cNP6Yp1sds5HZ4CkXYp7bs9plIYVZScKvuyxUy0H1VyBC_YWg0HvndPNb-vwh1LA6KMxRazlOwJ9iPR9YzHnYmGgPM3Je_ZzBfiPlRfq6hQBpGnNaypBI1XZ2tyFBhulsVLqyJe2SmM2Ud00kasOdMYgcN8FNFzq7IOE7E0FUQkIwLdUL1nrzepiYDp-5bGkxWRcL02cYfdqdm00G4m0GkUxAmdxa3oPNxZlt2NeBI_UVWQSgJE-DJVJQkDcyA0id27TV2RCDnmujYauNT_wYlyb0bFDx3pYzzNXfAXd4wHZxt75QaLZ5APJ0EVfiXJ0qki6kT-GRVmOimUbQA.vTULZL7LvS0WD8kR8ZUtLg.mb2f0StEmmkuuvsyz8UplMvF58FtZzlu8eEwzvPUvN0.hbhveEN40V-pgG2hSVgyKg", - "eyJlbmMiOiJBMTkyQ0JDLUhTMzg0IiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.DuYk92p7u-YIN-JKn-XThmlVcnhU9x5TieQ2uhsLQVNlo0iWC9JJPP6bT6aI6u_1BIS3yE8_tSGGL7eM-zyEk6LuTqSWFRaZcZC06d0MnS9eYZcw1T2D17fL-ki-NtCaTahJD7jE2s0HevRVW49YtL-_V8whnO_EyVjvXIAQlPYqhH_o-0Nzcpng9ggdAnuF2rY1_6iRPYFJ3BLQvG1oWhyJ9s6SBttlOa0i6mmFCVLHx6sRpdGAB3lbCL3wfmHq4tpIv77gfoYUNP0SNff-zNmBXF_wp3dCntLZFTjbfMpGyHlruF_uoaLqwdjYpUGNUFVUoeSiMnSbMKm9NxiDgQ.6Mdgcqz7bMU1UeoAwFC8pg.W36QWOlBaJezakUX5FMZzbAgeAu_R14AYKZCQmuhguw.5OeyIJ03olxmJft8uBmjuOFQPWNZMYLI", - "eyJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.ECulJArWFsPL2FlpCN0W8E7IseSjJg1cZqE3wz5jk9gvwgNForAUEv5KYZqhNI-p5IxkGV0f8K6Y2X8pWzbLwiPIjZe8_dVqHYJoINxqCSgWLBhz0V36qL9Nc_xARTBk4-ZteIu75NoXVeos9gNvFnkOCj4tm-jGo8z8EFO9XfODgjhiR4xv8VqUtvrkjo9GQConaga5zpV-J4JQlXbdqbDjnuwacnJAxYpFyuemqcgqsl6BnFX3tovGkmSUPqcvF1A6tiHqr-TEmcgVqo5C3xswknRBKTQRM00iAmJ92WlVdkoOCx6E6O7cVHFawZ14BLzWzm66Crb4tv0ucYvk_Q.mxolwUaoj5S5kHCfph0w8g.nFpgYdnYg3blHCCEi2XXQGkkKQBXs2OkZaH11m3PRvk.k8BAVT4EcyrUFVIKr-KOSPbF89xyL0Vri2rFTu2iIWM", - } - - for _, msg := range rsaSampleMessages { - obj, err := ParseEncrypted(msg) - if err != nil { - t.Error("unable to parse message", msg, err) - continue - } - plaintext, err := obj.Decrypt(rsaPrivateKey) - if err != nil { - t.Error("unable to decrypt message", msg, err) - continue - } - if string(plaintext) != "Lorem ipsum dolor sit amet" { - t.Error("plaintext is not what we expected for msg", msg) - } - } -} - -// Test vectors generated with nimbus-jose-jwt -func TestSampleNimbusJWEMessagesAESKW(t *testing.T) { - aesTestKeys := [][]byte{ - fromHexBytes("DF1FA4F36FFA7FC42C81D4B3C033928D"), - fromHexBytes("DF1FA4F36FFA7FC42C81D4B3C033928D95EC9CDC2D82233C"), - fromHexBytes("DF1FA4F36FFA7FC42C81D4B3C033928D95EC9CDC2D82233C333C35BA29044E90"), - } - - aesSampleMessages := [][]string{ - { - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTI4R0NNIiwidGFnIjoib2ZMd2Q5NGloVWFRckJ0T1pQUDdjUSIsImFsZyI6IkExMjhHQ01LVyIsIml2IjoiV2Z3TnN5cjEwWUFjY2p2diJ9.9x3RxdqIS6P9xjh93Eu1bQ.6fs3_fSGt2jull_5.YDlzr6sWACkFg_GU5MEc-ZEWxNLwI_JMKe_jFA.f-pq-V7rlSSg_q2e1gDygw", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTkyR0NNIiwidGFnIjoic2RneXB1ckFjTEFzTmZJU0lkZUNpUSIsImFsZyI6IkExMjhHQ01LVyIsIml2IjoieVFMR0dCdDJFZ0c1THdyViJ9.arslKo4aKlh6f4s0z1_-U-8JbmhAoZHN.Xw2Q-GX98YXwuc4i.halTEWMWAYZbv-qOD52G6bte4x6sxlh1_VpGEA.Z1spn016v58cW6Q2o0Qxag", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMjU2R0NNIiwidGFnIjoicTNzejF5VUlhbVBDYXJfZ05kSVJqQSIsImFsZyI6IkExMjhHQ01LVyIsIml2IjoiM0ZRM0FsLWJWdWhmcEIyQyJ9.dhVipWbzIdsINttuZM4hnjpHvwEHf0VsVrOp4GAg01g.dk7dUyt1Qj13Pipw.5Tt70ONATF0BZAS8dBkYmCV7AQUrfb8qmKNLmw.A6ton9MQjZg0b3C0QcW-hg", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwidGFnIjoiUHNpTGphZnJZNE16UlRmNlBPLTZfdyIsImFsZyI6IkExMjhHQ01LVyIsIml2IjoiSUFPbnd2ODR5YXFEaUxtbSJ9.swf92_LyCvjsvkynHTuMNXRl_MX2keU-fMDWIMezHG4.LOp9SVIXzs4yTnOtMyXZYQ.HUlXrzqJ1qXYl3vUA-ydezCg77WvJNtKdmZ3FPABoZw.8UYl1LOofQLAxHHvWqoTbg", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTkyQ0JDLUhTMzg0IiwidGFnIjoiWGRndHQ5dUVEMVlVeU1rVHl6M3lqZyIsImFsZyI6IkExMjhHQ01LVyIsIml2IjoiWF90V2RhSmh6X3J1SHJvQSJ9.JQ3dS1JSgzIFi5M9ig63FoFU1nHBTmPwXY_ovNE2m1JOSUvHtalmihIuraPDloCf.e920JVryUIWt7zJJQM-www.8DUrl4LmsxIEhRr9RLTHG9tBTOcwXqEbQHAJd_qMHzE.wHinoqGUhL4O7lx125kponpwNtlp8VGJ", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwidGFnIjoicGgyaTdoY0FWNlh3ZkQta1RHYlVXdyIsImFsZyI6IkExMjhHQ01LVyIsIml2IjoiaG41Smk4Wm1rUmRrSUxWVSJ9._bQlJXl22dhsBgYPhkxUyinBNi871teGWbviOueWj2PqG9OPxIc9SDS8a27YLSVDMircd5Q1Df28--vcXIABQA.DssmhrAg6w_f2VDaPpxTbQ.OGclEmqrxwvZqAfn7EgXlIfXgr0wiGvEbZz3zADnqJs.YZeP0uKVEiDl8VyC-s20YN-RbdyGNsbdtoGDP3eMof8", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiQTEyOEtXIn0.TEMcXEoY8WyqGjYs5GZgS-M_Niwu6wDY.i-26KtTt51Td6Iwd.wvhkagvPsLj3QxhPBbfH_th8OqxisUtme2UadQ.vlfvBPv3bw2Zk2H60JVNLQ", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTkyR0NNIiwiYWxnIjoiQTEyOEtXIn0.gPaR6mgQ9TUx05V6DRfgTQeZxl0ZSzBa5uQd-qw6yLs.MojplOD77FkMooS-.2yuD7dKR_C3sFbhgwiBccKKOF8DrSvNiwX7wPQ.qDKUbSvMnJv0qifjpWC14g", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiQTEyOEtXIn0.Fg-dgSkUW1KEaL5YDPoWHNL8fpX1WxWVLA9OOWsjIFhQVDKyUZI7BQ.mjRBpyJTZf7H-quf.YlNHezMadtaSKp23G-ozmYhHOeHwuJnvWGTtGg.YagnR7awBItUlMDo4uklvg", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiQTEyOEtXIn0.x1vYzUE-E2XBWva9OPuwtqfQaf9rlJCIBAyAe6N2q2kWfJrkxGxFsQ.gAwe78dyODFaoP2IOityAA.Yh5YfovkWxGBNAs1sVhvXow_2izHHsBiYEc9JYD6kVg.mio1p3ncp2wLEaEaRa7P0w", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTkyQ0JDLUhTMzg0IiwiYWxnIjoiQTEyOEtXIn0.szGrdnmF7D5put2aRBvSSFfp0vRgkRGYaafijJIqAF6PWd1IxsysZRV8aQkQOW1cB6d0fXsTfYM.Ru25LVOOk4xhaK-cIZ0ThA.pF9Ok5zot7elVqXFW5YYHV8MuF9gVGzpQnG1XDs_g_w.-7la0uwcNPpteev185pMHZjbVDXlrec8", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiYWxnIjoiQTEyOEtXIn0.cz-hRv0xR5CnOcnoRWNK8Q9poyVYzRCVTjfmEXQN6xPOZUkJ3zKNqb8Pir_FS0o2TVvxmIbuxeISeATTR2Ttx_YGCNgMkc93.SF5rEQT94lZR-UORcMKqGw.xphygoU7zE0ZggOczXCi_ytt-Evln8CL-7WLDlWcUHg.5h99r8xCCwP2PgDbZqzCJ13oFfB2vZWetD5qZjmmVho", - }, - { - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTI4R0NNIiwidGFnIjoiVWR5WUVKdEJ5ZTA5dzdjclY0cXI1QSIsImFsZyI6IkExOTJHQ01LVyIsIml2IjoiZlBBV0QwUmdSbHlFdktQcCJ9.P1uTfTuH-imL-NJJMpuTRA.22yqZ1NIfx3KNPgc.hORWZaTSgni1FS-JT90vJly-cU37qTn-tWSqTg.gMN0ufXF92rSXupTtBNkhA", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTkyR0NNIiwidGFnIjoiOU9qX3B2LTJSNW5lZl9YbWVkUWltUSIsImFsZyI6IkExOTJHQ01LVyIsIml2IjoiY3BybGEwYUYzREVQNmFJTSJ9.6NVpAm_APiC7km2v-oNR8g23K9U_kf1-.jIg-p8tNwSvwxch0.1i-GPaxS4qR6Gy4tzeVtSdRFRSKQSMpmn-VhzA.qhFWPqtA6vVPl7OM3DThsA", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMjU2R0NNIiwidGFnIjoiOVc3THg3MVhGQVJCb3NaLVZ5dXc4ZyIsImFsZyI6IkExOTJHQ01LVyIsIml2IjoiZ1N4ZE5heFdBSVBRR0tHYiJ9.3YjPz6dVQwAtCekvtXiHZrooOUlmCsMSvyfwmGwdrOA.hA_C0IDJmGaRzsB0.W4l7OPqpFxiVOZTGfAlRktquyRTo4cEOk9KurQ.l4bGxOkO_ql_jlPo3Oz3TQ", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwidGFnIjoiOHJYbWl2WXFWZjNfbHhhd2NUbHJoUSIsImFsZyI6IkExOTJHQ01LVyIsIml2IjoiVXBWeXprVTNKcjEwYXRqYyJ9.8qft-Q_xqUbo5j_aVrVNHchooeLttR4Kb6j01O8k98M.hXO-5IKBYCL9UdwBFVm0tg.EBM4lCZX_K6tfqYmfoDxVPHcf6cT--AegXTTjfSqsIw.Of8xUvEQSh3xgFT3uENnAg", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTkyQ0JDLUhTMzg0IiwidGFnIjoiVnItSnVaX0tqV2hSWWMzdzFwZ3cwdyIsImFsZyI6IkExOTJHQ01LVyIsIml2IjoiRGg2R3dISVBVS3ljZGNZeCJ9.YSEDjCnGWr_n9H94AvLoRnwm6bdU9w6-Q67k-QQRVcKRd6673pgH9zEF9A9Dt6o1.gcmVN4kxqBuMq6c7GrK3UQ.vWzJb0He6OY1lhYYjYS7CLh55REAAq1O7yNN-ND4R5Q.OD0B6nwyFaDr_92ysDOtlVnJaeoIqhGw", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwidGFnIjoieEtad1BGYURpQ3NqUnBqZUprZHhmZyIsImFsZyI6IkExOTJHQ01LVyIsIml2IjoieTVHRFdteXdkb2R1SDJlYyJ9.AW0gbhWqlptOQ1y9aoNVwrTIIkBfrp33C2OWJsbrDRk6lhxg_IgFhMDTE37moReySGUtttC4CXQD_7etHmd3Hw.OvKXK-aRKlXHOpJQ9ZY_YQ.Ngv7WarDDvR2uBj_DavPAR3DYuIaygvSSdcHrc8-ZqM.MJ6ElitzFCKf_0h5fIJw8uOLC6ps7dKZPozF8juQmUY", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiQTE5MktXIn0.8qu63pppcSvp1vv37WrZ44qcCTg7dQMA.cDp-f8dJTrDEpZW4.H6OBJYs4UvFR_IZHLYQZxB6u9a0wOdAif2LNfQ.1dB-id0UIwRSlmwHx5BJCg", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTkyR0NNIiwiYWxnIjoiQTE5MktXIn0._FdoKQvC8qUs7K0upriEihUwztK8gOwonXpOxdIwrfs.UO38ok8gDdpLVa1T.x1GvHdVCy4fxoQRg-OQK4Ez3jDOvu9gllLPeEA.3dLeZGIprh_nHizOTVi1xw", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiQTE5MktXIn0.uzCJskgSIK6VkjJIu-dQi18biqaY0INc_A1Ehx0oESafgtR99_n4IA.W2eKK8Y14WwTowI_.J2cJC7R6Bz6maR0s1UBMPyRi5BebNUAmof4pvw.-7w6htAlc4iUsOJ6I04rFg", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiQTE5MktXIn0.gImQeQETp_6dfJypFDPLlv7c5pCzuq86U16gzrLiCXth6X9XfxJpvQ.YlC4MxjtLWrsyEvlFhvsqw.Vlpvmg9F3gkz4e1xG01Yl2RXx-jG99rF5UvCxOBXSLc.RZUrU_FoR5bG3M-j3GY0Dw", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTkyQ0JDLUhTMzg0IiwiYWxnIjoiQTE5MktXIn0.T2EfQ6Tu2wJyRMgZzfvBYmQNCCfdMudMrg86ibEMVAOUKJPtR3WMPEb_Syy9p2VjrLKRlv7nebo.GPc8VbarPPRtzIRATB8NsA.ugPCqLvVLwh55bWlwjsFkmWzJ31z5z-wuih2oJqmG_U.m7FY3EjvV6mKosEYJ5cY7ezFoVQoJS8X", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiYWxnIjoiQTE5MktXIn0.OgLMhZ-2ZhslQyHfzOfyC-qmT6bNg9AdpP59B4jtyxWkQu3eW475WCdiAjojjeyBtVRGQ5vOomwaOIFejY_IekzH6I_taii3.U9x44MF6Wyz5TIwIzwhoxQ.vK7yvSF2beKdNxNY_7n4XdF7JluCGZoxdFJyTJVkSmI.bXRlI8KL-g7gpprQxGmXjVYjYghhWJq7mlCfWI8q2uA", - }, - { - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTI4R0NNIiwidGFnIjoiR3BjX3pfbjduZjJVZlEtWGdsaTBaQSIsImFsZyI6IkEyNTZHQ01LVyIsIml2IjoiUk40eUdhOVlvYlFhUmZ1TCJ9.Q4ukD6_hZpmASAVcqWJ9Wg.Zfhny_1WNdlp4fH-.3sekDCjkExQCcv28ZW4yrcFnz0vma3vgoenSXA.g8_Ird2Y0itTCDP61du-Yg", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTkyR0NNIiwidGFnIjoiWC05UkNVWVh4U3NRelcwelVJS01VUSIsImFsZyI6IkEyNTZHQ01LVyIsIml2IjoiY3JNMnJfa3RrdWpyQ1h5OSJ9.c0q2jCxxV4y1h9u_Xvn7FqUDnbkmNEG4.S_noOTZKuUo9z1l6.ez0RdA25vXMUGH96iXmj3DEVox0J7TasJMnzgg.RbuSPTte_NzTtEEokbc5Ig", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMjU2R0NNIiwidGFnIjoiWmwyaDFpUW11QWZWd2lJeVp5RHloZyIsImFsZyI6IkEyNTZHQ01LVyIsIml2Ijoib19xZmljb0N0NzNzRWo1QyJ9.NpJxRJ0aqcpekD6HU2u9e6_pL_11JXjWvjfeQnAKkZU.4c5qBcBBrMWi27Lf.NKwNIb4b6cRDJ1TwMKsPrjs7ADn6aNoBdQClVw.yNWmSSRBqQfIQObzj8zDqw", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwidGFnIjoiMXdwVEI3LWhjdzZUVXhCbVh2UzdhUSIsImFsZyI6IkEyNTZHQ01LVyIsIml2IjoiOUdIVnZJaDZ0a09vX2pHUSJ9.MFgIhp9mzlq9hoPqqKVKHJ3HL79EBYtV4iNhD63yqiU.UzW5iq8ou21VpZYJgKEN8A.1gOEzA4uAPvHP76GMfs9uLloAV10mKaxiZVAeL7iQA0.i1X_2i0bCAz-soXF9bI_zw", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTkyQ0JDLUhTMzg0IiwidGFnIjoiNThocUtsSk15Y1BFUEFRUlNfSzlNUSIsImFsZyI6IkEyNTZHQ01LVyIsIml2IjoiUDh3aTBWMTluVnZqNXpkOSJ9.FXidOWHNFJODO74Thq3J2cC-Z2B8UZkn7SikeosU0bUK6Jx_lzzmUZ-Lafadpdpj.iLfcDbpuBKFiSfiBzUQc7Q.VZK-aD7BFspqfvbwa0wE2wwWxdomzk2IKMetFe8bI44.7wC6rJRGa4x48xbYMd6NH9VzK8uNn4Cb", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwidGFnIjoicGcwOEpUcXdzMXdEaXBaRUlpVExoQSIsImFsZyI6IkEyNTZHQ01LVyIsIml2IjoiSlpodk9CdU1RUDFFZTZTNSJ9.wqVgTPm6TcYCTkpbwmn9sW4mgJROH2A3dIdSXo5oKIQUIVbQsmy7KXH8UYO2RS9slMGtb869C8o0My67GKg9dQ.ogrRiLlqjB1S5j-7a05OwA.2Y_LyqhU4S_RXMsB74bxcBacd23J2Sp5Lblw-sOkaUY.XGMiYoU-f3GaEzSvG41vpJP2DMGbeDFoWmkUGLUjc4M", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiQTI1NktXIn0.QiIZm9NYfahqYFIbiaoUhCCHjotHMkup.EsU0XLn4FjzzCILn.WuCoQkm9vzo95E7hxBtfYpt-Mooc_vmSTyzj6Q.NbeeYVy6gQPlmhoWDrZwaQ", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTkyR0NNIiwiYWxnIjoiQTI1NktXIn0.1ol3j_Lt0Os3UMe2Gypj0o8b77k0FSmqD7kNRNoMa9U.vZ2HMTgN2dgUd42h.JvNcy8-c8sYzOC089VtFSg2BOQx3YF8CqSTuJw.t03LRioWWKN3d7SjinU6SQ", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiQTI1NktXIn0.gbkk03l1gyrE9qGEMVtORiyyUqKsgzbqjLd8lw0RQ07WWn--TV4BgA.J8ThH4ac2UhSsMIP.g-W1piEGrdi3tNwQDJXpYm3fQjTf82mtVCrCOg.-vY05P4kiB9FgF2vwrSeXQ", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiQTI1NktXIn0.k86pQs7gmQIzuIWRFwesF32XY2xi1WbYxi7XUf_CYlOlehwGCTINHg.3NcC9VzfQgsECISKf4xy-g.v2amdo-rgeGsg-II_tvPukX9D-KAP27xxf2uQJ277Ws.E4LIE3fte3glAnPpnd8D9Q", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMTkyQ0JDLUhTMzg0IiwiYWxnIjoiQTI1NktXIn0.b8iN0Am3fCUvj7sBd7Z0lpfzBjh1MOgojV7J5rDfrcTU3b35RGYgEV1RdcrtUTBgUwITDjmU7jM.wsSDBFghDga_ERv36I2AOg.6uJsucCb2YReFOJGBdo4zidTIKLUmZBIXfm_M0AJpKk.YwdAfXI3HHcw2wLSnfCRtw4huZQtSKhz", - "eyJ6aXAiOiJERUYiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiYWxnIjoiQTI1NktXIn0.akY9pHCbkHPh5VpXIrX0At41XnJIKBR9iMMkf301vKeJNAZYJTxWzeJhFd-DhQ47tMctc3YYkwZkQ5I_9fGYb_f0oBcw4esh.JNwuuHud78h6S99NO1oBQQ.0RwckPYATBgvw67upkAQ1AezETHc-gh3rryz19i5ryc.3XClRTScgzfMgLCHxHHoRF8mm9VVGXv_Ahtx65PskKQ", - }, - } - - for i, msgs := range aesSampleMessages { - for _, msg := range msgs { - obj, err := ParseEncrypted(msg) - if err != nil { - t.Error("unable to parse message", msg, err) - continue - } - plaintext, err := obj.Decrypt(aesTestKeys[i]) - if err != nil { - t.Error("unable to decrypt message", msg, err) - continue - } - if string(plaintext) != "Lorem ipsum dolor sit amet" { - t.Error("plaintext is not what we expected for msg", msg) - } - } - } -} - -// Test vectors generated with jose4j -func TestSampleJose4jJWEMessagesECDH(t *testing.T) { - ecTestKey := &ecdsa.PrivateKey{ - PublicKey: ecdsa.PublicKey{ - Curve: elliptic.P256(), - X: fromBase64Int("weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ"), - Y: fromBase64Int("e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck"), - }, - D: fromBase64Int("VEmDZpDXXK8p8N0Cndsxs924q6nS1RXFASRl6BfUqdw"), - } - - ecSampleMessages := []string{ - "eyJhbGciOiJFQ0RILUVTIiwiZW5jIjoiQTEyOENCQy1IUzI1NiIsImVwayI6eyJrdHkiOiJFQyIsIngiOiJTQzAtRnJHUkVvVkpKSmg1TGhORmZqZnFXMC1XSUFyd3RZMzJzQmFQVVh3IiwieSI6ImFQMWlPRENveU9laTVyS1l2VENMNlRMZFN5UEdUN0djMnFsRnBwNXdiWFEiLCJjcnYiOiJQLTI1NiJ9fQ..3mifklTnTTGuA_etSUBBCw.dj8KFM8OlrQ3rT35nHcHZ7A5p84VB2OZb054ghSjS-M.KOIgnJjz87LGqMtikXGxXw", - "eyJhbGciOiJFQ0RILUVTIiwiZW5jIjoiQTE5MkNCQy1IUzM4NCIsImVwayI6eyJrdHkiOiJFQyIsIngiOiJUaHRGc0lRZ1E5MkZOYWFMbUFDQURLbE93dmNGVlRORHc4ampfWlJidUxjIiwieSI6IjJmRDZ3UXc3YmpYTm1nVThXMGpFbnl5ZUZkX3Y4ZmpDa3l1R29vTFhGM0EiLCJjcnYiOiJQLTI1NiJ9fQ..90zFayMkKc-fQC_19f6P3A.P1Y_7lMnfkUQOXW_en31lKZ3zAn1nEYn6fXLjmyVPrQ.hrgwy1cePVfhMWT0h-crKTXldglHZ-4g", - "eyJhbGciOiJFQ0RILUVTIiwiZW5jIjoiQTI1NkNCQy1IUzUxMiIsImVwayI6eyJrdHkiOiJFQyIsIngiOiI5R1Z6c3VKNWgySl96UURVUFR3WU5zUkFzVzZfY2RzN0pELVQ2RDREQ1ZVIiwieSI6InFZVGl1dVU4aTB1WFpoaS14VGlRNlZJQm5vanFoWENPVnpmWm1pR2lRTEUiLCJjcnYiOiJQLTI1NiJ9fQ..v2reRlDkIsw3eWEsTCc1NA.0qakrFdbhtBCTSl7EREf9sxgHBP9I-Xw29OTJYnrqP8.54ozViEBYYmRkcKp7d2Ztt4hzjQ9Vb5zCeijN_RQrcI", - "eyJhbGciOiJFQ0RILUVTK0EyNTZLVyIsImVuYyI6IkExMjhDQkMtSFMyNTYiLCJlcGsiOnsia3R5IjoiRUMiLCJ4IjoiOElUemg3VVFaaUthTWtfME9qX1hFaHZENXpUWjE2Ti13WVdjeTJYUC1tdyIsInkiOiJPNUJiVEk0bUFpU005ZmpCejBRU3pXaU5vbnl3cWlQLUN0RGgwdnNGYXNRIiwiY3J2IjoiUC0yNTYifX0.D3DP3wqPvJv4TYYfhnfrOG6nsM-MMH_CqGfnOGjgdXHNF7xRwEJBOA.WL9Kz3gNYA7S5Rs5mKcXmA.EmQkXhO_nFqAwxJWaM0DH4s3pmCscZovB8YWJ3Ru4N8.Bf88uzwfxiyTjpejU5B0Ng", - "eyJhbGciOiJFQ0RILUVTK0EyNTZLVyIsImVuYyI6IkExOTJDQkMtSFMzODQiLCJlcGsiOnsia3R5IjoiRUMiLCJ4IjoiMjlJMk4zRkF0UlBlNGhzYjRLWlhTbmVyV0wyTVhtSUN1LXJJaXhNSHpJQSIsInkiOiJvMjY1bzFReEdmbDhzMHQ0U1JROS00RGNpc3otbXh4NlJ6WVF4SktyeWpJIiwiY3J2IjoiUC0yNTYifX0.DRmsmXz6fCnLc_njDIKdpM7Oc4jTqd_yd9J94TOUksAstEUkAl9Ie3Wg-Ji_LzbdX2xRLXIimcw.FwJOHPQhnqKJCfxt1_qRnQ.ssx3q1ZYILsMTln5q-K8HVn93BVPI5ViusstKMxZzRs.zzcfzWNYSdNDdQ4CiHfymj0bePaAbVaT", - "eyJhbGciOiJFQ0RILUVTK0EyNTZLVyIsImVuYyI6IkEyNTZDQkMtSFM1MTIiLCJlcGsiOnsia3R5IjoiRUMiLCJ4IjoiRUp6bTViQnRzVXJNYTl2Y1Q2d1hZRXI3ZjNMcjB0N1V4SDZuZzdGcFF0VSIsInkiOiJRYTNDSDllVTFXYjItdFdVSDN3Sk9fTDVMZXRsRUlMQWNkNE9XR2tFd0hZIiwiY3J2IjoiUC0yNTYifX0.5WxwluZpVWAOJdVrsnDIlEc4_wfRE1gXOaQyx_rKkElNz157Ykf-JsAD7aEvXfx--NKF4js5zYyjeCtxWBhRWPOoNNZJlqV_.Iuo82-qsP2S1SgQQklAnrw.H4wB6XoLKOKWCu6Y3LPAEuHkvyvr-xAh4IBm53uRF8g._fOLKq0bqDZ8KNjni_MJ4olHNaYz376dV9eNmp9O9PU", - "eyJhbGciOiJFQ0RILUVTK0ExOTJLVyIsImVuYyI6IkExMjhDQkMtSFMyNTYiLCJlcGsiOnsia3R5IjoiRUMiLCJ4IjoiZktNSG5sRkoxajBTSnJ3WGtVWlpaX3BtWHdUQlJtcHhlaTkxdUpaczUycyIsInkiOiJLRkxKaXhEUTJQcjEybWp1aFdYb3pna2U1V3lhWnhmTWlxZkJ0OEJpbkRvIiwiY3J2IjoiUC0yNTYifX0.2LSD2Mw4tyYJyfsmpVmzBtJRd12jMEYGdlhFbaXIbKi5A33CGNQ1tg.s40aAjmZOvK8Us86FCBdHg.jpYSMAKp___oMCoWM495mTfbi_YC80ObeoCmGE3H_gs.A6V-jJJRY1yz24CaXGUbzg", - "eyJhbGciOiJFQ0RILUVTK0ExOTJLVyIsImVuYyI6IkExOTJDQkMtSFMzODQiLCJlcGsiOnsia3R5IjoiRUMiLCJ4IjoiSDRxcFUzeWtuRktWRnV4SmxLa3NZSE5ieHF3aXM0WWtCVVFHVE1Td05JQSIsInkiOiJHb0lpRUZaUGRRSHJCbVR4ZTA3akJoZmxrdWNqUjVoX1QwNWVXc3Zib0prIiwiY3J2IjoiUC0yNTYifX0.KTrwwV2uzD--gf3PGG-kjEAGgi7u0eMqZPZfa4kpyFGm3x8t2m1NHdz3t9rfiqjuaqsxPKhF4gs.cu16fEOzYaSxhHu_Ht9w4g.BRJdxVBI9spVtY5KQ6gTR4CNcKvmLUMKZap0AO-RF2I.DZyUaa2p6YCIaYtjWOjC9GN_VIYgySlZ", - "eyJhbGciOiJFQ0RILUVTK0ExOTJLVyIsImVuYyI6IkEyNTZDQkMtSFM1MTIiLCJlcGsiOnsia3R5IjoiRUMiLCJ4IjoieDBYSGRkSGM2Q0ktSnlfbUVMOEZZRExhWnV0UkVFczR4c3BMQmcwZk1jbyIsInkiOiJEa0xzOUJGTlBkTTVTNkpLYVJ3cnV1TWMwcUFzWW9yNW9fZWp6NXBNVXFrIiwiY3J2IjoiUC0yNTYifX0.mfCxJ7JYIqTMqcAh5Vp2USF0eF7OhOeluqda7YagOUJNwxA9wC9o23DSoLUylfrZUfanZrJJJcG69awlv-LY7anOLHlp3Ht5.ec48A_JWb4qa_PVHWZaTfQ.kDAjIDb3LzJpfxNh-DiAmAuaKMYaOGSTb0rkiJLuVeY.oxGCpPlii4pr89XMk4b9s084LucTqPGU6TLbOW2MZoc", - "eyJhbGciOiJFQ0RILUVTK0ExMjhLVyIsImVuYyI6IkExMjhDQkMtSFMyNTYiLCJlcGsiOnsia3R5IjoiRUMiLCJ4IjoiQXB5TnlqU2d0bmRUcFg0eENYenNDRnZva1l3X18weXg2dGRUYzdPUUhIMCIsInkiOiJYUHdHMDVDaW1vOGlhWmxZbDNsMEp3ZllhY1FZWHFuM2RRZEJUWFpldDZBIiwiY3J2IjoiUC0yNTYifX0.yTA2PwK9IPqkaGPenZ9R-gOn9m9rvcSEfuX_Nm8AkuwHIYLzzYeAEA.ZW1F1iyHYKfo-YoanNaIVg.PouKQD94DlPA5lbpfGJXY-EJhidC7l4vSayVN2vVzvA.MexquqtGaXKUvX7WBmD4bA", - "eyJhbGciOiJFQ0RILUVTK0ExMjhLVyIsImVuYyI6IkExOTJDQkMtSFMzODQiLCJlcGsiOnsia3R5IjoiRUMiLCJ4IjoiaDRWeGNzNVUzWk1fTlp4WmJxQ3hMTVB5UmEtR2ktSVNZa0xDTzE1RHJkZyIsInkiOiJFeVotS3dWNVE5OXlnWk5zU0lpSldpR3hqbXNLUk1WVE5sTTNSd1VYTFRvIiwiY3J2IjoiUC0yNTYifX0.wo56VISyL1QAbi2HLuVut5NGF2FvxKt7B8zHzJ3FpmavPozfbVZV08-GSYQ6jLQWJ4xsO80I4Kg.3_9Bo5ozvD96WHGhqp_tfQ.48UkJ6jk6WK70QItb2QZr0edKH7O-aMuVahTEeqyfW4.ulMlY2tbC341ct20YSmNdtc84FRz1I4g", - "eyJhbGciOiJFQ0RILUVTK0ExMjhLVyIsImVuYyI6IkEyNTZDQkMtSFM1MTIiLCJlcGsiOnsia3R5IjoiRUMiLCJ4IjoiN0xZRzZZWTJkel9ZaGNvNnRCcG1IX0tPREQ2X2hwX05tajdEc1c2RXgxcyIsInkiOiI5Y2lPeDcwUkdGT0tpVnBRX0NHQXB5NVlyeThDazBmUkpwNHVrQ2tjNmQ0IiwiY3J2IjoiUC0yNTYifX0.bWwW3J80k46HG1fQAZxUroko2OO8OKkeRavr_o3AnhJDMvp78OR229x-fZUaBm4uWv27_Yjm0X9T2H2lhlIli2Rl9v1PNC77.1NmsJBDGI1fDjRzyc4mtyA.9KfCFynQj7LmJq08qxAG4c-6ZPz1Lh3h3nUbgVwB0TI.cqech0d8XHzWfkWqgKZq1SlAfmO0PUwOsNVkuByVGWk", - } - - for _, msg := range ecSampleMessages { - obj, err := ParseEncrypted(msg) - if err != nil { - t.Error("unable to parse message", msg, err) - continue - } - plaintext, err := obj.Decrypt(ecTestKey) - if err != nil { - t.Error("unable to decrypt message", msg, err) - continue - } - if string(plaintext) != "Lorem ipsum dolor sit amet." { - t.Error("plaintext is not what we expected for msg", msg) - } - } -} diff --git a/vendor/gopkg.in/square/go-jose.v2/jwk_test.go b/vendor/gopkg.in/square/go-jose.v2/jwk_test.go deleted file mode 100644 index b7d48ec87..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/jwk_test.go +++ /dev/null @@ -1,715 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jose - -import ( - "bytes" - "crypto" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rsa" - "crypto/x509" - "encoding/hex" - "math/big" - "reflect" - "testing" - - "golang.org/x/crypto/ed25519" - - "gopkg.in/square/go-jose.v2/json" -) - -// Test chain of two X.509 certificates -var testCertificates, _ = x509.ParseCertificates(fromBase64Bytes(` -MIIDfDCCAmSgAwIBAgIJANWAkzF7PA8/MA0GCSqGSIb3DQEBCwUAMFUxCzAJ -BgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UEChMHY2VydGlnbzEQMA4G -A1UECxMHZXhhbXBsZTEVMBMGA1UEAxMMZXhhbXBsZS1sZWFmMB4XDTE2MDYx -MDIyMTQxMVoXDTIzMDQxNTIyMTQxMVowVTELMAkGA1UEBhMCVVMxCzAJBgNV -BAgTAkNBMRAwDgYDVQQKEwdjZXJ0aWdvMRAwDgYDVQQLEwdleGFtcGxlMRUw -EwYDVQQDEwxleGFtcGxlLWxlYWYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQC7stSvfQyGuHw3v34fisqIdDXberrFoFk9ht/WdXgYzX2uLNKd -sR/J5sbWSl8K/5djpzj31eIzqU69w8v7SChM5x9bouDsABHz3kZucx5cSafE -gJojysBkcrq3VY+aJanzbL+qErYX+lhRpPcZK6JMWIwar8Y3B2la4yWwieec -w2/WfEVvG0M/DOYKnR8QHFsfl3US1dnBM84czKPyt9r40gDk2XiH/lGts5a9 -4rAGvbr8IMCtq0mA5aH3Fx3mDSi3+4MZwygCAHrF5O5iSV9rEI+m2+7j2S+j -HDUnvV+nqcpb9m6ENECnYX8FD2KcqlOjTmw8smDy09N2Np6i464lAgMBAAGj -TzBNMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAsBgNVHREEJTAj -hwR/AAABhxAAAAAAAAAAAAAAAAAAAAABgglsb2NhbGhvc3QwDQYJKoZIhvcN -AQELBQADggEBAGM4aa/qrURUweZBIwZYv8O9b2+r4l0HjGAh982/B9sMlM05 -kojyDCUGvj86z18Lm8mKr4/y+i0nJ+vDIksEvfDuzw5ALAXGcBzPJKtICUf7 -LstA/n9NNpshWz0kld9ylnB5mbUzSFDncVyeXkEf5sGQXdIIZT9ChRBoiloS -aa7dvBVCcsX1LGP2LWqKtD+7nUnw5qCwtyAVT8pthEUxFTpywoiJS5ZdzeEx -8MNGvUeLFj2kleqPF78EioEQlSOxViCuctEtnQuPcDLHNFr10byTZY9roObi -qdsJLMVvb2XliJjAqaPa9AkYwGE6xHw2ispwg64Rse0+AtKups19WIUwggNT -MIICO6ADAgECAgkAqD4tCWKt9/AwDQYJKoZIhvcNAQELBQAwVTELMAkGA1UE -BhMCVVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQKEwdjZXJ0aWdvMRAwDgYDVQQL -EwdleGFtcGxlMRUwEwYDVQQDEwxleGFtcGxlLXJvb3QwHhcNMTYwNjEwMjIx -NDExWhcNMjMwNDE1MjIxNDExWjBVMQswCQYDVQQGEwJVUzELMAkGA1UECBMC -Q0ExEDAOBgNVBAoTB2NlcnRpZ28xEDAOBgNVBAsTB2V4YW1wbGUxFTATBgNV -BAMTDGV4YW1wbGUtcm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAMo4ShKI2MxDz/NQVxBbz0tbD5R5NcobA0NKkaPKLyMEpnWVY9ucyauM -joNn1F568cfOoF0pm3700U8UTPt2MMxEHIi4mFG/OF8UF+Voh1J42Tb42lRo -W5RRR3ogh4+7QB1G94nxkYddHAJ4QMhUJlLigFg8c6Ff/MxYODy9I7ilLFOM -Zzsjx8fFpRKRXNQFt471P/V4WTSba7GzdTOJRyTZf/xipF36n8RoEQPvyde8 -pEAsCC4oDOrEiCTdxw8rRJVAU0Wr55XX+qjxyi55C6oykIC/BWR+lUqGd7IL -Y2Uyt/OVxllt8b+KuVKNCfn4TFlfgizLWkJRs6JV9KuwJ20CAwEAAaMmMCQw -DgYDVR0PAQH/BAQDAgIEMBIGA1UdEwEB/wQIMAYBAf8CAQAwDQYJKoZIhvcN -AQELBQADggEBAIsQlTrm9NT6gts0cs4JHp8AutuMrvGyLpIUOlJcEybvgxaz -LebIMGZek5w3yEJiCyCK9RdNDP3Kdc/+nM6PhvzfPOVo58+0tMCYyEpZVXhD -zmasNDP4fMbiUpczvx5OwPw/KuhwD+1ITuZUQnQlqXgTYoj9n39+qlgUsHos -WXHmfzd6Fcz96ADSXg54IL2cEoJ41Q3ewhA7zmWWPLMAl21aex2haiAmzqqN -xXyfZTnGNnE3lkV1yVguOrqDZyMRdcxDFvxvtmEeMtYV2Mc/zlS9ccrcOkrc -mZSDxthLu3UMl98NA2NrCGWwzJwpk36vQ0PRSbibsCMarFspP8zbIoU=`)) - -func TestCurveSize(t *testing.T) { - size256 := curveSize(elliptic.P256()) - size384 := curveSize(elliptic.P384()) - size521 := curveSize(elliptic.P521()) - if size256 != 32 { - t.Error("P-256 have 32 bytes") - } - if size384 != 48 { - t.Error("P-384 have 48 bytes") - } - if size521 != 66 { - t.Error("P-521 have 66 bytes") - } -} - -func TestRoundtripRsaPrivate(t *testing.T) { - jwk, err := fromRsaPrivateKey(rsaTestKey) - if err != nil { - t.Error("problem constructing JWK from rsa key", err) - } - - rsa2, err := jwk.rsaPrivateKey() - if err != nil { - t.Error("problem converting RSA private -> JWK", err) - } - - if rsa2.N.Cmp(rsaTestKey.N) != 0 { - t.Error("RSA private N mismatch") - } - if rsa2.E != rsaTestKey.E { - t.Error("RSA private E mismatch") - } - if rsa2.D.Cmp(rsaTestKey.D) != 0 { - t.Error("RSA private D mismatch") - } - if len(rsa2.Primes) != 2 { - t.Error("RSA private roundtrip expected two primes") - } - if rsa2.Primes[0].Cmp(rsaTestKey.Primes[0]) != 0 { - t.Error("RSA private P mismatch") - } - if rsa2.Primes[1].Cmp(rsaTestKey.Primes[1]) != 0 { - t.Error("RSA private Q mismatch") - } -} - -func TestRsaPrivateInsufficientPrimes(t *testing.T) { - brokenRsaPrivateKey := rsa.PrivateKey{ - PublicKey: rsa.PublicKey{ - N: rsaTestKey.N, - E: rsaTestKey.E, - }, - D: rsaTestKey.D, - Primes: []*big.Int{rsaTestKey.Primes[0]}, - } - - _, err := fromRsaPrivateKey(&brokenRsaPrivateKey) - if err != ErrUnsupportedKeyType { - t.Error("expected unsupported key type error, got", err) - } -} - -func TestRsaPrivateExcessPrimes(t *testing.T) { - brokenRsaPrivateKey := rsa.PrivateKey{ - PublicKey: rsa.PublicKey{ - N: rsaTestKey.N, - E: rsaTestKey.E, - }, - D: rsaTestKey.D, - Primes: []*big.Int{ - rsaTestKey.Primes[0], - rsaTestKey.Primes[1], - big.NewInt(3), - }, - } - - _, err := fromRsaPrivateKey(&brokenRsaPrivateKey) - if err != ErrUnsupportedKeyType { - t.Error("expected unsupported key type error, got", err) - } -} - -func TestRoundtripEcPublic(t *testing.T) { - for i, ecTestKey := range []*ecdsa.PrivateKey{ecTestKey256, ecTestKey384, ecTestKey521} { - jwk, err := fromEcPublicKey(&ecTestKey.PublicKey) - - ec2, err := jwk.ecPublicKey() - if err != nil { - t.Error("problem converting ECDSA private -> JWK", i, err) - } - - if !reflect.DeepEqual(ec2.Curve, ecTestKey.Curve) { - t.Error("ECDSA private curve mismatch", i) - } - if ec2.X.Cmp(ecTestKey.X) != 0 { - t.Error("ECDSA X mismatch", i) - } - if ec2.Y.Cmp(ecTestKey.Y) != 0 { - t.Error("ECDSA Y mismatch", i) - } - } -} - -func TestRoundtripEcPrivate(t *testing.T) { - for i, ecTestKey := range []*ecdsa.PrivateKey{ecTestKey256, ecTestKey384, ecTestKey521} { - jwk, err := fromEcPrivateKey(ecTestKey) - - ec2, err := jwk.ecPrivateKey() - if err != nil { - t.Error("problem converting ECDSA private -> JWK", i, err) - } - - if !reflect.DeepEqual(ec2.Curve, ecTestKey.Curve) { - t.Error("ECDSA private curve mismatch", i) - } - if ec2.X.Cmp(ecTestKey.X) != 0 { - t.Error("ECDSA X mismatch", i) - } - if ec2.Y.Cmp(ecTestKey.Y) != 0 { - t.Error("ECDSA Y mismatch", i) - } - if ec2.D.Cmp(ecTestKey.D) != 0 { - t.Error("ECDSA D mismatch", i) - } - } -} - -func TestRoundtripX5C(t *testing.T) { - jwk := JSONWebKey{ - Key: rsaTestKey, - KeyID: "bar", - Algorithm: "foo", - Certificates: testCertificates, - } - - jsonbar, err := jwk.MarshalJSON() - if err != nil { - t.Error("problem marshaling", err) - } - - var jwk2 JSONWebKey - err = jwk2.UnmarshalJSON(jsonbar) - if err != nil { - t.Error("problem unmarshalling", err) - } - - if !reflect.DeepEqual(testCertificates, jwk2.Certificates) { - t.Error("Certificates not equal", jwk.Certificates, jwk2.Certificates) - } - - jsonbar2, err := jwk2.MarshalJSON() - if err != nil { - t.Error("problem marshaling", err) - } - if !bytes.Equal(jsonbar, jsonbar2) { - t.Error("roundtrip should not lose information") - } -} - -func TestMarshalUnmarshal(t *testing.T) { - kid := "DEADBEEF" - - for i, key := range []interface{}{ecTestKey256, ecTestKey384, ecTestKey521, rsaTestKey, ed25519PrivateKey} { - for _, use := range []string{"", "sig", "enc"} { - jwk := JSONWebKey{Key: key, KeyID: kid, Algorithm: "foo"} - if use != "" { - jwk.Use = use - } - - jsonbar, err := jwk.MarshalJSON() - if err != nil { - t.Error("problem marshaling", i, err) - } - - var jwk2 JSONWebKey - err = jwk2.UnmarshalJSON(jsonbar) - if err != nil { - t.Error("problem unmarshalling", i, err) - } - - jsonbar2, err := jwk2.MarshalJSON() - if err != nil { - t.Error("problem marshaling", i, err) - } - - if !bytes.Equal(jsonbar, jsonbar2) { - t.Error("roundtrip should not lose information", i) - } - if jwk2.KeyID != kid { - t.Error("kid did not roundtrip JSON marshalling", i) - } - - if jwk2.Algorithm != "foo" { - t.Error("alg did not roundtrip JSON marshalling", i) - } - - if jwk2.Use != use { - t.Error("use did not roundtrip JSON marshalling", i) - } - } - } -} - -func TestMarshalNonPointer(t *testing.T) { - type EmbedsKey struct { - Key JSONWebKey - } - - keyJSON := []byte(`{ - "e": "AQAB", - "kty": "RSA", - "n": "vd7rZIoTLEe-z1_8G1FcXSw9CQFEJgV4g9V277sER7yx5Qjz_Pkf2YVth6wwwFJEmzc0hoKY-MMYFNwBE4hQHw" - }`) - var parsedKey JSONWebKey - err := json.Unmarshal(keyJSON, &parsedKey) - if err != nil { - t.Errorf("Error unmarshalling key: %v", err) - return - } - ek := EmbedsKey{ - Key: parsedKey, - } - out, err := json.Marshal(ek) - if err != nil { - t.Errorf("Error marshalling JSON: %v", err) - return - } - expected := "{\"Key\":{\"kty\":\"RSA\",\"n\":\"vd7rZIoTLEe-z1_8G1FcXSw9CQFEJgV4g9V277sER7yx5Qjz_Pkf2YVth6wwwFJEmzc0hoKY-MMYFNwBE4hQHw\",\"e\":\"AQAB\"}}" - if string(out) != expected { - t.Error("Failed to marshal embedded non-pointer JWK properly:", string(out)) - } -} - -func TestMarshalUnmarshalInvalid(t *testing.T) { - // Make an invalid curve coordinate by creating a byte array that is one - // byte too large, and setting the first byte to 1 (otherwise it's just zero). - invalidCoord := make([]byte, curveSize(ecTestKey256.Curve)+1) - invalidCoord[0] = 1 - - keys := []interface{}{ - // Empty keys - &rsa.PrivateKey{}, - &ecdsa.PrivateKey{}, - // Invalid keys - &ecdsa.PrivateKey{ - PublicKey: ecdsa.PublicKey{ - // Missing values in pub key - Curve: elliptic.P256(), - }, - }, - &ecdsa.PrivateKey{ - PublicKey: ecdsa.PublicKey{ - // Invalid curve - Curve: nil, - X: ecTestKey256.X, - Y: ecTestKey256.Y, - }, - }, - &ecdsa.PrivateKey{ - // Valid pub key, but missing priv key values - PublicKey: ecTestKey256.PublicKey, - }, - &ecdsa.PrivateKey{ - // Invalid pub key, values too large - PublicKey: ecdsa.PublicKey{ - Curve: ecTestKey256.Curve, - X: big.NewInt(0).SetBytes(invalidCoord), - Y: big.NewInt(0).SetBytes(invalidCoord), - }, - D: ecTestKey256.D, - }, - nil, - } - - for i, key := range keys { - jwk := JSONWebKey{Key: key} - _, err := jwk.MarshalJSON() - if err == nil { - t.Error("managed to serialize invalid key", i) - } - } -} - -func TestWebKeyVectorsInvalid(t *testing.T) { - keys := []string{ - // Invalid JSON - "{X", - // Empty key - "{}", - // Invalid RSA keys - `{"kty":"RSA"}`, - `{"kty":"RSA","e":""}`, - `{"kty":"RSA","e":"XXXX"}`, - `{"kty":"RSA","d":"XXXX"}`, - // Invalid EC keys - `{"kty":"EC","crv":"ABC"}`, - `{"kty":"EC","crv":"P-256"}`, - `{"kty":"EC","crv":"P-256","d":"XXX"}`, - `{"kty":"EC","crv":"ABC","d":"dGVzdA","x":"dGVzdA"}`, - `{"kty":"EC","crv":"P-256","d":"dGVzdA","x":"dGVzdA"}`, - } - - for _, key := range keys { - var jwk2 JSONWebKey - err := jwk2.UnmarshalJSON([]byte(key)) - if err == nil { - t.Error("managed to parse invalid key:", key) - } - } -} - -// Test vectors from RFC 7520 -var cookbookJWKs = []string{ - // EC Public - stripWhitespace(`{ - "kty": "EC", - "kid": "bilbo.baggins@hobbiton.example", - "use": "sig", - "crv": "P-521", - "x": "AHKZLLOsCOzz5cY97ewNUajB957y-C-U88c3v13nmGZx6sYl_oJXu9 - A5RkTKqjqvjyekWF-7ytDyRXYgCF5cj0Kt", - "y": "AdymlHvOiLxXkEhayXQnNCvDX4h9htZaCJN34kfmC6pV5OhQHiraVy - SsUdaQkAgDPrwQrJmbnX9cwlGfP-HqHZR1" - }`), - - //ED Private - stripWhitespace(`{ - "kty": "OKP", - "crv": "Ed25519", - "d": "nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A", - "x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo" - }`), - - // EC Private - stripWhitespace(`{ - "kty": "EC", - "kid": "bilbo.baggins@hobbiton.example", - "use": "sig", - "crv": "P-521", - "x": "AHKZLLOsCOzz5cY97ewNUajB957y-C-U88c3v13nmGZx6sYl_oJXu9 - A5RkTKqjqvjyekWF-7ytDyRXYgCF5cj0Kt", - "y": "AdymlHvOiLxXkEhayXQnNCvDX4h9htZaCJN34kfmC6pV5OhQHiraVy - SsUdaQkAgDPrwQrJmbnX9cwlGfP-HqHZR1", - "d": "AAhRON2r9cqXX1hg-RoI6R1tX5p2rUAYdmpHZoC1XNM56KtscrX6zb - KipQrCW9CGZH3T4ubpnoTKLDYJ_fF3_rJt" - }`), - - // RSA Public - stripWhitespace(`{ - "kty": "RSA", - "kid": "bilbo.baggins@hobbiton.example", - "use": "sig", - "n": "n4EPtAOCc9AlkeQHPzHStgAbgs7bTZLwUBZdR8_KuKPEHLd4rHVTeT - -O-XV2jRojdNhxJWTDvNd7nqQ0VEiZQHz_AJmSCpMaJMRBSFKrKb2wqV - wGU_NsYOYL-QtiWN2lbzcEe6XC0dApr5ydQLrHqkHHig3RBordaZ6Aj- - oBHqFEHYpPe7Tpe-OfVfHd1E6cS6M1FZcD1NNLYD5lFHpPI9bTwJlsde - 3uhGqC0ZCuEHg8lhzwOHrtIQbS0FVbb9k3-tVTU4fg_3L_vniUFAKwuC - LqKnS2BYwdq_mzSnbLY7h_qixoR7jig3__kRhuaxwUkRz5iaiQkqgc5g - HdrNP5zw", - "e": "AQAB" - }`), - - // RSA Private - stripWhitespace(`{"kty":"RSA", - "kid":"juliet@capulet.lit", - "use":"enc", - "n":"t6Q8PWSi1dkJj9hTP8hNYFlvadM7DflW9mWepOJhJ66w7nyoK1gPNqFMSQRy - O125Gp-TEkodhWr0iujjHVx7BcV0llS4w5ACGgPrcAd6ZcSR0-Iqom-QFcNP - 8Sjg086MwoqQU_LYywlAGZ21WSdS_PERyGFiNnj3QQlO8Yns5jCtLCRwLHL0 - Pb1fEv45AuRIuUfVcPySBWYnDyGxvjYGDSM-AqWS9zIQ2ZilgT-GqUmipg0X - OC0Cc20rgLe2ymLHjpHciCKVAbY5-L32-lSeZO-Os6U15_aXrk9Gw8cPUaX1 - _I8sLGuSiVdt3C_Fn2PZ3Z8i744FPFGGcG1qs2Wz-Q", - "e":"AQAB", - "d":"GRtbIQmhOZtyszfgKdg4u_N-R_mZGU_9k7JQ_jn1DnfTuMdSNprTeaSTyWfS - NkuaAwnOEbIQVy1IQbWVV25NY3ybc_IhUJtfri7bAXYEReWaCl3hdlPKXy9U - vqPYGR0kIXTQRqns-dVJ7jahlI7LyckrpTmrM8dWBo4_PMaenNnPiQgO0xnu - ToxutRZJfJvG4Ox4ka3GORQd9CsCZ2vsUDmsXOfUENOyMqADC6p1M3h33tsu - rY15k9qMSpG9OX_IJAXmxzAh_tWiZOwk2K4yxH9tS3Lq1yX8C1EWmeRDkK2a - hecG85-oLKQt5VEpWHKmjOi_gJSdSgqcN96X52esAQ", - "p":"2rnSOV4hKSN8sS4CgcQHFbs08XboFDqKum3sc4h3GRxrTmQdl1ZK9uw-PIHf - QP0FkxXVrx-WE-ZEbrqivH_2iCLUS7wAl6XvARt1KkIaUxPPSYB9yk31s0Q8 - UK96E3_OrADAYtAJs-M3JxCLfNgqh56HDnETTQhH3rCT5T3yJws", - "q":"1u_RiFDP7LBYh3N4GXLT9OpSKYP0uQZyiaZwBtOCBNJgQxaj10RWjsZu0c6I - edis4S7B_coSKB0Kj9PaPaBzg-IySRvvcQuPamQu66riMhjVtG6TlV8CLCYK - rYl52ziqK0E_ym2QnkwsUX7eYTB7LbAHRK9GqocDE5B0f808I4s", - "dp":"KkMTWqBUefVwZ2_Dbj1pPQqyHSHjj90L5x_MOzqYAJMcLMZtbUtwKqvVDq3 - tbEo3ZIcohbDtt6SbfmWzggabpQxNxuBpoOOf_a_HgMXK_lhqigI4y_kqS1w - Y52IwjUn5rgRrJ-yYo1h41KR-vz2pYhEAeYrhttWtxVqLCRViD6c", - "dq":"AvfS0-gRxvn0bwJoMSnFxYcK1WnuEjQFluMGfwGitQBWtfZ1Er7t1xDkbN9 - GQTB9yqpDoYaN06H7CFtrkxhJIBQaj6nkF5KKS3TQtQ5qCzkOkmxIe3KRbBy - mXxkb5qwUpX5ELD5xFc6FeiafWYY63TmmEAu_lRFCOJ3xDea-ots", - "qi":"lSQi-w9CpyUReMErP1RsBLk7wNtOvs5EQpPqmuMvqW57NBUczScEoPwmUqq - abu9V0-Py4dQ57_bapoKRu1R90bvuFnU63SHWEFglZQvJDMeAvmj4sm-Fp0o - Yu_neotgQ0hzbI5gry7ajdYy9-2lNx_76aBZoOUu9HCJ-UsfSOI8"}`), - - // X.509 Certificate Chain - stripWhitespace(`{"kty":"RSA", - "use":"sig", - "kid":"1b94c", - "n":"vrjOfz9Ccdgx5nQudyhdoR17V-IubWMeOZCwX_jj0hgAsz2J_pqYW08 - PLbK_PdiVGKPrqzmDIsLI7sA25VEnHU1uCLNwBuUiCO11_-7dYbsr4iJmG0Q - u2j8DsVyT1azpJC_NG84Ty5KKthuCaPod7iI7w0LK9orSMhBEwwZDCxTWq4a - YWAchc8t-emd9qOvWtVMDC2BXksRngh6X5bUYLy6AyHKvj-nUy1wgzjYQDwH - MTplCoLtU-o-8SNnZ1tmRoGE9uJkBLdh5gFENabWnU5m1ZqZPdwS-qo-meMv - VfJb6jJVWRpl2SUtCnYG2C32qvbWbjZ_jBPD5eunqsIo1vQ", - "e":"AQAB", - "x5c": - ["MIIDQjCCAiqgAwIBAgIGATz/FuLiMA0GCSqGSIb3DQEBBQUAMGIxCzAJB - gNVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRwwGgYD - VQQKExNQaW5nIElkZW50aXR5IENvcnAuMRcwFQYDVQQDEw5CcmlhbiBDYW1 - wYmVsbDAeFw0xMzAyMjEyMzI5MTVaFw0xODA4MTQyMjI5MTVaMGIxCzAJBg - NVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRwwGgYDV - QQKExNQaW5nIElkZW50aXR5IENvcnAuMRcwFQYDVQQDEw5CcmlhbiBDYW1w - YmVsbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL64zn8/QnH - YMeZ0LncoXaEde1fiLm1jHjmQsF/449IYALM9if6amFtPDy2yvz3YlRij66 - s5gyLCyO7ANuVRJx1NbgizcAblIgjtdf/u3WG7K+IiZhtELto/A7Fck9Ws6 - SQvzRvOE8uSirYbgmj6He4iO8NCyvaK0jIQRMMGQwsU1quGmFgHIXPLfnpn - fajr1rVTAwtgV5LEZ4Iel+W1GC8ugMhyr4/p1MtcIM42EA8BzE6ZQqC7VPq - PvEjZ2dbZkaBhPbiZAS3YeYBRDWm1p1OZtWamT3cEvqqPpnjL1XyW+oyVVk - aZdklLQp2Btgt9qr21m42f4wTw+Xrp6rCKNb0CAwEAATANBgkqhkiG9w0BA - QUFAAOCAQEAh8zGlfSlcI0o3rYDPBB07aXNswb4ECNIKG0CETTUxmXl9KUL - +9gGlqCz5iWLOgWsnrcKcY0vXPG9J1r9AqBNTqNgHq2G03X09266X5CpOe1 - zFo+Owb1zxtp3PehFdfQJ610CDLEaS9V9Rqp17hCyybEpOGVwe8fnk+fbEL - 2Bo3UPGrpsHzUoaGpDftmWssZkhpBJKVMJyf/RuP2SmmaIzmnw9JiSlYhzo - 4tpzd5rFXhjRbg4zW9C+2qok+2+qDM1iJ684gPHMIY8aLWrdgQTxkumGmTq - gawR+N5MDtdPTEQ0XfIBc2cJEUyMTY5MPvACWpkA6SdS4xSvdXK3IVfOWA=="]}`), -} - -// SHA-256 thumbprints of the above keys, hex-encoded -var cookbookJWKThumbprints = []string{ - "747ae2dd2003664aeeb21e4753fe7402846170a16bc8df8f23a8cf06d3cbe793", - "f6934029a341ddf81dceb753e91d17efe16664f40d9f4ed84bc5ea87e111f29d", - "747ae2dd2003664aeeb21e4753fe7402846170a16bc8df8f23a8cf06d3cbe793", - "f63838e96077ad1fc01c3f8405774dedc0641f558ebb4b40dccf5f9b6d66a932", - "0fc478f8579325fcee0d4cbc6d9d1ce21730a6e97e435d6008fb379b0ebe47d4", - "0ddb05bfedbec2070fa037324ba397396561d3425d6d69245570c261dc49dee3", -} - -func TestWebKeyVectorsValid(t *testing.T) { - for _, key := range cookbookJWKs { - var jwk2 JSONWebKey - err := jwk2.UnmarshalJSON([]byte(key)) - if err != nil { - t.Error("unable to parse valid key:", key, err) - } - } -} - -func TestThumbprint(t *testing.T) { - for i, key := range cookbookJWKs { - var jwk2 JSONWebKey - err := jwk2.UnmarshalJSON([]byte(key)) - if err != nil { - t.Error("unable to parse valid key:", key, err) - } - - tp, err := jwk2.Thumbprint(crypto.SHA256) - if err != nil { - t.Error("unable to compute thumbprint:", key, err) - } - - tpHex := hex.EncodeToString(tp) - if cookbookJWKThumbprints[i] != tpHex { - t.Error("incorrect thumbprint:", i, cookbookJWKThumbprints[i], tpHex) - } - } -} - -func TestMarshalUnmarshalJWKSet(t *testing.T) { - jwk1 := JSONWebKey{Key: rsaTestKey, KeyID: "ABCDEFG", Algorithm: "foo"} - jwk2 := JSONWebKey{Key: rsaTestKey, KeyID: "GFEDCBA", Algorithm: "foo"} - var set JSONWebKeySet - set.Keys = append(set.Keys, jwk1) - set.Keys = append(set.Keys, jwk2) - - jsonbar, err := json.Marshal(&set) - if err != nil { - t.Error("problem marshalling set", err) - } - var set2 JSONWebKeySet - err = json.Unmarshal(jsonbar, &set2) - if err != nil { - t.Error("problem unmarshalling set", err) - } - jsonbar2, err := json.Marshal(&set2) - if err != nil { - t.Error("problem marshalling set", err) - } - if !bytes.Equal(jsonbar, jsonbar2) { - t.Error("roundtrip should not lose information") - } -} - -func TestJWKSetKey(t *testing.T) { - jwk1 := JSONWebKey{Key: rsaTestKey, KeyID: "ABCDEFG", Algorithm: "foo"} - jwk2 := JSONWebKey{Key: rsaTestKey, KeyID: "GFEDCBA", Algorithm: "foo"} - var set JSONWebKeySet - set.Keys = append(set.Keys, jwk1) - set.Keys = append(set.Keys, jwk2) - k := set.Key("ABCDEFG") - if len(k) != 1 { - t.Errorf("method should return slice with one key not %d", len(k)) - } - if k[0].KeyID != "ABCDEFG" { - t.Error("method should return key with ID ABCDEFG") - } -} - -func TestJWKSymmetricKey(t *testing.T) { - sample1 := `{"kty":"oct","alg":"A128KW","k":"GawgguFyGrWKav7AX4VKUg"}` - sample2 := `{"kty":"oct","k":"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow","kid":"HMAC key used in JWS spec Appendix A.1 example"}` - - var jwk1 JSONWebKey - json.Unmarshal([]byte(sample1), &jwk1) - - if jwk1.Algorithm != "A128KW" { - t.Errorf("expected Algorithm to be A128KW, but was '%s'", jwk1.Algorithm) - } - expected1 := fromHexBytes("19ac2082e1721ab58a6afec05f854a52") - if !bytes.Equal(jwk1.Key.([]byte), expected1) { - t.Errorf("expected Key to be '%s', but was '%s'", hex.EncodeToString(expected1), hex.EncodeToString(jwk1.Key.([]byte))) - } - - var jwk2 JSONWebKey - json.Unmarshal([]byte(sample2), &jwk2) - - if jwk2.KeyID != "HMAC key used in JWS spec Appendix A.1 example" { - t.Errorf("expected KeyID to be 'HMAC key used in JWS spec Appendix A.1 example', but was '%s'", jwk2.KeyID) - } - expected2 := fromHexBytes(` - 0323354b2b0fa5bc837e0665777ba68f5ab328e6f054c928a90f84b2d2502ebf - d3fb5a92d20647ef968ab4c377623d223d2e2172052e4f08c0cd9af567d080a3`) - if !bytes.Equal(jwk2.Key.([]byte), expected2) { - t.Errorf("expected Key to be '%s', but was '%s'", hex.EncodeToString(expected2), hex.EncodeToString(jwk2.Key.([]byte))) - } -} - -func TestJWKSymmetricRoundtrip(t *testing.T) { - jwk1 := JSONWebKey{Key: []byte{1, 2, 3, 4}} - marshaled, err := jwk1.MarshalJSON() - if err != nil { - t.Error("failed to marshal valid JWK object", err) - } - - var jwk2 JSONWebKey - err = jwk2.UnmarshalJSON(marshaled) - if err != nil { - t.Error("failed to unmarshal valid JWK object", err) - } - - if !bytes.Equal(jwk1.Key.([]byte), jwk2.Key.([]byte)) { - t.Error("round-trip of symmetric JWK gave different raw keys") - } -} - -func TestJWKSymmetricInvalid(t *testing.T) { - invalid := JSONWebKey{} - _, err := invalid.MarshalJSON() - if err == nil { - t.Error("excepted error on marshaling invalid symmetric JWK object") - } - - var jwk JSONWebKey - err = jwk.UnmarshalJSON([]byte(`{"kty":"oct"}`)) - if err == nil { - t.Error("excepted error on unmarshaling invalid symmetric JWK object") - } -} - -func TestJWKIsPublic(t *testing.T) { - bigInt := big.NewInt(0) - eccPub := ecdsa.PublicKey{elliptic.P256(), bigInt, bigInt} - rsaPub := rsa.PublicKey{bigInt, 1} - - cases := []struct { - key interface{} - expectedIsPublic bool - }{ - {&eccPub, true}, - {&ecdsa.PrivateKey{eccPub, bigInt}, false}, - {&rsaPub, true}, - {&rsa.PrivateKey{rsaPub, bigInt, []*big.Int{bigInt, bigInt}, rsa.PrecomputedValues{}}, false}, - {ed25519PublicKey, true}, - {ed25519PrivateKey, false}, - } - - for _, tc := range cases { - k := &JSONWebKey{Key: tc.key} - if public := k.IsPublic(); public != tc.expectedIsPublic { - t.Errorf("expected IsPublic to return %t, got %t", tc.expectedIsPublic, public) - } - } -} - -func TestJWKValid(t *testing.T) { - bigInt := big.NewInt(0) - eccPub := ecdsa.PublicKey{elliptic.P256(), bigInt, bigInt} - rsaPub := rsa.PublicKey{bigInt, 1} - edPubEmpty := ed25519.PublicKey([]byte{}) - edPrivEmpty := ed25519.PublicKey([]byte{}) - - cases := []struct { - key interface{} - expectedValidity bool - }{ - {nil, false}, - {&ecdsa.PublicKey{}, false}, - {&eccPub, true}, - {&ecdsa.PrivateKey{}, false}, - {&ecdsa.PrivateKey{eccPub, bigInt}, true}, - {&rsa.PublicKey{}, false}, - {&rsaPub, true}, - {&rsa.PrivateKey{}, false}, - {&rsa.PrivateKey{rsaPub, bigInt, []*big.Int{bigInt, bigInt}, rsa.PrecomputedValues{}}, true}, - {ed25519PublicKey, true}, - {ed25519PrivateKey, true}, - {edPubEmpty, false}, - {edPrivEmpty, false}, - } - - for _, tc := range cases { - k := &JSONWebKey{Key: tc.key} - valid := k.Valid() - if valid != tc.expectedValidity { - t.Errorf("expected Valid to return %t, got %t", tc.expectedValidity, valid) - } - if valid { - wasPublic := k.IsPublic() - p := k.Public() // all aforemention keys are asymmetric - if !p.Valid() { - t.Errorf("unable to derive public key from valid asymmetric key") - } - if wasPublic != k.IsPublic() { - t.Errorf("original key was touched during public key derivation") - } - } - } -} diff --git a/vendor/gopkg.in/square/go-jose.v2/jws_test.go b/vendor/gopkg.in/square/go-jose.v2/jws_test.go deleted file mode 100644 index 1b80419dd..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/jws_test.go +++ /dev/null @@ -1,616 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jose - -import ( - "crypto/x509" - "strings" - "testing" -) - -const trustedCA = ` ------BEGIN CERTIFICATE----- -MIIE6DCCAtCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDEwlUcnVz -dGVkQ0EwHhcNMTgwMzI4MTg0MzA0WhcNMzgwMzI4MTg0MzA0WjAUMRIwEAYDVQQD -EwlUcnVzdGVkQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCsHcd3 -uaKBilWQUe2epNf86xvq2HZV+JDULjJlKfUQAkpG+huHDEMiPEFPSlQK17bFj7gc -qOx/INeeCU2nBVtZDtlm3U0jfQWO2F2kZgH1JWnEArrAWWy3BP/NYv7apBLcl7nD -hkL4USVUnXF8mtuegiSMI2YT7TVchGzYMjrj/j+oRuDm1GF1OxoIMeUuVmqyJ6jK -Kxv9YVmCB+e/QaUltkPGwxl2dKWdBwECXDgSr7hcZhT8ANmgFR1dJjLCy0Us12yw -5eKUANDlfNP+z9urykoAwHXpBlmga1ze45aL+p+7K+8sl/PgMqKO7VdT5GBsOCzf -xaBDG5Qy92Di34Sc27ZZz0mfaIy5kySnceBclMyWb8vdhEGkyHVsGpWc63JBmtg+ -bKeh876m7KVLfiykfpMqHUhq/ImQwiQTwX2RonFK5gP+XU0I9V+4rE0iqucbcvCS -HuHzhf6B+TybhalRsvOZ6GB/SokF5YCmf8ylAq4be/HSxnJQcBhpSSQp0zz4ZKOD -ikXuwf29yhWZ0lgIyaZpT9H4QecWNcyx4UcqO3wQAGjxadTG3gzjLu/OJwPkw+bK -RvXWSBZjlQ9+JPmrHH+oKMgHshR4TQmtmXqXLaarrAe+HXCZEiBKFOqPgeo2RMxr -LAO+MYIsVtEz39gISRhEvqcAls01sV1l7oGicQIDAQABo0UwQzAOBgNVHQ8BAf8E -BAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUy9Nqk0mDRwC5tcmN -xQ1YWO5MAhgwDQYJKoZIhvcNAQELBQADggIBAHbpsqY+tPSj8BSky+acZoZjF7fZ -Ae3MKVogwm5tecmwTKf5xDj9J99ZpGvcWCKtoxxWw0LZ+JI/aeqANSRDXZIelcIw -yZefw06z/coQJwAIy1RSoKJPV72mkG0Es9w2HxSEoLaZ9tql0TyV8D/QseUM8Yt/ -nNtShRoj6iMnZjhmut5pLfrLWHwQkt4fguBpL7rtydS/wAsOmnJ7lmOrU6zrBJzD -vEER3AJtgdIt4GvKf4MupKLgKvYDB4sUQVmMyAS78B9+WZDDRTClsx+/Oc1ggkWz -8X7EmIw+3U9V2hd67qZ81EwcSB8ixV06E7ZcbhnJs7ds7swqUjwMArFWuzqO4cjW -2BnyVzCO9pymFLI7qol32xCEgaQlOVS/kFHP3meygfeaeYe902sJw6NevOA4e0AO -AKR8FDfGRXJ9cOmYzeHeWKex8yt1Ul6+N8SXzjOhf39JM0QqTfHN7pPfFthTAFOs -9rI/buJteJqR1WxgVk/jY4wLGEOcEyO6Y/Uj5iWWTvm5G/C1yZfSg+NvWoytxZ7P -3S0qtEfmT4UwuHBsd5ZfEZoxb+GbqL/nhrKz/0B9LyKS0SJP9+mz7nSORz7t35Uc -BhiG6T9W7P/NRW4Tqb2tEN1VwU6eP5SEf7c7C1VVaepk0fvc1p5dl67IERqPucPD -dT2rDsCMBV7SXMUM ------END CERTIFICATE-----` - -const intermediateCA = ` ------BEGIN CERTIFICATE----- -MIIEHTCCAgWgAwIBAgIQXzZsEQv0cvSRLJAkS9FmWTANBgkqhkiG9w0BAQsFADAU -MRIwEAYDVQQDEwlUcnVzdGVkQ0EwHhcNMTgwMzI4MTg0MzMzWhcNMzgwMzI4MTg0 -MzAzWjAZMRcwFQYDVQQDEw5JbnRlcm1lZGlhdGVDQTCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAN3aYpH/1yEYf/kHuHWyO3AO4tgwlYYLhCDT2GvaPdaE -cqhe/VuYiqx3xY7IRDqsW2rau/OXgW6KzLHdRZHogK07hUj1Lfr7X+Oqbp22IV4y -dyiL7jwK9AtVXvDuuv5ET+oRfV82j0uhyk0ueGD9r6C/h+6NTzHBD+3xo6Yuc0Vk -BfY5zIyhaFqlm1aRYvupDRjC/63uBgAlrGxy2LyiTMVnYMuxoJM5ahDepz3sqjuN -WVyPhfGwIezjXuXRdEvlmWX05XLnsTdP4zu4fHq9Z7c3TKWWONM3z64ECAZmGQVf -MAcEDX7qP0gZX5PCT+0WcvTgTWE4Q+WIh5AmYyxQ04cCAwEAAaNmMGQwDgYDVR0P -AQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFMAYlq86RZzT -WxLpYE7KTTM7DHOuMB8GA1UdIwQYMBaAFMvTapNJg0cAubXJjcUNWFjuTAIYMA0G -CSqGSIb3DQEBCwUAA4ICAQBmYRpQoWEm5g16kwUrpwWrH7OIqqMtUhM1dcskECfk -i3/hcsV+MQRkGHLIItucYIWqs7oOQIglsyGcohAbnvE1PVtKKojUHC0lfbjgIenD -Pbvz15QB6A3KLDR82QbQGeGniACy924p66zlfPwHJbkMo5ZaqtNqI//EIa2YCpyy -okhFXaSFmPWXXrTOCsEEsFJKsoSCH1KUpTcwACGkkilNseg1edZB6/lBDwybxVuY -+dbUlHip3r5tFcP66Co3tKAaEcVY0AsZ/8GKwH+IM2AR6q7jdn9Gp2OX4E1ul9Wy -+hW5GHMmfixkgTVwRowuKgkCPEKV2/Xy3k9rlSpnKr2NpYYq0mu6An9HYt8THQ+e -wGZHwWufuDFDWuzlu7CxFOjpXLKv8qqVnwSFC91S3HsPAzPKLC9ZMEC+iQs2Vkes -Os0nFLZeMaMGAO5W6xiyQ5p94oo0bqa1XbmSV1bNp1HWuNEGIiZKrEUDxfYuDc6f -C6hJZKsjJkMkBeadlQAlLcjIx1rDV171CKLLTxy/dT5kv4p9UrJlnleyMVG6S/3d -6nX/WLSgZIMYbOwiZVVPlSrobuG38ULJMCSuxndxD0l+HahJaH8vYXuR67A0XT+b -TEe305AI6A/9MEaRrActBnq6/OviQgBsKAvtTv1FmDbnpZsKeoFuwc3OPdTveQdC -RA== ------END CERTIFICATE-----` - -func TestEmbeddedHMAC(t *testing.T) { - // protected: {"alg":"HS256", "jwk":{"kty":"oct", "k":"MTEx"}}, aka HMAC key. - msg := `{"payload":"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ","protected":"eyJhbGciOiJIUzI1NiIsICJqd2siOnsia3R5Ijoib2N0IiwgImsiOiJNVEV4In19","signature":"lvo41ZZsuHwQvSh0uJtEXRR3vmuBJ7in6qMoD7p9jyo"}` - - _, err := ParseSigned(msg) - if err == nil { - t.Error("should not allow parsing JWS with embedded JWK with HMAC key") - } -} - -func TestCompactParseJWS(t *testing.T) { - // Should parse - msg := "eyJhbGciOiJYWVoifQ.cGF5bG9hZA.c2lnbmF0dXJl" - _, err := ParseSigned(msg) - if err != nil { - t.Error("Unable to parse valid message:", err) - } - - // Should parse (detached signature missing payload) - msg = "eyJhbGciOiJYWVoifQ..c2lnbmF0dXJl" - _, err = ParseSigned(msg) - if err != nil { - t.Error("Unable to parse valid message:", err) - } - - // Messages that should fail to parse - failures := []string{ - // Not enough parts - "eyJhbGciOiJYWVoifQ.cGF5bG9hZA", - // Invalid signature - "eyJhbGciOiJYWVoifQ.cGF5bG9hZA.////", - // Invalid payload - "eyJhbGciOiJYWVoifQ.////.c2lnbmF0dXJl", - // Invalid header - "////.eyJhbGciOiJYWVoifQ.c2lnbmF0dXJl", - // Invalid header - "cGF5bG9hZA.cGF5bG9hZA.c2lnbmF0dXJl", - } - - for i := range failures { - _, err = ParseSigned(failures[i]) - if err == nil { - t.Error("Able to parse invalid message") - } - } -} - -func TestFullParseJWS(t *testing.T) { - // Messages that should succeed to parse - successes := []string{ - "{\"payload\":\"CUJD\",\"signatures\":[{\"protected\":\"e30\",\"header\":{\"kid\":\"XYZ\"},\"signature\":\"CUJD\"},{\"protected\":\"e30\",\"signature\":\"CUJD\"}]}", - } - - for i := range successes { - _, err := ParseSigned(successes[i]) - if err != nil { - t.Error("Unble to parse valid message", err, successes[i]) - } - } - - // Messages that should fail to parse - failures := []string{ - // Empty - "{}", - // Invalid JSON - "{XX", - // Invalid protected header - "{\"payload\":\"CUJD\",\"signatures\":[{\"protected\":\"CUJD\",\"header\":{\"kid\":\"XYZ\"},\"signature\":\"CUJD\"}]}", - // Invalid protected header - "{\"payload\":\"CUJD\",\"protected\":\"CUJD\",\"header\":{\"kid\":\"XYZ\"},\"signature\":\"CUJD\"}", - // Invalid protected header - "{\"payload\":\"CUJD\",\"signatures\":[{\"protected\":\"###\",\"header\":{\"kid\":\"XYZ\"},\"signature\":\"CUJD\"}]}", - // Invalid payload - "{\"payload\":\"###\",\"signatures\":[{\"protected\":\"CUJD\",\"header\":{\"kid\":\"XYZ\"},\"signature\":\"CUJD\"}]}", - // Invalid payload - "{\"payload\":\"CUJD\",\"signatures\":[{\"protected\":\"e30\",\"header\":{\"kid\":\"XYZ\"},\"signature\":\"###\"}]}", - } - - for i := range failures { - _, err := ParseSigned(failures[i]) - if err == nil { - t.Error("Able to parse invalid message", err, failures[i]) - } - } -} - -func TestRejectUnprotectedJWSNonce(t *testing.T) { - // No need to test compact, since that's always protected - - // Flattened JSON - input := `{ - "header": { "nonce": "should-cause-an-error" }, - "payload": "does-not-matter", - "signature": "does-not-matter" - }` - _, err := ParseSigned(input) - if err == nil { - t.Error("JWS with an unprotected nonce parsed as valid.") - } else if err != ErrUnprotectedNonce { - t.Errorf("Improper error for unprotected nonce: %v", err) - } - - // Full JSON - input = `{ - "payload": "does-not-matter", - "signatures": [{ - "header": { "nonce": "should-cause-an-error" }, - "signature": "does-not-matter" - }] - }` - _, err = ParseSigned(input) - if err == nil { - t.Error("JWS with an unprotected nonce parsed as valid.") - } else if err != ErrUnprotectedNonce { - t.Errorf("Improper error for unprotected nonce: %v", err) - } -} - -func TestVerifyFlattenedWithIncludedUnprotectedKey(t *testing.T) { - input := `{ - "header": { - "alg": "RS256", - "jwk": { - "e": "AQAB", - "kty": "RSA", - "n": "tSwgy3ORGvc7YJI9B2qqkelZRUC6F1S5NwXFvM4w5-M0TsxbFsH5UH6adigV0jzsDJ5imAechcSoOhAh9POceCbPN1sTNwLpNbOLiQQ7RD5mY_pSUHWXNmS9R4NZ3t2fQAzPeW7jOfF0LKuJRGkekx6tXP1uSnNibgpJULNc4208dgBaCHo3mvaE2HV2GmVl1yxwWX5QZZkGQGjNDZYnjFfa2DKVvFs0QbAk21ROm594kAxlRlMMrvqlf24Eq4ERO0ptzpZgm_3j_e4hGRD39gJS7kAzK-j2cacFQ5Qi2Y6wZI2p-FCq_wiYsfEAIkATPBiLKl_6d_Jfcvs_impcXQ" - } - }, - "payload": "Zm9vCg", - "signature": "hRt2eYqBd_MyMRNIh8PEIACoFtmBi7BHTLBaAhpSU6zyDAFdEBaX7us4VB9Vo1afOL03Q8iuoRA0AT4akdV_mQTAQ_jhTcVOAeXPr0tB8b8Q11UPQ0tXJYmU4spAW2SapJIvO50ntUaqU05kZd0qw8-noH1Lja-aNnU-tQII4iYVvlTiRJ5g8_CADsvJqOk6FcHuo2mG643TRnhkAxUtazvHyIHeXMxydMMSrpwUwzMtln4ZJYBNx4QGEq6OhpAD_VSp-w8Lq5HOwGQoNs0bPxH1SGrArt67LFQBfjlVr94E1sn26p4vigXm83nJdNhWAMHHE9iV67xN-r29LT-FjA" - }` - - jws, err := ParseSigned(input) - if err != nil { - t.Error("Unable to parse valid message.") - } - if len(jws.Signatures) != 1 { - t.Error("Too many or too few signatures.") - } - sig := jws.Signatures[0] - if sig.Header.JSONWebKey == nil { - t.Error("No JWK in signature header.") - } - payload, err := jws.Verify(sig.Header.JSONWebKey) - if err != nil { - t.Errorf("Signature did not validate: %v", err) - } - if string(payload) != "foo\n" { - t.Errorf("Payload was incorrect: '%s' should have been 'foo\\n'", string(payload)) - } -} - -// Test verification of a detached signature -func TestDetachedVerifyJWS(t *testing.T) { - rsaPublicKey, err := x509.ParsePKIXPublicKey(fromBase64Bytes(` - MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3aLSGwbeX0ZA2Ha+EvELaIFGzO - 91+Q15JQc/tdGdCgGW3XAbrh7ZUhDh1XKzbs+UOQxqn3Eq4YOx18IG0WsJSuCaHQIxnDlZ - t/GP8WLwjMC0izlJLm2SyfM/EEoNpmTC3w6MQ2dHK7SZ9Zoq+sKijQd+V7CYdr8zHMpDrd - NKoEcR0HjmvzzdMoUChhkGH5TaNbZyollULTggepaYUKS8QphqdSDMWiSetKG+g6V87lv6 - CVYyK1FF6g7Esp5OOj5pNn3/bmF+7V+b7TvK91NCIlURCjE9toRgNoIP4TDnWRn/vvfZ3G - zNrtWmlizqz3r5KdvIs71ahWgMUSD4wfazrwIDAQAB`)) - if err != nil { - t.Fatal(err) - } - - sampleMessages := []string{ - "eyJhbGciOiJSUzI1NiJ9.TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ.YHX849fvekz6wJGeyqnQhFqyHFcUXNJKj3o2w3ddR46YLlsCopUJrlifRU_ZuTWzpYxt5oC--T2eoqMhlCvltSWrE5_1_EumqiMfAYsZULx9E6Jns7q3w7mttonYFSIh7aR3-yg2HMMfTCgoAY1y_AZ4VjXwHDcZ5gu1oZDYgvZF4uXtCmwT6e5YtR1m8abiWPF8BgoTG_BD3KV6ClLj_QQiNFdfdxAMDw7vKVOKG1T7BFtz6cDs2Q3ILS4To5E2IjcVSSYS8mi77EitCrWmrqbK_G3WCdKeUFGnMnyuKXaCDy_7FLpAZ6Z5RomRr5iskXeJZdZqIKcJV8zl4fpsPA", - "eyJhbGciOiJSUzM4NCJ9.TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ.meyfoOTjAAjXHFYiNlU7EEnsYtbeUYeEglK6BL_cxISEr2YAGLr1Gwnn2HnucTnH6YilyRio7ZC1ohy_ZojzmaljPHqpr8kn1iqNFu9nFE2M16ZPgJi38-PGzppcDNliyzOQO-c7L-eA-v8Gfww5uyRaOJdiWg-hUJmeGBIngPIeLtSVmhJtz8oTeqeNdUOqQv7f7VRCuvagLhW1PcEM91VUS-gS0WEUXoXWZ2lp91No0v1O24izgX3__FKiX_16XhrOfAgJ82F61vjbTIQYwhexHPZyYTlXYt_scNRzFGhSKeGFin4zVdFLOXWJqKWdUd5IrDP5Nya3FSoWbWDXAg", - } - - for _, msg := range sampleMessages { - obj, err := ParseSigned(msg) - if err != nil { - t.Error("unable to parse message", msg, err) - continue - } - payload := obj.payload - obj.payload = nil - err = obj.DetachedVerify(payload, rsaPublicKey) - if err != nil { - t.Error("unable to verify message", msg, err) - continue - } - idx, _, err := obj.DetachedVerifyMulti(payload, rsaPublicKey) - if idx != 0 || err != nil { - t.Error("unable to verify message", msg, err) - continue - } - } -} - -func TestVerifyFlattenedWithPrivateProtected(t *testing.T) { - // The protected field contains a Private Header Parameter name, per - // https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-41#section-4 - // Base64-decoded, it's '{"nonce":"8HIepUNFZUa-exKTrXVf4g"}' - input := `{"header":{"alg":"RS256","jwk":{"kty":"RSA","n":"7ixeydcbxxppzxrBphrW1atUiEZqTpiHDpI-79olav5XxAgWolHmVsJyxzoZXRxmtED8PF9-EICZWBGdSAL9ZTD0hLUCIsPcpdgT_LqNW3Sh2b2caPL2hbMF7vsXvnCGg9varpnHWuYTyRrCLUF9vM7ES-V3VCYTa7LcCSRm56Gg9r19qar43Z9kIKBBxpgt723v2cC4bmLmoAX2s217ou3uCpCXGLOeV_BesG4--Nl3pso1VhCfO85wEWjmW6lbv7Kg4d7Jdkv5DjDZfJ086fkEAYZVYGRpIgAvJBH3d3yKDCrSByUEud1bWuFjQBmMaeYOrVDXO_mbYg5PwUDMhw","e":"AQAB"}},"protected":"eyJub25jZSI6IjhISWVwVU5GWlVhLWV4S1RyWFZmNGcifQ","payload":"eyJjb250YWN0IjpbIm1haWx0bzpmb29AYmFyLmNvbSJdfQ","signature":"AyvVGMgXsQ1zTdXrZxE_gyO63pQgotL1KbI7gv6Wi8I7NRy0iAOkDAkWcTQT9pcCYApJ04lXfEDZfP5i0XgcFUm_6spxi5mFBZU-NemKcvK9dUiAbXvb4hB3GnaZtZiuVnMQUb_ku4DOaFFKbteA6gOYCnED_x7v0kAPHIYrQnvIa-KZ6pTajbV9348zgh9TL7NgGIIsTcMHd-Jatr4z1LQ0ubGa8tS300hoDhVzfoDQaEetYjCo1drR1RmdEN1SIzXdHOHfubjA3ZZRbrF_AJnNKpRRoIwzu1VayOhRmdy1qVSQZq_tENF4VrQFycEL7DhG7JLoXC4T2p1urwMlsw"}` - - jws, err := ParseSigned(input) - if err != nil { - t.Error("Unable to parse valid message.") - } - if len(jws.Signatures) != 1 { - t.Error("Too many or too few signatures.") - } - sig := jws.Signatures[0] - if sig.Header.JSONWebKey == nil { - t.Error("No JWK in signature header.") - } - payload, err := jws.Verify(sig.Header.JSONWebKey) - if err != nil { - t.Errorf("Signature did not validate: %v", err) - } - expected := "{\"contact\":[\"mailto:foo@bar.com\"]}" - if string(payload) != expected { - t.Errorf("Payload was incorrect: '%s' should have been '%s'", string(payload), expected) - } -} - -// Test vectors generated with nimbus-jose-jwt -func TestSampleNimbusJWSMessagesRSA(t *testing.T) { - rsaPublicKey, err := x509.ParsePKIXPublicKey(fromBase64Bytes(` - MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3aLSGwbeX0ZA2Ha+EvELaIFGzO - 91+Q15JQc/tdGdCgGW3XAbrh7ZUhDh1XKzbs+UOQxqn3Eq4YOx18IG0WsJSuCaHQIxnDlZ - t/GP8WLwjMC0izlJLm2SyfM/EEoNpmTC3w6MQ2dHK7SZ9Zoq+sKijQd+V7CYdr8zHMpDrd - NKoEcR0HjmvzzdMoUChhkGH5TaNbZyollULTggepaYUKS8QphqdSDMWiSetKG+g6V87lv6 - CVYyK1FF6g7Esp5OOj5pNn3/bmF+7V+b7TvK91NCIlURCjE9toRgNoIP4TDnWRn/vvfZ3G - zNrtWmlizqz3r5KdvIs71ahWgMUSD4wfazrwIDAQAB`)) - if err != nil { - panic(err) - } - - rsaSampleMessages := []string{ - "eyJhbGciOiJSUzI1NiJ9.TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ.YHX849fvekz6wJGeyqnQhFqyHFcUXNJKj3o2w3ddR46YLlsCopUJrlifRU_ZuTWzpYxt5oC--T2eoqMhlCvltSWrE5_1_EumqiMfAYsZULx9E6Jns7q3w7mttonYFSIh7aR3-yg2HMMfTCgoAY1y_AZ4VjXwHDcZ5gu1oZDYgvZF4uXtCmwT6e5YtR1m8abiWPF8BgoTG_BD3KV6ClLj_QQiNFdfdxAMDw7vKVOKG1T7BFtz6cDs2Q3ILS4To5E2IjcVSSYS8mi77EitCrWmrqbK_G3WCdKeUFGnMnyuKXaCDy_7FLpAZ6Z5RomRr5iskXeJZdZqIKcJV8zl4fpsPA", - "eyJhbGciOiJSUzM4NCJ9.TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ.meyfoOTjAAjXHFYiNlU7EEnsYtbeUYeEglK6BL_cxISEr2YAGLr1Gwnn2HnucTnH6YilyRio7ZC1ohy_ZojzmaljPHqpr8kn1iqNFu9nFE2M16ZPgJi38-PGzppcDNliyzOQO-c7L-eA-v8Gfww5uyRaOJdiWg-hUJmeGBIngPIeLtSVmhJtz8oTeqeNdUOqQv7f7VRCuvagLhW1PcEM91VUS-gS0WEUXoXWZ2lp91No0v1O24izgX3__FKiX_16XhrOfAgJ82F61vjbTIQYwhexHPZyYTlXYt_scNRzFGhSKeGFin4zVdFLOXWJqKWdUd5IrDP5Nya3FSoWbWDXAg", - "eyJhbGciOiJSUzUxMiJ9.TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ.rQPz0PDh8KyE2AX6JorgI0MLwv-qi1tcWlz6tuZuWQG1hdrlzq5tR1tQg1evYNc_SDDX87DWTSKXT7JEqhKoFixLfZa13IJrOc7FB8r5ZLx7OwOBC4F--OWrvxMA9Y3MTJjPN3FemQePUo-na2vNUZv-YgkcbuOgbO3hTxwQ7j1JGuqy-YutXOFnccdXvntp3t8zYZ4Mg1It_IyL9pzgGqHIEmMV1pCFGHsDa-wStB4ffmdhrADdYZc0q_SvxUdobyC_XzZCz9ENzGIhgwYxyyrqg7kjqUGoKmCLmoSlUFW7goTk9IC5SXdUyLPuESxOWNfHoRClGav230GYjPFQFA", - "eyJhbGciOiJQUzI1NiJ9.TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ.UTtxjsv_6x4CdlAmZfAW6Lun3byMjJbcwRp_OlPH2W4MZaZar7aql052mIB_ddK45O9VUz2aphYVRvKPZY8WHmvlTUU30bk0z_cDJRYB9eIJVMOiRCYj0oNkz1iEZqsP0YgngxwuUDv4Q4A6aJ0Bo5E_rZo3AnrVHMHUjPp_ZRRSBFs30tQma1qQ0ApK4Gxk0XYCYAcxIv99e78vldVRaGzjEZmQeAVZx4tGcqZP20vG1L84nlhSGnOuZ0FhR8UjRFLXuob6M7EqtMRoqPgRYw47EI3fYBdeSivAg98E5S8R7R1NJc7ef-l03RvfUSY0S3_zBq_4PlHK6A-2kHb__w", - "eyJhbGciOiJSUzM4NCJ9.TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ.meyfoOTjAAjXHFYiNlU7EEnsYtbeUYeEglK6BL_cxISEr2YAGLr1Gwnn2HnucTnH6YilyRio7ZC1ohy_ZojzmaljPHqpr8kn1iqNFu9nFE2M16ZPgJi38-PGzppcDNliyzOQO-c7L-eA-v8Gfww5uyRaOJdiWg-hUJmeGBIngPIeLtSVmhJtz8oTeqeNdUOqQv7f7VRCuvagLhW1PcEM91VUS-gS0WEUXoXWZ2lp91No0v1O24izgX3__FKiX_16XhrOfAgJ82F61vjbTIQYwhexHPZyYTlXYt_scNRzFGhSKeGFin4zVdFLOXWJqKWdUd5IrDP5Nya3FSoWbWDXAg", - "eyJhbGciOiJSUzUxMiJ9.TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ.rQPz0PDh8KyE2AX6JorgI0MLwv-qi1tcWlz6tuZuWQG1hdrlzq5tR1tQg1evYNc_SDDX87DWTSKXT7JEqhKoFixLfZa13IJrOc7FB8r5ZLx7OwOBC4F--OWrvxMA9Y3MTJjPN3FemQePUo-na2vNUZv-YgkcbuOgbO3hTxwQ7j1JGuqy-YutXOFnccdXvntp3t8zYZ4Mg1It_IyL9pzgGqHIEmMV1pCFGHsDa-wStB4ffmdhrADdYZc0q_SvxUdobyC_XzZCz9ENzGIhgwYxyyrqg7kjqUGoKmCLmoSlUFW7goTk9IC5SXdUyLPuESxOWNfHoRClGav230GYjPFQFA", - } - - for _, msg := range rsaSampleMessages { - obj, err := ParseSigned(msg) - if err != nil { - t.Error("unable to parse message", msg, err) - continue - } - payload, err := obj.Verify(rsaPublicKey) - if err != nil { - t.Error("unable to verify message", msg, err) - continue - } - if string(payload) != "Lorem ipsum dolor sit amet" { - t.Error("payload is not what we expected for msg", msg) - } - } -} - -// Test vectors generated with nimbus-jose-jwt -func TestSampleNimbusJWSMessagesEC(t *testing.T) { - ecPublicKeyP256, err := x509.ParsePKIXPublicKey(fromBase64Bytes("MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIg62jq6FyL1otEj9Up7S35BUrwGF9TVrAzrrY1rHUKZqYIGEg67u/imjgadVcr7y9Q32I0gB8W8FHqbqt696rA==")) - if err != nil { - panic(err) - } - ecPublicKeyP384, err := x509.ParsePKIXPublicKey(fromBase64Bytes("MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEPXsVlqCtN2oTY+F+hFZm3M0ldYpb7IeeJM5wYmT0k1RaqzBFDhDMNnYK5Q5x+OyssZrAtHgYDFw02AVJhhng/eHRp7mqmL/vI3wbxJtrLKYldIbBA+9fYBQcKeibjlu5")) - if err != nil { - panic(err) - } - ecPublicKeyP521, err := x509.ParsePKIXPublicKey(fromBase64Bytes("MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAa2w3MMJ5FWD6tSf68G+Wy5jIhWXOD3IA7pE5IC/myQzo1lWcD8KS57SM6nm4POtPcxyLmDhL7FLuh8DKoIZyvtAAdK8+tOQP7XXRlT2bkvzIuazp05It3TAPu00YzTIpKfDlc19Y1lvf7etrbFqhShD92B+hHmhT4ddrdbPCBDW8hvU=")) - if err != nil { - panic(err) - } - - ecPublicKeys := []interface{}{ecPublicKeyP256, ecPublicKeyP384, ecPublicKeyP521} - - ecSampleMessages := []string{ - "eyJhbGciOiJFUzI1NiJ9.TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ.MEWJVlvGRQyzMEGOYm4rwuiwxrX-6LjnlbaRDAuhwmnBm2Gtn7pRpGXRTMFZUXsSGDz2L1p-Hz1qn8j9bFIBtQ", - "eyJhbGciOiJFUzM4NCJ9.TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ.nbdjPnJPYQtVNNdBIx8-KbFKplTxrz-hnW5UNhYUY7SBkwHK4NZnqc2Lv4DXoA0aWHq9eiypgOh1kmyPWGEmqKAHUx0xdIEkBoHk3ZsbmhOQuq2jL_wcMUG6nTWNhLrB", - "eyJhbGciOiJFUzUxMiJ9.TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ.AeYNFC1rwIgQv-5fwd8iRyYzvTaSCYTEICepgu9gRId-IW99kbSVY7yH0MvrQnqI-a0L8zwKWDR35fW5dukPAYRkADp3Y1lzqdShFcEFziUVGo46vqbiSajmKFrjBktJcCsfjKSaLHwxErF-T10YYPCQFHWb2nXJOOI3CZfACYqgO84g", - } - - for i, msg := range ecSampleMessages { - obj, err := ParseSigned(msg) - if err != nil { - t.Error("unable to parse message", msg, err) - continue - } - payload, err := obj.Verify(ecPublicKeys[i]) - if err != nil { - t.Error("unable to verify message", msg, err) - continue - } - if string(payload) != "Lorem ipsum dolor sit amet" { - t.Error("payload is not what we expected for msg", msg) - } - } -} - -// Test vectors generated with nimbus-jose-jwt -func TestSampleNimbusJWSMessagesHMAC(t *testing.T) { - hmacTestKey := fromHexBytes("DF1FA4F36FFA7FC42C81D4B3C033928D") - - hmacSampleMessages := []string{ - "eyJhbGciOiJIUzI1NiJ9.TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ.W5tc_EUhxexcvLYEEOckyyvdb__M5DQIVpg6Nmk1XGM", - "eyJhbGciOiJIUzM4NCJ9.TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ.sBu44lXOJa4Nd10oqOdYH2uz3lxlZ6o32QSGHaoGdPtYTDG5zvSja6N48CXKqdAh", - "eyJhbGciOiJIUzUxMiJ9.TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ.M0yR4tmipsORIix-BitIbxEPGaxPchDfj8UNOpKuhDEfnb7URjGvCKn4nOlyQ1z9mG1FKbwnqR1hOVAWSzAU_w", - } - - for _, msg := range hmacSampleMessages { - obj, err := ParseSigned(msg) - if err != nil { - t.Error("unable to parse message", msg, err) - continue - } - payload, err := obj.Verify(hmacTestKey) - if err != nil { - t.Error("unable to verify message", msg, err) - continue - } - if string(payload) != "Lorem ipsum dolor sit amet" { - t.Error("payload is not what we expected for msg", msg) - } - } -} - -func TestHeaderFieldsCompact(t *testing.T) { - msg := "eyJhbGciOiJFUzUxMiJ9.TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ.AeYNFC1rwIgQv-5fwd8iRyYzvTaSCYTEICepgu9gRId-IW99kbSVY7yH0MvrQnqI-a0L8zwKWDR35fW5dukPAYRkADp3Y1lzqdShFcEFziUVGo46vqbiSajmKFrjBktJcCsfjKSaLHwxErF-T10YYPCQFHWb2nXJOOI3CZfACYqgO84g" - - obj, err := ParseSigned(msg) - if err != nil { - t.Fatal("unable to parse message", msg, err) - } - if obj.Signatures[0].Header.Algorithm != "ES512" { - t.Error("merged header did not contain expected alg value") - } - if obj.Signatures[0].Protected.Algorithm != "ES512" { - t.Error("protected header did not contain expected alg value") - } - if obj.Signatures[0].Unprotected.Algorithm != "" { - t.Error("unprotected header contained an alg value") - } -} - -func TestHeaderFieldsFull(t *testing.T) { - msg := `{"payload":"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ","protected":"eyJhbGciOiJFUzUxMiJ9","header":{"custom":"test"},"signature":"AeYNFC1rwIgQv-5fwd8iRyYzvTaSCYTEICepgu9gRId-IW99kbSVY7yH0MvrQnqI-a0L8zwKWDR35fW5dukPAYRkADp3Y1lzqdShFcEFziUVGo46vqbiSajmKFrjBktJcCsfjKSaLHwxErF-T10YYPCQFHWb2nXJOOI3CZfACYqgO84g"}` - - obj, err := ParseSigned(msg) - if err != nil { - t.Fatal("unable to parse message", msg, err) - } - if obj.Signatures[0].Header.Algorithm != "ES512" { - t.Error("merged header did not contain expected alg value") - } - if obj.Signatures[0].Protected.Algorithm != "ES512" { - t.Error("protected header did not contain expected alg value") - } - if obj.Signatures[0].Unprotected.Algorithm != "" { - t.Error("unprotected header contained an alg value") - } - if obj.Signatures[0].Unprotected.ExtraHeaders["custom"] != "test" { - t.Error("unprotected header did not contain custom header value") - } -} - -// Test vectors generated with nimbus-jose-jwt -func TestErrorMissingPayloadJWS(t *testing.T) { - _, err := (&rawJSONWebSignature{}).sanitized() - if err == nil { - t.Error("was able to parse message with missing payload") - } - if !strings.Contains(err.Error(), "missing payload") { - t.Errorf("unexpected error message, should contain 'missing payload': %s", err) - } -} - -// Test that a null value in the header doesn't panic -func TestNullHeaderValue(t *testing.T) { - msg := `{ - "payload": - "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGF - tcGxlLmNvbS9pc19yb290Ijp0cnVlfQ", - "protected":"eyJhbGciOiJFUzI1NiIsIm5vbmNlIjpudWxsfQ", - "header": - {"kid":"e9bc097a-ce51-4036-9562-d2ade882db0d"}, - "signature": - "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8IS - lSApmWQxfKTUJqPP3-Kg6NU1Q" - }` - - defer func() { - if r := recover(); r != nil { - t.Errorf("ParseSigned panic'd when parsing a message with a null protected header value") - } - }() - ParseSigned(msg) -} - -// Test for bug: -// https://github.com/square/go-jose/issues/157 -func TestEmbedJWKBug(t *testing.T) { - signerKey := SigningKey{ - Key: &JSONWebKey{ - Key: rsaTestKey, - KeyID: "rsa-test-key", - }, - Algorithm: RS256, - } - - signer, err := NewSigner(signerKey, &SignerOptions{EmbedJWK: true}) - if err != nil { - t.Fatal(err) - } - - signerNoEmbed, err := NewSigner(signerKey, &SignerOptions{EmbedJWK: false}) - if err != nil { - t.Fatal(err) - } - - jws, err := signer.Sign([]byte("Lorem ipsum dolor sit amet")) - if err != nil { - t.Fatal(err) - } - - jwsNoEmbed, err := signerNoEmbed.Sign([]byte("Lorem ipsum dolor sit amet")) - if err != nil { - t.Fatal(err) - } - - // This used to panic with: - // json: error calling MarshalJSON for type *jose.JSONWebKey: square/go-jose: unknown key type '%!s()' - output := jws.FullSerialize() - outputNoEmbed := jwsNoEmbed.FullSerialize() - - // Expected output with embed set to true is a JWS with the public JWK embedded, with kid header empty. - // Expected output with embed set to false is that we set the kid header for key identification instead. - parsed, err := ParseSigned(output) - if err != nil { - t.Fatal(err) - } - - parsedNoEmbed, err := ParseSigned(outputNoEmbed) - if err != nil { - t.Fatal(err) - } - - if parsed.Signatures[0].Header.KeyID != "" { - t.Error("expected kid field in protected header to be empty") - } - if parsed.Signatures[0].Header.JSONWebKey.KeyID != "rsa-test-key" { - t.Error("expected rsa-test-key to be kid in embedded JWK in protected header") - } - if parsedNoEmbed.Signatures[0].Header.KeyID != "rsa-test-key" { - t.Error("expected kid field in protected header to be rsa-test-key") - } - if parsedNoEmbed.Signatures[0].Header.JSONWebKey != nil { - t.Error("expected no embedded JWK to be present") - } -} - -func TestJWSWithCertificateChain(t *testing.T) { - signerKey := SigningKey{ - Key: rsaTestKey, - Algorithm: RS256, - } - - certs := []string{ - // CN=TrustedSigner, signed by IntermediateCA - "MIIDLDCCAhSgAwIBAgIQNsV1i7m3kXGugqOQuuC7FzANBgkqhkiG9w0BAQsFADAZMRcwFQYDVQQDEw5JbnRlcm1lZGlhdGVDQTAeFw0xODAzMjgxODQzNDlaFw0zODAzMjgxODQzMDJaMBgxFjAUBgNVBAMTDVRydXN0ZWRTaWduZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLpvmOEDRxzQJUKHLkLQSsFDo9eGnolSERa6fz1E1F4wmk6nieHqssPd28C6Vb1sHJFne/j93DXNrx7W9Gy9fQvWa+VNHfGuYAodaS2pyV4VUPWMXI2a+qjxW85orq34XtcHzU+qm+ekR5W06ypW+xewbXJW//P9ulrsv3bDoDFaiggHY/u3p5CRSB9mg+Pbpf6E/k/N85sFJUsRE9hzgwg27Kqhh6p3hP3QnA+0WZRcWhwG0gykoD6layRLCPVcxlTSUdpyStDiK8w2whLJQfixCBGLS3/tB/GKb726bxTQK72OLzIMtOo4ZMtTva7bcA2PRgwfRz7bJg4DXz7oHTAgMBAAGjcTBvMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHQYDVR0OBBYEFCpZEyJGAyK//NsYSSC4xkOqNnh3MB8GA1UdIwQYMBaAFMAYlq86RZzTWxLpYE7KTTM7DHOuMA0GCSqGSIb3DQEBCwUAA4IBAQBSIln6jPFkctPC17le0O+wkCStFOuqUM9cjwPuj4xBQ47RxmC0Pjv52N3TuVH7slmMykITQO/vVqQZguf+N5u4BCh223qWiu1muYBTfBPXCPgJjJ79bUL/dy9QEocOfPiIqTFC6xHKeSUCu6qi5jCPFynOaoVvlNPZEb2MR+QrkKVzg09aDEfk6J+wE6eH9+kNOtwvd/z2a2t2hterURtJEnYt7AQGviEpUf1gbHxCE9f3FW5iJGdgcshrk5ZwUfxvND2x4qFq2fYQRxNBnkO+TSYzwYoAItcGAUvlZFH+rdsq3N+UpRptXRkj5iMq59VlcXFOT675EkkNREgromWn", - // CN=IntermediateCA, signed by TrustedCA - "MIIEHTCCAgWgAwIBAgIQXzZsEQv0cvSRLJAkS9FmWTANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDEwlUcnVzdGVkQ0EwHhcNMTgwMzI4MTg0MzMzWhcNMzgwMzI4MTg0MzAzWjAZMRcwFQYDVQQDEw5JbnRlcm1lZGlhdGVDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN3aYpH/1yEYf/kHuHWyO3AO4tgwlYYLhCDT2GvaPdaEcqhe/VuYiqx3xY7IRDqsW2rau/OXgW6KzLHdRZHogK07hUj1Lfr7X+Oqbp22IV4ydyiL7jwK9AtVXvDuuv5ET+oRfV82j0uhyk0ueGD9r6C/h+6NTzHBD+3xo6Yuc0VkBfY5zIyhaFqlm1aRYvupDRjC/63uBgAlrGxy2LyiTMVnYMuxoJM5ahDepz3sqjuNWVyPhfGwIezjXuXRdEvlmWX05XLnsTdP4zu4fHq9Z7c3TKWWONM3z64ECAZmGQVfMAcEDX7qP0gZX5PCT+0WcvTgTWE4Q+WIh5AmYyxQ04cCAwEAAaNmMGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFMAYlq86RZzTWxLpYE7KTTM7DHOuMB8GA1UdIwQYMBaAFMvTapNJg0cAubXJjcUNWFjuTAIYMA0GCSqGSIb3DQEBCwUAA4ICAQBmYRpQoWEm5g16kwUrpwWrH7OIqqMtUhM1dcskECfki3/hcsV+MQRkGHLIItucYIWqs7oOQIglsyGcohAbnvE1PVtKKojUHC0lfbjgIenDPbvz15QB6A3KLDR82QbQGeGniACy924p66zlfPwHJbkMo5ZaqtNqI//EIa2YCpyyokhFXaSFmPWXXrTOCsEEsFJKsoSCH1KUpTcwACGkkilNseg1edZB6/lBDwybxVuY+dbUlHip3r5tFcP66Co3tKAaEcVY0AsZ/8GKwH+IM2AR6q7jdn9Gp2OX4E1ul9Wy+hW5GHMmfixkgTVwRowuKgkCPEKV2/Xy3k9rlSpnKr2NpYYq0mu6An9HYt8THQ+ewGZHwWufuDFDWuzlu7CxFOjpXLKv8qqVnwSFC91S3HsPAzPKLC9ZMEC+iQs2VkesOs0nFLZeMaMGAO5W6xiyQ5p94oo0bqa1XbmSV1bNp1HWuNEGIiZKrEUDxfYuDc6fC6hJZKsjJkMkBeadlQAlLcjIx1rDV171CKLLTxy/dT5kv4p9UrJlnleyMVG6S/3d6nX/WLSgZIMYbOwiZVVPlSrobuG38ULJMCSuxndxD0l+HahJaH8vYXuR67A0XT+bTEe305AI6A/9MEaRrActBnq6/OviQgBsKAvtTv1FmDbnpZsKeoFuwc3OPdTveQdCRA==", - } - - testCases := []struct { - // Cert chain to embed in message - chain []string - // Intermediates & root certificate to verify against - intermediates []string - root string - // Should this test case verify? - success bool - }{ - {certs, nil, trustedCA, true}, - {certs, []string{intermediateCA}, trustedCA, true}, - {certs[0:1], nil, intermediateCA, true}, - {certs[0:1], nil, trustedCA, false}, - {[]string{}, nil, trustedCA, false}, - } - - for i, testCase := range testCases { - signer, err := NewSigner(signerKey, &SignerOptions{ - ExtraHeaders: map[HeaderKey]interface{}{HeaderKey("x5c"): testCase.chain}, - }) - if err != nil { - t.Fatal(err) - } - - signed, err := signer.Sign([]byte("Lorem ipsum dolor sit amet")) - if err != nil { - t.Fatal(err) - } - - parsed, err := ParseSigned(signed.FullSerialize()) - if err != nil { - t.Fatal(err) - } - - opts := x509.VerifyOptions{ - DNSName: "TrustedSigner", - Roots: x509.NewCertPool(), - } - - ok := opts.Roots.AppendCertsFromPEM([]byte(testCase.root)) - if !ok { - t.Fatal("failed to parse trusted root certificate") - } - - if len(testCase.intermediates) > 0 { - opts.Intermediates = x509.NewCertPool() - for _, intermediate := range testCase.intermediates { - ok := opts.Intermediates.AppendCertsFromPEM([]byte(intermediate)) - if !ok { - t.Fatal("failed to parse trusted root certificate") - } - } - } - - chains, err := parsed.Signatures[0].Protected.Certificates(opts) - if testCase.success && (len(chains) == 0 || err != nil) { - t.Fatalf("failed to verify certificate chain for test case %d: %s", i, err) - } - if !testCase.success && (len(chains) != 0 && err == nil) { - t.Fatalf("incorrectly verified certificate chain for test case %d (should fail)", i) - } - } -} diff --git a/vendor/gopkg.in/square/go-jose.v2/jwt/builder_test.go b/vendor/gopkg.in/square/go-jose.v2/jwt/builder_test.go deleted file mode 100644 index 8213c47fc..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/jwt/builder_test.go +++ /dev/null @@ -1,507 +0,0 @@ -/*- - * Copyright 2016 Zbigniew Mandziejewicz - * Copyright 2016 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jwt - -import ( - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "encoding/hex" - "encoding/pem" - "errors" - "fmt" - "io" - "reflect" - "sort" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "gopkg.in/square/go-jose.v2" - "gopkg.in/square/go-jose.v2/json" -) - -type testClaims struct { - Subject string `json:"sub"` -} - -type invalidMarshalClaims struct { -} - -var errInvalidMarshalClaims = errors.New("Failed marshaling invalid claims.") - -func (c invalidMarshalClaims) MarshalJSON() ([]byte, error) { - return nil, errInvalidMarshalClaims -} - -var sampleClaims = Claims{ - Subject: "42", - IssuedAt: NewNumericDate(time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC)), - Issuer: "issuer", - Audience: Audience{"a1", "a2"}, -} - -type numberClaims struct { - Int int64 `json:"int"` - Float float64 `json:"float"` -} - -func TestIntegerAndFloatsNormalize(t *testing.T) { - c := numberClaims{1 << 60, 12345.6789} - - normalized, err := normalize(c) - if err != nil { - t.Fatal(err) - } - - ni, err := (normalized["int"].(json.Number)).Int64() - nf, err := (normalized["float"].(json.Number)).Float64() - - if ni != c.Int { - t.Error(fmt.Sprintf("normalize failed to preserve int64 (got %v, wanted %v, type %s)", normalized["int"], c.Int, reflect.TypeOf(normalized["int"]))) - } - if nf != c.Float { - t.Error(fmt.Sprintf("normalize failed to preserve float64 (got %v, wanted %v, type %s)", normalized["float"], c.Float, reflect.TypeOf(normalized["float"]))) - } -} - -func TestBuilderCustomClaimsNonPointer(t *testing.T) { - jwt, err := Signed(rsaSigner).Claims(testClaims{"foo"}).CompactSerialize() - require.NoError(t, err, "Error creating JWT.") - - parsed, err := ParseSigned(jwt) - require.NoError(t, err, "Error parsing JWT.") - - out := &testClaims{} - if assert.NoError(t, parsed.Claims(&testPrivRSAKey1.PublicKey, out), "Error unmarshaling claims.") { - assert.Equal(t, "foo", out.Subject) - } -} - -func TestBuilderCustomClaimsPointer(t *testing.T) { - jwt, err := Signed(rsaSigner).Claims(&testClaims{"foo"}).CompactSerialize() - require.NoError(t, err, "Error creating JWT.") - - parsed, err := ParseSigned(jwt) - require.NoError(t, err, "Error parsing JWT.") - - out := &testClaims{} - if assert.NoError(t, parsed.Claims(&testPrivRSAKey1.PublicKey, out), "Error unmarshaling claims.") { - assert.Equal(t, "foo", out.Subject) - } -} - -func TestBuilderMergeClaims(t *testing.T) { - jwt, err := Signed(rsaSigner). - Claims(&Claims{ - Subject: "42", - }). - Claims(map[string]interface{}{ - "Scopes": []string{"read:users"}, - }). - CompactSerialize() - require.NoError(t, err, "Error creating JWT.") - - parsed, err := ParseSigned(jwt) - require.NoError(t, err, "Error parsing JWT.") - - out := make(map[string]interface{}) - if assert.NoError(t, parsed.Claims(&testPrivRSAKey1.PublicKey, &out), "Error unmarshaling claims.") { - assert.Equal(t, map[string]interface{}{ - "sub": "42", - "Scopes": []interface{}{"read:users"}, - }, out) - } - - _, err = Signed(rsaSigner).Claims("invalid-claims").Claims(&testClaims{"foo"}).CompactSerialize() - assert.Equal(t, err, ErrInvalidClaims) - - _, err = Signed(rsaSigner).Claims(&invalidMarshalClaims{}).CompactSerialize() - assert.EqualError(t, err, "json: error calling MarshalJSON for type *jwt.invalidMarshalClaims: Failed marshaling invalid claims.") -} - -func TestSignedFullSerializeAndToken(t *testing.T) { - b := Signed(rsaSigner).Claims(&testClaims{"foo"}) - - jwt, err := b.FullSerialize() - require.NoError(t, err, "Error creating JWT.") - parsed, err := ParseSigned(jwt) - require.NoError(t, err, "Error parsing JWT.") - out := &testClaims{} - if assert.NoError(t, parsed.Claims(&testPrivRSAKey1.PublicKey, &out), "Error unmarshaling claims.") { - assert.Equal(t, &testClaims{ - Subject: "foo", - }, out) - } - - jwt2, err := b.Token() - require.NoError(t, err, "Error creating JWT.") - out2 := &testClaims{} - if assert.NoError(t, jwt2.Claims(&testPrivRSAKey1.PublicKey, &out2), "Error unmarshaling claims.") { - assert.Equal(t, &testClaims{ - Subject: "foo", - }, out2) - } - - b2 := Signed(rsaSigner).Claims(&invalidMarshalClaims{}) - _, err = b2.FullSerialize() - require.EqualError(t, err, "json: error calling MarshalJSON for type *jwt.invalidMarshalClaims: Failed marshaling invalid claims.") - _, err = b2.Token() - require.EqualError(t, err, "json: error calling MarshalJSON for type *jwt.invalidMarshalClaims: Failed marshaling invalid claims.") -} - -func TestEncryptedFullSerializeAndToken(t *testing.T) { - recipient := jose.Recipient{ - Algorithm: jose.RSA1_5, - Key: testPrivRSAKey1.Public(), - } - encrypter, err := jose.NewEncrypter(jose.A128CBC_HS256, recipient, nil) - require.NoError(t, err, "Error creating encrypter.") - - b := Encrypted(encrypter).Claims(&testClaims{"foo"}) - - jwt, err := b.FullSerialize() - require.NoError(t, err, "Error creating JWT.") - parsed, err := ParseEncrypted(jwt) - require.NoError(t, err, "Error parsing JWT.") - out := &testClaims{} - if assert.NoError(t, parsed.Claims(testPrivRSAKey1, &out)) { - assert.Equal(t, &testClaims{ - Subject: "foo", - }, out) - } - - jwt2, err := b.Token() - require.NoError(t, err, "Error creating JWT.") - out2 := &testClaims{} - if assert.NoError(t, jwt2.Claims(testPrivRSAKey1, &out2)) { - assert.Equal(t, &testClaims{ - Subject: "foo", - }, out2) - } - - b2 := Encrypted(encrypter).Claims(&invalidMarshalClaims{}) - - _, err = b2.FullSerialize() - require.EqualError(t, err, "json: error calling MarshalJSON for type *jwt.invalidMarshalClaims: Failed marshaling invalid claims.") - _, err = b2.Token() - require.EqualError(t, err, "json: error calling MarshalJSON for type *jwt.invalidMarshalClaims: Failed marshaling invalid claims.") -} - -func TestBuilderSignedAndEncrypted(t *testing.T) { - recipient := jose.Recipient{ - Algorithm: jose.RSA1_5, - Key: testPrivRSAKey1.Public(), - } - encrypter, err := jose.NewEncrypter(jose.A128CBC_HS256, recipient, (&jose.EncrypterOptions{}).WithContentType("JWT").WithType("JWT")) - require.NoError(t, err, "Error creating encrypter.") - - jwt1, err := SignedAndEncrypted(rsaSigner, encrypter).Claims(&testClaims{"foo"}).Token() - require.NoError(t, err, "Error marshaling signed-then-encrypted token.") - if nested, err := jwt1.Decrypt(testPrivRSAKey1); assert.NoError(t, err, "Error decrypting signed-then-encrypted token.") { - out := &testClaims{} - assert.NoError(t, nested.Claims(&testPrivRSAKey1.PublicKey, out)) - assert.Equal(t, &testClaims{"foo"}, out) - } - - b := SignedAndEncrypted(rsaSigner, encrypter).Claims(&testClaims{"foo"}) - tok1, err := b.CompactSerialize() - if assert.NoError(t, err) { - jwt, err := ParseSignedAndEncrypted(tok1) - if assert.NoError(t, err, "Error parsing signed-then-encrypted compact token.") { - if nested, err := jwt.Decrypt(testPrivRSAKey1); assert.NoError(t, err) { - out := &testClaims{} - assert.NoError(t, nested.Claims(&testPrivRSAKey1.PublicKey, out)) - assert.Equal(t, &testClaims{"foo"}, out) - } - } - } - - tok2, err := b.FullSerialize() - if assert.NoError(t, err) { - jwe, err := ParseSignedAndEncrypted(tok2) - if assert.NoError(t, err, "Error parsing signed-then-encrypted full token.") { - assert.Equal(t, []jose.Header{{ - Algorithm: string(jose.RSA1_5), - ExtraHeaders: map[jose.HeaderKey]interface{}{ - jose.HeaderType: "JWT", - jose.HeaderContentType: "JWT", - "enc": "A128CBC-HS256", - }, - }}, jwe.Headers) - if jws, err := jwe.Decrypt(testPrivRSAKey1); assert.NoError(t, err) { - assert.Equal(t, []jose.Header{{ - Algorithm: string(jose.RS256), - ExtraHeaders: map[jose.HeaderKey]interface{}{ - jose.HeaderType: "JWT", - }, - }}, jws.Headers) - out := &testClaims{} - assert.NoError(t, jws.Claims(&testPrivRSAKey1.PublicKey, out)) - assert.Equal(t, &testClaims{"foo"}, out) - } - } - } - - b2 := SignedAndEncrypted(rsaSigner, encrypter).Claims(&invalidMarshalClaims{}) - _, err = b2.CompactSerialize() - assert.EqualError(t, err, "json: error calling MarshalJSON for type *jwt.invalidMarshalClaims: Failed marshaling invalid claims.") - _, err = b2.FullSerialize() - assert.EqualError(t, err, "json: error calling MarshalJSON for type *jwt.invalidMarshalClaims: Failed marshaling invalid claims.") - - encrypter2, err := jose.NewEncrypter(jose.A128CBC_HS256, recipient, nil) - require.NoError(t, err, "Error creating encrypter.") - _, err = SignedAndEncrypted(rsaSigner, encrypter2).CompactSerialize() - assert.EqualError(t, err, "square/go-jose/jwt: expected content type to be JWT (cty header)") -} - -func TestBuilderHeadersSigner(t *testing.T) { - tests := []struct { - Keys []*rsa.PrivateKey - Claims interface{} - }{ - { - Keys: []*rsa.PrivateKey{testPrivRSAKey1}, - Claims: &Claims{Issuer: "foo"}, - }, - { - Keys: []*rsa.PrivateKey{testPrivRSAKey1, testPrivRSAKey2}, - Claims: &Claims{Issuer: "foo"}, - }, - } - - for i, tc := range tests { - wantKeyIDs := make([]string, len(tc.Keys)) - signingKeys := make([]jose.SigningKey, len(tc.Keys)) - - for j, key := range tc.Keys { - keyIDBytes := make([]byte, 20) - if _, err := io.ReadFull(rand.Reader, keyIDBytes); err != nil { - t.Fatalf("failed to read random bytes: %v", err) - } - keyID := hex.EncodeToString(keyIDBytes) - - wantKeyIDs[j] = keyID - signingKeys[j] = jose.SigningKey{ - Algorithm: jose.RS256, - Key: &jose.JSONWebKey{ - KeyID: keyID, - Algorithm: "RSA", - Key: key, - }, - } - } - - signer, err := jose.NewMultiSigner(signingKeys, nil) - if err != nil { - t.Errorf("case %d: NewMultiSigner(): %v", i, err) - continue - } - - var token string - if len(tc.Keys) == 1 { - token, err = Signed(signer).Claims(tc.Claims).CompactSerialize() - } else { - token, err = Signed(signer).Claims(tc.Claims).FullSerialize() - } - if err != nil { - t.Errorf("case %d: failed to create token: %v", i, err) - continue - } - jws, err := jose.ParseSigned(token) - if err != nil { - t.Errorf("case %d: parse signed: %v", i, err) - continue - } - gotKeyIDs := make([]string, len(jws.Signatures)) - for i, sig := range jws.Signatures { - gotKeyIDs[i] = sig.Header.KeyID - } - sort.Strings(wantKeyIDs) - sort.Strings(gotKeyIDs) - if !reflect.DeepEqual(wantKeyIDs, gotKeyIDs) { - t.Errorf("case %d: wanted=%q got=%q", i, wantKeyIDs, gotKeyIDs) - } - } -} - -func TestBuilderHeadersEncrypter(t *testing.T) { - key := testPrivRSAKey1 - claims := &Claims{Issuer: "foo"} - - keyIDBytes := make([]byte, 20) - if _, err := io.ReadFull(rand.Reader, keyIDBytes); err != nil { - t.Fatalf("failed to read random bytes: %v", err) - } - keyID := hex.EncodeToString(keyIDBytes) - - wantKeyID := keyID - recipient := jose.Recipient{ - Algorithm: jose.RSA1_5, - Key: key.Public(), - KeyID: keyID, - } - - wantType := jose.ContentType("JWT") - encrypter, err := jose.NewEncrypter(jose.A128CBC_HS256, recipient, (&jose.EncrypterOptions{}).WithType(wantType)) - require.NoError(t, err, "failed to create encrypter") - - token, err := Encrypted(encrypter).Claims(claims).CompactSerialize() - require.NoError(t, err, "failed to create token") - - jwe, err := jose.ParseEncrypted(token) - if assert.NoError(t, err, "error parsing encrypted token") { - assert.Equal(t, jose.Header{ - ExtraHeaders: map[jose.HeaderKey]interface{}{ - jose.HeaderType: string(wantType), - "enc": "A128CBC-HS256", - }, - Algorithm: string(jose.RSA1_5), - KeyID: wantKeyID, - }, jwe.Header) - } -} - -func BenchmarkMapClaims(b *testing.B) { - m := map[string]interface{}{ - "sub": "42", - "iat": 1451606400, - "iss": "issuer", - "aud": []string{"a1", "a2"}, - } - - for i := 0; i < b.N; i++ { - Signed(rsaSigner).Claims(m) - } -} - -func BenchmarkStructClaims(b *testing.B) { - for i := 0; i < b.N; i++ { - Signed(rsaSigner).Claims(sampleClaims) - } -} - -func BenchmarkSignedCompactSerializeRSA(b *testing.B) { - tb := Signed(rsaSigner).Claims(sampleClaims) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - tb.CompactSerialize() - } -} - -func BenchmarkSignedCompactSerializeSHA(b *testing.B) { - tb := Signed(hmacSigner).Claims(sampleClaims) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - tb.CompactSerialize() - } -} - -func mustUnmarshalRSA(data string) *rsa.PrivateKey { - block, _ := pem.Decode([]byte(data)) - if block == nil { - panic("failed to decode PEM data") - } - key, err := x509.ParsePKCS8PrivateKey(block.Bytes) - if err != nil { - panic("failed to parse RSA key: " + err.Error()) - } - if key, ok := key.(*rsa.PrivateKey); ok { - return key - } - panic("key is not of type *rsa.PrivateKey") -} - -func mustMakeSigner(alg jose.SignatureAlgorithm, k interface{}) jose.Signer { - sig, err := jose.NewSigner(jose.SigningKey{Algorithm: alg, Key: k}, (&jose.SignerOptions{}).WithType("JWT")) - if err != nil { - panic("failed to create signer:" + err.Error()) - } - - return sig -} - -var ( - sharedKey = []byte("secret") - sharedEncryptionKey = []byte("itsa16bytesecret") - - testPrivRSAKey1 = mustUnmarshalRSA(`-----BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDIHBvDHAr7jh8h -xaqBCl11fjI9YZtdC5b3HtXTXZW3c2dIOImNUjffT8POP6p5OpzivmC1om7iOyuZ -3nJjC9LT3zqqs3f2i5d4mImxEuqG6uWdryFfkp0uIv5VkjVO+iQWd6pDAPGP7r1Z -foXCleyCtmyNH4JSkJneNPOk/4BxO8vcvRnCMT/Gv81IT6H+OQ6OovWOuJr8RX9t -1wuCjC9ezZxeI9ONffhiO5FMrVh5H9LJTl3dPOVa4aEcOvgd45hBmvxAyXqf8daE -6Kl2O7vQ4uwgnSTVXYIIjCjbepuersApIMGx/XPSgiU1K3Xtah/TBvep+S3VlwPc -q/QH25S9AgMBAAECggEAe+y8XKYfPw4SxY1uPB+5JSwT3ON3nbWxtjSIYy9Pqp5z -Vcx9kuFZ7JevQSk4X38m7VzM8282kC/ono+d8yy9Uayq3k/qeOqV0X9Vti1qxEbw -ECkG1/MqGApfy4qSLOjINInDDV+mOWa2KJgsKgdCwuhKbVMYGB2ozG2qfYIlfvlY -vLcBEpGWmswJHNmkcjTtGFIyJgPbsI6ndkkOeQbqQKAaadXtG1xUzH+vIvqaUl/l -AkNf+p4qhPkHsoAWXf1qu9cYa2T8T+mEo79AwlgVC6awXQWNRTiyClDJC7cu6NBy -ZHXCLFMbalzWF9qeI2OPaFX2x3IBWrbyDxcJ4TSdQQKBgQD/Fp/uQonMBh1h4Vi4 -HlxZdqSOArTitXValdLFGVJ23MngTGV/St4WH6eRp4ICfPyldsfcv6MZpNwNm1Rn -lB5Gtpqpby1dsrOSfvVbY7U3vpLnd8+hJ/lT5zCYt5Eor46N6iWRkYWzNe4PixiF -z1puGUvFCbZdeeACVrPLmW3JKQKBgQDI0y9WTf8ezKPbtap4UEE6yBf49ftohVGz -p4iD6Ng1uqePwKahwoVXKOc179CjGGtW/UUBORAoKRmxdHajHq6LJgsBxpaARz21 -COPy99BUyp9ER5P8vYn63lC7Cpd/K7uyMjaz1DAzYBZIeVZHIw8O9wuGNJKjRFy9 -SZyD3V0ddQKBgFMdohrWH2QVEfnUnT3Q1rJn0BJdm2bLTWOosbZ7G72TD0xAWEnz -sQ1wXv88n0YER6X6YADziEdQykq8s/HT91F/KkHO8e83zP8M0xFmGaQCOoelKEgQ -aFMIX3NDTM7+9OoUwwz9Z50PE3SJFAJ1n7eEEoYvNfabQXxBl+/dHEKRAoGAPEvU -EaiXacrtg8EWrssB2sFLGU/ZrTciIbuybFCT4gXp22pvXXAHEvVP/kzDqsRhLhwb -BNP6OuSkNziNikpjA5pngZ/7fgZly54gusmW/m5bxWdsUl0iOXVYbeAvPlqGH2me -LP4Pfs1hw17S/cbT9Z1NE31jbavP4HFikeD73SUCgYEArQfuudml6ei7XZ1Emjq8 -jZiD+fX6e6BD/ISatVnuyZmGj9wPFsEhY2BpLiAMQHMDIvH9nlKzsFvjkTPB86qG -jCh3D67Os8eSBk5uRC6iW3Fc4DXvB5EFS0W9/15Sl+V5vXAcrNMpYS82OTSMG2Gt -b9Ym/nxaqyTu0PxajXkKm5Q= ------END PRIVATE KEY-----`) - - testPrivRSAKey2 = mustUnmarshalRSA(`-----BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCxJ09jkXZ5Okyq -FrEKrs+GTzZRvoLziyzDTIZLJC6BVryau4gaFjuBG+pnm4z53oDP0XVnjFsx1mBw -R6RHeXlXbxLXsMfJpMzU9I2SRen9DokpD187CAnjLOoN9QRl1h8CA+sqR5Jw9mdl -mdaBKC99M9QYAPK3vGNfPC4soo8LDSBiemmt5raL4WSfoYh/6qg5rHUTymY28uxV -ew3I9Yp+3ltIw+WlRDtW5l+MM5CSUofjj2zcgcG3LEuPtvyZ+CSObxxcZZugm9zc -JdiazNyUxtX8yAj3Xg8Hde0jt0QDXv7A+U0KMVi9lX6PJEaNj4tOhOmQhJVMzAyr -1W/bifZVAgMBAAECggEAduKnn21GMZLTUi4KP94SvNK55F/Sp7hVoPbhBNpSL1BT -IBAMBV24LyvZwhAcqq8MiOrLPGNv6+EvNQqPD7xQl0GeRouHeCYVpDA+NdSfc8jm -eVysjwQVBpTkudsdSW5JvuN8VRJVD2P8/a0gy+p4/C/k/Prd6DoQAiBz6FZrYoEd -iYgIegHOMXWd4vzO3ENOWSIUI6ci7Aro+Y0Z75kfiVokAGhUcFgrZ58E82fBYh8I -cxO20oMnucGrLicQzj536jx4wX3Cdd4jr9UVEJ9ZII1ldlp03nZlFLXqJH1547Aq -ZM+3vVcBGoJ8T9ZQ4VDAL++0K2DLC9JkTARAYCEi/QKBgQDebIc1+2zblhQtVQ/e -IbEErZcB7v+TkUoRoBfR0lj7bKBFJgRe37fgu1xf95/s63okdnOw/OuQqtGmgx/J -TL3yULBdNcwTCRm41t+cqoGymjK0VRbqk6CWBId0E3r5TaCVWedk2JI2XwTvIJ1A -eDiqfJeDHUD44yaonwbysj9ZDwKBgQDL5VQfTppVaJk2PXNwhAkRQklZ8RFmt/7p -yA3dddQNdwMk4Fl8F7QuO1gBxDiHdnwIrlEOz6fTsM3LwIS+Q12P1vYFIhpo7HDB -wvjfMwCPxBIS4jI28RgcAf0VbZ/+CHAm6bb9iDwsjXhh1J5oOm5VKnju6/rPH/QY -+md40pnSWwKBgBnKPbdNquafNUG4XjmkcHEZa6wGuU20CAGZLYnfuP+WLdM2wET7 -7cc6ElDyVnHTL/twXKPF/85rcBm9lH7zzgZ9wqVcKoh+gqQDDjSNNLKv3Hc6cojK -i1E5vzb/Vz/290q5/PGdhv6U7+6GOpWSGwfxoGPMjY8OT5o3rkeP0XaTAoGBALLR -GQmr4eZtqZDMK+XNpjYgsDvVE7HGRCW7cY17vNFiQruglloiX778BJ7n+7uxye3D -EwuuSj15ncLHwKMsaW2w1GqEEi1azzjfSWxWSnPLPR6aifdtUfueMtsMHXio5dL6 -vaV0SXG5UI5b7eDy/bhrW0wOYRQtreIKGZz49jZpAoGBAIvxYngkLwmq6g6MmnAc -YK4oT6YAm2wfSy2mzpEQP5r1igp1rN7T46o7FMUPDLS9wK3ESAaIYe01qT6Yftcc -5qF+yiOGDTr9XQiHwe4BcyrNEMfUjDhDU5ao2gH8+t1VGr1KspLsUNbedrJwZsY4 -UCZVKEEDHzKfLO/iBgKjJQF7 ------END PRIVATE KEY-----`) - - rsaSigner = mustMakeSigner(jose.RS256, testPrivRSAKey1) - hmacSigner = mustMakeSigner(jose.HS256, sharedKey) -) diff --git a/vendor/gopkg.in/square/go-jose.v2/jwt/claims_test.go b/vendor/gopkg.in/square/go-jose.v2/jwt/claims_test.go deleted file mode 100644 index 6799aab23..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/jwt/claims_test.go +++ /dev/null @@ -1,80 +0,0 @@ -/*- - * Copyright 2016 Zbigniew Mandziejewicz - * Copyright 2016 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jwt - -import ( - "testing" - "time" - - "gopkg.in/square/go-jose.v2/json" - - "github.com/stretchr/testify/assert" -) - -func TestEncodeClaims(t *testing.T) { - now := time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC) - - c := Claims{ - Issuer: "issuer", - Subject: "subject", - Audience: Audience{"a1", "a2"}, - NotBefore: NewNumericDate(time.Time{}), - IssuedAt: NewNumericDate(now), - Expiry: NewNumericDate(now.Add(1 * time.Hour)), - } - - b, err := json.Marshal(c) - assert.NoError(t, err) - - expected := `{"iss":"issuer","sub":"subject","aud":["a1","a2"],"exp":1451610000,"iat":1451606400}` - assert.Equal(t, expected, string(b)) -} - -func TestDecodeClaims(t *testing.T) { - s := []byte(`{"iss":"issuer","sub":"subject","aud":["a1","a2"],"exp":1451610000,"iat":1451606400}`) - now := time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC) - - c := Claims{} - if err := json.Unmarshal(s, &c); assert.NoError(t, err) { - assert.Equal(t, "issuer", c.Issuer) - assert.Equal(t, "subject", c.Subject) - assert.Equal(t, Audience{"a1", "a2"}, c.Audience) - assert.True(t, now.Equal(c.IssuedAt.Time())) - assert.True(t, now.Add(1*time.Hour).Equal(c.Expiry.Time())) - } - - s2 := []byte(`{"aud": "a1"}`) - c2 := Claims{} - if err := json.Unmarshal(s2, &c2); assert.NoError(t, err) { - assert.Equal(t, Audience{"a1"}, c2.Audience) - } - - invalid := []struct { - Raw string - Err error - }{ - {`{"aud": 5}`, ErrUnmarshalAudience}, - {`{"aud": ["foo", 5, "bar"]}`, ErrUnmarshalAudience}, - {`{"exp": "invalid"}`, ErrUnmarshalNumericDate}, - } - - for _, v := range invalid { - c := Claims{} - assert.Equal(t, v.Err, json.Unmarshal([]byte(v.Raw), &c)) - } -} diff --git a/vendor/gopkg.in/square/go-jose.v2/jwt/example_test.go b/vendor/gopkg.in/square/go-jose.v2/jwt/example_test.go deleted file mode 100644 index bebe64da0..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/jwt/example_test.go +++ /dev/null @@ -1,340 +0,0 @@ -/*- - * Copyright 2016 Zbigniew Mandziejewicz - * Copyright 2016 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jwt_test - -import ( - "fmt" - "strings" - "time" - - "crypto/rsa" - "crypto/x509" - "encoding/pem" - - "gopkg.in/square/go-jose.v2" - "gopkg.in/square/go-jose.v2/jwt" -) - -var sharedKey = []byte("secret") -var sharedEncryptionKey = []byte("itsa16bytesecret") -var signer, _ = jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: sharedKey}, &jose.SignerOptions{}) - -func ExampleParseSigned() { - raw := `eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJpc3N1ZXIiLCJzdWIiOiJzdWJqZWN0In0.gpHyA1B1H6X4a4Edm9wo7D3X2v3aLSDBDG2_5BzXYe0` - tok, err := jwt.ParseSigned(raw) - if err != nil { - panic(err) - } - - out := jwt.Claims{} - if err := tok.Claims(sharedKey, &out); err != nil { - panic(err) - } - fmt.Printf("iss: %s, sub: %s\n", out.Issuer, out.Subject) - // Output: iss: issuer, sub: subject -} - -func ExampleParseEncrypted() { - key := []byte("itsa16bytesecret") - raw := `eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIn0..jg45D9nmr6-8awml.z-zglLlEw9MVkYHi-Znd9bSwc-oRGbqKzf9WjXqZxno.kqji2DiZHZmh-1bLF6ARPw` - tok, err := jwt.ParseEncrypted(raw) - if err != nil { - panic(err) - } - - out := jwt.Claims{} - if err := tok.Claims(key, &out); err != nil { - panic(err) - } - fmt.Printf("iss: %s, sub: %s\n", out.Issuer, out.Subject) - // Output: iss: issuer, sub: subject -} - -func ExampleParseSignedAndEncrypted() { - raw := `eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIiwiY3R5IjoiSldUIn0..-keV-9YpsxotBEHw.yC9SHWgnkjykgJqXZGlzYC5Wg_EdWKO5TgfqeqsWWJYw7fX9zXQE3NtXmA3nAiUrYOr3H2s0AgTeAhTNbELLEHQu0blfRaPa_uKOAgFgmhJwbGe2iFLn9J0U72wk56318nI-pTLCV8FijoGpXvAxQlaKrPLKkl9yDQimPhb7UiDwLWYkJeoayciAXhR5f40E8ORGjCz8oawXRvjDaSjgRElUwy4kMGzvJy_difemEh4lfMSIwUNVEqJkEYaalRttSymMYuV6NvBVU0N0Jb6omdM4tW961OySB4KPWCWH9UJUX0XSEcqbW9WLxpg3ftx5R7xNiCnaVaCx_gJZfXJ9yFLqztIrKh2N05zHM0tddSOwCOnq7_1rJtaVz0nTXjSjf1RrVaxJya59p3K-e41QutiGFiJGzXG-L2OyLETIaVSU3ptvaCz4IxCF3GzeCvOgaICvXkpBY1-bv-fk1ilyjmcTDnLp2KivWIxcnoQmpN9xj06ZjagdG09AHUhS5WixADAg8mIdGcanNblALecnCWG-otjM9Kw.RZoaHtSgnzOin2od3D9tnA` - tok, err := jwt.ParseSignedAndEncrypted(raw) - if err != nil { - panic(err) - } - - nested, err := tok.Decrypt(sharedEncryptionKey) - if err != nil { - panic(err) - } - - out := jwt.Claims{} - if err := nested.Claims(&rsaPrivKey.PublicKey, &out); err != nil { - panic(err) - } - - fmt.Printf("iss: %s, sub: %s\n", out.Issuer, out.Subject) - // Output: iss: issuer, sub: subject -} - -func ExampleClaims_Validate() { - cl := jwt.Claims{ - Subject: "subject", - Issuer: "issuer", - NotBefore: jwt.NewNumericDate(time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC)), - Expiry: jwt.NewNumericDate(time.Date(2016, 1, 1, 0, 15, 0, 0, time.UTC)), - Audience: jwt.Audience{"leela", "fry"}, - } - - err := cl.Validate(jwt.Expected{ - Issuer: "issuer", - Time: time.Date(2016, 1, 1, 0, 10, 0, 0, time.UTC), - }) - if err != nil { - panic(err) - } - - fmt.Printf("valid!") - // Output: valid! -} - -func ExampleClaims_Validate_withParse() { - raw := `eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJpc3N1ZXIiLCJzdWIiOiJzdWJqZWN0In0.gpHyA1B1H6X4a4Edm9wo7D3X2v3aLSDBDG2_5BzXYe0` - tok, err := jwt.ParseSigned(raw) - if err != nil { - panic(err) - } - - cl := jwt.Claims{} - if err := tok.Claims(sharedKey, &cl); err != nil { - panic(err) - } - - err = cl.Validate(jwt.Expected{ - Issuer: "issuer", - Subject: "subject", - }) - if err != nil { - panic(err) - } - - fmt.Printf("valid!") - // Output: valid! -} - -func ExampleSigned() { - key := []byte("secret") - sig, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: key}, (&jose.SignerOptions{}).WithType("JWT")) - if err != nil { - panic(err) - } - - cl := jwt.Claims{ - Subject: "subject", - Issuer: "issuer", - NotBefore: jwt.NewNumericDate(time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC)), - Audience: jwt.Audience{"leela", "fry"}, - } - raw, err := jwt.Signed(sig).Claims(cl).CompactSerialize() - if err != nil { - panic(err) - } - - fmt.Println(raw) - // Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsibGVlbGEiLCJmcnkiXSwiaXNzIjoiaXNzdWVyIiwibmJmIjoxNDUxNjA2NDAwLCJzdWIiOiJzdWJqZWN0In0.4PgCj0VO-uG_cb1mNA38NjJyp0N-NdGIDLoYelEkciw -} - -func ExampleSigned_privateClaims() { - key := []byte("secret") - sig, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: key}, (&jose.SignerOptions{}).WithType("JWT")) - if err != nil { - panic(err) - } - - cl := jwt.Claims{ - Subject: "subject", - Issuer: "issuer", - NotBefore: jwt.NewNumericDate(time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC)), - Audience: jwt.Audience{"leela", "fry"}, - } - - // When setting private claims, make sure to add struct tags - // to specify how to serialize the field. The naming behavior - // should match the encoding/json package otherwise. - privateCl := struct { - CustomClaim string `json:"custom"` - }{ - "custom claim value", - } - - raw, err := jwt.Signed(sig).Claims(cl).Claims(privateCl).CompactSerialize() - if err != nil { - panic(err) - } - - fmt.Println(raw) - // Ouput: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsibGVlbGEiLCJmcnkiXSwiY3VzdG9tIjoiY3VzdG9tIGNsYWltIHZhbHVlIiwiaXNzIjoiaXNzdWVyIiwibmJmIjoxNDUxNjA2NDAwLCJzdWIiOiJzdWJqZWN0In0.knXH3ReNJToS5XI7BMCkk80ugpCup3tOy53xq-ga47o -} - -func ExampleEncrypted() { - enc, err := jose.NewEncrypter( - jose.A128GCM, - jose.Recipient{Algorithm: jose.DIRECT, Key: sharedEncryptionKey}, - (&jose.EncrypterOptions{}).WithType("JWT"), - ) - if err != nil { - panic(err) - } - - cl := jwt.Claims{ - Subject: "subject", - Issuer: "issuer", - } - raw, err := jwt.Encrypted(enc).Claims(cl).CompactSerialize() - if err != nil { - panic(err) - } - - fmt.Println(raw) -} - -func ExampleSignedAndEncrypted() { - enc, err := jose.NewEncrypter( - jose.A128GCM, - jose.Recipient{ - Algorithm: jose.DIRECT, - Key: sharedEncryptionKey, - }, - (&jose.EncrypterOptions{}).WithType("JWT").WithContentType("JWT")) - if err != nil { - panic(err) - } - - cl := jwt.Claims{ - Subject: "subject", - Issuer: "issuer", - } - raw, err := jwt.SignedAndEncrypted(rsaSigner, enc).Claims(cl).CompactSerialize() - if err != nil { - panic(err) - } - - fmt.Println(raw) -} - -func ExampleSigned_multipleClaims() { - c := &jwt.Claims{ - Subject: "subject", - Issuer: "issuer", - } - c2 := struct { - Scopes []string - }{ - []string{"foo", "bar"}, - } - raw, err := jwt.Signed(signer).Claims(c).Claims(c2).CompactSerialize() - if err != nil { - panic(err) - } - - fmt.Println(raw) - // Output: eyJhbGciOiJIUzI1NiJ9.eyJTY29wZXMiOlsiZm9vIiwiYmFyIl0sImlzcyI6Imlzc3VlciIsInN1YiI6InN1YmplY3QifQ.esKOIsmwkudr_gnfnB4SngxIr-7pspd5XzG3PImfQ6Y -} - -func ExampleJSONWebToken_Claims_map() { - raw := `eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJpc3N1ZXIiLCJzdWIiOiJzdWJqZWN0In0.gpHyA1B1H6X4a4Edm9wo7D3X2v3aLSDBDG2_5BzXYe0` - tok, err := jwt.ParseSigned(raw) - if err != nil { - panic(err) - } - - out := make(map[string]interface{}) - if err := tok.Claims(sharedKey, &out); err != nil { - panic(err) - } - - fmt.Printf("iss: %s, sub: %s\n", out["iss"], out["sub"]) - // Output: iss: issuer, sub: subject -} - -func ExampleJSONWebToken_Claims_multiple() { - raw := `eyJhbGciOiJIUzI1NiJ9.eyJTY29wZXMiOlsiZm9vIiwiYmFyIl0sImlzcyI6Imlzc3VlciIsInN1YiI6InN1YmplY3QifQ.esKOIsmwkudr_gnfnB4SngxIr-7pspd5XzG3PImfQ6Y` - tok, err := jwt.ParseSigned(raw) - if err != nil { - panic(err) - } - - out := jwt.Claims{} - out2 := struct { - Scopes []string - }{} - if err := tok.Claims(sharedKey, &out, &out2); err != nil { - panic(err) - } - fmt.Printf("iss: %s, sub: %s, scopes: %s\n", out.Issuer, out.Subject, strings.Join(out2.Scopes, ",")) - // Output: iss: issuer, sub: subject, scopes: foo,bar -} - -func mustUnmarshalRSA(data string) *rsa.PrivateKey { - block, _ := pem.Decode([]byte(data)) - if block == nil { - panic("failed to decode PEM data") - } - key, err := x509.ParsePKCS8PrivateKey(block.Bytes) - if err != nil { - panic("failed to parse RSA key: " + err.Error()) - } - if key, ok := key.(*rsa.PrivateKey); ok { - return key - } - panic("key is not of type *rsa.PrivateKey") -} - -func mustMakeSigner(alg jose.SignatureAlgorithm, k interface{}) jose.Signer { - sig, err := jose.NewSigner(jose.SigningKey{Algorithm: alg, Key: k}, nil) - if err != nil { - panic("failed to create signer:" + err.Error()) - } - - return sig -} - -var rsaPrivKey = mustUnmarshalRSA(`-----BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDIHBvDHAr7jh8h -xaqBCl11fjI9YZtdC5b3HtXTXZW3c2dIOImNUjffT8POP6p5OpzivmC1om7iOyuZ -3nJjC9LT3zqqs3f2i5d4mImxEuqG6uWdryFfkp0uIv5VkjVO+iQWd6pDAPGP7r1Z -foXCleyCtmyNH4JSkJneNPOk/4BxO8vcvRnCMT/Gv81IT6H+OQ6OovWOuJr8RX9t -1wuCjC9ezZxeI9ONffhiO5FMrVh5H9LJTl3dPOVa4aEcOvgd45hBmvxAyXqf8daE -6Kl2O7vQ4uwgnSTVXYIIjCjbepuersApIMGx/XPSgiU1K3Xtah/TBvep+S3VlwPc -q/QH25S9AgMBAAECggEAe+y8XKYfPw4SxY1uPB+5JSwT3ON3nbWxtjSIYy9Pqp5z -Vcx9kuFZ7JevQSk4X38m7VzM8282kC/ono+d8yy9Uayq3k/qeOqV0X9Vti1qxEbw -ECkG1/MqGApfy4qSLOjINInDDV+mOWa2KJgsKgdCwuhKbVMYGB2ozG2qfYIlfvlY -vLcBEpGWmswJHNmkcjTtGFIyJgPbsI6ndkkOeQbqQKAaadXtG1xUzH+vIvqaUl/l -AkNf+p4qhPkHsoAWXf1qu9cYa2T8T+mEo79AwlgVC6awXQWNRTiyClDJC7cu6NBy -ZHXCLFMbalzWF9qeI2OPaFX2x3IBWrbyDxcJ4TSdQQKBgQD/Fp/uQonMBh1h4Vi4 -HlxZdqSOArTitXValdLFGVJ23MngTGV/St4WH6eRp4ICfPyldsfcv6MZpNwNm1Rn -lB5Gtpqpby1dsrOSfvVbY7U3vpLnd8+hJ/lT5zCYt5Eor46N6iWRkYWzNe4PixiF -z1puGUvFCbZdeeACVrPLmW3JKQKBgQDI0y9WTf8ezKPbtap4UEE6yBf49ftohVGz -p4iD6Ng1uqePwKahwoVXKOc179CjGGtW/UUBORAoKRmxdHajHq6LJgsBxpaARz21 -COPy99BUyp9ER5P8vYn63lC7Cpd/K7uyMjaz1DAzYBZIeVZHIw8O9wuGNJKjRFy9 -SZyD3V0ddQKBgFMdohrWH2QVEfnUnT3Q1rJn0BJdm2bLTWOosbZ7G72TD0xAWEnz -sQ1wXv88n0YER6X6YADziEdQykq8s/HT91F/KkHO8e83zP8M0xFmGaQCOoelKEgQ -aFMIX3NDTM7+9OoUwwz9Z50PE3SJFAJ1n7eEEoYvNfabQXxBl+/dHEKRAoGAPEvU -EaiXacrtg8EWrssB2sFLGU/ZrTciIbuybFCT4gXp22pvXXAHEvVP/kzDqsRhLhwb -BNP6OuSkNziNikpjA5pngZ/7fgZly54gusmW/m5bxWdsUl0iOXVYbeAvPlqGH2me -LP4Pfs1hw17S/cbT9Z1NE31jbavP4HFikeD73SUCgYEArQfuudml6ei7XZ1Emjq8 -jZiD+fX6e6BD/ISatVnuyZmGj9wPFsEhY2BpLiAMQHMDIvH9nlKzsFvjkTPB86qG -jCh3D67Os8eSBk5uRC6iW3Fc4DXvB5EFS0W9/15Sl+V5vXAcrNMpYS82OTSMG2Gt -b9Ym/nxaqyTu0PxajXkKm5Q= ------END PRIVATE KEY-----`) - -var rsaSigner = mustMakeSigner(jose.RS256, rsaPrivKey) diff --git a/vendor/gopkg.in/square/go-jose.v2/jwt/jwt_test.go b/vendor/gopkg.in/square/go-jose.v2/jwt/jwt_test.go deleted file mode 100644 index 130c283f8..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/jwt/jwt_test.go +++ /dev/null @@ -1,137 +0,0 @@ -/*- - * Copyright 2016 Zbigniew Mandziejewicz - * Copyright 2016 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jwt - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -var ( - hmacSignedToken = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiaXNzIjoiaXNzdWVyIiwic2NvcGVzIjpbInMxIiwiczIiXX0.Y6_PfQHrzRJ_Vlxij5VI07-pgDIuJNN3Z_g5sSaGQ0c` - rsaSignedToken = `eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJpc3N1ZXIiLCJzY29wZXMiOlsiczEiLCJzMiJdLCJzdWIiOiJzdWJqZWN0In0.UDDtyK9gC9kyHltcP7E_XODsnqcJWZIiXeGmSAH7SE9YKy3N0KSfFIN85dCNjTfs6zvy4rkrCHzLB7uKAtzMearh3q7jL4nxbhUMhlUcs_9QDVoN4q_j58XmRqBqRnBk-RmDu9TgcV8RbErP4awpIhwWb5UU-hR__4_iNbHdKqwSUPDKYGlf5eicuiYrPxH8mxivk4LRD-vyRdBZZKBt0XIDnEU4TdcNCzAXojkftqcFWYsczwS8R4JHd1qYsMyiaWl4trdHZkO4QkeLe34z4ZAaPMt3wE-gcU-VoqYTGxz-K3Le2VaZ0r3j_z6bOInsv0yngC_cD1dCXMyQJWnWjQ` - invalidPayloadSignedToken = `eyJhbGciOiJIUzI1NiJ9.aW52YWxpZC1wYXlsb2Fk.ScBKKm18jcaMLGYDNRUqB5gVMRZl4DM6dh3ShcxeNgY` - invalidPartsSignedToken = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiaXNzIjoiaXNzdWVyIiwic2NvcGVzIjpbInMxIiwiczIiXX0` - hmacEncryptedToken = `eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIn0..NZrU98U4QNO0y-u6.HSq5CvlmkUT1BPqLGZ4.1-zuiZ4RbHrTTUoA8Dvfhg` - rsaEncryptedToken = `eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.IvkVHHiI8JwwavvTR80xGjYvkzubMrZ-TDDx8k8SNJMEylfFfNUc7F2rC3WAABF_xmJ3SW2A6on-S6EAG97k0RsjqHHNqZuaFpDvjeuLqZFfYKzI45aCtkGG4C2ij2GbeySqJ784CcvFJPUWJ-6VPN2Ho2nhefUSqig0jE2IvOKy1ywTj_VBVBxF_dyXFnXwxPKGUQr3apxrWeRJfDh2Cf8YPBlLiRznjfBfwgePB1jP7WCZNwItj10L7hsT_YWEx01XJcbxHaXFLwKyVzwWaDhreFyaWMRbGqEfqVuOT34zfmhLDhQlgLLwkXrvYqX90NsQ9Ftg0LLIfRMbsfdgug.BFy2Tj1RZN8yq2Lk-kMiZQ.9Z0eOyPiv5cEzmXh64RlAQ36Uvz0WpZgqRcc2_69zHTmUOv0Vnl1I6ks8sTraUEvukAilolNBjBj47s0b4b-Og.VM8-eJg5ZsqnTqs0LtGX_Q` - invalidPayloadEncryptedToken = `eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIn0..T4jCS4Yyw1GCH0aW.y4gFaMITdBs_QZM8RKrL.6MPyk1cMVaOJFoNGlEuaRQ` - invalidPartsEncryptedToken = `eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIn0..NZrU98U4QNO0y-u6.HSq5CvlmkUT1BPqLGZ4` - signedAndEncryptedToken = `eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiY3R5IjoiSldUIn0.icnR7M1HSgMDaUnJhfzT5nLmT0eRPeNsKPkioNcyq9TZsm-LgbE7wZkNFGfQqYwvbmrZ3UpOhNkrq4n2KN3N1dtjH9TVxzfMxz2OMh0dRWUNMi58EMadhmIpH3PLyyaeDyd0dyHpOIRPFTAoOdn2GoO_flV5CvPMhgdVKYB3h3vQW-ZZDu4cOZwXAjTuThdoUZCNWFhJhXyj-PrKLyVpX6rE1o4X05IS8008SLZyx-PZlsUPyLs6CJi7Z4PzZRzOJTV00a-7UOi-fBKBZV5V8eRpWuzJ673pMALlRCBzrRin-JeEA_QnAejtMAHG7RSGP60easQN4I-0jLTQNNNynw.oFrO-5ZgRrnWmbkPsbyMiQ.BVaWUzlrdfhe0otPJpb3DGoDCT6-BOmN_Pgq5NOqVFYIAwG5pM4pf7TaiPUJeQLf0phbLgpT4RfJ20Zhwfc2MH5unCqc8TZEP2dOrYRhb8o-X57x6IQppIDbjK2i_CAWf3yF5JUB7qRqOizpKZTh3HFTVEglY3WF8tAJ8KpnatTUmwcnqlyjdBFvYu4usiyvc_u9wNbXx5-lFt0slQYleHQMUirBprKyswIBjMoFJEe7kDvU_MCKI4NI9_fSfWJpaUdNxQEvRYR1PV4ZQdwBY0X9u2n2QH5iVQMrmgmQ5hPbWxwRv1-7jXBMPBpGeFQZHeEtSwif1_Umwyt8cDyRChb3OM7XQ3eY0UJRrbmvhcLWIcMp8FpblDaBinbjD6qIVXZVmaAdIbi2a_HblfoeL3-UABb82AAxOqQcAFjDEDTR2TFalDXSwgPZrAaQ_Mql3eFe9r2y0UVkgG7XYF4ik8sSK48CkZPUvkZFr-K9QMq-RZLzT3Zw0edxNaKgje27S26H9qClh6CCr9nk38AZZ76_Xz7f-Fil5xI0Dq95UzvwW__U3JJWE6OVUVx_RVJgdOJn8_B7hluckwBLUblscA.83pPXNnH0sKgHvFboiJVDA` - invalidSignedAndEncryptedToken = `eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.QKYu3DkFEXBUa2U0Sgtm-e44BMuaFVbMu2T-GB3qEGONrmOuaB5BtNCvBUnuj6HR0v6u-tvawToRSzExQQLFTvPcLiQR8iclWirqAFUqLrg8kRU3qIRLkmErYeGIfCML1jq9ofKg0DI5-YrU5RSyUg9cwfXKEx8KNwFcjeVeDZwWEACdU8xBnQp57rNfr0Tj-dPnGKID7LU5ZV0vhK90FpEG7UqOeSHFmvONQyz6Ca-ZkE8X2swqGad-q5xl8f9pApdFqHzADox5OlgtxPkr-Khkm6WGfvf1K_e-iW5LYtvWIAjNByft2TexsNcYpdAO2oNAgh2nkhoohl-zCWU-og.UAU65JWKqvHZ_Z0V-xLyjQ.M6sQ4lAzKFelSmL6C6uoK00rB8IFCAK-eJ0iByGhtg8eYtmSBFsP_oUySfKPtxcPRkQ7YxnEX5D-DOo20wCV7il2Be9No__0R6_5heISOMXcKmKP3D6pFusaPisNGOgLw8SKXBuVpe20PvOJ9RgOXRKucSR2UMINXtqIn9RdxbKOlBBmMJhnX4TeQ00fRILng2sMbUHsWExSthQODHGx6VcwLFp-Aqmsnv2q2KkLpA8sEm48AHHFQXSGtlVGVgWKi3dOQYUnDJW4P64Xxr1Uq3yT7w_dRwK4BA7l3Biecj5dwkKrFMJ_RaCt-ED_R15zpxg6PmnXeeJnif58Fai40ZWOsGvLZNYwL1jbi-TrsargpdUQedfzuTk8Na2NkCzFNg2BYXVDHJ_WAX1daVyhvunaURwAlBatAcmnOGxWebwV1xQoQ7iHg6ZGohCannn_pqGwJlMHMgnCcnCIhwfj9uL9Ejz_TVceZNMlT1KvLRafVfxGhkp48bdnd8OcXmjT9pQzZUB3OqrstWKhbItZ1xMpy6dZ54ldWvtTTyQ4tQJaVWgXERUM1erDT6Ypyl15-fumOB9MRcgMG3NDblKowA.P9WTBITvVUgrLjX6bS0opQ` -) - -type customClaims struct { - Scopes []string `json:"scopes,omitempty"` -} - -func TestDecodeToken(t *testing.T) { - tok, err := ParseSigned(hmacSignedToken) - if assert.NoError(t, err, "Error parsing signed token.") { - c := &Claims{} - c2 := &customClaims{} - if assert.NoError(t, tok.Claims(sharedKey, c, c2)) { - assert.Equal(t, "subject", c.Subject) - assert.Equal(t, "issuer", c.Issuer) - assert.Equal(t, []string{"s1", "s2"}, c2.Scopes) - } - } - assert.EqualError(t, tok.Claims([]byte("invalid-secret")), "square/go-jose: error in cryptographic primitive") - - tok2, err := ParseSigned(rsaSignedToken) - if assert.NoError(t, err, "Error parsing encrypted token.") { - c := make(map[string]interface{}) - if assert.NoError(t, tok2.Claims(&testPrivRSAKey1.PublicKey, &c)) { - assert.Equal(t, map[string]interface{}{ - "sub": "subject", - "iss": "issuer", - "scopes": []interface{}{"s1", "s2"}, - }, c) - } - } - assert.EqualError(t, tok.Claims(&testPrivRSAKey2.PublicKey), "square/go-jose: error in cryptographic primitive") - - tok3, err := ParseSigned(invalidPayloadSignedToken) - if assert.NoError(t, err, "Error parsing signed token.") { - assert.Error(t, tok3.Claims(sharedKey, &Claims{}), "Expected unmarshaling claims to fail.") - } - - _, err = ParseSigned(invalidPartsSignedToken) - assert.EqualError(t, err, "square/go-jose: compact JWS format must have three parts") - - tok4, err := ParseEncrypted(hmacEncryptedToken) - if assert.NoError(t, err, "Error parsing encrypted token.") { - c := Claims{} - if assert.NoError(t, tok4.Claims(sharedEncryptionKey, &c)) { - assert.Equal(t, "foo", c.Subject) - } - } - assert.EqualError(t, tok4.Claims([]byte("invalid-secret-key")), "square/go-jose: error in cryptographic primitive") - - tok5, err := ParseEncrypted(rsaEncryptedToken) - if assert.NoError(t, err, "Error parsing encrypted token.") { - c := make(map[string]interface{}) - if assert.NoError(t, tok5.Claims(testPrivRSAKey1, &c)) { - assert.Equal(t, map[string]interface{}{ - "sub": "subject", - "iss": "issuer", - "scopes": []interface{}{"s1", "s2"}, - }, c) - } - } - assert.EqualError(t, tok5.Claims(testPrivRSAKey2), "square/go-jose: error in cryptographic primitive") - - tok6, err := ParseEncrypted(invalidPayloadEncryptedToken) - if assert.NoError(t, err, "Error parsing encrypted token.") { - assert.Error(t, tok6.Claims(sharedEncryptionKey, &Claims{})) - } - - _, err = ParseEncrypted(invalidPartsEncryptedToken) - assert.EqualError(t, err, "square/go-jose: compact JWE format must have five parts") - - tok7, err := ParseSignedAndEncrypted(signedAndEncryptedToken) - if assert.NoError(t, err, "Error parsing signed-then-encrypted token.") { - c := make(map[string]interface{}) - if nested, err := tok7.Decrypt(testPrivRSAKey1); assert.NoError(t, err) { - assert.NoError(t, nested.Claims(testPrivRSAKey1.Public(), &c)) - assert.Equal(t, map[string]interface{}{ - "sub": "subject", - "iss": "issuer", - "scopes": []interface{}{"s1", "s2"}, - }, c) - assert.EqualError(t, nested.Claims(testPrivRSAKey2.Public()), "square/go-jose: error in cryptographic primitive") - } - } - _, err = tok7.Decrypt(testPrivRSAKey2) - assert.EqualError(t, err, "square/go-jose: error in cryptographic primitive") - - _, err = ParseSignedAndEncrypted(invalidSignedAndEncryptedToken) - assert.EqualError(t, err, "square/go-jose/jwt: expected content type to be JWT (cty header)") -} - -func BenchmarkDecodeSignedToken(b *testing.B) { - for i := 0; i < b.N; i++ { - ParseSigned(hmacSignedToken) - } -} - -func BenchmarkDecodeEncryptedHMACToken(b *testing.B) { - for i := 0; i < b.N; i++ { - ParseEncrypted(hmacEncryptedToken) - } -} diff --git a/vendor/gopkg.in/square/go-jose.v2/jwt/validation_test.go b/vendor/gopkg.in/square/go-jose.v2/jwt/validation_test.go deleted file mode 100644 index 7df850f79..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/jwt/validation_test.go +++ /dev/null @@ -1,92 +0,0 @@ -/*- - * Copyright 2016 Zbigniew Mandziejewicz - * Copyright 2016 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jwt - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestFieldsMatch(t *testing.T) { - c := Claims{ - Issuer: "issuer", - Subject: "subject", - Audience: []string{"a1", "a2"}, - ID: "42", - } - - valid := []Expected{ - {Issuer: "issuer"}, - {Subject: "subject"}, - {Audience: Audience{"a1", "a2"}}, - {Audience: Audience{"a2", "a1"}}, - {ID: "42"}, - } - - for _, v := range valid { - assert.NoError(t, c.Validate(v)) - } - - invalid := []struct { - Expected Expected - Error error - }{ - {Expected{Issuer: "invalid-issuer"}, ErrInvalidIssuer}, - {Expected{Subject: "invalid-subject"}, ErrInvalidSubject}, - {Expected{Audience: Audience{"invalid-audience"}}, ErrInvalidAudience}, - {Expected{ID: "invalid-id"}, ErrInvalidID}, - } - - for _, v := range invalid { - assert.Equal(t, v.Error, c.Validate(v.Expected)) - } -} - -func TestExpiryAndNotBefore(t *testing.T) { - now := time.Date(2016, 1, 1, 12, 0, 0, 0, time.UTC) - twelveHoursAgo := now.Add(-12 * time.Hour) - - c := Claims{ - IssuedAt: NewNumericDate(twelveHoursAgo), - NotBefore: NewNumericDate(twelveHoursAgo), - Expiry: NewNumericDate(now), - } - - // expired - default leeway (1 minute) - assert.NoError(t, c.Validate(Expected{Time: now})) - err := c.Validate(Expected{Time: now.Add(2 * DefaultLeeway)}) - if assert.Error(t, err) { - assert.Equal(t, err, ErrExpired) - } - - // expired - no leeway - assert.NoError(t, c.ValidateWithLeeway(Expected{Time: now}, 0)) - err = c.ValidateWithLeeway(Expected{Time: now.Add(1 * time.Second)}, 0) - if assert.Error(t, err) { - assert.Equal(t, err, ErrExpired) - } - - // not before - default leeway (1 minute) - assert.NoError(t, c.Validate(Expected{Time: twelveHoursAgo})) - err = c.Validate(Expected{Time: twelveHoursAgo.Add(-2 * DefaultLeeway)}) - if assert.Error(t, err) { - assert.Equal(t, err, ErrNotValidYet) - } -} diff --git a/vendor/gopkg.in/square/go-jose.v2/opaque_test.go b/vendor/gopkg.in/square/go-jose.v2/opaque_test.go deleted file mode 100644 index d6f7cc378..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/opaque_test.go +++ /dev/null @@ -1,192 +0,0 @@ -/*- - * Copyright 2018 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jose - -import ( - "fmt" - "testing" -) - -type signWrapper struct { - pk *JSONWebKey - wrapped payloadSigner - algs []SignatureAlgorithm -} - -var _ = OpaqueSigner(&signWrapper{}) - -func (sw *signWrapper) Algs() []SignatureAlgorithm { - return sw.algs -} - -func (sw *signWrapper) Public() *JSONWebKey { - return sw.pk -} - -func (sw *signWrapper) SignPayload(payload []byte, alg SignatureAlgorithm) ([]byte, error) { - sig, err := sw.wrapped.signPayload(payload, alg) - if err != nil { - return nil, err - } - return sig.Signature, nil -} - -type verifyWrapper struct { - wrapped []payloadVerifier -} - -var _ = OpaqueVerifier(&verifyWrapper{}) - -func (vw *verifyWrapper) VerifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error { - if len(vw.wrapped) == 0 { - return fmt.Errorf("error: verifier had no keys") - } - var err error - for _, v := range vw.wrapped { - err = v.verifyPayload(payload, signature, alg) - if err == nil { - return nil - } - } - return err -} - -func TestRoundtripsJWSOpaque(t *testing.T) { - sigAlgs := []SignatureAlgorithm{RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512, EdDSA} - - serializers := []func(*JSONWebSignature) (string, error){ - func(obj *JSONWebSignature) (string, error) { return obj.CompactSerialize() }, - func(obj *JSONWebSignature) (string, error) { return obj.FullSerialize(), nil }, - } - - corrupter := func(obj *JSONWebSignature) {} - - for _, alg := range sigAlgs { - signingKey, verificationKey := GenerateSigningTestKey(alg) - - for i, serializer := range serializers { - sw := makeOpaqueSigner(t, signingKey, alg) - vw := makeOpaqueVerifier(t, []interface{}{verificationKey}, alg) - - err := RoundtripJWS(alg, serializer, corrupter, sw, verificationKey, "test_nonce") - if err != nil { - t.Error(err, alg, i) - } - - err = RoundtripJWS(alg, serializer, corrupter, signingKey, vw, "test_nonce") - if err != nil { - t.Error(err, alg, i) - } - - err = RoundtripJWS(alg, serializer, corrupter, sw, vw, "test_nonce") - if err != nil { - t.Error(err, alg, i) - } - } - } -} - -func makeOpaqueSigner(t *testing.T, signingKey interface{}, alg SignatureAlgorithm) *signWrapper { - ri, err := makeJWSRecipient(alg, signingKey) - if err != nil { - t.Fatal(err) - } - return &signWrapper{ - wrapped: ri.signer, - algs: []SignatureAlgorithm{alg}, - pk: &JSONWebKey{Key: ri.publicKey()}, - } -} - -func makeOpaqueVerifier(t *testing.T, verificationKey []interface{}, alg SignatureAlgorithm) *verifyWrapper { - var verifiers []payloadVerifier - for _, vk := range verificationKey { - verifier, err := newVerifier(vk) - if err != nil { - t.Fatal(err) - } - verifiers = append(verifiers, verifier) - } - return &verifyWrapper{wrapped: verifiers} -} - -func TestOpaqueSignerKeyRotation(t *testing.T) { - - sigAlgs := []SignatureAlgorithm{RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512, EdDSA} - - serializers := []func(*JSONWebSignature) (string, error){ - func(obj *JSONWebSignature) (string, error) { return obj.CompactSerialize() }, - func(obj *JSONWebSignature) (string, error) { return obj.FullSerialize(), nil }, - } - - for _, alg := range sigAlgs { - for i, serializer := range serializers { - sk1, pk1 := GenerateSigningTestKey(alg) - sk2, pk2 := GenerateSigningTestKey(alg) - - sw := makeOpaqueSigner(t, sk1, alg) - sw.pk.KeyID = "first" - vw := makeOpaqueVerifier(t, []interface{}{pk1, pk2}, alg) - - signer, err := NewSigner( - SigningKey{Algorithm: alg, Key: sw}, - &SignerOptions{NonceSource: staticNonceSource("test_nonce")}, - ) - if err != nil { - t.Fatal(err, alg, i) - } - - jws1, err := signer.Sign([]byte("foo bar baz")) - if err != nil { - t.Fatal(err, alg, i) - } - jws1 = rtSerialize(t, serializer, jws1, vw) - if kid := jws1.Signatures[0].Protected.KeyID; kid != "first" { - t.Errorf("expected kid %q but got %q", "first", kid) - } - - swNext := makeOpaqueSigner(t, sk2, alg) - swNext.pk.KeyID = "next" - sw.wrapped = swNext.wrapped - sw.pk = swNext.pk - - jws2, err := signer.Sign([]byte("foo bar baz next")) - if err != nil { - t.Error(err, alg, i) - } - jws2 = rtSerialize(t, serializer, jws2, vw) - if kid := jws2.Signatures[0].Protected.KeyID; kid != "next" { - t.Errorf("expected kid %q but got %q", "next", kid) - } - } - } -} - -func rtSerialize(t *testing.T, serializer func(*JSONWebSignature) (string, error), sig *JSONWebSignature, vk interface{}) *JSONWebSignature { - b, err := serializer(sig) - if err != nil { - t.Fatal(err) - } - sig, err = ParseSigned(b) - if err != nil { - t.Fatal(err) - } - if _, err := sig.Verify(vk); err != nil { - t.Fatal(err) - } - return sig -} diff --git a/vendor/gopkg.in/square/go-jose.v2/signing_test.go b/vendor/gopkg.in/square/go-jose.v2/signing_test.go deleted file mode 100644 index 4ed2482e8..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/signing_test.go +++ /dev/null @@ -1,523 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jose - -import ( - "bytes" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "fmt" - "io" - "reflect" - "testing" - - "gopkg.in/square/go-jose.v2/json" -) - -type staticNonceSource string - -func (sns staticNonceSource) Nonce() (string, error) { - return string(sns), nil -} - -func RoundtripJWS(sigAlg SignatureAlgorithm, serializer func(*JSONWebSignature) (string, error), corrupter func(*JSONWebSignature), signingKey interface{}, verificationKey interface{}, nonce string) error { - opts := &SignerOptions{} - if nonce != "" { - opts.NonceSource = staticNonceSource(nonce) - } - - signer, err := NewSigner(SigningKey{Algorithm: sigAlg, Key: signingKey}, opts) - if err != nil { - return fmt.Errorf("error on new signer: %s", err) - } - - input := []byte("Lorem ipsum dolor sit amet") - obj, err := signer.Sign(input) - if err != nil { - return fmt.Errorf("error on sign: %s", err) - } - - msg, err := serializer(obj) - if err != nil { - return fmt.Errorf("error on serialize: %s", err) - } - - obj, err = ParseSigned(msg) - if err != nil { - return fmt.Errorf("error on parse: %s", err) - } - - // (Maybe) mangle the object - corrupter(obj) - - output, err := obj.Verify(verificationKey) - if err != nil { - return fmt.Errorf("error on verify: %s", err) - } - - // Check that verify works with embedded keys (if present) - for i, sig := range obj.Signatures { - if sig.Header.JSONWebKey != nil { - _, err = obj.Verify(sig.Header.JSONWebKey) - if err != nil { - return fmt.Errorf("error on verify with embedded key %d: %s", i, err) - } - } - - // Check that the nonce correctly round-tripped (if present) - if sig.Header.Nonce != nonce { - return fmt.Errorf("Incorrect nonce returned: [%s]", sig.Header.Nonce) - } - } - - if bytes.Compare(output, input) != 0 { - return fmt.Errorf("input/output do not match, got '%s', expected '%s'", output, input) - } - - return nil -} - -func TestRoundtripsJWS(t *testing.T) { - // Test matrix - sigAlgs := []SignatureAlgorithm{RS256, RS384, RS512, PS256, PS384, PS512, HS256, HS384, HS512, ES256, ES384, ES512, EdDSA} - - serializers := []func(*JSONWebSignature) (string, error){ - func(obj *JSONWebSignature) (string, error) { return obj.CompactSerialize() }, - func(obj *JSONWebSignature) (string, error) { return obj.FullSerialize(), nil }, - } - - corrupter := func(obj *JSONWebSignature) {} - - for _, alg := range sigAlgs { - signingKey, verificationKey := GenerateSigningTestKey(alg) - - for i, serializer := range serializers { - err := RoundtripJWS(alg, serializer, corrupter, signingKey, verificationKey, "test_nonce") - if err != nil { - t.Error(err, alg, i) - } - } - } -} - -func TestRoundtripsJWSCorruptSignature(t *testing.T) { - // Test matrix - sigAlgs := []SignatureAlgorithm{RS256, RS384, RS512, PS256, PS384, PS512, HS256, HS384, HS512, ES256, ES384, ES512, EdDSA} - - serializers := []func(*JSONWebSignature) (string, error){ - func(obj *JSONWebSignature) (string, error) { return obj.CompactSerialize() }, - func(obj *JSONWebSignature) (string, error) { return obj.FullSerialize(), nil }, - } - - corrupters := []func(*JSONWebSignature){ - func(obj *JSONWebSignature) { - // Changes bytes in signature - obj.Signatures[0].Signature[10]++ - }, - func(obj *JSONWebSignature) { - // Set totally invalid signature - obj.Signatures[0].Signature = []byte("###") - }, - } - - // Test all different configurations - for _, alg := range sigAlgs { - signingKey, verificationKey := GenerateSigningTestKey(alg) - - for i, serializer := range serializers { - for j, corrupter := range corrupters { - err := RoundtripJWS(alg, serializer, corrupter, signingKey, verificationKey, "test_nonce") - if err == nil { - t.Error("failed to detect corrupt signature", err, alg, i, j) - } - } - } - } -} - -func TestSignerWithBrokenRand(t *testing.T) { - sigAlgs := []SignatureAlgorithm{RS256, RS384, RS512, PS256, PS384, PS512} - - serializer := func(obj *JSONWebSignature) (string, error) { return obj.CompactSerialize() } - corrupter := func(obj *JSONWebSignature) {} - - // Break rand reader - readers := []func() io.Reader{ - // Totally broken - func() io.Reader { return bytes.NewReader([]byte{}) }, - // Not enough bytes - func() io.Reader { return io.LimitReader(rand.Reader, 20) }, - } - - defer resetRandReader() - - for _, alg := range sigAlgs { - signingKey, verificationKey := GenerateSigningTestKey(alg) - for i, getReader := range readers { - randReader = getReader() - err := RoundtripJWS(alg, serializer, corrupter, signingKey, verificationKey, "test_nonce") - if err == nil { - t.Error("signer should fail if rand is broken", alg, i) - } - } - } -} - -func TestJWSInvalidKey(t *testing.T) { - signingKey0, verificationKey0 := GenerateSigningTestKey(RS256) - _, verificationKey1 := GenerateSigningTestKey(ES256) - _, verificationKey2 := GenerateSigningTestKey(EdDSA) - - signer, err := NewSigner(SigningKey{Algorithm: RS256, Key: signingKey0}, nil) - if err != nil { - panic(err) - } - - input := []byte("Lorem ipsum dolor sit amet") - obj, err := signer.Sign(input) - if err != nil { - panic(err) - } - - // Must work with correct key - _, err = obj.Verify(verificationKey0) - if err != nil { - t.Error("error on verify", err) - } - - // Must not work with incorrect key - _, err = obj.Verify(verificationKey1) - if err == nil { - t.Error("verification should fail with incorrect key") - } - - // Must not work with incorrect key - _, err = obj.Verify(verificationKey2) - if err == nil { - t.Error("verification should fail with incorrect key") - } - - // Must not work with invalid key - _, err = obj.Verify("") - if err == nil { - t.Error("verification should fail with incorrect key") - } -} - -func TestMultiRecipientJWS(t *testing.T) { - sharedKey := []byte{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - } - jwkSharedKey := JSONWebKey{ - KeyID: "123", - Key: sharedKey, - } - - signer, err := NewMultiSigner([]SigningKey{ - {RS256, rsaTestKey}, - {HS384, sharedKey}, - {HS512, jwkSharedKey}, - }, nil) - if err != nil { - t.Fatal("error creating signer: ", err) - } - - input := []byte("Lorem ipsum dolor sit amet") - obj, err := signer.Sign(input) - if err != nil { - t.Fatal("error on sign: ", err) - } - - _, err = obj.CompactSerialize() - if err == nil { - t.Fatal("message with multiple recipient was compact serialized") - } - - msg := obj.FullSerialize() - - obj, err = ParseSigned(msg) - if err != nil { - t.Fatal("error on parse: ", err) - } - - i, _, output, err := obj.VerifyMulti(&rsaTestKey.PublicKey) - if err != nil { - t.Fatal("error on verify: ", err) - } - - if i != 0 { - t.Fatal("signature index should be 0 for RSA key") - } - - if bytes.Compare(output, input) != 0 { - t.Fatal("input/output do not match", output, input) - } - - i, _, output, err = obj.VerifyMulti(sharedKey) - if err != nil { - t.Fatal("error on verify: ", err) - } - - if i != 1 { - t.Fatal("signature index should be 1 for EC key") - } - - if bytes.Compare(output, input) != 0 { - t.Fatal("input/output do not match", output, input) - } -} - -func GenerateSigningTestKey(sigAlg SignatureAlgorithm) (sig, ver interface{}) { - switch sigAlg { - case EdDSA: - sig = ed25519PrivateKey - ver = ed25519PublicKey - case RS256, RS384, RS512, PS256, PS384, PS512: - sig = rsaTestKey - ver = &rsaTestKey.PublicKey - case HS256, HS384, HS512: - sig, _, _ = randomKeyGenerator{size: 16}.genKey() - ver = sig - case ES256: - key, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - sig = key - ver = &key.PublicKey - case ES384: - key, _ := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) - sig = key - ver = &key.PublicKey - case ES512: - key, _ := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) - sig = key - ver = &key.PublicKey - default: - panic("Must update test case") - } - - return -} - -func TestInvalidSignerAlg(t *testing.T) { - _, err := NewSigner(SigningKey{"XYZ", nil}, nil) - if err == nil { - t.Error("should not accept invalid algorithm") - } - - _, err = NewSigner(SigningKey{"XYZ", []byte{}}, nil) - if err == nil { - t.Error("should not accept invalid algorithm") - } -} - -func TestInvalidJWS(t *testing.T) { - signer, err := NewSigner(SigningKey{PS256, rsaTestKey}, nil) - if err != nil { - panic(err) - } - - obj, err := signer.Sign([]byte("Lorem ipsum dolor sit amet")) - obj.Signatures[0].header = &rawHeader{} - obj.Signatures[0].header.set(headerCritical, []string{"TEST"}) - - _, err = obj.Verify(&rsaTestKey.PublicKey) - if err == nil { - t.Error("should not verify message with unknown crit header") - } - - // Try without alg header - obj.Signatures[0].protected = &rawHeader{} - obj.Signatures[0].header = &rawHeader{} - - _, err = obj.Verify(&rsaTestKey.PublicKey) - if err == nil { - t.Error("should not verify message with missing headers") - } -} - -func TestSignerKid(t *testing.T) { - kid := "DEADBEEF" - payload := []byte("Lorem ipsum dolor sit amet") - - key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - t.Error("problem generating test signing key", err) - } - - basejwk := JSONWebKey{Key: key} - jsonbar, err := basejwk.MarshalJSON() - if err != nil { - t.Error("problem marshalling base JWK", err) - } - - var jsonmsi map[string]interface{} - err = json.Unmarshal(jsonbar, &jsonmsi) - if err != nil { - t.Error("problem unmarshalling base JWK", err) - } - jsonmsi["kid"] = kid - jsonbar2, err := json.Marshal(jsonmsi) - if err != nil { - t.Error("problem marshalling kided JWK", err) - } - - var jwk JSONWebKey - err = jwk.UnmarshalJSON(jsonbar2) - if err != nil { - t.Error("problem unmarshalling kided JWK", err) - } - - signer, err := NewSigner(SigningKey{ES256, &jwk}, nil) - if err != nil { - t.Error("problem creating signer with *JSONWebKey", err) - } - signed, err := signer.Sign(payload) - - serialized := signed.FullSerialize() - - parsed, err := ParseSigned(serialized) - if err != nil { - t.Error("problem parsing signed object", err) - } - - if parsed.Signatures[0].Header.KeyID != kid { - t.Error("KeyID did not survive trip") - } - - signer, err = NewSigner(SigningKey{ES256, jwk}, nil) - if err != nil { - t.Error("problem creating signer with JSONWebKey", err) - } -} - -func TestEmbedJwk(t *testing.T) { - var payload = []byte("Lorem ipsum dolor sit amet") - key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - t.Error("Failed to generate key") - } - - signer, err := NewSigner(SigningKey{ES256, key}, &SignerOptions{EmbedJWK: true}) - if err != nil { - t.Error("Failed to create signer") - } - - object, err := signer.Sign(payload) - if err != nil { - t.Error("Failed to sign payload") - } - - object, err = ParseSigned(object.FullSerialize()) - if err != nil { - t.Error("Failed to parse jws") - } - - jwk, err := object.Signatures[0].protected.getJWK() - if jwk == nil || err != nil { - t.Error("JWK isn't set in protected header") - } - - // This time, sign and do not embed JWK in message - signer, err = NewSigner(SigningKey{ES256, key}, &SignerOptions{EmbedJWK: false}) - - object, err = signer.Sign(payload) - if err != nil { - t.Error("Failed to sign payload") - } - - object, err = ParseSigned(object.FullSerialize()) - if err != nil { - t.Error("Failed to parse jws") - } - - jwk2, err := object.Signatures[0].protected.getJWK() - if err != nil { - t.Error("JWK is invalid in protected header") - } - if jwk2 != nil { - t.Error("JWK is set in protected header") - } -} - -func TestSignerOptionsEd(t *testing.T) { - key, _ := GenerateSigningTestKey(EdDSA) - opts := &SignerOptions{ - EmbedJWK: true, - } - opts.WithContentType("JWT") - opts.WithType("JWT") - sig, err := NewSigner(SigningKey{EdDSA, key}, opts) - if err != nil { - t.Error("Failed to create signer") - } - - if !reflect.DeepEqual(*opts, sig.Options()) { - t.Error("Signer options do not match") - } -} - -func TestSignerOptions(t *testing.T) { - key, _ := GenerateSigningTestKey(HS256) - opts := &SignerOptions{ - EmbedJWK: true, - } - opts.WithContentType("JWT") - opts.WithType("JWT") - sig, err := NewSigner(SigningKey{HS256, key}, opts) - if err != nil { - t.Error("Failed to create signer") - } - - if !reflect.DeepEqual(*opts, sig.Options()) { - t.Error("Signer options do not match") - } -} - -// Test that extra headers are generated and parsed in a round trip. -func TestSignerExtraHeaderInclusion(t *testing.T) { - var payload = []byte("Lorem ipsum dolor sit amet") - - key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - t.Error("Failed to generate key") - } - - signer, err := NewSigner(SigningKey{ES256, key}, (&SignerOptions{}).WithContentType("foo/bar").WithHeader(HeaderKey("myCustomHeader"), "xyz")) - if err != nil { - t.Error("Failed to create signer", err) - } - - object, err := signer.Sign(payload) - if err != nil { - t.Error("Failed to sign payload") - } - - object, err = ParseSigned(object.FullSerialize()) - if err != nil { - t.Error("Failed to parse jws") - } - - correct := map[HeaderKey]interface{}{ - HeaderContentType: "foo/bar", - HeaderKey("myCustomHeader"): "xyz", - } - - if !reflect.DeepEqual(object.Signatures[0].Header.ExtraHeaders, correct) { - t.Errorf("Mismatch in extra headers: %#v", object.Signatures[0].Header.ExtraHeaders) - } -} diff --git a/vendor/gopkg.in/square/go-jose.v2/symmetric_test.go b/vendor/gopkg.in/square/go-jose.v2/symmetric_test.go deleted file mode 100644 index 67f535e3b..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/symmetric_test.go +++ /dev/null @@ -1,131 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jose - -import ( - "bytes" - "crypto/cipher" - "crypto/rand" - "io" - "testing" -) - -func TestInvalidSymmetricAlgorithms(t *testing.T) { - _, err := newSymmetricRecipient("XYZ", []byte{}) - if err != ErrUnsupportedAlgorithm { - t.Error("should not accept invalid algorithm") - } - - enc := &symmetricKeyCipher{} - _, err = enc.encryptKey([]byte{}, "XYZ") - if err != ErrUnsupportedAlgorithm { - t.Error("should not accept invalid algorithm") - } -} - -func TestAeadErrors(t *testing.T) { - aead := &aeadContentCipher{ - keyBytes: 16, - authtagBytes: 16, - getAead: func(key []byte) (cipher.AEAD, error) { - return nil, ErrCryptoFailure - }, - } - - parts, err := aead.encrypt([]byte{}, []byte{}, []byte{}) - if err != ErrCryptoFailure { - t.Error("should handle aead failure") - } - - _, err = aead.decrypt([]byte{}, []byte{}, parts) - if err != ErrCryptoFailure { - t.Error("should handle aead failure") - } -} - -func TestInvalidKey(t *testing.T) { - gcm := newAESGCM(16).(*aeadContentCipher) - _, err := gcm.getAead([]byte{}) - if err == nil { - t.Error("should not accept invalid key") - } -} - -func TestStaticKeyGen(t *testing.T) { - key := make([]byte, 32) - io.ReadFull(rand.Reader, key) - - gen := &staticKeyGenerator{key: key} - if gen.keySize() != len(key) { - t.Error("static key generator reports incorrect size") - } - - generated, _, err := gen.genKey() - if err != nil { - t.Error("static key generator should always succeed", err) - } - if !bytes.Equal(generated, key) { - t.Error("static key generator returns different data") - } -} - -func TestVectorsAESGCM(t *testing.T) { - // Source: http://tools.ietf.org/html/draft-ietf-jose-json-web-encryption-29#appendix-A.1 - plaintext := []byte{ - 84, 104, 101, 32, 116, 114, 117, 101, 32, 115, 105, 103, 110, 32, - 111, 102, 32, 105, 110, 116, 101, 108, 108, 105, 103, 101, 110, 99, - 101, 32, 105, 115, 32, 110, 111, 116, 32, 107, 110, 111, 119, 108, - 101, 100, 103, 101, 32, 98, 117, 116, 32, 105, 109, 97, 103, 105, - 110, 97, 116, 105, 111, 110, 46} - - aad := []byte{ - 101, 121, 74, 104, 98, 71, 99, 105, 79, 105, 74, 83, 85, 48, 69, - 116, 84, 48, 70, 70, 85, 67, 73, 115, 73, 109, 86, 117, 89, 121, 73, - 54, 73, 107, 69, 121, 78, 84, 90, 72, 81, 48, 48, 105, 102, 81} - - expectedCiphertext := []byte{ - 229, 236, 166, 241, 53, 191, 115, 196, 174, 43, 73, 109, 39, 122, - 233, 96, 140, 206, 120, 52, 51, 237, 48, 11, 190, 219, 186, 80, 111, - 104, 50, 142, 47, 167, 59, 61, 181, 127, 196, 21, 40, 82, 242, 32, - 123, 143, 168, 226, 73, 216, 176, 144, 138, 247, 106, 60, 16, 205, - 160, 109, 64, 63, 192} - - expectedAuthtag := []byte{ - 92, 80, 104, 49, 133, 25, 161, 215, 173, 101, 219, 211, 136, 91, 210, 145} - - // Mock random reader - randReader = bytes.NewReader([]byte{ - 177, 161, 244, 128, 84, 143, 225, 115, 63, 180, 3, 255, 107, 154, - 212, 246, 138, 7, 110, 91, 112, 46, 34, 105, 47, 130, 203, 46, 122, - 234, 64, 252, 227, 197, 117, 252, 2, 219, 233, 68, 180, 225, 77, 219}) - defer resetRandReader() - - enc := newAESGCM(32) - key, _, _ := randomKeyGenerator{size: 32}.genKey() - out, err := enc.encrypt(key, aad, plaintext) - if err != nil { - t.Error("Unable to encrypt:", err) - return - } - - if bytes.Compare(out.ciphertext, expectedCiphertext) != 0 { - t.Error("Ciphertext did not match") - } - if bytes.Compare(out.tag, expectedAuthtag) != 0 { - t.Error("Auth tag did not match") - } -} diff --git a/vendor/gopkg.in/square/go-jose.v2/utils_test.go b/vendor/gopkg.in/square/go-jose.v2/utils_test.go deleted file mode 100644 index 09440303d..000000000 --- a/vendor/gopkg.in/square/go-jose.v2/utils_test.go +++ /dev/null @@ -1,70 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jose - -import ( - "crypto/rand" - "encoding/base64" - "encoding/hex" - "math/big" - "regexp" -) - -// Reset random reader to original value -func resetRandReader() { - randReader = rand.Reader -} - -// Build big int from hex-encoded string. Strips whitespace (for testing). -func fromHexInt(base16 string) *big.Int { - re := regexp.MustCompile(`\s+`) - val, ok := new(big.Int).SetString(re.ReplaceAllString(base16, ""), 16) - if !ok { - panic("Invalid test data") - } - return val -} - -// Build big int from base64-encoded string. Strips whitespace (for testing). -func fromBase64Int(encoded string) *big.Int { - re := regexp.MustCompile(`\s+`) - val, err := base64.RawURLEncoding.DecodeString(re.ReplaceAllString(encoded, "")) - if err != nil { - panic("Invalid test data: " + err.Error()) - } - return new(big.Int).SetBytes(val) -} - -// Decode hex-encoded string into byte array. Strips whitespace (for testing). -func fromHexBytes(base16 string) []byte { - re := regexp.MustCompile(`\s+`) - val, err := hex.DecodeString(re.ReplaceAllString(base16, "")) - if err != nil { - panic("Invalid test data") - } - return val -} - -// Decode base64-encoded string into byte array. Strips whitespace (for testing). -func fromBase64Bytes(b64 string) []byte { - re := regexp.MustCompile(`\s+`) - val, err := base64.StdEncoding.DecodeString(re.ReplaceAllString(b64, "")) - if err != nil { - panic("Invalid test data") - } - return val -} diff --git a/vendor/modules.txt b/vendor/modules.txt new file mode 100644 index 000000000..7bc668d1f --- /dev/null +++ b/vendor/modules.txt @@ -0,0 +1,133 @@ +# github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf +github.com/alecthomas/units +# github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da +github.com/armon/go-metrics +# github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 +github.com/beorn7/perks/quantile +# github.com/cespare/xxhash v1.1.0 +github.com/cespare/xxhash +# github.com/coreos/go-oidc v2.0.0+incompatible +github.com/coreos/go-oidc +# github.com/go-kit/kit v0.8.0 +github.com/go-kit/kit/log +github.com/go-kit/kit/log/level +# github.com/go-logfmt/logfmt v0.4.0 +github.com/go-logfmt/logfmt +# github.com/golang/protobuf v1.2.0 +github.com/golang/protobuf/proto +# github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db +github.com/golang/snappy +# github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c +github.com/google/btree +# github.com/hashicorp/errwrap v1.0.0 +github.com/hashicorp/errwrap +# github.com/hashicorp/go-immutable-radix v1.0.0 +github.com/hashicorp/go-immutable-radix +# github.com/hashicorp/go-msgpack v0.5.3 +github.com/hashicorp/go-msgpack/codec +# github.com/hashicorp/go-multierror v1.0.0 +github.com/hashicorp/go-multierror +# github.com/hashicorp/go-sockaddr v1.0.0 +github.com/hashicorp/go-sockaddr +# github.com/hashicorp/golang-lru v0.5.0 +github.com/hashicorp/golang-lru/simplelru +# github.com/hashicorp/memberlist v0.1.4 +github.com/hashicorp/memberlist +# github.com/inconshreveable/mousetrap v1.0.0 +github.com/inconshreveable/mousetrap +# github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 +github.com/kr/logfmt +# github.com/matttproud/golang_protobuf_extensions v1.0.1 +github.com/matttproud/golang_protobuf_extensions/pbutil +# github.com/miekg/dns v1.0.14 +github.com/miekg/dns +# github.com/oklog/run v0.0.0-20180308005104-6934b124db28 +github.com/oklog/run +# github.com/oklog/ulid v1.3.1 +github.com/oklog/ulid +# github.com/opentracing/opentracing-go v1.0.1 +github.com/opentracing/opentracing-go +github.com/opentracing/opentracing-go/log +# github.com/pkg/errors v0.8.0 +github.com/pkg/errors +# github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 +github.com/pquerna/cachecontrol +github.com/pquerna/cachecontrol/cacheobject +# github.com/prometheus/client_golang v0.9.1 +github.com/prometheus/client_golang/prometheus +github.com/prometheus/client_golang/prometheus/promhttp +github.com/prometheus/client_golang/prometheus/internal +# github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 +github.com/prometheus/client_model/go +# github.com/prometheus/common v0.2.0 +github.com/prometheus/common/expfmt +github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg +github.com/prometheus/common/model +# github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d +github.com/prometheus/procfs +github.com/prometheus/procfs/nfs +github.com/prometheus/procfs/xfs +github.com/prometheus/procfs/internal/util +# github.com/prometheus/prometheus v2.7.1+incompatible +github.com/prometheus/prometheus/pkg/labels +github.com/prometheus/prometheus/promql +github.com/prometheus/prometheus/pkg/gate +github.com/prometheus/prometheus/pkg/textparse +github.com/prometheus/prometheus/pkg/timestamp +github.com/prometheus/prometheus/pkg/value +github.com/prometheus/prometheus/storage +github.com/prometheus/prometheus/util/stats +github.com/prometheus/prometheus/util/strutil +github.com/prometheus/prometheus/util/testutil +github.com/prometheus/prometheus/storage/tsdb +# github.com/prometheus/tsdb v0.4.0 +github.com/prometheus/tsdb +github.com/prometheus/tsdb/labels +github.com/prometheus/tsdb/chunkenc +github.com/prometheus/tsdb/chunks +github.com/prometheus/tsdb/fileutil +github.com/prometheus/tsdb/index +github.com/prometheus/tsdb/wal +# github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b +github.com/satori/go.uuid +# github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 +github.com/sean-/seed +# github.com/serialx/hashring v0.0.0-20180504054112-49a4782e9908 +github.com/serialx/hashring +# github.com/spf13/cobra v0.0.3 +github.com/spf13/cobra +# github.com/spf13/pflag v1.0.3 +github.com/spf13/pflag +# golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3 +golang.org/x/crypto/ed25519 +golang.org/x/crypto/ed25519/internal/edwards25519 +# golang.org/x/net v0.0.0-20181114220301-adae6a3d119a +golang.org/x/net/context +golang.org/x/net/context/ctxhttp +golang.org/x/net/ipv4 +golang.org/x/net/ipv6 +golang.org/x/net/bpf +golang.org/x/net/internal/iana +golang.org/x/net/internal/socket +# golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be +golang.org/x/oauth2 +golang.org/x/oauth2/internal +# golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 +golang.org/x/sync/errgroup +# golang.org/x/sys v0.0.0-20190124100055-b90733256f2e +golang.org/x/sys/unix +# golang.org/x/time v0.0.0-20170424234030-8be79e1e0910 +golang.org/x/time/rate +# google.golang.org/appengine v1.1.0 +google.golang.org/appengine/urlfetch +google.golang.org/appengine/internal +google.golang.org/appengine/internal/urlfetch +google.golang.org/appengine/internal/base +google.golang.org/appengine/internal/datastore +google.golang.org/appengine/internal/log +google.golang.org/appengine/internal/remote_api +# gopkg.in/square/go-jose.v2 v2.0.0-20180411045311-89060dee6a84 +gopkg.in/square/go-jose.v2 +gopkg.in/square/go-jose.v2/jwt +gopkg.in/square/go-jose.v2/cipher +gopkg.in/square/go-jose.v2/json