JAL-1925 update source version in license
[jalview.git] / test / jalview / datamodel / SequenceTest.java
index 3f91710..24d9193 100644 (file)
@@ -1,25 +1,62 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
+ * Copyright (C) 2015 The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.datamodel;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNull;
+import static org.testng.AssertJUnit.assertSame;
+import static org.testng.AssertJUnit.assertTrue;
 
+import java.util.Arrays;
 import java.util.List;
 
-import org.junit.Before;
-import org.junit.Test;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
 
 public class SequenceTest
 {
-  Sequence seq;
+  SequenceI seq;
 
-  @Before
+  @BeforeMethod(alwaysRun = true)
   public void setUp()
   {
     seq = new Sequence("FER1", "AKPNGVL");
   }
-  @Test
+
+  @Test(groups = { "Functional" })
+  public void testInsertGapsAndGapmaps()
+  {
+    SequenceI aseq = seq.deriveSequence();
+    aseq.insertCharAt(2, 3, '-');
+    aseq.insertCharAt(6, 3, '-');
+    assertEquals("Gap insertions not correct", "AK---P---NGVL",
+            aseq.getSequenceAsString());
+    List<int[]> gapInt = aseq.getInsertions();
+    assertEquals("Gap interval 1 start wrong", 2, gapInt.get(0)[0]);
+    assertEquals("Gap interval 1 end wrong", 4, gapInt.get(0)[1]);
+    assertEquals("Gap interval 2 start wrong", 6, gapInt.get(1)[0]);
+    assertEquals("Gap interval 2 end wrong", 8, gapInt.get(1)[1]);
+  }
+
+  @Test(groups = { "Functional" })
   public void testGetAnnotation()
   {
     // initial state returns null not an empty array
@@ -35,12 +72,15 @@ public class SequenceTest
     assertNull(seq.getAnnotation());
   }
 
-  @Test
+  @Test(groups = { "Functional" })
   public void testGetAnnotation_forLabel()
   {
-    AlignmentAnnotation ann1 = addAnnotation("label1", "desc1", "calcId1", 1f);
-    AlignmentAnnotation ann2 = addAnnotation("label2", "desc2", "calcId2", 1f);
-    AlignmentAnnotation ann3 = addAnnotation("label1", "desc3", "calcId3", 1f);
+    AlignmentAnnotation ann1 = addAnnotation("label1", "desc1", "calcId1",
+            1f);
+    AlignmentAnnotation ann2 = addAnnotation("label2", "desc2", "calcId2",
+            1f);
+    AlignmentAnnotation ann3 = addAnnotation("label1", "desc3", "calcId3",
+            1f);
     AlignmentAnnotation[] anns = seq.getAnnotation("label1");
     assertEquals(2, anns.length);
     assertSame(ann1, anns[0]);
@@ -48,17 +88,16 @@ public class SequenceTest
   }
 
   private AlignmentAnnotation addAnnotation(String label,
-          String description, String calcId,
-          float value)
+          String description, String calcId, float value)
   {
-    final AlignmentAnnotation annotation = new AlignmentAnnotation(label, description,
-            value);
+    final AlignmentAnnotation annotation = new AlignmentAnnotation(label,
+            description, value);
     annotation.setCalcId(calcId);
     seq.addAlignmentAnnotation(annotation);
     return annotation;
   }
 
-  @Test
+  @Test(groups = { "Functional" })
   public void testGetAlignmentAnnotations_forCalcIdAndLabel()
   {
     AlignmentAnnotation ann1 = addAnnotation("label1", "desc1", "calcId1",
@@ -69,16 +108,14 @@ public class SequenceTest
             1f);
     AlignmentAnnotation ann4 = addAnnotation("label2", "desc3", "calcId2",
             1f);
-    AlignmentAnnotation ann5 = addAnnotation("label5", "desc3", null,
-            1f);
-    AlignmentAnnotation ann6 = addAnnotation(null, "desc3", "calcId3",
-            1f);
+    AlignmentAnnotation ann5 = addAnnotation("label5", "desc3", null, 1f);
+    AlignmentAnnotation ann6 = addAnnotation(null, "desc3", "calcId3", 1f);
     List<AlignmentAnnotation> anns = seq.getAlignmentAnnotations("calcId2",
             "label2");
     assertEquals(2, anns.size());
     assertSame(ann2, anns.get(0));
     assertSame(ann4, anns.get(1));
-    
+
     assertTrue(seq.getAlignmentAnnotations("calcId2", "label3").isEmpty());
     assertTrue(seq.getAlignmentAnnotations("calcId3", "label5").isEmpty());
     assertTrue(seq.getAlignmentAnnotations("calcId2", null).isEmpty());
@@ -91,10 +128,10 @@ public class SequenceTest
    * setting the sequenceRef on the annotation. Adding the same annotation twice
    * should be ignored.
    */
-  @Test
+  @Test(groups = { "Functional" })
   public void testAddAlignmentAnnotation()
   {
-    assertNull(seq.annotation);
+    assertNull(seq.getAnnotation());
     final AlignmentAnnotation annotation = new AlignmentAnnotation("a",
             "b", 2d);
     assertNull(annotation.sequenceRef);
@@ -120,4 +157,264 @@ public class SequenceTest
     assertSame(annotation2, anns[1]);
 
   }
+
+  @Test(groups = { "Functional" })
+  public void testGetStartGetEnd()
+  {
+    SequenceI seq = new Sequence("test", "ABCDEF");
+    assertEquals(1, seq.getStart());
+    assertEquals(6, seq.getEnd());
+
+    seq = new Sequence("test", "--AB-C-DEF--");
+    assertEquals(1, seq.getStart());
+    assertEquals(6, seq.getEnd());
+
+    seq = new Sequence("test", "----");
+    assertEquals(1, seq.getStart());
+    assertEquals(0, seq.getEnd()); // ??
+  }
+
+  /**
+   * Tests for the method that returns an alignment column position (base 1) for
+   * a given sequence position (base 1).
+   */
+  @Test(groups = { "Functional" })
+  public void testFindIndex()
+  {
+    SequenceI seq = new Sequence("test", "ABCDEF");
+    assertEquals(0, seq.findIndex(0));
+    assertEquals(1, seq.findIndex(1));
+    assertEquals(5, seq.findIndex(5));
+    assertEquals(6, seq.findIndex(6));
+    assertEquals(6, seq.findIndex(9));
+
+    seq = new Sequence("test", "-A--B-C-D-E-F--");
+    assertEquals(2, seq.findIndex(1));
+    assertEquals(5, seq.findIndex(2));
+    assertEquals(7, seq.findIndex(3));
+
+    // before start returns 0
+    assertEquals(0, seq.findIndex(0));
+    assertEquals(0, seq.findIndex(-1));
+
+    // beyond end returns last residue column
+    assertEquals(13, seq.findIndex(99));
+
+  }
+
+  /**
+   * Tests for the method that returns a dataset sequence position (base 1) for
+   * an aligned column position (base 0).
+   */
+  @Test(groups = { "Functional" })
+  public void testFindPosition()
+  {
+    SequenceI seq = new Sequence("test", "ABCDEF");
+    assertEquals(1, seq.findPosition(0));
+    assertEquals(6, seq.findPosition(5));
+    // assertEquals(-1, seq.findPosition(6)); // fails
+
+    seq = new Sequence("test", "AB-C-D--");
+    assertEquals(1, seq.findPosition(0));
+    assertEquals(2, seq.findPosition(1));
+    // gap position 'finds' residue to the right (not the left as per javadoc)
+    assertEquals(3, seq.findPosition(2));
+    assertEquals(3, seq.findPosition(3));
+    assertEquals(4, seq.findPosition(4));
+    assertEquals(4, seq.findPosition(5));
+    // returns 1 more than sequence length if off the end ?!?
+    assertEquals(5, seq.findPosition(6));
+    assertEquals(5, seq.findPosition(7));
+
+    seq = new Sequence("test", "--AB-C-DEF--");
+    assertEquals(1, seq.findPosition(0));
+    assertEquals(1, seq.findPosition(1));
+    assertEquals(1, seq.findPosition(2));
+    assertEquals(2, seq.findPosition(3));
+    assertEquals(3, seq.findPosition(4));
+    assertEquals(3, seq.findPosition(5));
+    assertEquals(4, seq.findPosition(6));
+    assertEquals(4, seq.findPosition(7));
+    assertEquals(5, seq.findPosition(8));
+    assertEquals(6, seq.findPosition(9));
+    assertEquals(7, seq.findPosition(10));
+    assertEquals(7, seq.findPosition(11));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testDeleteChars()
+  {
+    SequenceI seq = new Sequence("test", "ABCDEF");
+    assertEquals(1, seq.getStart());
+    assertEquals(6, seq.getEnd());
+    seq.deleteChars(2, 3);
+    assertEquals("ABDEF", seq.getSequenceAsString());
+    assertEquals(1, seq.getStart());
+    assertEquals(5, seq.getEnd());
+
+    seq = new Sequence("test", "ABCDEF");
+    seq.deleteChars(0, 2);
+    assertEquals("CDEF", seq.getSequenceAsString());
+    assertEquals(3, seq.getStart());
+    assertEquals(6, seq.getEnd());
+  }
+
+  @Test(groups = { "Functional" })
+  public void testInsertCharAt()
+  {
+    // non-static methods:
+    SequenceI seq = new Sequence("test", "ABCDEF");
+    seq.insertCharAt(0, 'z');
+    assertEquals("zABCDEF", seq.getSequenceAsString());
+    seq.insertCharAt(2, 2, 'x');
+    assertEquals("zAxxBCDEF", seq.getSequenceAsString());
+
+    // for static method see StringUtilsTest
+  }
+
+  /**
+   * Test the method that returns an array of aligned sequence positions where
+   * the array index is the data sequence position (both base 0).
+   */
+  @Test(groups = { "Functional" })
+  public void testGapMap()
+  {
+    SequenceI seq = new Sequence("test", "-A--B-CD-E--F-");
+    seq.createDatasetSequence();
+    assertEquals("[1, 4, 6, 7, 9, 12]", Arrays.toString(seq.gapMap()));
+  }
+
+  /**
+   * Test the method that gets sequence features, either from the sequence or
+   * its dataset.
+   */
+  @Test(groups = { "Functional" })
+  public void testGetSequenceFeatures()
+  {
+    SequenceI seq = new Sequence("test", "GATCAT");
+    seq.createDatasetSequence();
+
+    assertNull(seq.getSequenceFeatures());
+
+    /*
+     * SequenceFeature on sequence
+     */
+    SequenceFeature sf = new SequenceFeature();
+    seq.addSequenceFeature(sf);
+    SequenceFeature[] sfs = seq.getSequenceFeatures();
+    assertEquals(1, sfs.length);
+    assertSame(sf, sfs[0]);
+
+    /*
+     * SequenceFeature on sequence and dataset sequence; returns that on
+     * sequence
+     */
+    SequenceFeature sf2 = new SequenceFeature();
+    seq.getDatasetSequence().addSequenceFeature(sf2);
+    sfs = seq.getSequenceFeatures();
+    assertEquals(1, sfs.length);
+    assertSame(sf, sfs[0]);
+
+    /*
+     * SequenceFeature on dataset sequence only
+     */
+    seq.setSequenceFeatures(null);
+    sfs = seq.getSequenceFeatures();
+    assertEquals(1, sfs.length);
+    assertSame(sf2, sfs[0]);
+
+    /*
+     * Corrupt case - no SequenceFeature, dataset's dataset is the original
+     * sequence. Test shows no infinite loop results.
+     */
+    seq.getDatasetSequence().setSequenceFeatures(null);
+    seq.getDatasetSequence().setDatasetSequence(seq); // loop!
+    assertNull(seq.getSequenceFeatures());
+  }
+
+  /**
+   * Test the method that returns an array, indexed by sequence position, whose
+   * entries are the residue positions at the sequence position (or to the right
+   * if a gap)
+   */
+  @Test(groups = { "Functional" })
+  public void testFindPositionMap()
+  {
+    /*
+     * Note: Javadoc for findPosition says it returns the residue position to
+     * the left of a gapped position; in fact it returns the position to the
+     * right. Also it returns a non-existent residue position for a gap beyond
+     * the sequence.
+     */
+    Sequence seq = new Sequence("TestSeq", "AB.C-D E.");
+    int[] map = seq.findPositionMap();
+    assertEquals(Arrays.toString(new int[] { 1, 2, 3, 3, 4, 4, 5, 5, 6 }),
+            Arrays.toString(map));
+  }
+
+  /**
+   * Test for getSubsequence
+   */
+  @Test(groups = { "Functional" })
+  public void testGetSubsequence()
+  {
+    SequenceI seq = new Sequence("TestSeq", "ABCDEFG");
+    seq.createDatasetSequence();
+
+    // positions are base 0, end position is exclusive
+    SequenceI subseq = seq.getSubSequence(2, 4);
+
+    assertEquals("CD", subseq.getSequenceAsString());
+    // start/end are base 1 positions
+    assertEquals(3, subseq.getStart());
+    assertEquals(4, subseq.getEnd());
+    // subsequence shares the full dataset sequence
+    assertSame(seq.getDatasetSequence(), subseq.getDatasetSequence());
+  }
+
+  /**
+   * Test for deriveSequence applied to a sequence with a dataset
+   */
+  @Test(groups = { "Functional" })
+  public void testDeriveSequence_existingDataset()
+  {
+    SequenceI seq = new Sequence("Seq1", "CD");
+    seq.setDatasetSequence(new Sequence("Seq1", "ABCDEF"));
+    seq.setStart(3);
+    seq.setEnd(4);
+    SequenceI derived = seq.deriveSequence();
+    assertEquals("CD", derived.getSequenceAsString());
+    assertSame(seq.getDatasetSequence(), derived.getDatasetSequence());
+  }
+
+  /**
+   * Test for deriveSequence applied to an ungapped sequence with no dataset
+   */
+  @Test(groups = { "Functional" })
+  public void testDeriveSequence_noDatasetUngapped()
+  {
+    SequenceI seq = new Sequence("Seq1", "ABCDEF");
+    assertEquals(1, seq.getStart());
+    assertEquals(6, seq.getEnd());
+    SequenceI derived = seq.deriveSequence();
+    assertEquals("ABCDEF", derived.getSequenceAsString());
+    assertEquals("ABCDEF", derived.getDatasetSequence()
+            .getSequenceAsString());
+  }
+
+  /**
+   * Test for deriveSequence applied to a gapped sequence with no dataset
+   */
+  @Test(groups = { "Functional" })
+  public void testDeriveSequence_noDatasetGapped()
+  {
+    SequenceI seq = new Sequence("Seq1", "AB-C.D EF");
+    assertEquals(1, seq.getStart());
+    assertEquals(6, seq.getEnd());
+    assertNull(seq.getDatasetSequence());
+    SequenceI derived = seq.deriveSequence();
+    assertEquals("AB-C.D EF", derived.getSequenceAsString());
+    assertEquals("ABCDEF", derived.getDatasetSequence()
+            .getSequenceAsString());
+  }
 }