cmd/exchange_wrapper_standards: Fix race on t.Context in exchange wrapper tests

* Tests: Fix race on t.Context in exchange wrapper tests

* fixup! Tests: Fix race on t.Context in exchange wrapper tests
This commit is contained in:
Gareth Kirwan
2025-08-14 09:58:14 +07:00
committed by GitHub
parent 52aff643e7
commit b0fa9c9881

View File

@@ -178,6 +178,8 @@ var validWrapperParams = []reflect.Type{
latestRateRequest,
}
type testCtxKey string
func executeExchangeWrapperTests(ctx context.Context, t *testing.T, exch exchange.IBotExchange, assetParams []assetPair) {
t.Helper()
iExchange := reflect.TypeOf(&exch).Elem()
@@ -195,7 +197,7 @@ func executeExchangeWrapperTests(ctx context.Context, t *testing.T, exch exchang
if slices.ContainsFunc(validWrapperParams, func(t reflect.Type) bool {
return input.AssignableTo(t)
}) {
assetLen = len(assetParams) - 1
assetLen = len(assetParams)
break
}
}
@@ -207,24 +209,25 @@ func executeExchangeWrapperTests(ctx context.Context, t *testing.T, exch exchang
e = time.Now()
s = e.Add(-time.Minute * 3)
}
for y := 0; y <= assetLen; y++ {
inputs := make([]reflect.Value, method.Type().NumIn())
argGenerator := &MethodArgumentGenerator{
Exchange: exch,
AssetParams: assetParams[y],
MethodName: methodName,
Start: s,
End: e,
}
for z := range method.Type().NumIn() {
argGenerator.MethodInputType = method.Type().In(z)
generatedArg := generateMethodArg(ctx, t, argGenerator)
inputs[z] = *generatedArg
}
assetY := assetParams[y].Asset.String()
pairY := assetParams[y].Pair.String()
t.Run(methodName+"-"+assetY+"-"+pairY, func(t *testing.T) {
for y := range assetLen {
ap := assetParams[y]
t.Run(methodName+"-"+ap.Asset.String()+"-"+ap.Pair.String(), func(t *testing.T) {
t.Parallel()
// Create a new context for each test run to avoid race conditions
ctx := context.WithValue(ctx, testCtxKey("test"), t.Name()) //nolint:govet // Intentional shadow
inputs := make([]reflect.Value, method.Type().NumIn())
argGenerator := &MethodArgumentGenerator{
Exchange: exch,
AssetParams: ap,
MethodName: methodName,
Start: s,
End: e,
}
for z := range method.Type().NumIn() {
argGenerator.MethodInputType = method.Type().In(z)
generatedArg := generateMethodArg(ctx, t, argGenerator)
inputs[z] = *generatedArg
}
CallExchangeMethod(t, method, inputs, methodName, exch)
})
}
@@ -245,12 +248,16 @@ func CallExchangeMethod(t *testing.T, methodToCall reflect.Value, methodValues [
if isUnacceptableError(t, err) != nil {
literalInputs := make([]any, len(methodValues))
for j := range methodValues {
if methodValues[j].Kind() == reflect.Ptr {
switch {
case methodValues[j].Type().Implements(contextParam):
// Errorf will use reflection on ctx and cause a race, so we need to replace it
literalInputs[j] = "<context>"
case methodValues[j].Kind() == reflect.Ptr:
// dereference pointers just to add a bit more clarity
literalInputs[j] = methodValues[j].Elem().Interface()
continue
default:
literalInputs[j] = methodValues[j].Interface()
}
literalInputs[j] = methodValues[j].Interface()
}
t.Errorf("%v Func '%v' Error: '%v'. Inputs: %v.", exch.GetName(), methodName, err, literalInputs)
}
@@ -340,8 +347,7 @@ func generateMethodArg(ctx context.Context, t *testing.T, argGenerator *MethodAr
OneTimePassword: "test",
})
case argGenerator.MethodInputType.Implements(contextParam):
// Need to deploy a context.Context value as nil value is not
// checked throughout codebase.
// Need to deploy a context.Context value as nil value is not checked throughout codebase
input = reflect.ValueOf(ctx)
case argGenerator.MethodInputType.AssignableTo(feeBuilderParam):
input = reflect.ValueOf(&exchange.FeeBuilder{