Skip to content

Commit 8d6772a

Browse files
committed
[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.
1 parent 7c5c089 commit 8d6772a

2 files changed

Lines changed: 60 additions & 3 deletions

File tree

src/main/java/org/apache/commons/csv/CSVRecord.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,22 @@ public String get(final int i) {
8383
/**
8484
* Returns a value by name.
8585
*
86+
* <p>Note: This requires a field mapping obtained from the original parser.
87+
* A check using {@link #isMapped(String)} should be used to determine if a
88+
* mapping exists from the provide {@code name} to a field index. In this case an
89+
* exception will only be thrown if the record does not contain a field corresponding
90+
* to the mapping, that is the record length is not consistent with the mapping size.
91+
*
8692
* @param name
8793
* the name of the column to be retrieved.
8894
* @return the column value, maybe null depending on {@link CSVFormat#getNullString()}.
8995
* @throws IllegalStateException
9096
* if no header mapping was provided
9197
* @throws IllegalArgumentException
9298
* if {@code name} is not mapped or if the record is inconsistent
99+
* @see #isMapped(String)
93100
* @see #isConsistent()
101+
* @see #getParser()
94102
* @see CSVFormat#withNullString(String)
95103
*/
96104
public String get(final String name) {
@@ -136,12 +144,15 @@ public String getComment() {
136144
}
137145

138146
private Map<String, Integer> getHeaderMapRaw() {
139-
return parser.getHeaderMapRaw();
147+
return parser == null ? null : parser.getHeaderMapRaw();
140148
}
141149

142150
/**
143151
* Returns the parser.
144152
*
153+
* <p>Note: The parser is not part of the serialized state of the record. A null check
154+
* should be used when the record may have originated from a serialized form.
155+
*
145156
* @return the parser.
146157
* @since 1.7
147158
*/

src/test/java/org/apache/commons/csv/CSVRecordTest.java

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,15 @@
2323
import static org.junit.jupiter.api.Assertions.assertThrows;
2424
import static org.junit.jupiter.api.Assertions.assertTrue;
2525

26+
import java.io.ByteArrayInputStream;
2627
import java.io.ByteArrayOutputStream;
2728
import java.io.IOException;
29+
import java.io.ObjectInputStream;
2830
import java.io.ObjectOutputStream;
2931
import java.io.StringReader;
3032
import java.util.ArrayList;
3133
import java.util.Collections;
34+
import java.util.HashMap;
3235
import java.util.Map;
3336
import java.util.TreeMap;
3437
import java.util.concurrent.ConcurrentHashMap;
@@ -192,15 +195,58 @@ public void testRemoveAndAddColumns() throws IOException {
192195
}
193196

194197
@Test
195-
public void testSerialization() throws IOException {
198+
public void testSerialization() throws IOException, ClassNotFoundException {
196199
CSVRecord shortRec;
197-
try (final CSVParser parser = CSVParser.parse("a,b", CSVFormat.newFormat(','))) {
200+
try (final CSVParser parser = CSVParser.parse("A,B\n#my comment\nOne,Two", CSVFormat.DEFAULT.withHeader().withCommentMarker('#'))) {
198201
shortRec = parser.iterator().next();
199202
}
200203
final ByteArrayOutputStream out = new ByteArrayOutputStream();
201204
try (ObjectOutputStream oos = new ObjectOutputStream(out)) {
202205
oos.writeObject(shortRec);
203206
}
207+
final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
208+
try (ObjectInputStream ois = new ObjectInputStream(in)) {
209+
final Object object = ois.readObject();
210+
assertTrue(object instanceof CSVRecord);
211+
final CSVRecord rec = (CSVRecord) object;
212+
assertEquals(1L, rec.getRecordNumber());
213+
assertEquals("One", rec.get(0));
214+
assertEquals("Two", rec.get(1));
215+
assertEquals(2, rec.size());
216+
assertEquals(shortRec.getCharacterPosition(), rec.getCharacterPosition());
217+
assertEquals("my comment", rec.getComment());
218+
// The parser is not serialized
219+
assertNull(rec.getParser());
220+
// Check all header map functionality is absent
221+
assertTrue(rec.isConsistent());
222+
assertFalse(rec.isMapped("A"));
223+
assertFalse(rec.isSet("A"));
224+
assertEquals(0, rec.toMap().size());
225+
// This will throw
226+
try {
227+
rec.get("A");
228+
org.junit.jupiter.api.Assertions.fail("Access by name is not expected after deserialisation");
229+
} catch (IllegalStateException expected) {
230+
// OK
231+
}
232+
}
233+
}
234+
235+
/**
236+
* Test deserialisation of a record created using version 1.6.
237+
*
238+
* @throws IOException Signals that an I/O exception has occurred.
239+
*/
240+
@Test
241+
public void testDeserialisation() throws IOException {
242+
CSVRecord shortRec;
243+
try (final CSVParser parser = CSVParser.parse("A,B\n#my comment\nOne,Two", CSVFormat.DEFAULT.withHeader().withCommentMarker('#'))) {
244+
shortRec = parser.iterator().next();
245+
}
246+
try (FileOutputStream out = new FileOutputStream("/tmp/csvRecord.ser");
247+
ObjectOutputStream oos = new ObjectOutputStream(out)) {
248+
oos.writeObject(shortRec);
249+
}
204250
}
205251

206252
@Test

0 commit comments

Comments
 (0)