Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package jalview.datamodel.features

File NCListTest.java

 

Code metrics

16
309
20
1
682
464
30
0.1
15.45
20
1.5

Classes

Class Line # Actions
NCListTest 22 309 30 0
1.0100%
 

Contributing tests

This file is covered by 16 tests. .

Source view

1    package jalview.datamodel.features;
2    import static org.testng.Assert.assertEquals;
3    import static org.testng.Assert.assertFalse;
4    import static org.testng.Assert.assertSame;
5    import static org.testng.Assert.assertTrue;
6   
7    import jalview.datamodel.ContiguousI;
8    import jalview.datamodel.Range;
9    import jalview.datamodel.SequenceFeature;
10   
11    import java.util.ArrayList;
12    import java.util.Collections;
13    import java.util.Comparator;
14    import java.util.List;
15    import java.util.Random;
16   
17    import junit.extensions.PA;
18   
19    import org.testng.annotations.DataProvider;
20    import org.testng.annotations.Test;
21   
 
22    public class NCListTest
23    {
24   
25    private Random random = new Random(107);
26   
27    private Comparator<ContiguousI> sorter = new RangeComparator(true);
28   
29    /**
30    * A basic sanity test of the constructor
31    */
 
32  1 toggle @Test(groups = "Functional")
33    public void testConstructor()
34    {
35  1 List<Range> ranges = new ArrayList<Range>();
36  1 ranges.add(new Range(20, 20));
37  1 ranges.add(new Range(10, 20));
38  1 ranges.add(new Range(15, 30));
39  1 ranges.add(new Range(10, 30));
40  1 ranges.add(new Range(11, 19));
41  1 ranges.add(new Range(10, 20));
42  1 ranges.add(new Range(1, 100));
43   
44  1 NCList<Range> ncl = new NCList<Range>(ranges);
45  1 String expected = "[1-100 [10-30 [10-20 [10-20 [11-19]]]], 15-30 [20-20]]";
46  1 assertEquals(ncl.toString(), expected);
47  1 assertTrue(ncl.isValid());
48   
49  1 Collections.reverse(ranges);
50  1 ncl = new NCList<Range>(ranges);
51  1 assertEquals(ncl.toString(), expected);
52  1 assertTrue(ncl.isValid());
53    }
54   
 
55  1 toggle @Test(groups = "Functional")
56    public void testFindOverlaps()
57    {
58  1 List<Range> ranges = new ArrayList<Range>();
59  1 ranges.add(new Range(20, 50));
60  1 ranges.add(new Range(30, 70));
61  1 ranges.add(new Range(1, 100));
62  1 ranges.add(new Range(70, 120));
63   
64  1 NCList<Range> ncl = new NCList<Range>(ranges);
65   
66  1 List<Range> overlaps = ncl.findOverlaps(121, 122);
67  1 assertEquals(overlaps.size(), 0);
68   
69  1 overlaps = ncl.findOverlaps(21, 22);
70  1 assertEquals(overlaps.size(), 2);
71  1 assertEquals(((ContiguousI) overlaps.get(0)).getBegin(), 1);
72  1 assertEquals(((ContiguousI) overlaps.get(0)).getEnd(), 100);
73  1 assertEquals(((ContiguousI) overlaps.get(1)).getBegin(), 20);
74  1 assertEquals(((ContiguousI) overlaps.get(1)).getEnd(), 50);
75   
76  1 overlaps = ncl.findOverlaps(110, 110);
77  1 assertEquals(overlaps.size(), 1);
78  1 assertEquals(((ContiguousI) overlaps.get(0)).getBegin(), 70);
79  1 assertEquals(((ContiguousI) overlaps.get(0)).getEnd(), 120);
80    }
81   
 
82  1 toggle @Test(groups = "Functional")
83    public void testAdd_onTheEnd()
84    {
85  1 List<Range> ranges = new ArrayList<Range>();
86  1 ranges.add(new Range(20, 50));
87  1 NCList<Range> ncl = new NCList<Range>(ranges);
88  1 assertEquals(ncl.toString(), "[20-50]");
89  1 assertTrue(ncl.isValid());
90   
91  1 ncl.add(new Range(60, 70));
92  1 assertEquals(ncl.toString(), "[20-50, 60-70]");
93  1 assertTrue(ncl.isValid());
94    }
95   
 
96  1 toggle @Test(groups = "Functional")
97    public void testAdd_inside()
98    {
99  1 List<Range> ranges = new ArrayList<Range>();
100  1 ranges.add(new Range(20, 50));
101  1 NCList<Range> ncl = new NCList<Range>(ranges);
102  1 assertEquals(ncl.toString(), "[20-50]");
103  1 assertTrue(ncl.isValid());
104   
105  1 ncl.add(new Range(30, 40));
106  1 assertEquals(ncl.toString(), "[20-50 [30-40]]");
107    }
108   
 
109  1 toggle @Test(groups = "Functional")
110    public void testAdd_onTheFront()
111    {
112  1 List<Range> ranges = new ArrayList<Range>();
113  1 ranges.add(new Range(20, 50));
114  1 NCList<Range> ncl = new NCList<Range>(ranges);
115  1 assertEquals(ncl.toString(), "[20-50]");
116  1 assertTrue(ncl.isValid());
117   
118  1 ncl.add(new Range(5, 15));
119  1 assertEquals(ncl.toString(), "[5-15, 20-50]");
120  1 assertTrue(ncl.isValid());
121    }
122   
 
123  1 toggle @Test(groups = "Functional")
124    public void testAdd_enclosing()
125    {
126  1 List<Range> ranges = new ArrayList<Range>();
127  1 ranges.add(new Range(20, 50));
128  1 ranges.add(new Range(30, 60));
129  1 NCList<Range> ncl = new NCList<Range>(ranges);
130  1 assertEquals(ncl.toString(), "[20-50, 30-60]");
131  1 assertTrue(ncl.isValid());
132  1 assertEquals(ncl.getStart(), 20);
133   
134  1 ncl.add(new Range(10, 70));
135  1 assertEquals(ncl.toString(), "[10-70 [20-50, 30-60]]");
136  1 assertTrue(ncl.isValid());
137    }
138   
 
139  1 toggle @Test(groups = "Functional")
140    public void testAdd_spanning()
141    {
142  1 List<Range> ranges = new ArrayList<Range>();
143  1 ranges.add(new Range(20, 40));
144  1 ranges.add(new Range(60, 70));
145  1 NCList<Range> ncl = new NCList<Range>(ranges);
146  1 assertEquals(ncl.toString(), "[20-40, 60-70]");
147  1 assertTrue(ncl.isValid());
148   
149  1 ncl.add(new Range(30, 50));
150  1 assertEquals(ncl.toString(), "[20-40, 30-50, 60-70]");
151  1 assertTrue(ncl.isValid());
152   
153  1 ncl.add(new Range(40, 65));
154  1 assertEquals(ncl.toString(), "[20-40, 30-50, 40-65, 60-70]");
155  1 assertTrue(ncl.isValid());
156    }
157   
158    /**
159    * Provides the scales for pseudo-random NCLists i.e. the range of the maximal
160    * [0-scale] interval to be stored
161    *
162    * @return
163    */
 
164  1 toggle @DataProvider(name = "scalesOfLife")
165    public Object[][] getScales()
166    {
167  1 return new Object[][] { new Integer[] { 10 }, new Integer[] { 100 } };
168    }
169   
170    /**
171    * Do a number of pseudo-random (reproducible) builds of an NCList, to
172    * exercise as many methods of the class as possible while generating the
173    * range of possible structure topologies
174    * <ul>
175    * <li>verify that add adds an entry and increments size</li>
176    * <li>...except where the entry is already contained (by equals test)</li>
177    * <li>verify that the structure is valid at all stages of construction</li>
178    * <li>generate, run and verify a range of overlap queries</li>
179    * <li>tear down the structure by deleting entries, verifying correctness at
180    * each stage</li>
181    * </ul>
182    */
 
183  2 toggle @Test(groups = "Functional", dataProvider = "scalesOfLife")
184    public void test_pseudoRandom(Integer scale)
185    {
186  2 NCList<SequenceFeature> ncl = new NCList<SequenceFeature>();
187  2 List<SequenceFeature> features = new ArrayList<SequenceFeature>(scale);
188   
189  2 testAdd_pseudoRandom(scale, ncl, features);
190   
191    /*
192    * sort the list of added ranges - this doesn't affect the test,
193    * just makes it easier to inspect the data in the debugger
194    */
195  2 Collections.sort(features, sorter);
196   
197  2 testFindOverlaps_pseudoRandom(ncl, scale, features);
198   
199  2 testDelete_pseudoRandom(ncl, features);
200    }
201   
202    /**
203    * Pick randomly selected entries to delete in turn, checking the NCList size
204    * and validity at each stage, until it is empty
205    *
206    * @param ncl
207    * @param features
208    */
 
209  2 toggle protected void testDelete_pseudoRandom(NCList<SequenceFeature> ncl,
210    List<SequenceFeature> features)
211    {
212  2 int deleted = 0;
213   
214  93 while (!features.isEmpty())
215    {
216  91 assertEquals(ncl.size(), features.size());
217  91 int toDelete = random.nextInt(features.size());
218  91 SequenceFeature entry = features.get(toDelete);
219  91 assertTrue(ncl.contains(entry), String.format(
220    "NCList doesn't contain entry [%d] '%s'!", deleted,
221    entry.toString()));
222   
223  91 ncl.delete(entry);
224  91 assertFalse(ncl.contains(entry), String.format(
225    "NCList still contains deleted entry [%d] '%s'!", deleted,
226    entry.toString()));
227  91 features.remove(toDelete);
228  91 deleted++;
229   
230  91 assertTrue(ncl.isValid(), String.format(
231    "NCList invalid after %d deletions, last deleted was '%s'",
232    deleted, entry.toString()));
233   
234    /*
235    * brute force check that deleting one entry didn't delete any others
236    */
237  2122 for (int i = 0; i < features.size(); i++)
238    {
239  2031 SequenceFeature sf = features.get(i);
240  2031 assertTrue(ncl.contains(sf), String.format(
241    "NCList doesn't contain entry [%d] %s after deleting '%s'!",
242    i, sf.toString(), entry.toString()));
243    }
244    }
245  2 assertEquals(ncl.size(), 0); // all gone
246    }
247   
248    /**
249    * Randomly generate entries and add them to the NCList, checking its validity
250    * and size at each stage. A few entries should be duplicates (by equals test)
251    * so not get added.
252    *
253    * @param scale
254    * @param ncl
255    * @param features
256    */
 
257  2 toggle protected void testAdd_pseudoRandom(Integer scale,
258    NCList<SequenceFeature> ncl,
259    List<SequenceFeature> features)
260    {
261  2 int count = 0;
262  2 final int size = 50;
263   
264  102 for (int i = 0; i < size; i++)
265    {
266  100 int r1 = random.nextInt(scale + 1);
267  100 int r2 = random.nextInt(scale + 1);
268  100 int from = Math.min(r1, r2);
269  100 int to = Math.max(r1, r2);
270   
271    /*
272    * choice of two feature values means that occasionally an identical
273    * feature may be generated, in which case it should not be added
274    */
275  100 float value = (float) i % 2;
276  100 SequenceFeature feature = new SequenceFeature("Pfam", "", from, to,
277    value, "group");
278   
279    /*
280    * add to NCList - with duplicate entries (by equals) disallowed
281    */
282  100 ncl.add(feature, false);
283  100 if (features.contains(feature))
284    {
285  9 System.out.println("Duplicate feature generated "
286    + feature.toString());
287    }
288    else
289    {
290  91 features.add(feature);
291  91 count++;
292    }
293   
294    /*
295    * check list format is valid at each stage of its construction
296    */
297  100 assertTrue(ncl.isValid(),
298    String.format("Failed for scale = %d, i=%d", scale, i));
299  100 assertEquals(ncl.size(), count);
300    }
301    // System.out.println(ncl.prettyPrint());
302    }
303   
304    /**
305    * A helper method that generates pseudo-random range queries and veries that
306    * findOverlaps returns the correct matches
307    *
308    * @param ncl
309    * the NCList to query
310    * @param scale
311    * ncl maximal range is [0, scale]
312    * @param features
313    * a list of the ranges stored in ncl
314    */
 
315  2 toggle protected void testFindOverlaps_pseudoRandom(NCList<SequenceFeature> ncl,
316    int scale,
317    List<SequenceFeature> features)
318    {
319  2 int halfScale = scale / 2;
320  2 int minIterations = 20;
321   
322    /*
323    * generates ranges in [-halfScale, scale+halfScale]
324    * - some should be internal to [0, scale] P = 1/4
325    * - some should lie before 0 P = 1/16
326    * - some should lie after scale P = 1/16
327    * - some should overlap left P = 1/4
328    * - some should overlap right P = 1/4
329    * - some should enclose P = 1/8
330    *
331    * 50 iterations give a 96% probability of including the
332    * unlikeliest case; keep going until we have done all!
333    */
334  2 boolean inside = false;
335  2 boolean enclosing = false;
336  2 boolean before = false;
337  2 boolean after = false;
338  2 boolean overlapLeft = false;
339  2 boolean overlapRight = false;
340  2 boolean allCasesCovered = false;
341   
342  2 int i = 0;
343  42 while (i < minIterations || !allCasesCovered)
344    {
345  40 i++;
346  40 int r1 = random.nextInt((scale + 1) * 2);
347  40 int r2 = random.nextInt((scale + 1) * 2);
348  40 int from = Math.min(r1, r2) - halfScale;
349  40 int to = Math.max(r1, r2) - halfScale;
350   
351    /*
352    * ensure all cases of interest get covered
353    */
354  40 inside |= from >= 0 && to <= scale;
355  40 enclosing |= from <= 0 && to >= scale;
356  40 before |= to < 0;
357  40 after |= from > scale;
358  40 overlapLeft |= from < 0 && to >= 0 && to <= scale;
359  40 overlapRight |= from >= 0 && from <= scale && to > scale;
360  40 if (!allCasesCovered)
361    {
362  25 allCasesCovered |= inside && enclosing && before && after
363    && overlapLeft && overlapRight;
364  25 if (allCasesCovered)
365    {
366  2 System.out
367    .println(String
368    .format("Covered all findOverlaps cases after %d iterations for scale %d",
369    i, scale));
370    }
371    }
372   
373  40 verifyFindOverlaps(ncl, from, to, features);
374    }
375    }
376   
377    /**
378    * A helper method that verifies that overlaps found by interrogating an
379    * NCList correctly match those found by brute force search
380    *
381    * @param ncl
382    * @param from
383    * @param to
384    * @param features
385    */
 
386  40 toggle protected void verifyFindOverlaps(NCList<SequenceFeature> ncl, int from,
387    int to, List<SequenceFeature> features)
388    {
389  40 List<SequenceFeature> overlaps = ncl.findOverlaps(from, to);
390   
391    /*
392    * check returned entries do indeed overlap from-to range
393    */
394  40 for (ContiguousI sf : overlaps)
395    {
396  1043 int begin = sf.getBegin();
397  1043 int end = sf.getEnd();
398  1043 assertTrue(begin <= to && end >= from, String.format(
399    "[%d, %d] does not overlap query range [%d, %d]", begin, end,
400    from, to));
401    }
402   
403    /*
404    * check overlapping ranges are included in the results
405    * (the test above already shows non-overlapping ranges are not)
406    */
407  40 for (ContiguousI sf : features)
408    {
409  1820 int begin = sf.getBegin();
410  1820 int end = sf.getEnd();
411  1820 if (begin <= to && end >= from)
412    {
413  1043 boolean found = overlaps.contains(sf);
414  1043 assertTrue(found, String.format(
415    "[%d, %d] missing in query range [%d, %d]", begin, end,
416    from, to));
417    }
418    }
419    }
420   
 
421  1 toggle @Test(groups = "Functional")
422    public void testGetEntries()
423    {
424  1 List<Range> ranges = new ArrayList<Range>();
425  1 Range r1 = new Range(20, 20);
426  1 Range r2 = new Range(10, 20);
427  1 Range r3 = new Range(15, 30);
428  1 Range r4 = new Range(10, 30);
429  1 Range r5 = new Range(11, 19);
430  1 Range r6 = new Range(10, 20);
431  1 ranges.add(r1);
432  1 ranges.add(r2);
433  1 ranges.add(r3);
434  1 ranges.add(r4);
435  1 ranges.add(r5);
436  1 ranges.add(r6);
437   
438  1 NCList<Range> ncl = new NCList<Range>(ranges);
439  1 Range r7 = new Range(1, 100);
440  1 ncl.add(r7);
441   
442  1 List<Range> contents = ncl.getEntries();
443  1 assertEquals(contents.size(), 7);
444  1 assertTrue(contents.contains(r1));
445  1 assertTrue(contents.contains(r2));
446  1 assertTrue(contents.contains(r3));
447  1 assertTrue(contents.contains(r4));
448  1 assertTrue(contents.contains(r5));
449  1 assertTrue(contents.contains(r6));
450  1 assertTrue(contents.contains(r7));
451   
452  1 ncl = new NCList<Range>();
453  1 assertTrue(ncl.getEntries().isEmpty());
454    }
455   
 
456  1 toggle @Test(groups = "Functional")
457    public void testDelete()
458    {
459  1 List<Range> ranges = new ArrayList<Range>();
460  1 Range r1 = new Range(20, 30);
461  1 ranges.add(r1);
462  1 NCList<Range> ncl = new NCList<Range>(ranges);
463  1 assertTrue(ncl.getEntries().contains(r1));
464   
465  1 Range r2 = new Range(20, 30);
466  1 assertFalse(ncl.delete(null)); // null argument
467  1 assertFalse(ncl.delete(r2)); // never added
468  1 assertTrue(ncl.delete(r1)); // success
469  1 assertTrue(ncl.getEntries().isEmpty());
470   
471    /*
472    * tests where object.equals() == true
473    */
474  1 NCList<SequenceFeature> features = new NCList<SequenceFeature>();
475  1 SequenceFeature sf1 = new SequenceFeature("type", "desc", 1, 10, 2f,
476    "group");
477  1 SequenceFeature sf2 = new SequenceFeature("type", "desc", 1, 10, 2f,
478    "group");
479  1 features.add(sf1);
480  1 assertEquals(sf1, sf2); // sf1.equals(sf2)
481  1 assertFalse(features.delete(sf2)); // equality is not enough for deletion
482  1 assertTrue(features.getEntries().contains(sf1)); // still there!
483  1 assertTrue(features.delete(sf1));
484  1 assertTrue(features.getEntries().isEmpty()); // gone now
485   
486    /*
487    * test with duplicate objects in NCList
488    */
489  1 features.add(sf1);
490  1 features.add(sf1);
491  1 assertEquals(features.getEntries().size(), 2);
492  1 assertSame(features.getEntries().get(0), sf1);
493  1 assertSame(features.getEntries().get(1), sf1);
494  1 assertTrue(features.delete(sf1)); // first match only is deleted
495  1 assertTrue(features.contains(sf1));
496  1 assertEquals(features.size(), 1);
497  1 assertTrue(features.delete(sf1));
498  1 assertTrue(features.getEntries().isEmpty());
499    }
500   
 
501  1 toggle @Test(groups = "Functional")
502    public void testAdd_overlapping()
503    {
504  1 List<Range> ranges = new ArrayList<Range>();
505  1 ranges.add(new Range(40, 50));
506  1 ranges.add(new Range(20, 30));
507  1 NCList<Range> ncl = new NCList<Range>(ranges);
508  1 assertEquals(ncl.toString(), "[20-30, 40-50]");
509  1 assertTrue(ncl.isValid());
510   
511    /*
512    * add range overlapping internally
513    */
514  1 ncl.add(new Range(25, 35));
515  1 assertEquals(ncl.toString(), "[20-30, 25-35, 40-50]");
516  1 assertTrue(ncl.isValid());
517   
518    /*
519    * add range overlapping last range
520    */
521  1 ncl.add(new Range(45, 55));
522  1 assertEquals(ncl.toString(), "[20-30, 25-35, 40-50, 45-55]");
523  1 assertTrue(ncl.isValid());
524   
525    /*
526    * add range overlapping first range
527    */
528  1 ncl.add(new Range(15, 25));
529  1 assertEquals(ncl.toString(), "[15-25, 20-30, 25-35, 40-50, 45-55]");
530  1 assertTrue(ncl.isValid());
531    }
532   
533    /**
534    * Test the contains method (which uses object equals test)
535    */
 
536  1 toggle @Test(groups = "Functional")
537    public void testContains()
538    {
539  1 NCList<SequenceFeature> ncl = new NCList<SequenceFeature>();
540  1 SequenceFeature sf1 = new SequenceFeature("type", "desc", 1, 10, 2f,
541    "group");
542  1 SequenceFeature sf2 = new SequenceFeature("type", "desc", 1, 10, 2f,
543    "group");
544  1 SequenceFeature sf3 = new SequenceFeature("type", "desc", 1, 10, 2f,
545    "anothergroup");
546  1 ncl.add(sf1);
547   
548  1 assertTrue(ncl.contains(sf1));
549  1 assertTrue(ncl.contains(sf2)); // sf1.equals(sf2)
550  1 assertFalse(ncl.contains(sf3)); // !sf1.equals(sf3)
551   
552    /*
553    * make some deeper structure in the NCList
554    */
555  1 SequenceFeature sf4 = new SequenceFeature("type", "desc", 2, 9, 2f,
556    "group");
557  1 ncl.add(sf4);
558  1 assertTrue(ncl.contains(sf4));
559  1 SequenceFeature sf5 = new SequenceFeature("type", "desc", 4, 5, 2f,
560    "group");
561  1 SequenceFeature sf6 = new SequenceFeature("type", "desc", 6, 8, 2f,
562    "group");
563  1 ncl.add(sf5);
564  1 ncl.add(sf6);
565  1 assertTrue(ncl.contains(sf5));
566  1 assertTrue(ncl.contains(sf6));
567    }
568   
 
569  1 toggle @Test(groups = "Functional")
570    public void testIsValid()
571    {
572  1 List<Range> ranges = new ArrayList<Range>();
573  1 Range r1 = new Range(40, 50);
574  1 ranges.add(r1);
575  1 NCList<Range> ncl = new NCList<Range>(ranges);
576  1 assertTrue(ncl.isValid());
577   
578  1 Range r2 = new Range(42, 44);
579  1 ncl.add(r2);
580  1 assertTrue(ncl.isValid());
581  1 Range r3 = new Range(46, 48);
582  1 ncl.add(r3);
583  1 assertTrue(ncl.isValid());
584  1 Range r4 = new Range(43, 43);
585  1 ncl.add(r4);
586  1 assertTrue(ncl.isValid());
587   
588  1 assertEquals(ncl.toString(), "[40-50 [42-44 [43-43], 46-48]]");
589  1 assertTrue(ncl.isValid());
590   
591  1 PA.setValue(r1, "start", 43);
592  1 assertFalse(ncl.isValid()); // r2 not inside r1
593  1 PA.setValue(r1, "start", 40);
594  1 assertTrue(ncl.isValid());
595   
596  1 PA.setValue(r3, "start", 41);
597  1 assertFalse(ncl.isValid()); // r3 should precede r2
598  1 PA.setValue(r3, "start", 46);
599  1 assertTrue(ncl.isValid());
600   
601  1 PA.setValue(r4, "start", 41);
602  1 assertFalse(ncl.isValid()); // r4 not inside r2
603  1 PA.setValue(r4, "start", 43);
604  1 assertTrue(ncl.isValid());
605   
606  1 PA.setValue(r4, "start", 44);
607  1 assertFalse(ncl.isValid()); // r4 has reverse range
608    }
609   
 
610  1 toggle @Test(groups = "Functional")
611    public void testPrettyPrint()
612    {
613    /*
614    * construct NCList from a list of ranges
615    * they are sorted then assembled into NCList subregions
616    * notice that 42-42 end up inside 41-46
617    */
618  1 List<Range> ranges = new ArrayList<Range>();
619  1 ranges.add(new Range(40, 50));
620  1 ranges.add(new Range(45, 55));
621  1 ranges.add(new Range(40, 45));
622  1 ranges.add(new Range(41, 46));
623  1 ranges.add(new Range(42, 42));
624  1 ranges.add(new Range(42, 42));
625  1 NCList<Range> ncl = new NCList<Range>(ranges);
626  1 assertTrue(ncl.isValid());
627  1 assertEquals(ncl.toString(),
628    "[40-50 [40-45], 41-46 [42-42 [42-42]], 45-55]");
629  1 String expected = "40-50\n 40-45\n41-46\n 42-42\n 42-42\n45-55\n";
630  1 assertEquals(ncl.prettyPrint(), expected);
631   
632    /*
633    * repeat but now add ranges one at a time
634    * notice that 42-42 end up inside 40-50 so we get
635    * a different but equal valid NCList structure
636    */
637  1 ranges.clear();
638  1 ncl = new NCList<Range>(ranges);
639  1 ncl.add(new Range(40, 50));
640  1 ncl.add(new Range(45, 55));
641  1 ncl.add(new Range(40, 45));
642  1 ncl.add(new Range(41, 46));
643  1 ncl.add(new Range(42, 42));
644  1 ncl.add(new Range(42, 42));
645  1 assertTrue(ncl.isValid());
646  1 assertEquals(ncl.toString(),
647    "[40-50 [40-45 [42-42 [42-42]], 41-46], 45-55]");
648  1 expected = "40-50\n 40-45\n 42-42\n 42-42\n 41-46\n45-55\n";
649  1 assertEquals(ncl.prettyPrint(), expected);
650    }
651   
652    /**
653    * A test that shows different valid trees can be constructed from the same
654    * set of ranges, depending on the order of construction
655    */
 
656  1 toggle @Test(groups = "Functional")
657    public void testConstructor_alternativeTrees()
658    {
659  1 List<Range> ranges = new ArrayList<Range>();
660  1 ranges.add(new Range(10, 60));
661  1 ranges.add(new Range(20, 30));
662  1 ranges.add(new Range(40, 50));
663   
664    /*
665    * constructor with greedy traversal of sorted ranges to build nested
666    * containment lists results in 20-30 inside 10-60, 40-50 a sibling
667    */
668  1 NCList<Range> ncl = new NCList<Range>(ranges);
669  1 assertEquals(ncl.toString(), "[10-60 [20-30], 40-50]");
670  1 assertTrue(ncl.isValid());
671   
672    /*
673    * adding ranges one at a time results in 40-50
674    * a sibling of 20-30 inside 10-60
675    */
676  1 ncl = new NCList<Range>(new Range(10, 60));
677  1 ncl.add(new Range(20, 30));
678  1 ncl.add(new Range(40, 50));
679  1 assertEquals(ncl.toString(), "[10-60 [20-30, 40-50]]");
680  1 assertTrue(ncl.isValid());
681    }
682    }