Author: sebb
Date: Tue Feb  3 01:33:53 2009
New Revision: 740183

URL: http://svn.apache.org/viewvc?rev=740183&view=rev
Log:
Bug 46491 - Incorrect value for the last variable in "CSV Data Set Config" 
(error in processing quoted strings)

Added:
    
jakarta/jmeter/trunk/test/src/org/apache/jmeter/save/TestCSVSaveService.java   
(with props)
Modified:
    jakarta/jmeter/trunk/src/core/org/apache/jmeter/save/CSVSaveService.java
    jakarta/jmeter/trunk/xdocs/changes.xml

Modified: 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/save/CSVSaveService.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/save/CSVSaveService.java?rev=740183&r1=740182&r2=740183&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/core/org/apache/jmeter/save/CSVSaveService.java 
(original)
+++ jakarta/jmeter/trunk/src/core/org/apache/jmeter/save/CSVSaveService.java 
Tue Feb  3 01:33:53 2009
@@ -58,6 +58,7 @@
 /**
  * This class provides a means for saving/reading test results as CSV files.
  */
+// For unit tests, @see TestCSVSaveService
 public final class CSVSaveService {
     private static final Logger log = LoggingManager.getLoggerForClass();
 
@@ -137,7 +138,11 @@
                 lineNumber = 0;
             }
             String [] parts;
-            while ((parts = csvReadFile(dataReader, 
saveConfig.getDelimiter().charAt(0))).length != 0) {
+            final char delim = saveConfig.getDelimiter().charAt(0);
+            // TODO: does it matter that an empty line will terminate the loop?
+            // CSV output files should never contain empty lines, so probably 
not
+            // If so, then need to check whether the reader is at EOF
+            while ((parts = csvReadFile(dataReader, delim)).length != 0) {
                 lineNumber++;
                 SampleEvent event = 
CSVSaveService.makeResultFromDelimitedString(parts,saveConfig,lineNumber);
                 if (event != null){
@@ -208,6 +213,8 @@
                         timeStamp = Long.parseLong(text);
                     } catch (NumberFormatException e) {// see if this works
                         log.warn(e.toString());
+                        // method is only ever called from one thread at a time
+                        // so it's OK to use a static DateFormat
                         Date stamp = DEFAULT_DATE_FORMAT.parse(text);
                         timeStamp = stamp.getTime();
                         log.warn("Setting date format to: 
"+DEFAULT_DATE_FORMAT_STRING);
@@ -911,9 +918,11 @@
     /**
      * Reads from file and splits input into strings according to the 
delimiter,
      * taking note of quoted strings.
-     *
+     * <p>
      * Handles DOS (CRLF), Unix (LF), and Mac (CR) line-endings equally.
-     *
+     * <p>
+     * N.B. a blank line is returned as a zero length array, whereas "" is 
returned
+     * as an empty string. This is inconsistent.
      * @param infile input file  - must support mark(1)
      * @param delim delimiter (e.g. comma)
      * @return array of strings
@@ -924,8 +933,9 @@
         int state = INITIAL;
         List list = new ArrayList();
         ByteArrayOutputStream baos = new ByteArrayOutputStream(200);
+        boolean push = false;
         while(-1 != (ch=infile.read())){
-            boolean push = false;
+            push = false;
             switch(state){
             case INITIAL:
                 if (ch == QUOTING_CHAR){
@@ -983,15 +993,19 @@
                 break;
             }
         } // while not EOF
-        if (ch == -1){
+        if (ch == -1){// EOF (or end of string) so collect any remaining data
             if (state == QUOTED){
                 throw new IOException(state+" Missing trailing quote-char in 
quoted field:[\""+baos.toString()+"]");
             }
-            if (baos.size() > 0) {
+            // Do we have some data, or a trailing empty field?
+            if (baos.size() > 0 // we have some data
+                    || push     // we've started a field
+                    || state == EMBEDDEDQUOTE // Just seen ""
+                ) {
                 list.add(baos.toString());
             }
         }
-        return (String[]) list.toArray(new String[]{});
+        return (String[]) list.toArray(new String[list.size()]);
     }
 
     private static boolean isDelimOrEOL(char delim, int ch) {

Added: 
jakarta/jmeter/trunk/test/src/org/apache/jmeter/save/TestCSVSaveService.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/test/src/org/apache/jmeter/save/TestCSVSaveService.java?rev=740183&view=auto
==============================================================================
--- 
jakarta/jmeter/trunk/test/src/org/apache/jmeter/save/TestCSVSaveService.java 
(added)
+++ 
jakarta/jmeter/trunk/test/src/org/apache/jmeter/save/TestCSVSaveService.java 
Tue Feb  3 01:33:53 2009
@@ -0,0 +1,103 @@
+/*
+ * 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 java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.apache.jmeter.junit.JMeterTestCase;
+
+public class TestCSVSaveService extends JMeterTestCase {
+
+       public TestCSVSaveService(String name) {
+               super(name);
+       }
+       
+       private void checkSplitString(String input, char delim, String 
[]expected) throws Exception {
+        String out[] = CSVSaveService.csvSplitString(input, delim);        
+        checkStrings(expected, out);
+       }
+
+    private void checkStrings(String[] expected, String[] out) {
+        assertEquals("Incorrect number of strings returned",expected.length, 
out.length);
+        for(int i = 0; i < out.length; i++){
+           assertEquals("Incorrect entry returned",expected[i], out[i]);
+        }
+    }
+       
+       // This is what JOrphanUtils.split() does
+       public void testSplitEmpty() throws Exception {
+        checkSplitString("",         ',', new String[]{});    
+       }
+       
+       // These tests should agree with those for JOrphanUtils.split() as far 
as possible
+       
+       public void testSplitUnquoted() throws Exception {
+        checkSplitString("a",         ',', new String[]{"a"});
+        checkSplitString("a,bc,d,e", ',', new String[]{"a","bc","d","e"});
+        checkSplitString(",bc,d,e",  ',', new String[]{"","bc","d","e"});
+        checkSplitString("a,,d,e",   ',', new String[]{"a","","d","e"});
+        checkSplitString("a,bc, ,e", ',', new String[]{"a","bc"," ","e"});
+        checkSplitString("a,bc,d, ", ',', new String[]{"a","bc","d"," "});
+        checkSplitString("a,bc,d,",  ',', new String[]{"a","bc","d",""});
+        checkSplitString("a,bc,,",   ',', new String[]{"a","bc","",""});
+        checkSplitString("a,,,",     ',', new String[]{"a","","",""});
+        checkSplitString("a,bc,d,\n",',', new String[]{"a","bc","d",""});
+    }
+
+    public void testSplitQuoted() throws Exception {
+        checkSplitString("a,bc,d,e",     ',', new String[]{"a","bc","d","e"});
+        checkSplitString(",bc,d,e",      ',', new String[]{"","bc","d","e"});
+        checkSplitString("\"\",bc,d,e",  ',', new String[]{"","bc","d","e"});
+        checkSplitString("a,,d,e",       ',', new String[]{"a","","d","e"});
+        checkSplitString("a,\"\",d,e",   ',', new String[]{"a","","d","e"});
+        checkSplitString("a,bc, ,e",     ',', new String[]{"a","bc"," ","e"});
+        checkSplitString("a,bc,\" \",e", ',', new String[]{"a","bc"," ","e"});
+        checkSplitString("a,bc,d, ",     ',', new String[]{"a","bc","d"," "});
+        checkSplitString("a,bc,d,\" \"", ',', new String[]{"a","bc","d"," "});
+        checkSplitString("a,bc,d,",      ',', new String[]{"a","bc","d",""});
+        checkSplitString("a,bc,d,\"\"",  ',', new String[]{"a","bc","d",""});
+        checkSplitString("a,bc,d,\"\"\n",',', new String[]{"a","bc","d",""});
+    }
+
+    public void testSplitBadQuote() throws Exception {
+        try {
+            checkSplitString("a\"b",',',null);
+            fail("Should have generated IOException");
+        } catch (IOException e) {
+        }
+    }
+    
+    public void testSplitMultiLine() throws Exception  {
+        String line="a,,\"c\nd\",e\n,,f,g,";
+        String[] out;
+        BufferedReader br = new BufferedReader(new StringReader(line));
+        out = CSVSaveService.csvReadFile(br, ',');
+        checkStrings(new String[]{"a","","c\nd","e"}, out);
+        out = CSVSaveService.csvReadFile(br, ',');
+        checkStrings(new String[]{"","","f","g",""}, out);
+        assertEquals("Expected to be at EOF",-1,br.read());
+        // Empty strings at EOF
+        out = CSVSaveService.csvReadFile(br, ',');
+        checkStrings(new String[]{}, out);
+        out = CSVSaveService.csvReadFile(br, ',');
+        checkStrings(new String[]{}, out);
+    }
+}

Propchange: 
jakarta/jmeter/trunk/test/src/org/apache/jmeter/save/TestCSVSaveService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
jakarta/jmeter/trunk/test/src/org/apache/jmeter/save/TestCSVSaveService.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: jakarta/jmeter/trunk/xdocs/changes.xml
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/changes.xml?rev=740183&r1=740182&r2=740183&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/changes.xml (original)
+++ jakarta/jmeter/trunk/xdocs/changes.xml Tue Feb  3 01:33:53 2009
@@ -185,6 +185,7 @@
 <li>Fix potential thread safety issue in JMeterThread class</li>
 <li>Mailer Visualiser - fix parsing of multiple e-mail address when using Test 
button</li>
 <li>Bug 46435 - More verbose error msg for error 501 (Proxy Server)</li>
+<li>Bug 46491 - Incorrect value for the last variable in "CSV Data Set Config" 
(error in processing quoted strings)</li>
 </ul>
 
 <h3>Improvements</h3>



---------------------------------------------------------------------
To unsubscribe, e-mail: jmeter-dev-unsubscr...@jakarta.apache.org
For additional commands, e-mail: jmeter-dev-h...@jakarta.apache.org

Reply via email to