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.Iterator;
36 import java.util.List;
38 import org.testng.annotations.BeforeClass;
39 import org.testng.annotations.Test;
41 public class ColumnSelectionTest
44 @BeforeClass(alwaysRun = true)
45 public void setUpJvOptionPane()
47 JvOptionPane.setInteractiveMode(false);
48 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
51 @Test(groups = { "Functional" })
52 public void testAddElement()
54 ColumnSelection cs = new ColumnSelection();
58 cs.addElement(5); // ignored
59 List<Integer> sel = cs.getSelected();
60 assertEquals("[2, 5, 3]", sel.toString());
63 @Test(groups = { "Functional" })
64 public void testSetElementsFrom()
66 ColumnSelection fromcs = new ColumnSelection();
67 ColumnSelection tocs = new ColumnSelection();
68 HiddenColumns hidden = new HiddenColumns();
74 tocs.setElementsFrom(fromcs, hidden);
75 assertTrue(tocs.equals(fromcs));
77 hidden.hideColumns(4, 6);
78 tocs.setElementsFrom(fromcs, hidden);
80 // expect cols 2 and 3 to be selected but not 5
81 ColumnSelection expectcs = new ColumnSelection();
82 expectcs.addElement(2);
83 expectcs.addElement(3);
84 assertTrue(tocs.equals(expectcs));
88 * Test the remove method - in particular to verify that remove(int i) removes
89 * the element whose value is i, _NOT_ the i'th element.
91 @Test(groups = { "Functional" })
92 public void testRemoveElement()
94 ColumnSelection cs = new ColumnSelection();
98 // removing elements not in the list has no effect
101 List<Integer> sel = cs.getSelected();
102 assertEquals(2, sel.size());
103 assertEquals(new Integer(2), sel.get(0));
104 assertEquals(new Integer(5), sel.get(1));
106 // removing an element in the list removes it
108 // ...and also from the read-only view
109 assertEquals(1, sel.size());
110 sel = cs.getSelected();
111 assertEquals(1, sel.size());
112 assertEquals(new Integer(5), sel.get(0));
116 * Test the method that hides a specified column including any adjacent
117 * selected columns. This is a convenience method for the case where multiple
118 * column regions are selected and then hidden using menu option View | Hide |
121 @Test(groups = { "Functional" })
122 public void testHideColumns_withSelection()
124 // create random alignment
125 AlignmentGenerator gen = new AlignmentGenerator(false);
126 AlignmentI al = gen.generate(50, 20, 123, 5, 5);
128 ColumnSelection cs = new ColumnSelection();
129 // select columns 4-6
133 // hide column 5 (and adjacent):
134 cs.hideSelectedColumns(5, al.getHiddenColumns());
136 Iterator<int[]> regions = al.getHiddenColumns().iterator();
137 assertEquals(1, al.getHiddenColumns().getNumberOfRegions());
138 assertEquals("[4, 6]", Arrays.toString(regions.next()));
139 // none now selected:
140 assertTrue(cs.getSelected().isEmpty());
142 // repeat, hiding column 4 (5 and 6)
143 al = gen.generate(50, 20, 123, 5, 5);
144 cs = new ColumnSelection();
148 cs.hideSelectedColumns(4, al.getHiddenColumns());
149 regions = al.getHiddenColumns().iterator();
150 assertEquals(1, al.getHiddenColumns().getNumberOfRegions());
151 assertEquals("[4, 6]", Arrays.toString(regions.next()));
152 assertTrue(cs.getSelected().isEmpty());
154 // repeat, hiding column (4, 5 and) 6
155 al = gen.generate(50, 20, 123, 5, 5);
156 cs = new ColumnSelection();
160 cs.hideSelectedColumns(6, al.getHiddenColumns());
161 regions = al.getHiddenColumns().iterator();
162 assertEquals(1, al.getHiddenColumns().getNumberOfRegions());
163 assertEquals("[4, 6]", Arrays.toString(regions.next()));
164 assertTrue(cs.getSelected().isEmpty());
166 // repeat, with _only_ adjacent columns selected
167 al = gen.generate(50, 20, 123, 5, 5);
168 cs = new ColumnSelection();
171 cs.hideSelectedColumns(5, al.getHiddenColumns());
172 regions = al.getHiddenColumns().iterator();
173 assertEquals(1, al.getHiddenColumns().getNumberOfRegions());
174 assertEquals("[4, 6]", Arrays.toString(regions.next()));
175 assertTrue(cs.getSelected().isEmpty());
179 * Test the method that hides all (possibly disjoint) selected column ranges
181 @Test(groups = { "Functional" })
182 public void testHideSelectedColumns()
184 // create random alignment
185 AlignmentGenerator gen = new AlignmentGenerator(false);
186 AlignmentI al = gen.generate(50, 20, 123, 5, 5);
188 ColumnSelection cs = new ColumnSelection();
189 int[] sel = { 2, 3, 4, 7, 8, 9, 20, 21, 22 };
195 HiddenColumns cols = al.getHiddenColumns();
196 cols.hideColumns(15, 18);
198 cs.hideSelectedColumns(al);
199 assertTrue(cs.getSelected().isEmpty());
200 Iterator<int[]> regions = cols.iterator();
201 assertEquals(4, cols.getNumberOfRegions());
202 assertEquals("[2, 4]", Arrays.toString(regions.next()));
203 assertEquals("[7, 9]", Arrays.toString(regions.next()));
204 assertEquals("[15, 18]", Arrays.toString(regions.next()));
205 assertEquals("[20, 22]", Arrays.toString(regions.next()));
209 * Test the method that gets runs of selected columns ordered by column. If
210 * this fails, HideSelectedColumns may also fail
212 @Test(groups = { "Functional" })
213 public void testGetSelectedRanges()
216 * getSelectedRanges returns ordered columns regardless
217 * of the order in which they are added
219 ColumnSelection cs = new ColumnSelection();
220 int[] sel = { 4, 3, 7, 21, 9, 20, 8, 22, 2 };
226 range = cs.getSelectedRanges();
227 assertEquals(3, range.size());
228 assertEquals("[2, 4]", Arrays.toString(range.get(0)));
229 assertEquals("[7, 9]", Arrays.toString(range.get(1)));
230 assertEquals("[20, 22]", Arrays.toString(range.get(2)));
233 range = cs.getSelectedRanges();
234 assertEquals(3, range.size());
235 assertEquals("[0, 4]", Arrays.toString(range.get(0)));
238 @Test(groups = { "Functional" })
239 public void testInvertColumnSelection()
241 // create random alignment
242 AlignmentGenerator gen = new AlignmentGenerator(false);
243 AlignmentI al = gen.generate(50, 20, 123, 5, 5);
245 ColumnSelection cs = new ColumnSelection();
250 HiddenColumns cols = al.getHiddenColumns();
251 cols.hideColumns(3, 3);
252 cols.hideColumns(6, 6);
254 // invert selection from start (inclusive) to end (exclusive)
255 cs.invertColumnSelection(2, 9, al);
256 assertEquals("[2, 5, 7]", cs.getSelected().toString());
258 cs.invertColumnSelection(1, 9, al);
259 assertEquals("[1, 4, 8]", cs.getSelected().toString());
262 @Test(groups = { "Functional" })
263 public void testMaxColumnSelection()
265 ColumnSelection cs = new ColumnSelection();
269 assertEquals(513, cs.getMax());
270 cs.removeElement(513);
271 assertEquals(1, cs.getMax());
273 assertEquals(0, cs.getMax());
276 assertEquals(513, cs.getMax());
280 @Test(groups = { "Functional" })
281 public void testMinColumnSelection()
283 ColumnSelection cs = new ColumnSelection();
287 assertEquals(0, cs.getMin());
289 assertEquals(1, cs.getMin());
291 assertEquals(0, cs.getMin());
294 @Test(groups = { "Functional" })
295 public void testEquals()
297 ColumnSelection cs = new ColumnSelection();
302 // same selections added in a different order
303 ColumnSelection cs2 = new ColumnSelection();
308 assertTrue(cs.equals(cs2));
309 assertTrue(cs.equals(cs));
310 assertTrue(cs2.equals(cs));
311 assertTrue(cs2.equals(cs2));
314 assertFalse(cs.equals(cs2));
315 assertFalse(cs2.equals(cs));
317 cs2.removeElement(12);
318 assertTrue(cs.equals(cs2));
322 cs2.hideSelectedColumns(88);
323 assertFalse(cs.equals(cs2));
325 * unhiding a column adds it to selection!
327 /* cs2.revealHiddenColumns(88);
328 assertFalse(cs.equals(cs2));
330 assertTrue(cs.equals(cs2));
334 * Test the method that returns selected columns, in the order in which they
337 @Test(groups = { "Functional" })
338 public void testGetSelected()
340 ColumnSelection cs = new ColumnSelection();
341 int[] sel = { 4, 3, 7, 21 };
347 List<Integer> selected = cs.getSelected();
348 assertEquals(4, selected.size());
349 assertEquals("[4, 3, 7, 21]", selected.toString());
352 * getSelected returns a read-only view of the list
353 * verify the view follows any changes in it
358 assertEquals("[3, 21, 1]", selected.toString());
362 * Test to verify that the list returned by getSelection cannot be modified
364 @Test(groups = { "Functional" })
365 public void testGetSelected_isReadOnly()
367 ColumnSelection cs = new ColumnSelection();
370 List<Integer> selected = cs.getSelected();
374 fail("expected exception");
375 } catch (UnsupportedOperationException e)
382 fail("expected exception");
383 } catch (UnsupportedOperationException e)
390 fail("expected exception");
391 } catch (UnsupportedOperationException e)
397 Collections.sort(selected);
398 fail("expected exception");
399 } catch (UnsupportedOperationException e)
406 * Test that demonstrates a ConcurrentModificationException is thrown if you
407 * change the selection while iterating over it
410 groups = "Functional",
411 expectedExceptions = { ConcurrentModificationException.class })
412 public void testGetSelected_concurrentModification()
414 ColumnSelection cs = new ColumnSelection();
420 * simulate changing the list under us (e.g. in a separate
421 * thread) while iterating over it -> ConcurrentModificationException
423 List<Integer> selected = cs.getSelected();
424 for (Integer col : selected)
426 if (col.intValue() == 0)
433 @Test(groups = "Functional")
434 public void testMarkColumns()
436 ColumnSelection cs = new ColumnSelection();
437 cs.addElement(5); // this will be cleared
438 BitSet toMark = new BitSet();
444 assertTrue(cs.markColumns(toMark, 3, 8, false, false, false));
445 List<Integer> selected = cs.getSelected();
446 assertEquals(2, selected.size());
447 assertTrue(selected.contains(3));
448 assertTrue(selected.contains(6));
451 @Test(groups = "Functional")
452 public void testMarkColumns_extend()
454 ColumnSelection cs = new ColumnSelection();
457 BitSet toMark = new BitSet();
464 * extending selection of {3, 6} should leave {1, 3, 5, 6} selected
466 assertTrue(cs.markColumns(toMark, 3, 8, false, true, false));
467 List<Integer> selected = cs.getSelected();
468 assertEquals(4, selected.size());
469 assertTrue(selected.contains(1));
470 assertTrue(selected.contains(3));
471 assertTrue(selected.contains(5));
472 assertTrue(selected.contains(6));
475 @Test(groups = "Functional")
476 public void testMarkColumns_invert()
478 ColumnSelection cs = new ColumnSelection();
479 cs.addElement(5); // this will be cleared
480 BitSet toMark = new BitSet();
487 * inverted selection of {3, 6} should select {4, 5, 7, 8}
489 assertTrue(cs.markColumns(toMark, 3, 8, true, false, false));
490 List<Integer> selected = cs.getSelected();
491 assertEquals(4, selected.size());
492 assertTrue(selected.contains(4));
493 assertTrue(selected.contains(5));
494 assertTrue(selected.contains(7));
495 assertTrue(selected.contains(8));
498 @Test(groups = "Functional")
499 public void testMarkColumns_toggle()
501 ColumnSelection cs = new ColumnSelection();
502 cs.addElement(1); // outside change range
505 cs.addElement(10); // outside change range
506 BitSet toMark = new BitSet();
513 * toggling state of {3, 6} should leave {1, 4, 6, 10} selected
515 assertTrue(cs.markColumns(toMark, 3, 8, false, false, true));
516 List<Integer> selected = cs.getSelected();
517 assertEquals(4, selected.size());
518 assertTrue(selected.contains(1));
519 assertTrue(selected.contains(4));
520 assertTrue(selected.contains(6));
521 assertTrue(selected.contains(10));
524 @Test(groups = "Functional")
525 public void testCopyConstructor()
527 ColumnSelection cs = new ColumnSelection();
531 ColumnSelection cs2 = new ColumnSelection(cs);
532 assertTrue(cs2.hasSelectedColumns());
534 // order of column selection is preserved
535 assertEquals("[3, 1]", cs2.getSelected().toString());
539 @Test(groups = { "Functional" })
540 public void testStretchGroup_expand()
543 * test that emulates clicking column 4 (selected)
544 * and dragging right to column 5 (all base 0)
546 ColumnSelection cs = new ColumnSelection();
548 SequenceGroup sg = new SequenceGroup();
551 cs.stretchGroup(5, sg, 4, 4);
552 assertEquals(cs.getSelected().size(), 2);
553 assertTrue(cs.contains(4));
554 assertTrue(cs.contains(5));
555 assertEquals(sg.getStartRes(), 4);
556 assertEquals(sg.getEndRes(), 5);
559 * emulate drag right with columns 10-20 already selected
562 for (int i = 10; i <= 20; i++)
566 assertEquals(cs.getSelected().size(), 11);
567 sg = new SequenceGroup();
570 cs.stretchGroup(21, sg, 10, 20);
571 assertEquals(cs.getSelected().size(), 12);
572 assertTrue(cs.contains(10));
573 assertTrue(cs.contains(21));
574 assertEquals(sg.getStartRes(), 10);
575 assertEquals(sg.getEndRes(), 21);
578 @Test(groups = { "Functional" })
579 public void testStretchGroup_shrink()
582 * emulate drag left to 19 with columns 10-20 already selected
584 ColumnSelection cs = new ColumnSelection();
585 for (int i = 10; i <= 20; i++)
589 assertEquals(cs.getSelected().size(), 11);
590 SequenceGroup sg = new SequenceGroup();
593 cs.stretchGroup(19, sg, 10, 20);
594 assertEquals(cs.getSelected().size(), 10);
595 assertTrue(cs.contains(10));
596 assertTrue(cs.contains(19));
597 assertFalse(cs.contains(20));
598 assertEquals(sg.getStartRes(), 10);
599 assertEquals(sg.getEndRes(), 19);