JAL-3383 code and unit test tweaks
[jalview.git] / test / jalview / datamodel / features / FeatureStoreTest.java
index 6e7dd02..db0fabf 100644 (file)
@@ -4,22 +4,30 @@ import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertSame;
 import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
 
 import jalview.datamodel.SequenceFeature;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
 import org.testng.annotations.Test;
 
+import junit.extensions.PA;
+
 public class FeatureStoreTest
 {
+  private FeatureStore newFeatureStore()
+  {
+    return new FeatureStore();
+  }
 
   @Test(groups = "Functional")
   public void testFindFeatures_nonNested()
   {
-    FeatureStore fs = new FeatureStore();
+    FeatureStore fs = newFeatureStore();
     fs.addFeature(new SequenceFeature("", "", 10, 20, Float.NaN,
             null));
     // same range different description
@@ -27,21 +35,21 @@ public class FeatureStoreTest
     fs.addFeature(new SequenceFeature("", "", 15, 25, Float.NaN, null));
     fs.addFeature(new SequenceFeature("", "", 20, 35, Float.NaN, null));
 
-    List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
+    List<SequenceFeature> overlaps = fs.findFeatures(1, 9);
     assertTrue(overlaps.isEmpty());
 
-    overlaps = fs.findOverlappingFeatures(8, 10);
+    overlaps = fs.findFeatures(8, 10);
     assertEquals(overlaps.size(), 2);
     assertEquals(overlaps.get(0).getEnd(), 20);
     assertEquals(overlaps.get(1).getEnd(), 20);
 
-    overlaps = fs.findOverlappingFeatures(12, 16);
+    overlaps = fs.findFeatures(12, 16);
     assertEquals(overlaps.size(), 3);
     assertEquals(overlaps.get(0).getEnd(), 20);
     assertEquals(overlaps.get(1).getEnd(), 20);
     assertEquals(overlaps.get(2).getEnd(), 25);
 
-    overlaps = fs.findOverlappingFeatures(33, 33);
+    overlaps = fs.findFeatures(33, 33);
     assertEquals(overlaps.size(), 1);
     assertEquals(overlaps.get(0).getEnd(), 35);
   }
@@ -49,7 +57,7 @@ public class FeatureStoreTest
   @Test(groups = "Functional")
   public void testFindFeatures_nested()
   {
-    FeatureStore fs = new FeatureStore();
+    FeatureStore fs = newFeatureStore();
     SequenceFeature sf1 = addFeature(fs, 10, 50);
     SequenceFeature sf2 = addFeature(fs, 10, 40);
     SequenceFeature sf3 = addFeature(fs, 20, 30);
@@ -59,25 +67,25 @@ public class FeatureStoreTest
     fs.addFeature(sf4);
     SequenceFeature sf5 = addFeature(fs, 35, 36);
 
-    List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
+    List<SequenceFeature> overlaps = fs.findFeatures(1, 9);
     assertTrue(overlaps.isEmpty());
 
-    overlaps = fs.findOverlappingFeatures(10, 15);
+    overlaps = fs.findFeatures(10, 15);
     assertEquals(overlaps.size(), 2);
     assertTrue(overlaps.contains(sf1));
     assertTrue(overlaps.contains(sf2));
 
-    overlaps = fs.findOverlappingFeatures(45, 60);
+    overlaps = fs.findFeatures(45, 60);
     assertEquals(overlaps.size(), 1);
     assertTrue(overlaps.contains(sf1));
 
-    overlaps = fs.findOverlappingFeatures(32, 38);
+    overlaps = fs.findFeatures(32, 38);
     assertEquals(overlaps.size(), 3);
     assertTrue(overlaps.contains(sf1));
     assertTrue(overlaps.contains(sf2));
     assertTrue(overlaps.contains(sf5));
 
-    overlaps = fs.findOverlappingFeatures(15, 25);
+    overlaps = fs.findFeatures(15, 25);
     assertEquals(overlaps.size(), 4);
     assertTrue(overlaps.contains(sf1));
     assertTrue(overlaps.contains(sf2));
@@ -88,7 +96,7 @@ public class FeatureStoreTest
   @Test(groups = "Functional")
   public void testFindFeatures_mixed()
   {
-    FeatureStore fs = new FeatureStore();
+    FeatureStore fs = newFeatureStore();
     SequenceFeature sf1 = addFeature(fs, 10, 50);
     SequenceFeature sf2 = addFeature(fs, 1, 15);
     SequenceFeature sf3 = addFeature(fs, 20, 30);
@@ -96,30 +104,30 @@ public class FeatureStoreTest
     SequenceFeature sf5 = addFeature(fs, 60, 100);
     SequenceFeature sf6 = addFeature(fs, 70, 70);
 
-    List<SequenceFeature> overlaps = fs.findOverlappingFeatures(200, 200);
+    List<SequenceFeature> overlaps = fs.findFeatures(200, 200);
     assertTrue(overlaps.isEmpty());
 
-    overlaps = fs.findOverlappingFeatures(1, 9);
+    overlaps = fs.findFeatures(1, 9);
     assertEquals(overlaps.size(), 1);
     assertTrue(overlaps.contains(sf2));
 
-    overlaps = fs.findOverlappingFeatures(5, 18);
+    overlaps = fs.findFeatures(5, 18);
     assertEquals(overlaps.size(), 2);
     assertTrue(overlaps.contains(sf1));
     assertTrue(overlaps.contains(sf2));
 
-    overlaps = fs.findOverlappingFeatures(30, 40);
+    overlaps = fs.findFeatures(30, 40);
     assertEquals(overlaps.size(), 3);
     assertTrue(overlaps.contains(sf1));
     assertTrue(overlaps.contains(sf3));
     assertTrue(overlaps.contains(sf4));
 
-    overlaps = fs.findOverlappingFeatures(80, 90);
+    overlaps = fs.findFeatures(80, 90);
     assertEquals(overlaps.size(), 2);
     assertTrue(overlaps.contains(sf4));
     assertTrue(overlaps.contains(sf5));
 
-    overlaps = fs.findOverlappingFeatures(68, 70);
+    overlaps = fs.findFeatures(68, 70);
     assertEquals(overlaps.size(), 3);
     assertTrue(overlaps.contains(sf4));
     assertTrue(overlaps.contains(sf5));
@@ -145,7 +153,7 @@ public class FeatureStoreTest
   @Test(groups = "Functional")
   public void testFindFeatures_contactFeatures()
   {
-    FeatureStore fs = new FeatureStore();
+    FeatureStore fs = newFeatureStore();
 
     SequenceFeature sf = new SequenceFeature("disulphide bond", "bond", 10,
             20, Float.NaN, null);
@@ -154,93 +162,135 @@ public class FeatureStoreTest
     /*
      * neither contact point in range
      */
-    List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
+    List<SequenceFeature> overlaps = fs.findFeatures(1, 9);
     assertTrue(overlaps.isEmpty());
 
     /*
      * neither contact point in range
      */
-    overlaps = fs.findOverlappingFeatures(11, 19);
+    overlaps = fs.findFeatures(11, 19);
     assertTrue(overlaps.isEmpty());
 
     /*
      * first contact point in range
      */
-    overlaps = fs.findOverlappingFeatures(5, 15);
+    overlaps = fs.findFeatures(5, 15);
     assertEquals(overlaps.size(), 1);
     assertTrue(overlaps.contains(sf));
 
     /*
      * second contact point in range
      */
-    overlaps = fs.findOverlappingFeatures(15, 25);
+    overlaps = fs.findFeatures(15, 25);
     assertEquals(overlaps.size(), 1);
     assertTrue(overlaps.contains(sf));
 
     /*
      * both contact points in range
      */
-    overlaps = fs.findOverlappingFeatures(5, 25);
+    overlaps = fs.findFeatures(5, 25);
     assertEquals(overlaps.size(), 1);
     assertTrue(overlaps.contains(sf));
   }
 
-  /**
-   * Tests for the method that returns false for an attempt to add a feature
-   * that would enclose, or be enclosed by, another feature
-   */
   @Test(groups = "Functional")
-  public void testAddNonNestedFeature()
+  public void testGetPositionalFeatures_withResultList()
   {
-    FeatureStore fs = new FeatureStore();
-
-    String type = "Domain";
-    SequenceFeature sf1 = new SequenceFeature(type, type, 10, 20,
+    FeatureStore store = newFeatureStore();
+    SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
             Float.NaN, null);
-    assertTrue(fs.addNonNestedFeature(sf1));
+    store.addFeature(sf1);
+    // contact feature
+    SequenceFeature sf2 = new SequenceFeature("Disulphide bond", "desc", 18,
+            45, Float.NaN, null);
+    store.addFeature(sf2);
 
-    // co-located feature is ok
-    SequenceFeature sf2 = new SequenceFeature(type, type, 10, 20,
-            Float.NaN, null);
-    assertTrue(fs.addNonNestedFeature(sf2));
+    List<SequenceFeature> features = new ArrayList<>();
+    store.getPositionalFeatures(features);
+    assertEquals(features.size(), 2);
+    assertTrue(features.contains(sf1));
+    assertTrue(features.contains(sf2));
 
-    // overlap left is ok
-    SequenceFeature sf3 = new SequenceFeature(type, type, 5, 15, Float.NaN,
-            null);
-    assertTrue(fs.addNonNestedFeature(sf3));
+    /*
+     * no check for duplicates
+     */
+    features.remove(sf1);
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf2));
+    store.getPositionalFeatures(features);
+    assertEquals(features.size(), 3);
+    assertTrue(features.contains(sf1));
+    assertTrue(features.contains(sf2)); // two copies now
+    features.remove(sf2);
+    assertTrue(features.contains(sf2)); // one copy left
+    assertEquals(features.size(), 2);
 
-    // overlap right is ok
-    SequenceFeature sf4 = new SequenceFeature(type, type, 15, 25,
-            Float.NaN, null);
-    assertTrue(fs.addNonNestedFeature(sf4));
+    /*
+     * null argument throws exception
+     */
+    try
+    {
+      store.getPositionalFeatures(null);
+      fail("expected exception");
+    } catch (NullPointerException e)
+    {
+      // expected
+    }
+  }
 
-    // add enclosing feature is not ok
-    SequenceFeature sf5 = new SequenceFeature(type, type, 10, 21,
-            Float.NaN, null);
-    assertFalse(fs.addNonNestedFeature(sf5));
-    SequenceFeature sf6 = new SequenceFeature(type, type, 4, 15, Float.NaN,
-            null);
-    assertFalse(fs.addNonNestedFeature(sf6));
-    SequenceFeature sf7 = new SequenceFeature(type, type, 1, 50, Float.NaN,
-            null);
-    assertFalse(fs.addNonNestedFeature(sf7));
+  @Test(groups = "Functional")
+  public void testGetNonPositionalFeatures()
+  {
+    FeatureStore store = newFeatureStore();
+    List<SequenceFeature> features = store.getNonPositionalFeatures();
+    assertTrue(features.isEmpty());
 
-    // add enclosed feature is not ok
-    SequenceFeature sf8 = new SequenceFeature(type, type, 10, 19,
+    SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
             Float.NaN, null);
-    assertFalse(fs.addNonNestedFeature(sf8));
-    SequenceFeature sf9 = new SequenceFeature(type, type, 16, 25,
+    store.addFeature(sf1);
+    assertTrue(features.isEmpty());
+
+    SequenceFeature sf2 = new SequenceFeature("Metal", "desc", 0, 0,
             Float.NaN, null);
-    assertFalse(fs.addNonNestedFeature(sf9));
-    SequenceFeature sf10 = new SequenceFeature(type, type, 7, 7, Float.NaN,
-            null);
-    assertFalse(fs.addNonNestedFeature(sf10));
+    store.addFeature(sf2);
+    features = store.getNonPositionalFeatures();
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf2));
+
+    /*
+     * with result list argument
+     */
+    features.clear();
+    store.getNonPositionalFeatures(features);
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf2));
+
+    /*
+     * no check for duplicates
+     */
+    store.getNonPositionalFeatures(features);
+    assertEquals(features.size(), 2);
+    assertTrue(features.contains(sf2)); // two copies
+    features.remove(sf2);
+    assertTrue(features.contains(sf2));
+
+    /*
+     * null argument throws exception
+     */
+    try
+    {
+      store.getNonPositionalFeatures(null);
+      fail("expected exception");
+    } catch (NullPointerException e)
+    {
+      // expected
+    }
   }
 
   @Test(groups = "Functional")
   public void testGetPositionalFeatures()
   {
-    FeatureStore store = new FeatureStore();
+    FeatureStore store = newFeatureStore();
     SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
             Float.NaN, null);
     store.addFeature(sf1);
@@ -287,7 +337,7 @@ public class FeatureStoreTest
   @Test(groups = "Functional")
   public void testDelete()
   {
-    FeatureStore store = new FeatureStore();
+    FeatureStore store = newFeatureStore();
     SequenceFeature sf1 = addFeature(store, 10, 20);
     assertTrue(store.getPositionalFeatures().contains(sf1));
 
@@ -359,7 +409,7 @@ public class FeatureStoreTest
   @Test(groups = "Functional")
   public void testAddFeature()
   {
-    FeatureStore fs = new FeatureStore();
+    FeatureStore fs = newFeatureStore();
 
     SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
             Float.NaN, null);
@@ -410,7 +460,7 @@ public class FeatureStoreTest
   @Test(groups = "Functional")
   public void testIsEmpty()
   {
-    FeatureStore fs = new FeatureStore();
+    FeatureStore fs = newFeatureStore();
     assertTrue(fs.isEmpty());
     assertEquals(fs.getFeatureCount(true), 0);
 
@@ -463,9 +513,9 @@ public class FeatureStoreTest
     assertEquals(fs.getFeatureCount(true), 3);
     assertTrue(fs.delete(sf1));
     assertEquals(fs.getFeatureCount(true), 2);
-    // FeatureStore should now only contain features in the NCList
-    assertTrue(fs.nonNestedFeatures.isEmpty());
-    assertEquals(fs.nestedFeatures.size(), 2);
+    Collection<SequenceFeature> intervalStore = (Collection<SequenceFeature>) PA
+            .getValue(fs, "features");
+    assertEquals(intervalStore.size(), 2);
     assertFalse(fs.isEmpty());
     assertTrue(fs.delete(sf2));
     assertEquals(fs.getFeatureCount(true), 1);
@@ -478,7 +528,7 @@ public class FeatureStoreTest
   @Test(groups = "Functional")
   public void testGetFeatureGroups()
   {
-    FeatureStore fs = new FeatureStore();
+    FeatureStore fs = newFeatureStore();
     assertTrue(fs.getFeatureGroups(true).isEmpty());
     assertTrue(fs.getFeatureGroups(false).isEmpty());
 
@@ -545,7 +595,7 @@ public class FeatureStoreTest
   @Test(groups = "Functional")
   public void testGetTotalFeatureLength()
   {
-    FeatureStore fs = new FeatureStore();
+    FeatureStore fs = newFeatureStore();
     assertEquals(fs.getTotalFeatureLength(), 0);
 
     addFeature(fs, 10, 20); // 11
@@ -621,7 +671,7 @@ public class FeatureStoreTest
   @Test(groups = "Functional")
   public void testGetMinimumScore_getMaximumScore()
   {
-    FeatureStore fs = new FeatureStore();
+    FeatureStore fs = newFeatureStore();
     assertEquals(fs.getMinimumScore(true), Float.NaN); // positional
     assertEquals(fs.getMaximumScore(true), Float.NaN);
     assertEquals(fs.getMinimumScore(false), Float.NaN); // non-positional
@@ -693,14 +743,15 @@ public class FeatureStoreTest
   @Test(groups = "Functional")
   public void testListContains()
   {
-    assertFalse(FeatureStore.listContains(null, null));
-    List<SequenceFeature> features = new ArrayList<SequenceFeature>();
-    assertFalse(FeatureStore.listContains(features, null));
+    FeatureStore featureStore = newFeatureStore();
+    assertFalse(featureStore.listContains(null, null));
+    List<SequenceFeature> features = new ArrayList<>();
+    assertFalse(featureStore.listContains(features, null));
 
     SequenceFeature sf1 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
             "group1");
-    assertFalse(FeatureStore.listContains(null, sf1));
-    assertFalse(FeatureStore.listContains(features, sf1));
+    assertFalse(featureStore.listContains(null, sf1));
+    assertFalse(featureStore.listContains(features, sf1));
 
     features.add(sf1);
     SequenceFeature sf2 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
@@ -709,14 +760,14 @@ public class FeatureStoreTest
             "group1");
 
     // sf2.equals(sf1) so contains should return true
-    assertTrue(FeatureStore.listContains(features, sf2));
-    assertFalse(FeatureStore.listContains(features, sf3));
+    assertTrue(featureStore.listContains(features, sf2));
+    assertFalse(featureStore.listContains(features, sf3));
   }
 
   @Test(groups = "Functional")
   public void testGetFeaturesForGroup()
   {
-    FeatureStore fs = new FeatureStore();
+    FeatureStore fs = newFeatureStore();
 
     /*
      * with no features
@@ -774,7 +825,7 @@ public class FeatureStoreTest
   @Test(groups = "Functional")
   public void testShiftFeatures()
   {
-    FeatureStore fs = new FeatureStore();
+    FeatureStore fs = newFeatureStore();
     assertFalse(fs.shiftFeatures(0, 1)); // nothing to do
 
     SequenceFeature sf1 = new SequenceFeature("Cath", "", 2, 5, 0f, null);
@@ -861,7 +912,7 @@ public class FeatureStoreTest
     /*
      * add a feature and a nested feature
      */
-    FeatureStore store = new FeatureStore();
+    FeatureStore store = newFeatureStore();
     SequenceFeature sf1 = addFeature(store, 10, 20);
     // sf2 is nested in sf1 so will be stored in nestedFeatures
     SequenceFeature sf2 = addFeature(store, 12, 14);
@@ -869,8 +920,10 @@ public class FeatureStoreTest
     assertEquals(features.size(), 2);
     assertTrue(features.contains(sf1));
     assertTrue(features.contains(sf2));
-    assertTrue(store.nonNestedFeatures.contains(sf1));
-    assertTrue(store.nestedFeatures.contains(sf2));
+    Collection<SequenceFeature> intervalStore = (Collection<SequenceFeature>) PA
+            .getValue(store, "features");
+    assertTrue(intervalStore.contains(sf1));
+    assertTrue(intervalStore.contains(sf2));
   
     /*
      * delete the first feature
@@ -892,7 +945,7 @@ public class FeatureStoreTest
   @Test(groups = "Functional")
   public void testContains()
   {
-    FeatureStore fs = new FeatureStore();
+    FeatureStore fs = newFeatureStore();
     SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
             Float.NaN, "group1");
     SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
@@ -935,4 +988,28 @@ public class FeatureStoreTest
     assertFalse(fs.contains(sf1));
     assertTrue(fs.contains(sf7));
   }
+
+  @Test(groups = "Functional")
+  public void testFindFeatures_withResultList()
+  {
+    FeatureStore fs = newFeatureStore();
+    SequenceFeature sf1 = addFeature(fs, 10, 50);
+    SequenceFeature sf2 = addFeature(fs, 150, 250);
+  
+    List<SequenceFeature> overlaps = new ArrayList<>();
+    List<SequenceFeature> result = fs.findFeatures(200, 200,
+            overlaps);
+    assertSame(result, overlaps);
+    assertEquals(result.size(), 1);
+    assertTrue(result.contains(sf2));
+    assertFalse(result.contains(sf1));
+
+    /*
+     * if no list supplied, method creates one
+     */
+    result = fs.findFeatures(200, 200, null);
+    assertEquals(result.size(), 1);
+    assertTrue(result.contains(sf2));
+    assertFalse(result.contains(sf1));
+  }
 }