refactor(接口测试): 优化误报执行过程处理逻辑
Signed-off-by: fit2-zhao <yong.zhao@fit2cloud.com>
This commit is contained in:
parent
1f04e436dc
commit
2b586710db
|
@ -2,11 +2,13 @@ package io.metersphere.api.exec.api;
|
|||
|
||||
import io.metersphere.api.exec.queue.DBTestQueue;
|
||||
import io.metersphere.api.jmeter.JMeterService;
|
||||
import io.metersphere.api.jmeter.utils.ApiFakeErrorUtil;
|
||||
import io.metersphere.api.jmeter.utils.SmoothWeighted;
|
||||
import io.metersphere.base.domain.ApiDefinitionExecResultWithBLOBs;
|
||||
import io.metersphere.commons.constants.CommonConstants;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.commons.utils.GenerateHashTreeUtil;
|
||||
import io.metersphere.commons.utils.JSON;
|
||||
import io.metersphere.constants.RunModeConstants;
|
||||
import io.metersphere.dto.BaseSystemConfigDTO;
|
||||
import io.metersphere.dto.JmeterRunRequestDTO;
|
||||
|
@ -15,15 +17,13 @@ import io.metersphere.service.RemakeReportService;
|
|||
import io.metersphere.service.SystemParameterService;
|
||||
import io.metersphere.utils.LoggerUtil;
|
||||
import io.metersphere.vo.BooleanPool;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
public class ApiCaseParallelExecuteService {
|
||||
|
@ -35,6 +35,7 @@ public class ApiCaseParallelExecuteService {
|
|||
private RedisTemplate<String, Object> redisTemplate;
|
||||
@Resource
|
||||
private RemakeReportService remakeReportService;
|
||||
|
||||
public void parallel(Map<String, ApiDefinitionExecResultWithBLOBs> executeQueue, RunModeConfigDTO config, DBTestQueue executionQueue, String runMode) {
|
||||
BooleanPool pool = GenerateHashTreeUtil.isResourcePool(config.getResourcePoolId());
|
||||
// 初始化分配策略
|
||||
|
@ -73,13 +74,15 @@ public class ApiCaseParallelExecuteService {
|
|||
}
|
||||
// 开始执行
|
||||
runRequest.getExtendedParameters().put("projectId", executionQueue.getDetail().getProjectIds());
|
||||
|
||||
runRequest.setFakeErrorMap(ApiFakeErrorUtil.get(
|
||||
JSON.parseArray(executionQueue.getDetail().getProjectIds())));
|
||||
LoggerUtil.info("进入并行模式,开始执行用例:[" + result.getName() + "] 报告ID [" + reportId + "]");
|
||||
} catch (Exception e) {
|
||||
remakeReportService.testEnded(runRequest, e.getMessage());
|
||||
LoggerUtil.error("脚本处理失败", runRequest.getReportId(), e);
|
||||
continue;
|
||||
}
|
||||
// 误报规则
|
||||
jMeterService.run(runRequest);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import io.metersphere.api.dto.definition.request.ParameterConfig;
|
|||
import io.metersphere.api.exec.queue.DBTestQueue;
|
||||
import io.metersphere.api.jmeter.JMeterService;
|
||||
import io.metersphere.api.jmeter.NewDriverManager;
|
||||
import io.metersphere.api.jmeter.utils.ApiFakeErrorUtil;
|
||||
import io.metersphere.api.jmeter.utils.SmoothWeighted;
|
||||
import io.metersphere.base.domain.ApiDefinitionExecResultWithBLOBs;
|
||||
import io.metersphere.base.domain.ApiExecutionQueueDetail;
|
||||
|
@ -77,6 +78,8 @@ public class ApiCaseSerialService {
|
|||
if (runRequest.getPool().isPool()) {
|
||||
SmoothWeighted.setServerConfig(runRequest.getPoolId(), redisTemplate);
|
||||
}
|
||||
runRequest.setFakeErrorMap(ApiFakeErrorUtil.get(
|
||||
JSON.parseArray(queue.getProjectIds())));
|
||||
// 开始执行
|
||||
runRequest.getExtendedParameters().put(PROJECT_ID, queue.getProjectIds());
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -14,6 +14,7 @@ import io.metersphere.api.dto.scenario.Body;
|
|||
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
||||
import io.metersphere.api.jmeter.JMeterService;
|
||||
import io.metersphere.api.jmeter.NewDriverManager;
|
||||
import io.metersphere.api.jmeter.utils.ApiFakeErrorUtil;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
|
||||
import io.metersphere.base.mapper.ApiDefinitionMapper;
|
||||
|
@ -115,27 +116,24 @@ public class ApiExecuteService {
|
|||
}
|
||||
|
||||
public MsExecResponseDTO exec(RunCaseRequest request, Map<String, Object> extendedParameters) {
|
||||
ApiTestCaseWithBLOBs testCaseWithBLOBs = request.getBloBs();
|
||||
PerformInspectionUtil.countMatches(testCaseWithBLOBs.getRequest(), testCaseWithBLOBs.getId());
|
||||
ApiTestCaseWithBLOBs testCase = request.getBloBs();
|
||||
PerformInspectionUtil.countMatches(testCase.getRequest(), testCase.getId());
|
||||
if (StringUtils.equals(request.getRunMode(), ApiRunMode.JENKINS_API_PLAN.name())) {
|
||||
testCaseWithBLOBs = apiTestCaseMapper.selectByPrimaryKey(request.getReportId());
|
||||
testCase = apiTestCaseMapper.selectByPrimaryKey(request.getReportId());
|
||||
request.setCaseId(request.getReportId());
|
||||
//通过测试计划id查询环境
|
||||
request.setReportId(request.getTestPlanId());
|
||||
}
|
||||
LoggerUtil.info("开始执行单条用例【 " + testCaseWithBLOBs.getId() + " 】", request.getReportId());
|
||||
LoggerUtil.info("开始执行单条用例【 " + testCase.getId() + " 】", request.getReportId());
|
||||
RunModeConfigDTO runModeConfigDTO = new RunModeConfigDTO();
|
||||
jMeterService.verifyPool(testCaseWithBLOBs.getProjectId(), runModeConfigDTO);
|
||||
jMeterService.verifyPool(testCase.getProjectId(), runModeConfigDTO);
|
||||
|
||||
// 多态JSON普通转换会丢失内容,需要通过 ObjectMapper 获取
|
||||
JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(testCaseWithBLOBs.getId(), StringUtils.isEmpty(request.getReportId()) ? request.getId() : request.getReportId(), request.getRunMode(), null, null);
|
||||
if (testCaseWithBLOBs != null && StringUtils.isNotEmpty(testCaseWithBLOBs.getRequest())) {
|
||||
JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(testCase.getId(),
|
||||
StringUtils.isEmpty(request.getReportId()) ? request.getId()
|
||||
: request.getReportId(), request.getRunMode(), null,null);
|
||||
if (testCase != null && StringUtils.isNotEmpty(testCase.getRequest())) {
|
||||
try {
|
||||
HashTree jmeterHashTree = this.generateHashTree(request, testCaseWithBLOBs, runModeConfigDTO);
|
||||
if (LoggerUtil.getLogger().isDebugEnabled()) {
|
||||
LoggerUtil.debug("生成jmx文件:" + ElementUtil.hashTreeToString(jmeterHashTree));
|
||||
}
|
||||
|
||||
HashTree jmeterHashTree = this.generateHashTree(request, testCase, runModeConfigDTO);
|
||||
// 调用执行方法
|
||||
runRequest.setHashTree(jmeterHashTree);
|
||||
if (MapUtils.isNotEmpty(extendedParameters)) {
|
||||
|
@ -148,11 +146,16 @@ public class ApiExecuteService {
|
|||
BaseSystemConfigDTO baseInfo = systemParameterService.getBaseInfo();
|
||||
runRequest.setPlatformUrl(GenerateHashTreeUtil.getPlatformUrl(baseInfo, runRequest, null));
|
||||
}
|
||||
jMeterService.run(runRequest);
|
||||
String projectId = testCase.getProjectId();
|
||||
runRequest.setFakeErrorMap(ApiFakeErrorUtil.get(new ArrayList<>() {{
|
||||
this.add(projectId);
|
||||
}}));
|
||||
} catch (Exception ex) {
|
||||
remakeReportService.updateReport(runRequest, ex.getMessage());
|
||||
LogUtil.error(ex.getMessage(), ex);
|
||||
return new MsExecResponseDTO(request.getCaseId(), request.getReport().getId(), request.getRunMode());
|
||||
}
|
||||
jMeterService.run(runRequest);
|
||||
}
|
||||
return new MsExecResponseDTO(request.getCaseId(), request.getReport().getId(), request.getRunMode());
|
||||
}
|
||||
|
@ -165,6 +168,9 @@ public class ApiExecuteService {
|
|||
request.getTestElement().getHashTree().get(0).setName(request.getId());
|
||||
}
|
||||
JmeterRunRequestDTO runRequest = this.initRunRequest(request, bodyFiles);
|
||||
runRequest.setFakeErrorMap(ApiFakeErrorUtil.get(new ArrayList<>() {{
|
||||
this.add(request.getProjectId());
|
||||
}}));
|
||||
// 开始执行
|
||||
jMeterService.run(runRequest);
|
||||
return new MsExecResponseDTO(runRequest.getTestId(), runRequest.getReportId(), runRequest.getRunMode());
|
||||
|
|
|
@ -13,6 +13,7 @@ import io.metersphere.api.exec.api.ApiCaseExecuteService;
|
|||
import io.metersphere.api.exec.queue.DBTestQueue;
|
||||
import io.metersphere.api.jmeter.JMeterService;
|
||||
import io.metersphere.api.jmeter.NewDriverManager;
|
||||
import io.metersphere.api.jmeter.utils.ApiFakeErrorUtil;
|
||||
import io.metersphere.base.domain.ApiScenario;
|
||||
import io.metersphere.base.domain.ApiScenarioExample;
|
||||
import io.metersphere.base.domain.ApiScenarioReportWithBLOBs;
|
||||
|
@ -466,6 +467,8 @@ public class ApiScenarioExecuteService {
|
|||
test.setProperty(ApiTestConstants.JAR_PATH, JSON.toJSONString(loadJar.keySet().stream().toList()));
|
||||
runRequest.setCustomJarInfo(loadJar);
|
||||
}
|
||||
runRequest.setFakeErrorMap(ApiFakeErrorUtil.get(
|
||||
NewDriverManager.getProjectIds(request)));
|
||||
jMeterService.run(runRequest);
|
||||
return request.getId();
|
||||
}
|
||||
|
|
|
@ -4,8 +4,10 @@ import io.metersphere.api.dto.RunModeDataDTO;
|
|||
import io.metersphere.api.dto.automation.RunScenarioRequest;
|
||||
import io.metersphere.api.exec.queue.DBTestQueue;
|
||||
import io.metersphere.api.jmeter.JMeterService;
|
||||
import io.metersphere.api.jmeter.utils.ApiFakeErrorUtil;
|
||||
import io.metersphere.api.jmeter.utils.SmoothWeighted;
|
||||
import io.metersphere.commons.utils.GenerateHashTreeUtil;
|
||||
import io.metersphere.commons.utils.JSON;
|
||||
import io.metersphere.constants.RunModeConstants;
|
||||
import io.metersphere.dto.BaseSystemConfigDTO;
|
||||
import io.metersphere.dto.JmeterRunRequestDTO;
|
||||
|
@ -57,6 +59,8 @@ public class ApiScenarioParallelService {
|
|||
dataDTO.getPlanEnvMap(), runRequest));
|
||||
}
|
||||
runRequest.getExtendedParameters().put("projectId", executionQueue.getDetail().getProjectIds());
|
||||
runRequest.setFakeErrorMap(ApiFakeErrorUtil.get(
|
||||
JSON.parseArray(executionQueue.getDetail().getProjectIds())));
|
||||
LoggerUtil.info("进入并行模式,准备执行场景:[ " +
|
||||
executeQueue.get(reportId).getReport().getName() + " ]", reportId);
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.metersphere.api.exec.scenario;
|
|||
|
||||
import io.metersphere.api.exec.queue.DBTestQueue;
|
||||
import io.metersphere.api.jmeter.JMeterService;
|
||||
import io.metersphere.api.jmeter.utils.ApiFakeErrorUtil;
|
||||
import io.metersphere.api.jmeter.utils.SmoothWeighted;
|
||||
import io.metersphere.base.domain.ApiExecutionQueueDetail;
|
||||
import io.metersphere.base.domain.ApiScenarioReport;
|
||||
|
@ -99,6 +100,8 @@ public class ApiScenarioSerialService {
|
|||
}
|
||||
// 开始执行
|
||||
runRequest.getExtendedParameters().put("projectId", queue.getProjectIds());
|
||||
runRequest.setFakeErrorMap(ApiFakeErrorUtil.get(
|
||||
JSON.parseArray(queue.getProjectIds())));
|
||||
} catch (Exception e) {
|
||||
remakeReportService.testEnded(runRequest, e.getMessage());
|
||||
LoggerUtil.error("脚本处理失败", runRequest.getReportId(), e);
|
||||
|
|
|
@ -90,25 +90,25 @@ public class JMeterService {
|
|||
|
||||
/**
|
||||
* 添加调试监听
|
||||
*
|
||||
* @param testId
|
||||
* @param testPlan
|
||||
*/
|
||||
private void addDebugListener(String testId, HashTree testPlan, String runMode) {
|
||||
private void addDebugListener(JmeterRunRequestDTO request) {
|
||||
MsDebugListener resultCollector = new MsDebugListener();
|
||||
resultCollector.setName(testId);
|
||||
resultCollector.setName(request.getReportId());
|
||||
resultCollector.setProperty(TestElement.TEST_CLASS, MsDebugListener.class.getName());
|
||||
resultCollector.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ViewResultsFullVisualizer"));
|
||||
resultCollector.setEnabled(true);
|
||||
resultCollector.setRunMode(runMode);
|
||||
|
||||
resultCollector.setRunMode(request.getRunMode());
|
||||
resultCollector.setFakeErrorMap(request.getFakeErrorMap());
|
||||
// 添加DEBUG标示
|
||||
HashTree test = ArrayUtils.isNotEmpty(testPlan.getArray()) ? testPlan.getTree(testPlan.getArray()[0]) : null;
|
||||
if (test != null && ArrayUtils.isNotEmpty(test.getArray()) && test.getArray()[0] instanceof ThreadGroup) {
|
||||
HashTree test = ArrayUtils.isNotEmpty(request.getHashTree().getArray())
|
||||
? request.getHashTree().getTree(request.getHashTree().getArray()[0]) : null;
|
||||
|
||||
if (test != null && ArrayUtils.isNotEmpty(test.getArray())
|
||||
&& test.getArray()[0] instanceof ThreadGroup) {
|
||||
ThreadGroup group = (ThreadGroup) test.getArray()[0];
|
||||
group.setProperty(BackendListenerConstants.MS_DEBUG.name(), true);
|
||||
}
|
||||
testPlan.add(testPlan.getArray()[0], resultCollector);
|
||||
request.getHashTree().add(request.getHashTree().getArray()[0], resultCollector);
|
||||
}
|
||||
|
||||
private void runLocal(JmeterRunRequestDTO request) {
|
||||
|
@ -131,12 +131,12 @@ public class JMeterService {
|
|||
&& request.getExtendedParameters().containsKey(ExtendedParameter.SYNC_STATUS)
|
||||
&& (Boolean) request.getExtendedParameters().get(ExtendedParameter.SYNC_STATUS)) {
|
||||
LoggerUtil.debug("为请求 [ " + request.getReportId() + " ] 添加Debug Listener");
|
||||
addDebugListener(request.getReportId(), request.getHashTree(), request.getRunMode());
|
||||
addDebugListener(request);
|
||||
}
|
||||
|
||||
if (request.isDebug()) {
|
||||
LoggerUtil.debug("为请求 [ " + request.getReportId() + " ] 添加Debug Listener");
|
||||
addDebugListener(request.getReportId(), request.getHashTree(), request.getRunMode());
|
||||
addDebugListener(request);
|
||||
} else {
|
||||
LoggerUtil.debug("为请求 [ " + request.getReportId() + " ] 添加同步接收结果 Listener");
|
||||
JMeterBase.addBackendListener(request, request.getHashTree(), MsApiBackendListener.class.getCanonicalName());
|
||||
|
@ -178,6 +178,7 @@ public class JMeterService {
|
|||
engine.start();
|
||||
} catch (Exception e) {
|
||||
remakeReportService.testEnded(request, e.getMessage());
|
||||
redisTemplateService.delFilePathAndScript(request.getReportId(), request.getTestId());
|
||||
LoggerUtil.error("调用K8S执行请求[ " + request.getTestId() + " ]失败:", request.getReportId(), e);
|
||||
}
|
||||
} else if ((MapUtils.isNotEmpty(request.getExtendedParameters())
|
||||
|
@ -203,6 +204,7 @@ public class JMeterService {
|
|||
apiPoolDebugService.run(request, resources);
|
||||
} catch (Exception e) {
|
||||
remakeReportService.updateReport(request, e.getMessage());
|
||||
redisTemplateService.delFilePathAndScript(request.getReportId(), request.getTestId());
|
||||
LoggerUtil.error("发送请求[ " + request.getTestId() + " ] 执行失败,进行数据回滚:", request.getReportId(), e);
|
||||
MSException.throwException("调用资源池执行失败,请检查资源池是否配置正常");
|
||||
}
|
||||
|
@ -231,6 +233,7 @@ public class JMeterService {
|
|||
}
|
||||
} catch (Exception e) {
|
||||
remakeReportService.testEnded(request, e.getMessage());
|
||||
redisTemplateService.delFilePath(request.getReportId());
|
||||
LoggerUtil.error("发送请求[ " + request.getTestId() + " ] 执行失败,进行数据回滚:", request.getReportId(), e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,7 @@ package io.metersphere.api.jmeter;
|
|||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import io.metersphere.api.exec.queue.PoolExecBlockingQueueUtil;
|
||||
import io.metersphere.api.jmeter.utils.JmxFileUtil;
|
||||
import io.metersphere.commons.constants.ApiRunMode;
|
||||
import io.metersphere.commons.constants.ExtendedParameter;
|
||||
import io.metersphere.commons.utils.JSON;
|
||||
import io.metersphere.dto.ResultDTO;
|
||||
import io.metersphere.service.ApiExecutionQueueService;
|
||||
|
@ -14,6 +12,7 @@ import io.metersphere.utils.LoggerUtil;
|
|||
import lombok.Data;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.kafka.clients.consumer.ConsumerRecord;
|
||||
|
||||
|
@ -60,13 +59,12 @@ public class KafkaListenerTask implements Runnable {
|
|||
return;
|
||||
}
|
||||
|
||||
if (dto.getArbitraryData() != null && dto.getArbitraryData().containsKey(ExtendedParameter.TEST_END)
|
||||
&& (Boolean) dto.getArbitraryData().get(ExtendedParameter.TEST_END)) {
|
||||
redisTemplateService.delete(JmxFileUtil.getExecuteFileKeyInRedis(dto.getReportId()));
|
||||
if (BooleanUtils.isTrue(dto.getHasEnded())) {
|
||||
redisTemplateService.delFilePath(dto.getReportId());
|
||||
resultDTOS.add(dto);
|
||||
// 全局并发队列
|
||||
PoolExecBlockingQueueUtil.offer(dto.getReportId());
|
||||
LoggerUtil.info("KAFKA消费结果处理状态:" + dto.getArbitraryData().get(ExtendedParameter.TEST_END), String.valueOf(record.key()));
|
||||
LoggerUtil.info("KAFKA消费结束:", record.key());
|
||||
}
|
||||
// 携带结果
|
||||
if (CollectionUtils.isNotEmpty(dto.getRequestResults())) {
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
package io.metersphere.api.jmeter;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import io.metersphere.api.exec.queue.PoolExecBlockingQueueUtil;
|
||||
import io.metersphere.api.jmeter.utils.JmxFileUtil;
|
||||
import io.metersphere.api.jmeter.utils.ReportStatusUtil;
|
||||
import io.metersphere.utils.ReportStatusUtil;
|
||||
import io.metersphere.commons.constants.CommonConstants;
|
||||
import io.metersphere.commons.utils.*;
|
||||
import io.metersphere.commons.vo.ResultVO;
|
||||
import io.metersphere.vo.ResultVO;
|
||||
import io.metersphere.constants.BackendListenerConstants;
|
||||
import io.metersphere.constants.RunModeConstants;
|
||||
import io.metersphere.dto.MsRegexDTO;
|
||||
import io.metersphere.dto.ResultDTO;
|
||||
import io.metersphere.jmeter.JMeterBase;
|
||||
import io.metersphere.service.ApiExecutionQueueService;
|
||||
|
@ -65,8 +66,6 @@ public class MsApiBackendListener extends AbstractBackendListenerClient implemen
|
|||
if (dto.isRetryEnable()) {
|
||||
queues.addAll(sampleResults);
|
||||
} else {
|
||||
redisTemplateService.delete(JmxFileUtil.getExecuteFileKeyInRedis(dto.getReportId()));
|
||||
|
||||
if (!StringUtils.equals(dto.getReportType(), RunModeConstants.SET_REPORT.toString())) {
|
||||
dto.setConsole(FixedCapacityUtil.getJmeterLogger(getReportId(), false));
|
||||
}
|
||||
|
@ -84,9 +83,6 @@ public class MsApiBackendListener extends AbstractBackendListenerClient implemen
|
|||
public void teardownTest(BackendListenerContext context) {
|
||||
try {
|
||||
LoggerUtil.info("进入TEST-END处理报告" + dto.getRunMode(), dto.getReportId());
|
||||
|
||||
redisTemplateService.delete(JmxFileUtil.getExecuteFileKeyInRedis(dto.getReportId()));
|
||||
|
||||
super.teardownTest(context);
|
||||
// 获取执行日志
|
||||
if (!StringUtils.equals(dto.getReportType(), RunModeConstants.SET_REPORT.toString())) {
|
||||
|
@ -125,6 +121,7 @@ public class MsApiBackendListener extends AbstractBackendListenerClient implemen
|
|||
LoggerUtil.error("结果集处理异常", dto.getReportId(), e);
|
||||
} finally {
|
||||
queues.clear();
|
||||
redisTemplateService.delFilePath(dto.getReportId());
|
||||
FileUtils.deleteBodyFiles(dto.getReportId());
|
||||
if (FileServer.getFileServer() != null) {
|
||||
LoggerUtil.info("进入监听,开始关闭CSV", dto.getReportId());
|
||||
|
@ -158,6 +155,12 @@ public class MsApiBackendListener extends AbstractBackendListenerClient implemen
|
|||
if (StringUtils.isNotEmpty(ept)) {
|
||||
dto.setExtendedParameters(JSON.parseObject(context.getParameter(BackendListenerConstants.EPT.name()), Map.class));
|
||||
}
|
||||
if (StringUtils.isNotBlank(context.getParameter(BackendListenerConstants.FAKE_ERROR.name()))) {
|
||||
Map<String, List<MsRegexDTO>> fakeErrorMap = JSON.parseObject(
|
||||
context.getParameter(BackendListenerConstants.FAKE_ERROR.name()),
|
||||
new TypeReference<Map<String, List<MsRegexDTO>>>() {});
|
||||
dto.setFakeErrorMap(fakeErrorMap);
|
||||
}
|
||||
}
|
||||
|
||||
private String getReportId() {
|
||||
|
|
|
@ -23,6 +23,7 @@ import io.metersphere.api.dto.RunningParamKeys;
|
|||
import io.metersphere.api.exec.queue.PoolExecBlockingQueueUtil;
|
||||
import io.metersphere.commons.constants.ApiRunMode;
|
||||
import io.metersphere.commons.utils.*;
|
||||
import io.metersphere.dto.MsRegexDTO;
|
||||
import io.metersphere.dto.RequestResult;
|
||||
import io.metersphere.jmeter.JMeterBase;
|
||||
import io.metersphere.service.definition.ApiDefinitionEnvService;
|
||||
|
@ -38,6 +39,7 @@ import org.apache.jmeter.testelement.property.BooleanProperty;
|
|||
import org.apache.jmeter.threads.JMeterVariables;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -57,6 +59,7 @@ public class MsDebugListener extends AbstractListenerElement implements SampleLi
|
|||
private String runMode;
|
||||
|
||||
private ApiDefinitionEnvService apiDefinitionEnvService;
|
||||
private Map<String, List<MsRegexDTO>> fakeErrorMap;
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
|
@ -64,6 +67,10 @@ public class MsDebugListener extends AbstractListenerElement implements SampleLi
|
|||
return clone;
|
||||
}
|
||||
|
||||
public void setFakeErrorMap(Map<String, List<MsRegexDTO>> fakeErrorMap) {
|
||||
this.fakeErrorMap = fakeErrorMap;
|
||||
}
|
||||
|
||||
public boolean isErrorLogging() {
|
||||
return getPropertyAsBoolean(ERROR_LOGGING);
|
||||
}
|
||||
|
@ -160,7 +167,7 @@ public class MsDebugListener extends AbstractListenerElement implements SampleLi
|
|||
SampleResult result = event.getResult();
|
||||
this.setVars(result);
|
||||
if (isSampleWanted(result.isSuccessful(), result) && !StringUtils.equals(result.getSampleLabel(), RunningParamKeys.RUNNING_DEBUG_SAMPLER_NAME)) {
|
||||
RequestResult requestResult = JMeterBase.getRequestResult(result);
|
||||
RequestResult requestResult = JMeterBase.getRequestResult(result, fakeErrorMap);
|
||||
if (requestResult != null && ResultParseUtil.isNotAutoGenerateSampler(requestResult)) {
|
||||
MsgDTO dto = new MsgDTO();
|
||||
dto.setExecEnd(false);
|
||||
|
|
|
@ -97,6 +97,14 @@ public class NewDriverManager {
|
|||
public static Map<String, List<ProjectJarConfig>> loadJar(RunDefinitionRequest request, BooleanPool pool) {
|
||||
// 加载自定义JAR
|
||||
MsTestPlan testPlan = (MsTestPlan) request.getTestElement();
|
||||
List<String> projectIds = getProjectIds(request);
|
||||
Map<String, List<ProjectJarConfig>> jars = getJars(projectIds, pool);
|
||||
testPlan.setProjectJarIds(projectIds);
|
||||
|
||||
return jars;
|
||||
}
|
||||
|
||||
public static List<String> getProjectIds(RunDefinitionRequest request) {
|
||||
List<String> projectIds = new ArrayList<>();
|
||||
projectIds.add(request.getProjectId());
|
||||
if (MapUtils.isNotEmpty(request.getEnvironmentMap())) {
|
||||
|
@ -106,10 +114,6 @@ public class NewDriverManager {
|
|||
}
|
||||
});
|
||||
}
|
||||
Map<String, List<ProjectJarConfig>> jars = getJars(projectIds, pool);
|
||||
testPlan.setProjectJarIds(projectIds);
|
||||
|
||||
return jars;
|
||||
return projectIds;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package io.metersphere.api.jmeter.utils;
|
||||
|
||||
import io.metersphere.base.domain.ErrorReportLibraryExample;
|
||||
import io.metersphere.base.domain.ErrorReportLibraryWithBLOBs;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.commons.utils.JSON;
|
||||
import io.metersphere.commons.utils.JSONUtil;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.dto.MsRegexDTO;
|
||||
import io.metersphere.xpack.fake.error.ErrorReportLibraryService;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ApiFakeErrorUtil {
|
||||
|
||||
private static final String REGEX_CONFIG = "regexConfig";
|
||||
|
||||
public static Map<String, List<MsRegexDTO>> get(List<String> projectIds) {
|
||||
Map<String, List<MsRegexDTO>> fakeErrorMap = new HashMap<>();
|
||||
if (CollectionUtils.isEmpty(projectIds)) {
|
||||
return fakeErrorMap;
|
||||
}
|
||||
ErrorReportLibraryService service = CommonBeanFactory.getBean(ErrorReportLibraryService.class);
|
||||
if (service != null) {
|
||||
ErrorReportLibraryExample example = new ErrorReportLibraryExample();
|
||||
example.createCriteria().andProjectIdIn(projectIds).andStatusEqualTo(true);
|
||||
List<ErrorReportLibraryWithBLOBs> bloBs = service.selectByExampleWithBLOBs(example);
|
||||
bloBs.forEach(item -> {
|
||||
if (StringUtils.isNotEmpty(item.getContent())) {
|
||||
try {
|
||||
Map<String, Object> assertionMap = JSON.parseObject(item.getContent(), Map.class);
|
||||
if (assertionMap != null) {
|
||||
MsRegexDTO regexConfig = JSON.parseObject(
|
||||
JSONUtil.toJSONString(assertionMap.get(REGEX_CONFIG)), MsRegexDTO.class);
|
||||
regexConfig.setErrorCode(item.getErrorCode());
|
||||
if (fakeErrorMap.containsKey(item.getProjectId())) {
|
||||
fakeErrorMap.get(item.getProjectId()).add(regexConfig);
|
||||
} else {
|
||||
fakeErrorMap.put(item.getProjectId(), new LinkedList<>() {{
|
||||
this.add(regexConfig);
|
||||
}});
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return fakeErrorMap;
|
||||
}
|
||||
}
|
|
@ -3,5 +3,4 @@ package io.metersphere.commons.constants;
|
|||
public class ExtendedParameter {
|
||||
public static final String SYNC_STATUS = "SYN_RES";
|
||||
public static final String SAVE_RESULT = "SAVE_RESULT";
|
||||
public static final String TEST_END = "TEST_END";
|
||||
}
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
package io.metersphere.commons.utils;
|
||||
|
||||
import io.metersphere.api.dto.FakeErrorLibraryDTO;
|
||||
import io.metersphere.api.dto.definition.FakeError;
|
||||
import io.metersphere.api.dto.definition.MsRegexDTO;
|
||||
import io.metersphere.base.domain.ErrorReportLibraryExample;
|
||||
import io.metersphere.base.domain.ErrorReportLibraryWithBLOBs;
|
||||
import io.metersphere.commons.enums.ApiReportStatus;
|
||||
import io.metersphere.dto.RequestResult;
|
||||
import io.metersphere.utils.JsonUtils;
|
||||
import io.metersphere.xpack.fake.error.ErrorReportLibraryService;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 误报解析类
|
||||
*
|
||||
* @author xiaogang
|
||||
*/
|
||||
public class FakeErrorParse {
|
||||
|
||||
public static FakeErrorLibraryDTO parseAssertions(RequestResult result) {
|
||||
FakeErrorLibraryDTO fakeError = new FakeErrorLibraryDTO();
|
||||
if (StringUtils.isNotBlank(result.getFakeErrorMessage())) {
|
||||
FakeError errorReportDTO = JsonUtils.parseObject(result.getFakeErrorMessage(), FakeError.class);
|
||||
ErrorReportLibraryService service = CommonBeanFactory.getBean(ErrorReportLibraryService.class);
|
||||
if (service != null) {
|
||||
ErrorReportLibraryExample example = new ErrorReportLibraryExample();
|
||||
example.createCriteria().andProjectIdEqualTo(errorReportDTO.getProjectId()).andStatusEqualTo(true);
|
||||
List<ErrorReportLibraryWithBLOBs> bloBs = service.selectByExampleWithBLOBs(example);
|
||||
List<MsRegexDTO> regexList = new ArrayList<>();
|
||||
bloBs.forEach(item -> {
|
||||
if (StringUtils.isNotEmpty(item.getContent())) {
|
||||
try {
|
||||
Map<String, Object> assertionMap = JSON.parseObject(item.getContent(), Map.class);
|
||||
if (assertionMap != null) {
|
||||
MsRegexDTO regexConfig = JSON.parseObject(JSONUtil.toJSONString(assertionMap.get("regexConfig")), MsRegexDTO.class);
|
||||
regexConfig.setErrorCode(item.getErrorCode());
|
||||
regexList.add(regexConfig);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
//根据配置来筛选断言、获取误报编码、获取接口状态是否是误报
|
||||
List<String> errorCodeList = new ArrayList<>();
|
||||
regexList.forEach(item -> {
|
||||
if (StringUtils.isNotEmpty(item.getSubject())) {
|
||||
switch (item.getSubject()) {
|
||||
case "Response Code" ->
|
||||
item.setPass(parseResponseCode(result.getResponseResult().getResponseCode(), item.getValue(), item.getCondition()));
|
||||
|
||||
case "Response Headers" ->
|
||||
item.setPass(parseResponseCode(result.getResponseResult().getHeaders(), item.getValue(), item.getCondition()));
|
||||
|
||||
case "Response Data" ->
|
||||
item.setPass(parseResponseCode(result.getResponseResult().getBody(), item.getValue(), item.getCondition()));
|
||||
default -> item.setPass(false);
|
||||
}
|
||||
}
|
||||
if (item.isPass()) {
|
||||
errorCodeList.add(item.getErrorCode());
|
||||
}
|
||||
});
|
||||
boolean higherThanError = errorReportDTO.isHigherThanError();
|
||||
boolean higherThanSuccess = errorReportDTO.isHigherThanSuccess();
|
||||
if (CollectionUtils.isNotEmpty(errorCodeList)) {
|
||||
if ((higherThanError && !result.isSuccess()) || (higherThanSuccess && result.isSuccess())) {
|
||||
fakeError.setRequestStatus(ApiReportStatus.FAKE_ERROR.name());
|
||||
}
|
||||
fakeError.setErrorCodeList(errorCodeList);
|
||||
}
|
||||
LogUtil.info(" FAKE_ERROR result: config-higherThanError:" + higherThanError
|
||||
+ ", config-higherThanSuccess:" + higherThanSuccess
|
||||
+ ", resultIsSuccess: " + result.isSuccess()
|
||||
+ ", isFakeError: " + ((higherThanError && !result.isSuccess()) || (higherThanSuccess && result.isSuccess()))
|
||||
+ "; status:" + fakeError.getRequestStatus());
|
||||
}
|
||||
}
|
||||
fakeError.setResult(result);
|
||||
return fakeError;
|
||||
}
|
||||
|
||||
private static boolean parseResponseCode(String result, String regexDTO, String condition) {
|
||||
return switch (condition.toUpperCase()) {
|
||||
case "CONTAINS" -> result.contains(regexDTO);
|
||||
|
||||
case "NOT_CONTAINS" -> notContains(result, regexDTO);
|
||||
|
||||
case "EQUALS" -> StringUtils.equals(result, regexDTO);
|
||||
|
||||
case "START_WITH" -> result.startsWith(regexDTO);
|
||||
|
||||
case "END_WITH" -> result.endsWith(regexDTO);
|
||||
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean notContains(String result, String regexDTO) {
|
||||
return !result.contains(regexDTO);
|
||||
}
|
||||
}
|
|
@ -165,7 +165,7 @@ public class GenerateHashTreeUtil {
|
|||
} catch (Exception ex) {
|
||||
LoggerUtil.error("场景资源:" + item.getName() + ", 生成执行脚本失败",
|
||||
runRequest.getReportId(), ex);
|
||||
MSException.throwException("场景资源:" + item.getName() + ", 生成执行脚本失败");
|
||||
MSException.throwException("场景资源:" + item.getName() + ", 生成执行脚本失败" + ex.getMessage());
|
||||
}
|
||||
|
||||
LogUtil.info(testPlan.getJmx(jmeterHashTree));
|
||||
|
|
|
@ -3,13 +3,11 @@ package io.metersphere.commons.utils;
|
|||
import com.fasterxml.jackson.core.util.DefaultIndenter;
|
||||
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.metersphere.api.dto.FakeErrorLibraryDTO;
|
||||
import io.metersphere.api.dto.RequestResultExpandDTO;
|
||||
import io.metersphere.commons.enums.ApiReportStatus;
|
||||
import io.metersphere.commons.enums.ResponseFormatType;
|
||||
import io.metersphere.dto.RequestResult;
|
||||
import io.metersphere.dto.ResponseResult;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -20,29 +18,22 @@ import java.util.Map;
|
|||
*/
|
||||
public class ResponseUtil {
|
||||
|
||||
public static RequestResultExpandDTO parseByRequestResult(RequestResult baseResult) {
|
||||
//根据responseheader的信息来处理返回数据
|
||||
baseResult = ResponseUtil.parseResponseBodyByHeader(baseResult);
|
||||
public static RequestResultExpandDTO parseByRequestResult(RequestResult requestResult) {
|
||||
requestResult = ResponseUtil.parseResponseBodyByHeader(requestResult);
|
||||
//解析是否含有误报库信息
|
||||
FakeErrorLibraryDTO errorCodeDTO = FakeErrorParse.parseAssertions(baseResult);
|
||||
RequestResult requestResult = errorCodeDTO.getResult();
|
||||
RequestResultExpandDTO expandDTO = new RequestResultExpandDTO();
|
||||
BeanUtils.copyBean(expandDTO, requestResult);
|
||||
if (CollectionUtils.isNotEmpty(errorCodeDTO.getErrorCodeList())) {
|
||||
if (StringUtils.isNotBlank(requestResult.getFakeErrorCode())) {
|
||||
Map<String, String> expandMap = new HashMap<>();
|
||||
expandMap.put(ApiReportStatus.FAKE_ERROR.name(), errorCodeDTO.getErrorCodeStr());
|
||||
if (StringUtils.equalsIgnoreCase(errorCodeDTO.getRequestStatus(), ApiReportStatus.FAKE_ERROR.name())) {
|
||||
expandMap.put(ApiReportStatus.FAKE_ERROR.name(), requestResult.getFakeErrorCode());
|
||||
if (StringUtils.equalsIgnoreCase(requestResult.getStatus(), ApiReportStatus.FAKE_ERROR.name())) {
|
||||
expandMap.put("status", ApiReportStatus.FAKE_ERROR.name());
|
||||
}
|
||||
expandDTO.setAttachInfoMap(expandMap);
|
||||
LogUtil.info(" FAKE_ERROR result.id:" + errorCodeDTO.getRequestStatus() + "; AttachInfoMap:" + JSON.toJSONString(expandDTO.getAttachInfoMap()));
|
||||
}
|
||||
if (StringUtils.equalsIgnoreCase(errorCodeDTO.getRequestStatus(), ApiReportStatus.FAKE_ERROR.name())) {
|
||||
expandDTO.setStatus(errorCodeDTO.getRequestStatus());
|
||||
if (StringUtils.equalsIgnoreCase(requestResult.getStatus(), ApiReportStatus.FAKE_ERROR.name())) {
|
||||
expandDTO.setStatus(requestResult.getStatus());
|
||||
}
|
||||
LogUtil.info(" FAKE_ERROR result.id:" + errorCodeDTO.getRequestStatus()
|
||||
+ ";status:" + expandDTO.getStatus()
|
||||
+ " AttachInfoMap:" + (expandDTO.getAttachInfoMap() == null ? "null" : JSON.toJSONString(expandDTO.getAttachInfoMap())));
|
||||
return expandDTO;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,9 @@ package io.metersphere.commons.utils;
|
|||
|
||||
|
||||
import io.metersphere.api.dto.ApiScenarioReportBaseInfoDTO;
|
||||
import io.metersphere.api.dto.FakeErrorLibraryDTO;
|
||||
import io.metersphere.base.domain.ApiScenarioReportResultWithBLOBs;
|
||||
import io.metersphere.commons.enums.ApiReportStatus;
|
||||
import io.metersphere.dto.RequestResult;
|
||||
import io.metersphere.utils.LoggerUtil;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -15,26 +12,15 @@ import java.util.UUID;
|
|||
|
||||
public class ResultConversionUtil {
|
||||
|
||||
public static ApiScenarioReportResultWithBLOBs getApiScenarioReportResult(String reportId, RequestResult requestResult) {
|
||||
//解析误报内容
|
||||
FakeErrorLibraryDTO errorCodeDTO = FakeErrorParse.parseAssertions(requestResult);
|
||||
RequestResult result = errorCodeDTO.getResult();
|
||||
public static ApiScenarioReportResultWithBLOBs getApiScenarioReportResult(String reportId, RequestResult result) {
|
||||
String resourceId = result.getResourceId();
|
||||
|
||||
ApiScenarioReportResultWithBLOBs report = newScenarioReportResult(reportId, resourceId);
|
||||
report.setTotalAssertions(Long.parseLong(result.getTotalAssertions() + StringUtils.EMPTY));
|
||||
report.setPassAssertions(Long.parseLong(result.getPassAssertions() + StringUtils.EMPTY));
|
||||
String status = result.getError() == 0 ? ApiReportStatus.SUCCESS.name() : ApiReportStatus.ERROR.name();
|
||||
if (CollectionUtils.isNotEmpty(errorCodeDTO.getErrorCodeList())) {
|
||||
report.setErrorCode(errorCodeDTO.getErrorCodeStr());
|
||||
}
|
||||
if (StringUtils.equalsIgnoreCase(errorCodeDTO.getRequestStatus(), ApiReportStatus.FAKE_ERROR.name())) {
|
||||
status = errorCodeDTO.getRequestStatus();
|
||||
}
|
||||
requestResult.setStatus(status);
|
||||
report.setStatus(status);
|
||||
report.setErrorCode(result.getFakeErrorCode());
|
||||
report.setStatus(result.getStatus());
|
||||
report.setRequestTime(result.getEndTime() - result.getStartTime());
|
||||
LoggerUtil.info("报告ID [ " + reportId + " ] 执行请求:【 " + requestResult.getName() + "】 入库存储");
|
||||
LoggerUtil.info("报告ID [ " + reportId + " ] 执行请求:【 " + result.getName() + "】 入库存储");
|
||||
return report;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import org.springframework.stereotype.Component;
|
|||
public class ApiExecutionQueueListener {
|
||||
private ApiExecutionQueueService queueService;
|
||||
|
||||
@QuartzScheduled(cron = "0 0/10 0/1 * * ?")
|
||||
@QuartzScheduled(cron = "0 0/30 0/1 * * ?")
|
||||
public void execute() {
|
||||
if (queueService == null) {
|
||||
queueService = CommonBeanFactory.getBean(ApiExecutionQueueService.class);
|
||||
|
|
|
@ -6,7 +6,6 @@ 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.api.jmeter.utils.JmxFileUtil;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.*;
|
||||
import io.metersphere.base.mapper.ext.BaseApiExecutionQueueMapper;
|
||||
|
@ -46,8 +45,6 @@ public class ApiExecutionQueueService {
|
|||
@Resource
|
||||
private ApiExecutionQueueDetailMapper executionQueueDetailMapper;
|
||||
@Resource
|
||||
private RedisTemplateService redisTemplateService;
|
||||
@Resource
|
||||
private ApiScenarioSerialService apiScenarioSerialService;
|
||||
@Resource
|
||||
private ApiScenarioReportService apiScenarioReportService;
|
||||
|
@ -227,7 +224,10 @@ public class ApiExecutionQueueService {
|
|||
public DBTestQueue handleQueue(String id, String testId) {
|
||||
ApiExecutionQueue executionQueue = queueMapper.selectByPrimaryKey(id);
|
||||
DBTestQueue queue = new DBTestQueue();
|
||||
if (executionQueue != null) {
|
||||
if (executionQueue == null) {
|
||||
LoggerUtil.info("The queue was accidentally deleted:【" + id + "】");
|
||||
return queue;
|
||||
}
|
||||
BeanUtils.copyBean(queue, executionQueue);
|
||||
LoggerUtil.info("Get the next execution point:【" + id + "】");
|
||||
|
||||
|
@ -238,7 +238,9 @@ public class ApiExecutionQueueService {
|
|||
|
||||
if (CollectionUtils.isNotEmpty(queues)) {
|
||||
// 处理掉当前已经执行完成的资源
|
||||
List<ApiExecutionQueueDetail> completedQueues = queues.stream().filter(item -> StringUtils.equals(item.getTestId(), testId)).collect(Collectors.toList());
|
||||
List<ApiExecutionQueueDetail> completedQueues = queues.stream()
|
||||
.filter(item -> StringUtils.equals(item.getTestId(), testId))
|
||||
.collect(Collectors.toList());
|
||||
if (CollectionUtils.isNotEmpty(completedQueues)) {
|
||||
ApiExecutionQueueDetail completed = completedQueues.get(0);
|
||||
queue.setCompletedReportId(completed.getReportId());
|
||||
|
@ -256,9 +258,6 @@ public class ApiExecutionQueueService {
|
|||
LoggerUtil.info("execution complete,clear queue:【" + id + "】");
|
||||
queueMapper.deleteByPrimaryKey(id);
|
||||
}
|
||||
} else {
|
||||
LoggerUtil.info("The queue was accidentally deleted:【" + id + "】");
|
||||
}
|
||||
return queue;
|
||||
}
|
||||
|
||||
|
@ -312,9 +311,8 @@ public class ApiExecutionQueueService {
|
|||
}
|
||||
return;
|
||||
}
|
||||
// 获取串行下一个执行节点
|
||||
// 清理当前节点并获取下一个要执行的资源
|
||||
DBTestQueue executionQueue = this.handleQueue(dto.getQueueId(), dto.getTestId());
|
||||
if (executionQueue != null) {
|
||||
// 串行失败停止
|
||||
if (BooleanUtils.isTrue(executionQueue.getFailure()) && StringUtils.isNotEmpty(executionQueue.getCompletedReportId())) {
|
||||
boolean isNext = failure(executionQueue, dto);
|
||||
|
@ -325,22 +323,16 @@ public class ApiExecutionQueueService {
|
|||
LoggerUtil.info("开始处理执行队列:" + executionQueue.getId() + " 当前资源是:" + dto.getTestId() + "报告ID:" + dto.getReportId());
|
||||
if (executionQueue.getDetail() != null && StringUtils.isNotEmpty(executionQueue.getDetail().getTestId())) {
|
||||
if (StringUtils.equals(dto.getRunType(), RunModeConstants.SERIAL.toString())) {
|
||||
LoggerUtil.info("当前执行队列是:" + JSON.toJSONString(executionQueue.getDetail()));
|
||||
// 防止重复执行
|
||||
String key = StringUtils.join(RunModeConstants.SERIAL.name(), "_", executionQueue.getDetail().getReportId());
|
||||
boolean isNext = redisTemplateService.setIfAbsent(key, executionQueue.getDetail().getQueueId());
|
||||
if (!isNext) {
|
||||
return;
|
||||
}
|
||||
redisTemplateService.expire(key);
|
||||
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())) {
|
||||
// 场景执行
|
||||
apiScenarioSerialService.serial(executionQueue);
|
||||
} else {
|
||||
// 接口用例执行
|
||||
apiCaseSerialService.serial(executionQueue);
|
||||
}
|
||||
}
|
||||
|
@ -350,12 +342,6 @@ public class ApiExecutionQueueService {
|
|||
queueMapper.deleteByPrimaryKey(dto.getQueueId());
|
||||
LoggerUtil.info("Queue execution ends:" + dto.getQueueId());
|
||||
}
|
||||
|
||||
ApiExecutionQueueDetailExample example = new ApiExecutionQueueDetailExample();
|
||||
example.createCriteria().andQueueIdEqualTo(dto.getQueueId()).andTestIdEqualTo(dto.getTestId());
|
||||
executionQueueDetailMapper.deleteByExample(example);
|
||||
}
|
||||
LoggerUtil.info("处理队列结束:" + dto.getReportId() + "QID:" + dto.getQueueId());
|
||||
}
|
||||
|
||||
private void margeReport(ResultDTO dto) {
|
||||
|
@ -396,7 +382,6 @@ public class ApiExecutionQueueService {
|
|||
dto.setQueueId(item.getQueueId());
|
||||
dto.setTestId(item.getTestId());
|
||||
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())) {
|
||||
redisTemplateService.delete(JmxFileUtil.getExecuteFileKeyInRedis(item.getReportId()));
|
||||
ApiScenarioReportWithBLOBs report = apiScenarioReportMapper.selectByPrimaryKey(item.getReportId());
|
||||
// 报告已经被删除则队列也删除
|
||||
if (report == null) {
|
||||
|
@ -408,10 +393,6 @@ public class ApiExecutionQueueService {
|
|||
apiScenarioReportMapper.updateByPrimaryKeySelective(report);
|
||||
LoggerUtil.info("超时处理报告:" + report.getId());
|
||||
if (queue != null && StringUtils.equalsIgnoreCase(item.getType(), RunModeConstants.SERIAL.toString())) {
|
||||
// 删除串行资源锁
|
||||
String key = StringUtils.join(RunModeConstants.SERIAL.name(), "_", dto.getReportId());
|
||||
redisTemplateService.delete(key);
|
||||
|
||||
LoggerUtil.info("超时处理报告:【" + report.getId() + "】进入下一个执行");
|
||||
dto.setTestPlanReportId(queue.getReportId());
|
||||
dto.setReportId(queue.getReportId());
|
||||
|
@ -424,7 +405,6 @@ public class ApiExecutionQueueService {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
redisTemplateService.delete(JmxFileUtil.getExecuteFileKeyInRedis(item.getReportId()));
|
||||
// 用例/接口超时结果处理
|
||||
ApiDefinitionExecResultWithBLOBs result = apiDefinitionExecResultMapper.selectByPrimaryKey(item.getReportId());
|
||||
if (result != null && StringUtils.equalsAnyIgnoreCase(result.getStatus(), TestPlanReportStatus.RUNNING.name())) {
|
||||
|
@ -476,8 +456,6 @@ public class ApiExecutionQueueService {
|
|||
checkTestPlanCaseTestEnd(null, null, reportId);
|
||||
});
|
||||
}
|
||||
// 清除异常队列/一般是服务突然停止产生
|
||||
extApiExecutionQueueMapper.delete();
|
||||
}
|
||||
|
||||
public void stop(String reportId) {
|
||||
|
@ -539,11 +517,46 @@ public class ApiExecutionQueueService {
|
|||
* 服务异常重启处理
|
||||
*/
|
||||
public void exceptionHandling() {
|
||||
try {
|
||||
LogUtil.info("开始处理服务重启导致执行未完成的报告状态");
|
||||
// 更新报告状态
|
||||
extApiScenarioReportMapper.updateAllStatus();
|
||||
// 更新用例报告状态
|
||||
extApiDefinitionExecResultMapper.updateAllStatus();
|
||||
LogUtil.info("处理服务重启导致执行未完成的报告状态完成");
|
||||
// 清理队列
|
||||
final List<String> apiModes = new ArrayList<>() {{
|
||||
this.add(ApiRunMode.SCENARIO.name());
|
||||
this.add(ApiRunMode.SCHEDULE_SCENARIO.name());
|
||||
this.add(ApiRunMode.SCENARIO_PLAN.name());
|
||||
this.add(ApiRunMode.SCHEDULE_SCENARIO_PLAN.name());
|
||||
this.add(ApiRunMode.JENKINS_SCENARIO_PLAN.name());
|
||||
this.add(ApiRunMode.DEFINITION.name());
|
||||
this.add(ApiRunMode.JENKINS.name());
|
||||
this.add(ApiRunMode.API_PLAN.name());
|
||||
this.add(ApiRunMode.SCHEDULE_API_PLAN.name());
|
||||
this.add(ApiRunMode.JENKINS_API_PLAN.name());
|
||||
this.add(ApiRunMode.MANUAL_PLAN.name());
|
||||
}};
|
||||
|
||||
ApiExecutionQueueExample queueExample = new ApiExecutionQueueExample();
|
||||
queueExample.createCriteria().andRunModeIn(apiModes);
|
||||
List<ApiExecutionQueue> queues = apiExecutionQueueMapper.selectByExample(queueExample);
|
||||
if (CollectionUtils.isNotEmpty(queues)) {
|
||||
List<String> ids = queues.stream().map(ApiExecutionQueue::getId).collect(Collectors.toList());
|
||||
ApiExecutionQueueDetailExample queueDetailExample = new ApiExecutionQueueDetailExample();
|
||||
queueDetailExample.createCriteria().andQueueIdIn(ids);
|
||||
apiExecutionQueueDetailMapper.deleteByExample(queueDetailExample);
|
||||
// 通知测试计划
|
||||
queues.forEach(item -> {
|
||||
if (StringUtils.endsWith(item.getRunMode(), "PLAN")) {
|
||||
checkTestPlanCaseTestEnd(null, null, item.getReportId());
|
||||
}
|
||||
});
|
||||
apiExecutionQueueMapper.deleteByExample(queueExample);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LoggerUtil.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -374,7 +374,7 @@ public class ApiJMeterFileService {
|
|||
|
||||
Object jmxFileInfoObj = redisTemplateService.get(JmxFileUtil.getExecuteFileKeyInRedis(request.getReportId()));
|
||||
List<AttachmentBodyFile> fileInJmx = JmxFileUtil.formatRedisJmxFileString(jmxFileInfoObj);
|
||||
redisTemplateService.delete(JmxFileUtil.getExecuteFileKeyInRedis(request.getReportId()));
|
||||
redisTemplateService.delFilePath(request.getReportId());
|
||||
|
||||
if (CollectionUtils.isNotEmpty(request.getBodyFiles())) {
|
||||
request.getBodyFiles().forEach(attachmentBodyFile -> {
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
package io.metersphere.service;
|
||||
|
||||
import io.metersphere.api.jmeter.utils.JmxFileUtil;
|
||||
import io.metersphere.utils.LoggerUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Service
|
||||
public class RedisTemplateService {
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
public static final long TIME_OUT = 30;
|
||||
|
||||
public boolean setIfAbsent(String key, String value) {
|
||||
try {
|
||||
|
@ -22,15 +20,6 @@ public class RedisTemplateService {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean expire(String key) {
|
||||
try {
|
||||
return redisTemplate.expire(key, TIME_OUT, TimeUnit.MINUTES);
|
||||
} catch (Exception e) {
|
||||
LoggerUtil.error(key, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Object get(String key) {
|
||||
try {
|
||||
return redisTemplate.opsForValue().get(key);
|
||||
|
@ -48,4 +37,13 @@ public class RedisTemplateService {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void delFilePathAndScript(String reportId, String testId) {
|
||||
delete(JmxFileUtil.getExecuteScriptKey(reportId, testId));
|
||||
delete(JmxFileUtil.getExecuteFileKeyInRedis(reportId));
|
||||
}
|
||||
|
||||
public void delFilePath(String reportId) {
|
||||
delete(JmxFileUtil.getExecuteFileKeyInRedis(reportId));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,15 +9,11 @@ import io.metersphere.commons.utils.FixedCapacityUtil;
|
|||
import io.metersphere.dto.JmeterRunRequestDTO;
|
||||
import io.metersphere.dto.ResultDTO;
|
||||
import io.metersphere.utils.LoggerUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class RemakeReportService {
|
||||
@Resource
|
||||
private RedisTemplateService redisTemplateService;
|
||||
|
||||
public void queueNext(JmeterRunRequestDTO request, String errorMsg) {
|
||||
try {
|
||||
ResultDTO dto = new ResultDTO();
|
||||
|
@ -35,11 +31,8 @@ public class RemakeReportService {
|
|||
LoggerUtil.info("Check Processing Test Plan report status.queueId:" + dto.getQueueId() + ",runMode:" + dto.getRunMode() + ",testId:" + dto.getTestId(), dto.getReportId());
|
||||
CommonBeanFactory.getBean(ApiExecutionQueueService.class).checkTestPlanCaseTestEnd(dto.getTestId(), dto.getRunMode(), dto.getTestPlanReportId());
|
||||
} catch (Exception e) {
|
||||
LoggerUtil.error("回退报告异常", request.getReportId(), e);
|
||||
} finally {
|
||||
ApiLocalRunner.clearCache(request.getReportId());
|
||||
redisTemplateService.delete(JmxFileUtil.getExecuteScriptKey(request.getReportId(), request.getTestId()));
|
||||
redisTemplateService.delete(JmxFileUtil.getExecuteFileKeyInRedis(request.getReportId()));
|
||||
LoggerUtil.error("回退报告异常", request.getReportId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ package io.metersphere.service;
|
|||
|
||||
import io.metersphere.api.dto.automation.ApiTestReportVariable;
|
||||
import io.metersphere.api.exec.scenario.ApiEnvironmentRunningParamService;
|
||||
import io.metersphere.api.jmeter.utils.ReportStatusUtil;
|
||||
import io.metersphere.utils.ReportStatusUtil;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
|
||||
import io.metersphere.base.mapper.ApiScenarioMapper;
|
||||
|
@ -13,7 +13,7 @@ import io.metersphere.commons.enums.ApiReportStatus;
|
|||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.commons.utils.DateUtils;
|
||||
import io.metersphere.commons.utils.JSON;
|
||||
import io.metersphere.commons.vo.ResultVO;
|
||||
import io.metersphere.vo.ResultVO;
|
||||
import io.metersphere.constants.RunModeConstants;
|
||||
import io.metersphere.dto.BaseSystemConfigDTO;
|
||||
import io.metersphere.dto.RequestResult;
|
||||
|
@ -204,11 +204,6 @@ public class TestResultService {
|
|||
}
|
||||
|
||||
public void testEnded(ResultDTO dto) {
|
||||
// 删除串行资源锁
|
||||
if (StringUtils.equals(dto.getRunType(), RunModeConstants.SERIAL.toString())) {
|
||||
String key = StringUtils.join(RunModeConstants.SERIAL.name(), "_", dto.getReportId());
|
||||
redisTemplateService.delete(key);
|
||||
}
|
||||
if (dto.getRequestResults() == null) {
|
||||
dto.setRequestResults(new LinkedList<>());
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import io.metersphere.api.dto.automation.ExecuteType;
|
|||
import io.metersphere.api.dto.automation.RunScenarioRequest;
|
||||
import io.metersphere.api.dto.datacount.ApiDataCountResult;
|
||||
import io.metersphere.api.dto.definition.RunDefinitionRequest;
|
||||
import io.metersphere.api.jmeter.utils.ReportStatusUtil;
|
||||
import io.metersphere.utils.ReportStatusUtil;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.*;
|
||||
import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper;
|
||||
|
@ -20,7 +20,7 @@ import io.metersphere.commons.enums.ApiReportStatus;
|
|||
import io.metersphere.commons.enums.ExecutionExecuteTypeEnum;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.*;
|
||||
import io.metersphere.commons.vo.ResultVO;
|
||||
import io.metersphere.vo.ResultVO;
|
||||
import io.metersphere.constants.RunModeConstants;
|
||||
import io.metersphere.dto.*;
|
||||
import io.metersphere.i18n.Translator;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package io.metersphere.constants;
|
||||
|
||||
public enum BackendListenerConstants {
|
||||
RETRY_ENABLE, TEST_ID, NAME, REPORT_ID, RUN_MODE, REPORT_TYPE, CLASS_NAME, MS_TEST_PLAN_REPORT_ID, RUN, KAFKA_CONFIG, QUEUE_ID, RUN_TYPE, EPT, MS_DEBUG
|
||||
RETRY_ENABLE, TEST_ID, NAME, REPORT_ID, RUN_MODE, REPORT_TYPE,
|
||||
CLASS_NAME, MS_TEST_PLAN_REPORT_ID, RUN, KAFKA_CONFIG, QUEUE_ID,
|
||||
RUN_TYPE, EPT, MS_DEBUG, FAKE_ERROR
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package io.metersphere.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class FakeErrorDTO {
|
||||
private String projectId;
|
||||
private boolean higherThanSuccess;
|
||||
private boolean higherThanError;
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
package io.metersphere.api.dto;
|
||||
package io.metersphere.dto;
|
||||
|
||||
import io.metersphere.dto.RequestResult;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
|
@ -97,6 +97,9 @@ public class JmeterRunRequestDTO {
|
|||
//自定义jar信息
|
||||
private Map<String, List<ProjectJarConfig>> customJarInfo;
|
||||
|
||||
// 自定义误报库
|
||||
private Map<String, List<MsRegexDTO>> fakeErrorMap;
|
||||
|
||||
private String triggerMode;
|
||||
|
||||
public JmeterRunRequestDTO() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package io.metersphere.api.dto.definition;
|
||||
package io.metersphere.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
|
@ -54,5 +54,6 @@ public class RequestResult {
|
|||
}
|
||||
|
||||
private String fakeErrorMessage;
|
||||
|
||||
// 误报编码名称
|
||||
private String fakeErrorCode;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ public class ResultDTO {
|
|||
private String runType;
|
||||
private String console;
|
||||
private String runningDebugSampler;
|
||||
// 是否是结束操作
|
||||
private Boolean hasEnded;
|
||||
// 失败重试
|
||||
private boolean retryEnable;
|
||||
/**
|
||||
|
@ -26,5 +28,7 @@ public class ResultDTO {
|
|||
|
||||
// 预留一个参数,可以放任何数据
|
||||
private Map<String, Object> arbitraryData;
|
||||
// 误报规则
|
||||
Map<String, List<MsRegexDTO>> fakeErrorMap;
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package io.metersphere.enums;
|
||||
|
||||
public enum ApiReportStatus {
|
||||
PENDING, RUNNING, RERUNNING, ERROR, SUCCESS, FAKE_ERROR, STOPPED, TIMEOUT
|
||||
}
|
|
@ -1,12 +1,11 @@
|
|||
package io.metersphere.jmeter;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import io.metersphere.constants.BackendListenerConstants;
|
||||
import io.metersphere.constants.HttpMethodConstants;
|
||||
import io.metersphere.dto.*;
|
||||
import io.metersphere.utils.JMeterVars;
|
||||
import io.metersphere.utils.JsonUtils;
|
||||
import io.metersphere.utils.ListenerUtil;
|
||||
import io.metersphere.utils.LoggerUtil;
|
||||
import io.metersphere.enums.ApiReportStatus;
|
||||
import io.metersphere.utils.*;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -26,8 +25,10 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
public class JMeterBase {
|
||||
|
||||
private final static String THREAD_SPLIT = " ";
|
||||
private final static String TRANSACTION = "Transaction=";
|
||||
private final static String SPLIT_EQ = "split==";
|
||||
private final static String SPLIT_AND = "split&&";
|
||||
|
||||
public static HashTree getHashTree(Object scriptWrapper) throws Exception {
|
||||
Field field = scriptWrapper.getClass().getDeclaredField("testPlan");
|
||||
|
@ -51,6 +52,9 @@ public class JMeterBase {
|
|||
arguments.addArgument(BackendListenerConstants.QUEUE_ID.name(), request.getQueueId());
|
||||
arguments.addArgument(BackendListenerConstants.RUN_TYPE.name(), request.getRunType());
|
||||
arguments.addArgument(BackendListenerConstants.RETRY_ENABLE.name(), String.valueOf(request.isRetryEnable()));
|
||||
if (MapUtils.isNotEmpty(request.getFakeErrorMap())) {
|
||||
arguments.addArgument(BackendListenerConstants.FAKE_ERROR.name(), JSON.toJSONString(request.getFakeErrorMap()));
|
||||
}
|
||||
if (MapUtils.isNotEmpty(request.getExtendedParameters())) {
|
||||
arguments.addArgument(BackendListenerConstants.EPT.name(), JsonUtils.toJSONString(request.getExtendedParameters()));
|
||||
}
|
||||
|
@ -65,9 +69,8 @@ public class JMeterBase {
|
|||
LoggerUtil.info("报告添加BackendListener 结束", request.getTestId());
|
||||
}
|
||||
|
||||
public static RequestResult getRequestResult(SampleResult result) {
|
||||
public static RequestResult getRequestResult(SampleResult result, Map<String, List<MsRegexDTO>> fakeErrorMap) {
|
||||
LoggerUtil.debug("开始处理结果资源【" + result.getSampleLabel() + "】");
|
||||
|
||||
String threadName = StringUtils.substringBeforeLast(result.getThreadName(), THREAD_SPLIT);
|
||||
RequestResult requestResult = new RequestResult();
|
||||
requestResult.setThreadName(threadName);
|
||||
|
@ -92,7 +95,7 @@ public class JMeterBase {
|
|||
}
|
||||
|
||||
for (SampleResult subResult : result.getSubResults()) {
|
||||
requestResult.getSubRequestResults().add(getRequestResult(subResult));
|
||||
requestResult.getSubRequestResults().add(getRequestResult(subResult, fakeErrorMap));
|
||||
}
|
||||
ResponseResult responseResult = requestResult.getResponseResult();
|
||||
// 超过20M的文件不入库
|
||||
|
@ -140,6 +143,16 @@ public class JMeterBase {
|
|||
}
|
||||
|
||||
LoggerUtil.debug("处理结果资源【" + result.getSampleLabel() + "】结束");
|
||||
// 误报处理
|
||||
FakeErrorLibraryDTO errorCodeDTO = FakeErrorUtils.parseAssertions(requestResult, fakeErrorMap);
|
||||
if (CollectionUtils.isNotEmpty(errorCodeDTO.getErrorCodeList())) {
|
||||
requestResult.setFakeErrorCode(errorCodeDTO.getErrorCodeStr());
|
||||
}
|
||||
String status = requestResult.getError() == 0 ? "SUCCESS" : "ERROR";
|
||||
if (StringUtils.equalsIgnoreCase(errorCodeDTO.getRequestStatus(), ApiReportStatus.FAKE_ERROR.name())) {
|
||||
status = ApiReportStatus.FAKE_ERROR.name();
|
||||
}
|
||||
requestResult.setStatus(status);
|
||||
return requestResult;
|
||||
}
|
||||
|
||||
|
@ -147,13 +160,13 @@ public class JMeterBase {
|
|||
ResponseAssertionResult responseAssertionResult = new ResponseAssertionResult();
|
||||
|
||||
responseAssertionResult.setName(assertionResult.getName());
|
||||
if (StringUtils.isNotEmpty(assertionResult.getName()) && assertionResult.getName().indexOf("split==") != -1) {
|
||||
if (StringUtils.isNotEmpty(assertionResult.getName()) && assertionResult.getName().indexOf(SPLIT_EQ) != -1) {
|
||||
if (assertionResult.getName().indexOf("JSR223") != -1) {
|
||||
String[] array = assertionResult.getName().split("split==", 3);
|
||||
String[] array = assertionResult.getName().split(SPLIT_EQ, 3);
|
||||
if (array.length > 2 && "JSR223".equals(array[0])) {
|
||||
responseAssertionResult.setName(array[1]);
|
||||
if (array[2].indexOf("split&&") != -1) {
|
||||
String[] content = array[2].split("split&&");
|
||||
if (array[2].indexOf(SPLIT_AND) != -1) {
|
||||
String[] content = array[2].split(SPLIT_AND);
|
||||
responseAssertionResult.setContent(content[0]);
|
||||
if (content.length > 1) {
|
||||
responseAssertionResult.setScript(content[1]);
|
||||
|
@ -163,7 +176,7 @@ public class JMeterBase {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
String[] array = assertionResult.getName().split("split==");
|
||||
String[] array = assertionResult.getName().split(SPLIT_EQ);
|
||||
responseAssertionResult.setName(array[0]);
|
||||
StringBuffer content = new StringBuffer();
|
||||
for (int i = 1; i < array.length; i++) {
|
||||
|
@ -214,7 +227,7 @@ public class JMeterBase {
|
|||
List<String> environmentList = new ArrayList<>();
|
||||
sampleResults.forEach(result -> {
|
||||
ListenerUtil.setVars(result);
|
||||
RequestResult requestResult = JMeterBase.getRequestResult(result);
|
||||
RequestResult requestResult = JMeterBase.getRequestResult(result, dto.getFakeErrorMap());
|
||||
if (StringUtils.equals(result.getSampleLabel(), ListenerUtil.RUNNING_DEBUG_SAMPLER_NAME)) {
|
||||
String evnStr = result.getResponseDataAsString();
|
||||
environmentList.add(evnStr);
|
||||
|
@ -222,7 +235,7 @@ public class JMeterBase {
|
|||
//检查是否有关系到最终执行结果的全局前后置脚本。
|
||||
boolean resultNotFilterOut = ListenerUtil.checkResultIsNotFilterOut(requestResult);
|
||||
if (resultNotFilterOut) {
|
||||
if (StringUtils.isNotEmpty(requestResult.getName()) && requestResult.getName().startsWith("Transaction=")) {
|
||||
if (StringUtils.isNotEmpty(requestResult.getName()) && requestResult.getName().startsWith(TRANSACTION)) {
|
||||
transactionFormat(requestResult.getSubRequestResults(), requestResults);
|
||||
} else {
|
||||
requestResults.add(requestResult);
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
package io.metersphere.utils;
|
||||
|
||||
import io.metersphere.dto.FakeErrorDTO;
|
||||
import io.metersphere.dto.FakeErrorLibraryDTO;
|
||||
import io.metersphere.dto.MsRegexDTO;
|
||||
import io.metersphere.dto.RequestResult;
|
||||
import io.metersphere.enums.ApiReportStatus;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 误报解析类
|
||||
*
|
||||
* @author xiaogang
|
||||
*/
|
||||
public class FakeErrorUtils {
|
||||
public static FakeErrorLibraryDTO parseAssertions(RequestResult result, Map<String, List<MsRegexDTO>> fakeErrorMap) {
|
||||
FakeErrorLibraryDTO fakeError = new FakeErrorLibraryDTO();
|
||||
try {
|
||||
if (StringUtils.isNotBlank(result.getFakeErrorMessage())) {
|
||||
FakeErrorDTO errorReportDTO = JsonUtils.parseObject(result.getFakeErrorMessage(), FakeErrorDTO.class);
|
||||
if (MapUtils.isNotEmpty(fakeErrorMap) && errorReportDTO != null) {
|
||||
List<MsRegexDTO> regexList = fakeErrorMap.get(errorReportDTO.getProjectId());
|
||||
//根据配置来筛选断言、获取误报编码、获取接口状态是否是误报
|
||||
List<String> errorCodeList = new ArrayList<>();
|
||||
regexList.forEach(item -> {
|
||||
if (StringUtils.isNotEmpty(item.getSubject())) {
|
||||
switch (item.getSubject()) {
|
||||
case "Response Code" ->
|
||||
item.setPass(parseResponseCode(result.getResponseResult().getResponseCode(), item.getValue(), item.getCondition()));
|
||||
|
||||
case "Response Headers" ->
|
||||
item.setPass(parseResponseCode(result.getResponseResult().getHeaders(), item.getValue(), item.getCondition()));
|
||||
|
||||
case "Response Data" ->
|
||||
item.setPass(parseResponseCode(result.getResponseResult().getBody(), item.getValue(), item.getCondition()));
|
||||
default -> item.setPass(false);
|
||||
}
|
||||
}
|
||||
if (item.isPass()) {
|
||||
errorCodeList.add(item.getErrorCode());
|
||||
}
|
||||
});
|
||||
boolean higherThanError = errorReportDTO.isHigherThanError();
|
||||
boolean higherThanSuccess = errorReportDTO.isHigherThanSuccess();
|
||||
if (CollectionUtils.isNotEmpty(errorCodeList)) {
|
||||
if ((higherThanError && !result.isSuccess()) || (higherThanSuccess && result.isSuccess())) {
|
||||
fakeError.setRequestStatus(ApiReportStatus.FAKE_ERROR.name());
|
||||
}
|
||||
fakeError.setErrorCodeList(errorCodeList);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LoggerUtil.error("误报处理错误:", e);
|
||||
}
|
||||
return fakeError;
|
||||
}
|
||||
|
||||
private static boolean parseResponseCode(String result, String regexDTO, String condition) {
|
||||
return switch (condition.toUpperCase()) {
|
||||
case "CONTAINS" -> result.contains(regexDTO);
|
||||
|
||||
case "NOT_CONTAINS" -> notContains(result, regexDTO);
|
||||
|
||||
case "EQUALS" -> StringUtils.equals(result, regexDTO);
|
||||
|
||||
case "START_WITH" -> result.startsWith(regexDTO);
|
||||
|
||||
case "END_WITH" -> result.endsWith(regexDTO);
|
||||
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean notContains(String result, String regexDTO) {
|
||||
return !result.contains(regexDTO);
|
||||
}
|
||||
}
|
|
@ -72,4 +72,13 @@ public class JsonUtils {
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T convertValue(Object content, Class<T> valueType) {
|
||||
try {
|
||||
return objectMapper.convertValue(content, valueType);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
package io.metersphere.api.jmeter.utils;
|
||||
package io.metersphere.utils;
|
||||
|
||||
import io.metersphere.commons.constants.CommonConstants;
|
||||
import io.metersphere.commons.enums.ApiReportStatus;
|
||||
import io.metersphere.commons.utils.JSONUtil;
|
||||
import io.metersphere.commons.vo.ResultVO;
|
||||
import io.metersphere.dto.RequestResult;
|
||||
import io.metersphere.dto.ResultDTO;
|
||||
import io.metersphere.utils.LoggerUtil;
|
||||
import io.metersphere.utils.RetryResultUtil;
|
||||
import io.metersphere.enums.ApiReportStatus;
|
||||
import io.metersphere.vo.ResultVO;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -18,6 +14,9 @@ import java.util.Map;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
public class ReportStatusUtil {
|
||||
public static final String LOCAL_STATUS_KEY = "LOCAL_STATUS_KEY";
|
||||
public static final String REPORT_STATUS = "REPORT_STATUS";
|
||||
|
||||
public static List<RequestResult> filterRetryResults(List<RequestResult> results) {
|
||||
List<RequestResult> list = new LinkedList<>();
|
||||
if (CollectionUtils.isNotEmpty(results)) {
|
||||
|
@ -50,9 +49,9 @@ public class ReportStatusUtil {
|
|||
if (StringUtils.equals(resultVO.getStatus(), ApiReportStatus.ERROR.name())) {
|
||||
return resultVO;
|
||||
}
|
||||
if (MapUtils.isNotEmpty(dto.getArbitraryData()) && dto.getArbitraryData().containsKey(CommonConstants.REPORT_STATUS)) {
|
||||
if (MapUtils.isNotEmpty(dto.getArbitraryData()) && dto.getArbitraryData().containsKey(REPORT_STATUS)) {
|
||||
// 资源池执行整体传输失败,单条传输内容,获取资源池执行统计的状态
|
||||
resultVO.setStatus(JSONUtil.convertValue(dto.getArbitraryData().get(CommonConstants.REPORT_STATUS), ResultVO.class).getStatus());
|
||||
resultVO.setStatus(JsonUtils.convertValue(dto.getArbitraryData().get(REPORT_STATUS), ResultVO.class).getStatus());
|
||||
}
|
||||
// 过滤掉重试结果后进行统计
|
||||
List<RequestResult> requestResults = filterRetryResults(dto.getRequestResults());
|
||||
|
@ -84,13 +83,13 @@ public class ReportStatusUtil {
|
|||
|
||||
public static ResultVO computedProcess(ResultDTO dto) {
|
||||
ResultVO result = new ResultVO();
|
||||
if (MapUtils.isNotEmpty(dto.getArbitraryData()) && dto.getArbitraryData().containsKey(CommonConstants.LOCAL_STATUS_KEY)) {
|
||||
if (MapUtils.isNotEmpty(dto.getArbitraryData()) && dto.getArbitraryData().containsKey(LOCAL_STATUS_KEY)) {
|
||||
// 本地执行状态
|
||||
result = JSONUtil.convertValue(dto.getArbitraryData().get(CommonConstants.LOCAL_STATUS_KEY), ResultVO.class);
|
||||
result = JsonUtils.convertValue(dto.getArbitraryData().get(LOCAL_STATUS_KEY), ResultVO.class);
|
||||
}
|
||||
if (MapUtils.isNotEmpty(dto.getArbitraryData()) && dto.getArbitraryData().containsKey(CommonConstants.REPORT_STATUS)) {
|
||||
if (MapUtils.isNotEmpty(dto.getArbitraryData()) && dto.getArbitraryData().containsKey(REPORT_STATUS)) {
|
||||
// 资源池执行整体传输失败,单条传输内容,获取资源池执行统计的状态
|
||||
result = JSONUtil.convertValue(dto.getArbitraryData().get(CommonConstants.REPORT_STATUS), ResultVO.class);
|
||||
result = JsonUtils.convertValue(dto.getArbitraryData().get(REPORT_STATUS), ResultVO.class);
|
||||
}
|
||||
result = getStatus(dto, result);
|
||||
if (result != null && result.getScenarioTotal() > 0 && result.getScenarioTotal() == result.getScenarioSuccess()) {
|
|
@ -1,4 +1,4 @@
|
|||
package io.metersphere.commons.vo;
|
||||
package io.metersphere.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
|
@ -40,6 +40,7 @@ import org.apache.jmeter.testelement.property.BooleanProperty;
|
|||
import org.apache.jmeter.threads.JMeterVariables;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -148,7 +149,7 @@ public class MsDebugListener extends AbstractListenerElement implements SampleLi
|
|||
SampleResult result = event.getResult();
|
||||
this.setVars(result);
|
||||
if (isSampleWanted(result.isSuccessful(), result) && !StringUtils.equals(result.getSampleLabel(), RunningParamKeys.RUNNING_DEBUG_SAMPLER_NAME)) {
|
||||
RequestResult requestResult = JMeterBase.getRequestResult(result);
|
||||
RequestResult requestResult = JMeterBase.getRequestResult(result, new HashMap<>());
|
||||
if (requestResult != null && ResultParseUtil.isNotAutoGenerateSampler(requestResult)) {
|
||||
MsgDto dto = new MsgDto();
|
||||
dto.setExecEnd(false);
|
||||
|
|
Loading…
Reference in New Issue