Clover icon

Coverage Report

  1. Project Clover database Mon Sep 2 2024 17:57:51 BST
  2. Package jalview.datamodel.features

File FeatureMatcherSetTest.java

 

Code metrics

0
191
9
1
439
284
12
0.06
21.22
9
1.33

Classes

Class Line # Actions
FeatureMatcherSetTest 40 191 12
0.98598.5%
 

Contributing tests

This file is covered by 9 tests. .

Source view

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.features;
22   
23    import static org.testng.Assert.assertEquals;
24    import static org.testng.Assert.assertFalse;
25    import static org.testng.Assert.assertNull;
26    import static org.testng.Assert.assertSame;
27    import static org.testng.Assert.assertTrue;
28    import static org.testng.Assert.fail;
29   
30    import jalview.datamodel.SequenceFeature;
31    import jalview.util.matcher.Condition;
32   
33    import java.util.HashMap;
34    import java.util.Iterator;
35    import java.util.Locale;
36    import java.util.Map;
37   
38    import org.testng.annotations.Test;
39   
 
40    public class FeatureMatcherSetTest
41    {
 
42  1 toggle @Test(groups = "Functional")
43    public void testMatches_byAttribute()
44    {
45    /*
46    * a numeric matcher - MatcherTest covers more conditions
47    */
48  1 FeatureMatcherI fm = FeatureMatcher.byAttribute(Condition.GE, "-2",
49    "AF");
50  1 FeatureMatcherSetI fms = new FeatureMatcherSet();
51  1 fms.and(fm);
52  1 SequenceFeature sf = new SequenceFeature("Cath", "desc", 11, 12, "grp");
53  1 assertFalse(fms.matches(sf));
54  1 sf.setValue("AF", "foobar");
55  1 assertFalse(fms.matches(sf));
56  1 sf.setValue("AF", "-2");
57  1 assertTrue(fms.matches(sf));
58  1 sf.setValue("AF", "-1");
59  1 assertTrue(fms.matches(sf));
60  1 sf.setValue("AF", "-3");
61  1 assertFalse(fms.matches(sf));
62  1 sf.setValue("AF", "");
63  1 assertFalse(fms.matches(sf));
64   
65    /*
66    * a string pattern matcher
67    */
68  1 fm = FeatureMatcher.byAttribute(Condition.Contains, "Cat", "AF");
69  1 fms = new FeatureMatcherSet();
70  1 fms.and(fm);
71  1 assertFalse(fms.matches(sf));
72  1 sf.setValue("AF", "raining cats and dogs");
73  1 assertTrue(fms.matches(sf));
74    }
75   
 
76  1 toggle @Test(groups = "Functional")
77    public void testAnd()
78    {
79    // condition1: AF value contains "dog" (matches)
80  1 FeatureMatcherI fm1 = FeatureMatcher.byAttribute(Condition.Contains,
81    "dog", "AF");
82    // condition 2: CSQ value does not contain "how" (does not match)
83  1 FeatureMatcherI fm2 = FeatureMatcher.byAttribute(Condition.NotContains,
84    "how", "CSQ");
85   
86  1 SequenceFeature sf = new SequenceFeature("Cath", "helix domain", 11, 12,
87    6.2f, "grp");
88  1 sf.setValue("AF", "raining cats and dogs");
89  1 sf.setValue("CSQ", "showers");
90   
91  1 assertTrue(fm1.matches(sf));
92  1 assertFalse(fm2.matches(sf));
93   
94  1 FeatureMatcherSetI fms = new FeatureMatcherSet();
95  1 assertTrue(fms.matches(sf)); // if no conditions, then 'all' pass
96  1 fms.and(fm1);
97  1 assertTrue(fms.matches(sf));
98  1 fms.and(fm2);
99  1 assertFalse(fms.matches(sf));
100   
101    /*
102    * OR a failed attribute condition with a matched label condition
103    */
104  1 fms = new FeatureMatcherSet();
105  1 fms.and(fm2);
106  1 assertFalse(fms.matches(sf));
107  1 FeatureMatcher byLabelPass = FeatureMatcher.byLabel(Condition.Contains,
108    "Helix");
109  1 fms.or(byLabelPass);
110  1 assertTrue(fms.matches(sf));
111   
112    /*
113    * OR a failed attribute condition with a failed score condition
114    */
115  1 fms = new FeatureMatcherSet();
116  1 fms.and(fm2);
117  1 assertFalse(fms.matches(sf));
118  1 FeatureMatcher byScoreFail = FeatureMatcher.byScore(Condition.LT,
119    "5.9");
120  1 fms.or(byScoreFail);
121  1 assertFalse(fms.matches(sf));
122   
123    /*
124    * OR failed attribute and score conditions with matched label condition
125    */
126  1 fms = new FeatureMatcherSet();
127  1 fms.or(fm2);
128  1 fms.or(byScoreFail);
129  1 assertFalse(fms.matches(sf));
130  1 fms.or(byLabelPass);
131  1 assertTrue(fms.matches(sf));
132    }
133   
 
134  1 toggle @Test(groups = "Functional")
135    public void testToString()
136    {
137  1 Locale.setDefault(Locale.ENGLISH);
138  1 FeatureMatcherI fm1 = FeatureMatcher.byAttribute(Condition.LT, "1.2",
139    "AF");
140  1 assertEquals(fm1.toString(), "AF < 1.2");
141   
142  1 FeatureMatcher fm2 = FeatureMatcher.byAttribute(Condition.NotContains,
143    "path", "CLIN_SIG");
144  1 assertEquals(fm2.toString(), "CLIN_SIG does not contain 'path'");
145   
146    /*
147    * AND them
148    */
149  1 FeatureMatcherSetI fms = new FeatureMatcherSet();
150  1 assertEquals(fms.toString(), "");
151  1 fms.and(fm1);
152  1 assertEquals(fms.toString(), "AF < 1.2");
153  1 fms.and(fm2);
154  1 assertEquals(fms.toString(),
155    "(AF < 1.2) and (CLIN_SIG does not contain 'path')");
156   
157    /*
158    * OR them
159    */
160  1 fms = new FeatureMatcherSet();
161  1 assertEquals(fms.toString(), "");
162  1 fms.or(fm1);
163  1 assertEquals(fms.toString(), "AF < 1.2");
164  1 fms.or(fm2);
165  1 assertEquals(fms.toString(),
166    "(AF < 1.2) or (CLIN_SIG does not contain 'path')");
167   
168  1 try
169    {
170  1 fms.and(fm1);
171  0 fail("Expected exception");
172    } catch (IllegalStateException e)
173    {
174    // expected
175    }
176    }
177   
 
178  1 toggle @Test(groups = "Functional")
179    public void testOr()
180    {
181    // condition1: AF value contains "dog" (matches)
182  1 FeatureMatcherI fm1 = FeatureMatcher.byAttribute(Condition.Contains,
183    "dog", "AF");
184    // condition 2: CSQ value does not contain "how" (does not match)
185  1 FeatureMatcherI fm2 = FeatureMatcher.byAttribute(Condition.NotContains,
186    "how", "CSQ");
187   
188  1 SequenceFeature sf = new SequenceFeature("Cath", "desc", 11, 12, "grp");
189  1 sf.setValue("AF", "raining cats and dogs");
190  1 sf.setValue("CSQ", "showers");
191   
192  1 assertTrue(fm1.matches(sf));
193  1 assertFalse(fm2.matches(sf));
194   
195  1 FeatureMatcherSetI fms = new FeatureMatcherSet();
196  1 assertTrue(fms.matches(sf)); // if no conditions, then 'all' pass
197  1 fms.or(fm1);
198  1 assertTrue(fms.matches(sf));
199  1 fms.or(fm2);
200  1 assertTrue(fms.matches(sf)); // true or false makes true
201   
202  1 fms = new FeatureMatcherSet();
203  1 fms.or(fm2);
204  1 assertFalse(fms.matches(sf));
205  1 fms.or(fm1);
206  1 assertTrue(fms.matches(sf)); // false or true makes true
207   
208  1 try
209    {
210  1 fms.and(fm2);
211  0 fail("Expected exception");
212    } catch (IllegalStateException e)
213    {
214    // expected
215    }
216    }
217   
 
218  1 toggle @Test(groups = "Functional")
219    public void testIsEmpty()
220    {
221  1 FeatureMatcherI fm = FeatureMatcher.byAttribute(Condition.GE, "-2.0",
222    "AF");
223  1 FeatureMatcherSetI fms = new FeatureMatcherSet();
224  1 assertTrue(fms.isEmpty());
225  1 fms.and(fm);
226  1 assertFalse(fms.isEmpty());
227    }
228   
 
229  1 toggle @Test(groups = "Functional")
230    public void testGetMatchers()
231    {
232  1 FeatureMatcherSetI fms = new FeatureMatcherSet();
233   
234    /*
235    * empty iterable:
236    */
237  1 Iterator<FeatureMatcherI> iterator = fms.getMatchers().iterator();
238  1 assertFalse(iterator.hasNext());
239   
240    /*
241    * one matcher:
242    */
243  1 FeatureMatcherI fm1 = FeatureMatcher.byAttribute(Condition.GE, "-2",
244    "AF");
245  1 fms.and(fm1);
246  1 iterator = fms.getMatchers().iterator();
247  1 assertSame(fm1, iterator.next());
248  1 assertFalse(iterator.hasNext());
249   
250    /*
251    * two matchers:
252    */
253  1 FeatureMatcherI fm2 = FeatureMatcher.byAttribute(Condition.LT, "8f",
254    "AF");
255  1 fms.and(fm2);
256  1 iterator = fms.getMatchers().iterator();
257  1 assertSame(fm1, iterator.next());
258  1 assertSame(fm2, iterator.next());
259  1 assertFalse(iterator.hasNext());
260    }
261   
262    /**
263    * Tests for the 'compound attribute' key i.e. where first key's value is a
264    * map from which we take the value for the second key, e.g. CSQ : Consequence
265    */
 
266  1 toggle @Test(groups = "Functional")
267    public void testMatches_compoundKey()
268    {
269    /*
270    * a numeric matcher - MatcherTest covers more conditions
271    */
272  1 FeatureMatcherI fm = FeatureMatcher.byAttribute(Condition.GE, "-2",
273    "CSQ", "Consequence");
274  1 SequenceFeature sf = new SequenceFeature("Cath", "desc", 2, 10, "grp");
275  1 FeatureMatcherSetI fms = new FeatureMatcherSet();
276  1 fms.and(fm);
277  1 assertFalse(fms.matches(sf));
278  1 Map<String, String> csq = new HashMap<>();
279  1 sf.setValue("CSQ", csq);
280  1 assertFalse(fms.matches(sf));
281  1 csq.put("Consequence", "-2");
282  1 assertTrue(fms.matches(sf));
283  1 csq.put("Consequence", "-1");
284  1 assertTrue(fms.matches(sf));
285  1 csq.put("Consequence", "-3");
286  1 assertFalse(fms.matches(sf));
287  1 csq.put("Consequence", "");
288  1 assertFalse(fms.matches(sf));
289  1 csq.put("Consequence", "junk");
290  1 assertFalse(fms.matches(sf));
291   
292    /*
293    * a string pattern matcher
294    */
295  1 fm = FeatureMatcher.byAttribute(Condition.Contains, "Cat", "CSQ",
296    "Consequence");
297  1 fms = new FeatureMatcherSet();
298  1 fms.and(fm);
299  1 assertFalse(fms.matches(sf));
300  1 csq.put("PolyPhen", "damaging");
301  1 assertFalse(fms.matches(sf));
302  1 csq.put("Consequence", "damaging");
303  1 assertFalse(fms.matches(sf));
304  1 csq.put("Consequence", "Catastrophic");
305  1 assertTrue(fms.matches(sf));
306    }
307   
308    /**
309    * Tests for toStableString which (unlike toString) does not i18n the
310    * conditions
311    *
312    * @see FeatureMatcherTest#testToStableString()
313    */
 
314  1 toggle @Test(groups = "Functional")
315    public void testToStableString()
316    {
317  1 FeatureMatcherI fm1 = FeatureMatcher.byAttribute(Condition.LT, "1.2",
318    "AF");
319  1 assertEquals(fm1.toStableString(), "AF LT 1.2");
320   
321  1 FeatureMatcher fm2 = FeatureMatcher.byAttribute(Condition.NotContains,
322    "path", "CLIN_SIG");
323  1 assertEquals(fm2.toStableString(), "CLIN_SIG NotContains path");
324   
325    /*
326    * AND them
327    */
328  1 FeatureMatcherSetI fms = new FeatureMatcherSet();
329  1 assertEquals(fms.toStableString(), "");
330  1 fms.and(fm1);
331    // no brackets needed if a single condition
332  1 assertEquals(fms.toStableString(), "AF LT 1.2");
333    // brackets if more than one condition
334  1 fms.and(fm2);
335  1 assertEquals(fms.toStableString(),
336    "(AF LT 1.2) AND (CLIN_SIG NotContains path)");
337   
338    /*
339    * OR them
340    */
341  1 fms = new FeatureMatcherSet();
342  1 assertEquals(fms.toStableString(), "");
343  1 fms.or(fm1);
344  1 assertEquals(fms.toStableString(), "AF LT 1.2");
345  1 fms.or(fm2);
346  1 assertEquals(fms.toStableString(),
347    "(AF LT 1.2) OR (CLIN_SIG NotContains path)");
348   
349    /*
350    * attribute or value including space is quoted
351    */
352  1 FeatureMatcher fm3 = FeatureMatcher.byAttribute(Condition.NotMatches,
353    "foo bar", "CSQ", "Poly Phen");
354  1 assertEquals(fm3.toStableString(),
355    "'CSQ:Poly Phen' NotMatches 'foo bar'");
356  1 fms.or(fm3);
357  1 assertEquals(fms.toStableString(),
358    "(AF LT 1.2) OR (CLIN_SIG NotContains path) OR ('CSQ:Poly Phen' NotMatches 'foo bar')");
359   
360  1 try
361    {
362  1 fms.and(fm1);
363  0 fail("Expected exception");
364    } catch (IllegalStateException e)
365    {
366    // expected
367    }
368    }
369   
370    /**
371    * Tests for parsing a string representation of a FeatureMatcherSet
372    *
373    * @see FeatureMatcherSetTest#testToStableString()
374    */
 
375  1 toggle @Test(groups = "Functional")
376    public void testFromString()
377    {
378  1 String descriptor = "AF LT 1.2";
379  1 FeatureMatcherSetI fms = FeatureMatcherSet.fromString(descriptor);
380   
381    /*
382    * shortcut asserts by verifying a 'roundtrip',
383    * which we trust if other tests pass :-)
384    */
385  1 assertEquals(fms.toStableString(), descriptor);
386   
387    // brackets optional, quotes optional, condition case insensitive
388  1 fms = FeatureMatcherSet.fromString("('AF' lt '1.2')");
389  1 assertEquals(fms.toStableString(), descriptor);
390   
391  1 descriptor = "(AF LT 1.2) AND (CLIN_SIG NotContains path)";
392  1 fms = FeatureMatcherSet.fromString(descriptor);
393  1 assertEquals(fms.toStableString(), descriptor);
394   
395    // AND is not case-sensitive
396  1 fms = FeatureMatcherSet
397    .fromString("(AF LT 1.2) and (CLIN_SIG NotContains path)");
398  1 assertEquals(fms.toStableString(), descriptor);
399   
400  1 descriptor = "(AF LT 1.2) OR (CLIN_SIG NotContains path)";
401  1 fms = FeatureMatcherSet.fromString(descriptor);
402  1 assertEquals(fms.toStableString(), descriptor);
403   
404    // OR is not case-sensitive
405  1 fms = FeatureMatcherSet
406    .fromString("(AF LT 1.2) or (CLIN_SIG NotContains path)");
407  1 assertEquals(fms.toStableString(), descriptor);
408   
409    // can get away without brackets on last match condition
410  1 fms = FeatureMatcherSet
411    .fromString("(AF LT 1.2) or CLIN_SIG NotContains path");
412  1 assertEquals(fms.toStableString(), descriptor);
413   
414  1 descriptor = "(AF LT 1.2) OR (CLIN_SIG NotContains path) OR ('CSQ:Poly Phen' NotMatches 'foo bar')";
415  1 fms = FeatureMatcherSet.fromString(descriptor);
416  1 assertEquals(fms.toStableString(), descriptor);
417   
418    // can't mix OR and AND
419  1 descriptor = "(AF LT 1.2) OR (CLIN_SIG NotContains path) AND ('CSQ:Poly Phen' NotMatches 'foo bar')";
420  1 assertNull(FeatureMatcherSet.fromString(descriptor));
421   
422    // can't mix AND and OR
423  1 descriptor = "(AF LT 1.2) and (CLIN_SIG NotContains path) or ('CSQ:Poly Phen' NotMatches 'foo bar')";
424  1 assertNull(FeatureMatcherSet.fromString(descriptor));
425   
426    // brackets missing
427  1 assertNull(FeatureMatcherSet
428    .fromString("AF LT 1.2 or CLIN_SIG NotContains path"));
429   
430    // invalid conjunction
431  1 assertNull(FeatureMatcherSet.fromString("(AF LT 1.2) but (AF GT -2)"));
432   
433    // unbalanced quote (1)
434  1 assertNull(FeatureMatcherSet.fromString("('AF lt '1.2')"));
435   
436    // unbalanced quote (2)
437  1 assertNull(FeatureMatcherSet.fromString("('AF' lt '1.2)"));
438    }
439    }