Skip to content

Commit 6c059a6

Browse files
committed
working on adding tests
1 parent 1239e98 commit 6c059a6

File tree

5 files changed

+104
-40
lines changed

5 files changed

+104
-40
lines changed

src/main/java/htsjdk/tribble/index/AbstractIndex.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.io.BufferedOutputStream;
3030
import java.io.File;
3131
import java.io.IOException;
32+
import java.nio.charset.StandardCharsets;
3233
import java.nio.file.Files;
3334
import java.nio.file.Path;
3435
import java.util.ArrayList;
@@ -302,10 +303,10 @@ private void writeHeader(final LittleEndianOutputStream dos) throws IOException
302303
private void readHeader(final LittleEndianInputStream dis) throws IOException {
303304

304305
version = dis.readInt();
305-
indexedPath = IOUtil.getPath(dis.readString());
306+
indexedPath = IOUtil.getPath(dis.readString(StandardCharsets.US_ASCII));
306307
indexedFileSize = dis.readLong();
307308
indexedFileTS = dis.readLong();
308-
indexedFileMD5 = dis.readString();
309+
indexedFileMD5 = dis.readString(StandardCharsets.US_ASCII);
309310
flags = dis.readInt();
310311
if (version < 3 && (flags & SEQUENCE_DICTIONARY_FLAG) == SEQUENCE_DICTIONARY_FLAG) {
311312
readSequenceDictionary(dis);
@@ -314,8 +315,8 @@ private void readHeader(final LittleEndianInputStream dis) throws IOException {
314315
if (version >= 3) {
315316
int nProperties = dis.readInt();
316317
while (nProperties-- > 0) {
317-
final String key = dis.readString();
318-
final String value = dis.readString();
318+
final String key = dis.readString(StandardCharsets.US_ASCII);
319+
final String value = dis.readString(StandardCharsets.US_ASCII);
319320
properties.put(key, value);
320321
}
321322
}
@@ -332,7 +333,7 @@ private void readSequenceDictionary(final LittleEndianInputStream dis) throws IO
332333
final int size = dis.readInt();
333334
if (size < 0) throw new IllegalStateException("Size of the sequence dictionary entries is negative");
334335
for (int x = 0; x < size; x++) {
335-
dis.readString();
336+
dis.readString(StandardCharsets.US_ASCII);
336337
dis.readInt();
337338
}
338339
}

src/main/java/htsjdk/tribble/index/interval/IntervalTreeIndex.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import java.io.IOException;
2727
import java.io.InputStream;
28+
import java.nio.charset.StandardCharsets;
2829
import java.nio.file.Path;
2930
import java.util.ArrayList;
3031
import java.util.Arrays;
@@ -210,7 +211,7 @@ public void read(final LittleEndianInputStream dis) throws IOException {
210211

211212
tree = new IntervalTree();
212213

213-
name = dis.readString();
214+
name = dis.readString(StandardCharsets.US_ASCII);
214215
int nIntervals = dis.readInt();
215216
while (nIntervals-- > 0) {
216217

src/main/java/htsjdk/tribble/util/LittleEndianInputStream.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import java.io.FilterInputStream;
1717
import java.io.IOException;
1818
import java.io.InputStream;
19+
import java.nio.charset.Charset;
20+
import java.nio.charset.StandardCharsets;
1921

2022

2123
/**
@@ -105,22 +107,33 @@ public final float readFloat() throws IOException {
105107
}
106108

107109
/**
108-
* Read a null terminated byte array and return result as a string
109-
*
110-
* @return
111-
* @throws IOException
110+
* Read a null terminated byte array and return result as a String
111+
* This method decodes theh bytes as UTF-8 string
112+
* @throws IOException if reading from the stream fails for some reason
113+
* @throws EOFException if the stream ends without encountering a null terminator.
114+
* @deprecated Prefer the {@link #readString(Charset)} which allows specifying a charset explicitly
112115
*/
113-
116+
@Deprecated
114117
public String readString() throws IOException {
115-
ByteArrayOutputStream bis = new ByteArrayOutputStream(100);
118+
return readString(StandardCharsets.UTF_8);
119+
}
120+
121+
/**
122+
* Read a null terminated byte array and return result as a String
123+
* @param charset the Charset to use when decoding the bytes to a String
124+
* @throws IOException if reading from the stream fails for some reason
125+
* @throws EOFException if the stream ends without encountering a null terminator.
126+
*/
127+
public String readString(final Charset charset) throws IOException {
128+
final ByteArrayOutputStream bis = new ByteArrayOutputStream(100);
116129
int b;
117130
while ((b = in.read()) != 0) {
118131
if(b < 0) {
119132
throw new EOFException();
120133
}
121134
bis.write((byte)b);
122135
}
123-
return bis.toString();
136+
return bis.toString(charset.name());
124137
}
125138

126139

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package htsjdk.testutil;
2+
3+
import org.testng.Assert;
4+
5+
public interface TestCase<T> {
6+
void test(ThrowingSupplier<T> functionToTest);
7+
8+
9+
interface ThrowingConsumer<T> {
10+
void test(T a) throws Exception;
11+
}
12+
13+
static <T> TestCase<T> match(final T expected) {
14+
return new ComparisonTestCase<>((T actual) -> Assert.assertEquals(actual, expected));
15+
}
16+
17+
static <T> TestCase<T> mismatch(final T expected) {
18+
return new ComparisonTestCase<>((T actual) -> Assert.assertNotEquals(actual, expected));
19+
}
20+
21+
static <T> TestCase<T> exception(final Class<? extends Exception> exceptionClass) {
22+
return functionToTest -> Assert.assertThrows(exceptionClass, functionToTest::produce);
23+
}
24+
25+
interface ThrowingSupplier<T> {
26+
T produce() throws Exception;
27+
}
28+
}
29+
30+
final class ComparisonTestCase<T> implements TestCase<T> {
31+
private final ThrowingConsumer<T> test;
32+
33+
@Override
34+
public void test(ThrowingSupplier<T> supplier) {
35+
try {
36+
test.test(supplier.produce());
37+
} catch (AssertionError e) {
38+
throw e;
39+
} catch (Exception e) {
40+
throw new AssertionError(e);
41+
}
42+
}
43+
44+
ComparisonTestCase(ThrowingConsumer<T> test) {
45+
this.test = test;
46+
}
47+
48+
}
Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,46 @@
11
package htsjdk.tribble.util;
22

3-
import com.google.common.io.LittleEndianDataOutputStream;
43
import htsjdk.HtsjdkTest;
5-
import org.testng.Assert;
4+
import htsjdk.testutil.TestCase;
5+
import org.testng.annotations.DataProvider;
66
import org.testng.annotations.Test;
77

88
import java.io.BufferedInputStream;
9-
import java.io.BufferedOutputStream;
109
import java.io.EOFException;
1110
import java.io.FileInputStream;
1211
import java.io.FileOutputStream;
1312
import java.io.IOException;
14-
import java.io.OutputStream;
15-
import java.nio.file.Files;
16-
17-
import static org.testng.Assert.*;
13+
import java.io.PrintStream;
14+
import java.nio.charset.Charset;
15+
import java.nio.charset.StandardCharsets;
1816

1917
public class LittleEndianInputStreamTest extends HtsjdkTest {
2018

21-
@Test(expectedExceptions = EOFException.class)
22-
public void testReadStringEOF() throws IOException {
23-
final String emptyFile = "src/test/resources/htsjdk/tribble/util/string_with_extended_ascii_no_terminator.bin";
24-
try(final LittleEndianInputStream in = new LittleEndianInputStream(new BufferedInputStream(new FileInputStream(emptyFile)))){
25-
in.readString();
26-
}
27-
}
2819

29-
@Test
30-
public void testReadStringWithExtendedCharacters() throws IOException {
31-
final String emptyFile = "src/test/resources/htsjdk/tribble/util/string_with_extended_ascii_and_null_terminator.bin";
32-
try(final LittleEndianInputStream in = new LittleEndianInputStream(new BufferedInputStream(new FileInputStream(emptyFile)))){
33-
Assert.assertEquals(in.readString(), "very dràààààmatic and null terminated");
34-
}
20+
@DataProvider
21+
public Object[][] testCases() {
22+
final String missingTerminator = "src/test/resources/htsjdk/tribble/util/string_with_extended_ascii_no_terminator.bin";
23+
final String extendedAsciiFile = "src/test/resources/htsjdk/tribble/util/string_with_extended_ascii_and_null_terminator.bin";
24+
final Object utf8File = "src/test/resources/htsjdk/tribble/util/string_with_utf8_emoji_and_null_terminator.txt";
25+
return new Object[][]{
26+
{missingTerminator, StandardCharsets.ISO_8859_1, TestCase.exception(EOFException.class)},
27+
{missingTerminator, StandardCharsets.US_ASCII, TestCase.exception(EOFException.class)},
28+
{missingTerminator, StandardCharsets.UTF_8, TestCase.exception(EOFException.class)},
29+
{extendedAsciiFile, StandardCharsets.ISO_8859_1, TestCase.match("very dràààààmatic and null terminated")},
30+
{extendedAsciiFile, StandardCharsets.US_ASCII, TestCase.mismatch("very dràààààmatic and null terminated")},
31+
{extendedAsciiFile, StandardCharsets.UTF_8, TestCase.mismatch("very dràààààmatic and null terminated")},
32+
{utf8File, StandardCharsets.UTF_8, TestCase.match("🐋 UTF8 is Great 🐋")},
33+
{utf8File, StandardCharsets.ISO_8859_1, TestCase.mismatch("🐋 UTF8 is Great 🐋")}
34+
};
3535
}
3636

37-
38-
@Test(expectedExceptions = EOFException.class)
39-
public void write() throws IOException {
40-
final String emptyFile = "src/test/resources/htsjdk/tribble/util/string_with_extended_ascii_and_null_terminator.bin";
41-
try(final LittleEndianDataOutputStream out = new LittleEndianDataOutputStream(new FileOutputStream(emptyFile))){
42-
out.writeBytes("very dràààààmatic and null terminated\0");
43-
}
37+
@Test(dataProvider = "testCases")
38+
public void testAllCases(String filename, Charset charset, TestCase<String> expected) {
39+
expected.test(() -> {
40+
try(final LittleEndianInputStream in = new LittleEndianInputStream(new BufferedInputStream(new FileInputStream(filename)))){
41+
return in.readString(charset);
42+
}
43+
});
4444
}
45+
4546
}

0 commit comments

Comments
 (0)