From 4610d0919e2103e8fc71c4189d082acb3cebc405 Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Wed, 7 Jun 2023 14:06:11 +0800 Subject: [PATCH] =?UTF-8?q?build:=20=E5=8A=A8=E6=80=81=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E6=8F=92=E4=BB=B6=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/annotation/PluginSubType.java | 12 +++ .../plugin/api/dto/TestElementDTO.java | 9 +- .../jmeter/processors/MSJSR223Processor.java | 26 +++++ .../dto/jmeter/sampler/MSDebugSampler.java | 64 ++++++++++++ .../io/metersphere/api/util/JSONUtils.java | 98 +++++++++++++++++++ .../api/controller/PluginSubTypeTests.java | 38 +++++++ 6 files changed, 241 insertions(+), 6 deletions(-) create mode 100644 backend/framework/plugin/src/main/java/io/metersphere/plugin/annotation/PluginSubType.java create mode 100644 backend/services/api-test/src/main/java/io/metersphere/api/dto/jmeter/processors/MSJSR223Processor.java create mode 100644 backend/services/api-test/src/main/java/io/metersphere/api/dto/jmeter/sampler/MSDebugSampler.java create mode 100644 backend/services/api-test/src/main/java/io/metersphere/api/util/JSONUtils.java create mode 100644 backend/services/api-test/src/test/java/io/metersphere/api/controller/PluginSubTypeTests.java diff --git a/backend/framework/plugin/src/main/java/io/metersphere/plugin/annotation/PluginSubType.java b/backend/framework/plugin/src/main/java/io/metersphere/plugin/annotation/PluginSubType.java new file mode 100644 index 0000000000..5b3749c9b1 --- /dev/null +++ b/backend/framework/plugin/src/main/java/io/metersphere/plugin/annotation/PluginSubType.java @@ -0,0 +1,12 @@ +package io.metersphere.plugin.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface PluginSubType { + String value(); +} \ No newline at end of file diff --git a/backend/framework/plugin/src/main/java/io/metersphere/plugin/api/dto/TestElementDTO.java b/backend/framework/plugin/src/main/java/io/metersphere/plugin/api/dto/TestElementDTO.java index 1f67b3ea66..48f36245c3 100644 --- a/backend/framework/plugin/src/main/java/io/metersphere/plugin/api/dto/TestElementDTO.java +++ b/backend/framework/plugin/src/main/java/io/metersphere/plugin/api/dto/TestElementDTO.java @@ -4,25 +4,22 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonTypeInfo; import io.metersphere.plugin.util.PluginLogUtils; import lombok.Data; - import org.apache.jmeter.save.SaveService; import org.apache.jorphan.collections.HashTree; import org.apache.jorphan.collections.ListedHashTree; import java.io.ByteArrayOutputStream; +import java.io.Serializable; import java.util.LinkedList; import java.util.List; -@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "clazzName") @Data +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") @JsonIgnoreProperties(ignoreUnknown = true) -public abstract class TestElementDTO { +public abstract class TestElementDTO implements Serializable { // 组件类型 private String type; - // 用于数据反射对象 - private String clazzName = TestElementDTO.class.getCanonicalName(); - // 当前组件唯一标示 private String uuid; diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/jmeter/processors/MSJSR223Processor.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/jmeter/processors/MSJSR223Processor.java new file mode 100644 index 0000000000..646994e058 --- /dev/null +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/jmeter/processors/MSJSR223Processor.java @@ -0,0 +1,26 @@ +package io.metersphere.api.dto.jmeter.processors; + +import io.metersphere.plugin.annotation.PluginSubType; +import io.metersphere.plugin.api.dto.BaseConfigDTO; +import io.metersphere.plugin.api.dto.TestElementDTO; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.jorphan.collections.HashTree; + +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper = true) +@PluginSubType("MSJSR223Processor") +public class MSJSR223Processor extends TestElementDTO { + private String script; + private String scriptLanguage; + private Boolean jsrEnable; + + @Override + public void toHashTree(HashTree tree, List hashTree, BaseConfigDTO baseConfig) { + if (!this.isEnable()) { + return; + } + } +} diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/jmeter/sampler/MSDebugSampler.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/jmeter/sampler/MSDebugSampler.java new file mode 100644 index 0000000000..69e6e8215b --- /dev/null +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/jmeter/sampler/MSDebugSampler.java @@ -0,0 +1,64 @@ +package io.metersphere.api.dto.jmeter.sampler; + +import io.metersphere.plugin.annotation.PluginSubType; +import io.metersphere.plugin.api.dto.BaseConfigDTO; +import io.metersphere.plugin.api.dto.TestElementDTO; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.jmeter.sampler.DebugSampler; +import org.apache.jmeter.save.SaveService; +import org.apache.jmeter.testelement.TestElement; +import org.apache.jorphan.collections.HashTree; + +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper = true) +@PluginSubType("MSDebugSampler") +public class MSDebugSampler extends TestElementDTO { + private boolean displayJMeterProperties = false; + private boolean displayJMeterVariables = true; + private boolean displaySystemProperties = false; + + @Override + public void toHashTree(HashTree tree, List hashTree, BaseConfigDTO configDTO) { + BaseConfigDTO config = (BaseConfigDTO) configDTO; + // 非导出操作,且不是启用状态则跳过执行 + if (!this.isEnable()) { + return; + } + final HashTree groupTree = tree.add(debugSampler()); + if (CollectionUtils.isNotEmpty(hashTree)) { + hashTree.forEach(el -> { + // 给所有孩子加一个父亲标志 + el.setParent(this); + el.toHashTree(groupTree, el.getHashTree(), config); + }); + } + } + + + private DebugSampler debugSampler() { + DebugSampler debugSampler = new DebugSampler(); + debugSampler.setEnabled(this.isEnable()); + if (StringUtils.isEmpty(this.getName())) { + this.setName(MSDebugSampler.class.getSimpleName()); + } + debugSampler.setName(this.getName()); + debugSampler.setProperty(TestElement.TEST_CLASS, DebugSampler.class.getName()); + debugSampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI")); + + debugSampler.setDisplaySystemProperties(this.displaySystemProperties); + debugSampler.setDisplayJMeterVariables(this.displayJMeterVariables); + debugSampler.setDisplayJMeterProperties(this.displayJMeterProperties); + + //上面三行直接Set属性会导致DebugSampler构建时取不到值,可能是JMeter的Bug,需要SetProperty + debugSampler.setProperty("displayJMeterProperties", this.displayJMeterProperties); + debugSampler.setProperty("displayJMeterVariables", this.displayJMeterVariables); + debugSampler.setProperty("displaySystemProperties", this.displaySystemProperties); + return debugSampler; + } + +} diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/util/JSONUtils.java b/backend/services/api-test/src/main/java/io/metersphere/api/util/JSONUtils.java new file mode 100644 index 0000000000..63fa0c8590 --- /dev/null +++ b/backend/services/api-test/src/main/java/io/metersphere/api/util/JSONUtils.java @@ -0,0 +1,98 @@ +package io.metersphere.api.util; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.jsontype.NamedType; +import com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver; +import com.fasterxml.jackson.databind.type.CollectionType; +import io.metersphere.api.dto.jmeter.processors.MSJSR223Processor; +import io.metersphere.api.dto.jmeter.sampler.MSDebugSampler; + +import java.io.IOException; +import java.io.InputStream; +import java.util.LinkedList; +import java.util.List; + +public class JSONUtils { + private static final ObjectMapper objectMapper = new ObjectMapper(); + private static StdSubtypeResolver resolver = new StdSubtypeResolver(); + + static { + // 添加处理资源文件的类 + final List namedTypes = new LinkedList<>(); + namedTypes.add(new NamedType(MSJSR223Processor.class, MSJSR223Processor.class.getSimpleName())); + namedTypes.add(new NamedType(MSDebugSampler.class, MSDebugSampler.class.getSimpleName())); + + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + // 自动检测所有类的全部属性 + objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); + // 如果一个对象中没有任何的属性,那么在序列化的时候就会报错 + objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); + objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); + namedTypes.forEach(namedType -> resolver.registerSubtypes(namedType)); + objectMapper.setSubtypeResolver(resolver); + } + + public static String toJSONString(Object value) { + try { + return objectMapper.writeValueAsString(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static Object parseObject(String content) { + return parseObject(content, Object.class); + } + + public static T parseObject(String content, Class valueType) { + try { + return objectMapper.readValue(content, valueType); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static T parseObject(InputStream src, Class valueType) { + try { + return objectMapper.readValue(src, valueType); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static T parseObject(String content, TypeReference valueType) { + try { + return objectMapper.readValue(content, valueType); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static List parseArray(String content) { + return parseArray(content, Object.class); + } + + public static List parseArray(String content, Class valueType) { + CollectionType javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, valueType); + try { + return objectMapper.readValue(content, javaType); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * 设置动态加载的jar的Resolver + * + * @param namedTypes + */ + public static void setResolver(List namedTypes) { + namedTypes.forEach(namedType -> resolver.registerSubtypes(namedType)); + objectMapper.setSubtypeResolver(resolver); + } +} diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/PluginSubTypeTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/PluginSubTypeTests.java new file mode 100644 index 0000000000..e20423e5d2 --- /dev/null +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/PluginSubTypeTests.java @@ -0,0 +1,38 @@ +package io.metersphere.api.controller; + +import io.metersphere.api.dto.jmeter.processors.MSJSR223Processor; +import io.metersphere.api.dto.jmeter.sampler.MSDebugSampler; +import io.metersphere.api.util.JSONUtils; +import io.metersphere.plugin.api.dto.TestElementDTO; +import org.junit.jupiter.api.*; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.LinkedList; +import java.util.UUID; + + +@SpringBootTest +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@AutoConfigureMockMvc +public class PluginSubTypeTests { + + @Test + @Order(0) + public void pluginSubTypeTest() throws Exception { + MSDebugSampler debugSampler = new MSDebugSampler(); + debugSampler.setName("测试DebugSampler"); + debugSampler.setUuid(UUID.randomUUID().toString()); + LinkedList hashTree = new LinkedList<>(); + hashTree.add(debugSampler); + MSJSR223Processor msjsr223Processor = new MSJSR223Processor(); + msjsr223Processor.setName("测试jsr223"); + msjsr223Processor.setJsrEnable(true); + msjsr223Processor.setHashTree(hashTree); + + String json = JSONUtils.toJSONString(msjsr223Processor); + Assertions.assertNotNull(json); + TestElementDTO testElementDTO = JSONUtils.parseObject(json, TestElementDTO.class); + Assertions.assertNotNull(testElementDTO); + } +}