package picard.illumina;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import picard.illumina.parser.ReadDescriptor;
import picard.illumina.parser.ReadStructure;
import picard.illumina.parser.ReadType;
import java.util.ArrayList;
import java.util.List;
import static htsjdk.samtools.util.CollectionUtil.makeList;
import static picard.illumina.parser.ReadType.*;
public class ReadStructureTest {
//to make construction of lists more intelligible
public ReadDescriptor rd(final int length, final ReadType rt) {
return new ReadDescriptor(length, rt);
}
//Many of these readStructures would be non-sensical but check different test classes/combinations
@DataProvider(name="validReadStructures")
public Object[][] validReadStructures() {
return new Object[][] {
{"2T", makeList(rd(2, T)), 1, 0, 0},
{"1234B", makeList(rd(1234, B)), 0, 1, 0},
{Integer.MAX_VALUE + "S", makeList(rd(Integer.MAX_VALUE, S)), 0, 0, 1},
{"76T76T", makeList(rd(76, T), rd(76, T)), 2, 0, 0},
{"76T1B", makeList(rd(76, T), rd(1, B)), 1, 1, 0},
{"76B1T", makeList(rd(76, B), rd(1, T)), 1, 1, 0},
{"1S1B", makeList(rd(1, S), rd(1, B)), 0, 1, 1},
{"1T999S", makeList(rd(1, T), rd(999, S)), 1, 0, 1},
{"100T20T100T", makeList(rd(100, T), rd(20, T), rd(100, T)), 3, 0, 0},
{"2S50S10S", makeList(rd(2, S), rd(50, S), rd(10, S)), 0, 0, 3},
{"10T1B11T", makeList(rd(10, T), rd(1, B), rd(11, T)), 2, 1, 0},
{"201T13T111B", makeList(rd(201, T), rd(13, T), rd(111, B)), 2, 1, 0},
{"15B1T1T", makeList(rd(15, B), rd(1, T), rd(1, T)), 2, 1, 0},
{"99B7T6B", makeList(rd(99, B), rd(7, T), rd(6, B)), 1, 2, 0},
{"631B776S638T", makeList(rd(631, B), rd(776, S), rd(638, T)), 1, 1, 1},
{"3T7B60S2T", makeList(rd(3, T), rd(7, B), rd(60, S), rd(2, T)), 2, 1, 1},
{"20B9S100T1T", makeList(rd(20, B), rd(9, S), rd(100, T), rd(1, T)), 2, 1, 1},
{"33T42B9T81B", makeList(rd(33, T), rd(42, B), rd(9, T), rd(81, B)), 2, 2, 0},
{"28B56B13T123S", makeList(rd(28, B), rd(56, B), rd(13, T), rd(123,S)), 1, 2, 1},
{"92S8B8B32B", makeList(rd(92, S), rd(8, B), rd(8, B), rd(32, B)), 0, 3, 1},
{"2S88B7T8S9T9T84B100S2S4B3B", makeList(rd(2,S), rd(88,B), rd(7,T), rd(8,S), rd(9,T), rd(9,T), rd(84,B), rd(100,S), rd(2,S), rd(4,B), rd(3,B)), 3, 4, 4}
};
}
@DataProvider(name="invalidReadStructures")
public Object[][] invalidReadStructures() {
return new Object[][]{
{"", new ArrayList<ReadDescriptor>()},
{"0T", makeList(rd(0, T))},
{"-1T", makeList(rd(-1, T))},
{"0S" , makeList(rd(0, S))},
{"-1B", makeList(rd(-1, B))},
{"8C", null},
{"B5", null},
{"SS", null},
{"75TS", null},
{"8*T", null},
{"-66S1B", makeList(rd(-66, S), rd(1, B))},
{"-0T5B8C", null},
{"77T82B0S", makeList(rd(77, T), rd(82, B), rd(0, S))}
};
}
@DataProvider(name="invalidReadStructuresFromList")
public Object[][] invalidReadStructuresFromList() {
int numTests = 0;
for(final Object [] args : invalidReadStructures()) {
if(args[1] != null) ++numTests;
}
final Object [][] outObjs = new Object[numTests][2];
numTests = 0;
for(final Object [] args : invalidReadStructures()) {
if(args[1] != null) {
outObjs[numTests++] = args;
}
}
return outObjs;
}
@Test(dataProvider = "validReadStructures")
public void testValidStructuresFromString(final String rsString, final List<ReadDescriptor> descriptors, final int numTemplates, final int numBarcodes, final int numSkips) {
final ReadStructure readStructure = new ReadStructure(rsString);
testReadStructure(readStructure, rsString, descriptors, numTemplates, numBarcodes, numSkips);
}
@Test(dataProvider = "validReadStructures")
public void testValidStructuresFromList(final String rsString, final List<ReadDescriptor> descriptors, final int numTemplates, final int numBarcodes, final int numSkips) {
final ReadStructure readStructure = new ReadStructure(descriptors);
testReadStructure(readStructure, rsString, descriptors, numTemplates, numBarcodes, numSkips);
}
private void testReadStructure(final ReadStructure readStructure, final String structureString, final List<ReadDescriptor> descriptors, final int numTemplates, final int numBarcodes, final int numSkips) {
Assert.assertEquals(readStructure.toString(), structureString);
int totalCycles = 0;
int tIndex = 0;
int bIndex = 0;
int sIndex = 0;
for(int i = 0; i < descriptors.size(); i++) {
Assert.assertEquals(readStructure.descriptors.get(i), descriptors.get(i));
switch(readStructure.descriptors.get(i).type) {
case T:
Assert.assertEquals(i, readStructure.templates.getIndices()[tIndex++]);
break;
case B:
Assert.assertEquals(i, readStructure.barcodes.getIndices()[bIndex++]);
break;
case S:
Assert.assertEquals(i, readStructure.skips.getIndices()[sIndex++]);
break;
default:
Assert.fail("Unrecognized read type: " + readStructure.descriptors.get(i).type);
}
totalCycles += readStructure.descriptors.get(i).length;
}
Assert.assertEquals(readStructure.totalCycles, totalCycles);
Assert.assertEquals(readStructure.barcodes.length(), numBarcodes);
Assert.assertEquals(readStructure.templates.length(), numTemplates);
Assert.assertEquals(readStructure.skips.length(), numSkips);
}
@Test(dataProvider = "invalidReadStructures", expectedExceptions = IllegalArgumentException.class)
public void testInvalidReadStructureFromString(final String rsString, final List<ReadDescriptor> descriptors) {
final ReadStructure readStructure = new ReadStructure(rsString);
}
@Test(dataProvider = "invalidReadStructuresFromList", expectedExceptions = IllegalArgumentException.class)
public void testInvalidReadStructureFromList(final String rsString, final List<ReadDescriptor> descriptors) {
final ReadStructure readStructure = new ReadStructure(descriptors);
}
@DataProvider(name="substructuresToReadStructureData")
public Object [][] substructureToReadStructureData() {
return new Object[][] {
{new ReadStructure("10T10T").templates, "10T10T" },
{new ReadStructure("10T8B10T").nonSkips, "10T8B10T"},
{new ReadStructure("8S10T8B8S10T").nonSkips, "10T8B10T"},
{new ReadStructure("10T8S8S10T").skips, "8S8S" },
{new ReadStructure("8B").barcodes, "8B" }
};
}
@Test(dataProvider = "substructuresToReadStructureData")
public void testSubstructureToReadStructure(final ReadStructure.Substructure substructure, final String outputRs) {
Assert.assertEquals(substructure.toReadStructure().toString(), outputRs);
}
@DataProvider(name="substructureToReadStructureNegativeData")
public Object[][] substructureToReadStructureNegativeData() {
return new Object[][] {
{new ReadStructure("10T").barcodes },
{new ReadStructure("10S").nonSkips },
{new ReadStructure("10S8B").templates},
};
}
@Test(dataProvider = "substructureToReadStructureNegativeData", expectedExceptions = IllegalArgumentException.class)
public void testSubstructureToReadStructure(final ReadStructure.Substructure substructure) {
substructure.toReadStructure().toString();
}
}