2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.datamodel;
23 import static org.testng.AssertJUnit.assertEquals;
24 import static org.testng.AssertJUnit.assertFalse;
25 import static org.testng.AssertJUnit.assertTrue;
26 import static org.testng.AssertJUnit.fail;
28 import jalview.analysis.AlignmentGenerator;
29 import jalview.gui.JvOptionPane;
31 import java.util.Arrays;
32 import java.util.BitSet;
33 import java.util.Collections;
34 import java.util.ConcurrentModificationException;
35 import java.util.List;
37 import org.testng.annotations.BeforeClass;
38 import org.testng.annotations.Test;
40 public class ColumnSelectionTest
43 @BeforeClass(alwaysRun = true)
44 public void setUpJvOptionPane()
46 JvOptionPane.setInteractiveMode(false);
47 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
50 @Test(groups = { "Functional" })
51 public void testAddElement()
53 ColumnSelection cs = new ColumnSelection();
57 cs.addElement(5); // ignored
58 List<Integer> sel = cs.getSelected();
59 assertEquals("[2, 5, 3]", sel.toString());
62 @Test(groups = { "Functional" })
63 public void testSetElementsFrom()
65 ColumnSelection fromcs = new ColumnSelection();
66 ColumnSelection tocs = new ColumnSelection();
67 HiddenColumns hidden = new HiddenColumns();
73 tocs.setElementsFrom(fromcs, hidden);
74 assertTrue(tocs.equals(fromcs));
76 hidden.hideColumns(4, 6);
77 tocs.setElementsFrom(fromcs, hidden);
79 // expect cols 2 and 3 to be selected but not 5
80 ColumnSelection expectcs = new ColumnSelection();
81 expectcs.addElement(2);
82 expectcs.addElement(3);
83 assertTrue(tocs.equals(expectcs));
87 * Test the remove method - in particular to verify that remove(int i) removes
88 * the element whose value is i, _NOT_ the i'th element.
90 @Test(groups = { "Functional" })
91 public void testRemoveElement()
93 ColumnSelection cs = new ColumnSelection();
97 // removing elements not in the list has no effect
100 List<Integer> sel = cs.getSelected();
101 assertEquals(2, sel.size());
102 assertEquals(new Integer(2), sel.get(0));
103 assertEquals(new Integer(5), sel.get(1));
105 // removing an element in the list removes it
107 // ...and also from the read-only view
108 assertEquals(1, sel.size());
109 sel = cs.getSelected();
110 assertEquals(1, sel.size());
111 assertEquals(new Integer(5), sel.get(0));
115 * Test the method that hides a specified column including any adjacent
116 * selected columns. This is a convenience method for the case where multiple
117 * column regions are selected and then hidden using menu option View | Hide |
120 @Test(groups = { "Functional" })
121 public void testHideColumns_withSelection()
123 // create random alignment
124 AlignmentGenerator gen = new AlignmentGenerator(false);
125 AlignmentI al = gen.generate(50, 20, 123, 5, 5);
127 ColumnSelection cs = new ColumnSelection();
128 // select columns 4-6
132 // hide column 5 (and adjacent):
133 cs.hideSelectedColumns(5, al.getHiddenColumns());
135 List<int[]> hidden = al.getHiddenColumns().getHiddenRegions();
136 assertEquals(1, hidden.size());
137 assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
138 // none now selected:
139 assertTrue(cs.getSelected().isEmpty());
141 // repeat, hiding column 4 (5 and 6)
142 al = gen.generate(50, 20, 123, 5, 5);
143 cs = new ColumnSelection();
147 cs.hideSelectedColumns(4, al.getHiddenColumns());
148 hidden = al.getHiddenColumns().getHiddenRegions();
149 assertEquals(1, hidden.size());
150 assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
151 assertTrue(cs.getSelected().isEmpty());
153 // repeat, hiding column (4, 5 and) 6
154 al = gen.generate(50, 20, 123, 5, 5);
155 cs = new ColumnSelection();
159 cs.hideSelectedColumns(6, al.getHiddenColumns());
160 hidden = al.getHiddenColumns().getHiddenRegions();
161 assertEquals(1, hidden.size());
162 assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
163 assertTrue(cs.getSelected().isEmpty());
165 // repeat, with _only_ adjacent columns selected
166 al = gen.generate(50, 20, 123, 5, 5);
167 cs = new ColumnSelection();
170 cs.hideSelectedColumns(5, al.getHiddenColumns());
171 hidden = al.getHiddenColumns().getHiddenRegions();
172 assertEquals(1, hidden.size());
173 assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
174 assertTrue(cs.getSelected().isEmpty());
178 * Test the method that hides all (possibly disjoint) selected column ranges
180 @Test(groups = { "Functional" })
181 public void testHideSelectedColumns()
183 // create random alignment
184 AlignmentGenerator gen = new AlignmentGenerator(false);
185 AlignmentI al = gen.generate(50, 20, 123, 5, 5);
187 ColumnSelection cs = new ColumnSelection();
188 int[] sel = { 2, 3, 4, 7, 8, 9, 20, 21, 22 };
194 HiddenColumns cols = al.getHiddenColumns();
195 cols.hideColumns(15, 18);
197 cs.hideSelectedColumns(al);
198 assertTrue(cs.getSelected().isEmpty());
199 List<int[]> hidden = cols.getHiddenRegions();
200 assertEquals(4, hidden.size());
201 assertEquals("[2, 4]", Arrays.toString(hidden.get(0)));
202 assertEquals("[7, 9]", Arrays.toString(hidden.get(1)));
203 assertEquals("[15, 18]", Arrays.toString(hidden.get(2)));
204 assertEquals("[20, 22]", Arrays.toString(hidden.get(3)));
208 * Test the method that gets runs of selected columns ordered by column. If
209 * this fails, HideSelectedColumns may also fail
211 @Test(groups = { "Functional" })
212 public void testGetSelectedRanges()
215 * getSelectedRanges returns ordered columns regardless
216 * of the order in which they are added
218 ColumnSelection cs = new ColumnSelection();
219 int[] sel = { 4, 3, 7, 21, 9, 20, 8, 22, 2 };
225 range = cs.getSelectedRanges();
226 assertEquals(3, range.size());
227 assertEquals("[2, 4]", Arrays.toString(range.get(0)));
228 assertEquals("[7, 9]", Arrays.toString(range.get(1)));
229 assertEquals("[20, 22]", Arrays.toString(range.get(2)));
232 range = cs.getSelectedRanges();
233 assertEquals(3, range.size());
234 assertEquals("[0, 4]", Arrays.toString(range.get(0)));
237 @Test(groups = { "Functional" })
238 public void testInvertColumnSelection()
240 // create random alignment
241 AlignmentGenerator gen = new AlignmentGenerator(false);
242 AlignmentI al = gen.generate(50, 20, 123, 5, 5);
244 ColumnSelection cs = new ColumnSelection();
249 HiddenColumns cols = al.getHiddenColumns();
250 cols.hideColumns(3, 3);
251 cols.hideColumns(6, 6);
253 // invert selection from start (inclusive) to end (exclusive)
254 cs.invertColumnSelection(2, 9, al);
255 assertEquals("[2, 5, 7]", cs.getSelected().toString());
257 cs.invertColumnSelection(1, 9, al);
258 assertEquals("[1, 4, 8]", cs.getSelected().toString());
261 @Test(groups = { "Functional" })
262 public void testMaxColumnSelection()
264 ColumnSelection cs = new ColumnSelection();
268 assertEquals(513, cs.getMax());
269 cs.removeElement(513);
270 assertEquals(1, cs.getMax());
272 assertEquals(0, cs.getMax());
275 assertEquals(513, cs.getMax());
279 @Test(groups = { "Functional" })
280 public void testMinColumnSelection()
282 ColumnSelection cs = new ColumnSelection();
286 assertEquals(0, cs.getMin());
288 assertEquals(1, cs.getMin());
290 assertEquals(0, cs.getMin());
293 @Test(groups = { "Functional" })
294 public void testEquals()
296 ColumnSelection cs = new ColumnSelection();
301 // same selections added in a different order
302 ColumnSelection cs2 = new ColumnSelection();
307 assertTrue(cs.equals(cs2));
308 assertTrue(cs.equals(cs));
309 assertTrue(cs2.equals(cs));
310 assertTrue(cs2.equals(cs2));
313 assertFalse(cs.equals(cs2));
314 assertFalse(cs2.equals(cs));
316 cs2.removeElement(12);
317 assertTrue(cs.equals(cs2));
321 cs2.hideSelectedColumns(88);
322 assertFalse(cs.equals(cs2));
324 * unhiding a column adds it to selection!
326 /* cs2.revealHiddenColumns(88);
327 assertFalse(cs.equals(cs2));
329 assertTrue(cs.equals(cs2));
333 * Test the method that returns selected columns, in the order in which they
336 @Test(groups = { "Functional" })
337 public void testGetSelected()
339 ColumnSelection cs = new ColumnSelection();
340 int[] sel = { 4, 3, 7, 21 };
346 List<Integer> selected = cs.getSelected();
347 assertEquals(4, selected.size());
348 assertEquals("[4, 3, 7, 21]", selected.toString());
351 * getSelected returns a read-only view of the list
352 * verify the view follows any changes in it
357 assertEquals("[3, 21, 1]", selected.toString());
361 * Test to verify that the list returned by getSelection cannot be modified
363 @Test(groups = { "Functional" })
364 public void testGetSelected_isReadOnly()
366 ColumnSelection cs = new ColumnSelection();
369 List<Integer> selected = cs.getSelected();
373 fail("expected exception");
374 } catch (UnsupportedOperationException e)
381 fail("expected exception");
382 } catch (UnsupportedOperationException e)
389 fail("expected exception");
390 } catch (UnsupportedOperationException e)
396 Collections.sort(selected);
397 fail("expected exception");
398 } catch (UnsupportedOperationException e)
405 * Test that demonstrates a ConcurrentModificationException is thrown if you
406 * change the selection while iterating over it
409 groups = "Functional",
410 expectedExceptions = { ConcurrentModificationException.class })
411 public void testGetSelected_concurrentModification()
413 ColumnSelection cs = new ColumnSelection();
419 * simulate changing the list under us (e.g. in a separate
420 * thread) while iterating over it -> ConcurrentModificationException
422 List<Integer> selected = cs.getSelected();
423 for (Integer col : selected)
425 if (col.intValue() == 0)
432 @Test(groups = "Functional")
433 public void testMarkColumns()
435 ColumnSelection cs = new ColumnSelection();
436 cs.addElement(5); // this will be cleared
437 BitSet toMark = new BitSet();
443 assertTrue(cs.markColumns(toMark, 3, 8, false, false, false));
444 List<Integer> selected = cs.getSelected();
445 assertEquals(2, selected.size());
446 assertTrue(selected.contains(3));
447 assertTrue(selected.contains(6));
450 @Test(groups = "Functional")
451 public void testMarkColumns_extend()
453 ColumnSelection cs = new ColumnSelection();
456 BitSet toMark = new BitSet();
463 * extending selection of {3, 6} should leave {1, 3, 5, 6} selected
465 assertTrue(cs.markColumns(toMark, 3, 8, false, true, false));
466 List<Integer> selected = cs.getSelected();
467 assertEquals(4, selected.size());
468 assertTrue(selected.contains(1));
469 assertTrue(selected.contains(3));
470 assertTrue(selected.contains(5));
471 assertTrue(selected.contains(6));
474 @Test(groups = "Functional")
475 public void testMarkColumns_invert()
477 ColumnSelection cs = new ColumnSelection();
478 cs.addElement(5); // this will be cleared
479 BitSet toMark = new BitSet();
486 * inverted selection of {3, 6} should select {4, 5, 7, 8}
488 assertTrue(cs.markColumns(toMark, 3, 8, true, false, false));
489 List<Integer> selected = cs.getSelected();
490 assertEquals(4, selected.size());
491 assertTrue(selected.contains(4));
492 assertTrue(selected.contains(5));
493 assertTrue(selected.contains(7));
494 assertTrue(selected.contains(8));
497 @Test(groups = "Functional")
498 public void testMarkColumns_toggle()
500 ColumnSelection cs = new ColumnSelection();
501 cs.addElement(1); // outside change range
504 cs.addElement(10); // outside change range
505 BitSet toMark = new BitSet();
512 * toggling state of {3, 6} should leave {1, 4, 6, 10} selected
514 assertTrue(cs.markColumns(toMark, 3, 8, false, false, true));
515 List<Integer> selected = cs.getSelected();
516 assertEquals(4, selected.size());
517 assertTrue(selected.contains(1));
518 assertTrue(selected.contains(4));
519 assertTrue(selected.contains(6));
520 assertTrue(selected.contains(10));
523 @Test(groups = "Functional")
524 public void testCopyConstructor()
526 ColumnSelection cs = new ColumnSelection();
530 ColumnSelection cs2 = new ColumnSelection(cs);
531 assertTrue(cs2.hasSelectedColumns());
533 // order of column selection is preserved
534 assertEquals("[3, 1]", cs2.getSelected().toString());
538 @Test(groups = { "Functional" })
539 public void testStretchGroup_expand()
542 * test that emulates clicking column 4 (selected)
543 * and dragging right to column 5 (all base 0)
545 ColumnSelection cs = new ColumnSelection();
547 SequenceGroup sg = new SequenceGroup();
550 cs.stretchGroup(5, sg, 4, 4);
551 assertEquals(cs.getSelected().size(), 2);
552 assertTrue(cs.contains(4));
553 assertTrue(cs.contains(5));
554 assertEquals(sg.getStartRes(), 4);
555 assertEquals(sg.getEndRes(), 5);
558 * emulate drag right with columns 10-20 already selected
561 for (int i = 10; i <= 20; i++)
565 assertEquals(cs.getSelected().size(), 11);
566 sg = new SequenceGroup();
569 cs.stretchGroup(21, sg, 10, 20);
570 assertEquals(cs.getSelected().size(), 12);
571 assertTrue(cs.contains(10));
572 assertTrue(cs.contains(21));
573 assertEquals(sg.getStartRes(), 10);
574 assertEquals(sg.getEndRes(), 21);
577 @Test(groups = { "Functional" })
578 public void testStretchGroup_shrink()
581 * emulate drag left to 19 with columns 10-20 already selected
583 ColumnSelection cs = new ColumnSelection();
584 for (int i = 10; i <= 20; i++)
588 assertEquals(cs.getSelected().size(), 11);
589 SequenceGroup sg = new SequenceGroup();
592 cs.stretchGroup(19, sg, 10, 20);
593 assertEquals(cs.getSelected().size(), 10);
594 assertTrue(cs.contains(10));
595 assertTrue(cs.contains(19));
596 assertFalse(cs.contains(20));
597 assertEquals(sg.getStartRes(), 10);
598 assertEquals(sg.getEndRes(), 19);