Merge branch 'bug/JAL-2541cutWithFeatures' into features/JAL-2446NCList
[jalview.git] / test / jalview / datamodel / SequenceTest.java
index 25804bc..ebf4857 100644 (file)
@@ -23,12 +23,14 @@ package jalview.datamodel;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.AssertJUnit.assertNotSame;
 import static org.testng.AssertJUnit.assertNull;
 import static org.testng.AssertJUnit.assertSame;
 import static org.testng.AssertJUnit.assertTrue;
 import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
 
 import jalview.datamodel.PDBEntry.Type;
+import jalview.gui.JvOptionPane;
 import jalview.util.MapList;
 
 import java.io.File;
@@ -37,12 +39,25 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Vector;
 
+import junit.extensions.PA;
+
+import junit.extensions.PA;
+
 import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 public class SequenceTest
 {
+
+  @BeforeClass(alwaysRun = true)
+  public void setUpJvOptionPane()
+  {
+    JvOptionPane.setInteractiveMode(false);
+    JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
+  }
+
   Sequence seq;
 
   @BeforeMethod(alwaysRun = true)
@@ -70,11 +85,11 @@ public class SequenceTest
   public void testIsProtein()
   {
     // test Protein
-    assertTrue(new Sequence("prot","ASDFASDFASDF").isProtein());
+    assertTrue(new Sequence("prot", "ASDFASDFASDF").isProtein());
     // test DNA
-    assertFalse(new Sequence("prot","ACGTACGTACGT").isProtein());
+    assertFalse(new Sequence("prot", "ACGTACGTACGT").isProtein());
     // test RNA
-    SequenceI sq = new Sequence("prot","ACGUACGUACGU");
+    SequenceI sq = new Sequence("prot", "ACGUACGUACGU");
     assertFalse(sq.isProtein());
     // change sequence, should trigger an update of cached result
     sq.setSequence("ASDFASDFADSF");
@@ -275,19 +290,129 @@ public class SequenceTest
   @Test(groups = { "Functional" })
   public void testDeleteChars()
   {
+    /*
+     * internal delete
+     */
     SequenceI sq = new Sequence("test", "ABCDEF");
+    assertNull(PA.getValue(sq, "datasetSequence"));
     assertEquals(1, sq.getStart());
     assertEquals(6, sq.getEnd());
     sq.deleteChars(2, 3);
     assertEquals("ABDEF", sq.getSequenceAsString());
     assertEquals(1, sq.getStart());
     assertEquals(5, sq.getEnd());
+    assertNull(PA.getValue(sq, "datasetSequence"));
+
+    /*
+     * delete at start
+     */
+    sq = new Sequence("test", "ABCDEF");
+    sq.deleteChars(0, 2);
+    assertEquals("CDEF", sq.getSequenceAsString());
+    assertEquals(3, sq.getStart());
+    assertEquals(6, sq.getEnd());
+    assertNull(PA.getValue(sq, "datasetSequence"));
+
+    /*
+     * delete at end
+     */
+    sq = new Sequence("test", "ABCDEF");
+    sq.deleteChars(4, 6);
+    assertEquals("ABCD", sq.getSequenceAsString());
+    assertEquals(1, sq.getStart());
+    assertEquals(4, sq.getEnd());
+    assertNull(PA.getValue(sq, "datasetSequence"));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testDeleteChars_withDbRefsAndFeatures()
+  {
+    /*
+     * internal delete - new dataset sequence created
+     * gets a copy of any dbrefs
+     */
+    SequenceI sq = new Sequence("test", "ABCDEF");
+    sq.createDatasetSequence();
+    DBRefEntry dbr1 = new DBRefEntry("Uniprot", "0", "a123");
+    sq.addDBRef(dbr1);
+    Object ds = PA.getValue(sq, "datasetSequence");
+    assertNotNull(ds);
+    assertEquals(1, sq.getStart());
+    assertEquals(6, sq.getEnd());
+    sq.deleteChars(2, 3);
+    assertEquals("ABDEF", sq.getSequenceAsString());
+    assertEquals(1, sq.getStart());
+    assertEquals(5, sq.getEnd());
+    Object newDs = PA.getValue(sq, "datasetSequence");
+    assertNotNull(newDs);
+    assertNotSame(ds, newDs);
+    assertNotNull(sq.getDBRefs());
+    assertEquals(1, sq.getDBRefs().length);
+    assertNotSame(dbr1, sq.getDBRefs()[0]);
+    assertEquals(dbr1, sq.getDBRefs()[0]);
+
+    /*
+     * internal delete with sequence features
+     * (failure case for JAL-2541)
+     */
+    sq = new Sequence("test", "ABCDEF");
+    sq.createDatasetSequence();
+    SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 2, 4, 2f,
+            "CathGroup");
+    sq.addSequenceFeature(sf1);
+    ds = PA.getValue(sq, "datasetSequence");
+    assertNotNull(ds);
+    assertEquals(1, sq.getStart());
+    assertEquals(6, sq.getEnd());
+    sq.deleteChars(2, 4);
+    assertEquals("ABEF", sq.getSequenceAsString());
+    assertEquals(1, sq.getStart());
+    assertEquals(4, sq.getEnd());
+    newDs = PA.getValue(sq, "datasetSequence");
+    assertNotNull(newDs);
+    assertNotSame(ds, newDs);
+    SequenceFeature[] sfs = sq.getSequenceFeatures();
+    assertNotNull(sfs);
+    assertEquals(1, sfs.length);
+    assertNotSame(sf1, sfs[0]);
+    assertEquals(sf1, sfs[0]);
 
+    /*
+     * delete at start - no new dataset sequence created
+     * any sequence features remain as before
+     */
     sq = new Sequence("test", "ABCDEF");
+    sq.createDatasetSequence();
+    ds = PA.getValue(sq, "datasetSequence");
+    sf1 = new SequenceFeature("Cath", "desc", 2, 4, 2f, "CathGroup");
+    sq.addSequenceFeature(sf1);
     sq.deleteChars(0, 2);
     assertEquals("CDEF", sq.getSequenceAsString());
     assertEquals(3, sq.getStart());
     assertEquals(6, sq.getEnd());
+    assertSame(ds, PA.getValue(sq, "datasetSequence"));
+    sfs = sq.getSequenceFeatures();
+    assertNotNull(sfs);
+    assertEquals(1, sfs.length);
+    assertSame(sf1, sfs[0]);
+
+    /*
+     * delete at end - no new dataset sequence created
+     * any dbrefs remain as before
+     */
+    sq = new Sequence("test", "ABCDEF");
+    sq.createDatasetSequence();
+    ds = PA.getValue(sq, "datasetSequence");
+    dbr1 = new DBRefEntry("Uniprot", "0", "a123");
+    sq.addDBRef(dbr1);
+    sq.deleteChars(4, 6);
+    assertEquals("ABCD", sq.getSequenceAsString());
+    assertEquals(1, sq.getStart());
+    assertEquals(4, sq.getEnd());
+    assertSame(ds, PA.getValue(sq, "datasetSequence"));
+    assertNotNull(sq.getDBRefs());
+    assertEquals(1, sq.getDBRefs().length);
+    assertSame(dbr1, sq.getDBRefs()[0]);
   }
 
   @Test(groups = { "Functional" })
@@ -330,13 +455,12 @@ public class SequenceTest
     /*
      * SequenceFeature on sequence
      */
-    SequenceFeature sf = new SequenceFeature();
+    SequenceFeature sf = new SequenceFeature("Cath", "desc", 2, 4, 2f, null);
     sq.addSequenceFeature(sf);
     SequenceFeature[] sfs = sq.getSequenceFeatures();
     assertEquals(1, sfs.length);
     assertSame(sf, sfs[0]);
 
-
     /*
      * SequenceFeature on sequence and dataset sequence; returns that on
      * sequence
@@ -425,12 +549,27 @@ public class SequenceTest
   @Test(groups = { "Functional" })
   public void testCreateDatasetSequence()
   {
-    SequenceI sq = new Sequence("my","ASDASD");
+    SequenceI sq = new Sequence("my", "ASDASD");
+    sq.addSequenceFeature(new SequenceFeature("type", "desc", 1, 10, 1f,
+            "group"));
+    sq.addDBRef(new DBRefEntry("source", "version", "accession"));
     assertNull(sq.getDatasetSequence());
+    assertNotNull(PA.getValue(sq, "sequenceFeatures")); // to be removed!
+    assertNotNull(PA.getValue(sq, "sequenceFeatureStore"));
+    assertNotNull(PA.getValue(sq, "dbrefs"));
+
     SequenceI rds = sq.createDatasetSequence();
     assertNotNull(rds);
     assertNull(rds.getDatasetSequence());
-    assertEquals(sq.getDatasetSequence(), rds);
+    assertSame(sq.getDatasetSequence(), rds);
+
+    // sequence features and dbrefs transferred to dataset sequence
+    assertNull(PA.getValue(sq, "sequenceFeatures"));
+    assertNull(PA.getValue(sq, "sequenceFeatureStore"));
+    assertNull(PA.getValue(sq, "dbrefs"));
+    assertNotNull(PA.getValue(rds, "sequenceFeatures"));
+    assertNotNull(PA.getValue(rds, "sequenceFeatureStore"));
+    assertNotNull(PA.getValue(rds, "dbrefs"));
   }
 
   /**
@@ -459,12 +598,11 @@ public class SequenceTest
     sq.addPDBId(new PDBEntry("1PDB", "B", Type.PDB, "filePath/test1"));
     sq.addPDBId(new PDBEntry("2PDB", "A", Type.MMCIF, "filePath/test2"));
     sq.addPDBId(new PDBEntry("2PDB", "B", Type.MMCIF, "filePath/test2"));
-    
+
     // these are the same as ones already added
     DBRefEntry pdb1pdb = new DBRefEntry("PDB", "version1", "1PDB");
     DBRefEntry pdb2pdb = new DBRefEntry("PDB", "version2", "2PDB");
 
-    
     List<DBRefEntry> primRefs = Arrays.asList(new DBRefEntry[] { pdb1pdb,
         pdb2pdb });
 
@@ -474,15 +612,15 @@ public class SequenceTest
             new DBRefEntry("PDB", "version3", "3PDB")); // should do nothing
     sq.getDatasetSequence().addDBRef(
             new DBRefEntry("PDB", "version4", "4PDB")); // should do nothing
-    
-    PDBEntry pdbe1a=new PDBEntry("1PDB", "A", Type.PDB, "filePath/test1");
+
+    PDBEntry pdbe1a = new PDBEntry("1PDB", "A", Type.PDB, "filePath/test1");
     PDBEntry pdbe1b = new PDBEntry("1PDB", "B", Type.PDB, "filePath/test1");
-    PDBEntry pdbe2a=new PDBEntry("2PDB", "A", Type.MMCIF, "filePath/test2");
-    PDBEntry pdbe2b = new PDBEntry("2PDB", "B", Type.MMCIF, "filePath/test2");
-    sq.getDatasetSequence().addPDBId(
-            pdbe1a);
-    sq.getDatasetSequence().addPDBId(
-            pdbe1b);
+    PDBEntry pdbe2a = new PDBEntry("2PDB", "A", Type.MMCIF,
+            "filePath/test2");
+    PDBEntry pdbe2b = new PDBEntry("2PDB", "B", Type.MMCIF,
+            "filePath/test2");
+    sq.getDatasetSequence().addPDBId(pdbe1a);
+    sq.getDatasetSequence().addPDBId(pdbe1b);
     sq.getDatasetSequence().addPDBId(pdbe2a);
     sq.getDatasetSequence().addPDBId(pdbe2b);
 
@@ -544,7 +682,7 @@ public class SequenceTest
     assertNotNull(sq.getSequenceFeatures());
     assertArrayEquals(sq.getSequenceFeatures(),
             derived.getSequenceFeatures());
-    
+
     /*
      *  verify we have primary db refs *just* for PDB IDs with associated
      *  PDBEntry objects
@@ -599,7 +737,7 @@ public class SequenceTest
             12.4f, "group"));
     seq1.addPDBId(new PDBEntry("1A70", "B", Type.PDB, "File"));
     seq1.addDBRef(new DBRefEntry("EMBL", "1.2", "AZ12345"));
-    
+
     SequenceI copy = new Sequence(seq1);
 
     assertNull(copy.getDatasetSequence());
@@ -675,9 +813,13 @@ public class SequenceTest
     // copy has a copy of the sequence feature:
     SequenceFeature[] sfs = copy.getSequenceFeatures();
     assertEquals(1, sfs.length);
-    if (seq1.getDatasetSequence()!=null && copy.getDatasetSequence()==seq1.getDatasetSequence()) {
+    if (seq1.getDatasetSequence() != null
+            && copy.getDatasetSequence() == seq1.getDatasetSequence())
+    {
       assertTrue(sfs[0] == seq1.getSequenceFeatures()[0]);
-    } else {
+    }
+    else
+    {
       assertFalse(sfs[0] == seq1.getSequenceFeatures()[0]);
     }
     assertTrue(sfs[0].equals(seq1.getSequenceFeatures()[0]));
@@ -699,6 +841,36 @@ public class SequenceTest
     assertEquals(' ', sq.getCharAt(-1));
   }
 
+  @Test(groups = { "Functional" })
+  public void testAddSequenceFeatures()
+  {
+    SequenceI sq = new Sequence("", "abcde");
+    // type may not be null
+    assertFalse(sq.addSequenceFeature(new SequenceFeature(null, "desc", 4,
+            8, 0f, null)));
+    assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath", "desc", 4,
+            8, 0f, null)));
+    // can't add a duplicate feature
+    assertFalse(sq.addSequenceFeature(new SequenceFeature("Cath", "desc",
+            4, 8, 0f, null)));
+    // can add a different feature
+    assertTrue(sq.addSequenceFeature(new SequenceFeature("Scop", "desc", 4,
+            8, 0f, null))); // different type
+    assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath",
+            "description", 4, 8, 0f, null)));// different description
+    assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath", "desc", 3,
+            8, 0f, null))); // different start position
+    assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath", "desc", 4,
+            9, 0f, null))); // different end position
+    assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath", "desc", 4,
+            8, 1f, null))); // different score
+    assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath", "desc", 4,
+            8, Float.NaN, null))); // score NaN
+    assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath", "desc", 4,
+            8, 0f, "Metal"))); // different group
+    assertEquals(8, sq.getFeatures().getAllFeatures().size());
+  }
+
   /**
    * Tests for adding (or updating) dbrefs
    * 
@@ -867,11 +1039,11 @@ public class SequenceTest
   public void testGetPrimaryDBRefs_nucleotide()
   {
     SequenceI sq = new Sequence("aseq", "TGATCACTCGACTAGCATCAGCATA", 10, 34);
-  
+
     // primary - Ensembl
     DBRefEntry dbr1 = new DBRefEntry("ENSEMBL", "0", "ENSG1234");
     sq.addDBRef(dbr1);
-  
+
     // not primary - Ensembl 'transcript' mapping of sub-sequence
     DBRefEntry dbr2 = new DBRefEntry("ENSEMBL", "0", "ENST1234");
     dbr2.setMap(new Mapping(null, new MapList(new int[] { 15, 25 },
@@ -891,7 +1063,7 @@ public class SequenceTest
     // not primary - to protein
     DBRefEntry dbr5 = new DBRefEntry("UNIPROT", "0", "Q87654");
     sq.addDBRef(dbr5);
-  
+
     List<DBRefEntry> primaryDBRefs = sq.getPrimaryDBRefs();
     assertEquals(2, primaryDBRefs.size());
     assertTrue(primaryDBRefs.contains(dbr1));
@@ -913,7 +1085,7 @@ public class SequenceTest
     seq.addDBRef(new DBRefEntry("PDB", "0", "3a6sB"));
     // 7 is not a valid chain code:
     seq.addDBRef(new DBRefEntry("PDB", "0", "2GIS7"));
-    
+
     seq.updatePDBIds();
     List<PDBEntry> pdbIds = seq.getAllPDBEntries();
     assertEquals(4, pdbIds.size());