Update vegeta to a version supporting go modules (#1811)

This allows us to drop the explicit overrides in downstream repositories and it also looks so much nicer :).

I'd hope the change is non-breaking to downstream repositories, given the interface is strictly widened here.
This commit is contained in:
Markus Thömmes 2020-10-15 16:25:57 +02:00 committed by GitHub
parent 08db0e8fd7
commit 51839ea5e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 1406 additions and 204 deletions

2
go.mod
View File

@ -31,7 +31,7 @@ require (
github.com/prometheus/client_golang v1.6.0
github.com/prometheus/common v0.9.1
github.com/spf13/pflag v1.0.5
github.com/tsenart/vegeta v12.7.1-0.20190725001342-b5f4fca92137+incompatible
github.com/tsenart/vegeta/v12 v12.8.4
go.opencensus.io v0.22.4
go.uber.org/atomic v1.6.0
go.uber.org/automaxprocs v1.3.0

22
go.sum
View File

@ -154,6 +154,7 @@ github.com/Shopify/sarama v1.23.1/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sE
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
github.com/alecthomas/jsonschema v0.0.0-20180308105923-f2c93856175a/go.mod h1:qpebaTNSsyUn5rPSJMsfqEtDw71TTggXM6stUDI16HA=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
@ -213,6 +214,7 @@ github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8n
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
github.com/bwmarrin/snowflake v0.0.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
github.com/c2h5oh/datasize v0.0.0-20171227191756-4eba002a5eae/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@ -271,8 +273,10 @@ github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8l
github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY=
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-gk v0.0.0-20140819190930-201884a44051/go.mod h1:qm+vckxRlDt0aOla0RYJJVeqHZlWfOm2UIxHaqPB46E=
github.com/dgryski/go-gk v0.0.0-20200319235926-a69029f61654 h1:XOPLOMn/zT4jIgxfxSsoXPxkrzz0FaCHwp33x5POJ+Q=
github.com/dgryski/go-gk v0.0.0-20200319235926-a69029f61654/go.mod h1:qm+vckxRlDt0aOla0RYJJVeqHZlWfOm2UIxHaqPB46E=
github.com/dgryski/go-lttb v0.0.0-20180810165845-318fcdf10a77/go.mod h1:Va5MyIzkU0rAM92tn3hb3Anb7oz7KcnixF49+2wOMe4=
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
github.com/djherbis/atime v1.0.0/go.mod h1:5W+KBIuTwVGcqjIfaTwt+KSYX1o6uep8dtevevQP/f8=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
@ -476,6 +480,15 @@ github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAO
github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkYFkPcDKwRXegd+iM6E7matEszMG5HhwytU8=
github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk=
github.com/gomodule/redigo v1.7.0/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc=
github.com/gonum/diff v0.0.0-20181124234638-500114f11e71/go.mod h1:22dM4PLscQl+Nzf64qNBurVJvfyvZELT0iRW2l/NN70=
github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg=
github.com/gonum/integrate v0.0.0-20181209220457-a422b5c0fdf2/go.mod h1:pDgmNM6seYpwvPos3q+zxlXMsbve6mOIPucUnUOrI7Y=
github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhSyOzRwuXkOgAvijx4o+4YMUJJo9OvPYMkks=
github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2EAE789SSiSJNqxPaC0aE9J8NTOI0Jo/A=
github.com/gonum/mathext v0.0.0-20181121095525-8a4bf007ea55/go.mod h1:fmo8aiSEWkJeiGXUJf+sPvuDgEFgqIoZSs843ePKrGg=
github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw=
github.com/gonum/stat v0.0.0-20181125101827-41a0da705a5b/go.mod h1:Z4GIJBJO3Wa4gD4vbwQxXXZ+WHmW6E9ixmNrwvs0iZs=
github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@ -619,6 +632,7 @@ github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb v0.0.0-20161215172503-049f9b42e9a5/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
github.com/influxdata/tdigest v0.0.0-20180711151920-a7d76c6f093a/go.mod h1:9GkyshztGufsdPQWjH+ifgnIr3xNUL5syI70g2dzU1o=
github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9 h1:MHTrDWmQpHq/hkq+7cw9oYAt2PqUw52TZazRA0N7PGE=
github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
@ -733,6 +747,7 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
github.com/mholt/archiver/v3 v3.3.0/go.mod h1:YnQtqsp+94Rwd0D/rk5cnLrxusUBUXg+08Ebtr1Mqao=
github.com/miekg/dns v1.1.17/go.mod h1:WgzbA6oji13JREwiNsRDNfl7jYdPnmz+VEuLrA+/48M=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
@ -958,8 +973,11 @@ github.com/tektoncd/plumbing/pipelinerun-logs v0.0.0-20191206114338-712d544c2c21
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tsenart/go-tsz v0.0.0-20180814232043-cdeb9e1e981e/go.mod h1:SWZznP1z5Ki7hDT2ioqiFKEse8K9tU2OUvaRI0NeGQo=
github.com/tsenart/vegeta v12.7.1-0.20190725001342-b5f4fca92137+incompatible h1:ErZrHhRveAoznVW80gbrxz+qxJNydpA2fcQxTPHkZbU=
github.com/tsenart/vegeta v12.7.1-0.20190725001342-b5f4fca92137+incompatible/go.mod h1:Smz/ZWfhKRcyDDChZkG3CyTHdj87lHzio/HOCkbndXM=
github.com/tsenart/vegeta/v12 v12.8.4 h1:UQ7tG7WkDorKj0wjx78Z4/vsMBP8RJQMGJqRVrkvngg=
github.com/tsenart/vegeta/v12 v12.8.4/go.mod h1:ZiJtwLn/9M4fTPdMY7bdbIeyNeFVE8/AHbWFqCsUuho=
github.com/ugorji/go v1.1.1/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
@ -1052,6 +1070,7 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@ -1278,6 +1297,7 @@ golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDq
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190807223507-b346f7fd45de/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@ -1619,6 +1639,8 @@ knative.dev/test-infra v0.0.0-20201013100530-45e0761df397/go.mod h1:PwM5WCaFn0Hl
mvdan.cc/xurls/v2 v2.0.0/go.mod h1:2/webFPYOXN9jp/lzuj0zuAVlF+9g4KPFJANH1oJhRU=
pack.ag/amqp v0.11.0/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4=
pack.ag/amqp v0.11.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4=
pgregory.net/rapid v0.3.3 h1:jCjBsY4ln4Atz78QoBWxUEvAHaFyNDQg9+WU62aCn1U=
pgregory.net/rapid v0.3.3/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=

View File

@ -22,7 +22,7 @@ import (
"strings"
"time"
vegeta "github.com/tsenart/vegeta/lib"
vegeta "github.com/tsenart/vegeta/v12/lib"
)
// combinedPacer is a Pacer that combines multiple Pacers and runs them sequentially when being used for attack.
@ -103,6 +103,12 @@ func (cp *combinedPacer) Pace(elapsedTime time.Duration, elapsedHits uint64) (ti
return curPacer.Pace(curElapsedTime, curElapsedHits)
}
func (cp *combinedPacer) Rate(elapsedTime time.Duration) float64 {
curPacer := cp.pacers[cp.curPacerIndex]
curElapsedTime := time.Duration(uint64(elapsedTime) - cp.prevElapsedTime)
return curPacer.Rate(curElapsedTime)
}
// pacerIndex returns the index of pacer that pacerTimeOffset falls into
func (cp *combinedPacer) pacerIndex(pacerTimeOffset uint64) uint {
i, j := 0, len(cp.stepDurations)

View File

@ -20,7 +20,7 @@ import (
"testing"
"time"
vegeta "github.com/tsenart/vegeta/lib"
vegeta "github.com/tsenart/vegeta/v12/lib"
)
func TestCombinedPacer(t *testing.T) {

View File

@ -22,7 +22,7 @@ import (
"math"
"time"
vegeta "github.com/tsenart/vegeta/lib"
vegeta "github.com/tsenart/vegeta/v12/lib"
)
// steadyUpPacer is a Pacer that describes attack request rates that increases in the beginning then becomes steady.
@ -107,6 +107,12 @@ func (sup *steadyUpPacer) Pace(elapsedTime time.Duration, elapsedHits uint64) (t
return nextHitIn, false
}
// Rate returns a Pacer's instantaneous hit rate (per seconds) at the given elapsed
// duration of an attack.
func (sup *steadyUpPacer) Rate(elapsedTime time.Duration) float64 {
return sup.hitsPerNs(elapsedTime) * 1e9
}
// hits returns the number of expected hits for this pacer during the given time.
func (sup *steadyUpPacer) hits(t time.Duration) float64 {
// If t is smaller than the upDuration, calculate the hits as a trapezoid.

View File

@ -20,7 +20,7 @@ import (
"testing"
"time"
vegeta "github.com/tsenart/vegeta/lib"
vegeta "github.com/tsenart/vegeta/v12/lib"
)
func TestSteadyUpPacer(t *testing.T) {

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2013-2016 Tomás Senart
Copyright (c) 2013-2020 Tomás Senart
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

5
vendor/github.com/mailru/easyjson/.gitignore generated vendored Normal file
View File

@ -0,0 +1,5 @@
.root
*_easyjson.go
*.iml
.idea
*.swp

12
vendor/github.com/mailru/easyjson/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,12 @@
language: go
go:
- tip
- stable
matrix:
allow_failures:
- go: tip
install:
- go get golang.org/x/lint/golint

54
vendor/github.com/mailru/easyjson/Makefile generated vendored Normal file
View File

@ -0,0 +1,54 @@
all: test
clean:
rm -rf bin
rm -rf tests/*_easyjson.go
rm -rf benchmark/*_easyjson.go
build:
go build -i -o ./bin/easyjson ./easyjson
generate: build
bin/easyjson -stubs \
./tests/snake.go \
./tests/data.go \
./tests/omitempty.go \
./tests/nothing.go \
./tests/named_type.go \
./tests/custom_map_key_type.go \
./tests/embedded_type.go \
./tests/reference_to_pointer.go \
./tests/html.go \
bin/easyjson -all ./tests/data.go
bin/easyjson -all ./tests/nothing.go
bin/easyjson -all ./tests/errors.go
bin/easyjson -all ./tests/html.go
bin/easyjson -snake_case ./tests/snake.go
bin/easyjson -omit_empty ./tests/omitempty.go
bin/easyjson -build_tags=use_easyjson ./benchmark/data.go
bin/easyjson ./tests/nested_easy.go
bin/easyjson ./tests/named_type.go
bin/easyjson ./tests/custom_map_key_type.go
bin/easyjson ./tests/embedded_type.go
bin/easyjson ./tests/reference_to_pointer.go
bin/easyjson ./tests/key_marshaler_map.go
bin/easyjson -disallow_unknown_fields ./tests/disallow_unknown.go
test: generate
go test \
./tests \
./jlexer \
./gen \
./buffer
cd benchmark && go test -benchmem -tags use_easyjson -bench .
golint -set_exit_status ./tests/*_easyjson.go
bench-other: generate
cd benchmark && make
bench-python:
benchmark/ujson.sh
.PHONY: clean generate test build

336
vendor/github.com/mailru/easyjson/README.md generated vendored Normal file
View File

@ -0,0 +1,336 @@
# easyjson [![Build Status](https://travis-ci.org/mailru/easyjson.svg?branch=master)](https://travis-ci.org/mailru/easyjson) [![Go Report Card](https://goreportcard.com/badge/github.com/mailru/easyjson)](https://goreportcard.com/report/github.com/mailru/easyjson)
Package easyjson provides a fast and easy way to marshal/unmarshal Go structs
to/from JSON without the use of reflection. In performance tests, easyjson
outperforms the standard `encoding/json` package by a factor of 4-5x, and other
JSON encoding packages by a factor of 2-3x.
easyjson aims to keep generated Go code simple enough so that it can be easily
optimized or fixed. Another goal is to provide users with the ability to
customize the generated code by providing options not available with the
standard `encoding/json` package, such as generating "snake_case" names or
enabling `omitempty` behavior by default.
## Usage
```sh
# install
go get -u github.com/mailru/easyjson/...
# run
easyjson -all <file>.go
```
The above will generate `<file>_easyjson.go` containing the appropriate marshaler and
unmarshaler funcs for all structs contained in `<file>.go`.
Please note that easyjson requires a full Go build environment and the `GOPATH`
environment variable to be set. This is because easyjson code generation
invokes `go run` on a temporary file (an approach to code generation borrowed
from [ffjson](https://github.com/pquerna/ffjson)).
## Options
```txt
Usage of easyjson:
-all
generate marshaler/unmarshalers for all structs in a file
-build_tags string
build tags to add to generated file
-leave_temps
do not delete temporary files
-no_std_marshalers
don't generate MarshalJSON/UnmarshalJSON funcs
-noformat
do not run 'gofmt -w' on output file
-omit_empty
omit empty fields by default
-output_filename string
specify the filename of the output
-pkg
process the whole package instead of just the given file
-snake_case
use snake_case names instead of CamelCase by default
-lower_camel_case
use lowerCamelCase instead of CamelCase by default
-stubs
only generate stubs for marshaler/unmarshaler funcs
-disallow_unknown_fields
return error if some unknown field in json appeared
```
Using `-all` will generate marshalers/unmarshalers for all Go structs in the
file. If `-all` is not provided, then only those structs whose preceding
comment starts with `easyjson:json` will have marshalers/unmarshalers
generated. For example:
```go
//easyjson:json
type A struct {}
```
Additional option notes:
* `-snake_case` tells easyjson to generate snake\_case field names by default
(unless overridden by a field tag). The CamelCase to snake\_case conversion
algorithm should work in most cases (ie, HTTPVersion will be converted to
"http_version").
* `-build_tags` will add the specified build tags to generated Go sources.
## Generated Marshaler/Unmarshaler Funcs
For Go struct types, easyjson generates the funcs `MarshalEasyJSON` /
`UnmarshalEasyJSON` for marshaling/unmarshaling JSON. In turn, these satisify
the `easyjson.Marshaler` and `easyjson.Unmarshaler` interfaces and when used in
conjunction with `easyjson.Marshal` / `easyjson.Unmarshal` avoid unnecessary
reflection / type assertions during marshaling/unmarshaling to/from JSON for Go
structs.
easyjson also generates `MarshalJSON` and `UnmarshalJSON` funcs for Go struct
types compatible with the standard `json.Marshaler` and `json.Unmarshaler`
interfaces. Please be aware that using the standard `json.Marshal` /
`json.Unmarshal` for marshaling/unmarshaling will incur a significant
performance penalty when compared to using `easyjson.Marshal` /
`easyjson.Unmarshal`.
Additionally, easyjson exposes utility funcs that use the `MarshalEasyJSON` and
`UnmarshalEasyJSON` for marshaling/unmarshaling to and from standard readers
and writers. For example, easyjson provides `easyjson.MarshalToHTTPResponseWriter`
which marshals to the standard `http.ResponseWriter`. Please see the [GoDoc
listing](https://godoc.org/github.com/mailru/easyjson) for the full listing of
utility funcs that are available.
## Controlling easyjson Marshaling and Unmarshaling Behavior
Go types can provide their own `MarshalEasyJSON` and `UnmarshalEasyJSON` funcs
that satisify the `easyjson.Marshaler` / `easyjson.Unmarshaler` interfaces.
These will be used by `easyjson.Marshal` and `easyjson.Unmarshal` when defined
for a Go type.
Go types can also satisify the `easyjson.Optional` interface, which allows the
type to define its own `omitempty` logic.
## Type Wrappers
easyjson provides additional type wrappers defined in the `easyjson/opt`
package. These wrap the standard Go primitives and in turn satisify the
easyjson interfaces.
The `easyjson/opt` type wrappers are useful when needing to distinguish between
a missing value and/or when needing to specifying a default value. Type
wrappers allow easyjson to avoid additional pointers and heap allocations and
can significantly increase performance when used properly.
## Memory Pooling
easyjson uses a buffer pool that allocates data in increasing chunks from 128
to 32768 bytes. Chunks of 512 bytes and larger will be reused with the help of
`sync.Pool`. The maximum size of a chunk is bounded to reduce redundant memory
allocation and to allow larger reusable buffers.
easyjson's custom allocation buffer pool is defined in the `easyjson/buffer`
package, and the default behavior pool behavior can be modified (if necessary)
through a call to `buffer.Init()` prior to any marshaling or unmarshaling.
Please see the [GoDoc listing](https://godoc.org/github.com/mailru/easyjson/buffer)
for more information.
## Issues, Notes, and Limitations
* easyjson is still early in its development. As such, there are likely to be
bugs and missing features when compared to `encoding/json`. In the case of a
missing feature or bug, please create a GitHub issue. Pull requests are
welcome!
* Unlike `encoding/json`, object keys are case-sensitive. Case-insensitive
matching is not currently provided due to the significant performance hit
when doing case-insensitive key matching. In the future, case-insensitive
object key matching may be provided via an option to the generator.
* easyjson makes use of `unsafe`, which simplifies the code and
provides significant performance benefits by allowing no-copy
conversion from `[]byte` to `string`. That said, `unsafe` is used
only when unmarshaling and parsing JSON, and any `unsafe` operations
/ memory allocations done will be safely deallocated by
easyjson. Set the build tag `easyjson_nounsafe` to compile it
without `unsafe`.
* easyjson is compatible with Google App Engine. The `appengine` build
tag (set by App Engine's environment) will automatically disable the
use of `unsafe`, which is not allowed in App Engine's Standard
Environment. Note that the use with App Engine is still experimental.
* Floats are formatted using the default precision from Go's `strconv` package.
As such, easyjson will not correctly handle high precision floats when
marshaling/unmarshaling JSON. Note, however, that there are very few/limited
uses where this behavior is not sufficient for general use. That said, a
different package may be needed if precise marshaling/unmarshaling of high
precision floats to/from JSON is required.
* While unmarshaling, the JSON parser does the minimal amount of work needed to
skip over unmatching parens, and as such full validation is not done for the
entire JSON value being unmarshaled/parsed.
* Currently there is no true streaming support for encoding/decoding as
typically for many uses/protocols the final, marshaled length of the JSON
needs to be known prior to sending the data. Currently this is not possible
with easyjson's architecture.
* easyjson parser and codegen based on reflection, so it wont works on `package main`
files, because they cant be imported by parser.
## Benchmarks
Most benchmarks were done using the example
[13kB example JSON](https://dev.twitter.com/rest/reference/get/search/tweets)
(9k after eliminating whitespace). This example is similar to real-world data,
is well-structured, and contains a healthy variety of different types, making
it ideal for JSON serialization benchmarks.
Note:
* For small request benchmarks, an 80 byte portion of the above example was
used.
* For large request marshaling benchmarks, a struct containing 50 regular
samples was used, making a ~500kB output JSON.
* Benchmarks are showing the results of easyjson's default behaviour,
which makes use of `unsafe`.
Benchmarks are available in the repository and can be run by invoking `make`.
### easyjson vs. encoding/json
easyjson is roughly 5-6 times faster than the standard `encoding/json` for
unmarshaling, and 3-4 times faster for non-concurrent marshaling. Concurrent
marshaling is 6-7x faster if marshaling to a writer.
### easyjson vs. ffjson
easyjson uses the same approach for JSON marshaling as
[ffjson](https://github.com/pquerna/ffjson), but takes a significantly
different approach to lexing and parsing JSON during unmarshaling. This means
easyjson is roughly 2-3x faster for unmarshaling and 1.5-2x faster for
non-concurrent unmarshaling.
As of this writing, `ffjson` seems to have issues when used concurrently:
specifically, large request pooling hurts `ffjson`'s performance and causes
scalability issues. These issues with `ffjson` can likely be fixed, but as of
writing remain outstanding/known issues with `ffjson`.
easyjson and `ffjson` have similar performance for small requests, however
easyjson outperforms `ffjson` by roughly 2-5x times for large requests when
used with a writer.
### easyjson vs. go/codec
[go/codec](https://github.com/ugorji/go) provides
compile-time helpers for JSON generation. In this case, helpers do not work
like marshalers as they are encoding-independent.
easyjson is generally 2x faster than `go/codec` for non-concurrent benchmarks
and about 3x faster for concurrent encoding (without marshaling to a writer).
In an attempt to measure marshaling performance of `go/codec` (as opposed to
allocations/memcpy/writer interface invocations), a benchmark was done with
resetting length of a byte slice rather than resetting the whole slice to nil.
However, the optimization in this exact form may not be applicable in practice,
since the memory is not freed between marshaling operations.
### easyjson vs 'ujson' python module
[ujson](https://github.com/esnme/ultrajson) is using C code for parsing, so it
is interesting to see how plain golang compares to that. It is imporant to note
that the resulting object for python is slower to access, since the library
parses JSON object into dictionaries.
easyjson is slightly faster for unmarshaling and 2-3x faster than `ujson` for
marshaling.
### Benchmark Results
`ffjson` results are from February 4th, 2016, using the latest `ffjson` and go1.6.
`go/codec` results are from March 4th, 2016, using the latest `go/codec` and go1.6.
#### Unmarshaling
| lib | json size | MB/s | allocs/op | B/op |
|:---------|:----------|-----:|----------:|------:|
| standard | regular | 22 | 218 | 10229 |
| standard | small | 9.7 | 14 | 720 |
| | | | | |
| easyjson | regular | 125 | 128 | 9794 |
| easyjson | small | 67 | 3 | 128 |
| | | | | |
| ffjson | regular | 66 | 141 | 9985 |
| ffjson | small | 17.6 | 10 | 488 |
| | | | | |
| codec | regular | 55 | 434 | 19299 |
| codec | small | 29 | 7 | 336 |
| | | | | |
| ujson | regular | 103 | N/A | N/A |
#### Marshaling, one goroutine.
| lib | json size | MB/s | allocs/op | B/op |
|:----------|:----------|-----:|----------:|------:|
| standard | regular | 75 | 9 | 23256 |
| standard | small | 32 | 3 | 328 |
| standard | large | 80 | 17 | 1.2M |
| | | | | |
| easyjson | regular | 213 | 9 | 10260 |
| easyjson* | regular | 263 | 8 | 742 |
| easyjson | small | 125 | 1 | 128 |
| easyjson | large | 212 | 33 | 490k |
| easyjson* | large | 262 | 25 | 2879 |
| | | | | |
| ffjson | regular | 122 | 153 | 21340 |
| ffjson** | regular | 146 | 152 | 4897 |
| ffjson | small | 36 | 5 | 384 |
| ffjson** | small | 64 | 4 | 128 |
| ffjson | large | 134 | 7317 | 818k |
| ffjson** | large | 125 | 7320 | 827k |
| | | | | |
| codec | regular | 80 | 17 | 33601 |
| codec*** | regular | 108 | 9 | 1153 |
| codec | small | 42 | 3 | 304 |
| codec*** | small | 56 | 1 | 48 |
| codec | large | 73 | 483 | 2.5M |
| codec*** | large | 103 | 451 | 66007 |
| | | | | |
| ujson | regular | 92 | N/A | N/A |
\* marshaling to a writer,
\*\* using `ffjson.Pool()`,
\*\*\* reusing output slice instead of resetting it to nil
#### Marshaling, concurrent.
| lib | json size | MB/s | allocs/op | B/op |
|:----------|:----------|-----:|----------:|------:|
| standard | regular | 252 | 9 | 23257 |
| standard | small | 124 | 3 | 328 |
| standard | large | 289 | 17 | 1.2M |
| | | | | |
| easyjson | regular | 792 | 9 | 10597 |
| easyjson* | regular | 1748 | 8 | 779 |
| easyjson | small | 333 | 1 | 128 |
| easyjson | large | 718 | 36 | 548k |
| easyjson* | large | 2134 | 25 | 4957 |
| | | | | |
| ffjson | regular | 301 | 153 | 21629 |
| ffjson** | regular | 707 | 152 | 5148 |
| ffjson | small | 62 | 5 | 384 |
| ffjson** | small | 282 | 4 | 128 |
| ffjson | large | 438 | 7330 | 1.0M |
| ffjson** | large | 131 | 7319 | 820k |
| | | | | |
| codec | regular | 183 | 17 | 33603 |
| codec*** | regular | 671 | 9 | 1157 |
| codec | small | 147 | 3 | 304 |
| codec*** | small | 299 | 1 | 48 |
| codec | large | 190 | 483 | 2.5M |
| codec*** | large | 752 | 451 | 77574 |
\* marshaling to a writer,
\*\* using `ffjson.Pool()`,
\*\*\* reusing output slice instead of resetting it to nil

3
vendor/github.com/mailru/easyjson/go.mod generated vendored Normal file
View File

@ -0,0 +1,3 @@
module github.com/mailru/easyjson
go 1.12

78
vendor/github.com/mailru/easyjson/helpers.go generated vendored Normal file
View File

@ -0,0 +1,78 @@
// Package easyjson contains marshaler/unmarshaler interfaces and helper functions.
package easyjson
import (
"io"
"io/ioutil"
"net/http"
"strconv"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// Marshaler is an easyjson-compatible marshaler interface.
type Marshaler interface {
MarshalEasyJSON(w *jwriter.Writer)
}
// Marshaler is an easyjson-compatible unmarshaler interface.
type Unmarshaler interface {
UnmarshalEasyJSON(w *jlexer.Lexer)
}
// Optional defines an undefined-test method for a type to integrate with 'omitempty' logic.
type Optional interface {
IsDefined() bool
}
// Marshal returns data as a single byte slice. Method is suboptimal as the data is likely to be copied
// from a chain of smaller chunks.
func Marshal(v Marshaler) ([]byte, error) {
w := jwriter.Writer{}
v.MarshalEasyJSON(&w)
return w.BuildBytes()
}
// MarshalToWriter marshals the data to an io.Writer.
func MarshalToWriter(v Marshaler, w io.Writer) (written int, err error) {
jw := jwriter.Writer{}
v.MarshalEasyJSON(&jw)
return jw.DumpTo(w)
}
// MarshalToHTTPResponseWriter sets Content-Length and Content-Type headers for the
// http.ResponseWriter, and send the data to the writer. started will be equal to
// false if an error occurred before any http.ResponseWriter methods were actually
// invoked (in this case a 500 reply is possible).
func MarshalToHTTPResponseWriter(v Marshaler, w http.ResponseWriter) (started bool, written int, err error) {
jw := jwriter.Writer{}
v.MarshalEasyJSON(&jw)
if jw.Error != nil {
return false, 0, jw.Error
}
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Content-Length", strconv.Itoa(jw.Size()))
started = true
written, err = jw.DumpTo(w)
return
}
// Unmarshal decodes the JSON in data into the object.
func Unmarshal(data []byte, v Unmarshaler) error {
l := jlexer.Lexer{Data: data}
v.UnmarshalEasyJSON(&l)
return l.Error()
}
// UnmarshalFromReader reads all the data in the reader and decodes as JSON into the object.
func UnmarshalFromReader(r io.Reader, v Unmarshaler) error {
data, err := ioutil.ReadAll(r)
if err != nil {
return err
}
l := jlexer.Lexer{Data: data}
v.UnmarshalEasyJSON(&l)
return l.Error()
}

45
vendor/github.com/mailru/easyjson/raw.go generated vendored Normal file
View File

@ -0,0 +1,45 @@
package easyjson
import (
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// RawMessage is a raw piece of JSON (number, string, bool, object, array or
// null) that is extracted without parsing and output as is during marshaling.
type RawMessage []byte
// MarshalEasyJSON does JSON marshaling using easyjson interface.
func (v *RawMessage) MarshalEasyJSON(w *jwriter.Writer) {
if len(*v) == 0 {
w.RawString("null")
} else {
w.Raw(*v, nil)
}
}
// UnmarshalEasyJSON does JSON unmarshaling using easyjson interface.
func (v *RawMessage) UnmarshalEasyJSON(l *jlexer.Lexer) {
*v = RawMessage(l.Raw())
}
// UnmarshalJSON implements encoding/json.Unmarshaler interface.
func (v *RawMessage) UnmarshalJSON(data []byte) error {
*v = data
return nil
}
var nullBytes = []byte("null")
// MarshalJSON implements encoding/json.Marshaler interface.
func (v RawMessage) MarshalJSON() ([]byte, error) {
if len(v) == 0 {
return nullBytes, nil
}
return v, nil
}
// IsDefined is required for integration with omitempty easyjson logic.
func (v *RawMessage) IsDefined() bool {
return len(*v) > 0
}

View File

@ -1,165 +0,0 @@
// This file has been modified from the original generated code to make it work with
// type alias jsonResult so that the methods aren't exposed in Result.
package vegeta
import (
"time"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
type jsonResult Result
func (r *jsonResult) decode(in *jlexer.Lexer) {
isTopLevel := in.IsStart()
if in.IsNull() {
if isTopLevel {
in.Consumed()
}
in.Skip()
return
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
in.WantColon()
if in.IsNull() {
in.Skip()
in.WantComma()
continue
}
switch key {
case "attack":
r.Attack = string(in.String())
case "seq":
r.Seq = uint64(in.Uint64())
case "code":
r.Code = uint16(in.Uint16())
case "timestamp":
if data := in.Raw(); in.Ok() {
in.AddError((r.Timestamp).UnmarshalJSON(data))
}
case "latency":
r.Latency = time.Duration(in.Int64())
case "bytes_out":
r.BytesOut = uint64(in.Uint64())
case "bytes_in":
r.BytesIn = uint64(in.Uint64())
case "error":
r.Error = string(in.String())
case "body":
if in.IsNull() {
in.Skip()
r.Body = nil
} else {
r.Body = in.Bytes()
}
default:
in.SkipRecursive()
}
in.WantComma()
}
in.Delim('}')
if isTopLevel {
in.Consumed()
}
}
func (r jsonResult) encode(out *jwriter.Writer) {
out.RawByte('{')
first := true
_ = first
{
const prefix string = ",\"attack\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(r.Attack))
}
{
const prefix string = ",\"seq\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.Uint64(uint64(r.Seq))
}
{
const prefix string = ",\"code\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.Uint16(uint16(r.Code))
}
{
const prefix string = ",\"timestamp\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.Raw((r.Timestamp).MarshalJSON())
}
{
const prefix string = ",\"latency\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.Int64(int64(r.Latency))
}
{
const prefix string = ",\"bytes_out\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.Uint64(uint64(r.BytesOut))
}
{
const prefix string = ",\"bytes_in\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.Uint64(uint64(r.BytesIn))
}
{
const prefix string = ",\"error\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(r.Error))
}
{
const prefix string = ",\"body\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.Base64Bytes(r.Body)
}
out.RawByte('}')
}

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2013-2016 Tomás Senart
Copyright (c) 2013-2020 Tomás Senart
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

View File

@ -10,6 +10,7 @@ import (
"net"
"net/http"
"net/url"
"strconv"
"sync"
"time"
@ -28,6 +29,7 @@ type Attacker struct {
seqmu sync.Mutex
seq uint64
began time.Time
chunked bool
}
const (
@ -40,6 +42,9 @@ const (
// DefaultConnections is the default amount of max open idle connections per
// target host.
DefaultConnections = 10000
// DefaultMaxConnections is the default amount of connections per target
// host.
DefaultMaxConnections = 0
// DefaultWorkers is the default initial number of workers used to carry an attack.
DefaultWorkers = 10
// DefaultMaxWorkers is the default maximum number of workers used to carry an attack.
@ -81,6 +86,7 @@ func NewAttacker(opts ...func(*Attacker)) *Attacker {
Dial: a.dialer.Dial,
TLSClientConfig: DefaultTLSConfig,
MaxIdleConnsPerHost: DefaultConnections,
MaxConnsPerHost: DefaultMaxConnections,
},
}
@ -113,6 +119,21 @@ func Connections(n int) func(*Attacker) {
}
}
// MaxConnections returns a functional option which sets the number of maximum
// connections per target host.
func MaxConnections(n int) func(*Attacker) {
return func(a *Attacker) {
tr := a.client.Transport.(*http.Transport)
tr.MaxConnsPerHost = n
}
}
// ChunkedBody returns a functional option which makes the attacker send the
// body of each request with the chunked transfer encoding.
func ChunkedBody(b bool) func(*Attacker) {
return func(a *Attacker) { a.chunked = b }
}
// Redirects returns a functional option which sets the maximum
// number of redirects an Attacker will follow.
func Redirects(n int) func(*Attacker) {
@ -229,6 +250,16 @@ func Client(c *http.Client) func(*Attacker) {
return func(a *Attacker) { a.client = *c }
}
// ProxyHeader returns a functional option that allows you to add your own
// Proxy CONNECT headers
func ProxyHeader(h http.Header) func(*Attacker) {
return func(a *Attacker) {
if tr, ok := a.client.Transport.(*http.Transport); ok {
tr.ProxyConnectHeader = h
}
}
}
// Attack reads its Targets from the passed Targeter and attacks them at
// the rate specified by the Pacer. When the duration is zero the attack
// runs until Stop is called. Results are sent to the returned channel as soon
@ -336,11 +367,24 @@ func (a *Attacker) hit(tr Targeter, name string) *Result {
return &res
}
res.Method = tgt.Method
res.URL = tgt.URL
req, err := tgt.Request()
if err != nil {
return &res
}
if name != "" {
req.Header.Set("X-Vegeta-Attack", name)
}
req.Header.Set("X-Vegeta-Seq", strconv.FormatUint(res.Seq, 10))
if a.chunked {
req.TransferEncoding = append(req.TransferEncoding, "chunked")
}
r, err := a.client.Do(req)
if err != nil {
return &res
@ -368,5 +412,7 @@ func (a *Attacker) hit(tr Targeter, name string) *Result {
res.Error = r.Status
}
res.Headers = r.Header
return &res
}

154
vendor/github.com/tsenart/vegeta/v12/lib/attack_fuzz.go generated vendored Normal file
View File

@ -0,0 +1,154 @@
// +build gofuzz
package vegeta
import (
"encoding/binary"
"fmt"
"io/ioutil"
"net"
"net/http"
"os"
"time"
)
// FuzzAttackerTCP fuzzes binary responses to attacker.
func FuzzAttackerTCP(fuzz []byte) int {
// Ignore empty fuzz
if len(fuzz) == 0 {
return -1
}
// Start server
directory, err := ioutil.TempDir("/tmp", "fuzz")
if err != nil {
panic(err.Error())
}
socket := fmt.Sprintf("%s/attacker.sock", directory)
listener, err := net.Listen("unix", socket)
if err != nil {
panic(err.Error())
}
go func() {
connection, err := listener.Accept()
if err != nil {
panic(err.Error())
}
_, err = connection.Write(fuzz)
if err != nil {
panic(err.Error())
}
err = connection.Close()
if err != nil {
panic(err.Error())
}
}()
defer listener.Close()
defer os.RemoveAll(directory)
// Setup targeter
targeter := Targeter(func(target *Target) error {
target.Method = "GET"
target.URL = "http://vegeta.test"
return nil
})
// Deliver a single hit
attacker := NewAttacker(
UnixSocket(socket),
Workers(1),
MaxWorkers(1),
Timeout(time.Second),
KeepAlive(false),
)
result := attacker.hit(targeter, "fuzz")
if result.Error != "" {
return 0
}
return 1
}
// FuzzAttackerHTTP fuzzes valid HTTP responses to attacker.
func FuzzAttackerHTTP(fuzz []byte) int {
// Decode response
code, headers, body, ok := decodeFuzzResponse(fuzz)
if !ok {
return -1
}
// Start server
directory, err := ioutil.TempDir("/tmp", "fuzz")
if err != nil {
panic(err.Error())
}
socket := fmt.Sprintf("%s/attacker.sock", directory)
listener, err := net.Listen("unix", socket)
if err != nil {
panic(err.Error())
}
handler := func(response http.ResponseWriter, request *http.Request) {
for name, values := range headers {
for _, value := range values {
response.Header().Add(name, value)
}
}
response.WriteHeader(int(code))
_, err := response.Write(body)
if err != nil {
panic(err.Error())
}
}
server := http.Server{
Handler: http.HandlerFunc(handler),
}
defer server.Close()
defer listener.Close()
defer os.RemoveAll(directory)
go server.Serve(listener)
// Setup targeter
targeter := Targeter(func(target *Target) error {
target.Method = "GET"
target.URL = "http://vegeta.test"
return nil
})
// Deliver a single hit
attacker := NewAttacker(
UnixSocket(socket),
Workers(1),
MaxWorkers(1),
Timeout(time.Second),
KeepAlive(false),
)
result := attacker.hit(targeter, "fuzz")
if result.Error != "" {
return 0
}
return 1
}
func decodeFuzzResponse(fuzz []byte) (
code int,
headers map[string][]string,
body []byte,
ok bool,
) {
if len(fuzz) < 2 {
return
}
headers = make(map[string][]string)
body = []byte{}
code = int(binary.LittleEndian.Uint16(fuzz[0:2]))
if len(fuzz) == 2 {
ok = true
return
}
fuzz, ok = decodeFuzzHeaders(fuzz[2:], headers)
if !ok {
return
}
body = fuzz
ok = true
return
}

View File

@ -68,11 +68,15 @@ func (bs *Buckets) UnmarshalText(value []byte) error {
if len(value) < 2 || value[0] != '[' || value[len(value)-1] != ']' {
return fmt.Errorf("bad buckets: %s", value)
}
for _, v := range strings.Split(string(value[1:len(value)-1]), ",") {
for i, v := range strings.Split(string(value[1:len(value)-1]), ",") {
d, err := time.ParseDuration(strings.TrimSpace(v))
if err != nil {
return err
}
// add a default range of [0-Buckets[0]) if needed
if i == 0 && d > 0 {
*bs = append(*bs, 0)
}
*bs = append(*bs, d)
}
if len(*bs) == 0 {

View File

@ -89,6 +89,11 @@ func (m *Metrics) Add(r *Result) {
// derived summary metrics which don't need to be run on every Add call.
func (m *Metrics) Close() {
m.init()
if m.Requests == 0 {
return
}
m.Rate = float64(m.Requests)
m.Throughput = float64(m.success)
m.Duration = m.Latest.Sub(m.Earliest)
@ -104,6 +109,7 @@ func (m *Metrics) Close() {
m.Success = float64(m.success) / float64(m.Requests)
m.Latencies.Mean = time.Duration(float64(m.Latencies.Total) / float64(m.Requests))
m.Latencies.P50 = m.Latencies.Quantile(0.50)
m.Latencies.P90 = m.Latencies.Quantile(0.90)
m.Latencies.P95 = m.Latencies.Quantile(0.95)
m.Latencies.P99 = m.Latencies.Quantile(0.99)
}
@ -130,12 +136,16 @@ type LatencyMetrics struct {
Mean time.Duration `json:"mean"`
// P50 is the 50th percentile request latency.
P50 time.Duration `json:"50th"`
// P90 is the 90th percentile request latency.
P90 time.Duration `json:"90th"`
// P95 is the 95th percentile request latency.
P95 time.Duration `json:"95th"`
// P99 is the 99th percentile request latency.
P99 time.Duration `json:"99th"`
// Max is the maximum observed request latency.
Max time.Duration `json:"max"`
// Min is the minimum observed request latency.
Min time.Duration `json:"min"`
estimator estimator
}
@ -146,6 +156,9 @@ func (l *LatencyMetrics) Add(latency time.Duration) {
if l.Total += latency; latency > l.Max {
l.Max = latency
}
if latency < l.Min || l.Min == 0 {
l.Min = latency
}
l.estimator.Add(float64(latency))
}

View File

@ -6,12 +6,17 @@ import (
"time"
)
// A Pacer defines the rate of hits during an Attack by
// returning the duration an Attacker should wait until
// hitting the next Target. If the second return value
// is true, the attack will terminate.
// A Pacer defines the rate of hits during an Attack.
type Pacer interface {
// Pace returns the duration an Attacker should wait until
// hitting the next Target, given an already elapsed duration and
// completed hits. If the second return value is true, an attacker
// should stop sending hits.
Pace(elapsed time.Duration, hits uint64) (wait time.Duration, stop bool)
// Rate returns a Pacer's instantaneous hit rate (per seconds)
// at the given elapsed duration of an attack.
Rate(elapsed time.Duration) float64
}
// A PacerFunc is a function adapter type that implements
@ -65,6 +70,13 @@ func (cp ConstantPacer) Pace(elapsed time.Duration, hits uint64) (time.Duration,
return delta - elapsed, false
}
// Rate returns a ConstantPacer's instantaneous hit rate (i.e. requests per second)
// at the given elapsed duration of an attack. Since it's constant, the return
// value is independent of the given elapsed duration.
func (cp ConstantPacer) Rate(elapsed time.Duration) float64 {
return cp.hitsPerNs() * 1e9
}
// hitsPerNs returns the attack rate this ConstantPacer represents, in
// fractional hits per nanosecond.
func (cp ConstantPacer) hitsPerNs() float64 {
@ -184,6 +196,12 @@ func (sp SinePacer) Pace(elapsedTime time.Duration, elapsedHits uint64) (time.Du
return nextHitIn, false
}
// Rate returns a SinePacer's instantaneous hit rate (i.e. requests per second)
// at the given elapsed duration of an attack.
func (sp SinePacer) Rate(elapsed time.Duration) float64 {
return sp.hitsPerNs(elapsed) * 1e9
}
// ampHits returns AP/2𝛑, which is the number of hits added or subtracted
// from the Mean due to the Amplitude over a quarter of the Period,
// i.e. from 0 → 𝛑/2 radians
@ -240,7 +258,7 @@ func (p LinearPacer) Pace(elapsed time.Duration, hits uint64) (time.Duration, bo
return 0, false
}
rate := p.rate(elapsed)
rate := p.Rate(elapsed)
interval := math.Round(1e9 / rate)
if n := uint64(interval); n != 0 && math.MaxInt64/n < hits {
@ -254,6 +272,15 @@ func (p LinearPacer) Pace(elapsed time.Duration, hits uint64) (time.Duration, bo
return wait, false
}
// Rate returns a LinearPacer's instantaneous hit rate (i.e. requests per second)
// at the given elapsed duration of an attack.
func (p LinearPacer) Rate(elapsed time.Duration) float64 {
a := p.Slope
x := elapsed.Seconds()
b := p.StartAt.hitsPerNs() * 1e9
return a*x + b
}
// hits returns the number of hits that have been sent during an attack
// lasting t nanoseconds. It returns a float so we can tell exactly how
// much we've missed our target by when solving numerically in Pace.
@ -268,12 +295,3 @@ func (p LinearPacer) hits(t time.Duration) float64 {
return (a*math.Pow(x, 2))/2 + b*x
}
// rate calculates the instantaneous rate of attack at
// t nanoseconds after the attack began.
func (p LinearPacer) rate(t time.Duration) float64 {
a := p.Slope
x := t.Seconds()
b := p.StartAt.hitsPerNs() * 1e9
return a*x + b
}

View File

@ -57,7 +57,7 @@ func NewHistogramReporter(h *Histogram) Reporter {
func NewTextReporter(m *Metrics) Reporter {
const fmtstr = "Requests\t[total, rate, throughput]\t%d, %.2f, %.2f\n" +
"Duration\t[total, attack, wait]\t%s, %s, %s\n" +
"Latencies\t[mean, 50, 95, 99, max]\t%s, %s, %s, %s, %s\n" +
"Latencies\t[min, mean, 50, 90, 95, 99, max]\t%s, %s, %s, %s, %s, %s, %s\n" +
"Bytes In\t[total, mean]\t%d, %.2f\n" +
"Bytes Out\t[total, mean]\t%d, %.2f\n" +
"Success\t[ratio]\t%.2f%%\n" +
@ -67,8 +67,16 @@ func NewTextReporter(m *Metrics) Reporter {
tw := tabwriter.NewWriter(w, 0, 8, 2, ' ', tabwriter.StripEscape)
if _, err = fmt.Fprintf(tw, fmtstr,
m.Requests, m.Rate, m.Throughput,
m.Duration+m.Wait, m.Duration, m.Wait,
m.Latencies.Mean, m.Latencies.P50, m.Latencies.P95, m.Latencies.P99, m.Latencies.Max,
round(m.Duration+m.Wait),
round(m.Duration),
round(m.Wait),
round(m.Latencies.Min),
round(m.Latencies.Mean),
round(m.Latencies.P50),
round(m.Latencies.P90),
round(m.Latencies.P95),
round(m.Latencies.P99),
round(m.Latencies.Max),
m.BytesIn.Total, m.BytesIn.Mean,
m.BytesOut.Total, m.BytesOut.Mean,
m.Success*100,
@ -104,6 +112,25 @@ func NewTextReporter(m *Metrics) Reporter {
}
}
var durations = [...]time.Duration{
time.Hour,
time.Minute,
time.Second,
time.Millisecond,
time.Microsecond,
time.Nanosecond,
}
// round to the next most precise unit
func round(d time.Duration) time.Duration {
for i, unit := range durations {
if d >= unit && i < len(durations)-1 {
return d.Round(durations[i+1])
}
}
return d
}
// NewJSONReporter returns a Reporter that writes out Metrics as JSON.
func NewJSONReporter(m *Metrics) Reporter {
return func(w io.Writer) error {

View File

@ -7,12 +7,15 @@ import (
"encoding/csv"
"encoding/gob"
"io"
"net/http"
"net/textproto"
"sort"
"strconv"
"strings"
"time"
"github.com/mailru/easyjson/jlexer"
jwriter "github.com/mailru/easyjson/jwriter"
"github.com/mailru/easyjson/jwriter"
)
func init() {
@ -30,6 +33,9 @@ type Result struct {
BytesIn uint64 `json:"bytes_in"`
Error string `json:"error"`
Body []byte `json:"body"`
Method string `json:"method"`
URL string `json:"url"`
Headers http.Header `json:"headers"`
}
// End returns the time at which a Result ended.
@ -45,7 +51,32 @@ func (r Result) Equal(other Result) bool {
r.BytesIn == other.BytesIn &&
r.BytesOut == other.BytesOut &&
r.Error == other.Error &&
bytes.Equal(r.Body, other.Body)
bytes.Equal(r.Body, other.Body) &&
r.Method == other.Method &&
r.URL == other.URL &&
headerEqual(r.Headers, other.Headers)
}
func headerEqual(h1, h2 http.Header) bool {
if len(h1) != len(h2) {
return false
}
if h1 == nil || h2 == nil {
return h1 == nil && h2 == nil
}
for key, values1 := range h1 {
values2 := h2[key]
if len(values1) != len(values2) {
return false
}
for i := range values1 {
if values1[i] != values2[i] {
return false
}
}
}
return true
}
// Results is a slice of Result type elements.
@ -150,8 +181,10 @@ func NewCSVEncoder(w io.Writer) Encoder {
base64.StdEncoding.EncodeToString(r.Body),
r.Attack,
strconv.FormatUint(r.Seq, 10),
r.Method,
r.URL,
base64.StdEncoding.EncodeToString(headerBytes(r.Headers)),
})
if err != nil {
return err
}
@ -162,10 +195,19 @@ func NewCSVEncoder(w io.Writer) Encoder {
}
}
func headerBytes(h http.Header) []byte {
if h == nil {
return nil
}
var hdr bytes.Buffer
_ = h.Write(&hdr)
return append(hdr.Bytes(), '\r', '\n')
}
// NewCSVDecoder returns a Decoder that decodes CSV encoded Results.
func NewCSVDecoder(rd io.Reader) Decoder {
dec := csv.NewReader(rd)
dec.FieldsPerRecord = 9
func NewCSVDecoder(r io.Reader) Decoder {
dec := csv.NewReader(r)
dec.FieldsPerRecord = 12
dec.TrimLeadingSpace = true
return func(r *Result) error {
@ -201,23 +243,42 @@ func NewCSVDecoder(rd io.Reader) Decoder {
}
r.Error = rec[5]
r.Body, err = base64.StdEncoding.DecodeString(rec[6])
if r.Body, err = base64.StdEncoding.DecodeString(rec[6]); err != nil {
return err
}
r.Attack = rec[7]
if r.Seq, err = strconv.ParseUint(rec[8], 10, 64); err != nil {
return err
}
r.Method = rec[9]
r.URL = rec[10]
if rec[11] != "" {
pr := textproto.NewReader(bufio.NewReader(
base64.NewDecoder(base64.StdEncoding, strings.NewReader(rec[11]))))
hdr, err := pr.ReadMIMEHeader()
if err != nil {
return err
}
r.Headers = http.Header(hdr)
}
return err
}
}
//go:generate easyjson -no_std_marshalers -output_filename results_easyjson.go results.go
//easyjson:json
type jsonResult Result
// NewJSONEncoder returns an Encoder that dumps the given *Results as a JSON
// object.
func NewJSONEncoder(w io.Writer) Encoder {
var jw jwriter.Writer
return func(r *Result) error {
(*jsonResult)(r).encode(&jw)
(*jsonResult)(r).MarshalEasyJSON(&jw)
if jw.Error != nil {
return jw.Error
}
@ -232,10 +293,10 @@ func NewJSONDecoder(r io.Reader) Decoder {
rd := bufio.NewReader(r)
return func(r *Result) (err error) {
var jl jlexer.Lexer
if jl.Data, err = rd.ReadSlice('\n'); err != nil {
if jl.Data, err = rd.ReadBytes('\n'); err != nil {
return err
}
(*jsonResult)(r).decode(&jl)
(*jsonResult)(r).UnmarshalEasyJSON(&jl)
return jl.Error()
}
}

View File

@ -0,0 +1,223 @@
// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT.
package vegeta
import (
json "encoding/json"
easyjson "github.com/mailru/easyjson"
jlexer "github.com/mailru/easyjson/jlexer"
jwriter "github.com/mailru/easyjson/jwriter"
http "net/http"
time "time"
)
// suppress unused package warning
var (
_ *json.RawMessage
_ *jlexer.Lexer
_ *jwriter.Writer
_ easyjson.Marshaler
)
func easyjsonBd1621b8DecodeGithubComTsenartVegetaV12Lib(in *jlexer.Lexer, out *jsonResult) {
isTopLevel := in.IsStart()
if in.IsNull() {
if isTopLevel {
in.Consumed()
}
in.Skip()
return
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
in.WantColon()
if in.IsNull() {
in.Skip()
in.WantComma()
continue
}
switch key {
case "attack":
out.Attack = string(in.String())
case "seq":
out.Seq = uint64(in.Uint64())
case "code":
out.Code = uint16(in.Uint16())
case "timestamp":
if data := in.Raw(); in.Ok() {
in.AddError((out.Timestamp).UnmarshalJSON(data))
}
case "latency":
out.Latency = time.Duration(in.Int64())
case "bytes_out":
out.BytesOut = uint64(in.Uint64())
case "bytes_in":
out.BytesIn = uint64(in.Uint64())
case "error":
out.Error = string(in.String())
case "body":
if in.IsNull() {
in.Skip()
out.Body = nil
} else {
out.Body = in.Bytes()
}
case "method":
out.Method = string(in.String())
case "url":
out.URL = string(in.String())
case "headers":
if in.IsNull() {
in.Skip()
} else {
in.Delim('{')
if !in.IsDelim('}') {
out.Headers = make(http.Header)
} else {
out.Headers = nil
}
for !in.IsDelim('}') {
key := string(in.String())
in.WantColon()
var v2 []string
if in.IsNull() {
in.Skip()
v2 = nil
} else {
in.Delim('[')
if v2 == nil {
if !in.IsDelim(']') {
v2 = make([]string, 0, 4)
} else {
v2 = []string{}
}
} else {
v2 = (v2)[:0]
}
for !in.IsDelim(']') {
var v3 string
v3 = string(in.String())
v2 = append(v2, v3)
in.WantComma()
}
in.Delim(']')
}
(out.Headers)[key] = v2
in.WantComma()
}
in.Delim('}')
}
default:
in.SkipRecursive()
}
in.WantComma()
}
in.Delim('}')
if isTopLevel {
in.Consumed()
}
}
func easyjsonBd1621b8EncodeGithubComTsenartVegetaV12Lib(out *jwriter.Writer, in jsonResult) {
out.RawByte('{')
first := true
_ = first
{
const prefix string = ",\"attack\":"
out.RawString(prefix[1:])
out.String(string(in.Attack))
}
{
const prefix string = ",\"seq\":"
out.RawString(prefix)
out.Uint64(uint64(in.Seq))
}
{
const prefix string = ",\"code\":"
out.RawString(prefix)
out.Uint16(uint16(in.Code))
}
{
const prefix string = ",\"timestamp\":"
out.RawString(prefix)
out.Raw((in.Timestamp).MarshalJSON())
}
{
const prefix string = ",\"latency\":"
out.RawString(prefix)
out.Int64(int64(in.Latency))
}
{
const prefix string = ",\"bytes_out\":"
out.RawString(prefix)
out.Uint64(uint64(in.BytesOut))
}
{
const prefix string = ",\"bytes_in\":"
out.RawString(prefix)
out.Uint64(uint64(in.BytesIn))
}
{
const prefix string = ",\"error\":"
out.RawString(prefix)
out.String(string(in.Error))
}
{
const prefix string = ",\"body\":"
out.RawString(prefix)
out.Base64Bytes(in.Body)
}
{
const prefix string = ",\"method\":"
out.RawString(prefix)
out.String(string(in.Method))
}
{
const prefix string = ",\"url\":"
out.RawString(prefix)
out.String(string(in.URL))
}
{
const prefix string = ",\"headers\":"
out.RawString(prefix)
if in.Headers == nil && (out.Flags&jwriter.NilMapAsEmpty) == 0 {
out.RawString(`null`)
} else {
out.RawByte('{')
v6First := true
for v6Name, v6Value := range in.Headers {
if v6First {
v6First = false
} else {
out.RawByte(',')
}
out.String(string(v6Name))
out.RawByte(':')
if v6Value == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 {
out.RawString("null")
} else {
out.RawByte('[')
for v7, v8 := range v6Value {
if v7 > 0 {
out.RawByte(',')
}
out.String(string(v8))
}
out.RawByte(']')
}
}
out.RawByte('}')
}
}
out.RawByte('}')
}
// MarshalEasyJSON supports easyjson.Marshaler interface
func (v jsonResult) MarshalEasyJSON(w *jwriter.Writer) {
easyjsonBd1621b8EncodeGithubComTsenartVegetaV12Lib(w, v)
}
// UnmarshalEasyJSON supports easyjson.Unmarshaler interface
func (v *jsonResult) UnmarshalEasyJSON(l *jlexer.Lexer) {
easyjsonBd1621b8DecodeGithubComTsenartVegetaV12Lib(l, v)
}

View File

@ -0,0 +1,63 @@
// +build gofuzz
package vegeta
import (
"bytes"
"io"
)
// FuzzResultsFormatDetection tests result list format detection.
func FuzzResultsFormatDetection(fuzz []byte) int {
decoder := DecoderFor(bytes.NewReader(fuzz))
if decoder == nil {
return 0
}
ok := readAllResults(decoder)
if !ok {
return 0
}
return 1
}
// FuzzGobDecoder tests decoding a gob format result list.
func FuzzGobDecoder(fuzz []byte) int {
decoder := NewDecoder(bytes.NewReader(fuzz))
ok := readAllResults(decoder)
if !ok {
return 0
}
return 1
}
// FuzzCSVDecoder tests decoding a CSV format result list.
func FuzzCSVDecoder(fuzz []byte) int {
decoder := NewCSVDecoder(bytes.NewReader(fuzz))
ok := readAllResults(decoder)
if !ok {
return 0
}
return 1
}
// FuzzJSONDecoder tests decoding a JSON format result list.
func FuzzJSONDecoder(fuzz []byte) int {
decoder := NewJSONDecoder(bytes.NewReader(fuzz))
ok := readAllResults(decoder)
if !ok {
return 0
}
return 1
}
func readAllResults(decoder Decoder) (ok bool) {
for {
result := &Result{}
err := decoder.Decode(result)
if err == io.EOF {
return true
} else if err != nil {
return false
}
}
}

View File

@ -270,7 +270,7 @@ func NewHTTPTargeter(src io.Reader, body []byte, hdr http.Header) Targeter {
}
line = strings.TrimSpace(sc.Text())
if len(line) != 0 && line[0] != '#'{
if len(line) != 0 && line[0] != '#' {
break
}
}
@ -300,6 +300,8 @@ func NewHTTPTargeter(src io.Reader, body []byte, hdr http.Header) Targeter {
for sc.Scan() {
if line = strings.TrimSpace(sc.Text()); line == "" {
break
} else if strings.HasPrefix(line, "#") {
continue
} else if strings.HasPrefix(line, "@") {
if tgt.Body, err = ioutil.ReadFile(line[1:]); err != nil {
return fmt.Errorf("bad body: %s", err)
@ -327,7 +329,7 @@ func NewHTTPTargeter(src io.Reader, body []byte, hdr http.Header) Targeter {
}
}
var httpMethodChecker = regexp.MustCompile("^[A-Z]+\\s")
var httpMethodChecker = regexp.MustCompile(`^[A-Z]+\s`)
// A line starts with an http method when the first word is uppercase ascii
// followed by a space.

View File

@ -0,0 +1,68 @@
// +build gofuzz
package vegeta
import (
"bytes"
"net/http"
)
// FuzzHTTPTargeter tests decoding an HTTP encoded target list.
func FuzzHTTPTargeter(fuzz []byte) int {
headers, body, fuzz, ok := decodeFuzzTargetDefaults(fuzz)
if !ok {
return -1
}
targeter := NewHTTPTargeter(
bytes.NewReader(fuzz),
body,
headers,
)
_, err := ReadAllTargets(targeter)
if err != nil {
return 0
}
return 1
}
// FuzzJSONTargeter tests decoding a JSON encoded target list.
func FuzzJSONTargeter(fuzz []byte) int {
headers, body, fuzz, ok := decodeFuzzTargetDefaults(fuzz)
if !ok {
return -1
}
targeter := NewJSONTargeter(
bytes.NewReader(fuzz),
body,
headers,
)
_, err := ReadAllTargets(targeter)
if err != nil {
return 0
}
return 1
}
func decodeFuzzTargetDefaults(fuzz []byte) (
headers http.Header,
body []byte,
rest []byte,
ok bool,
) {
if len(fuzz) < 2 {
return
}
headers = make(map[string][]string)
body = []byte{}
rest = []byte{}
rest, ok = decodeFuzzHeaders(fuzz, headers)
if !ok {
return
}
if len(rest) == 0 {
ok = true
return
}
body, rest, ok = extractFuzzByteString(rest)
return
}

120
vendor/github.com/tsenart/vegeta/v12/lib/util_fuzz.go generated vendored Normal file
View File

@ -0,0 +1,120 @@
// +build gofuzz
package vegeta
func decodeFuzzHeaders(fuzz []byte, headers map[string][]string) (
rest []byte,
ok bool,
) {
rest = fuzz
for {
if len(rest) == 0 {
// Consumed all fuzz
ok = true
return
}
if fuzz[0] == 0 {
// Headers terminated
if len(rest) == 1 {
rest = []byte{}
} else {
rest = rest[1:]
}
ok = true
return
}
if len(fuzz) == 1 {
// Invalid headers encoding
return
}
rest, ok = decodeFuzzHeader(rest[1:], headers)
if !ok {
return
}
}
}
func decodeFuzzHeader(fuzz []byte, headers map[string][]string) (
rest []byte,
ok bool,
) {
if len(fuzz) == 0 {
ok = true
return
}
name, rest, ok := extractFuzzString(fuzz)
if !ok {
return
}
value, rest, ok := extractFuzzString(rest)
if !ok {
return
}
if header, ok := headers[name]; ok {
headers[name] = append(header, value)
} else {
headers[name] = []string{value}
}
ok = true
return
}
func extractFuzzString(fuzz []byte) (
value string,
rest []byte,
ok bool,
) {
if len(fuzz) < 2 {
// Invalid string encoding
return
}
length := int(fuzz[0])
if length == 0 {
// Invalid length
return
}
if len(fuzz) < (length + 1) {
// Insufficient fuzz
return
}
value = string(fuzz[1 : length+1])
if len(fuzz) == (length + 1) {
// Consumed all fuzz
rest = []byte{}
} else {
// More fuzz
rest = fuzz[length+1:]
}
ok = true
return
}
func extractFuzzByteString(fuzz []byte) (
value []byte,
rest []byte,
ok bool,
) {
if len(fuzz) < 2 {
// Invalid byte string encoding
return
}
length := int(fuzz[0])
if length == 0 {
// Invalid length
return
}
if len(fuzz) < (length + 1) {
// Insufficient fuzz
return
}
value = fuzz[1 : length+1]
if len(fuzz) == (length + 1) {
// Consumed all fuzz
rest = []byte{}
} else {
// More fuzz
rest = fuzz[length+1:]
}
ok = true
return
}

5
vendor/modules.txt vendored
View File

@ -206,6 +206,7 @@ github.com/kelseyhightower/envconfig
# github.com/konsorten/go-windows-terminal-sequences v1.0.3
github.com/konsorten/go-windows-terminal-sequences
# github.com/mailru/easyjson v0.7.1-0.20191009090205-6c0755d89d1e
github.com/mailru/easyjson
github.com/mailru/easyjson/buffer
github.com/mailru/easyjson/jlexer
github.com/mailru/easyjson/jwriter
@ -260,9 +261,9 @@ github.com/sirupsen/logrus
# github.com/spf13/pflag v1.0.5
## explicit
github.com/spf13/pflag
# github.com/tsenart/vegeta v12.7.1-0.20190725001342-b5f4fca92137+incompatible
# github.com/tsenart/vegeta/v12 v12.8.4
## explicit
github.com/tsenart/vegeta/lib
github.com/tsenart/vegeta/v12/lib
# go.opencensus.io v0.22.4
## explicit
go.opencensus.io