@convex-dev/aggregate
Version:
[](https://badge.fury.io/js/@convex-dev%2Faggregate)
206 lines (200 loc) • 6.08 kB
text/typescript
import { describe, expect, test } from "vitest";
import { convexTest } from "convex-test";
import schema from "./schema.js";
import { modules } from "./setup.test.js";
import {
atOffsetHandler,
aggregateBetweenHandler,
deleteHandler,
getHandler,
insertHandler,
offsetHandler,
sumHandler,
validateTree,
getOrCreateTree,
} from "./btree.js";
describe("btree", () => {
test("insert", async () => {
const t = convexTest(schema, modules);
await t.run(async (ctx) => {
await getOrCreateTree(ctx.db, 4, false);
// Insert lots of keys. At each stage, the tree is valid.
async function insert(key: number, value: string) {
await insertHandler(ctx, { key, value });
await validateTree(ctx);
const get = await getHandler(ctx, { key });
expect(get).toEqual({
k: key,
v: value,
s: 0,
});
}
await insert(1, "a");
await insert(4, "b");
await insert(3, "c");
await insert(2, "d");
await insert(5, "e");
await insert(6, "e");
await insert(7, "e");
await insert(10, "e");
await insert(0, "e");
await insert(-1, "e");
await insert(9, "e");
await insert(8, "e");
});
});
test("delete", async () => {
const t = convexTest(schema, modules);
await t.run(async (ctx) => {
await getOrCreateTree(ctx.db, 4, false);
async function insert(key: number, value: string) {
await insertHandler(ctx, { key, value });
await validateTree(ctx);
const get = await getHandler(ctx, { key });
expect(get).toEqual({
k: key,
v: value,
s: 0,
});
}
// Delete keys. At each stage, the tree is valid.
async function del(key: number) {
await deleteHandler(ctx, { key });
await validateTree(ctx);
const get = await getHandler(ctx, { key });
expect(get).toBeNull();
}
await insert(1, "a");
await insert(2, "b");
await del(1);
await del(2);
await insert(1, "a");
await insert(2, "a");
await insert(3, "c");
await insert(4, "d");
await insert(5, "e");
await del(3);
await insert(6, "e");
await insert(7, "e");
await insert(10, "e");
await insert(0, "e");
await insert(-1, "e");
await insert(9, "e");
await insert(8, "e");
await del(-1);
await del(6);
await del(7);
await del(0);
});
});
test("atOffset and offsetOf", async () => {
const t = convexTest(schema, modules);
await t.run(async (ctx) => {
await getOrCreateTree(ctx.db, 4, false);
async function insert(key: number, value: string) {
await insertHandler(ctx, { key, value });
await validateTree(ctx);
const rank = await offsetHandler(ctx, { key });
expect(rank).not.toBeNull();
const atIndex = await atOffsetHandler(ctx, {
offset: rank!,
});
expect(atIndex).toEqual({
k: key,
v: value,
s: 0,
});
}
async function checkRank(key: number, rank: number) {
const r = await offsetHandler(ctx, { key });
expect(r).toEqual(rank);
const atOffset = await atOffsetHandler(ctx, { offset: rank });
expect(atOffset.k).toEqual(key);
}
await insert(1, "a");
await insert(4, "b");
await insert(3, "c");
await insert(2, "d");
await insert(5, "e");
await insert(6, "e");
await insert(7, "e");
await insert(10, "e");
await insert(0, "e");
await insert(-1, "e");
await insert(9, "e");
await insert(8, "e");
await checkRank(-1, 0);
await checkRank(10, 11);
await checkRank(5, 6);
});
});
test("countBetween", async () => {
const t = convexTest(schema, modules);
await t.run(async (ctx) => {
await getOrCreateTree(ctx.db, 4, false);
async function insert(key: number, value: string) {
await insertHandler(ctx, { key, value });
await validateTree(ctx);
}
async function countBetween(
k1: number | undefined,
k2: number | undefined,
count: number
) {
const c = await aggregateBetweenHandler(ctx, { k1, k2 });
expect(c).toEqual({
count,
sum: 0,
});
}
await insert(0, "a");
await insert(1, "a");
await insert(2, "d");
await insert(3, "c");
await insert(4, "b");
await insert(5, "e");
await insert(6, "e");
await insert(7, "e");
await insert(8, "e");
await insert(9, "e");
await countBetween(-1, 10, 10);
await countBetween(undefined, undefined, 10);
await countBetween(4, 6, 1);
await countBetween(0.5, 8.5, 8);
await countBetween(6, 9, 2);
});
});
test("sums", async () => {
const t = convexTest(schema, modules);
await t.run(async (ctx) => {
await getOrCreateTree(ctx.db, 4, false);
async function insert(key: number, value: string, summand: number) {
const sumBefore = await sumHandler(ctx);
await insertHandler(ctx, { key, value, summand });
await validateTree(ctx);
const sumAfter = await sumHandler(ctx);
expect(sumAfter).toEqual(sumBefore + summand);
}
async function del(key: number) {
const sumBefore = await sumHandler(ctx);
const itemBefore = await getHandler(ctx, { key });
expect(itemBefore).not.toBeNull();
await deleteHandler(ctx, { key });
await validateTree(ctx);
const sumAfter = await sumHandler(ctx);
expect(sumAfter).toEqual(sumBefore - itemBefore!.s);
}
await insert(1, "a", 1);
await insert(4, "b", 2);
await insert(3, "c", 3);
await insert(2, "d", 4);
await insert(5, "e", 5);
await insert(6, "e", 6);
await del(3);
await del(2);
await del(1);
await del(5);
await del(4);
});
});
});