Skip to content

Commit d2b68dc

Browse files
committed
Add execute-js load test
1 parent fab801e commit d2b68dc

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed

e2e/artillery/configs/execute.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
config:
2+
target: "dummy"
3+
phases:
4+
# Over 60s, ramp up to creating 50 vusers per second
5+
- duration: 60
6+
arrivalRate: 5
7+
rampTo: 50
8+
name: "Ramp Up"
9+
# Over 300s, create 50 vusers per second
10+
- duration: 300
11+
arrivalRate: 50
12+
name: "Sustained Encrypt & Decrypt"
13+
# Over 60s, ramp down to creating 5 vusers per second
14+
- duration: 60
15+
arrivalRate: 10
16+
name: "Ramp Down"
17+
processor: "../src/processors/multi-endpoints.ts"
18+
19+
scenarios:
20+
- name: "Execute JS Stress Test"
21+
weight: 100
22+
flow:
23+
- function: "runExecuteJSTest"
24+
- think: 0.1

e2e/artillery/src/processors/multi-endpoints.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,28 @@ const PkpSignResultSchema = z.object({
1818
sigType: z.string().min(1, 'Signature type cannot be empty'),
1919
});
2020

21+
// Execute JS Result Schema
22+
const ExecuteJsResultSchema = z.object({
23+
success: z.boolean(),
24+
signatures: z.record(
25+
z.string(),
26+
z.object({
27+
signature: z.string().regex(/^0x[a-fA-F0-9]+$/, 'Invalid hex signature'),
28+
verifyingKey: z
29+
.string()
30+
.regex(/^0x[a-fA-F0-9]+$/, 'Invalid hex verifying key'),
31+
signedData: z
32+
.string()
33+
.regex(/^0x[a-fA-F0-9]+$/, 'Invalid hex signed data'),
34+
recoveryId: z.number().int().min(0).max(3, 'Recovery ID must be 0-3'),
35+
publicKey: z.string().regex(/^0x[a-fA-F0-9]+$/, 'Invalid hex public key'),
36+
sigType: z.string().min(1, 'Signature type cannot be empty'),
37+
})
38+
),
39+
response: z.string(),
40+
logs: z.string(),
41+
});
42+
2143
// Global variables to cache expensive operations
2244
let litClient: any = null;
2345
let authManager: any = null;
@@ -211,6 +233,73 @@ export async function runEncryptDecryptTest() {
211233
}
212234
}
213235

236+
// test '/web/execute/v2' endpoint
237+
export async function runExecuteJSTest() {
238+
const startTime = Date.now();
239+
240+
try {
241+
// 1. Initialise shared resources (only happens once)
242+
await initialiseSharedResources();
243+
244+
// 2. Read state
245+
const state = await StateManager.readFile();
246+
247+
// Create auth context
248+
const authContext = await createAuthContextFromState();
249+
250+
// Perform executeJs operation
251+
const litActionCode = `
252+
(async () => {
253+
const { sigName, toSign, publicKey } = jsParams;
254+
const { keccak256, arrayify } = ethers.utils;
255+
256+
const toSignBytes = new TextEncoder().encode(toSign);
257+
const toSignBytes32 = keccak256(toSignBytes);
258+
const toSignBytes32Array = arrayify(toSignBytes32);
259+
260+
const sigShare = await Lit.Actions.signEcdsa({
261+
toSign: toSignBytes32Array,
262+
publicKey,
263+
sigName,
264+
});
265+
})();`;
266+
267+
const result = await litClient.executeJs({
268+
code: litActionCode,
269+
authContext,
270+
jsParams: {
271+
message: 'Test message from e2e executeJs',
272+
sigName: 'e2e-test-sig',
273+
toSign: 'Test message from e2e executeJs',
274+
publicKey: state.masterAccount.pkp.publicKey,
275+
},
276+
});
277+
278+
// Validate the result using Zod schema
279+
const validatedResult = ExecuteJsResultSchema.parse(result);
280+
281+
const endTime = Date.now();
282+
const duration = endTime - startTime;
283+
284+
console.log(`✅ executeJs successful in ${duration}ms`);
285+
console.log('✅ executeJs result:', validatedResult);
286+
287+
// For Artillery, just return - no need to call next()
288+
return;
289+
} catch (error) {
290+
const endTime = Date.now();
291+
const duration = endTime - startTime;
292+
293+
console.error(
294+
`❌ executeJs failed in ${duration}ms:`,
295+
error instanceof Error ? error.message : String(error)
296+
);
297+
298+
// Throw the error to let Artillery handle it
299+
throw error;
300+
}
301+
}
302+
214303
// test '/web/sign_session_key' endpoint
215304
export async function runSignSessionKeyTest() {
216305
// ❗️ IT'S IMPORTANT TO SET THIS TO FALSE FOR TESTING

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"artillery:balance-status": "LOG_LEVEL=silent bun run ./e2e/artillery/src/balance-status.ts",
2929
"artillery:pkp-sign": "DEBUG_HTTP=true LOG_LEVEL=silent dotenvx run --env-file=.env -- sh -c 'artillery run ./e2e/artillery/configs/pkp-sign.yml ${ARTILLERY_KEY:+--record --key $ARTILLERY_KEY}'",
3030
"artillery:encrypt-decrypt": "DEBUG_HTTP=true LOG_LEVEL=silent dotenvx run --env-file=.env -- sh -c 'artillery run ./e2e/artillery/configs/encrypt-decrypt.yml ${ARTILLERY_KEY:+--record --key $ARTILLERY_KEY}'",
31+
"artillery:execute-js": "DEBUG_HTTP=true LOG_LEVEL=silent dotenvx run --env-file=.env -- sh -c 'artillery run ./e2e/artillery/configs/execute.yml ${ARTILLERY_KEY:+--record --key $ARTILLERY_KEY}'",
3132
"artillery:sign-session-key": "DEBUG_HTTP=true LOG_LEVEL=silent dotenvx run --env-file=.env -- sh -c 'artillery run ./e2e/artillery/configs/sign-session-key.yml ${ARTILLERY_KEY:+--record --key $ARTILLERY_KEY}'"
3233
},
3334
"private": true,

0 commit comments

Comments
 (0)