Merge branch 'develop' into bug/JAL-2541cutRelocateFeatures
[jalview.git] / test / jalview / util / matcher / MatcherTest.java
diff --git a/test/jalview/util/matcher/MatcherTest.java b/test/jalview/util/matcher/MatcherTest.java
new file mode 100644 (file)
index 0000000..a47fb60
--- /dev/null
@@ -0,0 +1,273 @@
+package jalview.util.matcher;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.util.Locale;
+
+import org.testng.annotations.Test;
+
+import junit.extensions.PA;
+
+public class MatcherTest
+{
+  @Test(groups = "Functional")
+  public void testConstructor()
+  {
+    MatcherI m = new Matcher(Condition.Contains, "foo");
+    assertEquals(m.getCondition(), Condition.Contains);
+    assertEquals(m.getPattern(), "foo");
+    assertEquals(PA.getValue(m, "uppercasePattern"), "FOO");
+    assertEquals(m.getFloatValue(), 0f);
+
+    m = new Matcher(Condition.GT, -2.1f);
+    assertEquals(m.getCondition(), Condition.GT);
+    assertEquals(m.getPattern(), "-2.1");
+    assertEquals(m.getFloatValue(), -2.1f);
+
+    m = new Matcher(Condition.NotContains, "-1.2f");
+    assertEquals(m.getCondition(), Condition.NotContains);
+    assertEquals(m.getPattern(), "-1.2f");
+    assertEquals(m.getFloatValue(), 0f);
+
+    m = new Matcher(Condition.GE, "-1.2f");
+    assertEquals(m.getCondition(), Condition.GE);
+    assertEquals(m.getPattern(), "-1.2");
+    assertEquals(m.getFloatValue(), -1.2f);
+
+    try
+    {
+      new Matcher(null, 0f);
+      fail("Expected exception");
+    } catch (NullPointerException e)
+    {
+      // expected
+    }
+
+    try
+    {
+      new Matcher(Condition.LT, "123,456");
+      fail("Expected exception");
+    } catch (NumberFormatException e)
+    {
+      // expected
+    }
+  }
+
+  /**
+   * Tests for float comparison conditions
+   */
+  @Test(groups = "Functional")
+  public void testMatches_float()
+  {
+    /*
+     * EQUALS test
+     */
+    MatcherI m = new Matcher(Condition.EQ, 2f);
+    assertTrue(m.matches("2"));
+    assertTrue(m.matches("2.0"));
+    assertFalse(m.matches("2.01"));
+
+    /*
+     * NOT EQUALS test
+     */
+    m = new Matcher(Condition.NE, 2f);
+    assertFalse(m.matches("2"));
+    assertFalse(m.matches("2.0"));
+    assertTrue(m.matches("2.01"));
+
+    /*
+     * >= test
+     */
+    m = new Matcher(Condition.GE, 2f);
+    assertTrue(m.matches("2"));
+    assertTrue(m.matches("2.1"));
+    assertFalse(m.matches("1.9"));
+
+    /*
+     * > test
+     */
+    m = new Matcher(Condition.GT, 2f);
+    assertFalse(m.matches("2"));
+    assertTrue(m.matches("2.1"));
+    assertFalse(m.matches("1.9"));
+
+    /*
+     * <= test
+     */
+    m = new Matcher(Condition.LE, 2f);
+    assertTrue(m.matches("2"));
+    assertFalse(m.matches("2.1"));
+    assertTrue(m.matches("1.9"));
+
+    /*
+     * < test
+     */
+    m = new Matcher(Condition.LT, 2f);
+    assertFalse(m.matches("2"));
+    assertFalse(m.matches("2.1"));
+    assertTrue(m.matches("1.9"));
+  }
+
+  @Test(groups = "Functional")
+  public void testMatches_floatNullOrInvalid()
+  {
+    for (Condition cond : Condition.values())
+    {
+      if (cond.isNumeric())
+      {
+        MatcherI m = new Matcher(cond, 2f);
+        assertFalse(m.matches(null));
+        assertFalse(m.matches(""));
+        assertFalse(m.matches("two"));
+      }
+    }
+  }
+
+  /**
+   * Tests for string comparison conditions
+   */
+  @Test(groups = "Functional")
+  public void testMatches_pattern()
+  {
+    /*
+     * Contains
+     */
+    MatcherI m = new Matcher(Condition.Contains, "benign");
+    assertTrue(m.matches("benign"));
+    assertTrue(m.matches("MOSTLY BENIGN OBSERVED")); // not case-sensitive
+    assertFalse(m.matches("pathogenic"));
+    assertFalse(m.matches(null));
+
+    /*
+     * does not contain
+     */
+    m = new Matcher(Condition.NotContains, "benign");
+    assertFalse(m.matches("benign"));
+    assertFalse(m.matches("MOSTLY BENIGN OBSERVED")); // not case-sensitive
+    assertTrue(m.matches("pathogenic"));
+    assertTrue(m.matches(null)); // null value passes this condition
+
+    /*
+     * matches
+     */
+    m = new Matcher(Condition.Matches, "benign");
+    assertTrue(m.matches("benign"));
+    assertTrue(m.matches(" Benign ")); // trim before testing
+    assertFalse(m.matches("MOSTLY BENIGN"));
+    assertFalse(m.matches("pathogenic"));
+    assertFalse(m.matches(null));
+
+    /*
+     * does not match
+     */
+    m = new Matcher(Condition.NotMatches, "benign");
+    assertFalse(m.matches("benign"));
+    assertFalse(m.matches(" Benign ")); // trim before testing
+    assertTrue(m.matches("MOSTLY BENIGN"));
+    assertTrue(m.matches("pathogenic"));
+    assertTrue(m.matches(null));
+
+    /*
+     * value is present (is not null)
+     */
+    m = new Matcher(Condition.Present, null);
+    assertTrue(m.matches("benign"));
+    assertTrue(m.matches(""));
+    assertFalse(m.matches(null));
+
+    /*
+     * value is not present (is null)
+     */
+    m = new Matcher(Condition.NotPresent, null);
+    assertFalse(m.matches("benign"));
+    assertFalse(m.matches(""));
+    assertTrue(m.matches(null));
+
+    /*
+     * a float with a string match condition will be treated as string
+     */
+    Matcher m1 = new Matcher(Condition.Contains, "32");
+    assertFalse(m1.matches(-203f));
+    assertTrue(m1.matches(-4321.0f));
+  }
+
+  /**
+   * If a float is passed with a string condition it gets converted to a string
+   */
+  @Test(groups = "Functional")
+  public void testMatches_floatWithStringCondition()
+  {
+    MatcherI m = new Matcher(Condition.Contains, 1.2e-6f);
+    assertTrue(m.matches("1.2e-6"));
+
+    m = new Matcher(Condition.Contains, 0.0000001f);
+    assertTrue(m.matches("1.0e-7"));
+    assertTrue(m.matches("1.0E-7"));
+    assertFalse(m.matches("0.0000001f"));
+  }
+
+  @Test(groups = "Functional")
+  public void testToString()
+  {
+    Locale.setDefault(Locale.ENGLISH);
+
+    MatcherI m = new Matcher(Condition.LT, 1.2e-6f);
+    assertEquals(m.toString(), "< 1.2E-6");
+
+    m = new Matcher(Condition.NotMatches, "ABC");
+    assertEquals(m.toString(), "Does not match 'ABC'");
+
+    m = new Matcher(Condition.Contains, -1.2f);
+    assertEquals(m.toString(), "Contains '-1.2'");
+  }
+
+  @Test(groups = "Functional")
+  public void testEquals()
+  {
+    /*
+     * string condition
+     */
+    MatcherI m = new Matcher(Condition.NotMatches, "ABC");
+    assertFalse(m.equals(null));
+    assertFalse(m.equals("foo"));
+    assertTrue(m.equals(m));
+    assertTrue(m.equals(new Matcher(Condition.NotMatches, "ABC")));
+    // not case-sensitive:
+    assertTrue(m.equals(new Matcher(Condition.NotMatches, "abc")));
+    assertFalse(m.equals(new Matcher(Condition.Matches, "ABC")));
+    assertFalse(m.equals(new Matcher(Condition.NotMatches, "def")));
+
+    /*
+     * numeric conditions
+     */
+    m = new Matcher(Condition.LT, -1f);
+    assertFalse(m.equals(null));
+    assertFalse(m.equals("foo"));
+    assertTrue(m.equals(m));
+    assertTrue(m.equals(new Matcher(Condition.LT, -1f)));
+    assertTrue(m.equals(new Matcher(Condition.LT, "-1f")));
+    assertTrue(m.equals(new Matcher(Condition.LT, "-1.00f")));
+    assertFalse(m.equals(new Matcher(Condition.LE, -1f)));
+    assertFalse(m.equals(new Matcher(Condition.GE, -1f)));
+    assertFalse(m.equals(new Matcher(Condition.NE, -1f)));
+    assertFalse(m.equals(new Matcher(Condition.LT, 1f)));
+    assertFalse(m.equals(new Matcher(Condition.LT, -1.1f)));
+  }
+
+  @Test(groups = "Functional")
+  public void testHashCode()
+  {
+    MatcherI m1 = new Matcher(Condition.NotMatches, "ABC");
+    MatcherI m2 = new Matcher(Condition.NotMatches, "ABC");
+    MatcherI m3 = new Matcher(Condition.NotMatches, "AB");
+    MatcherI m4 = new Matcher(Condition.Matches, "ABC");
+    assertEquals(m1.hashCode(), m2.hashCode());
+    assertNotEquals(m1.hashCode(), m3.hashCode());
+    assertNotEquals(m1.hashCode(), m4.hashCode());
+    assertNotEquals(m3.hashCode(), m4.hashCode());
+  }
+}