chore: 定义接口组件和转换器接口

This commit is contained in:
AgAngle 2023-11-05 12:24:15 +08:00 committed by Craftsman
parent 6d87d98e01
commit 835beb3b49
13 changed files with 278 additions and 4 deletions

View File

@ -0,0 +1,72 @@
package io.metersphere.plugin.api.spi;
import org.apache.jorphan.collections.HashTree;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
/**
* @author jianxing
* @createTime 2021-10-30 10:07
* MsTestElement 具体实现类转换为 HashTree
*/
public abstract class AbstractJmeterElementConverter<T extends MsTestElement> {
private Class<? extends MsTestElement> msTestElementClass;
/**
* 解析器集合
* key MsTestElement 实现类的 Class
* value 为对应的转换器
*/
private static final Map<Class<? extends MsTestElement>, AbstractJmeterElementConverter> parserMap = new HashMap();
public AbstractJmeterElementConverter() {
Type genericSuperclass = getClass().getGenericSuperclass();
if (genericSuperclass instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
// 获取泛型的具体类型 MsTestElement 的具体实现类
msTestElementClass = (Class<? extends MsTestElement>) parameterizedType.getActualTypeArguments()[0];
// 注册到解析器集合中
parserMap.put(msTestElementClass, this);
}
}
/**
* MsTestElement 具体实现类转换为 HashTree
*
* @param tree
* @param msTestElement
* @param config
*/
public abstract void toHashTree(HashTree tree, T msTestElement, MsParameter config);
/**
* 解析 MsTestElement 的子节点
*
* @param tree
* @param msTestElement
* @param config
*/
public void parseChild(HashTree tree, AbstractMsTestElement msTestElement, MsParameter config) {
if (msTestElement != null && msTestElement.getChildren() != null) {
for (MsTestElement testElement : msTestElement.getChildren()) {
AbstractJmeterElementConverter converter = getConverter(testElement);
converter.toHashTree(tree, msTestElement, config);
}
}
}
/**
* 获取对应组件的转换器
*
* @param msTestElement
* @return
*/
public static AbstractJmeterElementConverter getConverter(MsTestElement msTestElement) {
return parserMap.get(msTestElement.getClass());
}
}

View File

@ -0,0 +1,25 @@
package io.metersphere.plugin.api.spi;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import lombok.Data;
import java.util.LinkedList;
/**
*@Author: jianxing
*@CreateTime: 2023-10-30 15:08
*/
@Data
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "polymorphicName")
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class AbstractMsTestElement implements MsTestElement {
// 组件标签名称
private String name;
// 是否启用
private Boolean enable = true;
// 子组件
private LinkedList<AbstractMsTestElement> children;
}

View File

@ -0,0 +1,8 @@
package io.metersphere.plugin.api.spi;
/**
* @Author: jianxing
* @CreateTime: 2023-10-27 17:30
*/
public class MsParameter {
}

View File

@ -0,0 +1,17 @@
package io.metersphere.plugin.api.spi;
import org.pf4j.ExtensionPoint;
/**
* MS 中的测试组件
* 即场景中的每个步骤组件
* 或者接口定义对应的协议组件
*/
public interface MsTestElement extends ExtensionPoint {
}

View File

@ -0,0 +1,10 @@
package io.metersphere.sdk.dto.api.request;
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
public class MsScenario extends AbstractMsTestElement {
}

View File

@ -0,0 +1,10 @@
package io.metersphere.sdk.dto.api.request;
import io.metersphere.plugin.api.spi.MsParameter;
/**
* @Author: jianxing
* @CreateTime: 2023-10-27 17:30
*/
public class ParameterConfig extends MsParameter {
}

View File

@ -0,0 +1,11 @@
package io.metersphere.sdk.dto.api.request.http;
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
public class MsHTTPElement extends AbstractMsTestElement {
private String domain;
}

View File

@ -0,0 +1,10 @@
package io.metersphere.api.dto.request;
import io.metersphere.plugin.api.spi.MsParameter;
/**
* @Author: jianxing
* @CreateTime: 2023-10-27 17:30
*/
public class ParameterConfig extends MsParameter {
}

View File

@ -3,10 +3,15 @@ package io.metersphere.api.controller;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import io.metersphere.api.util.ApiDataUtils;
import io.metersphere.plugin.api.dto.TestElementDTO;
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.metersphere.plugin.api.spi.MsTestElement;
import io.metersphere.sdk.dto.api.request.logic.controller.MsLoopController;
import io.metersphere.sdk.dto.api.request.post.processors.MsPostJSR223Processor;
import io.metersphere.sdk.dto.api.request.sampler.MsDebugSampler;
import io.metersphere.system.base.BaseApiPluginTestService;
import io.metersphere.system.service.PluginLoadService;
import io.metersphere.system.uid.IDGenerator;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.*;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
@ -20,6 +25,11 @@ import java.util.List;
@AutoConfigureMockMvc
public class PluginSubTypeTests {
@Resource
private BaseApiPluginTestService baseApiPluginTestService;
@Resource
private PluginLoadService pluginLoadService;
@Test
@Order(0)
@ -79,4 +89,25 @@ public class PluginSubTypeTests {
TestElementDTO testElementDTO = ApiDataUtils.parseObject(json, TestElementDTO.class);
Assertions.assertNotNull(testElementDTO);
}
@Test
@Order(4)
public void jdbcPluginSubTypeTest() throws Exception {
// 上传 jdbc 插件
baseApiPluginTestService.addJdbcPlugin();
List<Class<? extends MsTestElement>> extensionClasses =
pluginLoadService.getMsPluginManager().getExtensionClasses(MsTestElement.class);
// 注册序列化类
extensionClasses.forEach(ApiDataUtils::setResolver);
String jdbcJson = """
{
"polymorphicName": "MsJDBCElement",
"test": "测试MsJDBCElement"
}
""";
AbstractMsTestElement testElementDTO = ApiDataUtils.parseObject(jdbcJson, AbstractMsTestElement.class);
Assertions.assertNotNull(testElementDTO);
}
}

View File

@ -29,6 +29,9 @@ public class PluginScriptService {
private ExtPluginScriptMapper extPluginScriptMapper;
public void add(String pluginId, List<String> frontendScript) {
if (CollectionUtils.isEmpty(frontendScript)) {
return;
}
Set<String> ids = new HashSet<>();
List<PluginScript> pluginScripts = new ArrayList<>(frontendScript.size());
for (String script : frontendScript) {

View File

@ -0,0 +1,77 @@
package io.metersphere.system.base;
import io.metersphere.system.domain.Plugin;
import io.metersphere.system.dto.request.PluginUpdateRequest;
import io.metersphere.system.mapper.PluginMapper;
import io.metersphere.system.service.PluginService;
import jakarta.annotation.Resource;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.FileInputStream;
import static io.metersphere.sdk.constants.InternalUserRole.ADMIN;
/**
* @Author: jianxing
* @CreateTime: 2023-10-20 11:32
*/
@Service
public class BaseApiPluginTestService {
@Resource
private PluginService pluginService;
@Resource
private PluginMapper pluginMapper;
private static Plugin jdbcPlugin;
/**
* 添加插件供测试使用
*
* @return
* @throws Exception
*/
public Plugin addJdbcPlugin() throws Exception {
if (hasJdbcPlugin()) {
return jdbcPlugin;
}
PluginUpdateRequest request = new PluginUpdateRequest();
File jarFile = new File(
this.getClass().getClassLoader().getResource("file/jdbc-sampler-v3.x.jar")
.getPath()
);
FileInputStream inputStream = new FileInputStream(jarFile);
MockMultipartFile mockMultipartFile = new MockMultipartFile(jarFile.getName(), jarFile.getName(), "jar", inputStream);
request.setName("测试jdbc插件");
request.setGlobal(true);
request.setEnable(true);
request.setCreateUser(ADMIN.name());
jdbcPlugin = pluginService.add(request, mockMultipartFile);
return jdbcPlugin;
}
public Plugin getJdbcPlugin() throws Exception {
if (!hasJdbcPlugin()) {
return this.addJdbcPlugin();
}
return jdbcPlugin;
}
public boolean hasJdbcPlugin() {
if (jdbcPlugin != null) {
return true;
}
jdbcPlugin = pluginMapper.selectByPrimaryKey("jdbc");
return jdbcPlugin != null;
}
public void deleteJdbcPlugin() {
if (jdbcPlugin != null) {
pluginService.delete(jdbcPlugin.getId());
jdbcPlugin = null;
}
}
}

View File

@ -17,10 +17,7 @@ import io.metersphere.system.mapper.PluginOrganizationMapper;
import io.metersphere.system.mapper.PluginScriptMapper;
import io.metersphere.system.dto.request.PlatformOptionRequest;
import io.metersphere.system.dto.request.PluginUpdateRequest;
import io.metersphere.system.service.JdbcDriverPluginService;
import io.metersphere.system.service.OrganizationService;
import io.metersphere.system.service.PluginService;
import io.metersphere.system.service.UserLoginService;
import io.metersphere.system.service.*;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.*;
@ -68,6 +65,8 @@ public class PluginControllerTests extends BaseTest {
private OrganizationService organizationService;
@Resource
private JdbcDriverPluginService jdbcDriverPluginService;
@Resource
private PluginScriptService pluginScriptService;
private static Plugin addPlugin;
private static Plugin anotherAddPlugin;
@ -131,6 +130,7 @@ public class PluginControllerTests extends BaseTest {
// 增加覆盖率
this.requestGetWithOkAndReturn(DEFAULT_LIST);
pluginScriptService.add(null, null);
// 校验 global tru e时organizationIds 为空
request.setGlobal(false);