[CSV-248] Test the parser and map functionality after deserialization

Methods with unexpected return values (null or exceptions) have been
documented. All other methods will just fail as if the record came from
a parser without a header.
This commit is contained in:
aherbert 2020-01-21 12:22:48 +00:00
parent 7c5c08921c
commit 8d6772a320
2 changed files with 60 additions and 3 deletions

View File

@ -83,6 +83,12 @@ public final class CSVRecord implements Serializable, Iterable<String> {
/** /**
* Returns a value by name. * 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 provide {@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.
*
* @param name * @param name
* the name of the column to be retrieved. * the name of the column to be retrieved.
* @return the column value, maybe null depending on {@link CSVFormat#getNullString()}. * @return the column value, maybe null depending on {@link CSVFormat#getNullString()}.
@ -90,7 +96,9 @@ public final class CSVRecord implements Serializable, Iterable<String> {
* if no header mapping was provided * if no header mapping was provided
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if {@code name} is not mapped or if the record is inconsistent * if {@code name} is not mapped or if the record is inconsistent
* @see #isMapped(String)
* @see #isConsistent() * @see #isConsistent()
* @see #getParser()
* @see CSVFormat#withNullString(String) * @see CSVFormat#withNullString(String)
*/ */
public String get(final String name) { public String get(final String name) {
@ -136,12 +144,15 @@ public final class CSVRecord implements Serializable, Iterable<String> {
} }
private Map<String, Integer> getHeaderMapRaw() { private Map<String, Integer> getHeaderMapRaw() {
return parser.getHeaderMapRaw(); return parser == null ? null : parser.getHeaderMapRaw();
} }
/** /**
* Returns the parser. * 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.
*
* @return the parser. * @return the parser.
* @since 1.7 * @since 1.7
*/ */

View File

@ -23,12 +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.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.io.StringReader; import java.io.StringReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -192,15 +195,58 @@ public class CSVRecordTest {
} }
@Test @Test
public void testSerialization() throws IOException { public void testSerialization() throws IOException, ClassNotFoundException {
CSVRecord shortRec; CSVRecord shortRec;
try (final CSVParser parser = CSVParser.parse("a,b", CSVFormat.newFormat(','))) { try (final CSVParser parser = CSVParser.parse("A,B\n#my comment\nOne,Two", CSVFormat.DEFAULT.withHeader().withCommentMarker('#'))) {
shortRec = parser.iterator().next(); shortRec = parser.iterator().next();
} }
final ByteArrayOutputStream out = new ByteArrayOutputStream(); final ByteArrayOutputStream out = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(out)) { try (ObjectOutputStream oos = new ObjectOutputStream(out)) {
oos.writeObject(shortRec); 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 (IllegalStateException expected) {
// OK
}
}
}
/**
* Test deserialisation of a record created using version 1.6.
*
* @throws IOException Signals that an I/O exception has occurred.
*/
@Test
public void testDeserialisation() throws IOException {
CSVRecord shortRec;
try (final CSVParser parser = CSVParser.parse("A,B\n#my comment\nOne,Two", CSVFormat.DEFAULT.withHeader().withCommentMarker('#'))) {
shortRec = parser.iterator().next();
}
try (FileOutputStream out = new FileOutputStream("/tmp/csvRecord.ser");
ObjectOutputStream oos = new ObjectOutputStream(out)) {
oos.writeObject(shortRec);
}
} }
@Test @Test