From eb80bb6f1e1cee7a4e47c1574424ecc2a368bccf Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Tue, 21 Dec 2021 19:53:21 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=88=86=E5=B8=83=E5=BC=8F=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E7=BC=BA=E9=99=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ApiAutomationController.java | 2 - .../controller/ApiJmeterFileController.java | 4 +- .../dto/definition/request/ElementUtil.java | 54 +++++++++++++++++++ .../api/exec/api/ApiExecuteService.java | 17 +++--- .../exec/api/TestPlanApiExecuteService.java | 2 - .../exec/scenario/ApiScenarioEnvService.java | 16 +++++- .../scenario/ApiScenarioExecuteService.java | 14 ++--- .../scenario/ApiScenarioSerialService.java | 39 +++++++++++--- .../api/exec/utils/GenerateHashTreeUtil.java | 10 ++-- .../io/metersphere/api/jmeter/FixedTask.java | 3 -- .../metersphere/api/jmeter/JMeterService.java | 6 ++- .../metersphere/api/jmeter/MessageCache.java | 6 +-- .../api/service/ApiAutomationService.java | 2 +- .../ApiDefinitionExecResultService.java | 52 ++++++------------ .../api/service/ApiJmeterFileService.java | 4 +- .../ApiScenarioReportResultService.java | 7 ++- .../ApiScenarioReportStructureService.java | 44 ++++++++++----- .../api/service/RemakeReportService.java | 2 - .../metersphere/task/service/TaskService.java | 3 -- .../api/automation/report/ApiReportDetail.vue | 9 +++- 20 files changed, 191 insertions(+), 105 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java b/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java index ac60bcbc9f..8a4dbebbb3 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java @@ -7,7 +7,6 @@ import io.metersphere.api.dto.automation.*; import io.metersphere.api.dto.automation.parse.ScenarioImport; import io.metersphere.api.dto.definition.RunDefinitionRequest; import io.metersphere.api.exec.queue.ExecThreadPoolExecutor; -import io.metersphere.api.jmeter.MessageCache; import io.metersphere.api.service.ApiAutomationService; import io.metersphere.base.domain.ApiScenario; import io.metersphere.base.domain.ApiScenarioWithBLOBs; @@ -330,7 +329,6 @@ public class ApiAutomationController { @GetMapping(value = "/stop/{reportId}") public void stop(@PathVariable String reportId) { if (StringUtils.isNotEmpty(reportId)) { - MessageCache.caseExecResourceLock.remove(reportId); execThreadPoolExecutor.removeQueue(reportId); new LocalRunner().stop(reportId); } 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 c6ee61370a..f50e415443 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiJmeterFileController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiJmeterFileController.java @@ -47,8 +47,8 @@ public class ApiJmeterFileController { } @GetMapping("download") - public ResponseEntity downloadJmeterFiles(@RequestParam("testId") String testId, @RequestParam("reportId") String reportId, @RequestParam("runMode") String runMode) { - byte[] bytes = apiJmeterFileService.downloadJmeterFiles(runMode, testId, reportId); + public ResponseEntity downloadJmeterFiles(@RequestParam("testId") String testId, @RequestParam("reportId") String reportId, @RequestParam("runMode") String runMode, @RequestParam("reportType") String reportType) { + byte[] bytes = apiJmeterFileService.downloadJmeterFiles(runMode, testId, reportId, reportType); return ResponseEntity.ok() .contentType(MediaType.parseMediaType("application/octet-stream")) .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + reportId + "_" + testId + ".zip\"") diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/ElementUtil.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/ElementUtil.java index ef8259ad12..d329e60c5a 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/ElementUtil.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/ElementUtil.java @@ -24,6 +24,7 @@ import io.metersphere.commons.exception.MSException; import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.FileUtils; import io.metersphere.commons.utils.LogUtil; +import io.metersphere.constants.RunModeConstants; import io.metersphere.plugin.core.MsParameter; import io.metersphere.plugin.core.MsTestElement; import io.metersphere.service.EnvironmentGroupProjectService; @@ -270,6 +271,24 @@ public class ElementUtil { } }; + public final static List requests = new ArrayList() {{ + this.add("HTTPSamplerProxy"); + this.add("DubboSampler"); + this.add("JDBCSampler"); + this.add("TCPSampler"); + this.add("JSR223Processor"); + this.add("JSR223PreProcessor"); + this.add("JSR223PostProcessor"); + this.add("JDBCPreProcessor"); + this.add("JDBCPostProcessor"); + this.add("JmeterElement"); + this.add("TestPlan"); + this.add("ThreadGroup"); + this.add("DNSCacheManager"); + this.add("DebugSampler"); + this.add("AuthManager"); + }}; + private static void formatSampler(JSONObject element) { if (element == null || StringUtils.isEmpty(element.getString("type"))) { return; @@ -340,6 +359,41 @@ public class ElementUtil { } } + public static void dataFormatting(JSONArray hashTree, String id, String reportType) { + for (int i = 0; i < hashTree.size(); i++) { + JSONObject element = hashTree.getJSONObject(i); + formatSampler(element); + if (element != null && element.get("clazzName") == null && clazzMap.containsKey(element.getString("type"))) { + element.fluentPut("clazzName", clazzMap.get(element.getString("type"))); + } + if (StringUtils.equals(reportType, RunModeConstants.SET_REPORT.toString())) { + if (element != null && requests.contains(element.getString("type")) && !element.getString("resourceId").contains(id)) { + element.fluentPut("resourceId", id + "=" + element.getString("resourceId")); + } + } + if (element.containsKey("hashTree")) { + JSONArray elementJSONArray = element.getJSONArray("hashTree"); + dataFormatting(elementJSONArray, id, reportType); + } + } + } + + public static void dataFormatting(JSONObject element, String id, String reportType) { + if (element != null && element.get("clazzName") == null && clazzMap.containsKey(element.getString("type"))) { + element.fluentPut("clazzName", clazzMap.get(element.getString("type"))); + } + if (StringUtils.equals(reportType, RunModeConstants.SET_REPORT.toString())) { + if (element != null && requests.contains(element.getString("type")) && !element.getString("resourceId").contains(id)) { + element.fluentPut("resourceId", id + "=" + element.getString("resourceId")); + } + } + formatSampler(element); + if (element != null && element.containsKey("hashTree")) { + JSONArray elementJSONArray = element.getJSONArray("hashTree"); + dataFormatting(elementJSONArray, id, reportType); + } + } + public static void dataSetDomain(JSONArray hashTree, MsParameter msParameter) { try { ObjectMapper mapper = new ObjectMapper(); diff --git a/backend/src/main/java/io/metersphere/api/exec/api/ApiExecuteService.java b/backend/src/main/java/io/metersphere/api/exec/api/ApiExecuteService.java index be0d64fd50..835e528bca 100644 --- a/backend/src/main/java/io/metersphere/api/exec/api/ApiExecuteService.java +++ b/backend/src/main/java/io/metersphere/api/exec/api/ApiExecuteService.java @@ -18,7 +18,6 @@ import io.metersphere.api.dto.scenario.Body; import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import io.metersphere.api.exec.utils.ApiDefinitionExecResultUtil; import io.metersphere.api.jmeter.JMeterService; -import io.metersphere.api.jmeter.MessageCache; import io.metersphere.api.service.ApiTestEnvironmentService; import io.metersphere.api.service.TcpApiParamService; import io.metersphere.base.domain.*; @@ -120,7 +119,6 @@ public class ApiExecuteService { } List responseDTOS = new LinkedList<>(); for (RunCaseRequest runCaseRequest : executeQueue) { - MessageCache.caseExecResourceLock.put(runCaseRequest.getReportId(), runCaseRequest.getReport()); responseDTOS.add(exec(runCaseRequest)); } return responseDTOS; @@ -153,13 +151,14 @@ public class ApiExecuteService { JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(testCaseWithBLOBs.getId(), StringUtils.isEmpty(request.getReportId()) ? request.getId() : request.getReportId(), request.getRunMode(), jmeterHashTree); jMeterService.run(runRequest); } catch (Exception ex) { - ApiDefinitionExecResult result = MessageCache.caseExecResourceLock.get(request.getReportId()); - result.setStatus("error"); - apiDefinitionExecResultMapper.updateByPrimaryKey(result); - ApiTestCaseWithBLOBs caseWithBLOBs = apiTestCaseMapper.selectByPrimaryKey(request.getCaseId()); - caseWithBLOBs.setStatus("error"); - apiTestCaseMapper.updateByPrimaryKey(caseWithBLOBs); - MessageCache.caseExecResourceLock.remove(request.getReportId()); + ApiDefinitionExecResult result = apiDefinitionExecResultMapper.selectByPrimaryKey(request.getReportId()); + if (result != null) { + result.setStatus("error"); + apiDefinitionExecResultMapper.updateByPrimaryKey(result); + ApiTestCaseWithBLOBs caseWithBLOBs = apiTestCaseMapper.selectByPrimaryKey(request.getCaseId()); + caseWithBLOBs.setStatus("error"); + apiTestCaseMapper.updateByPrimaryKey(caseWithBLOBs); + } LogUtil.error(ex.getMessage(), ex); } } diff --git a/backend/src/main/java/io/metersphere/api/exec/api/TestPlanApiExecuteService.java b/backend/src/main/java/io/metersphere/api/exec/api/TestPlanApiExecuteService.java index 8979a79e71..a1ec72b6b0 100644 --- a/backend/src/main/java/io/metersphere/api/exec/api/TestPlanApiExecuteService.java +++ b/backend/src/main/java/io/metersphere/api/exec/api/TestPlanApiExecuteService.java @@ -7,7 +7,6 @@ import io.metersphere.api.exec.scenario.ApiScenarioSerialService; import io.metersphere.api.exec.utils.ApiDefinitionExecResultUtil; import io.metersphere.api.exec.utils.GenerateHashTreeUtil; import io.metersphere.api.jmeter.JMeterService; -import io.metersphere.api.jmeter.MessageCache; import io.metersphere.api.service.ApiExecutionQueueService; import io.metersphere.base.domain.ApiDefinitionExecResult; import io.metersphere.base.domain.ApiExecutionQueue; @@ -102,7 +101,6 @@ public class TestPlanApiExecuteService { ApiDefinitionExecResult report = ApiDefinitionExecResultUtil.addResult(request, testPlanApiCase, APITestStatus.Running.name(), batchMapper); executeQueue.put(report.getId(), testPlanApiCase); executeThreadIdMap.put(testPlanApiCase.getId(), report.getId()); - MessageCache.caseExecResourceLock.put(report.getId(), report); responseDTOS.add(new MsExecResponseDTO(testPlanApiCase.getId(), report.getId(), request.getTriggerMode())); }); sqlSession.flushStatements(); diff --git a/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioEnvService.java b/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioEnvService.java index 3cc2cdd296..bf5219081d 100644 --- a/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioEnvService.java +++ b/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioEnvService.java @@ -225,7 +225,7 @@ public class ApiScenarioEnvService { } String definition = apiScenarioWithBLOBs.getScenarioDefinition(); MsScenario scenario = JSONObject.parseObject(definition, MsScenario.class); - GenerateHashTreeUtil.parse(definition, scenario); + GenerateHashTreeUtil.parse(definition, scenario, apiScenarioWithBLOBs.getId(), null); if (StringUtils.equals(environmentType, EnvironmentType.JSON.toString())) { scenario.setEnvironmentMap(JSON.parseObject(environmentJson, Map.class)); } else if (StringUtils.equals(environmentType, EnvironmentType.GROUP.toString())) { @@ -428,4 +428,18 @@ public class ApiScenarioEnvService { config.setConfig(envConfig); } } + + public Map planEnvMap(String testPlanScenarioId) { + Map planEnvMap = new HashMap<>(); + TestPlanApiScenario planApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(testPlanScenarioId); + String envJson = planApiScenario.getEnvironment(); + String envType = planApiScenario.getEnvironmentType(); + String envGroupId = planApiScenario.getEnvironmentGroupId(); + if (StringUtils.equals(envType, EnvironmentType.JSON.toString()) && StringUtils.isNotBlank(envJson)) { + planEnvMap = JSON.parseObject(envJson, Map.class); + } else if (StringUtils.equals(envType, EnvironmentType.GROUP.toString()) && StringUtils.isNotBlank(envGroupId)) { + planEnvMap = environmentGroupProjectService.getEnvMap(envGroupId); + } + return planEnvMap; + } } diff --git a/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioExecuteService.java b/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioExecuteService.java index 206bd79bda..f993372ce8 100644 --- a/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioExecuteService.java +++ b/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioExecuteService.java @@ -150,7 +150,7 @@ public class ApiScenarioExecuteService { responseDTOS.add(new MsExecResponseDTO(JSON.toJSONString(scenarioIds), serialReportId, request.getRunMode())); // 增加并行集合报告 if (request.getConfig() != null && request.getConfig().getMode().equals(RunModeConstants.PARALLEL.toString())) { - apiScenarioReportStructureService.save(apiScenarios, serialReportId); + apiScenarioReportStructureService.save(apiScenarios, serialReportId, request.getConfig() != null ? request.getConfig().getReportType() : null); } } // 开始执行 @@ -160,7 +160,7 @@ public class ApiScenarioExecuteService { DBTestQueue executionQueue = apiExecutionQueueService.add(executeQueue, request.getConfig().getResourcePoolId(), ApiRunMode.SCENARIO.name(), serialReportId, reportType, request.getRunMode()); if (request.getConfig() != null && request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) { if (StringUtils.isNotEmpty(serialReportId)) { - apiScenarioReportStructureService.save(apiScenarios, serialReportId); + apiScenarioReportStructureService.save(apiScenarios, serialReportId, request.getConfig() != null ? request.getConfig().getReportType() : null); } SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); ApiScenarioReportMapper batchMapper = sqlSession.getMapper(ApiScenarioReportMapper.class); @@ -267,7 +267,7 @@ public class ApiScenarioExecuteService { // 生成并行报告和HashTree RunModeDataDTO runModeDataDTO = new RunModeDataDTO(report, testPlanScenarioId); if (request.getConfig() != null && !request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) { - runModeDataDTO.setHashTree(GenerateHashTreeUtil.generateHashTree(scenario, reportId, planEnvMap)); + runModeDataDTO.setHashTree(GenerateHashTreeUtil.generateHashTree(scenario, reportId, planEnvMap, request.getConfig().getReportType())); } executeQueue.put(report.getId(), runModeDataDTO); } catch (Exception ex) { @@ -284,7 +284,7 @@ public class ApiScenarioExecuteService { // 生成文档结构 if (request.getConfig() == null || !StringUtils.equals(request.getConfig().getReportType(), RunModeConstants.SET_REPORT.toString())) { - apiScenarioReportStructureService.save(scenario, report.getId()); + apiScenarioReportStructureService.save(scenario, report.getId(), request.getConfig() != null ? request.getConfig().getReportType() : null); } // 重置报告ID reportId = UUID.randomUUID().toString(); @@ -317,7 +317,7 @@ public class ApiScenarioExecuteService { try { RunModeDataDTO runModeDataDTO = new RunModeDataDTO(report, item.getId()); if (request.getConfig() != null && !request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) { - HashTree hashTree = GenerateHashTreeUtil.generateHashTree(item, StringUtils.isNotEmpty(serialReportId) ? serialReportId + "-" + i : reportId, new HashMap<>()); + HashTree hashTree = GenerateHashTreeUtil.generateHashTree(item, StringUtils.isNotEmpty(serialReportId) ? serialReportId + "-" + i : reportId, new HashMap<>(), request.getConfig().getReportType()); runModeDataDTO.setHashTree(hashTree); } executeQueue.put(report.getId(), runModeDataDTO); @@ -332,7 +332,7 @@ public class ApiScenarioExecuteService { } // 生成报告结构 if (request.getConfig() == null || !StringUtils.equals(request.getConfig().getReportType(), RunModeConstants.SET_REPORT.toString())) { - apiScenarioReportStructureService.save(item, report.getId()); + apiScenarioReportStructureService.save(item, report.getId(), request.getConfig() != null ? request.getConfig().getReportType() : null); } // 重置报告ID reportId = UUID.randomUUID().toString(); @@ -370,7 +370,7 @@ public class ApiScenarioExecuteService { apiScenarioReportMapper.insert(report); if (request.isSaved()) { ApiScenarioWithBLOBs scenario = apiScenarioMapper.selectByPrimaryKey(request.getScenarioId()); - apiScenarioReportStructureService.save(scenario, report.getId()); + apiScenarioReportStructureService.save(scenario, report.getId(), request.getConfig() != null ? request.getConfig().getReportType() : null); } uploadBodyFiles(request.getBodyFileRequestIds(), bodyFiles); FileUtils.createBodyFiles(request.getScenarioFileIds(), scenarioFiles); diff --git a/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioSerialService.java b/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioSerialService.java index db4312c4fa..c0d75599a9 100644 --- a/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioSerialService.java +++ b/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioSerialService.java @@ -15,17 +15,21 @@ import io.metersphere.api.dto.definition.request.sampler.MsJDBCSampler; import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler; import io.metersphere.api.exec.utils.GenerateHashTreeUtil; import io.metersphere.api.jmeter.JMeterService; +import io.metersphere.api.service.ApiExecutionQueueService; import io.metersphere.api.service.ApiTestEnvironmentService; +import io.metersphere.api.service.TestResultService; import io.metersphere.base.domain.*; import io.metersphere.base.mapper.*; import io.metersphere.commons.constants.APITestStatus; import io.metersphere.commons.constants.ApiRunMode; import io.metersphere.commons.exception.MSException; +import io.metersphere.commons.utils.BeanUtils; import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.HashTreeUtil; import io.metersphere.commons.utils.LogUtil; import io.metersphere.constants.RunModeConstants; import io.metersphere.dto.JmeterRunRequestDTO; +import io.metersphere.dto.ResultDTO; import io.metersphere.plugin.core.MsTestElement; import io.metersphere.utils.LoggerUtil; import org.apache.commons.lang3.StringUtils; @@ -51,6 +55,10 @@ public class ApiScenarioSerialService { private TestPlanApiCaseMapper testPlanApiCaseMapper; @Resource private ApiTestCaseMapper apiTestCaseMapper; + @Resource + private TestPlanApiScenarioMapper testPlanApiScenarioMapper; + @Resource + private ApiScenarioEnvService apiScenarioEnvService; public void serial(ApiExecutionQueue executionQueue, ApiExecutionQueueDetail queue) { LoggerUtil.debug("Scenario run-执行脚本装载-进入串行准备"); @@ -73,12 +81,22 @@ public class ApiScenarioSerialService { HashTree hashTree = null; if (StringUtils.isEmpty(executionQueue.getPoolId())) { if (StringUtils.equalsAny(executionQueue.getRunMode(), ApiRunMode.SCENARIO.name(), ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) { - ApiScenarioWithBLOBs scenario = apiScenarioMapper.selectByPrimaryKey(queue.getTestId()); + ApiScenarioWithBLOBs scenario = null; Map planEnvMap = new LinkedHashMap<>(); - if (StringUtils.isNotEmpty(queue.getEvnMap())) { + if (StringUtils.equalsAny(executionQueue.getRunMode(), ApiRunMode.SCENARIO.name())) { + scenario = apiScenarioMapper.selectByPrimaryKey(queue.getTestId()); + } else { + TestPlanApiScenario planApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(queue.getTestId()); + if (planApiScenario != null) { + planEnvMap = apiScenarioEnvService.planEnvMap(queue.getTestId()); + queue.setEvnMap(JSON.toJSONString(planEnvMap)); + scenario = apiScenarioMapper.selectByPrimaryKey(planApiScenario.getApiScenarioId()); + } + } + if ((planEnvMap == null || planEnvMap.isEmpty()) && StringUtils.isNotEmpty(queue.getEvnMap())) { planEnvMap = JSON.parseObject(queue.getEvnMap(), Map.class); } - hashTree = GenerateHashTreeUtil.generateHashTree(scenario, queue.getReportId(), planEnvMap); + hashTree = GenerateHashTreeUtil.generateHashTree(scenario, queue.getReportId(), planEnvMap, executionQueue.getReportType()); } else { hashTree = generateHashTree(queue.getTestId()); } @@ -86,6 +104,9 @@ public class ApiScenarioSerialService { this.initEnv(hashTree); } String reportId = StringUtils.isNotEmpty(executionQueue.getReportId()) ? executionQueue.getReportId() : queue.getReportId(); + if (!StringUtils.equals(executionQueue.getRunMode(), ApiRunMode.SCENARIO.name())) { + reportId = queue.getReportId(); + } JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(queue.getTestId(), reportId, executionQueue.getRunMode(), hashTree); runRequest.setReportType(executionQueue.getReportType()); runRequest.setPool(GenerateHashTreeUtil.isResourcePool(executionQueue.getPoolId())); @@ -96,11 +117,14 @@ public class ApiScenarioSerialService { // 开始执行 jMeterService.run(runRequest); } catch (Exception e) { - LogUtil.error("执行终止:" + e.getMessage()); + LoggerUtil.error("执行终止:" + e.getMessage()); + ResultDTO dto = new ResultDTO(); + BeanUtils.copyBean(dto, queue); + dto.setRunType(RunModeConstants.SERIAL.toString()); + dto.setReportType(executionQueue.getReportType()); + dto.setRunMode(executionQueue.getRunMode()); if (StringUtils.equalsAny(executionQueue.getRunMode(), ApiRunMode.SCENARIO.name(), ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) { - ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(queue.getReportId()); - report.setStatus(APITestStatus.Error.name()); - apiScenarioReportMapper.updateByPrimaryKey(report); + CommonBeanFactory.getBean(TestResultService.class).testEnded(dto); } else { ApiDefinitionExecResult apiDefinitionExecResult = apiDefinitionExecResultMapper.selectByPrimaryKey(queue.getReportId()); if (apiDefinitionExecResult != null) { @@ -108,6 +132,7 @@ public class ApiScenarioSerialService { apiDefinitionExecResultMapper.updateByPrimaryKey(apiDefinitionExecResult); } } + CommonBeanFactory.getBean(ApiExecutionQueueService.class).queueNext(dto); } } diff --git a/backend/src/main/java/io/metersphere/api/exec/utils/GenerateHashTreeUtil.java b/backend/src/main/java/io/metersphere/api/exec/utils/GenerateHashTreeUtil.java index 07737a9141..8d1dd393b0 100644 --- a/backend/src/main/java/io/metersphere/api/exec/utils/GenerateHashTreeUtil.java +++ b/backend/src/main/java/io/metersphere/api/exec/utils/GenerateHashTreeUtil.java @@ -32,16 +32,16 @@ public class GenerateHashTreeUtil { public static MsScenario parseScenarioDefinition(String scenarioDefinition) { MsScenario scenario = JSONObject.parseObject(scenarioDefinition, MsScenario.class); - parse(scenarioDefinition, scenario); + parse(scenarioDefinition, scenario, scenario.getId(), null); return scenario; } - public static void parse(String scenarioDefinition, MsScenario scenario) { + public static void parse(String scenarioDefinition, MsScenario scenario, String id, String reportType) { ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); try { JSONObject element = JSON.parseObject(scenarioDefinition); - ElementUtil.dataFormatting(element); + ElementUtil.dataFormatting(element, id, reportType); // 多态JSON普通转换会丢失内容,需要通过 ObjectMapper 获取 if (element != null && StringUtils.isNotEmpty(element.getString("hashTree"))) { LinkedList elements = mapper.readValue(element.getString("hashTree"), @@ -99,7 +99,7 @@ public class GenerateHashTreeUtil { return null; } - public static HashTree generateHashTree(ApiScenarioWithBLOBs item, String reportId, Map planEnvMap) { + public static HashTree generateHashTree(ApiScenarioWithBLOBs item, String reportId, Map planEnvMap, String reportType) { HashTree jmeterHashTree = new HashTree(); MsTestPlan testPlan = new MsTestPlan(); testPlan.setHashTree(new LinkedList<>()); @@ -112,7 +112,7 @@ public class GenerateHashTreeUtil { if (planEnvMap != null && planEnvMap.size() > 0) { scenario.setEnvironmentMap(planEnvMap); } - GenerateHashTreeUtil.parse(item.getScenarioDefinition(), scenario); + GenerateHashTreeUtil.parse(item.getScenarioDefinition(), scenario, item.getId(), reportType); group.setEnableCookieShare(scenario.isEnableCookieShare()); LinkedList scenarios = new LinkedList<>(); 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 d2641d55ed..b6eb280650 100644 --- a/backend/src/main/java/io/metersphere/api/jmeter/FixedTask.java +++ b/backend/src/main/java/io/metersphere/api/jmeter/FixedTask.java @@ -12,9 +12,6 @@ public class FixedTask { @Scheduled(cron = "0 */5 * * * ?") public void execute() { - if (MessageCache.caseExecResourceLock.size() > 10000) { - MessageCache.caseExecResourceLock.clear(); - } if (queueService == null) { queueService = CommonBeanFactory.getBean(ApiExecutionQueueService.class); } diff --git a/backend/src/main/java/io/metersphere/api/jmeter/JMeterService.java b/backend/src/main/java/io/metersphere/api/jmeter/JMeterService.java index 54f1820483..c085e13a3c 100644 --- a/backend/src/main/java/io/metersphere/api/jmeter/JMeterService.java +++ b/backend/src/main/java/io/metersphere/api/jmeter/JMeterService.java @@ -107,7 +107,11 @@ public class JMeterService { if (baseInfo != null) { platformUrl = baseInfo.getUrl(); } - platformUrl += "/api/jmeter/download?testId=" + request.getTestId() + "&reportId=" + request.getReportId() + "&runMode=" + request.getRunMode(); + platformUrl += "/api/jmeter/download?testId=" + + request.getTestId() + + "&reportId=" + request.getReportId() + + "&runMode=" + request.getRunMode() + + "&reportType=" + request.getReportType(); request.setPlatformUrl(platformUrl); request.setKafkaConfig(KafkaConfig.getKafka()); diff --git a/backend/src/main/java/io/metersphere/api/jmeter/MessageCache.java b/backend/src/main/java/io/metersphere/api/jmeter/MessageCache.java index 1f7edd8acb..235f84d6c0 100644 --- a/backend/src/main/java/io/metersphere/api/jmeter/MessageCache.java +++ b/backend/src/main/java/io/metersphere/api/jmeter/MessageCache.java @@ -1,7 +1,5 @@ package io.metersphere.api.jmeter; -import io.metersphere.base.domain.ApiDefinitionExecResult; - import javax.websocket.Session; import java.util.HashMap; import java.util.LinkedList; @@ -11,9 +9,7 @@ import java.util.concurrent.ConcurrentHashMap; public class MessageCache { public final static ConcurrentHashMap reportCache = new ConcurrentHashMap<>(); - // 用例并发锁 - public final static ConcurrentHashMap caseExecResourceLock = new ConcurrentHashMap<>(); - + public final static Map jmeterLogTask = new HashMap<>(); // 定时任务报告 diff --git a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java index 3fa56fb398..79129c721d 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -721,7 +721,7 @@ public class ApiAutomationService { if (scenario == null) { return null; } - GenerateHashTreeUtil.parse(apiScenario.getScenarioDefinition(), scenario); + GenerateHashTreeUtil.parse(apiScenario.getScenarioDefinition(), scenario, apiScenario.getId(), null); String environmentType = apiScenario.getEnvironmentType(); String environmentJson = apiScenario.getEnvironmentJson(); String environmentGroupId = apiScenario.getEnvironmentGroupId(); 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 9b29e08195..b4607c0f08 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java @@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import io.metersphere.api.cache.TestPlanReportExecuteCatch; import io.metersphere.api.dto.datacount.ExecutedCaseInfoResult; -import io.metersphere.api.jmeter.MessageCache; import io.metersphere.base.domain.*; import io.metersphere.base.mapper.ApiDefinitionExecResultMapper; import io.metersphere.base.mapper.ApiDefinitionMapper; @@ -320,34 +319,22 @@ public class ApiDefinitionExecResultService { private ApiDefinitionExecResult save(RequestResult item, String reportId, String console, int expectProcessResultCount, String type, String testId, boolean isFirst) { if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) { - ApiDefinitionExecResult saveResult = MessageCache.caseExecResourceLock.get(reportId); - if (saveResult == null) { - saveResult = apiDefinitionExecResultMapper.selectByPrimaryKey(reportId); - } + ApiDefinitionExecResult saveResult = new ApiDefinitionExecResult(); item.getResponseResult().setConsole(console); - boolean saved = true; - if (saveResult == null || expectProcessResultCount > 1) { - saveResult = new ApiDefinitionExecResult(); - if (isFirst) { - saveResult.setId(reportId); - } else { - saveResult.setId(UUID.randomUUID().toString()); - } - saveResult.setActuator("LOCAL"); - saveResult.setName(item.getName()); - if (StringUtils.equals(type, ApiRunMode.JENKINS_API_PLAN.name())) { - saveResult.setTriggerMode(TriggerMode.API.name()); - } else if (StringUtils.equals(type, ApiRunMode.MANUAL_PLAN.name())) { - saveResult.setTriggerMode(TriggerMode.MANUAL.name()); - } else { - saveResult.setTriggerMode(TriggerMode.SCHEDULE.name()); - } - saveResult.setType(type); - saveResult.setCreateTime(item.getStartTime()); - if (SessionUtils.getUser() != null) { - saveResult.setUserId(SessionUtils.getUser().getId()); - } - saved = false; + saveResult.setId(reportId); + saveResult.setActuator("LOCAL"); + saveResult.setName(item.getName()); + if (StringUtils.equals(type, ApiRunMode.JENKINS_API_PLAN.name())) { + saveResult.setTriggerMode(TriggerMode.API.name()); + } else if (StringUtils.equals(type, ApiRunMode.MANUAL_PLAN.name())) { + saveResult.setTriggerMode(TriggerMode.MANUAL.name()); + } else { + saveResult.setTriggerMode(TriggerMode.SCHEDULE.name()); + } + saveResult.setType(type); + saveResult.setCreateTime(item.getStartTime()); + if (SessionUtils.getUser() != null) { + saveResult.setUserId(SessionUtils.getUser().getId()); } String status = item.isSuccess() ? "success" : "error"; @@ -367,14 +354,7 @@ public class ApiDefinitionExecResultService { if (StringUtils.isNotEmpty(saveResult.getTriggerMode()) && saveResult.getTriggerMode().equals("CASE")) { saveResult.setTriggerMode(TriggerMode.MANUAL.name()); } - if (!saved) { - apiDefinitionExecResultMapper.insert(saveResult); - } else { - apiDefinitionExecResultMapper.updateByPrimaryKeyWithBLOBs(saveResult); - } - if (StringUtils.isNotEmpty(reportId)) { - MessageCache.caseExecResourceLock.remove(reportId); - } + apiDefinitionExecResultMapper.updateByPrimaryKeyWithBLOBs(saveResult); return saveResult; } return null; 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 139af4ed96..a03fd1074f 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiJmeterFileService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiJmeterFileService.java @@ -58,7 +58,7 @@ public class ApiJmeterFileService { return listBytesToZip(files); } - public byte[] downloadJmeterFiles(String runMode, String remoteTestId, String reportId) { + public byte[] downloadJmeterFiles(String runMode, String remoteTestId, String reportId, String reportType) { Map planEnvMap = new HashMap<>(); ApiScenarioWithBLOBs scenario = null; if (StringUtils.equalsAny(runMode, ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name())) { @@ -96,7 +96,7 @@ public class ApiJmeterFileService { planEnvMap = environmentGroupProjectService.getEnvMap(envGroupId); } } - hashTree = GenerateHashTreeUtil.generateHashTree(scenario, reportId, planEnvMap); + hashTree = GenerateHashTreeUtil.generateHashTree(scenario, reportId, planEnvMap, reportType); } return zipFilesToByteArray((reportId + "_" + remoteTestId), hashTree); } diff --git a/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportResultService.java b/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportResultService.java index 2b8488fd42..f287a38d7f 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportResultService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportResultService.java @@ -43,7 +43,12 @@ public class ApiScenarioReportResultService { report.setId(UUID.randomUUID().toString()); result.setEndTime(System.currentTimeMillis()); if (result.getResponseResult() != null) { - result.getResponseResult().setResponseTime((result.getEndTime() - result.getStartTime())); + long time = result.getEndTime() - result.getStartTime(); + if (time > 0) { + result.getResponseResult().setResponseTime(time); + } else { + result.setEndTime(result.getEndTime()); + } } String resourceId = result.getResourceId(); if (StringUtils.isNotEmpty(resourceId) && resourceId.contains("_")) { diff --git a/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportStructureService.java b/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportStructureService.java index 55a4172a4e..550d74473b 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportStructureService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportStructureService.java @@ -8,6 +8,7 @@ import io.metersphere.api.dto.StepTreeDTO; import io.metersphere.base.domain.*; import io.metersphere.base.mapper.ApiScenarioReportResultMapper; import io.metersphere.base.mapper.ApiScenarioReportStructureMapper; +import io.metersphere.constants.RunModeConstants; import io.metersphere.dto.RequestResult; import io.metersphere.utils.LoggerUtil; import org.apache.commons.collections.CollectionUtils; @@ -32,10 +33,10 @@ public class ApiScenarioReportStructureService { private static final List requests = Arrays.asList("HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "JSR223Processor", "AbstractSampler"); - public void save(List apiScenarios, String reportId) { + public void save(List apiScenarios, String reportId, String reportType) { List dtoList = new LinkedList<>(); for (ApiScenarioWithBLOBs bos : apiScenarios) { - StepTreeDTO dto = dataFormatting(bos); + StepTreeDTO dto = dataFormatting(bos, reportType); dtoList.add(dto); } if (LoggerUtil.getLogger().isDebugEnabled()) { @@ -44,9 +45,9 @@ public class ApiScenarioReportStructureService { this.save(reportId, dtoList); } - public void save(ApiScenarioWithBLOBs apiScenario, String reportId) { + public void save(ApiScenarioWithBLOBs apiScenario, String reportId, String reportType) { List dtoList = new LinkedList<>(); - StepTreeDTO dto = dataFormatting(apiScenario); + StepTreeDTO dto = dataFormatting(apiScenario, reportType); dtoList.add(dto); this.save(reportId, dtoList); } @@ -70,28 +71,40 @@ public class ApiScenarioReportStructureService { } } - public static StepTreeDTO dataFormatting(ApiScenarioWithBLOBs apiScenario) { + public static StepTreeDTO dataFormatting(ApiScenarioWithBLOBs apiScenario, String reportType) { JSONObject element = JSON.parseObject(apiScenario.getScenarioDefinition()); StepTreeDTO dto = null; if (element != null && element.getBoolean("enable")) { - dto = new StepTreeDTO(apiScenario.getName(), element.getString("resourceId"), element.getString("type"), element.getIntValue("index")); + String resourceId = element.getString("resourceId"); + if (StringUtils.equals(reportType, RunModeConstants.SET_REPORT.toString())) { + if (StringUtils.isNotEmpty(resourceId) && StringUtils.isNotEmpty(apiScenario.getId()) && !resourceId.contains(apiScenario.getId())) { + resourceId = apiScenario.getId() + "=" + element.getString("resourceId"); + } + } + dto = new StepTreeDTO(apiScenario.getName(), resourceId, element.getString("type"), element.getIntValue("index")); if (element.containsKey("hashTree") && !requests.contains(dto.getType())) { JSONArray elementJSONArray = element.getJSONArray("hashTree"); - dataFormatting(elementJSONArray, dto); + dataFormatting(elementJSONArray, dto, apiScenario.getId(), reportType); } } return dto; } - public static void dataFormatting(JSONArray hashTree, StepTreeDTO dto) { + public static void dataFormatting(JSONArray hashTree, StepTreeDTO dto, String id, String reportType) { for (int i = 0; i < hashTree.size(); i++) { JSONObject element = hashTree.getJSONObject(i); if (element != null && element.getBoolean("enable")) { - StepTreeDTO children = new StepTreeDTO(element.getString("name"), element.getString("resourceId"), element.getString("type"), element.getIntValue("index")); + String resourceId = element.getString("resourceId"); + if (StringUtils.equals(reportType, RunModeConstants.SET_REPORT.toString())) { + if (StringUtils.isNotEmpty(resourceId) && StringUtils.isNotEmpty(id) && !resourceId.contains(id)) { + resourceId = id + "=" + element.getString("resourceId"); + } + } + StepTreeDTO children = new StepTreeDTO(element.getString("name"), resourceId, element.getString("type"), element.getIntValue("index")); dto.getChildren().add(children); if (element.containsKey("hashTree") && !requests.contains(children.getType())) { JSONArray elementJSONArray = element.getJSONArray("hashTree"); - dataFormatting(elementJSONArray, children); + dataFormatting(elementJSONArray, children, id, reportType); } } } @@ -127,7 +140,7 @@ public class ApiScenarioReportStructureService { } } - private void calculateStep(List dtoList, AtomicLong stepError) { + private void calculateStep(List dtoList, AtomicLong stepError, AtomicLong stepTotal) { for (StepTreeDTO step : dtoList) { // 失败结果数量 AtomicLong error = new AtomicLong(); @@ -135,6 +148,9 @@ public class ApiScenarioReportStructureService { if (error.longValue() > 0) { stepError.set((stepError.longValue() + 1)); } + if (CollectionUtils.isNotEmpty(step.getChildren())) { + stepTotal.set((stepTotal.longValue() + step.getChildren().size())); + } } } @@ -194,8 +210,6 @@ public class ApiScenarioReportStructureService { ApiScenarioReportStructureWithBLOBs scenarioReportStructure = reportStructureWithBLOBs.get(0); List stepList = JSONArray.parseArray(new String(scenarioReportStructure.getResourceTree(), StandardCharsets.UTF_8), StepTreeDTO.class); - reportDTO.setScenarioStepTotal(stepList.size()); - // 匹配结果 Map> maps = reportResults.stream().collect(Collectors.groupingBy(ApiScenarioReportResult::getResourceId)); this.reportFormatting(stepList, maps); @@ -213,7 +227,9 @@ public class ApiScenarioReportStructureService { reportDTO.setScenarioSuccess((totalScenario.longValue() - scenarioError.longValue())); AtomicLong stepError = new AtomicLong(); - calculateStep(stepList, stepError); + AtomicLong stepTotal = new AtomicLong(); + calculateStep(stepList, stepError, stepTotal); + reportDTO.setScenarioStepTotal(stepTotal.longValue()); reportDTO.setScenarioStepError(stepError.longValue()); reportDTO.setScenarioStepSuccess((stepList.size() - stepError.longValue())); diff --git a/backend/src/main/java/io/metersphere/api/service/RemakeReportService.java b/backend/src/main/java/io/metersphere/api/service/RemakeReportService.java index 6ce25d299d..9d65b19161 100644 --- a/backend/src/main/java/io/metersphere/api/service/RemakeReportService.java +++ b/backend/src/main/java/io/metersphere/api/service/RemakeReportService.java @@ -114,7 +114,6 @@ public class RemakeReportService { } } } - MessageCache.caseExecResourceLock.remove(request.getReportId()); } catch (Exception e) { LogUtil.error(e); } @@ -143,6 +142,5 @@ public class RemakeReportService { } report.setStatus(APITestStatus.Error.name()); apiScenarioReportMapper.insert(report); - MessageCache.caseExecResourceLock.remove(report.getId()); } } diff --git a/backend/src/main/java/io/metersphere/task/service/TaskService.java b/backend/src/main/java/io/metersphere/task/service/TaskService.java index 4c43048517..ab213addee 100644 --- a/backend/src/main/java/io/metersphere/task/service/TaskService.java +++ b/backend/src/main/java/io/metersphere/task/service/TaskService.java @@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON; import io.metersphere.api.dto.automation.TaskRequest; import io.metersphere.api.exec.queue.ExecThreadPoolExecutor; import io.metersphere.api.jmeter.JMeterService; -import io.metersphere.api.jmeter.MessageCache; import io.metersphere.base.domain.*; import io.metersphere.base.mapper.ApiDefinitionExecResultMapper; import io.metersphere.base.mapper.ApiScenarioReportMapper; @@ -124,7 +123,6 @@ public class TaskService { result.setStatus("STOP"); apiDefinitionExecResultMapper.updateByPrimaryKeySelective(result); actuator = result.getActuator(); - MessageCache.caseExecResourceLock.remove(result.getId()); } } else if (StringUtils.equals(request.getType(), "SCENARIO")) { ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(request.getReportId()); @@ -145,7 +143,6 @@ public class TaskService { item.setStatus("STOP"); apiDefinitionExecResultMapper.updateByPrimaryKeySelective(item); actuator = item.getActuator(); - MessageCache.caseExecResourceLock.remove(item.getId()); request.setReportId(item.getId()); extracted(poolMap, request, actuator); } diff --git a/frontend/src/business/components/api/automation/report/ApiReportDetail.vue b/frontend/src/business/components/api/automation/report/ApiReportDetail.vue index 85d3dbb8e9..34b41f173c 100644 --- a/frontend/src/business/components/api/automation/report/ApiReportDetail.vue +++ b/frontend/src/business/components/api/automation/report/ApiReportDetail.vue @@ -21,7 +21,7 @@ -
{{ content.console }}
+ @@ -50,6 +50,7 @@ import {RequestFactory} from "../../definition/model/ApiTestModel"; import {windowPrint, getUUID, getCurrentProjectID} from "@/common/js/utils"; import {getScenarioReport, getShareScenarioReport} from "@/network/api"; import {STEP} from "@/business/components/api/automation/scenario/Setting"; +import MsCodeEdit from "@/business/components/common/components/MsCodeEdit"; export default { name: "MsApiReport", @@ -57,6 +58,7 @@ export default { MsApiReportViewHeader, MsApiReportExport, MsMainContainer, + MsCodeEdit, MsContainer, MsScenarioResults, MsRequestResultTail, MsMetricChart, MsScenarioResult, MsRequestResult }, data() { @@ -526,7 +528,10 @@ export default { .report-container .is-active .fail { color: inherit; } - +.report-console { + height: calc(100vh - 270px); + overflow-y: auto; +} .export-button { float: right; }