Skip to content

Commit

Permalink
test: add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
alexghr committed Jan 18, 2024
1 parent 030d419 commit 79a3328
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 3 deletions.
115 changes: 115 additions & 0 deletions yarn-project/kv-store/src/lmdb/counter.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { randomBytes } from 'crypto';
import { Database, open } from 'lmdb';

import { LmdbAztecCounter } from './counter.js';

describe('LmdbAztecCounter', () => {
let db: Database;

beforeEach(() => {
db = open({} as any);
});

describe.each([
['floating point number', () => Math.random()],
['integers', () => (Math.random() * 1000) | 0],
['strings', () => randomBytes(8).toString('hex')],
['strings', () => [Math.random(), randomBytes(8).toString('hex')]],
])('counts occurrences of %s values', (_, genKey) => {
let counter: LmdbAztecCounter<ReturnType<typeof genKey>>;
beforeEach(() => {
counter = new LmdbAztecCounter(db, 'test');
});

it('returns 0 for unknown keys', () => {
expect(counter.get(genKey())).toEqual(0);
});

it('increments values', async () => {
const key = genKey();
await counter.update(key, 1);

expect(counter.get(key)).toEqual(1);
});

it('decrements values', async () => {
const key = genKey();
await counter.update(key, 1);
await counter.update(key, -1);

expect(counter.get(key)).toEqual(0);
});

it('increments values by a delta', async () => {
const key = genKey();
await counter.update(key, 1);
await counter.update(key, 2);

expect(counter.get(key)).toEqual(3);
});

it('resets the counter', async () => {
const key = genKey();
await counter.update(key, 1);
await counter.update(key, 2);
await counter.set(key, 0);

expect(counter.get(key)).toEqual(0);
});

it('iterates over entries', async () => {
const key = genKey();
await counter.update(key, 1);
await counter.update(key, 2);

expect([...counter.entries()]).toEqual([[key, 3]]);
});
});

it.each([
[
[
['c', 2342],
['a', 8],
['b', 1],
],
[
['a', 8],
['b', 1],
['c', 2342],
],
],
[
[
[10, 2],
[18, 1],
[1, 2],
],
[
[1, 2],
[10, 2],
[18, 1],
],
],
[
[
[[10, 'a'], 1],
[[10, 'c'], 2],
[[11, 'b'], 1],
[[9, 'f'], 1],
[[10, 'b'], 1],
],
[
[[9, 'f'], 1],
[[10, 'a'], 1],
[[10, 'b'], 1],
[[10, 'c'], 2],
[[11, 'b'], 1],
],
],
])('iterates in key order', async (insertOrder, expectedOrder) => {
const counter = new LmdbAztecCounter(db, 'test');
await Promise.all(insertOrder.map(([key, value]) => counter.update(key, value as number)));
expect([...counter.entries()]).toEqual(expectedOrder);
});
});
9 changes: 8 additions & 1 deletion yarn-project/kv-store/src/lmdb/counter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type CountMapKey<K> = ['count_map', string, 'slot', K];
/**
* A counter implementation backed by LMDB
*/
export class LMDBCounter<K extends Key> implements AztecCounter<K> {
export class LmdbAztecCounter<K extends Key> implements AztecCounter<K> {
#db: Database<[K, number], CountMapKey<K>>;
#name: string;

Expand All @@ -33,9 +33,16 @@ export class LMDBCounter<K extends Key> implements AztecCounter<K> {
const slot = this.#slot(key);
const [_, current] = this.#db.get(slot) ?? [key, 0];
const next = current + delta;

if (next < 0) {
throw new Error(`Cannot update ${key} in counter ${this.#name} below zero`);
}

if (next === 0) {
void this.#db.remove(slot);
} else {
// store the key inside the entry because LMDB might return an internal representation
// of the key when iterating over the database
void this.#db.put(slot, [key, next]);
}

Expand Down
4 changes: 2 additions & 2 deletions yarn-project/kv-store/src/lmdb/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { AztecMap, AztecMultiMap } from '../interfaces/map.js';
import { AztecSingleton } from '../interfaces/singleton.js';
import { AztecKVStore } from '../interfaces/store.js';
import { LmdbAztecArray } from './array.js';
import { LMDBCounter } from './counter.js';
import { LmdbAztecCounter } from './counter.js';
import { LmdbAztecMap } from './map.js';
import { LmdbAztecSingleton } from './singleton.js';

Expand Down Expand Up @@ -91,7 +91,7 @@ export class AztecLmdbStore implements AztecKVStore {
}

createCounter<K extends string | number | Array<string | number>>(name: string): AztecCounter<K> {
return new LMDBCounter(this.#data, name);
return new LmdbAztecCounter(this.#data, name);
}

/**
Expand Down

0 comments on commit 79a3328

Please sign in to comment.