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

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

View File

@ -10,28 +10,24 @@ import io.metersphere.api.dto.scenario.DatabaseConfig;
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
import io.metersphere.api.exec.queue.DBTestQueue;
import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.service.definition.ApiCaseResultService;
import io.metersphere.service.ApiExecutionQueueService;
import io.metersphere.service.scenario.ApiScenarioReportStructureService;
import io.metersphere.commons.enums.ApiReportStatus;
import io.metersphere.commons.utils.ApiDefinitionExecResultUtil;
import io.metersphere.commons.utils.GenerateHashTreeUtil;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
import io.metersphere.base.mapper.ApiTestCaseMapper;
import io.metersphere.base.mapper.plan.TestPlanApiCaseMapper;
import io.metersphere.base.mapper.ext.ExtApiTestCaseMapper;
import io.metersphere.base.mapper.plan.TestPlanApiCaseMapper;
import io.metersphere.commons.constants.*;
import io.metersphere.commons.enums.ApiReportStatus;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.JSON;
import io.metersphere.commons.utils.*;
import io.metersphere.constants.RunModeConstants;
import io.metersphere.dto.MsExecResponseDTO;
import io.metersphere.dto.RunModeConfigDTO;
import io.metersphere.environment.service.BaseEnvGroupProjectService;
import io.metersphere.environment.service.BaseEnvironmentService;
import io.metersphere.service.ApiExecutionQueueService;
import io.metersphere.service.ServiceUtils;
import io.metersphere.service.definition.ApiCaseResultService;
import io.metersphere.service.scenario.ApiScenarioReportStructureService;
import io.metersphere.utils.LoggerUtil;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.CollectionUtils;
@ -288,6 +284,8 @@ public class ApiCaseExecuteService {
List<MsExecResponseDTO> responseDTOS = new LinkedList<>();
List<ApiTestCaseWithBLOBs> caseList = extApiTestCaseMapper.unTrashCaseListByIds(request.getIds());
// 检查执行内容合规性
PerformInspectionUtil.caseInspection(caseList);
LoggerUtil.debug("查询到执行数据:" + caseList.size());
Map<String, List<String>> testCaseEnvMap = new HashMap<>();

View File

@ -119,6 +119,7 @@ public class ApiExecuteService {
public MsExecResponseDTO exec(RunCaseRequest request, Map<String, Object> extendedParameters) {
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());
@ -232,9 +233,10 @@ public class ApiExecuteService {
// 加载自定义JAR
NewDriverManager.loadJar(request);
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());
@ -255,6 +257,7 @@ public class ApiExecuteService {
}
public HashTree generateHashTree(RunCaseRequest request, ApiTestCaseWithBLOBs testCaseWithBLOBs) throws Exception {
PerformInspectionUtil.countMatches(testCaseWithBLOBs.getRequest(), testCaseWithBLOBs.getId());
JSONObject elementObj = JSONUtil.parseObject(testCaseWithBLOBs.getRequest());
ElementUtil.dataFormatting(elementObj);

View File

@ -7,44 +7,36 @@ import io.metersphere.api.dto.automation.ApiScenarioReportResult;
import io.metersphere.api.dto.automation.ExecuteType;
import io.metersphere.api.dto.automation.RunScenarioRequest;
import io.metersphere.api.dto.definition.RunDefinitionRequest;
import io.metersphere.api.dto.definition.request.MsTestPlan;
import io.metersphere.api.dto.definition.request.ParameterConfig;
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.dto.BaseSystemConfigDTO;
import io.metersphere.service.ApiExecutionQueueService;
import io.metersphere.service.SystemParameterService;
import io.metersphere.service.scenario.ApiScenarioReportService;
import io.metersphere.service.scenario.ApiScenarioReportStructureService;
import io.metersphere.service.definition.TcpApiParamService;
import io.metersphere.base.domain.ApiScenario;
import io.metersphere.base.domain.ApiScenarioExample;
import io.metersphere.base.domain.ApiScenarioReportWithBLOBs;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.base.domain.TestPlanApiScenario;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiScenarioMapper;
import io.metersphere.base.mapper.ApiScenarioReportMapper;
import io.metersphere.base.mapper.plan.TestPlanApiScenarioMapper;
import io.metersphere.base.mapper.ext.ExtApiScenarioMapper;
import io.metersphere.base.mapper.plan.TestPlanApiScenarioMapper;
import io.metersphere.base.mapper.plan.ext.ExtTestPlanScenarioCaseMapper;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.ReportTriggerMode;
import io.metersphere.commons.enums.ApiReportStatus;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.FileUtils;
import io.metersphere.commons.utils.JSON;
import io.metersphere.commons.utils.*;
import io.metersphere.constants.RunModeConstants;
import io.metersphere.dto.BaseSystemConfigDTO;
import io.metersphere.dto.JmeterRunRequestDTO;
import io.metersphere.dto.MsExecResponseDTO;
import io.metersphere.dto.RunModeConfigDTO;
import io.metersphere.environment.service.BaseEnvGroupProjectService;
import io.metersphere.i18n.Translator;
import io.metersphere.plugin.core.MsTestElement;
import io.metersphere.service.ApiExecutionQueueService;
import io.metersphere.service.ServiceUtils;
import io.metersphere.commons.utils.GenerateHashTreeUtil;
import io.metersphere.service.SystemParameterService;
import io.metersphere.service.definition.TcpApiParamService;
import io.metersphere.service.scenario.ApiScenarioReportService;
import io.metersphere.service.scenario.ApiScenarioReportStructureService;
import io.metersphere.utils.LoggerUtil;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.CollectionUtils;
@ -58,14 +50,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -128,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);
@ -419,8 +406,11 @@ public class ApiScenarioExecuteService {
HashTree hashTree = request.getTestElement().generateHashTree(config);
String runMode = StringUtils.isEmpty(request.getRunMode()) ? ApiRunMode.SCENARIO.name() : request.getRunMode();
JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(request.getId(), request.getId(), runMode, hashTree);
LoggerUtil.info(new MsTestPlan().getJmx(hashTree));
runRequest.setDebug(true);
String jmx = request.getTestElement().getJmx(hashTree);
LoggerUtil.info(jmx);
PerformInspectionUtil.inspection(jmx, request.getScenarioId(), 0);
if (request.getConfig() != null && StringUtils.isNotEmpty(request.getConfig().getResourcePoolId())) {
runRequest.setPool(GenerateHashTreeUtil.isResourcePool(request.getConfig().getResourcePoolId()));
runRequest.setPoolId(request.getConfig().getResourcePoolId());

View File

@ -123,6 +123,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();
if (!runRequest.getPool().isPool()) {

View File

@ -0,0 +1,53 @@
package io.metersphere.commons.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;
}
}