diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..18f85a8 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @carpawell @cthulhu-rider @roman-khimov diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml new file mode 100644 index 0000000..022b4ef --- /dev/null +++ b/.github/workflows/go.yml @@ -0,0 +1,45 @@ +name: Tests + +on: + push: + branches: + - master + paths-ignore: + - '*.md' + pull_request: + branches: + - master + paths-ignore: + - '*.md' + +jobs: + test: + runs-on: ubuntu-22.04 + strategy: + matrix: + go: [ '1.19.x', '1.20.x', '1.21' ] + steps: + - name: Setup go + uses: actions/setup-go@v4 + with: + cache: true + go-version: ${{ matrix.go }} + + - name: Check out code + uses: actions/checkout@v3 + + - name: Run go test + run: go test -coverprofile=coverage.txt -covermode=atomic ./... + + lint: + runs-on: ubuntu-22.04 + steps: + - uses: actions/setup-go@v4 + with: + go-version: 1.19 + - uses: actions/checkout@v3 + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + version: latest + args: --timeout=5m diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..54a2261 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,56 @@ +# This file contains all available configuration options +# with their default values. + +# options for analysis running +run: + # timeout for analysis, e.g. 30s, 5m, default is 1m + timeout: 5m + + # include test files or not, default is true + tests: false + +# output configuration options +output: + # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" + format: tab + +# all available settings of specific linters +linters-settings: + exhaustive: + # indicates that switch statements are to be considered exhaustive if a + # 'default' case is present, even if all enum members aren't listed in the + # switch + default-signifies-exhaustive: true + govet: + # report about shadowed variables + check-shadowing: false + +linters: + enable: + # mandatory linters + - govet + - revive + + # some default golangci-lint linters + - errcheck + - gosimple + - godot + - ineffassign + - staticcheck + - typecheck + - unused + + # extra linters + - bidichk + - durationcheck + - exhaustive + - exportloopref + - gofmt + - goimports + - misspell + - predeclared + - reassign + - whitespace + disable-all: true + fast: false + diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index cf7f947..0000000 --- a/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: go -go: - - 1.11.x - - 1.12.x -env: - - GO111MODULE=on -install: - - go get -v golang.org/x/lint/golint - - go mod tidy -v -script: - - golint -set_exit_status ./... - - go test -race -coverprofile=coverage.txt -covermode=atomic ./... -after_success: - - bash <(curl -s https://codecov.io/bash) -matrix: - allow_failures: - - go: tip \ No newline at end of file diff --git a/README.md b/README.md index e141fe4..2590f89 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # Golang HRW implementation -[![Build Status](https://travis-ci.org/nspcc-dev/hrw.svg?branch=master)](https://travis-ci.org/nspcc-dev/hrw) [![codecov](https://codecov.io/gh/nspcc-dev/hrw/badge.svg)](https://codecov.io/gh/nspcc-dev/hrw) [![Report](https://goreportcard.com/badge/github.com/nspcc-dev/hrw)](https://goreportcard.com/report/github.com/nspcc-dev/hrw) [![GitHub release](https://img.shields.io/github/release/nspcc-dev/hrw.svg)](https://github.com/nspcc-dev/hrw) diff --git a/go.mod b/go.mod index fd8be23..efec6b6 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,14 @@ module github.com/nspcc-dev/hrw -go 1.14 +go 1.19 require ( - github.com/spaolacci/murmur3 v1.1.0 - github.com/stretchr/testify v1.3.0 + github.com/stretchr/testify v1.8.4 + github.com/twmb/murmur3 v1.1.8 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index d6c0f7c..5103686 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,12 @@ -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/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -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= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg= +github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/hrw.go b/hrw.go index 07087df..124353d 100644 --- a/hrw.go +++ b/hrw.go @@ -9,11 +9,11 @@ import ( "reflect" "sort" - "github.com/spaolacci/murmur3" + "github.com/twmb/murmur3" ) type ( - // Hasher interface used by SortSliceByValue + // Hasher interface used by SortSliceByValue. Hasher interface{ Hash() uint64 } sorter struct { @@ -23,7 +23,7 @@ type ( } ) -// Boundaries of valid normalized weights +// Boundaries of valid normalized weights. const ( NormalizedMaxWeight = 1.0 NormalizedMinWeight = 0.0 @@ -45,12 +45,12 @@ func distance(x uint64, y uint64) uint64 { return acc } -// Hash uses murmur3 hash to return uint64 +// Hash uses murmur3 hash to return uint64. func Hash(key []byte) uint64 { return murmur3.Sum64(key) } -// Sort receive nodes and hash, and sort it by distance +// Sort receive nodes and hash, and sort it by distance. func Sort(nodes []uint64, hash uint64) []uint64 { l := len(nodes) sorted := make([]uint64, l) @@ -66,7 +66,7 @@ func Sort(nodes []uint64, hash uint64) []uint64 { return sorted } -// SortByWeight receive nodes, weights and hash, and sort it by distance * weight +// SortByWeight receive nodes, weights and hash, and sort it by distance * weight. func SortByWeight(nodes []uint64, weights []float64, hash uint64) []uint64 { result := make([]uint64, len(nodes)) copy(nodes, result) @@ -74,7 +74,7 @@ func SortByWeight(nodes []uint64, weights []float64, hash uint64) []uint64 { return result } -// SortSliceByValue received []T and hash to sort by value-distance +// SortSliceByValue received []T and hash to sort by value-distance. func SortSliceByValue(slice interface{}, hash uint64) { rule := prepareRule(slice) if rule != nil { @@ -83,7 +83,7 @@ func SortSliceByValue(slice interface{}, hash uint64) { } } -// SortSliceByWeightValue received []T, weights and hash to sort by value-distance * weights +// SortSliceByWeightValue received []T, weights and hash to sort by value-distance * weights. func SortSliceByWeightValue(slice interface{}, weights []float64, hash uint64) { rule := prepareRule(slice) if rule != nil { @@ -92,14 +92,14 @@ func SortSliceByWeightValue(slice interface{}, weights []float64, hash uint64) { } } -// SortSliceByIndex received []T and hash to sort by index-distance +// SortSliceByIndex received []T and hash to sort by index-distance. func SortSliceByIndex(slice interface{}, hash uint64) { length := reflect.ValueOf(slice).Len() swap := reflect.Swapper(slice) sortByDistance(length, true, nil, hash, swap) } -// SortSliceByWeightIndex received []T, weights and hash to sort by index-distance * weights +// SortSliceByWeightIndex received []T, weights and hash to sort by index-distance * weights. func SortSliceByWeightIndex(slice interface{}, weights []float64, hash uint64) { length := reflect.ValueOf(slice).Len() swap := reflect.Swapper(slice) @@ -199,7 +199,7 @@ func prepareRule(slice interface{}) []uint64 { return rule } -// ValidateWeights checks if weights are normalized between 0.0 and 1.0 +// ValidateWeights checks if weights are normalized between 0.0 and 1.0. func ValidateWeights(weights []float64) error { for i := range weights { if math.IsNaN(weights[i]) || weights[i] > NormalizedMaxWeight || weights[i] < NormalizedMinWeight {