keyvaluedb_shared_tests/
lib.rs

1//! Shared tests for keyvaluedb functionality, to be executed against actual implementations.
2
3#![deny(clippy::all)]
4
5use keyvaluedb::{DBKey, DBKeyRef, DBKeyValue, DBKeyValueRef, IoStatsKind, KeyValueDB};
6use std::io;
7
8/// A test for `KeyValueDB::get`.
9pub async fn test_put_and_get<DB: KeyValueDB>(db: DB) -> io::Result<()> {
10    let key1 = b"key1";
11
12    let mut transaction = db.transaction();
13    transaction.put(0, key1, b"horse");
14    db.write(transaction).await.map_err(|e| e.error)?;
15    assert_eq!(db.get(0, key1).await?.unwrap(), b"horse");
16    Ok(())
17}
18
19/// A test for `KeyValueDB::num_keys`.
20pub async fn test_num_keys<DB: KeyValueDB>(db: DB) -> io::Result<()> {
21    let key1 = b"key1";
22    let key2 = b"key2";
23
24    let mut transaction = db.transaction();
25    transaction.put(0, key1, b"horse");
26    transaction.put(0, key2, b"horse2");
27    db.write(transaction).await.map_err(|e| e.error)?;
28    assert_eq!(db.num_keys(0).await?, 2);
29    Ok(())
30}
31
32/// A test for `KeyValueDB::get` and delete with transaction.
33pub async fn test_delete_and_get<DB: KeyValueDB>(db: DB) -> io::Result<()> {
34    let key1 = b"key1";
35
36    let mut transaction = db.transaction();
37    transaction.put(0, key1, b"horse");
38    db.write(transaction).await.map_err(|e| e.error)?;
39    assert_eq!(db.get(0, key1).await?.unwrap(), b"horse");
40
41    let mut transaction = db.transaction();
42    transaction.delete(0, key1);
43    db.write(transaction).await.map_err(|e| e.error)?;
44    assert!(db.get(0, key1).await?.is_none());
45    Ok(())
46}
47
48/// A test for `KeyValueDB::get` and delete without transaction.
49pub async fn test_delete_and_get_single<DB: KeyValueDB>(db: DB) -> io::Result<()> {
50    let key1 = b"key1";
51
52    let mut transaction = db.transaction();
53    transaction.put(0, key1, b"horse");
54    db.write(transaction).await.map_err(|e| e.error)?;
55    assert_eq!(db.get(0, key1).await?.unwrap(), b"horse");
56
57    assert_eq!(db.delete(0, key1).await?, Some(b"horse".to_vec()));
58    assert!(db.get(0, key1).await?.is_none());
59    assert_eq!(db.delete(0, key1).await?, None);
60
61    Ok(())
62}
63
64/// A test for `KeyValueDB::get`.
65/// Assumes the `db` has only 1 column.
66pub async fn test_get_fails_with_non_existing_column<DB: KeyValueDB>(db: DB) -> io::Result<()> {
67    assert!(db.get(1, b"").await.is_err());
68    Ok(())
69}
70
71/// A test for `KeyValueDB::write`.
72pub async fn test_write_clears_buffered_ops<DB: KeyValueDB>(db: DB) -> io::Result<()> {
73    let mut batch = db.transaction();
74    batch.put(0, b"foo", b"bar");
75    db.write(batch).await.map_err(|e| e.error)?;
76
77    assert_eq!(db.get(0, b"foo").await?.unwrap(), b"bar");
78
79    let mut batch = db.transaction();
80    batch.put(0, b"foo", b"baz");
81    db.write(batch).await.map_err(|e| e.error)?;
82
83    assert_eq!(db.get(0, b"foo").await?.unwrap(), b"baz");
84    Ok(())
85}
86
87/// A test for `KeyValueDB::iter`.
88pub async fn test_iter<DB: KeyValueDB>(db: DB) -> io::Result<()> {
89    let key1 = b"key1";
90    let key2 = b"key2";
91
92    let mut transaction = db.transaction();
93    transaction.put(0, key1, key1);
94    transaction.put(0, key2, key2);
95    db.write(transaction).await.map_err(|e| e.error)?;
96
97    let mut contents: Vec<DBKeyValue> = Vec::new();
98    let out = db
99        .iter(0, None, |kv: DBKeyValueRef| {
100            contents.push((kv.0.clone(), kv.1.clone()));
101            Ok(Option::<()>::None)
102        })
103        .await?;
104    assert!(out.is_none());
105    assert_eq!(contents.len(), 2);
106    assert_eq!(contents[0].0, key1);
107    assert_eq!(contents[0].1, key1);
108    assert_eq!(contents[1].0, key2);
109    assert_eq!(contents[1].1, key2);
110
111    // test iter with early return
112    let mut contents: Vec<DBKeyValue> = Vec::new();
113    let out = db
114        .iter(0, None, |kv: DBKeyValueRef| {
115            contents.push((kv.0.clone(), kv.1.clone()));
116            Ok(Option::<()>::Some(()))
117        })
118        .await?;
119    assert!(out.is_some());
120    assert_eq!(contents.len(), 1);
121    assert_eq!(contents[0].0, key1);
122    assert_eq!(contents[0].1, key1);
123    Ok(())
124}
125
126/// A test for `KeyValueDB::iter_keys`.
127pub async fn test_iter_keys<DB: KeyValueDB>(db: DB) -> io::Result<()> {
128    let key1 = b"key1";
129    let key2 = b"key2";
130
131    let mut transaction = db.transaction();
132    transaction.put(0, key1, key1);
133    transaction.put(0, key2, key2);
134    db.write(transaction).await.map_err(|e| e.error)?;
135
136    let mut contents: Vec<DBKey> = Vec::new();
137    let out = db
138        .iter_keys(0, None, |k: DBKeyRef| {
139            contents.push(k.clone());
140            Ok(Option::<()>::None)
141        })
142        .await?;
143    assert!(out.is_none());
144    assert_eq!(contents.len(), 2);
145    assert_eq!(contents[0], key1);
146    assert_eq!(contents[1], key2);
147
148    // test iter keys with early return
149    let mut contents: Vec<DBKey> = Vec::new();
150    let out = db
151        .iter_keys(0, None, |k: DBKeyRef| {
152            contents.push(k.clone());
153            Ok(Option::<()>::Some(()))
154        })
155        .await?;
156    assert!(out.is_some());
157    assert_eq!(contents.len(), 1);
158    assert_eq!(contents[0], key1);
159
160    Ok(())
161}
162
163/// A test for `KeyValueDB::iter` with a prefix.
164pub async fn test_iter_with_prefix<DB: KeyValueDB>(db: DB) -> io::Result<()> {
165    let key1 = b"0";
166    let key2 = b"ab";
167    let key3 = b"abc";
168    let key4 = b"abcd";
169
170    let mut batch = db.transaction();
171    batch.put(0, key1, key1);
172    batch.put(0, key2, key2);
173    batch.put(0, key3, key3);
174    batch.put(0, key4, key4);
175    db.write(batch).await.map_err(|e| e.error)?;
176
177    // empty prefix
178    let mut contents: Vec<DBKeyValue> = Vec::new();
179    let out = db
180        .iter(0, Some(b""), |kv: DBKeyValueRef| {
181            contents.push((kv.0.clone(), kv.1.clone()));
182            Ok(Option::<()>::None)
183        })
184        .await?;
185    assert!(out.is_none());
186    assert_eq!(contents.len(), 4);
187    assert_eq!(contents[0].0, key1);
188    assert_eq!(contents[1].0, key2);
189    assert_eq!(contents[2].0, key3);
190    assert_eq!(contents[3].0, key4);
191
192    // empty prefix with early return
193    let mut contents: Vec<DBKeyValue> = Vec::new();
194    let out = db
195        .iter(0, Some(b""), |kv: DBKeyValueRef| {
196            contents.push((kv.0.clone(), kv.1.clone()));
197            Ok(Option::<()>::Some(()))
198        })
199        .await?;
200    assert!(out.is_some());
201    assert_eq!(contents.len(), 1);
202    assert_eq!(contents[0].0, key1);
203
204    // prefix a
205    let mut contents: Vec<DBKeyValue> = Vec::new();
206    db.iter(0, Some(b"a"), |kv: DBKeyValueRef| {
207        contents.push((kv.0.clone(), kv.1.clone()));
208        Ok(Option::<()>::None)
209    })
210    .await?;
211    assert_eq!(contents.len(), 3);
212    assert_eq!(contents[0].0, key2);
213    assert_eq!(contents[1].0, key3);
214    assert_eq!(contents[2].0, key4);
215
216    // prefix abc
217    let mut contents: Vec<DBKeyValue> = Vec::new();
218    db.iter(0, Some(b"abc"), |kv: DBKeyValueRef| {
219        contents.push((kv.0.clone(), kv.1.clone()));
220        Ok(Option::<()>::None)
221    })
222    .await?;
223    assert_eq!(contents.len(), 2);
224    assert_eq!(contents[0].0, key3);
225    assert_eq!(contents[1].0, key4);
226
227    // prefix abcde
228    let mut contents: Vec<DBKeyValue> = Vec::new();
229    db.iter(0, Some(b"abcde"), |kv: DBKeyValueRef| {
230        contents.push((kv.0.clone(), kv.1.clone()));
231        Ok(Option::<()>::None)
232    })
233    .await?;
234    assert_eq!(contents.len(), 0);
235
236    // prefix 0
237    let mut contents: Vec<DBKeyValue> = Vec::new();
238    db.iter(0, Some(b"0"), |kv: DBKeyValueRef| {
239        contents.push((kv.0.clone(), kv.1.clone()));
240        Ok(Option::<()>::None)
241    })
242    .await?;
243    assert_eq!(contents.len(), 1);
244    assert_eq!(contents[0].0, key1);
245    Ok(())
246}
247
248/// The number of columns required to run `test_io_stats`.
249pub const IO_STATS_NUM_COLUMNS: u32 = 3;
250
251/// A test for `KeyValueDB::io_stats`.
252/// Assumes that the `db` has at least 3 columns.
253pub async fn test_io_stats<DB: KeyValueDB>(db: DB) -> io::Result<()> {
254    let key1 = b"kkk";
255    let mut batch = db.transaction();
256    batch.put(0, key1, key1);
257    batch.put(1, key1, key1);
258    batch.put(2, key1, key1);
259
260    for _ in 0..10 {
261        db.get(0, key1).await?;
262    }
263
264    db.write(batch).await.map_err(|e| e.error)?;
265
266    let io_stats = db.io_stats(IoStatsKind::SincePrevious);
267    assert_eq!(io_stats.transactions, 1);
268    assert_eq!(io_stats.writes, 3);
269    assert_eq!(io_stats.bytes_written, 18);
270    assert_eq!(io_stats.reads, 10);
271    assert_eq!(io_stats.bytes_read, 30);
272
273    let new_io_stats = db.io_stats(IoStatsKind::SincePrevious);
274    // Since we taken previous statistic period,
275    // this is expected to be totally empty.
276    assert_eq!(new_io_stats.transactions, 0);
277
278    // but the overall should be there
279    let new_io_stats = db.io_stats(IoStatsKind::Overall);
280    assert_eq!(new_io_stats.bytes_written, 18);
281
282    let mut batch = db.transaction();
283    batch.delete(0, key1);
284    batch.delete(1, key1);
285    batch.delete(2, key1);
286
287    // transaction is not commited yet
288    assert_eq!(db.io_stats(IoStatsKind::SincePrevious).writes, 0);
289
290    db.write(batch).await.map_err(|e| e.error)?;
291    // now it is, and delete is counted as write
292    assert_eq!(db.io_stats(IoStatsKind::SincePrevious).writes, 3);
293    Ok(())
294}
295
296/// The number of columns required to run `test_delete_prefix`.
297pub const DELETE_PREFIX_NUM_COLUMNS: u32 = 7;
298
299/// A test for `KeyValueDB::delete_prefix`.
300pub async fn test_delete_prefix<DB: KeyValueDB + 'static>(db: DB) -> io::Result<()> {
301    let keys = [
302        &[][..],
303        &[0u8][..],
304        &[0, 1][..],
305        &[1][..],
306        &[1, 0][..],
307        &[1, 255][..],
308        &[1, 255, 255][..],
309        &[2][..],
310        &[2, 0][..],
311        &[2, 255][..],
312        &[255; 16][..],
313    ];
314    let tests: [_; DELETE_PREFIX_NUM_COLUMNS as usize] = [
315        // standard
316        (
317            &[1u8][..],
318            [
319                true, true, true, false, false, false, false, true, true, true, true,
320            ],
321        ),
322        // edge
323        (
324            &[1u8, 255, 255][..],
325            [
326                true, true, true, true, true, true, false, true, true, true, true,
327            ],
328        ),
329        // none 1
330        (
331            &[1, 2][..],
332            [
333                true, true, true, true, true, true, true, true, true, true, true,
334            ],
335        ),
336        // none 2
337        (
338            &[8][..],
339            [
340                true, true, true, true, true, true, true, true, true, true, true,
341            ],
342        ),
343        // last value
344        (
345            &[255, 255][..],
346            [
347                true, true, true, true, true, true, true, true, true, true, false,
348            ],
349        ),
350        // last value, limit prefix
351        (
352            &[255][..],
353            [
354                true, true, true, true, true, true, true, true, true, true, false,
355            ],
356        ),
357        // all
358        (
359            &[][..],
360            [
361                false, false, false, false, false, false, false, false, false, false, false,
362            ],
363        ),
364    ];
365    for (ix, test) in tests.iter().enumerate() {
366        let ix = ix as u32;
367
368        // Init Transaction
369        let mut batch = db.transaction();
370        for (i, key) in keys.iter().enumerate() {
371            batch.put(ix, key, [i as u8]);
372        }
373        db.write(batch).await.map_err(|e| e.error)?;
374
375        // Delete Transaction
376        let mut batch = db.transaction();
377        batch.delete_prefix(ix, test.0);
378        db.write(batch).await.map_err(|e| e.error)?;
379
380        // Check Test
381        let mut state = [true; 11];
382        for (c, key) in keys.iter().enumerate() {
383            state[c] = db.get(ix, key).await?.is_some();
384        }
385        assert_eq!(state, test.1, "at {}", ix);
386    }
387
388    Ok(())
389}
390
391/// A complex test.
392pub async fn test_complex<DB: KeyValueDB>(db: DB) -> io::Result<()> {
393    let key1 = b"02c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
394    let key2 = b"03c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
395    let key3 = b"04c00000000b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
396    let key4 = b"04c01111110b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
397    let key5 = b"04c02222220b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
398
399    let mut batch = db.transaction();
400    batch.put(0, key1, b"cat");
401    batch.put(0, key2, b"dog");
402    batch.put(0, key3, b"caterpillar");
403    batch.put(0, key4, b"beef");
404    batch.put(0, key5, b"fish");
405    db.write(batch).await.map_err(|e| e.error)?;
406
407    assert_eq!(db.get(0, key1).await?.unwrap(), b"cat");
408
409    let mut contents: Vec<DBKeyValue> = Vec::new();
410    db.iter(0, None, |kv: DBKeyValueRef| {
411        contents.push((kv.0.clone(), kv.1.clone()));
412        Ok(Option::<()>::None)
413    })
414    .await?;
415    assert_eq!(contents.len(), 5);
416    assert_eq!(contents[0].0, key1.to_vec());
417    assert_eq!(contents[0].1, b"cat");
418    assert_eq!(contents[1].0, key2.to_vec());
419    assert_eq!(contents[1].1, b"dog");
420
421    let mut contents: Vec<DBKeyValue> = Vec::new();
422    db.iter(0, Some(b"04c0"), |kv: DBKeyValueRef| {
423        contents.push((kv.0.clone(), kv.1.clone()));
424        Ok(Option::<()>::None)
425    })
426    .await?;
427    assert_eq!(contents[0].1, b"caterpillar");
428    assert_eq!(contents[1].1, b"beef");
429    assert_eq!(contents[2].1, b"fish");
430
431    let mut batch = db.transaction();
432    batch.delete(0, key1);
433    db.write(batch).await.map_err(|e| e.error)?;
434
435    assert!(db.get(0, key1).await?.is_none());
436
437    let mut batch = db.transaction();
438    batch.put(0, key1, b"cat");
439    db.write(batch).await.map_err(|e| e.error)?;
440
441    let mut transaction = db.transaction();
442    transaction.put(0, key3, b"elephant");
443    transaction.delete(0, key1);
444    db.write(transaction).await.map_err(|e| e.error)?;
445    assert!(db.get(0, key1).await?.is_none());
446    assert_eq!(db.get(0, key3).await?.unwrap(), b"elephant");
447
448    assert_eq!(
449        db.first_with_prefix(0, key3).await?.unwrap(),
450        (key3.to_vec(), b"elephant".to_vec())
451    );
452    assert_eq!(
453        db.first_with_prefix(0, key2).await?.unwrap(),
454        (key2.to_vec(), b"dog".to_vec())
455    );
456
457    let mut transaction = db.transaction();
458    transaction.put(0, key1, b"horse");
459    transaction.delete(0, key3);
460    db.write(transaction).await.map_err(|e| e.error)?;
461    assert!(db.get(0, key3).await?.is_none());
462    assert_eq!(db.get(0, key1).await?.unwrap(), b"horse");
463
464    assert!(db.get(0, key3).await?.is_none());
465    assert_eq!(db.get(0, key1).await?.unwrap(), b"horse");
466    Ok(())
467}