d29f00010b1f1241c2098663d69571fbd8c3af8e
[jalview.git] / test / jalview / util / matcher / MatcherTest.java
1 package jalview.util.matcher;
2
3 import static org.testng.Assert.assertEquals;
4 import static org.testng.Assert.assertFalse;
5 import static org.testng.Assert.assertNotEquals;
6 import static org.testng.Assert.assertSame;
7 import static org.testng.Assert.assertTrue;
8 import static org.testng.Assert.fail;
9
10 import java.util.Locale;
11
12 import org.testng.annotations.Test;
13
14 import jalview.util.matcher.Matcher.PatternType;
15 import junit.extensions.PA;
16
17 public class MatcherTest
18 {
19   @Test(groups = "Functional")
20   public void testConstructor()
21   {
22     MatcherI m = new Matcher(Condition.Contains, "foo");
23     assertEquals(m.getCondition(), Condition.Contains);
24     assertEquals(m.getPattern(), "foo");
25     assertEquals(PA.getValue(m, "uppercasePattern"), "FOO");
26     assertEquals(PA.getValue(m, "floatValue"), 0f);
27     assertEquals(PA.getValue(m, "longValue"), 0L);
28     assertSame(PA.getValue(m, "patternType"), PatternType.String);
29
30     m = new Matcher(Condition.GT, -2.1f);
31     assertEquals(m.getCondition(), Condition.GT);
32     assertEquals(m.getPattern(), "-2.1");
33     assertEquals(PA.getValue(m, "floatValue"), -2.1f);
34     assertEquals(PA.getValue(m, "longValue"), 0L);
35     assertSame(PA.getValue(m, "patternType"), PatternType.Float);
36
37     m = new Matcher(Condition.NotContains, "-1.2f");
38     assertEquals(m.getCondition(), Condition.NotContains);
39     assertEquals(m.getPattern(), "-1.2f");
40     assertEquals(PA.getValue(m, "floatValue"), 0f);
41     assertEquals(PA.getValue(m, "longValue"), 0L);
42     assertSame(PA.getValue(m, "patternType"), PatternType.String);
43
44     m = new Matcher(Condition.GE, "-1.2f");
45     assertEquals(m.getCondition(), Condition.GE);
46     assertEquals(m.getPattern(), "-1.2");
47     assertEquals(PA.getValue(m, "floatValue"), -1.2f);
48     assertEquals(PA.getValue(m, "longValue"), 0L);
49     assertSame(PA.getValue(m, "patternType"), PatternType.Float);
50
51     m = new Matcher(Condition.GE, "113890813");
52     assertEquals(m.getCondition(), Condition.GE);
53     assertEquals(m.getPattern(), "113890813");
54     assertEquals(PA.getValue(m, "floatValue"), 0f);
55     assertEquals(PA.getValue(m, "longValue"), 113890813L);
56     assertSame(PA.getValue(m, "patternType"), PatternType.Integer);
57
58     m = new Matcher(Condition.GE, "-987f");
59     assertEquals(m.getCondition(), Condition.GE);
60     assertEquals(m.getPattern(), "-987.0");
61     assertEquals(PA.getValue(m, "floatValue"), -987f);
62     assertEquals(PA.getValue(m, "longValue"), 0L);
63     assertSame(PA.getValue(m, "patternType"), PatternType.Float);
64
65     try
66     {
67       new Matcher(null, 0f);
68       fail("Expected exception");
69     } catch (NullPointerException e)
70     {
71       // expected
72     }
73
74     try
75     {
76       new Matcher(Condition.LT, "123,456");
77       fail("Expected exception");
78     } catch (NumberFormatException e)
79     {
80       // expected - see Long.valueOf()
81     }
82
83     try
84     {
85       new Matcher(Condition.LT, "123_456");
86       fail("Expected exception");
87     } catch (NumberFormatException e)
88     {
89       // expected - see Long.valueOf()
90     }
91
92     try
93     {
94       new Matcher(Condition.LT, "123456L");
95       fail("Expected exception");
96     } catch (NumberFormatException e)
97     {
98       // expected - see Long.valueOf()
99     }
100   }
101
102   /**
103    * Tests for float comparison conditions
104    */
105   @Test(groups = "Functional")
106   public void testMatches_float()
107   {
108     /*
109      * EQUALS test
110      */
111     MatcherI m = new Matcher(Condition.EQ, 2f);
112     assertTrue(m.matches("2"));
113     assertTrue(m.matches("2.0"));
114     assertFalse(m.matches("2.01"));
115
116     /*
117      * NOT EQUALS test
118      */
119     m = new Matcher(Condition.NE, 2f);
120     assertFalse(m.matches("2"));
121     assertFalse(m.matches("2.0"));
122     assertTrue(m.matches("2.01"));
123
124     /*
125      * >= test
126      */
127     m = new Matcher(Condition.GE, "2f");
128     assertTrue(m.matches("2"));
129     assertTrue(m.matches("2.1"));
130     assertFalse(m.matches("1.9"));
131
132     /*
133      * > test
134      */
135     m = new Matcher(Condition.GT, 2f);
136     assertFalse(m.matches("2"));
137     assertTrue(m.matches("2.1"));
138     assertFalse(m.matches("1.9"));
139
140     /*
141      * <= test
142      */
143     m = new Matcher(Condition.LE, "2.0f");
144     assertTrue(m.matches("2"));
145     assertFalse(m.matches("2.1"));
146     assertTrue(m.matches("1.9"));
147
148     /*
149      * < test
150      */
151     m = new Matcher(Condition.LT, 2f);
152     assertFalse(m.matches("2"));
153     assertFalse(m.matches("2.1"));
154     assertTrue(m.matches("1.9"));
155   }
156
157   /**
158    * Verifies that all numeric match conditions fail when applied to non-numeric
159    * or null values
160    */
161   @Test(groups = "Functional")
162   public void testNumericMatch_nullOrInvalidValue()
163   {
164     for (Condition cond : Condition.values())
165     {
166       if (cond.isNumeric())
167       {
168         MatcherI m1 = new Matcher(cond, 2.1f);
169         MatcherI m2 = new Matcher(cond, 2345L);
170         assertFalse(m1.matches(null));
171         assertFalse(m1.matches(""));
172         assertFalse(m1.matches("two"));
173         assertFalse(m2.matches(null));
174         assertFalse(m2.matches(""));
175         assertFalse(m2.matches("two"));
176       }
177     }
178   }
179
180   /**
181    * Tests for string comparison conditions
182    */
183   @Test(groups = "Functional")
184   public void testMatches_pattern()
185   {
186     /*
187      * Contains
188      */
189     MatcherI m = new Matcher(Condition.Contains, "benign");
190     assertTrue(m.matches("benign"));
191     assertTrue(m.matches("MOSTLY BENIGN OBSERVED")); // not case-sensitive
192     assertFalse(m.matches("pathogenic"));
193     assertFalse(m.matches(null));
194
195     /*
196      * does not contain
197      */
198     m = new Matcher(Condition.NotContains, "benign");
199     assertFalse(m.matches("benign"));
200     assertFalse(m.matches("MOSTLY BENIGN OBSERVED")); // not case-sensitive
201     assertTrue(m.matches("pathogenic"));
202     assertTrue(m.matches(null)); // null value passes this condition
203
204     /*
205      * matches
206      */
207     m = new Matcher(Condition.Matches, "benign");
208     assertTrue(m.matches("benign"));
209     assertTrue(m.matches(" Benign ")); // trim before testing
210     assertFalse(m.matches("MOSTLY BENIGN"));
211     assertFalse(m.matches("pathogenic"));
212     assertFalse(m.matches(null));
213
214     /*
215      * does not match
216      */
217     m = new Matcher(Condition.NotMatches, "benign");
218     assertFalse(m.matches("benign"));
219     assertFalse(m.matches(" Benign ")); // trimmed before testing
220     assertTrue(m.matches("MOSTLY BENIGN"));
221     assertTrue(m.matches("pathogenic"));
222     assertTrue(m.matches(null));
223
224     /*
225      * value is present (is not null)
226      */
227     m = new Matcher(Condition.Present, null);
228     assertTrue(m.matches("benign"));
229     assertTrue(m.matches(""));
230     assertFalse(m.matches(null));
231
232     /*
233      * value is not present (is null)
234      */
235     m = new Matcher(Condition.NotPresent, null);
236     assertFalse(m.matches("benign"));
237     assertFalse(m.matches(""));
238     assertTrue(m.matches(null));
239
240     /*
241      * a number with a string match condition will be treated as string
242      */
243     Matcher m1 = new Matcher(Condition.Contains, "32");
244     assertFalse(m1.matchesFloat("-203f", 0f));
245     assertTrue(m1.matchesFloat("-4321.0f", 0f));
246     assertFalse(m1.matchesFloat("-203", 0f));
247     assertTrue(m1.matchesFloat("-4321", 0f));
248   }
249
250   /**
251    * If a float is passed with a string condition it gets converted to a string
252    */
253   @Test(groups = "Functional")
254   public void testMatches_floatWithStringCondition()
255   {
256     MatcherI m = new Matcher(Condition.Contains, 1.2e-6f);
257     assertEquals(m.getPattern(), "1.2E-6");
258     assertEquals(PA.getValue(m, "uppercasePattern"), "1.2E-6");
259     assertEquals(PA.getValue(m, "floatValue"), 0f);
260     assertEquals(PA.getValue(m, "longValue"), 0L);
261     assertSame(PA.getValue(m, "patternType"), PatternType.String);
262     assertTrue(m.matches("1.2e-6"));
263
264     m = new Matcher(Condition.Contains, 0.0000001f);
265     assertEquals(m.getPattern(), "1.0E-7");
266     assertTrue(m.matches("1.0e-7"));
267     assertTrue(m.matches("1.0E-7"));
268     assertFalse(m.matches("0.0000001f"));
269   }
270
271   @Test(groups = "Functional")
272   public void testToString()
273   {
274     Locale.setDefault(Locale.ENGLISH);
275
276     MatcherI m = new Matcher(Condition.LT, 1.2e-6f);
277     assertEquals(m.toString(), "< 1.2E-6");
278
279     m = new Matcher(Condition.GE, "20200413");
280     assertEquals(m.toString(), ">= 20200413");
281
282     m = new Matcher(Condition.NotMatches, "ABC");
283     assertEquals(m.toString(), "Does not match 'ABC'");
284
285     m = new Matcher(Condition.Contains, -1.2f);
286     assertEquals(m.toString(), "Contains '-1.2'");
287   }
288
289   @Test(groups = "Functional")
290   public void testEquals()
291   {
292     /*
293      * string condition
294      */
295     MatcherI m = new Matcher(Condition.NotMatches, "ABC");
296     assertFalse(m.equals(null));
297     assertFalse(m.equals("foo"));
298     assertTrue(m.equals(m));
299     assertTrue(m.equals(new Matcher(Condition.NotMatches, "ABC")));
300     // not case-sensitive:
301     assertTrue(m.equals(new Matcher(Condition.NotMatches, "abc")));
302     assertFalse(m.equals(new Matcher(Condition.Matches, "ABC")));
303     assertFalse(m.equals(new Matcher(Condition.NotMatches, "def")));
304
305     /*
306      * numeric conditions - float values
307      */
308     m = new Matcher(Condition.LT, -1f);
309     assertFalse(m.equals(null));
310     assertFalse(m.equals("foo"));
311     assertTrue(m.equals(m));
312     assertTrue(m.equals(new Matcher(Condition.LT, -1f)));
313     assertTrue(m.equals(new Matcher(Condition.LT, "-1f")));
314     assertTrue(m.equals(new Matcher(Condition.LT, "-1.00f")));
315     assertFalse(m.equals(new Matcher(Condition.LE, -1f)));
316     assertFalse(m.equals(new Matcher(Condition.GE, -1f)));
317     assertFalse(m.equals(new Matcher(Condition.NE, -1f)));
318     assertFalse(m.equals(new Matcher(Condition.LT, 1f)));
319     assertFalse(m.equals(new Matcher(Condition.LT, -1.1f)));
320
321     /*
322      * numeric conditions - integer values
323      */
324     m = new Matcher(Condition.LT, -123456);
325     assertFalse(m.equals(null));
326     assertFalse(m.equals("foo"));
327     assertTrue(m.equals(m));
328     assertTrue(m.equals(new Matcher(Condition.LT, -123456)));
329     assertTrue(m.equals(new Matcher(Condition.LT, "-123456")));
330     assertFalse(m.equals(new Matcher(Condition.LT, -123456f)));
331     assertFalse(m.equals(new Matcher(Condition.LT, "-123456f")));
332   }
333
334   @Test(groups = "Functional")
335   public void testHashCode()
336   {
337     MatcherI m1 = new Matcher(Condition.NotMatches, "ABC");
338     MatcherI m2 = new Matcher(Condition.NotMatches, "ABC");
339     MatcherI m3 = new Matcher(Condition.NotMatches, "AB");
340     MatcherI m4 = new Matcher(Condition.Matches, "ABC");
341     assertEquals(m1.hashCode(), m2.hashCode());
342     assertNotEquals(m1.hashCode(), m3.hashCode());
343     assertNotEquals(m1.hashCode(), m4.hashCode());
344     assertNotEquals(m3.hashCode(), m4.hashCode());
345   }
346
347   /**
348    * Tests for integer comparison conditions
349    */
350   @Test(groups = "Functional")
351   public void testMatches_long()
352   {
353     /*
354      * EQUALS test
355      */
356     MatcherI m = new Matcher(Condition.EQ, 2);
357     assertTrue(m.matches("2"));
358     assertTrue(m.matches("+2"));
359     // a float value may be passed to an integer matcher
360     assertTrue(m.matches("2.0"));
361     assertTrue(m.matches("2.000000f"));
362     assertFalse(m.matches("2.01"));
363   
364     /*
365      * NOT EQUALS test
366      */
367     m = new Matcher(Condition.NE, 123);
368     assertFalse(m.matches("123"));
369     assertFalse(m.matches("123.0"));
370     assertTrue(m.matches("-123"));
371   
372     /*
373      * >= test
374      */
375     m = new Matcher(Condition.GE, "113890813");
376     assertTrue(m.matches("113890813"));
377     assertTrue(m.matches("113890814"));
378     assertFalse(m.matches("-113890813"));
379   
380     /*
381      * > test
382      */
383     m = new Matcher(Condition.GT, 113890813);
384     assertFalse(m.matches("113890813"));
385     assertTrue(m.matches("113890814"));
386   
387     /*
388      * <= test
389      */
390     m = new Matcher(Condition.LE, "113890813");
391     assertTrue(m.matches("113890813"));
392     assertFalse(m.matches("113890814"));
393     assertTrue(m.matches("113890812"));
394   
395     /*
396      * < test
397      */
398     m = new Matcher(Condition.LT, 113890813);
399     assertFalse(m.matches("113890813"));
400     assertFalse(m.matches("113890814"));
401     assertTrue(m.matches("113890812"));
402   }
403
404   /**
405    * Tests comparing a float value with an integer condition
406    */
407   @Test(groups = "Functional")
408   public void testMatches_floatValueIntegerCondition()
409   {
410     MatcherI m = new Matcher(Condition.GT, 1234);
411     assertEquals(PA.getValue(m, "longValue"), 1234L);
412     assertSame(PA.getValue(m, "patternType"), PatternType.Integer);
413     assertTrue(m.matches("1235"));
414     assertTrue(m.matches("9867.345"));
415     assertTrue(m.matches("9867.345f"));
416   }
417 }