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 contents: Vec<DBKeyValue> = Vec::new();
98    let (contents, out) = db
99        .iter(0, None, contents, |contents, 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 contents: Vec<DBKeyValue> = Vec::new();
113    let (contents, out) = db
114        .iter(0, None, contents, |contents, 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 contents: Vec<DBKey> = Vec::new();
137    let (contents, out) = db
138        .iter_keys(0, None, contents, |contents, 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 contents: Vec<DBKey> = Vec::new();
150    let (contents, out) = db
151        .iter_keys(0, None, contents, |contents, 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 contents: Vec<DBKeyValue> = Vec::new();
179    let (contents, out) = db
180        .iter(0, Some(b""), contents, |contents, 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 contents: Vec<DBKeyValue> = Vec::new();
194    let (contents, out) = db
195        .iter(0, Some(b""), contents, |contents, 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 contents: Vec<DBKeyValue> = Vec::new();
206    let (contents, _) = db
207        .iter(0, Some(b"a"), contents, |contents, kv: DBKeyValueRef| {
208            contents.push((kv.0.clone(), kv.1.clone()));
209            Ok(Option::<()>::None)
210        })
211        .await?;
212    assert_eq!(contents.len(), 3);
213    assert_eq!(contents[0].0, key2);
214    assert_eq!(contents[1].0, key3);
215    assert_eq!(contents[2].0, key4);
216
217    // prefix abc
218    let contents: Vec<DBKeyValue> = Vec::new();
219    let (contents, _) = db
220        .iter(0, Some(b"abc"), contents, |contents, kv: DBKeyValueRef| {
221            contents.push((kv.0.clone(), kv.1.clone()));
222            Ok(Option::<()>::None)
223        })
224        .await?;
225    assert_eq!(contents.len(), 2);
226    assert_eq!(contents[0].0, key3);
227    assert_eq!(contents[1].0, key4);
228
229    // prefix abcde
230    let contents: Vec<DBKeyValue> = Vec::new();
231    let (contents, _) = db
232        .iter(
233            0,
234            Some(b"abcde"),
235            contents,
236            |contents, kv: DBKeyValueRef| {
237                contents.push((kv.0.clone(), kv.1.clone()));
238                Ok(Option::<()>::None)
239            },
240        )
241        .await?;
242    assert_eq!(contents.len(), 0);
243
244    // prefix 0
245    let contents: Vec<DBKeyValue> = Vec::new();
246    let (contents, _) = db
247        .iter(0, Some(b"0"), contents, |contents, kv: DBKeyValueRef| {
248            contents.push((kv.0.clone(), kv.1.clone()));
249            Ok(Option::<()>::None)
250        })
251        .await?;
252    assert_eq!(contents.len(), 1);
253    assert_eq!(contents[0].0, key1);
254    Ok(())
255}
256
257/// The number of columns required to run `test_io_stats`.
258pub const IO_STATS_NUM_COLUMNS: u32 = 3;
259
260/// A test for `KeyValueDB::io_stats`.
261/// Assumes that the `db` has at least 3 columns.
262pub async fn test_io_stats<DB: KeyValueDB>(db: DB) -> io::Result<()> {
263    let key1 = b"kkk";
264    let mut batch = db.transaction();
265    batch.put(0, key1, key1);
266    batch.put(1, key1, key1);
267    batch.put(2, key1, key1);
268
269    for _ in 0..10 {
270        db.get(0, key1).await?;
271    }
272
273    db.write(batch).await.map_err(|e| e.error)?;
274
275    let io_stats = db.io_stats(IoStatsKind::SincePrevious);
276    assert_eq!(io_stats.transactions, 1);
277    assert_eq!(io_stats.writes, 3);
278    assert_eq!(io_stats.bytes_written, 18);
279    assert_eq!(io_stats.reads, 10);
280    assert_eq!(io_stats.bytes_read, 30);
281
282    let new_io_stats = db.io_stats(IoStatsKind::SincePrevious);
283    // Since we taken previous statistic period,
284    // this is expected to be totally empty.
285    assert_eq!(new_io_stats.transactions, 0);
286
287    // but the overall should be there
288    let new_io_stats = db.io_stats(IoStatsKind::Overall);
289    assert_eq!(new_io_stats.bytes_written, 18);
290
291    let mut batch = db.transaction();
292    batch.delete(0, key1);
293    batch.delete(1, key1);
294    batch.delete(2, key1);
295
296    // transaction is not commited yet
297    assert_eq!(db.io_stats(IoStatsKind::SincePrevious).writes, 0);
298
299    db.write(batch).await.map_err(|e| e.error)?;
300    // now it is, and delete is counted as write
301    assert_eq!(db.io_stats(IoStatsKind::SincePrevious).writes, 3);
302    Ok(())
303}
304
305/// The number of columns required to run `test_delete_prefix`.
306pub const DELETE_PREFIX_NUM_COLUMNS: u32 = 7;
307
308/// A test for `KeyValueDB::delete_prefix`.
309pub async fn test_delete_prefix<DB: KeyValueDB + 'static>(db: DB) -> io::Result<()> {
310    let keys = [
311        &[][..],
312        &[0u8][..],
313        &[0, 1][..],
314        &[1][..],
315        &[1, 0][..],
316        &[1, 255][..],
317        &[1, 255, 255][..],
318        &[2][..],
319        &[2, 0][..],
320        &[2, 255][..],
321        &[255; 16][..],
322    ];
323    let tests: [_; DELETE_PREFIX_NUM_COLUMNS as usize] = [
324        // standard
325        (
326            &[1u8][..],
327            [
328                true, true, true, false, false, false, false, true, true, true, true,
329            ],
330        ),
331        // edge
332        (
333            &[1u8, 255, 255][..],
334            [
335                true, true, true, true, true, true, false, true, true, true, true,
336            ],
337        ),
338        // none 1
339        (
340            &[1, 2][..],
341            [
342                true, true, true, true, true, true, true, true, true, true, true,
343            ],
344        ),
345        // none 2
346        (
347            &[8][..],
348            [
349                true, true, true, true, true, true, true, true, true, true, true,
350            ],
351        ),
352        // last value
353        (
354            &[255, 255][..],
355            [
356                true, true, true, true, true, true, true, true, true, true, false,
357            ],
358        ),
359        // last value, limit prefix
360        (
361            &[255][..],
362            [
363                true, true, true, true, true, true, true, true, true, true, false,
364            ],
365        ),
366        // all
367        (
368            &[][..],
369            [
370                false, false, false, false, false, false, false, false, false, false, false,
371            ],
372        ),
373    ];
374    for (ix, test) in tests.iter().enumerate() {
375        let ix = ix as u32;
376
377        // Init Transaction
378        let mut batch = db.transaction();
379        for (i, key) in keys.iter().enumerate() {
380            batch.put(ix, key, [i as u8]);
381        }
382        db.write(batch).await.map_err(|e| e.error)?;
383
384        // Delete Transaction
385        let mut batch = db.transaction();
386        batch.delete_prefix(ix, test.0);
387        db.write(batch).await.map_err(|e| e.error)?;
388
389        // Check Test
390        let mut state = [true; 11];
391        for (c, key) in keys.iter().enumerate() {
392            state[c] = db.get(ix, key).await?.is_some();
393        }
394        assert_eq!(state, test.1, "at {}", ix);
395    }
396
397    Ok(())
398}
399
400/// A complex test.
401pub async fn test_complex<DB: KeyValueDB>(db: DB) -> io::Result<()> {
402    let key1 = b"02c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
403    let key2 = b"03c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
404    let key3 = b"04c00000000b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
405    let key4 = b"04c01111110b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
406    let key5 = b"04c02222220b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
407
408    let mut batch = db.transaction();
409    batch.put(0, key1, b"cat");
410    batch.put(0, key2, b"dog");
411    batch.put(0, key3, b"caterpillar");
412    batch.put(0, key4, b"beef");
413    batch.put(0, key5, b"fish");
414    db.write(batch).await.map_err(|e| e.error)?;
415
416    assert_eq!(db.get(0, key1).await?.unwrap(), b"cat");
417
418    let contents: Vec<DBKeyValue> = Vec::new();
419    let (contents, _) = db
420        .iter(0, None, contents, |contents, kv: DBKeyValueRef| {
421            contents.push((kv.0.clone(), kv.1.clone()));
422            Ok(Option::<()>::None)
423        })
424        .await?;
425    assert_eq!(contents.len(), 5);
426    assert_eq!(contents[0].0, key1.to_vec());
427    assert_eq!(contents[0].1, b"cat");
428    assert_eq!(contents[1].0, key2.to_vec());
429    assert_eq!(contents[1].1, b"dog");
430
431    let contents: Vec<DBKeyValue> = Vec::new();
432    let (contents, _) = db
433        .iter(0, Some(b"04c0"), contents, |contents, kv: DBKeyValueRef| {
434            contents.push((kv.0.clone(), kv.1.clone()));
435            Ok(Option::<()>::None)
436        })
437        .await?;
438    assert_eq!(contents[0].1, b"caterpillar");
439    assert_eq!(contents[1].1, b"beef");
440    assert_eq!(contents[2].1, b"fish");
441
442    let mut batch = db.transaction();
443    batch.delete(0, key1);
444    db.write(batch).await.map_err(|e| e.error)?;
445
446    assert!(db.get(0, key1).await?.is_none());
447
448    let mut batch = db.transaction();
449    batch.put(0, key1, b"cat");
450    db.write(batch).await.map_err(|e| e.error)?;
451
452    let mut transaction = db.transaction();
453    transaction.put(0, key3, b"elephant");
454    transaction.delete(0, key1);
455    db.write(transaction).await.map_err(|e| e.error)?;
456    assert!(db.get(0, key1).await?.is_none());
457    assert_eq!(db.get(0, key3).await?.unwrap(), b"elephant");
458
459    assert_eq!(
460        db.first_with_prefix(0, key3).await?.unwrap(),
461        (key3.to_vec(), b"elephant".to_vec())
462    );
463    assert_eq!(
464        db.first_with_prefix(0, key2).await?.unwrap(),
465        (key2.to_vec(), b"dog".to_vec())
466    );
467
468    let mut transaction = db.transaction();
469    transaction.put(0, key1, b"horse");
470    transaction.delete(0, key3);
471    db.write(transaction).await.map_err(|e| e.error)?;
472    assert!(db.get(0, key3).await?.is_none());
473    assert_eq!(db.get(0, key1).await?.unwrap(), b"horse");
474
475    assert!(db.get(0, key3).await?.is_none());
476    assert_eq!(db.get(0, key1).await?.unwrap(), b"horse");
477    Ok(())
478}
479
480pub async fn test_cleanup<DB: KeyValueDB>(db: DB) -> io::Result<()> {
481    db.cleanup().await
482}