refactor(接口测试): 大批量执行效率优化修复多节点执行阻塞时间长问题

This commit is contained in:
fit2-zhao 2022-01-29 17:46:58 +08:00 committed by fit2-zhao
parent f97917b581
commit e119cdf628
30 changed files with 687 additions and 689 deletions

View File

@ -1,9 +1,9 @@
package io.metersphere.api.dto;
import io.metersphere.api.dto.automation.APIScenarioReportResult;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import lombok.Getter;
import lombok.Setter;
import org.apache.jorphan.collections.HashTree;
import java.util.Map;
@ -11,7 +11,7 @@ import java.util.Map;
@Setter
public class RunModeDataDTO {
// 执行HashTree
private HashTree hashTree;
private ApiScenarioWithBLOBs scenario;
// 测试场景/测试用例
private String testId;

View File

@ -13,10 +13,10 @@ import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
import io.metersphere.api.dto.mockconfig.MockConfigStaticData;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
import io.metersphere.api.service.ApiAutomationService;
import io.metersphere.api.service.ApiTestEnvironmentService;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
import io.metersphere.base.mapper.ApiScenarioMapper;
import io.metersphere.commons.constants.MsTestElementConstants;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.FileUtils;
@ -96,10 +96,10 @@ public class MsScenario extends MsTestElement {
return;
} else if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) {
try {
ApiAutomationService apiAutomationService = CommonBeanFactory.getBean(ApiAutomationService.class);
ApiScenarioMapper apiAutomationService = CommonBeanFactory.getBean(ApiScenarioMapper.class);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
ApiScenarioWithBLOBs scenario = apiAutomationService.getApiScenario(this.getId());
ApiScenarioWithBLOBs scenario = apiAutomationService.selectByPrimaryKey(this.getId());
if (scenario != null && StringUtils.isNotEmpty(scenario.getScenarioDefinition())) {
JSONObject element = JSON.parseObject(scenario.getScenarioDefinition());
// 历史数据处理
@ -179,9 +179,9 @@ public class MsScenario extends MsTestElement {
}
ParameterConfig newConfig = new ParameterConfig();
if (this.isEnvironmentEnable()) {
ApiAutomationService apiAutomationService = CommonBeanFactory.getBean(ApiAutomationService.class);
ApiScenarioMapper apiScenarioMapper = CommonBeanFactory.getBean(ApiScenarioMapper.class);
EnvironmentGroupProjectService environmentGroupProjectService = CommonBeanFactory.getBean(EnvironmentGroupProjectService.class);
ApiScenarioWithBLOBs scenario = apiAutomationService.getApiScenario(this.getId());
ApiScenarioWithBLOBs scenario = apiScenarioMapper.selectByPrimaryKey(this.getId());
String environmentType = scenario.getEnvironmentType();
String environmentJson = scenario.getEnvironmentJson();
String environmentGroupId = scenario.getEnvironmentGroupId();

View File

@ -7,9 +7,9 @@ import io.metersphere.api.dto.definition.BatchRunDefinitionRequest;
import io.metersphere.api.exec.queue.DBTestQueue;
import io.metersphere.api.exec.scenario.ApiScenarioSerialService;
import io.metersphere.api.exec.utils.ApiDefinitionExecResultUtil;
import io.metersphere.api.service.ApiCaseResultService;
import io.metersphere.api.service.ApiExecutionQueueService;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
import io.metersphere.base.mapper.ApiTestCaseMapper;
import io.metersphere.base.mapper.TestPlanApiCaseMapper;
import io.metersphere.base.mapper.ext.ExtApiTestCaseMapper;
@ -26,24 +26,16 @@ import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections4.comparators.FixedOrderComparator;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.*;
@Service
@Transactional(rollbackFor = Exception.class)
public class ApiCaseExecuteService {
@Resource
private TestPlanApiCaseMapper testPlanApiCaseMapper;
@Resource
private SqlSessionFactory sqlSessionFactory;
@Resource
private ApiScenarioSerialService apiScenarioSerialService;
@Resource
private ApiExecutionQueueService apiExecutionQueueService;
@ -55,6 +47,8 @@ public class ApiCaseExecuteService {
private ApiTestCaseMapper apiTestCaseMapper;
@Resource
private EnvironmentGroupProjectService environmentGroupProjectService;
@Resource
private ApiCaseResultService apiCaseResultService;
/**
* 测试计划case执行
@ -79,8 +73,6 @@ public class ApiCaseExecuteService {
example.createCriteria().andIdIn(ids);
example.setOrderByClause("`order` DESC");
List<TestPlanApiCase> planApiCases = testPlanApiCaseMapper.selectByExample(example);
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiDefinitionExecResultMapper batchMapper = sqlSession.getMapper(ApiDefinitionExecResultMapper.class);
if (StringUtils.isEmpty(request.getTriggerMode())) {
request.setTriggerMode(ApiRunMode.API_PLAN.name());
}
@ -89,14 +81,12 @@ public class ApiCaseExecuteService {
List<MsExecResponseDTO> responseDTOS = new LinkedList<>();
String status = request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString()) ? APITestStatus.Waiting.name() : APITestStatus.Running.name();
planApiCases.forEach(testPlanApiCase -> {
ApiDefinitionExecResult report = ApiDefinitionExecResultUtil.addResult(request, testPlanApiCase, status, batchMapper);
ApiDefinitionExecResult report = ApiDefinitionExecResultUtil.addResult(request, testPlanApiCase, status);
executeQueue.put(testPlanApiCase.getId(), report);
responseDTOS.add(new MsExecResponseDTO(testPlanApiCase.getId(), report.getId(), request.getTriggerMode()));
});
sqlSession.flushStatements();
if (sqlSession != null && sqlSessionFactory != null) {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
apiCaseResultService.batchSave(executeQueue);
LoggerUtil.debug("开始生成测试计划队列");
String reportType = request.getConfig().getReportType();
@ -155,8 +145,6 @@ public class ApiCaseExecuteService {
}
}
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiDefinitionExecResultMapper batchMapper = sqlSession.getMapper(ApiDefinitionExecResultMapper.class);
if (StringUtils.isEmpty(request.getTriggerMode())) {
request.setTriggerMode(ApiRunMode.DEFINITION.name());
}
@ -168,14 +156,12 @@ public class ApiCaseExecuteService {
ApiDefinitionExecResult report = ApiDefinitionExecResultUtil.initBase(caseWithBLOBs.getId(), APITestStatus.Running.name(), null, request.getConfig());
report.setStatus(status);
report.setName(caseWithBLOBs.getName());
batchMapper.insert(report);
report.setVersionId(caseWithBLOBs.getVersionId());
executeQueue.put(caseWithBLOBs.getId(), report);
responseDTOS.add(new MsExecResponseDTO(caseWithBLOBs.getId(), report.getId(), request.getTriggerMode()));
});
sqlSession.flushStatements();
if (sqlSession != null && sqlSessionFactory != null) {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
apiCaseResultService.batchSave(executeQueue);
String reportType = request.getConfig().getReportType();
String poolId = request.getConfig().getResourcePoolId();

View File

@ -8,7 +8,6 @@ import io.metersphere.base.domain.ApiDefinitionExecResult;
import io.metersphere.constants.RunModeConstants;
import io.metersphere.dto.JmeterRunRequestDTO;
import io.metersphere.dto.RunModeConfigDTO;
import io.metersphere.utils.LoggerUtil;
import org.apache.jorphan.collections.HashTree;
import org.springframework.stereotype.Service;
@ -26,16 +25,11 @@ public class ApiCaseParallelExecuteService {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
Thread.currentThread().setName("API-CASE-THREAD");
for (String testId : executeQueue.keySet()) {
ApiDefinitionExecResult result = executeQueue.get(testId);
String reportId = result.getId();
HashTree hashTree = null;
if (!GenerateHashTreeUtil.isResourcePool(config.getResourcePoolId()).isPool()) {
hashTree = apiScenarioSerialService.generateHashTree(testId, result.getId(), runMode, config.getEnvMap());
}
JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(testId, reportId, runMode, hashTree);
runRequest.setPool(GenerateHashTreeUtil.isResourcePool(config.getResourcePoolId()));
runRequest.setTestPlanReportId(executionQueue.getReportId());
@ -46,10 +40,11 @@ public class ApiCaseParallelExecuteService {
if (executionQueue.getQueue() != null) {
runRequest.setPlatformUrl(executionQueue.getQueue().getId());
}
jMeterService.run(runRequest);
if (!GenerateHashTreeUtil.isResourcePool(config.getResourcePoolId()).isPool()) {
hashTree = apiScenarioSerialService.generateHashTree(testId, config.getEnvMap(), runRequest);
runRequest.setHashTree(hashTree);
}
} catch (Exception e) {
LoggerUtil.error("并发执行用例失败:" + e.getMessage());
jMeterService.run(runRequest);
}
}
});

View File

@ -22,12 +22,10 @@ public class ExecTask implements Runnable {
LoggerUtil.info("开始执行报告ID" + request.getReportId() + " 】,资源ID【 " + request.getTestId() + "");
JMeterService jMeterService = CommonBeanFactory.getBean(JMeterService.class);
jMeterService.addQueue(request);
if (request.getPool() == null || !request.getPool().isPool()) {
Object res = PoolExecBlockingQueueUtil.take(request.getReportId());
if (res == null && !JmeterThreadUtils.isRunning(request.getReportId(), request.getTestId())) {
LoggerUtil.info("执行报告:【 " + request.getReportId() + " 】,资源ID【 " + request.getTestId() + " 】执行超时");
}
}
LoggerUtil.info("任务:【 " + request.getReportId() + " 】执行完成");
}
}

View File

@ -1,7 +1,6 @@
package io.metersphere.api.exec.queue;
import io.metersphere.api.exec.utils.NamedThreadFactory;
import io.metersphere.api.jmeter.MessageCache;
import io.metersphere.dto.JmeterRunRequestDTO;
import io.metersphere.utils.LoggerUtil;
import org.apache.commons.collections.CollectionUtils;
@ -93,6 +92,7 @@ public class ExecThreadPoolExecutor {
buffer.append(" 队列大小:" + (queue.size() + queue.remainingCapacity())).append("\n");
buffer.append(" 当前排队线程数:" + (msRejectedExecutionHandler.getBufferQueue().size() + queue.size())).append("\n");
buffer.append(" 队列剩余大小:" + queue.remainingCapacity()).append("\n");
buffer.append(" 阻塞队列大小:" + PoolExecBlockingQueueUtil.queue.size()).append("\n");
buffer.append(" 队列使用度:" + divide(queue.size(), queue.size() + queue.remainingCapacity()));
LoggerUtil.info(buffer.toString());
@ -104,7 +104,6 @@ public class ExecThreadPoolExecutor {
public void setCorePoolSize(int corePoolSize) {
try {
MessageCache.corePoolSize = corePoolSize;
threadPool.setCorePoolSize(corePoolSize);
threadPool.setMaximumPoolSize(corePoolSize);
threadPool.allowCoreThreadTimeOut(true);

View File

@ -11,7 +11,10 @@ import io.metersphere.api.dto.definition.request.ParameterConfig;
import io.metersphere.api.exec.queue.DBTestQueue;
import io.metersphere.api.exec.utils.GenerateHashTreeUtil;
import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.api.service.*;
import io.metersphere.api.service.ApiExecutionQueueService;
import io.metersphere.api.service.ApiScenarioReportService;
import io.metersphere.api.service.ApiScenarioReportStructureService;
import io.metersphere.api.service.TcpApiParamService;
import io.metersphere.base.domain.ApiScenarioExample;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.base.domain.TestPlanApiScenario;
@ -22,7 +25,6 @@ import io.metersphere.base.mapper.ext.ExtApiScenarioMapper;
import io.metersphere.commons.constants.APITestStatus;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.ReportTriggerMode;
import io.metersphere.commons.constants.TriggerMode;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.FileUtils;
import io.metersphere.commons.utils.LogUtil;
@ -42,11 +44,7 @@ import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.collections4.comparators.FixedOrderComparator;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.jorphan.collections.HashTree;
import org.mybatis.spring.SqlSessionUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
@ -76,21 +74,17 @@ public class ApiScenarioExecuteService {
@Resource
private ApiScenarioReportService apiScenarioReportService;
@Resource
private RemakeReportService remakeReportService;
@Resource
private EnvironmentGroupProjectService environmentGroupProjectService;
@Resource
private ApiScenarioReportStructureService apiScenarioReportStructureService;
private ApiScenarioReportStructureService reportStructureService;
@Resource
private ApiScenarioSerialService apiScenarioSerialService;
private ApiScenarioSerialService serialService;
@Resource
private ApiScenarioParallelService apiScenarioParallelService;
private ApiScenarioParallelService parallelService;
@Resource
private TcpApiParamService tcpApiParamService;
@Resource
private JMeterService jMeterService;
@Resource
private SqlSessionFactory sqlSessionFactory;
public List<MsExecResponseDTO> run(RunScenarioRequest request) {
if (LoggerUtil.getLogger().isDebugEnabled()) {
@ -119,7 +113,7 @@ public class ApiScenarioExecuteService {
LoggerUtil.info("Scenario run-执行脚本装载-开始针对所有执行场景进行环境检查");
apiScenarioEnvService.checkEnv(request, apiScenarios);
// 集合报告设置
if (request.getConfig() != null && StringUtils.equals(request.getConfig().getReportType(), RunModeConstants.SET_REPORT.toString())
if (StringUtils.equals(request.getConfig().getReportType(), RunModeConstants.SET_REPORT.toString())
&& StringUtils.isNotEmpty(request.getConfig().getReportName())) {
if (request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) {
request.setExecuteType(ExecuteType.Completed.name());
@ -128,14 +122,14 @@ public class ApiScenarioExecuteService {
}
serialReportId = UUID.randomUUID().toString();
}
List<MsExecResponseDTO> responseDTOS = new LinkedList<>();
Map<String, RunModeDataDTO> executeQueue = new LinkedHashMap<>();
List<String> scenarioIds = new ArrayList<>();
StringBuilder scenarioNames = new StringBuilder();
LoggerUtil.info("Scenario run-执行脚本装载-初始化执行队列");
if (StringUtils.equalsAny(request.getRunMode(), ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) {
if (StringUtils.equalsAny(request.getRunMode(), ApiRunMode.SCENARIO_PLAN.name(),
ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) {
//测试计划执行
assemblyPlanScenario(apiScenarios, request, executeQueue, scenarioIds, scenarioNames);
} else {
@ -144,58 +138,43 @@ public class ApiScenarioExecuteService {
}
LoggerUtil.info("Scenario run-执行脚本装载-初始化执行队列完成:" + executeQueue.size());
List<MsExecResponseDTO> responseDTOS = new LinkedList<>();
if (executeQueue.isEmpty()) {
return responseDTOS;
}
if (GenerateHashTreeUtil.isSetReport(request.getConfig())) {
LoggerUtil.info("Scenario run-执行脚本装载-初始化集成报告:" + serialReportId);
request.getConfig().setReportId(UUID.randomUUID().toString());
APIScenarioReportResult report = apiScenarioReportService.init(request.getConfig().getReportId(),
JSON.toJSONString(CollectionUtils.isNotEmpty(scenarioIds) && scenarioIds.size() > 50 ? scenarioIds.subList(0, 50) : scenarioIds),
scenarioNames.length() >= 3000 ? scenarioNames.substring(0, 2000) : scenarioNames.deleteCharAt(scenarioNames.length() - 1).toString(),
ReportTriggerMode.MANUAL.name(), ExecuteType.Saved.name(), request.getProjectId(), request.getReportUserID(), request.getConfig(), JSON.toJSONString(scenarioIds));
String reportScenarioIds = JSON.toJSONString(CollectionUtils.isNotEmpty(scenarioIds) && scenarioIds.size() > 50 ? scenarioIds.subList(0, 50) : scenarioIds);
APIScenarioReportResult report = apiScenarioReportService.init(request.getConfig().getReportId(), reportScenarioIds,
scenarioNames.toString(), ReportTriggerMode.MANUAL.name(), ExecuteType.Saved.name(), request.getProjectId(),
request.getReportUserID(), request.getConfig());
report.setVersionId(apiScenarios.get(0).getVersionId());
report.setName(request.getConfig().getReportName());
report.setId(serialReportId);
request.getConfig().setAmassReport(serialReportId);
report.setStatus(APITestStatus.Running.name());
apiScenarioReportMapper.insert(report);
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, request.getConfig() != null
? request.getConfig().getReportType() : null);
reportStructureService.save(apiScenarios, serialReportId, request.getConfig().getReportType());
}
}
// 开始执行
if (executeQueue != null && executeQueue.size() > 0) {
String reportType = request.getConfig().getReportType();
String planReportId = StringUtils.isNotEmpty(request.getTestPlanReportId()) ? request.getTestPlanReportId() : serialReportId;
// 生成执行队列
DBTestQueue executionQueue = apiExecutionQueueService.add(executeQueue, request.getConfig().getResourcePoolId()
, ApiRunMode.SCENARIO.name(), planReportId, reportType, request.getRunMode(), request.getConfig());
if (request.getConfig() != null && request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) {
if (StringUtils.isNotEmpty(serialReportId)) {
apiScenarioReportStructureService.save(apiScenarios, serialReportId, request.getConfig() != null ? request.getConfig().getReportType() : null);
}
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiScenarioReportMapper batchMapper = sqlSession.getMapper(ApiScenarioReportMapper.class);
// 非集合报告先生成执行队列
if (StringUtils.isEmpty(serialReportId)) {
for (String reportId : executeQueue.keySet()) {
APIScenarioReportResult report = executeQueue.get(reportId).getReport();
report.setStatus(APITestStatus.Waiting.name());
batchMapper.insert(report);
responseDTOS.add(new MsExecResponseDTO(executeQueue.get(reportId).getTestId(), reportId, request.getRunMode()));
}
sqlSession.flushStatements();
if (sqlSession != null && sqlSessionFactory != null) {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
}
if (executionQueue.getQueue() != null) {
apiScenarioSerialService.serial(executionQueue, executionQueue.getQueue());
}
// 预生成报告
apiScenarioReportService.batchSave(executeQueue, serialReportId, request.getRunMode(), responseDTOS);
// 开始执行
if (StringUtils.equals(request.getConfig().getMode(), RunModeConstants.SERIAL.toString())) {
serialService.serial(executionQueue, executionQueue.getQueue());
} else {
apiScenarioParallelService.parallel(executeQueue, request, serialReportId, responseDTOS, executionQueue);
}
parallelService.parallel(executeQueue, request, serialReportId, executionQueue);
}
return responseDTOS;
}
@ -239,11 +218,9 @@ public class ApiScenarioExecuteService {
if (scenario.getStepTotal() == null || scenario.getStepTotal() == 0) {
continue;
}
APIScenarioReportResult report;
Map<String, String> planEnvMap = new HashMap<>();
//测试计划页面触发的执行方式生成报告时createScenarioReport第二个参数需要特殊处理
// 获取场景用例单独的执行环境
Map<String, String> planEnvMap = new HashMap<>();
TestPlanApiScenario planApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(testPlanScenarioId);
String envJson = planApiScenario.getEnvironment();
String envType = planApiScenario.getEnvironmentType();
@ -259,36 +236,23 @@ public class ApiScenarioExecuteService {
if (StringUtils.isEmpty(projectId)) {
projectId = scenario.getProjectId();
}
report = apiScenarioReportService.init(reportId, testPlanScenarioId, scenario.getName(), request.getTriggerMode(),
request.getExecuteType(), projectId, request.getReportUserID(), request.getConfig(), scenario.getId());
APIScenarioReportResult report = apiScenarioReportService.init(reportId, testPlanScenarioId, scenario.getName(), request.getTriggerMode(),
request.getExecuteType(), projectId, request.getReportUserID(), request.getConfig());
report.setVersionId(scenario.getVersionId());
scenarioIds.add(scenario.getId());
if (request.getConfig() != null && StringUtils.isNotBlank(request.getConfig().getResourcePoolId())) {
RunModeDataDTO runModeDataDTO = new RunModeDataDTO();
runModeDataDTO.setTestId(testPlanScenarioId);
runModeDataDTO.setPlanEnvMap(planEnvMap);
runModeDataDTO.setReport(report);
runModeDataDTO.setReportId(report.getId());
runModeDataDTO.setScenario(scenario);
executeQueue.put(report.getId(), runModeDataDTO);
} else {
try {
// 生成并行报告和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, request.getConfig().getReportType()));
}
executeQueue.put(report.getId(), runModeDataDTO);
} catch (Exception ex) {
scenarioIds.remove(scenario.getId());
executeQueue.remove(report.getId());
remakeReportService.remakeScenario(request.getRunMode(), testPlanScenarioId, scenario, report);
continue;
}
}
scenarioNames.append(scenario.getName()).append(",");
// 生成文档结构
if (request.getConfig() == null || !StringUtils.equals(request.getConfig().getReportType(), RunModeConstants.SET_REPORT.toString())) {
apiScenarioReportStructureService.save(scenario, report.getId(), request.getConfig() != null ? request.getConfig().getReportType() : null);
if (!StringUtils.equals(request.getConfig().getReportType(), RunModeConstants.SET_REPORT.toString())) {
reportStructureService.save(scenario, report.getId(), request.getConfig() != null ? request.getConfig().getReportType() : null);
}
// 重置报告ID
reportId = UUID.randomUUID().toString();
@ -306,11 +270,11 @@ public class ApiScenarioExecuteService {
continue;
}
APIScenarioReportResult report = apiScenarioReportService.init(reportId, item.getId(), item.getName(), request.getTriggerMode(),
request.getExecuteType(), item.getProjectId(), request.getReportUserID(), request.getConfig(), item.getId());
request.getExecuteType(), item.getProjectId(), request.getReportUserID(), request.getConfig());
scenarioIds.add(item.getId());
report.setVersionId(item.getVersionId());
scenarioNames.append(item.getName()).append(",");
if (request.getConfig() != null && StringUtils.isNotBlank(request.getConfig().getResourcePoolId())) {
RunModeDataDTO runModeDataDTO = new RunModeDataDTO();
runModeDataDTO.setTestId(item.getId());
runModeDataDTO.setPlanEnvMap(new HashMap<>());
@ -320,28 +284,11 @@ public class ApiScenarioExecuteService {
runModeDataDTO.setReport(report);
runModeDataDTO.setReportId(report.getId());
executeQueue.put(report.getId(), runModeDataDTO);
} else {
try {
// 生成报告和HashTree
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, request.getConfig().getEnvMap(), request.getConfig().getReportType());
runModeDataDTO.setHashTree(hashTree);
}
runModeDataDTO.setPlanEnvMap(request.getConfig().getEnvMap());
runModeDataDTO.setScenario(item);
executeQueue.put(report.getId(), runModeDataDTO);
} catch (Exception ex) {
scenarioIds.remove(item.getId());
if (StringUtils.equalsAny(request.getTriggerMode(), TriggerMode.BATCH.name(), TriggerMode.SCHEDULE.name())) {
remakeReportService.remakeScenario(request.getRunMode(), null, item, report);
} else {
MSException.throwException(ex);
}
}
}
// 生成报告结构
if (request.getConfig() == null || !StringUtils.equals(request.getConfig().getReportType(), RunModeConstants.SET_REPORT.toString())) {
apiScenarioReportStructureService.save(item, report.getId(), request.getConfig() != null ? request.getConfig().getReportType() : null);
if (!StringUtils.equals(request.getConfig().getReportType(), RunModeConstants.SET_REPORT.toString())) {
reportStructureService.save(item, report.getId(), request.getConfig().getReportType());
}
// 重置报告ID
reportId = UUID.randomUUID().toString();
@ -381,13 +328,12 @@ public class ApiScenarioExecuteService {
request.getExecuteType(),
request.getProjectId(),
SessionUtils.getUserId(),
request.getConfig(),
request.getId());
request.getConfig());
ApiScenarioWithBLOBs scenario = apiScenarioMapper.selectByPrimaryKey(request.getScenarioId());
String reportType = request.getConfig() != null ? request.getConfig().getReportType() : null;
if (scenario != null) {
report.setVersionId(scenario.getVersionId());
apiScenarioReportStructureService.save(scenario, report.getId(), reportType);
reportStructureService.save(scenario, report.getId(), reportType);
} else {
if (request.getTestElement() != null && CollectionUtils.isNotEmpty(request.getTestElement().getHashTree())) {
ApiScenarioWithBLOBs apiScenario = new ApiScenarioWithBLOBs();
@ -396,7 +342,7 @@ public class ApiScenarioExecuteService {
if (testElement != null) {
apiScenario.setName(testElement.getName());
apiScenario.setScenarioDefinition(JSON.toJSONString(testElement));
apiScenarioReportStructureService.save(apiScenario, report.getId(), reportType);
reportStructureService.save(apiScenario, report.getId(), reportType);
}
}
}

View File

@ -2,53 +2,28 @@ package io.metersphere.api.exec.scenario;
import com.alibaba.fastjson.JSON;
import io.metersphere.api.dto.RunModeDataDTO;
import io.metersphere.api.dto.automation.APIScenarioReportResult;
import io.metersphere.api.dto.automation.RunScenarioRequest;
import io.metersphere.api.exec.queue.DBTestQueue;
import io.metersphere.api.exec.utils.GenerateHashTreeUtil;
import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.base.mapper.ApiScenarioReportMapper;
import io.metersphere.constants.RunModeConstants;
import io.metersphere.dto.JmeterRunRequestDTO;
import io.metersphere.dto.MsExecResponseDTO;
import io.metersphere.utils.LoggerUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
@Service
public class ApiScenarioParallelService {
@Resource
private SqlSessionFactory sqlSessionFactory;
@Resource
private JMeterService jMeterService;
public void parallel(Map<String, RunModeDataDTO> executeQueue, RunScenarioRequest request, String serialReportId, List<MsExecResponseDTO> responseDTOS, DBTestQueue executionQueue) {
if (StringUtils.isEmpty(serialReportId)) {
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiScenarioReportMapper batchMapper = sqlSession.getMapper(ApiScenarioReportMapper.class);
// 开始并发执行
public void parallel(Map<String, RunModeDataDTO> executeQueue, RunScenarioRequest request, String serialReportId, DBTestQueue executionQueue) {
for (String reportId : executeQueue.keySet()) {
//存储报告
APIScenarioReportResult report = executeQueue.get(reportId).getReport();
batchMapper.insert(report);
responseDTOS.add(new MsExecResponseDTO(executeQueue.get(reportId).getTestId(), reportId, request.getRunMode()));
}
sqlSession.flushStatements();
if (sqlSession != null && sqlSessionFactory != null) {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
}
for (String reportId : executeQueue.keySet()) {
JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(executeQueue.get(reportId).getTestId(), StringUtils.isNotEmpty(serialReportId) ? serialReportId : reportId, request.getRunMode(), executeQueue.get(reportId).getHashTree());
RunModeDataDTO dataDTO = executeQueue.get(reportId);
JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(dataDTO.getTestId(), StringUtils.isNotEmpty(serialReportId) ? serialReportId : reportId, request.getRunMode(), null);
runRequest.setReportType(StringUtils.isNotEmpty(serialReportId) ? RunModeConstants.SET_REPORT.toString() : RunModeConstants.INDEPENDENCE.toString());
runRequest.setQueueId(executionQueue.getId());
if (request.getConfig() != null) {
@ -56,12 +31,15 @@ public class ApiScenarioParallelService {
runRequest.setPoolId(request.getConfig().getResourcePoolId());
}
runRequest.setTestPlanReportId(request.getTestPlanReportId());
runRequest.setHashTree(executeQueue.get(reportId).getHashTree());
runRequest.setPlatformUrl(executionQueue.getDetailMap().get(reportId));
runRequest.setRunType(RunModeConstants.PARALLEL.toString());
if (LoggerUtil.getLogger().isDebugEnabled()) {
LoggerUtil.debug("Scenario run-开始并发执行:" + JSON.toJSONString(request));
}
// 本地执行生成hashTree
if (request.getConfig() != null && !runRequest.getPool().isPool()) {
runRequest.setHashTree(GenerateHashTreeUtil.generateHashTree(dataDTO.getScenario(), dataDTO.getPlanEnvMap(), runRequest));
}
jMeterService.run(runRequest);
}
}

View File

@ -15,15 +15,13 @@ 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.ApiDefinitionExecResultService;
import io.metersphere.api.service.ApiExecutionQueueService;
import io.metersphere.api.service.ApiTestEnvironmentService;
import io.metersphere.api.service.TestResultService;
import io.metersphere.api.service.RemakeReportService;
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;
@ -80,8 +78,19 @@ public class ApiScenarioSerialService {
}
LoggerUtil.info("Scenario run-开始执行队列ID" + executionQueue.getReportId() + "");
try {
String reportId = StringUtils.isNotEmpty(executionQueue.getReportId()) ? executionQueue.getReportId() : queue.getReportId();
if (!StringUtils.equals(executionQueue.getRunMode(), ApiRunMode.SCENARIO.name())) {
reportId = queue.getReportId();
}
HashTree hashTree = null;
JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(queue.getTestId(), reportId, executionQueue.getRunMode(), hashTree);
runRequest.setReportType(executionQueue.getReportType());
runRequest.setPool(GenerateHashTreeUtil.isResourcePool(executionQueue.getPoolId()));
runRequest.setTestPlanReportId(executionQueue.getReportId());
runRequest.setRunType(RunModeConstants.SERIAL.toString());
runRequest.setQueueId(executionQueue.getId());
runRequest.setPoolId(executionQueue.getPoolId());
try {
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 = null;
@ -99,53 +108,30 @@ public class ApiScenarioSerialService {
if ((planEnvMap == null || planEnvMap.isEmpty()) && StringUtils.isNotEmpty(queue.getEvnMap())) {
planEnvMap = JSON.parseObject(queue.getEvnMap(), Map.class);
}
hashTree = GenerateHashTreeUtil.generateHashTree(scenario, queue.getReportId(), planEnvMap, executionQueue.getReportType());
hashTree = GenerateHashTreeUtil.generateHashTree(scenario, planEnvMap, runRequest);
} else {
Map<String, String> map = new LinkedHashMap<>();
if (StringUtils.isNotEmpty(queue.getEvnMap())) {
map = JSON.parseObject(queue.getEvnMap(), Map.class);
}
hashTree = generateHashTree(queue.getTestId(), queue.getReportId(), executionQueue.getRunMode(), map);
hashTree = generateHashTree(queue.getTestId(), map, runRequest);
}
// 更新环境变量
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()));
runRequest.setTestPlanReportId(executionQueue.getReportId());
runRequest.setRunType(RunModeConstants.SERIAL.toString());
runRequest.setQueueId(executionQueue.getId());
runRequest.setPoolId(executionQueue.getPoolId());
runRequest.setHashTree(hashTree);
if (queue != null) {
runRequest.setPlatformUrl(queue.getId());
}
// 开始执行
jMeterService.run(runRequest);
} catch (Exception e) {
LoggerUtil.error("执行终止:" + e.getMessage());
RemakeReportService remakeReportService = CommonBeanFactory.getBean(RemakeReportService.class);
remakeReportService.remake(runRequest);
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())) {
CommonBeanFactory.getBean(TestResultService.class).testEnded(dto);
} else {
ApiDefinitionExecResult apiDefinitionExecResult = apiDefinitionExecResultMapper.selectByPrimaryKey(queue.getReportId());
if (apiDefinitionExecResult != null) {
apiDefinitionExecResult.setStatus("Error");
apiDefinitionExecResultMapper.updateByPrimaryKey(apiDefinitionExecResult);
CommonBeanFactory.getBean(ApiDefinitionExecResultService.class)
.editStatus(apiDefinitionExecResult, executionQueue.getRunMode(), "Error"
, System.currentTimeMillis(), apiDefinitionExecResult.getId(), queue.getTestId());
}
}
BeanUtils.copyBean(dto, runRequest);
CommonBeanFactory.getBean(ApiExecutionQueueService.class).queueNext(dto);
LoggerUtil.error("执行终止:" + e.getMessage());
}
}
@ -156,7 +142,8 @@ public class ApiScenarioSerialService {
hashTreeUtil.mergeParamDataMap(null, envParamsMap);
}
public HashTree generateHashTree(String testId, String reportId, String runMode, Map<String, String> envMap) {
public HashTree generateHashTree(String testId, Map<String, String> envMap, JmeterRunRequestDTO runRequest) {
try {
ApiTestCaseWithBLOBs caseWithBLOBs = apiTestCaseMapper.selectByPrimaryKey(testId);
String envId = null;
if (caseWithBLOBs == null) {
@ -173,7 +160,7 @@ public class ApiScenarioSerialService {
HashTree jmeterHashTree = new HashTree();
MsTestPlan testPlan = new MsTestPlan();
testPlan.setHashTree(new LinkedList<>());
try {
MsThreadGroup group = new MsThreadGroup();
group.setLabel(caseWithBLOBs.getName());
group.setName(caseWithBLOBs.getName());
@ -185,18 +172,13 @@ public class ApiScenarioSerialService {
testPlan.getHashTree().add(group);
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), new ParameterConfig());
return jmeterHashTree;
}
} catch (Exception ex) {
ApiDefinitionExecResult apiDefinitionExecResult = apiDefinitionExecResultMapper.selectByPrimaryKey(reportId);
if (apiDefinitionExecResult != null) {
apiDefinitionExecResult.setStatus("Error");
apiDefinitionExecResultMapper.updateByPrimaryKey(apiDefinitionExecResult);
CommonBeanFactory.getBean(ApiDefinitionExecResultService.class)
.editStatus(apiDefinitionExecResult, runMode, "error"
, System.currentTimeMillis(), apiDefinitionExecResult.getId(), testId);
}
MSException.throwException(ex.getMessage());
}
RemakeReportService remakeReportService = CommonBeanFactory.getBean(RemakeReportService.class);
remakeReportService.remake(runRequest);
ResultDTO dto = new ResultDTO();
BeanUtils.copyBean(dto, runRequest);
CommonBeanFactory.getBean(ApiExecutionQueueService.class).queueNext(dto);
}
return null;
}

View File

@ -4,7 +4,6 @@ import io.metersphere.api.dto.definition.BatchRunDefinitionRequest;
import io.metersphere.base.domain.ApiDefinitionExecResult;
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
import io.metersphere.base.domain.TestPlanApiCase;
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
import io.metersphere.base.mapper.ApiTestCaseMapper;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.TriggerMode;
@ -40,7 +39,7 @@ public class ApiDefinitionExecResultUtil {
return apiResult;
}
public static ApiDefinitionExecResult addResult(BatchRunDefinitionRequest request, TestPlanApiCase key, String status, ApiDefinitionExecResultMapper batchMapper) {
public static ApiDefinitionExecResult addResult(BatchRunDefinitionRequest request, TestPlanApiCase key, String status) {
ApiDefinitionExecResult apiResult = new ApiDefinitionExecResult();
apiResult.setId(UUID.randomUUID().toString());
apiResult.setCreateTime(System.currentTimeMillis());
@ -68,7 +67,6 @@ public class ApiDefinitionExecResultUtil {
apiResult.setType(ApiRunMode.API_PLAN.name());
apiResult.setStatus(status);
apiResult.setContent(request.getPlanReportId());
batchMapper.insert(apiResult);
return apiResult;
}

View File

@ -10,15 +10,19 @@ import io.metersphere.api.dto.EnvironmentType;
import io.metersphere.api.dto.definition.request.*;
import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
import io.metersphere.api.jmeter.ResourcePoolCalculation;
import io.metersphere.api.service.ApiExecutionQueueService;
import io.metersphere.api.service.RemakeReportService;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.base.domain.TestResourcePool;
import io.metersphere.base.mapper.TestResourcePoolMapper;
import io.metersphere.commons.constants.ResourcePoolTypeEnum;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.constants.RunModeConstants;
import io.metersphere.dto.JmeterRunRequestDTO;
import io.metersphere.dto.JvmInfoDTO;
import io.metersphere.dto.ResultDTO;
import io.metersphere.dto.RunModeConfigDTO;
import io.metersphere.plugin.core.MsTestElement;
import io.metersphere.service.EnvironmentGroupProjectService;
@ -120,14 +124,14 @@ public class GenerateHashTreeUtil {
}
}
public static HashTree generateHashTree(ApiScenarioWithBLOBs item, String reportId, Map<String, String> planEnvMap, String reportType) {
public static HashTree generateHashTree(ApiScenarioWithBLOBs item, Map<String, String> planEnvMap, JmeterRunRequestDTO runRequest) {
HashTree jmeterHashTree = new HashTree();
MsTestPlan testPlan = new MsTestPlan();
testPlan.setHashTree(new LinkedList<>());
try {
MsThreadGroup group = new MsThreadGroup();
group.setLabel(item.getName());
group.setName(reportId);
group.setName(runRequest.getReportId());
MsScenario scenario = JSONObject.parseObject(item.getScenarioDefinition(), MsScenario.class);
group.setOnSampleError(scenario.getOnSampleError());
if (planEnvMap != null && planEnvMap.size() > 0) {
@ -144,11 +148,15 @@ public class GenerateHashTreeUtil {
group.setHashTree(scenarios);
testPlan.getHashTree().add(group);
} catch (Exception ex) {
MSException.throwException(ex.getMessage());
RemakeReportService remakeReportService = CommonBeanFactory.getBean(RemakeReportService.class);
remakeReportService.remake(runRequest);
ResultDTO dto = new ResultDTO();
BeanUtils.copyBean(dto, runRequest);
CommonBeanFactory.getBean(ApiExecutionQueueService.class).queueNext(dto);
}
ParameterConfig config = new ParameterConfig();
config.setScenarioId(item.getId());
config.setReportType(reportType);
config.setReportType(runRequest.getReportType());
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), config);
return jmeterHashTree;
}

View File

@ -3,7 +3,6 @@ package io.metersphere.api.jmeter;
import io.metersphere.api.exec.queue.PoolExecBlockingQueueUtil;
import io.metersphere.api.service.ApiExecutionQueueService;
import io.metersphere.api.service.MsResultService;
import io.metersphere.api.service.TestResultService;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.utils.CommonBeanFactory;
@ -21,7 +20,7 @@ public class APISingleResultListener extends MsExecListener {
@Override
public void handleTeardownTest(ResultDTO dto, Map<String, Object> kafkaConfig) {
LoggerUtil.info("处理单条执行结果报告【" + dto.getReportId() + " 】,资源【 " + dto.getTestId() + "");
dto.setConsole(CommonBeanFactory.getBean(MsResultService.class).getJmeterLogger(dto.getReportId()));
dto.setConsole(FixedCapacityUtils.getJmeterLogger(dto.getReportId()));
CommonBeanFactory.getBean(TestResultService.class).saveResults(dto);
// 更新报告最后接收到请求的时间
@ -38,7 +37,7 @@ public class APISingleResultListener extends MsExecListener {
LoggerUtil.info("进入TEST-END处理报告【" + dto.getReportId() + " 】整体执行完成;" + dto.getRunMode());
// 全局并发队列
PoolExecBlockingQueueUtil.offer(dto.getReportId());
dto.setConsole(CommonBeanFactory.getBean(MsResultService.class).getJmeterLogger(dto.getReportId()));
dto.setConsole(FixedCapacityUtils.getJmeterLogger(dto.getReportId()));
// 整体执行结束更新资源状态
CommonBeanFactory.getBean(TestResultService.class).testEnded(dto);

View File

@ -1,11 +1,14 @@
package io.metersphere.api.jmeter;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
public class FixedCapacityUtils {
public static Map<Long, StringBuffer> fixedCapacityCache = Collections.synchronizedMap(new LRUHashMap<>());
public final static Map<String, Long> jmeterLogTask = new HashMap<>();
public static StringBuffer get(Long key) {
return fixedCapacityCache.get(key);
@ -28,4 +31,25 @@ public class FixedCapacityUtils {
return size() > capacity;
}
}
public static String getJmeterLogger(String testId) {
try {
Long startTime = FixedCapacityUtils.jmeterLogTask.get(testId);
if (startTime == null) {
startTime = FixedCapacityUtils.jmeterLogTask.get("[" + testId + "]");
}
if (startTime == null) {
startTime = System.currentTimeMillis();
}
Long endTime = System.currentTimeMillis();
Long finalStartTime = startTime;
String logMessage = FixedCapacityUtils.fixedCapacityCache.entrySet().stream()
.filter(map -> map.getKey() > finalStartTime && map.getKey() < endTime)
.map(map -> map.getValue()).collect(Collectors.joining());
return logMessage;
} catch (Exception e) {
return "";
}
}
}

View File

@ -2,7 +2,6 @@ package io.metersphere.api.jmeter;
import io.metersphere.api.service.ApiExecutionQueueService;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.utils.LoggerUtil;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@ -15,7 +14,6 @@ public class FixedTask {
if (queueService == null) {
queueService = CommonBeanFactory.getBean(ApiExecutionQueueService.class);
}
LoggerUtil.info("进入超时处理");
queueService.timeOut();
}
}

View File

@ -17,6 +17,7 @@ import io.metersphere.performance.engine.Engine;
import io.metersphere.performance.engine.EngineFactory;
import io.metersphere.service.SystemParameterService;
import io.metersphere.utils.LoggerUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.save.SaveService;
import org.apache.jmeter.testelement.TestElement;
@ -25,7 +26,6 @@ import org.apache.jorphan.collections.HashTree;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import javax.annotation.PostConstruct;
@ -34,7 +34,6 @@ import java.io.File;
import java.util.List;
@Service
@Transactional(rollbackFor = Exception.class)
public class JMeterService {
public static final String BASE_URL = "http://%s:%d";
@Resource
@ -77,11 +76,11 @@ public class JMeterService {
private void runLocal(JmeterRunRequestDTO request) {
init();
if (!MessageCache.jmeterLogTask.containsKey(request.getReportId())) {
MessageCache.jmeterLogTask.put(request.getReportId(), System.currentTimeMillis());
if (!FixedCapacityUtils.jmeterLogTask.containsKey(request.getReportId())) {
FixedCapacityUtils.jmeterLogTask.put(request.getReportId(), System.currentTimeMillis());
}
LoggerUtil.debug("监听MessageCache.tasks当前容量" + MessageCache.jmeterLogTask.size());
LoggerUtil.debug("监听MessageCache.tasks当前容量" + FixedCapacityUtils.jmeterLogTask.size());
if (request.isDebug() && !StringUtils.equalsAny(request.getRunMode(), ApiRunMode.DEFINITION.name())) {
LoggerUtil.debug("为请求 [ " + request.getReportId() + " ] 添加同步接收结果 Listener");
JMeterBase.addSyncListener(request, request.getHashTree(), APISingleResultListener.class.getCanonicalName());
@ -135,9 +134,16 @@ public class JMeterService {
}
}
private void send(JmeterRunRequestDTO request) {
private synchronized void send(JmeterRunRequestDTO request) {
try {
List<JvmInfoDTO> resources = GenerateHashTreeUtil.setPoolResource(request.getPoolId());
if (CollectionUtils.isEmpty(resources)) {
LoggerUtil.info("未获取到资源池,请检查配置【系统设置-系统-测试资源池】");
RemakeReportService remakeReportService = CommonBeanFactory.getBean(RemakeReportService.class);
remakeReportService.remake(request);
return;
}
int index = (int) (Math.random() * resources.size());
JvmInfoDTO jvmInfoDTO = resources.get(index);
TestResourceDTO testResource = jvmInfoDTO.getTestResource();
@ -150,7 +156,6 @@ public class JMeterService {
String uri = String.format(BASE_URL + "/jmeter/api/start", nodeIp, port);
LoggerUtil.info("开始发送请求【 " + request.getReportId() + " 】,资源【 " + request.getTestId() + "" + uri + " 节点执行");
ResponseEntity<String> result = restTemplate.postForEntity(uri, request, String.class);
if (result == null || !StringUtils.equals("SUCCESS", result.getBody())) {
RemakeReportService remakeReportService = CommonBeanFactory.getBean(RemakeReportService.class);
@ -168,14 +173,40 @@ public class JMeterService {
public void run(JmeterRunRequestDTO request) {
CommonBeanFactory.getBean(ExecThreadPoolExecutor.class).addTask(request);
}
public void addQueue(JmeterRunRequestDTO request) {
if (request.getPool().isPool()) {
this.runNode(request);
} else {
CommonBeanFactory.getBean(ExecThreadPoolExecutor.class).addTask(request);
}
}
public void addQueue(JmeterRunRequestDTO request) {
this.runLocal(request);
}
public boolean getRunningQueue(String poolId, String reportId) {
try {
List<JvmInfoDTO> resources = GenerateHashTreeUtil.setPoolResource(poolId);
if (CollectionUtils.isEmpty(resources)) {
return false;
}
boolean isRunning = false;
for (JvmInfoDTO jvmInfoDTO : resources) {
TestResourceDTO testResource = jvmInfoDTO.getTestResource();
String configuration = testResource.getConfiguration();
NodeDTO node = JSON.parseObject(configuration, NodeDTO.class);
String nodeIp = node.getIp();
Integer port = node.getPort();
String uri = String.format(BASE_URL + "/jmeter/get/running/queue/" + reportId, nodeIp, port);
ResponseEntity<Boolean> result = restTemplate.getForEntity(uri, Boolean.class);
if (result != null && result.getBody()) {
isRunning = true;
break;
}
}
return isRunning;
} catch (Exception e) {
return false;
}
}
}

View File

@ -1,10 +1,12 @@
package io.metersphere.api.jmeter;
import io.metersphere.api.exec.queue.ExecThreadPoolExecutor;
import io.metersphere.api.exec.queue.PoolExecBlockingQueueUtil;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.LogUtil;
import org.apache.commons.lang3.StringUtils;
public class JmeterThreadUtils {
private final static String THREAD_SPLIT = " ";
public static String stop(String name) {
ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
@ -24,6 +26,15 @@ public class JmeterThreadUtils {
}
public static boolean isRunning(String reportId, String testId) {
if (StringUtils.isEmpty(reportId)) {
return false;
}
if (PoolExecBlockingQueueUtil.queue.containsKey(reportId)) {
return true;
}
if (CommonBeanFactory.getBean(ExecThreadPoolExecutor.class).check(reportId)) {
return true;
}
ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
int noThreads = currentGroup.activeCount();
Thread[] lstThreads = new Thread[noThreads];

View File

@ -1,19 +0,0 @@
package io.metersphere.api.jmeter;
import javax.websocket.Session;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class MessageCache {
public final static ConcurrentHashMap<String, Session> reportCache = new ConcurrentHashMap<>();
public final static Map<String, Long> jmeterLogTask = new HashMap<>();
// 定时任务报告
public final static List<String> jobReportCache = new LinkedList<>();
public static int corePoolSize = 10;
}

View File

@ -23,7 +23,6 @@ import io.metersphere.api.dto.RequestResultExpandDTO;
import io.metersphere.api.dto.RunningParamKeys;
import io.metersphere.api.exec.queue.PoolExecBlockingQueueUtil;
import io.metersphere.api.exec.utils.ResultParseUtil;
import io.metersphere.api.service.MsResultService;
import io.metersphere.commons.utils.*;
import io.metersphere.dto.RequestResult;
import io.metersphere.jmeter.JMeterBase;
@ -156,7 +155,7 @@ public class MsDebugListener extends AbstractListenerElement implements SampleLi
dto.setReportId("send." + this.getName());
dto.setToReport(this.getName());
String console = CommonBeanFactory.getBean(MsResultService.class).getJmeterLogger(this.getName());
String console = FixedCapacityUtils.getJmeterLogger(this.getName());
if (StringUtils.isNotEmpty(requestResult.getName()) && requestResult.getName().startsWith("Transaction=")) {
requestResult.getSubRequestResults().forEach(transactionResult -> {
transactionResult.getResponseResult().setConsole(console);

View File

@ -7,7 +7,6 @@ import io.metersphere.base.domain.TestResourcePool;
import io.metersphere.base.domain.TestResourcePoolExample;
import io.metersphere.base.mapper.TestResourceMapper;
import io.metersphere.base.mapper.TestResourcePoolMapper;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.dto.JvmInfoDTO;
import io.metersphere.dto.NodeDTO;
@ -71,9 +70,6 @@ public class ResourcePoolCalculation {
availableNodes.add(nodeJvm);
}
}
if (CollectionUtils.isEmpty(availableNodes)) {
MSException.throwException("未获取到资源池,请检查配置【系统设置-系统-测试资源池】");
}
return availableNodes;
}
}

View File

@ -9,8 +9,6 @@ import io.metersphere.api.dto.automation.parse.ScenarioImport;
import io.metersphere.api.dto.automation.parse.ScenarioImportParserFactory;
import io.metersphere.api.dto.datacount.ApiDataCountResult;
import io.metersphere.api.dto.datacount.ApiMethodUrlDTO;
import io.metersphere.api.dto.definition.ApiDefinitionResult;
import io.metersphere.api.dto.definition.ApiTestCaseInfo;
import io.metersphere.api.dto.definition.RunDefinitionRequest;
import io.metersphere.api.dto.definition.request.*;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
@ -106,10 +104,6 @@ public class ApiAutomationService {
@Resource
private EsbApiParamService esbApiParamService;
@Resource
private ApiTestCaseService apiTestCaseService;
@Resource
private ApiDefinitionService apiDefinitionService;
@Resource
private ApiTestEnvironmentMapper apiTestEnvironmentMapper;
@Resource
private UserMapper userMapper;
@ -137,7 +131,8 @@ public class ApiAutomationService {
private ApiScenarioExecuteService apiScenarioExecuteService;
@Resource
private ExtProjectVersionMapper extProjectVersionMapper;
@Resource
private MsHashTreeService hashTreeService;
private ThreadLocal<Long> currentScenarioOrder = new ThreadLocal<>();
@ -680,126 +675,16 @@ public class ApiAutomationService {
}
}
public ApiScenarioDTO getApiScenario(String id) {
return extApiScenarioMapper.selectById(id);
}
public ApiScenarioDTO getNewApiScenario(String id) {
ApiScenarioDTO scenarioWithBLOBs = extApiScenarioMapper.selectById(id);
if (scenarioWithBLOBs != null && StringUtils.isNotEmpty(scenarioWithBLOBs.getScenarioDefinition())) {
JSONObject element = JSON.parseObject(scenarioWithBLOBs.getScenarioDefinition());
this.dataFormatting(element);
hashTreeService.dataFormatting(element);
scenarioWithBLOBs.setScenarioDefinition(JSON.toJSONString(element));
}
return scenarioWithBLOBs;
}
private final static List<String> requests = new ArrayList<String>() {{
this.add("HTTPSamplerProxy");
this.add("DubboSampler");
this.add("JDBCSampler");
this.add("TCPSampler");
}};
private void setElement(JSONObject element, Integer num, Boolean enable, String versionName, Boolean versionEnable) {
element.put("num", num);
element.put("enable", enable == null ? false : enable);
element.put("versionName", versionName);
element.put("versionEnable", versionEnable == null ? false : versionEnable);
}
private JSONObject setRequest(JSONObject element) {
boolean enable = element.getBoolean("enable");
boolean isExist = false;
if (StringUtils.equalsIgnoreCase(element.getString("refType"), "CASE")) {
ApiTestCaseInfo apiTestCase = apiTestCaseService.get(element.getString("id"));
if (apiTestCase != null) {
if (StringUtils.equalsIgnoreCase(element.getString("referenced"), "REF")) {
JSONObject refElement = JSON.parseObject(apiTestCase.getRequest());
ElementUtil.dataFormatting(refElement);
JSONArray array = refElement.getJSONArray("hashTree");
BeanUtils.copyBean(element, refElement);
if (array != null) {
ElementUtil.mergeHashTree(element, refElement.getJSONArray("hashTree"));
}
element.put("referenced", "REF");
element.put("disabled", true);
element.put("name", apiTestCase.getName());
}
element.put("id", apiTestCase.getId());
isExist = true;
this.setElement(element, apiTestCase.getNum(), enable, apiTestCase.getVersionName(), apiTestCase.getVersionEnable());
}
} else {
ApiDefinitionResult definitionWithBLOBs = apiDefinitionService.getById(element.getString("id"));
if (definitionWithBLOBs != null) {
element.put("id", definitionWithBLOBs.getId());
this.setElement(element, definitionWithBLOBs.getNum(), enable, definitionWithBLOBs.getVersionName(), definitionWithBLOBs.getVersionEnable());
isExist = true;
}
}
if (!isExist) {
if (StringUtils.equalsIgnoreCase(element.getString("referenced"), "REF")) {
element.put("enable", false);
}
element.put("num", "");
}
return element;
}
private JSONObject setRefScenario(JSONObject element) {
boolean enable = element.containsKey("enable") ? element.getBoolean("enable") : true;
ApiScenarioDTO scenarioWithBLOBs = extApiScenarioMapper.selectById(element.getString("id"));
if (scenarioWithBLOBs != null && StringUtils.isNotEmpty(scenarioWithBLOBs.getScenarioDefinition())) {
boolean environmentEnable = element.containsKey("environmentEnable")
? element.getBoolean("environmentEnable") : false;
if (StringUtils.equalsIgnoreCase(element.getString("referenced"), "REF")) {
element = JSON.parseObject(scenarioWithBLOBs.getScenarioDefinition());
element.put("referenced", "REF");
element.put("name", scenarioWithBLOBs.getName());
}
element.put("id", scenarioWithBLOBs.getId());
element.put("environmentEnable", environmentEnable);
this.setElement(element, scenarioWithBLOBs.getNum(), enable, scenarioWithBLOBs.getVersionName(), scenarioWithBLOBs.getVersionEnable());
} else {
if (StringUtils.equalsIgnoreCase(element.getString("referenced"), "REF")) {
element.put("enable", false);
}
element.put("num", "");
}
return element;
}
public void dataFormatting(JSONArray hashTree) {
for (int i = 0; i < hashTree.size(); i++) {
JSONObject element = hashTree.getJSONObject(i);
if (element != null && StringUtils.equalsIgnoreCase(element.getString("type"), "scenario")) {
element = this.setRefScenario(element);
hashTree.set(i, element);
} else if (element != null && requests.contains(element.getString("type"))) {
element = this.setRequest(element);
hashTree.set(i, element);
}
if (element.containsKey("hashTree")) {
JSONArray elementJSONArray = element.getJSONArray("hashTree");
dataFormatting(elementJSONArray);
}
}
}
public void dataFormatting(JSONObject element) {
if (element != null && StringUtils.equalsIgnoreCase(element.getString("type"), "scenario")) {
element = this.setRefScenario(element);
} else if (element != null && requests.contains(element.getString("type"))) {
element = this.setRequest(element);
}
if (element != null && element.containsKey("hashTree")) {
JSONArray elementJSONArray = element.getJSONArray("hashTree");
dataFormatting(elementJSONArray);
}
}
public String setDomain(ApiScenarioEnvRequest request) {
Boolean enable = request.getEnvironmentEnable();
String scenarioDefinition = request.getDefinition();
@ -1179,7 +1064,6 @@ public class ApiAutomationService {
apiScenarioMapper.updateByExampleSelective(
apiScenarioWithBLOBs,
apiScenarioExample);
// apiScenarioReferenceIdService.saveByApiScenario(apiScenarioWithBLOBs);
}
public void bathEditEnv(ApiScenarioBatchRequest request) {
@ -1440,45 +1324,6 @@ public class ApiAutomationService {
return apiImport;
}
private void setHashTree(JSONArray hashTree) {
// 将引用转成复制
if (CollectionUtils.isNotEmpty(hashTree)) {
for (int i = 0; i < hashTree.size(); i++) {
JSONObject object = (JSONObject) hashTree.get(i);
String referenced = object.getString("referenced");
if (StringUtils.isNotBlank(referenced) && StringUtils.equals(referenced, "REF")) {
// 检测引用对象是否存在若果不存在则改成复制对象
String refType = object.getString("refType");
if (StringUtils.isNotEmpty(refType)) {
if (refType.equals("CASE")) {
ApiTestCaseWithBLOBs bloBs = apiTestCaseService.get(object.getString("id"));
if (bloBs != null) {
object = JSON.parseObject(bloBs.getRequest());
object.put("id", bloBs.getId());
object.put("name", bloBs.getName());
hashTree.set(i, object);
}
} else {
ApiScenarioWithBLOBs bloBs = apiScenarioMapper.selectByPrimaryKey(object.getString("id"));
if (bloBs != null) {
object = JSON.parseObject(bloBs.getScenarioDefinition());
hashTree.set(i, object);
}
}
} else if ("scenario".equals(object.getString("type"))) {
ApiScenarioWithBLOBs bloBs = apiScenarioMapper.selectByPrimaryKey(object.getString("id"));
if (bloBs != null) {
object = JSON.parseObject(bloBs.getScenarioDefinition());
hashTree.set(i, object);
}
}
}
if (object != null && CollectionUtils.isNotEmpty(object.getJSONArray("hashTree"))) {
setHashTree(object.getJSONArray("hashTree"));
}
}
}
}
private List<ApiScenarioWithBLOBs> getExportResult(ApiScenarioBatchRequest request) {
ServiceUtils.getSelectAllIds(request, request.getCondition(),
@ -1493,7 +1338,7 @@ public class ApiAutomationService {
JSONObject scenario = JSONObject.parseObject(item.getScenarioDefinition());
JSONArray hashTree = scenario.getJSONArray("hashTree");
if (hashTree != null) {
setHashTree(hashTree);
hashTreeService.setHashTree(hashTree);
scenario.put("hashTree", hashTree);
}
item.setScenarioDefinition(JSON.toJSONString(scenario));
@ -1717,78 +1562,16 @@ public class ApiAutomationService {
public List<ApiMethodUrlDTO> parseUrl(ApiScenarioWithBLOBs scenario) {
List<ApiMethodUrlDTO> urlList = new ArrayList<>();
try {
String scenarioDefinition = scenario.getScenarioDefinition();
JSONObject scenarioObj = JSONObject.parseObject(scenarioDefinition);
List<ApiMethodUrlDTO> stepUrlList = this.getMethodUrlDTOByHashTreeJsonObj(scenarioObj);
List<ApiMethodUrlDTO> stepUrlList = hashTreeService.getMethodUrlDTOByHashTreeJsonObj(scenarioObj);
if (CollectionUtils.isNotEmpty(stepUrlList)) {
Collection unionList = CollectionUtils.union(urlList, stepUrlList);
urlList = new ArrayList<>(unionList);
}
} catch (Exception e) {
LogUtil.error(e);
}
return urlList;
}
private List<ApiMethodUrlDTO> getMethodUrlDTOByHashTreeJsonObj(JSONObject obj) {
List<ApiMethodUrlDTO> returnList = new ArrayList<>();
if (obj != null && obj.containsKey("hashTree")) {
JSONArray hashArr = obj.getJSONArray("hashTree");
for (int i = 0; i < hashArr.size(); i++) {
JSONObject elementObj = hashArr.getJSONObject(i);
if (elementObj == null) {
continue;
}
if (elementObj.containsKey("url") && elementObj.containsKey("method")) {
String url = elementObj.getString("url");
String method = elementObj.getString("method");
ApiMethodUrlDTO dto = new ApiMethodUrlDTO(url, method);
if (!returnList.contains(dto)) {
returnList.add(dto);
}
}
if (elementObj.containsKey("path") && elementObj.containsKey("method")) {
String path = elementObj.getString("path");
String method = elementObj.getString("method");
ApiMethodUrlDTO dto = new ApiMethodUrlDTO(path, method);
if (!returnList.contains(dto)) {
returnList.add(dto);
}
}
if (elementObj.containsKey("id") && elementObj.containsKey("refType")) {
String refType = elementObj.getString("refType");
String id = elementObj.getString("id");
if (StringUtils.equals("CASE", refType)) {
ApiDefinition apiDefinition = apiTestCaseService.findApiUrlAndMethodById(id);
if (apiDefinition != null) {
ApiMethodUrlDTO dto = new ApiMethodUrlDTO(apiDefinition.getPath(), apiDefinition.getMethod());
if (!returnList.contains(dto)) {
returnList.add(dto);
}
}
} else if (StringUtils.equals("API", refType)) {
ApiDefinition apiDefinition = apiDefinitionService.selectUrlAndMethodById(id);
if (apiDefinition != null) {
ApiMethodUrlDTO dto = new ApiMethodUrlDTO(apiDefinition.getPath(), apiDefinition.getMethod());
if (!returnList.contains(dto)) {
returnList.add(dto);
}
}
}
}
List<ApiMethodUrlDTO> stepUrlList = this.getMethodUrlDTOByHashTreeJsonObj(elementObj);
if (CollectionUtils.isNotEmpty(stepUrlList)) {
Collection unionList = CollectionUtils.union(returnList, stepUrlList);
returnList = new ArrayList<>(unionList);
}
}
}
return returnList;
}
public ScenarioEnv getApiScenarioProjectId(String id) {
ApiScenarioWithBLOBs scenario = apiScenarioMapper.selectByPrimaryKey(id);
@ -1926,7 +1709,6 @@ public class ApiAutomationService {
return returnList;
} else {
apiScenarioList.forEach(item -> {
String testName = item.getName();
MsTestPlan testPlan = new MsTestPlan();
testPlan.setHashTree(new LinkedList<>());
JmxInfoDTO dto = apiTestService.updateJmxString(generateJmx(item), item.getProjectId());

View File

@ -0,0 +1,34 @@
package io.metersphere.api.service;
import io.metersphere.base.domain.ApiDefinitionExecResult;
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.Map;
@Service
public class ApiCaseResultService {
@Resource
private SqlSessionFactory sqlSessionFactory;
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public void batchSave(Map<String, ApiDefinitionExecResult> executeQueue) {
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiDefinitionExecResultMapper batchMapper = sqlSession.getMapper(ApiDefinitionExecResultMapper.class);
for (String testId : executeQueue.keySet()) {
ApiDefinitionExecResult report = executeQueue.get(testId);
batchMapper.insert(report);
}
sqlSession.flushStatements();
if (sqlSession != null && sqlSessionFactory != null) {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
}
}

View File

@ -7,6 +7,7 @@ import io.metersphere.api.dto.datacount.ExecutedCaseInfoResult;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanMapper;
import io.metersphere.commons.constants.*;
import io.metersphere.commons.utils.DateUtils;
import io.metersphere.commons.utils.LogUtil;
@ -21,35 +22,29 @@ import io.metersphere.track.dto.TestPlanDTO;
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
import io.metersphere.track.request.testcase.TrackCount;
import io.metersphere.track.service.TestCaseReviewApiCaseService;
import io.metersphere.track.service.TestPlanApiCaseService;
import io.metersphere.track.service.TestPlanService;
import io.metersphere.track.service.TestPlanTestCaseService;
import io.metersphere.utils.LoggerUtil;
import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
public class ApiDefinitionExecResultService {
Logger testPlanLog = LoggerFactory.getLogger("testPlanExecuteLog");
@Resource
private ApiDefinitionExecResultMapper apiDefinitionExecResultMapper;
@Resource
private ExtApiDefinitionExecResultMapper extApiDefinitionExecResultMapper;
@Resource
private TestPlanApiCaseService testPlanApiCaseService;
private TestPlanApiCaseMapper testPlanApiCaseMapper;
@Resource
private TestPlanService testPlanService;
private ExtTestPlanMapper extTestPlanMapper;
@Resource
private ApiTestCaseMapper apiTestCaseMapper;
@Resource
@ -68,11 +63,6 @@ public class ApiDefinitionExecResultService {
private UserMapper userMapper;
public void saveApiResult(List<RequestResult> requestResults, ResultDTO dto) {
boolean isFirst = true;
int count = requestResults.stream()
.filter(item -> !StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_"))
.collect(Collectors.toList()).size();
LoggerUtil.info("接收到API/CASE执行结果【 " + requestResults.size() + "");
for (RequestResult item : requestResults) {
@ -81,12 +71,11 @@ public class ApiDefinitionExecResultService {
item.getResponseResult().setResponseTime((item.getEndTime() - item.getStartTime()));
}
if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) {
ApiDefinitionExecResult result = this.save(item, dto.getReportId(), dto.getConsole(), count, dto.getRunMode(), dto.getTestId(), isFirst);
ApiDefinitionExecResult result = this.save(item, dto.getReportId(), dto.getConsole(), dto.getRunMode(), dto.getTestId());
if (result != null) {
// 发送通知
sendNotice(result);
}
isFirst = false;
}
}
}
@ -136,18 +125,26 @@ public class ApiDefinitionExecResultService {
}
}
public void setExecResult(String id, String status, Long time) {
TestPlanApiCase apiCase = new TestPlanApiCase();
apiCase.setId(id);
apiCase.setStatus(status);
apiCase.setUpdateTime(time);
testPlanApiCaseMapper.updateByPrimaryKeySelective(apiCase);
}
public void editStatus(ApiDefinitionExecResult saveResult, String type, String status, Long time, String reportId, String testId) {
String name = testId;
String version = "";
if (StringUtils.equalsAnyIgnoreCase(type, ApiRunMode.API_PLAN.name(), ApiRunMode.SCHEDULE_API_PLAN.name(), ApiRunMode.JENKINS_API_PLAN.name(), ApiRunMode.MANUAL_PLAN.name())) {
TestPlanApiCase testPlanApiCase = testPlanApiCaseService.getById(testId);
TestPlanApiCase testPlanApiCase = testPlanApiCaseMapper.selectByPrimaryKey(testId);
ApiTestCaseWithBLOBs caseWithBLOBs = null;
if (testPlanApiCase != null) {
testPlanApiCaseService.setExecResult(testId, status, time);
this.setExecResult(testId, status, time);
caseWithBLOBs = apiTestCaseMapper.selectByPrimaryKey(testPlanApiCase.getApiCaseId());
testPlanApiCase.setStatus(status);
testPlanApiCase.setUpdateTime(System.currentTimeMillis());
testPlanApiCaseService.updateByPrimaryKeySelective(testPlanApiCase);
testPlanApiCaseMapper.updateByPrimaryKeySelective(testPlanApiCase);
if (LoggerUtil.getLogger().isDebugEnabled()) {
LoggerUtil.debug("更新测试计划用例【 " + testPlanApiCase.getId() + "");
}
@ -198,22 +195,14 @@ public class ApiDefinitionExecResultService {
* 定时任务时userID要改为定时任务中的用户
*/
public void saveApiResultByScheduleTask(List<RequestResult> requestResults, ResultDTO dto) {
boolean isFirst = true;
int countExpectProcessResultCount = 0;
if (CollectionUtils.isNotEmpty(requestResults)) {
for (RequestResult resultItem : requestResults) {
if (!StringUtils.startsWithAny(resultItem.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) {
countExpectProcessResultCount++;
}
}
LoggerUtil.info("接收到定时任务执行结果【 " + requestResults.size() + "");
for (RequestResult item : requestResults) {
if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) {
//对响应内容进行进一步解析如果有附加信息比如误报库信息则根据附加信息内的数据进行其他判读
RequestResultExpandDTO expandDTO = ResponseUtil.parseByRequestResult(item);
ApiDefinitionExecResult reportResult = this.save(item, dto.getReportId(), dto.getConsole(), countExpectProcessResultCount, dto.getRunMode(), dto.getTestId(), isFirst);
ApiDefinitionExecResult reportResult = this.save(item, dto.getReportId(), dto.getConsole(), dto.getRunMode(), dto.getTestId());
String status = item.isSuccess() ? "success" : "error";
if (reportResult != null) {
status = reportResult.getStatus();
@ -222,17 +211,16 @@ public class ApiDefinitionExecResultService {
status = expandDTO.getStatus();
}
if (StringUtils.equalsAny(dto.getRunMode(), ApiRunMode.SCHEDULE_API_PLAN.name(), ApiRunMode.JENKINS_API_PLAN.name())) {
TestPlanApiCase apiCase = testPlanApiCaseService.getById(dto.getTestId());
TestPlanApiCase apiCase = testPlanApiCaseMapper.selectByPrimaryKey(dto.getTestId());
if (apiCase != null) {
apiCase.setStatus(status);
apiCase.setUpdateTime(System.currentTimeMillis());
testPlanApiCaseService.updateByPrimaryKeySelective(apiCase);
testPlanApiCaseMapper.updateByPrimaryKeySelective(apiCase);
}
} else {
testPlanApiCaseService.setExecResult(dto.getTestId(), status, item.getStartTime());
this.setExecResult(dto.getTestId(), status, item.getStartTime());
testCaseReviewApiCaseService.setExecResult(dto.getTestId(), status, item.getStartTime());
}
isFirst = false;
}
}
}
@ -243,7 +231,7 @@ public class ApiDefinitionExecResultService {
if (StringUtils.isNotEmpty(dto.getReportId())) {
apiIdResultMap.put(dto.getReportId(), status);
}
testPlanLog.info("TestPlanReportId[" + dto.getTestPlanReportId() + "] APICASE OVER. API CASE STATUS:" + JSONObject.toJSONString(apiIdResultMap));
LoggerUtil.info("TestPlanReportId[" + dto.getTestPlanReportId() + "] APICASE OVER. API CASE STATUS:" + JSONObject.toJSONString(apiIdResultMap));
}
/**
@ -251,7 +239,7 @@ public class ApiDefinitionExecResultService {
*/
public void updateTestCaseStates(String testPlanApiCaseId) {
try {
TestPlanApiCase testPlanApiCase = testPlanApiCaseService.getById(testPlanApiCaseId);
TestPlanApiCase testPlanApiCase = testPlanApiCaseMapper.selectByPrimaryKey(testPlanApiCaseId);
if (testPlanApiCase == null) return;
ApiTestCaseWithBLOBs apiTestCase = apiTestCaseService.get(testPlanApiCase.getApiCaseId());
testPlanTestCaseService.updateTestCaseStates(apiTestCase.getId(), apiTestCase.getName(), testPlanApiCase.getTestPlanId(), TrackCount.TESTCASE);
@ -322,7 +310,7 @@ public class ApiDefinitionExecResultService {
} else if ("load".equals(item.getCaseType())) {
planRequest.setLoadId(item.getTestCaseID());
}
List<TestPlanDTO> dtoList = testPlanService.selectTestPlanByRelevancy(planRequest);
List<TestPlanDTO> dtoList = extTestPlanMapper.selectTestPlanByRelevancy(planRequest);
item.setTestPlanDTOList(dtoList);
returnList.add(item);
} else {
@ -334,7 +322,7 @@ public class ApiDefinitionExecResultService {
}
}
private ApiDefinitionExecResult save(RequestResult item, String reportId, String console, int expectProcessResultCount, String type, String testId, boolean isFirst) {
private ApiDefinitionExecResult save(RequestResult item, String reportId, String console, String type, String testId) {
if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) {
ApiDefinitionExecResult saveResult = apiDefinitionExecResultMapper.selectByPrimaryKey(reportId);
if (saveResult == null) {

View File

@ -5,6 +5,8 @@ import io.metersphere.api.dto.RunModeDataDTO;
import io.metersphere.api.dto.automation.ScenarioStatus;
import io.metersphere.api.exec.queue.DBTestQueue;
import io.metersphere.api.exec.scenario.ApiScenarioSerialService;
import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.api.jmeter.JmeterThreadUtils;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
import io.metersphere.base.mapper.ApiExecutionQueueDetailMapper;
@ -13,6 +15,7 @@ import io.metersphere.base.mapper.ApiScenarioReportMapper;
import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper;
import io.metersphere.base.mapper.ext.ExtApiExecutionQueueMapper;
import io.metersphere.base.mapper.ext.ExtApiScenarioReportMapper;
import io.metersphere.commons.constants.APITestStatus;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.TestPlanReportStatus;
import io.metersphere.commons.utils.BeanUtils;
@ -23,12 +26,15 @@ import io.metersphere.dto.RunModeConfigDTO;
import io.metersphere.track.service.TestPlanReportService;
import io.metersphere.utils.LoggerUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.*;
@ -54,10 +60,12 @@ public class ApiExecutionQueueService {
private ExtApiDefinitionExecResultMapper extApiDefinitionExecResultMapper;
@Resource
private ExtApiScenarioReportMapper extApiScenarioReportMapper;
@Resource
private JMeterService jMeterService;
@Resource
private ExtApiExecutionQueueMapper extApiExecutionQueueMapper;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public DBTestQueue add(Object runObj, String poolId, String type, String reportId, String reportType, String runMode, RunModeConfigDTO config) {
ApiExecutionQueue executionQueue = new ApiExecutionQueue();
executionQueue.setId(UUID.randomUUID().toString());
@ -237,13 +245,16 @@ public class ApiExecutionQueueService {
long count = executionQueueDetailMapper.countByExample(queueDetailExample);
if (count == 0) {
queueMapper.deleteByPrimaryKey(dto.getQueueId());
if (StringUtils.equals(dto.getReportType(), RunModeConstants.SET_REPORT.toString())) {
apiScenarioReportService.margeReport(dto.getReportId());
}
}
return;
}
DBTestQueue executionQueue = this.handleQueue(dto.getQueueId(), dto.getTestId());
if (executionQueue != null) {
// 串行失败停止
if (executionQueue.getFailure() && StringUtils.isNotEmpty(executionQueue.getCompletedReportId())) {
if (BooleanUtils.isTrue(executionQueue.getFailure()) && StringUtils.isNotEmpty(executionQueue.getCompletedReportId())) {
boolean isNext = failure(executionQueue, dto);
if (!isNext) {
return;
@ -273,21 +284,34 @@ public class ApiExecutionQueueService {
final int SECOND_MILLIS = 1000;
final int MINUTE_MILLIS = 60 * SECOND_MILLIS;
// 计算二十分钟前的超时报告
final long twentyMinutesAgo = System.currentTimeMillis() - (20 * MINUTE_MILLIS);
final long twentyMinutesAgo = System.currentTimeMillis() - (30 * MINUTE_MILLIS);
ApiExecutionQueueDetailExample example = new ApiExecutionQueueDetailExample();
example.createCriteria().andCreateTimeLessThan(twentyMinutesAgo);
List<ApiExecutionQueueDetail> queueDetails = executionQueueDetailMapper.selectByExample(example);
queueDetails.forEach(item -> {
for (ApiExecutionQueueDetail item : queueDetails) {
ApiExecutionQueue queue = queueMapper.selectByPrimaryKey(item.getQueueId());
if (queue != null && StringUtils.equalsAnyIgnoreCase(queue.getRunMode(),
if (queue == null) {
continue;
}
// 在资源池中执行
if (StringUtils.isNotEmpty(queue.getPoolId())
&& jMeterService.getRunningQueue(queue.getPoolId(), item.getReportId())) {
continue;
}
// 检查执行报告是否还在等待队列中或执行线程中
if (JmeterThreadUtils.isRunning(item.getReportId(), item.getTestId())) {
continue;
}
// 检查是否已经超时
if (StringUtils.equalsAnyIgnoreCase(queue.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(item.getReportId());
if (report != null && StringUtils.equalsAnyIgnoreCase(report.getStatus(), TestPlanReportStatus.RUNNING.name())
if (report != null && StringUtils.equalsAnyIgnoreCase(report.getStatus(), TestPlanReportStatus.RUNNING.name(), APITestStatus.Waiting.name())
&& report.getUpdateTime() < twentyMinutesAgo) {
report.setStatus(ScenarioStatus.Timeout.name());
apiScenarioReportMapper.updateByPrimaryKeySelective(report);
@ -311,13 +335,13 @@ public class ApiExecutionQueueService {
}
} else {
ApiDefinitionExecResult result = apiDefinitionExecResultMapper.selectByPrimaryKey(item.getReportId());
if (result != null && StringUtils.equalsAnyIgnoreCase(result.getStatus(), TestPlanReportStatus.RUNNING.name())) {
if (result != null && StringUtils.equalsAnyIgnoreCase(result.getStatus(), TestPlanReportStatus.RUNNING.name(), APITestStatus.Waiting.name())) {
result.setStatus(ScenarioStatus.Timeout.name());
apiDefinitionExecResultMapper.updateByPrimaryKeySelective(result);
executionQueueDetailMapper.deleteByPrimaryKey(item.getId());
}
}
});
}
ApiExecutionQueueExample queueDetailExample = new ApiExecutionQueueExample();
queueDetailExample.createCriteria().andReportTypeEqualTo(RunModeConstants.SET_REPORT.toString()).andCreateTimeLessThan(twentyMinutesAgo);
@ -325,7 +349,7 @@ public class ApiExecutionQueueService {
if (CollectionUtils.isNotEmpty(executionQueues)) {
executionQueues.forEach(item -> {
ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(item.getReportId());
if (report != null && StringUtils.equalsAnyIgnoreCase(report.getStatus(), TestPlanReportStatus.RUNNING.name())
if (report != null && StringUtils.equalsAnyIgnoreCase(report.getStatus(), TestPlanReportStatus.RUNNING.name(), APITestStatus.Waiting.name())
&& (report.getUpdateTime() < twentyMinutesAgo)) {
report.setStatus(ScenarioStatus.Timeout.name());
apiScenarioReportMapper.updateByPrimaryKeySelective(report);

View File

@ -14,6 +14,7 @@ import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.FileUtils;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.dto.JmeterRunRequestDTO;
import io.metersphere.service.EnvironmentGroupProjectService;
import io.metersphere.service.JarConfigService;
import io.metersphere.service.PluginService;
@ -48,6 +49,10 @@ public class ApiJmeterFileService {
public byte[] downloadJmeterFiles(String runMode, String remoteTestId, String reportId, String reportType, String queueId) {
Map<String, String> planEnvMap = new HashMap<>();
JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(remoteTestId, reportId, runMode, null);
runRequest.setReportType(reportType);
runRequest.setQueueId(queueId);
ApiScenarioWithBLOBs scenario = null;
if (StringUtils.equalsAny(runMode, ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name())) {
// 获取场景用例单独的执行环境
@ -71,7 +76,7 @@ public class ApiJmeterFileService {
}
HashTree hashTree = null;
if (StringUtils.equalsAnyIgnoreCase(runMode, ApiRunMode.DEFINITION.name(), ApiRunMode.JENKINS_API_PLAN.name(), ApiRunMode.API_PLAN.name(), ApiRunMode.SCHEDULE_API_PLAN.name(), ApiRunMode.MANUAL_PLAN.name())) {
hashTree = apiScenarioSerialService.generateHashTree(remoteTestId, reportId, runMode, envMap);
hashTree = apiScenarioSerialService.generateHashTree(remoteTestId, envMap, runRequest);
} else {
if (scenario == null) {
scenario = apiScenarioMapper.selectByPrimaryKey(remoteTestId);
@ -92,11 +97,7 @@ public class ApiJmeterFileService {
planEnvMap = environmentGroupProjectService.getEnvMap(envGroupId);
}
}
try {
hashTree = GenerateHashTreeUtil.generateHashTree(scenario, reportId, planEnvMap, reportType);
} catch (Exception e) {
executionQueueDetailMapper.deleteByPrimaryKey(queueId);
}
hashTree = GenerateHashTreeUtil.generateHashTree(scenario, planEnvMap, runRequest);
}
return zipFilesToByteArray((reportId + "_" + remoteTestId), hashTree);
}

View File

@ -3,22 +3,18 @@ package io.metersphere.api.service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.APIReportBatchRequest;
import io.metersphere.api.dto.DeleteAPIReportRequest;
import io.metersphere.api.dto.EnvironmentType;
import io.metersphere.api.dto.QueryAPIReportRequest;
import io.metersphere.api.dto.*;
import io.metersphere.api.dto.automation.APIScenarioReportResult;
import io.metersphere.api.dto.automation.ExecuteType;
import io.metersphere.api.dto.automation.ScenarioStatus;
import io.metersphere.api.dto.datacount.ApiDataCountResult;
import io.metersphere.api.jmeter.ReportCounter;
import io.metersphere.api.jmeter.FixedCapacityUtils;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.ExtApiScenarioReportMapper;
import io.metersphere.commons.constants.*;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.DateUtils;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.ServiceUtils;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.constants.RunModeConstants;
@ -36,12 +32,15 @@ import io.metersphere.utils.LoggerUtil;
import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
@ -82,7 +81,7 @@ public class ApiScenarioReportService {
@Resource
private ApiScenarioReportStructureMapper apiScenarioReportStructureMapper;
@Resource
private MsResultService resultService;
private SqlSessionFactory sqlSessionFactory;
public void saveResult(List<RequestResult> requestResults, ResultDTO dto) {
// 报告详情内容
@ -238,9 +237,9 @@ public class ApiScenarioReportService {
ApiScenarioReport report = editReport(dto.getReportType(), dto.getReportId(), status, dto.getRunMode());
TestPlanApiScenario testPlanApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(dto.getTestId());
if (testPlanApiScenario != null) {
if(report != null){
if (report != null) {
testPlanApiScenario.setLastResult(report.getStatus());
}else {
} else {
if (errorSize > 0) {
testPlanApiScenario.setLastResult(ScenarioStatus.Fail.name());
} else {
@ -333,7 +332,7 @@ public class ApiScenarioReportService {
report.setStatus(size > 0 ? ScenarioStatus.Error.name() : ScenarioStatus.Success.name());
report.setEndTime(System.currentTimeMillis());
// 更新控制台信息
apiScenarioReportStructureService.update(reportId, resultService.getJmeterLogger(reportId));
apiScenarioReportStructureService.update(reportId, FixedCapacityUtils.getJmeterLogger(reportId));
// 更新报告
apiScenarioReportMapper.updateByPrimaryKey(report);
}
@ -351,9 +350,9 @@ public class ApiScenarioReportService {
scenario = apiScenarioMapper.selectByPrimaryKey(report.getScenarioId());
}
if (scenario != null) {
if(StringUtils.equalsAnyIgnoreCase(status,ExecuteResult.errorReportResult.name())){
if (StringUtils.equalsAnyIgnoreCase(status, ExecuteResult.errorReportResult.name())) {
scenario.setLastResult(status);
}else {
} else {
scenario.setLastResult(errorSize > 0 ? "Fail" : ScenarioStatus.Success.name());
}
@ -650,32 +649,6 @@ public class ApiScenarioReportService {
return extApiScenarioReportMapper.countByApiScenarioId();
}
@Resource
private RestTemplate restTemplate;
private static final String BASE_URL = "http://%s:%d";
public Integer get(String reportId, ReportCounter counter) {
int count = 0;
try {
for (JvmInfoDTO item : counter.getPoolUrls()) {
TestResourceDTO testResource = item.getTestResource();
String configuration = testResource.getConfiguration();
NodeDTO node = JSON.parseObject(configuration, NodeDTO.class);
String nodeIp = node.getIp();
Integer port = node.getPort();
String uri = String.format(BASE_URL + "/jmeter/getRunning/" + reportId, nodeIp, port);
ResponseEntity<Integer> result = restTemplate.getForEntity(uri, Integer.class);
if (result == null) {
count += result.getBody();
}
}
} catch (Exception e) {
LogUtil.error(e.getMessage());
}
return count;
}
public Map<String, String> getReportStatusByReportIds(Collection<String> values) {
if (CollectionUtils.isEmpty(values)) {
return new HashMap<>();
@ -688,7 +661,7 @@ public class ApiScenarioReportService {
return map;
}
public APIScenarioReportResult init(String id, String scenarioId, String scenarioName, String triggerMode, String execType, String projectId, String userID, RunModeConfigDTO config, String desc) {
public APIScenarioReportResult init(String id, String scenarioId, String scenarioName, String triggerMode, String execType, String projectId, String userID, RunModeConfigDTO config) {
APIScenarioReportResult report = new APIScenarioReportResult();
if (triggerMode.equals(ApiRunMode.SCENARIO.name()) || triggerMode.equals(ApiRunMode.DEFINITION.name())) {
triggerMode = ReportTriggerMode.MANUAL.name();
@ -696,6 +669,7 @@ public class ApiScenarioReportService {
report.setId(id);
report.setTestId(id);
if (StringUtils.isNotEmpty(scenarioName)) {
scenarioName = scenarioName.length() >= 3000 ? scenarioName.substring(0, 2000) : scenarioName;
report.setName(scenarioName);
} else {
report.setName("场景调试");
@ -703,7 +677,9 @@ public class ApiScenarioReportService {
report.setUpdateTime(System.currentTimeMillis());
report.setCreateTime(System.currentTimeMillis());
report.setStatus(APITestStatus.Running.name());
String status = config != null && StringUtils.equals(config.getMode(), RunModeConstants.SERIAL.toString())
? APITestStatus.Waiting.name() : APITestStatus.Running.name();
report.setStatus(status);
if (StringUtils.isNotEmpty(userID)) {
report.setUserId(userID);
report.setCreateUser(userID);
@ -736,11 +712,11 @@ public class ApiScenarioReportService {
}
}
String status;//增加误报状态判断
if(errorSize > 0){
if (errorSize > 0) {
status = ScenarioStatus.Error.name();
}else if(errorReportResultSize > 0){
} else if (errorReportResultSize > 0) {
status = ExecuteResult.errorReportResult.name();
}else {
} else {
status = ScenarioStatus.Success.name();
}
@ -764,4 +740,22 @@ public class ApiScenarioReportService {
deleteByIds(ids);
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void batchSave(Map<String, RunModeDataDTO> executeQueue, String serialReportId, String runMode, List<MsExecResponseDTO> responseDTOS) {
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiScenarioReportMapper batchMapper = sqlSession.getMapper(ApiScenarioReportMapper.class);
if (StringUtils.isEmpty(serialReportId)) {
for (String reportId : executeQueue.keySet()) {
APIScenarioReportResult report = executeQueue.get(reportId).getReport();
batchMapper.insert(report);
responseDTOS.add(new MsExecResponseDTO(executeQueue.get(reportId).getTestId(), reportId, runMode));
}
sqlSession.flushStatements();
if (sqlSession != null && sqlSessionFactory != null) {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
}
}
}

View File

@ -0,0 +1,260 @@
package io.metersphere.api.service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.automation.ApiScenarioDTO;
import io.metersphere.api.dto.datacount.ApiMethodUrlDTO;
import io.metersphere.api.dto.definition.ApiDefinitionResult;
import io.metersphere.api.dto.definition.ApiTestCaseInfo;
import io.metersphere.api.dto.definition.request.ElementUtil;
import io.metersphere.base.domain.ApiDefinition;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
import io.metersphere.base.mapper.ApiScenarioMapper;
import io.metersphere.base.mapper.ext.ExtApiScenarioMapper;
import io.metersphere.commons.utils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Service
public class MsHashTreeService {
@Resource
private ApiTestCaseService apiTestCaseService;
@Resource
private ApiScenarioMapper apiScenarioMapper;
@Resource
private ApiDefinitionService apiDefinitionService;
@Resource
private ExtApiScenarioMapper extApiScenarioMapper;
private static final String CASE = "CASE";
private static final String REFERENCED = "referenced";
private static final String REF = "REF";
private static final String REF_TYPE = "refType";
private static final String ID = "id";
private static final String NAME = "name";
private static final String SCENARIO = "scenario";
private static final String TYPE = "type";
private static final String HASH_TREE = "hashTree";
private static final String PATH = "path";
private static final String METHOD = "method";
private static final String ENABLE = "enable";
private static final String NUM = "num";
private static final String ENV_ENABLE = "environmentEnable";
private static final String DISABLED = "disabled";
private static final String VERSION_NAME = "versionName";
private static final String VERSION_ENABLE = "versionEnable";
private static final String URL = "url";
public void setHashTree(JSONArray hashTree) {
// 将引用转成复制
if (CollectionUtils.isEmpty(hashTree)) {
return;
}
for (int i = 0; i < hashTree.size(); i++) {
JSONObject object = (JSONObject) hashTree.get(i);
String referenced = object.getString(REFERENCED);
if (StringUtils.isNotBlank(referenced) && StringUtils.equals(referenced, REF)) {
// 检测引用对象是否存在若果不存在则改成复制对象
String refType = object.getString(REF_TYPE);
if (StringUtils.isNotEmpty(refType)) {
if (refType.equals(CASE)) {
ApiTestCaseWithBLOBs bloBs = apiTestCaseService.get(object.getString(ID));
if (bloBs != null) {
object = JSON.parseObject(bloBs.getRequest());
object.put(ID, bloBs.getId());
object.put(NAME, bloBs.getName());
hashTree.set(i, object);
}
} else {
ApiScenarioWithBLOBs bloBs = apiScenarioMapper.selectByPrimaryKey(object.getString(ID));
if (bloBs != null) {
object = JSON.parseObject(bloBs.getScenarioDefinition());
hashTree.set(i, object);
}
}
} else if (SCENARIO.equals(object.getString(TYPE))) {
ApiScenarioWithBLOBs bloBs = apiScenarioMapper.selectByPrimaryKey(object.getString(ID));
if (bloBs != null) {
object = JSON.parseObject(bloBs.getScenarioDefinition());
hashTree.set(i, object);
}
}
}
if (object != null && CollectionUtils.isNotEmpty(object.getJSONArray(HASH_TREE))) {
setHashTree(object.getJSONArray(HASH_TREE));
}
}
}
public List<ApiMethodUrlDTO> getMethodUrlDTOByHashTreeJsonObj(JSONObject obj) {
List<ApiMethodUrlDTO> returnList = new ArrayList<>();
if (obj != null && obj.containsKey(HASH_TREE)) {
JSONArray hashArr = obj.getJSONArray(HASH_TREE);
for (int i = 0; i < hashArr.size(); i++) {
JSONObject elementObj = hashArr.getJSONObject(i);
if (elementObj == null) {
continue;
}
if (elementObj.containsKey(URL) && elementObj.containsKey(METHOD)) {
String url = elementObj.getString(URL);
String method = elementObj.getString(METHOD);
ApiMethodUrlDTO dto = new ApiMethodUrlDTO(url, method);
if (!returnList.contains(dto)) {
returnList.add(dto);
}
}
if (elementObj.containsKey(PATH) && elementObj.containsKey(METHOD)) {
String path = elementObj.getString(PATH);
String method = elementObj.getString(METHOD);
ApiMethodUrlDTO dto = new ApiMethodUrlDTO(path, method);
if (!returnList.contains(dto)) {
returnList.add(dto);
}
}
if (elementObj.containsKey(ID) && elementObj.containsKey(REF_TYPE)) {
String refType = elementObj.getString(REF_TYPE);
String id = elementObj.getString(ID);
if (StringUtils.equals(CASE, refType)) {
ApiDefinition apiDefinition = apiTestCaseService.findApiUrlAndMethodById(id);
if (apiDefinition != null) {
ApiMethodUrlDTO dto = new ApiMethodUrlDTO(apiDefinition.getPath(), apiDefinition.getMethod());
if (!returnList.contains(dto)) {
returnList.add(dto);
}
}
} else if (StringUtils.equals("API", refType)) {
ApiDefinition apiDefinition = apiDefinitionService.selectUrlAndMethodById(id);
if (apiDefinition != null) {
ApiMethodUrlDTO dto = new ApiMethodUrlDTO(apiDefinition.getPath(), apiDefinition.getMethod());
if (!returnList.contains(dto)) {
returnList.add(dto);
}
}
}
}
List<ApiMethodUrlDTO> stepUrlList = this.getMethodUrlDTOByHashTreeJsonObj(elementObj);
if (CollectionUtils.isNotEmpty(stepUrlList)) {
Collection unionList = CollectionUtils.union(returnList, stepUrlList);
returnList = new ArrayList<>(unionList);
}
}
}
return returnList;
}
private final static List<String> requests = new ArrayList<String>() {{
this.add("HTTPSamplerProxy");
this.add("DubboSampler");
this.add("JDBCSampler");
this.add("TCPSampler");
}};
private void setElement(JSONObject element, Integer num, Boolean enable, String versionName, Boolean versionEnable) {
element.put(NUM, num);
element.put(ENABLE, enable == null ? false : enable);
element.put(VERSION_NAME, versionName);
element.put(VERSION_ENABLE, versionEnable == null ? false : versionEnable);
}
private JSONObject setRequest(JSONObject element) {
boolean enable = element.getBoolean(ENABLE);
boolean isExist = false;
if (StringUtils.equalsIgnoreCase(element.getString(REF_TYPE), CASE)) {
ApiTestCaseInfo apiTestCase = apiTestCaseService.get(element.getString(ID));
if (apiTestCase != null) {
if (StringUtils.equalsIgnoreCase(element.getString(REFERENCED), REF)) {
JSONObject refElement = JSON.parseObject(apiTestCase.getRequest());
ElementUtil.dataFormatting(refElement);
JSONArray array = refElement.getJSONArray(HASH_TREE);
BeanUtils.copyBean(element, refElement);
if (array != null) {
ElementUtil.mergeHashTree(element, refElement.getJSONArray(HASH_TREE));
}
element.put(REFERENCED, REF);
element.put(DISABLED, true);
element.put(NAME, apiTestCase.getName());
}
element.put(ID, apiTestCase.getId());
isExist = true;
this.setElement(element, apiTestCase.getNum(), enable, apiTestCase.getVersionName(), apiTestCase.getVersionEnable());
}
} else {
ApiDefinitionResult definitionWithBLOBs = apiDefinitionService.getById(element.getString(ID));
if (definitionWithBLOBs != null) {
element.put(ID, definitionWithBLOBs.getId());
this.setElement(element, definitionWithBLOBs.getNum(), enable, definitionWithBLOBs.getVersionName(), definitionWithBLOBs.getVersionEnable());
isExist = true;
}
}
if (!isExist) {
if (StringUtils.equalsIgnoreCase(element.getString(REFERENCED), REF)) {
element.put(ENABLE, false);
}
element.put(NUM, "");
}
return element;
}
private JSONObject setRefScenario(JSONObject element) {
boolean enable = element.containsKey(ENABLE) ? element.getBoolean(ENABLE) : true;
ApiScenarioDTO scenarioWithBLOBs = extApiScenarioMapper.selectById(element.getString(ID));
if (scenarioWithBLOBs != null && StringUtils.isNotEmpty(scenarioWithBLOBs.getScenarioDefinition())) {
boolean environmentEnable = element.containsKey(ENV_ENABLE)
? element.getBoolean(ENV_ENABLE) : false;
if (StringUtils.equalsIgnoreCase(element.getString(REFERENCED), REF)) {
element = JSON.parseObject(scenarioWithBLOBs.getScenarioDefinition());
element.put(REFERENCED, REF);
element.put(NAME, scenarioWithBLOBs.getName());
}
element.put(ID, scenarioWithBLOBs.getId());
element.put(ENV_ENABLE, environmentEnable);
this.setElement(element, scenarioWithBLOBs.getNum(), enable, scenarioWithBLOBs.getVersionName(), scenarioWithBLOBs.getVersionEnable());
} else {
if (StringUtils.equalsIgnoreCase(element.getString(REFERENCED), REF)) {
element.put(ENABLE, false);
}
element.put(NUM, "");
}
return element;
}
public void dataFormatting(JSONArray hashTree) {
for (int i = 0; i < hashTree.size(); i++) {
JSONObject element = hashTree.getJSONObject(i);
if (element != null && StringUtils.equalsIgnoreCase(element.getString(TYPE), SCENARIO)) {
element = this.setRefScenario(element);
hashTree.set(i, element);
} else if (element != null && requests.contains(element.getString(TYPE))) {
element = this.setRequest(element);
hashTree.set(i, element);
}
if (element.containsKey(HASH_TREE)) {
JSONArray elementJSONArray = element.getJSONArray(HASH_TREE);
dataFormatting(elementJSONArray);
}
}
}
public void dataFormatting(JSONObject element) {
if (element != null && StringUtils.equalsIgnoreCase(element.getString(TYPE), SCENARIO)) {
element = this.setRefScenario(element);
} else if (element != null && requests.contains(element.getString(TYPE))) {
element = this.setRequest(element);
}
if (element != null && element.containsKey(HASH_TREE)) {
JSONArray elementJSONArray = element.getJSONArray(HASH_TREE);
dataFormatting(elementJSONArray);
}
}
}

View File

@ -1,32 +0,0 @@
package io.metersphere.api.service;
import io.metersphere.api.jmeter.FixedCapacityUtils;
import io.metersphere.api.jmeter.MessageCache;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
public class MsResultService {
public String getJmeterLogger(String testId) {
try {
Long startTime = MessageCache.jmeterLogTask.get(testId);
if (startTime == null) {
startTime = MessageCache.jmeterLogTask.get("[" + testId + "]");
}
if (startTime == null) {
startTime = System.currentTimeMillis();
}
Long endTime = System.currentTimeMillis();
Long finalStartTime = startTime;
String logMessage = FixedCapacityUtils.fixedCapacityCache.entrySet().stream()
.filter(map -> map.getKey() > finalStartTime && map.getKey() < endTime)
.map(map -> map.getValue()).collect(Collectors.joining());
return logMessage;
} catch (Exception e) {
return "";
}
}
}

View File

@ -12,18 +12,18 @@ import io.metersphere.dto.JmeterRunRequestDTO;
import io.metersphere.dto.ResultDTO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
@Service
@Transactional(rollbackFor = Exception.class)
public class RemakeReportService {
@Resource
private ApiScenarioReportMapper apiScenarioReportMapper;
@Resource
private ApiScenarioMapper apiScenarioMapper;
@Resource
private ApiTestCaseMapper apiTestCaseMapper;
@Resource
private ApiDefinitionExecResultMapper execResultMapper;
@Resource
private TestPlanApiCaseMapper testPlanApiCaseMapper;
@ -55,6 +55,19 @@ public class RemakeReportService {
testCaseReviewApiCaseMapper.updateByPrimaryKeySelective(testCaseReviewApiCase);
}
}
} else if (StringUtils.equals(request.getRunMode(), ApiRunMode.DEFINITION.name())) {
ApiDefinitionExecResult result = execResultMapper.selectByPrimaryKey(request.getReportId());
if (result != null) {
result.setStatus("error");
result.setEndTime(System.currentTimeMillis());
execResultMapper.updateByPrimaryKeySelective(result);
ApiTestCaseWithBLOBs apiTestCase = apiTestCaseMapper.selectByPrimaryKey(request.getTestId());
if (apiTestCase != null) {
apiTestCase.setStatus("error");
apiTestCase.setUpdateTime(System.currentTimeMillis());
apiTestCaseMapper.updateByPrimaryKeySelective(apiTestCase);
}
}
} else if (StringUtils.equals(request.getRunMode(), ApiRunMode.SCENARIO_PLAN.name())) {
ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(request.getReportId());
if (report != null) {
@ -94,7 +107,7 @@ public class RemakeReportService {
ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(request.getReportId());
if (report != null) {
report.setStatus(APITestStatus.Error.name());
apiScenarioReportMapper.updateByPrimaryKey(report);
apiScenarioReportMapper.updateByPrimaryKeySelective(report);
}
if (StringUtils.isNotEmpty(request.getTestId())) {
ApiScenarioWithBLOBs scenarioWithBLOBs = apiScenarioMapper.selectByPrimaryKey(request.getTestId());
@ -103,14 +116,11 @@ public class RemakeReportService {
scenarioWithBLOBs.setPassRate("0%");
scenarioWithBLOBs.setReportId(report.getId());
scenarioWithBLOBs.setExecuteTimes(1);
apiScenarioMapper.updateByPrimaryKey(scenarioWithBLOBs);
apiScenarioMapper.updateByPrimaryKeySelective(scenarioWithBLOBs);
}
}
}
// 处理队列
ApiExecutionQueueDetailExample example = new ApiExecutionQueueDetailExample();
example.createCriteria().andQueueIdEqualTo(request.getQueueId()).andTestIdEqualTo(request.getTestId());
CommonBeanFactory.getBean(ApiExecutionQueueDetailMapper.class).deleteByExample(example);
ResultDTO dto = new ResultDTO();
BeanUtils.copyBean(dto, request);
dto.setQueueId(request.getQueueId());

View File

@ -3,6 +3,7 @@ package io.metersphere.api.service;
import io.metersphere.api.dto.automation.ApiTestReportVariable;
import io.metersphere.api.jmeter.ExecutedHandleSingleton;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiScenarioMapper;
import io.metersphere.base.mapper.ApiScenarioReportMapper;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.NoticeConstants;
@ -43,6 +44,8 @@ public class TestResultService {
@Resource
private ApiAutomationService apiAutomationService;
@Resource
private ApiScenarioMapper apiScenarioMapper;
@Resource
private TestPlanApiCaseService testPlanApiCaseService;
@Resource
private TestPlanTestCaseService testPlanTestCaseService;
@ -85,7 +88,7 @@ public class TestResultService {
if (StringUtils.equalsAny(dto.getRunMode(), ApiRunMode.SCENARIO.name(), ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) {
ApiScenarioReport scenarioReport = apiScenarioReportService.testEnded(dto);
if (scenarioReport != null) {
ApiScenarioWithBLOBs apiScenario = apiAutomationService.getApiScenario(scenarioReport.getScenarioId());
ApiScenarioWithBLOBs apiScenario = apiScenarioMapper.selectByPrimaryKey(scenarioReport.getScenarioId());
String environment = "";
//执行人
String userName = "";
@ -128,7 +131,7 @@ public class TestResultService {
if (StringUtils.equalsAny(runMode, ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) {
TestPlanScenarioCaseService testPlanScenarioCaseService = CommonBeanFactory.getBean(TestPlanScenarioCaseService.class);
TestPlanApiScenario testPlanApiScenario = testPlanScenarioCaseService.get(testPlanScenarioId);
ApiScenarioWithBLOBs apiScenario = CommonBeanFactory.getBean(ApiAutomationService.class).getApiScenario(testPlanApiScenario.getApiScenarioId());
ApiScenarioWithBLOBs apiScenario = apiScenarioMapper.selectByPrimaryKey(testPlanApiScenario.getApiScenarioId());
testPlanTestCaseService.updateTestCaseStates(apiScenario.getId(), apiScenario.getName(), testPlanApiScenario.getTestPlanId(), TrackCount.AUTOMATION);
}
} catch (Exception e) {

View File

@ -3,6 +3,7 @@ package io.metersphere.task.service;
import com.alibaba.fastjson.JSON;
import io.metersphere.api.dto.automation.TaskRequest;
import io.metersphere.api.exec.queue.ExecThreadPoolExecutor;
import io.metersphere.api.exec.queue.PoolExecBlockingQueueUtil;
import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.api.service.ApiExecutionQueueService;
import io.metersphere.base.domain.*;
@ -120,6 +121,7 @@ public class TaskService {
// 从队列移除
execThreadPoolExecutor.removeQueue(request.getReportId());
apiExecutionQueueService.stop(request.getReportId());
PoolExecBlockingQueueUtil.offer(request.getReportId());
if (StringUtils.equals(request.getType(), "API")) {
ApiDefinitionExecResult result = apiDefinitionExecResultMapper.selectByPrimaryKey(request.getReportId());
if (result != null) {
@ -151,6 +153,7 @@ public class TaskService {
// 从队列移除
execThreadPoolExecutor.removeQueue(item.getId());
apiExecutionQueueService.stop(item.getId());
PoolExecBlockingQueueUtil.offer(item.getId());
}
}
} else if (StringUtils.equals(request.getType(), "SCENARIO")) {
@ -165,6 +168,7 @@ public class TaskService {
// 从队列移除
execThreadPoolExecutor.removeQueue(report.getId());
apiExecutionQueueService.stop(report.getId());
PoolExecBlockingQueueUtil.offer(report.getId());
}
}
} else if (StringUtils.equals(request.getType(), "PERFORMANCE")) {
@ -177,6 +181,7 @@ public class TaskService {
// 从队列移除
execThreadPoolExecutor.removeQueue(loadTestReport.getId());
apiExecutionQueueService.stop(loadTestReport.getId());
PoolExecBlockingQueueUtil.offer(loadTestReport.getId());
}
}
}