From c21055b9093814ac8a96926e4a25d70f91d651a3 Mon Sep 17 00:00:00 2001 From: Jonn Smith Date: Wed, 30 Oct 2019 10:47:26 -0400 Subject: [PATCH] Fixes indexing for codecs that implement getPathToDataFile (#1429) * Updated IndexFactory so it is possible to index files with codecs that override getPathToDataFile. * Moved VCFRedirectCodec to it's own top level test class to share between tests * Fixes #1428 Co-authored-by: Jonn Smith Co-authored-by: Louis Bergelson --- .../htsjdk/tribble/index/IndexFactory.java | 19 +++++++-- .../tribble/AbstractFeatureReaderTest.java | 29 ++------------ .../java/htsjdk/tribble/VCFRedirectCodec.java | 33 ++++++++++++++++ .../tribble/index/IndexFactoryTest.java | 39 +++++++++++++++++++ .../redirectingCodecTest/vcf.gz.redirect | 2 +- .../redirectingCodecTest/vcf.redirect | 2 +- 6 files changed, 93 insertions(+), 31 deletions(-) create mode 100644 src/test/java/htsjdk/tribble/VCFRedirectCodec.java diff --git a/src/main/java/htsjdk/tribble/index/IndexFactory.java b/src/main/java/htsjdk/tribble/index/IndexFactory.java index 9cd1d66165..f9be841fe8 100644 --- a/src/main/java/htsjdk/tribble/index/IndexFactory.java +++ b/src/main/java/htsjdk/tribble/index/IndexFactory.java @@ -439,13 +439,24 @@ public FeatureIterator(final File inputFile, final FeatureCodec WRAPPER = SkippingByteChannel::new; - public static final String REDIRECTING_CODEC_TEST_FILES = "src/test/resources/htsjdk/tribble/AbstractFeatureReaderTest/redirectingCodecTest/"; /** * Asserts readability and correctness of VCF over HTTP. The VCF is indexed and requires and index. @@ -233,8 +230,8 @@ public SeekableByteChannel truncate(long size) throws IOException { @DataProvider public Object[][] getVcfRedirects(){ return new Object[][]{ - {REDIRECTING_CODEC_TEST_FILES + "vcf.redirect"}, - {REDIRECTING_CODEC_TEST_FILES + "vcf.gz.redirect"} + {VCFRedirectCodec.REDIRECTING_CODEC_TEST_FILE_ROOT + "vcf.redirect"}, + {VCFRedirectCodec.REDIRECTING_CODEC_TEST_FILE_ROOT + "vcf.gz.redirect"} }; } @@ -244,8 +241,8 @@ public Object[][] getVcfRedirects(){ */ @Test(dataProvider = "getVcfRedirects") public void testCodecWithGetPathToDataFile(String vcfRedirect) throws IOException { - final VcfRedirectCodec vcfRedirectCodec = new VcfRedirectCodec(); - final String vcf = REDIRECTING_CODEC_TEST_FILES + "dataFiles/test.vcf"; + final VCFRedirectCodec vcfRedirectCodec = new VCFRedirectCodec(); + final String vcf = VCFRedirectCodec.REDIRECTING_CODEC_TEST_FILE_ROOT + "dataFiles/test.vcf"; Assert.assertTrue(vcfRedirectCodec.canDecode(vcfRedirect), "should have been able to decode " + vcfRedirect); try(FeatureReader redirectReader = AbstractFeatureReader.getFeatureReader(vcfRedirect, vcfRedirectCodec, false); FeatureReader directReader = AbstractFeatureReader.getFeatureReader(vcf, new VCFCodec(), false)){ @@ -260,22 +257,4 @@ public void testCodecWithGetPathToDataFile(String vcfRedirect) throws IOExceptio } } - /** - * codec which redirects to another location after reading the input file - */ - private static class VcfRedirectCodec extends VCFCodec{ - @Override - public boolean canDecode(String potentialInput) { - return super.canDecode(this.getPathToDataFile(potentialInput)); - } - - @Override - public String getPathToDataFile(String path) { - try { - return Files.readAllLines(IOUtil.getPath(path)).get(0); - } catch (IOException e) { - throw new RuntimeIOException(e); - } - } - } } diff --git a/src/test/java/htsjdk/tribble/VCFRedirectCodec.java b/src/test/java/htsjdk/tribble/VCFRedirectCodec.java new file mode 100644 index 0000000000..0027e6321c --- /dev/null +++ b/src/test/java/htsjdk/tribble/VCFRedirectCodec.java @@ -0,0 +1,33 @@ +package htsjdk.tribble; + +import htsjdk.samtools.util.IOUtil; +import htsjdk.samtools.util.RuntimeIOException; +import htsjdk.variant.vcf.VCFCodec; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +/** + * Test codec which redirects to another location after reading the input file + * It's an example of a codec which uses {@link FeatureCodec#getPathToDataFile(String)} + */ +public class VCFRedirectCodec extends VCFCodec { + public static final String REDIRECTING_CODEC_TEST_FILE_ROOT = "src/test/resources/htsjdk/tribble/AbstractFeatureReaderTest/redirectingCodecTest/"; + + @Override + public boolean canDecode(final String potentialInput) { + return super.canDecode(this.getPathToDataFile(potentialInput)); + } + + @Override + public String getPathToDataFile(final String path) { + try { + final Path inputPath = IOUtil.getPath(path); + final Path dataFilePath = IOUtil.getPath(Files.readAllLines(inputPath).get(0)); + return inputPath.getParent().resolve(dataFilePath).toString(); + } catch (final IOException e) { + throw new RuntimeIOException(e); + } + } +} diff --git a/src/test/java/htsjdk/tribble/index/IndexFactoryTest.java b/src/test/java/htsjdk/tribble/index/IndexFactoryTest.java index 414e66358a..5904776f47 100644 --- a/src/test/java/htsjdk/tribble/index/IndexFactoryTest.java +++ b/src/test/java/htsjdk/tribble/index/IndexFactoryTest.java @@ -29,12 +29,15 @@ import htsjdk.samtools.SAMSequenceRecord; import htsjdk.samtools.util.IOUtil; import htsjdk.samtools.util.Interval; +import htsjdk.tribble.AbstractFeatureReader; import htsjdk.tribble.TestUtils; import htsjdk.tribble.Tribble; import htsjdk.tribble.TribbleException; +import htsjdk.tribble.VCFRedirectCodec; import htsjdk.tribble.bed.BEDCodec; import htsjdk.tribble.index.tabix.TabixFormat; import htsjdk.tribble.index.tabix.TabixIndex; +import htsjdk.tribble.readers.LineIterator; import htsjdk.variant.bcf2.BCF2Codec; import htsjdk.variant.variantcontext.VariantContext; import htsjdk.variant.vcf.VCFCodec; @@ -219,4 +222,40 @@ public void testCreateLinearIndexFromBCF(final File inputBCF) throws IOException } } } + + @DataProvider + public Object[][] getRedirectFiles(){ + return new Object[][] { + {VCFRedirectCodec.REDIRECTING_CODEC_TEST_FILE_ROOT + "vcf.gz.redirect", IndexFactory.IndexType.TABIX}, + {VCFRedirectCodec.REDIRECTING_CODEC_TEST_FILE_ROOT + "vcf.redirect", IndexFactory.IndexType.INTERVAL_TREE}, + {VCFRedirectCodec.REDIRECTING_CODEC_TEST_FILE_ROOT + "vcf.redirect", IndexFactory.IndexType.LINEAR} + }; + } + + @Test(dataProvider = "getRedirectFiles") + public void testIndexRedirectedFiles(String input, IndexFactory.IndexType type) throws IOException { + final VCFRedirectCodec codec = new VCFRedirectCodec(); + final File dir = IOUtil.createTempDir("redirec-test", "dir"); + try { + final File tmpInput = new File(dir, new File(input).getName()); + Files.copy(new File(input), tmpInput); + final File tmpDataFile = new File(codec.getPathToDataFile(tmpInput.toString())); + Assert.assertTrue(new File(tmpDataFile.getAbsoluteFile().getParent()).mkdir()); + final File originalDataFile = new File(codec.getPathToDataFile(input)); + Files.copy(originalDataFile, tmpDataFile); + + try(final AbstractFeatureReader featureReader = AbstractFeatureReader.getFeatureReader(tmpInput.getAbsolutePath(), codec, false)) { + Assert.assertFalse(featureReader.hasIndex()); + } + final Index index = IndexFactory.createIndex(tmpInput, codec, type); + index.writeBasedOnFeatureFile(tmpDataFile); + + try(final AbstractFeatureReader featureReader = AbstractFeatureReader.getFeatureReader(tmpInput.getAbsolutePath(), codec)) { + Assert.assertTrue(featureReader.hasIndex()); + Assert.assertEquals(featureReader.query("20",1110696,1230237).stream().count(), 2); + } + } finally { + IOUtil.recursiveDelete(dir.toPath()); + } + } } diff --git a/src/test/resources/htsjdk/tribble/AbstractFeatureReaderTest/redirectingCodecTest/vcf.gz.redirect b/src/test/resources/htsjdk/tribble/AbstractFeatureReaderTest/redirectingCodecTest/vcf.gz.redirect index e552554b0f..750633e867 100644 --- a/src/test/resources/htsjdk/tribble/AbstractFeatureReaderTest/redirectingCodecTest/vcf.gz.redirect +++ b/src/test/resources/htsjdk/tribble/AbstractFeatureReaderTest/redirectingCodecTest/vcf.gz.redirect @@ -1 +1 @@ -src/test/resources/htsjdk/tribble/AbstractFeatureReaderTest/redirectingCodecTest/dataFiles/test.vcf.gz \ No newline at end of file +dataFiles/test.vcf.gz \ No newline at end of file diff --git a/src/test/resources/htsjdk/tribble/AbstractFeatureReaderTest/redirectingCodecTest/vcf.redirect b/src/test/resources/htsjdk/tribble/AbstractFeatureReaderTest/redirectingCodecTest/vcf.redirect index a94bc44d13..bfe5d5734b 100644 --- a/src/test/resources/htsjdk/tribble/AbstractFeatureReaderTest/redirectingCodecTest/vcf.redirect +++ b/src/test/resources/htsjdk/tribble/AbstractFeatureReaderTest/redirectingCodecTest/vcf.redirect @@ -1 +1 @@ -src/test/resources/htsjdk/tribble/AbstractFeatureReaderTest/redirectingCodecTest/dataFiles/test.vcf \ No newline at end of file +dataFiles/test.vcf