@@ -103,3 +103,149 @@ func TestFlushing(t *testing.T) {
103
103
t .Fatal ("wrong value" )
104
104
}
105
105
}
106
+
107
+ func TestSync (t * testing.T ) {
108
+ child := ds .NewMapDatastore ()
109
+ d := NewAutoBatching (child , 100 )
110
+
111
+ put := func (key ds.Key ) {
112
+ if err := d .Put (key , []byte (key .String ())); err != nil {
113
+ t .Fatal (err )
114
+ }
115
+ }
116
+ del := func (key ds.Key ) {
117
+ if err := d .Delete (key ); err != nil {
118
+ t .Fatal (err )
119
+ }
120
+ }
121
+
122
+ get := func (d ds.Datastore , key ds.Key ) {
123
+ val , err := d .Get (key )
124
+ if err != nil {
125
+ t .Fatal (err )
126
+ }
127
+
128
+ if ! bytes .Equal (val , []byte (key .String ())) {
129
+ t .Fatal ("wrong value" )
130
+ }
131
+ }
132
+ invalidGet := func (d ds.Datastore , key ds.Key ) {
133
+ if _ , err := d .Get (key ); err != ds .ErrNotFound {
134
+ t .Fatal ("should not have found value" )
135
+ }
136
+ }
137
+
138
+ // Test if Syncing Puts works
139
+ internalSyncTest (t , d , child , put , del , get , invalidGet )
140
+
141
+ // Test if Syncing Deletes works
142
+ internalSyncTest (t , d , child , del , put , invalidGet , get )
143
+ }
144
+
145
+ // This function can be used to test Sync Puts and Deletes
146
+ // For clarity comments are written as if op = Put and undoOp = Delete
147
+ func internalSyncTest (t * testing.T , d , child ds.Datastore , op , undoOp func (ds.Key ),
148
+ checkOp , checkUndoOp func (ds.Datastore , ds.Key )) {
149
+ var keys []ds.Key
150
+ keymap := make (map [ds.Key ]int )
151
+ for i := 0 ; i < 4 ; i ++ {
152
+ k := ds .NewKey (fmt .Sprintf ("%d" , i ))
153
+ keymap [k ] = len (keys )
154
+ keys = append (keys , k )
155
+ for j := 0 ; j < 2 ; j ++ {
156
+ k := ds .NewKey (fmt .Sprintf ("%d/%d" , i , j ))
157
+ keymap [k ] = len (keys )
158
+ keys = append (keys , k )
159
+ for k := 0 ; k < 2 ; k ++ {
160
+ k := ds .NewKey (fmt .Sprintf ("%d/%d/%d" , i , j , k ))
161
+ keymap [k ] = len (keys )
162
+ keys = append (keys , k )
163
+ }
164
+ }
165
+ }
166
+
167
+ for _ , k := range keys {
168
+ op (k )
169
+ }
170
+
171
+ // Get works normally.
172
+ for _ , k := range keys {
173
+ checkOp (d , k )
174
+ }
175
+
176
+ // Put not flushed
177
+ checkUndoOp (child , ds .NewKey ("0" ))
178
+
179
+ // Delete works.
180
+ deletedKey := ds .NewKey ("2/1/1" )
181
+ undoOp (deletedKey )
182
+ checkUndoOp (d , deletedKey )
183
+
184
+ // Put still not flushed
185
+ checkUndoOp (child , ds .NewKey ("0" ))
186
+
187
+ // Sync the tree "0/*/*"
188
+ if err := d .Sync (ds .NewKey ("0" )); err != nil {
189
+ t .Fatal (err )
190
+ }
191
+
192
+ // Try to get keys "0/*/*" from the child datastore
193
+ checkKeyRange (t , keymap , keys , d , [][]string {{"0" , "0/1/1" }}, checkOp )
194
+
195
+ // Verify no other keys were synchronized
196
+ checkKeyRange (t , keymap , keys , child , [][]string {{"1" , "3/1/1" }}, checkUndoOp )
197
+
198
+ // Sync the tree "1/1/*"
199
+ if err := d .Sync (ds .NewKey ("1/1" )); err != nil {
200
+ t .Fatal (err )
201
+ }
202
+
203
+ // Try to get keys "0/*/*" and "1/1/*" from the child datastore
204
+ checkKeyRange (t , keymap , keys , d , [][]string {{"0" , "0/1/1" }, {"1/1" , "1/1/1" }}, checkOp )
205
+
206
+ // Verify no other keys were synchronized
207
+ checkKeyRange (t , keymap , keys , child , [][]string {{"1" , "1/0/1" }, {"2" , "3/1/1" }}, checkUndoOp )
208
+
209
+ // Sync the tree "3/1/1"
210
+ if err := d .Sync (ds .NewKey ("3/1/1" )); err != nil {
211
+ t .Fatal (err )
212
+ }
213
+
214
+ // Try to get keys "0/*/*", "1/1/*", "3/1/1" from the child datastore
215
+ checkKeyRange (t , keymap , keys , d , [][]string {{"0" , "0/1/1" }, {"1/1" , "1/1/1" }, {"3/1/1" , "3/1/1" }}, checkOp )
216
+
217
+ // Verify no other keys were synchronized
218
+ checkKeyRange (t , keymap , keys , child , [][]string {{"1" , "1/0/1" }, {"2" , "3/1/0" }}, checkUndoOp )
219
+
220
+ if err := d .Sync (ds.Key {}); err != nil {
221
+ t .Fatal (err )
222
+ }
223
+
224
+ // Never flushed the deleted key.
225
+ checkUndoOp (child , deletedKey )
226
+
227
+ // Try to get all keys except the deleted key from the child datastore
228
+ checkKeyRange (t , keymap , keys , d , [][]string {{"0" , "2/1/0" }, {"3" , "3/1/1" }}, checkOp )
229
+
230
+ // Add the deleted key into the datastore
231
+ op (deletedKey )
232
+
233
+ // Sync it
234
+ if err := d .Sync (deletedKey ); err != nil {
235
+ t .Fatal (err )
236
+ }
237
+
238
+ // Check it
239
+ checkOp (d , deletedKey )
240
+ }
241
+
242
+ func checkKeyRange (t * testing.T , keymap map [ds.Key ]int , keys []ds.Key ,
243
+ d ds.Datastore , validKeyRanges [][]string , checkFn func (ds.Datastore , ds.Key )) {
244
+ t .Helper ()
245
+ for _ , validKeyBoundaries := range validKeyRanges {
246
+ start , end := keymap [ds .NewKey (validKeyBoundaries [0 ])], keymap [ds .NewKey (validKeyBoundaries [1 ])]
247
+ for _ , k := range keys [start :end ] {
248
+ checkFn (d , k )
249
+ }
250
+ }
251
+ }
0 commit comments