package picard.illumina.parser; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import picard.PicardException; import java.io.File; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.List; public class FilterParserTest { private static final File TestDataDir = new File("testdata/picard/illumina/parserTests"); private static final File BaseCallsDir = new File(TestDataDir, "filterParser"); private static final boolean F = false; private static final boolean T = true; public static final Boolean[] s_1_0001_filter = {F, F, T, F, T, T, F, F, T, F, T, T, F, T, T}; public static final Boolean[] s_1_0002_filter = {F, F, F, F, F, T, T, F, F, F, F, T, F, F, F, T, T, T, T, T}; public static final Boolean[] s_1_0003_filter = {T, F, F, F, T, T, F, F}; public static final Boolean[] s_1_0004_filter = {T, F, F, F, F, T, F, F, F, F, T, F, F, F, F, T, T, F, F, T, T, F, T, F, T, T, F, F, T, T, F, T, T, T, T, F, T, T, T, T, F, T, F, F, F, T, F, T, F, T, T, F, F, T, T, T, F, F, T, T}; public static final Boolean[] tileToValue(int tile) { switch (tile) { case 1: return s_1_0001_filter; case 2: return s_1_0002_filter; case 3: return s_1_0003_filter; case 4: return s_1_0004_filter; } throw new RuntimeException("You shouldn't reach this statement!"); } public static final Boolean[] allTilesToValues(Integer[] tiles) { Boolean[][] values = new Boolean[tiles.length][]; for (int i = 0; i < tiles.length; i++) { values[i] = tileToValue(tiles[i]); } return arrayFlatten(values); } public static final List<Integer> arrayToList(final Integer[] array) { final List<Integer> list = new ArrayList<Integer>(); for (int item : array) { list.add(item); } return list; } public static final <T> T[] arrayFlatten(final T[][] arrays) { int total = 0; for (T[] arr : arrays) { total += arr.length; } int resultIndex = 0; final T[] result = (T[]) Array.newInstance(arrays[0][0].getClass(), total); for (int i = 0; i < arrays.length; i++) { System.arraycopy(arrays[i], 0, result, resultIndex, arrays[i].length); resultIndex += arrays[i].length; } return result; } @DataProvider(name = "passingTiles") public Object[][] passingTiles() { return new Object[][]{ {new Integer[]{1}}, {new Integer[]{2}}, {new Integer[]{4}}, {new Integer[]{1, 4}}, {new Integer[]{2, 3}}, {new Integer[]{1, 2, 3, 4}} }; } @Test(dataProvider = "passingTiles") public void passingParserTest(Integer[] tiles) { final IlluminaFileUtil fUtil = new IlluminaFileUtil(BaseCallsDir, 1); final Boolean[] values = allTilesToValues(tiles); final List<Integer> tileList = arrayToList(tiles); final FilterParser fp = new FilterParser(((PerTileFileUtil) fUtil.getUtil(IlluminaFileUtil.SupportedIlluminaFormat.Filter)).getFiles(tileList)); fp.verifyData(tileList, null); //filter parser doesn't care about cycle for (final boolean expectedValue : values) { Assert.assertTrue(fp.hasNext()); Assert.assertEquals(fp.next().isPf(), expectedValue); } Assert.assertFalse(fp.hasNext()); //seek back to the beginning and do it again! fp.seekToTile(tiles[0]); for (final boolean expectedValue : values) { Assert.assertTrue(fp.hasNext()); Assert.assertEquals(fp.next().isPf(), expectedValue); } Assert.assertFalse(fp.hasNext()); fp.close(); } @DataProvider(name = "seekToTile") public Object[][] seekToTile() { return new Object[][]{ //seek after how many, tiles to load, expected values {0, 2, new Integer[]{2}, new Boolean[][]{s_1_0002_filter}}, {4, 4, new Integer[]{1, 4}, new Boolean[][]{new Boolean[]{F, F, T, F}, s_1_0004_filter}}, {0, 3, new Integer[]{2, 3}, new Boolean[][]{s_1_0003_filter}}, {15, 3, new Integer[]{1, 2, 3, 4}, new Boolean[][]{s_1_0001_filter, s_1_0003_filter, s_1_0004_filter}} }; } @Test(dataProvider = "seekToTile") public void passingSeekingParserTest(int skipBefore, int tileToSkipTo, Integer[] tiles, Boolean[][] expectedValues) { final IlluminaFileUtil fUtil = new IlluminaFileUtil(BaseCallsDir, 1); final Boolean[] values = arrayFlatten(expectedValues); final List<Integer> tileList = arrayToList(tiles); final FilterParser fp = new FilterParser(((PerTileFileUtil) fUtil.getUtil(IlluminaFileUtil.SupportedIlluminaFormat.Filter)).getFiles(tileList)); int read = 0; for (final boolean expectedValue : values) { if (read == skipBefore) { fp.seekToTile(tileToSkipTo); } Assert.assertTrue(fp.hasNext()); Assert.assertEquals(fp.next().isPf(), expectedValue, " Failed on read: " + read); ++read; } Assert.assertFalse(fp.hasNext()); fp.close(); } @DataProvider(name = "failingVerifyTiles") public Object[][] failingVerifyTiles() { return new Object[][]{ {new Integer[]{1}, new Integer[]{2}}, {new Integer[]{2}, new Integer[]{1}}, {new Integer[]{4}, new Integer[]{5}}, {new Integer[]{1, 4}, new Integer[]{1, 3, 4}}, {new Integer[]{2, 3}, new Integer[]{2, 3, 4}}, {new Integer[]{1, 2, 3, 4}, new Integer[]{1, 2, 3, 4, 5}}, {new Integer[]{2, 3, 4}, new Integer[]{1, 2, 3, 4}} }; } @Test(dataProvider = "failingVerifyTiles", expectedExceptions = PicardException.class) public void verifyDataTest(final Integer[] initTiles, final Integer[] verifyTiles) { final IlluminaFileUtil fUtil = new IlluminaFileUtil(BaseCallsDir, 1); final List<Integer> initTileList = arrayToList(initTiles); final List<Integer> verifyTileList = arrayToList(verifyTiles); final FilterParser fp = new FilterParser(((PerTileFileUtil) fUtil.getUtil(IlluminaFileUtil.SupportedIlluminaFormat.Filter)).getFiles(initTileList)); fp.verifyData(verifyTileList, null); //filter parser doesn't care about cycle values fp.close(); } }