feat(接口自动化): 修改资源池执行方式,由主动推送数据改为被动拉取。
This commit is contained in:
parent
5bbee94e00
commit
b75e52122a
|
@ -0,0 +1,39 @@
|
||||||
|
package io.metersphere.api.controller;
|
||||||
|
|
||||||
|
import io.metersphere.api.service.ApiJmeterFileService;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/jmeter")
|
||||||
|
public class ApiJmeterFileController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ApiJmeterFileService apiJmeterFileService;
|
||||||
|
|
||||||
|
@GetMapping("download")
|
||||||
|
public ResponseEntity<byte[]> downloadJmeterFiles(@RequestParam("testId") String testId, @RequestParam("reportId") String reportId, @RequestParam("runMode") String runMode, @RequestParam("testPlanScenarioId") String testPlanScenarioId) {
|
||||||
|
byte[] bytes = apiJmeterFileService.downloadJmeterFiles(runMode,testId, reportId, testPlanScenarioId);
|
||||||
|
return ResponseEntity.ok()
|
||||||
|
.contentType(MediaType.parseMediaType("application/octet-stream"))
|
||||||
|
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + testId + ".zip\"")
|
||||||
|
.body(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("download/jar")
|
||||||
|
public ResponseEntity<byte[]> downloadJmeterFiles() {
|
||||||
|
byte[] bytes = apiJmeterFileService.downloadJmeterJar();
|
||||||
|
return ResponseEntity.ok()
|
||||||
|
.contentType(MediaType.parseMediaType("application/octet-stream"))
|
||||||
|
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + UUID.randomUUID().toString() + ".zip\"")
|
||||||
|
.body(bytes);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package io.metersphere.api.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class RunModeDataDTO {
|
||||||
|
// 执行HashTree
|
||||||
|
private HashTree hashTree;
|
||||||
|
// 测试场景/测试用例
|
||||||
|
private String testId;
|
||||||
|
// 报告id
|
||||||
|
private String reportId;
|
||||||
|
public RunModeDataDTO(String testId,String reportId) {
|
||||||
|
this.testId = testId;
|
||||||
|
this.reportId = reportId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RunModeDataDTO(HashTree hashTree,String reportId) {
|
||||||
|
this.hashTree = hashTree;
|
||||||
|
this.reportId = reportId;
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import lombok.Setter;
|
||||||
@Setter
|
@Setter
|
||||||
public class RunRequest {
|
public class RunRequest {
|
||||||
private String testId;
|
private String testId;
|
||||||
|
private String url;
|
||||||
private String userId;
|
private String userId;
|
||||||
private boolean isDebug;
|
private boolean isDebug;
|
||||||
private String runMode;
|
private String runMode;
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package io.metersphere.api.dto.definition;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.automation.RunModeConfig;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class BatchRunDefinitionRequest {
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private List<String> planIds;
|
||||||
|
|
||||||
|
private RunModeConfig config;
|
||||||
|
|
||||||
|
}
|
|
@ -40,8 +40,6 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
|
|
||||||
public final static String TEST_ID = "ms.test.id";
|
public final static String TEST_ID = "ms.test.id";
|
||||||
|
|
||||||
public final static String TEST_REPORT_ID = "ms.test.report.name";
|
|
||||||
|
|
||||||
private final static String THREAD_SPLIT = " ";
|
private final static String THREAD_SPLIT = " ";
|
||||||
|
|
||||||
private final static String ID_SPLIT = "-";
|
private final static String ID_SPLIT = "-";
|
||||||
|
@ -76,8 +74,6 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
private String testId;
|
private String testId;
|
||||||
|
|
||||||
private String debugReportId;
|
private String debugReportId;
|
||||||
// 只有合并报告是这个有值
|
|
||||||
private String setReportId;
|
|
||||||
|
|
||||||
//获得控制台内容
|
//获得控制台内容
|
||||||
private PrintStream oldPrintStream = System.out;
|
private PrintStream oldPrintStream = System.out;
|
||||||
|
@ -156,8 +152,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
TestResult testResult = new TestResult();
|
TestResult testResult = new TestResult();
|
||||||
testResult.setTestId(testId);
|
testResult.setTestId(testId);
|
||||||
testResult.setTotal(queue.size());
|
testResult.setTotal(queue.size());
|
||||||
testResult.setSetReportId(this.setReportId);
|
testResult.setConsole(getConsole());
|
||||||
testResult.setConsole(getConsole());
|
|
||||||
|
|
||||||
// 一个脚本里可能包含多个场景(ThreadGroup),所以要区分开,key: 场景Id
|
// 一个脚本里可能包含多个场景(ThreadGroup),所以要区分开,key: 场景Id
|
||||||
final Map<String, ScenarioResult> scenarios = new LinkedHashMap<>();
|
final Map<String, ScenarioResult> scenarios = new LinkedHashMap<>();
|
||||||
|
@ -506,7 +501,6 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
|
|
||||||
private void setParam(BackendListenerContext context) {
|
private void setParam(BackendListenerContext context) {
|
||||||
this.testId = context.getParameter(TEST_ID);
|
this.testId = context.getParameter(TEST_ID);
|
||||||
this.setReportId = context.getParameter(TEST_REPORT_ID);
|
|
||||||
this.runMode = context.getParameter("runMode");
|
this.runMode = context.getParameter("runMode");
|
||||||
this.debugReportId = context.getParameter("debugReportId");
|
this.debugReportId = context.getParameter("debugReportId");
|
||||||
if (StringUtils.isBlank(this.runMode)) {
|
if (StringUtils.isBlank(this.runMode)) {
|
||||||
|
|
|
@ -3,13 +3,11 @@ package io.metersphere.api.jmeter;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import io.metersphere.api.dto.RunRequest;
|
import io.metersphere.api.dto.RunRequest;
|
||||||
import io.metersphere.api.dto.automation.RunModeConfig;
|
import io.metersphere.api.dto.automation.RunModeConfig;
|
||||||
import io.metersphere.api.dto.definition.request.MsTestPlan;
|
|
||||||
import io.metersphere.api.dto.scenario.request.BodyFile;
|
import io.metersphere.api.dto.scenario.request.BodyFile;
|
||||||
import io.metersphere.api.service.ApiScenarioReportService;
|
import io.metersphere.api.service.ApiScenarioReportService;
|
||||||
import io.metersphere.base.domain.JarConfig;
|
import io.metersphere.base.domain.JarConfig;
|
||||||
import io.metersphere.base.domain.TestResource;
|
import io.metersphere.base.domain.TestResource;
|
||||||
import io.metersphere.commons.constants.ApiRunMode;
|
import io.metersphere.commons.constants.ApiRunMode;
|
||||||
import io.metersphere.commons.constants.RunModeConstants;
|
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.commons.utils.*;
|
import io.metersphere.commons.utils.*;
|
||||||
import io.metersphere.config.JmeterProperties;
|
import io.metersphere.config.JmeterProperties;
|
||||||
|
@ -31,13 +29,8 @@ import org.apache.jorphan.collections.HashTree;
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
import org.springframework.core.io.FileSystemResource;
|
import org.springframework.core.io.FileSystemResource;
|
||||||
import org.springframework.http.HttpEntity;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
|
||||||
import org.springframework.util.MultiValueMap;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
|
@ -47,7 +40,10 @@ import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class JMeterService {
|
public class JMeterService {
|
||||||
|
@ -125,10 +121,6 @@ public class JMeterService {
|
||||||
BackendListener backendListener = new BackendListener();
|
BackendListener backendListener = new BackendListener();
|
||||||
backendListener.setName(testId);
|
backendListener.setName(testId);
|
||||||
Arguments arguments = new Arguments();
|
Arguments arguments = new Arguments();
|
||||||
if (config != null && config.getMode().equals(RunModeConstants.SERIAL.toString()) && config.getReportType().equals(RunModeConstants.SET_REPORT.toString())) {
|
|
||||||
arguments.addArgument(APIBackendListenerClient.TEST_REPORT_ID, config.getReportId());
|
|
||||||
|
|
||||||
}
|
|
||||||
arguments.addArgument(APIBackendListenerClient.TEST_ID, testId);
|
arguments.addArgument(APIBackendListenerClient.TEST_ID, testId);
|
||||||
if (StringUtils.isNotBlank(runMode)) {
|
if (StringUtils.isNotBlank(runMode)) {
|
||||||
arguments.addArgument("runMode", runMode);
|
arguments.addArgument("runMode", runMode);
|
||||||
|
@ -141,6 +133,16 @@ public class JMeterService {
|
||||||
testPlan.add(testPlan.getArray()[0], backendListener);
|
testPlan.add(testPlan.getArray()[0], backendListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addBackendListener(String testId, HashTree testPlan) {
|
||||||
|
BackendListener backendListener = new BackendListener();
|
||||||
|
backendListener.setName(testId);
|
||||||
|
Arguments arguments = new Arguments();
|
||||||
|
arguments.addArgument(APIBackendListenerClient.TEST_ID, testId);
|
||||||
|
backendListener.setArguments(arguments);
|
||||||
|
backendListener.setClassname(APIBackendListenerClient.class.getCanonicalName());
|
||||||
|
testPlan.add(testPlan.getArray()[0], backendListener);
|
||||||
|
}
|
||||||
|
|
||||||
public void runDefinition(String testId, HashTree testPlan, String debugReportId, String runMode) {
|
public void runDefinition(String testId, HashTree testPlan, String debugReportId, String runMode) {
|
||||||
try {
|
try {
|
||||||
init();
|
init();
|
||||||
|
@ -198,7 +200,7 @@ public class JMeterService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] fileToByte(File tradeFile) {
|
public byte[] fileToByte(File tradeFile) {
|
||||||
byte[] buffer = null;
|
byte[] buffer = null;
|
||||||
try (FileInputStream fis = new FileInputStream(tradeFile);
|
try (FileInputStream fis = new FileInputStream(tradeFile);
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();) {
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();) {
|
||||||
|
@ -213,7 +215,7 @@ public class JMeterService {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Object> getZipJar() {
|
public List<Object> getZipJar() {
|
||||||
List<Object> jarFiles = new LinkedList<>();
|
List<Object> jarFiles = new LinkedList<>();
|
||||||
// jar 包
|
// jar 包
|
||||||
JarConfigService jarConfigService = CommonBeanFactory.getBean(JarConfigService.class);
|
JarConfigService jarConfigService = CommonBeanFactory.getBean(JarConfigService.class);
|
||||||
|
@ -249,7 +251,7 @@ public class JMeterService {
|
||||||
return jarFiles;
|
return jarFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Object> getJar() {
|
public List<Object> getJar() {
|
||||||
List<Object> jarFiles = new LinkedList<>();
|
List<Object> jarFiles = new LinkedList<>();
|
||||||
// jar 包
|
// jar 包
|
||||||
JarConfigService jarConfigService = CommonBeanFactory.getBean(JarConfigService.class);
|
JarConfigService jarConfigService = CommonBeanFactory.getBean(JarConfigService.class);
|
||||||
|
@ -280,7 +282,7 @@ public class JMeterService {
|
||||||
return jarFiles;
|
return jarFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Object> getMultipartFiles(HashTree hashTree) {
|
public List<Object> getMultipartFiles(HashTree hashTree) {
|
||||||
List<Object> multipartFiles = new LinkedList<>();
|
List<Object> multipartFiles = new LinkedList<>();
|
||||||
// 获取附件
|
// 获取附件
|
||||||
List<BodyFile> files = new LinkedList<>();
|
List<BodyFile> files = new LinkedList<>();
|
||||||
|
@ -306,12 +308,7 @@ public class JMeterService {
|
||||||
return multipartFiles;
|
return multipartFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void runTest(String testId, HashTree hashTree, String runMode, boolean isDebug, RunModeConfig config) {
|
public void runTest(String testId, String reportId, String runMode, String testPlanScenarioId, RunModeConfig config) {
|
||||||
// 获取JMX使用到的附件
|
|
||||||
List<Object> multipartFiles = getMultipartFiles(hashTree);
|
|
||||||
// 获取JAR
|
|
||||||
List<Object> jarFiles = getJar();
|
|
||||||
|
|
||||||
// 获取可以执行的资源池
|
// 获取可以执行的资源池
|
||||||
String resourcePoolId = config.getResourcePoolId();
|
String resourcePoolId = config.getResourcePoolId();
|
||||||
TestResource testResource = resourcePoolCalculation.getPool(resourcePoolId);
|
TestResource testResource = resourcePoolCalculation.getPool(resourcePoolId);
|
||||||
|
@ -327,54 +324,26 @@ public class JMeterService {
|
||||||
if (baseInfo != null) {
|
if (baseInfo != null) {
|
||||||
metersphereUrl = baseInfo.getUrl();
|
metersphereUrl = baseInfo.getUrl();
|
||||||
}
|
}
|
||||||
// 检查≈地址是否正确
|
|
||||||
String jmeterPingUrl = metersphereUrl + "/jmeter/ping";
|
|
||||||
// docker 不能从 localhost 中下载文件
|
|
||||||
if (StringUtils.contains(metersphereUrl, "http://localhost")
|
|
||||||
|| !UrlTestUtils.testUrlWithTimeOut(jmeterPingUrl, 1000)) {
|
|
||||||
MSException.throwException(Translator.get("run_load_test_file_init_error"));
|
|
||||||
}
|
|
||||||
|
|
||||||
String uri = String.format(BASE_URL + "/jmeter/api/run", nodeIp, port);
|
|
||||||
try {
|
try {
|
||||||
File file = new File(FileUtils.BODY_FILE_DIR + "/tmp");
|
|
||||||
if (!file.exists()) {
|
|
||||||
file.createNewFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
RunRequest runRequest = new RunRequest();
|
RunRequest runRequest = new RunRequest();
|
||||||
runRequest.setTestId(testId);
|
runRequest.setTestId(testId);
|
||||||
runRequest.setDebug(isDebug);
|
metersphereUrl += "/api/jmeter/download?testId=" + testId + "&reportId=" + reportId + "&testPlanScenarioId" + "&runMode=" + runMode;
|
||||||
|
if (StringUtils.isNotEmpty(testPlanScenarioId)) {
|
||||||
|
metersphereUrl += "=" + testPlanScenarioId;
|
||||||
|
}
|
||||||
|
runRequest.setUrl(metersphereUrl);
|
||||||
runRequest.setRunMode(runMode);
|
runRequest.setRunMode(runMode);
|
||||||
runRequest.setConfig(config);
|
String uri = String.format(BASE_URL + "/jmeter/api/start", nodeIp, port);
|
||||||
runRequest.setUserId(Objects.requireNonNull(SessionUtils.getUser()).getId());
|
ResponseEntity<String> result = restTemplate.postForEntity(uri, runRequest, String.class);
|
||||||
runRequest.setJmx(new MsTestPlan().getJmx(hashTree));
|
|
||||||
MultiValueMap<String, Object> postParameters = new LinkedMultiValueMap<>();
|
|
||||||
if (CollectionUtils.isEmpty(multipartFiles)) {
|
|
||||||
multipartFiles.add(new FileSystemResource(file));
|
|
||||||
}
|
|
||||||
if (CollectionUtils.isEmpty(jarFiles)) {
|
|
||||||
jarFiles.add(new FileSystemResource(file));
|
|
||||||
}
|
|
||||||
postParameters.put("files", multipartFiles);
|
|
||||||
postParameters.put("jarFiles", jarFiles);
|
|
||||||
postParameters.add("request", JSON.toJSONString(runRequest));
|
|
||||||
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
|
|
||||||
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN));
|
|
||||||
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(postParameters, headers);
|
|
||||||
|
|
||||||
ResponseEntity<String> result = restTemplate.postForEntity(uri, request, String.class);
|
|
||||||
if (result == null || !StringUtils.equals("SUCCESS", result.getBody())) {
|
if (result == null || !StringUtils.equals("SUCCESS", result.getBody())) {
|
||||||
// 清理零时报告
|
// 清理零时报告
|
||||||
ApiScenarioReportService apiScenarioReportService = CommonBeanFactory.getBean(ApiScenarioReportService.class);
|
ApiScenarioReportService apiScenarioReportService = CommonBeanFactory.getBean(ApiScenarioReportService.class);
|
||||||
apiScenarioReportService.delete(testId);
|
apiScenarioReportService.delete(reportId);
|
||||||
MSException.throwException("执行失败:" + result);
|
MSException.throwException("执行失败:" + result);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
MSException.throwException("Please check node-controller status.");
|
MSException.throwException(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,6 @@ public class TestResult {
|
||||||
|
|
||||||
private String testId;
|
private String testId;
|
||||||
|
|
||||||
private String setReportId;
|
|
||||||
|
|
||||||
private int scenarioTotal;
|
private int scenarioTotal;
|
||||||
|
|
||||||
private int scenarioSuccess;
|
private int scenarioSuccess;
|
||||||
|
|
|
@ -776,7 +776,7 @@ public class ApiAutomationService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HashTree generateHashTree(ApiScenarioWithBLOBs item, String reportId, Map<String, String> planEnvMap) {
|
public HashTree generateHashTree(ApiScenarioWithBLOBs item, String reportId, Map<String, String> planEnvMap) {
|
||||||
HashTree jmeterHashTree = new HashTree();
|
HashTree jmeterHashTree = new HashTree();
|
||||||
MsTestPlan testPlan = new MsTestPlan();
|
MsTestPlan testPlan = new MsTestPlan();
|
||||||
testPlan.setHashTree(new LinkedList<>());
|
testPlan.setHashTree(new LinkedList<>());
|
||||||
|
@ -903,7 +903,7 @@ public class ApiAutomationService {
|
||||||
request.setTriggerMode(ReportTriggerMode.MANUAL.name());
|
request.setTriggerMode(ReportTriggerMode.MANUAL.name());
|
||||||
}
|
}
|
||||||
String reportId = request.getId();
|
String reportId = request.getId();
|
||||||
Map<APIScenarioReportResult, HashTree> map = new LinkedHashMap<>();
|
Map<APIScenarioReportResult, RunModeDataDTO> map = new LinkedHashMap<>();
|
||||||
List<String> scenarioIds = new ArrayList<>();
|
List<String> scenarioIds = new ArrayList<>();
|
||||||
StringBuilder scenarioNames = new StringBuilder();
|
StringBuilder scenarioNames = new StringBuilder();
|
||||||
// 按照场景执行
|
// 按照场景执行
|
||||||
|
@ -928,19 +928,23 @@ public class ApiAutomationService {
|
||||||
if (request.isTestPlanScheduleJob()) {
|
if (request.isTestPlanScheduleJob()) {
|
||||||
String savedScenarioId = testPlanScenarioId + ":" + request.getTestPlanReportId();
|
String savedScenarioId = testPlanScenarioId + ":" + request.getTestPlanReportId();
|
||||||
report = createScenarioReport(reportId, savedScenarioId, item.getName(), request.getTriggerMode(),
|
report = createScenarioReport(reportId, savedScenarioId, item.getName(), request.getTriggerMode(),
|
||||||
request.getExecuteType(), item.getProjectId(), request.getReportUserID(),request.getConfig());
|
request.getExecuteType(), item.getProjectId(), request.getReportUserID(), request.getConfig());
|
||||||
} else {
|
} else {
|
||||||
report = createScenarioReport(reportId, testPlanScenarioId, item.getName(), request.getTriggerMode(),
|
report = createScenarioReport(reportId, testPlanScenarioId, item.getName(), request.getTriggerMode(),
|
||||||
request.getExecuteType(), item.getProjectId(), request.getReportUserID(),request.getConfig());
|
request.getExecuteType(), item.getProjectId(), request.getReportUserID(), request.getConfig());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
report = createScenarioReport(reportId, ExecuteType.Marge.name().equals(request.getExecuteType()) ? serialReportId : item.getId(), item.getName(), request.getTriggerMode(),
|
report = createScenarioReport(reportId, ExecuteType.Marge.name().equals(request.getExecuteType()) ? serialReportId : item.getId(), item.getName(), request.getTriggerMode(),
|
||||||
request.getExecuteType(), item.getProjectId(), request.getReportUserID(),request.getConfig());
|
request.getExecuteType(), item.getProjectId(), request.getReportUserID(), request.getConfig());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// 生成报告和HashTree
|
if (request.getConfig() != null && StringUtils.isNotBlank(request.getConfig().getResourcePoolId())) {
|
||||||
HashTree hashTree = generateHashTree(item, reportId, planEnvMap);
|
map.put(report, new RunModeDataDTO(item.getId(), report.getId()));
|
||||||
map.put(report, hashTree);
|
} else {
|
||||||
|
// 生成报告和HashTree
|
||||||
|
HashTree hashTree = generateHashTree(item, reportId, planEnvMap);
|
||||||
|
map.put(report, new RunModeDataDTO(hashTree, report.getId()));
|
||||||
|
}
|
||||||
scenarioIds.add(item.getId());
|
scenarioIds.add(item.getId());
|
||||||
scenarioNames.append(item.getName()).append(",");
|
scenarioNames.append(item.getName()).append(",");
|
||||||
// 重置报告ID
|
// 重置报告ID
|
||||||
|
@ -953,7 +957,7 @@ public class ApiAutomationService {
|
||||||
if (request.getConfig() != null && StringUtils.equals(request.getConfig().getReportType(), RunModeConstants.SET_REPORT.toString()) && StringUtils.isNotEmpty(request.getConfig().getReportName())) {
|
if (request.getConfig() != null && StringUtils.equals(request.getConfig().getReportType(), RunModeConstants.SET_REPORT.toString()) && StringUtils.isNotEmpty(request.getConfig().getReportName())) {
|
||||||
request.getConfig().setReportId(UUID.randomUUID().toString());
|
request.getConfig().setReportId(UUID.randomUUID().toString());
|
||||||
APIScenarioReportResult report = createScenarioReport(request.getConfig().getReportId(), JSON.toJSONString(scenarioIds), scenarioNames.deleteCharAt(scenarioNames.toString().length() - 1).toString(), ReportTriggerMode.MANUAL.name(),
|
APIScenarioReportResult report = createScenarioReport(request.getConfig().getReportId(), JSON.toJSONString(scenarioIds), scenarioNames.deleteCharAt(scenarioNames.toString().length() - 1).toString(), ReportTriggerMode.MANUAL.name(),
|
||||||
ExecuteType.Saved.name(), request.getProjectId(), request.getReportUserID(),request.getConfig());
|
ExecuteType.Saved.name(), request.getProjectId(), request.getReportUserID(), request.getConfig());
|
||||||
report.setName(request.getConfig().getReportName());
|
report.setName(request.getConfig().getReportName());
|
||||||
report.setId(serialReportId);
|
report.setId(serialReportId);
|
||||||
apiScenarioReportMapper.insert(report);
|
apiScenarioReportMapper.insert(report);
|
||||||
|
@ -974,7 +978,7 @@ public class ApiAutomationService {
|
||||||
return request.getId();
|
return request.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void run(Map<APIScenarioReportResult, HashTree> map, RunScenarioRequest request, String serialReportId) {
|
private void run(Map<APIScenarioReportResult, RunModeDataDTO> map, RunScenarioRequest request, String serialReportId) {
|
||||||
// 开始选择执行模式
|
// 开始选择执行模式
|
||||||
ExecutorService executorService = Executors.newFixedThreadPool(map.size());
|
ExecutorService executorService = Executors.newFixedThreadPool(map.size());
|
||||||
if (request.getConfig() != null && request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) {
|
if (request.getConfig() != null && request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) {
|
||||||
|
@ -987,7 +991,7 @@ public class ApiAutomationService {
|
||||||
apiScenarioReportMapper.insert(key);
|
apiScenarioReportMapper.insert(key);
|
||||||
reportIds.add(key.getId());
|
reportIds.add(key.getId());
|
||||||
try {
|
try {
|
||||||
Future<ApiScenarioReport> future = executorService.submit(new SerialScenarioExecTask(jMeterService, apiScenarioReportMapper, key.getId(), map.get(key), request));
|
Future<ApiScenarioReport> future = executorService.submit(new SerialScenarioExecTask(jMeterService, apiScenarioReportMapper, map.get(key), request));
|
||||||
ApiScenarioReport report = future.get();
|
ApiScenarioReport report = future.get();
|
||||||
// 如果开启失败结束执行,则判断返回结果状态
|
// 如果开启失败结束执行,则判断返回结果状态
|
||||||
if (request.getConfig().isOnSampleError()) {
|
if (request.getConfig().isOnSampleError()) {
|
||||||
|
@ -1015,7 +1019,7 @@ public class ApiAutomationService {
|
||||||
for (APIScenarioReportResult report : map.keySet()) {
|
for (APIScenarioReportResult report : map.keySet()) {
|
||||||
//存储报告
|
//存储报告
|
||||||
batchMapper.insert(report);
|
batchMapper.insert(report);
|
||||||
executorService.submit(new ParallelScenarioExecTask(jMeterService, report.getId(), map.get(report), request));
|
executorService.submit(new ParallelScenarioExecTask(jMeterService, map.get(report), request));
|
||||||
}
|
}
|
||||||
sqlSession.flushStatements();
|
sqlSession.flushStatements();
|
||||||
}
|
}
|
||||||
|
@ -1095,14 +1099,14 @@ public class ApiAutomationService {
|
||||||
if (request.isTestPlanScheduleJob()) {
|
if (request.isTestPlanScheduleJob()) {
|
||||||
String savedScenarioId = testPlanScenarioId + ":" + request.getTestPlanReportId();
|
String savedScenarioId = testPlanScenarioId + ":" + request.getTestPlanReportId();
|
||||||
report = createScenarioReport(group.getName(), savedScenarioId, item.getName(), request.getTriggerMode(),
|
report = createScenarioReport(group.getName(), savedScenarioId, item.getName(), request.getTriggerMode(),
|
||||||
request.getExecuteType(), item.getProjectId(), request.getReportUserID(),request.getConfig());
|
request.getExecuteType(), item.getProjectId(), request.getReportUserID(), request.getConfig());
|
||||||
} else {
|
} else {
|
||||||
report = createScenarioReport(group.getName(), testPlanScenarioId, item.getName(), request.getTriggerMode() == null ? ReportTriggerMode.MANUAL.name() : request.getTriggerMode(),
|
report = createScenarioReport(group.getName(), testPlanScenarioId, item.getName(), request.getTriggerMode() == null ? ReportTriggerMode.MANUAL.name() : request.getTriggerMode(),
|
||||||
request.getExecuteType(), item.getProjectId(), request.getReportUserID(),request.getConfig());
|
request.getExecuteType(), item.getProjectId(), request.getReportUserID(), request.getConfig());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
report = createScenarioReport(group.getName(), item.getId(), item.getName(), request.getTriggerMode() == null ? ReportTriggerMode.MANUAL.name() : request.getTriggerMode(),
|
report = createScenarioReport(group.getName(), item.getId(), item.getName(), request.getTriggerMode() == null ? ReportTriggerMode.MANUAL.name() : request.getTriggerMode(),
|
||||||
request.getExecuteType(), item.getProjectId(), request.getReportUserID(),request.getConfig());
|
request.getExecuteType(), item.getProjectId(), request.getReportUserID(), request.getConfig());
|
||||||
}
|
}
|
||||||
batchMapper.insert(report);
|
batchMapper.insert(report);
|
||||||
reportIds.add(group.getName());
|
reportIds.add(group.getName());
|
||||||
|
@ -1223,12 +1227,7 @@ public class ApiAutomationService {
|
||||||
List<String> reportIds = new LinkedList<>();
|
List<String> reportIds = new LinkedList<>();
|
||||||
try {
|
try {
|
||||||
HashTree hashTree = generateHashTree(apiScenarios, request, reportIds);
|
HashTree hashTree = generateHashTree(apiScenarios, request, reportIds);
|
||||||
if (request.getConfig() != null && StringUtils.isNotBlank(request.getConfig().getResourcePoolId())) {
|
jMeterService.runSerial(JSON.toJSONString(reportIds), hashTree, request.getReportId(), runMode, request.getConfig());
|
||||||
jMeterService.runTest(JSON.toJSONString(reportIds), hashTree, runMode, false, request.getConfig());
|
|
||||||
} else {
|
|
||||||
jMeterService.runSerial(JSON.toJSONString(reportIds), hashTree, request.getReportId(), runMode, request.getConfig());
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtil.error(e.getMessage());
|
LogUtil.error(e.getMessage());
|
||||||
MSException.throwException(e.getMessage());
|
MSException.throwException(e.getMessage());
|
||||||
|
@ -1322,7 +1321,7 @@ public class ApiAutomationService {
|
||||||
}
|
}
|
||||||
|
|
||||||
APIScenarioReportResult report = createScenarioReport(request.getId(), request.getScenarioId(), request.getScenarioName(), ReportTriggerMode.MANUAL.name(), request.getExecuteType(), request.getProjectId(),
|
APIScenarioReportResult report = createScenarioReport(request.getId(), request.getScenarioId(), request.getScenarioName(), ReportTriggerMode.MANUAL.name(), request.getExecuteType(), request.getProjectId(),
|
||||||
SessionUtils.getUserId(),request.getConfig());
|
SessionUtils.getUserId(), request.getConfig());
|
||||||
apiScenarioReportMapper.insert(report);
|
apiScenarioReportMapper.insert(report);
|
||||||
|
|
||||||
uploadBodyFiles(request.getBodyFileRequestIds(), bodyFiles);
|
uploadBodyFiles(request.getBodyFileRequestIds(), bodyFiles);
|
||||||
|
|
|
@ -589,7 +589,7 @@ public class ApiDefinitionService {
|
||||||
|
|
||||||
// 调用执行方法
|
// 调用执行方法
|
||||||
if (request.getConfig() != null && StringUtils.isNotBlank(request.getConfig().getResourcePoolId())) {
|
if (request.getConfig() != null && StringUtils.isNotBlank(request.getConfig().getResourcePoolId())) {
|
||||||
jMeterService.runTest(request.getId(), hashTree, runMode, request.getReportId() != null, request.getConfig());
|
jMeterService.runTest(request.getId(), request.getId(), runMode, null, request.getConfig());
|
||||||
} else {
|
} else {
|
||||||
jMeterService.runDefinition(request.getId(), hashTree, request.getReportId(), runMode);
|
jMeterService.runDefinition(request.getId(), hashTree, request.getReportId(), runMode);
|
||||||
}
|
}
|
||||||
|
@ -637,6 +637,7 @@ public class ApiDefinitionService {
|
||||||
ApiDefinitionExecResult result = extApiDefinitionExecResultMapper.selectMaxResultByResourceId(testId);
|
ApiDefinitionExecResult result = extApiDefinitionExecResultMapper.selectMaxResultByResourceId(testId);
|
||||||
return buildAPIReportResult(result);
|
return buildAPIReportResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public APIReportResult getReportById(String testId) {
|
public APIReportResult getReportById(String testId) {
|
||||||
ApiDefinitionExecResult result = apiDefinitionExecResultMapper.selectByPrimaryKey(testId);
|
ApiDefinitionExecResult result = apiDefinitionExecResultMapper.selectByPrimaryKey(testId);
|
||||||
return buildAPIReportResult(result);
|
return buildAPIReportResult(result);
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
package io.metersphere.api.service;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import io.metersphere.api.dto.definition.request.MsTestPlan;
|
||||||
|
import io.metersphere.api.dto.scenario.request.BodyFile;
|
||||||
|
import io.metersphere.api.jmeter.JMeterService;
|
||||||
|
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
|
||||||
|
import io.metersphere.base.domain.JarConfig;
|
||||||
|
import io.metersphere.base.domain.TestPlanApiScenario;
|
||||||
|
import io.metersphere.base.mapper.ApiScenarioMapper;
|
||||||
|
import io.metersphere.base.mapper.TestPlanApiScenarioMapper;
|
||||||
|
import io.metersphere.commons.constants.ApiRunMode;
|
||||||
|
import io.metersphere.commons.exception.MSException;
|
||||||
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
|
import io.metersphere.service.JarConfigService;
|
||||||
|
import io.metersphere.track.service.TestPlanApiCaseService;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ApiJmeterFileService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ApiAutomationService apiAutomationService;
|
||||||
|
@Resource
|
||||||
|
private TestPlanApiCaseService testPlanApiCaseService;
|
||||||
|
@Resource
|
||||||
|
private TestPlanApiScenarioMapper testPlanApiScenarioMapper;
|
||||||
|
@Resource
|
||||||
|
private ApiScenarioMapper apiScenarioMapper;
|
||||||
|
@Resource
|
||||||
|
private JMeterService jMeterService;
|
||||||
|
|
||||||
|
public byte[] downloadJmeterFiles(String runMode, String testId, String reportId, String testPlanScenarioId) {
|
||||||
|
Map<String, String> planEnvMap = new HashMap<>();
|
||||||
|
if (StringUtils.isNotEmpty(testPlanScenarioId)) {
|
||||||
|
// 获取场景用例单独的执行环境
|
||||||
|
TestPlanApiScenario planApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(testPlanScenarioId);
|
||||||
|
String environment = planApiScenario.getEnvironment();
|
||||||
|
if (StringUtils.isNotBlank(environment)) {
|
||||||
|
planEnvMap = JSON.parseObject(environment, Map.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HashTree hashTree = null;
|
||||||
|
if (ApiRunMode.DEFINITION.name().equals(runMode) || ApiRunMode.API_PLAN.name().equals(runMode)) {
|
||||||
|
hashTree = testPlanApiCaseService.generateHashTree(testId);
|
||||||
|
} else {
|
||||||
|
ApiScenarioWithBLOBs item = apiScenarioMapper.selectByPrimaryKey(testId);
|
||||||
|
if (item == null) {
|
||||||
|
MSException.throwException("未找到执行场景。");
|
||||||
|
}
|
||||||
|
hashTree = apiAutomationService.generateHashTree(item, reportId, planEnvMap);
|
||||||
|
}
|
||||||
|
//jMeterService.addBackendListener(reportId, hashTree);
|
||||||
|
return zipFilesToByteArray(testId, hashTree);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] downloadJmeterJar() {
|
||||||
|
Map<String, byte[]> files = new HashMap<>();
|
||||||
|
// 获取JAR
|
||||||
|
Map<String, byte[]> jarFiles = this.getJar();
|
||||||
|
if (!com.alibaba.excel.util.CollectionUtils.isEmpty(jarFiles)) {
|
||||||
|
for (String k : jarFiles.keySet()) {
|
||||||
|
byte[] v = jarFiles.get(k);
|
||||||
|
files.put(k, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return listBytesToZip(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, byte[]> getJar() {
|
||||||
|
Map<String, byte[]> jarFiles = new LinkedHashMap<>();
|
||||||
|
// jar 包
|
||||||
|
JarConfigService jarConfigService = CommonBeanFactory.getBean(JarConfigService.class);
|
||||||
|
List<JarConfig> jars = jarConfigService.list();
|
||||||
|
jars.forEach(jarConfig -> {
|
||||||
|
try {
|
||||||
|
String path = jarConfig.getPath();
|
||||||
|
File file = new File(path);
|
||||||
|
if (file.isDirectory() && !path.endsWith("/")) {
|
||||||
|
file = new File(path + "/");
|
||||||
|
}
|
||||||
|
byte[] fileByte = jMeterService.fileToByte(file);
|
||||||
|
if (fileByte != null) {
|
||||||
|
jarFiles.put(file.getName(), fileByte);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return jarFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, byte[]> getMultipartFiles(HashTree hashTree) {
|
||||||
|
Map<String, byte[]> multipartFiles = new LinkedHashMap<>();
|
||||||
|
// 获取附件
|
||||||
|
List<BodyFile> files = new LinkedList<>();
|
||||||
|
jMeterService.getFiles(hashTree, files);
|
||||||
|
if (CollectionUtils.isNotEmpty(files)) {
|
||||||
|
for (BodyFile bodyFile : files) {
|
||||||
|
File file = new File(bodyFile.getName());
|
||||||
|
if (file != null && !file.exists()) {
|
||||||
|
byte[] fileByte = jMeterService.fileToByte(file);
|
||||||
|
if (fileByte != null) {
|
||||||
|
multipartFiles.put(file.getName(), fileByte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return multipartFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] zipFilesToByteArray(String testId, HashTree hashTree) {
|
||||||
|
String fileName = testId + ".jmx";
|
||||||
|
String jmx = new MsTestPlan().getJmx(hashTree);
|
||||||
|
Map<String, byte[]> files = new HashMap<>();
|
||||||
|
// 每个测试生成一个文件夹
|
||||||
|
files.put(fileName, jmx.getBytes(StandardCharsets.UTF_8));
|
||||||
|
// 获取JMX使用到的附件
|
||||||
|
Map<String, byte[]> multipartFiles = this.getMultipartFiles(hashTree);
|
||||||
|
if (!com.alibaba.excel.util.CollectionUtils.isEmpty(multipartFiles)) {
|
||||||
|
for (String k : multipartFiles.keySet()) {
|
||||||
|
byte[] v = multipartFiles.get(k);
|
||||||
|
files.put(k, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return listBytesToZip(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] listBytesToZip(Map<String, byte[]> mapReport) {
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
ZipOutputStream zos = new ZipOutputStream(baos);
|
||||||
|
for (Map.Entry<String, byte[]> report : mapReport.entrySet()) {
|
||||||
|
ZipEntry entry = new ZipEntry(report.getKey());
|
||||||
|
entry.setSize(report.getValue().length);
|
||||||
|
zos.putNextEntry(entry);
|
||||||
|
zos.write(report.getValue());
|
||||||
|
}
|
||||||
|
zos.closeEntry();
|
||||||
|
zos.close();
|
||||||
|
return baos.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -358,33 +358,6 @@ public class ApiScenarioReportService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void margeReport(TestResult result, StringBuilder scenarioIds, StringBuilder scenarioNames, String runMode, String projectId, String userId, List<String> reportIds) {
|
|
||||||
// 合并生成一份报告
|
|
||||||
if (StringUtils.isNotEmpty(result.getSetReportId())) {
|
|
||||||
// 清理其他报告保留一份合并后的报告
|
|
||||||
this.deleteByIds(reportIds);
|
|
||||||
|
|
||||||
ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(result.getSetReportId());
|
|
||||||
report.setStatus(result.getError() > 0 ? "Error" : "Success");
|
|
||||||
if (StringUtils.isNotEmpty(userId)) {
|
|
||||||
report.setUserId(userId);
|
|
||||||
} else {
|
|
||||||
report.setUserId(SessionUtils.getUserId());
|
|
||||||
}
|
|
||||||
report.setExecuteType(ExecuteType.Saved.name());
|
|
||||||
report.setProjectId(projectId);
|
|
||||||
report.setScenarioName(scenarioNames.toString().substring(0, scenarioNames.toString().length() - 1));
|
|
||||||
report.setScenarioId(scenarioIds.toString());
|
|
||||||
apiScenarioReportMapper.updateByPrimaryKey(report);
|
|
||||||
ApiScenarioReportDetail detail = new ApiScenarioReportDetail();
|
|
||||||
detail.setContent(JSON.toJSONString(result).getBytes(StandardCharsets.UTF_8));
|
|
||||||
detail.setReportId(report.getId());
|
|
||||||
detail.setProjectId(report.getProjectId());
|
|
||||||
apiScenarioReportDetailMapper.insert(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void margeReport(String reportId, List<String> reportIds) {
|
public void margeReport(String reportId, List<String> reportIds) {
|
||||||
// 合并生成一份报告
|
// 合并生成一份报告
|
||||||
if (CollectionUtils.isNotEmpty(reportIds)) {
|
if (CollectionUtils.isNotEmpty(reportIds)) {
|
||||||
|
|
|
@ -3,35 +3,33 @@
|
||||||
*/
|
*/
|
||||||
package io.metersphere.api.service.task;
|
package io.metersphere.api.service.task;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.RunModeDataDTO;
|
||||||
import io.metersphere.api.dto.automation.RunScenarioRequest;
|
import io.metersphere.api.dto.automation.RunScenarioRequest;
|
||||||
import io.metersphere.api.jmeter.JMeterService;
|
import io.metersphere.api.jmeter.JMeterService;
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.commons.utils.LogUtil;
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.jorphan.collections.HashTree;
|
|
||||||
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
public class ParallelScenarioExecTask<T> implements Callable<T> {
|
public class ParallelScenarioExecTask<T> implements Callable<T> {
|
||||||
private RunScenarioRequest request;
|
private RunScenarioRequest request;
|
||||||
private JMeterService jMeterService;
|
private JMeterService jMeterService;
|
||||||
private HashTree hashTree;
|
private RunModeDataDTO runModeDataDTO;
|
||||||
private String id;
|
|
||||||
|
|
||||||
public ParallelScenarioExecTask(JMeterService jMeterService, String id, HashTree hashTree, RunScenarioRequest request) {
|
public ParallelScenarioExecTask(JMeterService jMeterService, RunModeDataDTO runModeDataDTO, RunScenarioRequest request) {
|
||||||
this.jMeterService = jMeterService;
|
this.jMeterService = jMeterService;
|
||||||
this.request = request;
|
this.request = request;
|
||||||
this.hashTree = hashTree;
|
this.runModeDataDTO = runModeDataDTO;
|
||||||
this.id = id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T call() {
|
public T call() {
|
||||||
try {
|
try {
|
||||||
if (request.getConfig() != null && StringUtils.isNotBlank(request.getConfig().getResourcePoolId())) {
|
if (request.getConfig() != null && StringUtils.isNotBlank(request.getConfig().getResourcePoolId())) {
|
||||||
jMeterService.runTest(id, hashTree, request.getRunMode(), false, request.getConfig());
|
jMeterService.runTest(runModeDataDTO.getTestId(), runModeDataDTO.getReportId(), request.getRunMode(), request.getPlanScenarioId(), request.getConfig());
|
||||||
} else {
|
} else {
|
||||||
jMeterService.runSerial(id, hashTree, request.getReportId(), request.getRunMode(), request.getConfig());
|
jMeterService.runSerial(runModeDataDTO.getReportId(), runModeDataDTO.getHashTree(), request.getReportId(), request.getRunMode(), request.getConfig());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*/
|
*/
|
||||||
package io.metersphere.api.service.task;
|
package io.metersphere.api.service.task;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.RunModeDataDTO;
|
||||||
import io.metersphere.api.dto.automation.RunScenarioRequest;
|
import io.metersphere.api.dto.automation.RunScenarioRequest;
|
||||||
import io.metersphere.api.jmeter.JMeterService;
|
import io.metersphere.api.jmeter.JMeterService;
|
||||||
import io.metersphere.base.domain.ApiScenarioReport;
|
import io.metersphere.base.domain.ApiScenarioReport;
|
||||||
|
@ -11,7 +12,6 @@ import io.metersphere.commons.constants.APITestStatus;
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.commons.utils.LogUtil;
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.jorphan.collections.HashTree;
|
|
||||||
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
@ -19,32 +19,30 @@ public class SerialScenarioExecTask<T> implements Callable<T> {
|
||||||
private RunScenarioRequest request;
|
private RunScenarioRequest request;
|
||||||
private JMeterService jMeterService;
|
private JMeterService jMeterService;
|
||||||
private ApiScenarioReportMapper apiScenarioReportMapper;
|
private ApiScenarioReportMapper apiScenarioReportMapper;
|
||||||
private HashTree hashTree;
|
private RunModeDataDTO runModeDataDTO;
|
||||||
ApiScenarioReport report = null;
|
ApiScenarioReport report = null;
|
||||||
private String id;
|
|
||||||
|
|
||||||
public SerialScenarioExecTask(JMeterService jMeterService, ApiScenarioReportMapper apiScenarioReportMapper, String id, HashTree hashTree, RunScenarioRequest request) {
|
public SerialScenarioExecTask(JMeterService jMeterService, ApiScenarioReportMapper apiScenarioReportMapper, RunModeDataDTO runModeDataDTO, RunScenarioRequest request) {
|
||||||
this.jMeterService = jMeterService;
|
this.jMeterService = jMeterService;
|
||||||
this.apiScenarioReportMapper = apiScenarioReportMapper;
|
this.apiScenarioReportMapper = apiScenarioReportMapper;
|
||||||
this.request = request;
|
this.request = request;
|
||||||
this.hashTree = hashTree;
|
this.runModeDataDTO = runModeDataDTO;
|
||||||
this.id = id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T call() {
|
public T call() {
|
||||||
try {
|
try {
|
||||||
if (request.getConfig() != null && StringUtils.isNotBlank(request.getConfig().getResourcePoolId())) {
|
if (request.getConfig() != null && StringUtils.isNotBlank(request.getConfig().getResourcePoolId())) {
|
||||||
jMeterService.runTest(id, hashTree, request.getRunMode(), false, request.getConfig());
|
jMeterService.runTest(runModeDataDTO.getTestId(), runModeDataDTO.getReportId(), request.getRunMode(), request.getPlanScenarioId(), request.getConfig());
|
||||||
} else {
|
} else {
|
||||||
jMeterService.runSerial(id, hashTree, request.getReportId(), request.getRunMode(), request.getConfig());
|
jMeterService.runSerial(runModeDataDTO.getReportId(), runModeDataDTO.getHashTree(), request.getReportId(), request.getRunMode(), request.getConfig());
|
||||||
}
|
}
|
||||||
// 轮询查看报告状态,最多200次,防止死循环
|
// 轮询查看报告状态,最多200次,防止死循环
|
||||||
int index = 1;
|
int index = 1;
|
||||||
while (index < 200) {
|
while (index < 200) {
|
||||||
Thread.sleep(3000);
|
Thread.sleep(3000);
|
||||||
index++;
|
index++;
|
||||||
report = apiScenarioReportMapper.selectByPrimaryKey(id);
|
report = apiScenarioReportMapper.selectByPrimaryKey(runModeDataDTO.getReportId());
|
||||||
if (report != null && !report.getStatus().equals(APITestStatus.Running.name())) {
|
if (report != null && !report.getStatus().equals(APITestStatus.Running.name())) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,8 @@ public class ShiroUtils {
|
||||||
filterChainDefinitionMap.put("/sso/signin", "anon");
|
filterChainDefinitionMap.put("/sso/signin", "anon");
|
||||||
filterChainDefinitionMap.put("/sso/callback", "anon");
|
filterChainDefinitionMap.put("/sso/callback", "anon");
|
||||||
filterChainDefinitionMap.put("/license/valid", "anon");
|
filterChainDefinitionMap.put("/license/valid", "anon");
|
||||||
|
filterChainDefinitionMap.put("/api/jmeter/download", "anon");
|
||||||
|
filterChainDefinitionMap.put("/api/jmeter/download/jar", "anon");
|
||||||
|
|
||||||
// for swagger
|
// for swagger
|
||||||
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
|
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
|
||||||
|
|
|
@ -4,18 +4,16 @@ import com.github.pagehelper.Page;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
||||||
import io.metersphere.api.dto.definition.ApiTestCaseRequest;
|
import io.metersphere.api.dto.definition.ApiTestCaseRequest;
|
||||||
|
import io.metersphere.api.dto.definition.BatchRunDefinitionRequest;
|
||||||
import io.metersphere.api.dto.definition.TestPlanApiCaseDTO;
|
import io.metersphere.api.dto.definition.TestPlanApiCaseDTO;
|
||||||
import io.metersphere.commons.constants.OperLogConstants;
|
import io.metersphere.commons.constants.OperLogConstants;
|
||||||
import io.metersphere.commons.constants.PermissionConstants;
|
import io.metersphere.commons.constants.PermissionConstants;
|
||||||
import io.metersphere.commons.constants.RoleConstants;
|
|
||||||
import io.metersphere.commons.utils.PageUtils;
|
import io.metersphere.commons.utils.PageUtils;
|
||||||
import io.metersphere.commons.utils.Pager;
|
import io.metersphere.commons.utils.Pager;
|
||||||
import io.metersphere.log.annotation.MsAuditLog;
|
import io.metersphere.log.annotation.MsAuditLog;
|
||||||
import io.metersphere.track.request.testcase.TestPlanApiCaseBatchRequest;
|
import io.metersphere.track.request.testcase.TestPlanApiCaseBatchRequest;
|
||||||
import io.metersphere.track.service.TestPlanApiCaseService;
|
import io.metersphere.track.service.TestPlanApiCaseService;
|
||||||
import org.apache.shiro.authz.annotation.Logical;
|
|
||||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
@ -66,4 +64,8 @@ public class TestPlanApiCaseController {
|
||||||
testPlanApiCaseService.batchUpdateEnv(request);
|
testPlanApiCaseService.batchUpdateEnv(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/run")
|
||||||
|
public String run(@RequestPart("request") BatchRunDefinitionRequest request) {
|
||||||
|
return testPlanApiCaseService.run(request);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,46 @@
|
||||||
package io.metersphere.track.service;
|
package io.metersphere.track.service;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.github.pagehelper.Page;
|
import com.github.pagehelper.Page;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
|
import io.metersphere.api.dto.RunModeDataDTO;
|
||||||
import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
||||||
import io.metersphere.api.dto.definition.ApiTestCaseRequest;
|
import io.metersphere.api.dto.definition.ApiTestCaseRequest;
|
||||||
|
import io.metersphere.api.dto.definition.BatchRunDefinitionRequest;
|
||||||
import io.metersphere.api.dto.definition.TestPlanApiCaseDTO;
|
import io.metersphere.api.dto.definition.TestPlanApiCaseDTO;
|
||||||
|
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||||
|
import io.metersphere.api.dto.definition.request.MsTestPlan;
|
||||||
|
import io.metersphere.api.dto.definition.request.MsThreadGroup;
|
||||||
|
import io.metersphere.api.dto.definition.request.ParameterConfig;
|
||||||
|
import io.metersphere.api.dto.definition.request.sampler.MsDubboSampler;
|
||||||
|
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.jmeter.JMeterService;
|
||||||
import io.metersphere.api.service.ApiDefinitionExecResultService;
|
import io.metersphere.api.service.ApiDefinitionExecResultService;
|
||||||
import io.metersphere.api.service.ApiTestCaseService;
|
import io.metersphere.api.service.ApiTestCaseService;
|
||||||
import io.metersphere.base.domain.*;
|
import io.metersphere.base.domain.*;
|
||||||
|
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
|
||||||
import io.metersphere.base.mapper.ApiTestCaseMapper;
|
import io.metersphere.base.mapper.ApiTestCaseMapper;
|
||||||
import io.metersphere.base.mapper.TestPlanApiCaseMapper;
|
import io.metersphere.base.mapper.TestPlanApiCaseMapper;
|
||||||
import io.metersphere.base.mapper.TestPlanMapper;
|
import io.metersphere.base.mapper.TestPlanMapper;
|
||||||
import io.metersphere.base.mapper.ext.ExtTestPlanApiCaseMapper;
|
import io.metersphere.base.mapper.ext.ExtTestPlanApiCaseMapper;
|
||||||
import io.metersphere.commons.utils.PageUtils;
|
import io.metersphere.commons.constants.ApiRunMode;
|
||||||
import io.metersphere.commons.utils.Pager;
|
import io.metersphere.commons.constants.RunModeConstants;
|
||||||
import io.metersphere.commons.utils.ServiceUtils;
|
import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.commons.utils.SessionUtils;
|
import io.metersphere.commons.utils.*;
|
||||||
|
import io.metersphere.dto.BaseSystemConfigDTO;
|
||||||
import io.metersphere.log.vo.OperatingLogDetails;
|
import io.metersphere.log.vo.OperatingLogDetails;
|
||||||
|
import io.metersphere.service.SystemParameterService;
|
||||||
import io.metersphere.track.request.testcase.TestPlanApiCaseBatchRequest;
|
import io.metersphere.track.request.testcase.TestPlanApiCaseBatchRequest;
|
||||||
|
import io.metersphere.track.service.task.ParallelApiExecTask;
|
||||||
|
import io.metersphere.track.service.task.SerialApiExecTask;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.jorphan.collections.HashTree;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
@ -26,6 +48,9 @@ import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
@ -45,6 +70,12 @@ public class TestPlanApiCaseService {
|
||||||
private TestPlanMapper testPlanMapper;
|
private TestPlanMapper testPlanMapper;
|
||||||
@Resource
|
@Resource
|
||||||
ApiTestCaseMapper apiTestCaseMapper;
|
ApiTestCaseMapper apiTestCaseMapper;
|
||||||
|
@Resource
|
||||||
|
private SystemParameterService systemParameterService;
|
||||||
|
@Resource
|
||||||
|
private JMeterService jMeterService;
|
||||||
|
@Resource
|
||||||
|
private ApiDefinitionExecResultMapper mapper;
|
||||||
|
|
||||||
public TestPlanApiCase getInfo(String caseId, String testPlanId) {
|
public TestPlanApiCase getInfo(String caseId, String testPlanId) {
|
||||||
TestPlanApiCaseExample example = new TestPlanApiCaseExample();
|
TestPlanApiCaseExample example = new TestPlanApiCaseExample();
|
||||||
|
@ -219,4 +250,169 @@ public class TestPlanApiCaseService {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private MsTestElement parse(String api, String planId) {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
|
try {
|
||||||
|
JSONObject element = JSON.parseObject(api);
|
||||||
|
LinkedList<MsTestElement> list = new LinkedList<>();
|
||||||
|
if (element != null && StringUtils.isNotEmpty(element.getString("hashTree"))) {
|
||||||
|
LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"),
|
||||||
|
new TypeReference<LinkedList<MsTestElement>>() {
|
||||||
|
});
|
||||||
|
list.addAll(elements);
|
||||||
|
}
|
||||||
|
TestPlanApiCase apiCase = testPlanApiCaseMapper.selectByPrimaryKey(planId);
|
||||||
|
Map<String, String> envMap = null;
|
||||||
|
if (apiCase != null) {
|
||||||
|
envMap = JSON.parseObject(apiCase.getEnvironmentId(), Map.class);
|
||||||
|
}
|
||||||
|
if (element.getString("type").equals("HTTPSamplerProxy")) {
|
||||||
|
MsHTTPSamplerProxy httpSamplerProxy = JSON.parseObject(api, MsHTTPSamplerProxy.class);
|
||||||
|
httpSamplerProxy.setHashTree(list);
|
||||||
|
if (envMap != null && envMap.containsKey(httpSamplerProxy.getProjectId())) {
|
||||||
|
httpSamplerProxy.setUseEnvironment(envMap.get(httpSamplerProxy.getProjectId()));
|
||||||
|
}
|
||||||
|
return httpSamplerProxy;
|
||||||
|
}
|
||||||
|
if (element.getString("type").equals("TCPSampler")) {
|
||||||
|
MsTCPSampler msTCPSampler = JSON.parseObject(api, MsTCPSampler.class);
|
||||||
|
if (envMap != null && envMap.containsKey(msTCPSampler.getProjectId())) {
|
||||||
|
msTCPSampler.setUseEnvironment(envMap.get(msTCPSampler.getProjectId()));
|
||||||
|
}
|
||||||
|
msTCPSampler.setHashTree(list);
|
||||||
|
return msTCPSampler;
|
||||||
|
}
|
||||||
|
if (element.getString("type").equals("DubboSampler")) {
|
||||||
|
MsDubboSampler dubboSampler = JSON.parseObject(api, MsDubboSampler.class);
|
||||||
|
if (envMap != null && envMap.containsKey(dubboSampler.getProjectId())) {
|
||||||
|
dubboSampler.setUseEnvironment(envMap.get(dubboSampler.getProjectId()));
|
||||||
|
}
|
||||||
|
dubboSampler.setHashTree(list);
|
||||||
|
return dubboSampler;
|
||||||
|
}
|
||||||
|
if (element.getString("type").equals("JDBCSampler")) {
|
||||||
|
MsJDBCSampler jDBCSampler = JSON.parseObject(api, MsJDBCSampler.class);
|
||||||
|
if (envMap != null && envMap.containsKey(jDBCSampler.getProjectId())) {
|
||||||
|
jDBCSampler.setUseEnvironment(envMap.get(jDBCSampler.getProjectId()));
|
||||||
|
}
|
||||||
|
jDBCSampler.setHashTree(list);
|
||||||
|
return jDBCSampler;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
LogUtil.error(e.getMessage());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashTree generateHashTree(String testId) {
|
||||||
|
TestPlanApiCase apiCase = testPlanApiCaseMapper.selectByPrimaryKey(testId);
|
||||||
|
if (apiCase != null) {
|
||||||
|
ApiTestCaseWithBLOBs caseWithBLOBs = apiTestCaseMapper.selectByPrimaryKey(apiCase.getApiCaseId());
|
||||||
|
HashTree jmeterHashTree = new HashTree();
|
||||||
|
MsTestPlan testPlan = new MsTestPlan();
|
||||||
|
testPlan.setHashTree(new LinkedList<>());
|
||||||
|
if (caseWithBLOBs != null) {
|
||||||
|
try {
|
||||||
|
MsThreadGroup group = new MsThreadGroup();
|
||||||
|
group.setLabel(caseWithBLOBs.getName());
|
||||||
|
group.setName(testId);
|
||||||
|
MsTestElement testElement = parse(caseWithBLOBs.getRequest(), testId);
|
||||||
|
group.setHashTree(new LinkedList<>());
|
||||||
|
group.getHashTree().add(testElement);
|
||||||
|
testPlan.getHashTree().add(group);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
MSException.throwException(ex.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), new ParameterConfig());
|
||||||
|
return jmeterHashTree;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String modeRun(BatchRunDefinitionRequest request) {
|
||||||
|
List<String> ids = request.getPlanIds();
|
||||||
|
TestPlanApiCaseExample example = new TestPlanApiCaseExample();
|
||||||
|
example.createCriteria().andIdIn(ids);
|
||||||
|
List<TestPlanApiCase> planApiCases = testPlanApiCaseMapper.selectByExample(example);
|
||||||
|
|
||||||
|
// 开始选择执行模式
|
||||||
|
ExecutorService executorService = Executors.newFixedThreadPool(planApiCases.size());
|
||||||
|
if (request.getConfig() != null && request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) {
|
||||||
|
// 开始串行执行
|
||||||
|
Thread thread = new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (TestPlanApiCase key : planApiCases) {
|
||||||
|
try {
|
||||||
|
RunModeDataDTO modeDataDTO = null;
|
||||||
|
if (StringUtils.isNotBlank(request.getConfig().getResourcePoolId())) {
|
||||||
|
modeDataDTO = new RunModeDataDTO(key.getId(), UUID.randomUUID().toString());
|
||||||
|
} else {
|
||||||
|
// 生成报告和HashTree
|
||||||
|
HashTree hashTree = generateHashTree(key.getId());
|
||||||
|
modeDataDTO = new RunModeDataDTO(hashTree, UUID.randomUUID().toString());
|
||||||
|
}
|
||||||
|
Future<ApiDefinitionExecResult> future = executorService.submit(new SerialApiExecTask(jMeterService, mapper, modeDataDTO, request.getConfig(), ApiRunMode.API_PLAN.name()));
|
||||||
|
ApiDefinitionExecResult report = future.get();
|
||||||
|
// 如果开启失败结束执行,则判断返回结果状态
|
||||||
|
if (request.getConfig().isOnSampleError()) {
|
||||||
|
if (report == null || !report.getStatus().equals("Success")) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.error("执行终止:" + e.getMessage());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
thread.start();
|
||||||
|
} else {
|
||||||
|
// 开始并发执行
|
||||||
|
for (TestPlanApiCase key : planApiCases) {
|
||||||
|
RunModeDataDTO modeDataDTO = null;
|
||||||
|
if (StringUtils.isNotBlank(request.getConfig().getResourcePoolId())) {
|
||||||
|
modeDataDTO = new RunModeDataDTO(key.getId(), UUID.randomUUID().toString());
|
||||||
|
} else {
|
||||||
|
// 生成报告和HashTree
|
||||||
|
HashTree hashTree = generateHashTree(key.getId());
|
||||||
|
modeDataDTO = new RunModeDataDTO(hashTree, UUID.randomUUID().toString());
|
||||||
|
}
|
||||||
|
executorService.submit(new ParallelApiExecTask(jMeterService, mapper, modeDataDTO, request.getConfig(), ApiRunMode.API_PLAN.name()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return request.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试执行
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String run(BatchRunDefinitionRequest request) {
|
||||||
|
if (request.getConfig() != null) {
|
||||||
|
if (request.getConfig().getMode().equals(RunModeConstants.PARALLEL.toString())) {
|
||||||
|
// 校验并发数量
|
||||||
|
int count = 50;
|
||||||
|
BaseSystemConfigDTO dto = systemParameterService.getBaseInfo();
|
||||||
|
if (StringUtils.isNotEmpty(dto.getConcurrency())) {
|
||||||
|
count = Integer.parseInt(dto.getConcurrency());
|
||||||
|
}
|
||||||
|
if (request.getPlanIds().size() > count) {
|
||||||
|
MSException.throwException("并发数量过大,请重新选择!");
|
||||||
|
}
|
||||||
|
return this.modeRun(request);
|
||||||
|
} else {
|
||||||
|
return this.modeRun(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return request.getId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package io.metersphere.track.service.task;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.RunModeDataDTO;
|
||||||
|
import io.metersphere.api.dto.automation.RunModeConfig;
|
||||||
|
import io.metersphere.api.jmeter.JMeterService;
|
||||||
|
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
|
||||||
|
import io.metersphere.commons.exception.MSException;
|
||||||
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
public class ParallelApiExecTask<T> implements Callable<T> {
|
||||||
|
private RunModeConfig config;
|
||||||
|
private JMeterService jMeterService;
|
||||||
|
private RunModeDataDTO runModeDataDTO;
|
||||||
|
private String runMode;
|
||||||
|
private ApiDefinitionExecResultMapper mapper;
|
||||||
|
|
||||||
|
public ParallelApiExecTask(JMeterService jMeterService, ApiDefinitionExecResultMapper mapper, RunModeDataDTO runModeDataDTO, RunModeConfig config, String runMode) {
|
||||||
|
this.jMeterService = jMeterService;
|
||||||
|
this.config = config;
|
||||||
|
this.runModeDataDTO = runModeDataDTO;
|
||||||
|
this.runMode = runMode;
|
||||||
|
this.mapper = mapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T call() {
|
||||||
|
try {
|
||||||
|
if (config != null && StringUtils.isNotBlank(config.getResourcePoolId())) {
|
||||||
|
jMeterService.runTest(runModeDataDTO.getTestId(), runModeDataDTO.getReportId(), runMode, null, config);
|
||||||
|
} else {
|
||||||
|
jMeterService.runDefinition(runModeDataDTO.getReportId(), runModeDataDTO.getHashTree(), null, runMode);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
LogUtil.error(ex.getMessage());
|
||||||
|
MSException.throwException(ex.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package io.metersphere.track.service.task;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.RunModeDataDTO;
|
||||||
|
import io.metersphere.api.dto.automation.RunModeConfig;
|
||||||
|
import io.metersphere.api.jmeter.JMeterService;
|
||||||
|
import io.metersphere.base.domain.ApiDefinitionExecResult;
|
||||||
|
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
|
||||||
|
import io.metersphere.commons.exception.MSException;
|
||||||
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
public class SerialApiExecTask<T> implements Callable<T> {
|
||||||
|
private RunModeConfig config;
|
||||||
|
private JMeterService jMeterService;
|
||||||
|
private RunModeDataDTO runModeDataDTO;
|
||||||
|
private String runMode;
|
||||||
|
private ApiDefinitionExecResultMapper mapper;
|
||||||
|
|
||||||
|
public SerialApiExecTask(JMeterService jMeterService, ApiDefinitionExecResultMapper mapper, RunModeDataDTO runModeDataDTO, RunModeConfig config, String runMode) {
|
||||||
|
this.jMeterService = jMeterService;
|
||||||
|
this.config = config;
|
||||||
|
this.runModeDataDTO = runModeDataDTO;
|
||||||
|
this.runMode = runMode;
|
||||||
|
this.mapper = mapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T call() {
|
||||||
|
try {
|
||||||
|
if (config != null && StringUtils.isNotBlank(config.getResourcePoolId())) {
|
||||||
|
jMeterService.runTest(runModeDataDTO.getTestId(), runModeDataDTO.getReportId(), runMode, null, config);
|
||||||
|
} else {
|
||||||
|
jMeterService.runDefinition(runModeDataDTO.getReportId(), runModeDataDTO.getHashTree(), null, runMode);
|
||||||
|
}
|
||||||
|
// 轮询查看报告状态,最多200次,防止死循环
|
||||||
|
ApiDefinitionExecResult report = null;
|
||||||
|
int index = 1;
|
||||||
|
while (index < 200) {
|
||||||
|
Thread.sleep(3000);
|
||||||
|
index++;
|
||||||
|
report = mapper.selectByPrimaryKey(runModeDataDTO.getReportId());
|
||||||
|
if (report != null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (T) report;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
LogUtil.error(ex.getMessage());
|
||||||
|
MSException.throwException(ex.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue