blob: 0f08f23de2f16e3b23022c624c4564cbc21b8776 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jmeter.save;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import java.util.List;
import org.apache.jmeter.junit.JMeterTestCase;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.collections.HashTree;
import org.junit.jupiter.api.Test;
public class TestSaveService extends JMeterTestCase {
// testLoadAndSave test files
private static final String[] FILES = new String[] {
"AssertionTestPlan.jmx",
"AuthManagerTestPlan.jmx",
"HeaderManagerTestPlan.jmx",
"InterleaveTestPlan2.jmx",
"InterleaveTestPlan.jmx",
"LoopTestPlan.jmx",
"Modification Manager.jmx",
"OnceOnlyTestPlan.jmx",
"proxy.jmx",
"ProxyServerTestPlan.jmx",
"SimpleTestPlan.jmx",
"GuiTest.jmx",
"GuiTest231.jmx",
// autogenerated test files
"GenTest27.jmx", // 2.7
"GenTest210.jmx", // 2.10
"GenTest2_13.jmx", // 2.13
"GenTest3_0.jmx", // 3.0
};
// Test files for testLoadAndSave; output will generally be different in size but same number of lines
private static final String[] FILES_LINES = new String[] {
"GuiTest231_original.jmx",
"GenTest25.jmx", // GraphAccumVisualizer obsolete, BSFSamplerGui now a TestBean
"GenTest251.jmx", // GraphAccumVisualizer obsolete, BSFSamplerGui now a TestBean
"GenTest26.jmx", // GraphAccumVisualizer now obsolete
"GenTest27_original.jmx", // CTT changed to use intProp for mode
};
// Test files for testLoad; output will generally be different in size and line count
private static final String[] FILES_LOAD_ONLY = new String[] {
"GuiTest_original.jmx",
"GenTest22.jmx",
"GenTest231.jmx",
"GenTest24.jmx",
};
private static final boolean saveOut = JMeterUtils.getPropDefault("testsaveservice.saveout", false);
@Test
public void testPROPVERSION() {
assertEquals(
SaveService.PROPVERSION,
SaveService.getPropertyVersion(),
"Property Version mismatch, ensure you update SaveService#PROPVERSION field with _version property value from saveservice.properties"
);
}
@Test
public void testLoadAndSave() throws Exception {
boolean failed = false; // Did a test fail?
for (final String fileName : FILES) {
final File testFile = findTestFile("testfiles/" + fileName);
final File savedFile = findTestFile("testfiles/Saved" + fileName);
failed |= loadAndSave(testFile, fileName, true, savedFile);
}
for (final String fileName : FILES_LINES) {
final File testFile = findTestFile("testfiles/" + fileName);
final File savedFile = findTestFile("testfiles/Saved" + fileName);
failed |= loadAndSave(testFile, fileName, false, savedFile);
}
if (failed) // TODO make these separate tests?
{
fail("One or more failures detected");
}
}
private boolean loadAndSave(File testFile, String fileName, boolean checkSize, File savedFile) throws Exception {
boolean failed = false;
final FileStats origStats = getFileStats(testFile);
final FileStats savedStats = getFileStats(savedFile);
ByteArrayOutputStream out = new ByteArrayOutputStream(Math.toIntExact(testFile.length()));
try {
HashTree tree = SaveService.loadTree(testFile);
SaveService.saveTree(tree, out);
} finally {
out.close(); // Make sure all the data is flushed out
}
final FileStats compareStats = savedStats == FileStats.NO_STATS ? origStats : savedStats;
final FileStats outputStats;
try (ByteArrayInputStream ins = new ByteArrayInputStream(out.toByteArray());
Reader insReader = new InputStreamReader(ins, Charset.defaultCharset());
BufferedReader bufferedReader = new BufferedReader(insReader)) {
outputStats = computeFileStats(bufferedReader);
}
// We only check the length of the result. Comparing the
// actual result (out.toByteArray==original) will usually
// fail, because the order of the properties within each
// test element may change. Comparing the lengths should be
// enough to detect most problem cases...
if (checkSize && !compareStats.isSameSize(outputStats) || !compareStats.hasSameLinesCount(outputStats)) {
failed = true;
System.out.println();
System.out.println("Loading file testfiles/" + fileName + " and "
+ "saving it back changes its size from " + compareStats.size + " to " + outputStats.size + ".");
if (!origStats.hasSameLinesCount(outputStats)) {
System.out.println("Number of lines changes from " + compareStats.lines + " to " + outputStats.lines);
}
if (saveOut) {
final File outFile = findTestFile("testfiles/" + fileName + ".out");
System.out.println("Write " + outFile);
try (FileOutputStream outf = new FileOutputStream(outFile)) {
outf.write(out.toByteArray());
}
System.out.println("Wrote " + outFile);
}
}
// Note this test will fail if a property is added or
// removed to any of the components used in the test
// files. The way to solve this is to appropriately change
// the test file.
return failed;
}
private FileStats getFileStats(File testFile) throws IOException,
FileNotFoundException {
if (testFile == null || !testFile.exists()) {
return FileStats.NO_STATS;
}
try (FileInputStream fis = new FileInputStream(testFile);
InputStreamReader fileReader = new InputStreamReader(fis, Charset.defaultCharset());
BufferedReader bufferedReader = new BufferedReader(fileReader)) {
return computeFileStats(bufferedReader);
}
}
/**
* Calculate size and line count ignoring EOL and
* "jmeterTestPlan" element which may vary because of
* different attributes/attribute lengths.
*/
private FileStats computeFileStats(BufferedReader br) throws IOException {
int length = 0;
int lines = 0;
String line;
while ((line = br.readLine()) != null) {
lines++;
if (!line.startsWith("<jmeterTestPlan")) {
length += line.length();
}
}
return new FileStats(length, lines);
}
@Test
public void testLoad() throws Exception {
for (String fileName : FILES_LOAD_ONLY) {
File file = findTestFile("testfiles/" + fileName);
try {
HashTree tree = SaveService.loadTree(file);
assertNotNull(tree);
} catch (IllegalArgumentException ex) {
ex.addSuppressed(new Throwable("fileName=" + file.getAbsolutePath()));
throw ex;
}
}
}
@Test
public void testClasses(){
List<String> missingClasses = SaveService.checkClasses();
if (missingClasses.size() > 0) {
fail("One or more classes not found:"+missingClasses);
}
}
private static class FileStats {
int size;
int lines;
final static FileStats NO_STATS = new FileStats(-1, -1);
public FileStats(int size, int lines) {
this.size = size;
this.lines = lines;
}
public boolean isSameSize(FileStats other) {
if (other == null) {
return false;
}
return size == other.size;
}
public boolean hasSameLinesCount(FileStats other) {
if (other == null) {
return false;
}
return lines == other.lines;
}
}
}