feat(接口测试): jmx导入
This commit is contained in:
parent
3710ed3370
commit
68276ef05d
|
@ -123,6 +123,7 @@ module_not_null=所属模块不能为空格
|
||||||
user_not_exists=该项目下无该用户
|
user_not_exists=该项目下无该用户
|
||||||
test_case_already_exists=该项目下已存在该测试用例
|
test_case_already_exists=该项目下已存在该测试用例
|
||||||
parse_data_error=解析数据出错
|
parse_data_error=解析数据出错
|
||||||
|
parse_empty_data=未解析到数据
|
||||||
missing_header_information=缺少头部信息
|
missing_header_information=缺少头部信息
|
||||||
test_case_exist=该项目下已存在用例:
|
test_case_exist=该项目下已存在用例:
|
||||||
node_deep_limit=节点深度不超过8层!
|
node_deep_limit=节点深度不超过8层!
|
||||||
|
|
|
@ -123,6 +123,7 @@ module_starts_with=The module must start with '/'
|
||||||
user_not_exists=The user in this project is not exists
|
user_not_exists=The user in this project is not exists
|
||||||
test_case_already_exists=The test case in this project is exists
|
test_case_already_exists=The test case in this project is exists
|
||||||
parse_data_error=Parse data error
|
parse_data_error=Parse data error
|
||||||
|
parse_empty_data=Parse empty data
|
||||||
missing_header_information=Missing header information
|
missing_header_information=Missing header information
|
||||||
test_case_exist=A test case already exists under this project:
|
test_case_exist=A test case already exists under this project:
|
||||||
node_deep_limit=The node depth does not exceed 8 layers!
|
node_deep_limit=The node depth does not exceed 8 layers!
|
||||||
|
|
|
@ -124,6 +124,7 @@ module_starts_with=所属模块必须以'/'开始
|
||||||
user_not_exists=该项目下无该用户
|
user_not_exists=该项目下无该用户
|
||||||
test_case_already_exists=该项目下已存在该测试用例
|
test_case_already_exists=该项目下已存在该测试用例
|
||||||
parse_data_error=解析数据出错
|
parse_data_error=解析数据出错
|
||||||
|
parse_empty_data=未解析到数据
|
||||||
missing_header_information=缺少头部信息
|
missing_header_information=缺少头部信息
|
||||||
test_case_exist=该项目下已存在用例:
|
test_case_exist=该项目下已存在用例:
|
||||||
node_deep_limit=节点深度不超过8层!
|
node_deep_limit=节点深度不超过8层!
|
||||||
|
|
|
@ -124,6 +124,7 @@ module_starts_with=所屬模塊必須以'/'開始
|
||||||
user_not_exists=該項目下無該用戶
|
user_not_exists=該項目下無該用戶
|
||||||
test_case_already_exists=該項目下已存在該測試用例
|
test_case_already_exists=該項目下已存在該測試用例
|
||||||
parse_data_error=解析數據出錯
|
parse_data_error=解析數據出錯
|
||||||
|
parse_empty_data=未解析到数据
|
||||||
missing_header_information=缺少頭部信息
|
missing_header_information=缺少頭部信息
|
||||||
test_case_exist=該項目下已存在用例:
|
test_case_exist=該項目下已存在用例:
|
||||||
node_deep_limit=節點深度不超過8層!
|
node_deep_limit=節點深度不超過8層!
|
||||||
|
|
|
@ -312,7 +312,7 @@ public class ApiDefinitionController {
|
||||||
@PostMapping(value = "/export/{type}")
|
@PostMapping(value = "/export/{type}")
|
||||||
@Operation(summary = "接口测试-接口管理-导出接口定义")
|
@Operation(summary = "接口测试-接口管理-导出接口定义")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_EXPORT)
|
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_EXPORT)
|
||||||
public ApiExportResponse export(@RequestBody ApiDefinitionBatchRequest request, @PathVariable String type) {
|
public ApiExportResponse export(@RequestBody ApiDefinitionBatchExportRequest request, @PathVariable String type) {
|
||||||
return apiDefinitionExportService.export(request, type, SessionUtils.getUserId());
|
return apiDefinitionExportService.export(request, type, SessionUtils.getUserId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package io.metersphere.api.dto.converter;
|
||||||
import io.metersphere.api.dto.definition.ApiDefinitionMockDTO;
|
import io.metersphere.api.dto.definition.ApiDefinitionMockDTO;
|
||||||
import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -17,7 +18,7 @@ public class ApiImportDataAnalysisResult {
|
||||||
|
|
||||||
// 新增接口数据
|
// 新增接口数据
|
||||||
List<ApiDefinitionDetail> insertApiList = new ArrayList<>();
|
List<ApiDefinitionDetail> insertApiList = new ArrayList<>();
|
||||||
// 存在的接口数据. Map<导入的接口 , 已存在的接口>
|
// 存在的接口数据
|
||||||
List<ExistenceApiDefinitionDetail> existenceApiList = new ArrayList<>();
|
List<ExistenceApiDefinitionDetail> existenceApiList = new ArrayList<>();
|
||||||
// 接口的用例数据
|
// 接口的用例数据
|
||||||
Map<String, List<ApiTestCaseDTO>> apiIdAndTestCaseMap = new HashMap<>();
|
Map<String, List<ApiTestCaseDTO>> apiIdAndTestCaseMap = new HashMap<>();
|
||||||
|
@ -27,4 +28,8 @@ public class ApiImportDataAnalysisResult {
|
||||||
public void addExistenceApi(ApiDefinitionDetail importApi, ApiDefinitionDetail exportApi) {
|
public void addExistenceApi(ApiDefinitionDetail importApi, ApiDefinitionDetail exportApi) {
|
||||||
this.existenceApiList.add(new ExistenceApiDefinitionDetail(importApi, exportApi));
|
this.existenceApiList.add(new ExistenceApiDefinitionDetail(importApi, exportApi));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return CollectionUtils.isEmpty(insertApiList) && CollectionUtils.isEmpty(existenceApiList);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -20,4 +20,14 @@ public class ApiImportFileParseResult {
|
||||||
private Map<String, List<ApiTestCaseDTO>> caseMap = new HashMap<>();
|
private Map<String, List<ApiTestCaseDTO>> caseMap = new HashMap<>();
|
||||||
// mock数据
|
// mock数据
|
||||||
private Map<String, List<ApiDefinitionMockDTO>> mockMap = new HashMap<>();
|
private Map<String, List<ApiDefinitionMockDTO>> mockMap = new HashMap<>();
|
||||||
|
|
||||||
|
public List<String> getApiProtocols() {
|
||||||
|
List<String> protocols = new ArrayList<>();
|
||||||
|
for (ApiDefinitionDetail apiDefinitionDetail : data) {
|
||||||
|
if (!protocols.contains(apiDefinitionDetail.getProtocol())) {
|
||||||
|
protocols.add(apiDefinitionDetail.getProtocol());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return protocols;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
package io.metersphere.api.dto.definition;
|
||||||
|
|
||||||
|
import com.google.common.base.CaseFormat;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.Pattern;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lan
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class ApiDefinitionBatchExportRequest extends ApiDefinitionBatchRequest implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|
||||||
|
@Schema(description = "是否同步导出接口用例")
|
||||||
|
private boolean exportApiCase;
|
||||||
|
|
||||||
|
@Schema(description = "是否同步导出接口Mock")
|
||||||
|
private boolean exportApiMock;
|
||||||
|
|
||||||
|
@Schema(description = "排序字段(model中的字段 : asc/desc)")
|
||||||
|
private Map<@Valid @Pattern(regexp = "^[A-Za-z]+$") String, @Valid @NotBlank String> sort;
|
||||||
|
|
||||||
|
public String getSortString() {
|
||||||
|
if (sort == null || sort.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (Map.Entry<String, String> entry : sort.entrySet()) {
|
||||||
|
String column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, entry.getKey());
|
||||||
|
sb.append(column)
|
||||||
|
.append(StringUtils.SPACE)
|
||||||
|
.append(StringUtils.equalsIgnoreCase(entry.getValue(), "DESC") ? "DESC" : "ASC")
|
||||||
|
.append(",");
|
||||||
|
}
|
||||||
|
return sb.substring(0, sb.length() - 1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,10 +32,4 @@ public class ApiDefinitionBatchRequest extends TableBatchProcessDTO implements S
|
||||||
|
|
||||||
@Schema(description = "模块ID(根据模块树查询时要把当前节点以及子节点都放在这里。)")
|
@Schema(description = "模块ID(根据模块树查询时要把当前节点以及子节点都放在这里。)")
|
||||||
private List<@NotBlank String> moduleIds;
|
private List<@NotBlank String> moduleIds;
|
||||||
|
|
||||||
@Schema(description = "是否同步导出接口用例")
|
|
||||||
private boolean exportApiCase;
|
|
||||||
|
|
||||||
@Schema(description = "是否同步导出接口Mock")
|
|
||||||
private boolean exportApiMock;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ public interface ExtApiDefinitionMapper {
|
||||||
|
|
||||||
List<String> getIds(@Param("request") TableBatchProcessDTO request, @Param("projectId") String projectId, @Param("protocols") List<String> protocols, @Param("deleted") boolean deleted);
|
List<String> getIds(@Param("request") TableBatchProcessDTO request, @Param("projectId") String projectId, @Param("protocols") List<String> protocols, @Param("deleted") boolean deleted);
|
||||||
|
|
||||||
|
List<String> getIdsBySort(@Param("request") TableBatchProcessDTO request, @Param("projectId") String projectId, @Param("protocols") List<String> protocols, @Param("orderColumns") String orderColumns);
|
||||||
|
|
||||||
List<String> getRefIds(@Param("ids") List<String> ids, @Param("deleted") boolean deleted);
|
List<String> getRefIds(@Param("ids") List<String> ids, @Param("deleted") boolean deleted);
|
||||||
|
|
||||||
List<String> getIdsByRefId(@Param("refIds") List<String> refIds, @Param("deleted") boolean deleted);
|
List<String> getIdsByRefId(@Param("refIds") List<String> refIds, @Param("deleted") boolean deleted);
|
||||||
|
|
|
@ -89,6 +89,28 @@
|
||||||
<include refid="queryWhereConditionByBaseQueryRequest"/>
|
<include refid="queryWhereConditionByBaseQueryRequest"/>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="getIdsBySort" resultType="java.lang.String">
|
||||||
|
SELECT id
|
||||||
|
FROM api_definition
|
||||||
|
where project_id = #{projectId} and deleted is false
|
||||||
|
<if test="protocols != null and protocols.size() > 0">
|
||||||
|
AND protocol in
|
||||||
|
<foreach collection="protocols" item="protocol" separator="," open="(" close=")">
|
||||||
|
#{protocol}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
<if test="request.moduleIds != null and request.moduleIds.size() != 0">
|
||||||
|
AND module_id IN
|
||||||
|
<foreach collection="request.moduleIds" item="item" open="(" separator="," close=")">
|
||||||
|
#{item}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
<include refid="queryWhereConditionByBaseQueryRequest"/>
|
||||||
|
<if test="orderColumns != null">
|
||||||
|
ORDER BY #{orderColumns}
|
||||||
|
</if>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
<select id="getRefIds" resultType="java.lang.String">
|
<select id="getRefIds" resultType="java.lang.String">
|
||||||
SELECT
|
SELECT
|
||||||
|
|
|
@ -30,8 +30,4 @@ public interface ApiDefinitionImportParser<T> {
|
||||||
*/
|
*/
|
||||||
ApiImportDataAnalysisResult generateInsertAndUpdateData(ApiImportFileParseResult importParser, List<ApiDefinitionDetail> existenceApiDefinitionList);
|
ApiImportDataAnalysisResult generateInsertAndUpdateData(ApiImportFileParseResult importParser, List<ApiDefinitionDetail> existenceApiDefinitionList);
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取解析协议类型
|
|
||||||
*/
|
|
||||||
String getParseProtocol();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
package io.metersphere.api.parser;
|
package io.metersphere.api.parser;
|
||||||
|
|
||||||
import io.metersphere.api.constants.ApiImportPlatform;
|
import io.metersphere.api.constants.ApiImportPlatform;
|
||||||
import io.metersphere.api.parser.api.HarParserApiDefinition;
|
import io.metersphere.api.parser.api.*;
|
||||||
import io.metersphere.api.parser.api.MetersphereParserApiDefinition;
|
|
||||||
import io.metersphere.api.parser.api.PostmanParserApiDefinition;
|
|
||||||
import io.metersphere.api.parser.api.Swagger3ParserApiDefinition;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
public class ImportParserFactory {
|
public class ImportParserFactory {
|
||||||
|
@ -17,6 +14,8 @@ public class ImportParserFactory {
|
||||||
return new MetersphereParserApiDefinition();
|
return new MetersphereParserApiDefinition();
|
||||||
} else if (StringUtils.equalsIgnoreCase(ApiImportPlatform.Har.name(), platform)) {
|
} else if (StringUtils.equalsIgnoreCase(ApiImportPlatform.Har.name(), platform)) {
|
||||||
return new HarParserApiDefinition();
|
return new HarParserApiDefinition();
|
||||||
|
} else if (StringUtils.equalsIgnoreCase(ApiImportPlatform.Jmeter.name(), platform)) {
|
||||||
|
return new JmeterParserApiDefinition();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,33 +270,6 @@ public class HarParserApiDefinition extends HttpApiDefinitionImportAbstractParse
|
||||||
|
|
||||||
return resultList;
|
return resultList;
|
||||||
}
|
}
|
||||||
// private void addBodyHeader(MsHTTPElement request) {
|
|
||||||
// String contentType = StringUtils.EMPTY;
|
|
||||||
// if (request.getBody() != null && StringUtils.isNotBlank(request.getBody().getType())) {
|
|
||||||
// switch (request.getBody().getType()) {
|
|
||||||
// case Body.WWW_FROM:
|
|
||||||
// contentType = "application/x-www-form-urlencoded";
|
|
||||||
// break;
|
|
||||||
// case Body.JSON_STR:
|
|
||||||
// contentType = "application/json";
|
|
||||||
// break;
|
|
||||||
// case Body.XML:
|
|
||||||
// contentType = "application/xml";
|
|
||||||
// break;
|
|
||||||
// case Body.BINARY:
|
|
||||||
// contentType = "application/octet-stream";
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// List<KeyValue> headers = request.getHeaders();
|
|
||||||
// if (headers == null) {
|
|
||||||
// headers = new ArrayList<>();
|
|
||||||
// request.setHeaders(headers);
|
|
||||||
// }
|
|
||||||
// if (StringUtils.isNotEmpty(contentType)) {
|
|
||||||
// addContentType(request.getHeaders(), contentType);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
private void parseParameters(HarRequest harRequest, MsHTTPElement request) {
|
private void parseParameters(HarRequest harRequest, MsHTTPElement request) {
|
||||||
List<HarQueryParam> queryStringList = harRequest.queryString;
|
List<HarQueryParam> queryStringList = harRequest.queryString;
|
||||||
|
|
|
@ -12,9 +12,9 @@ import io.metersphere.api.dto.request.http.MsHTTPElement;
|
||||||
import io.metersphere.api.dto.request.http.body.*;
|
import io.metersphere.api.dto.request.http.body.*;
|
||||||
import io.metersphere.api.parser.ApiDefinitionImportParser;
|
import io.metersphere.api.parser.ApiDefinitionImportParser;
|
||||||
import io.metersphere.project.dto.environment.auth.NoAuth;
|
import io.metersphere.project.dto.environment.auth.NoAuth;
|
||||||
import io.metersphere.project.dto.environment.http.HttpConfig;
|
|
||||||
import io.metersphere.sdk.exception.MSException;
|
import io.metersphere.sdk.exception.MSException;
|
||||||
import io.metersphere.sdk.util.LogUtils;
|
import io.metersphere.sdk.util.LogUtils;
|
||||||
|
import io.metersphere.system.uid.IDGenerator;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
@ -30,11 +30,6 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
public abstract class HttpApiDefinitionImportAbstractParser<T> implements ApiDefinitionImportParser<T> {
|
public abstract class HttpApiDefinitionImportAbstractParser<T> implements ApiDefinitionImportParser<T> {
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getParseProtocol() {
|
|
||||||
return HttpConfig.HttpProtocolType.HTTP.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApiImportDataAnalysisResult generateInsertAndUpdateData(ApiImportFileParseResult importParser, List<ApiDefinitionDetail> existenceApiDefinitionList) {
|
public ApiImportDataAnalysisResult generateInsertAndUpdateData(ApiImportFileParseResult importParser, List<ApiDefinitionDetail> existenceApiDefinitionList) {
|
||||||
// API类型,通过 Method & Path 组合判断,接口是否存在
|
// API类型,通过 Method & Path 组合判断,接口是否存在
|
||||||
|
@ -62,16 +57,6 @@ public abstract class HttpApiDefinitionImportAbstractParser<T> implements ApiDef
|
||||||
return insertAndUpdateData;
|
return insertAndUpdateData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUniqueName(String originalName, List<String> existenceNameList) {
|
|
||||||
String returnName = originalName;
|
|
||||||
int index = 1;
|
|
||||||
while (existenceNameList.contains(returnName)) {
|
|
||||||
returnName = originalName + " - " + index;
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
return returnName;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getApiTestStr(InputStream source) {
|
protected String getApiTestStr(InputStream source) {
|
||||||
StringBuilder testStr = null;
|
StringBuilder testStr = null;
|
||||||
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(source, StandardCharsets.UTF_8))) {
|
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(source, StandardCharsets.UTF_8))) {
|
||||||
|
@ -91,6 +76,7 @@ public abstract class HttpApiDefinitionImportAbstractParser<T> implements ApiDef
|
||||||
|
|
||||||
protected ApiDefinitionDetail buildApiDefinition(String name, String path, String method, String modulePath, ImportRequest importRequest) {
|
protected ApiDefinitionDetail buildApiDefinition(String name, String path, String method, String modulePath, ImportRequest importRequest) {
|
||||||
ApiDefinitionDetail apiDefinition = new ApiDefinitionDetail();
|
ApiDefinitionDetail apiDefinition = new ApiDefinitionDetail();
|
||||||
|
apiDefinition.setId(IDGenerator.nextStr());
|
||||||
apiDefinition.setName(name);
|
apiDefinition.setName(name);
|
||||||
apiDefinition.setPath(formatPath(path));
|
apiDefinition.setPath(formatPath(path));
|
||||||
apiDefinition.setProtocol(importRequest.getProtocol());
|
apiDefinition.setProtocol(importRequest.getProtocol());
|
||||||
|
|
|
@ -0,0 +1,194 @@
|
||||||
|
package io.metersphere.api.parser.api;
|
||||||
|
|
||||||
|
import io.metersphere.api.constants.ApiConstants;
|
||||||
|
import io.metersphere.api.domain.ApiDefinition;
|
||||||
|
import io.metersphere.api.dto.converter.ApiDefinitionDetail;
|
||||||
|
import io.metersphere.api.dto.converter.ApiImportDataAnalysisResult;
|
||||||
|
import io.metersphere.api.dto.converter.ApiImportFileParseResult;
|
||||||
|
import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
||||||
|
import io.metersphere.api.dto.request.ImportRequest;
|
||||||
|
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
||||||
|
import io.metersphere.api.parser.ApiDefinitionImportParser;
|
||||||
|
import io.metersphere.api.parser.ms.MsTestElementParser;
|
||||||
|
import io.metersphere.api.utils.ApiDefinitionImportUtils;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsProtocolTestElement;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
import io.metersphere.sdk.exception.MSException;
|
||||||
|
import io.metersphere.sdk.util.CommonBeanFactory;
|
||||||
|
import io.metersphere.sdk.util.LogUtils;
|
||||||
|
import io.metersphere.system.dto.ProtocolDTO;
|
||||||
|
import io.metersphere.system.service.ApiPluginService;
|
||||||
|
import io.metersphere.system.uid.IDGenerator;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.jmeter.save.SaveService;
|
||||||
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class JmeterParserApiDefinition implements ApiDefinitionImportParser<ApiImportFileParseResult> {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApiImportFileParseResult parse(InputStream inputSource, ImportRequest request) throws Exception {
|
||||||
|
try {
|
||||||
|
Object scriptWrapper = SaveService.loadElement(inputSource);
|
||||||
|
HashTree hashTree = this.getHashTree(scriptWrapper);
|
||||||
|
MsTestElementParser parser = new MsTestElementParser();
|
||||||
|
AbstractMsTestElement msTestElement = parser.parse(hashTree);
|
||||||
|
List<AbstractMsProtocolTestElement> msElement = parser.getAbstractMsProtocolTestElement(msTestElement);
|
||||||
|
LinkedHashMap<ApiDefinitionDetail, List<ApiTestCaseDTO>> allImportDetails = this.parseImportFile(request.getProjectId(), msElement);
|
||||||
|
return this.genApiDefinitionImport(allImportDetails);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtils.error(e);
|
||||||
|
throw new MSException("当前JMX版本不兼容");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ApiImportFileParseResult genApiDefinitionImport(LinkedHashMap<ApiDefinitionDetail, List<ApiTestCaseDTO>> allImportDetails) {
|
||||||
|
Map<ApiDefinitionDetail, List<ApiTestCaseDTO>> groupWithUniqueIdentification = this.mergeApiCaseWithUniqueIdentification(allImportDetails);
|
||||||
|
ApiImportFileParseResult returnDTO = new ApiImportFileParseResult();
|
||||||
|
groupWithUniqueIdentification.forEach((definitionImportDetail, caseData) -> {
|
||||||
|
String apiID = IDGenerator.nextStr();
|
||||||
|
definitionImportDetail.setId(apiID);
|
||||||
|
returnDTO.getData().add(definitionImportDetail);
|
||||||
|
caseData.forEach(item -> {
|
||||||
|
item.setId(IDGenerator.nextStr());
|
||||||
|
item.setApiDefinitionId(apiID);
|
||||||
|
});
|
||||||
|
if (CollectionUtils.isNotEmpty(caseData)) {
|
||||||
|
returnDTO.getCaseMap().put(apiID, caseData);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return returnDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<ApiDefinitionDetail, List<ApiTestCaseDTO>> mergeApiCaseWithUniqueIdentification(LinkedHashMap<ApiDefinitionDetail, List<ApiTestCaseDTO>> allImportDetails) {
|
||||||
|
Map<ApiDefinitionDetail, List<ApiTestCaseDTO>> returnMap = new HashMap<>();
|
||||||
|
Map<String, ApiDefinitionDetail> filterApiMap = new HashMap<>();
|
||||||
|
Map<String, List<ApiTestCaseDTO>> uniqueCaseMap = new HashMap<>();
|
||||||
|
allImportDetails.forEach((api, apiCase) -> {
|
||||||
|
String key = api.getMethod() + StringUtils.SPACE + api.getPath();
|
||||||
|
if (!filterApiMap.containsKey(key)) {
|
||||||
|
filterApiMap.put(key, api);
|
||||||
|
}
|
||||||
|
if (uniqueCaseMap.containsKey(key)) {
|
||||||
|
uniqueCaseMap.get(key).addAll(apiCase);
|
||||||
|
} else {
|
||||||
|
uniqueCaseMap.put(key, apiCase);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
filterApiMap.forEach((key, api) -> {
|
||||||
|
returnMap.put(api, ApiDefinitionImportUtils.apiCaseRename(uniqueCaseMap.get(key)));
|
||||||
|
});
|
||||||
|
return returnMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LinkedHashMap<ApiDefinitionDetail, List<ApiTestCaseDTO>> parseImportFile(String projectId, List<AbstractMsProtocolTestElement> msElement) {
|
||||||
|
LinkedHashMap<ApiDefinitionDetail, List<ApiTestCaseDTO>> returnMap = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
ApiPluginService apiPluginService = CommonBeanFactory.getBean(ApiPluginService.class);
|
||||||
|
assert apiPluginService != null;
|
||||||
|
|
||||||
|
List<ProtocolDTO> protocolDTOList = apiPluginService.getProtocolsByProjectId(projectId);
|
||||||
|
|
||||||
|
Map<String, String> polymorphicNameMap = protocolDTOList.stream().collect(Collectors.toMap(ProtocolDTO::getPolymorphicName, ProtocolDTO::getProtocol));
|
||||||
|
|
||||||
|
for (AbstractMsProtocolTestElement protocolTestElement : msElement) {
|
||||||
|
ApiDefinitionDetail definition = new ApiDefinitionDetail();
|
||||||
|
definition.setName(protocolTestElement.getName());
|
||||||
|
if (protocolTestElement instanceof MsHTTPElement msHTTPElement) {
|
||||||
|
definition.setMethod(msHTTPElement.getMethod());
|
||||||
|
definition.setPath(msHTTPElement.getPath());
|
||||||
|
definition.setProtocol(ApiConstants.HTTP_PROTOCOL);
|
||||||
|
} else {
|
||||||
|
definition.setProtocol(polymorphicNameMap.get(protocolTestElement.getClass().getSimpleName()));
|
||||||
|
definition.setMethod(definition.getProtocol());
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(definition.getProtocol())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
definition.setRequest(protocolTestElement);
|
||||||
|
definition.setResponse(new ArrayList<>());
|
||||||
|
|
||||||
|
|
||||||
|
ApiTestCaseDTO apiTestCaseDTO = new ApiTestCaseDTO();
|
||||||
|
apiTestCaseDTO.setName(definition.getName());
|
||||||
|
apiTestCaseDTO.setPriority("P0");
|
||||||
|
apiTestCaseDTO.setStatus(definition.getStatus());
|
||||||
|
apiTestCaseDTO.setProjectId(definition.getProjectId());
|
||||||
|
apiTestCaseDTO.setFollow(false);
|
||||||
|
apiTestCaseDTO.setMethod(definition.getMethod());
|
||||||
|
apiTestCaseDTO.setPath(definition.getPath());
|
||||||
|
apiTestCaseDTO.setRequest(definition.getRequest());
|
||||||
|
apiTestCaseDTO.setProtocol(definition.getProtocol());
|
||||||
|
apiTestCaseDTO.setProjectId(definition.getProjectId());
|
||||||
|
|
||||||
|
returnMap.put(definition, new ArrayList<>(Collections.singletonList(apiTestCaseDTO)));
|
||||||
|
}
|
||||||
|
return returnMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private HashTree getHashTree(Object scriptWrapper) throws Exception {
|
||||||
|
Field field = scriptWrapper.getClass().getDeclaredField("testPlan");
|
||||||
|
field.setAccessible(true);
|
||||||
|
return (HashTree) field.get(scriptWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApiImportDataAnalysisResult generateInsertAndUpdateData(ApiImportFileParseResult importParser, List<ApiDefinitionDetail> existenceApiDefinitionList) {
|
||||||
|
List<ApiDefinitionDetail> importDataList = importParser.getData();
|
||||||
|
Map<String, List<ApiDefinitionDetail>> protocolImportMap = importDataList.stream().collect(Collectors.groupingBy(ApiDefinitionDetail::getProtocol));
|
||||||
|
Map<String, List<ApiDefinitionDetail>> existenceProtocolMap = existenceApiDefinitionList.stream().collect(Collectors.groupingBy(ApiDefinitionDetail::getProtocol));
|
||||||
|
|
||||||
|
ApiImportDataAnalysisResult insertAndUpdateData = new ApiImportDataAnalysisResult();
|
||||||
|
for (Map.Entry<String, List<ApiDefinitionDetail>> entry : protocolImportMap.entrySet()) {
|
||||||
|
List<ApiDefinitionDetail> importList = entry.getValue();
|
||||||
|
List<ApiDefinitionDetail> existenceList = existenceProtocolMap.get(entry.getKey());
|
||||||
|
|
||||||
|
ApiImportDataAnalysisResult httpResult = compareApiData(importList, existenceList, entry.getKey());
|
||||||
|
insertAndUpdateData.getInsertApiList().addAll(httpResult.getInsertApiList());
|
||||||
|
insertAndUpdateData.getExistenceApiList().addAll(httpResult.getExistenceApiList());
|
||||||
|
}
|
||||||
|
insertAndUpdateData.getApiIdAndTestCaseMap().putAll(importParser.getCaseMap());
|
||||||
|
return insertAndUpdateData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ApiImportDataAnalysisResult compareApiData(List<ApiDefinitionDetail> importData, List<ApiDefinitionDetail> existenceApiData, String protocol) {
|
||||||
|
ApiImportDataAnalysisResult insertAndUpdateData = new ApiImportDataAnalysisResult();
|
||||||
|
|
||||||
|
if (CollectionUtils.isEmpty(importData)) {
|
||||||
|
return insertAndUpdateData;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CollectionUtils.isEmpty(existenceApiData)) {
|
||||||
|
insertAndUpdateData.setInsertApiList(importData);
|
||||||
|
return insertAndUpdateData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// API类型,通过 Method & Path 组合判断,接口是否存在
|
||||||
|
Map<String, ApiDefinitionDetail> savedApiDefinitionMap = null;
|
||||||
|
Map<String, ApiDefinitionDetail> importDataMap = null;
|
||||||
|
|
||||||
|
if (StringUtils.equalsIgnoreCase(protocol, ApiConstants.HTTP_PROTOCOL)) {
|
||||||
|
savedApiDefinitionMap = existenceApiData.stream().collect(Collectors.toMap(t -> t.getMethod() + t.getPath(), t -> t, (oldValue, newValue) -> newValue));
|
||||||
|
importDataMap = importData.stream().collect(Collectors.toMap(t -> t.getMethod() + t.getPath(), t -> t, (oldValue, newValue) -> newValue));
|
||||||
|
} else {
|
||||||
|
savedApiDefinitionMap = existenceApiData.stream().collect(Collectors.toMap(ApiDefinition::getName, t -> t, (oldValue, newValue) -> newValue));
|
||||||
|
importDataMap = importData.stream().collect(Collectors.toMap(ApiDefinition::getName, t -> t, (oldValue, newValue) -> newValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<String, ApiDefinitionDetail> entry : importDataMap.entrySet()) {
|
||||||
|
if (savedApiDefinitionMap.containsKey(entry.getKey())) {
|
||||||
|
insertAndUpdateData.addExistenceApi(entry.getValue(), savedApiDefinitionMap.get(entry.getKey()));
|
||||||
|
} else {
|
||||||
|
insertAndUpdateData.getInsertApiList().add(entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return insertAndUpdateData;
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
||||||
import io.metersphere.api.dto.export.MetersphereApiExportResponse;
|
import io.metersphere.api.dto.export.MetersphereApiExportResponse;
|
||||||
import io.metersphere.api.dto.request.ImportRequest;
|
import io.metersphere.api.dto.request.ImportRequest;
|
||||||
import io.metersphere.api.utils.ApiDataUtils;
|
import io.metersphere.api.utils.ApiDataUtils;
|
||||||
|
import io.metersphere.api.utils.ApiDefinitionImportUtils;
|
||||||
import io.metersphere.sdk.exception.MSException;
|
import io.metersphere.sdk.exception.MSException;
|
||||||
import io.metersphere.sdk.util.LogUtils;
|
import io.metersphere.sdk.util.LogUtils;
|
||||||
import io.metersphere.system.uid.IDGenerator;
|
import io.metersphere.system.uid.IDGenerator;
|
||||||
|
@ -60,44 +61,16 @@ public class MetersphereParserApiDefinition extends HttpApiDefinitionImportAbstr
|
||||||
}
|
}
|
||||||
returnDTO.getData().add(definitionImportDetail);
|
returnDTO.getData().add(definitionImportDetail);
|
||||||
if (CollectionUtils.isNotEmpty(caseList)) {
|
if (CollectionUtils.isNotEmpty(caseList)) {
|
||||||
returnDTO.getCaseMap().put(apiID, this.apiCaseRename(caseList));
|
returnDTO.getCaseMap().put(apiID, ApiDefinitionImportUtils.apiCaseRename(caseList));
|
||||||
}
|
}
|
||||||
if (CollectionUtils.isNotEmpty(mockList)) {
|
if (CollectionUtils.isNotEmpty(mockList)) {
|
||||||
returnDTO.getMockMap().put(apiID, this.apiMockRename(mockList));
|
returnDTO.getMockMap().put(apiID, ApiDefinitionImportUtils.apiMockRename(mockList));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return returnDTO;
|
return returnDTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ApiTestCaseDTO> apiCaseRename(List<ApiTestCaseDTO> caseList) {
|
|
||||||
List<ApiTestCaseDTO> returnList = new ArrayList<>();
|
|
||||||
if (CollectionUtils.isNotEmpty(caseList)) {
|
|
||||||
List<String> caseNameList = new ArrayList<>();
|
|
||||||
for (ApiTestCaseDTO apiCase : caseList) {
|
|
||||||
String uniqueName = this.getUniqueName(apiCase.getName(), caseNameList);
|
|
||||||
apiCase.setName(uniqueName);
|
|
||||||
caseNameList.add(uniqueName);
|
|
||||||
returnList.add(apiCase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnList;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ApiDefinitionMockDTO> apiMockRename(List<ApiDefinitionMockDTO> caseList) {
|
|
||||||
List<ApiDefinitionMockDTO> returnList = new ArrayList<>();
|
|
||||||
if (CollectionUtils.isNotEmpty(caseList)) {
|
|
||||||
List<String> caseNameList = new ArrayList<>();
|
|
||||||
for (ApiDefinitionMockDTO apiMock : caseList) {
|
|
||||||
String uniqueName = this.getUniqueName(apiMock.getName(), caseNameList);
|
|
||||||
apiMock.setName(uniqueName);
|
|
||||||
caseNameList.add(uniqueName);
|
|
||||||
returnList.add(apiMock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnList;
|
|
||||||
}
|
|
||||||
|
|
||||||
//合并相同路径下的用例和mock
|
//合并相同路径下的用例和mock
|
||||||
private List<ApiDefinitionExportDetail> mergeApiCaseWithUniqueIdentification(List<ApiDefinitionExportDetail> apiDefinitions) {
|
private List<ApiDefinitionExportDetail> mergeApiCaseWithUniqueIdentification(List<ApiDefinitionExportDetail> apiDefinitions) {
|
||||||
List<ApiDefinitionExportDetail> returnList = new ArrayList<>();
|
List<ApiDefinitionExportDetail> returnList = new ArrayList<>();
|
||||||
|
|
|
@ -8,6 +8,7 @@ import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
||||||
import io.metersphere.api.dto.request.ImportRequest;
|
import io.metersphere.api.dto.request.ImportRequest;
|
||||||
import io.metersphere.api.parser.api.postman.PostmanCollection;
|
import io.metersphere.api.parser.api.postman.PostmanCollection;
|
||||||
import io.metersphere.api.parser.api.postman.PostmanItem;
|
import io.metersphere.api.parser.api.postman.PostmanItem;
|
||||||
|
import io.metersphere.api.utils.ApiDefinitionImportUtils;
|
||||||
import io.metersphere.sdk.exception.MSException;
|
import io.metersphere.sdk.exception.MSException;
|
||||||
import io.metersphere.sdk.util.JSON;
|
import io.metersphere.sdk.util.JSON;
|
||||||
import io.metersphere.sdk.util.LogUtils;
|
import io.metersphere.sdk.util.LogUtils;
|
||||||
|
@ -109,23 +110,9 @@ public class PostmanParserApiDefinition extends PostmanAbstractParserParserApiDe
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
filterApiMap.forEach((key, api) -> {
|
filterApiMap.forEach((key, api) -> {
|
||||||
returnMap.put(api, this.apiCaseRename(uniqueCaseMap.get(key)));
|
returnMap.put(api, ApiDefinitionImportUtils.apiRename(uniqueCaseMap.get(key)));
|
||||||
});
|
});
|
||||||
return returnMap;
|
return returnMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ApiDefinitionDetail> apiCaseRename(List<ApiDefinitionDetail> caseList) {
|
|
||||||
List<ApiDefinitionDetail> returnList = new ArrayList<>();
|
|
||||||
if (CollectionUtils.isNotEmpty(caseList)) {
|
|
||||||
List<String> caseNameList = new ArrayList<>();
|
|
||||||
for (ApiDefinitionDetail apiCase : caseList) {
|
|
||||||
String uniqueName = this.getUniqueName(apiCase.getName(), caseNameList);
|
|
||||||
apiCase.setName(uniqueName);
|
|
||||||
caseNameList.add(uniqueName);
|
|
||||||
returnList.add(apiCase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnList;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,30 @@
|
||||||
package io.metersphere.api.parser.ms;
|
package io.metersphere.api.parser.ms;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.ApiFile;
|
||||||
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
||||||
|
import io.metersphere.api.dto.request.http.MsHeader;
|
||||||
|
import io.metersphere.api.dto.request.http.QueryParam;
|
||||||
|
import io.metersphere.api.dto.request.http.body.*;
|
||||||
import io.metersphere.plugin.api.spi.AbstractMsElementConverter;
|
import io.metersphere.plugin.api.spi.AbstractMsElementConverter;
|
||||||
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
import io.metersphere.project.api.KeyValueEnableParam;
|
||||||
|
import io.metersphere.sdk.util.BeanUtils;
|
||||||
|
import io.metersphere.sdk.util.LogUtils;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.jmeter.protocol.http.control.HeaderManager;
|
||||||
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
|
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
|
||||||
|
import org.apache.jmeter.protocol.http.util.HTTPArgument;
|
||||||
|
import org.apache.jmeter.protocol.http.util.HTTPFileArg;
|
||||||
|
import org.apache.jmeter.testelement.property.JMeterProperty;
|
||||||
import org.apache.jorphan.collections.HashTree;
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: jianxing
|
* @Author: jianxing
|
||||||
|
@ -13,9 +33,151 @@ import org.apache.jorphan.collections.HashTree;
|
||||||
public class HTTPSamplerConverter extends AbstractMsElementConverter<HTTPSamplerProxy> {
|
public class HTTPSamplerConverter extends AbstractMsElementConverter<HTTPSamplerProxy> {
|
||||||
@Override
|
@Override
|
||||||
public void toMsElement(AbstractMsTestElement parent, HTTPSamplerProxy httpSampler, HashTree hashTree) {
|
public void toMsElement(AbstractMsTestElement parent, HTTPSamplerProxy httpSampler, HashTree hashTree) {
|
||||||
MsHTTPElement msHTTPElement = new MsHTTPElement();
|
MsHTTPElement msHTTPElement = this.convertHttpSampler(httpSampler);
|
||||||
// todo 解析HTTP请求
|
|
||||||
parent.getChildren().add(msHTTPElement);
|
parent.getChildren().add(msHTTPElement);
|
||||||
parseChild(msHTTPElement, httpSampler, hashTree);
|
parseChild(msHTTPElement, httpSampler, hashTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MsHTTPElement convertHttpSampler(HTTPSamplerProxy source) {
|
||||||
|
MsHTTPElement samplerProxy = new MsHTTPElement();
|
||||||
|
samplerProxy.setQuery(new ArrayList<>());
|
||||||
|
samplerProxy.setRest(new ArrayList<>());
|
||||||
|
try {
|
||||||
|
|
||||||
|
BeanUtils.copyBean(samplerProxy, source);
|
||||||
|
// 处理HTTP协议的请求头
|
||||||
|
List<MsHeader> headerKvList = new LinkedList<>();
|
||||||
|
HeaderManager headerManager = source.getHeaderManager();
|
||||||
|
if (headerManager != null && headerManager.getHeaders() != null) {
|
||||||
|
for (int i = 0; i < headerManager.getHeaders().size(); i++) {
|
||||||
|
String headerKey = headerManager.getHeader(i).getName();
|
||||||
|
String value = headerManager.getHeader(i).getValue();
|
||||||
|
headerKvList.add(new MsHeader() {{
|
||||||
|
this.setKey(headerKey);
|
||||||
|
this.setValue(value);
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
samplerProxy.setHeaders(headerKvList);
|
||||||
|
// 初始化body
|
||||||
|
Body body = new Body();
|
||||||
|
body.setJsonBody(new JsonBody());
|
||||||
|
body.setFormDataBody(new FormDataBody());
|
||||||
|
body.setWwwFormBody(new WWWFormBody());
|
||||||
|
body.setRawBody(new RawBody());
|
||||||
|
body.setXmlBody(new XmlBody());
|
||||||
|
samplerProxy.setBody(body);
|
||||||
|
if (source.getHTTPFiles().length > 0) {
|
||||||
|
samplerProxy.getBody().setBodyType(Body.BodyType.FORM_DATA.name());
|
||||||
|
List<FormDataKV> keyValues = new LinkedList<>();
|
||||||
|
for (HTTPFileArg arg : source.getHTTPFiles()) {
|
||||||
|
FormDataKV keyValue = getFormDataKV(arg);
|
||||||
|
keyValues.add(keyValue);
|
||||||
|
}
|
||||||
|
samplerProxy.getBody().setFormDataBody(new FormDataBody() {{
|
||||||
|
this.setFormValues(keyValues);
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
samplerProxy.getOtherConfig().setConnectTimeout((long) source.getConnectTimeout());
|
||||||
|
samplerProxy.getOtherConfig().setResponseTimeout((long) source.getResponseTimeout());
|
||||||
|
samplerProxy.getOtherConfig().setFollowRedirects(source.getFollowRedirects());
|
||||||
|
samplerProxy.getOtherConfig().setAutoRedirects(source.getAutoRedirects());
|
||||||
|
|
||||||
|
if (source.getArguments() != null) {
|
||||||
|
String bodyType = this.getBodyType(samplerProxy.getHeaders());
|
||||||
|
if (source.getPostBodyRaw()) {
|
||||||
|
List<MsHeader> headers = samplerProxy.getHeaders();
|
||||||
|
boolean jsonType = false;
|
||||||
|
if (CollectionUtils.isNotEmpty(headers)) {
|
||||||
|
for (MsHeader header : headers) {
|
||||||
|
if (StringUtils.equals(header.getKey(), "Content-Type") && StringUtils.equals(header.getValue(), "application/json")) {
|
||||||
|
samplerProxy.getBody().setBodyType(Body.BodyType.JSON.name());
|
||||||
|
jsonType = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!jsonType) {
|
||||||
|
samplerProxy.getBody().setBodyType(Body.BodyType.RAW.name());
|
||||||
|
}
|
||||||
|
source.getArguments().getArgumentsAsMap().forEach((k, v) -> samplerProxy.getBody().setRawBody(new RawBody() {{
|
||||||
|
this.setValue(v);
|
||||||
|
}}));
|
||||||
|
} else if (StringUtils.isNotEmpty(bodyType) || ("POST".equalsIgnoreCase(source.getMethod()) && source.getArguments().getArgumentsAsMap().size() > 0)) {
|
||||||
|
samplerProxy.getBody().setBodyType(Body.BodyType.WWW_FORM.name());
|
||||||
|
List<WWWFormKV> keyValues = new LinkedList<>();
|
||||||
|
source.getArguments().getArguments().forEach(params -> {
|
||||||
|
WWWFormKV keyValue = new WWWFormKV();
|
||||||
|
parseParams(params, keyValue);
|
||||||
|
keyValues.add(keyValue);
|
||||||
|
});
|
||||||
|
samplerProxy.getBody().setWwwFormBody(new WWWFormBody() {{
|
||||||
|
this.setFormValues(keyValues);
|
||||||
|
}});
|
||||||
|
} else if (samplerProxy.getBody() != null && samplerProxy.getBody().getBodyType().equals(Body.BodyType.FORM_DATA.name())) {
|
||||||
|
source.getArguments().getArguments().forEach(params -> {
|
||||||
|
FormDataKV keyValue = new FormDataKV();
|
||||||
|
parseParams(params, keyValue);
|
||||||
|
samplerProxy.getBody().getFormDataBody().getFormValues().add(keyValue);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
List<QueryParam> keyValues = new LinkedList<>();
|
||||||
|
source.getArguments().getArguments().forEach(params -> {
|
||||||
|
QueryParam keyValue = new QueryParam();
|
||||||
|
parseParams(params, keyValue);
|
||||||
|
keyValues.add(keyValue);
|
||||||
|
});
|
||||||
|
if (CollectionUtils.isNotEmpty(keyValues)) {
|
||||||
|
samplerProxy.setQuery(keyValues);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
samplerProxy.setPath(source.getPath());
|
||||||
|
samplerProxy.setMethod(source.getMethod());
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtils.error(e);
|
||||||
|
}
|
||||||
|
return samplerProxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getBodyType(List<MsHeader> headers) {
|
||||||
|
if (CollectionUtils.isNotEmpty(headers)) {
|
||||||
|
List<MsHeader> keyValues = headers.stream().filter(keyValue -> "Content-Type".equals(keyValue.getKey()) && "application/x-www-form-urlencoded".equals(keyValue.getValue())).collect(Collectors.toList());
|
||||||
|
if (CollectionUtils.isNotEmpty(keyValues)) {
|
||||||
|
return keyValues.getFirst().getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static FormDataKV getFormDataKV(HTTPFileArg arg) {
|
||||||
|
ApiFile file = new ApiFile();
|
||||||
|
file.setFileId(arg.getParamName());
|
||||||
|
String fileName = arg.getPath();
|
||||||
|
if (fileName.contains("/")) {
|
||||||
|
fileName = fileName.substring(fileName.lastIndexOf("/") + 1);
|
||||||
|
}
|
||||||
|
file.setFileName(fileName);
|
||||||
|
|
||||||
|
FormDataKV keyValue = new FormDataKV();
|
||||||
|
keyValue.setKey(arg.getParamName());
|
||||||
|
keyValue.setValue(arg.getParamName());
|
||||||
|
keyValue.setContentType(arg.getMimeType());
|
||||||
|
keyValue.setContentType("file");
|
||||||
|
keyValue.setFiles(Collections.singletonList(file));
|
||||||
|
return keyValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseParams(JMeterProperty params, KeyValueEnableParam keyValue) {
|
||||||
|
if (params == null || keyValue == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Object objValue = params.getObjectValue();
|
||||||
|
if (objValue instanceof HTTPArgument) {
|
||||||
|
HTTPArgument argument = (HTTPArgument) objValue;
|
||||||
|
keyValue.setKey(argument.getName());
|
||||||
|
keyValue.setValue(argument.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
package io.metersphere.api.parser.ms;
|
package io.metersphere.api.parser.ms;
|
||||||
|
|
||||||
|
import io.metersphere.api.parser.ms.http.HeaderManagerConverter;
|
||||||
|
import io.metersphere.api.parser.ms.http.post.*;
|
||||||
|
import io.metersphere.api.parser.ms.http.pre.BeanShellPreProcessConverter;
|
||||||
|
import io.metersphere.api.parser.ms.http.pre.JDBCPreProcessConverter;
|
||||||
|
import io.metersphere.api.parser.ms.http.pre.JSR223PreProcessConverter;
|
||||||
import io.metersphere.plugin.api.spi.AbstractMsElementConverter;
|
import io.metersphere.plugin.api.spi.AbstractMsElementConverter;
|
||||||
import io.metersphere.plugin.sdk.util.PluginLogUtils;
|
import io.metersphere.plugin.sdk.util.PluginLogUtils;
|
||||||
import org.apache.jmeter.testelement.TestElement;
|
import org.apache.jmeter.testelement.TestElement;
|
||||||
|
@ -30,6 +35,22 @@ public class MsElementConverterRegister {
|
||||||
register(TestPlanConverter.class);
|
register(TestPlanConverter.class);
|
||||||
register(ThreadGroupConverter.class);
|
register(ThreadGroupConverter.class);
|
||||||
register(HTTPSamplerConverter.class);
|
register(HTTPSamplerConverter.class);
|
||||||
|
register(HeaderManagerConverter.class);
|
||||||
|
|
||||||
|
register(BeanShellPostProcessConverter.class);
|
||||||
|
register(ConstantTimerConverter.class);
|
||||||
|
register(JDBCPostProcessConverter.class);
|
||||||
|
register(JSONPostProcessorConverter.class);
|
||||||
|
register(JSR223PostProcessConverter.class);
|
||||||
|
register(RegexExtractorConverter.class);
|
||||||
|
register(XPath2ExtractorConverter.class);
|
||||||
|
register(XPathExtractorConverter.class);
|
||||||
|
|
||||||
|
register(BeanShellPreProcessConverter.class);
|
||||||
|
register(JDBCPreProcessConverter.class);
|
||||||
|
register(JSR223PreProcessConverter.class);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
package io.metersphere.api.parser.ms;
|
package io.metersphere.api.parser.ms;
|
||||||
|
|
||||||
import io.metersphere.api.dto.request.MsScenario;
|
import io.metersphere.api.dto.request.MsScenario;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsProtocolTestElement;
|
||||||
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
import org.apache.jmeter.testelement.TestElement;
|
import org.apache.jmeter.testelement.TestElement;
|
||||||
import org.apache.jorphan.collections.HashTree;
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: jianxing
|
* @Author: jianxing
|
||||||
* @CreateTime: 2023-10-27 10:07
|
* @CreateTime: 2023-10-27 10:07
|
||||||
|
@ -22,4 +26,16 @@ public class MsTestElementParser {
|
||||||
}
|
}
|
||||||
return msScenario;
|
return msScenario;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<AbstractMsProtocolTestElement> getAbstractMsProtocolTestElement(AbstractMsTestElement msTestElement) {
|
||||||
|
List<AbstractMsProtocolTestElement> result = new ArrayList<>();
|
||||||
|
if (msTestElement instanceof AbstractMsProtocolTestElement abstractMsProtocolTestElement) {
|
||||||
|
result.add(abstractMsProtocolTestElement);
|
||||||
|
} else {
|
||||||
|
for (AbstractMsTestElement child : msTestElement.getChildren()) {
|
||||||
|
result.addAll(this.getAbstractMsProtocolTestElement(child));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
package io.metersphere.api.parser.ms.http;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
||||||
|
import io.metersphere.api.dto.request.http.MsHeader;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsElementConverter;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
import org.apache.jmeter.protocol.http.control.HeaderManager;
|
||||||
|
import org.apache.jmeter.testelement.property.CollectionProperty;
|
||||||
|
import org.apache.jmeter.testelement.property.JMeterProperty;
|
||||||
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class HeaderManagerConverter extends AbstractMsElementConverter<HeaderManager> {
|
||||||
|
@Override
|
||||||
|
public void toMsElement(AbstractMsTestElement parent, HeaderManager element, HashTree hashTree) {
|
||||||
|
if (parent instanceof MsHTTPElement msHTTPElement) {
|
||||||
|
// 处理HTTP协议的请求头
|
||||||
|
List<MsHeader> headerKvList = msHTTPElement.getHeaders() == null ? new LinkedList<>() : msHTTPElement.getHeaders();
|
||||||
|
CollectionProperty collectionProperty = element.getHeaders();
|
||||||
|
List<String> extendsHeaderKey = headerKvList.stream().map(MsHeader::getKey).toList();
|
||||||
|
for (int i = 0; i < collectionProperty.size(); i++) {
|
||||||
|
JMeterProperty jMeterProperty = collectionProperty.get(i);
|
||||||
|
String key = jMeterProperty.getName();
|
||||||
|
if (!extendsHeaderKey.contains(key)) {
|
||||||
|
headerKvList.add(new MsHeader() {{
|
||||||
|
this.setKey(key);
|
||||||
|
this.setValue(jMeterProperty.getStringValue());
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msHTTPElement.setHeaders(headerKvList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package io.metersphere.api.parser.ms.http.post;
|
||||||
|
|
||||||
|
import io.metersphere.api.utils.ConverterUtils;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsElementConverter;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
import io.metersphere.project.api.processor.ScriptProcessor;
|
||||||
|
import io.metersphere.project.constants.ScriptLanguageType;
|
||||||
|
import org.apache.jmeter.extractor.BeanShellPostProcessor;
|
||||||
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
public class BeanShellPostProcessConverter extends AbstractMsElementConverter<BeanShellPostProcessor> {
|
||||||
|
@Override
|
||||||
|
public void toMsElement(AbstractMsTestElement parent, BeanShellPostProcessor element, HashTree hashTree) {
|
||||||
|
ScriptProcessor msScriptElement = new ScriptProcessor();
|
||||||
|
msScriptElement.setEnable(element.isEnabled());
|
||||||
|
msScriptElement.setScriptLanguage(ScriptLanguageType.BEANSHELL.name());
|
||||||
|
msScriptElement.setName(element.getPropertyAsString("TestElement.name"));
|
||||||
|
msScriptElement.setScript(element.getPropertyAsString("script"));
|
||||||
|
ConverterUtils.addPostProcess(parent, msScriptElement);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package io.metersphere.api.parser.ms.http.post;
|
||||||
|
|
||||||
|
import io.metersphere.api.utils.ConverterUtils;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsElementConverter;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
import io.metersphere.project.api.processor.TimeWaitingProcessor;
|
||||||
|
import org.apache.jmeter.timers.ConstantTimer;
|
||||||
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
public class ConstantTimerConverter extends AbstractMsElementConverter<ConstantTimer> {
|
||||||
|
@Override
|
||||||
|
public void toMsElement(AbstractMsTestElement parent, ConstantTimer element, HashTree hashTree) {
|
||||||
|
TimeWaitingProcessor msProcessor = new TimeWaitingProcessor();
|
||||||
|
msProcessor.setDelay(Long.parseLong(element.getDelay()));
|
||||||
|
msProcessor.setEnable(element.isEnabled());
|
||||||
|
msProcessor.setName(element.getName());
|
||||||
|
ConverterUtils.addPreProcess(parent, msProcessor);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package io.metersphere.api.parser.ms.http.post;
|
||||||
|
|
||||||
|
import io.metersphere.api.utils.ConverterUtils;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsElementConverter;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
import org.apache.jmeter.protocol.jdbc.processor.JDBCPostProcessor;
|
||||||
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
public class JDBCPostProcessConverter extends AbstractMsElementConverter<JDBCPostProcessor> {
|
||||||
|
@Override
|
||||||
|
public void toMsElement(AbstractMsTestElement parent, JDBCPostProcessor element, HashTree hashTree) {
|
||||||
|
ConverterUtils.addPostProcess(parent, ConverterUtils.genJDBCProcessor(element));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package io.metersphere.api.parser.ms.http.post;
|
||||||
|
|
||||||
|
import io.metersphere.api.utils.ConverterUtils;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsElementConverter;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
import io.metersphere.project.api.processor.extract.JSONPathExtract;
|
||||||
|
import io.metersphere.project.api.processor.extract.ResultMatchingExtract;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.jmeter.extractor.json.jsonpath.JSONPostProcessor;
|
||||||
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
public class JSONPostProcessorConverter extends AbstractMsElementConverter<JSONPostProcessor> {
|
||||||
|
@Override
|
||||||
|
public void toMsElement(AbstractMsTestElement parent, JSONPostProcessor element, HashTree hashTree) {
|
||||||
|
JSONPathExtract jsonPathExtract = new JSONPathExtract();
|
||||||
|
jsonPathExtract.setVariableName(element.getRefNames());
|
||||||
|
jsonPathExtract.setExpression(element.getJsonPathExpressions());
|
||||||
|
jsonPathExtract.setEnable(element.isEnabled());
|
||||||
|
|
||||||
|
if (StringUtils.equalsIgnoreCase(element.getMatchNumbers(), "-1")) {
|
||||||
|
jsonPathExtract.setResultMatchingRule(ResultMatchingExtract.ResultMatchingRuleType.ALL.name());
|
||||||
|
jsonPathExtract.setResultMatchingRuleNum(-1);
|
||||||
|
} else if (StringUtils.equalsIgnoreCase(element.getMatchNumbers(), "0")) {
|
||||||
|
jsonPathExtract.setResultMatchingRule(ResultMatchingExtract.ResultMatchingRuleType.RANDOM.name());
|
||||||
|
jsonPathExtract.setResultMatchingRuleNum(0);
|
||||||
|
} else {
|
||||||
|
jsonPathExtract.setResultMatchingRule(ResultMatchingExtract.ResultMatchingRuleType.SPECIFIC.name());
|
||||||
|
try {
|
||||||
|
jsonPathExtract.setResultMatchingRuleNum(Integer.parseInt(element.getMatchNumbers()));
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConverterUtils.addPostExtract(parent, jsonPathExtract);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package io.metersphere.api.parser.ms.http.post;
|
||||||
|
|
||||||
|
import io.metersphere.api.utils.ConverterUtils;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsElementConverter;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
import io.metersphere.project.api.processor.ScriptProcessor;
|
||||||
|
import org.apache.jmeter.extractor.JSR223PostProcessor;
|
||||||
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
public class JSR223PostProcessConverter extends AbstractMsElementConverter<JSR223PostProcessor> {
|
||||||
|
@Override
|
||||||
|
public void toMsElement(AbstractMsTestElement parent, JSR223PostProcessor element, HashTree hashTree) {
|
||||||
|
ScriptProcessor msScriptElement = new ScriptProcessor();
|
||||||
|
msScriptElement.setScriptLanguage(element.getScriptLanguage());
|
||||||
|
msScriptElement.setEnable(element.isEnabled());
|
||||||
|
msScriptElement.setName(element.getPropertyAsString("TestElement.name"));
|
||||||
|
msScriptElement.setScript(element.getPropertyAsString("script"));
|
||||||
|
ConverterUtils.addPostProcess(parent, msScriptElement);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package io.metersphere.api.parser.ms.http.post;
|
||||||
|
|
||||||
|
import io.metersphere.api.utils.ConverterUtils;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsElementConverter;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
import io.metersphere.project.api.processor.extract.RegexExtract;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.jmeter.extractor.RegexExtractor;
|
||||||
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
public class RegexExtractorConverter extends AbstractMsElementConverter<RegexExtractor> {
|
||||||
|
@Override
|
||||||
|
public void toMsElement(AbstractMsTestElement parent, RegexExtractor element, HashTree hashTree) {
|
||||||
|
RegexExtract regexExtract = new RegexExtract();
|
||||||
|
regexExtract.setVariableName(element.getRefName());
|
||||||
|
regexExtract.setExpression(element.getRegex());
|
||||||
|
regexExtract.setEnable(element.isEnabled());
|
||||||
|
regexExtract.setExtractScope(this.getUseField(element));
|
||||||
|
regexExtract.setResultMatchingRuleNum(element.getMatchNumber());
|
||||||
|
|
||||||
|
ConverterUtils.addPostExtract(parent, regexExtract);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getUseField(RegexExtractor element) {
|
||||||
|
String useHeaders = element.getPropertyAsString("RegexExtractor.useHeaders");
|
||||||
|
if (StringUtils.equalsIgnoreCase(useHeaders, "false")) {
|
||||||
|
return RegexExtract.ExtractScope.BODY.name();
|
||||||
|
} else if (StringUtils.equalsIgnoreCase(useHeaders, "unescaped")) {
|
||||||
|
return RegexExtract.ExtractScope.UNESCAPED_BODY.name();
|
||||||
|
} else if (StringUtils.equalsIgnoreCase(useHeaders, "as_document")) {
|
||||||
|
return RegexExtract.ExtractScope.BODY_AS_DOCUMENT.name();
|
||||||
|
} else if (StringUtils.equalsIgnoreCase(useHeaders, "true")) {
|
||||||
|
return RegexExtract.ExtractScope.RESPONSE_HEADERS.name();
|
||||||
|
} else if (StringUtils.equalsIgnoreCase(useHeaders, "request_headers")) {
|
||||||
|
return RegexExtract.ExtractScope.REQUEST_HEADERS.name();
|
||||||
|
} else if (StringUtils.equalsIgnoreCase(useHeaders, "URL")) {
|
||||||
|
return RegexExtract.ExtractScope.URL.name();
|
||||||
|
} else if (StringUtils.equalsIgnoreCase(useHeaders, "code")) {
|
||||||
|
return RegexExtract.ExtractScope.RESPONSE_CODE.name();
|
||||||
|
} else if (StringUtils.equalsIgnoreCase(useHeaders, "message")) {
|
||||||
|
return RegexExtract.ExtractScope.RESPONSE_MESSAGE.name();
|
||||||
|
}
|
||||||
|
return useHeaders;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package io.metersphere.api.parser.ms.http.post;
|
||||||
|
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsElementConverter;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
import org.apache.jmeter.assertions.ResponseAssertion;
|
||||||
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
public class ResponseAssertionConverter extends AbstractMsElementConverter<ResponseAssertion> {
|
||||||
|
@Override
|
||||||
|
public void toMsElement(AbstractMsTestElement parent, ResponseAssertion element, HashTree hashTree) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package io.metersphere.api.parser.ms.http.post;
|
||||||
|
|
||||||
|
import io.metersphere.api.utils.ConverterUtils;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsElementConverter;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
import io.metersphere.project.api.processor.extract.ResultMatchingExtract;
|
||||||
|
import io.metersphere.project.api.processor.extract.XPathExtract;
|
||||||
|
import org.apache.jmeter.extractor.XPath2Extractor;
|
||||||
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
public class XPath2ExtractorConverter extends AbstractMsElementConverter<XPath2Extractor> {
|
||||||
|
@Override
|
||||||
|
public void toMsElement(AbstractMsTestElement parent, XPath2Extractor element, HashTree hashTree) {
|
||||||
|
XPathExtract xPathExtract = new XPathExtract();
|
||||||
|
xPathExtract.setEnable(element.isEnabled());
|
||||||
|
xPathExtract.setResponseFormat(XPathExtract.ResponseFormat.XML.name());
|
||||||
|
xPathExtract.setVariableName(element.getRefName());
|
||||||
|
xPathExtract.setExpression(element.getXPathQuery());
|
||||||
|
|
||||||
|
if (element.getMatchNumber() == -1) {
|
||||||
|
xPathExtract.setResultMatchingRule(ResultMatchingExtract.ResultMatchingRuleType.ALL.name());
|
||||||
|
xPathExtract.setResultMatchingRuleNum(-1);
|
||||||
|
} else if (element.getMatchNumber() == 0) {
|
||||||
|
xPathExtract.setResultMatchingRule(ResultMatchingExtract.ResultMatchingRuleType.RANDOM.name());
|
||||||
|
xPathExtract.setResultMatchingRuleNum(0);
|
||||||
|
} else {
|
||||||
|
xPathExtract.setResultMatchingRule(ResultMatchingExtract.ResultMatchingRuleType.SPECIFIC.name());
|
||||||
|
xPathExtract.setResultMatchingRuleNum(element.getMatchNumber());
|
||||||
|
}
|
||||||
|
// xPathExtract.setVariableType(element.getPropertyAsString("type"));
|
||||||
|
// xPathExtract.setExpression(element.getPropertyAsString("expression"));
|
||||||
|
|
||||||
|
ConverterUtils.addPostExtract(parent, xPathExtract);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package io.metersphere.api.parser.ms.http.post;
|
||||||
|
|
||||||
|
import io.metersphere.api.utils.ConverterUtils;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsElementConverter;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
import io.metersphere.project.api.processor.extract.JSONPathExtract;
|
||||||
|
import io.metersphere.project.api.processor.extract.RegexExtract;
|
||||||
|
import io.metersphere.project.api.processor.extract.ResultMatchingExtract;
|
||||||
|
import io.metersphere.project.api.processor.extract.XPathExtract;
|
||||||
|
import org.apache.jmeter.extractor.XPathExtractor;
|
||||||
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
public class XPathExtractorConverter extends AbstractMsElementConverter<XPathExtractor> {
|
||||||
|
@Override
|
||||||
|
public void toMsElement(AbstractMsTestElement parent, XPathExtractor element, HashTree hashTree) {
|
||||||
|
|
||||||
|
JSONPathExtract jsonPathExtract = new JSONPathExtract();
|
||||||
|
RegexExtract regexExtract = new RegexExtract();
|
||||||
|
|
||||||
|
XPathExtract xPathExtract = new XPathExtract();
|
||||||
|
xPathExtract.setEnable(element.isEnabled());
|
||||||
|
xPathExtract.setResponseFormat(XPathExtract.ResponseFormat.HTML.name());
|
||||||
|
xPathExtract.setVariableName(element.getRefName());
|
||||||
|
xPathExtract.setExpression(element.getXPathQuery());
|
||||||
|
|
||||||
|
if (element.getMatchNumber() == -1) {
|
||||||
|
xPathExtract.setResultMatchingRule(ResultMatchingExtract.ResultMatchingRuleType.ALL.name());
|
||||||
|
xPathExtract.setResultMatchingRuleNum(-1);
|
||||||
|
} else if (element.getMatchNumber() == 0) {
|
||||||
|
xPathExtract.setResultMatchingRule(ResultMatchingExtract.ResultMatchingRuleType.RANDOM.name());
|
||||||
|
xPathExtract.setResultMatchingRuleNum(0);
|
||||||
|
} else {
|
||||||
|
xPathExtract.setResultMatchingRule(ResultMatchingExtract.ResultMatchingRuleType.SPECIFIC.name());
|
||||||
|
xPathExtract.setResultMatchingRuleNum(element.getMatchNumber());
|
||||||
|
}
|
||||||
|
ConverterUtils.addPostExtract(parent, xPathExtract);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package io.metersphere.api.parser.ms.http.pre;
|
||||||
|
|
||||||
|
import io.metersphere.api.utils.ConverterUtils;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsElementConverter;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
import io.metersphere.project.api.processor.ScriptProcessor;
|
||||||
|
import io.metersphere.project.constants.ScriptLanguageType;
|
||||||
|
import org.apache.jmeter.modifiers.BeanShellPreProcessor;
|
||||||
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
public class BeanShellPreProcessConverter extends AbstractMsElementConverter<BeanShellPreProcessor> {
|
||||||
|
@Override
|
||||||
|
public void toMsElement(AbstractMsTestElement parent, BeanShellPreProcessor element, HashTree hashTree) {
|
||||||
|
ScriptProcessor msScriptElement = new ScriptProcessor();
|
||||||
|
msScriptElement.setEnable(element.isEnabled());
|
||||||
|
msScriptElement.setScriptLanguage(ScriptLanguageType.BEANSHELL.name());
|
||||||
|
msScriptElement.setName(element.getPropertyAsString("TestElement.name"));
|
||||||
|
msScriptElement.setScript(element.getPropertyAsString("script"));
|
||||||
|
ConverterUtils.addPreProcess(parent, msScriptElement);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package io.metersphere.api.parser.ms.http.pre;
|
||||||
|
|
||||||
|
import io.metersphere.api.utils.ConverterUtils;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsElementConverter;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
import org.apache.jmeter.protocol.jdbc.processor.JDBCPreProcessor;
|
||||||
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
public class JDBCPreProcessConverter extends AbstractMsElementConverter<JDBCPreProcessor> {
|
||||||
|
@Override
|
||||||
|
public void toMsElement(AbstractMsTestElement parent, JDBCPreProcessor element, HashTree hashTree) {
|
||||||
|
ConverterUtils.addPreProcess(parent, ConverterUtils.genJDBCProcessor(element));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package io.metersphere.api.parser.ms.http.pre;
|
||||||
|
|
||||||
|
import io.metersphere.api.utils.ConverterUtils;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsElementConverter;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
import io.metersphere.project.api.processor.ScriptProcessor;
|
||||||
|
import org.apache.jmeter.modifiers.JSR223PreProcessor;
|
||||||
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
public class JSR223PreProcessConverter extends AbstractMsElementConverter<JSR223PreProcessor> {
|
||||||
|
@Override
|
||||||
|
public void toMsElement(AbstractMsTestElement parent, JSR223PreProcessor element, HashTree hashTree) {
|
||||||
|
|
||||||
|
ScriptProcessor msScriptElement = new ScriptProcessor();
|
||||||
|
msScriptElement.setScriptLanguage(element.getScriptLanguage());
|
||||||
|
msScriptElement.setEnable(element.isEnabled());
|
||||||
|
msScriptElement.setName(element.getPropertyAsString("TestElement.name"));
|
||||||
|
msScriptElement.setScript(element.getPropertyAsString("script"));
|
||||||
|
|
||||||
|
ConverterUtils.addPreProcess(parent, msScriptElement);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,8 @@
|
||||||
package io.metersphere.api.service.definition;
|
package io.metersphere.api.service.definition;
|
||||||
|
|
||||||
import io.metersphere.api.domain.*;
|
import io.metersphere.api.domain.ApiDefinitionModule;
|
||||||
import io.metersphere.api.dto.definition.ApiDefinitionBatchRequest;
|
import io.metersphere.api.domain.ApiDefinitionModuleExample;
|
||||||
import io.metersphere.api.dto.definition.ApiDefinitionWithBlob;
|
import io.metersphere.api.dto.definition.*;
|
||||||
import io.metersphere.api.dto.definition.ApiMockWithBlob;
|
|
||||||
import io.metersphere.api.dto.definition.ApiTestCaseWithBlob;
|
|
||||||
import io.metersphere.api.dto.export.ApiExportResponse;
|
import io.metersphere.api.dto.export.ApiExportResponse;
|
||||||
import io.metersphere.api.mapper.*;
|
import io.metersphere.api.mapper.*;
|
||||||
import io.metersphere.api.parser.api.MetersphereExportParser;
|
import io.metersphere.api.parser.api.MetersphereExportParser;
|
||||||
|
@ -16,6 +14,7 @@ import io.metersphere.sdk.exception.MSException;
|
||||||
import io.metersphere.system.utils.CustomFieldUtils;
|
import io.metersphere.system.utils.CustomFieldUtils;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -45,12 +44,12 @@ public class ApiDefinitionExportService {
|
||||||
private ApiDefinitionMapper apiDefinitionMapper;
|
private ApiDefinitionMapper apiDefinitionMapper;
|
||||||
|
|
||||||
|
|
||||||
public ApiExportResponse export(ApiDefinitionBatchRequest request, String type, String userId) {
|
public ApiExportResponse export(ApiDefinitionBatchExportRequest request, String type, String userId) {
|
||||||
List<String> ids = getBatchApiIds(request, request.getProjectId(), List.of(ModuleConstants.NODE_PROTOCOL_HTTP), false, userId);
|
List<String> ids = this.getBatchExportApiIds(request, request.getProjectId(), userId);
|
||||||
if (CollectionUtils.isEmpty(ids)) {
|
if (CollectionUtils.isEmpty(ids)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
List<ApiDefinitionWithBlob> list = extApiDefinitionMapper.selectApiDefinitionWithBlob(ids);
|
List<ApiDefinitionWithBlob> list = this.selectAndSortByIds(ids);
|
||||||
List<String> moduleIds = list.stream().map(ApiDefinitionWithBlob::getModuleId).toList();
|
List<String> moduleIds = list.stream().map(ApiDefinitionWithBlob::getModuleId).toList();
|
||||||
ApiDefinitionModuleExample example = new ApiDefinitionModuleExample();
|
ApiDefinitionModuleExample example = new ApiDefinitionModuleExample();
|
||||||
example.createCriteria().andIdIn(moduleIds);
|
example.createCriteria().andIdIn(moduleIds);
|
||||||
|
@ -63,20 +62,26 @@ public class ApiDefinitionExportService {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> getBatchApiIds(ApiDefinitionBatchRequest request, String projectId, List<String> protocols, boolean deleted, String userId) {
|
private List<ApiDefinitionWithBlob> selectAndSortByIds(List<String> ids) {
|
||||||
|
Map<String, ApiDefinitionWithBlob> apiMap = extApiDefinitionMapper.selectApiDefinitionWithBlob(ids).stream().collect(Collectors.toMap(ApiDefinitionWithBlob::getId, v -> v));
|
||||||
|
return ids.stream().map(apiMap::get).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getBatchExportApiIds(ApiDefinitionBatchExportRequest request, String exportType, String userId) {
|
||||||
|
List<String> protocols = request.getProtocols();
|
||||||
|
if (StringUtils.equalsIgnoreCase(exportType, "swagger")) {
|
||||||
|
protocols = List.of(ModuleConstants.NODE_PROTOCOL_HTTP);
|
||||||
|
}
|
||||||
|
|
||||||
if (request.isSelectAll()) {
|
if (request.isSelectAll()) {
|
||||||
CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(request.getCondition(), userId);
|
CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(request.getCondition(), userId);
|
||||||
List<String> ids = extApiDefinitionMapper.getIds(request, projectId, protocols, deleted);
|
List<String> ids = extApiDefinitionMapper.getIdsBySort(request, request.getProjectId(), protocols, request.getSortString());
|
||||||
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
|
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
|
||||||
ids.removeAll(request.getExcludeIds());
|
ids.removeAll(request.getExcludeIds());
|
||||||
}
|
}
|
||||||
return ids;
|
return ids;
|
||||||
} else {
|
} else {
|
||||||
request.getSelectIds().removeAll(request.getExcludeIds());
|
return request.getSelectIds();
|
||||||
ApiDefinitionExample definitionExample = new ApiDefinitionExample();
|
|
||||||
definitionExample.createCriteria().andIdIn(request.getSelectIds()).andProtocolIn(protocols).andDeletedEqualTo(deleted);
|
|
||||||
List<ApiDefinition> apiDefinitions = apiDefinitionMapper.selectByExample(definitionExample);
|
|
||||||
return apiDefinitions.stream().map(ApiDefinition::getId).toList();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,15 +95,11 @@ public class ApiDefinitionExportService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Resource
|
private ApiExportResponse exportMetersphere(ApiDefinitionBatchExportRequest request, List<ApiDefinitionWithBlob> list, Map<String, String> moduleMap) {
|
||||||
private ApiTestCaseBlobMapper apiTestCaseBlobMapper;
|
|
||||||
|
|
||||||
private ApiExportResponse exportMetersphere(ApiDefinitionBatchRequest request, List<ApiDefinitionWithBlob> list, Map<String, String> moduleMap) {
|
|
||||||
try {
|
try {
|
||||||
List<String> apiIds = list.stream().map(ApiDefinitionWithBlob::getId).toList();
|
List<String> apiIds = list.stream().map(ApiDefinitionWithBlob::getId).toList();
|
||||||
List<ApiTestCaseWithBlob> apiTestCaseWithBlobs = new ArrayList<>();
|
List<ApiTestCaseWithBlob> apiTestCaseWithBlobs = new ArrayList<>();
|
||||||
List<ApiMockWithBlob> apiMockWithBlobs = new ArrayList<>();
|
List<ApiMockWithBlob> apiMockWithBlobs = new ArrayList<>();
|
||||||
List<ApiTestCaseBlob> apiTestCaseBlobs = new ArrayList<>();
|
|
||||||
if (request.isExportApiCase()) {
|
if (request.isExportApiCase()) {
|
||||||
apiTestCaseWithBlobs = extApiTestCaseMapper.selectAllDetailByApiIds(apiIds);
|
apiTestCaseWithBlobs = extApiTestCaseMapper.selectAllDetailByApiIds(apiIds);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,10 @@ import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static io.metersphere.project.utils.NodeSortUtils.DEFAULT_NODE_INTERVAL_POS;
|
import static io.metersphere.project.utils.NodeSortUtils.DEFAULT_NODE_INTERVAL_POS;
|
||||||
|
@ -99,6 +102,9 @@ public class ApiDefinitionImportService {
|
||||||
if (StringUtils.isBlank(request.getProjectId())) {
|
if (StringUtils.isBlank(request.getProjectId())) {
|
||||||
request.setProjectId(projectId);
|
request.setProjectId(projectId);
|
||||||
}
|
}
|
||||||
|
if (StringUtils.equalsIgnoreCase(request.getType(), ApiImportPlatform.Jmeter.name())) {
|
||||||
|
request.setSyncCase(true);
|
||||||
|
}
|
||||||
//判断是否是定时任务进入
|
//判断是否是定时任务进入
|
||||||
if (StringUtils.equals(request.getType(), "SCHEDULE")) {
|
if (StringUtils.equals(request.getType(), "SCHEDULE")) {
|
||||||
request.setProtocol(ModuleConstants.NODE_PROTOCOL_HTTP);
|
request.setProtocol(ModuleConstants.NODE_PROTOCOL_HTTP);
|
||||||
|
@ -118,22 +124,26 @@ public class ApiDefinitionImportService {
|
||||||
this.initImportRequestAndCheck(file, request, projectId);
|
this.initImportRequestAndCheck(file, request, projectId);
|
||||||
ApiDefinitionImportParser<?> runService = ImportParserFactory.getImportParser(request.getPlatform());
|
ApiDefinitionImportParser<?> runService = ImportParserFactory.getImportParser(request.getPlatform());
|
||||||
assert runService != null;
|
assert runService != null;
|
||||||
ApiImportDataAnalysisResult apiImportDataAnalysisResult;
|
ApiImportDataAnalysisResult apiImportDataAnalysisResult = new ApiImportDataAnalysisResult();
|
||||||
try {
|
try {
|
||||||
//解析文件
|
//解析文件
|
||||||
ApiImportFileParseResult fileParseResult = (ApiImportFileParseResult) runService.parse(file == null ? null : file.getInputStream(), request);
|
ApiImportFileParseResult fileParseResult = (ApiImportFileParseResult) runService.parse(file == null ? null : file.getInputStream(), request);
|
||||||
|
if (!CollectionUtils.isEmpty(fileParseResult.getData())) {
|
||||||
ApiDefinitionPageRequest pageRequest = new ApiDefinitionPageRequest();
|
ApiDefinitionPageRequest pageRequest = new ApiDefinitionPageRequest();
|
||||||
pageRequest.setProjectId(request.getProjectId());
|
pageRequest.setProjectId(request.getProjectId());
|
||||||
pageRequest.setProtocols(Collections.singletonList(runService.getParseProtocol()));
|
pageRequest.setProtocols(fileParseResult.getApiProtocols());
|
||||||
List<ApiDefinitionDetail> existenceApiDefinitionList = extApiDefinitionMapper.importList(pageRequest);
|
List<ApiDefinitionDetail> existenceApiDefinitionList = extApiDefinitionMapper.importList(pageRequest);
|
||||||
//分析有哪些数据需要新增、有哪些数据需要更新
|
//分析有哪些数据需要新增、有哪些数据需要更新
|
||||||
apiImportDataAnalysisResult = runService.generateInsertAndUpdateData(fileParseResult, existenceApiDefinitionList);
|
apiImportDataAnalysisResult = runService.generateInsertAndUpdateData(fileParseResult, existenceApiDefinitionList);
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtils.error(e.getMessage(), e);
|
LogUtils.error(e.getMessage(), e);
|
||||||
throw new MSException(Translator.get("parse_data_error"));
|
throw new MSException(Translator.get("parse_data_error"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (apiImportDataAnalysisResult.isEmpty()) {
|
||||||
|
throw new MSException(Translator.get("parse_empty_data"));
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
//初始化版本信息,用于保存,以及以后真对具体版本导入进行拓展
|
//初始化版本信息,用于保存,以及以后真对具体版本导入进行拓展
|
||||||
String defaultVersion = extBaseProjectVersionMapper.getDefaultVersion(request.getProjectId());
|
String defaultVersion = extBaseProjectVersionMapper.getDefaultVersion(request.getProjectId());
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package io.metersphere.api.utils;
|
package io.metersphere.api.utils;
|
||||||
|
|
||||||
import io.metersphere.api.constants.ApiImportPlatform;
|
import io.metersphere.api.constants.ApiImportPlatform;
|
||||||
|
import io.metersphere.api.dto.converter.ApiDefinitionDetail;
|
||||||
|
import io.metersphere.api.dto.definition.ApiDefinitionMockDTO;
|
||||||
|
import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
||||||
import io.metersphere.api.dto.request.ImportRequest;
|
import io.metersphere.api.dto.request.ImportRequest;
|
||||||
import io.metersphere.project.domain.Project;
|
import io.metersphere.project.domain.Project;
|
||||||
import io.metersphere.sdk.constants.HttpMethodConstants;
|
import io.metersphere.sdk.constants.HttpMethodConstants;
|
||||||
|
@ -8,6 +11,10 @@ import io.metersphere.sdk.exception.MSException;
|
||||||
import io.metersphere.sdk.util.JSON;
|
import io.metersphere.sdk.util.JSON;
|
||||||
import io.metersphere.sdk.util.Translator;
|
import io.metersphere.sdk.util.Translator;
|
||||||
import io.metersphere.system.log.dto.LogDTO;
|
import io.metersphere.system.log.dto.LogDTO;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
public class ApiDefinitionImportUtils {
|
public class ApiDefinitionImportUtils {
|
||||||
|
@ -48,4 +55,56 @@ public class ApiDefinitionImportUtils {
|
||||||
dto.setOriginalValue(JSON.toJSONBytes(importData));
|
dto.setOriginalValue(JSON.toJSONBytes(importData));
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<ApiDefinitionDetail> apiRename(List<ApiDefinitionDetail> caseList) {
|
||||||
|
List<ApiDefinitionDetail> returnList = new ArrayList<>();
|
||||||
|
if (CollectionUtils.isNotEmpty(caseList)) {
|
||||||
|
List<String> caseNameList = new ArrayList<>();
|
||||||
|
for (ApiDefinitionDetail apiCase : caseList) {
|
||||||
|
String uniqueName = getUniqueName(apiCase.getName(), caseNameList);
|
||||||
|
apiCase.setName(uniqueName);
|
||||||
|
caseNameList.add(uniqueName);
|
||||||
|
returnList.add(apiCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ApiTestCaseDTO> apiCaseRename(List<ApiTestCaseDTO> caseList) {
|
||||||
|
List<ApiTestCaseDTO> returnList = new ArrayList<>();
|
||||||
|
if (CollectionUtils.isNotEmpty(caseList)) {
|
||||||
|
List<String> caseNameList = new ArrayList<>();
|
||||||
|
for (ApiTestCaseDTO apiCase : caseList) {
|
||||||
|
String uniqueName = getUniqueName(apiCase.getName(), caseNameList);
|
||||||
|
apiCase.setName(uniqueName);
|
||||||
|
caseNameList.add(uniqueName);
|
||||||
|
returnList.add(apiCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ApiDefinitionMockDTO> apiMockRename(List<ApiDefinitionMockDTO> caseList) {
|
||||||
|
List<ApiDefinitionMockDTO> returnList = new ArrayList<>();
|
||||||
|
if (CollectionUtils.isNotEmpty(caseList)) {
|
||||||
|
List<String> caseNameList = new ArrayList<>();
|
||||||
|
for (ApiDefinitionMockDTO apiMock : caseList) {
|
||||||
|
String uniqueName = ApiDefinitionImportUtils.getUniqueName(apiMock.getName(), caseNameList);
|
||||||
|
apiMock.setName(uniqueName);
|
||||||
|
caseNameList.add(uniqueName);
|
||||||
|
returnList.add(apiMock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getUniqueName(String originalName, List<String> existenceNameList) {
|
||||||
|
String returnName = originalName;
|
||||||
|
int index = 1;
|
||||||
|
while (existenceNameList.contains(returnName)) {
|
||||||
|
returnName = originalName + " - " + index;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return returnName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
package io.metersphere.api.utils;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.request.MsCommonElement;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
import io.metersphere.project.api.processor.ExtractPostProcessor;
|
||||||
|
import io.metersphere.project.api.processor.MsProcessor;
|
||||||
|
import io.metersphere.project.api.processor.SQLProcessor;
|
||||||
|
import io.metersphere.project.api.processor.extract.MsExtract;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.jmeter.testelement.AbstractTestElement;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
public class ConverterUtils {
|
||||||
|
public static void addPreProcess(AbstractMsTestElement parent, MsProcessor msProcessor) {
|
||||||
|
if (CollectionUtils.isEmpty(parent.getChildren())) {
|
||||||
|
MsCommonElement msCommonElement = new MsCommonElement();
|
||||||
|
msCommonElement.getPreProcessorConfig().getProcessors().add(msProcessor);
|
||||||
|
LinkedList<AbstractMsTestElement> children = new LinkedList<>();
|
||||||
|
children.add(msCommonElement);
|
||||||
|
parent.setChildren(children);
|
||||||
|
} else {
|
||||||
|
AbstractMsTestElement child = parent.getChildren().getFirst();
|
||||||
|
if (child instanceof MsCommonElement msCommonElement) {
|
||||||
|
msCommonElement.getPreProcessorConfig().getProcessors().add(msProcessor);
|
||||||
|
} else {
|
||||||
|
MsCommonElement msCommonElement = new MsCommonElement();
|
||||||
|
msCommonElement.getPreProcessorConfig().getProcessors().add(msProcessor);
|
||||||
|
parent.getChildren().add(msCommonElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addPostProcess(AbstractMsTestElement parent, MsProcessor msProcessor) {
|
||||||
|
if (CollectionUtils.isEmpty(parent.getChildren())) {
|
||||||
|
MsCommonElement msCommonElement = new MsCommonElement();
|
||||||
|
msCommonElement.getPostProcessorConfig().getProcessors().add(msProcessor);
|
||||||
|
LinkedList<AbstractMsTestElement> children = new LinkedList<>();
|
||||||
|
children.add(msCommonElement);
|
||||||
|
parent.setChildren(children);
|
||||||
|
} else {
|
||||||
|
AbstractMsTestElement child = parent.getChildren().getFirst();
|
||||||
|
if (child instanceof MsCommonElement msCommonElement) {
|
||||||
|
msCommonElement.getPostProcessorConfig().getProcessors().add(msProcessor);
|
||||||
|
} else {
|
||||||
|
MsCommonElement msCommonElement = new MsCommonElement();
|
||||||
|
msCommonElement.getPostProcessorConfig().getProcessors().add(msProcessor);
|
||||||
|
parent.getChildren().add(msCommonElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addPostExtract(AbstractMsTestElement parent, MsExtract msExtract) {
|
||||||
|
if (CollectionUtils.isEmpty(parent.getChildren())) {
|
||||||
|
ExtractPostProcessor extractPostProcessor = new ExtractPostProcessor();
|
||||||
|
extractPostProcessor.getExtractors().add(msExtract);
|
||||||
|
|
||||||
|
MsCommonElement msCommonElement = new MsCommonElement();
|
||||||
|
msCommonElement.getPostProcessorConfig().getProcessors().add(extractPostProcessor);
|
||||||
|
LinkedList<AbstractMsTestElement> children = new LinkedList<>();
|
||||||
|
children.add(msCommonElement);
|
||||||
|
parent.setChildren(children);
|
||||||
|
} else {
|
||||||
|
AbstractMsTestElement child = parent.getChildren().getFirst();
|
||||||
|
if (child instanceof MsCommonElement msCommonElement) {
|
||||||
|
ExtractPostProcessor extractPostProcessor = null;
|
||||||
|
for (Object processor : msCommonElement.getPostProcessorConfig().getProcessors()) {
|
||||||
|
if (processor instanceof ExtractPostProcessor) {
|
||||||
|
extractPostProcessor = (ExtractPostProcessor) processor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (extractPostProcessor == null) {
|
||||||
|
extractPostProcessor = new ExtractPostProcessor();
|
||||||
|
extractPostProcessor.getExtractors().add(msExtract);
|
||||||
|
msCommonElement.getPostProcessorConfig().getProcessors().add(extractPostProcessor);
|
||||||
|
} else {
|
||||||
|
extractPostProcessor.getExtractors().add(msExtract);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ExtractPostProcessor extractPostProcessor = new ExtractPostProcessor();
|
||||||
|
extractPostProcessor.getExtractors().add(msExtract);
|
||||||
|
|
||||||
|
MsCommonElement msCommonElement = new MsCommonElement();
|
||||||
|
msCommonElement.getPostProcessorConfig().getProcessors().add(extractPostProcessor);
|
||||||
|
parent.getChildren().add(msCommonElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SQLProcessor genJDBCProcessor(AbstractTestElement element) {
|
||||||
|
SQLProcessor msScriptElement = new SQLProcessor();
|
||||||
|
msScriptElement.setEnable(element.isEnabled());
|
||||||
|
msScriptElement.setName(element.getName());
|
||||||
|
msScriptElement.setScript(element.getPropertyAsString("query"));
|
||||||
|
try {
|
||||||
|
msScriptElement.setQueryTimeout(element.getPropertyAsLong("queryTimeout"));
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
|
msScriptElement.setResultVariable(element.getPropertyAsString("resultVariable"));
|
||||||
|
msScriptElement.setVariableNames(element.getPropertyAsString("variableNames"));
|
||||||
|
return msScriptElement;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1759,6 +1759,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
||||||
|
|
||||||
//导入类型以及文件后缀
|
//导入类型以及文件后缀
|
||||||
Map<String, String> importTypeAndSuffix = new LinkedHashMap<>();
|
Map<String, String> importTypeAndSuffix = new LinkedHashMap<>();
|
||||||
|
// importTypeAndSuffix.put("jmeter", "jmx");
|
||||||
importTypeAndSuffix.put("metersphere", "json");
|
importTypeAndSuffix.put("metersphere", "json");
|
||||||
importTypeAndSuffix.put("postman", "json");
|
importTypeAndSuffix.put("postman", "json");
|
||||||
importTypeAndSuffix.put("har", "har");
|
importTypeAndSuffix.put("har", "har");
|
||||||
|
@ -1997,11 +1998,40 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
||||||
Assertions.assertEquals(newApiDefinition.size(), 0);
|
Assertions.assertEquals(newApiDefinition.size(), 0);
|
||||||
Assertions.assertEquals(newApiBlobList.size(), 0);
|
Assertions.assertEquals(newApiBlobList.size(), 0);
|
||||||
Assertions.assertEquals(newApiTestCaseList.size(), 0);
|
Assertions.assertEquals(newApiTestCaseList.size(), 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 最后测试一把JMeter。 5个请求,其中有4个重复的。 导入之后应该是2个请求5个用例,其中1个请求有4个用例
|
||||||
|
File httpJmx = new File(
|
||||||
|
this.getClass().getClassLoader().getResource("file/import/jmeter/post-page.jmx")
|
||||||
|
.getPath()
|
||||||
|
);
|
||||||
|
|
||||||
|
FileInputStream inputStream = new FileInputStream(new File(Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/import/jmeter/post-page.jmx")).getPath()));
|
||||||
|
MockMultipartFile file = new MockMultipartFile("file", "post-page.jmx", MediaType.APPLICATION_OCTET_STREAM_VALUE, inputStream);
|
||||||
|
ImportRequest request = new ImportRequest();
|
||||||
|
request.setProjectId(importProject.getId());
|
||||||
|
request.setUserId("admin");
|
||||||
|
request.setPlatform("Jmeter");
|
||||||
|
request.setSyncCase(true);
|
||||||
|
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
|
||||||
|
paramMap.add("request", JSON.toJSONString(request));
|
||||||
|
paramMap.add("file", file);
|
||||||
|
this.requestMultipartWithOkAndReturn(IMPORT, paramMap);
|
||||||
|
List<ApiDefinitionModule> apiDefinitionModuleList = apiDefinitionModuleMapper.selectByExample(moduleExample);
|
||||||
|
Assertions.assertEquals(0, apiDefinitionModuleList.size());
|
||||||
|
List<ApiDefinitionBlob> apiDefinitionBlobs = apiDefinitionImportTestService.selectBlobByProjectId(importProject.getId());
|
||||||
|
Assertions.assertEquals(2, apiDefinitionBlobs.size());
|
||||||
|
|
||||||
|
List<ApiTestCase> newApiTestCaseList = apiTestCaseMapper.selectByExample(apiTestCaseExample);
|
||||||
|
Assertions.assertEquals(5, newApiTestCaseList.size());
|
||||||
|
//去重处理
|
||||||
|
List<String> apiDefinitionIdList = newApiTestCaseList.stream().map(ApiTestCase::getApiDefinitionId).distinct().collect(Collectors.toList());
|
||||||
|
Assertions.assertEquals(2, apiDefinitionIdList.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testExportAndImport(String exportProjectId, List<ApiDefinitionBlob> exportApiBlobs) throws Exception {
|
private void testExportAndImport(String exportProjectId, List<ApiDefinitionBlob> exportApiBlobs) throws Exception {
|
||||||
ApiDefinitionBatchRequest exportRequest = new ApiDefinitionBatchRequest();
|
ApiDefinitionBatchExportRequest exportRequest = new ApiDefinitionBatchExportRequest();
|
||||||
exportRequest.setProjectId(exportProjectId);
|
exportRequest.setProjectId(exportProjectId);
|
||||||
exportRequest.setSelectAll(true);
|
exportRequest.setSelectAll(true);
|
||||||
exportRequest.setExportApiCase(true);
|
exportRequest.setExportApiCase(true);
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,88 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.4.1">
|
||||||
|
<hashTree>
|
||||||
|
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="测试计划" enabled="true">
|
||||||
|
<stringProp name="TestPlan.comments"></stringProp>
|
||||||
|
<boolProp name="TestPlan.functional_mode">false</boolProp>
|
||||||
|
<boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
|
||||||
|
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
|
||||||
|
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
|
||||||
|
<collectionProp name="Arguments.arguments"/>
|
||||||
|
</elementProp>
|
||||||
|
<stringProp name="TestPlan.user_define_classpath"></stringProp>
|
||||||
|
</TestPlan>
|
||||||
|
<hashTree>
|
||||||
|
<PostThreadGroup guiclass="PostThreadGroupGui" testclass="PostThreadGroup" testname="tearDown线程组" enabled="true">
|
||||||
|
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||||
|
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="循环控制器" enabled="true">
|
||||||
|
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||||
|
<stringProp name="LoopController.loops">1</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
<stringProp name="ThreadGroup.num_threads">1</stringProp>
|
||||||
|
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
|
||||||
|
<boolProp name="ThreadGroup.scheduler">false</boolProp>
|
||||||
|
<stringProp name="ThreadGroup.duration"></stringProp>
|
||||||
|
<stringProp name="ThreadGroup.delay"></stringProp>
|
||||||
|
<boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
|
||||||
|
</PostThreadGroup>
|
||||||
|
<hashTree>
|
||||||
|
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP请求" enabled="true">
|
||||||
|
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
|
||||||
|
<collectionProp name="Arguments.arguments"/>
|
||||||
|
</elementProp>
|
||||||
|
<stringProp name="HTTPSampler.domain">mbd.baidu.com</stringProp>
|
||||||
|
<stringProp name="HTTPSampler.port"></stringProp>
|
||||||
|
<stringProp name="HTTPSampler.protocol">https</stringProp>
|
||||||
|
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||||
|
<stringProp name="HTTPSampler.path"></stringProp>
|
||||||
|
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||||
|
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||||
|
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||||
|
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||||
|
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||||
|
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||||
|
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||||
|
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||||
|
</HTTPSamplerProxy>
|
||||||
|
<hashTree/>
|
||||||
|
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="察看结果树" enabled="true">
|
||||||
|
<boolProp name="ResultCollector.error_logging">false</boolProp>
|
||||||
|
<objProp>
|
||||||
|
<name>saveConfig</name>
|
||||||
|
<value class="SampleSaveConfiguration">
|
||||||
|
<time>true</time>
|
||||||
|
<latency>true</latency>
|
||||||
|
<timestamp>true</timestamp>
|
||||||
|
<success>true</success>
|
||||||
|
<label>true</label>
|
||||||
|
<code>true</code>
|
||||||
|
<message>true</message>
|
||||||
|
<threadName>true</threadName>
|
||||||
|
<dataType>true</dataType>
|
||||||
|
<encoding>false</encoding>
|
||||||
|
<assertions>true</assertions>
|
||||||
|
<subresults>true</subresults>
|
||||||
|
<responseData>false</responseData>
|
||||||
|
<samplerData>false</samplerData>
|
||||||
|
<xml>false</xml>
|
||||||
|
<fieldNames>true</fieldNames>
|
||||||
|
<responseHeaders>false</responseHeaders>
|
||||||
|
<requestHeaders>false</requestHeaders>
|
||||||
|
<responseDataOnError>false</responseDataOnError>
|
||||||
|
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
|
||||||
|
<assertionsResultsToSave>0</assertionsResultsToSave>
|
||||||
|
<bytes>true</bytes>
|
||||||
|
<sentBytes>true</sentBytes>
|
||||||
|
<url>true</url>
|
||||||
|
<threadCounts>true</threadCounts>
|
||||||
|
<idleTime>true</idleTime>
|
||||||
|
<connectTime>true</connectTime>
|
||||||
|
</value>
|
||||||
|
</objProp>
|
||||||
|
<stringProp name="filename"></stringProp>
|
||||||
|
</ResultCollector>
|
||||||
|
<hashTree/>
|
||||||
|
</hashTree>
|
||||||
|
</hashTree>
|
||||||
|
</hashTree>
|
||||||
|
</jmeterTestPlan>
|
|
@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||||
import io.metersphere.project.api.processor.extract.MsExtract;
|
import io.metersphere.project.api.processor.extract.MsExtract;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,5 +18,5 @@ public class ExtractPostProcessor extends MsProcessor {
|
||||||
/**
|
/**
|
||||||
* 提取器列表
|
* 提取器列表
|
||||||
*/
|
*/
|
||||||
private List<MsExtract> extractors;
|
private List<MsExtract> extractors = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.Size;
|
import jakarta.validation.constraints.Size;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,5 +53,5 @@ public class SQLProcessor extends MsProcessor {
|
||||||
* 提取参数
|
* 提取参数
|
||||||
*/
|
*/
|
||||||
@Valid
|
@Valid
|
||||||
private List<KeyValueParam> extractParams;
|
private List<KeyValueParam> extractParams = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import io.metersphere.plugin.api.spi.AbstractApiPlugin;
|
||||||
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
import io.metersphere.plugin.api.spi.AbstractProtocolPlugin;
|
import io.metersphere.plugin.api.spi.AbstractProtocolPlugin;
|
||||||
import io.metersphere.plugin.api.spi.MsTestElement;
|
import io.metersphere.plugin.api.spi.MsTestElement;
|
||||||
|
import io.metersphere.project.domain.Project;
|
||||||
import io.metersphere.project.mapper.ProjectMapper;
|
import io.metersphere.project.mapper.ProjectMapper;
|
||||||
import io.metersphere.sdk.constants.PluginScenarioType;
|
import io.metersphere.sdk.constants.PluginScenarioType;
|
||||||
import io.metersphere.sdk.dto.api.task.ApiExecuteFileInfo;
|
import io.metersphere.sdk.dto.api.task.ApiExecuteFileInfo;
|
||||||
|
@ -64,6 +65,15 @@ public class ApiPluginService {
|
||||||
return protocols;
|
return protocols;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ProtocolDTO> getProtocolsByProjectId(String projectId) {
|
||||||
|
Project project = projectMapper.selectByPrimaryKey(projectId);
|
||||||
|
if (project == null) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
} else {
|
||||||
|
return this.getProtocols(project.getOrganizationId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private List<PluginWrapper> getOrgProtocolPluginWrappers(String orgId) {
|
private List<PluginWrapper> getOrgProtocolPluginWrappers(String orgId) {
|
||||||
return getOrgApiPluginWrappers(orgId).stream()
|
return getOrgApiPluginWrappers(orgId).stream()
|
||||||
.filter(plugin -> plugin.getPlugin() instanceof AbstractProtocolPlugin)
|
.filter(plugin -> plugin.getPlugin() instanceof AbstractProtocolPlugin)
|
||||||
|
|
Loading…
Reference in New Issue