JAL-1270 JUnit to TestNG refactoring
[jalview.git] / test / jalview / datamodel / SequenceTest.java
1 package jalview.datamodel;
2
3 import static org.testng.AssertJUnit.assertSame;
4 import static org.testng.AssertJUnit.assertEquals;
5 import static org.testng.AssertJUnit.assertTrue;
6 import static org.testng.AssertJUnit.assertNull;
7 import org.testng.annotations.Test;
8 import org.testng.annotations.BeforeMethod;
9 import java.util.Arrays;
10 import java.util.List;
11
12 public class SequenceTest
13 {
14   SequenceI seq;
15
16   @BeforeMethod
17   public void setUp()
18   {
19     seq = new Sequence("FER1", "AKPNGVL");
20   }
21   @Test
22   public void testInsertGapsAndGapmaps()
23   {
24     SequenceI aseq = seq.deriveSequence();
25     aseq.insertCharAt(2, 3, '-');
26     aseq.insertCharAt(6, 3, '-');
27     assertEquals("Gap insertions not correct", "AK---P---NGVL",
28             aseq.getSequenceAsString());
29     List<int[]> gapInt = aseq.getInsertions();
30     assertEquals("Gap interval 1 start wrong", 2, gapInt.get(0)[0]);
31     assertEquals("Gap interval 1 end wrong", 4, gapInt.get(0)[1]);
32     assertEquals("Gap interval 2 start wrong", 6, gapInt.get(1)[0]);
33     assertEquals("Gap interval 2 end wrong", 8, gapInt.get(1)[1]);
34   }
35
36   @Test
37   public void testGetAnnotation()
38   {
39     // initial state returns null not an empty array
40     assertNull(seq.getAnnotation());
41     AlignmentAnnotation ann = addAnnotation("label1", "desc1", "calcId1",
42             1f);
43     AlignmentAnnotation[] anns = seq.getAnnotation();
44     assertEquals(1, anns.length);
45     assertSame(ann, anns[0]);
46
47     // removing all annotations reverts array to null
48     seq.removeAlignmentAnnotation(ann);
49     assertNull(seq.getAnnotation());
50   }
51
52   @Test
53   public void testGetAnnotation_forLabel()
54   {
55     AlignmentAnnotation ann1 = addAnnotation("label1", "desc1", "calcId1", 1f);
56     AlignmentAnnotation ann2 = addAnnotation("label2", "desc2", "calcId2", 1f);
57     AlignmentAnnotation ann3 = addAnnotation("label1", "desc3", "calcId3", 1f);
58     AlignmentAnnotation[] anns = seq.getAnnotation("label1");
59     assertEquals(2, anns.length);
60     assertSame(ann1, anns[0]);
61     assertSame(ann3, anns[1]);
62   }
63
64   private AlignmentAnnotation addAnnotation(String label,
65           String description, String calcId,
66           float value)
67   {
68     final AlignmentAnnotation annotation = new AlignmentAnnotation(label, description,
69             value);
70     annotation.setCalcId(calcId);
71     seq.addAlignmentAnnotation(annotation);
72     return annotation;
73   }
74
75   @Test
76   public void testGetAlignmentAnnotations_forCalcIdAndLabel()
77   {
78     AlignmentAnnotation ann1 = addAnnotation("label1", "desc1", "calcId1",
79             1f);
80     AlignmentAnnotation ann2 = addAnnotation("label2", "desc2", "calcId2",
81             1f);
82     AlignmentAnnotation ann3 = addAnnotation("label2", "desc3", "calcId3",
83             1f);
84     AlignmentAnnotation ann4 = addAnnotation("label2", "desc3", "calcId2",
85             1f);
86     AlignmentAnnotation ann5 = addAnnotation("label5", "desc3", null,
87             1f);
88     AlignmentAnnotation ann6 = addAnnotation(null, "desc3", "calcId3",
89             1f);
90     List<AlignmentAnnotation> anns = seq.getAlignmentAnnotations("calcId2",
91             "label2");
92     assertEquals(2, anns.size());
93     assertSame(ann2, anns.get(0));
94     assertSame(ann4, anns.get(1));
95     
96     assertTrue(seq.getAlignmentAnnotations("calcId2", "label3").isEmpty());
97     assertTrue(seq.getAlignmentAnnotations("calcId3", "label5").isEmpty());
98     assertTrue(seq.getAlignmentAnnotations("calcId2", null).isEmpty());
99     assertTrue(seq.getAlignmentAnnotations(null, "label3").isEmpty());
100     assertTrue(seq.getAlignmentAnnotations(null, null).isEmpty());
101   }
102
103   /**
104    * Tests for addAlignmentAnnotation. Note this method has the side-effect of
105    * setting the sequenceRef on the annotation. Adding the same annotation twice
106    * should be ignored.
107    */
108   @Test
109   public void testAddAlignmentAnnotation()
110   {
111     assertNull(seq.getAnnotation());
112     final AlignmentAnnotation annotation = new AlignmentAnnotation("a",
113             "b", 2d);
114     assertNull(annotation.sequenceRef);
115     seq.addAlignmentAnnotation(annotation);
116     assertSame(seq, annotation.sequenceRef);
117     AlignmentAnnotation[] anns = seq.getAnnotation();
118     assertEquals(1, anns.length);
119     assertSame(annotation, anns[0]);
120
121     // re-adding does nothing
122     seq.addAlignmentAnnotation(annotation);
123     anns = seq.getAnnotation();
124     assertEquals(1, anns.length);
125     assertSame(annotation, anns[0]);
126
127     // an identical but different annotation can be added
128     final AlignmentAnnotation annotation2 = new AlignmentAnnotation("a",
129             "b", 2d);
130     seq.addAlignmentAnnotation(annotation2);
131     anns = seq.getAnnotation();
132     assertEquals(2, anns.length);
133     assertSame(annotation, anns[0]);
134     assertSame(annotation2, anns[1]);
135
136   }
137
138   @Test
139   public void testGetStartGetEnd()
140   {
141     SequenceI seq = new Sequence("test", "ABCDEF");
142     assertEquals(1, seq.getStart());
143     assertEquals(6, seq.getEnd());
144
145     seq = new Sequence("test", "--AB-C-DEF--");
146     assertEquals(1, seq.getStart());
147     assertEquals(6, seq.getEnd());
148
149     seq = new Sequence("test", "----");
150     assertEquals(1, seq.getStart());
151     assertEquals(0, seq.getEnd()); // ??
152   }
153
154   /**
155    * Tests for the method that returns an alignment column position (base 1) for
156    * a given sequence position (base 1).
157    */
158   @Test
159   public void testFindIndex()
160   {
161     SequenceI seq = new Sequence("test", "ABCDEF");
162     assertEquals(0, seq.findIndex(0));
163     assertEquals(1, seq.findIndex(1));
164     assertEquals(5, seq.findIndex(5));
165     assertEquals(6, seq.findIndex(6));
166     assertEquals(6, seq.findIndex(9));
167
168     seq = new Sequence("test", "-A--B-C-D-E-F--");
169     assertEquals(2, seq.findIndex(1));
170     assertEquals(5, seq.findIndex(2));
171     assertEquals(7, seq.findIndex(3));
172
173     // before start returns 0
174     assertEquals(0, seq.findIndex(0));
175     assertEquals(0, seq.findIndex(-1));
176
177     // beyond end returns last residue column
178     assertEquals(13, seq.findIndex(99));
179
180   }
181
182   /**
183    * Tests for the method that returns a dataset sequence position (base 1) for
184    * an aligned column position (base 0).
185    */
186   @Test
187   public void testFindPosition()
188   {
189     SequenceI seq = new Sequence("test", "ABCDEF");
190     assertEquals(1, seq.findPosition(0));
191     assertEquals(6, seq.findPosition(5));
192     // assertEquals(-1, seq.findPosition(6)); // fails
193
194     seq = new Sequence("test", "AB-C-D--");
195     assertEquals(1, seq.findPosition(0));
196     assertEquals(2, seq.findPosition(1));
197     // gap position 'finds' residue to the right (not the left as per javadoc)
198     assertEquals(3, seq.findPosition(2));
199     assertEquals(3, seq.findPosition(3));
200     assertEquals(4, seq.findPosition(4));
201     assertEquals(4, seq.findPosition(5));
202     // returns 1 more than sequence length if off the end ?!?
203     assertEquals(5, seq.findPosition(6));
204     assertEquals(5, seq.findPosition(7));
205
206     seq = new Sequence("test", "--AB-C-DEF--");
207     assertEquals(1, seq.findPosition(0));
208     assertEquals(1, seq.findPosition(1));
209     assertEquals(1, seq.findPosition(2));
210     assertEquals(2, seq.findPosition(3));
211     assertEquals(3, seq.findPosition(4));
212     assertEquals(3, seq.findPosition(5));
213     assertEquals(4, seq.findPosition(6));
214     assertEquals(4, seq.findPosition(7));
215     assertEquals(5, seq.findPosition(8));
216     assertEquals(6, seq.findPosition(9));
217     assertEquals(7, seq.findPosition(10));
218     assertEquals(7, seq.findPosition(11));
219   }
220
221   @Test
222   public void testDeleteChars()
223   {
224     SequenceI seq = new Sequence("test", "ABCDEF");
225     assertEquals(1, seq.getStart());
226     assertEquals(6, seq.getEnd());
227     seq.deleteChars(2, 3);
228     assertEquals("ABDEF", seq.getSequenceAsString());
229     assertEquals(1, seq.getStart());
230     assertEquals(5, seq.getEnd());
231
232     seq = new Sequence("test", "ABCDEF");
233     seq.deleteChars(0, 2);
234     assertEquals("CDEF", seq.getSequenceAsString());
235     assertEquals(3, seq.getStart());
236     assertEquals(6, seq.getEnd());
237   }
238
239   @Test
240   public void testInsertCharAt()
241   {
242     // non-static methods:
243     SequenceI seq = new Sequence("test", "ABCDEF");
244     seq.insertCharAt(0, 'z');
245     assertEquals("zABCDEF", seq.getSequenceAsString());
246     seq.insertCharAt(2, 2, 'x');
247     assertEquals("zAxxBCDEF", seq.getSequenceAsString());
248
249     // for static method see StringUtilsTest
250   }
251
252   /**
253    * Test the method that returns an array of aligned sequence positions where
254    * the array index is the data sequence position (both base 0).
255    */
256   @Test
257   public void testGapMap()
258   {
259     SequenceI seq = new Sequence("test", "-A--B-CD-E--F-");
260     seq.createDatasetSequence();
261     assertEquals("[1, 4, 6, 7, 9, 12]", Arrays.toString(seq.gapMap()));
262   }
263
264   /**
265    * Test the method that gets sequence features, either from the sequence or
266    * its dataset.
267    */
268   @Test
269   public void testGetSequenceFeatures()
270   {
271     SequenceI seq = new Sequence("test", "GATCAT");
272     seq.createDatasetSequence();
273
274     assertNull(seq.getSequenceFeatures());
275
276     /*
277      * SequenceFeature on sequence
278      */
279     SequenceFeature sf = new SequenceFeature();
280     seq.addSequenceFeature(sf);
281     SequenceFeature[] sfs = seq.getSequenceFeatures();
282     assertEquals(1, sfs.length);
283     assertSame(sf, sfs[0]);
284
285     /*
286      * SequenceFeature on sequence and dataset sequence; returns that on
287      * sequence
288      */
289     SequenceFeature sf2 = new SequenceFeature();
290     seq.getDatasetSequence().addSequenceFeature(sf2);
291     sfs = seq.getSequenceFeatures();
292     assertEquals(1, sfs.length);
293     assertSame(sf, sfs[0]);
294
295     /*
296      * SequenceFeature on dataset sequence only
297      */
298     seq.setSequenceFeatures(null);
299     sfs = seq.getSequenceFeatures();
300     assertEquals(1, sfs.length);
301     assertSame(sf2, sfs[0]);
302
303     /*
304      * Corrupt case - no SequenceFeature, dataset's dataset is the original
305      * sequence. Test shows no infinite loop results.
306      */
307     seq.getDatasetSequence().setSequenceFeatures(null);
308     seq.getDatasetSequence().setDatasetSequence(seq); // loop!
309     assertNull(seq.getSequenceFeatures());
310   }
311
312   /**
313    * Test the method that returns an array, indexed by sequence position, whose
314    * entries are the residue positions at the sequence position (or to the right
315    * if a gap)
316    */
317   @Test
318   public void testFindPositionMap()
319   {
320     /*
321      * Note: Javadoc for findPosition says it returns the residue position to
322      * the left of a gapped position; in fact it returns the position to the
323      * right. Also it returns a non-existent residue position for a gap beyond
324      * the sequence.
325      */
326     Sequence seq = new Sequence("TestSeq", "AB.C-D E.");
327     int[] map = seq.findPositionMap();
328     assertEquals(Arrays.toString(new int[]
329     { 1, 2, 3, 3, 4, 4, 5, 5, 6 }), Arrays.toString(map));
330   }
331
332   /**
333    * Test for getSubsequence
334    */
335   @Test
336   public void testGetSubsequence()
337   {
338     SequenceI seq = new Sequence("TestSeq", "ABCDEFG");
339     seq.createDatasetSequence();
340
341     // positions are base 0, end position is exclusive
342     SequenceI subseq = seq.getSubSequence(2, 4);
343
344     assertEquals("CD", subseq.getSequenceAsString());
345     // start/end are base 1 positions
346     assertEquals(3, subseq.getStart());
347     assertEquals(4, subseq.getEnd());
348     // subsequence shares the full dataset sequence
349     assertSame(seq.getDatasetSequence(), subseq.getDatasetSequence());
350   }
351
352   /**
353    * Test for deriveSequence applied to a sequence with a dataset
354    */
355   @Test
356   public void testDeriveSequence_existingDataset()
357   {
358     SequenceI seq = new Sequence("Seq1", "CD");
359     seq.setDatasetSequence(new Sequence("Seq1", "ABCDEF"));
360     seq.setStart(3);
361     seq.setEnd(4);
362     SequenceI derived = seq.deriveSequence();
363     assertEquals("CD", derived.getSequenceAsString());
364     assertSame(seq.getDatasetSequence(), derived.getDatasetSequence());
365   }
366
367   /**
368    * Test for deriveSequence applied to an ungapped sequence with no dataset
369    */
370   @Test
371   public void testDeriveSequence_noDatasetUngapped()
372   {
373     SequenceI seq = new Sequence("Seq1", "ABCDEF");
374     assertEquals(1, seq.getStart());
375     assertEquals(6, seq.getEnd());
376     SequenceI derived = seq.deriveSequence();
377     assertEquals("ABCDEF", derived.getSequenceAsString());
378     assertEquals("ABCDEF", derived.getDatasetSequence()
379             .getSequenceAsString());
380   }
381
382   /**
383    * Test for deriveSequence applied to a gapped sequence with no dataset
384    */
385   @Test
386   public void testDeriveSequence_noDatasetGapped()
387   {
388     SequenceI seq = new Sequence("Seq1", "AB-C.D EF");
389     assertEquals(1, seq.getStart());
390     assertEquals(6, seq.getEnd());
391     assertNull(seq.getDatasetSequence());
392     SequenceI derived = seq.deriveSequence();
393     assertEquals("AB-C.D EF", derived.getSequenceAsString());
394     assertEquals("ABCDEF", derived.getDatasetSequence()
395             .getSequenceAsString());
396   }
397 }