@durable-streams/client-conformance-tests 0.1.1 → 0.1.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.
- package/dist/adapters/typescript-adapter.cjs +588 -0
- package/dist/adapters/typescript-adapter.d.cts +1 -0
- package/dist/benchmark-runner-CLAR9oLd.cjs +1400 -0
- package/dist/chunk-BCwAaXi7.cjs +31 -0
- package/dist/cli.cjs +266 -0
- package/dist/cli.d.cts +1 -0
- package/dist/index.cjs +22 -0
- package/dist/index.d.cts +508 -0
- package/dist/protocol-3cf94Xyb.d.cts +472 -0
- package/dist/protocol-XeAOKBD-.cjs +175 -0
- package/dist/protocol.cjs +11 -0
- package/dist/protocol.d.cts +2 -0
- package/package.json +51 -36
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
//#region rolldown:runtime
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
+
get: ((k) => from[k]).bind(null, key),
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
+
value: mod,
|
|
21
|
+
enumerable: true
|
|
22
|
+
}) : target, mod));
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
|
|
26
|
+
Object.defineProperty(exports, '__toESM', {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
get: function () {
|
|
29
|
+
return __toESM;
|
|
30
|
+
}
|
|
31
|
+
});
|
package/dist/cli.cjs
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
require('./protocol-XeAOKBD-.cjs');
|
|
4
|
+
const require_benchmark_runner = require('./benchmark-runner-CLAR9oLd.cjs');
|
|
5
|
+
|
|
6
|
+
//#region src/cli.ts
|
|
7
|
+
const HELP = `
|
|
8
|
+
Durable Streams Client Conformance Test Suite
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
npx @durable-streams/client-conformance-tests --run <adapter> [options]
|
|
12
|
+
npx @durable-streams/client-conformance-tests --bench <adapter> [options]
|
|
13
|
+
|
|
14
|
+
Arguments:
|
|
15
|
+
<adapter> Path to client adapter executable, or "ts" for built-in TypeScript adapter
|
|
16
|
+
|
|
17
|
+
Conformance Test Options:
|
|
18
|
+
--run <adapter> Run conformance tests with the specified adapter
|
|
19
|
+
--suite <name> Run only specific suite(s): producer, consumer, lifecycle
|
|
20
|
+
Can be specified multiple times
|
|
21
|
+
--tag <name> Run only tests with specific tag(s)
|
|
22
|
+
Can be specified multiple times
|
|
23
|
+
--fail-fast Stop on first test failure
|
|
24
|
+
--timeout <ms> Timeout for each test in milliseconds (default: 30000)
|
|
25
|
+
|
|
26
|
+
Benchmark Options:
|
|
27
|
+
--bench <adapter> Run benchmarks with the specified adapter
|
|
28
|
+
--scenario <id> Run only specific scenario(s) by ID
|
|
29
|
+
Can be specified multiple times
|
|
30
|
+
--category <name> Run only scenarios in category: latency, throughput, streaming
|
|
31
|
+
Can be specified multiple times
|
|
32
|
+
--format <fmt> Output format: console, json, markdown (default: console)
|
|
33
|
+
|
|
34
|
+
Common Options:
|
|
35
|
+
--verbose Show detailed output for each operation
|
|
36
|
+
--port <port> Port for reference server (default: random)
|
|
37
|
+
--help, -h Show this help message
|
|
38
|
+
|
|
39
|
+
Conformance Test Examples:
|
|
40
|
+
# Test the TypeScript client
|
|
41
|
+
npx @durable-streams/client-conformance-tests --run ts
|
|
42
|
+
|
|
43
|
+
# Test a Python client adapter
|
|
44
|
+
npx @durable-streams/client-conformance-tests --run ./adapters/python_adapter.py
|
|
45
|
+
|
|
46
|
+
# Test only producer functionality
|
|
47
|
+
npx @durable-streams/client-conformance-tests --run ts --suite producer
|
|
48
|
+
|
|
49
|
+
# Test with verbose output and stop on first failure
|
|
50
|
+
npx @durable-streams/client-conformance-tests --run ts --verbose --fail-fast
|
|
51
|
+
|
|
52
|
+
Benchmark Examples:
|
|
53
|
+
# Run all benchmarks with TypeScript client
|
|
54
|
+
npx @durable-streams/client-conformance-tests --bench ts
|
|
55
|
+
|
|
56
|
+
# Run only latency benchmarks
|
|
57
|
+
npx @durable-streams/client-conformance-tests --bench ts --category latency
|
|
58
|
+
|
|
59
|
+
# Run specific scenario
|
|
60
|
+
npx @durable-streams/client-conformance-tests --bench ts --scenario latency-append
|
|
61
|
+
|
|
62
|
+
# Output as JSON for CI
|
|
63
|
+
npx @durable-streams/client-conformance-tests --bench ts --format json
|
|
64
|
+
|
|
65
|
+
Implementing a Client Adapter:
|
|
66
|
+
A client adapter is an executable that communicates via stdin/stdout using
|
|
67
|
+
JSON-line protocol. See the documentation for the protocol specification
|
|
68
|
+
and examples in different languages.
|
|
69
|
+
|
|
70
|
+
The adapter receives JSON commands on stdin (one per line) and responds
|
|
71
|
+
with JSON results on stdout (one per line).
|
|
72
|
+
|
|
73
|
+
Commands: init, create, connect, append, read, head, delete, shutdown, benchmark
|
|
74
|
+
|
|
75
|
+
Example flow:
|
|
76
|
+
Runner -> Client: {"type":"init","serverUrl":"http://localhost:3000"}
|
|
77
|
+
Client -> Runner: {"type":"init","success":true,"clientName":"my-client","clientVersion":"1.0.0"}
|
|
78
|
+
Runner -> Client: {"type":"create","path":"/test-stream"}
|
|
79
|
+
Client -> Runner: {"type":"create","success":true,"status":201}
|
|
80
|
+
...
|
|
81
|
+
`;
|
|
82
|
+
function parseArgs(args) {
|
|
83
|
+
let mode = null;
|
|
84
|
+
let clientAdapter = ``;
|
|
85
|
+
const suites = [];
|
|
86
|
+
const tags = [];
|
|
87
|
+
let failFast = false;
|
|
88
|
+
let testTimeout = 3e4;
|
|
89
|
+
const scenarios = [];
|
|
90
|
+
const categories = [];
|
|
91
|
+
let format = `console`;
|
|
92
|
+
let verbose = false;
|
|
93
|
+
let serverPort = 0;
|
|
94
|
+
let i = 0;
|
|
95
|
+
while (i < args.length) {
|
|
96
|
+
const arg = args[i];
|
|
97
|
+
if (arg === `--help` || arg === `-h`) {
|
|
98
|
+
console.log(HELP);
|
|
99
|
+
process.exit(0);
|
|
100
|
+
}
|
|
101
|
+
if (arg === `--run`) {
|
|
102
|
+
mode = `conformance`;
|
|
103
|
+
i++;
|
|
104
|
+
if (i >= args.length) {
|
|
105
|
+
console.error(`Error: --run requires an adapter path`);
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
clientAdapter = args[i];
|
|
109
|
+
} else if (arg === `--bench`) {
|
|
110
|
+
mode = `benchmark`;
|
|
111
|
+
i++;
|
|
112
|
+
if (i >= args.length) {
|
|
113
|
+
console.error(`Error: --bench requires an adapter path`);
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
clientAdapter = args[i];
|
|
117
|
+
} else if (arg === `--suite`) {
|
|
118
|
+
i++;
|
|
119
|
+
if (i >= args.length) {
|
|
120
|
+
console.error(`Error: --suite requires a suite name`);
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
const suite = args[i];
|
|
124
|
+
if (![
|
|
125
|
+
`producer`,
|
|
126
|
+
`consumer`,
|
|
127
|
+
`lifecycle`
|
|
128
|
+
].includes(suite)) {
|
|
129
|
+
console.error(`Error: Invalid suite "${suite}". Must be: producer, consumer, lifecycle`);
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
suites.push(suite);
|
|
133
|
+
} else if (arg === `--tag`) {
|
|
134
|
+
i++;
|
|
135
|
+
if (i >= args.length) {
|
|
136
|
+
console.error(`Error: --tag requires a tag name`);
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
tags.push(args[i]);
|
|
140
|
+
} else if (arg === `--scenario`) {
|
|
141
|
+
i++;
|
|
142
|
+
if (i >= args.length) {
|
|
143
|
+
console.error(`Error: --scenario requires a scenario ID`);
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
scenarios.push(args[i]);
|
|
147
|
+
} else if (arg === `--category`) {
|
|
148
|
+
i++;
|
|
149
|
+
if (i >= args.length) {
|
|
150
|
+
console.error(`Error: --category requires a category name`);
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
const category = args[i];
|
|
154
|
+
if (![
|
|
155
|
+
`latency`,
|
|
156
|
+
`throughput`,
|
|
157
|
+
`streaming`
|
|
158
|
+
].includes(category)) {
|
|
159
|
+
console.error(`Error: Invalid category "${category}". Must be: latency, throughput, streaming`);
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
categories.push(category);
|
|
163
|
+
} else if (arg === `--format`) {
|
|
164
|
+
i++;
|
|
165
|
+
if (i >= args.length) {
|
|
166
|
+
console.error(`Error: --format requires a format name`);
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
const fmt = args[i];
|
|
170
|
+
if (![
|
|
171
|
+
`console`,
|
|
172
|
+
`json`,
|
|
173
|
+
`markdown`
|
|
174
|
+
].includes(fmt)) {
|
|
175
|
+
console.error(`Error: Invalid format "${fmt}". Must be: console, json, markdown`);
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
format = fmt;
|
|
179
|
+
} else if (arg === `--verbose`) verbose = true;
|
|
180
|
+
else if (arg === `--fail-fast`) failFast = true;
|
|
181
|
+
else if (arg === `--timeout`) {
|
|
182
|
+
i++;
|
|
183
|
+
if (i >= args.length) {
|
|
184
|
+
console.error(`Error: --timeout requires a value in milliseconds`);
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
testTimeout = parseInt(args[i], 10);
|
|
188
|
+
if (isNaN(testTimeout)) {
|
|
189
|
+
console.error(`Error: --timeout must be a number`);
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
} else if (arg === `--port`) {
|
|
193
|
+
i++;
|
|
194
|
+
if (i >= args.length) {
|
|
195
|
+
console.error(`Error: --port requires a port number`);
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
serverPort = parseInt(args[i], 10);
|
|
199
|
+
if (isNaN(serverPort)) {
|
|
200
|
+
console.error(`Error: --port must be a number`);
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
} else if (arg.startsWith(`-`)) {
|
|
204
|
+
console.error(`Error: Unknown option "${arg}"`);
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
i++;
|
|
208
|
+
}
|
|
209
|
+
if (!mode || !clientAdapter) {
|
|
210
|
+
console.error(`Error: --run <adapter> or --bench <adapter> is required`);
|
|
211
|
+
console.log(`\nRun with --help for usage information`);
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
if (mode === `conformance`) {
|
|
215
|
+
const options = {
|
|
216
|
+
clientAdapter,
|
|
217
|
+
verbose,
|
|
218
|
+
failFast,
|
|
219
|
+
testTimeout,
|
|
220
|
+
serverPort
|
|
221
|
+
};
|
|
222
|
+
if (suites.length > 0) options.suites = suites;
|
|
223
|
+
if (tags.length > 0) options.tags = tags;
|
|
224
|
+
return {
|
|
225
|
+
mode: `conformance`,
|
|
226
|
+
options
|
|
227
|
+
};
|
|
228
|
+
} else {
|
|
229
|
+
const options = {
|
|
230
|
+
clientAdapter,
|
|
231
|
+
verbose,
|
|
232
|
+
serverPort,
|
|
233
|
+
format
|
|
234
|
+
};
|
|
235
|
+
if (scenarios.length > 0) options.scenarios = scenarios;
|
|
236
|
+
if (categories.length > 0) options.categories = categories;
|
|
237
|
+
return {
|
|
238
|
+
mode: `benchmark`,
|
|
239
|
+
options
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
async function main() {
|
|
244
|
+
const args = process.argv.slice(2);
|
|
245
|
+
if (args.length === 0) {
|
|
246
|
+
console.log(HELP);
|
|
247
|
+
process.exit(0);
|
|
248
|
+
}
|
|
249
|
+
const parsed = parseArgs(args);
|
|
250
|
+
if (!parsed) process.exit(1);
|
|
251
|
+
try {
|
|
252
|
+
if (parsed.mode === `conformance`) {
|
|
253
|
+
const summary = await require_benchmark_runner.runConformanceTests(parsed.options);
|
|
254
|
+
if (summary.failed > 0) process.exit(1);
|
|
255
|
+
} else {
|
|
256
|
+
const summary = await require_benchmark_runner.runBenchmarks(parsed.options);
|
|
257
|
+
if (summary.failed > 0) process.exit(1);
|
|
258
|
+
}
|
|
259
|
+
} catch (err) {
|
|
260
|
+
console.error(`Error running ${parsed.mode}:`, err);
|
|
261
|
+
process.exit(1);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
main();
|
|
265
|
+
|
|
266
|
+
//#endregion
|
package/dist/cli.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const require_protocol = require('./protocol-XeAOKBD-.cjs');
|
|
2
|
+
const require_benchmark_runner = require('./benchmark-runner-CLAR9oLd.cjs');
|
|
3
|
+
|
|
4
|
+
exports.ErrorCodes = require_protocol.ErrorCodes
|
|
5
|
+
exports.allScenarios = require_benchmark_runner.allScenarios
|
|
6
|
+
exports.calculateStats = require_protocol.calculateStats
|
|
7
|
+
exports.countTests = require_benchmark_runner.countTests
|
|
8
|
+
exports.decodeBase64 = require_protocol.decodeBase64
|
|
9
|
+
exports.encodeBase64 = require_protocol.encodeBase64
|
|
10
|
+
exports.filterByCategory = require_benchmark_runner.filterByCategory
|
|
11
|
+
exports.formatStats = require_protocol.formatStats
|
|
12
|
+
exports.getScenarioById = require_benchmark_runner.getScenarioById
|
|
13
|
+
exports.getScenariosByCategory = require_benchmark_runner.getScenariosByCategory
|
|
14
|
+
exports.loadEmbeddedTestSuites = require_benchmark_runner.loadEmbeddedTestSuites
|
|
15
|
+
exports.loadTestSuites = require_benchmark_runner.loadTestSuites
|
|
16
|
+
exports.parseCommand = require_protocol.parseCommand
|
|
17
|
+
exports.parseResult = require_protocol.parseResult
|
|
18
|
+
exports.runBenchmarks = require_benchmark_runner.runBenchmarks
|
|
19
|
+
exports.runConformanceTests = require_benchmark_runner.runConformanceTests
|
|
20
|
+
exports.scenariosByCategory = require_benchmark_runner.scenariosByCategory
|
|
21
|
+
exports.serializeCommand = require_protocol.serializeCommand
|
|
22
|
+
exports.serializeResult = require_protocol.serializeResult
|