feat(接口测试): 处理body参数的jmx转换
--task=1013377 --user=陈建星 接口测试-接口调试-后台调试执行 https://www.tapd.cn/55049933/s/1447114
This commit is contained in:
parent
a587b7bcb5
commit
b55ba39b58
|
@ -50,7 +50,7 @@ public class DefaultRepositoryDir {
|
||||||
private static final String PROJECT_FILE_MANAGEMENT_PREVIEW_DIR = PROJECT_DIR + "/file-management/preview";
|
private static final String PROJECT_FILE_MANAGEMENT_PREVIEW_DIR = PROJECT_DIR + "/file-management/preview";
|
||||||
/**
|
/**
|
||||||
* 接口调试相关文件的存储目录
|
* 接口调试相关文件的存储目录
|
||||||
* project/{projectId}/apiCase/{apiDebugId}
|
* project/{projectId}/api-debug/{apiDebugId}
|
||||||
*/
|
*/
|
||||||
private static final String PROJECT_API_DEBUG_DIR = PROJECT_DIR + "/api-debug/%s";
|
private static final String PROJECT_API_DEBUG_DIR = PROJECT_DIR + "/api-debug/%s";
|
||||||
private static final String PROJECT_BUG_DIR = PROJECT_DIR + "/bug/%s";
|
private static final String PROJECT_BUG_DIR = PROJECT_DIR + "/bug/%s";
|
||||||
|
|
|
@ -29,14 +29,29 @@ public class LocalRepositoryDir {
|
||||||
* 插件存储目录
|
* 插件存储目录
|
||||||
*/
|
*/
|
||||||
private static final String SYSTEM_PLUGIN_DIR = SYSTEM_ROOT_DIR + "/plugin";
|
private static final String SYSTEM_PLUGIN_DIR = SYSTEM_ROOT_DIR + "/plugin";
|
||||||
private static final String SYSTEM_BODY_ENVIRONMENT_TEM_DIR = SYSTEM_ROOT_DIR + "/body/environment/tmp";
|
/**
|
||||||
|
* 系统临时文件的存放目录
|
||||||
|
* system/temp
|
||||||
|
* 会定时清理
|
||||||
|
*/
|
||||||
|
private static final String SYSTEM_TEMP_DIR = SYSTEM_ROOT_DIR + "/temp";
|
||||||
|
/**
|
||||||
|
* 系统缓存文件存放目录
|
||||||
|
* 目前仅执行机缓存执行文件使用到
|
||||||
|
* system/cache
|
||||||
|
*/
|
||||||
|
private static final String SYSTEM_CACHE_DIR = SYSTEM_ROOT_DIR + "/cache";
|
||||||
/*------ end: 系统下资源目录 --------*/
|
/*------ end: 系统下资源目录 --------*/
|
||||||
|
|
||||||
public static String getPluginDir() {
|
public static String getPluginDir() {
|
||||||
return SYSTEM_PLUGIN_DIR;
|
return SYSTEM_PLUGIN_DIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getBodyEnvironmentTmpDir() {
|
public static String getSystemTempDir() {
|
||||||
return SYSTEM_BODY_ENVIRONMENT_TEM_DIR;
|
return SYSTEM_TEMP_DIR;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSystemCacheDir() {
|
||||||
|
return SYSTEM_CACHE_DIR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
package io.metersphere.sdk.constants;
|
package io.metersphere.sdk.constants;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
public enum StorageType {
|
public enum StorageType {
|
||||||
MINIO, GIT, LOCAL
|
|
||||||
|
MINIO, GIT, LOCAL;
|
||||||
|
|
||||||
|
public static boolean isGit(String storage) {
|
||||||
|
return StringUtils.equalsIgnoreCase(GIT.name(), storage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
package io.metersphere.sdk.dto.api.task;
|
||||||
|
|
||||||
|
import io.metersphere.sdk.dto.FileMetadataRepositoryDTO;
|
||||||
|
import io.metersphere.sdk.dto.FileModuleRepositoryDTO;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: jianxing
|
||||||
|
* @CreateTime: 2023-12-15 16:59
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ApiExecuteFileInfo {
|
||||||
|
private String fileId;
|
||||||
|
private String fileName;
|
||||||
|
/**
|
||||||
|
* 文件存储方式
|
||||||
|
*/
|
||||||
|
private String storage;
|
||||||
|
/**
|
||||||
|
* 项目ID
|
||||||
|
*/
|
||||||
|
private String projectId;
|
||||||
|
/**
|
||||||
|
* 资源ID
|
||||||
|
*/
|
||||||
|
private String resourceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* git文件的版本信息
|
||||||
|
*/
|
||||||
|
private FileMetadataRepositoryDTO fileMetadataRepositoryDTO;
|
||||||
|
/**
|
||||||
|
* 文件的仓库信息
|
||||||
|
*/
|
||||||
|
private FileModuleRepositoryDTO fileModuleRepositoryDTO;
|
||||||
|
}
|
|
@ -28,19 +28,28 @@ public class TaskRequest implements Serializable {
|
||||||
* 执行的资源ID
|
* 执行的资源ID
|
||||||
*/
|
*/
|
||||||
private String testId;
|
private String testId;
|
||||||
/**
|
|
||||||
* 点击调试时,尚未保存的文件ID列表
|
|
||||||
*/
|
|
||||||
private List<String> tempFileIds;
|
|
||||||
/**
|
/**
|
||||||
* 执行模式
|
* 执行模式
|
||||||
*/
|
*/
|
||||||
private String runMode;
|
private String runMode;
|
||||||
/**
|
/**
|
||||||
* 资源类型
|
* 资源类型
|
||||||
|
* ApiResourceType
|
||||||
*/
|
*/
|
||||||
private String resourceType;
|
private String resourceType;
|
||||||
|
/**
|
||||||
|
* 点击调试时,尚未保存的本地上传的文件列表
|
||||||
|
*/
|
||||||
|
private List<ApiExecuteFileInfo> localTempFiles;
|
||||||
|
/**
|
||||||
|
* 通过本地上传的文件ID列表
|
||||||
|
*/
|
||||||
|
private List<ApiExecuteFileInfo> localFiles;
|
||||||
|
/**
|
||||||
|
* 关联文件管理的文件列表
|
||||||
|
* 这里记录文件名,mino存的文件名是id
|
||||||
|
* 执行时下载文件后,按原文件命名
|
||||||
|
*/
|
||||||
|
private List<ApiExecuteFileInfo> refFiles;
|
||||||
// TODO 其它执行参数
|
// TODO 其它执行参数
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,22 @@
|
||||||
package io.metersphere.api.dto.debug;
|
package io.metersphere.api.dto.debug;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class ApiDebugRunRequest {
|
public class ApiDebugRunRequest {
|
||||||
|
@Schema(description = "接口ID")
|
||||||
|
@NotNull
|
||||||
private String id;
|
private String id;
|
||||||
|
@Schema(description = "环境ID")
|
||||||
private String environmentId;
|
private String environmentId;
|
||||||
|
|
||||||
@Schema(description = "点击调试时尚未保存的文件ID列表")
|
@Schema(description = "点击调试时尚未保存的文件ID列表")
|
||||||
private List<String> tempFileIds;
|
private List<String> tempFileIds;
|
||||||
|
@NotNull
|
||||||
|
@Schema(description = "请求内容")
|
||||||
private String request;
|
private String request;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package io.metersphere.api.dto.debug;
|
package io.metersphere.api.dto.debug;
|
||||||
|
|
||||||
import io.metersphere.validation.groups.Created;
|
|
||||||
import io.metersphere.validation.groups.Updated;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.Size;
|
import jakarta.validation.constraints.Size;
|
||||||
|
@ -20,13 +18,12 @@ public class ApiDebugUpdateRequest implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Schema(description = "接口pk", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "接口pk", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
@NotBlank(message = "{api_debug.id.not_blank}", groups = {Updated.class})
|
@NotBlank(message = "{api_debug.id.not_blank}")
|
||||||
@Size(min = 1, max = 50, message = "{api_debug.id.length_range}", groups = {Created.class, Updated.class})
|
@Size(max = 50, message = "{api_debug.id.length_range}")
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
@Schema(description = "接口名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "接口名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
@NotBlank(message = "{api_debug.name.not_blank}", groups = {Created.class})
|
@Size(max = 255, message = "{api_debug.name.length_range}")
|
||||||
@Size(min = 1, max = 255, message = "{api_debug.name.length_range}", groups = {Created.class, Updated.class})
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@Schema(description = "http协议类型post/get/其它协议则是协议名(mqtt)")
|
@Schema(description = "http协议类型post/get/其它协议则是协议名(mqtt)")
|
||||||
|
@ -36,12 +33,10 @@ public class ApiDebugUpdateRequest implements Serializable {
|
||||||
private String path;
|
private String path;
|
||||||
|
|
||||||
@Schema(description = "模块fk", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "模块fk", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
@NotBlank(message = "{api_debug.module_id.not_blank}", groups = {Created.class})
|
@Size(max = 50, message = "{api_debug.module_id.length_range}")
|
||||||
@Size(min = 1, max = 50, message = "{api_debug.module_id.length_range}", groups = {Created.class, Updated.class})
|
|
||||||
private String moduleId;
|
private String moduleId;
|
||||||
|
|
||||||
@Schema(description = "请求内容")
|
@Schema(description = "请求内容")
|
||||||
@NotBlank
|
|
||||||
private String request;
|
private String request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package io.metersphere.api.dto.debug;
|
package io.metersphere.api.dto.debug;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -8,9 +7,21 @@ import java.util.List;
|
||||||
@Data
|
@Data
|
||||||
public class ApiResourceRunRequest {
|
public class ApiResourceRunRequest {
|
||||||
private String id;
|
private String id;
|
||||||
|
/**
|
||||||
|
* 项目ID
|
||||||
|
*/
|
||||||
private String projectId;
|
private String projectId;
|
||||||
|
/**
|
||||||
|
* 资源ID
|
||||||
|
*/
|
||||||
private String testId;
|
private String testId;
|
||||||
|
/**
|
||||||
|
* 测试报告ID
|
||||||
|
*/
|
||||||
private String reportId;
|
private String reportId;
|
||||||
|
/**
|
||||||
|
* 环境ID
|
||||||
|
*/
|
||||||
private String environmentId;
|
private String environmentId;
|
||||||
/**
|
/**
|
||||||
* 执行模式
|
* 执行模式
|
||||||
|
@ -18,9 +29,15 @@ public class ApiResourceRunRequest {
|
||||||
private String runMode;
|
private String runMode;
|
||||||
/**
|
/**
|
||||||
* 资源类型
|
* 资源类型
|
||||||
|
* @see io.metersphere.api.constants.ApiResourceType
|
||||||
*/
|
*/
|
||||||
private String resourceType;
|
private String resourceType;
|
||||||
@Schema(description = "点击调试时尚未保存的文件ID列表")
|
/**
|
||||||
private List<String> tempFileIds;
|
* 请求内容
|
||||||
|
*/
|
||||||
private String request;
|
private String request;
|
||||||
|
/**
|
||||||
|
* 点击调试时尚未保存的文件列表
|
||||||
|
*/
|
||||||
|
private List<String> tempFileIds;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.metersphere.api.dto.request.http;
|
package io.metersphere.api.dto.request.http;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: jianxing
|
* @Author: jianxing
|
||||||
|
@ -8,6 +9,10 @@ import lombok.Data;
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class KeyValueParam {
|
public class KeyValueParam {
|
||||||
|
/**
|
||||||
|
* 参数ID
|
||||||
|
*/
|
||||||
|
private String id;
|
||||||
/**
|
/**
|
||||||
* 键
|
* 键
|
||||||
*/
|
*/
|
||||||
|
@ -16,4 +21,8 @@ public class KeyValueParam {
|
||||||
* 值
|
* 值
|
||||||
*/
|
*/
|
||||||
private String value;
|
private String value;
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
return StringUtils.isNotBlank(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import lombok.Data;
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class BinaryBody {
|
public class BinaryBody {
|
||||||
private String fileId;
|
private BodyFile bodyFile;
|
||||||
private String fileName;
|
|
||||||
private String description;
|
private String description;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,9 @@ package io.metersphere.api.dto.request.http.body;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: jianxing
|
* @Author: jianxing
|
||||||
* @CreateTime: 2023-11-06 16:59
|
* @CreateTime: 2023-11-06 16:59
|
||||||
|
@ -22,6 +25,35 @@ public class Body {
|
||||||
private RawBody rawBody;
|
private RawBody rawBody;
|
||||||
private BinaryBody binaryBody;
|
private BinaryBody binaryBody;
|
||||||
|
|
||||||
|
private static Map<BodyType, Class> bodyTypeClassMap = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
bodyTypeClassMap.put(BodyType.NONE, NoneBody.class);
|
||||||
|
bodyTypeClassMap.put(BodyType.FORM_DATA, FormDataBody.class);
|
||||||
|
bodyTypeClassMap.put(BodyType.WWW_FORM, WWWFormBody.class);
|
||||||
|
bodyTypeClassMap.put(BodyType.JSON, JsonBody.class);
|
||||||
|
bodyTypeClassMap.put(BodyType.XML, XmlBody.class);
|
||||||
|
bodyTypeClassMap.put(BodyType.RAW, RawBody.class);
|
||||||
|
bodyTypeClassMap.put(BodyType.BINARY, BinaryBody.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class getBodyClassByType() {
|
||||||
|
return bodyTypeClassMap.get(BodyType.valueOf(bodyType));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getBodyDataByType() {
|
||||||
|
Map<BodyType, Object> boadyDataMap = new HashMap<>();
|
||||||
|
boadyDataMap.put(BodyType.NONE, noneBody);
|
||||||
|
boadyDataMap.put(BodyType.FORM_DATA, formDataBody);
|
||||||
|
boadyDataMap.put(BodyType.WWW_FORM, wwwFormBody);
|
||||||
|
boadyDataMap.put(BodyType.JSON, jsonBody);
|
||||||
|
boadyDataMap.put(BodyType.XML, xmlBody);
|
||||||
|
boadyDataMap.put(BodyType.RAW, rawBody);
|
||||||
|
boadyDataMap.put(BodyType.BINARY, binaryBody);
|
||||||
|
return boadyDataMap.get(BodyType.valueOf(bodyType));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public enum BodyType {
|
public enum BodyType {
|
||||||
BINARY,
|
BINARY,
|
||||||
FORM_DATA,
|
FORM_DATA,
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package io.metersphere.api.dto.request.http.body;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class BodyFile {
|
||||||
|
/**
|
||||||
|
* 记录文件的ID,防止重名
|
||||||
|
* 生成脚本时,通过 fileId + value(文件名) 获取文件路径
|
||||||
|
*/
|
||||||
|
private String fileId;
|
||||||
|
/**
|
||||||
|
* 文件名称
|
||||||
|
*/
|
||||||
|
private String fileName;
|
||||||
|
}
|
|
@ -1,28 +1,20 @@
|
||||||
package io.metersphere.api.dto.request.http.body;
|
package io.metersphere.api.dto.request.http.body;
|
||||||
|
|
||||||
import io.metersphere.api.dto.request.http.KeyValueEnableParam;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: jianxing
|
* @Author: jianxing
|
||||||
* @CreateTime: 2023-11-06 18:11
|
* @CreateTime: 2023-11-06 18:11
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class FormDataKV extends KeyValueEnableParam {
|
public class FormDataKV extends WWWFormKV {
|
||||||
private String paramType;
|
|
||||||
private Boolean required = false;
|
private List<BodyFile> files;
|
||||||
private Integer minLength;
|
|
||||||
private Integer maxLength;
|
public boolean isFile() {
|
||||||
private String contentType;
|
return StringUtils.equalsIgnoreCase(getParamType(), WWWFormParamType.FILE.name());
|
||||||
private Boolean encode = false;
|
}
|
||||||
/**
|
|
||||||
* 记录文件的ID,防止重名
|
|
||||||
* 生成脚本时,通过 fileId + value(文件名) 获取文件路径
|
|
||||||
*/
|
|
||||||
private String fileId;
|
|
||||||
/**
|
|
||||||
* 文件存储方式
|
|
||||||
* 对象存储和引用(FILE_REF)
|
|
||||||
*/
|
|
||||||
private String storage;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ public class JsonBody {
|
||||||
/**
|
/**
|
||||||
* 是否启用 json-schema
|
* 是否启用 json-schema
|
||||||
*/
|
*/
|
||||||
private Boolean enableJsonSchema;
|
private Boolean enableJsonSchema = false;
|
||||||
/**
|
/**
|
||||||
* 没有启用 json-schema 时的 json 参数值
|
* 没有启用 json-schema 时的 json 参数值
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package io.metersphere.api.dto.request.http.body;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.request.http.KeyValueEnableParam;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: jianxing
|
||||||
|
* @CreateTime: 2023-11-06 18:11
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class WWWFormKV extends KeyValueEnableParam {
|
||||||
|
/**
|
||||||
|
* 参数类型
|
||||||
|
*
|
||||||
|
* @see WWWFormParamType
|
||||||
|
*/
|
||||||
|
private String paramType;
|
||||||
|
private Boolean required = false;
|
||||||
|
private Integer minLength;
|
||||||
|
private Integer maxLength;
|
||||||
|
private String contentType;
|
||||||
|
private Boolean encode = false;
|
||||||
|
|
||||||
|
enum WWWFormParamType {
|
||||||
|
/**
|
||||||
|
* 默认 application/text
|
||||||
|
*/
|
||||||
|
STRING, INTEGER, NUMBER, ARRAY,
|
||||||
|
/**
|
||||||
|
* 默认 application/octet-stream
|
||||||
|
*/
|
||||||
|
FILE,
|
||||||
|
/**
|
||||||
|
* 默认 application/json
|
||||||
|
*/
|
||||||
|
JSON
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,6 @@ public class JmeterTestElementParser implements TestElementParser {
|
||||||
|
|
||||||
private Boolean onSampleError;
|
private Boolean onSampleError;
|
||||||
private String name;
|
private String name;
|
||||||
private Boolean enable = true;
|
|
||||||
private ParameterConfig config;
|
private ParameterConfig config;
|
||||||
private boolean displayJMeterProperties = false;
|
private boolean displayJMeterProperties = false;
|
||||||
|
|
||||||
|
@ -36,13 +35,18 @@ public class JmeterTestElementParser implements TestElementParser {
|
||||||
|
|
||||||
private boolean displaySystemProperties = false;
|
private boolean displaySystemProperties = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析生成 jmx 脚本
|
||||||
|
* @param msTestElement
|
||||||
|
* @param config
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String parse(AbstractMsTestElement msTestElement, ParameterConfig config) {
|
public String parse(AbstractMsTestElement msTestElement, ParameterConfig config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
HashTree hashTree = new ListedHashTree();
|
HashTree hashTree = new ListedHashTree();
|
||||||
TestPlan testPlan = getPlan();
|
TestPlan testPlan = getPlan();
|
||||||
name = msTestElement.getName();
|
name = msTestElement.getName();
|
||||||
enable = msTestElement.getEnable();
|
|
||||||
final HashTree testPlanTree = hashTree.add(testPlan);
|
final HashTree testPlanTree = hashTree.add(testPlan);
|
||||||
final HashTree groupTree = testPlanTree.add(getThreadGroup());
|
final HashTree groupTree = testPlanTree.add(getThreadGroup());
|
||||||
// 添加 debugSampler
|
// 添加 debugSampler
|
||||||
|
@ -82,11 +86,11 @@ public class JmeterTestElementParser implements TestElementParser {
|
||||||
loopController.setName("LoopController");
|
loopController.setName("LoopController");
|
||||||
loopController.setProperty(TestElement.TEST_CLASS, LoopController.class.getName());
|
loopController.setProperty(TestElement.TEST_CLASS, LoopController.class.getName());
|
||||||
loopController.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("LoopControlPanel"));
|
loopController.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("LoopControlPanel"));
|
||||||
loopController.setEnabled(this.enable);
|
loopController.setEnabled(true);
|
||||||
loopController.setLoops(1);
|
loopController.setLoops(1);
|
||||||
|
|
||||||
ThreadGroup threadGroup = new ThreadGroup();
|
ThreadGroup threadGroup = new ThreadGroup();
|
||||||
threadGroup.setEnabled(this.enable);
|
threadGroup.setEnabled(true);
|
||||||
threadGroup.setName(config.getReportId());
|
threadGroup.setName(config.getReportId());
|
||||||
threadGroup.setProperty(TestElement.TEST_CLASS, ThreadGroup.class.getName());
|
threadGroup.setProperty(TestElement.TEST_CLASS, ThreadGroup.class.getName());
|
||||||
threadGroup.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ThreadGroupGui"));
|
threadGroup.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ThreadGroupGui"));
|
||||||
|
|
|
@ -2,31 +2,68 @@ package io.metersphere.api.parser.jmeter;
|
||||||
|
|
||||||
|
|
||||||
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
||||||
import io.metersphere.plugin.api.spi.AbstractJmeterElementConverter;
|
import io.metersphere.api.dto.request.http.body.Body;
|
||||||
|
import io.metersphere.api.parser.jmeter.body.MsBodyConverter;
|
||||||
|
import io.metersphere.api.parser.jmeter.body.MsBodyConverterFactory;
|
||||||
|
import io.metersphere.api.parser.jmeter.body.MsFormDataBodyConverter;
|
||||||
|
import io.metersphere.api.parser.jmeter.body.MsWWWFormBodyConverter;
|
||||||
import io.metersphere.plugin.api.dto.ParameterConfig;
|
import io.metersphere.plugin.api.dto.ParameterConfig;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractJmeterElementConverter;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
|
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
|
||||||
import org.apache.jmeter.save.SaveService;
|
import org.apache.jmeter.save.SaveService;
|
||||||
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 org.springframework.http.HttpMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: jianxing
|
* @Author: jianxing
|
||||||
* @CreateTime: 2023-10-27 10:07
|
* @CreateTime: 2023-10-27 10:07
|
||||||
*
|
* <p>
|
||||||
* 脚本解析器
|
* 脚本解析器
|
||||||
*/
|
*/
|
||||||
public class MsHTTPElementConverter extends AbstractJmeterElementConverter<MsHTTPElement> {
|
public class MsHTTPElementConverter extends AbstractJmeterElementConverter<MsHTTPElement> {
|
||||||
|
|
||||||
@Override
|
private ParameterConfig config;
|
||||||
public void toHashTree(HashTree tree, MsHTTPElement msHTTPElement, ParameterConfig msParameter) {
|
|
||||||
ParameterConfig config = msParameter;
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toHashTree(HashTree tree, MsHTTPElement msHTTPElement, ParameterConfig config) {
|
||||||
|
this.config = config;
|
||||||
HTTPSamplerProxy sampler = new HTTPSamplerProxy();
|
HTTPSamplerProxy sampler = new HTTPSamplerProxy();
|
||||||
sampler.setName(msHTTPElement.getName());
|
sampler.setName(msHTTPElement.getName());
|
||||||
sampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
|
sampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
|
||||||
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("HttpTestSampleGui"));
|
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("HttpTestSampleGui"));
|
||||||
|
|
||||||
|
sampler.setMethod(msHTTPElement.getMethod());
|
||||||
|
// todo 根据环境设置
|
||||||
|
sampler.setDomain(msHTTPElement.getUrl());
|
||||||
|
sampler.setPath(msHTTPElement.getPath());
|
||||||
|
|
||||||
|
handleBody(sampler, msHTTPElement);
|
||||||
HashTree httpTree = tree.add(sampler);
|
HashTree httpTree = tree.add(sampler);
|
||||||
parseChild(httpTree, msHTTPElement, config);
|
parseChild(httpTree, msHTTPElement, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析body参数
|
||||||
|
*
|
||||||
|
* @param sampler
|
||||||
|
* @param msHTTPElement
|
||||||
|
*/
|
||||||
|
private void handleBody(HTTPSamplerProxy sampler, MsHTTPElement msHTTPElement) {
|
||||||
|
Body body = msHTTPElement.getBody();
|
||||||
|
// 请求体处理
|
||||||
|
if (body != null) {
|
||||||
|
Class bodyClass = body.getBodyClassByType();
|
||||||
|
MsBodyConverter converter = MsBodyConverterFactory.getConverter(bodyClass);
|
||||||
|
|
||||||
|
// 这里get请求,不处理 form-date 和 www-form-urlencoded 类型的参数
|
||||||
|
// 否则会被 jmeter 作为 query 参数
|
||||||
|
if (StringUtils.equalsIgnoreCase(msHTTPElement.getMethod(), HttpMethod.GET.name())
|
||||||
|
&& (converter instanceof MsWWWFormBodyConverter || converter instanceof MsFormDataBodyConverter)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
converter.parse(sampler, body.getBodyDataByType(), config);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package io.metersphere.api.parser.jmeter.body;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.request.http.body.BinaryBody;
|
||||||
|
import io.metersphere.api.dto.request.http.body.BodyFile;
|
||||||
|
import io.metersphere.plugin.api.dto.ParameterConfig;
|
||||||
|
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
|
||||||
|
import org.apache.jmeter.protocol.http.util.HTTPFileArg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 Binary 参数
|
||||||
|
* @Author: jianxing
|
||||||
|
* @CreateTime: 2023-12-14 19:55
|
||||||
|
*/
|
||||||
|
public class MsBinaryBodyConverter extends MsBodyConverter<BinaryBody> {
|
||||||
|
@Override
|
||||||
|
public void parse(HTTPSamplerProxy sampler, BinaryBody body, ParameterConfig config) {
|
||||||
|
BodyFile bodyFile = body.getBodyFile();
|
||||||
|
HTTPFileArg httpFileArg = getHttpFileArg(bodyFile);
|
||||||
|
sampler.setHTTPFiles(new HTTPFileArg[]{httpFileArg});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
package io.metersphere.api.parser.jmeter.body;
|
||||||
|
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.request.http.body.BodyFile;
|
||||||
|
import io.metersphere.api.dto.request.http.body.WWWFormKV;
|
||||||
|
import io.metersphere.jmeter.mock.Mock;
|
||||||
|
import io.metersphere.plugin.api.dto.ParameterConfig;
|
||||||
|
import io.metersphere.sdk.constants.LocalRepositoryDir;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.http.entity.ContentType;
|
||||||
|
import org.apache.jmeter.config.Arguments;
|
||||||
|
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 java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: jianxing
|
||||||
|
* @CreateTime: 2023-10-27 10:07
|
||||||
|
* <p>
|
||||||
|
* body 解析器
|
||||||
|
*/
|
||||||
|
public abstract class MsBodyConverter<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析对应的请求体参数
|
||||||
|
* @param sampler
|
||||||
|
* @param body
|
||||||
|
* @param config
|
||||||
|
*/
|
||||||
|
public abstract void parse(HTTPSamplerProxy sampler, T body, ParameterConfig config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析文本类型的 kv 参数
|
||||||
|
* @param textFromValues
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected Arguments getArguments(List<? extends WWWFormKV> textFromValues) {
|
||||||
|
Arguments arguments = new Arguments();
|
||||||
|
textFromValues.forEach(formDataKV -> {
|
||||||
|
// 处理 mock 函数
|
||||||
|
String value = Mock.buildFunctionCallString(formDataKV.getValue());
|
||||||
|
if (value == null) {
|
||||||
|
value = StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
HTTPArgument httpArgument = new HTTPArgument(formDataKV.getKey(), value);
|
||||||
|
httpArgument.setAlwaysEncoded(formDataKV.getEncode());
|
||||||
|
if (StringUtils.isNotBlank(formDataKV.getContentType())) {
|
||||||
|
httpArgument.setContentType(formDataKV.getContentType());
|
||||||
|
}
|
||||||
|
arguments.addArgument(httpArgument);
|
||||||
|
});
|
||||||
|
return arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 form-data 和 binary 类型的文件转换为 jmeter 的 HTTPFileArg
|
||||||
|
*
|
||||||
|
* @param file
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected HTTPFileArg getHttpFileArg(BodyFile file) {
|
||||||
|
String fileId = file.getFileId();
|
||||||
|
String fileName = file.getFileName();
|
||||||
|
// 在对应目录下创建文件ID目录,将文件放入
|
||||||
|
String path = LocalRepositoryDir.getSystemCacheDir() + '/' + fileId + '/' + fileName;
|
||||||
|
if (!StringUtils.equals(File.separator, "/")) {
|
||||||
|
// windows 系统下运行,将 / 转换为 \,否则jmeter报错
|
||||||
|
path = path.replace("/", File.separator);
|
||||||
|
}
|
||||||
|
String mimetype = ContentType.APPLICATION_OCTET_STREAM.getMimeType();
|
||||||
|
HTTPFileArg fileArg = new HTTPFileArg(path, StringUtils.EMPTY, mimetype);
|
||||||
|
return fileArg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将文本中的 @xxx 转换成 ${__Mock(@xxx)}
|
||||||
|
* @param text
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected String parseTextMock(String text) {
|
||||||
|
String pattern = "@[a-zA-Z]*";
|
||||||
|
Pattern regex = Pattern.compile(pattern);
|
||||||
|
Matcher matcher = regex.matcher(text);
|
||||||
|
while (matcher.find()) {
|
||||||
|
text = text.replace(matcher.group(), "${__Mock(" + matcher.group() + ")}");
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理raw格式参数
|
||||||
|
* 包含了 json 等格式
|
||||||
|
* @param sampler
|
||||||
|
* @param raw
|
||||||
|
*/
|
||||||
|
protected static void handleRowBody(HTTPSamplerProxy sampler, String raw) {
|
||||||
|
Arguments arguments = new Arguments();
|
||||||
|
HTTPArgument httpArgument = new HTTPArgument();
|
||||||
|
httpArgument.setValue(raw);
|
||||||
|
httpArgument.setAlwaysEncoded(false);
|
||||||
|
httpArgument.setEnabled(true);
|
||||||
|
arguments.addArgument(httpArgument);
|
||||||
|
sampler.setPostBodyRaw(true);
|
||||||
|
sampler.setArguments(arguments);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package io.metersphere.api.parser.jmeter.body;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.request.http.body.*;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: jianxing
|
||||||
|
* @CreateTime: 2023-12-21 19:19
|
||||||
|
*/
|
||||||
|
public class MsBodyConverterFactory {
|
||||||
|
|
||||||
|
private static Map<Class, MsBodyConverter> converterMap = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
converterMap.put(RawBody.class, new MsRawBodyConverter());
|
||||||
|
converterMap.put(NoneBody.class, new MsNoneBodyConverter());
|
||||||
|
converterMap.put(FormDataBody.class, new MsFormDataBodyConverter());
|
||||||
|
converterMap.put(WWWFormBody.class, new MsWWWFormBodyConverter());
|
||||||
|
converterMap.put(JsonBody.class, new MsJsonBodyConverter());
|
||||||
|
converterMap.put(XmlBody.class, new MsXmlBodyConverter());
|
||||||
|
converterMap.put(BinaryBody.class, new MsBinaryBodyConverter());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MsBodyConverter getConverter(Class bodyClassByType) {
|
||||||
|
return converterMap.get(bodyClassByType);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package io.metersphere.api.parser.jmeter.body;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.request.http.body.FormDataBody;
|
||||||
|
import io.metersphere.api.dto.request.http.body.FormDataKV;
|
||||||
|
import io.metersphere.plugin.api.dto.ParameterConfig;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
|
||||||
|
import org.apache.jmeter.protocol.http.util.HTTPFileArg;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 form-data 类型的请求体
|
||||||
|
* @Author: jianxing
|
||||||
|
* @CreateTime: 2023-12-14 15:18
|
||||||
|
*/
|
||||||
|
public class MsFormDataBodyConverter extends MsBodyConverter<FormDataBody> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parse(HTTPSamplerProxy sampler, FormDataBody body, ParameterConfig config) {
|
||||||
|
List<FormDataKV> fromValues = body.getFromValues();
|
||||||
|
List<FormDataKV> validFromValues = fromValues.stream().filter(FormDataKV::isValid).collect(Collectors.toList());
|
||||||
|
List<FormDataKV> fileFromValues = validFromValues.stream().filter(FormDataKV::isFile).collect(Collectors.toList());
|
||||||
|
List<FormDataKV> textFromValues = validFromValues.stream().filter(kv -> !kv.isFile()).collect(Collectors.toList());
|
||||||
|
sampler.setDoMultipart(true);
|
||||||
|
sampler.setHTTPFiles(getHttpFileArg(fileFromValues));
|
||||||
|
sampler.setArguments(getArguments(textFromValues));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析文件类型的参数
|
||||||
|
* @param fileFromValues
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private HTTPFileArg[] getHttpFileArg(List<FormDataKV> fileFromValues) {
|
||||||
|
if (CollectionUtils.isEmpty(fileFromValues)) {
|
||||||
|
return new HTTPFileArg[0];
|
||||||
|
}
|
||||||
|
List<HTTPFileArg> list = new ArrayList<>();
|
||||||
|
if (fileFromValues != null) {
|
||||||
|
fileFromValues.forEach(formDataKV -> {
|
||||||
|
String paramName = formDataKV.getKey();
|
||||||
|
formDataKV.getFiles().forEach(file -> {
|
||||||
|
HTTPFileArg fileArg = getHttpFileArg(file);
|
||||||
|
fileArg.setParamName(paramName);
|
||||||
|
String mimetype = formDataKV.getContentType();
|
||||||
|
if (StringUtils.isBlank(mimetype)) {
|
||||||
|
fileArg.setMimeType(mimetype);
|
||||||
|
}
|
||||||
|
list.add(fileArg);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return list.toArray(new HTTPFileArg[0]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
package io.metersphere.api.parser.jmeter.body;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.request.http.body.JsonBody;
|
||||||
|
import io.metersphere.jmeter.mock.Mock;
|
||||||
|
import io.metersphere.plugin.api.dto.ParameterConfig;
|
||||||
|
import io.metersphere.sdk.util.JSON;
|
||||||
|
import io.metersphere.sdk.util.LogUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: jianxing
|
||||||
|
* @CreateTime: 2023-12-14 21:15
|
||||||
|
*/
|
||||||
|
public class MsJsonBodyConverter extends MsBodyConverter<JsonBody> {
|
||||||
|
@Override
|
||||||
|
public void parse(HTTPSamplerProxy sampler, JsonBody body, ParameterConfig config) {
|
||||||
|
sampler.setPostBodyRaw(true);
|
||||||
|
try {
|
||||||
|
String raw = null;
|
||||||
|
if (body.getEnableJsonSchema()) {
|
||||||
|
// todo jsonSchema
|
||||||
|
// JSONSchemaBuilder.generator(JSONUtil.toJSONString(this.getJsonSchema()))
|
||||||
|
// raw = StringEscapeUtils.unescapeJava();
|
||||||
|
} else {
|
||||||
|
raw = parseJsonMock(body.getJsonValue());
|
||||||
|
}
|
||||||
|
handleRowBody(sampler, raw);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtils.error("json mock value is abnormal", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将json中的 @xxx 转换成 ${__Mock(@xxx)}
|
||||||
|
* @param jsonStr
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String parseJsonMock(String jsonStr) {
|
||||||
|
if (StringUtils.isNotEmpty(jsonStr)) {
|
||||||
|
String value = StringUtils.chomp(jsonStr.trim());
|
||||||
|
try {
|
||||||
|
if (StringUtils.startsWith(value, "[") && StringUtils.endsWith(value, "]")) {
|
||||||
|
List list = JSON.parseArray(jsonStr);
|
||||||
|
parseMock(list);
|
||||||
|
return JSON.toJSONString(list);
|
||||||
|
} else {
|
||||||
|
Map<String, Object> map = JSON.parseObject(jsonStr, Map.class);
|
||||||
|
parseMock(map);
|
||||||
|
return JSON.toJSONString(map);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 如果json串中的格式不是标准的json格式,正则替换变量
|
||||||
|
return parseTextMock(jsonStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jsonStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseMock(List list) {
|
||||||
|
Map<Integer, String> replaceDataMap = new HashMap<>();
|
||||||
|
for (int index = 0; index < list.size(); index++) {
|
||||||
|
Object obj = list.get(index);
|
||||||
|
if (obj instanceof Map) {
|
||||||
|
parseMock((Map) obj);
|
||||||
|
} else if (obj instanceof String) {
|
||||||
|
if (StringUtils.isNotBlank((String) obj)) {
|
||||||
|
String str = Mock.buildFunctionCallString((String) obj);
|
||||||
|
replaceDataMap.put(index, str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Map.Entry<Integer, String> entry : replaceDataMap.entrySet()) {
|
||||||
|
int replaceIndex = entry.getKey();
|
||||||
|
String replaceStr = entry.getValue();
|
||||||
|
list.set(replaceIndex, replaceStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseMock(Map map) {
|
||||||
|
for (Object key : map.keySet()) {
|
||||||
|
Object value = map.get(key);
|
||||||
|
if (value instanceof List) {
|
||||||
|
parseMock((List) value);
|
||||||
|
} else if (value instanceof Map) {
|
||||||
|
parseMock((Map) value);
|
||||||
|
} else if (value instanceof String) {
|
||||||
|
if (StringUtils.isNotBlank((String) value)) {
|
||||||
|
value = Mock.buildFunctionCallString((String) value);
|
||||||
|
}
|
||||||
|
map.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package io.metersphere.api.parser.jmeter.body;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.request.http.body.NoneBody;
|
||||||
|
import io.metersphere.plugin.api.dto.ParameterConfig;
|
||||||
|
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: jianxing
|
||||||
|
* @CreateTime: 2023-12-14 21:15
|
||||||
|
*/
|
||||||
|
public class MsNoneBodyConverter extends MsBodyConverter<NoneBody> {
|
||||||
|
@Override
|
||||||
|
public void parse(HTTPSamplerProxy sampler, NoneBody body, ParameterConfig config) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package io.metersphere.api.parser.jmeter.body;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.request.http.body.RawBody;
|
||||||
|
import io.metersphere.plugin.api.dto.ParameterConfig;
|
||||||
|
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 Raw 格式参数
|
||||||
|
* @Author: jianxing
|
||||||
|
* @CreateTime: 2023-12-14 21:15
|
||||||
|
*/
|
||||||
|
public class MsRawBodyConverter extends MsBodyConverter<RawBody> {
|
||||||
|
@Override
|
||||||
|
public void parse(HTTPSamplerProxy sampler, RawBody body, ParameterConfig config) {
|
||||||
|
handleRowBody(sampler, body.getValue());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package io.metersphere.api.parser.jmeter.body;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.request.http.body.FormDataKV;
|
||||||
|
import io.metersphere.api.dto.request.http.body.WWWFormBody;
|
||||||
|
import io.metersphere.plugin.api.dto.ParameterConfig;
|
||||||
|
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: jianxing
|
||||||
|
* @CreateTime: 2023-12-14 20:34
|
||||||
|
*/
|
||||||
|
public class MsWWWFormBodyConverter extends MsBodyConverter<WWWFormBody> {
|
||||||
|
@Override
|
||||||
|
public void parse(HTTPSamplerProxy sampler, WWWFormBody body, ParameterConfig config) {
|
||||||
|
List<FormDataKV> fromValues = body.getFromValues();
|
||||||
|
List<FormDataKV> validFromValues = fromValues.stream().filter(FormDataKV::isValid).collect(Collectors.toList());
|
||||||
|
sampler.setArguments(getArguments(validFromValues));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package io.metersphere.api.parser.jmeter.body;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.request.http.body.XmlBody;
|
||||||
|
import io.metersphere.plugin.api.dto.ParameterConfig;
|
||||||
|
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: jianxing
|
||||||
|
* @CreateTime: 2023-12-14 21:15
|
||||||
|
*/
|
||||||
|
public class MsXmlBodyConverter extends MsBodyConverter<XmlBody> {
|
||||||
|
@Override
|
||||||
|
public void parse(HTTPSamplerProxy sampler, XmlBody body, ParameterConfig config) {
|
||||||
|
handleRowBody(sampler, body.getValue());
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,11 +7,16 @@ import io.metersphere.api.dto.debug.ApiResourceRunRequest;
|
||||||
import io.metersphere.api.parser.TestElementParser;
|
import io.metersphere.api.parser.TestElementParser;
|
||||||
import io.metersphere.api.parser.TestElementParserFactory;
|
import io.metersphere.api.parser.TestElementParserFactory;
|
||||||
import io.metersphere.api.utils.ApiDataUtils;
|
import io.metersphere.api.utils.ApiDataUtils;
|
||||||
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
|
||||||
import io.metersphere.plugin.api.dto.ParameterConfig;
|
import io.metersphere.plugin.api.dto.ParameterConfig;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
import io.metersphere.project.domain.ProjectApplication;
|
import io.metersphere.project.domain.ProjectApplication;
|
||||||
|
import io.metersphere.project.service.FileAssociationService;
|
||||||
|
import io.metersphere.project.service.FileManagementService;
|
||||||
|
import io.metersphere.project.service.FileMetadataService;
|
||||||
import io.metersphere.project.service.ProjectApplicationService;
|
import io.metersphere.project.service.ProjectApplicationService;
|
||||||
import io.metersphere.sdk.constants.ProjectApplicationType;
|
import io.metersphere.sdk.constants.ProjectApplicationType;
|
||||||
|
import io.metersphere.sdk.constants.StorageType;
|
||||||
|
import io.metersphere.sdk.dto.api.task.ApiExecuteFileInfo;
|
||||||
import io.metersphere.sdk.dto.api.task.TaskRequest;
|
import io.metersphere.sdk.dto.api.task.TaskRequest;
|
||||||
import io.metersphere.sdk.exception.MSException;
|
import io.metersphere.sdk.exception.MSException;
|
||||||
import io.metersphere.sdk.util.*;
|
import io.metersphere.sdk.util.*;
|
||||||
|
@ -25,6 +30,7 @@ import io.metersphere.system.service.TestResourcePoolService;
|
||||||
import io.metersphere.system.utils.TaskRunnerClient;
|
import io.metersphere.system.utils.TaskRunnerClient;
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.jmeter.util.JMeterUtils;
|
import org.apache.jmeter.util.JMeterUtils;
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
|
@ -37,6 +43,8 @@ import java.security.SecureRandom;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static io.metersphere.api.controller.result.ApiResultCode.RESOURCE_POOL_EXECUTE_ERROR;
|
import static io.metersphere.api.controller.result.ApiResultCode.RESOURCE_POOL_EXECUTE_ERROR;
|
||||||
|
|
||||||
|
@ -59,6 +67,15 @@ public class ApiExecuteService {
|
||||||
private StringRedisTemplate stringRedisTemplate;
|
private StringRedisTemplate stringRedisTemplate;
|
||||||
@Resource
|
@Resource
|
||||||
private JmeterProperties jmeterProperties;
|
private JmeterProperties jmeterProperties;
|
||||||
|
@Resource
|
||||||
|
private ApiFileResourceService apiFileResourceService;
|
||||||
|
@Resource
|
||||||
|
private FileAssociationService fileAssociationService;
|
||||||
|
@Resource
|
||||||
|
private FileMetadataService fileMetadataService;
|
||||||
|
@Resource
|
||||||
|
private FileManagementService fileManagementService;
|
||||||
|
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
private void init() {
|
private void init() {
|
||||||
|
@ -89,24 +106,24 @@ public class ApiExecuteService {
|
||||||
public void debug(ApiResourceRunRequest request) {
|
public void debug(ApiResourceRunRequest request) {
|
||||||
TestResourceDTO resourcePoolDTO = getAvailableResourcePoolDTO(request.getProjectId());
|
TestResourceDTO resourcePoolDTO = getAvailableResourcePoolDTO(request.getProjectId());
|
||||||
String reportId = request.getReportId();
|
String reportId = request.getReportId();
|
||||||
String testId = request.getTestId();
|
String testId = request.getTestId();
|
||||||
|
|
||||||
TaskRequest taskRequest = new TaskRequest();
|
TaskRequest taskRequest = new TaskRequest();
|
||||||
BeanUtils.copyBean(taskRequest, request);
|
BeanUtils.copyBean(taskRequest, request);
|
||||||
|
|
||||||
String msUrl = systemParameterService.getBaseInfo().getUrl();
|
|
||||||
taskRequest.setKafkaConfig(EncryptUtils.aesEncrypt(JSON.toJSONString(KafkaConfig.getKafkaConfig())));
|
taskRequest.setKafkaConfig(EncryptUtils.aesEncrypt(JSON.toJSONString(KafkaConfig.getKafkaConfig())));
|
||||||
taskRequest.setMinioConfig(EncryptUtils.aesEncrypt(JSON.toJSONString(getMinio())));
|
taskRequest.setMinioConfig(EncryptUtils.aesEncrypt(JSON.toJSONString(getMinio())));
|
||||||
taskRequest.setMsUrl(msUrl);
|
taskRequest.setMsUrl(systemParameterService.getBaseInfo().getUrl());
|
||||||
taskRequest.setReportId(reportId);
|
|
||||||
taskRequest.setRealTime(true);
|
taskRequest.setRealTime(true);
|
||||||
|
|
||||||
// todo 环境配置
|
// 设置执行文件参数
|
||||||
// EnvironmentRequest environmentRequest = environmentService.get(request.getEnvironmentId());
|
setTaskFileParam(request, taskRequest);
|
||||||
// todo 误报
|
|
||||||
// todo 获取接口插件和jar包
|
|
||||||
// todo 处理公共脚本
|
|
||||||
|
|
||||||
|
// todo 环境配置
|
||||||
|
// EnvironmentInfoDTO environmentInfoDTO = environmentService.get(request.getEnvironmentId());
|
||||||
|
// todo 误报
|
||||||
|
// todo 获取接口插件和jar包
|
||||||
|
// todo 处理公共脚本
|
||||||
|
// todo 接口用例 method 获取定义中的数据库字段
|
||||||
ParameterConfig parameterConfig = new ParameterConfig();
|
ParameterConfig parameterConfig = new ParameterConfig();
|
||||||
parameterConfig.setReportId(reportId);
|
parameterConfig.setReportId(reportId);
|
||||||
String executeScript = parseExecuteScript(request.getRequest(), parameterConfig);
|
String executeScript = parseExecuteScript(request.getRequest(), parameterConfig);
|
||||||
|
@ -130,8 +147,94 @@ public class ApiExecuteService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给 taskRequest 设置文件相关参数
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @param taskRequest
|
||||||
|
*/
|
||||||
|
private void setTaskFileParam(ApiResourceRunRequest request, TaskRequest taskRequest) {
|
||||||
|
// 查询通过本地上传的文件
|
||||||
|
List<ApiExecuteFileInfo> localFiles = apiFileResourceService.getByResourceId(request.getId()).
|
||||||
|
stream()
|
||||||
|
.map(file -> {
|
||||||
|
ApiExecuteFileInfo apiExecuteFileInfo = getApiExecuteFileInfo(file.getFileId(), file.getFileName(), file.getProjectId());
|
||||||
|
// 本地上传的文件需要 resourceId 查询对应的目录
|
||||||
|
apiExecuteFileInfo.setResourceId(request.getId());
|
||||||
|
return apiExecuteFileInfo;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
taskRequest.setLocalFiles(localFiles);
|
||||||
|
|
||||||
|
// 查询关联的文件管理的文件
|
||||||
|
List<ApiExecuteFileInfo> refFiles = fileAssociationService.getFiles(request.getId()).
|
||||||
|
stream()
|
||||||
|
.map(file -> {
|
||||||
|
ApiExecuteFileInfo refFileInfo = getApiExecuteFileInfo(file.getFileId(), file.getFileName(),
|
||||||
|
file.getProjectId(), file.getStorage());
|
||||||
|
if (StorageType.isGit(file.getStorage())) {
|
||||||
|
// 设置Git信息
|
||||||
|
refFileInfo.setFileMetadataRepositoryDTO(fileManagementService.getFileMetadataRepositoryDTO(file.getMetadataId()));
|
||||||
|
refFileInfo.setFileModuleRepositoryDTO(fileManagementService.getFileModuleRepositoryDTO(file.getModuleId()));
|
||||||
|
}
|
||||||
|
return refFileInfo;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
// 处理没有保存的临时文件
|
||||||
|
List<String> tempFileIds = request.getTempFileIds();
|
||||||
|
if (CollectionUtils.isNotEmpty(tempFileIds)) {
|
||||||
|
// 查询这些文件有哪些是关联文件管理的文件
|
||||||
|
List<ApiExecuteFileInfo> refTempFiles = fileMetadataService.getByFileIds(tempFileIds)
|
||||||
|
.stream()
|
||||||
|
.map(file -> {
|
||||||
|
String fileName = file.getName();
|
||||||
|
if (StringUtils.isNotBlank(file.getType())) {
|
||||||
|
fileName += "." + file.getType();
|
||||||
|
}
|
||||||
|
ApiExecuteFileInfo tempFileInfo = getApiExecuteFileInfo(file.getId(), fileName,
|
||||||
|
file.getProjectId(), file.getStorage());
|
||||||
|
if (StorageType.isGit(file.getStorage())) {
|
||||||
|
// 设置Git信息
|
||||||
|
tempFileInfo.setFileMetadataRepositoryDTO(fileManagementService.getFileMetadataRepositoryDTO(file.getId()));
|
||||||
|
tempFileInfo.setFileModuleRepositoryDTO(fileManagementService.getFileModuleRepositoryDTO(file.getModuleId()));
|
||||||
|
}
|
||||||
|
return tempFileInfo;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
// 添加临时的文件管理的文件
|
||||||
|
refFiles.addAll(refTempFiles);
|
||||||
|
|
||||||
|
Set<String> refTempFileIds = refTempFiles.stream().map(ApiExecuteFileInfo::getFileId).collect(Collectors.toSet());
|
||||||
|
// 去掉文件管理的文件,即通过本地上传的临时文件
|
||||||
|
List<ApiExecuteFileInfo> localTempFiles = tempFileIds.stream()
|
||||||
|
.filter(tempFileId -> !refTempFileIds.contains(tempFileId))
|
||||||
|
.map(tempFileId -> {
|
||||||
|
String fileName = apiFileResourceService.getTempFileNameByFileId(tempFileId);
|
||||||
|
ApiExecuteFileInfo apiExecuteFileInfo = getApiExecuteFileInfo(tempFileId, fileName, request.getProjectId());
|
||||||
|
return apiExecuteFileInfo;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
taskRequest.setLocalTempFiles(localTempFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
taskRequest.setRefFiles(refFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ApiExecuteFileInfo getApiExecuteFileInfo(String fileId, String fileName, String projectId) {
|
||||||
|
return getApiExecuteFileInfo(fileId, fileName, projectId, StorageType.MINIO.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ApiExecuteFileInfo getApiExecuteFileInfo(String fileId, String fileName, String projectId, String storage) {
|
||||||
|
ApiExecuteFileInfo apiExecuteFileInfo = new ApiExecuteFileInfo();
|
||||||
|
apiExecuteFileInfo.setStorage(storage);
|
||||||
|
apiExecuteFileInfo.setFileName(fileName);
|
||||||
|
apiExecuteFileInfo.setFileId(fileId);
|
||||||
|
apiExecuteFileInfo.setProjectId(projectId);
|
||||||
|
return apiExecuteFileInfo;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成执行脚本
|
* 生成执行脚本
|
||||||
|
*
|
||||||
* @param testElementStr
|
* @param testElementStr
|
||||||
* @param msParameter
|
* @param msParameter
|
||||||
* @return
|
* @return
|
||||||
|
@ -155,6 +258,7 @@ public class ApiExecuteService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前项目配置的接口默认资源池
|
* 获取当前项目配置的接口默认资源池
|
||||||
|
*
|
||||||
* @param projectId
|
* @param projectId
|
||||||
* @param
|
* @param
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -113,10 +113,12 @@ public class ApiDebugService {
|
||||||
apiDebugMapper.updateByPrimaryKeySelective(apiDebug);
|
apiDebugMapper.updateByPrimaryKeySelective(apiDebug);
|
||||||
// todo 校验 moduleId
|
// todo 校验 moduleId
|
||||||
|
|
||||||
ApiDebugBlob apiDebugBlob = new ApiDebugBlob();
|
if (StringUtils.isNotBlank(request.getRequest())) {
|
||||||
apiDebugBlob.setId(request.getId());
|
ApiDebugBlob apiDebugBlob = new ApiDebugBlob();
|
||||||
apiDebugBlob.setRequest(request.getRequest().getBytes());
|
apiDebugBlob.setId(request.getId());
|
||||||
apiDebugBlobMapper.updateByPrimaryKeySelective(apiDebugBlob);
|
apiDebugBlob.setRequest(request.getRequest().getBytes());
|
||||||
|
apiDebugBlobMapper.updateByPrimaryKeySelective(apiDebugBlob);
|
||||||
|
}
|
||||||
|
|
||||||
ApiFileResourceUpdateRequest resourceUpdateRequest = getApiFileResourceUpdateRequest(originApiDebug.getId(), originApiDebug.getProjectId(), updateUser);
|
ApiFileResourceUpdateRequest resourceUpdateRequest = getApiFileResourceUpdateRequest(originApiDebug.getId(), originApiDebug.getProjectId(), updateUser);
|
||||||
resourceUpdateRequest.setUploadFileIds(request.getUploadFileIds());
|
resourceUpdateRequest.setUploadFileIds(request.getUploadFileIds());
|
||||||
|
@ -159,6 +161,7 @@ public class ApiDebugService {
|
||||||
throw new MSException(API_DEBUG_EXIST);
|
throw new MSException(API_DEBUG_EXIST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ApiDebug checkResourceExist(String id) {
|
private ApiDebug checkResourceExist(String id) {
|
||||||
return ServiceUtils.checkResourceExist(apiDebugMapper.selectByPrimaryKey(id), "permission.system_api_debug.name");
|
return ServiceUtils.checkResourceExist(apiDebugMapper.selectByPrimaryKey(id), "permission.system_api_debug.name");
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import io.metersphere.api.domain.ApiFileResource;
|
||||||
import io.metersphere.api.dto.debug.*;
|
import io.metersphere.api.dto.debug.*;
|
||||||
import io.metersphere.api.dto.request.MsScenario;
|
import io.metersphere.api.dto.request.MsScenario;
|
||||||
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
||||||
|
import io.metersphere.api.dto.request.http.body.Body;
|
||||||
import io.metersphere.api.mapper.ApiDebugBlobMapper;
|
import io.metersphere.api.mapper.ApiDebugBlobMapper;
|
||||||
import io.metersphere.api.mapper.ApiDebugMapper;
|
import io.metersphere.api.mapper.ApiDebugMapper;
|
||||||
import io.metersphere.api.parser.ImportParserFactory;
|
import io.metersphere.api.parser.ImportParserFactory;
|
||||||
|
@ -29,9 +30,10 @@ import io.metersphere.sdk.constants.DefaultRepositoryDir;
|
||||||
import io.metersphere.sdk.constants.PermissionConstants;
|
import io.metersphere.sdk.constants.PermissionConstants;
|
||||||
import io.metersphere.sdk.constants.ProjectApplicationType;
|
import io.metersphere.sdk.constants.ProjectApplicationType;
|
||||||
import io.metersphere.sdk.constants.ResourcePoolTypeEnum;
|
import io.metersphere.sdk.constants.ResourcePoolTypeEnum;
|
||||||
|
import io.metersphere.sdk.file.FileCenter;
|
||||||
|
import io.metersphere.sdk.file.FileRequest;
|
||||||
import io.metersphere.sdk.util.BeanUtils;
|
import io.metersphere.sdk.util.BeanUtils;
|
||||||
import io.metersphere.sdk.util.CommonBeanFactory;
|
import io.metersphere.sdk.util.CommonBeanFactory;
|
||||||
import io.metersphere.sdk.util.FileAssociationSourceUtil;
|
|
||||||
import io.metersphere.sdk.util.JSON;
|
import io.metersphere.sdk.util.JSON;
|
||||||
import io.metersphere.system.base.BaseTest;
|
import io.metersphere.system.base.BaseTest;
|
||||||
import io.metersphere.system.controller.handler.ResultHolder;
|
import io.metersphere.system.controller.handler.ResultHolder;
|
||||||
|
@ -42,8 +44,6 @@ import io.metersphere.system.domain.TestResourcePoolOrganizationExample;
|
||||||
import io.metersphere.system.dto.pool.TestResourceDTO;
|
import io.metersphere.system.dto.pool.TestResourceDTO;
|
||||||
import io.metersphere.system.dto.pool.TestResourceNodeDTO;
|
import io.metersphere.system.dto.pool.TestResourceNodeDTO;
|
||||||
import io.metersphere.system.dto.pool.TestResourcePoolDTO;
|
import io.metersphere.system.dto.pool.TestResourcePoolDTO;
|
||||||
import io.metersphere.sdk.file.FileCenter;
|
|
||||||
import io.metersphere.sdk.file.FileRequest;
|
|
||||||
import io.metersphere.system.log.constants.OperationLogType;
|
import io.metersphere.system.log.constants.OperationLogType;
|
||||||
import io.metersphere.system.mapper.TestResourcePoolBlobMapper;
|
import io.metersphere.system.mapper.TestResourcePoolBlobMapper;
|
||||||
import io.metersphere.system.mapper.TestResourcePoolMapper;
|
import io.metersphere.system.mapper.TestResourcePoolMapper;
|
||||||
|
@ -339,7 +339,7 @@ public class ApiDebugControllerTests extends BaseTest {
|
||||||
*/
|
*/
|
||||||
private static void assertLinkFile(String id, List<String> fileIds) {
|
private static void assertLinkFile(String id, List<String> fileIds) {
|
||||||
FileAssociationService fileAssociationService = CommonBeanFactory.getBean(FileAssociationService.class);
|
FileAssociationService fileAssociationService = CommonBeanFactory.getBean(FileAssociationService.class);
|
||||||
List<String> linkFileIds = fileAssociationService.getFiles(id, FileAssociationSourceUtil.SOURCE_TYPE_API_DEBUG)
|
List<String> linkFileIds = fileAssociationService.getFiles(id)
|
||||||
.stream()
|
.stream()
|
||||||
.map(FileInfo::getFileId)
|
.map(FileInfo::getFileId)
|
||||||
.toList();
|
.toList();
|
||||||
|
@ -408,6 +408,42 @@ public class ApiDebugControllerTests extends BaseTest {
|
||||||
// @@请求成功
|
// @@请求成功
|
||||||
this.requestPostWithOk(DEBUG, request);
|
this.requestPostWithOk(DEBUG, request);
|
||||||
|
|
||||||
|
// 测试 FORM_DATA
|
||||||
|
MockMultipartFile file = getMockMultipartFile();
|
||||||
|
String fileId = doUploadTempFile(file);
|
||||||
|
request.setTempFileIds(List.of(fileId, fileMetadataId));
|
||||||
|
msHTTPElement = MsHTTPElementTest.getMsHttpElement();
|
||||||
|
Body generalBody = MsHTTPElementTest.getGeneralBody();
|
||||||
|
generalBody.setBodyType(Body.BodyType.FORM_DATA.name());
|
||||||
|
msHTTPElement.setBody(generalBody);
|
||||||
|
request.setRequest(ApiDataUtils.toJSONString(msHTTPElement));
|
||||||
|
this.requestPostWithOk(DEBUG, request);
|
||||||
|
|
||||||
|
// 测试 WWW_FORM
|
||||||
|
generalBody.setBodyType(Body.BodyType.WWW_FORM.name());
|
||||||
|
request.setRequest(ApiDataUtils.toJSONString(msHTTPElement));
|
||||||
|
this.requestPostWithOk(DEBUG, request);
|
||||||
|
|
||||||
|
// 测试 BINARY
|
||||||
|
generalBody.setBodyType(Body.BodyType.BINARY.name());
|
||||||
|
request.setRequest(ApiDataUtils.toJSONString(msHTTPElement));
|
||||||
|
this.requestPostWithOk(DEBUG, request);
|
||||||
|
|
||||||
|
// 测试 JSON
|
||||||
|
generalBody.setBodyType(Body.BodyType.JSON.name());
|
||||||
|
request.setRequest(ApiDataUtils.toJSONString(msHTTPElement));
|
||||||
|
this.requestPostWithOk(DEBUG, request);
|
||||||
|
|
||||||
|
// 测试 XML
|
||||||
|
generalBody.setBodyType(Body.BodyType.XML.name());
|
||||||
|
request.setRequest(ApiDataUtils.toJSONString(msHTTPElement));
|
||||||
|
this.requestPostWithOk(DEBUG, request);
|
||||||
|
|
||||||
|
// 测试 XML
|
||||||
|
generalBody.setBodyType(Body.BodyType.RAW.name());
|
||||||
|
request.setRequest(ApiDataUtils.toJSONString(msHTTPElement));
|
||||||
|
this.requestPostWithOk(DEBUG, request);
|
||||||
|
|
||||||
// 增加覆盖率
|
// 增加覆盖率
|
||||||
new TestElementParserFactory();
|
new TestElementParserFactory();
|
||||||
new ImportParserFactory();
|
new ImportParserFactory();
|
||||||
|
|
|
@ -415,7 +415,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
||||||
*/
|
*/
|
||||||
private static void assertLinkFile(String id, List<String> fileIds) {
|
private static void assertLinkFile(String id, List<String> fileIds) {
|
||||||
FileAssociationService fileAssociationService = CommonBeanFactory.getBean(FileAssociationService.class);
|
FileAssociationService fileAssociationService = CommonBeanFactory.getBean(FileAssociationService.class);
|
||||||
List<String> linkFileIds = fileAssociationService.getFiles(id, FileAssociationSourceUtil.SOURCE_TYPE_API_DEFINITION)
|
List<String> linkFileIds = fileAssociationService.getFiles(id)
|
||||||
.stream()
|
.stream()
|
||||||
.map(FileInfo::getFileId)
|
.map(FileInfo::getFileId)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
|
@ -3,6 +3,7 @@ package io.metersphere.api.controller;
|
||||||
import io.metersphere.api.controller.param.ApiTestCaseAddRequestDefinition;
|
import io.metersphere.api.controller.param.ApiTestCaseAddRequestDefinition;
|
||||||
import io.metersphere.api.domain.*;
|
import io.metersphere.api.domain.*;
|
||||||
import io.metersphere.api.dto.definition.*;
|
import io.metersphere.api.dto.definition.*;
|
||||||
|
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
||||||
import io.metersphere.api.mapper.*;
|
import io.metersphere.api.mapper.*;
|
||||||
import io.metersphere.api.service.ApiFileResourceService;
|
import io.metersphere.api.service.ApiFileResourceService;
|
||||||
import io.metersphere.api.utils.ApiDataUtils;
|
import io.metersphere.api.utils.ApiDataUtils;
|
||||||
|
@ -17,18 +18,16 @@ import io.metersphere.sdk.constants.PermissionConstants;
|
||||||
import io.metersphere.sdk.constants.SessionConstants;
|
import io.metersphere.sdk.constants.SessionConstants;
|
||||||
import io.metersphere.sdk.domain.Environment;
|
import io.metersphere.sdk.domain.Environment;
|
||||||
import io.metersphere.sdk.domain.EnvironmentExample;
|
import io.metersphere.sdk.domain.EnvironmentExample;
|
||||||
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
import io.metersphere.sdk.file.FileCenter;
|
||||||
|
import io.metersphere.sdk.file.FileRequest;
|
||||||
|
import io.metersphere.sdk.file.MinioRepository;
|
||||||
import io.metersphere.sdk.mapper.EnvironmentMapper;
|
import io.metersphere.sdk.mapper.EnvironmentMapper;
|
||||||
import io.metersphere.sdk.util.BeanUtils;
|
import io.metersphere.sdk.util.BeanUtils;
|
||||||
import io.metersphere.sdk.util.CommonBeanFactory;
|
import io.metersphere.sdk.util.CommonBeanFactory;
|
||||||
import io.metersphere.sdk.util.FileAssociationSourceUtil;
|
|
||||||
import io.metersphere.sdk.util.JSON;
|
import io.metersphere.sdk.util.JSON;
|
||||||
import io.metersphere.system.base.BaseTest;
|
import io.metersphere.system.base.BaseTest;
|
||||||
import io.metersphere.system.controller.handler.ResultHolder;
|
import io.metersphere.system.controller.handler.ResultHolder;
|
||||||
import io.metersphere.system.dto.sdk.request.PosRequest;
|
import io.metersphere.system.dto.sdk.request.PosRequest;
|
||||||
import io.metersphere.sdk.file.FileCenter;
|
|
||||||
import io.metersphere.sdk.file.FileRequest;
|
|
||||||
import io.metersphere.sdk.file.MinioRepository;
|
|
||||||
import io.metersphere.system.log.constants.OperationLogType;
|
import io.metersphere.system.log.constants.OperationLogType;
|
||||||
import io.metersphere.system.uid.NumGenerator;
|
import io.metersphere.system.uid.NumGenerator;
|
||||||
import io.metersphere.system.utils.Pager;
|
import io.metersphere.system.utils.Pager;
|
||||||
|
@ -240,7 +239,7 @@ public class ApiTestCaseControllerTests extends BaseTest {
|
||||||
*/
|
*/
|
||||||
private static void assertLinkFile(String id, List<String> fileIds) {
|
private static void assertLinkFile(String id, List<String> fileIds) {
|
||||||
FileAssociationService fileAssociationService = CommonBeanFactory.getBean(FileAssociationService.class);
|
FileAssociationService fileAssociationService = CommonBeanFactory.getBean(FileAssociationService.class);
|
||||||
List<String> linkFileIds = fileAssociationService.getFiles(id, FileAssociationSourceUtil.SOURCE_TYPE_API_TEST_CASE)
|
List<String> linkFileIds = fileAssociationService.getFiles(id)
|
||||||
.stream()
|
.stream()
|
||||||
.map(FileInfo::getFileId)
|
.map(FileInfo::getFileId)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
package io.metersphere.api.controller;
|
package io.metersphere.api.controller;
|
||||||
|
|
||||||
import io.metersphere.api.dto.definition.HttpResponse;
|
import io.metersphere.api.dto.definition.HttpResponse;
|
||||||
import io.metersphere.api.utils.ApiDataUtils;
|
|
||||||
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
|
||||||
import io.metersphere.sdk.constants.MsAssertionCondition;
|
|
||||||
import io.metersphere.api.dto.request.assertion.*;
|
import io.metersphere.api.dto.request.assertion.*;
|
||||||
import io.metersphere.api.dto.request.assertion.body.*;
|
import io.metersphere.api.dto.request.assertion.body.*;
|
||||||
import io.metersphere.api.dto.request.http.*;
|
import io.metersphere.api.dto.request.http.*;
|
||||||
|
@ -16,6 +13,9 @@ import io.metersphere.api.dto.request.processors.*;
|
||||||
import io.metersphere.api.dto.request.processors.extract.JSONPathExtract;
|
import io.metersphere.api.dto.request.processors.extract.JSONPathExtract;
|
||||||
import io.metersphere.api.dto.request.processors.extract.RegexExtract;
|
import io.metersphere.api.dto.request.processors.extract.RegexExtract;
|
||||||
import io.metersphere.api.dto.request.processors.extract.XPathExtract;
|
import io.metersphere.api.dto.request.processors.extract.XPathExtract;
|
||||||
|
import io.metersphere.api.utils.ApiDataUtils;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
import io.metersphere.sdk.constants.MsAssertionCondition;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@ -33,9 +33,14 @@ public class MsHTTPElementTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void bodyTest() {
|
public void bodyTest() {
|
||||||
|
|
||||||
MsHTTPElement msHTTPElement = getMsHttpElement();
|
MsHTTPElement msHTTPElement = getMsHttpElement();
|
||||||
|
msHTTPElement.setBody(getGeneralBody());
|
||||||
|
String json = ApiDataUtils.toJSONString(msHTTPElement);
|
||||||
|
Assertions.assertNotNull(json);
|
||||||
|
Assertions.assertEquals(ApiDataUtils.parseObject(json, AbstractMsTestElement.class), msHTTPElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Body getGeneralBody() {
|
||||||
Body body = new Body();
|
Body body = new Body();
|
||||||
body.setBodyType(Body.BodyType.FORM_DATA.name());
|
body.setBodyType(Body.BodyType.FORM_DATA.name());
|
||||||
|
|
||||||
|
@ -49,8 +54,14 @@ public class MsHTTPElementTest {
|
||||||
formDataKV.setParamType("text");
|
formDataKV.setParamType("text");
|
||||||
formDataKV.setDescription("test");
|
formDataKV.setDescription("test");
|
||||||
formDataKV.setRequired(true);
|
formDataKV.setRequired(true);
|
||||||
formDataKV.setValue("value");
|
formDataKV.setValue("@email");
|
||||||
formDataKV.setKey("key");
|
formDataKV.setKey("key");
|
||||||
|
FormDataKV formDataFileKV = new FormDataKV();
|
||||||
|
BodyFile bodyFile = new BodyFile();
|
||||||
|
bodyFile.setFileId("aaa");
|
||||||
|
bodyFile.setFileName("aaa");
|
||||||
|
formDataFileKV.setFiles(List.of(bodyFile));
|
||||||
|
formDataFileKV.setKey("fileKey");
|
||||||
formDataBody.setFromValues(List.of(formDataKV));
|
formDataBody.setFromValues(List.of(formDataKV));
|
||||||
body.setFormDataBody(formDataBody);
|
body.setFormDataBody(formDataBody);
|
||||||
|
|
||||||
|
@ -60,6 +71,7 @@ public class MsHTTPElementTest {
|
||||||
|
|
||||||
JsonBody jsonBody = new JsonBody();
|
JsonBody jsonBody = new JsonBody();
|
||||||
jsonBody.setJsonSchema("{}");
|
jsonBody.setJsonSchema("{}");
|
||||||
|
jsonBody.setEnableJsonSchema(false);
|
||||||
body.setJsonBody(jsonBody);
|
body.setJsonBody(jsonBody);
|
||||||
|
|
||||||
body.setNoneBody(new NoneBody());
|
body.setNoneBody(new NoneBody());
|
||||||
|
@ -73,14 +85,10 @@ public class MsHTTPElementTest {
|
||||||
body.setXmlBody(xmlBody);
|
body.setXmlBody(xmlBody);
|
||||||
|
|
||||||
BinaryBody binaryBody = new BinaryBody();
|
BinaryBody binaryBody = new BinaryBody();
|
||||||
binaryBody.setFileId("sdfsf2222");
|
binaryBody.setBodyFile(bodyFile);
|
||||||
binaryBody.setFileName("a.png");
|
|
||||||
body.setBinaryBody(binaryBody);
|
body.setBinaryBody(binaryBody);
|
||||||
|
|
||||||
msHTTPElement.setBody(body);
|
return body;
|
||||||
String json = ApiDataUtils.toJSONString(msHTTPElement);
|
|
||||||
Assertions.assertNotNull(json);
|
|
||||||
Assertions.assertEquals(ApiDataUtils.parseObject(json, AbstractMsTestElement.class), msHTTPElement);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -128,7 +128,7 @@ public class FunctionalCaseAttachmentService {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
//获取关联的附件信息
|
//获取关联的附件信息
|
||||||
List<FileInfo> files = fileAssociationService.getFiles(functionalCaseDetailDTO.getId(), FileAssociationSourceUtil.SOURCE_TYPE_FUNCTIONAL_CASE);
|
List<FileInfo> files = fileAssociationService.getFiles(functionalCaseDetailDTO.getId());
|
||||||
List<FunctionalCaseAttachmentDTO> filesDTOs = new ArrayList<>(Lists.transform(files, (fileInfo) -> {
|
List<FunctionalCaseAttachmentDTO> filesDTOs = new ArrayList<>(Lists.transform(files, (fileInfo) -> {
|
||||||
FunctionalCaseAttachmentDTO attachmentDTO = new FunctionalCaseAttachmentDTO();
|
FunctionalCaseAttachmentDTO attachmentDTO = new FunctionalCaseAttachmentDTO();
|
||||||
BeanUtils.copyBean(attachmentDTO, fileInfo);
|
BeanUtils.copyBean(attachmentDTO, fileInfo);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.metersphere.project.controller;
|
package io.metersphere.project.controller;
|
||||||
|
|
||||||
|
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
|
||||||
import io.metersphere.project.dto.environment.*;
|
import io.metersphere.project.dto.environment.*;
|
||||||
import io.metersphere.project.dto.environment.datasource.DataSource;
|
import io.metersphere.project.dto.environment.datasource.DataSource;
|
||||||
import io.metersphere.project.dto.environment.ssl.KeyStoreEntry;
|
import io.metersphere.project.dto.environment.ssl.KeyStoreEntry;
|
||||||
|
|
|
@ -36,4 +36,15 @@ public class FileInfo implements Serializable {
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
private Long createTime;
|
private Long createTime;
|
||||||
|
|
||||||
|
@Schema(description = "文件存储方式")
|
||||||
|
private String storage;
|
||||||
|
|
||||||
|
@Schema(description = "项目ID")
|
||||||
|
private String projectId;
|
||||||
|
|
||||||
|
@Schema(description = "模块ID")
|
||||||
|
private String moduleId;
|
||||||
|
|
||||||
|
@Schema(description = "文件资源ID")
|
||||||
|
private String metadataId;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ public interface ExtFileAssociationMapper {
|
||||||
FileAssociationSource selectNameBySourceTableAndId(@Param("querySql") String querySql, @Param("sourceId") String sourceId);
|
FileAssociationSource selectNameBySourceTableAndId(@Param("querySql") String querySql, @Param("sourceId") String sourceId);
|
||||||
List<FileAssociationSource> selectAssociationSourceBySourceTableAndIdList(@Param("querySql") String querySql, @Param("idList") List<String> sourceIdList);
|
List<FileAssociationSource> selectAssociationSourceBySourceTableAndIdList(@Param("querySql") String querySql, @Param("idList") List<String> sourceIdList);
|
||||||
|
|
||||||
List<FileInfo> selectAssociationFileInfo(@Param("sourceId") String sourceId, @Param("sourceType") String sourceType);
|
List<FileInfo> selectAssociationFileInfo(@Param("sourceId") String sourceId);
|
||||||
|
|
||||||
List<FileAssociation> selectFileIdsBySourceId(@Param("sourceIds")List<String> sourceIds, @Param("sourceType")String sourceType);
|
List<FileAssociation> selectFileIdsBySourceId(@Param("sourceIds")List<String> sourceIds, @Param("sourceType")String sourceType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,12 @@
|
||||||
SELECT
|
SELECT
|
||||||
file_association.id AS id,
|
file_association.id AS id,
|
||||||
file_association.file_id AS fileId,
|
file_association.file_id AS fileId,
|
||||||
CONCAT( file_metadata.`name`, '.', file_metadata.type ) AS fileName,
|
CONCAT( file_metadata.`name`, IF(LENGTH(file_metadata.type) = 0, '', '.'), file_metadata.type ) AS fileName,
|
||||||
file_metadata.size AS size,
|
file_metadata.size AS size,
|
||||||
|
file_metadata.storage,
|
||||||
|
file_metadata.project_id,
|
||||||
|
file_metadata.module_id,
|
||||||
|
file_metadata.id as metadataId,
|
||||||
'false' AS local,
|
'false' AS local,
|
||||||
file_association.create_user AS createUser,
|
file_association.create_user AS createUser,
|
||||||
file_association.create_time AS createTime
|
file_association.create_time AS createTime
|
||||||
|
@ -29,7 +33,6 @@
|
||||||
LEFT JOIN file_metadata ON file_association.file_id = file_metadata.id
|
LEFT JOIN file_metadata ON file_association.file_id = file_metadata.id
|
||||||
WHERE
|
WHERE
|
||||||
file_association.source_id = #{sourceId}
|
file_association.source_id = #{sourceId}
|
||||||
AND file_association.source_type = #{sourceType}
|
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectFileIdsBySourceId" resultType="io.metersphere.project.domain.FileAssociation">
|
<select id="selectFileIdsBySourceId" resultType="io.metersphere.project.domain.FileAssociation">
|
||||||
|
|
|
@ -25,7 +25,7 @@ public class CommandService {
|
||||||
|
|
||||||
public static String createFile(MultipartFile bodyFile) {
|
public static String createFile(MultipartFile bodyFile) {
|
||||||
MsFileUtils.validateFileName(bodyFile.getOriginalFilename());
|
MsFileUtils.validateFileName(bodyFile.getOriginalFilename());
|
||||||
String dir = LocalRepositoryDir.getBodyEnvironmentTmpDir();
|
String dir = LocalRepositoryDir.getSystemTempDir();
|
||||||
File fileDir = new File(dir);
|
File fileDir = new File(dir);
|
||||||
if (!fileDir.exists()) {
|
if (!fileDir.exists()) {
|
||||||
fileDir.mkdirs();
|
fileDir.mkdirs();
|
||||||
|
|
|
@ -337,11 +337,10 @@ public class FileAssociationService {
|
||||||
* 获取文件列表接口
|
* 获取文件列表接口
|
||||||
*
|
*
|
||||||
* @param sourceId
|
* @param sourceId
|
||||||
* @param sourceType
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public List<FileInfo> getFiles(String sourceId, String sourceType) {
|
public List<FileInfo> getFiles(String sourceId) {
|
||||||
return extFileAssociationMapper.selectAssociationFileInfo(sourceId, sourceType);
|
return extFileAssociationMapper.selectAssociationFileInfo(sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FileAssociation> getFileAssociations(List<String> sourceIds, String sourceType) {
|
public List<FileAssociation> getFileAssociations(List<String> sourceIds, String sourceType) {
|
||||||
|
|
|
@ -172,19 +172,27 @@ public class FileManagementService {
|
||||||
fileRequest.setStorage(fileMetadata.getStorage());
|
fileRequest.setStorage(fileMetadata.getStorage());
|
||||||
//获取git文件下载
|
//获取git文件下载
|
||||||
if (StringUtils.equals(fileMetadata.getStorage(), StorageType.GIT.name())) {
|
if (StringUtils.equals(fileMetadata.getStorage(), StorageType.GIT.name())) {
|
||||||
FileModuleRepository fileModuleRepository = fileModuleRepositoryMapper.selectByPrimaryKey(fileMetadata.getModuleId());
|
FileModuleRepositoryDTO repositoryDTO = getFileModuleRepositoryDTO(fileMetadata.getModuleId());
|
||||||
FileMetadataRepository fileMetadataRepository = fileMetadataRepositoryMapper.selectByPrimaryKey(fileMetadata.getId());
|
FileMetadataRepositoryDTO metadataRepositoryDTO = getFileMetadataRepositoryDTO(fileMetadata.getId());
|
||||||
|
|
||||||
FileModuleRepositoryDTO repositoryDTO = new FileModuleRepositoryDTO();
|
|
||||||
BeanUtils.copyBean(repositoryDTO, fileModuleRepository);
|
|
||||||
FileMetadataRepositoryDTO metadataRepositoryDTO = new FileMetadataRepositoryDTO();
|
|
||||||
BeanUtils.copyBean(metadataRepositoryDTO, fileMetadataRepository);
|
|
||||||
fileRequest.setGitFileRequest(repositoryDTO, metadataRepositoryDTO);
|
fileRequest.setGitFileRequest(repositoryDTO, metadataRepositoryDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fileService.download(fileRequest);
|
return fileService.download(fileRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FileMetadataRepositoryDTO getFileMetadataRepositoryDTO(String fileMetadataId) {
|
||||||
|
FileMetadataRepository fileMetadataRepository = fileMetadataRepositoryMapper.selectByPrimaryKey(fileMetadataId);
|
||||||
|
FileMetadataRepositoryDTO metadataRepositoryDTO = new FileMetadataRepositoryDTO();
|
||||||
|
BeanUtils.copyBean(metadataRepositoryDTO, fileMetadataRepository);
|
||||||
|
return metadataRepositoryDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileModuleRepositoryDTO getFileModuleRepositoryDTO(String moduleId) {
|
||||||
|
FileModuleRepository fileModuleRepository = fileModuleRepositoryMapper.selectByPrimaryKey(moduleId);
|
||||||
|
FileModuleRepositoryDTO repositoryDTO = new FileModuleRepositoryDTO();
|
||||||
|
BeanUtils.copyBean(repositoryDTO, fileModuleRepository);
|
||||||
|
return repositoryDTO;
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] getPreviewImg(FileMetadata fileMetadata) {
|
public byte[] getPreviewImg(FileMetadata fileMetadata) {
|
||||||
FileRequest previewRequest = new FileRequest();
|
FileRequest previewRequest = new FileRequest();
|
||||||
|
|
|
@ -669,4 +669,10 @@ public class FileMetadataService {
|
||||||
private String generateMinIOFilePath(String projectId) {
|
private String generateMinIOFilePath(String projectId) {
|
||||||
return DefaultRepositoryDir.getFileManagementDir(projectId);
|
return DefaultRepositoryDir.getFileManagementDir(projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<FileMetadata> getByFileIds(List<String> tempFileIds) {
|
||||||
|
FileMetadataExample example = new FileMetadataExample();
|
||||||
|
example.createCriteria().andIdIn(tempFileIds);
|
||||||
|
return fileMetadataMapper.selectByExample(example);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package io.metersphere.project.controller;
|
package io.metersphere.project.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
|
||||||
import io.metersphere.project.dto.environment.*;
|
import io.metersphere.project.dto.environment.*;
|
||||||
import io.metersphere.project.dto.environment.assertions.*;
|
import io.metersphere.project.dto.environment.assertions.*;
|
||||||
import io.metersphere.project.dto.environment.auth.AuthConfig;
|
import io.metersphere.project.dto.environment.auth.AuthConfig;
|
||||||
|
|
|
@ -2421,7 +2421,7 @@ public class FileManagementControllerTests extends BaseTest {
|
||||||
@Test
|
@Test
|
||||||
@Order(91)
|
@Order(91)
|
||||||
public void testQuery() throws Exception {
|
public void testQuery() throws Exception {
|
||||||
fileAssociationService.getFiles("TEST", FileAssociationSourceUtil.SOURCE_TYPE_FUNCTIONAL_CASE);
|
fileAssociationService.getFiles("TEST");
|
||||||
fileAssociationService.getFileAssociations(Collections.singletonList("TEST"), FileAssociationSourceUtil.SOURCE_TYPE_FUNCTIONAL_CASE);
|
fileAssociationService.getFileAssociations(Collections.singletonList("TEST"), FileAssociationSourceUtil.SOURCE_TYPE_FUNCTIONAL_CASE);
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue