fix(接口测试): 修复分布式执行相关缺陷
This commit is contained in:
parent
78e23135df
commit
eb80bb6f1e
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -47,8 +47,8 @@ public class ApiJmeterFileController {
|
|||
}
|
||||
|
||||
@GetMapping("download")
|
||||
public ResponseEntity<byte[]> downloadJmeterFiles(@RequestParam("testId") String testId, @RequestParam("reportId") String reportId, @RequestParam("runMode") String runMode) {
|
||||
byte[] bytes = apiJmeterFileService.downloadJmeterFiles(runMode, testId, reportId);
|
||||
public ResponseEntity<byte[]> 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\"")
|
||||
|
|
|
@ -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<String> requests = new ArrayList<String>() {{
|
||||
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();
|
||||
|
|
|
@ -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<MsExecResponseDTO> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<String, String> planEnvMap(String testPlanScenarioId) {
|
||||
Map<String, String> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<String, String> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<MsTestElement> elements = mapper.readValue(element.getString("hashTree"),
|
||||
|
@ -99,7 +99,7 @@ public class GenerateHashTreeUtil {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static HashTree generateHashTree(ApiScenarioWithBLOBs item, String reportId, Map<String, String> planEnvMap) {
|
||||
public static HashTree generateHashTree(ApiScenarioWithBLOBs item, String reportId, Map<String, String> 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<MsTestElement> scenarios = new LinkedList<>();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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,8 +9,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
|
||||
public class MessageCache {
|
||||
public final static ConcurrentHashMap<String, Session> reportCache = new ConcurrentHashMap<>();
|
||||
// 用例并发锁
|
||||
public final static ConcurrentHashMap<String, ApiDefinitionExecResult> caseExecResourceLock = new ConcurrentHashMap<>();
|
||||
|
||||
public final static Map<String, Long> jmeterLogTask = new HashMap<>();
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<String, String> 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);
|
||||
}
|
||||
|
|
|
@ -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("_")) {
|
||||
|
|
|
@ -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<String> requests = Arrays.asList("HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "JSR223Processor", "AbstractSampler");
|
||||
|
||||
public void save(List<ApiScenarioWithBLOBs> apiScenarios, String reportId) {
|
||||
public void save(List<ApiScenarioWithBLOBs> apiScenarios, String reportId, String reportType) {
|
||||
List<StepTreeDTO> 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<StepTreeDTO> 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<StepTreeDTO> dtoList, AtomicLong stepError) {
|
||||
private void calculateStep(List<StepTreeDTO> 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<StepTreeDTO> stepList = JSONArray.parseArray(new String(scenarioReportStructure.getResourceTree(), StandardCharsets.UTF_8), StepTreeDTO.class);
|
||||
|
||||
reportDTO.setScenarioStepTotal(stepList.size());
|
||||
|
||||
// 匹配结果
|
||||
Map<String, List<ApiScenarioReportResult>> 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()));
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<template slot="label">
|
||||
<span class="console">{{ $t('api_test.definition.request.console') }}</span>
|
||||
</template>
|
||||
<pre>{{ content.console }}</pre>
|
||||
<ms-code-edit :mode="'text'" :read-only="true" :data.sync="content.console" height="calc(100vh - 500px)"/>
|
||||
</el-tab-pane>
|
||||
|
||||
</el-tabs>
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue