From ca472e83786494f97f7a2279b0cec0a3b9debf04 Mon Sep 17 00:00:00 2001 From: "Captain.B" Date: Sun, 20 Jun 2021 16:10:39 +0800 Subject: [PATCH] =?UTF-8?q?refactor(=E6=80=A7=E8=83=BD=E6=B5=8B=E8=AF=95):?= =?UTF-8?q?=20=E5=88=87=E5=89=B2csv=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../performance/engine/EngineContext.java | 8 + .../performance/engine/EngineFactory.java | 19 +- .../xml/reader/jmx/JmeterDocumentParser.java | 66 ++++ .../performance/test/EditPerformanceTest.vue | 10 + .../components/PerformanceAdvancedConfig.vue | 295 ++++++++++-------- frontend/src/i18n/en-US.js | 2 + frontend/src/i18n/zh-CN.js | 8 +- frontend/src/i18n/zh-TW.js | 8 +- 8 files changed, 277 insertions(+), 139 deletions(-) diff --git a/backend/src/main/java/io/metersphere/performance/engine/EngineContext.java b/backend/src/main/java/io/metersphere/performance/engine/EngineContext.java index 05b23d5a50..e4ef1fa2b0 100644 --- a/backend/src/main/java/io/metersphere/performance/engine/EngineContext.java +++ b/backend/src/main/java/io/metersphere/performance/engine/EngineContext.java @@ -12,6 +12,7 @@ public class EngineContext { private String resourcePoolId; private String reportId; private Integer resourceIndex; + private double[] ratios; private Map properties = new HashMap<>(); private Map testResourceFiles = new HashMap<>(); @@ -92,6 +93,13 @@ public class EngineContext { this.resourceIndex = resourceIndex; } + public double[] getRatios() { + return ratios; + } + + public void setRatios(double[] ratios) { + this.ratios = ratios; + } public Map getTestResourceFiles() { return testResourceFiles; diff --git a/backend/src/main/java/io/metersphere/performance/engine/EngineFactory.java b/backend/src/main/java/io/metersphere/performance/engine/EngineFactory.java index 86adc07628..2b26fe5329 100644 --- a/backend/src/main/java/io/metersphere/performance/engine/EngineFactory.java +++ b/backend/src/main/java/io/metersphere/performance/engine/EngineFactory.java @@ -106,6 +106,7 @@ public class EngineFactory { engineContext.setResourcePoolId(loadTest.getTestResourcePoolId()); engineContext.setReportId(reportId); engineContext.setResourceIndex(resourceIndex); + engineContext.setRatios(ratios); if (StringUtils.isNotEmpty(loadTest.getLoadConfiguration())) { final JSONArray jsonArray = JSONObject.parseArray(loadTest.getLoadConfiguration()); @@ -155,6 +156,15 @@ public class EngineFactory { MSException.throwException("File type unknown"); } + if (CollectionUtils.isNotEmpty(resourceFiles)) { + Map data = new HashMap<>(); + resourceFiles.forEach(cf -> { + FileContent csvContent = fileService.getFileContent(cf.getId()); + data.put(cf.getName(), csvContent.getFile()); + }); + engineContext.setTestResourceFiles(data); + } + try (ByteArrayInputStream source = new ByteArrayInputStream(jmxBytes)) { String content = engineSourceParser.parse(engineContext, source); engineContext.setContent(content); @@ -166,15 +176,6 @@ public class EngineFactory { MSException.throwException(e); } - if (CollectionUtils.isNotEmpty(resourceFiles)) { - Map data = new HashMap<>(); - resourceFiles.forEach(cf -> { - FileContent csvContent = fileService.getFileContent(cf.getId()); - data.put(cf.getName(), csvContent.getFile()); - }); - engineContext.setTestResourceFiles(data); - } - return engineContext; } diff --git a/backend/src/main/java/io/metersphere/performance/parse/xml/reader/jmx/JmeterDocumentParser.java b/backend/src/main/java/io/metersphere/performance/parse/xml/reader/jmx/JmeterDocumentParser.java index c7f7165638..60e01119d1 100644 --- a/backend/src/main/java/io/metersphere/performance/parse/xml/reader/jmx/JmeterDocumentParser.java +++ b/backend/src/main/java/io/metersphere/performance/parse/xml/reader/jmx/JmeterDocumentParser.java @@ -22,8 +22,10 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.StringWriter; +import java.nio.charset.StandardCharsets; import java.util.HashSet; import java.util.List; +import java.util.StringTokenizer; public class JmeterDocumentParser implements DocumentParser { private final static String HASH_TREE_ELEMENT = "hashTree"; @@ -267,12 +269,76 @@ public class JmeterDocumentParser implements DocumentParser { if (StringUtils.equals(filenameTag, "filename")) { // 截取文件名 handleFilename(item); + // 切割CSV文件 + splitCsvFile(item); break; } } } } + private void splitCsvFile(Node item) { + Object csvConfig = context.getProperty("csvConfig"); + if (csvConfig == null) { + return; + } + double[] ratios = context.getRatios(); + int resourceIndex = context.getResourceIndex(); + String filename = item.getTextContent(); + byte[] content = context.getTestResourceFiles().get(filename); + StringTokenizer tokenizer = new StringTokenizer(new String(content), "\n"); + if (!tokenizer.hasMoreTokens()) { + return; + } + StringBuilder csv = new StringBuilder(); + Object config = ((JSONObject) csvConfig).get(filename); + boolean csvSplit = ((JSONObject) (config)).getBooleanValue("csvSplit"); + if (!csvSplit) { + return; + } + boolean csvHasHeader = ((JSONObject) (config)).getBooleanValue("csvHasHeader"); + if (csvHasHeader) { + String header = tokenizer.nextToken(); + csv.append(header).append("\n"); + } + int count = tokenizer.countTokens(); + + long current, offset = 0; + + // 计算偏移量 + for (int k = 0; k < resourceIndex; k++) { + offset += Math.round(count * ratios[k]); + } + + if (resourceIndex + 1 == ratios.length) { + current = count - offset; // 最后一个点可以分到的数量 + } else { + current = Math.round(count * ratios[resourceIndex]); // 当前节点可以分到的数量 + } + + long index = 1; + while (tokenizer.hasMoreTokens()) { + if (current == 0) { // 节点一个都没有分到,把所有的数据都给这个节点(极端情况) + String line = tokenizer.nextToken(); + csv.append(line).append("\n"); + } else { + if (index < offset) { + tokenizer.nextToken(); + index++; + continue; + } + if (index > current + offset) { + break; + } + String line = tokenizer.nextToken(); + csv.append(line).append("\n"); + } + index++; + } + // 替换文件 + context.getTestResourceFiles().put(filename, csv.toString().getBytes(StandardCharsets.UTF_8)); + } + private void processResponseAssertion(Element element) { NodeList childNodes = element.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { diff --git a/frontend/src/business/components/performance/test/EditPerformanceTest.vue b/frontend/src/business/components/performance/test/EditPerformanceTest.vue index 438dbae1a5..72bc0eb922 100644 --- a/frontend/src/business/components/performance/test/EditPerformanceTest.vue +++ b/frontend/src/business/components/performance/test/EditPerformanceTest.vue @@ -368,6 +368,7 @@ export default { fileChange(threadGroups) { let handler = this.$refs.pressureConfig; + let csvSet = new Set; threadGroups.forEach(tg => { tg.threadNumber = tg.threadNumber || 10; tg.duration = tg.duration || 10; @@ -377,12 +378,21 @@ export default { tg.threadType = tg.threadType || 'DURATION'; tg.iterateNum = tg.iterateNum || 1; tg.iterateRampUp = tg.iterateRampUp || 10; + + if (tg.csvFiles) { + tg.csvFiles.map(item => csvSet.add(item)); + } }); + let csvFiles = []; + for (const f of csvSet) { + csvFiles.push({name: f, csvSplit: false, csvHasHeader: true}); + } this.$set(handler, "threadGroups", threadGroups); this.$refs.basicConfig.threadGroups = threadGroups; this.$refs.pressureConfig.threadGroups = threadGroups; + this.$refs.advancedConfig.csvFiles = csvFiles; handler.calculateTotalChart(); }, diff --git a/frontend/src/business/components/performance/test/components/PerformanceAdvancedConfig.vue b/frontend/src/business/components/performance/test/components/PerformanceAdvancedConfig.vue index 4a21ccc793..38a2c8da4c 100644 --- a/frontend/src/business/components/performance/test/components/PerformanceAdvancedConfig.vue +++ b/frontend/src/business/components/performance/test/components/PerformanceAdvancedConfig.vue @@ -1,5 +1,110 @@