diff --git a/internal/datastore/crdb/crdb_test.go b/internal/datastore/crdb/crdb_test.go index 4bbefb8929..d90e91e25b 100644 --- a/internal/datastore/crdb/crdb_test.go +++ b/internal/datastore/crdb/crdb_test.go @@ -54,6 +54,7 @@ func (cds *crdbDatastore) ExampleRetryableError() error { } func TestCRDBDatastoreWithoutIntegrity(t *testing.T) { + t.Parallel() b := testdatastore.RunCRDBForTesting(t, "") test.All(t, test.DatastoreTesterFunc(func(revisionQuantization, gcInterval, gcWindow time.Duration, watchBufferLength uint16) (datastore.Datastore, error) { ctx := context.Background() @@ -72,10 +73,11 @@ func TestCRDBDatastoreWithoutIntegrity(t *testing.T) { }) return ds, nil - })) + }), false) } func TestCRDBDatastoreWithFollowerReads(t *testing.T) { + t.Parallel() followerReadDelay := time.Duration(4.8 * float64(time.Second)) gcWindow := 100 * time.Second @@ -136,6 +138,7 @@ var defaultKeyForTesting = proxy.KeyConfig{ } func TestCRDBDatastoreWithIntegrity(t *testing.T) { + t.Parallel() b := testdatastore.RunCRDBForTesting(t, "") test.All(t, test.DatastoreTesterFunc(func(revisionQuantization, gcInterval, gcWindow time.Duration, watchBufferLength uint16) (datastore.Datastore, error) { @@ -159,7 +162,7 @@ func TestCRDBDatastoreWithIntegrity(t *testing.T) { }) return ds, nil - })) + }), false) unwrappedTester := test.DatastoreTesterFunc(func(revisionQuantization, gcInterval, gcWindow time.Duration, watchBufferLength uint16) (datastore.Datastore, error) { ctx := context.Background() @@ -187,6 +190,7 @@ func TestCRDBDatastoreWithIntegrity(t *testing.T) { } func TestWatchFeatureDetection(t *testing.T) { + t.Parallel() pool, err := dockertest.NewPool("") require.NoError(t, err) cases := []struct { @@ -229,7 +233,9 @@ func TestWatchFeatureDetection(t *testing.T) { }, } for _, tt := range cases { + tt := tt t.Run(tt.name, func(t *testing.T) { + t.Parallel() ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) adminConn, connStrings := newCRDBWithUser(t, pool) diff --git a/internal/datastore/memdb/memdb_test.go b/internal/datastore/memdb/memdb_test.go index 238ecee9e6..43b14d0880 100644 --- a/internal/datastore/memdb/memdb_test.go +++ b/internal/datastore/memdb/memdb_test.go @@ -26,10 +26,12 @@ func (mdbt memDBTest) New(revisionQuantization, _, gcWindow time.Duration, watch } func TestMemdbDatastore(t *testing.T) { - test.All(t, memDBTest{}) + t.Parallel() + test.All(t, memDBTest{}, true) } func TestConcurrentWritePanic(t *testing.T) { + t.Parallel() require := require.New(t) ds, err := NewMemdbDatastore(0, 1*time.Hour, 1*time.Hour) @@ -81,6 +83,7 @@ func TestConcurrentWritePanic(t *testing.T) { } func TestConcurrentWriteRelsError(t *testing.T) { + t.Parallel() require := require.New(t) ds, err := NewMemdbDatastore(0, 1*time.Hour, 1*time.Hour) diff --git a/internal/datastore/mysql/datastore_test.go b/internal/datastore/mysql/datastore_test.go index c9eeeec066..671749f595 100644 --- a/internal/datastore/mysql/datastore_test.go +++ b/internal/datastore/mysql/datastore_test.go @@ -93,14 +93,16 @@ func createDatastoreTest(b testdatastore.RunningEngineForTest, tf datastoreTestF } func TestMySQLDatastoreDSNWithoutParseTime(t *testing.T) { + t.Parallel() _, err := NewMySQLDatastore(context.Background(), "root:password@(localhost:1234)/mysql") require.ErrorContains(t, err, "https://spicedb.dev/d/parse-time-mysql") } func TestMySQL8Datastore(t *testing.T) { + t.Parallel() b := testdatastore.RunMySQLForTestingWithOptions(t, testdatastore.MySQLTesterOptions{MigrateForNewDatastore: true}, "") dst := datastoreTester{b: b, t: t} - test.AllWithExceptions(t, test.DatastoreTesterFunc(dst.createDatastore), test.WithCategories(test.WatchSchemaCategory, test.WatchCheckpointsCategory)) + test.AllWithExceptions(t, test.DatastoreTesterFunc(dst.createDatastore), test.WithCategories(test.WatchSchemaCategory, test.WatchCheckpointsCategory), true) additionalMySQLTests(t, b) } @@ -660,6 +662,7 @@ func TransactionTimestampsTest(t *testing.T, ds datastore.Datastore) { } func TestMySQLMigrations(t *testing.T) { + t.Parallel() req := require.New(t) db := datastoreDB(t, false) @@ -681,6 +684,7 @@ func TestMySQLMigrations(t *testing.T) { } func TestMySQLMigrationsWithPrefix(t *testing.T) { + t.Parallel() req := require.New(t) prefix := "spicedb_" diff --git a/internal/datastore/mysql/migrations/driver.go b/internal/datastore/mysql/migrations/driver.go index e09bf828ba..cddcf6ccb2 100644 --- a/internal/datastore/mysql/migrations/driver.go +++ b/internal/datastore/mysql/migrations/driver.go @@ -16,7 +16,6 @@ import ( sq "github.com/Masterminds/squirrel" sqlDriver "github.com/go-sql-driver/mysql" - log "github.com/authzed/spicedb/internal/logging" "github.com/authzed/spicedb/pkg/migrate" ) @@ -57,10 +56,6 @@ func NewMySQLDriverFromDSN(url string, tablePrefix string, credentialsProvider d } db := sql.OpenDB(connector) - err = sqlDriver.SetLogger(&log.Logger) - if err != nil { - return nil, fmt.Errorf("unable to set logging to mysql driver: %w", err) - } return NewMySQLDriverFromDB(db, tablePrefix), nil } diff --git a/internal/datastore/postgres/postgres_shared_test.go b/internal/datastore/postgres/postgres_shared_test.go index 6bd77b8271..ee8df58b92 100644 --- a/internal/datastore/postgres/postgres_shared_test.go +++ b/internal/datastore/postgres/postgres_shared_test.go @@ -101,7 +101,7 @@ func testPostgresDatastore(t *testing.T, pc []postgresConfig) { return ds }) return ds, nil - })) + }), false) t.Run("TransactionTimestamps", createDatastoreTest( b, @@ -236,7 +236,7 @@ func testPostgresDatastoreWithoutCommitTimestamps(t *testing.T, pc []postgresCon return ds }) return ds, nil - }), test.WithCategories(test.WatchCategory)) + }), test.WithCategories(test.WatchCategory), false) }) } } diff --git a/internal/datastore/proxy/observable_test.go b/internal/datastore/proxy/observable_test.go index 9644c82cdd..63a388957c 100644 --- a/internal/datastore/proxy/observable_test.go +++ b/internal/datastore/proxy/observable_test.go @@ -20,7 +20,7 @@ func (obs observableTest) New(revisionQuantization, _, gcWindow time.Duration, w } func TestObservableProxy(t *testing.T) { - test.All(t, observableTest{}) + test.All(t, observableTest{}, true) } func (p *observableProxy) ExampleRetryableError() error { diff --git a/internal/datastore/proxy/schemacaching/estimatedsize_test.go b/internal/datastore/proxy/schemacaching/estimatedsize_test.go index 7848d1843f..275f544bf7 100644 --- a/internal/datastore/proxy/schemacaching/estimatedsize_test.go +++ b/internal/datastore/proxy/schemacaching/estimatedsize_test.go @@ -91,6 +91,8 @@ func TestEstimatedDefinitionSizes(t *testing.T) { for _, caveatDef := range fullyResolved.CaveatDefinitions { caveatDef := caveatDef t.Run("caveat "+caveatDef.Name, func(t *testing.T) { + t.Parallel() + serialized, _ := caveatDef.MarshalVT() sizevt := caveatDef.SizeVT() estimated := estimatedCaveatDefinitionSize(sizevt) diff --git a/internal/datastore/spanner/spanner_test.go b/internal/datastore/spanner/spanner_test.go index 1fbc6c49f2..35cb4a3926 100644 --- a/internal/datastore/spanner/spanner_test.go +++ b/internal/datastore/spanner/spanner_test.go @@ -28,6 +28,8 @@ func (sd *spannerDatastore) ExampleRetryableError() error { } func TestSpannerDatastore(t *testing.T) { + t.Parallel() + ctx := context.Background() b := testdatastore.RunSpannerForTesting(t, "", "head") @@ -43,7 +45,7 @@ func TestSpannerDatastore(t *testing.T) { return ds }) return ds, nil - }), test.WithCategories(test.GCCategory, test.WatchCategory, test.StatsCategory)) + }), test.WithCategories(test.GCCategory, test.WatchCategory, test.StatsCategory), true) t.Run("TestFakeStats", createDatastoreTest( b, diff --git a/internal/dispatch/graph/check_test.go b/internal/dispatch/graph/check_test.go index eab41591f7..80a7615879 100644 --- a/internal/dispatch/graph/check_test.go +++ b/internal/dispatch/graph/check_test.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/stretchr/testify/require" - "go.uber.org/goleak" "github.com/authzed/spicedb/internal/datastore/common" "github.com/authzed/spicedb/internal/datastore/memdb" @@ -30,7 +29,7 @@ import ( var ONR = tuple.ObjectAndRelation func TestSimpleCheck(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) + t.Parallel() type expected struct { relation string @@ -119,6 +118,7 @@ func TestSimpleCheck(t *testing.T) { userset := userset expected := expected t.Run(name, func(t *testing.T) { + t.Parallel() require := require.New(t) ctx, dispatch, revision := newLocalDispatcher(t) @@ -150,6 +150,7 @@ func TestSimpleCheck(t *testing.T) { } func TestMaxDepth(t *testing.T) { + t.Parallel() require := require.New(t) rawDS, err := memdb.NewMemdbDatastore(0, 0, memdb.DisableGC) @@ -182,6 +183,7 @@ func TestMaxDepth(t *testing.T) { } func TestCheckMetadata(t *testing.T) { + t.Parallel() type expected struct { relation string isMember bool @@ -287,6 +289,7 @@ func TestCheckMetadata(t *testing.T) { } func TestCheckPermissionOverSchema(t *testing.T) { + t.Parallel() testCases := []struct { name string schema string @@ -1370,6 +1373,7 @@ func addFrame(trace *v1.CheckDebugTrace, foundFrames *mapz.Set[string]) { } func TestCheckDebugging(t *testing.T) { + t.Parallel() type expectedFrame struct { resourceType *core.RelationReference resourceIDs []string @@ -1482,6 +1486,7 @@ func TestCheckDebugging(t *testing.T) { } func TestCheckWithHints(t *testing.T) { + t.Parallel() testCases := []struct { name string schema string @@ -1853,6 +1858,7 @@ func TestCheckWithHints(t *testing.T) { } func TestCheckHintsPartialApplication(t *testing.T) { + t.Parallel() require := require.New(t) dispatcher := NewLocalOnlyDispatcher(10, 100) @@ -1898,6 +1904,7 @@ func TestCheckHintsPartialApplication(t *testing.T) { } func TestCheckHintsPartialApplicationOverArrow(t *testing.T) { + t.Parallel() require := require.New(t) dispatcher := NewLocalOnlyDispatcher(10, 100) diff --git a/internal/dispatch/graph/dispatch_test.go b/internal/dispatch/graph/dispatch_test.go index 5d428e7662..48ab615e63 100644 --- a/internal/dispatch/graph/dispatch_test.go +++ b/internal/dispatch/graph/dispatch_test.go @@ -15,6 +15,7 @@ import ( ) func TestDispatchChunking(t *testing.T) { + t.Parallel() schema := ` definition user { relation self: user @@ -35,6 +36,7 @@ func TestDispatchChunking(t *testing.T) { ctx, dispatcher, revision := newLocalDispatcherWithSchemaAndRels(t, schema, append(enabled, resources...)) t.Run("check", func(t *testing.T) { + t.Parallel() for _, tpl := range resources[:1] { checkResult, err := dispatcher.DispatchCheck(ctx, &v1.DispatchCheckRequest{ ResourceRelation: RR(tpl.ResourceAndRelation.Namespace, "view"), @@ -55,6 +57,8 @@ func TestDispatchChunking(t *testing.T) { }) t.Run("lookup-resources", func(t *testing.T) { + t.Parallel() + for _, tpl := range resources[:1] { stream := dispatch.NewCollectingDispatchStream[*v1.DispatchLookupResourcesResponse](ctx) err := dispatcher.DispatchLookupResources(&v1.DispatchLookupResourcesRequest{ @@ -75,6 +79,8 @@ func TestDispatchChunking(t *testing.T) { }) t.Run("lookup-subjects", func(t *testing.T) { + t.Parallel() + for _, tpl := range resources[:1] { stream := dispatch.NewCollectingDispatchStream[*v1.DispatchLookupSubjectsResponse](ctx) diff --git a/internal/dispatch/graph/expand_test.go b/internal/dispatch/graph/expand_test.go index 06d2350e90..40b6aa552b 100644 --- a/internal/dispatch/graph/expand_test.go +++ b/internal/dispatch/graph/expand_test.go @@ -11,7 +11,6 @@ import ( "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/require" - "go.uber.org/goleak" "google.golang.org/protobuf/encoding/prototext" "google.golang.org/protobuf/testing/protocmp" @@ -137,7 +136,7 @@ var ( ) func TestExpand(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) + t.Parallel() testCases := []struct { start *core.ObjectAndRelation @@ -275,7 +274,7 @@ func onrExpr(onr *core.ObjectAndRelation) ast.Expr { } func TestMaxDepthExpand(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) + t.Parallel() require := require.New(t) @@ -306,7 +305,7 @@ func TestMaxDepthExpand(t *testing.T) { } func TestExpandOverSchema(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) + t.Parallel() testCases := []struct { name string diff --git a/internal/dispatch/graph/graph_test.go b/internal/dispatch/graph/graph_test.go index 564bebce14..ee50150521 100644 --- a/internal/dispatch/graph/graph_test.go +++ b/internal/dispatch/graph/graph_test.go @@ -13,11 +13,14 @@ import ( ) func TestUnwrapStatusError(t *testing.T) { + t.Parallel() + err := rewriteError(context.Background(), graph.NewCheckFailureErr(status.Error(codes.Canceled, "canceled"))) grpcutil.RequireStatus(t, codes.Canceled, err) } func TestConcurrencyLimitsWithOverallDefaultLimit(t *testing.T) { + t.Parallel() cl := ConcurrencyLimits{} require.Equal(t, uint16(0), cl.Check) require.Equal(t, uint16(0), cl.LookupResources) @@ -38,6 +41,7 @@ func TestConcurrencyLimitsWithOverallDefaultLimit(t *testing.T) { } func TestSharedConcurrencyLimits(t *testing.T) { + t.Parallel() cl := SharedConcurrencyLimits(42) require.Equal(t, uint16(42), cl.Check) require.Equal(t, uint16(42), cl.LookupResources) diff --git a/internal/dispatch/graph/lookupresources2_test.go b/internal/dispatch/graph/lookupresources2_test.go index fdf123ff17..32bfd34c3f 100644 --- a/internal/dispatch/graph/lookupresources2_test.go +++ b/internal/dispatch/graph/lookupresources2_test.go @@ -21,13 +21,11 @@ import ( "github.com/authzed/spicedb/pkg/genutil/mapz" core "github.com/authzed/spicedb/pkg/proto/core/v1" v1 "github.com/authzed/spicedb/pkg/proto/dispatch/v1" - "github.com/authzed/spicedb/pkg/testutil" "github.com/authzed/spicedb/pkg/tuple" ) func TestSimpleLookupResources2(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) - + // FIXME marking this parallel makes goleak detect a leaked goroutine testCases := []struct { start *core.RelationReference target *core.ObjectAndRelation @@ -159,7 +157,7 @@ func TestSimpleLookupResources2(t *testing.T) { } func TestSimpleLookupResourcesWithCursor2(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) + t.Parallel() for _, tc := range []struct { subject string @@ -242,7 +240,7 @@ func TestSimpleLookupResourcesWithCursor2(t *testing.T) { } func TestLookupResourcesCursorStability2(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) + t.Parallel() require := require.New(t) ctx, dispatcher, revision := newLocalDispatcher(t) @@ -309,6 +307,7 @@ func processResults2(stream *dispatch.CollectingDispatchStream[*v1.DispatchLooku } func TestMaxDepthLookup2(t *testing.T) { + t.Parallel() require := require.New(t) rawDS, err := memdb.NewMemdbDatastore(0, 0, memdb.DisableGC) @@ -338,6 +337,7 @@ func TestMaxDepthLookup2(t *testing.T) { } func TestLookupResources2OverSchemaWithCursors(t *testing.T) { + t.Parallel() testCases := []struct { name string schema string @@ -682,9 +682,11 @@ func TestLookupResources2OverSchemaWithCursors(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { + t.Parallel() for _, pageSize := range []int{0, 104, 1023} { pageSize := pageSize t.Run(fmt.Sprintf("ps-%d_", pageSize), func(t *testing.T) { + t.Parallel() require := require.New(t) dispatcher := NewLocalOnlyDispatcher(10, 100) @@ -741,10 +743,11 @@ func TestLookupResources2OverSchemaWithCursors(t *testing.T) { } foundResourceIDsSlice := foundResourceIDs.AsSlice() + expectedResourceIDs := slices.Clone(tc.expectedResourceIDs) slices.Sort(foundResourceIDsSlice) - slices.Sort(tc.expectedResourceIDs) + slices.Sort(expectedResourceIDs) - require.Equal(tc.expectedResourceIDs, foundResourceIDsSlice) + require.Equal(expectedResourceIDs, foundResourceIDsSlice) }) } }) @@ -752,7 +755,7 @@ func TestLookupResources2OverSchemaWithCursors(t *testing.T) { } func TestLookupResources2ImmediateTimeout(t *testing.T) { - defer goleak.VerifyNone(t, goleak.IgnoreCurrent()) + t.Parallel() require := require.New(t) @@ -787,7 +790,7 @@ func TestLookupResources2ImmediateTimeout(t *testing.T) { } func TestLookupResources2WithError(t *testing.T) { - defer goleak.VerifyNone(t, goleak.IgnoreCurrent()) + t.Parallel() require := require.New(t) @@ -822,7 +825,7 @@ func TestLookupResources2WithError(t *testing.T) { } func TestLookupResources2EnsureCheckHints(t *testing.T) { - defer goleak.VerifyNone(t, goleak.IgnoreCurrent()) + t.Parallel() tcs := []struct { name string diff --git a/internal/dispatch/graph/lookupresources_test.go b/internal/dispatch/graph/lookupresources_test.go index 009eccb6e9..d8ecdca6b0 100644 --- a/internal/dispatch/graph/lookupresources_test.go +++ b/internal/dispatch/graph/lookupresources_test.go @@ -9,7 +9,6 @@ import ( "github.com/ccoveille/go-safecast" "github.com/stretchr/testify/require" - "go.uber.org/goleak" "github.com/authzed/spicedb/internal/datastore/memdb" "github.com/authzed/spicedb/internal/dispatch" @@ -18,7 +17,6 @@ import ( "github.com/authzed/spicedb/pkg/genutil/mapz" core "github.com/authzed/spicedb/pkg/proto/core/v1" v1 "github.com/authzed/spicedb/pkg/proto/dispatch/v1" - "github.com/authzed/spicedb/pkg/testutil" "github.com/authzed/spicedb/pkg/tuple" ) @@ -39,7 +37,7 @@ func resolvedRes(resourceID string) *v1.ResolvedResource { } func TestSimpleLookupResources(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) + t.Parallel() testCases := []struct { start *core.RelationReference @@ -166,7 +164,7 @@ func TestSimpleLookupResources(t *testing.T) { } func TestSimpleLookupResourcesWithCursor(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) + t.Parallel() for _, tc := range []struct { subject string @@ -245,7 +243,7 @@ func TestSimpleLookupResourcesWithCursor(t *testing.T) { } func TestLookupResourcesCursorStability(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) + t.Parallel() require := require.New(t) ctx, dispatcher, revision := newLocalDispatcher(t) @@ -307,6 +305,7 @@ func processResults(stream *dispatch.CollectingDispatchStream[*v1.DispatchLookup } func TestMaxDepthLookup(t *testing.T) { + t.Parallel() require := require.New(t) rawDS, err := memdb.NewMemdbDatastore(0, 0, memdb.DisableGC) @@ -389,6 +388,7 @@ func genResourceIds(resourceName string, number int) []string { } func TestLookupResourcesOverSchemaWithCursors(t *testing.T) { + t.Parallel() testCases := []struct { name string schema string @@ -597,9 +597,11 @@ func TestLookupResourcesOverSchemaWithCursors(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { + t.Parallel() for _, pageSize := range []int{0, 104, 1023} { pageSize := pageSize t.Run(fmt.Sprintf("ps-%d_", pageSize), func(t *testing.T) { + t.Parallel() require := require.New(t) dispatcher := NewLocalOnlyDispatcher(10, 100) @@ -646,10 +648,11 @@ func TestLookupResourcesOverSchemaWithCursors(t *testing.T) { } foundResourceIDsSlice := foundResourceIDs.AsSlice() + expectedResourceIDs := slices.Clone(tc.expectedResourceIDs) slices.Sort(foundResourceIDsSlice) - slices.Sort(tc.expectedResourceIDs) + slices.Sort(expectedResourceIDs) - require.Equal(tc.expectedResourceIDs, foundResourceIDsSlice) + require.Equal(expectedResourceIDs, foundResourceIDsSlice) }) } }) @@ -657,7 +660,7 @@ func TestLookupResourcesOverSchemaWithCursors(t *testing.T) { } func TestLookupResourcesImmediateTimeout(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) + t.Parallel() require := require.New(t) @@ -690,7 +693,7 @@ func TestLookupResourcesImmediateTimeout(t *testing.T) { } func TestLookupResourcesWithError(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) + t.Parallel() require := require.New(t) diff --git a/internal/dispatch/graph/lookupsubjects_test.go b/internal/dispatch/graph/lookupsubjects_test.go index 7ec1e9c3da..98abf655db 100644 --- a/internal/dispatch/graph/lookupsubjects_test.go +++ b/internal/dispatch/graph/lookupsubjects_test.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/stretchr/testify/require" - "go.uber.org/goleak" "github.com/authzed/spicedb/internal/caveats" "github.com/authzed/spicedb/internal/datastore/common" @@ -19,7 +18,6 @@ import ( itestutil "github.com/authzed/spicedb/internal/testutil" corev1 "github.com/authzed/spicedb/pkg/proto/core/v1" v1 "github.com/authzed/spicedb/pkg/proto/dispatch/v1" - "github.com/authzed/spicedb/pkg/testutil" "github.com/authzed/spicedb/pkg/tuple" ) @@ -32,7 +30,7 @@ var ( ) func TestSimpleLookupSubjects(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) + t.Parallel() testCases := []struct { resourceType string @@ -194,6 +192,7 @@ func TestSimpleLookupSubjects(t *testing.T) { } func TestLookupSubjectsMaxDepth(t *testing.T) { + t.Parallel() require := require.New(t) rawDS, err := memdb.NewMemdbDatastore(0, 0, memdb.DisableGC) @@ -224,6 +223,7 @@ func TestLookupSubjectsMaxDepth(t *testing.T) { } func TestLookupSubjectsDispatchCount(t *testing.T) { + t.Parallel() testCases := []struct { resourceType string resourceID string @@ -277,6 +277,7 @@ func TestLookupSubjectsDispatchCount(t *testing.T) { } func TestLookupSubjectsOverSchema(t *testing.T) { + t.Parallel() testCases := []struct { name string schema string diff --git a/internal/dispatch/graph/package_test.go b/internal/dispatch/graph/package_test.go new file mode 100644 index 0000000000..50d508e110 --- /dev/null +++ b/internal/dispatch/graph/package_test.go @@ -0,0 +1,14 @@ +package graph + +import ( + "testing" + + "go.uber.org/goleak" + + "github.com/authzed/spicedb/pkg/testutil" +) + +// done so we can do t.Parallel() and still use goleak +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) +} diff --git a/internal/dispatch/graph/reachableresources_test.go b/internal/dispatch/graph/reachableresources_test.go index 9ccb97b86c..4a73ec2888 100644 --- a/internal/dispatch/graph/reachableresources_test.go +++ b/internal/dispatch/graph/reachableresources_test.go @@ -12,7 +12,6 @@ import ( "github.com/ccoveille/go-safecast" "github.com/stretchr/testify/require" - "go.uber.org/goleak" "golang.org/x/sync/errgroup" "github.com/authzed/spicedb/internal/datastore/memdb" @@ -27,7 +26,6 @@ import ( "github.com/authzed/spicedb/pkg/genutil/mapz" core "github.com/authzed/spicedb/pkg/proto/core/v1" v1 "github.com/authzed/spicedb/pkg/proto/dispatch/v1" - "github.com/authzed/spicedb/pkg/testutil" "github.com/authzed/spicedb/pkg/tuple" ) @@ -43,7 +41,7 @@ func reachable(onr *core.ObjectAndRelation, hasPermission bool) reachableResourc } func TestSimpleReachableResources(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) + t.Parallel() testCases := []struct { start *core.RelationReference @@ -198,6 +196,7 @@ func TestSimpleReachableResources(t *testing.T) { } func TestMaxDepthreachableResources(t *testing.T) { + t.Parallel() require := require.New(t) ctx, dispatcher, revision := newLocalDispatcher(t) @@ -303,6 +302,7 @@ func BenchmarkReachableResources(b *testing.B) { } func TestCaveatedReachableResources(t *testing.T) { + t.Parallel() testCases := []struct { name string schema string @@ -616,8 +616,7 @@ func TestCaveatedReachableResources(t *testing.T) { } func TestReachableResourcesWithConsistencyLimitOf1(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) - + t.Parallel() ctx, dispatcher, revision := newLocalDispatcherWithConcurrencyLimit(t, 1) defer dispatcher.Close() @@ -646,8 +645,7 @@ func TestReachableResourcesWithConsistencyLimitOf1(t *testing.T) { } func TestReachableResourcesMultipleEntrypointEarlyCancel(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) - + t.Parallel() rawDS, err := memdb.NewMemdbDatastore(0, 0, memdb.DisableGC) require.NoError(t, err) @@ -723,8 +721,7 @@ func TestReachableResourcesMultipleEntrypointEarlyCancel(t *testing.T) { } func TestReachableResourcesCursors(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) - + t.Parallel() rawDS, err := memdb.NewMemdbDatastore(0, 0, memdb.DisableGC) require.NoError(t, err) @@ -840,8 +837,7 @@ func TestReachableResourcesCursors(t *testing.T) { } func TestReachableResourcesPaginationWithLimit(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) - + t.Parallel() rawDS, err := memdb.NewMemdbDatastore(0, 0, memdb.DisableGC) require.NoError(t, err) @@ -870,6 +866,7 @@ func TestReachableResourcesPaginationWithLimit(t *testing.T) { for _, limit := range []uint32{1, 10, 50, 100, 150, 250, 500} { limit := limit t.Run(fmt.Sprintf("limit-%d", limit), func(t *testing.T) { + // FIXME t.Parallel() here introduces a race condition over the dispatcher dispatcher := NewLocalOnlyDispatcher(2, 100) var cursor *v1.Cursor foundResources := mapz.NewSet[string]() @@ -921,8 +918,7 @@ func TestReachableResourcesPaginationWithLimit(t *testing.T) { } func TestReachableResourcesWithQueryError(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) - + t.Parallel() rawDS, err := memdb.NewMemdbDatastore(0, 0, memdb.DisableGC) require.NoError(t, err) @@ -1004,6 +1000,8 @@ func (br *breakingReader) ReverseQueryRelationships( } func TestReachableResourcesOverSchema(t *testing.T) { + t.Parallel() + testCases := []struct { name string schema string @@ -1221,9 +1219,11 @@ func TestReachableResourcesOverSchema(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { + t.Parallel() for _, pageSize := range []int{0, 100, 1000} { pageSize := pageSize t.Run(fmt.Sprintf("ps-%d_", pageSize), func(t *testing.T) { + t.Parallel() require := require.New(t) dispatcher := NewLocalOnlyDispatcher(10, 100) @@ -1276,9 +1276,10 @@ func TestReachableResourcesOverSchema(t *testing.T) { foundResourceIDsSlice := foundResourceIDs.AsSlice() sort.Strings(foundResourceIDsSlice) - sort.Strings(tc.expectedResourceIDs) + expectedResourceIDs := slices.Clone(tc.expectedResourceIDs) + sort.Strings(expectedResourceIDs) - require.Equal(tc.expectedResourceIDs, foundResourceIDsSlice) + require.Equal(expectedResourceIDs, foundResourceIDsSlice) }) } }) @@ -1286,8 +1287,7 @@ func TestReachableResourcesOverSchema(t *testing.T) { } func TestReachableResourcesWithPreCancelation(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) - + t.Parallel() rawDS, err := memdb.NewMemdbDatastore(0, 0, memdb.DisableGC) require.NoError(t, err) @@ -1341,8 +1341,7 @@ func TestReachableResourcesWithPreCancelation(t *testing.T) { } func TestReachableResourcesWithUnexpectedContextCancelation(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) - + t.Parallel() rawDS, err := memdb.NewMemdbDatastore(0, 0, memdb.DisableGC) require.NoError(t, err) @@ -1426,8 +1425,7 @@ func (cr *cancelingReader) ReverseQueryRelationships( } func TestReachableResourcesWithCachingInParallelTest(t *testing.T) { - defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) - + t.Parallel() rawDS, err := memdb.NewMemdbDatastore(0, 0, memdb.DisableGC) require.NoError(t, err) diff --git a/internal/dispatch/remote/cluster_test.go b/internal/dispatch/remote/cluster_test.go index 58c7ee2115..50b8c1e70d 100644 --- a/internal/dispatch/remote/cluster_test.go +++ b/internal/dispatch/remote/cluster_test.go @@ -236,6 +236,7 @@ func TestCheckSecondaryDispatch(t *testing.T) { } { tc := tc t.Run(tc.name, func(t *testing.T) { + t.Parallel() conn := connectionForDispatching(t, &fakeDispatchSvc{dispatchCount: 1, sleepTime: tc.primarySleepTime}) secondaryConn := connectionForDispatching(t, &fakeDispatchSvc{dispatchCount: 2, sleepTime: 0 * time.Millisecond}) diff --git a/internal/relationships/validation_test.go b/internal/relationships/validation_test.go index 4749ad1684..a7d42430a9 100644 --- a/internal/relationships/validation_test.go +++ b/internal/relationships/validation_test.go @@ -242,7 +242,9 @@ func TestValidateRelationshipOperations(t *testing.T) { } for _, tc := range tcs { + tc := tc t.Run(tc.name, func(t *testing.T) { + t.Parallel() req := require.New(t) ds, err := memdb.NewMemdbDatastore(0, 0, memdb.DisableGC) diff --git a/internal/services/integrationtesting/cert_test.go b/internal/services/integrationtesting/cert_test.go index 91cc9e0df4..7b30b511b2 100644 --- a/internal/services/integrationtesting/cert_test.go +++ b/internal/services/integrationtesting/cert_test.go @@ -36,6 +36,8 @@ import ( ) func TestCertRotation(t *testing.T) { + t.Parallel() + const ( // length of time the initial cert is valid initialValidDuration = 3 * time.Second diff --git a/internal/services/integrationtesting/consistency_test.go b/internal/services/integrationtesting/consistency_test.go index bc17eb7df4..bf5a5dd5e8 100644 --- a/internal/services/integrationtesting/consistency_test.go +++ b/internal/services/integrationtesting/consistency_test.go @@ -55,6 +55,7 @@ func TestConsistency(t *testing.T) { filePath := filePath t.Run(path.Base(filePath), func(t *testing.T) { + t.Parallel() for _, dispatcherKind := range []string{"local", "caching"} { dispatcherKind := dispatcherKind diff --git a/internal/services/integrationtesting/ops_test.go b/internal/services/integrationtesting/ops_test.go index d98adf0882..263f384603 100644 --- a/internal/services/integrationtesting/ops_test.go +++ b/internal/services/integrationtesting/ops_test.go @@ -120,6 +120,8 @@ func (dr deleteCaveatedRelationship) Execute(tester opsTester) error { } func TestSchemaAndRelationshipsOperations(t *testing.T) { + t.Parallel() + tcs := []schemaTestCase{ // Test: write a basic, valid schema. { @@ -751,6 +753,7 @@ func TestSchemaAndRelationshipsOperations(t *testing.T) { for _, tc := range tcs { tc := tc t.Run(tc.name, func(t *testing.T) { + t.Parallel() for _, testerName := range []string{"v1"} { testerName := testerName t.Run(testerName, func(t *testing.T) { diff --git a/internal/services/v1/experimental_test.go b/internal/services/v1/experimental_test.go index 1b6b0ab78c..28f5c9ea39 100644 --- a/internal/services/v1/experimental_test.go +++ b/internal/services/v1/experimental_test.go @@ -51,7 +51,9 @@ func TestBulkImportRelationships(t *testing.T) { } for _, tc := range testCases { + tc := tc t.Run(tc.name, func(t *testing.T) { + t.Parallel() require := require.New(t) conn, cleanup, _, _ := testserver.NewTestServer(require, 0, memdb.DisableGC, true, tf.StandardDatastoreWithSchema) @@ -300,6 +302,7 @@ func TestBulkExportRelationshipsWithFilter(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { + t.Parallel() require := require.New(t) conn, cleanup, _, _ := testserver.NewTestServer(require, 0, memdb.DisableGC, true, tf.StandardDatastoreWithSchema) diff --git a/internal/taskrunner/preloadedtaskrunner_test.go b/internal/taskrunner/preloadedtaskrunner_test.go index acee93d83c..1290992ffc 100644 --- a/internal/taskrunner/preloadedtaskrunner_test.go +++ b/internal/taskrunner/preloadedtaskrunner_test.go @@ -14,8 +14,13 @@ import ( "go.uber.org/goleak" ) +// done so we can do t.Parallel() and still use goleak +func TestMain(m *testing.M) { + goleak.VerifyTestMain(m) +} + func TestPreloadedTaskRunnerCompletesAllTasks(t *testing.T) { - defer goleak.VerifyNone(t) + t.Parallel() tr := NewPreloadedTaskRunner(context.Background(), 2, 5) wg := sync.WaitGroup{} @@ -38,7 +43,7 @@ func TestPreloadedTaskRunnerCompletesAllTasks(t *testing.T) { } func TestPreloadedTaskRunnerCancelsEarlyDueToError(t *testing.T) { - defer goleak.VerifyNone(t) + t.Parallel() ctx := context.Background() ctx, cancel := context.WithCancel(ctx) @@ -76,7 +81,7 @@ func TestPreloadedTaskRunnerCancelsEarlyDueToError(t *testing.T) { } func TestPreloadedTaskRunnerCancelsEarlyDueToCancel(t *testing.T) { - defer goleak.VerifyNone(t) + t.Parallel() ctx := context.Background() ctx, cancel := context.WithCancel(ctx) @@ -115,7 +120,7 @@ func TestPreloadedTaskRunnerCancelsEarlyDueToCancel(t *testing.T) { } func TestPreloadedTaskRunnerReturnsError(t *testing.T) { - defer goleak.VerifyNone(t) + t.Parallel() ctx := context.Background() ctx, cancel := context.WithCancel(ctx) @@ -154,7 +159,7 @@ func TestPreloadedTaskRunnerReturnsError(t *testing.T) { } func TestPreloadedTaskRunnerEmpty(t *testing.T) { - defer goleak.VerifyNone(t) + t.Parallel() ctx := context.Background() ctx, cancel := context.WithCancel(ctx) diff --git a/internal/testutil/subjects_test.go b/internal/testutil/subjects_test.go index 55b93ccf11..b07254ea12 100644 --- a/internal/testutil/subjects_test.go +++ b/internal/testutil/subjects_test.go @@ -22,6 +22,8 @@ var ( ) func TestCompareSubjects(t *testing.T) { + t.Parallel() + tcs := []struct { first *v1.FoundSubject second *v1.FoundSubject diff --git a/magefiles/test.go b/magefiles/test.go index e1615d35bb..9af877e87e 100644 --- a/magefiles/test.go +++ b/magefiles/test.go @@ -23,17 +23,27 @@ func (t Test) All() error { return nil } -// Runs the unit tests and generates a coverage report -func (Test) UnitCover() error { - mg.Deps(Test{}.Unit) +// UnitCover Runs the unit tests and generates a coverage report +func (t Test) UnitCover() error { + if err := t.unit(true); err != nil { + return err + } fmt.Println("Running coverage...") return sh.RunV("go", "tool", "cover", "-html=coverage.txt") } // Unit Runs the unit tests -func (Test) Unit() error { +func (t Test) Unit() error { + return t.unit(false) +} + +func (Test) unit(coverage bool) error { fmt.Println("running unit tests") - return goTest("./...", "-tags", "ci,skipintegrationtests", "-race", "-timeout", "10m", "-covermode=atomic", "-count=1", "-coverprofile=coverage.txt") + args := []string{"-tags", "ci,skipintegrationtests", "-race", "-timeout", "10m", "-count=1"} + if coverage { + args = append(args, "-covermode=atomic", "-coverprofile=coverage.txt") + } + return goTest("./...", args...) } // Image Run tests that run the built image diff --git a/pkg/cmd/migrate.go b/pkg/cmd/migrate.go index b074909b6f..2880f79783 100644 --- a/pkg/cmd/migrate.go +++ b/pkg/cmd/migrate.go @@ -9,6 +9,8 @@ import ( "github.com/jzelinskie/cobrautil/v2" "github.com/spf13/cobra" + sqlDriver "github.com/go-sql-driver/mysql" + crdbmigrations "github.com/authzed/spicedb/internal/datastore/crdb/migrations" mysqlmigrations "github.com/authzed/spicedb/internal/datastore/mysql/migrations" "github.com/authzed/spicedb/internal/datastore/postgres/migrations" @@ -111,6 +113,12 @@ func migrateRun(cmd *cobra.Command, args []string) error { } } + // Do this outside NewMySQLDriverFromDSN to avoid races on MySQL datastore tests + err = sqlDriver.SetLogger(&log.Logger) + if err != nil { + return fmt.Errorf("unable to set logging to mysql driver: %w", err) + } + migrationDriver, err := mysqlmigrations.NewMySQLDriverFromDSN(dbURL, tablePrefix, credentialsProvider) if err != nil { return fmt.Errorf("unable to create migration driver for %s: %w", datastoreEngine, err) diff --git a/pkg/datastore/pagination/iterator_test.go b/pkg/datastore/pagination/iterator_test.go index 4cde4d61b8..22a924e2e5 100644 --- a/pkg/datastore/pagination/iterator_test.go +++ b/pkg/datastore/pagination/iterator_test.go @@ -142,7 +142,9 @@ func TestPaginatedIterator(t *testing.T) { } for _, tc := range testCases { + tc := tc t.Run(fmt.Sprintf("%d/%d-%d", tc.pageSize, tc.totalRelationships, tc.order), func(t *testing.T) { + t.Parallel() require := require.New(t) tpls := make([]*core.RelationTuple, 0, tc.totalRelationships) diff --git a/pkg/datastore/test/datastore.go b/pkg/datastore/test/datastore.go index cc8a0999f5..983b8435ca 100644 --- a/pkg/datastore/test/datastore.go +++ b/pkg/datastore/test/datastore.go @@ -84,104 +84,122 @@ func WithCategories(cats ...string) Categories { return c } +func parallel(t *testing.T, tester DatastoreTester, tt func(t *testing.T, tester DatastoreTester)) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + tt(t, tester) + } +} + +func serial(t *testing.T, tester DatastoreTester, tt func(t *testing.T, tester DatastoreTester)) func(t *testing.T) { + return func(t *testing.T) { + tt(t, tester) + } +} + // AllWithExceptions runs all generic datastore tests on a DatastoreTester, except // those specified test categories -func AllWithExceptions(t *testing.T, tester DatastoreTester, except Categories) { - t.Run("TestUseAfterClose", func(t *testing.T) { UseAfterCloseTest(t, tester) }) - - t.Run("TestNamespaceNotFound", func(t *testing.T) { NamespaceNotFoundTest(t, tester) }) - t.Run("TestNamespaceWrite", func(t *testing.T) { NamespaceWriteTest(t, tester) }) - t.Run("TestNamespaceDelete", func(t *testing.T) { NamespaceDeleteTest(t, tester) }) - t.Run("TestNamespaceMultiDelete", func(t *testing.T) { NamespaceMultiDeleteTest(t, tester) }) - t.Run("TestEmptyNamespaceDelete", func(t *testing.T) { EmptyNamespaceDeleteTest(t, tester) }) - t.Run("TestStableNamespaceReadWrite", func(t *testing.T) { StableNamespaceReadWriteTest(t, tester) }) - - t.Run("TestSimple", func(t *testing.T) { SimpleTest(t, tester) }) - t.Run("TestObjectIDs", func(t *testing.T) { ObjectIDsTest(t, tester) }) - t.Run("TestDeleteRelationships", func(t *testing.T) { DeleteRelationshipsTest(t, tester) }) - t.Run("TestDeleteNonExistant", func(t *testing.T) { DeleteNotExistantTest(t, tester) }) - t.Run("TestDeleteAlreadyDeleted", func(t *testing.T) { DeleteAlreadyDeletedTest(t, tester) }) - t.Run("TestRecreateRelationshipsAfterDeleteWithFilter", func(t *testing.T) { RecreateRelationshipsAfterDeleteWithFilter(t, tester) }) - t.Run("TestWriteDeleteWrite", func(t *testing.T) { WriteDeleteWriteTest(t, tester) }) - t.Run("TestCreateAlreadyExisting", func(t *testing.T) { CreateAlreadyExistingTest(t, tester) }) - t.Run("TestTouchAlreadyExistingWithoutCaveat", func(t *testing.T) { TouchAlreadyExistingTest(t, tester) }) - t.Run("TestCreateDeleteTouch", func(t *testing.T) { CreateDeleteTouchTest(t, tester) }) - t.Run("TestDeleteOneThousandIndividualInOneCall", func(t *testing.T) { DeleteOneThousandIndividualInOneCallTest(t, tester) }) - t.Run("TestCreateTouchDeleteTouch", func(t *testing.T) { CreateTouchDeleteTouchTest(t, tester) }) - t.Run("TestTouchAlreadyExistingCaveated", func(t *testing.T) { TouchAlreadyExistingCaveatedTest(t, tester) }) - t.Run("TestBulkDeleteRelationships", func(t *testing.T) { BulkDeleteRelationshipsTest(t, tester) }) - t.Run("TestDeleteCaveatedTuple", func(t *testing.T) { DeleteCaveatedTupleTest(t, tester) }) - t.Run("TestDeleteWithLimit", func(t *testing.T) { DeleteWithLimitTest(t, tester) }) - t.Run("TestQueryRelationshipsWithVariousFilters", func(t *testing.T) { QueryRelationshipsWithVariousFiltersTest(t, tester) }) - t.Run("TestDeleteRelationshipsWithVariousFilters", func(t *testing.T) { DeleteRelationshipsWithVariousFiltersTest(t, tester) }) - t.Run("TestTouchTypedAlreadyExistingWithoutCaveat", func(t *testing.T) { TypedTouchAlreadyExistingTest(t, tester) }) - t.Run("TestTouchTypedAlreadyExistingWithCaveat", func(t *testing.T) { TypedTouchAlreadyExistingWithCaveatTest(t, tester) }) - - t.Run("TestMultipleReadsInRWT", func(t *testing.T) { MultipleReadsInRWTTest(t, tester) }) - t.Run("TestConcurrentWriteSerialization", func(t *testing.T) { ConcurrentWriteSerializationTest(t, tester) }) - - t.Run("TestOrdering", func(t *testing.T) { OrderingTest(t, tester) }) - t.Run("TestLimit", func(t *testing.T) { LimitTest(t, tester) }) - t.Run("TestOrderedLimit", func(t *testing.T) { OrderedLimitTest(t, tester) }) - t.Run("TestResume", func(t *testing.T) { ResumeTest(t, tester) }) - t.Run("TestCursorErrors", func(t *testing.T) { CursorErrorsTest(t, tester) }) - t.Run("TestReverseQueryCursor", func(t *testing.T) { ReverseQueryCursorTest(t, tester) }) - - t.Run("TestRevisionQuantization", func(t *testing.T) { RevisionQuantizationTest(t, tester) }) - t.Run("TestRevisionSerialization", func(t *testing.T) { RevisionSerializationTest(t, tester) }) - t.Run("TestSequentialRevisions", func(t *testing.T) { SequentialRevisionsTest(t, tester) }) - t.Run("TestConcurrentRevisions", func(t *testing.T) { ConcurrentRevisionsTest(t, tester) }) - t.Run("TestCheckRevisions", func(t *testing.T) { CheckRevisionsTest(t, tester) }) +func AllWithExceptions(t *testing.T, tester DatastoreTester, except Categories, concurrent bool) { + runner := serial + if concurrent { + runner = parallel + } + + t.Run("TestUseAfterClose", runner(t, tester, UseAfterCloseTest)) + + t.Run("TestNamespaceNotFound", runner(t, tester, NamespaceNotFoundTest)) + t.Run("TestNamespaceWrite", runner(t, tester, NamespaceWriteTest)) + t.Run("TestNamespaceDelete", runner(t, tester, NamespaceDeleteTest)) + t.Run("TestNamespaceMultiDelete", runner(t, tester, NamespaceMultiDeleteTest)) + t.Run("TestEmptyNamespaceDelete", runner(t, tester, EmptyNamespaceDeleteTest)) + t.Run("TestStableNamespaceReadWrite", runner(t, tester, StableNamespaceReadWriteTest)) + + t.Run("TestSimple", runner(t, tester, SimpleTest)) + t.Run("TestObjectIDs", runner(t, tester, ObjectIDsTest)) + t.Run("TestDeleteRelationships", runner(t, tester, DeleteRelationshipsTest)) + t.Run("TestDeleteNonExistant", runner(t, tester, DeleteNotExistantTest)) + t.Run("TestDeleteAlreadyDeleted", runner(t, tester, DeleteAlreadyDeletedTest)) + t.Run("TestRecreateRelationshipsAfterDeleteWithFilter", runner(t, tester, RecreateRelationshipsAfterDeleteWithFilter)) + t.Run("TestWriteDeleteWrite", runner(t, tester, WriteDeleteWriteTest)) + t.Run("TestCreateAlreadyExisting", runner(t, tester, CreateAlreadyExistingTest)) + t.Run("TestTouchAlreadyExistingWithoutCaveat", runner(t, tester, TouchAlreadyExistingTest)) + t.Run("TestCreateDeleteTouch", runner(t, tester, CreateDeleteTouchTest)) + t.Run("TestDeleteOneThousandIndividualInOneCall", runner(t, tester, DeleteOneThousandIndividualInOneCallTest)) + t.Run("TestCreateTouchDeleteTouch", runner(t, tester, CreateTouchDeleteTouchTest)) + t.Run("TestTouchAlreadyExistingCaveated", runner(t, tester, TouchAlreadyExistingCaveatedTest)) + t.Run("TestBulkDeleteRelationships", runner(t, tester, BulkDeleteRelationshipsTest)) + t.Run("TestDeleteCaveatedTuple", runner(t, tester, DeleteCaveatedTupleTest)) + t.Run("TestDeleteWithLimit", runner(t, tester, DeleteWithLimitTest)) + t.Run("TestQueryRelationshipsWithVariousFilters", runner(t, tester, QueryRelationshipsWithVariousFiltersTest)) + t.Run("TestDeleteRelationshipsWithVariousFilters", runner(t, tester, DeleteRelationshipsWithVariousFiltersTest)) + t.Run("TestTouchTypedAlreadyExistingWithoutCaveat", runner(t, tester, TypedTouchAlreadyExistingTest)) + t.Run("TestTouchTypedAlreadyExistingWithCaveat", runner(t, tester, TypedTouchAlreadyExistingWithCaveatTest)) + + t.Run("TestMultipleReadsInRWT", runner(t, tester, MultipleReadsInRWTTest)) + t.Run("TestConcurrentWriteSerialization", runner(t, tester, ConcurrentWriteSerializationTest)) + + t.Run("TestOrdering", runner(t, tester, OrderingTest)) + t.Run("TestLimit", runner(t, tester, LimitTest)) + t.Run("TestOrderedLimit", runner(t, tester, OrderedLimitTest)) + t.Run("TestResume", runner(t, tester, ResumeTest)) + t.Run("TestCursorErrors", runner(t, tester, CursorErrorsTest)) + t.Run("TestReverseQueryCursor", runner(t, tester, ReverseQueryCursorTest)) + + t.Run("TestRevisionQuantization", runner(t, tester, RevisionQuantizationTest)) + t.Run("TestRevisionSerialization", runner(t, tester, RevisionSerializationTest)) + t.Run("TestSequentialRevisions", runner(t, tester, SequentialRevisionsTest)) + t.Run("TestConcurrentRevisions", runner(t, tester, ConcurrentRevisionsTest)) + t.Run("TestCheckRevisions", runner(t, tester, CheckRevisionsTest)) if !except.GC() { - t.Run("TestRevisionGC", func(t *testing.T) { RevisionGCTest(t, tester) }) - t.Run("TestInvalidReads", func(t *testing.T) { InvalidReadsTest(t, tester) }) + t.Run("TestRevisionGC", runner(t, tester, RevisionGCTest)) + t.Run("TestInvalidReads", runner(t, tester, InvalidReadsTest)) } - t.Run("TestBulkUpload", func(t *testing.T) { BulkUploadTest(t, tester) }) - t.Run("TestBulkUploadErrors", func(t *testing.T) { BulkUploadErrorsTest(t, tester) }) - t.Run("TestBulkUploadAlreadyExistsError", func(t *testing.T) { BulkUploadAlreadyExistsErrorTest(t, tester) }) - t.Run("TestBulkUploadAlreadyExistsSameCallError", func(t *testing.T) { BulkUploadAlreadyExistsSameCallErrorTest(t, tester) }) - t.Run("BulkUploadEditCaveat", func(t *testing.T) { BulkUploadEditCaveat(t, tester) }) + t.Run("TestBulkUpload", runner(t, tester, BulkUploadTest)) + t.Run("TestBulkUploadErrors", runner(t, tester, BulkUploadErrorsTest)) + t.Run("TestBulkUploadAlreadyExistsError", runner(t, tester, BulkUploadAlreadyExistsErrorTest)) + t.Run("TestBulkUploadAlreadyExistsSameCallError", runner(t, tester, BulkUploadAlreadyExistsSameCallErrorTest)) + t.Run("BulkUploadEditCaveat", runner(t, tester, BulkUploadEditCaveat)) if !except.Stats() { - t.Run("TestStats", func(t *testing.T) { StatsTest(t, tester) }) + t.Run("TestStats", runner(t, tester, StatsTest)) } - t.Run("TestRetries", func(t *testing.T) { RetryTest(t, tester) }) + t.Run("TestRetries", runner(t, tester, RetryTest)) - t.Run("TestCaveatNotFound", func(t *testing.T) { CaveatNotFoundTest(t, tester) }) - t.Run("TestWriteReadDeleteCaveat", func(t *testing.T) { WriteReadDeleteCaveatTest(t, tester) }) - t.Run("TestWriteCaveatedRelationship", func(t *testing.T) { WriteCaveatedRelationshipTest(t, tester) }) - t.Run("TestCaveatedRelationshipFilter", func(t *testing.T) { CaveatedRelationshipFilterTest(t, tester) }) - t.Run("TestCaveatSnapshotReads", func(t *testing.T) { CaveatSnapshotReadsTest(t, tester) }) + t.Run("TestCaveatNotFound", runner(t, tester, CaveatNotFoundTest)) + t.Run("TestWriteReadDeleteCaveat", runner(t, tester, WriteReadDeleteCaveatTest)) + t.Run("TestWriteCaveatedRelationship", runner(t, tester, WriteCaveatedRelationshipTest)) + t.Run("TestCaveatedRelationshipFilter", runner(t, tester, CaveatedRelationshipFilterTest)) + t.Run("TestCaveatSnapshotReads", runner(t, tester, CaveatSnapshotReadsTest)) if !except.Watch() { - t.Run("TestWatchBasic", func(t *testing.T) { WatchTest(t, tester) }) - t.Run("TestWatchCancel", func(t *testing.T) { WatchCancelTest(t, tester) }) - t.Run("TestCaveatedRelationshipWatch", func(t *testing.T) { CaveatedRelationshipWatchTest(t, tester) }) - t.Run("TestWatchWithTouch", func(t *testing.T) { WatchWithTouchTest(t, tester) }) - t.Run("TestWatchWithDelete", func(t *testing.T) { WatchWithDeleteTest(t, tester) }) - t.Run("TestWatchWithMetadata", func(t *testing.T) { WatchWithMetadataTest(t, tester) }) + t.Run("TestWatchBasic", runner(t, tester, WatchTest)) + t.Run("TestWatchCancel", runner(t, tester, WatchCancelTest)) + t.Run("TestCaveatedRelationshipWatch", runner(t, tester, CaveatedRelationshipWatchTest)) + t.Run("TestWatchWithTouch", runner(t, tester, WatchWithTouchTest)) + t.Run("TestWatchWithDelete", runner(t, tester, WatchWithDeleteTest)) + t.Run("TestWatchWithMetadata", runner(t, tester, WatchWithMetadataTest)) } if !except.Watch() && !except.WatchSchema() { - t.Run("TestWatchSchema", func(t *testing.T) { WatchSchemaTest(t, tester) }) - t.Run("TestWatchAll", func(t *testing.T) { WatchAllTest(t, tester) }) + t.Run("TestWatchSchema", runner(t, tester, WatchSchemaTest)) + t.Run("TestWatchAll", runner(t, tester, WatchAllTest)) } if !except.Watch() && !except.WatchCheckpoints() { - t.Run("TestWatchCheckpoints", func(t *testing.T) { WatchCheckpointsTest(t, tester) }) + t.Run("TestWatchCheckpoints", runner(t, tester, WatchCheckpointsTest)) } - t.Run("TestRelationshipCounters", func(t *testing.T) { RelationshipCountersTest(t, tester) }) - t.Run("TestUpdateRelationshipCounter", func(t *testing.T) { UpdateRelationshipCounterTest(t, tester) }) - t.Run("TestDeleteAllData", func(t *testing.T) { DeleteAllDataTest(t, tester) }) + t.Run("TestRelationshipCounters", runner(t, tester, RelationshipCountersTest)) + t.Run("TestUpdateRelationshipCounter", runner(t, tester, UpdateRelationshipCounterTest)) + t.Run("TestDeleteAllData", runner(t, tester, DeleteAllDataTest)) } // All runs all generic datastore tests on a DatastoreTester. -func All(t *testing.T, tester DatastoreTester) { - AllWithExceptions(t, tester, noException) +func All(t *testing.T, tester DatastoreTester, concurrent bool) { + AllWithExceptions(t, tester, noException, concurrent) } var testResourceNS = namespace.Namespace( diff --git a/pkg/schemadsl/compiler/compiler_test.go b/pkg/schemadsl/compiler/compiler_test.go index f060f78f6c..cd796169c3 100644 --- a/pkg/schemadsl/compiler/compiler_test.go +++ b/pkg/schemadsl/compiler/compiler_test.go @@ -21,6 +21,8 @@ var ( ) func TestCompile(t *testing.T) { + t.Parallel() + type compileTest struct { name string objectPrefix ObjectPrefixOption @@ -977,6 +979,7 @@ func TestCompile(t *testing.T) { for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { + t.Parallel() require := require.New(t) compiled, err := Compile(InputSchema{ input.Source(test.name), test.input, @@ -1056,6 +1059,8 @@ func filterSourcePositions(m protoreflect.Message) { } func TestSkipValidation(t *testing.T) { + t.Parallel() + _, err := Compile(InputSchema{"test", `definition a/def {}`}, AllowUnprefixedObjectType()) require.Error(t, err) @@ -1064,6 +1069,8 @@ func TestSkipValidation(t *testing.T) { } func TestSuperLargeCaveatCompile(t *testing.T) { + t.Parallel() + b, err := os.ReadFile("../parser/tests/superlarge.zed") if err != nil { panic(err) diff --git a/pkg/schemadsl/parser/parser_test.go b/pkg/schemadsl/parser/parser_test.go index 453f89c0c9..f5992e5177 100644 --- a/pkg/schemadsl/parser/parser_test.go +++ b/pkg/schemadsl/parser/parser_test.go @@ -127,6 +127,7 @@ func TestParser(t *testing.T) { for _, test := range parserTests { test := test t.Run(test.name, func(t *testing.T) { + t.Parallel() root := Parse(createAstNode, input.Source(test.name), test.input()) parseTree := getParseTree((root).(*testNode), 0) assert := assert.New(t)