@jamesaphoenix/tx-test-utils 0.4.2 → 0.4.3

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.
Files changed (56) hide show
  1. package/README.md +480 -0
  2. package/dist/adapters/better-sqlite3-adapter.d.ts +36 -0
  3. package/dist/adapters/better-sqlite3-adapter.d.ts.map +1 -0
  4. package/dist/adapters/better-sqlite3-adapter.js +78 -0
  5. package/dist/adapters/better-sqlite3-adapter.js.map +1 -0
  6. package/dist/chaos/chaos-utilities.d.ts +465 -0
  7. package/dist/chaos/chaos-utilities.d.ts.map +1 -0
  8. package/dist/chaos/chaos-utilities.js +793 -0
  9. package/dist/chaos/chaos-utilities.js.map +1 -0
  10. package/dist/chaos/chaos.test.d.ts +9 -0
  11. package/dist/chaos/chaos.test.d.ts.map +1 -0
  12. package/dist/chaos/chaos.test.js +498 -0
  13. package/dist/chaos/chaos.test.js.map +1 -0
  14. package/dist/chaos/index.d.ts +20 -0
  15. package/dist/chaos/index.d.ts.map +1 -0
  16. package/dist/chaos/index.js +39 -0
  17. package/dist/chaos/index.js.map +1 -0
  18. package/dist/database/index.d.ts +1 -1
  19. package/dist/database/index.d.ts.map +1 -1
  20. package/dist/database/index.js +1 -1
  21. package/dist/database/index.js.map +1 -1
  22. package/dist/database/test-database.d.ts +25 -5
  23. package/dist/database/test-database.d.ts.map +1 -1
  24. package/dist/database/test-database.js +142 -11
  25. package/dist/database/test-database.js.map +1 -1
  26. package/dist/factories/index.d.ts +0 -3
  27. package/dist/factories/index.d.ts.map +1 -1
  28. package/dist/factories/index.js +0 -6
  29. package/dist/factories/index.js.map +1 -1
  30. package/dist/factories/learning.factory.js +1 -1
  31. package/dist/factories/learning.factory.js.map +1 -1
  32. package/dist/helpers/index.d.ts +2 -0
  33. package/dist/helpers/index.d.ts.map +1 -1
  34. package/dist/helpers/index.js +4 -0
  35. package/dist/helpers/index.js.map +1 -1
  36. package/dist/helpers/shared-test-layer.d.ts +74 -0
  37. package/dist/helpers/shared-test-layer.d.ts.map +1 -0
  38. package/dist/helpers/shared-test-layer.js +104 -0
  39. package/dist/helpers/shared-test-layer.js.map +1 -0
  40. package/dist/helpers/sqlite-factory.d.ts +49 -0
  41. package/dist/helpers/sqlite-factory.d.ts.map +1 -0
  42. package/dist/helpers/sqlite-factory.js +74 -0
  43. package/dist/helpers/sqlite-factory.js.map +1 -0
  44. package/dist/index.d.ts +6 -2
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +30 -8
  47. package/dist/index.js.map +1 -1
  48. package/dist/singleton.d.ts +49 -0
  49. package/dist/singleton.d.ts.map +1 -0
  50. package/dist/singleton.js +66 -0
  51. package/dist/singleton.js.map +1 -0
  52. package/package.json +11 -10
  53. package/dist/factories/factories.test.d.ts +0 -8
  54. package/dist/factories/factories.test.d.ts.map +0 -1
  55. package/dist/factories/factories.test.js +0 -419
  56. package/dist/factories/factories.test.js.map +0 -1
@@ -0,0 +1,465 @@
1
+ /**
2
+ * Chaos Engineering Utilities Implementation
3
+ *
4
+ * Provides controlled failure injection for testing tx resilience.
5
+ *
6
+ * @module @tx/test-utils/chaos/chaos-utilities
7
+ */
8
+ import type { TestDatabase } from "../database/index.js";
9
+ /**
10
+ * Options for crashAfter utility.
11
+ */
12
+ export interface CrashAfterOptions {
13
+ /** Milliseconds before "crash" occurs */
14
+ ms: number;
15
+ /** Optional callback to execute before crash */
16
+ beforeCrash?: () => void | Promise<void>;
17
+ /** If true, throws instead of returning (default: false) */
18
+ throwOnCrash?: boolean;
19
+ }
20
+ /**
21
+ * Result of crashAfter operation.
22
+ */
23
+ export interface CrashAfterResult {
24
+ /** Whether the operation completed before the crash timeout */
25
+ completed: boolean;
26
+ /** Time elapsed in milliseconds */
27
+ elapsedMs: number;
28
+ /** Error if throwOnCrash was true and crash occurred */
29
+ error?: Error;
30
+ }
31
+ /**
32
+ * Simulate process death mid-operation.
33
+ *
34
+ * Wraps an async operation and "crashes" after specified time.
35
+ * Useful for testing transaction rollback and partial state handling.
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * // Test that a transaction rolls back on crash
40
+ * const result = await crashAfter({ ms: 100 }, async () => {
41
+ * await startLongOperation()
42
+ * await sleep(200) // This won't complete
43
+ * })
44
+ * expect(result.completed).toBe(false)
45
+ * ```
46
+ */
47
+ export declare const crashAfter: <T>(options: CrashAfterOptions, operation: () => Promise<T>) => Promise<CrashAfterResult & {
48
+ value?: T;
49
+ }>;
50
+ /**
51
+ * Custom error type for crash simulation.
52
+ */
53
+ export declare class CrashSimulationError extends Error {
54
+ readonly name = "CrashSimulationError";
55
+ readonly crashAfterMs: number;
56
+ constructor(ms: number);
57
+ }
58
+ /**
59
+ * Options for killHeartbeat utility.
60
+ */
61
+ export interface KillHeartbeatOptions {
62
+ /** The worker ID to kill heartbeat for */
63
+ workerId: string;
64
+ /** Test database instance */
65
+ db: TestDatabase;
66
+ }
67
+ /**
68
+ * Controller for managing worker heartbeat state.
69
+ * Allows simulating heartbeat failure and restoration.
70
+ */
71
+ export declare class WorkerHeartbeatController {
72
+ private readonly workerId;
73
+ private readonly db;
74
+ private originalHeartbeat;
75
+ private killed;
76
+ constructor(options: KillHeartbeatOptions);
77
+ /**
78
+ * Stop the heartbeat by setting last_heartbeat_at to a past time.
79
+ * This will trigger dead worker detection.
80
+ *
81
+ * @param minutesInPast How many minutes in the past to set the heartbeat (default: 60)
82
+ */
83
+ kill(minutesInPast?: number): void;
84
+ /**
85
+ * Restore the original heartbeat timestamp.
86
+ */
87
+ restore(): void;
88
+ /**
89
+ * Update heartbeat to current time (simulate alive worker).
90
+ */
91
+ revive(): void;
92
+ /**
93
+ * Check if heartbeat is currently killed.
94
+ */
95
+ isKilled(): boolean;
96
+ }
97
+ /**
98
+ * Kill a worker's heartbeat to trigger dead worker detection.
99
+ *
100
+ * @example
101
+ * ```typescript
102
+ * const controller = killHeartbeat({ workerId: 'worker-123', db: testDb })
103
+ * controller.kill(30) // Set heartbeat to 30 minutes ago
104
+ *
105
+ * // Worker should now be detected as dead
106
+ * const deadWorkers = await findDeadWorkers()
107
+ * expect(deadWorkers).toContain('worker-123')
108
+ *
109
+ * controller.restore() // Restore original heartbeat
110
+ * ```
111
+ */
112
+ export declare const killHeartbeat: (options: KillHeartbeatOptions) => WorkerHeartbeatController;
113
+ /**
114
+ * Options for raceWorkers utility.
115
+ */
116
+ export interface RaceWorkersOptions {
117
+ /** Number of workers to spawn */
118
+ count: number;
119
+ /** Task ID to claim */
120
+ taskId: string;
121
+ /** Test database instance */
122
+ db: TestDatabase;
123
+ /** Optional delay between worker attempts (ms) */
124
+ delayBetweenMs?: number;
125
+ /** Optional lease duration in minutes */
126
+ leaseDurationMinutes?: number;
127
+ }
128
+ /**
129
+ * Result of raceWorkers operation.
130
+ */
131
+ export interface RaceWorkersResult {
132
+ /** Worker ID that won the race (or null if none) */
133
+ winner: string | null;
134
+ /** All worker IDs that participated */
135
+ workers: string[];
136
+ /** Workers that failed to claim */
137
+ losers: string[];
138
+ /** Number of successful claims (should be 1 or 0) */
139
+ successfulClaims: number;
140
+ /** Any errors that occurred */
141
+ errors: Array<{
142
+ workerId: string;
143
+ error: string;
144
+ }>;
145
+ }
146
+ /**
147
+ * Spawn n workers that all attempt to claim the same task.
148
+ * Tests claim atomicity and race condition handling.
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * const result = await raceWorkers({
153
+ * count: 5,
154
+ * taskId: 'tx-abc123',
155
+ * db: testDb
156
+ * })
157
+ *
158
+ * expect(result.successfulClaims).toBe(1) // Only one winner
159
+ * expect(result.losers.length).toBe(4)
160
+ * ```
161
+ */
162
+ export declare const raceWorkers: (options: RaceWorkersOptions) => Promise<RaceWorkersResult>;
163
+ /**
164
+ * Types of corruption that can be injected.
165
+ */
166
+ export type CorruptionType = "null_required_field" | "invalid_status" | "invalid_json" | "truncated_string" | "future_timestamp" | "negative_score" | "orphaned_dependency" | "self_reference";
167
+ /**
168
+ * Options for corruptState utility.
169
+ */
170
+ export interface CorruptStateOptions {
171
+ /** Table to corrupt */
172
+ table: "tasks" | "task_claims" | "task_dependencies" | "workers" | "learnings";
173
+ /** Type of corruption to inject */
174
+ type: CorruptionType;
175
+ /** Test database instance */
176
+ db: TestDatabase;
177
+ /** Specific row ID to corrupt (optional - will create new row if not provided) */
178
+ rowId?: string;
179
+ /** Field to corrupt (for specific field corruption) */
180
+ field?: string;
181
+ }
182
+ /**
183
+ * Inject invalid data into the database for testing validation and recovery.
184
+ *
185
+ * @example
186
+ * ```typescript
187
+ * // Inject an invalid status
188
+ * const result = corruptState({
189
+ * table: 'tasks',
190
+ * type: 'invalid_status',
191
+ * db: testDb,
192
+ * rowId: 'tx-abc123'
193
+ * })
194
+ *
195
+ * // Test that validation catches it
196
+ * await expect(taskService.get('tx-abc123')).rejects.toThrow()
197
+ * ```
198
+ */
199
+ export declare const corruptState: (options: CorruptStateOptions) => {
200
+ rowId: string;
201
+ corrupted: boolean;
202
+ };
203
+ /**
204
+ * Options for replayJSONL utility.
205
+ */
206
+ export interface ReplayJSONLOptions {
207
+ /** Test database instance */
208
+ db: TestDatabase;
209
+ /** JSONL content to replay (string or array of operations) */
210
+ content: string | readonly SyncOperation[];
211
+ /** If true, clear existing data before replay (default: false) */
212
+ clearFirst?: boolean;
213
+ /** Optional timestamp to use as "now" for conflict resolution */
214
+ asOfTimestamp?: Date;
215
+ }
216
+ /**
217
+ * Sync operation structure (matches tx sync format).
218
+ */
219
+ export interface SyncOperation {
220
+ v: number;
221
+ op: "upsert" | "delete" | "dep_add" | "dep_remove";
222
+ ts: string;
223
+ id?: string;
224
+ blockerId?: string;
225
+ blockedId?: string;
226
+ data?: {
227
+ title?: string;
228
+ description?: string;
229
+ status?: string;
230
+ score?: number;
231
+ parentId?: string | null;
232
+ metadata?: Record<string, unknown>;
233
+ };
234
+ }
235
+ /**
236
+ * Result of replayJSONL operation.
237
+ */
238
+ export interface ReplayJSONLResult {
239
+ /** Number of operations replayed */
240
+ opsReplayed: number;
241
+ /** Number of tasks created */
242
+ tasksCreated: number;
243
+ /** Number of tasks updated */
244
+ tasksUpdated: number;
245
+ /** Number of tasks deleted */
246
+ tasksDeleted: number;
247
+ /** Number of dependencies added */
248
+ depsAdded: number;
249
+ /** Number of dependencies removed */
250
+ depsRemoved: number;
251
+ /** Any errors encountered */
252
+ errors: string[];
253
+ }
254
+ /**
255
+ * Deterministically replay a JSONL sync log against the database.
256
+ * Useful for testing sync conflict resolution and data migration.
257
+ *
258
+ * @example
259
+ * ```typescript
260
+ * const jsonl = `
261
+ * {"v":1,"op":"upsert","ts":"2024-01-01T00:00:00Z","id":"tx-abc123","data":{"title":"Task 1","status":"backlog","score":500}}
262
+ * {"v":1,"op":"upsert","ts":"2024-01-02T00:00:00Z","id":"tx-abc123","data":{"title":"Task 1 Updated","status":"active","score":600}}
263
+ * `
264
+ *
265
+ * const result = await replayJSONL({ db: testDb, content: jsonl })
266
+ * expect(result.tasksUpdated).toBe(1)
267
+ * ```
268
+ */
269
+ export declare const replayJSONL: (options: ReplayJSONLOptions) => ReplayJSONLResult;
270
+ /**
271
+ * Options for doubleComplete utility.
272
+ */
273
+ export interface DoubleCompleteOptions {
274
+ /** Task ID to attempt double completion */
275
+ taskId: string;
276
+ /** Test database instance */
277
+ db: TestDatabase;
278
+ /** Worker ID attempting the completion */
279
+ workerId?: string;
280
+ }
281
+ /**
282
+ * Result of doubleComplete operation.
283
+ */
284
+ export interface DoubleCompleteResult {
285
+ /** Whether the first completion succeeded */
286
+ firstCompleted: boolean;
287
+ /** Whether the second completion succeeded (should be false) */
288
+ secondCompleted: boolean;
289
+ /** Error from second completion attempt */
290
+ secondError?: string;
291
+ /** Original status before any completion */
292
+ originalStatus: string;
293
+ /** Final status after both attempts */
294
+ finalStatus: string;
295
+ }
296
+ /**
297
+ * Attempt to complete an already-completed task.
298
+ * Tests idempotency and double-completion handling.
299
+ *
300
+ * @example
301
+ * ```typescript
302
+ * const result = await doubleComplete({
303
+ * taskId: 'tx-abc123',
304
+ * db: testDb
305
+ * })
306
+ *
307
+ * expect(result.firstCompleted).toBe(true)
308
+ * expect(result.secondCompleted).toBe(false) // Should be idempotent
309
+ * ```
310
+ */
311
+ export declare const doubleComplete: (options: DoubleCompleteOptions) => DoubleCompleteResult;
312
+ /**
313
+ * Options for partialWrite utility.
314
+ */
315
+ export interface PartialWriteOptions {
316
+ /** Table to write to */
317
+ table: "tasks" | "task_claims" | "learnings";
318
+ /** Test database instance */
319
+ db: TestDatabase;
320
+ /** Number of rows to write */
321
+ rowCount: number;
322
+ /** Row number at which to "fail" (1-indexed) */
323
+ failAtRow: number;
324
+ /** If true, wrap in transaction for testing rollback */
325
+ useTransaction?: boolean;
326
+ }
327
+ /**
328
+ * Result of partialWrite operation.
329
+ */
330
+ export interface PartialWriteResult {
331
+ /** Number of rows successfully written */
332
+ rowsWritten: number;
333
+ /** Number of rows that failed */
334
+ rowsFailed: number;
335
+ /** Whether the failure triggered a rollback */
336
+ rolledBack: boolean;
337
+ /** IDs of rows that were written */
338
+ writtenIds: string[];
339
+ /** Error that caused the failure */
340
+ error?: string;
341
+ }
342
+ /**
343
+ * Simulate an interrupted database write operation.
344
+ * Tests transaction handling and partial failure recovery.
345
+ *
346
+ * @example
347
+ * ```typescript
348
+ * const result = partialWrite({
349
+ * table: 'tasks',
350
+ * db: testDb,
351
+ * rowCount: 10,
352
+ * failAtRow: 5,
353
+ * useTransaction: true
354
+ * })
355
+ *
356
+ * // With transaction, should rollback all
357
+ * expect(result.rolledBack).toBe(true)
358
+ * expect(result.rowsWritten).toBe(0)
359
+ * ```
360
+ */
361
+ export declare const partialWrite: (options: PartialWriteOptions) => PartialWriteResult;
362
+ /**
363
+ * Options for delayedClaim utility.
364
+ */
365
+ export interface DelayedClaimOptions {
366
+ /** Task ID to claim */
367
+ taskId: string;
368
+ /** Worker ID making the claim */
369
+ workerId: string;
370
+ /** Test database instance */
371
+ db: TestDatabase;
372
+ /** Delay in milliseconds before claiming */
373
+ delayMs: number;
374
+ /** If true, check for existing claim before and after delay */
375
+ checkRace?: boolean;
376
+ }
377
+ /**
378
+ * Result of delayedClaim operation.
379
+ */
380
+ export interface DelayedClaimResult {
381
+ /** Whether the claim was successful */
382
+ claimed: boolean;
383
+ /** Whether a race condition was detected */
384
+ raceDetected: boolean;
385
+ /** Worker ID that got the claim (may be different from requested) */
386
+ claimedBy: string | null;
387
+ /** Time waited in milliseconds */
388
+ waitedMs: number;
389
+ }
390
+ /**
391
+ * Perform a claim with artificial delay to test race conditions.
392
+ * Useful for testing claim conflict resolution.
393
+ *
394
+ * @example
395
+ * ```typescript
396
+ * // Start a delayed claim
397
+ * const delayedPromise = delayedClaim({
398
+ * taskId: 'tx-abc123',
399
+ * workerId: 'slow-worker',
400
+ * db: testDb,
401
+ * delayMs: 100,
402
+ * checkRace: true
403
+ * })
404
+ *
405
+ * // Another worker claims immediately
406
+ * await claimTask('tx-abc123', 'fast-worker')
407
+ *
408
+ * // Delayed claim should detect the race
409
+ * const result = await delayedPromise
410
+ * expect(result.raceDetected).toBe(true)
411
+ * expect(result.claimed).toBe(false)
412
+ * ```
413
+ */
414
+ export declare const delayedClaim: (options: DelayedClaimOptions) => Promise<DelayedClaimResult>;
415
+ /**
416
+ * Options for stressLoad utility.
417
+ */
418
+ export interface StressLoadOptions {
419
+ /** Number of tasks to create */
420
+ taskCount: number;
421
+ /** Test database instance */
422
+ db: TestDatabase;
423
+ /** If true, create with dependencies (slower but more realistic) */
424
+ withDependencies?: boolean;
425
+ /** Dependency ratio - what fraction of tasks should have dependencies (0-1) */
426
+ dependencyRatio?: number;
427
+ /** Batch size for inserts (default: 1000) */
428
+ batchSize?: number;
429
+ /** If true, include various statuses (not just backlog) */
430
+ mixedStatuses?: boolean;
431
+ }
432
+ /**
433
+ * Result of stressLoad operation.
434
+ */
435
+ export interface StressLoadResult {
436
+ /** Number of tasks created */
437
+ tasksCreated: number;
438
+ /** Number of dependencies created */
439
+ depsCreated: number;
440
+ /** Time taken in milliseconds */
441
+ elapsedMs: number;
442
+ /** Tasks created per second */
443
+ tasksPerSecond: number;
444
+ /** IDs of created tasks */
445
+ taskIds: string[];
446
+ }
447
+ /**
448
+ * Create a large number of tasks quickly for stress testing.
449
+ * Tests bulk operations and performance under load.
450
+ *
451
+ * @example
452
+ * ```typescript
453
+ * const result = stressLoad({
454
+ * taskCount: 10000,
455
+ * db: testDb,
456
+ * withDependencies: true,
457
+ * dependencyRatio: 0.3
458
+ * })
459
+ *
460
+ * console.log(`Created ${result.tasksCreated} tasks in ${result.elapsedMs}ms`)
461
+ * console.log(`Rate: ${result.tasksPerSecond.toFixed(0)} tasks/sec`)
462
+ * ```
463
+ */
464
+ export declare const stressLoad: (options: StressLoadOptions) => StressLoadResult;
465
+ //# sourceMappingURL=chaos-utilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chaos-utilities.d.ts","sourceRoot":"","sources":["../../src/chaos/chaos-utilities.ts"],"names":[],"mappings":"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"}