initial commit
This commit is contained in:
commit
4c11abd5d0
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
node_modules
|
||||
results
|
||||
*.log
|
||||
146
index.js
Normal file
146
index.js
Normal file
@ -0,0 +1,146 @@
|
||||
const shell = require('shelljs');
|
||||
const path = require('path');
|
||||
|
||||
const scriptsDir = path.join(__dirname, 'jmeter-scripts');
|
||||
|
||||
// Schedule configuration: time ranges and jmx file
|
||||
// const schedule = [
|
||||
// {
|
||||
// name: '20tps',
|
||||
// startHour: 23,
|
||||
// startMinute: 0,
|
||||
// endHour: 23,
|
||||
// endMinute: 10,
|
||||
// jmx: 'lastlocation_20tps_10min_3000req.jmx',
|
||||
// },
|
||||
// {
|
||||
// name: '50tps',
|
||||
// startHour: 23,
|
||||
// startMinute: 15,
|
||||
// endHour: 23,
|
||||
// endMinute: 25,
|
||||
// jmx: 'lastlocation_50tps_10min_3000req.jmx',
|
||||
// },
|
||||
// {
|
||||
// name: '100tps',
|
||||
// startHour: 23,
|
||||
// startMinute: 30,
|
||||
// endHour: 23,
|
||||
// endMinute: 40,
|
||||
// jmx: 'lastlocation_100tps_10min_3000req.jmx',
|
||||
// },
|
||||
// ];
|
||||
const schedule = [
|
||||
{
|
||||
name: '20tps',
|
||||
startHour: 16,
|
||||
startMinute: 55,
|
||||
endHour: 17,
|
||||
endMinute: 0,
|
||||
jmx: 'lastlocation_20tps_10min_3000req.jmx',
|
||||
},
|
||||
{
|
||||
name: '50tps',
|
||||
startHour: 23,
|
||||
startMinute: 15,
|
||||
endHour: 23,
|
||||
endMinute: 25,
|
||||
jmx: 'lastlocation_50tps_10min_3000req.jmx',
|
||||
},
|
||||
{
|
||||
name: '100tps',
|
||||
startHour: 23,
|
||||
startMinute: 30,
|
||||
endHour: 23,
|
||||
endMinute: 40,
|
||||
jmx: 'lastlocation_100tps_10min_3000req.jmx',
|
||||
},
|
||||
];
|
||||
|
||||
// Track currently running schedule to avoid rerun within same slot
|
||||
let currentlyRunning = null;
|
||||
|
||||
function isNowInSchedule(now, sched) {
|
||||
// now is a Date object
|
||||
const start = new Date(now);
|
||||
start.setHours(sched.startHour, sched.startMinute, 0, 0);
|
||||
const end = new Date(now);
|
||||
end.setHours(sched.endHour, sched.endMinute, 0, 0);
|
||||
return now >= start && now < end;
|
||||
}
|
||||
|
||||
function formatDateForFolder(date) {
|
||||
// Format YYYYMMDD_HHmmss for folder naming
|
||||
const pad = (n) => n.toString().padStart(2, '0');
|
||||
return (
|
||||
date.getFullYear().toString() +
|
||||
pad(date.getMonth() + 1) +
|
||||
pad(date.getDate()) +
|
||||
'_' +
|
||||
pad(date.getHours()) +
|
||||
pad(date.getMinutes()) +
|
||||
pad(date.getSeconds())
|
||||
);
|
||||
}
|
||||
|
||||
function runJMeter(jmxFile) {
|
||||
const now = new Date();
|
||||
const timestamp = formatDateForFolder(now);
|
||||
const resultFolder = path.join(
|
||||
__dirname,
|
||||
'results',
|
||||
`${timestamp}_${path.basename(jmxFile, '.jmx')}`
|
||||
);
|
||||
const resultCsv = path.join(resultFolder, 'result.csv');
|
||||
|
||||
// Create result folder
|
||||
shell.mkdir('-p', resultFolder);
|
||||
|
||||
// Build command
|
||||
const cmd = [
|
||||
'jmeter',
|
||||
'-n',
|
||||
'-t',
|
||||
`"${path.join(scriptsDir, jmxFile)}"`,
|
||||
'-l',
|
||||
`"${resultCsv}"`,
|
||||
'-e',
|
||||
'-o',
|
||||
`"${resultFolder}"`,
|
||||
].join(' ');
|
||||
|
||||
console.log(`[${now.toISOString()}] Running: ${cmd}`);
|
||||
|
||||
// Run command asynchronously
|
||||
shell.exec(cmd, { async: true }, (code, stdout, stderr) => {
|
||||
if (code === 0) {
|
||||
console.log(`[${new Date().toISOString()}] Finished running ${jmxFile}`);
|
||||
} else {
|
||||
console.error(`[${new Date().toISOString()}] JMeter exited with code ${code}`);
|
||||
console.error(stderr);
|
||||
}
|
||||
currentlyRunning = null; // Allow next scheduled run
|
||||
});
|
||||
}
|
||||
|
||||
function checkSchedule() {
|
||||
const now = new Date();
|
||||
|
||||
// If a job is already running, skip starting a new one
|
||||
if (currentlyRunning) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find schedule where current time fits
|
||||
const activeSchedule = schedule.find((sched) => isNowInSchedule(now, sched));
|
||||
|
||||
if (activeSchedule) {
|
||||
currentlyRunning = activeSchedule.name;
|
||||
runJMeter(activeSchedule.jmx);
|
||||
}
|
||||
}
|
||||
|
||||
// Run check every second
|
||||
setInterval(checkSchedule, 1000);
|
||||
|
||||
console.log(`Scheduler started on ${new Date()}. Waiting for scheduled times to run JMeter tests...`);
|
||||
101
jmeter-scripts/lastlocation_100tps_10min_3000req.jmx
Normal file
101
jmeter-scripts/lastlocation_100tps_10min_3000req.jmx
Normal file
@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.6.3">
|
||||
<hashTree>
|
||||
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="MainTest" enabled="true">
|
||||
<stringProp name="TestPlan.comments"></stringProp>
|
||||
<boolProp name="TestPlan.functional_mode">false</boolProp>
|
||||
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
|
||||
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="TestPlan.user_define_classpath"></stringProp>
|
||||
</TestPlan>
|
||||
<hashTree>
|
||||
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
|
||||
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
|
||||
<intProp name="LoopController.loops">-1</intProp>
|
||||
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||
</elementProp>
|
||||
<intProp name="ThreadGroup.num_threads">20</intProp> <!-- increased to 20 threads -->
|
||||
<intProp name="ThreadGroup.ramp_time">1</intProp>
|
||||
<longProp name="ThreadGroup.duration">600</longProp> <!-- 10 minutes -->
|
||||
<longProp name="ThreadGroup.delay">0</longProp>
|
||||
<boolProp name="ThreadGroup.scheduler">true</boolProp>
|
||||
<boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
|
||||
</ThreadGroup>
|
||||
<hashTree>
|
||||
<ConstantThroughputTimer guiclass="TestBeanGUI" testclass="ConstantThroughputTimer" testname="Constant Throughput Timer" enabled="true">
|
||||
<intProp name="calcMode">2</intProp> <!-- this thread group -->
|
||||
<doubleProp>
|
||||
<name>throughput</name>
|
||||
<value>6000.0</value> <!-- 6000 requests per minute = 100 TPS -->
|
||||
<savedValue>0.0</savedValue>
|
||||
</doubleProp>
|
||||
</ConstantThroughputTimer>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">{
|
||||
"consent_id": "cos_123123",
|
||||
"msisdn": "6282215561862",
|
||||
"latitude": "-6.9095928",
|
||||
"longitude": "107.5601655",
|
||||
"area": "500"
|
||||
}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<stringProp name="HTTPArgument.use_equals">true</stringProp>
|
||||
<stringProp name="HTTPArgument.name"></stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain">localhost</stringProp>
|
||||
<stringProp name="HTTPSampler.port">3000</stringProp>
|
||||
<stringProp name="HTTPSampler.protocol">http</stringProp>
|
||||
<stringProp name="HTTPSampler.path">/v1/last-location</stringProp>
|
||||
<stringProp name="HTTPSampler.method">POST</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<boolProp name="HTTPSampler.postBodyRaw">true</boolProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree>
|
||||
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
|
||||
<collectionProp name="HeaderManager.headers">
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Accept</stringProp>
|
||||
<stringProp name="Header.value">application/json</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Authorization</stringProp>
|
||||
<stringProp name="Header.value">Basic YWRtaW46MTIzNDU2</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Content-Type</stringProp>
|
||||
<stringProp name="Header.value">application/json</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</HeaderManager>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
<JSR223Listener guiclass="TestBeanGUI" testclass="JSR223Listener" testname="Stop After 3000 Requests" enabled="true">
|
||||
<stringProp name="scriptLanguage">groovy</stringProp>
|
||||
<stringProp name="script"><![CDATA[
|
||||
if (ctx.getThreadGroup().getSampleCount() >= 3000) {
|
||||
log.info("Reached 3000 requests, stopping test...");
|
||||
org.apache.jmeter.engine.StandardJMeterEngine.stopEngine();
|
||||
}
|
||||
]]></stringProp>
|
||||
</JSR223Listener>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
</jmeterTestPlan>
|
||||
101
jmeter-scripts/lastlocation_20tps_10min_3000req.jmx
Normal file
101
jmeter-scripts/lastlocation_20tps_10min_3000req.jmx
Normal file
@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.6.3">
|
||||
<hashTree>
|
||||
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="MainTest" enabled="true">
|
||||
<stringProp name="TestPlan.comments"></stringProp>
|
||||
<boolProp name="TestPlan.functional_mode">false</boolProp>
|
||||
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
|
||||
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="TestPlan.user_define_classpath"></stringProp>
|
||||
</TestPlan>
|
||||
<hashTree>
|
||||
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
|
||||
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
|
||||
<intProp name="LoopController.loops">-1</intProp>
|
||||
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||
</elementProp>
|
||||
<intProp name="ThreadGroup.num_threads">5</intProp>
|
||||
<intProp name="ThreadGroup.ramp_time">1</intProp>
|
||||
<longProp name="ThreadGroup.duration">600</longProp> <!-- 10 minutes -->
|
||||
<longProp name="ThreadGroup.delay">0</longProp>
|
||||
<boolProp name="ThreadGroup.scheduler">true</boolProp>
|
||||
<boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
|
||||
</ThreadGroup>
|
||||
<hashTree>
|
||||
<ConstantThroughputTimer guiclass="TestBeanGUI" testclass="ConstantThroughputTimer" testname="Constant Throughput Timer" enabled="true">
|
||||
<intProp name="calcMode">2</intProp> <!-- This thread group -->
|
||||
<doubleProp>
|
||||
<name>throughput</name>
|
||||
<value>1200.0</value> <!-- 1200 requests per minute = 20 TPS -->
|
||||
<savedValue>0.0</savedValue>
|
||||
</doubleProp>
|
||||
</ConstantThroughputTimer>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">{
|
||||
"consent_id": "cos_123123",
|
||||
"msisdn": "6282215561862",
|
||||
"latitude": "-6.9095928",
|
||||
"longitude": "107.5601655",
|
||||
"area": "500"
|
||||
}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<stringProp name="HTTPArgument.use_equals">true</stringProp>
|
||||
<stringProp name="HTTPArgument.name"></stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain">localhost</stringProp>
|
||||
<stringProp name="HTTPSampler.port">3000</stringProp>
|
||||
<stringProp name="HTTPSampler.protocol">http</stringProp>
|
||||
<stringProp name="HTTPSampler.path">/v1/last-location</stringProp>
|
||||
<stringProp name="HTTPSampler.method">POST</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<boolProp name="HTTPSampler.postBodyRaw">true</boolProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree>
|
||||
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
|
||||
<collectionProp name="HeaderManager.headers">
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Accept</stringProp>
|
||||
<stringProp name="Header.value">application/json</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Authorization</stringProp>
|
||||
<stringProp name="Header.value">Basic YWRtaW46MTIzNDU2</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Content-Type</stringProp>
|
||||
<stringProp name="Header.value">application/json</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</HeaderManager>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
<JSR223Listener guiclass="TestBeanGUI" testclass="JSR223Listener" testname="Stop After 3000 Requests" enabled="true">
|
||||
<stringProp name="scriptLanguage">groovy</stringProp>
|
||||
<stringProp name="script"><![CDATA[
|
||||
if (ctx.getThreadGroup().getSampleCount() >= 3000) {
|
||||
log.info("Reached 3000 requests, stopping test...");
|
||||
org.apache.jmeter.engine.StandardJMeterEngine.stopEngine();
|
||||
}
|
||||
]]></stringProp>
|
||||
</JSR223Listener>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
</jmeterTestPlan>
|
||||
101
jmeter-scripts/lastlocation_50tps_10min_3000req.jmx
Normal file
101
jmeter-scripts/lastlocation_50tps_10min_3000req.jmx
Normal file
@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.6.3">
|
||||
<hashTree>
|
||||
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="MainTest" enabled="true">
|
||||
<stringProp name="TestPlan.comments"></stringProp>
|
||||
<boolProp name="TestPlan.functional_mode">false</boolProp>
|
||||
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
|
||||
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="TestPlan.user_define_classpath"></stringProp>
|
||||
</TestPlan>
|
||||
<hashTree>
|
||||
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
|
||||
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
|
||||
<intProp name="LoopController.loops">-1</intProp>
|
||||
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||
</elementProp>
|
||||
<intProp name="ThreadGroup.num_threads">10</intProp> <!-- Increased threads to help sustain 50 TPS -->
|
||||
<intProp name="ThreadGroup.ramp_time">1</intProp>
|
||||
<longProp name="ThreadGroup.duration">600</longProp> <!-- 10 minutes -->
|
||||
<longProp name="ThreadGroup.delay">0</longProp>
|
||||
<boolProp name="ThreadGroup.scheduler">true</boolProp>
|
||||
<boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
|
||||
</ThreadGroup>
|
||||
<hashTree>
|
||||
<ConstantThroughputTimer guiclass="TestBeanGUI" testclass="ConstantThroughputTimer" testname="Constant Throughput Timer" enabled="true">
|
||||
<intProp name="calcMode">2</intProp> <!-- This thread group -->
|
||||
<doubleProp>
|
||||
<name>throughput</name>
|
||||
<value>3000.0</value> <!-- 3000 requests per minute = 50 TPS -->
|
||||
<savedValue>0.0</savedValue>
|
||||
</doubleProp>
|
||||
</ConstantThroughputTimer>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">{
|
||||
"consent_id": "cos_123123",
|
||||
"msisdn": "6282215561862",
|
||||
"latitude": "-6.9095928",
|
||||
"longitude": "107.5601655",
|
||||
"area": "500"
|
||||
}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<stringProp name="HTTPArgument.use_equals">true</stringProp>
|
||||
<stringProp name="HTTPArgument.name"></stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain">localhost</stringProp>
|
||||
<stringProp name="HTTPSampler.port">3000</stringProp>
|
||||
<stringProp name="HTTPSampler.protocol">http</stringProp>
|
||||
<stringProp name="HTTPSampler.path">/v1/last-location</stringProp>
|
||||
<stringProp name="HTTPSampler.method">POST</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<boolProp name="HTTPSampler.postBodyRaw">true</boolProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree>
|
||||
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
|
||||
<collectionProp name="HeaderManager.headers">
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Accept</stringProp>
|
||||
<stringProp name="Header.value">application/json</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Authorization</stringProp>
|
||||
<stringProp name="Header.value">Basic YWRtaW46MTIzNDU2</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Content-Type</stringProp>
|
||||
<stringProp name="Header.value">application/json</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</HeaderManager>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
<JSR223Listener guiclass="TestBeanGUI" testclass="JSR223Listener" testname="Stop After 3000 Requests" enabled="true">
|
||||
<stringProp name="scriptLanguage">groovy</stringProp>
|
||||
<stringProp name="script"><![CDATA[
|
||||
if (ctx.getThreadGroup().getSampleCount() >= 3000) {
|
||||
log.info("Reached 3000 requests, stopping test...");
|
||||
org.apache.jmeter.engine.StandardJMeterEngine.stopEngine();
|
||||
}
|
||||
]]></stringProp>
|
||||
</JSR223Listener>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
</jmeterTestPlan>
|
||||
22
notes.md
Normal file
22
notes.md
Normal file
@ -0,0 +1,22 @@
|
||||
jmeter -n -t tsel-simswap.jmx -l tsel-simswap.csv -e -o tsel-simswap
|
||||
|
||||
===============prompt================
|
||||
adjust it so it will run 50 tps, for 10 minutes and max 3000 request
|
||||
|
||||
===============prompt================
|
||||
now i have files like this
|
||||
|
||||
jmeter-scripts/lastlocation_20tps_10min_3000req.jmx
|
||||
jmeter-scripts/lastlocation_50tps_10min_3000req.jmx
|
||||
jmeter-scripts/lastlocation_100tps_10min_3000req.jmx
|
||||
index.js
|
||||
|
||||
make me a nodejs app, that will check the system clock every second to run the files in jmeter-scripts based on the time
|
||||
1. 23.00-23.10: jmeter-scripts/lastlocation_20tps_10min_3000req.jmx
|
||||
2. 23.15-23.25: jmeter-scripts/lastlocation_50tps_10min_3000req.jmx
|
||||
3. 23.30-23.40: jmeter-scripts/lastlocation_100tps_10min_3000req.jmx
|
||||
|
||||
i have prepare shelljs so when the time has come, it will run jmeter command like this
|
||||
```bash
|
||||
jmeter -n -t [jmx-file] -l [result-csv-file in a new folder] -e -o [output folder same as result-csv-file]
|
||||
```
|
||||
10
package.json
Normal file
10
package.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"scripts": {},
|
||||
"dependencies": {
|
||||
"shelljs": "^0.8.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/shelljs": "^0.8.15"
|
||||
},
|
||||
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
||||
}
|
||||
167
yarn.lock
Normal file
167
yarn.lock
Normal file
@ -0,0 +1,167 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@types/glob@~7.2.0":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb"
|
||||
integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==
|
||||
dependencies:
|
||||
"@types/minimatch" "*"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/minimatch@*":
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca"
|
||||
integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==
|
||||
|
||||
"@types/node@*":
|
||||
version "22.15.19"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.15.19.tgz#ba9f321675243af0456d607fa82a4865931e0cef"
|
||||
integrity sha512-3vMNr4TzNQyjHcRZadojpRaD9Ofr6LsonZAoQ+HMUa/9ORTPoxVIw0e0mpqWpdjj8xybyCM+oKOUH2vwFu/oEw==
|
||||
dependencies:
|
||||
undici-types "~6.21.0"
|
||||
|
||||
"@types/shelljs@^0.8.15":
|
||||
version "0.8.16"
|
||||
resolved "https://registry.yarnpkg.com/@types/shelljs/-/shelljs-0.8.16.tgz#d18efab20bb76e465575e16b8e0db94d2973036f"
|
||||
integrity sha512-40SUXiH0tZfAg/oKkkGF1kdHPAmE4slv2xAmbfa8VtE6ztHYwdpW2phlzHTVdJh5JOGqA3Cx1Hzp7kxFalKHYA==
|
||||
dependencies:
|
||||
"@types/glob" "~7.2.0"
|
||||
"@types/node" "*"
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
concat-map "0.0.1"
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||
|
||||
function-bind@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
|
||||
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
|
||||
|
||||
glob@^7.0.0:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
|
||||
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.1.1"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
hasown@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
|
||||
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
|
||||
dependencies:
|
||||
function-bind "^1.1.2"
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
|
||||
dependencies:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
interpret@^1.0.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
|
||||
integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
|
||||
|
||||
is-core-module@^2.16.0:
|
||||
version "2.16.1"
|
||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4"
|
||||
integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==
|
||||
dependencies:
|
||||
hasown "^2.0.2"
|
||||
|
||||
minimatch@^3.1.1:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
once@^1.3.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
|
||||
dependencies:
|
||||
wrappy "1"
|
||||
|
||||
path-is-absolute@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
|
||||
|
||||
path-parse@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
||||
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
||||
|
||||
rechoir@^0.6.2:
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
|
||||
integrity sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==
|
||||
dependencies:
|
||||
resolve "^1.1.6"
|
||||
|
||||
resolve@^1.1.6:
|
||||
version "1.22.10"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39"
|
||||
integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==
|
||||
dependencies:
|
||||
is-core-module "^2.16.0"
|
||||
path-parse "^1.0.7"
|
||||
supports-preserve-symlinks-flag "^1.0.0"
|
||||
|
||||
shelljs@^0.8.5:
|
||||
version "0.8.5"
|
||||
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c"
|
||||
integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==
|
||||
dependencies:
|
||||
glob "^7.0.0"
|
||||
interpret "^1.0.0"
|
||||
rechoir "^0.6.2"
|
||||
|
||||
supports-preserve-symlinks-flag@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
||||
|
||||
undici-types@~6.21.0:
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
|
||||
integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
|
||||
Loading…
Reference in New Issue
Block a user