@artilleryio/int-core 2.2.1 → 2.2.2-0f9e351

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/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@artilleryio/int-core",
3
- "version": "2.2.1",
3
+ "version": "2.2.2-0f9e351",
4
4
  "main": "./index.js",
5
5
  "license": "MPL-2.0",
6
6
  "dependencies": {
7
- "@artilleryio/int-commons": "*",
7
+ "@artilleryio/int-commons": "2.0.4-0f9e351",
8
8
  "@artilleryio/sketches-js": "^2.1.1",
9
9
  "agentkeepalive": "^4.1.0",
10
10
  "arrivals": "^2.1.2",
@@ -28,7 +28,6 @@
28
28
  "lodash": "^4.17.19",
29
29
  "ms": "^2.1.3",
30
30
  "protobufjs": "^7.2.4",
31
- "proxy": "^1.0.2",
32
31
  "socket.io-client": "^4.5.1",
33
32
  "socketio-wildcard": "^2.0.0",
34
33
  "tough-cookie": "^4.0.0",
@@ -48,9 +47,10 @@
48
47
  "@hapi/hapi": "^20.1.3",
49
48
  "express": "^4.16.3",
50
49
  "nock": "^11.8.2",
50
+ "proxy": "^2.1.1",
51
51
  "rewiremock": "^3.14.3",
52
52
  "sinon": "^4.5.0",
53
53
  "socket.io": "^4.7.1",
54
54
  "tap": "^16.3.7"
55
55
  }
56
- }
56
+ }
@@ -1,366 +0,0 @@
1
- og/* This Source Code Form is subject to the terms of the Mozilla Public
2
- * License, v. 2.0. If a copy of the MPL was not distributed with this
3
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
-
5
- 'use strict';
6
-
7
- const async = require('async');
8
- const _ = require('lodash');
9
- const WebSocket = require('ws');
10
- const HttpsProxyAgent = require('https-proxy-agent');
11
- const debug = require('debug')('ws');
12
- const url = require('url');
13
- const engineUtil = require('@artilleryio/int-commons').engine_util;
14
- const template = engineUtil.template;
15
-
16
- module.exports = WSEngine;
17
-
18
- function WSEngine(script) {
19
- this.config = script.config;
20
- }
21
-
22
- WSEngine.prototype.createScenario = function (scenarioSpec, ee) {
23
- const self = this;
24
- const tasks = _.map(scenarioSpec.flow, function (rs) {
25
- if (typeof rs.think !== 'undefined') {
26
- return engineUtil.createThink(
27
- rs,
28
- _.get(self.config, 'defaults.think', {})
29
- );
30
- }
31
-
32
- return self.step(rs, ee);
33
- });
34
-
35
- return self.compile(tasks, scenarioSpec.flow, ee);
36
- };
37
-
38
- function getMessageHandler(context, params, ee, timeout, callback) {
39
- let done = false;
40
-
41
- setTimeout(() => {
42
- if (!done) {
43
- const err = 'response timeout';
44
- ee.emit('error', err);
45
- return callback(err, context);
46
- }
47
- }, timeout * 1000);
48
-
49
- return function messageHandler(event) {
50
- ee.emit('counter', 'websocket.messages_received', 1);
51
- ee.emit('rate', 'websocket.receive_rate');
52
- done = true;
53
- const { data } = event;
54
-
55
- debug('WS receive: %s', data);
56
-
57
- if (!data) {
58
- return callback(new Error('Empty response from WS server'), context);
59
- }
60
-
61
- let fauxResponse;
62
- try {
63
- fauxResponse = { body: JSON.parse(data) };
64
- } catch (err) {
65
- fauxResponse = { body: event.data };
66
- }
67
-
68
- engineUtil.captureOrMatch(
69
- params,
70
- fauxResponse,
71
- context,
72
- function captured(err, result) {
73
- if (err) {
74
- ee.emit('error', err.message || err.code);
75
- return callback(err, context);
76
- }
77
-
78
- const { captures = {}, matches = {} } = result;
79
-
80
- debug('matches: ', matches);
81
- debug('captures: ', captures);
82
-
83
- // match and capture are strict by default:
84
- const haveFailedMatches = _.some(result.matches, function (v) {
85
- return !v.success && v.strict !== false;
86
- });
87
-
88
- const haveFailedCaptures = _.some(result.captures, function (v) {
89
- return v.failed;
90
- });
91
-
92
- if (haveFailedMatches || haveFailedCaptures) {
93
- // TODO: Emit the details of each failed capture/match
94
- return callback(new Error('Failed capture or match'), context);
95
- }
96
-
97
- _.each(result.matches, function (v) {
98
- ee.emit('match', v.success, {
99
- expected: v.expected,
100
- got: v.got,
101
- expression: v.expression,
102
- strict: v.strict
103
- });
104
- });
105
-
106
- _.each(result.captures, function (v, k) {
107
- _.set(context.vars, k, v.value);
108
- });
109
-
110
- return callback(null, context);
111
- }
112
- );
113
- };
114
- }
115
-
116
- WSEngine.prototype.step = function (requestSpec, ee) {
117
- const self = this;
118
-
119
- if (requestSpec.loop) {
120
- const steps = _.map(requestSpec.loop, function (rs) {
121
- return self.step(rs, ee);
122
- });
123
-
124
- return engineUtil.createLoopWithCount(requestSpec.count || -1, steps, {
125
- loopValue: requestSpec.loopValue || '$loopCount',
126
- overValues: requestSpec.over,
127
- whileTrue: self.config.processor
128
- ? self.config.processor[requestSpec.whileTrue]
129
- : undefined
130
- });
131
- }
132
-
133
- if (requestSpec.think) {
134
- return engineUtil.createThink(
135
- requestSpec,
136
- _.get(self.config, 'defaults.think', {})
137
- );
138
- }
139
-
140
- if (requestSpec.function) {
141
- return function (context, callback) {
142
- const processFunc = self.config.processor[requestSpec.function];
143
- if (processFunc) {
144
- processFunc(context, ee, function () {
145
- return callback(null, context);
146
- });
147
- }
148
- };
149
- }
150
-
151
- if (requestSpec.log) {
152
- return function (context, callback) {
153
- console.log(template(requestSpec.log, context));
154
- return process.nextTick(function () {
155
- callback(null, context);
156
- });
157
- };
158
- }
159
-
160
- if (requestSpec.connect) {
161
- return function (context, callback) {
162
- return process.nextTick(function () {
163
- callback(null, context);
164
- });
165
- };
166
- }
167
-
168
- const f = function (context, callback) {
169
- const params = requestSpec.wait || requestSpec.send;
170
-
171
- // match exists on a string, so check match is not a prototype
172
- let captureOrMatch = _.has(params, 'capture') || _.has(params, 'match');
173
-
174
- if (captureOrMatch) {
175
- // only process response if we're capturing
176
- let timeout =
177
- self.config.timeout || _.get(self.config, 'ws.timeout') || 10;
178
- context.ws.onmessage = getMessageHandler(
179
- context,
180
- params,
181
- ee,
182
- timeout,
183
- callback
184
- );
185
- } else {
186
- // Reset onmessage to stop steps interfering with each other
187
- context.ws.onmessage = undefined;
188
- }
189
-
190
- // Backwards compatible with previous version of `send` api
191
- let payload = captureOrMatch ? params.payload : params;
192
-
193
- if (payload !== undefined) {
194
- payload = template(payload, context);
195
- if (typeof payload === 'object') {
196
- payload = JSON.stringify(payload);
197
- } else {
198
- payload = _.toString(payload);
199
- }
200
-
201
- ee.emit('counter', 'websocket.messages_sent', 1);
202
- ee.emit('rate', 'websocket.send_rate');
203
- debug('WS send: %s', payload);
204
-
205
- context.ws.send(payload, function (err) {
206
- if (err) {
207
- debug(err);
208
- ee.emit('error', err);
209
- return callback(err, null);
210
- }
211
-
212
- // End step if we're not capturing
213
- if (!captureOrMatch) {
214
- return callback(null, context);
215
- }
216
- });
217
- } else if (captureOrMatch) {
218
- debug('WS wait: %j', params);
219
- } else {
220
- // in the end, we could not send anything, so report it and stop
221
- let err = 'invalid_step';
222
- debug(err, requestSpec);
223
- ee.emit('error', err);
224
- return callback(err, context);
225
- }
226
- };
227
-
228
- return f;
229
- };
230
-
231
- function getWsOptions(config) {
232
- const options = getWsConfig(config);
233
- const subprotocols = _.get(config, 'ws.subprotocols', []);
234
- const headers = _.get(config, 'ws.headers', {});
235
-
236
- const subprotocolHeader = _.find(headers, (value, headerName) => {
237
- return headerName.toLowerCase() === 'sec-websocket-protocol';
238
- });
239
-
240
- if (typeof subprotocolHeader !== 'undefined') {
241
- // NOTE: subprotocols defined via config.ws.subprotocols take precedence:
242
- subprotocols.push(...subprotocolHeader.split(',').map((s) => s.trim()));
243
- }
244
-
245
- return { options, subprotocols };
246
- }
247
-
248
- function getWsInstance(config, scenarioSpec, context, cb) {
249
- let wsArgs = {
250
- ...getWsOptions(config),
251
- target: config.target
252
- };
253
- const [{ connect }] = scenarioSpec;
254
-
255
- if (connect) {
256
- if (connect.function && config.processor[connect.function]) {
257
- const processFn = config.processor[connect.function];
258
-
259
- return processFn(wsArgs, context, (err) => {
260
- if (err) {
261
- debug('connect.function', err);
262
- return cb(err, null);
263
- }
264
-
265
- context.wsArgs = wsArgs;
266
-
267
- return cb(null, context);
268
- });
269
- } else if (_.isPlainObject(connect)) {
270
- const {
271
- target = config.target,
272
- headers = _.get(config, 'ws.headers', {}),
273
- subprotocols = _.get(config, 'ws.subprotocols', []),
274
- ...instanceConfig
275
- } = connect;
276
-
277
- const opt = getWsOptions({
278
- tls: config.tls,
279
- ws: { subprotocols, headers, ...instanceConfig }
280
- });
281
-
282
- wsArgs = {
283
- target: template(target, context),
284
- ...opt
285
- };
286
- } else {
287
- wsArgs.target = template(connect, context);
288
- }
289
- }
290
-
291
- debug('new WebSocket instance:', wsArgs);
292
-
293
- context.wsArgs = wsArgs;
294
-
295
- return cb(null, context);
296
- }
297
-
298
- WSEngine.prototype.compile = function (tasks, scenarioSpec, ee) {
299
- const config = this.config;
300
-
301
- return function scenario(initialContext, callback) {
302
- function zero(cb) {
303
- ee.emit('started');
304
-
305
- getWsInstance(config, scenarioSpec, initialContext, cb);
306
- }
307
-
308
- function one(context, cb) {
309
- const { wsArgs, ...contextWithoutWsArgs } = context;
310
- const ws = new WebSocket(
311
- wsArgs.target,
312
- wsArgs.subprotocols,
313
- wsArgs.options
314
- );
315
-
316
- ws.on('open', function () {
317
- contextWithoutWsArgs.ws = ws;
318
-
319
- return cb(null, contextWithoutWsArgs);
320
- });
321
-
322
- ws.once('error', function (err) {
323
- debug(err);
324
- ee.emit('error', err.message || err.code);
325
-
326
- return cb(err, {});
327
- });
328
- }
329
-
330
- initialContext._successCount = 0;
331
-
332
- const steps = _.flatten([zero, one, tasks]);
333
-
334
- async.waterfall(steps, function scenarioWaterfallCb(err, context) {
335
- if (err) {
336
- debug(err);
337
- }
338
-
339
- if (context && context.ws) {
340
- context.ws.close();
341
- }
342
-
343
- return callback(err, context);
344
- });
345
- };
346
- };
347
-
348
- function getWsConfig(config) {
349
- const tls = config.tls || {};
350
- const { proxy, ...options } = config.ws || {};
351
-
352
- if (proxy) {
353
- const { url: proxyUrl, ...proxyOptions } = proxy;
354
-
355
- debug('Set proxy: %s, options: %s', proxyUrl, proxyOptions);
356
-
357
- const agent = new HttpsProxyAgent({
358
- ...url.parse(proxyUrl),
359
- ...proxyOptions
360
- });
361
-
362
- options.agent = agent;
363
- }
364
-
365
- return _.extend(tls, options);
366
- }
@@ -1,10 +0,0 @@
1
- (undo-tree-save-format-version . 1)
2
- "545a0b3c114a212400ccd5c49280fc85dc34e487"
3
- [nil nil nil nil (25818 13444 881901 0) 0 nil]
4
- ([nil nil ((10895 . 10897) (t 25767 49356 0 0)) nil (25818 13444 881900 0) 0 nil])
5
- ([nil nil ((#("e" 0 1 (fontified t)) . -10896) (undo-tree-id0 . -1) (undo-tree-id1 . -1) 10897) nil (25818 13444 881899 0) 0 nil])
6
- ([nil nil ((10896 . 10915)) nil (25818 13444 881892 0) 0 nil])
7
- ([nil current ((10943 . 10944)) nil (25818 13444 881956 0) 0 nil])
8
- ([nil nil ((10866 . 10868) (10944 . 10957)) ((#("
9
- " 0 1 (fontified nil) 1 13 (fontified t)) . 10944) (undo-tree-id2 . -1) (#(" " 0 2 (fontified t)) . 10866)) (25818 13444 881888 0) 0 nil])
10
- nil