package au.com.bytecode.opencsv; /** * Created by IntelliJ IDEA. * User: Scott Conway * Date: Oct 7, 2009 * Time: 9:56:48 PM */ import org.junit.Before; import org.junit.Test; import java.io.IOException; import static org.junit.Assert.*; public class CSVParserTest { CSVParser csvParser; @Before public void setUp() { csvParser = new CSVParser(); } @Test public void testParseLine() throws Exception { String nextItem[] = csvParser.parseLine("This, is, a, test."); assertEquals(4, nextItem.length); assertEquals("This", nextItem[0]); assertEquals(" is", nextItem[1]); assertEquals(" a", nextItem[2]); assertEquals(" test.", nextItem[3]); } @Test public void parseSimpleString() throws IOException { String[] nextLine = csvParser.parseLine("a,b,c"); assertEquals(3, nextLine.length); assertEquals("a", nextLine[0]); assertEquals("b", nextLine[1]); assertEquals("c", nextLine[2]); assertFalse(csvParser.isPending()); } /** * Tests quotes in the middle of an element. * * @throws IOException if bad things happen */ @Test public void testParsedLineWithInternalQuota() throws IOException { String[] nextLine = csvParser.parseLine("a,123\"4\"567,c"); assertEquals(3, nextLine.length); assertEquals("123\"4\"567", nextLine[1]); } @Test public void parseQuotedStringWithCommas() throws IOException { String[] nextLine = csvParser.parseLine("a,\"b,b,b\",c"); assertEquals("a", nextLine[0]); assertEquals("b,b,b", nextLine[1]); assertEquals("c", nextLine[2]); assertEquals(3, nextLine.length); } @Test public void parseQuotedStringWithDefinedSeperator() throws IOException { csvParser = new CSVParser(':'); String[] nextLine = csvParser.parseLine("a:\"b:b:b\":c"); assertEquals("a", nextLine[0]); assertEquals("b:b:b", nextLine[1]); assertEquals("c", nextLine[2]); assertEquals(3, nextLine.length); } @Test public void parseQuotedStringWithDefinedSeperatorAndQuote() throws IOException { csvParser = new CSVParser(':', '\''); String[] nextLine = csvParser.parseLine("a:'b:b:b':c"); assertEquals("a", nextLine[0]); assertEquals("b:b:b", nextLine[1]); assertEquals("c", nextLine[2]); assertEquals(3, nextLine.length); } @Test public void parseEmptyElements() throws IOException { String[] nextLine = csvParser.parseLine(",,"); assertEquals(3, nextLine.length); assertEquals("", nextLine[0]); assertEquals("", nextLine[1]); assertEquals("", nextLine[2]); } @Test public void parseMultiLinedQuoted() throws IOException { String[] nextLine = csvParser.parseLine("a,\"PO Box 123,\nKippax,ACT. 2615.\nAustralia\",d.\n"); assertEquals(3, nextLine.length); assertEquals("a", nextLine[0]); assertEquals("PO Box 123,\nKippax,ACT. 2615.\nAustralia", nextLine[1]); assertEquals("d.\n", nextLine[2]); } @Test public void testADoubleQuoteAsDataElement() throws IOException { String[] nextLine = csvParser.parseLine("a,\"\"\"\",c");// a,"""",c assertEquals(3, nextLine.length); assertEquals("a", nextLine[0]); assertEquals(1, nextLine[1].length()); assertEquals("\"", nextLine[1]); assertEquals("c", nextLine[2]); } @Test public void testEscapedDoubleQuoteAsDataElement() throws IOException { String[] nextLine = csvParser.parseLine("\"test\",\"this,test,is,good\",\"\\\"test\\\"\",\"\\\"quote\\\"\""); // "test","this,test,is,good","\"test\",\"quote\"" assertEquals(4, nextLine.length); assertEquals("test", nextLine[0]); assertEquals("this,test,is,good", nextLine[1]); assertEquals("\"test\"", nextLine[2]); assertEquals("\"quote\"", nextLine[3]); } // @Test // public void testEscapingSeparator() throws IOException { // String[] nextLine = csvParser.parseLine("test,this\\,test\\,is\\,good"); // "test","this,test,is,good","\"test\",\"quote\"" // // assertEquals(2, nextLine.length); // // assertEquals("test", nextLine[0]); // assertEquals("this,test,is,good", nextLine[1]); // } @Test public void parseQuotedQuoteCharacters() throws IOException { String[] nextLine = csvParser.parseLineMulti("\"Glen \"\"The Man\"\" Smith\",Athlete,Developer\n"); assertEquals(3, nextLine.length); assertEquals("Glen \"The Man\" Smith", nextLine[0]); assertEquals("Athlete", nextLine[1]); assertEquals("Developer\n", nextLine[2]); } @Test public void parseMultipleQuotes() throws IOException { String[] nextLine = csvParser.parseLine("\"\"\"\"\"\",\"test\"\n"); // """""","test" representing: "", test assertEquals("\"\"", nextLine[0]); // check the tricky situation assertEquals("test\"\n", nextLine[1]); // make sure we didn't ruin the next field.. assertEquals(2, nextLine.length); } @Test public void parseTrickyString() throws IOException { String[] nextLine = csvParser.parseLine("\"a\nb\",b,\"\nd\",e\n"); assertEquals(4, nextLine.length); assertEquals("a\nb", nextLine[0]); assertEquals("b", nextLine[1]); assertEquals("\nd", nextLine[2]); assertEquals("e\n", nextLine[3]); } private String setUpMultiLineInsideQuotes() { StringBuffer sb = new StringBuffer(CSVParser.INITIAL_READ_SIZE); sb.append("Small test,\"This is a test across \ntwo lines.\""); return sb.toString(); } @Test public void testAMultiLineInsideQuotes() throws IOException { String testString = setUpMultiLineInsideQuotes(); String[] nextLine = csvParser.parseLine(testString); assertEquals(2, nextLine.length); assertEquals("Small test", nextLine[0]); assertEquals("This is a test across \ntwo lines.", nextLine[1]); assertFalse(csvParser.isPending()); } @Test public void testStrictQuoteSimple() throws IOException { csvParser = new CSVParser(',', '\"', '\\', true); String testString = "\"a\",\"b\",\"c\""; String[] nextLine = csvParser.parseLine(testString); assertEquals(3, nextLine.length); assertEquals("a", nextLine[0]); assertEquals("b", nextLine[1]); assertEquals("c", nextLine[2]); } @Test public void testStrictQuoteWithSpacesAndTabs() throws IOException { csvParser = new CSVParser(',', '\"', '\\', true); String testString = " \t \"a\",\"b\" \t , \"c\" "; String[] nextLine = csvParser.parseLine(testString); assertEquals(3, nextLine.length); assertEquals("a", nextLine[0]); assertEquals("b", nextLine[1]); assertEquals("c", nextLine[2]); } @Test public void testStrictQuoteWithGarbage() throws IOException { csvParser = new CSVParser(',', '\"', '\\', true); String testString = "abc',!@#\",\\\"\" xyz,"; String[] nextLine = csvParser.parseLine(testString); assertEquals(3, nextLine.length); assertEquals("", nextLine[0]); assertEquals(",\"", nextLine[1]); assertEquals("", nextLine[2]); } /** * Test issue 2263439 where an escaped quote was causing the parse to fail. * <p/> * Special thanks to Chris Morris for fixing this (id 1979054) * * @throws IOException */ @Test public void testIssue2263439() throws IOException { csvParser = new CSVParser(',', '\''); String[] nextLine = csvParser.parseLine("865,0,'AmeriKKKa\\'s_Most_Wanted','',294,0,0,0.734338696798625,'20081002052147',242429208,18448"); assertEquals(11, nextLine.length); assertEquals("865", nextLine[0]); assertEquals("0", nextLine[1]); assertEquals("AmeriKKKa's_Most_Wanted", nextLine[2]); assertEquals("", nextLine[3]); assertEquals("18448", nextLine[10]); } /** * Test issue 2859181 where an escaped character before a character * that did not need escaping was causing the parse to fail. * * @throws IOException */ @Test public void testIssue2859181() throws IOException { csvParser = new CSVParser(';'); String[] nextLine = csvParser.parseLine("field1;\\=field2;\"\"\"field3\"\"\""); // field1;\=field2;"""field3""" assertEquals(3, nextLine.length); assertEquals("field1", nextLine[0]); assertEquals("=field2", nextLine[1]); assertEquals("\"field3\"", nextLine[2]); } /** * Test issue 2726363 * <p/> * Data given: * <p/> * "804503689","London",""London""shop","address","116.453182","39.918884" * "453074125","NewYork","brief","address"","121.514683","31.228511" */ @Test public void testIssue2726363() throws IOException { String[] nextLine = csvParser.parseLine("\"804503689\",\"London\",\"\"London\"shop\",\"address\",\"116.453182\",\"39.918884\""); assertEquals(6, nextLine.length); assertEquals("804503689", nextLine[0]); assertEquals("London", nextLine[1]); assertEquals("\"London\"shop", nextLine[2]); assertEquals("address", nextLine[3]); assertEquals("116.453182", nextLine[4]); assertEquals("39.918884", nextLine[5]); } @Test(expected = IOException.class) public void anIOExceptionThrownifStringEndsInsideAQuotedString() throws IOException { String[] nextLine = csvParser.parseLine("This,is a \"bad line to parse."); } @Test public void parseLineMultiAllowsQuotesAcrossMultipleLines() throws IOException { String[] nextLine = csvParser.parseLineMulti("This,\"is a \"good\" line\\\\ to parse"); assertEquals(1, nextLine.length); assertEquals("This", nextLine[0]); assertTrue(csvParser.isPending()); nextLine = csvParser.parseLineMulti("because we are using parseLineMulti.\""); assertEquals(1, nextLine.length); assertEquals("is a \"good\" line\\ to parse\nbecause we are using parseLineMulti.", nextLine[0]); assertFalse(csvParser.isPending()); } @Test public void pendingIsClearedAfterCallToParseLine() throws IOException { String[] nextLine = csvParser.parseLineMulti("This,\"is a \"good\" line\\\\ to parse"); assertEquals(1, nextLine.length); assertEquals("This", nextLine[0]); assertTrue(csvParser.isPending()); nextLine = csvParser.parseLine("because we are using parseLineMulti."); assertEquals(1, nextLine.length); assertEquals("because we are using parseLineMulti.", nextLine[0]); assertFalse(csvParser.isPending()); } @Test public void returnPendingIfNullIsPassedIntoParseLineMulti() throws IOException { String[] nextLine = csvParser.parseLineMulti("This,\"is a \"goo\\d\" line\\\\ to parse\\"); assertEquals(1, nextLine.length); assertEquals("This", nextLine[0]); assertTrue(csvParser.isPending()); nextLine = csvParser.parseLineMulti(null); assertEquals(1, nextLine.length); assertEquals("is a \"good\" line\\ to parse\n", nextLine[0]); assertFalse(csvParser.isPending()); } @Test public void spacesAtEndOfQuotedStringDoNotCountIfStrictQuotesIsTrue() throws IOException { CSVParser parser = new CSVParser(CSVParser.DEFAULT_SEPARATOR, CSVParser.DEFAULT_QUOTE_CHARACTER, CSVParser.DEFAULT_ESCAPE_CHARACTER, true); String[] nextLine = parser.parseLine("\"Line with\", \"spaces at end\" "); assertEquals(2, nextLine.length); assertEquals("Line with", nextLine[0]); assertEquals("spaces at end", nextLine[1]); } @Test public void returnNullWhenNullPassedIn() throws IOException { String[] nextLine = csvParser.parseLine(null); assertNull(nextLine); } private static final String ESCAPE_TEST_STRING = "\\\\1\\2\\\"3\\"; // \\1\2\"\ @Test public void validateEscapeStringBeforeRealTest() { assertNotNull(ESCAPE_TEST_STRING); assertEquals(9, ESCAPE_TEST_STRING.length()); } @Test public void whichCharactersAreEscapable() { assertTrue(csvParser.isNextCharacterEscapable(ESCAPE_TEST_STRING, true, 0)); assertFalse(csvParser.isNextCharacterEscapable(ESCAPE_TEST_STRING, false, 0)); // Second character is not escapable because there is a non quote or non slash after it. assertFalse(csvParser.isNextCharacterEscapable(ESCAPE_TEST_STRING, true, 1)); assertFalse(csvParser.isNextCharacterEscapable(ESCAPE_TEST_STRING, false, 1)); // Fourth character is not escapable because there is a non quote or non slash after it. assertFalse(csvParser.isNextCharacterEscapable(ESCAPE_TEST_STRING, true, 3)); assertFalse(csvParser.isNextCharacterEscapable(ESCAPE_TEST_STRING, false, 3)); assertTrue(csvParser.isNextCharacterEscapable(ESCAPE_TEST_STRING, true, 5)); assertFalse(csvParser.isNextCharacterEscapable(ESCAPE_TEST_STRING, false, 5)); int lastChar = ESCAPE_TEST_STRING.length() - 1; assertFalse(csvParser.isNextCharacterEscapable(ESCAPE_TEST_STRING, true, lastChar)); assertFalse(csvParser.isNextCharacterEscapable(ESCAPE_TEST_STRING, false, lastChar)); } @Test public void whitespaceBeforeEscape() throws IOException { String[] nextItem = csvParser.parseLine("\"this\", \"is\",\"a test\""); //"this", "is","a test" assertEquals("this", nextItem[0]); assertEquals("is", nextItem[1]); assertEquals("a test", nextItem[2]); } @Test public void testIssue2958242WithoutQuotes() throws IOException { CSVParser testParser = new CSVParser('\t'); String[] nextItem = testParser.parseLine("zo\"\"har\"\"at\t10-04-1980\t29\tC:\\\\foo.txt"); assertEquals(4, nextItem.length); assertEquals("zo\"har\"at", nextItem[0]); assertEquals("10-04-1980", nextItem[1]); assertEquals("29", nextItem[2]); assertEquals("C:\\foo.txt", nextItem[3]); } @Test(expected = UnsupportedOperationException.class) public void quoteAndEscapeCannotBeTheSame() { CSVParser p = new CSVParser(CSVParser.DEFAULT_SEPARATOR, CSVParser.DEFAULT_QUOTE_CHARACTER, CSVParser.DEFAULT_QUOTE_CHARACTER); } @Test public void quoteAndEscapeCanBeTheSameIfNull() { CSVParser p = new CSVParser(CSVParser.DEFAULT_SEPARATOR, CSVParser.NULL_CHARACTER, CSVParser.NULL_CHARACTER); } @Test(expected = UnsupportedOperationException.class) public void separatorCharacterCannotBeNull() { CSVParser p = new CSVParser(CSVParser.NULL_CHARACTER); } @Test(expected = UnsupportedOperationException.class) public void separatorAndEscapeCannotBeTheSame() { CSVParser p = new CSVParser(CSVParser.DEFAULT_SEPARATOR, CSVParser.DEFAULT_QUOTE_CHARACTER, CSVParser.DEFAULT_SEPARATOR); } @Test(expected = UnsupportedOperationException.class) public void separatorAndQuoteCannotBeTheSame() { CSVParser p = new CSVParser(CSVParser.DEFAULT_SEPARATOR, CSVParser.DEFAULT_SEPARATOR, CSVParser.DEFAULT_ESCAPE_CHARACTER); } }