@artilleryio/int-commons 2.17.0-d38a728 → 2.17.0-d42fb8f
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/engine_util.js +54 -58
- package/jitter.js +3 -5
- package/package.json +3 -3
package/engine_util.js
CHANGED
|
@@ -2,14 +2,12 @@
|
|
|
2
2
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
4
4
|
|
|
5
|
-
'use strict';
|
|
6
|
-
|
|
7
5
|
const async = require('async');
|
|
8
6
|
const debug = require('debug')('engine_util');
|
|
9
7
|
const deepForEach = require('deep-for-each');
|
|
10
8
|
const espree = require('espree');
|
|
11
9
|
const L = require('lodash');
|
|
12
|
-
const vm = require('vm');
|
|
10
|
+
const vm = require('node:vm');
|
|
13
11
|
const ms = require('ms');
|
|
14
12
|
const A = require('async');
|
|
15
13
|
const { JSONPath: jsonpath } = require('jsonpath-plus');
|
|
@@ -19,7 +17,7 @@ const jitter = require('./jitter').jitter;
|
|
|
19
17
|
let xmlCapture;
|
|
20
18
|
try {
|
|
21
19
|
xmlCapture = require('artillery-xml-capture');
|
|
22
|
-
} catch (
|
|
20
|
+
} catch (_e) {
|
|
23
21
|
xmlCapture = null;
|
|
24
22
|
}
|
|
25
23
|
|
|
@@ -40,15 +38,15 @@ module.exports = {
|
|
|
40
38
|
function createThink(requestSpec, opts) {
|
|
41
39
|
opts = opts || {};
|
|
42
40
|
|
|
43
|
-
|
|
41
|
+
const thinkspec = requestSpec.think;
|
|
44
42
|
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
const f = function think(context, callback) {
|
|
44
|
+
const templatedThink = template(thinkspec, context);
|
|
47
45
|
let thinktime = Number.isInteger(L.toNumber(templatedThink))
|
|
48
46
|
? ms(`${templatedThink}s`)
|
|
49
47
|
: ms(templatedThink);
|
|
50
48
|
|
|
51
|
-
if (typeof thinktime
|
|
49
|
+
if (typeof thinktime === 'undefined') {
|
|
52
50
|
throw new Error(`Invalid think time: ${templatedThink || thinkspec}`);
|
|
53
51
|
}
|
|
54
52
|
|
|
@@ -62,7 +60,7 @@ function createThink(requestSpec, opts) {
|
|
|
62
60
|
opts.jitter,
|
|
63
61
|
thinktime
|
|
64
62
|
);
|
|
65
|
-
setTimeout(
|
|
63
|
+
setTimeout(() => {
|
|
66
64
|
callback(null, context);
|
|
67
65
|
}, thinktime);
|
|
68
66
|
};
|
|
@@ -79,13 +77,13 @@ function createLoopWithCount(count, steps, opts) {
|
|
|
79
77
|
count2 = template(count, context);
|
|
80
78
|
}
|
|
81
79
|
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
const from = parseLoopCount(count2).from;
|
|
81
|
+
const to = parseLoopCount(count2).to;
|
|
84
82
|
|
|
85
83
|
let i = from;
|
|
86
84
|
let newContext = context;
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
const loopIndexVar = opts?.loopValue || '$loopCount';
|
|
86
|
+
const loopElementVar = opts?.loopElement || '$loopElement';
|
|
89
87
|
// Should we stop early because the value of "over" is not an array
|
|
90
88
|
let abortEarly = false;
|
|
91
89
|
|
|
@@ -125,12 +123,10 @@ function createLoopWithCount(count, steps, opts) {
|
|
|
125
123
|
}
|
|
126
124
|
},
|
|
127
125
|
function repeated(cb) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
};
|
|
131
|
-
let steps2 = L.flatten([zero, steps]);
|
|
126
|
+
const zero = (cb2) => cb2(null, newContext);
|
|
127
|
+
const steps2 = L.flatten([zero, steps]);
|
|
132
128
|
|
|
133
|
-
A.waterfall(steps2,
|
|
129
|
+
A.waterfall(steps2, (err, context2) => {
|
|
134
130
|
if (err) {
|
|
135
131
|
return cb(err, context2);
|
|
136
132
|
}
|
|
@@ -152,7 +148,7 @@ function createLoopWithCount(count, steps, opts) {
|
|
|
152
148
|
}
|
|
153
149
|
});
|
|
154
150
|
},
|
|
155
|
-
|
|
151
|
+
(err, finalContext) => {
|
|
156
152
|
if (typeof finalContext === 'undefined') {
|
|
157
153
|
// this happens if test() returns false immediately, e.g. with
|
|
158
154
|
// nested loops where one of the inner loops goes over an
|
|
@@ -166,21 +162,19 @@ function createLoopWithCount(count, steps, opts) {
|
|
|
166
162
|
}
|
|
167
163
|
|
|
168
164
|
function createParallel(steps, opts) {
|
|
169
|
-
|
|
165
|
+
const limit = opts?.limitValue || 100;
|
|
170
166
|
|
|
171
167
|
return function aParallel(context, callback) {
|
|
172
|
-
|
|
173
|
-
|
|
168
|
+
const newContext = context;
|
|
169
|
+
const newCallback = callback;
|
|
174
170
|
|
|
175
171
|
// Remap the steps array to pass the context into each step.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
step(newContext, callback);
|
|
179
|
-
};
|
|
172
|
+
const newSteps = L.map(steps, (step) => (callback) => {
|
|
173
|
+
step(newContext, callback);
|
|
180
174
|
});
|
|
181
175
|
|
|
182
176
|
// Run each of the steps in parallel.
|
|
183
|
-
A.parallelLimit(newSteps, limit,
|
|
177
|
+
A.parallelLimit(newSteps, limit, (err, _finalContext) => {
|
|
184
178
|
// We don't need to do anything with the array of contexts returned from each step at the moment.
|
|
185
179
|
return newCallback(err, newContext);
|
|
186
180
|
});
|
|
@@ -197,7 +191,7 @@ function isProbableEnough(obj) {
|
|
|
197
191
|
probability = 100;
|
|
198
192
|
}
|
|
199
193
|
|
|
200
|
-
|
|
194
|
+
const r = L.random(100);
|
|
201
195
|
return r < probability;
|
|
202
196
|
}
|
|
203
197
|
|
|
@@ -221,7 +215,7 @@ function template(o, context, inPlace) {
|
|
|
221
215
|
}
|
|
222
216
|
const funcCallRegex =
|
|
223
217
|
/{{\s*(\$[A-Za-z0-9_]+\s*\(\s*[A-Za-z0-9_,\s]*\s*\))\s*}}/;
|
|
224
|
-
|
|
218
|
+
const match = o.match(funcCallRegex);
|
|
225
219
|
if (match) {
|
|
226
220
|
// This looks like it could be a function call:
|
|
227
221
|
const syntax = espree.parse(match[1]);
|
|
@@ -231,10 +225,11 @@ function template(o, context, inPlace) {
|
|
|
231
225
|
syntax.body.length === 1 &&
|
|
232
226
|
syntax.body[0].type === 'ExpressionStatement'
|
|
233
227
|
) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
228
|
+
const funcName = syntax.body[0].expression.callee.name;
|
|
229
|
+
const args = L.map(
|
|
230
|
+
syntax.body[0].expression.arguments,
|
|
231
|
+
(arg) => arg.value
|
|
232
|
+
);
|
|
238
233
|
if (funcName in context.funcs) {
|
|
239
234
|
return template(
|
|
240
235
|
o.replace(funcCallRegex, context.funcs[funcName].apply(null, args)),
|
|
@@ -271,7 +266,8 @@ function templateObjectOrArray(o, context) {
|
|
|
271
266
|
debug(
|
|
272
267
|
`path = ${path} ; value = ${JSON.stringify(
|
|
273
268
|
value
|
|
274
|
-
)} (${typeof value}) ; (subj type: ${
|
|
269
|
+
)} (${typeof value}) ; (subj type: ${
|
|
270
|
+
subj.length ? 'list' : 'hash'
|
|
275
271
|
}) ; newValue = ${JSON.stringify(newValue)} ; newPath = ${newPath}`
|
|
276
272
|
);
|
|
277
273
|
|
|
@@ -293,8 +289,8 @@ function templateObjectOrArray(o, context) {
|
|
|
293
289
|
}
|
|
294
290
|
|
|
295
291
|
function renderVariables(str, vars) {
|
|
296
|
-
const RX = /{{{?[\s$\w
|
|
297
|
-
let
|
|
292
|
+
const RX = /{{{?[\s$\w.[\]'"-]+}}}?/g;
|
|
293
|
+
let _rxmatch;
|
|
298
294
|
let result = str.substring(0, str.length);
|
|
299
295
|
|
|
300
296
|
// Special case for handling integer/boolean/object substitution:
|
|
@@ -312,7 +308,7 @@ function renderVariables(str, vars) {
|
|
|
312
308
|
}
|
|
313
309
|
|
|
314
310
|
while (result.search(RX) > -1) {
|
|
315
|
-
|
|
311
|
+
const templateStr = result.match(RX)[0];
|
|
316
312
|
const varName = templateStr.replace(/{/g, '').replace(/}/g, '').trim();
|
|
317
313
|
|
|
318
314
|
let varValue = L.get(vars, varName);
|
|
@@ -328,11 +324,11 @@ function renderVariables(str, vars) {
|
|
|
328
324
|
|
|
329
325
|
// Presume code is valid JS code (i.e. that it has been checked elsewhere)
|
|
330
326
|
function evil(sandbox, code) {
|
|
331
|
-
|
|
332
|
-
|
|
327
|
+
const context = vm.createContext(sandbox);
|
|
328
|
+
const script = new vm.Script(code);
|
|
333
329
|
try {
|
|
334
330
|
return script.runInContext(context);
|
|
335
|
-
} catch (
|
|
331
|
+
} catch (_e) {
|
|
336
332
|
return null;
|
|
337
333
|
}
|
|
338
334
|
}
|
|
@@ -345,8 +341,8 @@ function parseLoopCount(countSpec) {
|
|
|
345
341
|
from = 0;
|
|
346
342
|
to = countSpec;
|
|
347
343
|
} else if (typeof countSpec === 'string') {
|
|
348
|
-
if (isNaN(Number(countSpec))) {
|
|
349
|
-
if (/\d
|
|
344
|
+
if (Number.isNaN(Number(countSpec))) {
|
|
345
|
+
if (/\d-\d/.test(countSpec)) {
|
|
350
346
|
from = Number(countSpec.split('-')[0]);
|
|
351
347
|
to = Number(countSpec.split('-')[1]);
|
|
352
348
|
} else {
|
|
@@ -399,7 +395,7 @@ function captureOrMatch(params, response, context, done) {
|
|
|
399
395
|
return done(null, null);
|
|
400
396
|
}
|
|
401
397
|
|
|
402
|
-
|
|
398
|
+
const result = {
|
|
403
399
|
captures: {},
|
|
404
400
|
matches: {},
|
|
405
401
|
failedCaptures: false
|
|
@@ -409,15 +405,15 @@ function captureOrMatch(params, response, context, done) {
|
|
|
409
405
|
ensurePropertyIsAList(params, 'capture');
|
|
410
406
|
ensurePropertyIsAList(params, 'match');
|
|
411
407
|
|
|
412
|
-
|
|
408
|
+
const specs = params.capture.concat(params.match);
|
|
413
409
|
|
|
414
410
|
async.eachSeries(
|
|
415
411
|
specs,
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
412
|
+
(spec, next) => {
|
|
413
|
+
const parsedSpec = parseSpec(spec, response);
|
|
414
|
+
const parser = parsedSpec.parser;
|
|
415
|
+
const extractor = parsedSpec.extractor;
|
|
416
|
+
const expr = parsedSpec.expr;
|
|
421
417
|
|
|
422
418
|
// are we looking at body or headers:
|
|
423
419
|
var content = response.body;
|
|
@@ -425,7 +421,7 @@ function captureOrMatch(params, response, context, done) {
|
|
|
425
421
|
content = response.headers;
|
|
426
422
|
}
|
|
427
423
|
|
|
428
|
-
parser(content,
|
|
424
|
+
parser(content, (err, doc) => {
|
|
429
425
|
if (err) {
|
|
430
426
|
if (spec.as) {
|
|
431
427
|
result.captures[spec.as] = {
|
|
@@ -445,11 +441,11 @@ function captureOrMatch(params, response, context, done) {
|
|
|
445
441
|
return next(null);
|
|
446
442
|
}
|
|
447
443
|
|
|
448
|
-
|
|
444
|
+
const extractedValue = extractor(doc, template(expr, context), spec);
|
|
449
445
|
|
|
450
446
|
if (spec.value !== undefined) {
|
|
451
447
|
// this is a match spec
|
|
452
|
-
|
|
448
|
+
const expected = template(spec.value, context);
|
|
453
449
|
debug(
|
|
454
450
|
'match: %s, expected: %s, got: %s',
|
|
455
451
|
expr,
|
|
@@ -491,7 +487,7 @@ function captureOrMatch(params, response, context, done) {
|
|
|
491
487
|
return next(null);
|
|
492
488
|
});
|
|
493
489
|
},
|
|
494
|
-
|
|
490
|
+
(err) => {
|
|
495
491
|
if (err) {
|
|
496
492
|
return done(err, null);
|
|
497
493
|
} else {
|
|
@@ -602,8 +598,8 @@ function extractJSONPath(doc, expr, opts) {
|
|
|
602
598
|
|
|
603
599
|
// doc is a string or an object (body parsed by Request when headers indicate JSON)
|
|
604
600
|
function extractRegExp(doc, expr, opts) {
|
|
605
|
-
|
|
606
|
-
|
|
601
|
+
const group = opts.group;
|
|
602
|
+
const flags = opts.flags;
|
|
607
603
|
let str;
|
|
608
604
|
if (typeof doc === 'string') {
|
|
609
605
|
str = doc;
|
|
@@ -616,7 +612,7 @@ function extractRegExp(doc, expr, opts) {
|
|
|
616
612
|
} else {
|
|
617
613
|
rx = new RegExp(expr);
|
|
618
614
|
}
|
|
619
|
-
|
|
615
|
+
const match = rx.exec(str);
|
|
620
616
|
if (!match) {
|
|
621
617
|
return '';
|
|
622
618
|
}
|
|
@@ -641,8 +637,8 @@ function extractHeader(headers, headerName) {
|
|
|
641
637
|
}
|
|
642
638
|
|
|
643
639
|
function extractCheerio(doc, expr, opts) {
|
|
644
|
-
|
|
645
|
-
|
|
640
|
+
const $ = cheerio.load(doc);
|
|
641
|
+
const els = $(expr);
|
|
646
642
|
let i = 0;
|
|
647
643
|
if (typeof opts.index !== 'undefined') {
|
|
648
644
|
if (opts.index === 'random') {
|
package/jitter.js
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
4
4
|
|
|
5
|
-
'use strict';
|
|
6
|
-
|
|
7
5
|
module.exports = {
|
|
8
6
|
jitter: jitter
|
|
9
7
|
};
|
|
@@ -21,9 +19,9 @@ function jitter(sApprox) {
|
|
|
21
19
|
return sApprox;
|
|
22
20
|
}
|
|
23
21
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
const inputs = sApprox.split(':');
|
|
23
|
+
const nb = parseInt(inputs[0], 10);
|
|
24
|
+
const approxPercent = parseInt(inputs[1], 10);
|
|
27
25
|
|
|
28
26
|
let approx = approxPercent;
|
|
29
27
|
if (inputs[1].indexOf('%') >= 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@artilleryio/int-commons",
|
|
3
|
-
"version": "2.17.0-
|
|
3
|
+
"version": "2.17.0-d42fb8f",
|
|
4
4
|
"main": "./index.js",
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"dependencies": {
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"ms": "^2.1.3"
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
|
-
"lint": "
|
|
18
|
-
"lint-fix": "
|
|
17
|
+
"lint": "npx @biomejs/biome check .",
|
|
18
|
+
"lint-fix": "npx @biomejs/biome check --write .",
|
|
19
19
|
"test": "echo \"No test specified\" && exit 0"
|
|
20
20
|
}
|
|
21
21
|
}
|