@testsmith/perfornium 0.1.0

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 (164) hide show
  1. package/README.md +360 -0
  2. package/dist/cli/cli.d.ts +2 -0
  3. package/dist/cli/cli.js +192 -0
  4. package/dist/cli/commands/distributed.d.ts +11 -0
  5. package/dist/cli/commands/distributed.js +179 -0
  6. package/dist/cli/commands/import.d.ts +23 -0
  7. package/dist/cli/commands/import.js +461 -0
  8. package/dist/cli/commands/init.d.ts +7 -0
  9. package/dist/cli/commands/init.js +923 -0
  10. package/dist/cli/commands/mock.d.ts +7 -0
  11. package/dist/cli/commands/mock.js +281 -0
  12. package/dist/cli/commands/report.d.ts +5 -0
  13. package/dist/cli/commands/report.js +70 -0
  14. package/dist/cli/commands/run.d.ts +12 -0
  15. package/dist/cli/commands/run.js +260 -0
  16. package/dist/cli/commands/validate.d.ts +3 -0
  17. package/dist/cli/commands/validate.js +35 -0
  18. package/dist/cli/commands/worker.d.ts +27 -0
  19. package/dist/cli/commands/worker.js +320 -0
  20. package/dist/config/index.d.ts +2 -0
  21. package/dist/config/index.js +20 -0
  22. package/dist/config/parser.d.ts +19 -0
  23. package/dist/config/parser.js +330 -0
  24. package/dist/config/types/global-config.d.ts +74 -0
  25. package/dist/config/types/global-config.js +2 -0
  26. package/dist/config/types/hooks.d.ts +58 -0
  27. package/dist/config/types/hooks.js +3 -0
  28. package/dist/config/types/import-types.d.ts +33 -0
  29. package/dist/config/types/import-types.js +2 -0
  30. package/dist/config/types/index.d.ts +11 -0
  31. package/dist/config/types/index.js +27 -0
  32. package/dist/config/types/load-config.d.ts +32 -0
  33. package/dist/config/types/load-config.js +9 -0
  34. package/dist/config/types/output-config.d.ts +10 -0
  35. package/dist/config/types/output-config.js +2 -0
  36. package/dist/config/types/report-config.d.ts +10 -0
  37. package/dist/config/types/report-config.js +2 -0
  38. package/dist/config/types/runtime-types.d.ts +6 -0
  39. package/dist/config/types/runtime-types.js +2 -0
  40. package/dist/config/types/scenario-config.d.ts +30 -0
  41. package/dist/config/types/scenario-config.js +2 -0
  42. package/dist/config/types/step-types.d.ts +139 -0
  43. package/dist/config/types/step-types.js +2 -0
  44. package/dist/config/types/test-configuration.d.ts +18 -0
  45. package/dist/config/types/test-configuration.js +2 -0
  46. package/dist/config/types/worker-config.d.ts +12 -0
  47. package/dist/config/types/worker-config.js +2 -0
  48. package/dist/config/validator.d.ts +19 -0
  49. package/dist/config/validator.js +198 -0
  50. package/dist/core/csv-data-provider.d.ts +47 -0
  51. package/dist/core/csv-data-provider.js +265 -0
  52. package/dist/core/hooks-manager.d.ts +33 -0
  53. package/dist/core/hooks-manager.js +129 -0
  54. package/dist/core/index.d.ts +5 -0
  55. package/dist/core/index.js +11 -0
  56. package/dist/core/script-executor.d.ts +14 -0
  57. package/dist/core/script-executor.js +290 -0
  58. package/dist/core/step-executor.d.ts +41 -0
  59. package/dist/core/step-executor.js +680 -0
  60. package/dist/core/test-runner.d.ts +34 -0
  61. package/dist/core/test-runner.js +465 -0
  62. package/dist/core/threshold-evaluator.d.ts +43 -0
  63. package/dist/core/threshold-evaluator.js +170 -0
  64. package/dist/core/virtual-user-pool.d.ts +42 -0
  65. package/dist/core/virtual-user-pool.js +136 -0
  66. package/dist/core/virtual-user.d.ts +51 -0
  67. package/dist/core/virtual-user.js +488 -0
  68. package/dist/distributed/coordinator.d.ts +34 -0
  69. package/dist/distributed/coordinator.js +158 -0
  70. package/dist/distributed/health-monitor.d.ts +18 -0
  71. package/dist/distributed/health-monitor.js +72 -0
  72. package/dist/distributed/load-distributor.d.ts +17 -0
  73. package/dist/distributed/load-distributor.js +106 -0
  74. package/dist/distributed/remote-worker.d.ts +37 -0
  75. package/dist/distributed/remote-worker.js +241 -0
  76. package/dist/distributed/result-aggregator.d.ts +43 -0
  77. package/dist/distributed/result-aggregator.js +146 -0
  78. package/dist/dsl/index.d.ts +3 -0
  79. package/dist/dsl/index.js +11 -0
  80. package/dist/dsl/test-builder.d.ts +111 -0
  81. package/dist/dsl/test-builder.js +514 -0
  82. package/dist/importers/har-importer.d.ts +17 -0
  83. package/dist/importers/har-importer.js +172 -0
  84. package/dist/importers/open-api-importer.d.ts +23 -0
  85. package/dist/importers/open-api-importer.js +181 -0
  86. package/dist/importers/wsdl-importer.d.ts +42 -0
  87. package/dist/importers/wsdl-importer.js +440 -0
  88. package/dist/index.d.ts +5 -0
  89. package/dist/index.js +17 -0
  90. package/dist/load-patterns/arrivals.d.ts +7 -0
  91. package/dist/load-patterns/arrivals.js +118 -0
  92. package/dist/load-patterns/base.d.ts +9 -0
  93. package/dist/load-patterns/base.js +2 -0
  94. package/dist/load-patterns/basic.d.ts +7 -0
  95. package/dist/load-patterns/basic.js +117 -0
  96. package/dist/load-patterns/stepping.d.ts +6 -0
  97. package/dist/load-patterns/stepping.js +122 -0
  98. package/dist/metrics/collector.d.ts +72 -0
  99. package/dist/metrics/collector.js +662 -0
  100. package/dist/metrics/types.d.ts +135 -0
  101. package/dist/metrics/types.js +2 -0
  102. package/dist/outputs/base.d.ts +7 -0
  103. package/dist/outputs/base.js +2 -0
  104. package/dist/outputs/csv.d.ts +13 -0
  105. package/dist/outputs/csv.js +163 -0
  106. package/dist/outputs/graphite.d.ts +13 -0
  107. package/dist/outputs/graphite.js +126 -0
  108. package/dist/outputs/influxdb.d.ts +12 -0
  109. package/dist/outputs/influxdb.js +82 -0
  110. package/dist/outputs/json.d.ts +14 -0
  111. package/dist/outputs/json.js +107 -0
  112. package/dist/outputs/streaming-csv.d.ts +37 -0
  113. package/dist/outputs/streaming-csv.js +254 -0
  114. package/dist/outputs/streaming-json.d.ts +43 -0
  115. package/dist/outputs/streaming-json.js +353 -0
  116. package/dist/outputs/webhook.d.ts +16 -0
  117. package/dist/outputs/webhook.js +96 -0
  118. package/dist/protocols/base.d.ts +33 -0
  119. package/dist/protocols/base.js +2 -0
  120. package/dist/protocols/rest/handler.d.ts +67 -0
  121. package/dist/protocols/rest/handler.js +776 -0
  122. package/dist/protocols/soap/handler.d.ts +12 -0
  123. package/dist/protocols/soap/handler.js +165 -0
  124. package/dist/protocols/web/core-web-vitals.d.ts +121 -0
  125. package/dist/protocols/web/core-web-vitals.js +373 -0
  126. package/dist/protocols/web/handler.d.ts +50 -0
  127. package/dist/protocols/web/handler.js +706 -0
  128. package/dist/recorder/native-recorder.d.ts +14 -0
  129. package/dist/recorder/native-recorder.js +533 -0
  130. package/dist/recorder/scenario-recorder.d.ts +55 -0
  131. package/dist/recorder/scenario-recorder.js +296 -0
  132. package/dist/reporting/constants.d.ts +94 -0
  133. package/dist/reporting/constants.js +82 -0
  134. package/dist/reporting/enhanced-html-generator.d.ts +55 -0
  135. package/dist/reporting/enhanced-html-generator.js +965 -0
  136. package/dist/reporting/generator.d.ts +42 -0
  137. package/dist/reporting/generator.js +1217 -0
  138. package/dist/reporting/statistics.d.ts +144 -0
  139. package/dist/reporting/statistics.js +742 -0
  140. package/dist/reporting/templates/enhanced-report.hbs +2812 -0
  141. package/dist/reporting/templates/html.hbs +2453 -0
  142. package/dist/utils/faker-manager.d.ts +55 -0
  143. package/dist/utils/faker-manager.js +166 -0
  144. package/dist/utils/file-manager.d.ts +33 -0
  145. package/dist/utils/file-manager.js +154 -0
  146. package/dist/utils/handlebars-manager.d.ts +42 -0
  147. package/dist/utils/handlebars-manager.js +172 -0
  148. package/dist/utils/logger.d.ts +16 -0
  149. package/dist/utils/logger.js +46 -0
  150. package/dist/utils/template.d.ts +80 -0
  151. package/dist/utils/template.js +513 -0
  152. package/dist/utils/test-output-writer.d.ts +56 -0
  153. package/dist/utils/test-output-writer.js +643 -0
  154. package/dist/utils/time.d.ts +3 -0
  155. package/dist/utils/time.js +23 -0
  156. package/dist/utils/timestamp-helper.d.ts +17 -0
  157. package/dist/utils/timestamp-helper.js +53 -0
  158. package/dist/workers/manager.d.ts +18 -0
  159. package/dist/workers/manager.js +95 -0
  160. package/dist/workers/server.d.ts +21 -0
  161. package/dist/workers/server.js +205 -0
  162. package/dist/workers/worker.d.ts +19 -0
  163. package/dist/workers/worker.js +147 -0
  164. package/package.json +102 -0
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ThresholdEvaluator = void 0;
4
+ const logger_1 = require("../utils/logger");
5
+ class ThresholdEvaluator {
6
+ /**
7
+ * Evaluate all thresholds against a test result
8
+ */
9
+ static evaluate(thresholds, result, stepName) {
10
+ const failures = [];
11
+ for (const threshold of thresholds) {
12
+ try {
13
+ const failure = this.evaluateThreshold(threshold, result, stepName);
14
+ if (failure) {
15
+ failures.push(failure);
16
+ }
17
+ }
18
+ catch (error) {
19
+ logger_1.logger.warn(`Error evaluating threshold for metric ${threshold.metric}: ${error}`);
20
+ failures.push({
21
+ threshold,
22
+ actualValue: 'ERROR',
23
+ expectedValue: threshold.value,
24
+ message: `Threshold evaluation failed: ${error}`,
25
+ severity: 'error'
26
+ });
27
+ }
28
+ }
29
+ return {
30
+ passed: failures.length === 0,
31
+ failures
32
+ };
33
+ }
34
+ /**
35
+ * Evaluate a single threshold
36
+ */
37
+ static evaluateThreshold(threshold, result, stepName) {
38
+ const actualValue = this.extractMetricValue(threshold.metric, result);
39
+ const expectedValue = this.parseExpectedValue(threshold.value);
40
+ const operator = threshold.operator || 'lte'; // Default to less than or equal
41
+ const passed = this.compareValues(actualValue, expectedValue, operator);
42
+ if (!passed) {
43
+ const stepInfo = stepName ? ` in step "${stepName}"` : '';
44
+ const description = threshold.description ||
45
+ `${threshold.metric} threshold exceeded${stepInfo}`;
46
+ return {
47
+ threshold,
48
+ actualValue,
49
+ expectedValue,
50
+ message: `${description}: ${actualValue} ${this.getOperatorSymbol(operator)} ${expectedValue}`,
51
+ severity: threshold.severity || 'error'
52
+ };
53
+ }
54
+ return null;
55
+ }
56
+ /**
57
+ * Extract the actual metric value from test result
58
+ */
59
+ static extractMetricValue(metric, result) {
60
+ switch (metric) {
61
+ case 'response_time':
62
+ return result.duration;
63
+ case 'status_code':
64
+ return result.status || 0;
65
+ case 'error_rate':
66
+ // This would need to be calculated at a higher level
67
+ // For now, return 0 for success, 100 for failure
68
+ return result.success ? 0 : 100;
69
+ case 'throughput':
70
+ // Calculate requests per second (would need time window context)
71
+ return result.duration > 0 ? 1000 / result.duration : 0;
72
+ case 'custom':
73
+ // Custom metrics would be stored in result.custom_metrics
74
+ return result.custom_metrics || 0;
75
+ default:
76
+ throw new Error(`Unknown metric type: ${metric}`);
77
+ }
78
+ }
79
+ /**
80
+ * Parse expected value, handling units like "1s", "500ms", etc.
81
+ */
82
+ static parseExpectedValue(value) {
83
+ if (typeof value === 'number') {
84
+ return value;
85
+ }
86
+ const str = value.toString().toLowerCase();
87
+ // Handle time units
88
+ if (str.endsWith('ms')) {
89
+ return parseFloat(str.slice(0, -2));
90
+ }
91
+ if (str.endsWith('s')) {
92
+ return parseFloat(str.slice(0, -1)) * 1000; // Convert to ms
93
+ }
94
+ if (str.endsWith('m')) {
95
+ return parseFloat(str.slice(0, -1)) * 60000; // Convert to ms
96
+ }
97
+ // Handle percentage
98
+ if (str.endsWith('%')) {
99
+ return parseFloat(str.slice(0, -1));
100
+ }
101
+ // Default: try to parse as number
102
+ const parsed = parseFloat(str);
103
+ if (isNaN(parsed)) {
104
+ throw new Error(`Cannot parse threshold value: ${value}`);
105
+ }
106
+ return parsed;
107
+ }
108
+ /**
109
+ * Compare actual vs expected values using the specified operator
110
+ */
111
+ static compareValues(actual, expected, operator) {
112
+ const actualNum = typeof actual === 'string' ? parseFloat(actual.toString()) : actual;
113
+ if (isNaN(actualNum)) {
114
+ return operator === 'ne'; // Only "not equals" passes for non-numeric values
115
+ }
116
+ switch (operator) {
117
+ case 'lt': return actualNum < expected;
118
+ case 'lte': return actualNum <= expected;
119
+ case 'gt': return actualNum > expected;
120
+ case 'gte': return actualNum >= expected;
121
+ case 'eq': return actualNum === expected;
122
+ case 'ne': return actualNum !== expected;
123
+ default:
124
+ throw new Error(`Unknown operator: ${operator}`);
125
+ }
126
+ }
127
+ /**
128
+ * Get human-readable operator symbol
129
+ */
130
+ static getOperatorSymbol(operator) {
131
+ const symbols = {
132
+ 'lt': '<',
133
+ 'lte': 'โ‰ค',
134
+ 'gt': '>',
135
+ 'gte': 'โ‰ฅ',
136
+ 'eq': '=',
137
+ 'ne': 'โ‰ '
138
+ };
139
+ return symbols[operator] || operator;
140
+ }
141
+ /**
142
+ * Execute threshold action based on severity and configuration
143
+ */
144
+ static async executeThresholdActions(evaluationResult, stepName) {
145
+ for (const failure of evaluationResult.failures) {
146
+ const action = failure.threshold.action || 'log';
147
+ const stepInfo = stepName ? ` [Step: ${stepName}]` : '';
148
+ switch (action) {
149
+ case 'log':
150
+ logger_1.logger.warn(`Threshold violation${stepInfo}: ${failure.message}`);
151
+ break;
152
+ case 'fail_step':
153
+ logger_1.logger.error(`Step threshold violation${stepInfo}: ${failure.message}`);
154
+ throw new Error(`Step failed due to threshold violation: ${failure.message}`);
155
+ case 'fail_scenario':
156
+ logger_1.logger.error(`Scenario threshold violation${stepInfo}: ${failure.message}`);
157
+ throw new Error(`Scenario failed due to threshold violation: ${failure.message}`);
158
+ case 'fail_test':
159
+ logger_1.logger.error(`Test threshold violation${stepInfo}: ${failure.message}`);
160
+ throw new Error(`Test failed due to threshold violation: ${failure.message}`);
161
+ case 'abort':
162
+ logger_1.logger.error(`Critical threshold violation${stepInfo}: ${failure.message}`);
163
+ process.exit(1);
164
+ default:
165
+ logger_1.logger.warn(`Unknown threshold action: ${action}`);
166
+ }
167
+ }
168
+ }
169
+ }
170
+ exports.ThresholdEvaluator = ThresholdEvaluator;
@@ -0,0 +1,42 @@
1
+ import { VirtualUser } from './virtual-user';
2
+ import { MetricsCollector } from '../metrics/collector';
3
+ import { ProtocolHandler } from '../protocols/base';
4
+ import { Scenario } from '../config/types/hooks';
5
+ import { EventEmitter } from 'events';
6
+ export interface VUPoolConfig {
7
+ maxWorkers?: number;
8
+ maxVUsPerWorker?: number;
9
+ reuseVUs?: boolean;
10
+ preWarmVUs?: number;
11
+ workerIdleTimeout?: number;
12
+ }
13
+ export interface VUTask {
14
+ id: number;
15
+ scenarios: Scenario[];
16
+ priority?: number;
17
+ }
18
+ export declare class VirtualUserPool extends EventEmitter {
19
+ private config;
20
+ private metrics;
21
+ private handlers;
22
+ private testName;
23
+ private vuPool;
24
+ private availableVUs;
25
+ private busyVUs;
26
+ private workers;
27
+ private taskQueue;
28
+ private nextVUId;
29
+ private readonly DEFAULT_MAX_WORKERS;
30
+ private readonly DEFAULT_MAX_VUS_PER_WORKER;
31
+ private readonly DEFAULT_WORKER_IDLE_TIMEOUT;
32
+ constructor(metrics: MetricsCollector, handlers: Map<string, ProtocolHandler>, testName?: string, config?: VUPoolConfig);
33
+ initialize(): Promise<void>;
34
+ private preWarmVUs;
35
+ private createVU;
36
+ getVU(scenarios: Scenario[]): Promise<VirtualUser>;
37
+ releaseVU(vuId: number): void;
38
+ executeTask(task: VUTask): Promise<void>;
39
+ private startWorkerCleanup;
40
+ private terminateWorker;
41
+ shutdown(): Promise<void>;
42
+ }
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VirtualUserPool = void 0;
4
+ const virtual_user_1 = require("./virtual-user");
5
+ const logger_1 = require("../utils/logger");
6
+ const events_1 = require("events");
7
+ class VirtualUserPool extends events_1.EventEmitter {
8
+ constructor(metrics, handlers, testName = 'Load Test', config) {
9
+ super();
10
+ this.vuPool = new Map();
11
+ this.availableVUs = new Set();
12
+ this.busyVUs = new Set();
13
+ this.workers = new Map();
14
+ this.taskQueue = [];
15
+ this.nextVUId = 1;
16
+ this.DEFAULT_MAX_WORKERS = 4;
17
+ this.DEFAULT_MAX_VUS_PER_WORKER = 50;
18
+ this.DEFAULT_WORKER_IDLE_TIMEOUT = 30000;
19
+ this.metrics = metrics;
20
+ this.handlers = handlers;
21
+ this.testName = testName;
22
+ this.config = {
23
+ maxWorkers: config?.maxWorkers || this.DEFAULT_MAX_WORKERS,
24
+ maxVUsPerWorker: config?.maxVUsPerWorker || this.DEFAULT_MAX_VUS_PER_WORKER,
25
+ reuseVUs: config?.reuseVUs ?? true,
26
+ preWarmVUs: config?.preWarmVUs || 0,
27
+ workerIdleTimeout: config?.workerIdleTimeout || this.DEFAULT_WORKER_IDLE_TIMEOUT
28
+ };
29
+ }
30
+ async initialize() {
31
+ logger_1.logger.debug(`๐ŸŠ Initializing VU pool with config:`, this.config);
32
+ if (this.config.preWarmVUs && this.config.preWarmVUs > 0) {
33
+ await this.preWarmVUs(this.config.preWarmVUs);
34
+ }
35
+ this.startWorkerCleanup();
36
+ }
37
+ async preWarmVUs(count) {
38
+ logger_1.logger.debug(`๐Ÿ”ฅ Pre-warming ${count} virtual users...`);
39
+ const promises = [];
40
+ for (let i = 0; i < count; i++) {
41
+ promises.push(this.createVU());
42
+ }
43
+ await Promise.all(promises);
44
+ logger_1.logger.debug(`โœ… Pre-warmed ${count} virtual users`);
45
+ }
46
+ async createVU() {
47
+ const vuId = this.nextVUId++;
48
+ const vu = new virtual_user_1.VirtualUser(vuId, this.metrics, this.handlers, this.testName);
49
+ this.vuPool.set(vuId, vu);
50
+ this.availableVUs.add(vuId);
51
+ return vuId;
52
+ }
53
+ async getVU(scenarios) {
54
+ let vuId;
55
+ if (this.config.reuseVUs && this.availableVUs.size > 0) {
56
+ const iterator = this.availableVUs.values().next();
57
+ if (!iterator.done) {
58
+ vuId = iterator.value;
59
+ this.availableVUs.delete(vuId);
60
+ }
61
+ else {
62
+ vuId = await this.createVU();
63
+ }
64
+ }
65
+ else {
66
+ vuId = await this.createVU();
67
+ }
68
+ this.busyVUs.add(vuId);
69
+ const vu = this.vuPool.get(vuId);
70
+ await vu.setScenarios(scenarios);
71
+ return vu;
72
+ }
73
+ releaseVU(vuId) {
74
+ if (!this.busyVUs.has(vuId)) {
75
+ return;
76
+ }
77
+ this.busyVUs.delete(vuId);
78
+ if (this.config.reuseVUs) {
79
+ this.availableVUs.add(vuId);
80
+ }
81
+ else {
82
+ const vu = this.vuPool.get(vuId);
83
+ if (vu) {
84
+ vu.stop();
85
+ this.vuPool.delete(vuId);
86
+ }
87
+ }
88
+ }
89
+ async executeTask(task) {
90
+ const vu = await this.getVU(task.scenarios);
91
+ try {
92
+ await vu.executeScenarios();
93
+ }
94
+ finally {
95
+ this.releaseVU(vu.getId());
96
+ }
97
+ }
98
+ startWorkerCleanup() {
99
+ if (!this.config.workerIdleTimeout || this.config.workerIdleTimeout <= 0) {
100
+ return;
101
+ }
102
+ setInterval(() => {
103
+ const now = Date.now();
104
+ for (const [workerId, state] of this.workers.entries()) {
105
+ if (state.isIdle &&
106
+ state.activeVUs.size === 0 &&
107
+ now - state.lastActivity > this.config.workerIdleTimeout) {
108
+ this.terminateWorker(workerId);
109
+ }
110
+ }
111
+ }, 10000);
112
+ }
113
+ terminateWorker(workerId) {
114
+ const state = this.workers.get(workerId);
115
+ if (!state)
116
+ return;
117
+ state.worker.terminate();
118
+ this.workers.delete(workerId);
119
+ logger_1.logger.debug(`๐Ÿงน Terminated idle worker ${workerId}`);
120
+ }
121
+ async shutdown() {
122
+ logger_1.logger.debug('๐Ÿ›‘ Shutting down VU pool...');
123
+ for (const [vuId, vu] of this.vuPool) {
124
+ await vu.stop();
125
+ }
126
+ for (const [workerId, state] of this.workers) {
127
+ await state.worker.terminate();
128
+ }
129
+ this.vuPool.clear();
130
+ this.availableVUs.clear();
131
+ this.busyVUs.clear();
132
+ this.workers.clear();
133
+ logger_1.logger.debug('โœ… VU pool shut down complete');
134
+ }
135
+ }
136
+ exports.VirtualUserPool = VirtualUserPool;
@@ -0,0 +1,51 @@
1
+ import { Scenario, VUHooks } from '../config/types/hooks';
2
+ import { MetricsCollector } from '../metrics/collector';
3
+ import { ProtocolHandler } from '../protocols/base';
4
+ import { GlobalCSVConfig } from '../config';
5
+ export interface GlobalCSVOptions {
6
+ config: GlobalCSVConfig;
7
+ mode?: 'next' | 'unique' | 'random';
8
+ }
9
+ export declare class VirtualUser {
10
+ private id;
11
+ private context;
12
+ private metrics;
13
+ private stepExecutor;
14
+ private isActive;
15
+ private scenarios;
16
+ private csvProviders;
17
+ private vuHooksManager;
18
+ private testName;
19
+ private handlers;
20
+ private globalThinkTime?;
21
+ private globalCSVProvider?;
22
+ private globalCSVMode?;
23
+ constructor(id: number, metrics: MetricsCollector, handlers: Map<string, ProtocolHandler>, testName?: string, vuHooks?: VUHooks, globalThinkTime?: string | number, globalCSV?: GlobalCSVOptions);
24
+ setScenarios(scenarios: Scenario[]): Promise<void>;
25
+ /**
26
+ * Initialize CSV providers only for scenarios that need them
27
+ */
28
+ private initializeCSVProvidersIfNeeded;
29
+ /**
30
+ * Load global CSV data and merge into context variables
31
+ * Called once at the start of each VU execution cycle
32
+ */
33
+ private loadGlobalCSVData;
34
+ executeScenarios(): Promise<void>;
35
+ executeScenario(scenario: Scenario): Promise<void>;
36
+ private loadCSVDataIfNeeded;
37
+ private loadCSVDataForScenario;
38
+ private selectScenarios;
39
+ private executeSetup;
40
+ private executeTeardown;
41
+ private executeScript;
42
+ /**
43
+ * Get effective think time using hierarchical override:
44
+ * Step think_time > Scenario think_time > Global think_time
45
+ */
46
+ private getEffectiveThinkTime;
47
+ private applyThinkTime;
48
+ stop(): Promise<void>;
49
+ getId(): number;
50
+ isRunning(): boolean;
51
+ }