-
Notifications
You must be signed in to change notification settings - Fork 246
/
datastore.go
116 lines (94 loc) · 4.95 KB
/
datastore.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package test
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/require"
core "github.com/authzed/spicedb/pkg/proto/core/v1"
"github.com/authzed/spicedb/pkg/datastore"
"github.com/authzed/spicedb/pkg/namespace"
)
// veryLargeGCWindow is a very large time duration, which when passed to a constructor should
// effectively disable garbage collection.
const (
veryLargeGCWindow = 90000 * time.Second
veryLargeGCInterval = 90000 * time.Second
)
// DatastoreTester provides a generic datastore suite a means of initializing
// a particular datastore.
type DatastoreTester interface {
// New creates a new datastore instance for a single test.
New(revisionQuantization, gcInterval, gcWindow time.Duration, watchBufferLength uint16) (datastore.Datastore, error)
}
type DatastoreTesterFunc func(revisionQuantization, gcInterval, gcWindow time.Duration, watchBufferLength uint16) (datastore.Datastore, error)
func (f DatastoreTesterFunc) New(revisionQuantization, gcInterval, gcWindow time.Duration, watchBufferLength uint16) (datastore.Datastore, error) {
return f(revisionQuantization, gcInterval, gcWindow, watchBufferLength)
}
// AllExceptWatch runs all generic datastore tests on a DatastoreTester, except
// those invoking the watch API.
func AllExceptWatch(t *testing.T, tester DatastoreTester) {
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("TestDeleteRelationships", func(t *testing.T) { DeleteRelationshipsTest(t, tester) })
t.Run("TestInvalidReads", func(t *testing.T) { InvalidReadsTest(t, tester) })
t.Run("TestDeleteNonExistant", func(t *testing.T) { DeleteNotExistantTest(t, tester) })
t.Run("TestDeleteAlreadyDeleted", func(t *testing.T) { DeleteAlreadyDeletedTest(t, tester) })
t.Run("TestWriteDeleteWrite", func(t *testing.T) { WriteDeleteWriteTest(t, tester) })
t.Run("TestCreateAlreadyExisting", func(t *testing.T) { CreateAlreadyExistingTest(t, tester) })
t.Run("TestTouchAlreadyExisting", func(t *testing.T) { TouchAlreadyExistingTest(t, tester) })
t.Run("TestUsersets", func(t *testing.T) { UsersetsTest(t, tester) })
t.Run("TestMultipleReadsInRWT", func(t *testing.T) { MultipleReadsInRWTTest(t, tester) })
t.Run("TestConcurrentWriteSerialization", func(t *testing.T) { ConcurrentWriteSerializationTest(t, tester) })
t.Run("TestRevisionQuantization", func(t *testing.T) { RevisionQuantizationTest(t, tester) })
t.Run("TestRevisionSerialization", func(t *testing.T) { RevisionSerializationTest(t, tester) })
t.Run("TestRevisionGC", func(t *testing.T) { RevisionGCTest(t, tester) })
t.Run("TestStats", func(t *testing.T) { StatsTest(t, tester) })
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) })
}
// All runs all generic datastore tests on a DatastoreTester.
func All(t *testing.T, tester DatastoreTester) {
AllExceptWatch(t, tester)
t.Run("TestWatch", 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) })
}
var testResourceNS = namespace.Namespace(
testResourceNamespace,
namespace.MustRelation(testReaderRelation, nil),
)
var testGroupNS = namespace.Namespace(
testGroupNamespace,
namespace.MustRelation(testMemberRelation, nil),
)
var testUserNS = namespace.Namespace(testUserNamespace)
func makeTestTuple(resourceID, userID string) *core.RelationTuple {
return &core.RelationTuple{
ResourceAndRelation: &core.ObjectAndRelation{
Namespace: testResourceNamespace,
ObjectId: resourceID,
Relation: testReaderRelation,
},
Subject: &core.ObjectAndRelation{
Namespace: testUserNamespace,
ObjectId: userID,
Relation: ellipsis,
},
}
}
func setupDatastore(ds datastore.Datastore, require *require.Assertions) datastore.Revision {
ctx := context.Background()
revision, err := ds.ReadWriteTx(ctx, func(rwt datastore.ReadWriteTransaction) error {
return rwt.WriteNamespaces(ctx, testGroupNS, testResourceNS, testUserNS)
})
require.NoError(err)
return revision
}