cd444ceb649718aa730ae9f1f224d11d128be1ed
[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      * (these cases shouldn't arise as the match() method is coded)
243      */
244     Matcher m1 = new Matcher(Condition.Contains, "32");
245     assertFalse(m1.matchesFloat("-203f", 0f));
246     assertTrue(m1.matchesFloat("-4321.0f", 0f));
247     assertFalse(m1.matchesFloat("-203", 0f));
248     assertTrue(m1.matchesFloat("-4321", 0f));
249     assertFalse(m1.matchesLong("-203"));
250     assertTrue(m1.matchesLong("-4321"));
251     assertFalse(m1.matchesLong("-203f"));
252     assertTrue(m1.matchesLong("-4321.0f"));
253   }
254
255   /**
256    * If a float is passed with a string condition it gets converted to a string
257    */
258   @Test(groups = "Functional")
259   public void testMatches_floatWithStringCondition()
260   {
261     MatcherI m = new Matcher(Condition.Contains, 1.2e-6f);
262     assertEquals(m.getPattern(), "1.2E-6");
263     assertEquals(PA.getValue(m, "uppercasePattern"), "1.2E-6");
264     assertEquals(PA.getValue(m, "floatValue"), 0f);
265     assertEquals(PA.getValue(m, "longValue"), 0L);
266     assertSame(PA.getValue(m, "patternType"), PatternType.String);
267     assertTrue(m.matches("1.2e-6"));
268
269     m = new Matcher(Condition.Contains, 0.0000001f);
270     assertEquals(m.getPattern(), "1.0E-7");
271     assertTrue(m.matches("1.0e-7"));
272     assertTrue(m.matches("1.0E-7"));
273     assertFalse(m.matches("0.0000001f"));
274   }
275
276   @Test(groups = "Functional")
277   public void testToString()
278   {
279     Locale.setDefault(Locale.ENGLISH);
280
281     MatcherI m = new Matcher(Condition.LT, 1.2e-6f);
282     assertEquals(m.toString(), "< 1.2E-6");
283
284     m = new Matcher(Condition.GE, "20200413");
285     assertEquals(m.toString(), ">= 20200413");
286
287     m = new Matcher(Condition.NotMatches, "ABC");
288     assertEquals(m.toString(), "Does not match 'ABC'");
289
290     m = new Matcher(Condition.Contains, -1.2f);
291     assertEquals(m.toString(), "Contains '-1.2'");
292   }
293
294   @Test(groups = "Functional")
295   public void testEquals()
296   {
297     /*
298      * string condition
299      */
300     MatcherI m = new Matcher(Condition.NotMatches, "ABC");
301     assertFalse(m.equals(null));
302     assertFalse(m.equals("foo"));
303     assertTrue(m.equals(m));
304     assertTrue(m.equals(new Matcher(Condition.NotMatches, "ABC")));
305     // not case-sensitive:
306     assertTrue(m.equals(new Matcher(Condition.NotMatches, "abc")));
307     assertFalse(m.equals(new Matcher(Condition.Matches, "ABC")));
308     assertFalse(m.equals(new Matcher(Condition.NotMatches, "def")));
309
310     /*
311      * numeric conditions - float values
312      */
313     m = new Matcher(Condition.LT, -1f);
314     assertFalse(m.equals(null));
315     assertFalse(m.equals("foo"));
316     assertTrue(m.equals(m));
317     assertTrue(m.equals(new Matcher(Condition.LT, -1f)));
318     assertTrue(m.equals(new Matcher(Condition.LT, "-1f")));
319     assertTrue(m.equals(new Matcher(Condition.LT, "-1.00f")));
320     assertFalse(m.equals(new Matcher(Condition.LE, -1f)));
321     assertFalse(m.equals(new Matcher(Condition.GE, -1f)));
322     assertFalse(m.equals(new Matcher(Condition.NE, -1f)));
323     assertFalse(m.equals(new Matcher(Condition.LT, 1f)));
324     assertFalse(m.equals(new Matcher(Condition.LT, -1.1f)));
325
326     /*
327      * numeric conditions - integer values
328      */
329     m = new Matcher(Condition.LT, -123456);
330     assertFalse(m.equals(null));
331     assertFalse(m.equals("foo"));
332     assertTrue(m.equals(m));
333     assertTrue(m.equals(new Matcher(Condition.LT, -123456)));
334     assertFalse(m.equals(new Matcher(Condition.LT, +123456)));
335     assertTrue(m.equals(new Matcher(Condition.LT, "-123456")));
336     assertFalse(m.equals(new Matcher(Condition.LT, -123456f)));
337     assertFalse(m.equals(new Matcher(Condition.LT, "-123456f")));
338   }
339
340   @Test(groups = "Functional")
341   public void testHashCode()
342   {
343     MatcherI m1 = new Matcher(Condition.NotMatches, "ABC");
344     MatcherI m2 = new Matcher(Condition.NotMatches, "ABC");
345     MatcherI m3 = new Matcher(Condition.NotMatches, "AB");
346     MatcherI m4 = new Matcher(Condition.Matches, "ABC");
347     assertEquals(m1.hashCode(), m2.hashCode());
348     assertNotEquals(m1.hashCode(), m3.hashCode());
349     assertNotEquals(m1.hashCode(), m4.hashCode());
350     assertNotEquals(m3.hashCode(), m4.hashCode());
351   }
352
353   /**
354    * Tests for integer comparison conditions
355    */
356   @Test(groups = "Functional")
357   public void testMatches_long()
358   {
359     /*
360      * EQUALS test
361      */
362     MatcherI m = new Matcher(Condition.EQ, 2);
363     assertTrue(m.matches("2"));
364     assertTrue(m.matches("+2"));
365     assertFalse(m.matches("3"));
366     // a float value may be passed to an integer matcher
367     assertTrue(m.matches("2.0"));
368     assertTrue(m.matches("2.000000f"));
369     assertFalse(m.matches("2.01"));
370
371     /*
372      * NOT EQUALS test
373      */
374     m = new Matcher(Condition.NE, 123);
375     assertFalse(m.matches("123"));
376     assertFalse(m.matches("123.0"));
377     assertTrue(m.matches("-123"));
378
379     /*
380      * >= test
381      */
382     m = new Matcher(Condition.GE, "113890813");
383     assertTrue(m.matches("113890813"));
384     assertTrue(m.matches("113890814"));
385     assertFalse(m.matches("-113890813"));
386
387     /*
388      * > test
389      */
390     m = new Matcher(Condition.GT, 113890813);
391     assertFalse(m.matches("113890813"));
392     assertTrue(m.matches("113890814"));
393
394     /*
395      * <= test
396      */
397     m = new Matcher(Condition.LE, "113890813");
398     assertTrue(m.matches("113890813"));
399     assertFalse(m.matches("113890814"));
400     assertTrue(m.matches("113890812"));
401
402     /*
403      * < test
404      */
405     m = new Matcher(Condition.LT, 113890813);
406     assertFalse(m.matches("113890813"));
407     assertFalse(m.matches("113890814"));
408     assertTrue(m.matches("113890812"));
409   }
410
411   /**
412    * Tests comparing a float value with an integer condition
413    */
414   @Test(groups = "Functional")
415   public void testMatches_floatValueIntegerCondition()
416   {
417     MatcherI m = new Matcher(Condition.GT, 1234);
418     assertEquals(PA.getValue(m, "longValue"), 1234L);
419     assertSame(PA.getValue(m, "patternType"), PatternType.Integer);
420     assertTrue(m.matches("1235"));
421     assertTrue(m.matches("9867.345"));
422     assertTrue(m.matches("9867.345f"));
423   }
424 }