import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
-import static org.testng.AssertJUnit.assertNotSame;
import static org.testng.AssertJUnit.assertSame;
import static org.testng.AssertJUnit.assertTrue;
+import static org.testng.AssertJUnit.fail;
+
+import jalview.gui.JvOptionPane;
import java.util.Arrays;
import java.util.BitSet;
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
import java.util.List;
+import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class ColumnSelectionTest
{
+ @BeforeClass(alwaysRun = true)
+ public void setUpJvOptionPane()
+ {
+ JvOptionPane.setInteractiveMode(false);
+ JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
+ }
+
@Test(groups = { "Functional" })
public void testAddElement()
{
// removing an element in the list removes it
cs.removeElement(2);
- // ...but not from the copy list!
- assertEquals(2, sel.size());
+ // ...and also from the read-only view
+ assertEquals(1, sel.size());
sel = cs.getSelected();
assertEquals(1, sel.size());
assertEquals(new Integer(5), sel.get(0));
}
- @Test(groups={"Functional"})
+ @Test(groups = { "Functional" })
public void testLocateVisibleBoundsPathologicals()
{
// test some pathological cases we missed
- AlignmentI al = new Alignment(new SequenceI[] { new Sequence("refseqGaptest","KTDVTI----------NFI-----G----L")});
+ AlignmentI al = new Alignment(new SequenceI[] { new Sequence(
+ "refseqGaptest", "KTDVTI----------NFI-----G----L") });
ColumnSelection cs = new ColumnSelection();
cs.hideInsertionsFor(al.getSequenceAt(0));
assertEquals(
+ al.getSequenceAt(0).getCharAt(
cs.adjustForHiddenColumns(9)));
-
}
+
@Test(groups = { "Functional" })
public void testHideColumns()
{
assertEquals("[5, 5]", Arrays.toString(hidden.get(1)));
// hiding column 4 expands [3, 3] to [3, 4]
- // not fancy enough to coalesce this into [3, 5] though
+ // and merges to [5, 5] to make [3, 5]
cs.hideColumns(4);
hidden = cs.getHiddenColumns();
- assertEquals(2, hidden.size());
- assertEquals("[3, 4]", Arrays.toString(hidden.get(0)));
- assertEquals("[5, 5]", Arrays.toString(hidden.get(1)));
+ assertEquals(1, hidden.size());
+ assertEquals("[3, 5]", Arrays.toString(hidden.get(0)));
// clear hidden columns (note they are added to selected)
cs.revealAllHiddenColumns();
cs.addElement(1);
cs.hideColumns(3);
cs.hideColumns(7);
- cs.hideColumns(5,9);
+ cs.hideColumns(5, 9);
// same selections added in a different order
ColumnSelection cs2 = new ColumnSelection();
cs2.hideColumns(6, 9);
cs2.hideColumns(5, 8);
cs2.hideColumns(3);
-
+
assertTrue(cs.equals(cs2));
assertTrue(cs.equals(cs));
assertTrue(cs2.equals(cs));
* were added
*/
@Test(groups = { "Functional" })
- public void testGetSelection()
+ public void testGetSelected()
{
ColumnSelection cs = new ColumnSelection();
int[] sel = { 4, 3, 7, 21 };
cs.addElement(col);
}
- List<Integer> selected1 = cs.getSelected();
- assertEquals(4, selected1.size());
+ List<Integer> selected = cs.getSelected();
+ assertEquals(4, selected.size());
+ assertEquals("[4, 3, 7, 21]", selected.toString());
/*
- * getSelected returns a copy, verify the list
- * is externally immutable
+ * getSelected returns a read-only view of the list
+ * verify the view follows any changes in it
*/
- selected1.clear();
- List<Integer> selected2 = cs.getSelected();
- assertNotSame(selected1, selected2);
- assertEquals(4, selected2.size());
- int i = 0;
- for (int col : sel)
+ 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)
{
- assertEquals(col, selected2.get(i++).intValue());
+ // expected
}
+ try
+ {
+ Collections.sort(selected);
+ fail("expected exception");
+ } catch (UnsupportedOperationException e)
+ {
+ // expected
+ }
+ }
- cs.removeElement(7);
+ /**
+ * 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.removeElement(4);
+ cs.addElement(2);
- List<Integer> selected3 = cs.getSelected();
- assertEquals(3, selected3.size());
- assertEquals(3, selected3.get(0).intValue());
- assertEquals(21, selected3.get(1).intValue());
- assertEquals(1, selected3.get(2).intValue());
+ /*
+ * 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")
assertTrue(selected.contains(6));
assertTrue(selected.contains(10));
}
+
+ @Test(groups = "Functional")
+ public void testCopyConstructor()
+ {
+ ColumnSelection cs = new ColumnSelection();
+ cs.addElement(3);
+ cs.addElement(1);
+ cs.hideColumns(10, 11);
+ cs.hideColumns(5, 7);
+ assertEquals("[5, 7]", Arrays.toString(cs.getHiddenColumns().get(0)));
+
+ ColumnSelection cs2 = new ColumnSelection(cs);
+ assertTrue(cs2.hasSelectedColumns());
+ assertTrue(cs2.hasHiddenColumns());
+ // order of column selection is preserved
+ assertEquals("[3, 1]", cs2.getSelected().toString());
+ assertEquals(2, cs2.getHiddenColumns().size());
+ // hidden columns are held in column order
+ assertEquals("[5, 7]", Arrays.toString(cs2.getHiddenColumns().get(0)));
+ assertEquals("[10, 11]", Arrays.toString(cs2.getHiddenColumns().get(1)));
+ }
+
+ /**
+ * Test for the case when a hidden range encloses more one already hidden
+ * range
+ */
+ @Test(groups = { "Functional" })
+ public void testHideColumns_subsumingHidden()
+ {
+ /*
+ * JAL-2370 bug scenario:
+ * two hidden ranges subsumed by a third
+ */
+ ColumnSelection cs = new ColumnSelection();
+ cs.hideColumns(49, 59);
+ cs.hideColumns(69, 79);
+ List<int[]> hidden = cs.getHiddenColumns();
+ assertEquals(2, hidden.size());
+ assertEquals("[49, 59]", Arrays.toString(hidden.get(0)));
+ assertEquals("[69, 79]", Arrays.toString(hidden.get(1)));
+
+ cs.hideColumns(48, 80);
+ hidden = cs.getHiddenColumns();
+ assertEquals(1, hidden.size());
+ assertEquals("[48, 80]", Arrays.toString(hidden.get(0)));
+
+ /*
+ * another...joining hidden ranges
+ */
+ cs = new ColumnSelection();
+ cs.hideColumns(10, 20);
+ cs.hideColumns(30, 40);
+ cs.hideColumns(50, 60);
+ // hiding 21-49 should merge to one range
+ cs.hideColumns(21, 49);
+ hidden = cs.getHiddenColumns();
+ assertEquals(1, hidden.size());
+ assertEquals("[10, 60]", Arrays.toString(hidden.get(0)));
+
+ /*
+ * another...lef overlap, subsumption, right overlap,
+ * no overlap of existing hidden ranges
+ */
+ cs = new ColumnSelection();
+ cs.hideColumns(10, 20);
+ cs.hideColumns(10, 20);
+ cs.hideColumns(30, 35);
+ cs.hideColumns(40, 50);
+ cs.hideColumns(60, 70);
+
+ cs.hideColumns(15, 45);
+ hidden = cs.getHiddenColumns();
+ assertEquals(2, hidden.size());
+ assertEquals("[10, 50]", Arrays.toString(hidden.get(0)));
+ assertEquals("[60, 70]", Arrays.toString(hidden.get(1)));
+ }
+
+ @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);
+ }
}