diff --git a/pkg/datastore/test/datastore.go b/pkg/datastore/test/datastore.go index 0addafb726..48ef11e6a4 100644 --- a/pkg/datastore/test/datastore.go +++ b/pkg/datastore/test/datastore.go @@ -113,6 +113,8 @@ func AllWithExceptions(t *testing.T, tester DatastoreTester, except Categories) 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) }) if !except.GC() { t.Run("TestRevisionGC", func(t *testing.T) { RevisionGCTest(t, tester) }) diff --git a/pkg/datastore/test/revisions.go b/pkg/datastore/test/revisions.go index bda389e35c..1c42d69932 100644 --- a/pkg/datastore/test/revisions.go +++ b/pkg/datastore/test/revisions.go @@ -3,6 +3,7 @@ package test import ( "context" "fmt" + "sync" "testing" "time" @@ -170,3 +171,57 @@ func RevisionGCTest(t *testing.T, tester DatastoreTester) { require.NoError(ds.CheckRevision(ctx, newerRev), "expected newer head revision to be within GC Window") require.Error(ds.CheckRevision(ctx, previousRev), "expected revision head-1 to be outside GC Window") } + +func SequentialRevisionsTest(t *testing.T, tester DatastoreTester) { + require := require.New(t) + + ds, err := tester.New(0, 10*time.Second, 300*time.Minute, 1) + require.NoError(err) + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + var previous datastore.Revision + for i := 0; i < 50; i++ { + head, err := ds.HeadRevision(ctx) + require.NoError(err) + require.NoError(ds.CheckRevision(ctx, head), "expected head revision to be valid in GC Window") + + if previous != nil { + require.True(head.GreaterThan(previous) || head.Equal(previous)) + } + + previous = head + } +} + +func ConcurrentRevisionsTest(t *testing.T, tester DatastoreTester) { + require := require.New(t) + + ds, err := tester.New(0, 10*time.Second, 300*time.Minute, 1) + require.NoError(err) + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + var wg sync.WaitGroup + wg.Add(10) + + startingRev, err := ds.HeadRevision(ctx) + require.NoError(err) + + for i := 0; i < 10; i++ { + go func() { + defer wg.Done() + + for i := 0; i < 5; i++ { + head, err := ds.HeadRevision(ctx) + require.NoError(err) + require.NoError(ds.CheckRevision(ctx, head), "expected head revision to be valid in GC Window") + require.True(head.GreaterThan(startingRev) || head.Equal(startingRev)) + } + }() + } + + wg.Wait() +}