JAL-2446 pseudo-random generator unit test, and fixes arising
[jalview.git] / test / jalview / datamodel / features / NCListTest.java
1 package jalview.datamodel.features;
2
3 import static org.testng.Assert.assertEquals;
4 import static org.testng.Assert.assertTrue;
5
6 import java.util.ArrayList;
7 import java.util.Collections;
8 import java.util.List;
9 import java.util.Random;
10
11 import org.testng.annotations.Test;
12
13 public class NCListTest
14 {
15   class Range implements ContiguousI
16   {
17     int start;
18
19     int end;
20
21     @Override
22     public int getBegin()
23     {
24       return start;
25     }
26
27     @Override
28     public int getEnd()
29     {
30       return end;
31     }
32
33     Range(int i, int j)
34     {
35       start = i;
36       end = j;
37     }
38
39     @Override
40     public String toString() {
41       return String.valueOf(start) + "-" + String.valueOf(end);
42     }
43   }
44
45   /**
46    * A basic sanity test of the constructor
47    */
48   @Test(groups = "Functional")
49   public void testConstructor()
50   {
51     List<Range> ranges = new ArrayList<Range>();
52     ranges.add(new Range(20, 20));
53     ranges.add(new Range(10, 20));
54     ranges.add(new Range(15, 30));
55     ranges.add(new Range(10, 30));
56     ranges.add(new Range(11, 19));
57     ranges.add(new Range(10, 20));
58     ranges.add(new Range(1, 100));
59
60     NCList<Range> ncl = new NCList<Range>(ranges);
61     String expected = "[1-100 [10-30 [10-20 [10-20 [11-19]]]], 15-30 [20-20]]";
62     assertEquals(ncl.toString(), expected);
63     assertTrue(ncl.isValid());
64
65     Collections.reverse(ranges);
66     ncl = new NCList<Range>(ranges);
67     assertEquals(ncl.toString(), expected);
68     assertTrue(ncl.isValid());
69   }
70
71   @Test(groups = "Functional")
72   public void testFindOverlaps()
73   {
74     List<Range> ranges = new ArrayList<Range>();
75     ranges.add(new Range(20, 50));
76     ranges.add(new Range(30, 70));
77     ranges.add(new Range(1, 100));
78     ranges.add(new Range(70, 120));
79   
80     NCList<Range> ncl = new NCList<Range>(ranges);
81
82     List<Range> overlaps = ncl.findOverlaps(121, 122);
83     assertEquals(overlaps.size(), 0);
84
85     overlaps = ncl.findOverlaps(21, 22);
86     assertEquals(overlaps.size(), 2);
87     assertEquals(((ContiguousI) overlaps.get(0)).getBegin(), 1);
88     assertEquals(((ContiguousI) overlaps.get(0)).getEnd(), 100);
89     assertEquals(((ContiguousI) overlaps.get(1)).getBegin(), 20);
90     assertEquals(((ContiguousI) overlaps.get(1)).getEnd(), 50);
91
92     overlaps = ncl.findOverlaps(110, 110);
93     assertEquals(overlaps.size(), 1);
94     assertEquals(((ContiguousI) overlaps.get(0)).getBegin(), 70);
95     assertEquals(((ContiguousI) overlaps.get(0)).getEnd(), 120);
96   }
97
98   @Test(groups = "Functional")
99   public void testAdd_onTheEnd()
100   {
101     List<Range> ranges = new ArrayList<Range>();
102     ranges.add(new Range(20, 50));
103     NCList<Range> ncl = new NCList<Range>(ranges);
104     assertEquals(ncl.toString(), "[20-50]");
105     assertTrue(ncl.isValid());
106
107     ncl.add(new Range(60, 70));
108     assertEquals(ncl.toString(), "[20-50, 60-70]");
109     assertTrue(ncl.isValid());
110   }
111
112   @Test(groups = "Functional")
113   public void testAdd_inside()
114   {
115     List<Range> ranges = new ArrayList<Range>();
116     ranges.add(new Range(20, 50));
117     NCList<Range> ncl = new NCList<Range>(ranges);
118     assertEquals(ncl.toString(), "[20-50]");
119     assertTrue(ncl.isValid());
120
121     ncl.add(new Range(30, 40));
122     assertEquals(ncl.toString(), "[20-50 [30-40]]");
123   }
124
125   @Test(groups = "Functional")
126   public void testAdd_onTheFront()
127   {
128     List<Range> ranges = new ArrayList<Range>();
129     ranges.add(new Range(20, 50));
130     NCList<Range> ncl = new NCList<Range>(ranges);
131     assertEquals(ncl.toString(), "[20-50]");
132     assertTrue(ncl.isValid());
133
134     ncl.add(new Range(5, 15));
135     assertEquals(ncl.toString(), "[5-15, 20-50]");
136     assertTrue(ncl.isValid());
137   }
138
139   @Test(groups = "Functional")
140   public void testAdd_enclosing()
141   {
142     List<Range> ranges = new ArrayList<Range>();
143     ranges.add(new Range(20, 50));
144     ranges.add(new Range(30, 60));
145     NCList<Range> ncl = new NCList<Range>(ranges);
146     assertEquals(ncl.toString(), "[20-50, 30-60]");
147     assertTrue(ncl.isValid());
148     assertEquals(ncl.getStart(), 20);
149
150     ncl.add(new Range(10, 70));
151     assertEquals(ncl.toString(), "[10-70 [20-50, 30-60]]");
152     assertTrue(ncl.isValid());
153   }
154
155   @Test(groups = "Functional")
156   public void testAdd_spanning()
157   {
158     List<Range> ranges = new ArrayList<Range>();
159     ranges.add(new Range(20, 40));
160     ranges.add(new Range(60, 70));
161     NCList<Range> ncl = new NCList<Range>(ranges);
162     assertEquals(ncl.toString(), "[20-40, 60-70]");
163     assertTrue(ncl.isValid());
164
165     ncl.add(new Range(30, 50));
166     assertEquals(ncl.toString(), "[20-40, 30-50, 60-70]");
167     assertTrue(ncl.isValid());
168
169     ncl.add(new Range(40, 65));
170     assertEquals(ncl.toString(), "[20-40, 30-50, 40-65, 60-70]");
171     assertTrue(ncl.isValid());
172   }
173
174   /**
175    * Do a number of pseudo-random (reproducible) builds of an NCList, with
176    * checks for validity of the data structure, for greater (but not perfect!)
177    * confidence that corner cases are being handled correctly.
178    */
179   @Test(groups = "Functional")
180   public void testAdd_pseudoRandom()
181   {
182     Random r = new Random(108); // well why not?
183     int[] scales = new int[] { 10, 100, 1000 };
184
185     for (int scale : scales)
186     {
187       NCList<Range> ncl = new NCList<Range>();
188       int size = 0;
189       for (int i = 0; i < 100; i++)
190       {
191         int r1 = r.nextInt(scale);
192         int r2 = r.nextInt(scale);
193         int nextFrom = Math.min(r1, r2);
194         int nextTo = Math.max(r1, r2);
195         Range range = new Range(nextFrom, nextTo);
196         ncl.add(range);
197         assertTrue(ncl.isValid(),
198                 String.format("Failed for scale = %d, i=%d", scale, i));
199         size++;
200         assertEquals(ncl.getSize(), size);
201       }
202       System.out.println(ncl.prettyPrint());
203     }
204   }
205 }