@voidhash/mimic-effect 0.0.9 → 1.0.0-beta.2
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/.turbo/turbo-build.log +136 -90
- package/README.md +385 -0
- package/dist/ColdStorage.cjs +60 -0
- package/dist/ColdStorage.d.cts +53 -0
- package/dist/ColdStorage.d.cts.map +1 -0
- package/dist/ColdStorage.d.mts +53 -0
- package/dist/ColdStorage.d.mts.map +1 -0
- package/dist/ColdStorage.mjs +60 -0
- package/dist/ColdStorage.mjs.map +1 -0
- package/dist/DocumentManager.cjs +263 -82
- package/dist/DocumentManager.d.cts +44 -22
- package/dist/DocumentManager.d.cts.map +1 -1
- package/dist/DocumentManager.d.mts +44 -22
- package/dist/DocumentManager.d.mts.map +1 -1
- package/dist/DocumentManager.mjs +259 -67
- package/dist/DocumentManager.mjs.map +1 -1
- package/dist/Errors.cjs +54 -0
- package/dist/Errors.d.cts +96 -0
- package/dist/Errors.d.cts.map +1 -0
- package/dist/Errors.d.mts +96 -0
- package/dist/Errors.d.mts.map +1 -0
- package/dist/Errors.mjs +48 -0
- package/dist/Errors.mjs.map +1 -0
- package/dist/HotStorage.cjs +100 -0
- package/dist/HotStorage.d.cts +70 -0
- package/dist/HotStorage.d.cts.map +1 -0
- package/dist/HotStorage.d.mts +70 -0
- package/dist/HotStorage.d.mts.map +1 -0
- package/dist/HotStorage.mjs +100 -0
- package/dist/HotStorage.mjs.map +1 -0
- package/dist/Metrics.cjs +143 -0
- package/dist/Metrics.d.cts +31 -0
- package/dist/Metrics.d.cts.map +1 -0
- package/dist/Metrics.d.mts +31 -0
- package/dist/Metrics.d.mts.map +1 -0
- package/dist/Metrics.mjs +126 -0
- package/dist/Metrics.mjs.map +1 -0
- package/dist/MimicAuthService.cjs +61 -45
- package/dist/MimicAuthService.d.cts +61 -48
- package/dist/MimicAuthService.d.cts.map +1 -1
- package/dist/MimicAuthService.d.mts +61 -48
- package/dist/MimicAuthService.d.mts.map +1 -1
- package/dist/MimicAuthService.mjs +60 -36
- package/dist/MimicAuthService.mjs.map +1 -1
- package/dist/MimicClusterServerEngine.cjs +521 -0
- package/dist/MimicClusterServerEngine.d.cts +17 -0
- package/dist/MimicClusterServerEngine.d.cts.map +1 -0
- package/dist/MimicClusterServerEngine.d.mts +17 -0
- package/dist/MimicClusterServerEngine.d.mts.map +1 -0
- package/dist/MimicClusterServerEngine.mjs +523 -0
- package/dist/MimicClusterServerEngine.mjs.map +1 -0
- package/dist/MimicServer.cjs +205 -96
- package/dist/MimicServer.d.cts +9 -110
- package/dist/MimicServer.d.cts.map +1 -1
- package/dist/MimicServer.d.mts +9 -110
- package/dist/MimicServer.d.mts.map +1 -1
- package/dist/MimicServer.mjs +206 -90
- package/dist/MimicServer.mjs.map +1 -1
- package/dist/MimicServerEngine.cjs +97 -0
- package/dist/MimicServerEngine.d.cts +78 -0
- package/dist/MimicServerEngine.d.cts.map +1 -0
- package/dist/MimicServerEngine.d.mts +78 -0
- package/dist/MimicServerEngine.d.mts.map +1 -0
- package/dist/MimicServerEngine.mjs +97 -0
- package/dist/MimicServerEngine.mjs.map +1 -0
- package/dist/PresenceManager.cjs +75 -91
- package/dist/PresenceManager.d.cts +17 -66
- package/dist/PresenceManager.d.cts.map +1 -1
- package/dist/PresenceManager.d.mts +17 -66
- package/dist/PresenceManager.d.mts.map +1 -1
- package/dist/PresenceManager.mjs +74 -78
- package/dist/PresenceManager.mjs.map +1 -1
- package/dist/Protocol.cjs +146 -0
- package/dist/Protocol.d.cts +203 -0
- package/dist/Protocol.d.cts.map +1 -0
- package/dist/Protocol.d.mts +203 -0
- package/dist/Protocol.d.mts.map +1 -0
- package/dist/Protocol.mjs +132 -0
- package/dist/Protocol.mjs.map +1 -0
- package/dist/Types.d.cts +172 -0
- package/dist/Types.d.cts.map +1 -0
- package/dist/Types.d.mts +172 -0
- package/dist/Types.d.mts.map +1 -0
- package/dist/_virtual/rolldown_runtime.cjs +1 -25
- package/dist/_virtual/rolldown_runtime.mjs +4 -1
- package/dist/index.cjs +37 -75
- package/dist/index.d.cts +13 -12
- package/dist/index.d.mts +13 -12
- package/dist/index.mjs +12 -12
- package/dist/testing/ColdStorageTestSuite.cjs +508 -0
- package/dist/testing/ColdStorageTestSuite.d.cts +36 -0
- package/dist/testing/ColdStorageTestSuite.d.cts.map +1 -0
- package/dist/testing/ColdStorageTestSuite.d.mts +36 -0
- package/dist/testing/ColdStorageTestSuite.d.mts.map +1 -0
- package/dist/testing/ColdStorageTestSuite.mjs +508 -0
- package/dist/testing/ColdStorageTestSuite.mjs.map +1 -0
- package/dist/testing/FailingStorage.cjs +135 -0
- package/dist/testing/FailingStorage.d.cts +43 -0
- package/dist/testing/FailingStorage.d.cts.map +1 -0
- package/dist/testing/FailingStorage.d.mts +43 -0
- package/dist/testing/FailingStorage.d.mts.map +1 -0
- package/dist/testing/FailingStorage.mjs +136 -0
- package/dist/testing/FailingStorage.mjs.map +1 -0
- package/dist/testing/HotStorageTestSuite.cjs +585 -0
- package/dist/testing/HotStorageTestSuite.d.cts +40 -0
- package/dist/testing/HotStorageTestSuite.d.cts.map +1 -0
- package/dist/testing/HotStorageTestSuite.d.mts +40 -0
- package/dist/testing/HotStorageTestSuite.d.mts.map +1 -0
- package/dist/testing/HotStorageTestSuite.mjs +585 -0
- package/dist/testing/HotStorageTestSuite.mjs.map +1 -0
- package/dist/testing/StorageIntegrationTestSuite.cjs +349 -0
- package/dist/testing/StorageIntegrationTestSuite.d.cts +35 -0
- package/dist/testing/StorageIntegrationTestSuite.d.cts.map +1 -0
- package/dist/testing/StorageIntegrationTestSuite.d.mts +35 -0
- package/dist/testing/StorageIntegrationTestSuite.d.mts.map +1 -0
- package/dist/testing/StorageIntegrationTestSuite.mjs +349 -0
- package/dist/testing/StorageIntegrationTestSuite.mjs.map +1 -0
- package/dist/testing/assertions.cjs +114 -0
- package/dist/testing/assertions.mjs +109 -0
- package/dist/testing/assertions.mjs.map +1 -0
- package/dist/testing/index.cjs +14 -0
- package/dist/testing/index.d.cts +6 -0
- package/dist/testing/index.d.mts +6 -0
- package/dist/testing/index.mjs +7 -0
- package/dist/testing/types.cjs +15 -0
- package/dist/testing/types.d.cts +90 -0
- package/dist/testing/types.d.cts.map +1 -0
- package/dist/testing/types.d.mts +90 -0
- package/dist/testing/types.d.mts.map +1 -0
- package/dist/testing/types.mjs +16 -0
- package/dist/testing/types.mjs.map +1 -0
- package/package.json +18 -3
- package/src/ColdStorage.ts +136 -0
- package/src/DocumentManager.ts +550 -190
- package/src/Errors.ts +114 -0
- package/src/HotStorage.ts +239 -0
- package/src/Metrics.ts +187 -0
- package/src/MimicAuthService.ts +126 -64
- package/src/MimicClusterServerEngine.ts +946 -0
- package/src/MimicServer.ts +448 -195
- package/src/MimicServerEngine.ts +276 -0
- package/src/PresenceManager.ts +169 -240
- package/src/Protocol.ts +350 -0
- package/src/Types.ts +231 -0
- package/src/index.ts +57 -23
- package/src/testing/ColdStorageTestSuite.ts +589 -0
- package/src/testing/FailingStorage.ts +286 -0
- package/src/testing/HotStorageTestSuite.ts +762 -0
- package/src/testing/StorageIntegrationTestSuite.ts +504 -0
- package/src/testing/assertions.ts +181 -0
- package/src/testing/index.ts +83 -0
- package/src/testing/types.ts +100 -0
- package/tests/ColdStorage.test.ts +24 -0
- package/tests/DocumentManager.test.ts +158 -287
- package/tests/HotStorage.test.ts +24 -0
- package/tests/MimicAuthService.test.ts +102 -134
- package/tests/MimicClusterServerEngine.test.ts +587 -0
- package/tests/MimicServer.test.ts +90 -226
- package/tests/MimicServerEngine.test.ts +521 -0
- package/tests/PresenceManager.test.ts +22 -63
- package/tests/Protocol.test.ts +190 -0
- package/tests/StorageIntegration.test.ts +259 -0
- package/tsconfig.json +1 -1
- package/tsdown.config.ts +1 -1
- package/dist/DocumentProtocol.cjs +0 -94
- package/dist/DocumentProtocol.d.cts +0 -113
- package/dist/DocumentProtocol.d.cts.map +0 -1
- package/dist/DocumentProtocol.d.mts +0 -113
- package/dist/DocumentProtocol.d.mts.map +0 -1
- package/dist/DocumentProtocol.mjs +0 -89
- package/dist/DocumentProtocol.mjs.map +0 -1
- package/dist/MimicConfig.cjs +0 -60
- package/dist/MimicConfig.d.cts +0 -141
- package/dist/MimicConfig.d.cts.map +0 -1
- package/dist/MimicConfig.d.mts +0 -141
- package/dist/MimicConfig.d.mts.map +0 -1
- package/dist/MimicConfig.mjs +0 -50
- package/dist/MimicConfig.mjs.map +0 -1
- package/dist/MimicDataStorage.cjs +0 -83
- package/dist/MimicDataStorage.d.cts +0 -113
- package/dist/MimicDataStorage.d.cts.map +0 -1
- package/dist/MimicDataStorage.d.mts +0 -113
- package/dist/MimicDataStorage.d.mts.map +0 -1
- package/dist/MimicDataStorage.mjs +0 -74
- package/dist/MimicDataStorage.mjs.map +0 -1
- package/dist/WebSocketHandler.cjs +0 -365
- package/dist/WebSocketHandler.d.cts +0 -34
- package/dist/WebSocketHandler.d.cts.map +0 -1
- package/dist/WebSocketHandler.d.mts +0 -34
- package/dist/WebSocketHandler.d.mts.map +0 -1
- package/dist/WebSocketHandler.mjs +0 -355
- package/dist/WebSocketHandler.mjs.map +0 -1
- package/dist/auth/NoAuth.cjs +0 -43
- package/dist/auth/NoAuth.d.cts +0 -22
- package/dist/auth/NoAuth.d.cts.map +0 -1
- package/dist/auth/NoAuth.d.mts +0 -22
- package/dist/auth/NoAuth.d.mts.map +0 -1
- package/dist/auth/NoAuth.mjs +0 -36
- package/dist/auth/NoAuth.mjs.map +0 -1
- package/dist/errors.cjs +0 -74
- package/dist/errors.d.cts +0 -89
- package/dist/errors.d.cts.map +0 -1
- package/dist/errors.d.mts +0 -89
- package/dist/errors.d.mts.map +0 -1
- package/dist/errors.mjs +0 -67
- package/dist/errors.mjs.map +0 -1
- package/dist/storage/InMemoryDataStorage.cjs +0 -57
- package/dist/storage/InMemoryDataStorage.d.cts +0 -19
- package/dist/storage/InMemoryDataStorage.d.cts.map +0 -1
- package/dist/storage/InMemoryDataStorage.d.mts +0 -19
- package/dist/storage/InMemoryDataStorage.d.mts.map +0 -1
- package/dist/storage/InMemoryDataStorage.mjs +0 -48
- package/dist/storage/InMemoryDataStorage.mjs.map +0 -1
- package/src/DocumentProtocol.ts +0 -112
- package/src/MimicConfig.ts +0 -211
- package/src/MimicDataStorage.ts +0 -157
- package/src/WebSocketHandler.ts +0 -735
- package/src/auth/NoAuth.ts +0 -46
- package/src/errors.ts +0 -113
- package/src/storage/InMemoryDataStorage.ts +0 -66
- package/tests/DocumentProtocol.test.ts +0 -113
- package/tests/InMemoryDataStorage.test.ts +0 -190
- package/tests/MimicConfig.test.ts +0 -290
- package/tests/MimicDataStorage.test.ts +0 -190
- package/tests/NoAuth.test.ts +0 -94
- package/tests/WebSocketHandler.test.ts +0 -321
- package/tests/errors.test.ts +0 -77
|
@@ -0,0 +1,585 @@
|
|
|
1
|
+
import { HotStorageTag } from "../HotStorage.mjs";
|
|
2
|
+
import { assertEmpty, assertEqual, assertLength, assertSortedBy, assertTrue } from "./assertions.mjs";
|
|
3
|
+
import { Effect } from "effect";
|
|
4
|
+
import { Transaction } from "@voidhash/mimic";
|
|
5
|
+
|
|
6
|
+
//#region src/testing/HotStorageTestSuite.ts
|
|
7
|
+
/**
|
|
8
|
+
* @voidhash/mimic-effect/testing - HotStorage Test Suite
|
|
9
|
+
*
|
|
10
|
+
* Comprehensive test suite for HotStorage (WAL) adapter implementations.
|
|
11
|
+
* These tests verify that an adapter correctly implements the HotStorage interface
|
|
12
|
+
* and can reliably store/retrieve WAL entries for document recovery.
|
|
13
|
+
*/
|
|
14
|
+
const Categories = {
|
|
15
|
+
BasicOperations: "Basic Operations",
|
|
16
|
+
VersionFiltering: "Version Filtering",
|
|
17
|
+
OrderingGuarantees: "Ordering Guarantees",
|
|
18
|
+
TruncationEdgeCases: "Truncation Edge Cases",
|
|
19
|
+
WalEntryIntegrity: "WAL Entry Integrity",
|
|
20
|
+
DocumentIsolation: "Document Isolation",
|
|
21
|
+
LargeScaleOperations: "Large-Scale Operations",
|
|
22
|
+
DocumentIdEdgeCases: "Document ID Edge Cases",
|
|
23
|
+
GapChecking: "Gap Checking"
|
|
24
|
+
};
|
|
25
|
+
const makeEntry = (version, timestamp) => ({
|
|
26
|
+
transaction: Transaction.make([]),
|
|
27
|
+
version,
|
|
28
|
+
timestamp: timestamp !== null && timestamp !== void 0 ? timestamp : Date.now()
|
|
29
|
+
});
|
|
30
|
+
const makeEntryWithData = (version, data, timestamp) => ({
|
|
31
|
+
transaction: Transaction.make([{
|
|
32
|
+
type: "set",
|
|
33
|
+
path: ["data"],
|
|
34
|
+
value: data
|
|
35
|
+
}]),
|
|
36
|
+
version,
|
|
37
|
+
timestamp: timestamp !== null && timestamp !== void 0 ? timestamp : Date.now()
|
|
38
|
+
});
|
|
39
|
+
const tests = [
|
|
40
|
+
{
|
|
41
|
+
name: "getEntries returns empty array for non-existent document",
|
|
42
|
+
category: Categories.BasicOperations,
|
|
43
|
+
run: Effect.gen(function* () {
|
|
44
|
+
yield* assertEmpty(yield* (yield* HotStorageTag).getEntries("non-existent-hot-doc", 0), "Should return empty array for non-existent document");
|
|
45
|
+
})
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: "append then getEntries returns the entry",
|
|
49
|
+
category: Categories.BasicOperations,
|
|
50
|
+
run: Effect.gen(function* () {
|
|
51
|
+
const storage = yield* HotStorageTag;
|
|
52
|
+
const entry = makeEntry(1);
|
|
53
|
+
yield* storage.append("basic-append", entry);
|
|
54
|
+
const entries = yield* storage.getEntries("basic-append", 0);
|
|
55
|
+
yield* assertLength(entries, 1, "Should have one entry");
|
|
56
|
+
yield* assertEqual(entries[0].version, 1, "Entry version should match");
|
|
57
|
+
})
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "multiple append calls accumulate entries",
|
|
61
|
+
category: Categories.BasicOperations,
|
|
62
|
+
run: Effect.gen(function* () {
|
|
63
|
+
const storage = yield* HotStorageTag;
|
|
64
|
+
yield* storage.append("multi-append", makeEntry(1));
|
|
65
|
+
yield* storage.append("multi-append", makeEntry(2));
|
|
66
|
+
yield* storage.append("multi-append", makeEntry(3));
|
|
67
|
+
yield* assertLength(yield* storage.getEntries("multi-append", 0), 3, "Should have three entries");
|
|
68
|
+
})
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: "truncate removes entries with version <= upToVersion",
|
|
72
|
+
category: Categories.BasicOperations,
|
|
73
|
+
run: Effect.gen(function* () {
|
|
74
|
+
const storage = yield* HotStorageTag;
|
|
75
|
+
yield* storage.append("truncate-basic", makeEntry(1));
|
|
76
|
+
yield* storage.append("truncate-basic", makeEntry(2));
|
|
77
|
+
yield* storage.append("truncate-basic", makeEntry(3));
|
|
78
|
+
yield* storage.truncate("truncate-basic", 2);
|
|
79
|
+
const entries = yield* storage.getEntries("truncate-basic", 0);
|
|
80
|
+
yield* assertLength(entries, 1, "Should have one entry after truncate");
|
|
81
|
+
yield* assertEqual(entries[0].version, 3, "Only version 3 should remain");
|
|
82
|
+
})
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: "truncate on non-existent document does not error",
|
|
86
|
+
category: Categories.BasicOperations,
|
|
87
|
+
run: Effect.gen(function* () {
|
|
88
|
+
yield* (yield* HotStorageTag).truncate("non-existent-truncate", 100);
|
|
89
|
+
})
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: "getEntries(doc, 0) returns all entries",
|
|
93
|
+
category: Categories.VersionFiltering,
|
|
94
|
+
run: Effect.gen(function* () {
|
|
95
|
+
const storage = yield* HotStorageTag;
|
|
96
|
+
yield* storage.append("filter-all", makeEntry(1));
|
|
97
|
+
yield* storage.append("filter-all", makeEntry(2));
|
|
98
|
+
yield* storage.append("filter-all", makeEntry(3));
|
|
99
|
+
yield* assertLength(yield* storage.getEntries("filter-all", 0), 3, "sinceVersion=0 should return all entries");
|
|
100
|
+
})
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: "getEntries(doc, n) returns only entries with version > n",
|
|
104
|
+
category: Categories.VersionFiltering,
|
|
105
|
+
run: Effect.gen(function* () {
|
|
106
|
+
const storage = yield* HotStorageTag;
|
|
107
|
+
yield* storage.append("filter-n", makeEntry(1));
|
|
108
|
+
yield* storage.append("filter-n", makeEntry(2));
|
|
109
|
+
yield* storage.append("filter-n", makeEntry(3));
|
|
110
|
+
yield* storage.append("filter-n", makeEntry(4));
|
|
111
|
+
const entries = yield* storage.getEntries("filter-n", 2);
|
|
112
|
+
yield* assertLength(entries, 2, "Should return entries with version > 2");
|
|
113
|
+
yield* assertEqual(entries[0].version, 3, "First entry should be version 3");
|
|
114
|
+
yield* assertEqual(entries[1].version, 4, "Second entry should be version 4");
|
|
115
|
+
})
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
name: "getEntries(doc, exactVersion) excludes that exact version",
|
|
119
|
+
category: Categories.VersionFiltering,
|
|
120
|
+
run: Effect.gen(function* () {
|
|
121
|
+
const storage = yield* HotStorageTag;
|
|
122
|
+
yield* storage.append("filter-exact", makeEntry(5));
|
|
123
|
+
yield* storage.append("filter-exact", makeEntry(6));
|
|
124
|
+
yield* storage.append("filter-exact", makeEntry(7));
|
|
125
|
+
const entries = yield* storage.getEntries("filter-exact", 6);
|
|
126
|
+
yield* assertLength(entries, 1, "Should exclude version 6");
|
|
127
|
+
yield* assertEqual(entries[0].version, 7, "Only version 7 should be returned");
|
|
128
|
+
})
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: "getEntries(doc, maxVersion) returns empty array",
|
|
132
|
+
category: Categories.VersionFiltering,
|
|
133
|
+
run: Effect.gen(function* () {
|
|
134
|
+
const storage = yield* HotStorageTag;
|
|
135
|
+
yield* storage.append("filter-max", makeEntry(1));
|
|
136
|
+
yield* storage.append("filter-max", makeEntry(2));
|
|
137
|
+
yield* storage.append("filter-max", makeEntry(3));
|
|
138
|
+
yield* assertEmpty(yield* storage.getEntries("filter-max", 3), "sinceVersion >= maxVersion should return empty");
|
|
139
|
+
})
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: "getEntries(doc, MAX_SAFE_INTEGER) returns empty array",
|
|
143
|
+
category: Categories.VersionFiltering,
|
|
144
|
+
run: Effect.gen(function* () {
|
|
145
|
+
const storage = yield* HotStorageTag;
|
|
146
|
+
yield* storage.append("filter-huge", makeEntry(1));
|
|
147
|
+
yield* storage.append("filter-huge", makeEntry(1e6));
|
|
148
|
+
yield* assertEmpty(yield* storage.getEntries("filter-huge", Number.MAX_SAFE_INTEGER), "sinceVersion=MAX_SAFE_INTEGER should return empty");
|
|
149
|
+
})
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
name: "entries returned sorted by version ascending",
|
|
153
|
+
category: Categories.OrderingGuarantees,
|
|
154
|
+
run: Effect.gen(function* () {
|
|
155
|
+
const storage = yield* HotStorageTag;
|
|
156
|
+
yield* storage.append("order-test", makeEntry(1));
|
|
157
|
+
yield* storage.append("order-test", makeEntry(2));
|
|
158
|
+
yield* storage.append("order-test", makeEntry(3));
|
|
159
|
+
yield* assertSortedBy(yield* storage.getEntries("order-test", 0), "version", "Entries should be sorted by version");
|
|
160
|
+
})
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: "out-of-order appends are sorted correctly on retrieval",
|
|
164
|
+
category: Categories.OrderingGuarantees,
|
|
165
|
+
run: Effect.gen(function* () {
|
|
166
|
+
const storage = yield* HotStorageTag;
|
|
167
|
+
yield* storage.append("ooo-test", makeEntry(3));
|
|
168
|
+
yield* storage.append("ooo-test", makeEntry(1));
|
|
169
|
+
yield* storage.append("ooo-test", makeEntry(4));
|
|
170
|
+
yield* storage.append("ooo-test", makeEntry(2));
|
|
171
|
+
const entries = yield* storage.getEntries("ooo-test", 0);
|
|
172
|
+
yield* assertLength(entries, 4, "Should have all 4 entries");
|
|
173
|
+
yield* assertEqual(entries[0].version, 1, "First should be version 1");
|
|
174
|
+
yield* assertEqual(entries[1].version, 2, "Second should be version 2");
|
|
175
|
+
yield* assertEqual(entries[2].version, 3, "Third should be version 3");
|
|
176
|
+
yield* assertEqual(entries[3].version, 4, "Fourth should be version 4");
|
|
177
|
+
})
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: "truncate(doc, 0) removes nothing (versions > 0 kept)",
|
|
181
|
+
category: Categories.TruncationEdgeCases,
|
|
182
|
+
run: Effect.gen(function* () {
|
|
183
|
+
const storage = yield* HotStorageTag;
|
|
184
|
+
yield* storage.append("trunc-0", makeEntry(1));
|
|
185
|
+
yield* storage.append("trunc-0", makeEntry(2));
|
|
186
|
+
yield* storage.truncate("trunc-0", 0);
|
|
187
|
+
yield* assertLength(yield* storage.getEntries("trunc-0", 0), 2, "truncate(0) should keep all entries with version > 0");
|
|
188
|
+
})
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
name: "truncate(doc, maxVersion) removes all entries",
|
|
192
|
+
category: Categories.TruncationEdgeCases,
|
|
193
|
+
run: Effect.gen(function* () {
|
|
194
|
+
const storage = yield* HotStorageTag;
|
|
195
|
+
yield* storage.append("trunc-all", makeEntry(1));
|
|
196
|
+
yield* storage.append("trunc-all", makeEntry(2));
|
|
197
|
+
yield* storage.append("trunc-all", makeEntry(3));
|
|
198
|
+
yield* storage.truncate("trunc-all", 3);
|
|
199
|
+
yield* assertEmpty(yield* storage.getEntries("trunc-all", 0), "truncate(maxVersion) should remove all entries");
|
|
200
|
+
})
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
name: "truncate(doc, middleVersion) removes correct entries",
|
|
204
|
+
category: Categories.TruncationEdgeCases,
|
|
205
|
+
run: Effect.gen(function* () {
|
|
206
|
+
const storage = yield* HotStorageTag;
|
|
207
|
+
yield* storage.append("trunc-mid", makeEntry(1));
|
|
208
|
+
yield* storage.append("trunc-mid", makeEntry(2));
|
|
209
|
+
yield* storage.append("trunc-mid", makeEntry(3));
|
|
210
|
+
yield* storage.append("trunc-mid", makeEntry(4));
|
|
211
|
+
yield* storage.append("trunc-mid", makeEntry(5));
|
|
212
|
+
yield* storage.truncate("trunc-mid", 3);
|
|
213
|
+
const entries = yield* storage.getEntries("trunc-mid", 0);
|
|
214
|
+
yield* assertLength(entries, 2, "Should keep versions 4 and 5");
|
|
215
|
+
yield* assertEqual(entries[0].version, 4, "First remaining should be 4");
|
|
216
|
+
yield* assertEqual(entries[1].version, 5, "Second remaining should be 5");
|
|
217
|
+
})
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
name: "multiple truncates work correctly",
|
|
221
|
+
category: Categories.TruncationEdgeCases,
|
|
222
|
+
run: Effect.gen(function* () {
|
|
223
|
+
const storage = yield* HotStorageTag;
|
|
224
|
+
yield* storage.append("multi-trunc", makeEntry(1));
|
|
225
|
+
yield* storage.append("multi-trunc", makeEntry(2));
|
|
226
|
+
yield* storage.append("multi-trunc", makeEntry(3));
|
|
227
|
+
yield* storage.append("multi-trunc", makeEntry(4));
|
|
228
|
+
yield* storage.append("multi-trunc", makeEntry(5));
|
|
229
|
+
yield* storage.truncate("multi-trunc", 2);
|
|
230
|
+
yield* storage.truncate("multi-trunc", 4);
|
|
231
|
+
const entries = yield* storage.getEntries("multi-trunc", 0);
|
|
232
|
+
yield* assertLength(entries, 1, "Should only have version 5");
|
|
233
|
+
yield* assertEqual(entries[0].version, 5, "Only version 5 should remain");
|
|
234
|
+
})
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
name: "truncate followed by append works correctly",
|
|
238
|
+
category: Categories.TruncationEdgeCases,
|
|
239
|
+
run: Effect.gen(function* () {
|
|
240
|
+
const storage = yield* HotStorageTag;
|
|
241
|
+
yield* storage.append("trunc-append", makeEntry(1));
|
|
242
|
+
yield* storage.append("trunc-append", makeEntry(2));
|
|
243
|
+
yield* storage.truncate("trunc-append", 2);
|
|
244
|
+
yield* storage.append("trunc-append", makeEntry(3));
|
|
245
|
+
yield* storage.append("trunc-append", makeEntry(4));
|
|
246
|
+
const entries = yield* storage.getEntries("trunc-append", 0);
|
|
247
|
+
yield* assertLength(entries, 2, "Should have versions 3 and 4");
|
|
248
|
+
yield* assertEqual(entries[0].version, 3, "First should be 3");
|
|
249
|
+
yield* assertEqual(entries[1].version, 4, "Second should be 4");
|
|
250
|
+
})
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
name: "transaction data is preserved exactly",
|
|
254
|
+
category: Categories.WalEntryIntegrity,
|
|
255
|
+
run: Effect.gen(function* () {
|
|
256
|
+
const storage = yield* HotStorageTag;
|
|
257
|
+
const entry = makeEntryWithData(1, {
|
|
258
|
+
key: "value",
|
|
259
|
+
nested: { a: 1 }
|
|
260
|
+
});
|
|
261
|
+
yield* storage.append("tx-data", entry);
|
|
262
|
+
const entries = yield* storage.getEntries("tx-data", 0);
|
|
263
|
+
yield* assertLength(entries, 1, "Should have one entry");
|
|
264
|
+
yield* assertEqual(entries[0].transaction, entry.transaction, "Transaction should be preserved exactly");
|
|
265
|
+
})
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
name: "version number is preserved exactly",
|
|
269
|
+
category: Categories.WalEntryIntegrity,
|
|
270
|
+
run: Effect.gen(function* () {
|
|
271
|
+
const storage = yield* HotStorageTag;
|
|
272
|
+
const version = 42;
|
|
273
|
+
const entry = makeEntry(version);
|
|
274
|
+
yield* storage.append("version-preserve", entry);
|
|
275
|
+
yield* assertEqual((yield* storage.getEntries("version-preserve", 0))[0].version, version, "Version should be preserved exactly");
|
|
276
|
+
})
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
name: "timestamp is preserved exactly",
|
|
280
|
+
category: Categories.WalEntryIntegrity,
|
|
281
|
+
run: Effect.gen(function* () {
|
|
282
|
+
const storage = yield* HotStorageTag;
|
|
283
|
+
const timestamp = 17040672e5;
|
|
284
|
+
const entry = makeEntry(1, timestamp);
|
|
285
|
+
yield* storage.append("timestamp-preserve", entry);
|
|
286
|
+
yield* assertEqual((yield* storage.getEntries("timestamp-preserve", 0))[0].timestamp, timestamp, "Timestamp should be preserved exactly");
|
|
287
|
+
})
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
name: "complex transaction operations survive roundtrip",
|
|
291
|
+
category: Categories.WalEntryIntegrity,
|
|
292
|
+
run: Effect.gen(function* () {
|
|
293
|
+
const storage = yield* HotStorageTag;
|
|
294
|
+
const entry = {
|
|
295
|
+
transaction: Transaction.make([
|
|
296
|
+
{
|
|
297
|
+
type: "set",
|
|
298
|
+
path: ["a"],
|
|
299
|
+
value: 1
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
type: "set",
|
|
303
|
+
path: ["b", "c"],
|
|
304
|
+
value: "nested"
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
type: "set",
|
|
308
|
+
path: ["arr"],
|
|
309
|
+
value: [
|
|
310
|
+
1,
|
|
311
|
+
2,
|
|
312
|
+
3
|
|
313
|
+
]
|
|
314
|
+
}
|
|
315
|
+
]),
|
|
316
|
+
version: 1,
|
|
317
|
+
timestamp: Date.now()
|
|
318
|
+
};
|
|
319
|
+
yield* storage.append("complex-tx", entry);
|
|
320
|
+
yield* assertEqual((yield* storage.getEntries("complex-tx", 0))[0].transaction, entry.transaction, "Complex transaction should survive roundtrip");
|
|
321
|
+
})
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
name: "different documents have independent entry lists",
|
|
325
|
+
category: Categories.DocumentIsolation,
|
|
326
|
+
run: Effect.gen(function* () {
|
|
327
|
+
const storage = yield* HotStorageTag;
|
|
328
|
+
yield* storage.append("iso-hot-1", makeEntry(1));
|
|
329
|
+
yield* storage.append("iso-hot-1", makeEntry(2));
|
|
330
|
+
yield* storage.append("iso-hot-2", makeEntry(10));
|
|
331
|
+
const entries1 = yield* storage.getEntries("iso-hot-1", 0);
|
|
332
|
+
const entries2 = yield* storage.getEntries("iso-hot-2", 0);
|
|
333
|
+
yield* assertLength(entries1, 2, "Doc 1 should have 2 entries");
|
|
334
|
+
yield* assertLength(entries2, 1, "Doc 2 should have 1 entry");
|
|
335
|
+
yield* assertEqual(entries1[0].version, 1, "Doc 1 first entry version");
|
|
336
|
+
yield* assertEqual(entries2[0].version, 10, "Doc 2 first entry version");
|
|
337
|
+
})
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
name: "appending to one doc does not affect others",
|
|
341
|
+
category: Categories.DocumentIsolation,
|
|
342
|
+
run: Effect.gen(function* () {
|
|
343
|
+
const storage = yield* HotStorageTag;
|
|
344
|
+
yield* storage.append("append-iso-1", makeEntry(1));
|
|
345
|
+
const beforeAppend = yield* storage.getEntries("append-iso-1", 0);
|
|
346
|
+
yield* storage.append("append-iso-2", makeEntry(100));
|
|
347
|
+
yield* storage.append("append-iso-2", makeEntry(101));
|
|
348
|
+
const afterAppend = yield* storage.getEntries("append-iso-1", 0);
|
|
349
|
+
yield* assertEqual(beforeAppend.length, afterAppend.length, "Appending to doc 2 should not affect doc 1");
|
|
350
|
+
})
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
name: "truncating one doc does not affect others",
|
|
354
|
+
category: Categories.DocumentIsolation,
|
|
355
|
+
run: Effect.gen(function* () {
|
|
356
|
+
const storage = yield* HotStorageTag;
|
|
357
|
+
yield* storage.append("trunc-iso-1", makeEntry(1));
|
|
358
|
+
yield* storage.append("trunc-iso-1", makeEntry(2));
|
|
359
|
+
yield* storage.append("trunc-iso-2", makeEntry(1));
|
|
360
|
+
yield* storage.append("trunc-iso-2", makeEntry(2));
|
|
361
|
+
yield* storage.truncate("trunc-iso-1", 2);
|
|
362
|
+
const entries1 = yield* storage.getEntries("trunc-iso-1", 0);
|
|
363
|
+
const entries2 = yield* storage.getEntries("trunc-iso-2", 0);
|
|
364
|
+
yield* assertEmpty(entries1, "Doc 1 should be empty after truncate");
|
|
365
|
+
yield* assertLength(entries2, 2, "Doc 2 should still have 2 entries");
|
|
366
|
+
})
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
name: "handle 1000+ entries per document",
|
|
370
|
+
category: Categories.LargeScaleOperations,
|
|
371
|
+
run: Effect.gen(function* () {
|
|
372
|
+
const storage = yield* HotStorageTag;
|
|
373
|
+
const count = 1e3;
|
|
374
|
+
for (let i = 1; i <= count; i++) yield* storage.append("large-entries", makeEntry(i));
|
|
375
|
+
const entries = yield* storage.getEntries("large-entries", 0);
|
|
376
|
+
yield* assertLength(entries, count, `Should have ${count} entries`);
|
|
377
|
+
yield* assertSortedBy(entries, "version", "Should be sorted by version");
|
|
378
|
+
yield* assertEqual(entries[0].version, 1, "First should be version 1");
|
|
379
|
+
yield* assertEqual(entries[count - 1].version, count, `Last should be version ${count}`);
|
|
380
|
+
})
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
name: "handle 100+ documents",
|
|
384
|
+
category: Categories.LargeScaleOperations,
|
|
385
|
+
run: Effect.gen(function* () {
|
|
386
|
+
const storage = yield* HotStorageTag;
|
|
387
|
+
const docCount = 100;
|
|
388
|
+
for (let i = 0; i < docCount; i++) {
|
|
389
|
+
yield* storage.append(`multi-doc-${i}`, makeEntry(1));
|
|
390
|
+
yield* storage.append(`multi-doc-${i}`, makeEntry(2));
|
|
391
|
+
}
|
|
392
|
+
let totalEntries = 0;
|
|
393
|
+
for (let i = 0; i < docCount; i++) {
|
|
394
|
+
const entries = yield* storage.getEntries(`multi-doc-${i}`, 0);
|
|
395
|
+
totalEntries += entries.length;
|
|
396
|
+
yield* assertLength(entries, 2, `Doc ${i} should have 2 entries`);
|
|
397
|
+
}
|
|
398
|
+
yield* assertEqual(totalEntries, docCount * 2, "Total entries should match");
|
|
399
|
+
})
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
name: "large transaction data (10KB+) survives roundtrip",
|
|
403
|
+
category: Categories.LargeScaleOperations,
|
|
404
|
+
run: Effect.gen(function* () {
|
|
405
|
+
const storage = yield* HotStorageTag;
|
|
406
|
+
const entry = makeEntryWithData(1, { content: "x".repeat(10 * 1024) });
|
|
407
|
+
yield* storage.append("large-tx", entry);
|
|
408
|
+
const entries = yield* storage.getEntries("large-tx", 0);
|
|
409
|
+
yield* assertLength(entries, 1, "Should have one entry");
|
|
410
|
+
yield* assertEqual(entries[0].transaction, entry.transaction, "Large transaction data should survive roundtrip");
|
|
411
|
+
})
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
name: "long documentId (1000+ chars) works",
|
|
415
|
+
category: Categories.DocumentIdEdgeCases,
|
|
416
|
+
run: Effect.gen(function* () {
|
|
417
|
+
const storage = yield* HotStorageTag;
|
|
418
|
+
const longId = "h".repeat(1e3);
|
|
419
|
+
const entry = makeEntry(1);
|
|
420
|
+
yield* storage.append(longId, entry);
|
|
421
|
+
yield* assertLength(yield* storage.getEntries(longId, 0), 1, "Long documentId should work");
|
|
422
|
+
})
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
name: "unicode documentId works",
|
|
426
|
+
category: Categories.DocumentIdEdgeCases,
|
|
427
|
+
run: Effect.gen(function* () {
|
|
428
|
+
const storage = yield* HotStorageTag;
|
|
429
|
+
const unicodeId = "hot-doc-id";
|
|
430
|
+
const entry = makeEntry(1);
|
|
431
|
+
yield* storage.append(unicodeId, entry);
|
|
432
|
+
yield* assertLength(yield* storage.getEntries(unicodeId, 0), 1, "Unicode documentId should work");
|
|
433
|
+
})
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
name: "documentId with special chars works",
|
|
437
|
+
category: Categories.DocumentIdEdgeCases,
|
|
438
|
+
run: Effect.gen(function* () {
|
|
439
|
+
const storage = yield* HotStorageTag;
|
|
440
|
+
const specialId = "hot/path:to.wal";
|
|
441
|
+
const entry = makeEntry(1);
|
|
442
|
+
yield* storage.append(specialId, entry);
|
|
443
|
+
yield* assertLength(yield* storage.getEntries(specialId, 0), 1, "DocumentId with special chars should work");
|
|
444
|
+
})
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
name: "documentId with spaces works",
|
|
448
|
+
category: Categories.DocumentIdEdgeCases,
|
|
449
|
+
run: Effect.gen(function* () {
|
|
450
|
+
const storage = yield* HotStorageTag;
|
|
451
|
+
const spacedId = "hot doc with spaces";
|
|
452
|
+
const entry = makeEntry(1);
|
|
453
|
+
yield* storage.append(spacedId, entry);
|
|
454
|
+
yield* assertLength(yield* storage.getEntries(spacedId, 0), 1, "DocumentId with spaces should work");
|
|
455
|
+
})
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
name: "version 0 entry is handled correctly",
|
|
459
|
+
category: Categories.VersionFiltering,
|
|
460
|
+
run: Effect.gen(function* () {
|
|
461
|
+
const storage = yield* HotStorageTag;
|
|
462
|
+
yield* storage.append("version-0-entry", makeEntry(0));
|
|
463
|
+
yield* storage.append("version-0-entry", makeEntry(1));
|
|
464
|
+
yield* assertTrue((yield* storage.getEntries("version-0-entry", -1)).some((e) => e.version === 0), "Version 0 entry should be retrievable with sinceVersion < 0");
|
|
465
|
+
yield* assertTrue(!(yield* storage.getEntries("version-0-entry", 0)).some((e) => e.version === 0), "Version 0 entry should be excluded with sinceVersion = 0");
|
|
466
|
+
})
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
name: "appendWithCheck succeeds for first entry (expectedVersion=1)",
|
|
470
|
+
category: Categories.GapChecking,
|
|
471
|
+
run: Effect.gen(function* () {
|
|
472
|
+
const storage = yield* HotStorageTag;
|
|
473
|
+
const entry = makeEntry(1);
|
|
474
|
+
yield* storage.appendWithCheck("gap-check-first", entry, 1);
|
|
475
|
+
const entries = yield* storage.getEntries("gap-check-first", 0);
|
|
476
|
+
yield* assertLength(entries, 1, "Should have one entry");
|
|
477
|
+
yield* assertEqual(entries[0].version, 1, "Entry version should be 1");
|
|
478
|
+
})
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
name: "appendWithCheck succeeds for consecutive versions",
|
|
482
|
+
category: Categories.GapChecking,
|
|
483
|
+
run: Effect.gen(function* () {
|
|
484
|
+
const storage = yield* HotStorageTag;
|
|
485
|
+
yield* storage.appendWithCheck("gap-check-consecutive", makeEntry(1), 1);
|
|
486
|
+
yield* storage.appendWithCheck("gap-check-consecutive", makeEntry(2), 2);
|
|
487
|
+
yield* storage.appendWithCheck("gap-check-consecutive", makeEntry(3), 3);
|
|
488
|
+
const entries = yield* storage.getEntries("gap-check-consecutive", 0);
|
|
489
|
+
yield* assertLength(entries, 3, "Should have three entries");
|
|
490
|
+
yield* assertEqual(entries[0].version, 1, "First entry version should be 1");
|
|
491
|
+
yield* assertEqual(entries[1].version, 2, "Second entry version should be 2");
|
|
492
|
+
yield* assertEqual(entries[2].version, 3, "Third entry version should be 3");
|
|
493
|
+
})
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
name: "appendWithCheck fails for version gap (skipping version 2)",
|
|
497
|
+
category: Categories.GapChecking,
|
|
498
|
+
run: Effect.gen(function* () {
|
|
499
|
+
const storage = yield* HotStorageTag;
|
|
500
|
+
yield* storage.appendWithCheck("gap-check-fail", makeEntry(1), 1);
|
|
501
|
+
const result = yield* Effect.either(storage.appendWithCheck("gap-check-fail", makeEntry(3), 3));
|
|
502
|
+
yield* assertTrue(result._tag === "Left", "appendWithCheck should fail when there's a version gap");
|
|
503
|
+
if (result._tag === "Left") yield* assertTrue(result.left._tag === "WalVersionGapError", "Error should be WalVersionGapError");
|
|
504
|
+
const entries = yield* storage.getEntries("gap-check-fail", 0);
|
|
505
|
+
yield* assertLength(entries, 1, "Should only have version 1");
|
|
506
|
+
yield* assertEqual(entries[0].version, 1, "Only version 1 should exist");
|
|
507
|
+
})
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
name: "appendWithCheck fails if first entry is not version 1",
|
|
511
|
+
category: Categories.GapChecking,
|
|
512
|
+
run: Effect.gen(function* () {
|
|
513
|
+
const storage = yield* HotStorageTag;
|
|
514
|
+
const result = yield* Effect.either(storage.appendWithCheck("gap-check-not-first", makeEntry(2), 2));
|
|
515
|
+
yield* assertTrue(result._tag === "Left", "appendWithCheck should fail when first entry is not version 1");
|
|
516
|
+
if (result._tag === "Left") yield* assertTrue(result.left._tag === "WalVersionGapError", "Error should be WalVersionGapError");
|
|
517
|
+
yield* assertEmpty(yield* storage.getEntries("gap-check-not-first", 0), "No entries should exist after failed append");
|
|
518
|
+
})
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
name: "appendWithCheck fails when entry already exists at expectedVersion",
|
|
522
|
+
category: Categories.GapChecking,
|
|
523
|
+
run: Effect.gen(function* () {
|
|
524
|
+
const storage = yield* HotStorageTag;
|
|
525
|
+
yield* storage.appendWithCheck("gap-check-duplicate", makeEntry(1), 1);
|
|
526
|
+
yield* assertTrue((yield* Effect.either(storage.appendWithCheck("gap-check-duplicate", makeEntry(1), 1)))._tag === "Left", "appendWithCheck should fail when version already exists");
|
|
527
|
+
yield* assertLength(yield* storage.getEntries("gap-check-duplicate", 0), 1, "Should still only have one entry");
|
|
528
|
+
})
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
name: "appendWithCheck after truncate works correctly",
|
|
532
|
+
category: Categories.GapChecking,
|
|
533
|
+
run: Effect.gen(function* () {
|
|
534
|
+
const storage = yield* HotStorageTag;
|
|
535
|
+
yield* storage.appendWithCheck("gap-check-truncate", makeEntry(1), 1);
|
|
536
|
+
yield* storage.appendWithCheck("gap-check-truncate", makeEntry(2), 2);
|
|
537
|
+
yield* storage.appendWithCheck("gap-check-truncate", makeEntry(3), 3);
|
|
538
|
+
yield* storage.truncate("gap-check-truncate", 2);
|
|
539
|
+
yield* storage.appendWithCheck("gap-check-truncate", makeEntry(4), 4);
|
|
540
|
+
const entries = yield* storage.getEntries("gap-check-truncate", 0);
|
|
541
|
+
yield* assertLength(entries, 2, "Should have versions 3 and 4");
|
|
542
|
+
yield* assertEqual(entries[0].version, 3, "First should be version 3");
|
|
543
|
+
yield* assertEqual(entries[1].version, 4, "Second should be version 4");
|
|
544
|
+
})
|
|
545
|
+
}
|
|
546
|
+
];
|
|
547
|
+
/**
|
|
548
|
+
* Get all HotStorage test cases.
|
|
549
|
+
*
|
|
550
|
+
* @returns Array of test cases that require HotStorageTag
|
|
551
|
+
*/
|
|
552
|
+
const makeTests = () => tests;
|
|
553
|
+
/**
|
|
554
|
+
* Run all tests and collect results.
|
|
555
|
+
*
|
|
556
|
+
* @returns Effect that produces TestResults
|
|
557
|
+
*/
|
|
558
|
+
const runAll = () => Effect.gen(function* () {
|
|
559
|
+
const passed = [];
|
|
560
|
+
const failed = [];
|
|
561
|
+
for (const test of tests) {
|
|
562
|
+
const result = yield* Effect.either(test.run);
|
|
563
|
+
if (result._tag === "Right") passed.push(test);
|
|
564
|
+
else failed.push({
|
|
565
|
+
test,
|
|
566
|
+
error: result.left
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
return {
|
|
570
|
+
passed,
|
|
571
|
+
failed,
|
|
572
|
+
total: tests.length,
|
|
573
|
+
passCount: passed.length,
|
|
574
|
+
failCount: failed.length
|
|
575
|
+
};
|
|
576
|
+
});
|
|
577
|
+
const HotStorageTestSuite = {
|
|
578
|
+
Categories,
|
|
579
|
+
makeTests,
|
|
580
|
+
runAll
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
//#endregion
|
|
584
|
+
export { Categories, HotStorageTestSuite };
|
|
585
|
+
//# sourceMappingURL=HotStorageTestSuite.mjs.map
|