refactor(性能测试): 重构性能测试解析jmx的方式
This commit is contained in:
parent
ff664cd1b9
commit
285ca02ba1
|
@ -8,7 +8,7 @@ public class EngineContext {
|
||||||
private String testName;
|
private String testName;
|
||||||
private String namespace;
|
private String namespace;
|
||||||
private String fileType;
|
private String fileType;
|
||||||
private String content;
|
private byte[] content;
|
||||||
private String resourcePoolId;
|
private String resourcePoolId;
|
||||||
private String reportId;
|
private String reportId;
|
||||||
private Integer resourceIndex;
|
private Integer resourceIndex;
|
||||||
|
@ -52,11 +52,11 @@ public class EngineContext {
|
||||||
return this.properties.get(key);
|
return this.properties.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getContent() {
|
public byte[] getContent() {
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContent(String content) {
|
public void setContent(byte[] content) {
|
||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,25 +25,15 @@ import org.apache.commons.beanutils.ConstructorUtils;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.collections4.ListUtils;
|
import org.apache.commons.collections4.ListUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dom4j.Document;
|
||||||
|
import org.dom4j.Element;
|
||||||
import org.reflections8.Reflections;
|
import org.reflections8.Reflections;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.w3c.dom.Document;
|
|
||||||
import org.w3c.dom.Element;
|
|
||||||
import org.w3c.dom.Node;
|
|
||||||
import org.w3c.dom.NodeList;
|
|
||||||
import org.xml.sax.InputSource;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
import javax.xml.transform.Transformer;
|
|
||||||
import javax.xml.transform.TransformerException;
|
|
||||||
import javax.xml.transform.TransformerFactory;
|
|
||||||
import javax.xml.transform.dom.DOMSource;
|
|
||||||
import javax.xml.transform.stream.StreamResult;
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -239,7 +229,7 @@ public class EngineFactory {
|
||||||
engineContext.setTestResourceFiles(testResourceFiles);
|
engineContext.setTestResourceFiles(testResourceFiles);
|
||||||
|
|
||||||
try (ByteArrayInputStream source = new ByteArrayInputStream(jmxBytes)) {
|
try (ByteArrayInputStream source = new ByteArrayInputStream(jmxBytes)) {
|
||||||
String content = engineSourceParser.parse(engineContext, source);
|
byte[] content = engineSourceParser.parse(engineContext, source);
|
||||||
engineContext.setContent(content);
|
engineContext.setContent(content);
|
||||||
} catch (MSException e) {
|
} catch (MSException e) {
|
||||||
LogUtil.error(e.getMessage(), e);
|
LogUtil.error(e.getMessage(), e);
|
||||||
|
@ -309,80 +299,75 @@ public class EngineFactory {
|
||||||
return props.toString().getBytes(StandardCharsets.UTF_8);
|
return props.toString().getBytes(StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static byte[] mergeJmx(List<FileMetadata> jmxFiles) {
|
public static byte[] mergeJmx(List<FileMetadata> jmxFiles) {
|
||||||
try {
|
try {
|
||||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
|
||||||
DocumentBuilder docBuilder = factory.newDocumentBuilder();
|
|
||||||
Element hashTree = null;
|
Element hashTree = null;
|
||||||
Document rootDocument = null;
|
Document rootDocument = null;
|
||||||
for (FileMetadata fileMetadata : jmxFiles) {
|
for (FileMetadata fileMetadata : jmxFiles) {
|
||||||
FileContent fileContent = fileService.getFileContent(fileMetadata.getId());
|
FileContent fileContent = fileService.getFileContent(fileMetadata.getId());
|
||||||
final InputSource inputSource = new InputSource(new ByteArrayInputStream(fileContent.getFile()));
|
InputStream inputSource = new ByteArrayInputStream(fileContent.getFile());
|
||||||
if (hashTree == null) {
|
if (hashTree == null) {
|
||||||
rootDocument = docBuilder.parse(inputSource);
|
rootDocument = EngineSourceParserFactory.getDocument(inputSource);
|
||||||
Element jmeterTestPlan = rootDocument.getDocumentElement();
|
Element jmeterTestPlan = rootDocument.getRootElement();
|
||||||
NodeList childNodes = jmeterTestPlan.getChildNodes();
|
List<Element> childNodes = jmeterTestPlan.elements();
|
||||||
|
|
||||||
outer:
|
outer:
|
||||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
for (Element node : childNodes) {
|
||||||
Node node = childNodes.item(i);
|
|
||||||
if (node instanceof Element) {
|
|
||||||
// jmeterTestPlan的子元素肯定是<hashTree></hashTree>
|
// jmeterTestPlan的子元素肯定是<hashTree></hashTree>
|
||||||
NodeList childNodes1 = node.getChildNodes();
|
List<Element> childNodes1 = node.elements();
|
||||||
for (int j = 0; j < childNodes1.getLength(); j++) {
|
for (Element item : childNodes1) {
|
||||||
Node item = childNodes1.item(j);
|
if (StringUtils.equalsIgnoreCase("TestPlan", item.getName())) {
|
||||||
if (StringUtils.equalsIgnoreCase("hashTree", item.getNodeName())) {
|
hashTree = getNextSibling(item);
|
||||||
hashTree = (Element) node;
|
|
||||||
break outer;
|
break outer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Document document = docBuilder.parse(inputSource);
|
Document document = EngineSourceParserFactory.getDocument(inputSource);
|
||||||
Element jmeterTestPlan = document.getDocumentElement();
|
Element jmeterTestPlan = document.getRootElement();
|
||||||
NodeList childNodes = jmeterTestPlan.getChildNodes();
|
List<Element> childNodes = jmeterTestPlan.elements();
|
||||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
for (Element node : childNodes) {
|
||||||
Node node = childNodes.item(i);
|
|
||||||
if (node instanceof Element) {
|
|
||||||
// jmeterTestPlan的子元素肯定是<hashTree></hashTree>
|
// jmeterTestPlan的子元素肯定是<hashTree></hashTree>
|
||||||
Element secondHashTree = (Element) node;
|
Element secondHashTree = node;
|
||||||
NodeList secondChildNodes = secondHashTree.getChildNodes();
|
List<Element> secondChildNodes = secondHashTree.elements();
|
||||||
for (int j = 0; j < secondChildNodes.getLength(); j++) {
|
for (Element item : secondChildNodes) {
|
||||||
Node item = secondChildNodes.item(j);
|
if (StringUtils.equalsIgnoreCase("TestPlan", item.getName())) {
|
||||||
if (StringUtils.equalsIgnoreCase("TestPlan", item.getNodeName())) {
|
secondHashTree = getNextSibling(item);
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
if (StringUtils.equalsIgnoreCase("hashTree", item.getNodeName())) {
|
}
|
||||||
NodeList itemChildNodes = item.getChildNodes();
|
if (StringUtils.equalsIgnoreCase("hashTree", secondHashTree.getName())) {
|
||||||
for (int k = 0; k < itemChildNodes.getLength(); k++) {
|
List<Element> itemChildNodes = secondHashTree.elements();
|
||||||
Node item1 = itemChildNodes.item(k);
|
for (Element item1 : itemChildNodes) {
|
||||||
Node newNode = item1.cloneNode(true);
|
hashTree.add((Element) item1.clone());
|
||||||
rootDocument.adoptNode(newNode);
|
|
||||||
hashTree.appendChild(newNode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
inputSource.close();
|
||||||
}
|
}
|
||||||
}
|
return EngineSourceParserFactory.formatXml(rootDocument);
|
||||||
}
|
|
||||||
return documentToBytes(rootDocument);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
MSException.throwException(e);
|
MSException.throwException(e);
|
||||||
}
|
}
|
||||||
return new byte[0];
|
return new byte[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] documentToBytes(Document document) throws TransformerException {
|
private static Element getNextSibling(Element ele) {
|
||||||
DOMSource domSource = new DOMSource(document);
|
Element parent = ele.getParent();
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
if (parent != null) {
|
||||||
StreamResult result = new StreamResult(out);
|
Iterator<Element> iterator = parent.elementIterator();
|
||||||
TransformerFactory tf = TransformerFactory.newInstance();
|
while (iterator.hasNext()) {
|
||||||
Transformer transformer = tf.newTransformer();
|
Element next = iterator.next();
|
||||||
transformer.transform(domSource, result);
|
if (ele.equals(next)) {
|
||||||
return out.toByteArray();
|
return iterator.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
|
|
|
@ -5,5 +5,5 @@ import io.metersphere.performance.engine.EngineContext;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
public interface EngineSourceParser {
|
public interface EngineSourceParser {
|
||||||
String parse(EngineContext context, InputStream source) throws Exception;
|
byte[] parse(EngineContext context, InputStream source) throws Exception;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,96 @@
|
||||||
package io.metersphere.performance.parse;
|
package io.metersphere.performance.parse;
|
||||||
|
|
||||||
import io.metersphere.commons.constants.FileType;
|
import io.metersphere.commons.constants.FileType;
|
||||||
import io.metersphere.performance.parse.xml.XmlEngineSourceParse;
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
|
import io.metersphere.performance.parse.xml.reader.JmeterDocumentParser;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dom4j.Document;
|
||||||
|
import org.dom4j.DocumentException;
|
||||||
|
import org.dom4j.io.OutputFormat;
|
||||||
|
import org.dom4j.io.SAXReader;
|
||||||
|
import org.dom4j.io.XMLWriter;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
import org.xml.sax.helpers.XMLFilterImpl;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
public class EngineSourceParserFactory {
|
public class EngineSourceParserFactory {
|
||||||
|
public static final boolean IS_TRANS = true;
|
||||||
|
|
||||||
|
|
||||||
public static EngineSourceParser createEngineSourceParser(String type) {
|
public static EngineSourceParser createEngineSourceParser(String type) {
|
||||||
final FileType engineType = FileType.valueOf(type);
|
final FileType engineType = FileType.valueOf(type);
|
||||||
|
|
||||||
if (FileType.JMX.equals(engineType)) {
|
if (FileType.JMX.equals(engineType)) {
|
||||||
return new XmlEngineSourceParse();
|
return new JmeterDocumentParser();
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Document getDocument(InputStream source) throws DocumentException {
|
||||||
|
SAXReader reader = new SAXReader();
|
||||||
|
if (!IS_TRANS) {
|
||||||
|
reader.setXMLFilter(EngineSourceParserFactory.getFilter());
|
||||||
|
}
|
||||||
|
return reader.read(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] formatXml(Document document) throws Exception {
|
||||||
|
OutputFormat format = OutputFormat.createPrettyPrint();
|
||||||
|
try (
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
) {
|
||||||
|
XMLWriter xw = new XMLWriter(out, format);
|
||||||
|
xw.setEscapeText(IS_TRANS);
|
||||||
|
xw.write(document);
|
||||||
|
xw.flush();
|
||||||
|
xw.close();
|
||||||
|
return out.toByteArray();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LogUtil.error(e);
|
||||||
|
}
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static XMLFilterImpl getFilter() {
|
||||||
|
return new XMLFilterImpl() {
|
||||||
|
@Override
|
||||||
|
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||||
|
String text = new String(ch, start, length);
|
||||||
|
|
||||||
|
if (length == 1) {
|
||||||
|
if (StringUtils.equals("&", text)) {
|
||||||
|
char[] escape = "&".toCharArray();
|
||||||
|
super.characters(escape, start, escape.length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (StringUtils.equals("\"", text)) {
|
||||||
|
char[] escape = """.toCharArray();
|
||||||
|
super.characters(escape, start, escape.length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (StringUtils.equals("'", text)) {
|
||||||
|
char[] escape = "'".toCharArray();
|
||||||
|
super.characters(escape, start, escape.length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (StringUtils.equals("<", text)) {
|
||||||
|
char[] escape = "<".toCharArray();
|
||||||
|
super.characters(escape, start, escape.length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (StringUtils.equals(">", text)) {
|
||||||
|
char[] escape = ">".toCharArray();
|
||||||
|
super.characters(escape, start, escape.length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.characters(ch, start, length);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
package io.metersphere.performance.parse.xml;
|
|
||||||
|
|
||||||
import io.metersphere.performance.engine.EngineContext;
|
|
||||||
import io.metersphere.performance.parse.EngineSourceParser;
|
|
||||||
import io.metersphere.performance.parse.xml.reader.DocumentParser;
|
|
||||||
import io.metersphere.performance.parse.xml.reader.DocumentParserFactory;
|
|
||||||
import org.w3c.dom.Document;
|
|
||||||
import org.xml.sax.InputSource;
|
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
public class XmlEngineSourceParse implements EngineSourceParser {
|
|
||||||
@Override
|
|
||||||
public String parse(EngineContext context, InputStream source) throws Exception {
|
|
||||||
final InputSource inputSource = new InputSource(source);
|
|
||||||
|
|
||||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
|
||||||
|
|
||||||
DocumentBuilder docBuilder = factory.newDocumentBuilder();
|
|
||||||
final Document document = docBuilder.parse(inputSource);
|
|
||||||
|
|
||||||
final DocumentParser documentParser = createDocumentParser(context.getFileType());
|
|
||||||
|
|
||||||
return documentParser.parse(context, document);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DocumentParser createDocumentParser(String type) {
|
|
||||||
return DocumentParserFactory.createDocumentParser(type);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
package io.metersphere.performance.parse.xml.reader;
|
|
||||||
|
|
||||||
import io.metersphere.performance.engine.EngineContext;
|
|
||||||
import org.w3c.dom.Document;
|
|
||||||
|
|
||||||
public interface DocumentParser {
|
|
||||||
String parse(EngineContext context, Document document) throws Exception;
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
package io.metersphere.performance.parse.xml.reader;
|
|
||||||
|
|
||||||
import io.metersphere.commons.constants.FileType;
|
|
||||||
import io.metersphere.performance.parse.xml.reader.jmx.JmeterDocumentParser;
|
|
||||||
|
|
||||||
public class DocumentParserFactory {
|
|
||||||
public static DocumentParser createDocumentParser(String type) {
|
|
||||||
final FileType fileType = FileType.valueOf(type);
|
|
||||||
|
|
||||||
switch (fileType) {
|
|
||||||
case JMX:
|
|
||||||
return new JmeterDocumentParser();
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -13,7 +13,6 @@ import org.springframework.stereotype.Service;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
@ -60,11 +59,11 @@ public class JmeterFileService {
|
||||||
Map<String, byte[]> files = new HashMap<>();
|
Map<String, byte[]> files = new HashMap<>();
|
||||||
|
|
||||||
// 每个测试生成一个文件夹
|
// 每个测试生成一个文件夹
|
||||||
files.put(fileName, context.getContent().getBytes(StandardCharsets.UTF_8));
|
files.put(fileName, context.getContent());
|
||||||
// 保存jmx
|
// 保存jmx
|
||||||
LoadTestReportWithBLOBs record = new LoadTestReportWithBLOBs();
|
LoadTestReportWithBLOBs record = new LoadTestReportWithBLOBs();
|
||||||
record.setId(context.getReportId());
|
record.setId(context.getReportId());
|
||||||
record.setJmxContent(context.getContent());
|
record.setJmxContent(new String(context.getContent()));
|
||||||
extLoadTestReportMapper.updateJmxContentIfAbsent(record);
|
extLoadTestReportMapper.updateJmxContentIfAbsent(record);
|
||||||
// 保存 byte[]
|
// 保存 byte[]
|
||||||
Map<String, byte[]> jarFiles = context.getTestResourceFiles();
|
Map<String, byte[]> jarFiles = context.getTestResourceFiles();
|
||||||
|
|
Loading…
Reference in New Issue