CI: Fix golangci-lint linter issues, add prealloc linter and bump version depends for Go 1.18 (#915)

* Bump CI versions

* Specifically set go version as 1.17.x bumps it to 1.18

* Another

* Adjust AppVeyor

* Part 1 of linter issues

* Part 2

* Fix various linters and improvements

* Part 3

* Finishing touches

* Tests and EqualFold

* Fix nitterinos plus bonus requester jobs bump for exchanges with large number of tests

* Fix nitterinos and bump golangci-lint timeout for AppVeyor

* Address nits, ensure all books are returned on err due to syncer regression

* Fix the wiggins

* Fix duplication

* Fix nitterinos
This commit is contained in:
Adrian Gallagher
2022-04-20 13:45:15 +10:00
committed by GitHub
parent c48e5ea90a
commit 9a4eb9de84
216 changed files with 3493 additions and 2424 deletions

View File

@@ -2,6 +2,8 @@ package cache
import (
"testing"
"github.com/thrasher-corp/gocryptotrader/common/convert"
)
func TestCache(t *testing.T) {
@@ -16,12 +18,11 @@ func TestCache(t *testing.T) {
if v == nil {
t.Fatal("expected cache to contain \"hello\" key")
}
if v.(string) != "world" {
if convert.InterfaceToStringOrZeroValue(v) != "world" {
t.Fatal("expected \"hello\" key to contain value \"world\"")
}
r := lruCache.Remove("hello")
if !r {
if r := lruCache.Remove("hello"); !r {
t.Fatal("expected \"hello\" key to be removed from cache")
}
@@ -77,39 +78,39 @@ func TestAdd(t *testing.T) {
if v == nil {
t.Fatal("expected cache to contain \"2\" key")
}
if v.(int) != 2 {
if convert.InterfaceToIntOrZeroValue(v) != 2 {
t.Fatal("expected \"2\" key to contain value \"2\"")
}
k, v := lruCache.getNewest()
if k.(int) != 2 {
if convert.InterfaceToIntOrZeroValue(k) != 2 {
t.Fatal("expected latest key to be 2")
}
if v.(int) != 2 {
if convert.InterfaceToIntOrZeroValue(v) != 2 {
t.Fatal("expected latest value to be 2")
}
lruCache.Add(3, 3)
k, _ = lruCache.getNewest()
if k.(int) != 3 {
if convert.InterfaceToIntOrZeroValue(k) != 3 {
t.Fatal("expected latest key to be 3")
}
k, _ = lruCache.getOldest()
if k.(int) != 2 {
if convert.InterfaceToIntOrZeroValue(k) != 2 {
t.Fatal("expected oldest key to be 2")
}
k, v = lruCache.getOldest()
if k.(int) != 2 {
if convert.InterfaceToIntOrZeroValue(k) != 2 {
t.Fatal("expected oldest key to be 2")
}
if v.(int) != 2 {
if convert.InterfaceToIntOrZeroValue(v) != 2 {
t.Fatal("expected latest value to be 2")
}
lruCache.Add(2, 2)
k, _ = lruCache.getNewest()
if k.(int) != 2 {
if convert.InterfaceToIntOrZeroValue(k) != 2 {
t.Fatal("expected latest key to be 2")
}
k, _ = lruCache.getOldest()
if k.(int) != 3 {
if convert.InterfaceToIntOrZeroValue(k) != 3 {
t.Fatal("expected oldest key to be 3")
}
}

20
common/cache/lru.go vendored
View File

@@ -24,7 +24,9 @@ func NewLRUCache(capacity uint64) *LRU {
func (l *LRU) Add(key, value interface{}) {
if f, o := l.items[key]; o {
l.l.MoveToFront(f)
f.Value.(*item).value = value
if v, ok := f.Value.(*item); ok {
v.value = value
}
return
}
@@ -40,7 +42,9 @@ func (l *LRU) Add(key, value interface{}) {
func (l *LRU) Get(key interface{}) interface{} {
if i, f := l.items[key]; f {
l.l.MoveToFront(i)
return i.Value.(*item).value
if v, ok := i.Value.(*item); ok {
return v.value
}
}
return nil
}
@@ -48,7 +52,9 @@ func (l *LRU) Get(key interface{}) interface{} {
// GetOldest returns the oldest entry
func (l *LRU) getOldest() (key, value interface{}) {
if x := l.l.Back(); x != nil {
return x.Value.(*item).key, x.Value.(*item).value
if v, ok := x.Value.(*item); ok {
return v.key, v.value
}
}
return
}
@@ -56,7 +62,9 @@ func (l *LRU) getOldest() (key, value interface{}) {
// GetNewest returns the newest entry
func (l *LRU) getNewest() (key, value interface{}) {
if x := l.l.Front(); x != nil {
return x.Value.(*item).key, x.Value.(*item).value
if v, ok := x.Value.(*item); ok {
return v.key, v.value
}
}
return
}
@@ -99,5 +107,7 @@ func (l *LRU) removeOldestEntry() {
// removeElement element from the cache
func (l *LRU) removeElement(e *list.Element) {
l.l.Remove(e)
delete(l.items, e.Value.(*item).key)
if v, ok := e.Value.(*item); ok {
delete(l.items, v.key)
}
}

View File

@@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"os"
@@ -18,6 +17,7 @@ import (
"sync"
"time"
"github.com/thrasher-corp/gocryptotrader/common/file"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -257,7 +257,7 @@ func SendHTTPRequest(ctx context.Context, method, urlPath string, headers map[st
}
defer resp.Body.Close()
contents, err := ioutil.ReadAll(resp.Body)
contents, err := io.ReadAll(resp.Body)
if verbose {
log.Debugf(log.Global, "HTTP status: %s, Code: %v",
@@ -348,7 +348,7 @@ func CreateDir(dir string) error {
}
log.Warnf(log.Global, "Directory %s does not exist.. creating.\n", dir)
return os.MkdirAll(dir, 0770)
return os.MkdirAll(dir, file.DefaultPermissionOctal)
}
// ChangePermission lists all the directories and files in an array
@@ -357,8 +357,8 @@ func ChangePermission(directory string) error {
if err != nil {
return err
}
if info.Mode().Perm() != 0770 {
return os.Chmod(path, 0770)
if info.Mode().Perm() != file.DefaultPermissionOctal {
return os.Chmod(path, file.DefaultPermissionOctal)
}
return nil
})

View File

@@ -14,6 +14,8 @@ import (
"strings"
"testing"
"time"
"github.com/thrasher-corp/gocryptotrader/common/file"
)
func TestSendHTTPRequest(t *testing.T) {
@@ -509,7 +511,7 @@ func TestChangePermission(t *testing.T) {
if err == nil {
t.Fatal("expected an error on non-existent path")
}
err = os.Mkdir(testDir, 0777)
err = os.Mkdir(testDir, 0o777)
if err != nil {
t.Fatalf("Mkdir failed. Err: %v", err)
}
@@ -530,7 +532,7 @@ func TestChangePermission(t *testing.T) {
if err == nil {
t.Fatal("expected an error on non-existent path")
}
err = os.Mkdir(testDir, 0777)
err = os.Mkdir(testDir, 0o777)
if err != nil {
t.Fatalf("Mkdir failed. Err: %v", err)
}
@@ -543,8 +545,8 @@ func TestChangePermission(t *testing.T) {
if err != nil {
t.Fatalf("os.Stat failed. Err: %v", err)
}
if a.Mode().Perm() != 0770 {
t.Fatalf("expected file permissions differ. expecting 0770 got %#o", a.Mode().Perm())
if a.Mode().Perm() != file.DefaultPermissionOctal {
t.Fatalf("expected file permissions differ. expecting file.DefaultPermissionOctal got %#o", a.Mode().Perm())
}
err = os.Remove(testDir)
if err != nil {

View File

@@ -119,8 +119,7 @@ func DecimalToHumanFriendlyString(number decimal.Decimal, rounding int, decPoint
neg = true
}
str := number.String()
rnd := strings.Split(str, ".")
if len(rnd) == 1 {
if rnd := strings.Split(str, "."); len(rnd) == 1 {
rounding = 0
} else if len(rnd[1]) < rounding {
rounding = len(rnd[1])
@@ -164,3 +163,27 @@ func numberToHumanFriendlyString(str string, dec int, decPoint, thousandsSep str
return s
}
// InterfaceToFloat64OrZeroValue returns the type assertion value or variable zero value
func InterfaceToFloat64OrZeroValue(r interface{}) float64 {
if v, ok := r.(float64); ok {
return v
}
return 0
}
// InterfaceToIntOrZeroValue returns the type assertion value or variable zero value
func InterfaceToIntOrZeroValue(r interface{}) int {
if v, ok := r.(int); ok {
return v
}
return 0
}
// InterfaceToStringOrZeroValue returns the type assertion value or variable zero value
func InterfaceToStringOrZeroValue(r interface{}) string {
if v, ok := r.(string); ok {
return v
}
return ""
}

View File

@@ -282,3 +282,36 @@ func TestNumberToHumanFriendlyString(t *testing.T) {
t.Error("expected no comma")
}
}
func TestInterfaceToFloat64OrZeroValue(t *testing.T) {
var x interface{}
if r := InterfaceToFloat64OrZeroValue(x); r != 0 {
t.Errorf("expected 0, got: %v", r)
}
x = float64(420)
if r := InterfaceToFloat64OrZeroValue(x); r != 420 {
t.Errorf("expected 420, got: %v", x)
}
}
func TestInterfaceToIntOrZeroValue(t *testing.T) {
var x interface{}
if r := InterfaceToIntOrZeroValue(x); r != 0 {
t.Errorf("expected 0, got: %v", r)
}
x = int(420)
if r := InterfaceToIntOrZeroValue(x); r != 420 {
t.Errorf("expected 420, got: %v", x)
}
}
func TestInterfaceToStringOrZeroValue(t *testing.T) {
var x interface{}
if r := InterfaceToStringOrZeroValue(x); r != "" {
t.Errorf("expected empty string, got: %v", r)
}
x = string("meow")
if r := InterfaceToStringOrZeroValue(x); r != "meow" {
t.Errorf("expected meow, got: %v", x)
}
}

View File

@@ -148,7 +148,7 @@ func TestGetHMAC(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if string(sha1) != string(expectedSha1) {
if !bytes.Equal(sha1, expectedSha1) {
t.Errorf("Common GetHMAC error: Expected '%x'. Actual '%x'",
expectedSha1, sha1,
)
@@ -157,7 +157,7 @@ func TestGetHMAC(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if string(sha256) != string(expectedsha256) {
if !bytes.Equal(sha256, expectedsha256) {
t.Errorf("Common GetHMAC error: Expected '%x'. Actual '%x'",
expectedsha256, sha256,
)
@@ -166,7 +166,7 @@ func TestGetHMAC(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if string(sha512) != string(expectedsha512) {
if !bytes.Equal(sha512, expectedsha512) {
t.Errorf("Common GetHMAC error: Expected '%x'. Actual '%x'",
expectedsha512, sha512,
)
@@ -175,7 +175,7 @@ func TestGetHMAC(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if string(sha512384) != string(expectedsha512384) {
if !bytes.Equal(sha512384, expectedsha512384) {
t.Errorf("Common GetHMAC error: Expected '%x'. Actual '%x'",
expectedsha512384, sha512384,
)
@@ -184,7 +184,7 @@ func TestGetHMAC(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if string(md5) != string(expectedmd5) {
if !bytes.Equal(md5, expectedmd5) {
t.Errorf("Common GetHMAC error: Expected '%x'. Actual '%x'",
expectedmd5, md5,
)

View File

@@ -8,6 +8,7 @@ import (
"path/filepath"
"strings"
"github.com/thrasher-corp/gocryptotrader/common/file"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -52,7 +53,7 @@ func UnZip(src, dest string) (fileList []string, err error) {
continue
}
err = os.MkdirAll(filepath.Dir(fPath), 0770)
err = os.MkdirAll(filepath.Dir(fPath), file.DefaultPermissionOctal)
if err != nil {
return
}

View File

@@ -6,22 +6,25 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"io/fs"
"os"
"path/filepath"
)
// DefaultPermissionOctal is the default file and folder permission octal used throughout GCT
const DefaultPermissionOctal fs.FileMode = 0o770
// Write writes selected data to a file or returns an error if it fails. This
// func also ensures that all files are set to this permission (only rw access
// for the running user and the group the user is a member of)
func Write(file string, data []byte) error {
basePath := filepath.Dir(file)
if !Exists(basePath) {
if err := os.MkdirAll(basePath, 0770); err != nil {
if err := os.MkdirAll(basePath, DefaultPermissionOctal); err != nil {
return err
}
}
return ioutil.WriteFile(file, data, 0770)
return os.WriteFile(file, data, DefaultPermissionOctal)
}
// Writer creates a writer to a file or returns an error if it fails. This
@@ -30,11 +33,11 @@ func Write(file string, data []byte) error {
func Writer(file string) (*os.File, error) {
basePath := filepath.Dir(file)
if !Exists(basePath) {
if err := os.MkdirAll(basePath, 0770); err != nil {
if err := os.MkdirAll(basePath, DefaultPermissionOctal); err != nil {
return nil, err
}
}
return os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0770)
return os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, DefaultPermissionOctal)
}
// Move moves a file from a source path to a destination path
@@ -59,7 +62,7 @@ func Move(sourcePath, destPath string) error {
destDir := filepath.Dir(destPath)
if !Exists(destDir) {
err = os.MkdirAll(destDir, 0770)
err = os.MkdirAll(destDir, DefaultPermissionOctal)
if err != nil {
return err
}

View File

@@ -56,7 +56,7 @@ func TestWrite(t *testing.T) {
func TestMove(t *testing.T) {
tester := func(in, out string, write bool) error {
if write {
if err := ioutil.WriteFile(in, []byte("GoCryptoTrader"), 0770); err != nil {
if err := os.WriteFile(in, []byte("GoCryptoTrader"), DefaultPermissionOctal); err != nil {
return err
}
}
@@ -65,7 +65,7 @@ func TestMove(t *testing.T) {
return err
}
contents, err := ioutil.ReadFile(out)
contents, err := os.ReadFile(out)
if err != nil {
return err
}
@@ -124,7 +124,7 @@ func TestExists(t *testing.T) {
t.Error("non-existent file should not exist")
}
tmpFile := filepath.Join(os.TempDir(), "gct-test.txt")
if err := ioutil.WriteFile(tmpFile, []byte("hello world"), os.ModeAppend); err != nil {
if err := os.WriteFile(tmpFile, []byte("hello world"), os.ModeAppend); err != nil {
t.Fatal(err)
}
if e := Exists(tmpFile); !e {
@@ -258,7 +258,7 @@ func TestWriter(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if data, err := ioutil.ReadFile(got.Name()); err != nil || string(data) != testData {
if data, err := os.ReadFile(got.Name()); err != nil || string(data) != testData {
t.Errorf("Could not write the file, or contents were wrong: expected = %s, got =%s", testData, string(data))
}
})
@@ -274,7 +274,7 @@ func TestWriterNoPermissionFails(t *testing.T) {
t.Fatal(err)
}
defer os.RemoveAll(temp)
err = os.Chmod(temp, 0555)
err = os.Chmod(temp, 0o555)
if err != nil {
t.Fatal(err)
}

View File

@@ -89,9 +89,9 @@ func InformationRatio(returnsRates, benchmarkRates []float64, averageValues, ave
if len(benchmarkRates) != len(returnsRates) {
return 0, errInformationBadLength
}
var diffs []float64
diffs := make([]float64, len(returnsRates))
for i := range returnsRates {
diffs = append(diffs, returnsRates[i]-benchmarkRates[i])
diffs[i] = returnsRates[i] - benchmarkRates[i]
}
stdDev, err := PopulationStandardDeviation(diffs)
if err != nil {
@@ -135,11 +135,11 @@ func SampleStandardDeviation(values []float64) (float64, error) {
if err != nil {
return 0, err
}
var superMean []float64
superMean := make([]float64, len(values))
var combined float64
for i := range values {
result := math.Pow(values[i]-mean, 2)
superMean = append(superMean, result)
superMean[i] = result
combined += result
}
avg := combined / (float64(len(superMean)) - 1)
@@ -232,9 +232,9 @@ func SharpeRatio(movementPerCandle []float64, riskFreeRatePerInterval, average f
if totalIntervals == 0 {
return 0, errZeroValue
}
var excessReturns []float64
excessReturns := make([]float64, len(movementPerCandle))
for i := range movementPerCandle {
excessReturns = append(excessReturns, movementPerCandle[i]-riskFreeRatePerInterval)
excessReturns[i] = movementPerCandle[i] - riskFreeRatePerInterval
}
standardDeviation, err := PopulationStandardDeviation(excessReturns)
if err != nil {
@@ -284,9 +284,9 @@ func DecimalInformationRatio(returnsRates, benchmarkRates []decimal.Decimal, ave
if len(benchmarkRates) != len(returnsRates) {
return decimal.Zero, errInformationBadLength
}
var diffs []decimal.Decimal
diffs := make([]decimal.Decimal, len(returnsRates))
for i := range returnsRates {
diffs = append(diffs, returnsRates[i].Sub(benchmarkRates[i]))
diffs[i] = returnsRates[i].Sub(benchmarkRates[i])
}
stdDev, err := DecimalPopulationStandardDeviation(diffs)
if err != nil && !errors.Is(err, ErrInexactConversion) {
@@ -339,11 +339,11 @@ func DecimalSampleStandardDeviation(values []decimal.Decimal) (decimal.Decimal,
if err != nil {
return decimal.Zero, err
}
var superMean []decimal.Decimal
superMean := make([]decimal.Decimal, len(values))
var combined decimal.Decimal
for i := range values {
pow := values[i].Sub(mean).Pow(decimal.NewFromInt(2))
superMean = append(superMean, pow)
superMean[i] = pow
combined.Add(pow)
}
avg := combined.Div(decimal.NewFromInt(int64(len(superMean))).Sub(decimal.NewFromInt(1)))
@@ -380,9 +380,7 @@ func DecimalGeometricMean(values []decimal.Decimal) (decimal.Decimal, error) {
// DecimalPow is lovely because shopspring decimal cannot
// handle ^0.x and instead returns 1
func DecimalPow(x, y decimal.Decimal) decimal.Decimal {
fX, _ := x.Float64()
fY, _ := y.Float64()
pow := math.Pow(fX, fY)
pow := math.Pow(x.InexactFloat64(), y.InexactFloat64())
return decimal.NewFromFloat(pow)
}
@@ -405,7 +403,7 @@ func DecimalFinancialGeometricMean(values []decimal.Decimal) (decimal.Decimal, e
// as we cannot have negative or zero value geometric numbers
// adding a 1 to the percentage movements allows for differentiation between
// negative numbers (eg -0.1 translates to 0.9) and positive numbers (eg 0.1 becomes 1.1)
modVal, _ := values[i].Add(decimal.NewFromInt(1)).Float64()
modVal := values[i].Add(decimal.NewFromInt(1)).InexactFloat64()
product *= modVal
}
prod := 1 / float64(len(values))
@@ -461,9 +459,9 @@ func DecimalSharpeRatio(movementPerCandle []decimal.Decimal, riskFreeRatePerInte
if totalIntervals.IsZero() {
return decimal.Zero, errZeroValue
}
var excessReturns []decimal.Decimal
excessReturns := make([]decimal.Decimal, len(movementPerCandle))
for i := range movementPerCandle {
excessReturns = append(excessReturns, movementPerCandle[i].Sub(riskFreeRatePerInterval))
excessReturns[i] = movementPerCandle[i].Sub(riskFreeRatePerInterval)
}
standardDeviation, err := DecimalPopulationStandardDeviation(excessReturns)
if err != nil && !errors.Is(err, ErrInexactConversion) {

View File

@@ -184,9 +184,9 @@ func TestInformationRatio(t *testing.T) {
t.Error(avgComparison)
}
var eachDiff []float64
eachDiff := make([]float64, len(figures))
for i := range figures {
eachDiff = append(eachDiff, figures[i]-comparisonFigures[i])
eachDiff[i] = figures[i] - comparisonFigures[i]
}
stdDev, err := PopulationStandardDeviation(eachDiff)
if err != nil {
@@ -583,9 +583,9 @@ func TestDecimalInformationRatio(t *testing.T) {
t.Error(avgComparison)
}
var eachDiff []decimal.Decimal
eachDiff := make([]decimal.Decimal, len(figures))
for i := range figures {
eachDiff = append(eachDiff, figures[i].Sub(comparisonFigures[i]))
eachDiff[i] = figures[i].Sub(comparisonFigures[i])
}
stdDev, err := DecimalPopulationStandardDeviation(eachDiff)
if err != nil && !errors.Is(err, ErrInexactConversion) {
@@ -703,14 +703,13 @@ func TestDecimalStandardDeviation2(t *testing.T) {
if err != nil {
t.Error(err)
}
var superMean []decimal.Decimal
superMean := make([]decimal.Decimal, len(r))
for i := range r {
result := r[i].Sub(mean).Pow(decimal.NewFromInt(2))
superMean = append(superMean, result)
superMean[i] = result
}
superMeany := superMean[0].Add(superMean[1].Add(superMean[2].Add(superMean[3].Add(superMean[4].Add(superMean[5]))))).Div(decimal.NewFromInt(5))
fSuperMeany, _ := superMeany.Float64()
manualCalculation := decimal.NewFromFloat(math.Sqrt(fSuperMeany))
manualCalculation := decimal.NewFromFloat(math.Sqrt(superMeany.InexactFloat64()))
var codeCalcu decimal.Decimal
codeCalcu, err = DecimalSampleStandardDeviation(r)
if err != nil {