Index: src/components/org/apache/jmeter/config/TabularDataSetResources.properties
===================================================================
--- src/components/org/apache/jmeter/config/TabularDataSetResources.properties (revision 0)
+++ src/components/org/apache/jmeter/config/TabularDataSetResources.properties (revision 0)
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ *
+ */
+
+displayName=Tabular Data Set Config
+csv_data.displayName=Configure the Tabular Data
+variableNames.displayName=Variable Names (comma-delimited)
+variableNames.shortDescription=List your variable names in order to match the order of columns in your data. Separate by commas.
+delimiter.displayName=Delimiter (use '\\t' for tab)
+delimiter.shortDescription=Enter the delimiter ('\\t' for tab)
+data.displayName=Data
+data.shortDescription=The Data
Index: src/components/org/apache/jmeter/config/TabularDataSet.java
===================================================================
--- src/components/org/apache/jmeter/config/TabularDataSet.java (revision 0)
+++ src/components/org/apache/jmeter/config/TabularDataSet.java (revision 0)
@@ -0,0 +1,150 @@
+/*
+ * 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.config;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.jmeter.config.ConfigTestElement;
+import org.apache.jmeter.engine.event.LoopIterationEvent;
+import org.apache.jmeter.engine.event.LoopIterationListener;
+import org.apache.jmeter.testbeans.TestBean;
+import org.apache.jorphan.logging.LoggingManager;
+import org.apache.jorphan.util.JOrphanUtils;
+import org.apache.log.Logger;
+
+/**
+ * Use this config element when you want to vary the values of some user defined
+ * variables between iterations, i.e. loops.
+ *
+ * This element reads the Data text (CSV or the like) and splits it into rows
+ * and columns. For each iteration, a new row is read, and its columns are
+ * assigned to the user defined variable with the name of the Variable names.
+ *
+ * The rows are just the rows in the text, and the column are separated by the
+ * defined Delimiter.
+ *
+ * Each column gets the name from the comma separated Variable Names, and the
+ * number of Variable Names must be the same as the number of columns in every
+ * row, or else an exception will be thrown.
+ *
+ * When the last row is reached, it will simply start from the top again.
+ *
+ * The data is not trimmed, hence any whitespace that is not a delimiter will
+ * remain in the variable when used in the test.
+ *
+ */
+public class TabularDataSet extends ConfigTestElement implements TestBean,
+ LoopIterationListener {
+ private static final long serialVersionUID = 232L;
+ private static final Logger log = LoggingManager.getLoggerForClass();
+
+ private transient String variableNames;
+ private transient String delimiter;
+ private transient String data;
+ private transient boolean membersModifiedAndNeedsToBeReparsed = false;
+
+ private transient String[] variableNamesArray;
+ private transient List dataGrid;
+
+ public void iterationStart(LoopIterationEvent iterEvent) {
+ setUpData();
+ int lineNumber = iterEvent.getIteration() % dataGrid.size();
+ String[] row = dataGrid.get(lineNumber);
+ for (int i = 0; i < row.length; i++) {
+ String rowItem = row[i];
+ getThreadContext().getVariables().put(variableNamesArray[i], rowItem);
+ }
+ }
+
+ public String getVariableNames() {
+ return variableNames;
+ }
+
+ public void setVariableNames(String variableNames) {
+ this.variableNames = variableNames;
+ membersModifiedAndNeedsToBeReparsed = true;
+ }
+
+ public String getDelimiter() {
+ return delimiter;
+ }
+
+ public void setDelimiter(String delimiter) {
+ this.delimiter = delimiter;
+ membersModifiedAndNeedsToBeReparsed = true;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String value) {
+ this.data = value;
+ membersModifiedAndNeedsToBeReparsed = true;
+ }
+
+ private void setUpData() {
+ if (!membersModifiedAndNeedsToBeReparsed) {
+ return;
+ }
+
+ try {
+ variableNamesArray = JOrphanUtils.split(variableNames, ",");
+ dataGrid = new ArrayList();
+ BufferedReader bufferedReader = new BufferedReader(
+ new StringReader(data));
+ String row = null;
+ int lineNumber = 1;
+ while ((row = bufferedReader.readLine()) != null) {
+ String[] rowElements = JOrphanUtils.split(row, getActualDelimiter());
+ assertThatDimensionsOfVariableNamesAndRowAreSame(lineNumber, rowElements);
+ dataGrid.add(rowElements);
+ lineNumber++;
+ }
+ membersModifiedAndNeedsToBeReparsed = false;
+ } catch (IOException e) {
+ log.error("Could not parse data", e);
+ }
+ }
+
+ private void assertThatDimensionsOfVariableNamesAndRowAreSame(int line,
+ String[] rowElements) {
+ if (rowElements.length != variableNamesArray.length) {
+ String explicitErrorMessage =
+ "Data on line " + line + " has "
+ + rowElements.length + " columns " + "but require "
+ + variableNamesArray.length + " columns ("
+ + variableNames + ")\n" + "Note that delimiter is "
+ + getDelimiter();
+ throw new RuntimeException(explicitErrorMessage);
+ }
+ }
+
+ private String getActualDelimiter() {
+ if (delimiter.equals("\\t")) {
+ return "\t";
+ }
+ return delimiter;
+ }
+
+}
Index: src/components/org/apache/jmeter/config/TabularDataSetBeanInfo.java
===================================================================
--- src/components/org/apache/jmeter/config/TabularDataSetBeanInfo.java (revision 0)
+++ src/components/org/apache/jmeter/config/TabularDataSetBeanInfo.java (revision 0)
@@ -0,0 +1,55 @@
+/*
+ * 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.config;
+
+import java.beans.PropertyDescriptor;
+
+import org.apache.jmeter.testbeans.BeanInfoSupport;
+import org.apache.jmeter.testbeans.gui.TextAreaEditor;
+
+public class TabularDataSetBeanInfo extends BeanInfoSupport {
+
+ // These names must agree case-wise with the variable and property names
+ private static final String VARIABLE_NAMES = "variableNames"; //$NON-NLS-1$
+ private static final String DELIMITER = "delimiter"; //$NON-NLS-1$
+ private static final String DATA = "data"; //$NON-NLS-1$
+
+ public TabularDataSetBeanInfo() {
+ super(TabularDataSet.class);
+ createPropertyGroup("csv_data", //$NON-NLS-1$
+ new String[] { VARIABLE_NAMES, DELIMITER, DATA });
+
+ PropertyDescriptor p = property(VARIABLE_NAMES);
+ p.setValue(NOT_UNDEFINED, Boolean.TRUE);
+ p.setValue(DEFAULT, ""); //$NON-NLS-1$
+ p.setValue(NOT_EXPRESSION, Boolean.TRUE);
+
+ p = property(DELIMITER);
+ p.setValue(NOT_UNDEFINED, Boolean.TRUE);
+ p.setValue(DEFAULT, ","); //$NON-NLS-1$
+ p.setValue(NOT_EXPRESSION, Boolean.TRUE);
+
+ p = property(DATA);
+ p.setValue(NOT_UNDEFINED, Boolean.TRUE);
+ p.setValue(DEFAULT, ""); //$NON-NLS-1$
+ p.setValue(NOT_EXPRESSION, Boolean.TRUE);
+ p.setPropertyEditorClass(TextAreaEditor.class);
+ }
+
+}
Index: test/src/org/apache/jmeter/config/TestTabularDataSet.java
===================================================================
--- test/src/org/apache/jmeter/config/TestTabularDataSet.java (revision 0)
+++ test/src/org/apache/jmeter/config/TestTabularDataSet.java (revision 0)
@@ -0,0 +1,94 @@
+/*
+ * 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 to test FileServer methods
+ */
+
+package org.apache.jmeter.config;
+
+import org.apache.jmeter.engine.event.LoopIterationEvent;
+import org.apache.jmeter.threads.JMeterContext;
+import org.apache.jmeter.threads.JMeterContextService;
+import org.apache.jmeter.threads.JMeterVariables;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestTabularDataSet {
+
+ private JMeterVariables threadVars;
+ private TabularDataSet tabularDataSet;
+
+ @Before
+ public void setUp(){
+ JMeterContext jmcx = JMeterContextService.getContext();
+ jmcx.setVariables(new JMeterVariables());
+ threadVars = jmcx.getVariables();
+
+ tabularDataSet = new TabularDataSet();
+ tabularDataSet.setThreadContext(jmcx);
+ tabularDataSet.setData("1:1,1:2,1:3\n2:1,2:2,2:3");
+ tabularDataSet.setDelimiter(",");
+ tabularDataSet.setVariableNames("col1,col2,col3");
+ }
+
+ @Test
+ public void testGetFirstRow() throws Exception {
+ tabularDataSet.iterationStart(new LoopIterationEvent(tabularDataSet, 0));
+ assertCol("col1", "1:1");
+ assertCol("col2", "1:2");
+ assertCol("col3", "1:3");
+ }
+
+ @Test
+ public void testGetSecondRow() throws Exception {
+ tabularDataSet.iterationStart(new LoopIterationEvent(tabularDataSet, 1));
+ assertCol("col1", "2:1");
+ assertCol("col2", "2:2");
+ assertCol("col3", "2:3");
+ }
+
+ @Test
+ public void testStartFromBeginning() throws Exception {
+ tabularDataSet.iterationStart(new LoopIterationEvent(tabularDataSet, 2));
+ assertCol("col1", "1:1");
+ assertCol("col2", "1:2");
+ assertCol("col3", "1:3");
+ }
+
+ @Test
+ public void testChangedDataResultsInReparsing() throws Exception {
+ tabularDataSet.setData("1:1 new,1:2 new,1:3 new\n2:1 new,2:2 new,2:3 new");
+ tabularDataSet.iterationStart(new LoopIterationEvent(tabularDataSet, 2));
+ assertCol("col1", "1:1 new");
+ assertCol("col2", "1:2 new");
+ assertCol("col3", "1:3 new");
+ }
+
+ @Test(expected=RuntimeException.class)
+ public void testThrowsExceptionWhenVariableNamesAndColumnWidthMismatches() throws Exception {
+ tabularDataSet.setVariableNames("just one");
+ tabularDataSet.iterationStart(new LoopIterationEvent(tabularDataSet, 2));
+ }
+
+
+ private void assertCol(String columnName, String expected) {
+ Assert.assertEquals(expected, threadVars.get(columnName));
+ }
+}