fix(接口测试): 禁用接口执行调用自身引发死循环问题

--bug=1019430 --user=赵勇 【接口测试】接口测试中调用接口执行请求传入当前用例、场景ID导致递归调用 https://www.tapd.cn/55049933/s/1295542
This commit is contained in:
fit2-zhao 2022-11-14 15:32:43 +08:00 committed by f2c-ci-robot[bot]
parent bd5a2b66da
commit a92a15dfb3
6 changed files with 81 additions and 8 deletions

View File

@ -10,6 +10,7 @@ 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.exec.utils.GenerateHashTreeUtil;
import io.metersphere.api.exec.utils.PerformInspectionUtil;
import io.metersphere.api.service.ApiCaseResultService;
import io.metersphere.api.service.ApiExecutionQueueService;
import io.metersphere.api.service.ApiScenarioReportStructureService;
@ -222,6 +223,8 @@ public class ApiCaseExecuteService {
example.createCriteria().andIdIn(request.getIds());
List<ApiTestCaseWithBLOBs> caseList = apiTestCaseMapper.selectByExampleWithBLOBs(example);
LoggerUtil.debug("查询到执行数据:" + caseList.size());
// 检查执行内容合规性
PerformInspectionUtil.caseInspection(caseList);
// 环境检查
if (MapUtils.isEmpty(request.getConfig().getEnvMap())) {
this.checkEnv(caseList);

View File

@ -15,6 +15,7 @@ import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
import io.metersphere.api.exec.utils.ApiDefinitionExecResultUtil;
import io.metersphere.api.exec.utils.PerformInspectionUtil;
import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.api.service.ApiTestEnvironmentService;
import io.metersphere.api.service.TcpApiParamService;
@ -103,6 +104,8 @@ public class ApiExecuteService {
public MsExecResponseDTO exec(RunCaseRequest request) {
ApiTestCaseWithBLOBs testCaseWithBLOBs = request.getBloBs();
PerformInspectionUtil.countMatches(testCaseWithBLOBs.getRequest(), testCaseWithBLOBs.getId());
if (StringUtils.equals(request.getRunMode(), ApiRunMode.JENKINS_API_PLAN.name())) {
testCaseWithBLOBs = apiTestCaseMapper.selectByPrimaryKey(request.getReportId());
request.setCaseId(request.getReportId());
@ -179,10 +182,10 @@ public class ApiExecuteService {
}
HashTree hashTree = request.getTestElement().generateHashTree(config);
if (LoggerUtil.getLogger().isDebugEnabled()) {
LoggerUtil.debug("生成执行JMX内容【 " + request.getTestElement().getJmx(hashTree) + "");
}
String jmx = request.getTestElement().getJmx(hashTree);
LoggerUtil.info("生成执行JMX内容【 " + jmx + "");
// 检查执行内容合规性
PerformInspectionUtil.inspection(jmx, testId, 4);
JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(testId, request.getId(), runMode, hashTree);
runRequest.setDebug(request.isDebug());
@ -197,9 +200,10 @@ public class ApiExecuteService {
}
public HashTree generateHashTree(RunCaseRequest request, ApiTestCaseWithBLOBs testCaseWithBLOBs) throws Exception {
PerformInspectionUtil.countMatches(testCaseWithBLOBs.getRequest(), testCaseWithBLOBs.getId());
JSONObject elementObj = JSON.parseObject(testCaseWithBLOBs.getRequest(), Feature.DisableSpecialKeyDetect);
ElementUtil.dataFormatting(elementObj);
MsTestElement element = mapper.readValue(elementObj.toJSONString(), new TypeReference<MsTestElement>() {
});
element.setProjectId(testCaseWithBLOBs.getProjectId());

View File

@ -11,12 +11,15 @@ import io.metersphere.api.dto.definition.request.MsTestPlan;
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.exec.utils.PerformInspectionUtil;
import io.metersphere.api.jmeter.JMeterService;
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.*;
import io.metersphere.base.domain.ApiScenarioExample;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.base.domain.TestPlanApiScenario;
import io.metersphere.base.mapper.ApiScenarioMapper;
import io.metersphere.base.mapper.ApiScenarioReportMapper;
import io.metersphere.base.mapper.TestPlanApiScenarioMapper;
@ -27,7 +30,6 @@ import io.metersphere.commons.constants.ReportTriggerMode;
import io.metersphere.commons.constants.ReportTypeConstants;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.FileUtils;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.ServiceUtils;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.constants.RunModeConstants;
@ -111,6 +113,8 @@ public class ApiScenarioExecuteService {
if (apiScenarios != null && apiScenarios.size() == 1 && (apiScenarios.get(0).getStepTotal() == null || apiScenarios.get(0).getStepTotal() == 0)) {
MSException.throwException((apiScenarios.get(0).getName() + "" + Translator.get("automation_exec_info")));
}
// 检查执行内容合规性
PerformInspectionUtil.scenarioInspection(apiScenarios);
// 环境检查
LoggerUtil.info("Scenario run-执行脚本装载-开始针对所有执行场景进行环境检查");
apiScenarioEnvService.checkEnv(request, apiScenarios);
@ -361,7 +365,9 @@ public class ApiScenarioExecuteService {
FileUtils.createBodyFiles(request.getScenarioFileIds(), scenarioFiles);
this.testElement(request);
hashTree = request.getTestElement().generateHashTree(config);
LogUtil.info(request.getTestElement().getJmx(hashTree));
String jmx = request.getTestElement().getJmx(hashTree);
LoggerUtil.info(jmx);
PerformInspectionUtil.inspection(jmx, request.getScenarioId(), 0);
} catch (Exception e) {
LoggerUtil.error("调试失败", request.getReportId(), e);
MSException.throwException(e.getMessage());

View File

@ -14,6 +14,7 @@ import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
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.exec.utils.PerformInspectionUtil;
import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.api.jmeter.utils.SmoothWeighted;
import io.metersphere.api.service.ApiExecutionQueueService;
@ -196,6 +197,9 @@ public class ApiScenarioSerialService {
}
if (caseWithBLOBs != null) {
String data = caseWithBLOBs.getRequest();
// 检查执行内容合规性
PerformInspectionUtil.countMatches(data, caseWithBLOBs.getId());
HashTree jmeterHashTree = new HashTree();
MsTestPlan testPlan = new MsTestPlan();
testPlan.setHashTree(new LinkedList<>());

View File

@ -120,6 +120,9 @@ public class GenerateHashTreeUtil {
}
public static HashTree generateHashTree(ApiScenarioWithBLOBs item, Map<String, String> planEnvMap, JmeterRunRequestDTO runRequest) {
// 检查执行内容合规性
PerformInspectionUtil.countMatches(item.getScenarioDefinition(), item.getId());
HashTree jmeterHashTree = new HashTree();
MsTestPlan testPlan = new MsTestPlan();
testPlan.setHashTree(new LinkedList<>());

View File

@ -0,0 +1,53 @@
package io.metersphere.api.exec.utils;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
import io.metersphere.commons.exception.MSException;
import io.metersphere.utils.LoggerUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
public class PerformInspectionUtil {
private static final List<String> runPaths = List.of(
"/api/testcase/batch/run", "/api/testcase/jenkins/run",
"/api/definition/run", "/api/definition/run/debug",
"/api/automation/run", "/api/automation/run/debug", "/api/automation/jenkins/run");
public static void countMatches(String content, String checkItem) {
if (StringUtils.isNotBlank(content) && StringUtils.isNotBlank(checkItem) && isPathMatches(content)
&& StringUtils.contains(content, checkItem) && StringUtils.countMatches(content, checkItem) > 1) {
LoggerUtil.error("执行内容含自身信息", content, checkItem);
MSException.throwException("执行内容不能包含自身接口信息");
}
}
public static void inspection(String content, String checkItem, int size) {
if (StringUtils.isNotBlank(content) && StringUtils.isNotBlank(checkItem) && isPathMatches(content)
&& StringUtils.contains(content, checkItem) && StringUtils.countMatches(content, checkItem) > size) {
LoggerUtil.error("执行内容含自身信息", content, checkItem);
MSException.throwException("执行内容不能包含自身接口信息");
}
}
public static void scenarioInspection(List<ApiScenarioWithBLOBs> scenarios) {
if (CollectionUtils.isNotEmpty(scenarios)) {
scenarios.forEach(scenario -> {
countMatches(scenario.getScenarioDefinition(), scenario.getId());
});
}
}
public static void caseInspection(List<ApiTestCaseWithBLOBs> caseList) {
if (CollectionUtils.isNotEmpty(caseList)) {
caseList.forEach(item -> {
inspection(item.getRequest(), item.getId(), 2);
});
}
}
private static boolean isPathMatches(String content) {
return runPaths.stream().filter(path -> StringUtils.contains(content, path)).count() > 0;
}
}