Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
SearchResultsTest | 37 | 228 | 14 |
1 | /* | |
2 | * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) | |
3 | * Copyright (C) $$Year-Rel$$ The Jalview Authors | |
4 | * | |
5 | * This file is part of Jalview. | |
6 | * | |
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. | |
11 | * | |
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. | |
16 | * | |
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. | |
20 | */ | |
21 | package jalview.datamodel; | |
22 | ||
23 | import static org.testng.AssertJUnit.assertEquals; | |
24 | import static org.testng.AssertJUnit.assertFalse; | |
25 | import static org.testng.AssertJUnit.assertSame; | |
26 | import static org.testng.AssertJUnit.assertTrue; | |
27 | ||
28 | import java.util.BitSet; | |
29 | import java.util.List; | |
30 | ||
31 | import org.junit.Assert; | |
32 | import org.testng.annotations.BeforeClass; | |
33 | import org.testng.annotations.Test; | |
34 | ||
35 | import jalview.gui.JvOptionPane; | |
36 | ||
37 | public class SearchResultsTest | |
38 | { | |
39 | ||
40 | 1 | @BeforeClass(alwaysRun = true) |
41 | public void setUpJvOptionPane() | |
42 | { | |
43 | 1 | JvOptionPane.setInteractiveMode(false); |
44 | 1 | JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION); |
45 | } | |
46 | ||
47 | 1 | @Test(groups = { "Functional" }) |
48 | public void testToString() | |
49 | { | |
50 | 1 | SequenceI seq = new Sequence("Seq1", "abcdefghijklm"); |
51 | 1 | SearchResultsI sr = new SearchResults(); |
52 | 1 | sr.addResult(seq, 1, 1); |
53 | 1 | assertEquals("[Seq1/1-1]", sr.toString()); |
54 | 1 | sr.addResult(seq, 3, 5); |
55 | 1 | assertEquals("[Seq1/1-1, Seq1/3-5]", sr.toString()); |
56 | ||
57 | 1 | seq = new Sequence("Seq2", "pqrstuvwxy"); |
58 | 1 | sr.addResult(seq, 6, 7); |
59 | 1 | assertEquals("[Seq1/1-1, Seq1/3-5, Seq2/6-7]", sr.toString()); |
60 | } | |
61 | ||
62 | 1 | @Test(groups = { "Functional" }) |
63 | public void testEquals() | |
64 | { | |
65 | 1 | SequenceI seq1 = new Sequence("", "abcdefghijklm"); |
66 | 1 | SearchResultsI sr1 = new SearchResults(); |
67 | 1 | SearchResultsI sr2 = new SearchResults(); |
68 | ||
69 | 1 | assertFalse(sr1.equals(null)); // null object |
70 | 1 | assertFalse(sr1.equals(seq1)); // wrong type |
71 | 1 | assertTrue(sr1.equals(sr1)); // self |
72 | 1 | assertTrue(sr1.equals(sr2)); // empty |
73 | 1 | assertTrue(sr2.equals(sr1)); // reflexive |
74 | ||
75 | /* | |
76 | * if only one result is not empty | |
77 | */ | |
78 | 1 | sr1.addResult(seq1, 1, 1); |
79 | 1 | assertTrue(sr1.equals(sr1)); |
80 | 1 | assertFalse(sr1.equals(sr2)); |
81 | 1 | assertFalse(sr2.equals(sr1)); |
82 | ||
83 | /* | |
84 | * both the same | |
85 | */ | |
86 | 1 | sr2.addResult(seq1, 1, 1); |
87 | 1 | assertTrue(sr1.equals(sr2)); |
88 | 1 | assertTrue(sr2.equals(sr1)); |
89 | ||
90 | /* | |
91 | * both have three matches | |
92 | */ | |
93 | 1 | sr1.addResult(seq1, 3, 4); |
94 | 1 | sr1.addResult(seq1, 6, 8); |
95 | 1 | sr2.addResult(seq1, 3, 4); |
96 | 1 | sr2.addResult(seq1, 6, 8); |
97 | 1 | assertTrue(sr1.equals(sr1)); |
98 | 1 | assertTrue(sr2.equals(sr2)); |
99 | 1 | assertTrue(sr1.equals(sr2)); |
100 | 1 | assertTrue(sr2.equals(sr1)); |
101 | } | |
102 | ||
103 | /** | |
104 | * Matches that are similar but for distinct sequences are not equal | |
105 | */ | |
106 | 1 | @Test(groups = { "Functional" }) |
107 | public void testEquals_distinctSequences() | |
108 | { | |
109 | 1 | SequenceI seq1 = new Sequence("", "abcdefghijklm"); |
110 | 1 | SequenceI seq2 = new Sequence("", "abcdefghijklm"); |
111 | 1 | SearchResultsI sr1 = new SearchResults(); |
112 | 1 | SearchResultsI sr2 = new SearchResults(); |
113 | ||
114 | 1 | sr1.addResult(seq1, 1, 1); |
115 | 1 | sr2.addResult(seq2, 1, 1); |
116 | 1 | assertFalse(sr1.equals(sr2)); |
117 | 1 | assertFalse(sr2.equals(sr1)); |
118 | } | |
119 | ||
120 | /** | |
121 | * Matches that are the same except for ordering are not equal | |
122 | */ | |
123 | 1 | @Test(groups = { "Functional" }) |
124 | public void testEquals_orderDiffers() | |
125 | { | |
126 | 1 | SequenceI seq1 = new Sequence("", "abcdefghijklm"); |
127 | 1 | SearchResultsI sr1 = new SearchResults(); |
128 | 1 | SearchResultsI sr2 = new SearchResults(); |
129 | ||
130 | 1 | sr1.addResult(seq1, 1, 1); |
131 | 1 | sr1.addResult(seq1, 2, 2); |
132 | 1 | sr2.addResult(seq1, 2, 2); |
133 | 1 | sr2.addResult(seq1, 1, 1); |
134 | 1 | assertFalse(sr1.equals(sr2)); |
135 | 1 | assertFalse(sr2.equals(sr1)); |
136 | } | |
137 | ||
138 | /** | |
139 | * Verify that hashCode matches for equal objects | |
140 | */ | |
141 | 1 | @Test(groups = { "Functional" }) |
142 | public void testHashcode() | |
143 | { | |
144 | 1 | SequenceI seq1 = new Sequence("", "abcdefghijklm"); |
145 | 1 | SearchResultsI sr1 = new SearchResults(); |
146 | 1 | SearchResultsI sr2 = new SearchResults(); |
147 | ||
148 | /* | |
149 | * both empty | |
150 | */ | |
151 | 1 | assertEquals(sr1.hashCode(), sr2.hashCode()); |
152 | ||
153 | /* | |
154 | * both one match | |
155 | */ | |
156 | 1 | sr1.addResult(seq1, 1, 1); |
157 | 1 | sr2.addResult(seq1, 1, 1); |
158 | 1 | assertEquals(sr1.hashCode(), sr2.hashCode()); |
159 | ||
160 | /* | |
161 | * both three matches | |
162 | */ | |
163 | 1 | sr1.addResult(seq1, 3, 4); |
164 | 1 | sr1.addResult(seq1, 6, 8); |
165 | 1 | sr2.addResult(seq1, 3, 4); |
166 | 1 | sr2.addResult(seq1, 6, 8); |
167 | 1 | assertEquals(sr1.hashCode(), sr2.hashCode()); |
168 | } | |
169 | ||
170 | /** | |
171 | * Verify that SearchResults$Match constructor normalises start/end to the | |
172 | * 'forwards' direction | |
173 | */ | |
174 | 1 | @Test(groups = { "Functional" }) |
175 | public void testMatchConstructor() | |
176 | { | |
177 | 1 | SequenceI seq1 = new Sequence("", "abcdefghijklm"); |
178 | 1 | SearchResultMatchI m = new SearchResults().new Match(seq1, 2, 5); |
179 | 1 | assertSame(seq1, m.getSequence()); |
180 | 1 | assertEquals(2, m.getStart()); |
181 | 1 | assertEquals(5, m.getEnd()); |
182 | ||
183 | // now a reverse mapping: | |
184 | 1 | m = new SearchResults().new Match(seq1, 5, 2); |
185 | 1 | assertSame(seq1, m.getSequence()); |
186 | 1 | assertEquals(2, m.getStart()); |
187 | 1 | assertEquals(5, m.getEnd()); |
188 | } | |
189 | ||
190 | 1 | @Test(groups = { "Functional" }) |
191 | public void testMatchContains() | |
192 | { | |
193 | 1 | SequenceI seq1 = new Sequence("", "abcdefghijklm"); |
194 | 1 | SequenceI seq2 = new Sequence("", "abcdefghijklm"); |
195 | 1 | SearchResultMatchI m = new SearchResults().new Match(seq1, 2, 5); |
196 | ||
197 | 1 | assertTrue(m.contains(seq1, 2, 5)); |
198 | 1 | assertTrue(m.contains(seq1, 3, 5)); |
199 | 1 | assertTrue(m.contains(seq1, 2, 4)); |
200 | 1 | assertTrue(m.contains(seq1, 3, 3)); |
201 | ||
202 | 1 | assertFalse(m.contains(seq1, 2, 6)); |
203 | 1 | assertFalse(m.contains(seq1, 1, 5)); |
204 | 1 | assertFalse(m.contains(seq1, 1, 8)); |
205 | 1 | assertFalse(m.contains(seq2, 3, 3)); |
206 | 1 | assertFalse(m.contains(null, 3, 3)); |
207 | } | |
208 | ||
209 | 1 | @Test(groups = { "Functional" }) |
210 | public void testMatchAdjacent() | |
211 | { | |
212 | 1 | SequenceI seq1 = new Sequence("", "abcdefghijklm"); |
213 | 1 | SequenceI seq2 = new Sequence("", "abcdefghijklm"); |
214 | 1 | SearchResultMatchI m = new SearchResults().new Match(seq1, 2, 5); |
215 | ||
216 | 1 | assertTrue(m.adjacent(seq1, 2, 5)); |
217 | 1 | assertTrue(m.adjacent(seq1, 3, 5)); |
218 | 1 | assertTrue(m.adjacent(seq1, 2, 4)); |
219 | 1 | assertTrue(m.adjacent(seq1, 3, 3)); |
220 | ||
221 | 1 | assertTrue(m.adjacent(seq1, 2, 6)); |
222 | 1 | assertTrue(m.adjacent(seq1, 1, 5)); |
223 | 1 | assertTrue(m.adjacent(seq1, 1, 8)); |
224 | 1 | assertFalse(m.adjacent(seq1, 0, 0)); |
225 | 1 | assertFalse(m.adjacent(seq1, 7, 8)); |
226 | 1 | assertTrue(m.adjacent(seq1, 6, 8)); |
227 | 1 | assertTrue(m.adjacent(seq1, 5, 8)); |
228 | 1 | assertTrue(m.adjacent(seq1, 0, 1)); |
229 | ||
230 | 1 | assertFalse(m.adjacent(seq2, 3, 3)); |
231 | 1 | assertFalse(m.adjacent(null, 3, 3)); |
232 | } | |
233 | ||
234 | /** | |
235 | * test markColumns for creating column selections | |
236 | */ | |
237 | 1 | @Test(groups = { "Functional" }) |
238 | public void testMarkColumns() | |
239 | { | |
240 | 1 | int marked = 0; |
241 | 1 | SequenceI seq1 = new Sequence("", "abcdefghijklm"); |
242 | 1 | SequenceI seq2 = new Sequence("", "abcdefghijklm"); |
243 | 1 | SequenceGroup s1g = new SequenceGroup(), s2g = new SequenceGroup(), |
244 | sallg = new SequenceGroup(); | |
245 | 1 | s1g.addSequence(seq1, false); |
246 | 1 | s2g.addSequence(seq2, false); |
247 | 1 | sallg.addSequence(seq1, false); |
248 | 1 | sallg.addSequence(seq2, false); |
249 | ||
250 | 1 | SearchResultsI sr = new SearchResults(); |
251 | 1 | BitSet bs = new BitSet(); |
252 | ||
253 | 1 | SearchResultMatchI srm = null; |
254 | 1 | srm = sr.addResult(seq1, 1, 1); |
255 | 1 | Assert.assertNotNull("addResult didn't return Match", srm); |
256 | 1 | srm = sr.addResult(seq2, 1, 2); |
257 | 1 | assertEquals("Sequence reference not set", seq2, srm.getSequence()); |
258 | 1 | assertEquals("match start incorrect", 1, srm.getStart()); |
259 | 1 | assertEquals("match end incorrect", 2, srm.getEnd()); |
260 | ||
261 | // set start/end range for groups to cover matches | |
262 | ||
263 | 1 | s1g.setStartRes(0); |
264 | 1 | s1g.setEndRes(5); |
265 | 1 | s2g.setStartRes(0); |
266 | 1 | s2g.setEndRes(5); |
267 | 1 | sallg.setStartRes(0); |
268 | 1 | sallg.setEndRes(5); |
269 | ||
270 | /* | |
271 | * just seq1 | |
272 | */ | |
273 | 1 | marked = sr.markColumns(s1g, bs); |
274 | // check the bitset cardinality before checking the return value | |
275 | 1 | assertEquals("Didn't mark expected number", 1, bs.cardinality()); |
276 | 1 | assertEquals("Didn't return count of number of bits marked", 1, marked); |
277 | 1 | assertTrue("Didn't mark expected position", bs.get(0)); |
278 | // now check return value for marking the same again | |
279 | 1 | assertEquals( |
280 | "Didn't count number of bits marked for existing marked set", 0, | |
281 | sr.markColumns(s1g, bs)); | |
282 | 1 | bs.clear(); |
283 | ||
284 | /* | |
285 | * just seq2 | |
286 | */ | |
287 | 1 | marked = sr.markColumns(s2g, bs); |
288 | 1 | assertEquals("Didn't mark expected number", 2, bs.cardinality()); |
289 | 1 | assertEquals("Didn't return count of number of bits marked", 2, marked); |
290 | 1 | assertTrue("Didn't mark expected position (1)", bs.get(0)); |
291 | 1 | assertTrue("Didn't mark expected position (2)", bs.get(1)); |
292 | ||
293 | /* | |
294 | * both seq1 and seq2 | |
295 | * should be same as seq2 | |
296 | */ | |
297 | 1 | BitSet allbs = new BitSet(); |
298 | 1 | assertEquals(2, sr.markColumns(sallg, allbs)); |
299 | 1 | assertEquals(bs, allbs); |
300 | ||
301 | // now check range selection | |
302 | ||
303 | /* | |
304 | * limit s2g to just the second column, sallg to the first column | |
305 | */ | |
306 | 1 | s2g.setStartRes(1); |
307 | 1 | s2g.setEndRes(1); |
308 | 1 | sallg.setEndRes(0); |
309 | 1 | BitSet tbs = new BitSet(); |
310 | 1 | assertEquals("Group start/end didn't select columns to mark", 1, |
311 | sr.markColumns(s2g, tbs)); | |
312 | 1 | assertEquals("Group start/end didn't select columns to mark", 1, |
313 | sr.markColumns(sallg, tbs)); | |
314 | 1 | assertEquals( |
315 | "Didn't set expected number of columns in total for two successive marks", | |
316 | 2, tbs.cardinality()); | |
317 | } | |
318 | ||
319 | /** | |
320 | * Test to verify adding doesn't create duplicate results | |
321 | */ | |
322 | 1 | @Test(groups = { "Functional" }) |
323 | public void testAddResult() | |
324 | { | |
325 | 1 | SequenceI seq1 = new Sequence("", "abcdefghijklm"); |
326 | 1 | SearchResultsI sr = new SearchResults(); |
327 | 1 | sr.addResult(seq1, 3, 5); |
328 | 1 | assertEquals(1, sr.getCount()); |
329 | 1 | sr.addResult(seq1, 3, 5); |
330 | 1 | assertEquals(1, sr.getCount()); |
331 | 1 | sr.addResult(seq1, 3, 6); |
332 | 1 | assertEquals(2, sr.getCount()); |
333 | } | |
334 | ||
335 | /** | |
336 | * Test to verify appending creates a minimal set of results | |
337 | */ | |
338 | 1 | @Test(groups = { "Functional" }) |
339 | public void testAppendResult() | |
340 | { | |
341 | 1 | SequenceI seq1 = new Sequence("", "abcdefghijklm"), |
342 | seq2 = new Sequence("", "defdefdefdef"); | |
343 | 1 | SearchResultsI sr = new SearchResults(); |
344 | 1 | sr.appendResult(seq1, 3, 5); |
345 | 1 | assertEquals(1, sr.getCount()); |
346 | 1 | sr.appendResult(seq1, 3, 6); |
347 | 1 | assertEquals(1, sr.getCount()); |
348 | 1 | sr.appendResult(seq1, 8, 8); |
349 | 1 | assertEquals(2, sr.getCount()); |
350 | 1 | sr.appendResult(seq1, 7, 7); |
351 | 1 | assertEquals(1, sr.getCount()); |
352 | 1 | sr.appendResult(seq2, 7, 7); |
353 | 1 | assertEquals(2, sr.getCount()); |
354 | 1 | sr.appendResult(seq2, 2, 7); |
355 | 1 | assertTrue(sr.appendResult(seq2, 7, 49)); |
356 | 1 | assertTrue(sr.appendResult(seq2, 0, 30)); |
357 | 1 | assertEquals(2, sr.getCount()); |
358 | 1 | int c = 0; |
359 | 1 | for (SearchResultMatchI sre : sr.getResults()) |
360 | { | |
361 | 2 | c++; |
362 | } | |
363 | 1 | assertEquals(c, 2); |
364 | ||
365 | } | |
366 | ||
367 | /** | |
368 | * Test for method that checks if search results matches a sequence region | |
369 | */ | |
370 | 1 | @Test(groups = { "Functional" }) |
371 | public void testInvolvesSequence() | |
372 | { | |
373 | 1 | SequenceI dataset = new Sequence("genome", "ATGGCCCTTTAAGCAACATTT"); |
374 | // first 'exon': | |
375 | 1 | SequenceI cds1 = new Sequence("cds1/1-12", "ATGGCCCTTTAA"); |
376 | 1 | cds1.setDatasetSequence(dataset); |
377 | // overlapping second 'exon': | |
378 | 1 | SequenceI cds2 = new Sequence("cds2/7-18", "CTTTAAGCAACA"); |
379 | 1 | cds2.setDatasetSequence(dataset); |
380 | // unrelated sequence | |
381 | 1 | SequenceI cds3 = new Sequence("cds3", "ATGGCCCTTTAAGCAACA"); |
382 | ||
383 | 1 | SearchResults sr = new SearchResults(); |
384 | 1 | assertFalse(sr.involvesSequence(cds1)); |
385 | ||
386 | /* | |
387 | * cds1 and cds2 share the same dataset sequence, but | |
388 | * only cds1 overlaps match 4:6 (fixes bug JAL-3613) | |
389 | */ | |
390 | 1 | sr.addResult(dataset, 4, 6); |
391 | 1 | assertTrue(sr.involvesSequence(cds1)); |
392 | 1 | assertFalse(sr.involvesSequence(cds2)); |
393 | 1 | assertFalse(sr.involvesSequence(cds3)); |
394 | ||
395 | /* | |
396 | * search results overlap cds2 only | |
397 | */ | |
398 | 1 | sr = new SearchResults(); |
399 | 1 | sr.addResult(dataset, 18, 18); |
400 | 1 | assertFalse(sr.involvesSequence(cds1)); |
401 | 1 | assertTrue(sr.involvesSequence(cds2)); |
402 | ||
403 | /* | |
404 | * add a search result overlapping cds1 | |
405 | */ | |
406 | 1 | sr.addResult(dataset, 1, 1); |
407 | 1 | assertTrue(sr.involvesSequence(cds1)); |
408 | 1 | assertTrue(sr.involvesSequence(cds2)); |
409 | ||
410 | /* | |
411 | * single search result overlapping both | |
412 | */ | |
413 | 1 | sr = new SearchResults(); |
414 | 1 | sr.addResult(dataset, 10, 12); |
415 | 1 | assertTrue(sr.involvesSequence(cds1)); |
416 | 1 | assertTrue(sr.involvesSequence(cds2)); |
417 | ||
418 | /* | |
419 | * search results matching aligned sequence | |
420 | */ | |
421 | 1 | sr = new SearchResults(); |
422 | 1 | sr.addResult(cds1, 10, 12); |
423 | 1 | assertTrue(sr.involvesSequence(cds1)); |
424 | 1 | assertFalse(sr.involvesSequence(cds2)); |
425 | 1 | sr.addResult(cds2, 1, 3); // no start-end overlap |
426 | 1 | assertFalse(sr.involvesSequence(cds2)); |
427 | 1 | sr.addResult(cds2, 7, 9); // start-end overlap |
428 | 1 | assertTrue(sr.involvesSequence(cds2)); |
429 | } | |
430 | ||
431 | /** | |
432 | * Test extraction of Sequence objects for matched ranges on a sequence | |
433 | */ | |
434 | 1 | @Test(groups = { "Functional" }) |
435 | public void testGetSequences() | |
436 | { | |
437 | 1 | SequenceI seq1 = new Sequence("", "abcdefghijklm"); |
438 | 1 | SequenceI seq2 = new Sequence("", "nopqrstuvwxyz"); |
439 | 1 | seq2.setStart(23); |
440 | 1 | seq2.setEnd(35); |
441 | 1 | List<SequenceI> seqres = null; |
442 | ||
443 | 1 | SearchResultsI sr = new SearchResults(); |
444 | 1 | seqres = sr.getMatchingSubSequences(); |
445 | 1 | assertEquals(0, seqres.size()); |
446 | ||
447 | 1 | sr.addResult(seq1, 3, 5); |
448 | 1 | seqres = sr.getMatchingSubSequences(); |
449 | ||
450 | 1 | assertEquals(1, seqres.size()); |
451 | 1 | assertEquals("cde", seqres.get(0).getSequenceAsString()); |
452 | 1 | assertEquals(3, seqres.get(0).getStart()); |
453 | 1 | assertEquals(seq1, seqres.get(0).getDatasetSequence()); |
454 | ||
455 | 1 | sr.addResult(seq1, 3, 6); |
456 | 1 | seqres = sr.getMatchingSubSequences(); |
457 | ||
458 | 1 | assertEquals(2, seqres.size()); |
459 | 1 | assertEquals("cdef", seqres.get(1).getSequenceAsString()); |
460 | 1 | assertEquals(3, seqres.get(1).getStart()); |
461 | ||
462 | // this is a quirk - match on 26-29 yields subsequence 27-30 | |
463 | 1 | sr.addResult(seq2, 26, 29); |
464 | 1 | seqres = sr.getMatchingSubSequences(); |
465 | 1 | assertEquals(3, seqres.size()); |
466 | 1 | assertEquals("qrst", seqres.get(2).getSequenceAsString()); |
467 | 1 | assertEquals(26, seqres.get(2).getStart()); |
468 | } | |
469 | ||
470 | } |