diff --git a/backend/src/main/java/io/metersphere/api/controller/ApiJmeterFileController.java b/backend/src/main/java/io/metersphere/api/controller/ApiJmeterFileController.java index 3ac47493ef..c6ee61370a 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiJmeterFileController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiJmeterFileController.java @@ -51,7 +51,7 @@ public class ApiJmeterFileController { byte[] bytes = apiJmeterFileService.downloadJmeterFiles(runMode, testId, reportId); return ResponseEntity.ok() .contentType(MediaType.parseMediaType("application/octet-stream")) - .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + testId + ".zip\"") + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + reportId + "_" + testId + ".zip\"") .body(bytes); } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/assertions/document/DocumentUtils.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/assertions/document/DocumentUtils.java deleted file mode 100644 index 73c792063c..0000000000 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/assertions/document/DocumentUtils.java +++ /dev/null @@ -1,132 +0,0 @@ -package io.metersphere.api.dto.definition.request.assertions.document; - -import com.alibaba.fastjson.JSON; -import com.google.gson.Gson; -import io.metersphere.vo.Condition; -import io.metersphere.vo.ElementCondition; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.jmeter.util.JMeterUtils; -import org.apache.oro.text.regex.Pattern; - -import java.text.DecimalFormat; -import java.util.List; -import java.util.Map; - -public class DocumentUtils { - - public static boolean documentChecked(Object subj, String condition, ThreadLocal decimalFormatter) { - if (StringUtils.isNotEmpty(condition)) { - ElementCondition elementCondition = JSON.parseObject(condition, ElementCondition.class); - boolean isTrue = true; - if (CollectionUtils.isNotEmpty(elementCondition.getConditions())) { - for (Condition item : elementCondition.getConditions()) { - String expectedValue = item.getValue() != null ? item.getValue().toString() : ""; - String resValue = objectToString(subj, decimalFormatter); - switch (item.getKey()) { - case "value_eq": - isTrue = StringUtils.equals(resValue, expectedValue); - break; - case "value_not_eq": - isTrue = !StringUtils.equals(resValue, expectedValue); - break; - case "value_in": - isTrue = StringUtils.contains(resValue, expectedValue); - break; - case "length_eq": - isTrue = getLength(subj, decimalFormatter) == numberOf(item.getValue()); - break; - case "length_not_eq": - isTrue = getLength(subj, decimalFormatter) != numberOf(item.getValue()); - break; - case "length_gt": - isTrue = getLength(subj, decimalFormatter) > numberOf(item.getValue()); - break; - case "length_lt": - isTrue = getLength(subj, decimalFormatter) < numberOf(item.getValue()); - break; - case "regular": - Pattern pattern = JMeterUtils.getPatternCache().getPattern(expectedValue); - isTrue = JMeterUtils.getMatcher().matches(resValue, pattern); - break; - } - if (!isTrue) { - break; - } - } - } - return isTrue; - } - return true; - } - - public static String objectToString(Object subj, ThreadLocal decimalFormatter) { - String str; - if (subj == null) { - str = "null"; - } else if (subj instanceof Map) { - str = new Gson().toJson(subj); - } else if (!(subj instanceof Double) && !(subj instanceof Float)) { - str = subj.toString(); - } else { - str = ((DecimalFormat) decimalFormatter.get()).format(subj); - } - return str; - } - - - private static int getLength(Object value) { - if (value != null) { - if (value instanceof List) { - return ((List) value).size(); - } - return value.toString().length(); - } - return 0; - } - - private static int getLength(Object value, ThreadLocal decimalFormatter) { - if (value != null) { - if (value instanceof Map) { - return ((Map) value).size(); - } else if (value instanceof List) { - return ((List) value).size(); - } else if (!(value instanceof Double) && !(value instanceof Float)) { - return value.toString().length(); - } else { - return ((DecimalFormat) decimalFormatter.get()).format(value).length(); - } - } - return 0; - } - - private static long numberOf(Object value) { - if (value != null) { - try { - return Long.parseLong(value.toString()); - } catch (Exception e) { - return 0; - } - } - return 0; - } - - public static String documentMsg(Object resValue, String condition) { - String msg = ""; - if (StringUtils.isNotEmpty(condition)) { - ElementCondition elementCondition = JSON.parseObject(condition, ElementCondition.class); - if (CollectionUtils.isNotEmpty(elementCondition.getConditions())) { - for (Condition item : elementCondition.getConditions()) { - if (StringUtils.equalsAny(item.getKey(), "value_eq", "value_not_eq", "value_in")) { - msg = resValue != null ? resValue.toString() : ""; - } else if (StringUtils.equalsAny(item.getKey(), "length_eq", "length_not_eq", "length_gt", "length_lt")) { - msg = "长度是:" + getLength(resValue) + ""; - } else { - msg = resValue != null ? resValue.toString() : ""; - } - } - } - } - return msg; - } -} diff --git a/backend/src/main/java/io/metersphere/api/exec/queue/ExecThreadPoolExecutor.java b/backend/src/main/java/io/metersphere/api/exec/queue/ExecThreadPoolExecutor.java index 3451d2aa0b..89f51426e3 100644 --- a/backend/src/main/java/io/metersphere/api/exec/queue/ExecThreadPoolExecutor.java +++ b/backend/src/main/java/io/metersphere/api/exec/queue/ExecThreadPoolExecutor.java @@ -150,6 +150,17 @@ public class ExecThreadPoolExecutor { return workerQueue.stream().filter(task -> StringUtils.equals(((ExecTask) task).getRequest().getReportId(), reportId)).count() > 0; } + public boolean checkPlanReport(String planReportId) { + // 检查缓冲区 + Queue bufferQueue = msRejectedExecutionHandler.getBufferQueue(); + if (CollectionUtils.isNotEmpty(bufferQueue)) { + return bufferQueue.stream().filter(task -> StringUtils.equals(task.getTestPlanReportId(), planReportId)).count() > 0; + } + // 检查等待队列 + BlockingQueue workerQueue = threadPool.getQueue(); + return workerQueue.stream().filter(task -> StringUtils.equals(((ExecTask) task).getRequest().getTestPlanReportId(), planReportId)).count() > 0; + } + public String getWorkerQueue() { StringBuffer buffer = new StringBuffer(); BlockingQueue workerQueue = threadPool.getQueue(); diff --git a/backend/src/main/java/io/metersphere/api/exec/schedule/TestPlanReportListenerScheduled.java b/backend/src/main/java/io/metersphere/api/exec/schedule/TestPlanReportListenerScheduled.java index 1ef1848da6..25d2e1946b 100644 --- a/backend/src/main/java/io/metersphere/api/exec/schedule/TestPlanReportListenerScheduled.java +++ b/backend/src/main/java/io/metersphere/api/exec/schedule/TestPlanReportListenerScheduled.java @@ -1,6 +1,7 @@ package io.metersphere.api.exec.schedule; import io.metersphere.api.cache.TestPlanReportExecuteCatch; +import io.metersphere.api.exec.queue.ExecThreadPoolExecutor; import io.metersphere.api.jmeter.MessageCache; import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.track.service.TestPlanReportService; @@ -27,7 +28,9 @@ public class TestPlanReportListenerScheduled { private void listener(String planReportId) { LoggerUtil.info("检查测试计划执行报告:【" + planReportId + "】"); if (TestPlanReportExecuteCatch.getTestPlanExecuteInfo(planReportId) != null) { - CommonBeanFactory.getBean(TestPlanReportService.class).countReport(planReportId); + if (!CommonBeanFactory.getBean(ExecThreadPoolExecutor.class).checkPlanReport(planReportId)) { + CommonBeanFactory.getBean(TestPlanReportService.class).countReport(planReportId); + } } else { MessageCache.jobReportCache.remove(planReportId); LoggerUtil.info("测试计划执行报告:【" + planReportId + "】执行完成,剩余队列:" + MessageCache.jobReportCache.size()); diff --git a/backend/src/main/java/io/metersphere/api/jmeter/FixedTask.java b/backend/src/main/java/io/metersphere/api/jmeter/FixedTask.java index e5b2a1f0a7..17add78c05 100644 --- a/backend/src/main/java/io/metersphere/api/jmeter/FixedTask.java +++ b/backend/src/main/java/io/metersphere/api/jmeter/FixedTask.java @@ -3,7 +3,7 @@ package io.metersphere.api.jmeter; import com.alibaba.fastjson.JSON; import io.metersphere.api.service.ApiScenarioReportService; import io.metersphere.commons.utils.CommonBeanFactory; -import io.metersphere.commons.utils.LogUtil; +import io.metersphere.utils.LoggerUtil; import org.apache.commons.collections.CollectionUtils; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -29,10 +29,10 @@ public class FixedTask { if (MessageCache.concurrencyCounter != null && MessageCache.concurrencyCounter.size() > 0) { for (String key : MessageCache.concurrencyCounter.keySet()) { ReportCounter counter = MessageCache.concurrencyCounter.get(key); - LogUtil.info("集成报告:【" + key + "】总执行场景:【" + counter.getTestIds().size() + "】已经执行完成场景:【" + counter.getCompletedIds().size() + "】"); + LoggerUtil.info("集成报告:【" + key + "】总执行场景:【" + counter.getTestIds().size() + "】已经执行完成场景:【" + counter.getCompletedIds().size() + "】"); List filterList = counter.getTestIds().stream().filter(t -> !counter.getCompletedIds().contains(t)).collect(Collectors.toList()); - LogUtil.debug("剩余要执行的报告" + JSON.toJSONString(filterList)); + LoggerUtil.debug("剩余要执行的报告" + JSON.toJSONString(filterList)); // 合并 if (counter.getCompletedIds().size() >= counter.getTestIds().size()) { scenarioReportService.margeReport(key); @@ -51,14 +51,14 @@ public class FixedTask { // 资源池中已经没有执行的请求了 int runningCount = scenarioReportService.get(key, counter); if (runningCount == 0) { - LogUtil.error("发生未知异常,进行资源合并,请检查资源池是否正常运行"); + LoggerUtil.error("发生未知异常,进行资源合并,请检查资源池是否正常运行"); scenarioReportService.margeReport(key); guardTask.remove(key); MessageCache.concurrencyCounter.remove(key); } } } catch (Exception ex) { - LogUtil.error(ex.getMessage()); + LoggerUtil.error(ex.getMessage()); } } } diff --git a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java index b001c6b83d..4c2a33202f 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java @@ -195,36 +195,38 @@ public class ApiDefinitionExecResultService { Map caseReportMap = new HashMap<>(); boolean isFirst = true; int countExpectProcessResultCount = 0; - for (RequestResult resultItem : requestResults) { - if (!StringUtils.startsWithAny(resultItem.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) { - countExpectProcessResultCount++; + if (CollectionUtils.isNotEmpty(requestResults)) { + for (RequestResult resultItem : requestResults) { + if (!StringUtils.startsWithAny(resultItem.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) { + countExpectProcessResultCount++; + } } - } - LoggerUtil.info("接收到定时任务执行结果【 " + requestResults.size() + " 】"); + LoggerUtil.info("接收到定时任务执行结果【 " + requestResults.size() + " 】"); - for (RequestResult item : requestResults) { - if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) { - ApiDefinitionExecResult saveResult = this.save(item, dto.getReportId(), dto.getConsole(), countExpectProcessResultCount, dto.getRunMode(), dto.getTestId(), isFirst); - String status = item.isSuccess() ? "success" : "error"; - if (StringUtils.equalsAny(dto.getRunMode(), ApiRunMode.SCHEDULE_API_PLAN.name(), ApiRunMode.JENKINS_API_PLAN.name())) { - TestPlanApiCase apiCase = testPlanApiCaseService.getById(dto.getTestId()); - if (apiCase != null) { - apiCase.setStatus(status); - apiCase.setUpdateTime(System.currentTimeMillis()); - testPlanApiCaseService.updateByPrimaryKeySelective(apiCase); + for (RequestResult item : requestResults) { + if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) { + ApiDefinitionExecResult saveResult = this.save(item, dto.getReportId(), dto.getConsole(), countExpectProcessResultCount, dto.getRunMode(), dto.getTestId(), isFirst); + String status = item.isSuccess() ? "success" : "error"; + if (StringUtils.equalsAny(dto.getRunMode(), ApiRunMode.SCHEDULE_API_PLAN.name(), ApiRunMode.JENKINS_API_PLAN.name())) { + TestPlanApiCase apiCase = testPlanApiCaseService.getById(dto.getTestId()); + if (apiCase != null) { + apiCase.setStatus(status); + apiCase.setUpdateTime(System.currentTimeMillis()); + testPlanApiCaseService.updateByPrimaryKeySelective(apiCase); + } + } else { + testPlanApiCaseService.setExecResult(dto.getTestId(), status, item.getStartTime()); + testCaseReviewApiCaseService.setExecResult(dto.getTestId(), status, item.getStartTime()); } - } else { - testPlanApiCaseService.setExecResult(dto.getTestId(), status, item.getStartTime()); - testCaseReviewApiCaseService.setExecResult(dto.getTestId(), status, item.getStartTime()); + if (StringUtils.isNotEmpty(dto.getTestId())) { + apiIdResultMap.put(dto.getTestId(), item.isSuccess() ? TestPlanApiExecuteStatus.SUCCESS.name() : TestPlanApiExecuteStatus.FAILD.name()); + } + //更新报告ID + caseReportMap.put(dto.getTestId(), saveResult.getId()); + isFirst = false; + // 串行队列 + SerialBlockingQueueUtil.offer(dto, SerialBlockingQueueUtil.END_SIGN); } - if (StringUtils.isNotEmpty(dto.getTestId())) { - apiIdResultMap.put(dto.getTestId(), item.isSuccess() ? TestPlanApiExecuteStatus.SUCCESS.name() : TestPlanApiExecuteStatus.FAILD.name()); - } - //更新报告ID - caseReportMap.put(dto.getTestId(), saveResult.getId()); - isFirst = false; - // 串行队列 - SerialBlockingQueueUtil.offer(dto, SerialBlockingQueueUtil.END_SIGN); } } updateTestCaseStates(dto.getTestId()); diff --git a/backend/src/main/java/io/metersphere/api/service/ApiJmeterFileService.java b/backend/src/main/java/io/metersphere/api/service/ApiJmeterFileService.java index 6dfd3ce48f..e030a0bea8 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiJmeterFileService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiJmeterFileService.java @@ -98,7 +98,7 @@ public class ApiJmeterFileService { } hashTree = GenerateHashTreeUtil.generateHashTree(scenario, reportId, planEnvMap); } - return zipFilesToByteArray(remoteTestId, hashTree); + return zipFilesToByteArray((reportId + "_" + remoteTestId), hashTree); } public byte[] downloadJmeterJar() { diff --git a/frontend/src/business/components/api/automation/report/SysnApiReportDetail.vue b/frontend/src/business/components/api/automation/report/SysnApiReportDetail.vue index 7ff97cecbf..0cbdb50478 100644 --- a/frontend/src/business/components/api/automation/report/SysnApiReportDetail.vue +++ b/frontend/src/business/components/api/automation/report/SysnApiReportDetail.vue @@ -39,6 +39,12 @@ v-on:requestResult="requestResult" /> + + +
{{ content.console }}
+
- - - {{api.name}} - - - + - {{ api.method}} + {{ api.method }} - -
{{api.path ===null ? " " : api.path}}
+ +
{{ api.name }}
+
+ +
{{ api.path === null ? " " : api.path }}
-
- -
+
@@ -31,112 +27,113 @@