diff --git a/pom.xml b/pom.xml index 6a07d39c2..e8db60ec6 100644 --- a/pom.xml +++ b/pom.xml @@ -161,6 +161,12 @@ qpid-client 0.20 + + org.mockito + mockito-all + 1.9.5 + test + @@ -319,6 +325,15 @@ + + org.apache.maven.plugins + maven-surefire-plugin + 2.14.1 + + + -Xmx784m + + diff --git a/src/kg/apc/jmeter/config/TestCsvFileAction.java b/src/kg/apc/jmeter/config/TestCsvFileAction.java index 9a2969405..d7732b8f9 100644 --- a/src/kg/apc/jmeter/config/TestCsvFileAction.java +++ b/src/kg/apc/jmeter/config/TestCsvFileAction.java @@ -3,74 +3,66 @@ import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.io.File; import java.util.Iterator; import java.util.Map; import javax.swing.JTextArea; -import javax.swing.JTextField; public class TestCsvFileAction implements ActionListener { - private final JTextField filename; - private final JTextField prefix; - private final JTextField separator; - private final JTextArea infoArea; + private final VariablesFromCSVGui variablesCsvUi; - public TestCsvFileAction(JTextField fileName, JTextField prefix, JTextField separator, JTextArea infoArea) { - this.filename = fileName; - this.prefix = prefix; - this.separator = separator; - this.infoArea = infoArea; + public TestCsvFileAction(VariablesFromCSVGui variablesCsvUi) { + this.variablesCsvUi = variablesCsvUi; } @Override public void actionPerformed(ActionEvent e) { + JTextArea infoArea = variablesCsvUi.getCheckInfoTextArea(); infoArea.setText(""); infoArea.setForeground(Color.black); + VariablesFromCSV testElem = (VariablesFromCSV)variablesCsvUi.createTestElement(); + boolean noValues = true; String msgVars = ""; int count = 0; - File f = new File(filename.getText()); - if (!f.exists()) { - reportError("File '" + filename.getText() + "' was not found..."); - return; - } else { - try { - VariableFromCsvFileReader reader = new VariableFromCsvFileReader(filename.getText()); - Map vars = reader.getDataAsMap(prefix.getText(), separator.getText()); - Iterator iter = vars.keySet().iterator(); - while (iter.hasNext()) { - String var = iter.next(); - String value = vars.get(var); - if (!"".equals(value)) { - noValues = false; - } - msgVars = msgVars + "${" + var + "} = " + vars.get(var) + "\n"; - count++; + try { + Map vars = testElem.getArgumentsAsMap(); + Iterator iter = vars.keySet().iterator(); + + while (iter.hasNext()) { + String var = iter.next(); + String value = vars.get(var); + if (!"".equals(value)) { + noValues = false; } - } catch (Exception ex) { - reportError("Error processing file: " + ex.toString()); + msgVars = msgVars + "${" + var + "} = " + vars.get(var) + "\n"; + count++; } - } - if (count == 0) { - reportError("File parsed, but no variable found."); - } else if (noValues) { - reportOk("WARNING: File parsed, " + count + " variable" + (count > 1 ? "s" : "") + " found, but no variable have value!"); - reportOk(msgVars); - } else { - reportOk("File successfuly parsed, " + count + " variable" + (count > 1 ? "s" : "") + " found:"); - reportOk(msgVars); + + if (count == 0) { + reportError("File parsed, but no variable found."); + } else if (noValues) { + reportOk("WARNING: File parsed, " + count + " variable" + (count > 1 ? "s" : "") + " found, but no variable have value!"); + reportOk(msgVars); + } else { + reportOk("File successfuly parsed, " + count + " variable" + (count > 1 ? "s" : "") + " found:"); + reportOk(msgVars); + } + } catch (Exception ex) { + reportError("Error processing file: " + ex.toString()); } } private void reportError(String msg) { + JTextArea infoArea = variablesCsvUi.getCheckInfoTextArea(); infoArea.setText(infoArea.getText() + "Problem detected: " + msg + "\n"); infoArea.setForeground(Color.red); } private void reportOk(String string) { + JTextArea infoArea = variablesCsvUi.getCheckInfoTextArea(); infoArea.setText(infoArea.getText() + string + "\n"); } } diff --git a/src/kg/apc/jmeter/config/VariableFromCsvFileReader.java b/src/kg/apc/jmeter/config/VariableFromCsvFileReader.java index 42e059ba1..ac30bf240 100644 --- a/src/kg/apc/jmeter/config/VariableFromCsvFileReader.java +++ b/src/kg/apc/jmeter/config/VariableFromCsvFileReader.java @@ -1,7 +1,6 @@ package kg.apc.jmeter.config; import java.io.BufferedReader; -import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; @@ -18,46 +17,81 @@ public class VariableFromCsvFileReader { private static final Logger log = LoggingManager.getLoggerForClass(); - private File file; + private BufferedReader input; + /** + * Initialize a new CSV reader for the named file. + * + * @param csvFileName name of the CSV input file + */ public VariableFromCsvFileReader(String csvFileName) { - file = new File(csvFileName); + try { + input = new BufferedReader(new FileReader(csvFileName)); + } catch (FileNotFoundException ex) { + log.error("File not found: " + ex.getMessage()); + } + } + + /** + * Initialize a new CSV reader with a BufferedReader as input. + * + * @param input the CSV input + */ + public VariableFromCsvFileReader(BufferedReader input) { + this.input = input; } + /** + * Parses (name, value) pairs from the input and returns the result as a Map. The name is taken from the first column and + * value from the second column. If an input line contains only one column its value is defaulted to an empty string. + * Any extra columns are ignored. + * + * @param prefix a prefix to apply to the mapped variable names + * @param separator the field delimiter + * @return a map of (name, value) pairs + */ public Map getDataAsMap(String prefix, String separator) { + return getDataAsMap(prefix, separator, 0); + } + + /** + * Parses (name, value) pairs from the input and returns the result as a Map, with the option to skip the first line. + * The name is taken from the first column and value from the second column. If an input line contains only one + * column its value is defaulted to an empty string. Any extra columns are ignored. + * + * If the input contains headers, call with skipLines equal to the number of lines of headers. + * + * @param prefix a prefix to apply to the mapped variable names + * @param separator the field delimiter + * @param skipLines the number of lines at the beginning of the input to skip + * @return a map of (name, value) pairs + */ + public Map getDataAsMap(String prefix, String separator, int skipLines) { if (separator.isEmpty()) { throw new IllegalArgumentException("CSV separator cannot be empty"); } - HashMap ret = new HashMap(); - if (file.exists()) { + Map variables = new HashMap(); + if (input != null) { try { - BufferedReader reader = new BufferedReader(new FileReader(file)); - String line = reader.readLine(); - while (line != null) { - String[] lineValues = JOrphanUtils.split(line, separator, false); + String line; + int lineNum = 0; + while ((line = input.readLine()) != null) { + if (++lineNum > skipLines) { + String[] lineValues = JOrphanUtils.split(line, separator, false); - switch (lineValues.length) { - case 1: + if (lineValues.length == 1) { log.warn("Less than 2 columns at line: " + line); - ret.put(prefix + lineValues[0], ""); - break; - case 2: - ret.put(prefix + lineValues[0], lineValues[1]); - break; - default: - log.warn("Bad format for line: " + line); - break; + variables.put(prefix + lineValues[0], ""); + } else if (lineValues.length >= 2) { + variables.put(prefix + lineValues[0], lineValues[1]); + } } - - line = reader.readLine(); } - } catch (FileNotFoundException ex) { - log.error("File not found: " + ex.getMessage()); } catch (IOException ex) { log.error("Error while reading: " + ex.getMessage()); } } - return ret; + return variables; } } diff --git a/src/kg/apc/jmeter/config/VariablesFromCSV.java b/src/kg/apc/jmeter/config/VariablesFromCSV.java index b881d79a8..a5228a864 100644 --- a/src/kg/apc/jmeter/config/VariablesFromCSV.java +++ b/src/kg/apc/jmeter/config/VariablesFromCSV.java @@ -12,12 +12,13 @@ public class VariablesFromCSV extends Arguments{ public static final String VARIABLE_PREFIX = "variablesPrefix"; public static final String FILENAME = "filename"; public static final String SEPARATOR = "delimiter"; + public static final String SKIP_LINES = "skipLines"; public static final String STORE_SYS_PROP = "storeSysProp"; - //It seems org.apache.jmeter.engine.Precompiler requires only this method + //It seems org.apache.jmeter.engine.Precompiler requires only thishttps://groups.google.com/forum/#!topic/jmeter-plugins/gWn7MTgvTfE method @Override public Map getArgumentsAsMap() { - Map variables = new VariableFromCsvFileReader(getFileName()).getDataAsMap(getVariablePrefix(), getSeparator()); + Map variables = new VariableFromCsvFileReader(getFileName()).getDataAsMap(getVariablePrefix(), getSeparator(), getSkipLines()); //store in System Properties also if(isStoreAsSystemProperty()) { Iterator iter = variables.keySet().iterator(); @@ -56,6 +57,14 @@ public void setSeparator(String separator) { setProperty(SEPARATOR, separator); } + public int getSkipLines() { + return getPropertyAsInt(SKIP_LINES, 0); + } + + public void setSkipLines(int skipLines) { + setProperty(SKIP_LINES, skipLines); + } + public boolean isStoreAsSystemProperty() { return getPropertyAsBoolean(STORE_SYS_PROP); } diff --git a/src/kg/apc/jmeter/config/VariablesFromCSVGui.java b/src/kg/apc/jmeter/config/VariablesFromCSVGui.java index 4680db62c..0e76f99c9 100644 --- a/src/kg/apc/jmeter/config/VariablesFromCSVGui.java +++ b/src/kg/apc/jmeter/config/VariablesFromCSVGui.java @@ -27,6 +27,7 @@ public class VariablesFromCSVGui extends AbstractConfigGui { private JTextField fileName; private JTextField variablePrefix; private JTextField separator; + private JTextField skipLines; private JCheckBox storeSysProp; private JButton browseButton; @@ -55,6 +56,7 @@ public void configure(TestElement element) { fileName.setText(element.getPropertyAsString(VariablesFromCSV.FILENAME)); variablePrefix.setText(element.getPropertyAsString(VariablesFromCSV.VARIABLE_PREFIX)); separator.setText(element.getPropertyAsString(VariablesFromCSV.SEPARATOR)); + skipLines.setText(element.getPropertyAsString(VariablesFromCSV.SKIP_LINES)); storeSysProp.setSelected(element.getPropertyAsBoolean(VariablesFromCSV.STORE_SYS_PROP)); } @@ -74,6 +76,7 @@ public void modifyTestElement(TestElement te) { varsCsv.setFileName(fileName.getText()); varsCsv.setVariablePrefix(variablePrefix.getText()); varsCsv.setSeparator(separator.getText()); + varsCsv.setSkipLines(Integer.parseInt(skipLines.getText())); varsCsv.setStoreAsSystemProperty(storeSysProp.isSelected()); } } @@ -117,19 +120,22 @@ private void init() { addToPanel(mainPanel, labelConstraints, 0, 2, new JLabel("Separator (use '\\t' for tab): ", JLabel.RIGHT)); addToPanel(mainPanel, editConstraints, 1, 2, separator = new JTextField(20)); - addToPanel(mainPanel, labelConstraints, 0, 3, new JLabel("Store variables also in System Properties: ", JLabel.RIGHT)); - addToPanel(mainPanel, editConstraints, 1, 3, storeSysProp = new JCheckBox()); + addToPanel(mainPanel, labelConstraints, 0, 3, new JLabel("Skip initial lines: ", JLabel.RIGHT)); + addToPanel(mainPanel, editConstraints, 1, 3, skipLines = new JTextField(20)); + + addToPanel(mainPanel, labelConstraints, 0, 4, new JLabel("Store variables also in System Properties: ", JLabel.RIGHT)); + addToPanel(mainPanel, editConstraints, 1, 4, storeSysProp = new JCheckBox()); editConstraints.insets = new java.awt.Insets(4, 0, 0, 0); labelConstraints.insets = new java.awt.Insets(4, 0, 0, 2); - addToPanel(mainPanel, labelConstraints, 0, 4, checkButton = new JButton("Test CSV File")); + addToPanel(mainPanel, labelConstraints, 0, 5, checkButton = new JButton("Test CSV File")); labelConstraints.insets = new java.awt.Insets(4, 0, 0, 0); checkInfo = new JTextArea(); - addToPanel(mainPanel, editConstraints, 1, 4, GuiBuilderHelper.getTextAreaScrollPaneContainer(checkInfo, 10)); - checkButton.addActionListener(new TestCsvFileAction(fileName, variablePrefix, separator, checkInfo)); + addToPanel(mainPanel, editConstraints, 1, 5, GuiBuilderHelper.getTextAreaScrollPaneContainer(checkInfo, 10)); + checkButton.addActionListener(new TestCsvFileAction(this)); checkInfo.setEditable(false); checkInfo.setOpaque(false); @@ -138,6 +144,10 @@ private void init() { add(container, BorderLayout.CENTER); } + public JTextArea getCheckInfoTextArea() { + return checkInfo; + } + private void addToPanel(JPanel panel, GridBagConstraints constraints, int col, int row, JComponent component) { constraints.gridx = col; constraints.gridy = row; @@ -149,6 +159,7 @@ private void initFields() { fileName.setText(""); checkInfo.setText(""); separator.setText(";"); + skipLines.setText("0"); storeSysProp.setSelected(false); } } diff --git a/test/kg/apc/jmeter/config/TestCsvFileActionTest.java b/test/kg/apc/jmeter/config/TestCsvFileActionTest.java index c4c719a7d..ce56e0e31 100644 --- a/test/kg/apc/jmeter/config/TestCsvFileActionTest.java +++ b/test/kg/apc/jmeter/config/TestCsvFileActionTest.java @@ -3,11 +3,10 @@ import javax.swing.JTextArea; import javax.swing.JTextField; import java.awt.event.ActionEvent; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; + +import static org.mockito.Mockito.*; +import org.junit.*; + import static org.junit.Assert.*; /** @@ -43,34 +42,49 @@ public void tearDown() { */ @Test public void testActionPerformed() { - System.out.println("actionPerformed"); - JTextField file = new JTextField(fileName); - JTextField prefix = new JTextField(""); - JTextField separator = new JTextField(","); + VariablesFromCSV csvVarsTestElem = new VariablesFromCSV(); + csvVarsTestElem.setFileName(fileName); + csvVarsTestElem.setVariablePrefix(""); + csvVarsTestElem.setSeparator(","); + csvVarsTestElem.setSkipLines(0); + JTextArea infoArea = new JTextArea(); + + VariablesFromCSVGui ui = mock(VariablesFromCSVGui.class); + when(ui.createTestElement()).thenReturn(csvVarsTestElem); + when(ui.getCheckInfoTextArea()).thenReturn(infoArea); + + TestCsvFileAction instance = new TestCsvFileAction(ui); ActionEvent e = null; - TestCsvFileAction instance = new TestCsvFileAction(file, prefix, separator, infoArea); instance.actionPerformed(e); + assertTrue(infoArea.getText().startsWith("File successfuly parsed, 2")); - file.setText(fileName + ".notFound"); - instance.actionPerformed(e); - assertTrue(infoArea.getText().startsWith("Problem detected:")); } /** - * @see https://groups.google.com/forum/#!topic/jmeter-plugins/gWn7MTgvTfE + * Verify that exceptions are reported when test action is performed. + * + * see https://groups.google.com/forum/#!topic/jmeter-plugins/gWn7MTgvTfE */ @Test - public void testActionPerformed_eternal_loop() { - System.out.println("actionPerformed"); - String fileName1 = TestCsvFileActionTest.class.getResource("CSVSample_user.csv").getPath(); - JTextField file = new JTextField(fileName1); - JTextField prefix = new JTextField(""); - JTextField separator = new JTextField(""); + public void testActionPerformed_exception() { + String fileName = TestCsvFileActionTest.class.getResource("CSVSample_user.csv").getPath(); + VariablesFromCSV csvVarsTestElem = new VariablesFromCSV(); + csvVarsTestElem.setFileName(fileName); + csvVarsTestElem.setVariablePrefix(""); + csvVarsTestElem.setSeparator(""); + csvVarsTestElem.setSkipLines(0); + JTextArea infoArea = new JTextArea(); + + VariablesFromCSVGui ui = mock(VariablesFromCSVGui.class); + when(ui.createTestElement()).thenReturn(csvVarsTestElem); + when(ui.getCheckInfoTextArea()).thenReturn(infoArea); + + TestCsvFileAction instance = new TestCsvFileAction(ui); ActionEvent e = null; - TestCsvFileAction instance = new TestCsvFileAction(file, prefix, separator, infoArea); instance.actionPerformed(e); + assertTrue(infoArea.getText().startsWith("Problem detected:")); } } \ No newline at end of file diff --git a/test/kg/apc/jmeter/config/VariableFromCsvFileReaderTest.java b/test/kg/apc/jmeter/config/VariableFromCsvFileReaderTest.java index a5754bc05..bd38b80bf 100644 --- a/test/kg/apc/jmeter/config/VariableFromCsvFileReaderTest.java +++ b/test/kg/apc/jmeter/config/VariableFromCsvFileReaderTest.java @@ -1,15 +1,18 @@ package kg.apc.jmeter.config; +import java.io.BufferedReader; +import java.io.StringReader; import java.util.Map; + import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; + import static org.junit.Assert.*; /** - * * @author Stephane Hoblingre */ public class VariableFromCsvFileReaderTest { @@ -17,16 +20,16 @@ public class VariableFromCsvFileReaderTest { private final String fileName; public VariableFromCsvFileReaderTest() { - fileName = TestCsvFileActionTest.class.getResource("csvFileTest.csv").getPath(); + fileName = TestCsvFileActionTest.class.getResource("csvFileTest.csv").getPath(); } - @BeforeClass - public static void setUpClass() throws Exception { - } + @BeforeClass + public static void setUpClass() throws Exception { + } - @AfterClass - public static void tearDownClass() throws Exception { - } + @AfterClass + public static void tearDownClass() throws Exception { + } @Before public void setUp() { @@ -36,17 +39,136 @@ public void setUp() { public void tearDown() { } - /** - * Test of getDataAsMap method, of class VariableFromCsvFileReader. - */ - @Test - public void testGetDataAsMap() { - System.out.println("getDataAsMap"); - String prefix = ""; - String separator = ","; - VariableFromCsvFileReader instance = new VariableFromCsvFileReader(fileName); - Map result = instance.getDataAsMap(prefix, separator); - assertTrue(result.size() == 2); - } + /** + * Test of getDataAsMap method, of class VariableFromCsvFileReader. + */ + @Test + public void testGetDataAsMap() { + System.out.println("getDataAsMap"); + String prefix = ""; + String separator = ","; + VariableFromCsvFileReader instance = new VariableFromCsvFileReader(fileName); + Map result = instance.getDataAsMap(prefix, separator); + assertTrue(result.size() == 2); + } + + /** + * Test getDataAsMap() using a BufferedReader as input instead of a file. + */ + @Test + public void testBufferedReaderInput() { + String prefix = ""; + String separator = ","; + String csvData = "var0,val0\nvar1,val1"; + BufferedReader input = new BufferedReader(new StringReader(csvData)); + VariableFromCsvFileReader instance = new VariableFromCsvFileReader(input); + + Map variables = instance.getDataAsMap(prefix, separator); + + assertEquals("incorrect value for var0", "val0", variables.get("var0")); + assertEquals("incorrect value for var1", "val1", variables.get("var1")); + } + + /** + * Test getDataAsMap() for input with more than two columns. + */ + @Test + public void testExtraColumnsInput() { + String prefix = ""; + String separator = ","; + String csvData = "var0,val0,a comment\nvar1,val1"; + BufferedReader input = new BufferedReader(new StringReader(csvData)); + VariableFromCsvFileReader instance = new VariableFromCsvFileReader(input); + + Map variables = instance.getDataAsMap(prefix, separator); + + assertEquals("incorrect value for var0", "val0", variables.get("var0")); + assertEquals("incorrect value for var1", "val1", variables.get("var1")); + } + + /** + * Test getDataAsMap() with input that contains blank lines. + */ + @Test + public void testBlankLineInput() { + String prefix = ""; + String separator = ","; + String csvData = "var0,val0\n\nvar1,val1\n"; + BufferedReader input = new BufferedReader(new StringReader(csvData)); + VariableFromCsvFileReader instance = new VariableFromCsvFileReader(input); + Map variables = instance.getDataAsMap(prefix, separator); + + assertEquals("incorrect number of variables parsed from input", 2, variables.size()); + assertEquals("incorrect value for var0", "val0", variables.get("var0")); + assertEquals("incorrect value for var1", "val1", variables.get("var1")); + } + + /** + * Tests getDataAsMap() with input that contains only a single column. + */ + @Test + public void testSingleColumn() { + String prefix = ""; + String separator = ","; + String csvData = "var0\n\nvar1,val1\n"; + BufferedReader input = new BufferedReader(new StringReader(csvData)); + VariableFromCsvFileReader instance = new VariableFromCsvFileReader(input); + + Map variables = instance.getDataAsMap(prefix, separator); + + assertEquals("incorrect value for var0", "", variables.get("var0")); + assertEquals("incorrect value for var1", "val1", variables.get("var1")); + } + + /** + * Test getDataAsMap() with a non-blank variable prefix. + */ + @Test + public void testVariablePrefix() { + String prefix = "test"; + String separator = ","; + String csvData = "var0,val0,a comment\nvar1,val1"; + BufferedReader input = new BufferedReader(new StringReader(csvData)); + VariableFromCsvFileReader instance = new VariableFromCsvFileReader(input); + + Map variables = instance.getDataAsMap(prefix, separator); + + assertEquals("incorrect value for testvar0", "val0", variables.get("testvar0")); + assertEquals("incorrect value for testvar1", "val1", variables.get("testvar1")); + assertNull("var0 should not be mapped", variables.get("var0")); + assertNull("var1 should not be mapped", variables.get("var1")); + } + + /** + * Test getDataAsMap() skipping the first input line which is a header. + */ + @Test + public void testSkipHeaderLine() { + String prefix = ""; + String separator = ","; + String csvData = "name,value,description\nvar0,val0,a comment\nvar1,val1"; + BufferedReader input = new BufferedReader(new StringReader(csvData)); + VariableFromCsvFileReader instance = new VariableFromCsvFileReader(input); + + Map variables = instance.getDataAsMap(prefix, separator, 1); + + assertNull("header line was interpreted as variable data", variables.get("name")); + assertEquals("incorrect value for var0", "val0", variables.get("var0")); + assertEquals("incorrect value for var1", "val1", variables.get("var1")); + } + + /** + * Test getDataAsMap() with empty separator. see https://groups.google.com/forum/#!topic/jmeter-plugins/gWn7MTgvTfE + */ + @Test(expected=IllegalArgumentException.class) + public void testEmptySeparator() { + String prefix = ""; + String separator = ""; + String csvData = "name,value,description\nvar0,val0,a comment\nvar1,val1"; + BufferedReader input = new BufferedReader(new StringReader(csvData)); + VariableFromCsvFileReader instance = new VariableFromCsvFileReader(input); + + Map variables = instance.getDataAsMap(prefix, separator, 1); + } } \ No newline at end of file