+ ColumnSelection cs = new ColumnSelection();
+ int[] sel = { 2, 3, 4, 7, 8, 9, 20, 21, 22 };
+ for (int col : sel)
+ {
+ cs.addElement(col);
+ }
+
+ HiddenColumns cols = al.getHiddenColumns();
+ cols.hideColumns(15, 18);
+
+ cs.hideSelectedColumns(al);
+ assertTrue(cs.getSelected().isEmpty());
+ Iterator<int[]> regions = cols.iterator();
+ assertEquals(4, cols.getNumberOfRegions());
+ assertEquals("[2, 4]", Arrays.toString(regions.next()));
+ assertEquals("[7, 9]", Arrays.toString(regions.next()));
+ assertEquals("[15, 18]", Arrays.toString(regions.next()));
+ assertEquals("[20, 22]", Arrays.toString(regions.next()));
+ }
+
+ /**
+ * Test the method that gets runs of selected columns ordered by column. If
+ * this fails, HideSelectedColumns may also fail
+ */
+ @Test(groups = { "Functional" })
+ public void testGetSelectedRanges()
+ {
+ /*
+ * getSelectedRanges returns ordered columns regardless
+ * of the order in which they are added
+ */
+ ColumnSelection cs = new ColumnSelection();
+ int[] sel = { 4, 3, 7, 21, 9, 20, 8, 22, 2 };
+ for (int col : sel)
+ {
+ cs.addElement(col);
+ }
+ List<int[]> range;
+ range = cs.getSelectedRanges();
+ assertEquals(3, range.size());
+ assertEquals("[2, 4]", Arrays.toString(range.get(0)));
+ assertEquals("[7, 9]", Arrays.toString(range.get(1)));
+ assertEquals("[20, 22]", Arrays.toString(range.get(2)));
+ cs.addElement(0);
+ cs.addElement(1);
+ range = cs.getSelectedRanges();
+ assertEquals(3, range.size());
+ assertEquals("[0, 4]", Arrays.toString(range.get(0)));
+ }
+
+ @Test(groups = { "Functional" })
+ public void testInvertColumnSelection()
+ {
+ // create random alignment
+ AlignmentGenerator gen = new AlignmentGenerator(false);
+ AlignmentI al = gen.generate(50, 20, 123, 5, 5);
+
+ ColumnSelection cs = new ColumnSelection();
+ cs.addElement(4);
+ cs.addElement(6);
+ cs.addElement(8);
+
+ HiddenColumns cols = al.getHiddenColumns();
+ cols.hideColumns(3, 3);
+ cols.hideColumns(6, 6);
+
+ // invert selection from start (inclusive) to end (exclusive)
+ cs.invertColumnSelection(2, 9, al);
+ assertEquals("[2, 5, 7]", cs.getSelected().toString());
+
+ cs.invertColumnSelection(1, 9, al);
+ assertEquals("[1, 4, 8]", cs.getSelected().toString());
+ }
+
+ @Test(groups = { "Functional" })
+ public void testMaxColumnSelection()
+ {
+ ColumnSelection cs = new ColumnSelection();
+ cs.addElement(0);
+ cs.addElement(513);
+ cs.addElement(1);
+ assertEquals(513, cs.getMax());
+ cs.removeElement(513);
+ assertEquals(1, cs.getMax());
+ cs.removeElement(1);
+ assertEquals(0, cs.getMax());
+ cs.addElement(512);
+ cs.addElement(513);
+ assertEquals(513, cs.getMax());
+
+ }
+
+ @Test(groups = { "Functional" })
+ public void testMinColumnSelection()
+ {
+ ColumnSelection cs = new ColumnSelection();
+ cs.addElement(0);
+ cs.addElement(513);
+ cs.addElement(1);
+ assertEquals(0, cs.getMin());
+ cs.removeElement(0);
+ assertEquals(1, cs.getMin());
+ cs.addElement(0);
+ assertEquals(0, cs.getMin());
+ }
+
+ @Test(groups = { "Functional" })
+ public void testEquals()
+ {
+ ColumnSelection cs = new ColumnSelection();
+ cs.addElement(0);
+ cs.addElement(513);
+ cs.addElement(1);
+
+ // same selections added in a different order
+ ColumnSelection cs2 = new ColumnSelection();
+ cs2.addElement(1);
+ cs2.addElement(513);
+ cs2.addElement(0);
+
+ assertTrue(cs.equals(cs2));
+ assertTrue(cs.equals(cs));
+ assertTrue(cs2.equals(cs));
+ assertTrue(cs2.equals(cs2));
+
+ cs2.addElement(12);
+ assertFalse(cs.equals(cs2));
+ assertFalse(cs2.equals(cs));
+
+ cs2.removeElement(12);
+ assertTrue(cs.equals(cs2));
+ }
+
+ /*
+ cs2.hideSelectedColumns(88);
+ assertFalse(cs.equals(cs2));
+ /*
+ * unhiding a column adds it to selection!
+ */
+ /* cs2.revealHiddenColumns(88);
+ assertFalse(cs.equals(cs2));
+ cs.addElement(88);
+ assertTrue(cs.equals(cs2));
+ */
+
+ /**
+ * Test the method that returns selected columns, in the order in which they
+ * were added
+ */
+ @Test(groups = { "Functional" })
+ public void testGetSelected()
+ {
+ ColumnSelection cs = new ColumnSelection();
+ int[] sel = { 4, 3, 7, 21 };
+ for (int col : sel)
+ {
+ cs.addElement(col);
+ }
+
+ List<Integer> selected = cs.getSelected();
+ assertEquals(4, selected.size());
+ assertEquals("[4, 3, 7, 21]", selected.toString());
+
+ /*
+ * getSelected returns a read-only view of the list
+ * verify the view follows any changes in it
+ */
+ cs.removeElement(7);
+ cs.addElement(1);
+ cs.removeElement(4);
+ assertEquals("[3, 21, 1]", selected.toString());
+ }
+
+ /**
+ * Test to verify that the list returned by getSelection cannot be modified
+ */
+ @Test(groups = { "Functional" })
+ public void testGetSelected_isReadOnly()
+ {
+ ColumnSelection cs = new ColumnSelection();
+ cs.addElement(3);
+
+ List<Integer> selected = cs.getSelected();
+ try
+ {
+ selected.clear();
+ fail("expected exception");
+ } catch (UnsupportedOperationException e)
+ {
+ // expected
+ }
+ try
+ {
+ selected.add(1);
+ fail("expected exception");
+ } catch (UnsupportedOperationException e)
+ {
+ // expected
+ }
+ try
+ {
+ selected.remove(3);
+ fail("expected exception");
+ } catch (UnsupportedOperationException e)
+ {
+ // expected
+ }
+ try
+ {
+ Collections.sort(selected);
+ fail("expected exception");
+ } catch (UnsupportedOperationException e)
+ {
+ // expected
+ }
+ }
+
+ /**
+ * Test that demonstrates a ConcurrentModificationException is thrown if you
+ * change the selection while iterating over it
+ */
+ @Test(
+ groups = "Functional",
+ expectedExceptions = { ConcurrentModificationException.class })
+ public void testGetSelected_concurrentModification()
+ {
+ ColumnSelection cs = new ColumnSelection();
+ cs.addElement(0);
+ cs.addElement(1);
+ cs.addElement(2);
+
+ /*
+ * simulate changing the list under us (e.g. in a separate
+ * thread) while iterating over it -> ConcurrentModificationException
+ */
+ List<Integer> selected = cs.getSelected();
+ for (Integer col : selected)
+ {
+ if (col.intValue() == 0)
+ {
+ cs.removeElement(1);
+ }
+ }
+ }
+
+ @Test(groups = "Functional")
+ public void testMarkColumns()
+ {
+ ColumnSelection cs = new ColumnSelection();
+ cs.addElement(5); // this will be cleared
+ BitSet toMark = new BitSet();
+ toMark.set(1);
+ toMark.set(3);
+ toMark.set(6);
+ toMark.set(9);
+
+ assertTrue(cs.markColumns(toMark, 3, 8, false, false, false));
+ List<Integer> selected = cs.getSelected();
+ assertEquals(2, selected.size());
+ assertTrue(selected.contains(3));
+ assertTrue(selected.contains(6));
+ }
+
+ @Test(groups = "Functional")
+ public void testMarkColumns_extend()
+ {
+ ColumnSelection cs = new ColumnSelection();
+ cs.addElement(1);
+ cs.addElement(5);
+ BitSet toMark = new BitSet();
+ toMark.set(1);
+ toMark.set(3);
+ toMark.set(6);
+ toMark.set(9);
+
+ /*
+ * extending selection of {3, 6} should leave {1, 3, 5, 6} selected
+ */
+ assertTrue(cs.markColumns(toMark, 3, 8, false, true, false));
+ List<Integer> selected = cs.getSelected();
+ assertEquals(4, selected.size());
+ assertTrue(selected.contains(1));
+ assertTrue(selected.contains(3));
+ assertTrue(selected.contains(5));
+ assertTrue(selected.contains(6));
+ }
+
+ @Test(groups = "Functional")
+ public void testMarkColumns_invert()
+ {
+ ColumnSelection cs = new ColumnSelection();
+ cs.addElement(5); // this will be cleared
+ BitSet toMark = new BitSet();
+ toMark.set(1);
+ toMark.set(3);
+ toMark.set(6);
+ toMark.set(9);
+
+ /*
+ * inverted selection of {3, 6} should select {4, 5, 7, 8}
+ */
+ assertTrue(cs.markColumns(toMark, 3, 8, true, false, false));
+ List<Integer> selected = cs.getSelected();
+ assertEquals(4, selected.size());
+ assertTrue(selected.contains(4));
+ assertTrue(selected.contains(5));
+ assertTrue(selected.contains(7));
+ assertTrue(selected.contains(8));
+ }
+
+ @Test(groups = "Functional")
+ public void testMarkColumns_toggle()
+ {
+ ColumnSelection cs = new ColumnSelection();
+ cs.addElement(1); // outside change range
+ cs.addElement(3);
+ cs.addElement(4);
+ cs.addElement(10); // outside change range
+ BitSet toMark = new BitSet();
+ toMark.set(1);
+ toMark.set(3);
+ toMark.set(6);
+ toMark.set(9);
+
+ /*
+ * toggling state of {3, 6} should leave {1, 4, 6, 10} selected
+ */
+ assertTrue(cs.markColumns(toMark, 3, 8, false, false, true));
+ List<Integer> selected = cs.getSelected();
+ assertEquals(4, selected.size());
+ assertTrue(selected.contains(1));
+ assertTrue(selected.contains(4));
+ assertTrue(selected.contains(6));
+ assertTrue(selected.contains(10));
+ }
+
+ @Test(groups = "Functional")
+ public void testCopyConstructor()
+ {
+ ColumnSelection cs = new ColumnSelection();
+ cs.addElement(3);
+ cs.addElement(1);
+
+ ColumnSelection cs2 = new ColumnSelection(cs);
+ assertTrue(cs2.hasSelectedColumns());
+
+ // order of column selection is preserved
+ assertEquals("[3, 1]", cs2.getSelected().toString());
+ }
+
+
+ @Test(groups = { "Functional" })
+ public void testStretchGroup_expand()
+ {
+ /*
+ * test that emulates clicking column 4 (selected)
+ * and dragging right to column 5 (all base 0)
+ */
+ ColumnSelection cs = new ColumnSelection();
+ cs.addElement(4);
+ SequenceGroup sg = new SequenceGroup();
+ sg.setStartRes(4);
+ sg.setEndRes(4);
+ cs.stretchGroup(5, sg, 4, 4);
+ assertEquals(cs.getSelected().size(), 2);
+ assertTrue(cs.contains(4));
+ assertTrue(cs.contains(5));
+ assertEquals(sg.getStartRes(), 4);
+ assertEquals(sg.getEndRes(), 5);
+
+ /*
+ * emulate drag right with columns 10-20 already selected
+ */
+ cs.clear();
+ for (int i = 10; i <= 20; i++)
+ {
+ cs.addElement(i);
+ }
+ assertEquals(cs.getSelected().size(), 11);
+ sg = new SequenceGroup();
+ sg.setStartRes(10);
+ sg.setEndRes(20);
+ cs.stretchGroup(21, sg, 10, 20);
+ assertEquals(cs.getSelected().size(), 12);
+ assertTrue(cs.contains(10));
+ assertTrue(cs.contains(21));
+ assertEquals(sg.getStartRes(), 10);
+ assertEquals(sg.getEndRes(), 21);
+ }
+
+ @Test(groups = { "Functional" })
+ public void testStretchGroup_shrink()
+ {
+ /*
+ * emulate drag left to 19 with columns 10-20 already selected
+ */
+ ColumnSelection cs = new ColumnSelection();
+ for (int i = 10; i <= 20; i++)
+ {
+ cs.addElement(i);
+ }
+ assertEquals(cs.getSelected().size(), 11);
+ SequenceGroup sg = new SequenceGroup();
+ sg.setStartRes(10);
+ sg.setEndRes(20);
+ cs.stretchGroup(19, sg, 10, 20);
+ assertEquals(cs.getSelected().size(), 10);
+ assertTrue(cs.contains(10));
+ assertTrue(cs.contains(19));
+ assertFalse(cs.contains(20));
+ assertEquals(sg.getStartRes(), 10);
+ assertEquals(sg.getEndRes(), 19);