Merge branch 'master' into release

This commit is contained in:
Gary Gregory 2020-02-01 20:04:04 -05:00
commit 660f7c9f85
16 changed files with 262 additions and 62 deletions

View File

@ -5,14 +5,16 @@
INTRODUCTION:
This document contains the release notes for the 1.8 version of Apache Commons CSV.
This document contains the release notes for the 1.8-SNAPSHOT version of Apache Commons CSV.
Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format.
Commons CSV requires at least Java 6.
The Apache Commons CSV library provides a simple interface for reading and writing CSV files of various types.
Feature and bug fix release (Java 8)
Feature and bug fix release (Java 8).
This release fixes serialization compatibility of CSVRecord with versions 1.0 to 1.6. New fields added since
1.7 are not serialized. Support for Serializable is scheduled to be removed in version 2.0.
Changes in this version include:
@ -32,6 +34,7 @@ o CSV-241: CSVFormat#validate() does not account for allowDuplicateHeaderNames
o CSV-245: Post 1.7 release fixes. Thanks to Alex Herbert.
o CSV-252: Upgrade test framework to JUnit 5 Jupiter #49, #50. Thanks to Alex Herbert.
o CSV-247: A single empty header is allowed when not allowing empty column headers. #47. Thanks to Alex Herbert, Gary Gregory.
o CSV-248: CSVRecord is not Serializable. Thanks to Alex Herbert.
o Use test scope for supercsv #48. Thanks to Alex Herbert.
CHANGES
@ -41,6 +44,7 @@ o Update tests from H2 1.4.199 to 1.4.200. Thanks to Gary Gregory.
o Update tests from Hamcrest 2.1 to 2.2. Thanks to Gary Gregory.
o Update tests from Mockito 3.1.0 to 3.2.4. Thanks to Gary Gregory.
o Fix typos in site and test #53. Thanks to Chen.
o Fix typo performance test #55. Thanks to Chen.
Historical list of changes: https://commons.apache.org/proper/commons-csv/changes-report.html

View File

@ -32,7 +32,7 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.5.2</version>
<version>5.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
@ -140,7 +140,7 @@
<commons.release.version>1.8</commons.release.version>
<commons.release.desc>(Java 8)</commons.release.desc>
<!-- The RC version used in the staging repository URL. -->
<commons.rc.version>RC1</commons.rc.version>
<commons.rc.version>RC2</commons.rc.version>
<commons.bc.version>1.7</commons.bc.version>
<commons.componentid>csv</commons.componentid>
<commons.module.name>org.apache.commons.csv</commons.module.name>
@ -258,6 +258,7 @@
<!-- The ferc.gov files are included discussion in https://issues.apache.org/jira/browse/LEGAL-175. -->
<exclude>src/test/resources/ferc.gov/contract.txt</exclude>
<exclude>src/test/resources/ferc.gov/transaction.txt</exclude>
<exclude>src/test/resources/**/*.bin</exclude>
</excludes>
</configuration>
</plugin>
@ -376,6 +377,7 @@
<exclude>src/test/resources/CSVFileParser/testCSV85_ignoreEmpty.txt</exclude>
<exclude>src/test/resources/ferc.gov/contract.txt</exclude>
<exclude>src/test/resources/ferc.gov/transaction.txt</exclude>
<exclude>src/test/resources/**/*.bin</exclude>
</excludes>
</configuration>
</plugin>

View File

@ -38,7 +38,12 @@
<title>Apache Commons CSV Release Notes</title>
</properties>
<body>
<release version="1.8" date="2019-01-18" description="Feature and bug fix release (Java 8)">
<release version="1.8" date="2019-02-01" description="Feature and bug fix release (Java 8).
This release fixes serialization compatibility of CSVRecord with versions 1.0 to 1.6.
New fields added since 1.7 are not serialized. Support for Serializable is scheduled to be
removed in version 2.0.
">
<action issue="CSV-255" type="add" dev="ggregory" due-to="0x100">Add CSVRecord.isSet(int) method #52.</action>
<action issue="CSV-135" type="fix" dev="sebb" due-to="Mateusz Zakarczemny">Char escape doesn't work properly with quoting.</action>
<action issue="CSV-244" type="fix" dev="sebb">Test case failures following CSVFormat#equals() update.</action>
@ -48,11 +53,13 @@
<action issue="CSV-245" type="fix" dev="ggregory" due-to="Alex Herbert">Post 1.7 release fixes.</action>
<action issue="CSV-252" type="fix" dev="ggregory" due-to= "Alex Herbert">Upgrade test framework to JUnit 5 Jupiter #49, #50.</action>
<action issue="CSV-247" type="fix" dev="ggregory" due-to="Alex Herbert, Gary Gregory">A single empty header is allowed when not allowing empty column headers. #47.</action>
<action issue="CSV-248" type="fix" dev="ggregory" due-to="Alex Herbert">CSVRecord is not Serializable.</action>
<action type="fix" dev="ggregory" due-to="Alex Herbert">Use test scope for supercsv #48.</action>
<action type="update" dev="ggregory" due-to="Gary Gregory">Update tests from H2 1.4.199 to 1.4.200.</action>
<action type="update" dev="ggregory" due-to="Gary Gregory">Update tests from Hamcrest 2.1 to 2.2.</action>
<action type="update" dev="ggregory" due-to="Gary Gregory">Update tests from Mockito 3.1.0 to 3.2.4.</action>
<action type="update" dev="ggregory" due-to="Chen">Fix typos in site and test #53.</action>
<action type="update" dev="ggregory" due-to="Chen">Fix typo performance test #55.</action>
</release>
<release version="1.7" date="2019-06-01" description="Feature and bug fix release (Java 8)">
<action issue="CSV-233" type="add" dev="ggregory" due-to="Gary Gregory">Add predefined CSVFormats for printing MongoDB CSV and TSV.</action>

View File

@ -555,6 +555,11 @@ public final class CSVParser implements Iterable<CSVRecord>, Closeable {
* <p>
* The map keys are column names. The map values are 0-based indices.
* </p>
* <p>
* Note: The map can only provide a one-to-one mapping when the format did not
* contain null or duplicate column names.
* </p>
*
* @return a copy of the header map.
*/
public Map<String, Integer> getHeaderMap() {
@ -577,8 +582,14 @@ public final class CSVParser implements Iterable<CSVRecord>, Closeable {
/**
* Returns a read-only list of header names that iterates in column order.
* <p>
* Note: The list provides strings that can be used as keys in the header map.
* The list will not contain null column names if they were present in the input
* format.
* </p>
*
* @return read-only list of header names that iterates in column order.
* @see #getHeaderMap()
* @since 1.7
*/
public List<String> getHeaderNames() {

View File

@ -24,9 +24,19 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
/**
* A CSV record parsed from a CSV file.
*
* <p>
* Note: Support for {@link Serializable} is scheduled to be removed in version 2.0.
* In version 1.8 the mapping between the column header and the column index was
* removed from the serialised state. The class maintains serialization compatibility
* with versions pre-1.8 for the record values; these must be accessed by index
* following deserialization. There will be loss of any functionally linked to the header
* mapping when transferring serialised forms pre-1.8 to 1.8 and vice versa.
* </p>
*/
public final class CSVRecord implements Serializable, Iterable<String> {
@ -45,8 +55,8 @@ public final class CSVRecord implements Serializable, Iterable<String> {
/** The values of the record */
private final String[] values;
/** The parser that originates this record. */
private final CSVParser parser;
/** The parser that originates this record. This is not serialized. */
private final transient CSVParser parser;
CSVRecord(final CSVParser parser, final String[] values, final String comment, final long recordNumber,
final long characterPosition) {
@ -65,7 +75,7 @@ public final class CSVRecord implements Serializable, Iterable<String> {
* @return the String at the given enum String
*/
public String get(final Enum<?> e) {
return get(e.toString());
return get(Objects.toString(e, null));
}
/**
@ -82,6 +92,14 @@ public final class CSVRecord implements Serializable, Iterable<String> {
/**
* Returns a value by name.
*
* <p>
* Note: This requires a field mapping obtained from the original parser.
* A check using {@link #isMapped(String)} should be used to determine if a
* mapping exists from the provided {@code name} to a field index. In this case an
* exception will only be thrown if the record does not contain a field corresponding
* to the mapping, that is the record length is not consistent with the mapping size.
* </p>
*
* @param name
* the name of the column to be retrieved.
* @return the column value, maybe null depending on {@link CSVFormat#getNullString()}.
@ -89,7 +107,9 @@ public final class CSVRecord implements Serializable, Iterable<String> {
* if no header mapping was provided
* @throws IllegalArgumentException
* if {@code name} is not mapped or if the record is inconsistent
* @see #isMapped(String)
* @see #isConsistent()
* @see #getParser()
* @see CSVFormat#withNullString(String)
*/
public String get(final String name) {
@ -135,12 +155,17 @@ public final class CSVRecord implements Serializable, Iterable<String> {
}
private Map<String, Integer> getHeaderMapRaw() {
return parser.getHeaderMapRaw();
return parser == null ? null : parser.getHeaderMapRaw();
}
/**
* Returns the parser.
*
* <p>
* Note: The parser is not part of the serialized state of the record. A null check
* should be used when the record may have originated from a serialized form.
* </p>
*
* @return the parser.
* @since 1.7
*/

View File

@ -32,7 +32,7 @@ limitations under the License.
Parsing files with Apache Commons CSV is relatively straight forward.
The CSVFormat class provides some commonly used CSV variants:
<dl>
<dt><a href="https://commons.apache.org/proper/commons-csv/apidocs/org/apache/commons/csv/CSVFormat.html#DEFAULT">DEFAULT</a></dt><dd>Standard Comma Separated Value format, as for RFC4180 but allowing empty lines.</dd>
<dt><a href="https://commons.apache.org/proper/commons-csv/apidocs/org/apache/commons/csv/CSVFormat.html#EXCEL">EXCEL</a></dt><dd>The Microsoft Excel CSV format.</dd>

View File

@ -79,7 +79,7 @@ public class CSVBenchmark {
while ((line = in.readLine()) != null) {
count++;
}
bh.consume(count);
in.close();
return count;
@ -94,7 +94,7 @@ public class CSVBenchmark {
final String[] values = StringUtils.split(line, ',');
count += values.length;
}
bh.consume(count);
in.close();
return count;
@ -103,7 +103,7 @@ public class CSVBenchmark {
@Benchmark
public int parseCommonsCSV(final Blackhole bh) throws Exception {
final BufferedReader in = getReader();
final CSVFormat format = CSVFormat.DEFAULT.withHeader();
int count = 0;
@ -119,7 +119,7 @@ public class CSVBenchmark {
@Benchmark
public int parseGenJavaCSV(final Blackhole bh) throws Exception {
final BufferedReader in = getReader();
final CsvReader reader = new CsvReader(in);
reader.setFieldDelimiter(',');
@ -137,7 +137,7 @@ public class CSVBenchmark {
@Benchmark
public int parseJavaCSV(final Blackhole bh) throws Exception {
final BufferedReader in = getReader();
final com.csvreader.CsvReader reader = new com.csvreader.CsvReader(in, ',');
reader.setRecordDelimiter('\n');
@ -154,7 +154,7 @@ public class CSVBenchmark {
@Benchmark
public int parseOpenCSV(final Blackhole bh) throws Exception {
final BufferedReader in = getReader();
final com.opencsv.CSVReader reader = new com.opencsv.CSVReader(in, ',');
int count = 0;
@ -170,10 +170,10 @@ public class CSVBenchmark {
@Benchmark
public int parseSkifeCSV(final Blackhole bh) throws Exception {
final BufferedReader in = getReader();
final org.skife.csv.CSVReader reader = new org.skife.csv.SimpleReader();
reader.setSeperator(',');
final CountingReaderCallback callback = new CountingReaderCallback();
reader.parse(in, callback);
@ -194,7 +194,7 @@ public class CSVBenchmark {
@Benchmark
public int parseSuperCSV(final Blackhole bh) throws Exception {
final BufferedReader in = getReader();
final CsvListReader reader = new CsvListReader(in, CsvPreference.STANDARD_PREFERENCE);
int count = 0;

View File

@ -42,7 +42,7 @@ public class CSVFileParserTest {
private static final File BASE = new File("src/test/resources/CSVFileParser");
private String readTestData(BufferedReader reader) throws IOException {
private String readTestData(final BufferedReader reader) throws IOException {
String line;
do {
line = reader.readLine();
@ -61,7 +61,7 @@ public class CSVFileParserTest {
@ParameterizedTest
@MethodSource("generateData")
public void testCSVFile(File testFile) throws Exception {
public void testCSVFile(final File testFile) throws Exception {
try (FileReader fr = new FileReader(testFile); BufferedReader testData = new BufferedReader(fr)) {
String line = readTestData(testData);
assertNotNull("file must contain config line", line);
@ -108,7 +108,7 @@ public class CSVFileParserTest {
@ParameterizedTest
@MethodSource("generateData")
public void testCSVUrl(File testFile) throws Exception {
public void testCSVUrl(final File testFile) throws Exception {
try (FileReader fr = new FileReader(testFile); BufferedReader testData = new BufferedReader(fr)) {
String line = readTestData(testData);
assertNotNull("file must contain config line", line);

View File

@ -64,7 +64,7 @@ public class CSVFormatTest {
return format.withDelimiter(format.getDelimiter());
}
private void assertNotEquals(String name, String type, Object left, Object right) {
private void assertNotEquals(final String name, final String type, final Object left, final Object right) {
if (left.equals(right) || right.equals(left)) {
fail("Objects must not compare equal for " + name + "(" + type + ")");
}
@ -153,12 +153,12 @@ public class CSVFormatTest {
@Test
public void testEqualsHash() throws Exception {
Method[] methods = CSVFormat.class.getDeclaredMethods();
for (Method method : methods) {
final Method[] methods = CSVFormat.class.getDeclaredMethods();
for (final Method method : methods) {
if (Modifier.isPublic(method.getModifiers())) {
final String name = method.getName();
if (name.startsWith("with")) {
for (Class<?> cls : method.getParameterTypes()) {
for (final Class<?> cls : method.getParameterTypes()) {
final String type = cls.getCanonicalName();
if ("boolean".equals(type)) {
final Object defTrue = method.invoke(CSVFormat.DEFAULT, new Object[] {Boolean.TRUE});
@ -550,7 +550,7 @@ public class CSVFormatTest {
final CSVFormat csvFormat = CSVFormat.MYSQL;
NullPointerException e = assertThrows(NullPointerException.class, () -> csvFormat.format((Object[]) null));
final NullPointerException e = assertThrows(NullPointerException.class, () -> csvFormat.format((Object[]) null));
assertEquals(CSVFormat.class.getName(), e.getStackTrace()[0].getClassName());
}

View File

@ -724,6 +724,20 @@ public class CSVParserTest {
assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withHeader().parse(in).iterator());
}
@Test
public void testHeadersWithNullColumnName() throws IOException {
final Reader in = new StringReader("header1,null,header3\n1,2,3\n4,5,6");
final Iterator<CSVRecord> records = CSVFormat.DEFAULT
.withHeader()
.withNullString("null")
.withAllowMissingColumnNames()
.parse(in).iterator();
final CSVRecord record = records.next();
// Expect the null header to be missing
assertEquals(Arrays.asList("header1", "header3"), record.getParser().getHeaderNames());
assertEquals(2, record.getParser().getHeaderMap().size());
}
@Test
public void testIgnoreCaseHeaderMapping() throws Exception {
final Reader reader = new StringReader("1,2,3");

View File

@ -289,15 +289,25 @@ public class CSVPrinterTest {
@Test
public void testCSV135() throws IOException {
List<String> l = new LinkedList<String>();
l.add("\"\""); // ""
l.add("\\\\"); // \\
l.add("\\\"\\"); // \"\
tryFormat(l, null, null, "\"\",\\\\,\\\"\\"); // "",\\,\"\ (unchanged)
tryFormat(l, '"', null, "\"\"\"\"\"\",\\\\,\"\\\"\"\\\""); // """""",\\,"\""\" (quoted, and embedded DQ doubled)
tryFormat(l, null, '\\', "\"\",\\\\\\\\,\\\\\"\\\\"); // "",\\\\,\\"\\ (escapes escaped, not quoted)
tryFormat(l, '"', '\\', "\"\\\"\\\"\",\"\\\\\\\\\",\"\\\\\\\"\\\\\""); // "\"\"","\\\\","\\\"\\" (quoted, and embedded DQ & escape escaped)
tryFormat(l, '"', '"', "\"\"\"\"\"\",\\\\,\"\\\"\"\\\""); // """""",\\,"\""\" (quoted, embedded DQ escaped)
final List<String> list = new LinkedList<>();
list.add("\"\""); // ""
list.add("\\\\"); // \\
list.add("\\\"\\"); // \"\
//
// "",\\,\"\ (unchanged)
tryFormat(list, null, null, "\"\",\\\\,\\\"\\");
//
// """""",\\,"\""\" (quoted, and embedded DQ doubled)
tryFormat(list, '"', null, "\"\"\"\"\"\",\\\\,\"\\\"\"\\\"");
//
// "",\\\\,\\"\\ (escapes escaped, not quoted)
tryFormat(list, null, '\\', "\"\",\\\\\\\\,\\\\\"\\\\");
//
// "\"\"","\\\\","\\\"\\" (quoted, and embedded DQ & escape escaped)
tryFormat(list, '"', '\\', "\"\\\"\\\"\",\"\\\\\\\\\",\"\\\\\\\"\\\\\"");
//
// """""",\\,"\""\" (quoted, embedded DQ escaped)
tryFormat(list, '"', '"', "\"\"\"\"\"\",\\\\,\"\\\"\"\\\"");
}
@Test
@ -772,7 +782,8 @@ public class CSVPrinterTest {
@Test
public void testMySqlNullOutput() throws IOException {
Object[] s = new String[] { "NULL", null };
CSVFormat format = CSVFormat.MYSQL.withQuote(DQUOTE_CHAR).withNullString("NULL").withQuoteMode(QuoteMode.NON_NUMERIC);
CSVFormat format = CSVFormat.MYSQL.withQuote(DQUOTE_CHAR).withNullString("NULL")
.withQuoteMode(QuoteMode.NON_NUMERIC);
StringWriter writer = new StringWriter();
try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
printer.printRecord(s);
@ -1519,10 +1530,10 @@ public class CSVPrinterTest {
return CSVParser.parse(expected, format).getRecords().get(0).values();
}
private void tryFormat(List<String> l, Character quote, Character escape, String expected) throws IOException {
CSVFormat format = CSVFormat.DEFAULT.withQuote(quote).withEscape(escape).withRecordSeparator(null);
Appendable out = new StringBuilder();
CSVPrinter printer = new CSVPrinter(out, format);
private void tryFormat(final List<String> l, final Character quote, final Character escape, final String expected) throws IOException {
final CSVFormat format = CSVFormat.DEFAULT.withQuote(quote).withEscape(escape).withRecordSeparator(null);
final Appendable out = new StringBuilder();
final CSVPrinter printer = new CSVPrinter(out, format);
printer.printRecord(l);
printer.close();
assertEquals(expected, out.toString());

View File

@ -23,10 +23,15 @@ import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
@ -41,9 +46,9 @@ public class CSVRecordTest {
UNKNOWN_COLUMN
}
private String[] values;
private CSVRecord record, recordWithHeader;
private Map<String, Integer> headerMap;
private CSVRecord record, recordWithHeader;
private String[] values;
@BeforeEach
public void setUp() throws Exception {
@ -89,6 +94,11 @@ public class CSVRecordTest {
assertThrows(IllegalArgumentException.class, () -> recordWithHeader.get(EnumFixture.UNKNOWN_COLUMN));
}
@Test
public void testGetNullEnum() {
assertThrows(IllegalArgumentException.class, () -> recordWithHeader.get((Enum<?>) null));
}
@Test
public void testGetUnmappedName() {
assertThrows(IllegalArgumentException.class, () -> assertNull(recordWithHeader.get("fourth")));
@ -133,13 +143,6 @@ public class CSVRecordTest {
assertFalse(recordWithHeader.isMapped("fourth"));
}
@Test
public void testIsSetString() {
assertFalse(record.isSet("first"));
assertTrue(recordWithHeader.isSet("first"));
assertFalse(recordWithHeader.isSet("fourth"));
}
@Test
public void testIsSetInt() {
assertFalse(record.isSet(-1));
@ -150,6 +153,13 @@ public class CSVRecordTest {
assertFalse(recordWithHeader.isSet(1000));
}
@Test
public void testIsSetString() {
assertFalse(record.isSet("first"));
assertTrue(recordWithHeader.isSet("first"));
assertFalse(recordWithHeader.isSet("fourth"));
}
@Test
public void testIterator() {
int i = 0;
@ -185,17 +195,47 @@ public class CSVRecordTest {
}
@Test
public void testToMap() {
final Map<String, String> map = this.recordWithHeader.toMap();
this.validateMap(map, true);
public void testSerialization() throws IOException, ClassNotFoundException {
CSVRecord shortRec;
try (final CSVParser parser = CSVParser.parse("A,B\n#my comment\nOne,Two", CSVFormat.DEFAULT.withHeader().withCommentMarker('#'))) {
shortRec = parser.iterator().next();
}
final ByteArrayOutputStream out = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(out)) {
oos.writeObject(shortRec);
}
final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
try (ObjectInputStream ois = new ObjectInputStream(in)) {
final Object object = ois.readObject();
assertTrue(object instanceof CSVRecord);
final CSVRecord rec = (CSVRecord) object;
assertEquals(1L, rec.getRecordNumber());
assertEquals("One", rec.get(0));
assertEquals("Two", rec.get(1));
assertEquals(2, rec.size());
assertEquals(shortRec.getCharacterPosition(), rec.getCharacterPosition());
assertEquals("my comment", rec.getComment());
// The parser is not serialized
assertNull(rec.getParser());
// Check all header map functionality is absent
assertTrue(rec.isConsistent());
assertFalse(rec.isMapped("A"));
assertFalse(rec.isSet("A"));
assertEquals(0, rec.toMap().size());
// This will throw
try {
rec.get("A");
org.junit.jupiter.api.Assertions.fail("Access by name is not expected after deserialisation");
} catch (final IllegalStateException expected) {
// OK
}
}
}
@Test
public void testToMapWithShortRecord() throws Exception {
try (final CSVParser parser = CSVParser.parse("a,b", CSVFormat.DEFAULT.withHeader("A", "B", "C"))) {
final CSVRecord shortRec = parser.iterator().next();
shortRec.toMap();
}
public void testToMap() {
final Map<String, String> map = this.recordWithHeader.toMap();
this.validateMap(map, true);
}
@Test
@ -208,6 +248,14 @@ public class CSVRecordTest {
}
}
@Test
public void testToMapWithShortRecord() throws Exception {
try (final CSVParser parser = CSVParser.parse("a,b", CSVFormat.DEFAULT.withHeader("A", "B", "C"))) {
final CSVRecord shortRec = parser.iterator().next();
shortRec.toMap();
}
}
private void validateMap(final Map<String, String> map, final boolean allowsNulls) {
assertTrue(map.containsKey("first"));
assertTrue(map.containsKey("second"));

View File

@ -24,7 +24,6 @@ import java.nio.charset.StandardCharsets;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.commons.csv.QuoteMode;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

View File

@ -0,0 +1,80 @@
/*
* 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.commons.csv.issues;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.apache.commons.csv.CSVRecord;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
public class JiraCsv248Test {
/**
* Test deserialisation of a CSVRecord created using version 1.6.
*
* <p>This test asserts that serialization from 1.8 onwards is consistent with
* previous versions. Serialization was broken in version 1.7.
*
* @throws IOException Signals that an I/O exception has occurred.
* @throws ClassNotFoundException If the CSVRecord cannot be deserialized
*/
@Test
public void testJiraCsv248() throws IOException, ClassNotFoundException {
// Record was originally created using CSV version 1.6 with the following code:
//try (final CSVParser parser = CSVParser.parse("A,B\n#my comment\nOne,Two", CSVFormat.DEFAULT.withHeader().withCommentMarker('#'))) {
// CSVRecord rec = parser.iterator().next();
//}
try (InputStream in = getTestInput();
ObjectInputStream ois = new ObjectInputStream(in)) {
final Object object = ois.readObject();
assertTrue(object instanceof CSVRecord);
final CSVRecord rec = (CSVRecord) object;
assertEquals(1L, rec.getRecordNumber());
assertEquals("One", rec.get(0));
assertEquals("Two", rec.get(1));
assertEquals(2, rec.size());
// The comment and whitespace are ignored so this is not 17 but 4
assertEquals(4, rec.getCharacterPosition());
assertEquals("my comment", rec.getComment());
// The parser is not serialized
assertNull(rec.getParser());
// Check all header map functionality is absent
assertTrue(rec.isConsistent());
assertFalse(rec.isMapped("A"));
assertFalse(rec.isSet("A"));
assertEquals(0, rec.toMap().size());
// This will throw
try {
rec.get("A");
org.junit.jupiter.api.Assertions.fail("Access by name is not expected after deserialisation");
} catch (final IllegalStateException expected) {
// OK
}
}
}
private static InputStream getTestInput() {
return ClassLoader.getSystemClassLoader().getResourceAsStream("CSV-248/csvRecord.bin");
}
}

View File

@ -38,7 +38,7 @@ import org.junit.jupiter.api.Test;
/**
* Tests performance.
*
* To run this test, use: mvn test -Dtest=PeformanceTest
* To run this test, use: mvn test -Dtest=PerformanceTest
*/
@SuppressWarnings("boxing") // test code
public class PerformanceTest {
@ -112,12 +112,11 @@ public class PerformanceTest {
@Test
public void testReadBigFile() throws Exception {
long bestTime = Long.MAX_VALUE;
long count;
for (int i = 0; i < this.max; i++) {
final long startMillis;
long count;
try (final BufferedReader in = this.createBufferedReader()) {
startMillis = System.currentTimeMillis();
count = 0;
count = this.readAll(in);
}
final long totalMillis = System.currentTimeMillis() - startMillis;

Binary file not shown.