@rotorsoft/act-tck 1.26.9 → 1.26.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/@types/store-differential-tck.d.ts +57 -8
- package/dist/@types/store-differential-tck.d.ts.map +1 -1
- package/dist/@types/store-tck.d.ts.map +1 -1
- package/dist/index.cjs +377 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +377 -40
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -394,20 +394,28 @@ var mulberry322 = (seed) => {
|
|
|
394
394
|
};
|
|
395
395
|
};
|
|
396
396
|
var normalize_event = (e) => ({
|
|
397
|
+
stream: e.stream,
|
|
398
|
+
version: e.version,
|
|
399
|
+
name: e.name,
|
|
400
|
+
data: e.data,
|
|
401
|
+
pii: e.pii != null
|
|
402
|
+
});
|
|
403
|
+
var normalize_identity = (e) => ({
|
|
397
404
|
stream: e.stream,
|
|
398
405
|
version: e.version,
|
|
399
406
|
name: e.name,
|
|
400
407
|
data: e.data
|
|
401
408
|
});
|
|
402
|
-
var build_plan = (seed, stream_count) => {
|
|
409
|
+
var build_plan = (seed, stream_count, pii_isolation) => {
|
|
403
410
|
const rng = mulberry322(seed);
|
|
404
411
|
const tag = uid();
|
|
405
|
-
const event_prefix = `
|
|
406
|
-
const sub_prefix = `
|
|
412
|
+
const event_prefix = `Diff-${tag}-Evt-`;
|
|
413
|
+
const sub_prefix = `Diff-${tag}-Sub-`;
|
|
407
414
|
const event_streams = Array.from(
|
|
408
415
|
{ length: stream_count },
|
|
409
|
-
(_, i) => `${event_prefix}${i}`
|
|
416
|
+
(_, i) => `${event_prefix}S${i}`
|
|
410
417
|
);
|
|
418
|
+
const correlation = `corr-${tag}`;
|
|
411
419
|
let type_cursor = 0;
|
|
412
420
|
const next_msg = () => {
|
|
413
421
|
const kind = type_cursor++ % 3;
|
|
@@ -416,65 +424,246 @@ var build_plan = (seed, stream_count) => {
|
|
|
416
424
|
};
|
|
417
425
|
const batch = () => Array.from({ length: 1 + Math.floor(rng() * 3) }, next_msg);
|
|
418
426
|
const pick_stream = () => event_streams[Math.floor(rng() * event_streams.length)];
|
|
419
|
-
const ops = [];
|
|
420
|
-
for (const stream of event_streams)
|
|
421
|
-
ops.push({ t: "commit", stream, msgs: batch() });
|
|
422
|
-
const middle = 8 + Math.floor(rng() * 16);
|
|
423
|
-
for (let i = 0; i < middle; i++) {
|
|
424
|
-
const stream = pick_stream();
|
|
425
|
-
const kind = Math.floor(rng() * 3);
|
|
426
|
-
if (kind === 0) ops.push({ t: "commit", stream, msgs: batch() });
|
|
427
|
-
else if (kind === 1)
|
|
428
|
-
ops.push({ t: "snapshot", stream, count: Math.floor(rng() * 1e3) });
|
|
429
|
-
else ops.push({ t: "truncate", stream, count: Math.floor(rng() * 1e3) });
|
|
430
|
-
}
|
|
431
|
-
for (const stream of event_streams)
|
|
432
|
-
ops.push({ t: "commit", stream, msgs: batch() });
|
|
433
427
|
const lanes = ["default", "slow", "fast"];
|
|
434
|
-
const
|
|
435
|
-
|
|
428
|
+
const lease_prefix = `Diff-${tag}-Src-`;
|
|
429
|
+
const lease_sources = event_streams.map((_, i) => `${lease_prefix}S${i}`);
|
|
430
|
+
const subs = lease_sources.map((source, i) => ({
|
|
431
|
+
stream: `${sub_prefix}S${i}`,
|
|
436
432
|
source,
|
|
437
433
|
lane: lanes[i % lanes.length],
|
|
438
434
|
priority: i % 4
|
|
439
435
|
}));
|
|
440
|
-
|
|
436
|
+
const pick_sub = () => Math.floor(rng() * subs.length);
|
|
437
|
+
const ops = [];
|
|
438
|
+
const pii_stream = event_streams[0];
|
|
439
|
+
event_streams.forEach((stream, i) => {
|
|
440
|
+
ops.push({
|
|
441
|
+
t: "commit",
|
|
442
|
+
stream,
|
|
443
|
+
msgs: batch(),
|
|
444
|
+
pii: pii_isolation && i === 0 ? { email: `u-${tag}@example.com`, name: "Ursula" } : void 0
|
|
445
|
+
});
|
|
446
|
+
});
|
|
447
|
+
for (const src of lease_sources)
|
|
448
|
+
ops.push({ t: "commit", stream: src, msgs: [inc(1)] });
|
|
449
|
+
const middle = 12 + Math.floor(rng() * 20);
|
|
450
|
+
for (let i = 0; i < middle; i++) {
|
|
451
|
+
const kind = Math.floor(rng() * 10);
|
|
452
|
+
if (kind === 0) {
|
|
453
|
+
ops.push({ t: "commit", stream: pick_stream(), msgs: batch() });
|
|
454
|
+
} else if (kind === 1) {
|
|
455
|
+
ops.push({
|
|
456
|
+
t: "snapshot",
|
|
457
|
+
stream: pick_stream(),
|
|
458
|
+
count: Math.floor(rng() * 1e3)
|
|
459
|
+
});
|
|
460
|
+
} else if (kind === 2) {
|
|
461
|
+
ops.push({
|
|
462
|
+
t: "truncate",
|
|
463
|
+
stream: pick_stream(),
|
|
464
|
+
count: Math.floor(rng() * 1e3)
|
|
465
|
+
});
|
|
466
|
+
} else if (kind === 3) {
|
|
467
|
+
ops.push({
|
|
468
|
+
t: "truncate_windowed",
|
|
469
|
+
stream: pick_stream(),
|
|
470
|
+
max_id: rng() < 0.5
|
|
471
|
+
});
|
|
472
|
+
} else if (kind === 4) {
|
|
473
|
+
ops.push({ t: "claim", millis: 1e5 });
|
|
474
|
+
} else if (kind === 5) {
|
|
475
|
+
ops.push({ t: "ack", sub: pick_sub() });
|
|
476
|
+
} else if (kind === 6) {
|
|
477
|
+
ops.push({
|
|
478
|
+
t: "defer",
|
|
479
|
+
sub: pick_sub(),
|
|
480
|
+
due: 41024448e5 + Math.floor(rng() * 1e3)
|
|
481
|
+
});
|
|
482
|
+
} else if (kind === 7) {
|
|
483
|
+
ops.push({
|
|
484
|
+
t: "block",
|
|
485
|
+
sub: pick_sub(),
|
|
486
|
+
error: `boom-${Math.floor(rng() * 100)}`
|
|
487
|
+
});
|
|
488
|
+
} else if (kind === 8) {
|
|
489
|
+
ops.push({ t: "unblock", sub: pick_sub() });
|
|
490
|
+
} else {
|
|
491
|
+
if (rng() < 0.5) ops.push({ t: "reset_sub", sub: pick_sub() });
|
|
492
|
+
else
|
|
493
|
+
ops.push({
|
|
494
|
+
t: "prioritize",
|
|
495
|
+
sub: pick_sub(),
|
|
496
|
+
priority: Math.floor(rng() * 10)
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
const filter_name = "Incremented";
|
|
501
|
+
for (const stream of event_streams)
|
|
502
|
+
ops.push({ t: "commit", stream, msgs: [inc(1)] });
|
|
503
|
+
const query_cases = [
|
|
504
|
+
{
|
|
505
|
+
label: "names filter (single event name)",
|
|
506
|
+
query: { stream: `^${event_prefix}`, names: [filter_name] }
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
label: "correlation filter",
|
|
510
|
+
query: { stream: `^${event_prefix}`, correlation }
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
label: "limit bound",
|
|
514
|
+
query: { stream: `^${event_prefix}`, limit: 3 }
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
label: "backward + limit",
|
|
518
|
+
query: { stream: `^${event_prefix}`, backward: true, limit: 4 }
|
|
519
|
+
},
|
|
520
|
+
// Absolute `id` bounds (`after`/`before` with positive ids) are
|
|
521
|
+
// deliberately absent: event ids are the canonical "legitimately
|
|
522
|
+
// differs between adapters" field (see `normalize_event`), and full
|
|
523
|
+
// truncates renumber them differently per store, so a positive id
|
|
524
|
+
// bound selects a different absolute window on each adapter. The
|
|
525
|
+
// gated falsy-zero cases below compare only the *guard* behavior
|
|
526
|
+
// (filter applied → subset, vs filter dropped → all), which stays a
|
|
527
|
+
// well-defined divergence regardless of the concrete id values.
|
|
528
|
+
// #1199 edge inputs — opposite semantics across adapters today.
|
|
529
|
+
{
|
|
530
|
+
label: "empty names filter",
|
|
531
|
+
query: { stream: `^${event_prefix}`, names: [] },
|
|
532
|
+
gated: "queryEdgeInputs"
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
label: "before: 0 (falsy-zero guard)",
|
|
536
|
+
query: { stream: `^${event_prefix}`, before: 0 },
|
|
537
|
+
gated: "queryEdgeInputs"
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
label: "backward + after: 0 (falsy-zero guard)",
|
|
541
|
+
query: { stream: `^${event_prefix}`, backward: true, after: 0 },
|
|
542
|
+
gated: "queryEdgeInputs"
|
|
543
|
+
}
|
|
544
|
+
];
|
|
545
|
+
return {
|
|
546
|
+
event_prefix,
|
|
547
|
+
event_streams,
|
|
548
|
+
sub_prefix,
|
|
549
|
+
ops,
|
|
550
|
+
subs,
|
|
551
|
+
correlation,
|
|
552
|
+
pii_stream,
|
|
553
|
+
query_cases,
|
|
554
|
+
filter_name
|
|
555
|
+
};
|
|
441
556
|
};
|
|
442
|
-
var apply_plan = async (store, plan) => {
|
|
557
|
+
var apply_plan = async (store, plan, pii_isolation) => {
|
|
558
|
+
await store.subscribe(
|
|
559
|
+
plan.subs.map((s) => ({
|
|
560
|
+
stream: s.stream,
|
|
561
|
+
source: s.source,
|
|
562
|
+
lane: s.lane,
|
|
563
|
+
priority: s.priority
|
|
564
|
+
}))
|
|
565
|
+
);
|
|
566
|
+
const held = /* @__PURE__ */ new Map();
|
|
567
|
+
const owned = new Set(plan.subs.map((s) => s.stream));
|
|
443
568
|
for (const op of plan.ops) {
|
|
444
569
|
if (op.t === "commit") {
|
|
570
|
+
const msgs = op.pii && pii_isolation ? op.msgs.map((m, i) => i === 0 ? { ...m, pii: op.pii } : m) : op.msgs;
|
|
445
571
|
await store.commit(
|
|
446
572
|
op.stream,
|
|
447
|
-
|
|
448
|
-
make_meta({ stream: op.stream })
|
|
573
|
+
msgs,
|
|
574
|
+
make_meta({ stream: op.stream, correlation: plan.correlation })
|
|
449
575
|
);
|
|
450
576
|
} else if (op.t === "snapshot") {
|
|
451
577
|
await store.commit(
|
|
452
578
|
op.stream,
|
|
453
579
|
[{ name: SNAP_EVENT, data: { count: op.count } }],
|
|
454
|
-
make_meta({ stream: op.stream })
|
|
580
|
+
make_meta({ stream: op.stream, correlation: plan.correlation })
|
|
455
581
|
);
|
|
456
|
-
} else {
|
|
582
|
+
} else if (op.t === "truncate") {
|
|
457
583
|
await store.truncate([
|
|
458
584
|
{ stream: op.stream, snapshot: { count: op.count } }
|
|
459
585
|
]);
|
|
586
|
+
} else if (op.t === "truncate_windowed") {
|
|
587
|
+
await store.commit(
|
|
588
|
+
op.stream,
|
|
589
|
+
[{ name: SNAP_EVENT, data: { count: 1 } }],
|
|
590
|
+
make_meta({ stream: op.stream, correlation: plan.correlation })
|
|
591
|
+
);
|
|
592
|
+
await store.truncate([
|
|
593
|
+
{
|
|
594
|
+
stream: op.stream,
|
|
595
|
+
before: new Date(Date.now() + 6e4),
|
|
596
|
+
// A wide cap that still fits a 32-bit event-id column, so it
|
|
597
|
+
// never excludes the boundary snapshot on any adapter.
|
|
598
|
+
...op.max_id ? { max_id: 2147483647 } : {}
|
|
599
|
+
}
|
|
600
|
+
]);
|
|
601
|
+
} else if (op.t === "claim") {
|
|
602
|
+
const by = uid();
|
|
603
|
+
const leased = await store.claim(1e5, 1e5, by, op.millis);
|
|
604
|
+
for (const l of leased) if (owned.has(l.stream)) held.set(l.stream, by);
|
|
605
|
+
} else if (op.t === "ack") {
|
|
606
|
+
const stream = plan.subs[op.sub].stream;
|
|
607
|
+
const by = held.get(stream);
|
|
608
|
+
if (by) {
|
|
609
|
+
await store.ack([{ stream, at: 0, by, retry: 0, lagging: true }]);
|
|
610
|
+
held.delete(stream);
|
|
611
|
+
}
|
|
612
|
+
} else if (op.t === "defer") {
|
|
613
|
+
const stream = plan.subs[op.sub].stream;
|
|
614
|
+
const by = held.get(stream);
|
|
615
|
+
if (by) {
|
|
616
|
+
const lease = {
|
|
617
|
+
stream,
|
|
618
|
+
at: 0,
|
|
619
|
+
by,
|
|
620
|
+
retry: 0,
|
|
621
|
+
lagging: true,
|
|
622
|
+
due: op.due
|
|
623
|
+
};
|
|
624
|
+
await store.ack([lease]);
|
|
625
|
+
held.delete(stream);
|
|
626
|
+
}
|
|
627
|
+
} else if (op.t === "block") {
|
|
628
|
+
const stream = plan.subs[op.sub].stream;
|
|
629
|
+
const by = held.get(stream);
|
|
630
|
+
if (by) {
|
|
631
|
+
const lease = {
|
|
632
|
+
stream,
|
|
633
|
+
at: 0,
|
|
634
|
+
by,
|
|
635
|
+
retry: 0,
|
|
636
|
+
lagging: true,
|
|
637
|
+
error: op.error
|
|
638
|
+
};
|
|
639
|
+
await store.block([lease]);
|
|
640
|
+
held.delete(stream);
|
|
641
|
+
}
|
|
642
|
+
} else if (op.t === "unblock") {
|
|
643
|
+
const stream = plan.subs[op.sub].stream;
|
|
644
|
+
await store.unblock([stream]);
|
|
645
|
+
held.delete(stream);
|
|
646
|
+
} else if (op.t === "reset_sub") {
|
|
647
|
+
const stream = plan.subs[op.sub].stream;
|
|
648
|
+
await store.reset([stream]);
|
|
649
|
+
held.delete(stream);
|
|
650
|
+
} else {
|
|
651
|
+
await store.prioritize(
|
|
652
|
+
{ stream: plan.subs[op.sub].stream, stream_exact: true },
|
|
653
|
+
op.priority
|
|
654
|
+
);
|
|
460
655
|
}
|
|
461
656
|
}
|
|
462
|
-
await store.subscribe(
|
|
463
|
-
plan.subs.map((s) => ({
|
|
464
|
-
stream: s.stream,
|
|
465
|
-
source: s.source,
|
|
466
|
-
lane: s.lane,
|
|
467
|
-
priority: s.priority
|
|
468
|
-
}))
|
|
469
|
-
);
|
|
470
657
|
};
|
|
471
658
|
var runStoreDifferentialTck = (options) => {
|
|
472
659
|
describe6(`TCK / Store differential / ${options.name}`, () => {
|
|
473
660
|
const base_seed = options.seed ?? 2759;
|
|
474
661
|
const stream_count = options.streams ?? 4;
|
|
662
|
+
const pii_isolation = options.piiIsolation ?? true;
|
|
663
|
+
const skip = { ...options.skip };
|
|
475
664
|
const plans = Array.from(
|
|
476
665
|
{ length: options.runs ?? 8 },
|
|
477
|
-
(_, r) => build_plan(base_seed + r, stream_count)
|
|
666
|
+
(_, r) => build_plan(base_seed + r, stream_count, pii_isolation)
|
|
478
667
|
);
|
|
479
668
|
const live = [];
|
|
480
669
|
beforeAll2(async () => {
|
|
@@ -482,7 +671,7 @@ var runStoreDifferentialTck = (options) => {
|
|
|
482
671
|
const store = await spec.factory();
|
|
483
672
|
await store.drop();
|
|
484
673
|
await store.seed();
|
|
485
|
-
for (const plan of plans) await apply_plan(store, plan);
|
|
674
|
+
for (const plan of plans) await apply_plan(store, plan, pii_isolation);
|
|
486
675
|
live.push({ name: spec.name, store });
|
|
487
676
|
}
|
|
488
677
|
});
|
|
@@ -546,6 +735,21 @@ var runStoreDifferentialTck = (options) => {
|
|
|
546
735
|
return by_stream;
|
|
547
736
|
});
|
|
548
737
|
});
|
|
738
|
+
plan.query_cases.forEach((qc) => {
|
|
739
|
+
const gated = qc.gated && skip[qc.gated];
|
|
740
|
+
it6.skipIf(gated)(
|
|
741
|
+
`yields identical events under ${qc.label}`,
|
|
742
|
+
async () => {
|
|
743
|
+
await assert_identical(`query / ${qc.label}`, async (store) => {
|
|
744
|
+
const out = [];
|
|
745
|
+
await store.query((e) => {
|
|
746
|
+
out.push(normalize_event(e));
|
|
747
|
+
}, qc.query);
|
|
748
|
+
return out;
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
);
|
|
752
|
+
});
|
|
549
753
|
it6("yields identical query_stats output (head/tail/count/names)", async () => {
|
|
550
754
|
await assert_identical("query_stats", async (store) => {
|
|
551
755
|
const stats = await store.query_stats(
|
|
@@ -556,8 +760,8 @@ var runStoreDifferentialTck = (options) => {
|
|
|
556
760
|
const content = {};
|
|
557
761
|
for (const [stream, s] of stats) {
|
|
558
762
|
content[stream] = {
|
|
559
|
-
head:
|
|
560
|
-
tail:
|
|
763
|
+
head: normalize_identity(s.head),
|
|
764
|
+
tail: normalize_identity(
|
|
561
765
|
s.tail
|
|
562
766
|
),
|
|
563
767
|
count: s.count,
|
|
@@ -567,7 +771,7 @@ var runStoreDifferentialTck = (options) => {
|
|
|
567
771
|
return { keys, content };
|
|
568
772
|
});
|
|
569
773
|
});
|
|
570
|
-
it6("yields identical query_streams output", async () => {
|
|
774
|
+
it6("yields identical query_streams output (incl. lease-lifecycle state)", async () => {
|
|
571
775
|
await assert_identical("query_streams", async (store) => {
|
|
572
776
|
const rows = [];
|
|
573
777
|
const { count } = await store.query_streams(
|
|
@@ -578,7 +782,10 @@ var runStoreDifferentialTck = (options) => {
|
|
|
578
782
|
at: p.at,
|
|
579
783
|
blocked: p.blocked,
|
|
580
784
|
priority: p.priority,
|
|
581
|
-
lane: p.lane
|
|
785
|
+
lane: p.lane,
|
|
786
|
+
retry: p.retry,
|
|
787
|
+
error: p.error,
|
|
788
|
+
leased: p.leased_by != null
|
|
582
789
|
});
|
|
583
790
|
},
|
|
584
791
|
{ stream: `^${plan.sub_prefix}`, limit: 1e3 }
|
|
@@ -587,6 +794,60 @@ var runStoreDifferentialTck = (options) => {
|
|
|
587
794
|
return { count, rows };
|
|
588
795
|
});
|
|
589
796
|
});
|
|
797
|
+
it6.skipIf(skip.caseInsensitivePatterns)(
|
|
798
|
+
"matches case-sensitively under a lower-cased pattern filter",
|
|
799
|
+
async () => {
|
|
800
|
+
await assert_identical(
|
|
801
|
+
"query_streams lower-cased pattern",
|
|
802
|
+
async (store) => {
|
|
803
|
+
const collect_streams = async (pattern) => {
|
|
804
|
+
const streams = [];
|
|
805
|
+
await store.query_streams(
|
|
806
|
+
(p) => {
|
|
807
|
+
streams.push(p.stream);
|
|
808
|
+
},
|
|
809
|
+
{ stream: pattern, limit: 1e3 }
|
|
810
|
+
);
|
|
811
|
+
streams.sort((a, b) => a.localeCompare(b));
|
|
812
|
+
return streams;
|
|
813
|
+
};
|
|
814
|
+
const matched = await collect_streams(`^${plan.sub_prefix}S`);
|
|
815
|
+
const lowered = await collect_streams(
|
|
816
|
+
`^${plan.sub_prefix.toLowerCase()}s`
|
|
817
|
+
);
|
|
818
|
+
return { matched, lowered };
|
|
819
|
+
}
|
|
820
|
+
);
|
|
821
|
+
}
|
|
822
|
+
);
|
|
823
|
+
it6("yields identical events under an exact mixed-case stream lookup", async () => {
|
|
824
|
+
await assert_identical("query exact mixed-case", async (store) => {
|
|
825
|
+
const out = [];
|
|
826
|
+
await store.query(
|
|
827
|
+
(e) => {
|
|
828
|
+
out.push(normalize_event(e));
|
|
829
|
+
},
|
|
830
|
+
{ stream: plan.event_streams[0], stream_exact: true }
|
|
831
|
+
);
|
|
832
|
+
return out;
|
|
833
|
+
});
|
|
834
|
+
});
|
|
835
|
+
it6.skipIf(!pii_isolation)(
|
|
836
|
+
"erases pii identically via forget_pii",
|
|
837
|
+
async () => {
|
|
838
|
+
await assert_identical("forget_pii erase", async (store) => {
|
|
839
|
+
const erased = await store.forget_pii(plan.pii_stream);
|
|
840
|
+
const after = [];
|
|
841
|
+
await store.query(
|
|
842
|
+
(e) => {
|
|
843
|
+
after.push(normalize_event(e));
|
|
844
|
+
},
|
|
845
|
+
{ stream: plan.pii_stream, stream_exact: true }
|
|
846
|
+
);
|
|
847
|
+
return { erased, after };
|
|
848
|
+
});
|
|
849
|
+
}
|
|
850
|
+
);
|
|
590
851
|
});
|
|
591
852
|
});
|
|
592
853
|
});
|
|
@@ -1007,6 +1268,54 @@ var runStoreTck = (options) => {
|
|
|
1007
1268
|
committed.slice(0, -1).map((c) => c.id)
|
|
1008
1269
|
);
|
|
1009
1270
|
});
|
|
1271
|
+
it7("names:[] matches no events", async () => {
|
|
1272
|
+
const s = `q-names-empty-${uid()}`;
|
|
1273
|
+
await store.commit(
|
|
1274
|
+
s,
|
|
1275
|
+
[inc(1), dec(1)],
|
|
1276
|
+
make_meta({ stream: s })
|
|
1277
|
+
);
|
|
1278
|
+
const none = await collect(store, {
|
|
1279
|
+
stream: s,
|
|
1280
|
+
stream_exact: true,
|
|
1281
|
+
names: []
|
|
1282
|
+
});
|
|
1283
|
+
expect8(none).toHaveLength(0);
|
|
1284
|
+
const all = await collect(store, { stream: s, stream_exact: true });
|
|
1285
|
+
expect8(all).toHaveLength(2);
|
|
1286
|
+
});
|
|
1287
|
+
it7("after:0 and before:0 are honored as id bounds", async () => {
|
|
1288
|
+
const s = `q-zero-bound-${uid()}`;
|
|
1289
|
+
await store.commit(
|
|
1290
|
+
s,
|
|
1291
|
+
[inc(1), inc(2), inc(3)],
|
|
1292
|
+
make_meta({ stream: s })
|
|
1293
|
+
);
|
|
1294
|
+
expect8(
|
|
1295
|
+
await collect(store, { stream: s, stream_exact: true, before: 0 })
|
|
1296
|
+
).toHaveLength(0);
|
|
1297
|
+
expect8(
|
|
1298
|
+
await collect(store, {
|
|
1299
|
+
stream: s,
|
|
1300
|
+
stream_exact: true,
|
|
1301
|
+
before: 0,
|
|
1302
|
+
backward: true
|
|
1303
|
+
})
|
|
1304
|
+
).toHaveLength(0);
|
|
1305
|
+
const forward = await collect(store, {
|
|
1306
|
+
stream: s,
|
|
1307
|
+
stream_exact: true,
|
|
1308
|
+
after: 0
|
|
1309
|
+
});
|
|
1310
|
+
expect8(forward.every((e) => e.id > 0)).toBe(true);
|
|
1311
|
+
const backward = await collect(store, {
|
|
1312
|
+
stream: s,
|
|
1313
|
+
stream_exact: true,
|
|
1314
|
+
after: 0,
|
|
1315
|
+
backward: true
|
|
1316
|
+
});
|
|
1317
|
+
expect8(backward.every((e) => e.id > 0)).toBe(true);
|
|
1318
|
+
});
|
|
1010
1319
|
it7("created_after/created_before filter by timestamp", async () => {
|
|
1011
1320
|
const s = `q-ts-${uid()}`;
|
|
1012
1321
|
const committed = await store.commit(
|
|
@@ -1245,6 +1554,34 @@ var runStoreTck = (options) => {
|
|
|
1245
1554
|
if (error !== void 0) expect8(error).toBeInstanceOf(ValidationError);
|
|
1246
1555
|
else expect8(count).toBe(1);
|
|
1247
1556
|
});
|
|
1557
|
+
it7("stream filters match case-sensitively (query)", async () => {
|
|
1558
|
+
const tag = uid();
|
|
1559
|
+
const lower = `order-${tag}`;
|
|
1560
|
+
const upper = `Order-${tag}`;
|
|
1561
|
+
await seed_streams([lower, upper]);
|
|
1562
|
+
expect8(await streams_matching(`^order-${tag}`)).toEqual([lower]);
|
|
1563
|
+
expect8(await streams_matching(`^Order-${tag}$`)).toEqual([upper]);
|
|
1564
|
+
expect8(await streams_matching(`order-${tag}`)).toEqual([lower]);
|
|
1565
|
+
});
|
|
1566
|
+
it7("stream filters match case-sensitively (position filters)", async () => {
|
|
1567
|
+
const tag = uid();
|
|
1568
|
+
const lower = `csp-order-${tag}`;
|
|
1569
|
+
const upper = `csp-Order-${tag}`;
|
|
1570
|
+
await store.subscribe([{ stream: lower }, { stream: upper }]);
|
|
1571
|
+
const got = [];
|
|
1572
|
+
await store.query_streams((p) => got.push(p.stream), {
|
|
1573
|
+
stream: `^csp-order-${tag}`
|
|
1574
|
+
});
|
|
1575
|
+
expect8(got).toEqual([lower]);
|
|
1576
|
+
});
|
|
1577
|
+
it7("bulk stream ops match case-sensitively", async () => {
|
|
1578
|
+
const tag = uid();
|
|
1579
|
+
const lower = `bcs-order-${tag}`;
|
|
1580
|
+
const upper = `bcs-Order-${tag}`;
|
|
1581
|
+
await store.subscribe([{ stream: lower }, { stream: upper }]);
|
|
1582
|
+
const count = await store.reset({ stream: `^bcs-order-${tag}` });
|
|
1583
|
+
expect8(count).toBe(1);
|
|
1584
|
+
});
|
|
1248
1585
|
});
|
|
1249
1586
|
describe8("subscribe + claim + ack", () => {
|
|
1250
1587
|
it7("subscribes new streams and is idempotent on repeat", async () => {
|