package de.superx.util; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.BufferedReader; import java.io.FilterReader; import java.io.IOException; import java.io.LineNumberReader; import java.io.StringReader; import java.nio.CharBuffer; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.text.StrTokenizer; import org.junit.Assert; import org.junit.Test; public class TrailingDelimiterRemovingReaderTest { private static final String[] lines = new String[] { "1^2^3", "3^4^5", "6^7^8" }; private static final String GOOD_CSV_TRAILING = String.join("^\n", lines[0], lines[1]) + "^"; private static final String GOOD_CSV = String.join("\n", lines[0], lines[1]); private static final String BAD_CSV_TRAILING = lines[0] + "^\n^" + lines[1] + "^"; private static final String BAD_CSV = lines[0] + "\n" + lines[1] + "^"; @Test public void testStringTokenizerWithLeadingBackslash() throws IOException { StrTokenizer csvTokenizer = TrailingDelimiterRemovingReader.csvTokenizer; String input = "\\^one\\^two^three^^five"; csvTokenizer.reset(input); List result = new ArrayList(); while (csvTokenizer.hasNext()) { result.add(csvTokenizer.next()); } assertEquals("\\^one\\^two", result.get(0)); assertEquals("three", result.get(1)); assertEquals("", result.get(2)); assertEquals("five", result.get(3)); } @Test public void testGoodCsvTrailing() throws IOException { CharBuffer target = CharBuffer.allocate(100); int total; try (TrailingDelimiterRemovingReader tsrr = new TrailingDelimiterRemovingReader(new BufferedReader(new StringReader(GOOD_CSV_TRAILING)), "^", 3, true, null)) { total = readAllFrom(tsrr, target); } assertEquals("Count read", 12, total); } @Test public void testGoodCsv() throws IOException { CharBuffer target = CharBuffer.allocate(100); int total; TrailingDelimiterRemovingReader tsrr = new TrailingDelimiterRemovingReader(new BufferedReader(new StringReader(GOOD_CSV)), "^", 3, false, null); total = readAllFrom(tsrr, target); assertEquals("Count read", 12, total); } @Test public void testBadCsvTrailing() throws IOException { CharBuffer target = CharBuffer.allocate(100); TrailingDelimiterRemovingReader tsrr = new TrailingDelimiterRemovingReader(new BufferedReader(new StringReader(BAD_CSV_TRAILING)), "^", 3, true, null); RuntimeException exception = Assert.assertThrows(RuntimeException.class, () -> { readAllFrom(tsrr, target); }); assertTrue(exception.getMessage().contains("line 2")); assertTrue(exception.getMessage().contains("Expected 3")); assertTrue(exception.getMessage().contains("found 4")); } @Test public void testBadCsv() throws IOException { CharBuffer target = CharBuffer.allocate(100); TrailingDelimiterRemovingReader tsrr = new TrailingDelimiterRemovingReader(new BufferedReader(new StringReader(BAD_CSV)), "^", 3, false, null); RuntimeException exception = Assert.assertThrows(RuntimeException.class, () -> { readAllFrom(tsrr, target); }); assertTrue(exception.getMessage().contains("line 2")); assertTrue(exception.getMessage().contains("Expected 3")); assertTrue(exception.getMessage().contains("found 4")); } @Test public void testEscapedDelimiterCsv() throws IOException { String line = "^^^^^^^^^^^^^^Studienvergangenheit F1\\\\^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^525^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^11^^^^^^^\n"; CharBuffer target = CharBuffer.allocate(line.length()); LineNumberReader lnr = new LineNumberReader(new StringReader(line)); TrailingDelimiterRemovingReader tsrr = new TrailingDelimiterRemovingReader(new BufferedReader(lnr), "^", 105, true, null); int total = readAllFrom(tsrr, target); assertEquals("Count read", line.length() - lnr.getLineNumber(), total); } @Test public void testEscapedBackslashCsv() throws IOException { String line = "^^^^^^^^^^^^^^Studienverg\\^angenheit F1^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^525^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^11^^^^^^^\n"; CharBuffer target = CharBuffer.allocate(line.length()); LineNumberReader lnr = new LineNumberReader(new StringReader(line)); TrailingDelimiterRemovingReader tsrr = new TrailingDelimiterRemovingReader(new BufferedReader(lnr), "^", 105, true, null); int total = readAllFrom(tsrr, target); assertEquals("Count read", line.length() - lnr.getLineNumber(), total); } private int readAllFrom(FilterReader fr, CharBuffer target) throws IOException { int total = 0; int countRead = 0; while ((countRead = fr.read(target)) != -1) { total += countRead; } fr.close(); return total; } }