From 0e55d3f469e48d1824afac183b1f1c57fa143cb7 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Fri, 1 Nov 2024 13:27:29 +0300 Subject: [PATCH] Pull request 124: add-set-and-url Squashed commit of the following: commit 8d87787bdeb5da12c7eaa74040181aec8831a263 Author: Ainar Garipov Date: Fri Nov 1 12:16:54 2024 +0300 errors: fix type commit 986169fa4aa4a148b787c3ae140c4324f6b29915 Author: Ainar Garipov Date: Thu Oct 31 19:30:53 2024 +0300 all: add tests, imp code commit 0393ff0e981d5a14113ce5c431d9d6fdd4664d08 Author: Ainar Garipov Date: Thu Oct 31 18:45:47 2024 +0300 all: imp docs, tests commit ff7d161d0212cfd8330eba09cfc1fdd478176343 Author: Ainar Garipov Date: Thu Oct 31 17:19:00 2024 +0300 container: add sorted slice set; urlutil: add helpers --- bamboo-specs/bamboo.yaml | 8 +- container/containter_test.go | 34 +++++ container/mapset.go | 16 +-- container/mapset_example_test.go | 4 +- container/mapset_test.go | 86 ++++++++++++ container/sortedsliceset.go | 131 ++++++++++++++++++ container/sortedsliceset_example_test.go | 166 +++++++++++++++++++++++ container/sortedsliceset_test.go | 86 ++++++++++++ errors/const.go | 6 + go.mod | 8 +- go.sum | 16 +-- internal/tools/go.mod | 50 +++---- internal/tools/go.sum | 100 +++++++------- netutil/urlutil/url.go | 1 - netutil/urlutil/url_test.go | 12 +- netutil/urlutil/urlutil.go | 131 ++++++++++++++++++ netutil/urlutil/urlutil_example_test.go | 63 +++++++++ netutil/urlutil/urlutil_test.go | 121 +++++++++++++++++ scripts/make/go-bench.sh | 5 +- scripts/make/go-fuzz.sh | 2 +- scripts/make/go-test.sh | 2 +- 21 files changed, 934 insertions(+), 114 deletions(-) create mode 100644 container/containter_test.go create mode 100644 container/mapset_test.go create mode 100644 container/sortedsliceset.go create mode 100644 container/sortedsliceset_example_test.go create mode 100644 container/sortedsliceset_test.go create mode 100644 netutil/urlutil/urlutil.go create mode 100644 netutil/urlutil/urlutil_example_test.go create mode 100644 netutil/urlutil/urlutil_test.go diff --git a/bamboo-specs/bamboo.yaml b/bamboo-specs/bamboo.yaml index c567d6d..017ae13 100644 --- a/bamboo-specs/bamboo.yaml +++ b/bamboo-specs/bamboo.yaml @@ -51,6 +51,8 @@ 'interpreter': 'SHELL' 'scripts': - | + #!/bin/sh + set -e -f -u -x make VERBOSE=1 go-tools go-lint @@ -70,6 +72,8 @@ 'interpreter': 'SHELL' 'scripts': - | + #!/bin/sh + set -e -f -u -x make VERBOSE=1 go-tools md-lint sh-lint txt-lint @@ -89,9 +93,11 @@ 'interpreter': 'SHELL' 'scripts': - | + #!/bin/sh + set -e -f -u -x - make VERBOSE=1 go-deps go-test go-fuzz + make VERBOSE=1 go-deps go-bench go-test go-fuzz 'final-tasks': - 'clean' 'requirements': diff --git a/container/containter_test.go b/container/containter_test.go new file mode 100644 index 0000000..636b671 --- /dev/null +++ b/container/containter_test.go @@ -0,0 +1,34 @@ +package container_test + +import ( + "math/rand" + "time" +) + +// Common sinks for benchmarks. +var ( + sinkBool bool +) + +// Common constants for tests. +const ( + randStrLen = 8 + setMaxLen = 100_000 +) + +// newRandStrs returns a slice of random strings of length l with each string +// being strLen bytes long. +func newRandStrs(l, strLen int) (strs []string) { + src := rand.NewSource(time.Now().UnixNano()) + rng := rand.New(src) + + strs = make([]string, 0, l) + for range l { + data := make([]byte, strLen) + _, _ = rng.Read(data) + + strs = append(strs, string(data)) + } + + return strs +} diff --git a/container/mapset.go b/container/mapset.go index c2934dc..2f1fde6 100644 --- a/container/mapset.go +++ b/container/mapset.go @@ -28,7 +28,7 @@ func NewMapSet[T comparable](values ...T) (set *MapSet[T]) { return set } -// Add adds v to set. Add panics if set is a nil set, just like a nil map does. +// Add adds v to set. func (set *MapSet[T]) Add(v T) { set.m[v] = unit{} } @@ -61,21 +61,15 @@ func (set *MapSet[T]) Delete(v T) { } } -// Equal returns true if set is equal to other. +// Equal returns true if set is equal to other. set and other may be nil; Equal +// returns true if both are nil, but a nil *MapSet is not equal to a non-nil +// empty one. func (set *MapSet[T]) Equal(other *MapSet[T]) (ok bool) { if set == nil || other == nil { return set == other - } else if set.Len() != other.Len() { - return false } - for v := range set.m { - if _, ok = other.m[v]; !ok { - return false - } - } - - return true + return maps.Equal(set.m, other.m) } // Has returns true if v is in set. Calling Has on a nil set returns false, diff --git a/container/mapset_example_test.go b/container/mapset_example_test.go index 2ba6832..aa09fd5 100644 --- a/container/mapset_example_test.go +++ b/container/mapset_example_test.go @@ -103,9 +103,7 @@ func ExampleMapSet_nil() { panicked := false setPanicked := func() { - if v := recover(); v != nil { - panicked = true - } + panicked = recover() != nil } func() { diff --git a/container/mapset_test.go b/container/mapset_test.go new file mode 100644 index 0000000..888f1e9 --- /dev/null +++ b/container/mapset_test.go @@ -0,0 +1,86 @@ +package container_test + +import ( + "fmt" + "testing" + "time" + + "github.com/AdguardTeam/golibs/container" + "github.com/stretchr/testify/require" +) + +func BenchmarkMapSet_Add(b *testing.B) { + for n := 10; n <= setMaxLen; n *= 10 { + b.Run(fmt.Sprintf("%d_strings", n), func(b *testing.B) { + var set *container.MapSet[string] + + values := newRandStrs(n, randStrLen) + + b.ReportAllocs() + b.ResetTimer() + for range b.N { + set = container.NewMapSet[string]() + for _, v := range values { + set.Add(v) + } + } + + perIter := b.Elapsed() / time.Duration(b.N) + b.ReportMetric(float64(perIter)/float64(n), "ns/add") + + require.True(b, set.Has(values[0])) + }) + } + + // Most recent results: + // goos: linux + // goarch: amd64 + // pkg: github.com/AdguardTeam/golibs/container + // cpu: AMD Ryzen 7 PRO 4750U with Radeon Graphics + // BenchmarkMapSet_Add + // BenchmarkMapSet_Add/10_strings + // BenchmarkMapSet_Add/10_strings-16 702885 1514 ns/op 151.3 ns/add 491 B/op 4 allocs/op + // BenchmarkMapSet_Add/100_strings + // BenchmarkMapSet_Add/100_strings-16 66829 15960 ns/op 159.6 ns/add 5615 B/op 11 allocs/op + // BenchmarkMapSet_Add/1000_strings + // BenchmarkMapSet_Add/1000_strings-16 7400 206750 ns/op 206.7 ns/add 85713 B/op 36 allocs/op + // BenchmarkMapSet_Add/10000_strings + // BenchmarkMapSet_Add/10000_strings-16 592 1982110 ns/op 198.2 ns/add 676473 B/op 216 allocs/op + // BenchmarkMapSet_Add/100000_strings + // BenchmarkMapSet_Add/100000_strings-16 49 23063097 ns/op 230.6 ns/add 5597995 B/op 3903 allocs/op +} + +func BenchmarkMapSet_Has(b *testing.B) { + for n := 10; n <= setMaxLen; n *= 10 { + b.Run(fmt.Sprintf("%d_strings", n), func(b *testing.B) { + values := newRandStrs(n, randStrLen) + set := container.NewMapSet(values...) + value := values[n/2] + + b.ReportAllocs() + b.ResetTimer() + for range b.N { + sinkBool = set.Has(value) + } + + require.True(b, sinkBool) + }) + } + + // Most recent results: + // goos: linux + // goarch: amd64 + // pkg: github.com/AdguardTeam/golibs/container + // cpu: AMD Ryzen 7 PRO 4750U with Radeon Graphics + // BenchmarkMapSet_Has + // BenchmarkMapSet_Has/10_strings + // BenchmarkMapSet_Has/10_strings-16 171413164 6.886 ns/op 0 B/op 0 allocs/op + // BenchmarkMapSet_Has/100_strings + // BenchmarkMapSet_Has/100_strings-16 166819746 6.607 ns/op 0 B/op 0 allocs/op + // BenchmarkMapSet_Has/1000_strings + // BenchmarkMapSet_Has/1000_strings-16 179336127 6.870 ns/op 0 B/op 0 allocs/op + // BenchmarkMapSet_Has/10000_strings + // BenchmarkMapSet_Has/10000_strings-16 164002748 6.831 ns/op 0 B/op 0 allocs/op + // BenchmarkMapSet_Has/100000_strings + // BenchmarkMapSet_Has/100000_strings-16 170170257 6.518 ns/op 0 B/op 0 allocs/op +} diff --git a/container/sortedsliceset.go b/container/sortedsliceset.go new file mode 100644 index 0000000..9acb2dc --- /dev/null +++ b/container/sortedsliceset.go @@ -0,0 +1,131 @@ +package container + +import ( + "cmp" + "fmt" + "slices" +) + +// SortedSliceSet is a simple set implementation that has a sorted set of values +// as its underlying storage. +// +// TODO(a.garipov): Consider relaxing the type requirement or adding a version +// with a comparison function. +type SortedSliceSet[T cmp.Ordered] struct { + elems []T +} + +// NewSortedSliceSet returns a new *SortedSliceSet. elems must not be modified +// after calling NewSortedSliceSet. +func NewSortedSliceSet[T cmp.Ordered](elems ...T) (set *SortedSliceSet[T]) { + slices.Sort(elems) + + return &SortedSliceSet[T]{ + elems: elems, + } +} + +// Add adds v to set. +func (set *SortedSliceSet[T]) Add(v T) { + i, ok := slices.BinarySearch(set.elems, v) + if !ok { + set.elems = slices.Insert(set.elems, i, v) + } +} + +// Clear clears set in a way that retains the internal storage for later reuse +// to reduce allocations. Calling Clear on a nil set has no effect, just like a +// clear on a nil slice doesn't. +func (set *SortedSliceSet[T]) Clear() { + if set != nil { + clear(set.elems) + set.elems = set.elems[:0] + } +} + +// Clone returns a clone of set. If set is nil, clone is nil. +// +// NOTE: It calls [slices.Clone] on the underlying storage, so these elements +// are cloned shallowly. +func (set *SortedSliceSet[T]) Clone() (clone *SortedSliceSet[T]) { + if set == nil { + return nil + } + + return NewSortedSliceSet(slices.Clone(set.elems)...) +} + +// Delete deletes v from set. +func (set *SortedSliceSet[T]) Delete(v T) { + i, ok := slices.BinarySearch(set.elems, v) + if ok { + set.elems = slices.Delete(set.elems, i, i+1) + } +} + +// Equal returns true if set is equal to other. set and other may be nil; Equal +// returns true if both are nil, but a nil *SortedSliceSet is not equal to a +// non-nil empty one. +func (set *SortedSliceSet[T]) Equal(other *SortedSliceSet[T]) (ok bool) { + if set == nil || other == nil { + return set == other + } + + return slices.Equal(set.elems, other.elems) +} + +// Has returns true if v is in set. Calling Has on a nil set returns false, +// just like iterating over a nil or empty slice does. +func (set *SortedSliceSet[T]) Has(v T) (ok bool) { + if set == nil { + return false + } + + _, ok = slices.BinarySearch(set.elems, v) + + return ok +} + +// Len returns the length of set. A nil set has a length of zero, just like an +// nil or empty slice. +func (set *SortedSliceSet[T]) Len() (n int) { + if set == nil { + return 0 + } + + return len(set.elems) +} + +// Range calls f with each value of set in their sorted order. If cont is +// false, Range stops the iteration. Calling Range on a nil *SortedSliceSet has +// no effect. +func (set *SortedSliceSet[T]) Range(f func(v T) (cont bool)) { + if set == nil { + return + } + + for _, v := range set.elems { + if !f(v) { + break + } + } +} + +// type check +var _ fmt.Stringer = (*SortedSliceSet[int])(nil) + +// String implements the [fmt.Stringer] interface for *SortedSliceSet. Calling +// String on a nil *SortedSliceSet does not panic. +func (set *SortedSliceSet[T]) String() (s string) { + return fmt.Sprintf("%v", set.Values()) +} + +// Values returns the underlying slice of set. values must not be modified. +// Values returns nil if set is nil. +func (set *SortedSliceSet[T]) Values() (values []T) { + if set == nil { + return nil + } + + return set.elems +} diff --git a/container/sortedsliceset_example_test.go b/container/sortedsliceset_example_test.go new file mode 100644 index 0000000..2f536bc --- /dev/null +++ b/container/sortedsliceset_example_test.go @@ -0,0 +1,166 @@ +package container_test + +import ( + "fmt" + "slices" + + "github.com/AdguardTeam/golibs/container" +) + +func ExampleSortedSliceSet() { + const x = 1 + set := container.NewSortedSliceSet[int]() + + ok := set.Has(x) + fmt.Printf("%s contains %v is %t\n", set, x, ok) + + set.Add(x) + ok = set.Has(x) + fmt.Printf("%s contains %v is %t\n", set, x, ok) + + other := container.NewSortedSliceSet(x) + ok = set.Equal(other) + fmt.Printf("%s is equal to %s is %t\n", set, other, ok) + + set.Add(2) + values := set.Values() + slices.Sort(values) + fmt.Printf("values of %s are %v\n", set, values) + + set.Delete(x) + ok = set.Has(x) + fmt.Printf("%s contains %v is %t\n", set, x, ok) + + set.Range(func(n int) (cont bool) { + fmt.Printf("got value %d\n", n) + + return false + }) + + set = container.NewSortedSliceSet(x) + fmt.Printf("%s has length %d\n", set, set.Len()) + + set.Clear() + fmt.Printf("%s has length %d\n", set, set.Len()) + + // Output: + // + // [] contains 1 is false + // [1] contains 1 is true + // [1] is equal to [1] is true + // values of [1 2] are [1 2] + // [2] contains 1 is false + // got value 2 + // [1] has length 1 + // [] has length 0 +} + +func ExampleSortedSliceSet_Clone() { + var set *container.SortedSliceSet[int] + fmt.Printf("nil: %#v\n", set.Clone()) + + const x, y = 1, 2 + set = container.NewSortedSliceSet(x) + clone := set.Clone() + clone.Add(y) + + fmt.Printf("orig: %t %t\n", set.Has(x), set.Has(y)) + fmt.Printf("clone: %t %t\n", clone.Has(x), clone.Has(y)) + + // Output: + // nil: (*container.SortedSliceSet[int])(nil) + // orig: true false + // clone: true true +} + +func ExampleSortedSliceSet_Equal() { + const x, y = 1, 2 + set := container.NewSortedSliceSet(x) + + fmt.Printf("same: %t\n", set.Equal(container.NewSortedSliceSet(x))) + fmt.Printf("other elem: %t\n", set.Equal(container.NewSortedSliceSet(y))) + fmt.Printf("other len: %t\n", set.Equal(container.NewSortedSliceSet(x, y))) + fmt.Printf("nil: %t\n", set.Equal(nil)) + fmt.Printf("nil eq nil: %t\n", (*container.SortedSliceSet[int])(nil).Equal(nil)) + + // Output: + // same: true + // other elem: false + // other len: false + // nil: false + // nil eq nil: true +} + +func ExampleSortedSliceSet_nil() { + const x = 1 + + var set *container.SortedSliceSet[int] + + panicked := false + setPanicked := func() { + panicked = recover() != nil + } + + func() { + defer setPanicked() + + set.Clear() + }() + fmt.Printf("panic after clear: %t\n", panicked) + + func() { + defer setPanicked() + + set.Delete(x) + }() + fmt.Printf("panic after delete: %t\n", panicked) + + func() { + defer setPanicked() + + set.Has(x) + }() + fmt.Printf("panic after has: %t\n", panicked) + + func() { + defer setPanicked() + + set.Len() + }() + fmt.Printf("panic after len: %t\n", panicked) + + func() { + defer setPanicked() + + set.Range(func(n int) (cont bool) { + fmt.Printf("got value %d\n", n) + + return true + }) + }() + fmt.Printf("panic after range: %t\n", panicked) + + func() { + defer setPanicked() + + set.Values() + }() + fmt.Printf("panic after values: %t\n", panicked) + + func() { + defer setPanicked() + + set.Add(x) + }() + fmt.Printf("panic after add: %t\n", panicked) + + // Output: + // + // panic after clear: false + // panic after delete: true + // panic after has: false + // panic after len: false + // panic after range: false + // panic after values: false + // panic after add: true +} diff --git a/container/sortedsliceset_test.go b/container/sortedsliceset_test.go new file mode 100644 index 0000000..e0c01b9 --- /dev/null +++ b/container/sortedsliceset_test.go @@ -0,0 +1,86 @@ +package container_test + +import ( + "fmt" + "testing" + "time" + + "github.com/AdguardTeam/golibs/container" + "github.com/stretchr/testify/require" +) + +func BenchmarkSortedSliceSet_Add(b *testing.B) { + for n := 10; n <= setMaxLen; n *= 10 { + b.Run(fmt.Sprintf("%d_strings", n), func(b *testing.B) { + var set *container.SortedSliceSet[string] + + values := newRandStrs(n, randStrLen) + + b.ReportAllocs() + b.ResetTimer() + for range b.N { + set = container.NewSortedSliceSet[string]() + for _, v := range values { + set.Add(v) + } + } + + perIter := b.Elapsed() / time.Duration(b.N) + b.ReportMetric(float64(perIter)/float64(n), "ns/add") + + require.True(b, set.Has(values[0])) + }) + } + + // Most recent results: + // goos: linux + // goarch: amd64 + // pkg: github.com/AdguardTeam/golibs/container + // cpu: AMD Ryzen 7 PRO 4750U with Radeon Graphics + // BenchmarkSortedSliceSet_Add + // BenchmarkSortedSliceSet_Add/10_strings + // BenchmarkSortedSliceSet_Add/10_strings-16 1000000 1717 ns/op 171.7 ns/add 520 B/op 6 allocs/op + // BenchmarkSortedSliceSet_Add/100_strings + // BenchmarkSortedSliceSet_Add/100_strings-16 66405 16969 ns/op 169.7 ns/add 4488 B/op 9 allocs/op + // BenchmarkSortedSliceSet_Add/1000_strings + // BenchmarkSortedSliceSet_Add/1000_strings-16 2820 386448 ns/op 386.4 ns/add 35208 B/op 12 allocs/op + // BenchmarkSortedSliceSet_Add/10000_strings + // BenchmarkSortedSliceSet_Add/10000_strings-16 97 11721214 ns/op 1172 ns/add 665992 B/op 19 allocs/op + // BenchmarkSortedSliceSet_Add/100000_strings + // BenchmarkSortedSliceSet_Add/100000_strings-16 1 1330335923 ns/op 13303 ns/add 8923656 B/op 31 allocs/op +} + +func BenchmarkSortedSliceSet_Has(b *testing.B) { + for n := 10; n <= setMaxLen; n *= 10 { + b.Run(fmt.Sprintf("%d_strings", n), func(b *testing.B) { + values := newRandStrs(n, randStrLen) + set := container.NewSortedSliceSet(values...) + value := values[n/2] + + b.ReportAllocs() + b.ResetTimer() + for range b.N { + sinkBool = set.Has(value) + } + + require.True(b, sinkBool) + }) + } + + // Most recent results: + // goos: linux + // goarch: amd64 + // pkg: github.com/AdguardTeam/golibs/container + // cpu: AMD Ryzen 7 PRO 4750U with Radeon Graphics + // BenchmarkSortedSliceSet_Has + // BenchmarkSortedSliceSet_Has/10_strings + // BenchmarkSortedSliceSet_Has/10_strings-16 75554308 14.48 ns/op 0 B/op 0 allocs/op + // BenchmarkSortedSliceSet_Has/100_strings + // BenchmarkSortedSliceSet_Has/100_strings-16 43907683 28.66 ns/op 0 B/op 0 allocs/op + // BenchmarkSortedSliceSet_Has/1000_strings + // BenchmarkSortedSliceSet_Has/1000_strings-16 29775063 40.41 ns/op 0 B/op 0 allocs/op + // BenchmarkSortedSliceSet_Has/10000_strings + // BenchmarkSortedSliceSet_Has/10000_strings-16 20591700 57.83 ns/op 0 B/op 0 allocs/op + // BenchmarkSortedSliceSet_Has/100000_strings + // BenchmarkSortedSliceSet_Has/100000_strings-16 13058570 78.08 ns/op 0 B/op 0 allocs/op +} diff --git a/errors/const.go b/errors/const.go index 649be49..fe4507f 100644 --- a/errors/const.go +++ b/errors/const.go @@ -20,6 +20,9 @@ func (err Error) Error() (msg string) { // [ErrOutOfRange]. const ErrBadEnumValue Error = "bad enum value" +// ErrDuplicated indicates that a value that should be unique is duplicated. +const ErrDuplicated Error = "duplicated value" + // ErrEmptyValue indicates that a value is provided but it is empty. For // example, a non-null but empty JSON or YAML object. // @@ -38,6 +41,9 @@ const ErrNegative Error = "negative value" // For a value that is present but empty, use [ErrEmptyValue]. const ErrNoValue Error = "no value" +// ErrNotEmpty indicates that a value that must be empty isn't. +const ErrNotEmpty Error = "not empty" + // ErrNotPositive indicates that the provided value is negative or zero when it // should be greater than zero. // diff --git a/go.mod b/go.mod index f3c0f63..1bf15aa 100644 --- a/go.mod +++ b/go.mod @@ -4,14 +4,14 @@ go 1.23.2 require ( github.com/stretchr/testify v1.9.0 - golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 - golang.org/x/net v0.29.0 + golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c + golang.org/x/net v0.30.0 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.25.0 - golang.org/x/text v0.18.0 // indirect + golang.org/x/sys v0.26.0 + golang.org/x/text v0.19.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index ddcb55a..5ad5313 100644 --- a/go.sum +++ b/go.sum @@ -4,14 +4,14 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= -golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/internal/tools/go.mod b/internal/tools/go.mod index e3bfea8..7220766 100644 --- a/internal/tools/go.mod +++ b/internal/tools/go.mod @@ -6,24 +6,24 @@ require ( github.com/fzipp/gocyclo v0.6.0 github.com/golangci/misspell v0.6.0 github.com/gordonklaus/ineffassign v0.1.0 - github.com/kisielk/errcheck v1.7.0 + github.com/kisielk/errcheck v1.8.0 github.com/securego/gosec/v2 v2.21.4 github.com/uudashr/gocognit v1.1.3 - golang.org/x/tools v0.25.0 + golang.org/x/tools v0.26.0 golang.org/x/vuln v1.1.3 honnef.co/go/tools v0.5.1 mvdan.cc/gofumpt v0.7.0 - mvdan.cc/sh/v3 v3.9.0 + mvdan.cc/sh/v3 v3.10.0 mvdan.cc/unparam v0.0.0-20240917084806-57a3b4290ba3 ) require ( - cloud.google.com/go v0.115.1 // indirect + cloud.google.com/go v0.116.0 // indirect cloud.google.com/go/ai v0.8.2 // indirect - cloud.google.com/go/auth v0.9.7 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect + cloud.google.com/go/auth v0.10.0 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.5 // indirect cloud.google.com/go/compute/metadata v0.5.2 // indirect - cloud.google.com/go/longrunning v0.6.1 // indirect + cloud.google.com/go/longrunning v0.6.2 // indirect github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect github.com/ccojocar/zxcvbn-go v1.0.2 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect @@ -41,28 +41,28 @@ require ( github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect - go.opentelemetry.io/otel v1.30.0 // indirect - go.opentelemetry.io/otel/metric v1.30.0 // indirect - go.opentelemetry.io/otel/trace v1.30.0 // indirect - golang.org/x/crypto v0.27.0 // indirect - golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect - golang.org/x/exp/typeparams v0.0.0-20240909161429-701f63a606c0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect + go.opentelemetry.io/otel v1.31.0 // indirect + go.opentelemetry.io/otel/metric v1.31.0 // indirect + go.opentelemetry.io/otel/trace v1.31.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect + golang.org/x/exp/typeparams v0.0.0-20241009180824-f66d83c29e7c // indirect golang.org/x/mod v0.21.0 // indirect - golang.org/x/net v0.29.0 // indirect + golang.org/x/net v0.30.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/telemetry v0.0.0-20241003135049-3be6e8dcb6d1 // indirect - golang.org/x/term v0.24.0 // indirect - golang.org/x/text v0.18.0 // indirect - golang.org/x/time v0.6.0 // indirect - google.golang.org/api v0.199.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240930140551-af27646dc61f // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/telemetry v0.0.0-20241028140143-9c0d19e65ba0 // indirect + golang.org/x/term v0.25.0 // indirect + golang.org/x/text v0.19.0 // indirect + golang.org/x/time v0.7.0 // indirect + google.golang.org/api v0.203.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect google.golang.org/grpc v1.67.1 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect mvdan.cc/editorconfig v0.3.0 // indirect ) diff --git a/internal/tools/go.sum b/internal/tools/go.sum index 4b1b796..f3ce2fc 100644 --- a/internal/tools/go.sum +++ b/internal/tools/go.sum @@ -1,16 +1,16 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.115.1 h1:Jo0SM9cQnSkYfp44+v+NQXHpcHqlnRJk2qxh6yvxxxQ= -cloud.google.com/go v0.115.1/go.mod h1:DuujITeaufu3gL68/lOFIirVNJwQeyf5UXyi+Wbgknc= +cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= +cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= cloud.google.com/go/ai v0.8.2 h1:LEaQwqBv+k2ybrcdTtCTc9OPZXoEdcQaGrfvDYS6Bnk= cloud.google.com/go/ai v0.8.2/go.mod h1:Wb3EUUGWwB6yHBaUf/+oxUq/6XbCaU1yh0GrwUS8lr4= -cloud.google.com/go/auth v0.9.7 h1:ha65jNwOfI48YmUzNfMaUDfqt5ykuYIUnSartpU1+BA= -cloud.google.com/go/auth v0.9.7/go.mod h1:Xo0n7n66eHyOWWCnitop6870Ilwo3PiZyodVkkH1xWM= -cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY= -cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= +cloud.google.com/go/auth v0.10.0 h1:tWlkvFAh+wwTOzXIjrwM64karR1iTBZ/GRr0S/DULYo= +cloud.google.com/go/auth v0.10.0/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= +cloud.google.com/go/auth/oauth2adapt v0.2.5 h1:2p29+dePqsCHPP1bqDJcKj4qxRyYCcbzKpFyKGt3MTk= +cloud.google.com/go/auth/oauth2adapt v0.2.5/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= -cloud.google.com/go/longrunning v0.6.1 h1:lOLTFxYpr8hcRtcwWir5ITh1PAKUD/sG2lKrTSYjyMc= -cloud.google.com/go/longrunning v0.6.1/go.mod h1:nHISoOZpBcmlwbJmiVk5oDRz0qG/ZxPynEGs1iZ79s0= +cloud.google.com/go/longrunning v0.6.2 h1:xjDfh1pQcWPEvnfjZmwjKQEcHnpz6lHjfy7Fo0MK+hc= +cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= @@ -88,8 +88,8 @@ github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s= github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= -github.com/kisielk/errcheck v1.7.0 h1:+SbscKmWJ5mOK/bO1zS60F5I9WwZDWOfRsC4RwfwRV0= -github.com/kisielk/errcheck v1.7.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ= +github.com/kisielk/errcheck v1.8.0 h1:ZX/URYa7ilESY19ik/vBmCn6zdGQLxACwjAcWbHlYlg= +github.com/kisielk/errcheck v1.8.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -122,26 +122,26 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJu github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0 h1:hCq2hNMwsegUvPzI7sPOvtO9cqyy5GbWt/Ybp2xrx8Q= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0/go.mod h1:LqaApwGx/oUmzsbqxkzuBvyoPpkxk3JQWnqfVrJ3wCA= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI= -go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts= -go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= -go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w= -go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ= -go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc= -go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 h1:yMkBS9yViCc7U7yeLzJPM2XizlfdVvBRSmsQDWu6qc0= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0/go.mod h1:n8MR6/liuGB5EmTETUBeU5ZgqMOlqKRxUaqPQBOANZ8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM= +go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= +go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= +go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= +go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= +go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= +go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= -golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= -golang.org/x/exp/typeparams v0.0.0-20240909161429-701f63a606c0 h1:bVwtbF629Xlyxk6xLQq2TDYmqP0uiWaet5LwRebuY0k= -golang.org/x/exp/typeparams v0.0.0-20240909161429-701f63a606c0/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= +golang.org/x/exp/typeparams v0.0.0-20241009180824-f66d83c29e7c h1:F/15/6p7LyGUSoP0GE5CB/U9+TNEER1foNOP5sWLLnI= +golang.org/x/exp/typeparams v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -156,8 +156,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= @@ -174,19 +174,19 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/telemetry v0.0.0-20241003135049-3be6e8dcb6d1 h1:jwE+tSUxfuWvjwRDY/iWoNkRHMSCGwISTsx68LRVVO0= -golang.org/x/telemetry v0.0.0-20241003135049-3be6e8dcb6d1/go.mod h1:PsFMgI0jiuY7j+qwXANuh9a/x5kQESTSnRow3gapUyk= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20241028140143-9c0d19e65ba0 h1:od0RE4kmouF+x/o4zkTTSvBnGPZ2azGgCUmZdrbnEXM= +golang.org/x/telemetry v0.0.0-20241028140143-9c0d19e65ba0/go.mod h1:8nZWdGp9pq73ZI//QJyckMQab3yq7hoWi7SI0UIusVI= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= -golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -194,25 +194,25 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE= -golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= +golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/vuln v1.1.3 h1:NPGnvPOTgnjBc9HTaUx+nj+EaUYxl5SJOWqaDYGaFYw= golang.org/x/vuln v1.1.3/go.mod h1:7Le6Fadm5FOqE9C926BCD0g12NWyhg7cxV4BwcPFuNY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.199.0 h1:aWUXClp+VFJmqE0JPvpZOK3LDQMyFKYIow4etYd9qxs= -google.golang.org/api v0.199.0/go.mod h1:ohG4qSztDJmZdjK/Ar6MhbAmb/Rpi4JHOqagsh90K28= +google.golang.org/api v0.203.0 h1:SrEeuwU3S11Wlscsn+LA1kb/Y5xT8uggJSkIhD08NAU= +google.golang.org/api v0.203.0/go.mod h1:BuOVyCSYEPwJb3npWvDnNmFI92f3GeRnHNkETneT3SI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto/googleapis/api v0.0.0-20240930140551-af27646dc61f h1:jTm13A2itBi3La6yTGqn8bVSrc3ZZ1r8ENHlIXBfnRA= -google.golang.org/genproto/googleapis/api v0.0.0-20240930140551-af27646dc61f/go.mod h1:CLGoBuH1VHxAUXVPP8FfPwPEVJB6lz3URE5mY2SuayE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 h1:2oV8dfuIkM1Ti7DwXc0BJfnwr9csz4TDXI9EmiI+Rbw= +google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38/go.mod h1:vuAjtvlwkDKF6L1GQ0SokiRLCGFfeBUXWr/aFFkHACc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -229,8 +229,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -244,7 +244,7 @@ mvdan.cc/editorconfig v0.3.0 h1:D1D2wLYEYGpawWT5SpM5pRivgEgXjtEXwC9MWhEY0gQ= mvdan.cc/editorconfig v0.3.0/go.mod h1:NcJHuDtNOTEJ6251indKiWuzK6+VcrMuLzGMLKBFupQ= mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU= mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo= -mvdan.cc/sh/v3 v3.9.0 h1:it14fyjCdQUk4jf/aYxLO3FG8jFarR9GzMCtnlvvD7c= -mvdan.cc/sh/v3 v3.9.0/go.mod h1:cdBk8bgoiBI7lSZqK5JhUuq7OB64VQ7fgm85xelw3Nk= +mvdan.cc/sh/v3 v3.10.0 h1:v9z7N1DLZ7owyLM/SXZQkBSXcwr2IGMm2LY2pmhVXj4= +mvdan.cc/sh/v3 v3.10.0/go.mod h1:z/mSSVyLFGZzqb3ZIKojjyqIx/xbmz/UHdCSv9HmqXY= mvdan.cc/unparam v0.0.0-20240917084806-57a3b4290ba3 h1:YkmTN1n5U60NM02j7TCSWRlW3fqNiuXe/eVXf0dLFN8= mvdan.cc/unparam v0.0.0-20240917084806-57a3b4290ba3/go.mod h1:z5yboO1sP1Q9pcfvS597TpfbNXQjphDlkCJHzt13ybc= diff --git a/netutil/urlutil/url.go b/netutil/urlutil/url.go index 38d5538..8b4f721 100644 --- a/netutil/urlutil/url.go +++ b/netutil/urlutil/url.go @@ -1,4 +1,3 @@ -// Package urlutil contains types and utilities for dealing with URLs. package urlutil import ( diff --git a/netutil/urlutil/url_test.go b/netutil/urlutil/url_test.go index 3ea2ff9..ed7825e 100644 --- a/netutil/urlutil/url_test.go +++ b/netutil/urlutil/url_test.go @@ -28,12 +28,12 @@ func TestParseURL(t *testing.T) { }, { want: &urlutil.URL{ URL: url.URL{ - Scheme: "https", - Host: "www.example.com", + Scheme: urlutil.SchemeHTTPS, + Host: testHostname, }, }, name: "success", - in: "https://www.example.com", + in: "https://" + testHostname, wantErrMsg: "", }} @@ -80,13 +80,13 @@ func TestURL_UnmarshalJSON(t *testing.T) { }, { want: &urlutil.URL{ URL: url.URL{ - Scheme: "https", - Host: "www.example.com", + Scheme: urlutil.SchemeHTTPS, + Host: testHostname, }, }, name: "success", wantErrMsg: "", - in: []byte(`"https://www.example.com"`), + in: []byte(`"https://` + testHostname + `"`), }} for _, tc := range testCases { diff --git a/netutil/urlutil/urlutil.go b/netutil/urlutil/urlutil.go new file mode 100644 index 0000000..e220e72 --- /dev/null +++ b/netutil/urlutil/urlutil.go @@ -0,0 +1,131 @@ +// Package urlutil contains types and utilities for dealing with URLs. +package urlutil + +import ( + "fmt" + "net/url" + "strings" + + "github.com/AdguardTeam/golibs/errors" +) + +// Known scheme constants. +const ( + SchemeFile = "file" + SchemeGRPC = "grpc" + SchemeGRPCS = "grpcs" + SchemeHTTP = "http" + SchemeHTTPS = "https" +) + +// ValidateFileURL returns nil if u is a valid file URL. +// +// TODO(a.garipov): Make the validations stricter. +func ValidateFileURL(u *url.URL) (err error) { + if u == nil { + return fmt.Errorf("bad file url: %w", errors.ErrNoValue) + } + + defer func() { err = errors.Annotate(err, "bad file url %q: %w", u) }() + + if !strings.EqualFold(u.Scheme, SchemeFile) { + return fmt.Errorf("scheme: bad value: %q; want %q", u.Scheme, SchemeFile) + } + + return nil +} + +// IsValidGRPCURLScheme returns true if s is a valid gRPC(S) URL scheme. That +// is, [SchemeGRPC] or [SchemeGRPCS] +func IsValidGRPCURLScheme(s string) (ok bool) { + return strings.EqualFold(s, SchemeGRPC) || strings.EqualFold(s, SchemeGRPCS) +} + +// ValidateGRPCURL returns nil if u is a valid gRPC(S) URL. +// +// TODO(a.garipov): Make the validations stricter. +func ValidateGRPCURL(u *url.URL) (err error) { + if u == nil { + return fmt.Errorf("bad grpc(s) url: %w", errors.ErrNoValue) + } + + defer func() { err = errors.Annotate(err, "bad grpc(s) url %q: %w", u) }() + + if !IsValidGRPCURLScheme(u.Scheme) { + return fmt.Errorf( + "scheme: %w: %q; want %q or %q", + errors.ErrBadEnumValue, + u.Scheme, + SchemeGRPC, + SchemeGRPCS, + ) + } + + return nil +} + +// IsValidHTTPURLScheme returns true if s is a valid HTTP(S) URL scheme. That +// is, [SchemeHTTP] or [SchemeHTTPS] +func IsValidHTTPURLScheme(s string) (ok bool) { + return strings.EqualFold(s, SchemeHTTP) || strings.EqualFold(s, SchemeHTTPS) +} + +// ValidateHTTPURL returns nil if u is a valid HTTP(S) URL. +// +// TODO(a.garipov): Make the validations stricter. +func ValidateHTTPURL(u *url.URL) (err error) { + if u == nil { + return fmt.Errorf("bad http(s) url: %w", errors.ErrNoValue) + } + + defer func() { err = errors.Annotate(err, "bad http(s) url %q: %w", u) }() + + if !IsValidHTTPURLScheme(u.Scheme) { + return fmt.Errorf( + "scheme: %w: %q; want %q or %q", + errors.ErrBadEnumValue, + u.Scheme, + SchemeHTTP, + SchemeHTTPS, + ) + } + + return nil +} + +// redactedUserinfo is the redacted userinfo shared by all redacted URLs. +var redactedUserinfo = url.UserPassword("xxxxx", "xxxxx") + +// RedactUserinfo returns u if the URL does not contain any userinfo data. +// Otherwise, it returns a deep clone with both username and password redacted. +// u must not be nil. +func RedactUserinfo(u *url.URL) (redacted *url.URL) { + if u.User == nil { + return u + } + + ru := *u + ru.User = redactedUserinfo + + return &ru +} + +// RedactUserinfoInURLError checks if err is a [*url.Error] and, if it is, +// replaces the underlying URL string with a redacted version of u. u must not +// be nil. +func RedactUserinfoInURLError(u *url.URL, err error) { + if err == nil { + return + } + + errURL, ok := err.(*url.Error) + if !ok { + return + } + + if u.User == nil { + return + } + + errURL.URL = RedactUserinfo(u).String() +} diff --git a/netutil/urlutil/urlutil_example_test.go b/netutil/urlutil/urlutil_example_test.go new file mode 100644 index 0000000..e753f48 --- /dev/null +++ b/netutil/urlutil/urlutil_example_test.go @@ -0,0 +1,63 @@ +package urlutil_test + +import ( + "context" + "fmt" + "net" + "net/http" + "net/url" + "time" + + "github.com/AdguardTeam/golibs/errors" + "github.com/AdguardTeam/golibs/netutil/urlutil" +) + +func ExampleValidateHTTPURL() { + fmt.Println(urlutil.ValidateHTTPURL(nil)) + + fmt.Println(urlutil.ValidateHTTPURL(&url.URL{ + Scheme: urlutil.SchemeGRPC, + Host: "host.example", + })) + + fmt.Println(urlutil.ValidateHTTPURL(&url.URL{ + Scheme: urlutil.SchemeHTTP, + Host: "host.example", + })) + + fmt.Println(urlutil.ValidateHTTPURL(&url.URL{ + Scheme: "HTTP", + Host: "HOST.EXAMPLE", + })) + + // Output: + // bad http(s) url: no value + // bad http(s) url "grpc://host.example": scheme: bad enum value: "grpc"; want "http" or "https" + // + // +} + +func ExampleRedactUserinfoInURLError() { + c := &http.Client{ + Timeout: 1 * time.Second, + Transport: &http.Transport{ + DialContext: func(ctx context.Context, network, addr string) (conn net.Conn, err error) { + return nil, errors.Error("test error") + }, + }, + } + + u := &url.URL{ + Scheme: urlutil.SchemeHTTP, + Host: "does-not-exist.example", + User: url.UserPassword("secretUser", "secretPassword"), + } + + _, err := c.Get(u.String()) + urlutil.RedactUserinfoInURLError(u, err) + + fmt.Printf("got error: %s", err) + + // Output: + // got error: Get "http://xxxxx:xxxxx@does-not-exist.example": test error +} diff --git a/netutil/urlutil/urlutil_test.go b/netutil/urlutil/urlutil_test.go new file mode 100644 index 0000000..2130d45 --- /dev/null +++ b/netutil/urlutil/urlutil_test.go @@ -0,0 +1,121 @@ +package urlutil_test + +import ( + "fmt" + "net/http" + "net/url" + "testing" + + "github.com/AdguardTeam/golibs/errors" + "github.com/AdguardTeam/golibs/netutil/urlutil" + "github.com/AdguardTeam/golibs/testutil" + "github.com/stretchr/testify/assert" +) + +// Common constants for tests. +const ( + testHostname = "hostname.example" + testPassword = "pass" + testUsername = "user" +) + +// newTestURL is a helper function that returns a URL with dummy values. +func newTestURL(info *url.Userinfo) (u *url.URL) { + return &url.URL{ + Scheme: urlutil.SchemeHTTP, + User: info, + Host: testHostname, + Path: "/a/b/c/", + RawQuery: "d=e", + Fragment: "f", + } +} + +func TestRedactUserinfo(t *testing.T) { + urlRedacted := newTestURL(url.UserPassword("xxxxx", "xxxxx")) + + testCases := []struct { + in *url.URL + want *url.URL + name string + }{{ + in: newTestURL(url.UserPassword(testUsername, testPassword)), + want: urlRedacted, + name: "with_auth", + }, { + in: newTestURL(nil), + want: newTestURL(nil), + name: "without_auth", + }, { + in: newTestURL(url.UserPassword(testUsername, "")), + want: urlRedacted, + name: "only_user", + }} + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + assert.Equal(t, tc.want, urlutil.RedactUserinfo(tc.in)) + }) + } +} + +func TestRedactUserinfoInURLError(t *testing.T) { + testURL := &url.URL{ + Scheme: urlutil.SchemeHTTP, + User: url.UserPassword(testUsername, testPassword), + Host: testHostname, + } + + const errTest errors.Error = "test error" + + testURLError := &url.Error{ + Op: http.MethodGet, + URL: fmt.Sprintf("http://%s:%s@%s", testUsername, testPassword, testHostname), + Err: errTest, + } + + urlWithoutAuth := &url.URL{ + Scheme: urlutil.SchemeHTTP, + Host: testHostname, + } + + errWithoutAuth := &url.Error{ + Op: http.MethodGet, + URL: urlWithoutAuth.String(), + Err: errTest, + } + + testCases := []struct { + url *url.URL + in error + wantErrMsg string + name string + }{{ + url: testURL, + in: nil, + wantErrMsg: "", + name: "nil_error", + }, { + url: testURL, + in: testURLError, + wantErrMsg: `GET "http://xxxxx:xxxxx@` + testHostname + `": test error`, + name: "redacted", + }, { + url: urlWithoutAuth, + in: errWithoutAuth, + wantErrMsg: `GET "http://` + testHostname + `": test error`, + name: "without_auth", + }, { + url: testURL, + in: fmt.Errorf("not url error"), + wantErrMsg: "not url error", + name: "not_url_error", + }} + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + urlutil.RedactUserinfoInURLError(tc.url, tc.in) + testutil.AssertErrorMsg(t, tc.wantErrMsg, tc.in) + }) + } +} diff --git a/scripts/make/go-bench.sh b/scripts/make/go-bench.sh index 8a93678..a141710 100644 --- a/scripts/make/go-bench.sh +++ b/scripts/make/go-bench.sh @@ -31,10 +31,10 @@ else fi readonly race_flags -count_flags='--count=1' +count_flags='--count=2' go="${GO:-go}" shuffle_flags='--shuffle=on' -timeout_flags="${TIMEOUT_FLAGS:---timeout=30s}" +timeout_flags="${TIMEOUT_FLAGS:---timeout=5m}" readonly count_flags go shuffle_flags timeout_flags "$go" test \ @@ -46,6 +46,5 @@ readonly count_flags go shuffle_flags timeout_flags "$v_flags" \ --bench='.' \ --benchmem \ - --benchtime=1s \ --run='^$' \ ./... diff --git a/scripts/make/go-fuzz.sh b/scripts/make/go-fuzz.sh index f58fa16..96ccaa1 100644 --- a/scripts/make/go-fuzz.sh +++ b/scripts/make/go-fuzz.sh @@ -31,7 +31,7 @@ else fi readonly race_flags -count_flags='--count=1' +count_flags='--count=2' fuzztime_flags="${FUZZTIME_FLAGS:---fuzztime=20s}" go="${GO:-go}" shuffle_flags='--shuffle=on' diff --git a/scripts/make/go-test.sh b/scripts/make/go-test.sh index d04a665..8c8a045 100644 --- a/scripts/make/go-test.sh +++ b/scripts/make/go-test.sh @@ -36,7 +36,7 @@ else fi readonly race_flags -count_flags='--count=1' +count_flags='--count=2' cover_flags='--coverprofile=./cover.out' go="${GO:-go}" shuffle_flags='--shuffle=on'