diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b6c6db1..10f1c4e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,6 +4,8 @@ on: branches: - main pull_request: +env: + go_version: 1.21.6 jobs: golangci-lint: name: golangci-lint @@ -11,6 +13,10 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + - name: Pin Golang version for linting + uses: actions/setup-go@v5 + with: + go-version: ${{ env.go_version }} - name: Run golangci-lint uses: golangci/golangci-lint-action@v3 with: @@ -24,7 +30,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: 1.21.6 + go-version: ${{ env.go_version }} - name: Set up gotestfmt uses: GoTestTools/gotestfmt-action@v2 - uses: actions/cache@v4 @@ -67,7 +73,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: 1.21.6 + go-version: ${{ env.go_version }} - uses: actions/cache@v4 with: path: | diff --git a/schema/bool_test.go b/schema/bool_test.go index bca40e0..8256e77 100644 --- a/schema/bool_test.go +++ b/schema/bool_test.go @@ -152,17 +152,22 @@ var boolTestSerializationCases = map[string]struct { func TestBoolSerializationCycle(t *testing.T) { for name, tc := range boolTestSerializationCases { + // When executed in parallel, referencing tc from the + // outer scope will not produce the proper value, so we need + // to bind it to a variable, localTC, scoped inside + // the loop body. + localTC := tc t.Run(name, func(t *testing.T) { var boolType schema.Bool = schema.NewBoolSchema() - output, err := boolType.Unserialize(tc.input) + output, err := boolType.Unserialize(localTC.input) if err != nil { - if tc.expectedError { + if localTC.expectedError { return } - t.Fatalf("Failed to unserialize %v: %v", tc.input, err) + t.Fatalf("Failed to unserialize %v: %v", localTC.input, err) } - if output != tc.output { - t.Fatalf("Unexpected unserialize output for %v: %v", tc.input, output) + if output != localTC.output { + t.Fatalf("Unexpected unserialize output for %v: %v", localTC.input, output) } if err := boolType.Validate(output); err != nil { diff --git a/schema/units_test.go b/schema/units_test.go index 51f3bd1..b05d7ab 100644 --- a/schema/units_test.go +++ b/schema/units_test.go @@ -35,17 +35,22 @@ func TestUnitsParseInt(t *testing.T) { } for testCase, testData := range testMatrix { + // When executed in parallel, referencing testData from the + // outer scope will not produce the proper value, so we need + // to bind it to a variable, localTestData, scoped inside + // the loop body. + localTestData := testData t.Run(testCase, func(t *testing.T) { - result, err := testData.units.ParseInt(testData.input) + result, err := localTestData.units.ParseInt(localTestData.input) if err != nil { t.Fatal(err) } - if result != testData.expected { - t.Fatalf("Result mismatch, expected: %d, got: %d", testData.expected, result) + if result != localTestData.expected { + t.Fatalf("Result mismatch, expected: %d, got: %d", localTestData.expected, result) } - formatted := testData.units.FormatShortInt(result) - if formatted != testData.input { - t.Fatalf("Formatted result doesn't match input, expected: %s, got: %s", testData.input, formatted) + formatted := localTestData.units.FormatShortInt(result) + if formatted != localTestData.input { + t.Fatalf("Formatted result doesn't match input, expected: %s, got: %s", localTestData.input, formatted) } }) } @@ -70,17 +75,22 @@ func TestUnitsParseFloat(t *testing.T) { } for testCase, testData := range testMatrix { + // When executed in parallel, referencing testData from the + // outer scope will not produce the proper value, so we need + // to bind it to a variable, localTestData, scoped inside + // the loop body. + localTestData := testData t.Run(testCase, func(t *testing.T) { - result, err := testData.units.ParseFloat(testData.input) + result, err := localTestData.units.ParseFloat(localTestData.input) if err != nil { t.Fatal(err) } - if result != testData.expected { - t.Fatalf("Result mismatch, expected: %f, got: %f", testData.expected, result) + if result != localTestData.expected { + t.Fatalf("Result mismatch, expected: %f, got: %f", localTestData.expected, result) } - formatted := testData.units.FormatShortFloat(result) - if formatted != testData.input { - t.Fatalf("Formatted result doesn't match input, expected: %s, got: %s", testData.input, formatted) + formatted := localTestData.units.FormatShortFloat(result) + if formatted != localTestData.input { + t.Fatalf("Formatted result doesn't match input, expected: %s, got: %s", localTestData.input, formatted) } }) } diff --git a/schema/util_test.go b/schema/util_test.go index b1dafae..1b47292 100644 --- a/schema/util_test.go +++ b/schema/util_test.go @@ -22,11 +22,16 @@ func performSerializationTest[T any]( ) { t.Helper() for name, tc := range testCases { + // When executed in parallel, referencing tc from the + // outer scope will not produce the proper value, so we need + // to bind it to a variable, localTC, scoped inside + // the loop body. + localTC := tc t.Run(name, func(t *testing.T) { t.Helper() - unserialized, err := typeUnderTest.UnserializeType(tc.SerializedValue) + unserialized, err := typeUnderTest.UnserializeType(localTC.SerializedValue) if err != nil { - if tc.ExpectError { + if localTC.ExpectError { return } t.Fatal(err) @@ -34,10 +39,10 @@ func performSerializationTest[T any]( if err := typeUnderTest.ValidateType(unserialized); err != nil { t.Fatal(err) } - if !compareUnserialized(unserialized, tc.ExpectUnserializedValue) { + if !compareUnserialized(unserialized, localTC.ExpectUnserializedValue) { t.Fatalf( "Unexpected unserialized value, expected: %v, got: %v", - tc.ExpectUnserializedValue, + localTC.ExpectUnserializedValue, unserialized, ) } @@ -45,11 +50,11 @@ func performSerializationTest[T any]( if err != nil { t.Fatal(err) } - if !compareSerialized(serialized, tc.ExpectedSerializedValue) { + if !compareSerialized(serialized, localTC.ExpectedSerializedValue) { t.Fatalf( "Serialized value mismatch, expected: %v (%T), got: %v (%T)", - tc.ExpectedSerializedValue, - tc.ExpectedSerializedValue, + localTC.ExpectedSerializedValue, + localTC.ExpectedSerializedValue, serialized, serialized, )