From 89c72033621f43c67c64ff0f7c165b8c5f052af2 Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Wed, 31 Mar 2021 16:52:59 +0800 Subject: [PATCH 1/5] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E5=AE=9A=E4=B9=89):?= =?UTF-8?q?=20=E6=89=A7=E8=A1=8C=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/dto/definition/request/sampler/MsHTTPSamplerProxy.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java index 74e804c3f0..e91d6758d4 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java @@ -187,7 +187,7 @@ public class MsHTTPSamplerProxy extends MsTestElement { } } else { String url = this.getUrl(); - if (!url.startsWith("http://") && !url.startsWith("https://")) { + if (StringUtils.isNotEmpty(url) && !url.startsWith("http://") && !url.startsWith("https://")) { url = "http://" + url; } if (StringUtils.isNotEmpty(this.getPort()) && this.getPort().startsWith("${")) { From d88c97e81fe45d09ceba5e28e71b8d262221ab9b Mon Sep 17 00:00:00 2001 From: song-tianyang <75963100+song-tianyang@users.noreply.github.com> Date: Wed, 31 Mar 2021 18:09:20 +0800 Subject: [PATCH 2/5] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E9=A1=B5=E9=9D=A2=E5=9C=A8=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E7=82=B9=E5=87=BB=E8=BF=90=E8=A1=8C=E6=97=B6?= =?UTF-8?q?tab=E6=A0=87=E7=AD=BE=E5=91=BD=E5=90=8D=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复接口定义页面在接口列表点击运行时tab标签命名错误的问题 --- .../src/business/components/api/definition/ApiDefinition.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/business/components/api/definition/ApiDefinition.vue b/frontend/src/business/components/api/definition/ApiDefinition.vue index 3abdc02222..9f1fcbda0d 100644 --- a/frontend/src/business/components/api/definition/ApiDefinition.vue +++ b/frontend/src/business/components/api/definition/ApiDefinition.vue @@ -392,8 +392,8 @@ } }, runTest(data) { - this.setTabTitle(data); this.handleTabsEdit(this.$t("commons.api"), "TEST", data); + this.setTabTitle(data); }, saveApi(data) { this.setTabTitle(data); From e3848b81f4cf4fc2aa3dae0b26607c5b4948ce97 Mon Sep 17 00:00:00 2001 From: shiziyuan9527 Date: Wed, 31 Mar 2021 18:11:45 +0800 Subject: [PATCH 3/5] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E5=AE=9A=E4=B9=89):?= =?UTF-8?q?=20=E6=89=B9=E9=87=8F=E6=89=A7=E8=A1=8C=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/definition/components/Run.vue | 24 +++++++++++-------- .../components/case/ApiCaseList.vue | 2 ++ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/frontend/src/business/components/api/definition/components/Run.vue b/frontend/src/business/components/api/definition/components/Run.vue index 734419b84f..3ef992d3e9 100644 --- a/frontend/src/business/components/api/definition/components/Run.vue +++ b/frontend/src/business/components/api/definition/components/Run.vue @@ -58,22 +58,26 @@ } }, run() { - let testPlan = new TestPlan(); - let threadGroup = new ThreadGroup(); - threadGroup.hashTree = []; - testPlan.hashTree = [threadGroup]; - this.runData.forEach(item => { - threadGroup.hashTree.push(item); - }) - - let projectId = ""; + let projectId = this.$store.state.projectId; // 如果envMap不存在,是单接口调用 if (!this.envMap || this.envMap.size === 0) { projectId = this.$store.state.projectId; } else { // 场景步骤下接口调用 - projectId = this.runData.projectId; + if(this.runData.projectId){ + projectId = this.runData.projectId; + } } + + let testPlan = new TestPlan(); + let threadGroup = new ThreadGroup(); + threadGroup.hashTree = []; + testPlan.hashTree = [threadGroup]; + this.runData.forEach(item => { + item.projectId = projectId; + threadGroup.hashTree.push(item); + }) + let reqObj = {id: this.reportId, testElement: testPlan, type: this.type,projectId: projectId, environmentMap: strMapToObj(this.envMap)}; let bodyFiles = getBodyUploadFiles(reqObj, this.runData); let url = ""; diff --git a/frontend/src/business/components/api/definition/components/case/ApiCaseList.vue b/frontend/src/business/components/api/definition/components/case/ApiCaseList.vue index f63c1e8f92..0f27ac344f 100644 --- a/frontend/src/business/components/api/definition/components/case/ApiCaseList.vue +++ b/frontend/src/business/components/api/definition/components/case/ApiCaseList.vue @@ -305,6 +305,8 @@ this.$warning(this.$t('api_test.environment.select_environment')); return; } + this.envMap = new Map(); + this.envMap.set(this.$store.state.projectId,this.environment); this.runData = []; this.batchLoadingIds = []; this.selectdCases = []; From d90daa493007e5ff92a6329197b045af1de635b4 Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Wed, 31 Mar 2021 18:55:42 +0800 Subject: [PATCH 4/5] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E5=AE=9A=E4=B9=89):?= =?UTF-8?q?=20=E4=BF=AE=E5=A4=8D=E5=9F=9F=E5=90=8D=E5=B8=A6url=20=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../request/sampler/MsHTTPSamplerProxy.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java index e91d6758d4..f46e4d1162 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java @@ -160,14 +160,16 @@ public class MsHTTPSamplerProxy extends MsTestElement { sampler.setProtocol(urlObject.getProtocol()); sampler.setPath(urlObject.getPath()); } else { - String configStr = config.getConfig().get(this.getProjectId()).getHttpConfig().getSocket(); - sampler.setDomain(configStr); - if (config.getConfig().get(this.getProjectId()).getHttpConfig().getPort() > 0) { - sampler.setDomain(config.getConfig().get(this.getProjectId()).getHttpConfig().getDomain()); + sampler.setDomain(config.getConfig().get(this.getProjectId()).getHttpConfig().getDomain()); + url = config.getConfig().get(this.getProjectId()).getHttpConfig().getProtocol() + "://" + config.getConfig().get(this.getProjectId()).getHttpConfig().getSocket(); + URL urlObject = new URL(url); + String envPath = StringUtils.equals(urlObject.getPath(), "/") ? "" : urlObject.getPath(); + if (StringUtils.isNotBlank(this.getPath())) { + envPath += this.getPath(); } sampler.setPort(config.getConfig().get(this.getProjectId()).getHttpConfig().getPort()); sampler.setProtocol(config.getConfig().get(this.getProjectId()).getHttpConfig().getProtocol()); - sampler.setPath(this.getPath()); + sampler.setPath(envPath); } String envPath = sampler.getPath(); if (CollectionUtils.isNotEmpty(this.getRest()) && this.isRest()) { From fa08d597253728211e0b14eeb1f984f1dfb10273 Mon Sep 17 00:00:00 2001 From: "Captain.B" Date: Wed, 31 Mar 2021 19:05:10 +0800 Subject: [PATCH 5/5] =?UTF-8?q?refactor:=20=E5=A2=9E=E5=8A=A0=E9=A2=84?= =?UTF-8?q?=E6=9C=9F=E7=BB=93=E6=9D=9F=E6=97=B6=E9=97=B4=E7=9A=84=E5=8F=82?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../metersphere/config/KafkaProperties.java | 1 + .../controller/JmeterFileController.java | 3 +- .../xml/reader/jmx/JmeterDocumentParser.java | 53 +++++++++++++++++-- 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/io/metersphere/config/KafkaProperties.java b/backend/src/main/java/io/metersphere/config/KafkaProperties.java index d158b64fcc..63ade0be9f 100644 --- a/backend/src/main/java/io/metersphere/config/KafkaProperties.java +++ b/backend/src/main/java/io/metersphere/config/KafkaProperties.java @@ -11,6 +11,7 @@ public class KafkaProperties { public static final String KAFKA_PREFIX = "kafka"; private String acks = "0"; // 不要设置all + private String expectedDelayEndTime = "30000"; // 30s private String topic; private String fields; private String timestamp; diff --git a/backend/src/main/java/io/metersphere/performance/controller/JmeterFileController.java b/backend/src/main/java/io/metersphere/performance/controller/JmeterFileController.java index 6ad3c39089..4a80c5fa12 100644 --- a/backend/src/main/java/io/metersphere/performance/controller/JmeterFileController.java +++ b/backend/src/main/java/io/metersphere/performance/controller/JmeterFileController.java @@ -25,8 +25,9 @@ public class JmeterFileController { @GetMapping("download") public ResponseEntity downloadJmeterFiles(@RequestParam("testId") String testId, @RequestParam("resourceId") String resourceId, - @RequestParam("ratio") double ratio, @RequestParam("startTime") long startTime, + @RequestParam("ratio") double ratio, @RequestParam("reportId") String reportId, @RequestParam("resourceIndex") int resourceIndex) { + long startTime = System.currentTimeMillis(); byte[] bytes = jmeterFileService.downloadZip(testId, resourceId, ratio, startTime, reportId, resourceIndex); return ResponseEntity.ok() .contentType(MediaType.parseMediaType("application/octet-stream")) diff --git a/backend/src/main/java/io/metersphere/performance/parse/xml/reader/jmx/JmeterDocumentParser.java b/backend/src/main/java/io/metersphere/performance/parse/xml/reader/jmx/JmeterDocumentParser.java index a8d33e4391..790be02d19 100644 --- a/backend/src/main/java/io/metersphere/performance/parse/xml/reader/jmx/JmeterDocumentParser.java +++ b/backend/src/main/java/io/metersphere/performance/parse/xml/reader/jmx/JmeterDocumentParser.java @@ -29,6 +29,7 @@ public class JmeterDocumentParser implements DocumentParser { private final static String HASH_TREE_ELEMENT = "hashTree"; private final static String TEST_PLAN = "TestPlan"; private final static String STRING_PROP = "stringProp"; + private final static String BOOL_PROP = "boolProp"; private final static String COLLECTION_PROP = "collectionProp"; private final static String CONCURRENCY_THREAD_GROUP = "com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroup"; private final static String VARIABLE_THROUGHPUT_TIMER = "kg.apc.jmeter.timers.VariableThroughputTimer"; @@ -94,6 +95,7 @@ public class JmeterDocumentParser implements DocumentParser { processCheckoutDnsCacheManager(ele); processCheckoutArguments(ele); processCheckoutResponseAssertion(ele); + processCheckoutSerializeThreadgroups(ele); } else if (nodeNameEquals(ele, CONCURRENCY_THREAD_GROUP)) { processThreadGroupName(ele); processCheckoutTimer(ele); @@ -141,6 +143,21 @@ public class JmeterDocumentParser implements DocumentParser { } } + private void processCheckoutSerializeThreadgroups(Element element) { + NodeList childNodes = element.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node item = childNodes.item(i); + if (nodeNameEquals(item, BOOL_PROP)) { + String serializeName = ((Element) item).getAttribute("name"); + if (StringUtils.equals(serializeName, "TestPlan.serialize_threadgroups")) { + // 保存线程组是否是顺序执行 + context.addProperty("serialize_threadgroups", item.getTextContent()); + break; + } + } + } + } + private void processArgumentFiles(Element element) { NodeList childNodes = element.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { @@ -479,7 +496,7 @@ public class JmeterDocumentParser implements DocumentParser { item.appendChild(elementProp); } } - if (item instanceof Element && nodeNameEquals(item, "boolProp") + if (item instanceof Element && nodeNameEquals(item, BOOL_PROP) && org.apache.commons.lang3.StringUtils.equals(((Element) item).getAttribute("name"), "DNSCacheManager.isCustomResolver")) { item.getFirstChild().setNodeValue("true"); } @@ -511,7 +528,7 @@ public class JmeterDocumentParser implements DocumentParser { } private Element createBoolProp(Document document, String name, boolean value) { - Element boolProp = document.createElement("boolProp"); + Element boolProp = document.createElement(BOOL_PROP); boolProp.setAttribute("name", name); boolProp.appendChild(document.createTextNode(String.valueOf(value))); return boolProp; @@ -569,6 +586,8 @@ public class JmeterDocumentParser implements DocumentParser { collectionProp.appendChild(createKafkaProp(document, "test.name", context.getTestName())); collectionProp.appendChild(createKafkaProp(document, "test.startTime", context.getStartTime().toString())); collectionProp.appendChild(createKafkaProp(document, "test.reportId", context.getReportId())); + collectionProp.appendChild(createKafkaProp(document, "test.expectedEndTime", (String) context.getProperty("expectedEndTime"))); + collectionProp.appendChild(createKafkaProp(document, "test.expectedDelayEndTime", kafkaProperties.getExpectedDelayEndTime())); // 30s elementProp.appendChild(collectionProp); // set elementProp @@ -710,6 +729,8 @@ public class JmeterDocumentParser implements DocumentParser { default: break; } + // 处理预计结束时间 + processExpectedEndTime(duration); threadGroup.setAttribute("enabled", enabled); if (BooleanUtils.toBoolean(deleted)) { @@ -815,6 +836,8 @@ public class JmeterDocumentParser implements DocumentParser { default: break; } + // 处理预计结束时间 + processExpectedEndTime(hold); threadGroup.setAttribute("enabled", enabled); if (BooleanUtils.toBoolean(deleted)) { @@ -835,6 +858,27 @@ public class JmeterDocumentParser implements DocumentParser { threadGroup.appendChild(createStringProp(document, "Unit", "S")); } + private void processExpectedEndTime(String duration) { + long startTime = context.getStartTime(); + Long d = Long.parseLong(duration); + Object serialize = context.getProperty("TestPlan.serialize_threadgroups"); + String expectedEndTime = (String) context.getProperty("expectedEndTime"); + if (StringUtils.isBlank(expectedEndTime)) { + expectedEndTime = startTime + ""; + } + long endTime = Long.parseLong(expectedEndTime); + + if (BooleanUtils.toBoolean((String) serialize)) { + // 顺序执行线程组 + context.addProperty("expectedEndTime", String.valueOf(endTime + d * 1000)); + } else { + // 同时执行线程组 + if (endTime < startTime + d * 1000) { + context.addProperty("expectedEndTime", String.valueOf(startTime + d * 1000)); + } + } + } + private void processIterationThreadGroup(Element threadGroup) { // 检查 threadgroup 后面的hashtree是否为空 Node hashTree = threadGroup.getNextSibling(); @@ -903,8 +947,11 @@ public class JmeterDocumentParser implements DocumentParser { threadGroup.appendChild(createStringProp(document, "ThreadGroup.duration", "10")); threadGroup.appendChild(createStringProp(document, "ThreadGroup.delay", "")); threadGroup.appendChild(createBoolProp(document, "ThreadGroup.same_user_on_next_iteration", true)); - } + // 处理预计结束时间, (按照迭代次数 * 线程数)s + String duration = String.valueOf(Long.parseLong(loops) * Long.parseLong(threads)); + processExpectedEndTime(duration); + } private void processCheckoutTimer(Element element) { /*