diff options
Diffstat (limited to 'dependencies/pkg/mod/go.uber.org/atomic@v1.7.0')
44 files changed, 3177 insertions, 0 deletions
diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/.codecov.yml b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/.codecov.yml new file mode 100644 index 0000000..571116c --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/.codecov.yml @@ -0,0 +1,19 @@ +coverage: + range: 80..100 + round: down + precision: 2 + + status: + project: # measuring the overall project coverage + default: # context, you can create multiple ones with custom titles + enabled: yes # must be yes|true to enable this status + target: 100 # specify the target coverage for each commit status + # option: "auto" (must increase from parent commit or pull request base) + # option: "X%" a static target percentage to hit + if_not_found: success # if parent is not found report status as success, error, or failure + if_ci_failed: error # if ci fails report status as success, error, or failure + +# Also update COVER_IGNORE_PKGS in the Makefile. +ignore: + - /internal/gen-atomicint/ + - /internal/gen-valuewrapper/ diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/.github/PULL_REQUEST_TEMPLATE.md b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..de216f2 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,9 @@ +Before opening your pull request, please make sure that you've: + +- [ ] updated the changelog if the change is user-facing; +- [ ] [signed Uber's Contributor License Agreement](https://docs.google.com/a/uber.com/forms/d/1pAwS_-dA1KhPlfxzYLBqK6rsSWwRwH95OCCZrcsY5rk/viewform); +- [ ] added tests to cover your changes; +- [ ] run the test suite locally (`make test`); and finally, +- [ ] run the linters locally (`make lint`). + +Thanks for your contribution! diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/.gitignore b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/.gitignore new file mode 100644 index 0000000..c3fa253 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/.gitignore @@ -0,0 +1,12 @@ +/bin +.DS_Store +/vendor +cover.html +cover.out +lint.log + +# Binaries +*.test + +# Profiling output +*.prof diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/.travis.yml b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/.travis.yml new file mode 100644 index 0000000..13d0a4f --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/.travis.yml @@ -0,0 +1,27 @@ +sudo: false +language: go +go_import_path: go.uber.org/atomic + +env: + global: + - GO111MODULE=on + +matrix: + include: + - go: oldstable + - go: stable + env: LINT=1 + +cache: + directories: + - vendor + +before_install: + - go version + +script: + - test -z "$LINT" || make lint + - make cover + +after_success: + - bash <(curl -s https://codecov.io/bash) diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/CHANGELOG.md b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/CHANGELOG.md new file mode 100644 index 0000000..24c0274 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/CHANGELOG.md @@ -0,0 +1,76 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.7.0] - 2020-09-14 +### Added +- Support JSON serialization and deserialization of primitive atomic types. +- Support Text marshalling and unmarshalling for string atomics. + +### Changed +- Disallow incorrect comparison of atomic values in a non-atomic way. + +### Removed +- Remove dependency on `golang.org/x/{lint, tools}`. + +## [1.6.0] - 2020-02-24 +### Changed +- Drop library dependency on `golang.org/x/{lint, tools}`. + +## [1.5.1] - 2019-11-19 +- Fix bug where `Bool.CAS` and `Bool.Toggle` do work correctly together + causing `CAS` to fail even though the old value matches. + +## [1.5.0] - 2019-10-29 +### Changed +- With Go modules, only the `go.uber.org/atomic` import path is supported now. + If you need to use the old import path, please add a `replace` directive to + your `go.mod`. + +## [1.4.0] - 2019-05-01 +### Added + - Add `atomic.Error` type for atomic operations on `error` values. + +## [1.3.2] - 2018-05-02 +### Added +- Add `atomic.Duration` type for atomic operations on `time.Duration` values. + +## [1.3.1] - 2017-11-14 +### Fixed +- Revert optimization for `atomic.String.Store("")` which caused data races. + +## [1.3.0] - 2017-11-13 +### Added +- Add `atomic.Bool.CAS` for compare-and-swap semantics on bools. + +### Changed +- Optimize `atomic.String.Store("")` by avoiding an allocation. + +## [1.2.0] - 2017-04-12 +### Added +- Shadow `atomic.Value` from `sync/atomic`. + +## [1.1.0] - 2017-03-10 +### Added +- Add atomic `Float64` type. + +### Changed +- Support new `go.uber.org/atomic` import path. + +## [1.0.0] - 2016-07-18 + +- Initial release. + +[1.7.0]: https://github.com/uber-go/atomic/compare/v1.6.0...v1.7.0 +[1.6.0]: https://github.com/uber-go/atomic/compare/v1.5.1...v1.6.0 +[1.5.1]: https://github.com/uber-go/atomic/compare/v1.5.0...v1.5.1 +[1.5.0]: https://github.com/uber-go/atomic/compare/v1.4.0...v1.5.0 +[1.4.0]: https://github.com/uber-go/atomic/compare/v1.3.2...v1.4.0 +[1.3.2]: https://github.com/uber-go/atomic/compare/v1.3.1...v1.3.2 +[1.3.1]: https://github.com/uber-go/atomic/compare/v1.3.0...v1.3.1 +[1.3.0]: https://github.com/uber-go/atomic/compare/v1.2.0...v1.3.0 +[1.2.0]: https://github.com/uber-go/atomic/compare/v1.1.0...v1.2.0 +[1.1.0]: https://github.com/uber-go/atomic/compare/v1.0.0...v1.1.0 +[1.0.0]: https://github.com/uber-go/atomic/releases/tag/v1.0.0 diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/LICENSE.txt b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/LICENSE.txt new file mode 100644 index 0000000..8765c9f --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2016 Uber Technologies, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/Makefile b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/Makefile new file mode 100644 index 0000000..1b1376d --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/Makefile @@ -0,0 +1,78 @@ +# Directory to place `go install`ed binaries into. +export GOBIN ?= $(shell pwd)/bin + +GOLINT = $(GOBIN)/golint +GEN_ATOMICINT = $(GOBIN)/gen-atomicint +GEN_ATOMICWRAPPER = $(GOBIN)/gen-atomicwrapper +STATICCHECK = $(GOBIN)/staticcheck + +GO_FILES ?= $(shell find . '(' -path .git -o -path vendor ')' -prune -o -name '*.go' -print) + +# Also update ignore section in .codecov.yml. +COVER_IGNORE_PKGS = \ + go.uber.org/atomic/internal/gen-atomicint \ + go.uber.org/atomic/internal/gen-atomicwrapper + +.PHONY: build +build: + go build ./... + +.PHONY: test +test: + go test -race ./... + +.PHONY: gofmt +gofmt: + $(eval FMT_LOG := $(shell mktemp -t gofmt.XXXXX)) + gofmt -e -s -l $(GO_FILES) > $(FMT_LOG) || true + @[ ! -s "$(FMT_LOG)" ] || (echo "gofmt failed:" && cat $(FMT_LOG) && false) + +$(GOLINT): + cd tools && go install golang.org/x/lint/golint + +$(STATICCHECK): + cd tools && go install honnef.co/go/tools/cmd/staticcheck + +$(GEN_ATOMICWRAPPER): $(wildcard ./internal/gen-atomicwrapper/*) + go build -o $@ ./internal/gen-atomicwrapper + +$(GEN_ATOMICINT): $(wildcard ./internal/gen-atomicint/*) + go build -o $@ ./internal/gen-atomicint + +.PHONY: golint +golint: $(GOLINT) + $(GOLINT) ./... + +.PHONY: staticcheck +staticcheck: $(STATICCHECK) + $(STATICCHECK) ./... + +.PHONY: lint +lint: gofmt golint staticcheck generatenodirty + +# comma separated list of packages to consider for code coverage. +COVER_PKG = $(shell \ + go list -find ./... | \ + grep -v $(foreach pkg,$(COVER_IGNORE_PKGS),-e "^$(pkg)$$") | \ + paste -sd, -) + +.PHONY: cover +cover: + go test -coverprofile=cover.out -coverpkg $(COVER_PKG) -v ./... + go tool cover -html=cover.out -o cover.html + +.PHONY: generate +generate: $(GEN_ATOMICINT) $(GEN_ATOMICWRAPPER) + go generate ./... + +.PHONY: generatenodirty +generatenodirty: + @[ -z "$$(git status --porcelain)" ] || ( \ + echo "Working tree is dirty. Commit your changes first."; \ + exit 1 ) + @make generate + @status=$$(git status --porcelain); \ + [ -z "$$status" ] || ( \ + echo "Working tree is dirty after `make generate`:"; \ + echo "$$status"; \ + echo "Please ensure that the generated code is up-to-date." ) diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/README.md b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/README.md new file mode 100644 index 0000000..ade0c20 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/README.md @@ -0,0 +1,63 @@ +# atomic [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] [![Go Report Card][reportcard-img]][reportcard] + +Simple wrappers for primitive types to enforce atomic access. + +## Installation + +```shell +$ go get -u go.uber.org/atomic@v1 +``` + +### Legacy Import Path + +As of v1.5.0, the import path `go.uber.org/atomic` is the only supported way +of using this package. If you are using Go modules, this package will fail to +compile with the legacy import path path `github.com/uber-go/atomic`. + +We recommend migrating your code to the new import path but if you're unable +to do so, or if your dependencies are still using the old import path, you +will have to add a `replace` directive to your `go.mod` file downgrading the +legacy import path to an older version. + +``` +replace github.com/uber-go/atomic => github.com/uber-go/atomic v1.4.0 +``` + +You can do so automatically by running the following command. + +```shell +$ go mod edit -replace github.com/uber-go/atomic=github.com/uber-go/atomic@v1.4.0 +``` + +## Usage + +The standard library's `sync/atomic` is powerful, but it's easy to forget which +variables must be accessed atomically. `go.uber.org/atomic` preserves all the +functionality of the standard library, but wraps the primitive types to +provide a safer, more convenient API. + +```go +var atom atomic.Uint32 +atom.Store(42) +atom.Sub(2) +atom.CAS(40, 11) +``` + +See the [documentation][doc] for a complete API specification. + +## Development Status + +Stable. + +--- + +Released under the [MIT License](LICENSE.txt). + +[doc-img]: https://godoc.org/github.com/uber-go/atomic?status.svg +[doc]: https://godoc.org/go.uber.org/atomic +[ci-img]: https://travis-ci.com/uber-go/atomic.svg?branch=master +[ci]: https://travis-ci.com/uber-go/atomic +[cov-img]: https://codecov.io/gh/uber-go/atomic/branch/master/graph/badge.svg +[cov]: https://codecov.io/gh/uber-go/atomic +[reportcard-img]: https://goreportcard.com/badge/go.uber.org/atomic +[reportcard]: https://goreportcard.com/report/go.uber.org/atomic diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/assert_test.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/assert_test.go new file mode 100644 index 0000000..b3465b8 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/assert_test.go @@ -0,0 +1,45 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "encoding/json" + "errors" + "testing" + + "github.com/stretchr/testify/assert" +) + +// Marks the test as failed if the error cannot be cast into the provided type +// with errors.As. +// +// assertErrorAsType(t, err, new(ErrFoo)) +func assertErrorAsType(t *testing.T, err error, typ interface{}, msgAndArgs ...interface{}) bool { + t.Helper() + + return assert.True(t, errors.As(err, typ), msgAndArgs...) +} + +func assertErrorJSONUnmarshalType(t *testing.T, err error, msgAndArgs ...interface{}) bool { + t.Helper() + + return assertErrorAsType(t, err, new(*json.UnmarshalTypeError), msgAndArgs...) +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/bool.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/bool.go new file mode 100644 index 0000000..9cf1914 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/bool.go @@ -0,0 +1,81 @@ +// @generated Code generated by gen-atomicwrapper. + +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "encoding/json" +) + +// Bool is an atomic type-safe wrapper for bool values. +type Bool struct { + _ nocmp // disallow non-atomic comparison + + v Uint32 +} + +var _zeroBool bool + +// NewBool creates a new Bool. +func NewBool(v bool) *Bool { + x := &Bool{} + if v != _zeroBool { + x.Store(v) + } + return x +} + +// Load atomically loads the wrapped bool. +func (x *Bool) Load() bool { + return truthy(x.v.Load()) +} + +// Store atomically stores the passed bool. +func (x *Bool) Store(v bool) { + x.v.Store(boolToInt(v)) +} + +// CAS is an atomic compare-and-swap for bool values. +func (x *Bool) CAS(o, n bool) bool { + return x.v.CAS(boolToInt(o), boolToInt(n)) +} + +// Swap atomically stores the given bool and returns the old +// value. +func (x *Bool) Swap(o bool) bool { + return truthy(x.v.Swap(boolToInt(o))) +} + +// MarshalJSON encodes the wrapped bool into JSON. +func (x *Bool) MarshalJSON() ([]byte, error) { + return json.Marshal(x.Load()) +} + +// UnmarshalJSON decodes a bool from JSON. +func (x *Bool) UnmarshalJSON(b []byte) error { + var v bool + if err := json.Unmarshal(b, &v); err != nil { + return err + } + x.Store(v) + return nil +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/bool_ext.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/bool_ext.go new file mode 100644 index 0000000..c7bf7a8 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/bool_ext.go @@ -0,0 +1,53 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "strconv" +) + +//go:generate bin/gen-atomicwrapper -name=Bool -type=bool -wrapped=Uint32 -pack=boolToInt -unpack=truthy -cas -swap -json -file=bool.go + +func truthy(n uint32) bool { + return n == 1 +} + +func boolToInt(b bool) uint32 { + if b { + return 1 + } + return 0 +} + +// Toggle atomically negates the Boolean and returns the previous value. +func (b *Bool) Toggle() bool { + for { + old := b.Load() + if b.CAS(old, !old) { + return old + } + } +} + +// String encodes the wrapped value as a string. +func (b *Bool) String() string { + return strconv.FormatBool(b.Load()) +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/bool_test.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/bool_test.go new file mode 100644 index 0000000..bcba01d --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/bool_test.go @@ -0,0 +1,86 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestBool(t *testing.T) { + atom := NewBool(false) + require.False(t, atom.Toggle(), "Expected Toggle to return previous value.") + require.True(t, atom.Toggle(), "Expected Toggle to return previous value.") + require.False(t, atom.Toggle(), "Expected Toggle to return previous value.") + require.True(t, atom.Load(), "Unexpected state after swap.") + + require.True(t, atom.CAS(true, true), "CAS should swap when old matches") + require.True(t, atom.Load(), "CAS should have no effect") + require.True(t, atom.CAS(true, false), "CAS should swap when old matches") + require.False(t, atom.Load(), "CAS should have modified the value") + require.False(t, atom.CAS(true, false), "CAS should fail on old mismatch") + require.False(t, atom.Load(), "CAS should not have modified the value") + + atom.Store(false) + require.False(t, atom.Load(), "Unexpected state after store.") + + prev := atom.Swap(false) + require.False(t, prev, "Expected Swap to return previous value.") + + prev = atom.Swap(true) + require.False(t, prev, "Expected Swap to return previous value.") + + t.Run("JSON/Marshal", func(t *testing.T) { + atom.Store(true) + bytes, err := json.Marshal(atom) + require.NoError(t, err, "json.Marshal errored unexpectedly.") + require.Equal(t, []byte("true"), bytes, "json.Marshal encoded the wrong bytes.") + }) + + t.Run("JSON/Unmarshal", func(t *testing.T) { + err := json.Unmarshal([]byte("false"), &atom) + require.NoError(t, err, "json.Unmarshal errored unexpectedly.") + require.False(t, atom.Load(), "json.Unmarshal didn't set the correct value.") + }) + + t.Run("JSON/Unmarshal/Error", func(t *testing.T) { + err := json.Unmarshal([]byte("42"), &atom) + require.Error(t, err, "json.Unmarshal didn't error as expected.") + assertErrorJSONUnmarshalType(t, err, + "json.Unmarshal failed with unexpected error %v, want UnmarshalTypeError.", err) + }) + + t.Run("String", func(t *testing.T) { + t.Run("true", func(t *testing.T) { + assert.Equal(t, "true", NewBool(true).String(), + "String() returned an unexpected value.") + }) + + t.Run("false", func(t *testing.T) { + var b Bool + assert.Equal(t, "false", b.String(), + "String() returned an unexpected value.") + }) + }) +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/doc.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/doc.go new file mode 100644 index 0000000..ae7390e --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/doc.go @@ -0,0 +1,23 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// Package atomic provides simple wrappers around numerics to enforce atomic +// access. +package atomic diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/duration.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/duration.go new file mode 100644 index 0000000..027cfcb --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/duration.go @@ -0,0 +1,82 @@ +// @generated Code generated by gen-atomicwrapper. + +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "encoding/json" + "time" +) + +// Duration is an atomic type-safe wrapper for time.Duration values. +type Duration struct { + _ nocmp // disallow non-atomic comparison + + v Int64 +} + +var _zeroDuration time.Duration + +// NewDuration creates a new Duration. +func NewDuration(v time.Duration) *Duration { + x := &Duration{} + if v != _zeroDuration { + x.Store(v) + } + return x +} + +// Load atomically loads the wrapped time.Duration. +func (x *Duration) Load() time.Duration { + return time.Duration(x.v.Load()) +} + +// Store atomically stores the passed time.Duration. +func (x *Duration) Store(v time.Duration) { + x.v.Store(int64(v)) +} + +// CAS is an atomic compare-and-swap for time.Duration values. +func (x *Duration) CAS(o, n time.Duration) bool { + return x.v.CAS(int64(o), int64(n)) +} + +// Swap atomically stores the given time.Duration and returns the old +// value. +func (x *Duration) Swap(o time.Duration) time.Duration { + return time.Duration(x.v.Swap(int64(o))) +} + +// MarshalJSON encodes the wrapped time.Duration into JSON. +func (x *Duration) MarshalJSON() ([]byte, error) { + return json.Marshal(x.Load()) +} + +// UnmarshalJSON decodes a time.Duration from JSON. +func (x *Duration) UnmarshalJSON(b []byte) error { + var v time.Duration + if err := json.Unmarshal(b, &v); err != nil { + return err + } + x.Store(v) + return nil +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/duration_ext.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/duration_ext.go new file mode 100644 index 0000000..6273b66 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/duration_ext.go @@ -0,0 +1,40 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import "time" + +//go:generate bin/gen-atomicwrapper -name=Duration -type=time.Duration -wrapped=Int64 -pack=int64 -unpack=time.Duration -cas -swap -json -imports time -file=duration.go + +// Add atomically adds to the wrapped time.Duration and returns the new value. +func (d *Duration) Add(n time.Duration) time.Duration { + return time.Duration(d.v.Add(int64(n))) +} + +// Sub atomically subtracts from the wrapped time.Duration and returns the new value. +func (d *Duration) Sub(n time.Duration) time.Duration { + return time.Duration(d.v.Sub(int64(n))) +} + +// String encodes the wrapped value as a string. +func (d *Duration) String() string { + return d.Load().String() +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/duration_test.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/duration_test.go new file mode 100644 index 0000000..bc5cea5 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/duration_test.go @@ -0,0 +1,72 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "encoding/json" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestDuration(t *testing.T) { + atom := NewDuration(5 * time.Minute) + + require.Equal(t, 5*time.Minute, atom.Load(), "Load didn't work.") + require.Equal(t, 6*time.Minute, atom.Add(time.Minute), "Add didn't work.") + require.Equal(t, 4*time.Minute, atom.Sub(2*time.Minute), "Sub didn't work.") + + require.True(t, atom.CAS(4*time.Minute, time.Minute), "CAS didn't report a swap.") + require.Equal(t, time.Minute, atom.Load(), "CAS didn't set the correct value.") + + require.Equal(t, time.Minute, atom.Swap(2*time.Minute), "Swap didn't return the old value.") + require.Equal(t, 2*time.Minute, atom.Load(), "Swap didn't set the correct value.") + + atom.Store(10 * time.Minute) + require.Equal(t, 10*time.Minute, atom.Load(), "Store didn't set the correct value.") + + t.Run("JSON/Marshal", func(t *testing.T) { + atom.Store(time.Second) + bytes, err := json.Marshal(atom) + require.NoError(t, err, "json.Marshal errored unexpectedly.") + require.Equal(t, []byte("1000000000"), bytes, "json.Marshal encoded the wrong bytes.") + }) + + t.Run("JSON/Unmarshal", func(t *testing.T) { + err := json.Unmarshal([]byte("1000000000"), &atom) + require.NoError(t, err, "json.Unmarshal errored unexpectedly.") + require.Equal(t, time.Second, atom.Load(), "json.Unmarshal didn't set the correct value.") + }) + + t.Run("JSON/Unmarshal/Error", func(t *testing.T) { + err := json.Unmarshal([]byte("\"1000000000\""), &atom) + require.Error(t, err, "json.Unmarshal didn't error as expected.") + assertErrorJSONUnmarshalType(t, err, + "json.Unmarshal failed with unexpected error %v, want UnmarshalTypeError.", err) + }) + + t.Run("String", func(t *testing.T) { + assert.Equal(t, "42s", NewDuration(42*time.Second).String(), + "String() returned an unexpected value.") + }) +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/error.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/error.go new file mode 100644 index 0000000..a6166fb --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/error.go @@ -0,0 +1,51 @@ +// @generated Code generated by gen-atomicwrapper. + +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +// Error is an atomic type-safe wrapper for error values. +type Error struct { + _ nocmp // disallow non-atomic comparison + + v Value +} + +var _zeroError error + +// NewError creates a new Error. +func NewError(v error) *Error { + x := &Error{} + if v != _zeroError { + x.Store(v) + } + return x +} + +// Load atomically loads the wrapped error. +func (x *Error) Load() error { + return unpackError(x.v.Load()) +} + +// Store atomically stores the passed error. +func (x *Error) Store(v error) { + x.v.Store(packError(v)) +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/error_ext.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/error_ext.go new file mode 100644 index 0000000..ffe0be2 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/error_ext.go @@ -0,0 +1,39 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +// atomic.Value panics on nil inputs, or if the underlying type changes. +// Stabilize by always storing a custom struct that we control. + +//go:generate bin/gen-atomicwrapper -name=Error -type=error -wrapped=Value -pack=packError -unpack=unpackError -file=error.go + +type packedError struct{ Value error } + +func packError(v error) interface{} { + return packedError{v} +} + +func unpackError(v interface{}) error { + if err, ok := v.(packedError); ok { + return err.Value + } + return nil +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/error_test.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/error_test.go new file mode 100644 index 0000000..cab2e7d --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/error_test.go @@ -0,0 +1,55 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestErrorByValue(t *testing.T) { + err := &Error{} + require.Nil(t, err.Load(), "Initial value shall be nil") +} + +func TestNewErrorWithNilArgument(t *testing.T) { + err := NewError(nil) + require.Nil(t, err.Load(), "Initial value shall be nil") +} + +func TestErrorCanStoreNil(t *testing.T) { + err := NewError(errors.New("hello")) + err.Store(nil) + require.Nil(t, err.Load(), "Stored value shall be nil") +} + +func TestNewErrorWithError(t *testing.T) { + err1 := errors.New("hello1") + err2 := errors.New("hello2") + + atom := NewError(err1) + require.Equal(t, err1, atom.Load(), "Expected Load to return initialized value") + + atom.Store(err2) + require.Equal(t, err2, atom.Load(), "Expected Load to return overridden value") +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/example_test.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/example_test.go new file mode 100644 index 0000000..806e11c --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/example_test.go @@ -0,0 +1,43 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic_test + +import ( + "fmt" + + "go.uber.org/atomic" +) + +func Example() { + // Uint32 is a thin wrapper around the primitive uint32 type. + var atom atomic.Uint32 + + // The wrapper ensures that all operations are atomic. + atom.Store(42) + fmt.Println(atom.Inc()) + fmt.Println(atom.CAS(43, 0)) + fmt.Println(atom.Load()) + + // Output: + // 43 + // true + // 0 +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/float64.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/float64.go new file mode 100644 index 0000000..0719060 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/float64.go @@ -0,0 +1,76 @@ +// @generated Code generated by gen-atomicwrapper. + +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "encoding/json" + "math" +) + +// Float64 is an atomic type-safe wrapper for float64 values. +type Float64 struct { + _ nocmp // disallow non-atomic comparison + + v Uint64 +} + +var _zeroFloat64 float64 + +// NewFloat64 creates a new Float64. +func NewFloat64(v float64) *Float64 { + x := &Float64{} + if v != _zeroFloat64 { + x.Store(v) + } + return x +} + +// Load atomically loads the wrapped float64. +func (x *Float64) Load() float64 { + return math.Float64frombits(x.v.Load()) +} + +// Store atomically stores the passed float64. +func (x *Float64) Store(v float64) { + x.v.Store(math.Float64bits(v)) +} + +// CAS is an atomic compare-and-swap for float64 values. +func (x *Float64) CAS(o, n float64) bool { + return x.v.CAS(math.Float64bits(o), math.Float64bits(n)) +} + +// MarshalJSON encodes the wrapped float64 into JSON. +func (x *Float64) MarshalJSON() ([]byte, error) { + return json.Marshal(x.Load()) +} + +// UnmarshalJSON decodes a float64 from JSON. +func (x *Float64) UnmarshalJSON(b []byte) error { + var v float64 + if err := json.Unmarshal(b, &v); err != nil { + return err + } + x.Store(v) + return nil +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/float64_ext.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/float64_ext.go new file mode 100644 index 0000000..927b1ad --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/float64_ext.go @@ -0,0 +1,47 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import "strconv" + +//go:generate bin/gen-atomicwrapper -name=Float64 -type=float64 -wrapped=Uint64 -pack=math.Float64bits -unpack=math.Float64frombits -cas -json -imports math -file=float64.go + +// Add atomically adds to the wrapped float64 and returns the new value. +func (f *Float64) Add(s float64) float64 { + for { + old := f.Load() + new := old + s + if f.CAS(old, new) { + return new + } + } +} + +// Sub atomically subtracts from the wrapped float64 and returns the new value. +func (f *Float64) Sub(s float64) float64 { + return f.Add(-s) +} + +// String encodes the wrapped value as a string. +func (f *Float64) String() string { + // 'g' is the behavior for floats with %v. + return strconv.FormatFloat(f.Load(), 'g', -1, 64) +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/float64_test.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/float64_test.go new file mode 100644 index 0000000..bc04e77 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/float64_test.go @@ -0,0 +1,69 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestFloat64(t *testing.T) { + atom := NewFloat64(4.2) + + require.Equal(t, float64(4.2), atom.Load(), "Load didn't work.") + + require.True(t, atom.CAS(4.2, 0.5), "CAS didn't report a swap.") + require.Equal(t, float64(0.5), atom.Load(), "CAS didn't set the correct value.") + require.False(t, atom.CAS(0.0, 1.5), "CAS reported a swap.") + + atom.Store(42.0) + require.Equal(t, float64(42.0), atom.Load(), "Store didn't set the correct value.") + require.Equal(t, float64(42.5), atom.Add(0.5), "Add didn't work.") + require.Equal(t, float64(42.0), atom.Sub(0.5), "Sub didn't work.") + + t.Run("JSON/Marshal", func(t *testing.T) { + atom.Store(42.5) + bytes, err := json.Marshal(atom) + require.NoError(t, err, "json.Marshal errored unexpectedly.") + require.Equal(t, []byte("42.5"), bytes, "json.Marshal encoded the wrong bytes.") + }) + + t.Run("JSON/Unmarshal", func(t *testing.T) { + err := json.Unmarshal([]byte("40.5"), &atom) + require.NoError(t, err, "json.Unmarshal errored unexpectedly.") + require.Equal(t, float64(40.5), atom.Load(), "json.Unmarshal didn't set the correct value.") + }) + + t.Run("JSON/Unmarshal/Error", func(t *testing.T) { + err := json.Unmarshal([]byte("\"40.5\""), &atom) + require.Error(t, err, "json.Unmarshal didn't error as expected.") + assertErrorJSONUnmarshalType(t, err, + "json.Unmarshal failed with unexpected error %v, want UnmarshalTypeError.", err) + }) + + t.Run("String", func(t *testing.T) { + assert.Equal(t, "42.5", NewFloat64(42.5).String(), + "String() returned an unexpected value.") + }) +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/gen.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/gen.go new file mode 100644 index 0000000..50d6b24 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/gen.go @@ -0,0 +1,26 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +//go:generate bin/gen-atomicint -name=Int32 -wrapped=int32 -file=int32.go +//go:generate bin/gen-atomicint -name=Int64 -wrapped=int64 -file=int64.go +//go:generate bin/gen-atomicint -name=Uint32 -wrapped=uint32 -unsigned -file=uint32.go +//go:generate bin/gen-atomicint -name=Uint64 -wrapped=uint64 -unsigned -file=uint64.go diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/go.mod b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/go.mod new file mode 100644 index 0000000..daa7599 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/go.mod @@ -0,0 +1,8 @@ +module go.uber.org/atomic + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/stretchr/testify v1.3.0 +) + +go 1.13 diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/go.sum b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/go.sum new file mode 100644 index 0000000..4f76e62 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/go.sum @@ -0,0 +1,9 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/int32.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/int32.go new file mode 100644 index 0000000..18ae564 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/int32.go @@ -0,0 +1,102 @@ +// @generated Code generated by gen-atomicint. + +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "encoding/json" + "strconv" + "sync/atomic" +) + +// Int32 is an atomic wrapper around int32. +type Int32 struct { + _ nocmp // disallow non-atomic comparison + + v int32 +} + +// NewInt32 creates a new Int32. +func NewInt32(i int32) *Int32 { + return &Int32{v: i} +} + +// Load atomically loads the wrapped value. +func (i *Int32) Load() int32 { + return atomic.LoadInt32(&i.v) +} + +// Add atomically adds to the wrapped int32 and returns the new value. +func (i *Int32) Add(n int32) int32 { + return atomic.AddInt32(&i.v, n) +} + +// Sub atomically subtracts from the wrapped int32 and returns the new value. +func (i *Int32) Sub(n int32) int32 { + return atomic.AddInt32(&i.v, -n) +} + +// Inc atomically increments the wrapped int32 and returns the new value. +func (i *Int32) Inc() int32 { + return i.Add(1) +} + +// Dec atomically decrements the wrapped int32 and returns the new value. +func (i *Int32) Dec() int32 { + return i.Sub(1) +} + +// CAS is an atomic compare-and-swap. +func (i *Int32) CAS(old, new int32) bool { + return atomic.CompareAndSwapInt32(&i.v, old, new) +} + +// Store atomically stores the passed value. +func (i *Int32) Store(n int32) { + atomic.StoreInt32(&i.v, n) +} + +// Swap atomically swaps the wrapped int32 and returns the old value. +func (i *Int32) Swap(n int32) int32 { + return atomic.SwapInt32(&i.v, n) +} + +// MarshalJSON encodes the wrapped int32 into JSON. +func (i *Int32) MarshalJSON() ([]byte, error) { + return json.Marshal(i.Load()) +} + +// UnmarshalJSON decodes JSON into the wrapped int32. +func (i *Int32) UnmarshalJSON(b []byte) error { + var v int32 + if err := json.Unmarshal(b, &v); err != nil { + return err + } + i.Store(v) + return nil +} + +// String encodes the wrapped value as a string. +func (i *Int32) String() string { + v := i.Load() + return strconv.FormatInt(int64(v), 10) +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/int32_test.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/int32_test.go new file mode 100644 index 0000000..9992251 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/int32_test.go @@ -0,0 +1,82 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "encoding/json" + "math" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestInt32(t *testing.T) { + atom := NewInt32(42) + + require.Equal(t, int32(42), atom.Load(), "Load didn't work.") + require.Equal(t, int32(46), atom.Add(4), "Add didn't work.") + require.Equal(t, int32(44), atom.Sub(2), "Sub didn't work.") + require.Equal(t, int32(45), atom.Inc(), "Inc didn't work.") + require.Equal(t, int32(44), atom.Dec(), "Dec didn't work.") + + require.True(t, atom.CAS(44, 0), "CAS didn't report a swap.") + require.Equal(t, int32(0), atom.Load(), "CAS didn't set the correct value.") + + require.Equal(t, int32(0), atom.Swap(1), "Swap didn't return the old value.") + require.Equal(t, int32(1), atom.Load(), "Swap didn't set the correct value.") + + atom.Store(42) + require.Equal(t, int32(42), atom.Load(), "Store didn't set the correct value.") + + t.Run("JSON/Marshal", func(t *testing.T) { + bytes, err := json.Marshal(atom) + require.NoError(t, err, "json.Marshal errored unexpectedly.") + require.Equal(t, []byte("42"), bytes, "json.Marshal encoded the wrong bytes.") + }) + + t.Run("JSON/Unmarshal", func(t *testing.T) { + err := json.Unmarshal([]byte("40"), &atom) + require.NoError(t, err, "json.Unmarshal errored unexpectedly.") + require.Equal(t, int32(40), atom.Load(), "json.Unmarshal didn't set the correct value.") + }) + + t.Run("JSON/Unmarshal/Error", func(t *testing.T) { + err := json.Unmarshal([]byte(`"40"`), &atom) + require.Error(t, err, "json.Unmarshal didn't error as expected.") + assertErrorJSONUnmarshalType(t, err, + "json.Unmarshal failed with unexpected error %v, want UnmarshalTypeError.", err) + }) + + t.Run("String", func(t *testing.T) { + t.Run("positive", func(t *testing.T) { + atom := NewInt32(math.MaxInt32) + assert.Equal(t, "2147483647", atom.String(), + "String() returned an unexpected value.") + }) + + t.Run("negative", func(t *testing.T) { + atom := NewInt32(math.MinInt32) + assert.Equal(t, "-2147483648", atom.String(), + "String() returned an unexpected value.") + }) + }) +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/int64.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/int64.go new file mode 100644 index 0000000..2bcbbfa --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/int64.go @@ -0,0 +1,102 @@ +// @generated Code generated by gen-atomicint. + +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "encoding/json" + "strconv" + "sync/atomic" +) + +// Int64 is an atomic wrapper around int64. +type Int64 struct { + _ nocmp // disallow non-atomic comparison + + v int64 +} + +// NewInt64 creates a new Int64. +func NewInt64(i int64) *Int64 { + return &Int64{v: i} +} + +// Load atomically loads the wrapped value. +func (i *Int64) Load() int64 { + return atomic.LoadInt64(&i.v) +} + +// Add atomically adds to the wrapped int64 and returns the new value. +func (i *Int64) Add(n int64) int64 { + return atomic.AddInt64(&i.v, n) +} + +// Sub atomically subtracts from the wrapped int64 and returns the new value. +func (i *Int64) Sub(n int64) int64 { + return atomic.AddInt64(&i.v, -n) +} + +// Inc atomically increments the wrapped int64 and returns the new value. +func (i *Int64) Inc() int64 { + return i.Add(1) +} + +// Dec atomically decrements the wrapped int64 and returns the new value. +func (i *Int64) Dec() int64 { + return i.Sub(1) +} + +// CAS is an atomic compare-and-swap. +func (i *Int64) CAS(old, new int64) bool { + return atomic.CompareAndSwapInt64(&i.v, old, new) +} + +// Store atomically stores the passed value. +func (i *Int64) Store(n int64) { + atomic.StoreInt64(&i.v, n) +} + +// Swap atomically swaps the wrapped int64 and returns the old value. +func (i *Int64) Swap(n int64) int64 { + return atomic.SwapInt64(&i.v, n) +} + +// MarshalJSON encodes the wrapped int64 into JSON. +func (i *Int64) MarshalJSON() ([]byte, error) { + return json.Marshal(i.Load()) +} + +// UnmarshalJSON decodes JSON into the wrapped int64. +func (i *Int64) UnmarshalJSON(b []byte) error { + var v int64 + if err := json.Unmarshal(b, &v); err != nil { + return err + } + i.Store(v) + return nil +} + +// String encodes the wrapped value as a string. +func (i *Int64) String() string { + v := i.Load() + return strconv.FormatInt(int64(v), 10) +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/int64_test.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/int64_test.go new file mode 100644 index 0000000..ed5a104 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/int64_test.go @@ -0,0 +1,82 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "encoding/json" + "math" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestInt64(t *testing.T) { + atom := NewInt64(42) + + require.Equal(t, int64(42), atom.Load(), "Load didn't work.") + require.Equal(t, int64(46), atom.Add(4), "Add didn't work.") + require.Equal(t, int64(44), atom.Sub(2), "Sub didn't work.") + require.Equal(t, int64(45), atom.Inc(), "Inc didn't work.") + require.Equal(t, int64(44), atom.Dec(), "Dec didn't work.") + + require.True(t, atom.CAS(44, 0), "CAS didn't report a swap.") + require.Equal(t, int64(0), atom.Load(), "CAS didn't set the correct value.") + + require.Equal(t, int64(0), atom.Swap(1), "Swap didn't return the old value.") + require.Equal(t, int64(1), atom.Load(), "Swap didn't set the correct value.") + + atom.Store(42) + require.Equal(t, int64(42), atom.Load(), "Store didn't set the correct value.") + + t.Run("JSON/Marshal", func(t *testing.T) { + bytes, err := json.Marshal(atom) + require.NoError(t, err, "json.Marshal errored unexpectedly.") + require.Equal(t, []byte("42"), bytes, "json.Marshal encoded the wrong bytes.") + }) + + t.Run("JSON/Unmarshal", func(t *testing.T) { + err := json.Unmarshal([]byte("40"), &atom) + require.NoError(t, err, "json.Unmarshal errored unexpectedly.") + require.Equal(t, int64(40), atom.Load(), "json.Unmarshal didn't set the correct value.") + }) + + t.Run("JSON/Unmarshal/Error", func(t *testing.T) { + err := json.Unmarshal([]byte(`"40"`), &atom) + require.Error(t, err, "json.Unmarshal didn't error as expected.") + assertErrorJSONUnmarshalType(t, err, + "json.Unmarshal failed with unexpected error %v, want UnmarshalTypeError.", err) + }) + + t.Run("String", func(t *testing.T) { + t.Run("positive", func(t *testing.T) { + atom := NewInt64(math.MaxInt64) + assert.Equal(t, "9223372036854775807", atom.String(), + "String() returned an unexpected value.") + }) + + t.Run("negative", func(t *testing.T) { + atom := NewInt64(math.MinInt64) + assert.Equal(t, "-9223372036854775808", atom.String(), + "String() returned an unexpected value.") + }) + }) +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/internal/gen-atomicint/main.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/internal/gen-atomicint/main.go new file mode 100644 index 0000000..211cd34 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/internal/gen-atomicint/main.go @@ -0,0 +1,218 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// gen-atomicint generates an atomic wrapper around an integer type. +// +// gen-atomicint -name Int32 -wrapped int32 -file out.go +// +// The generated wrapper will use the functions in the sync/atomic package +// named after the generated type. +package main + +import ( + "bytes" + "errors" + "flag" + "fmt" + "go/format" + "io" + "log" + "os" + "text/template" +) + +func main() { + log.SetFlags(0) + if err := run(os.Args[1:]); err != nil { + log.Fatalf("%+v", err) + } +} + +func run(args []string) error { + var opts struct { + Name string + Wrapped string + File string + Unsigned bool + } + + flag := flag.NewFlagSet("gen-atomicint", flag.ContinueOnError) + + flag.StringVar(&opts.Name, "name", "", "name of the generated type (e.g. Int32)") + flag.StringVar(&opts.Wrapped, "wrapped", "", "name of the wrapped type (e.g. int32)") + flag.StringVar(&opts.File, "file", "", "output file path (default: stdout)") + flag.BoolVar(&opts.Unsigned, "unsigned", false, "whether the type is unsigned") + + if err := flag.Parse(args); err != nil { + return err + } + + if len(opts.Name) == 0 || len(opts.Wrapped) == 0 { + return errors.New("flags -name and -wrapped are required") + } + + var w io.Writer = os.Stdout + if file := opts.File; len(file) > 0 { + f, err := os.Create(file) + if err != nil { + return fmt.Errorf("create %q: %v", file, err) + } + defer f.Close() + + w = f + } + + data := struct { + Name string + Wrapped string + Unsigned bool + }{ + Name: opts.Name, + Wrapped: opts.Wrapped, + Unsigned: opts.Unsigned, + } + + var buff bytes.Buffer + if err := _tmpl.Execute(&buff, data); err != nil { + return fmt.Errorf("render template: %v", err) + } + + bs, err := format.Source(buff.Bytes()) + if err != nil { + return fmt.Errorf("reformat source: %v", err) + } + + _, err = w.Write(bs) + return err +} + +var _tmpl = template.Must(template.New("value.go").Parse(`// @generated Code generated by gen-atomicint. + +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "encoding/json" + "strconv" + "sync/atomic" +) + +// {{ .Name }} is an atomic wrapper around {{ .Wrapped }}. +type {{ .Name }} struct { + _ nocmp // disallow non-atomic comparison + + v {{ .Wrapped }} +} + +// New{{ .Name }} creates a new {{ .Name }}. +func New{{ .Name }}(i {{ .Wrapped }}) *{{ .Name }} { + return &{{ .Name }}{v: i} +} + +// Load atomically loads the wrapped value. +func (i *{{ .Name }}) Load() {{ .Wrapped }} { + return atomic.Load{{ .Name }}(&i.v) +} + +// Add atomically adds to the wrapped {{ .Wrapped }} and returns the new value. +func (i *{{ .Name }}) Add(n {{ .Wrapped }}) {{ .Wrapped }} { + return atomic.Add{{ .Name }}(&i.v, n) +} + +// Sub atomically subtracts from the wrapped {{ .Wrapped }} and returns the new value. +func (i *{{ .Name }}) Sub(n {{ .Wrapped }}) {{ .Wrapped }} { + return atomic.Add{{ .Name }}(&i.v, + {{- if .Unsigned -}} + ^(n - 1) + {{- else -}} + -n + {{- end -}} + ) +} + +// Inc atomically increments the wrapped {{ .Wrapped }} and returns the new value. +func (i *{{ .Name }}) Inc() {{ .Wrapped }} { + return i.Add(1) +} + +// Dec atomically decrements the wrapped {{ .Wrapped }} and returns the new value. +func (i *{{ .Name }}) Dec() {{ .Wrapped }} { + return i.Sub(1) +} + +// CAS is an atomic compare-and-swap. +func (i *{{ .Name }}) CAS(old, new {{ .Wrapped }}) bool { + return atomic.CompareAndSwap{{ .Name }}(&i.v, old, new) +} + +// Store atomically stores the passed value. +func (i *{{ .Name }}) Store(n {{ .Wrapped }}) { + atomic.Store{{ .Name }}(&i.v, n) +} + +// Swap atomically swaps the wrapped {{ .Wrapped }} and returns the old value. +func (i *{{ .Name }}) Swap(n {{ .Wrapped }}) {{ .Wrapped }} { + return atomic.Swap{{ .Name }}(&i.v, n) +} + +// MarshalJSON encodes the wrapped {{ .Wrapped }} into JSON. +func (i *{{ .Name }}) MarshalJSON() ([]byte, error) { + return json.Marshal(i.Load()) +} + +// UnmarshalJSON decodes JSON into the wrapped {{ .Wrapped }}. +func (i *{{ .Name }}) UnmarshalJSON(b []byte) error { + var v {{ .Wrapped }} + if err := json.Unmarshal(b, &v); err != nil { + return err + } + i.Store(v) + return nil +} + +// String encodes the wrapped value as a string. +func (i *{{ .Name }}) String() string { + v := i.Load() + {{ if .Unsigned -}} + return strconv.FormatUint(uint64(v), 10) + {{- else -}} + return strconv.FormatInt(int64(v), 10) + {{- end }} +} +`)) diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/internal/gen-atomicwrapper/main.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/internal/gen-atomicwrapper/main.go new file mode 100644 index 0000000..862c411 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/internal/gen-atomicwrapper/main.go @@ -0,0 +1,300 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// gen-atomicwrapper generates wrapper types around other atomic types. +// +// It supports plugging in functions which convert the value inside the atomic +// type to the user-facing value. For example, +// +// Given, atomic.Value and the functions, +// +// func packString(string) interface{} +// func unpackString(interface{}) string +// +// We can run the following command: +// +// gen-atomicwrapper -name String -wrapped Value \ +// -type string -pack fromString -unpack tostring +// +// This wil generate approximately, +// +// type String struct{ v Value } +// +// func (s *String) Load() string { +// return unpackString(v.Load()) +// } +// +// func (s *String) Store(s string) { +// return s.v.Store(packString(s)) +// } +// +// The packing/unpacking logic allows the stored value to be different from +// the user-facing value. +// +// Without -pack and -unpack, the output will be cast to the target type, +// defaulting to the zero value. +package main + +import ( + "bytes" + "errors" + "flag" + "fmt" + "go/format" + "io" + "log" + "os" + "sort" + "strings" + "text/template" +) + +func main() { + log.SetFlags(0) + if err := run(os.Args[1:]); err != nil { + log.Fatalf("%+v", err) + } +} + +type stringList []string + +func (sl *stringList) String() string { + return strings.Join(*sl, ",") +} + +func (sl *stringList) Set(s string) error { + for _, i := range strings.Split(s, ",") { + *sl = append(*sl, strings.TrimSpace(i)) + } + return nil +} + +func run(args []string) error { + var opts struct { + Name string + Wrapped string + Type string + + Imports stringList + Pack, Unpack string + + CAS bool + Swap bool + JSON bool + + File string + } + + flag := flag.NewFlagSet("gen-atomicwrapper", flag.ContinueOnError) + + // Required flags + flag.StringVar(&opts.Name, "name", "", + "name of the generated type (e.g. Duration)") + flag.StringVar(&opts.Wrapped, "wrapped", "", + "name of the wrapped atomic (e.g. Int64)") + flag.StringVar(&opts.Type, "type", "", + "name of the type exposed by the atomic (e.g. time.Duration)") + + // Optional flags + flag.Var(&opts.Imports, "imports", + "comma separated list of imports to add") + flag.StringVar(&opts.Pack, "pack", "", + "function to transform values with before storage") + flag.StringVar(&opts.Unpack, "unpack", "", + "function to reverse packing on loading") + flag.StringVar(&opts.File, "file", "", + "output file path (default: stdout)") + + // Switches for individual methods. Underlying atomics must support + // these. + flag.BoolVar(&opts.CAS, "cas", false, + "generate a `CAS(old, new) bool` method; requires -pack") + flag.BoolVar(&opts.Swap, "swap", false, + "generate a `Swap(new) old` method; requires -pack and -unpack") + flag.BoolVar(&opts.JSON, "json", false, + "generate `MarshalJSON/UnmarshJSON` methods") + + if err := flag.Parse(args); err != nil { + return err + } + + if len(opts.Name) == 0 || len(opts.Wrapped) == 0 || len(opts.Type) == 0 { + return errors.New("flags -name, -wrapped, and -type are required") + } + + if (len(opts.Pack) == 0) != (len(opts.Unpack) == 0) { + return errors.New("either both, or neither of -pack and -unpack must be specified") + } + + if opts.CAS && len(opts.Pack) == 0 { + return errors.New("flag -cas requires -pack") + } + + if opts.Swap && len(opts.Pack) == 0 { + return errors.New("flag -swap requires -pack and -unpack") + } + + var w io.Writer = os.Stdout + if file := opts.File; len(file) > 0 { + f, err := os.Create(file) + if err != nil { + return fmt.Errorf("create %q: %v", file, err) + } + defer f.Close() + + w = f + } + + // Import encoding/json if needed. + if opts.JSON { + found := false + for _, imp := range opts.Imports { + if imp == "encoding/json" { + found = true + break + } + } + + if !found { + opts.Imports = append(opts.Imports, "encoding/json") + } + } + + sort.Strings([]string(opts.Imports)) + + var buff bytes.Buffer + if err := _tmpl.Execute(&buff, opts); err != nil { + return fmt.Errorf("render template: %v", err) + } + + bs, err := format.Source(buff.Bytes()) + if err != nil { + return fmt.Errorf("reformat source: %v", err) + } + + _, err = w.Write(bs) + return err +} + +var _tmpl = template.Must(template.New("int.go").Parse(`// @generated Code generated by gen-atomicwrapper. + +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +{{ with .Imports }} +import ( + {{ range . -}} + {{ printf "%q" . }} + {{ end }} +) +{{ end }} + +// {{ .Name }} is an atomic type-safe wrapper for {{ .Type }} values. +type {{ .Name }} struct{ + _ nocmp // disallow non-atomic comparison + + v {{ .Wrapped }} +} + +var _zero{{ .Name }} {{ .Type }} + + +// New{{ .Name }} creates a new {{ .Name }}. +func New{{ .Name}}(v {{ .Type }}) *{{ .Name }} { + x := &{{ .Name }}{} + if v != _zero{{ .Name }} { + x.Store(v) + } + return x +} + +// Load atomically loads the wrapped {{ .Type }}. +func (x *{{ .Name }}) Load() {{ .Type }} { + {{ if .Unpack -}} + return {{ .Unpack }}(x.v.Load()) + {{- else -}} + if v := x.v.Load(); v != nil { + return v.({{ .Type }}) + } + return _zero{{ .Name }} + {{- end }} +} + +// Store atomically stores the passed {{ .Type }}. +func (x *{{ .Name }}) Store(v {{ .Type }}) { + {{ if .Pack -}} + x.v.Store({{ .Pack }}(v)) + {{- else -}} + x.v.Store(v) + {{- end }} +} + +{{ if .CAS -}} + // CAS is an atomic compare-and-swap for {{ .Type }} values. + func (x *{{ .Name }}) CAS(o, n {{ .Type }}) bool { + return x.v.CAS({{ .Pack }}(o), {{ .Pack }}(n)) + } +{{- end }} + +{{ if .Swap -}} + // Swap atomically stores the given {{ .Type }} and returns the old + // value. + func (x *{{ .Name }}) Swap(o {{ .Type }}) {{ .Type }} { + return {{ .Unpack }}(x.v.Swap({{ .Pack }}(o))) + } +{{- end }} + +{{ if .JSON -}} + // MarshalJSON encodes the wrapped {{ .Type }} into JSON. + func (x *{{ .Name }}) MarshalJSON() ([]byte, error) { + return json.Marshal(x.Load()) + } + + // UnmarshalJSON decodes a {{ .Type }} from JSON. + func (x *{{ .Name }}) UnmarshalJSON(b []byte) error { + var v {{ .Type }} + if err := json.Unmarshal(b, &v); err != nil { + return err + } + x.Store(v) + return nil + } +{{- end }} + +`)) diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/nocmp.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/nocmp.go new file mode 100644 index 0000000..a8201cb --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/nocmp.go @@ -0,0 +1,35 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +// nocmp is an uncomparable struct. Embed this inside another struct to make +// it uncomparable. +// +// type Foo struct { +// nocmp +// // ... +// } +// +// This DOES NOT: +// +// - Disallow shallow copies of structs +// - Disallow comparison of pointers to uncomparable structs +type nocmp [0]func() diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/nocmp_test.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/nocmp_test.go new file mode 100644 index 0000000..d4be166 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/nocmp_test.go @@ -0,0 +1,165 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "bytes" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "reflect" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNocmpComparability(t *testing.T) { + tests := []struct { + desc string + give interface{} + comparable bool + }{ + { + desc: "nocmp struct", + give: nocmp{}, + }, + { + desc: "struct with nocmp embedded", + give: struct{ nocmp }{}, + }, + { + desc: "pointer to struct with nocmp embedded", + give: &struct{ nocmp }{}, + comparable: true, + }, + + // All exported types must be uncomparable. + {desc: "Bool", give: Bool{}}, + {desc: "Duration", give: Duration{}}, + {desc: "Error", give: Error{}}, + {desc: "Float64", give: Float64{}}, + {desc: "Int32", give: Int32{}}, + {desc: "Int64", give: Int64{}}, + {desc: "String", give: String{}}, + {desc: "Uint32", give: Uint32{}}, + {desc: "Uint64", give: Uint64{}}, + {desc: "Value", give: Value{}}, + } + + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + typ := reflect.TypeOf(tt.give) + assert.Equalf(t, tt.comparable, typ.Comparable(), + "type %v comparablity mismatch", typ) + }) + } +} + +// nocmp must not add to the size of a struct in-memory. +func TestNocmpSize(t *testing.T) { + type x struct{ _ int } + + before := reflect.TypeOf(x{}).Size() + + type y struct { + _ nocmp + _ x + } + + after := reflect.TypeOf(y{}).Size() + + assert.Equal(t, before, after, + "expected nocmp to have no effect on struct size") +} + +// This test will fail to compile if we disallow copying of nocmp. +// +// We need to allow this so that users can do, +// +// var x atomic.Int32 +// x = atomic.NewInt32(1) +func TestNocmpCopy(t *testing.T) { + type foo struct{ _ nocmp } + + t.Run("struct copy", func(t *testing.T) { + a := foo{} + b := a + _ = b // unused + }) + + t.Run("pointer copy", func(t *testing.T) { + a := &foo{} + b := *a + _ = b // unused + }) +} + +const _badFile = `package atomic + +import "fmt" + +type Int64 struct { + nocmp + + v int64 +} + +func shouldNotCompile() { + var x, y Int64 + fmt.Println(x == y) +} +` + +func TestNocmpIntegration(t *testing.T) { + tempdir, err := ioutil.TempDir("", "nocmp") + require.NoError(t, err, "unable to set up temporary directory") + defer os.RemoveAll(tempdir) + + src := filepath.Join(tempdir, "src") + require.NoError(t, os.Mkdir(src, 0755), "unable to make source directory") + + nocmp, err := ioutil.ReadFile("nocmp.go") + require.NoError(t, err, "unable to read nocmp.go") + + require.NoError(t, + ioutil.WriteFile(filepath.Join(src, "nocmp.go"), nocmp, 0644), + "unable to write nocmp.go") + + require.NoError(t, + ioutil.WriteFile(filepath.Join(src, "bad.go"), []byte(_badFile), 0644), + "unable to write bad.go") + + var stderr bytes.Buffer + cmd := exec.Command("go", "build") + cmd.Dir = src + // Forget OS build enviroment and set up a minimal one for "go build" + // to run. + cmd.Env = []string{ + "GOCACHE=" + filepath.Join(tempdir, "gocache"), + } + cmd.Stderr = &stderr + require.Error(t, cmd.Run(), "bad.go must not compile") + + assert.Contains(t, stderr.String(), + "struct containing nocmp cannot be compared") +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/stress_test.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/stress_test.go new file mode 100644 index 0000000..da9969b --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/stress_test.go @@ -0,0 +1,274 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "errors" + "math" + "runtime" + "sync" + "sync/atomic" + "testing" +) + +const ( + _parallelism = 4 + _iterations = 1000 +) + +var _stressTests = map[string]func() func(){ + "i32/std": stressStdInt32, + "i32": stressInt32, + "i64/std": stressStdInt64, + "i64": stressInt64, + "u32/std": stressStdUint32, + "u32": stressUint32, + "u64/std": stressStdUint64, + "u64": stressUint64, + "f64": stressFloat64, + "bool": stressBool, + "string": stressString, + "duration": stressDuration, + "error": stressError, +} + +func TestStress(t *testing.T) { + for name, ff := range _stressTests { + t.Run(name, func(t *testing.T) { + defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(_parallelism)) + + start := make(chan struct{}) + var wg sync.WaitGroup + wg.Add(_parallelism) + f := ff() + for i := 0; i < _parallelism; i++ { + go func() { + defer wg.Done() + <-start + for j := 0; j < _iterations; j++ { + f() + } + }() + } + close(start) + wg.Wait() + }) + } +} + +func BenchmarkStress(b *testing.B) { + for name, ff := range _stressTests { + b.Run(name, func(b *testing.B) { + f := ff() + + b.Run("serial", func(b *testing.B) { + for i := 0; i < b.N; i++ { + f() + } + }) + + b.Run("parallel", func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + f() + } + }) + }) + }) + } +} + +func stressStdInt32() func() { + var atom int32 + return func() { + atomic.LoadInt32(&atom) + atomic.AddInt32(&atom, 1) + atomic.AddInt32(&atom, -2) + atomic.AddInt32(&atom, 1) + atomic.AddInt32(&atom, -1) + atomic.CompareAndSwapInt32(&atom, 1, 0) + atomic.SwapInt32(&atom, 5) + atomic.StoreInt32(&atom, 1) + } +} + +func stressInt32() func() { + var atom Int32 + return func() { + atom.Load() + atom.Add(1) + atom.Sub(2) + atom.Inc() + atom.Dec() + atom.CAS(1, 0) + atom.Swap(5) + atom.Store(1) + } +} + +func stressStdInt64() func() { + var atom int64 + return func() { + atomic.LoadInt64(&atom) + atomic.AddInt64(&atom, 1) + atomic.AddInt64(&atom, -2) + atomic.AddInt64(&atom, 1) + atomic.AddInt64(&atom, -1) + atomic.CompareAndSwapInt64(&atom, 1, 0) + atomic.SwapInt64(&atom, 5) + atomic.StoreInt64(&atom, 1) + } +} + +func stressInt64() func() { + var atom Int64 + return func() { + atom.Load() + atom.Add(1) + atom.Sub(2) + atom.Inc() + atom.Dec() + atom.CAS(1, 0) + atom.Swap(5) + atom.Store(1) + } +} + +func stressStdUint32() func() { + var atom uint32 + return func() { + atomic.LoadUint32(&atom) + atomic.AddUint32(&atom, 1) + // Adding `MaxUint32` is the same as subtracting 1 + atomic.AddUint32(&atom, math.MaxUint32-1) + atomic.AddUint32(&atom, 1) + atomic.AddUint32(&atom, math.MaxUint32) + atomic.CompareAndSwapUint32(&atom, 1, 0) + atomic.SwapUint32(&atom, 5) + atomic.StoreUint32(&atom, 1) + } +} + +func stressUint32() func() { + var atom Uint32 + return func() { + atom.Load() + atom.Add(1) + atom.Sub(2) + atom.Inc() + atom.Dec() + atom.CAS(1, 0) + atom.Swap(5) + atom.Store(1) + } +} + +func stressStdUint64() func() { + var atom uint64 + return func() { + atomic.LoadUint64(&atom) + atomic.AddUint64(&atom, 1) + // Adding `MaxUint64` is the same as subtracting 1 + atomic.AddUint64(&atom, math.MaxUint64-1) + atomic.AddUint64(&atom, 1) + atomic.AddUint64(&atom, math.MaxUint64) + atomic.CompareAndSwapUint64(&atom, 1, 0) + atomic.SwapUint64(&atom, 5) + atomic.StoreUint64(&atom, 1) + } +} + +func stressUint64() func() { + var atom Uint64 + return func() { + atom.Load() + atom.Add(1) + atom.Sub(2) + atom.Inc() + atom.Dec() + atom.CAS(1, 0) + atom.Swap(5) + atom.Store(1) + } +} + +func stressFloat64() func() { + var atom Float64 + return func() { + atom.Load() + atom.CAS(1.0, 0.1) + atom.Add(1.1) + atom.Sub(0.2) + atom.Store(1.0) + } +} + +func stressBool() func() { + var atom Bool + return func() { + atom.Load() + atom.Store(false) + atom.Swap(true) + atom.CAS(true, false) + atom.CAS(true, false) + atom.Load() + atom.Toggle() + atom.Toggle() + } +} + +func stressString() func() { + var atom String + return func() { + atom.Load() + atom.Store("abc") + atom.Load() + atom.Store("def") + atom.Load() + atom.Store("") + } +} + +func stressDuration() func() { + var atom = NewDuration(0) + return func() { + atom.Load() + atom.Add(1) + atom.Sub(2) + atom.CAS(1, 0) + atom.Swap(5) + atom.Store(1) + } +} + +func stressError() func() { + var atom = NewError(nil) + var err1 = errors.New("err1") + var err2 = errors.New("err2") + return func() { + atom.Load() + atom.Store(err1) + atom.Load() + atom.Store(err2) + atom.Load() + atom.Store(nil) + } +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/string.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/string.go new file mode 100644 index 0000000..225b7a2 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/string.go @@ -0,0 +1,54 @@ +// @generated Code generated by gen-atomicwrapper. + +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +// String is an atomic type-safe wrapper for string values. +type String struct { + _ nocmp // disallow non-atomic comparison + + v Value +} + +var _zeroString string + +// NewString creates a new String. +func NewString(v string) *String { + x := &String{} + if v != _zeroString { + x.Store(v) + } + return x +} + +// Load atomically loads the wrapped string. +func (x *String) Load() string { + if v := x.v.Load(); v != nil { + return v.(string) + } + return _zeroString +} + +// Store atomically stores the passed string. +func (x *String) Store(v string) { + x.v.Store(v) +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/string_ext.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/string_ext.go new file mode 100644 index 0000000..3a95582 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/string_ext.go @@ -0,0 +1,43 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +//go:generate bin/gen-atomicwrapper -name=String -type=string -wrapped=Value -file=string.go + +// String returns the wrapped value. +func (s *String) String() string { + return s.Load() +} + +// MarshalText encodes the wrapped string into a textual form. +// +// This makes it encodable as JSON, YAML, XML, and more. +func (s *String) MarshalText() ([]byte, error) { + return []byte(s.Load()), nil +} + +// UnmarshalText decodes text and replaces the wrapped string with it. +// +// This makes it decodable from JSON, YAML, XML, and more. +func (s *String) UnmarshalText(b []byte) error { + s.Store(string(b)) + return nil +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/string_test.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/string_test.go new file mode 100644 index 0000000..a730f5f --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/string_test.go @@ -0,0 +1,85 @@ +// Copyright (c) 2016-2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "encoding/json" + "encoding/xml" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestStringNoInitialValue(t *testing.T) { + atom := &String{} + require.Equal(t, "", atom.Load(), "Initial value should be blank string") +} + +func TestString(t *testing.T) { + atom := NewString("") + require.Equal(t, "", atom.Load(), "Expected Load to return initialized value") + + atom.Store("abc") + require.Equal(t, "abc", atom.Load(), "Unexpected value after Store") + + atom = NewString("bcd") + require.Equal(t, "bcd", atom.Load(), "Expected Load to return initialized value") + + t.Run("JSON/Marshal", func(t *testing.T) { + bytes, err := json.Marshal(atom) + require.NoError(t, err, "json.Marshal errored unexpectedly.") + require.Equal(t, []byte(`"bcd"`), bytes, "json.Marshal encoded the wrong bytes.") + }) + + t.Run("JSON/Unmarshal", func(t *testing.T) { + err := json.Unmarshal([]byte(`"abc"`), &atom) + require.NoError(t, err, "json.Unmarshal errored unexpectedly.") + require.Equal(t, "abc", atom.Load(), "json.Unmarshal didn't set the correct value.") + }) + + t.Run("JSON/Unmarshal/Error", func(t *testing.T) { + err := json.Unmarshal([]byte("42"), &atom) + require.Error(t, err, "json.Unmarshal didn't error as expected.") + assertErrorJSONUnmarshalType(t, err, + "json.Unmarshal failed with unexpected error %v, want UnmarshalTypeError.", err) + }) + + atom = NewString("foo") + + t.Run("XML/Marshal", func(t *testing.T) { + bytes, err := xml.Marshal(atom) + require.NoError(t, err, "xml.Marshal errored unexpectedly.") + require.Equal(t, []byte("<String>foo</String>"), bytes, "xml.Marshal encoded the wrong bytes.") + }) + + t.Run("XML/Unmarshal", func(t *testing.T) { + err := xml.Unmarshal([]byte("<String>bar</String>"), &atom) + require.NoError(t, err, "xml.Unmarshal errored unexpectedly.") + require.Equal(t, "bar", atom.Load(), "xml.Unmarshal didn't set the correct value.") + }) + + t.Run("String", func(t *testing.T) { + atom := NewString("foo") + assert.Equal(t, "foo", atom.String(), + "String() returned an unexpected value.") + }) +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/uint32.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/uint32.go new file mode 100644 index 0000000..a973aba --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/uint32.go @@ -0,0 +1,102 @@ +// @generated Code generated by gen-atomicint. + +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "encoding/json" + "strconv" + "sync/atomic" +) + +// Uint32 is an atomic wrapper around uint32. +type Uint32 struct { + _ nocmp // disallow non-atomic comparison + + v uint32 +} + +// NewUint32 creates a new Uint32. +func NewUint32(i uint32) *Uint32 { + return &Uint32{v: i} +} + +// Load atomically loads the wrapped value. +func (i *Uint32) Load() uint32 { + return atomic.LoadUint32(&i.v) +} + +// Add atomically adds to the wrapped uint32 and returns the new value. +func (i *Uint32) Add(n uint32) uint32 { + return atomic.AddUint32(&i.v, n) +} + +// Sub atomically subtracts from the wrapped uint32 and returns the new value. +func (i *Uint32) Sub(n uint32) uint32 { + return atomic.AddUint32(&i.v, ^(n - 1)) +} + +// Inc atomically increments the wrapped uint32 and returns the new value. +func (i *Uint32) Inc() uint32 { + return i.Add(1) +} + +// Dec atomically decrements the wrapped uint32 and returns the new value. +func (i *Uint32) Dec() uint32 { + return i.Sub(1) +} + +// CAS is an atomic compare-and-swap. +func (i *Uint32) CAS(old, new uint32) bool { + return atomic.CompareAndSwapUint32(&i.v, old, new) +} + +// Store atomically stores the passed value. +func (i *Uint32) Store(n uint32) { + atomic.StoreUint32(&i.v, n) +} + +// Swap atomically swaps the wrapped uint32 and returns the old value. +func (i *Uint32) Swap(n uint32) uint32 { + return atomic.SwapUint32(&i.v, n) +} + +// MarshalJSON encodes the wrapped uint32 into JSON. +func (i *Uint32) MarshalJSON() ([]byte, error) { + return json.Marshal(i.Load()) +} + +// UnmarshalJSON decodes JSON into the wrapped uint32. +func (i *Uint32) UnmarshalJSON(b []byte) error { + var v uint32 + if err := json.Unmarshal(b, &v); err != nil { + return err + } + i.Store(v) + return nil +} + +// String encodes the wrapped value as a string. +func (i *Uint32) String() string { + v := i.Load() + return strconv.FormatUint(uint64(v), 10) +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/uint32_test.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/uint32_test.go new file mode 100644 index 0000000..d251730 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/uint32_test.go @@ -0,0 +1,76 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "encoding/json" + "math" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestUint32(t *testing.T) { + atom := NewUint32(42) + + require.Equal(t, uint32(42), atom.Load(), "Load didn't work.") + require.Equal(t, uint32(46), atom.Add(4), "Add didn't work.") + require.Equal(t, uint32(44), atom.Sub(2), "Sub didn't work.") + require.Equal(t, uint32(45), atom.Inc(), "Inc didn't work.") + require.Equal(t, uint32(44), atom.Dec(), "Dec didn't work.") + + require.True(t, atom.CAS(44, 0), "CAS didn't report a swap.") + require.Equal(t, uint32(0), atom.Load(), "CAS didn't set the correct value.") + + require.Equal(t, uint32(0), atom.Swap(1), "Swap didn't return the old value.") + require.Equal(t, uint32(1), atom.Load(), "Swap didn't set the correct value.") + + atom.Store(42) + require.Equal(t, uint32(42), atom.Load(), "Store didn't set the correct value.") + + t.Run("JSON/Marshal", func(t *testing.T) { + bytes, err := json.Marshal(atom) + require.NoError(t, err, "json.Marshal errored unexpectedly.") + require.Equal(t, []byte("42"), bytes, "json.Marshal encoded the wrong bytes.") + }) + + t.Run("JSON/Unmarshal", func(t *testing.T) { + err := json.Unmarshal([]byte("40"), &atom) + require.NoError(t, err, "json.Unmarshal errored unexpectedly.") + require.Equal(t, uint32(40), atom.Load(), "json.Unmarshal didn't set the correct value.") + }) + + t.Run("JSON/Unmarshal/Error", func(t *testing.T) { + err := json.Unmarshal([]byte(`"40"`), &atom) + require.Error(t, err, "json.Unmarshal didn't error as expected.") + assertErrorJSONUnmarshalType(t, err, + "json.Unmarshal failed with unexpected error %v, want UnmarshalTypeError.", err) + }) + + t.Run("String", func(t *testing.T) { + // Use an integer with the signed bit set. If we're converting + // incorrectly, we'll get a negative value here. + atom := NewUint32(math.MaxUint32) + assert.Equal(t, "4294967295", atom.String(), + "String() returned an unexpected value.") + }) +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/uint64.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/uint64.go new file mode 100644 index 0000000..3b6c71f --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/uint64.go @@ -0,0 +1,102 @@ +// @generated Code generated by gen-atomicint. + +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "encoding/json" + "strconv" + "sync/atomic" +) + +// Uint64 is an atomic wrapper around uint64. +type Uint64 struct { + _ nocmp // disallow non-atomic comparison + + v uint64 +} + +// NewUint64 creates a new Uint64. +func NewUint64(i uint64) *Uint64 { + return &Uint64{v: i} +} + +// Load atomically loads the wrapped value. +func (i *Uint64) Load() uint64 { + return atomic.LoadUint64(&i.v) +} + +// Add atomically adds to the wrapped uint64 and returns the new value. +func (i *Uint64) Add(n uint64) uint64 { + return atomic.AddUint64(&i.v, n) +} + +// Sub atomically subtracts from the wrapped uint64 and returns the new value. +func (i *Uint64) Sub(n uint64) uint64 { + return atomic.AddUint64(&i.v, ^(n - 1)) +} + +// Inc atomically increments the wrapped uint64 and returns the new value. +func (i *Uint64) Inc() uint64 { + return i.Add(1) +} + +// Dec atomically decrements the wrapped uint64 and returns the new value. +func (i *Uint64) Dec() uint64 { + return i.Sub(1) +} + +// CAS is an atomic compare-and-swap. +func (i *Uint64) CAS(old, new uint64) bool { + return atomic.CompareAndSwapUint64(&i.v, old, new) +} + +// Store atomically stores the passed value. +func (i *Uint64) Store(n uint64) { + atomic.StoreUint64(&i.v, n) +} + +// Swap atomically swaps the wrapped uint64 and returns the old value. +func (i *Uint64) Swap(n uint64) uint64 { + return atomic.SwapUint64(&i.v, n) +} + +// MarshalJSON encodes the wrapped uint64 into JSON. +func (i *Uint64) MarshalJSON() ([]byte, error) { + return json.Marshal(i.Load()) +} + +// UnmarshalJSON decodes JSON into the wrapped uint64. +func (i *Uint64) UnmarshalJSON(b []byte) error { + var v uint64 + if err := json.Unmarshal(b, &v); err != nil { + return err + } + i.Store(v) + return nil +} + +// String encodes the wrapped value as a string. +func (i *Uint64) String() string { + v := i.Load() + return strconv.FormatUint(uint64(v), 10) +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/uint64_test.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/uint64_test.go new file mode 100644 index 0000000..9b8f399 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/uint64_test.go @@ -0,0 +1,76 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "encoding/json" + "math" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestUint64(t *testing.T) { + atom := NewUint64(42) + + require.Equal(t, uint64(42), atom.Load(), "Load didn't work.") + require.Equal(t, uint64(46), atom.Add(4), "Add didn't work.") + require.Equal(t, uint64(44), atom.Sub(2), "Sub didn't work.") + require.Equal(t, uint64(45), atom.Inc(), "Inc didn't work.") + require.Equal(t, uint64(44), atom.Dec(), "Dec didn't work.") + + require.True(t, atom.CAS(44, 0), "CAS didn't report a swap.") + require.Equal(t, uint64(0), atom.Load(), "CAS didn't set the correct value.") + + require.Equal(t, uint64(0), atom.Swap(1), "Swap didn't return the old value.") + require.Equal(t, uint64(1), atom.Load(), "Swap didn't set the correct value.") + + atom.Store(42) + require.Equal(t, uint64(42), atom.Load(), "Store didn't set the correct value.") + + t.Run("JSON/Marshal", func(t *testing.T) { + bytes, err := json.Marshal(atom) + require.NoError(t, err, "json.Marshal errored unexpectedly.") + require.Equal(t, []byte("42"), bytes, "json.Marshal encoded the wrong bytes.") + }) + + t.Run("JSON/Unmarshal", func(t *testing.T) { + err := json.Unmarshal([]byte("40"), &atom) + require.NoError(t, err, "json.Unmarshal errored unexpectedly.") + require.Equal(t, uint64(40), atom.Load(), "json.Unmarshal didn't set the correct value.") + }) + + t.Run("JSON/Unmarshal/Error", func(t *testing.T) { + err := json.Unmarshal([]byte(`"40"`), &atom) + require.Error(t, err, "json.Unmarshal didn't error as expected.") + assertErrorJSONUnmarshalType(t, err, + "json.Unmarshal failed with unexpected error %v, want UnmarshalTypeError.", err) + }) + + t.Run("String", func(t *testing.T) { + // Use an integer with the signed bit set. If we're converting + // incorrectly, we'll get a negative value here. + atom := NewUint64(math.MaxUint64) + assert.Equal(t, "18446744073709551615", atom.String(), + "String() returned an unexpected value.") + }) +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/value.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/value.go new file mode 100644 index 0000000..671f3a3 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/value.go @@ -0,0 +1,31 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import "sync/atomic" + +// Value shadows the type of the same name from sync/atomic +// https://godoc.org/sync/atomic#Value +type Value struct { + atomic.Value + + _ nocmp // disallow non-atomic comparison +} diff --git a/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/value_test.go b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/value_test.go new file mode 100644 index 0000000..bb9f301 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/atomic@v1.7.0/value_test.go @@ -0,0 +1,40 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package atomic + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestValue(t *testing.T) { + var v Value + assert.Nil(t, v.Load(), "initial Value is not nil") + + v.Store(42) + assert.Equal(t, 42, v.Load()) + + v.Store(84) + assert.Equal(t, 84, v.Load()) + + assert.Panics(t, func() { v.Store("foo") }) +} |