This is an automated email from the ASF dual-hosted git repository.

vavrtom pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git


The following commit(s) were added to refs/heads/main by this push:
     new 8f7909fbb2 QPID-8656: [Broker-J] Selector parsing logic error when 
combining NOT and LIKE (#230)
8f7909fbb2 is described below

commit 8f7909fbb2d6f9eae22b84e3a4782af6d7d70bbc
Author: Daniil Kirilyuk <[email protected]>
AuthorDate: Wed Dec 13 09:30:32 2023 +0100

    QPID-8656: [Broker-J] Selector parsing logic error when combining NOT and 
LIKE (#230)
---
 broker-core/src/main/grammar/SelectorParser.jj     |   2 +-
 .../server/filter/selector/ParseException.java     |   2 +-
 .../server/filter/selector/SelectorParser.java     | 162 +++++------
 .../selector/SelectorParserTokenManager.java       |  11 +
 .../server/filter/selector/SimpleCharStream.java   |   2 +-
 .../apache/qpid/server/filter/selector/Token.java  |   3 +-
 .../qpid/server/filter/selector/TokenMgrError.java |   3 +-
 .../server/filter/JMSSelectorFilterSyntaxTest.java | 319 +++++++++++++++++++++
 8 files changed, 416 insertions(+), 88 deletions(-)

diff --git a/broker-core/src/main/grammar/SelectorParser.jj 
b/broker-core/src/main/grammar/SelectorParser.jj
index 8aea8295e8..4271907cd9 100644
--- a/broker-core/src/main/grammar/SelectorParser.jj
+++ b/broker-core/src/main/grammar/SelectorParser.jj
@@ -459,7 +459,7 @@ Expression unaryExpr() :
                left = UnaryExpression.createNegate(left);
            }
            |
-           <NOT> left=unaryExpr()
+           <NOT> left=orExpression()
            {
                    left = UnaryExpression.createNOT( asBooleanExpression(left) 
);
            }
diff --git 
a/broker-core/src/main/java/org/apache/qpid/server/filter/selector/ParseException.java
 
b/broker-core/src/main/java/org/apache/qpid/server/filter/selector/ParseException.java
index bb456ef2db..ea28826696 100644
--- 
a/broker-core/src/main/java/org/apache/qpid/server/filter/selector/ParseException.java
+++ 
b/broker-core/src/main/java/org/apache/qpid/server/filter/selector/ParseException.java
@@ -205,4 +205,4 @@ public class ParseException extends Exception {
    }
 
 }
-/* JavaCC - OriginalChecksum=d315306e736475f86f69c53861799960 (do not edit 
this line) */
+/* JavaCC - OriginalChecksum=f191e3976fe6d5a6a93a2d6f845dcf9d (do not edit 
this line) */
diff --git 
a/broker-core/src/main/java/org/apache/qpid/server/filter/selector/SelectorParser.java
 
b/broker-core/src/main/java/org/apache/qpid/server/filter/selector/SelectorParser.java
index 0997a2d26f..80082f52c8 100644
--- 
a/broker-core/src/main/java/org/apache/qpid/server/filter/selector/SelectorParser.java
+++ 
b/broker-core/src/main/java/org/apache/qpid/server/filter/selector/SelectorParser.java
@@ -416,7 +416,7 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
         break;
       case NOT:
         jj_consume_token(NOT);
-        left = unaryExpr();
+        left = orExpression();
                     left = UnaryExpression.createNOT( 
asBooleanExpression(left) );
         break;
       case TRUE:
@@ -611,7 +611,7 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
   private boolean jj_3R_55() {
     if (jj_scan_token(IN)) return true;
     if (jj_scan_token(33)) return true;
-    if (jj_3R_38()) return true;
+    if (jj_3R_47()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
@@ -621,7 +621,7 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
     return false;
   }
 
-  private boolean jj_3R_47() {
+  private boolean jj_3R_46() {
     if (jj_scan_token(IS)) return true;
     if (jj_scan_token(NOT)) return true;
     if (jj_scan_token(NULL)) return true;
@@ -634,7 +634,7 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
     return false;
   }
 
-  private boolean jj_3R_33() {
+  private boolean jj_3R_39() {
     if (jj_scan_token(NULL)) return true;
     return false;
   }
@@ -661,13 +661,13 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
     return false;
   }
 
-  private boolean jj_3R_46() {
+  private boolean jj_3R_45() {
     if (jj_scan_token(28)) return true;
-    if (jj_3R_41()) return true;
+    if (jj_3R_30()) return true;
     return false;
   }
 
-  private boolean jj_3R_32() {
+  private boolean jj_3R_38() {
     if (jj_scan_token(FALSE)) return true;
     return false;
   }
@@ -675,28 +675,28 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
   private boolean jj_3_3() {
     if (jj_scan_token(NOT)) return true;
     if (jj_scan_token(BETWEEN)) return true;
-    if (jj_3R_43()) return true;
+    if (jj_3R_42()) return true;
     if (jj_scan_token(AND)) return true;
-    if (jj_3R_43()) return true;
+    if (jj_3R_42()) return true;
     return false;
   }
 
-  private boolean jj_3R_45() {
+  private boolean jj_3R_44() {
     if (jj_scan_token(27)) return true;
-    if (jj_3R_41()) return true;
+    if (jj_3R_30()) return true;
     return false;
   }
 
-  private boolean jj_3R_42() {
+  private boolean jj_3R_31() {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_45()) {
+    if (jj_3R_44()) {
     jj_scanpos = xsp;
-    if (jj_3R_46()) {
+    if (jj_3R_45()) {
     jj_scanpos = xsp;
     if (jj_3_1()) {
     jj_scanpos = xsp;
-    if (jj_3R_47()) return true;
+    if (jj_3R_46()) return true;
     }
     }
     }
@@ -705,20 +705,20 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
 
   private boolean jj_3R_54() {
     if (jj_scan_token(BETWEEN)) return true;
-    if (jj_3R_43()) return true;
+    if (jj_3R_42()) return true;
     if (jj_scan_token(AND)) return true;
-    if (jj_3R_43()) return true;
+    if (jj_3R_42()) return true;
     return false;
   }
 
-  private boolean jj_3R_31() {
+  private boolean jj_3R_37() {
     if (jj_scan_token(TRUE)) return true;
     return false;
   }
 
   private boolean jj_3R_58() {
     if (jj_scan_token(ESCAPE)) return true;
-    if (jj_3R_38()) return true;
+    if (jj_3R_47()) return true;
     return false;
   }
 
@@ -728,17 +728,17 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
     return false;
   }
 
-  private boolean jj_3R_30() {
+  private boolean jj_3R_36() {
     if (jj_scan_token(FLOATING_POINT_LITERAL)) return true;
     return false;
   }
 
-  private boolean jj_3R_39() {
-    if (jj_3R_41()) return true;
+  private boolean jj_3R_26() {
+    if (jj_3R_30()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_42()) { jj_scanpos = xsp; break; }
+      if (jj_3R_31()) { jj_scanpos = xsp; break; }
     }
     return false;
   }
@@ -746,7 +746,7 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
   private boolean jj_3_2() {
     if (jj_scan_token(NOT)) return true;
     if (jj_scan_token(LIKE)) return true;
-    if (jj_3R_38()) return true;
+    if (jj_3R_47()) return true;
     Token xsp;
     xsp = jj_scanpos;
     if (jj_3R_59()) jj_scanpos = xsp;
@@ -755,7 +755,7 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
 
   private boolean jj_3R_53() {
     if (jj_scan_token(LIKE)) return true;
-    if (jj_3R_38()) return true;
+    if (jj_3R_47()) return true;
     Token xsp;
     xsp = jj_scanpos;
     if (jj_3R_58()) jj_scanpos = xsp;
@@ -768,7 +768,7 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
     return false;
   }
 
-  private boolean jj_3R_29() {
+  private boolean jj_3R_35() {
     if (jj_scan_token(OCTAL_LITERAL)) return true;
     return false;
   }
@@ -792,13 +792,13 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
     return false;
   }
 
-  private boolean jj_3R_40() {
+  private boolean jj_3R_27() {
     if (jj_scan_token(AND)) return true;
-    if (jj_3R_39()) return true;
+    if (jj_3R_26()) return true;
     return false;
   }
 
-  private boolean jj_3R_28() {
+  private boolean jj_3R_34() {
     if (jj_scan_token(HEX_LITERAL)) return true;
     return false;
   }
@@ -813,7 +813,7 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
     return false;
   }
 
-  private boolean jj_3R_27() {
+  private boolean jj_3R_33() {
     if (jj_scan_token(DECIMAL_LITERAL)) return true;
     return false;
   }
@@ -824,12 +824,12 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
     return false;
   }
 
-  private boolean jj_3R_36() {
-    if (jj_3R_39()) return true;
+  private boolean jj_3R_21() {
+    if (jj_3R_26()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_40()) { jj_scanpos = xsp; break; }
+      if (jj_3R_27()) { jj_scanpos = xsp; break; }
     }
     return false;
   }
@@ -847,11 +847,11 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
 
   private boolean jj_3R_52() {
     if (jj_scan_token(32)) return true;
-    if (jj_3R_43()) return true;
+    if (jj_3R_42()) return true;
     return false;
   }
 
-  private boolean jj_3R_35() {
+  private boolean jj_3R_41() {
     if (jj_scan_token(QUOTED_ID)) return true;
     return false;
   }
@@ -862,25 +862,25 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
     return false;
   }
 
-  private boolean jj_3R_26() {
-    if (jj_3R_38()) return true;
+  private boolean jj_3R_32() {
+    if (jj_3R_47()) return true;
     return false;
   }
 
   private boolean jj_3R_51() {
     if (jj_scan_token(31)) return true;
-    if (jj_3R_43()) return true;
+    if (jj_3R_42()) return true;
     return false;
   }
 
-  private boolean jj_3R_34() {
+  private boolean jj_3R_40() {
     if (jj_scan_token(ID)) return true;
     return false;
   }
 
   private boolean jj_3R_61() {
     if (jj_scan_token(34)) return true;
-    if (jj_3R_38()) return true;
+    if (jj_3R_47()) return true;
     return false;
   }
 
@@ -894,30 +894,30 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
     return false;
   }
 
-  private boolean jj_3R_37() {
+  private boolean jj_3R_22() {
     if (jj_scan_token(OR)) return true;
-    if (jj_3R_36()) return true;
+    if (jj_3R_21()) return true;
     return false;
   }
 
-  private boolean jj_3R_23() {
+  private boolean jj_3R_28() {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_26()) {
+    if (jj_3R_32()) {
     jj_scanpos = xsp;
-    if (jj_3R_27()) {
+    if (jj_3R_33()) {
     jj_scanpos = xsp;
-    if (jj_3R_28()) {
+    if (jj_3R_34()) {
     jj_scanpos = xsp;
-    if (jj_3R_29()) {
+    if (jj_3R_35()) {
     jj_scanpos = xsp;
-    if (jj_3R_30()) {
+    if (jj_3R_36()) {
     jj_scanpos = xsp;
-    if (jj_3R_31()) {
+    if (jj_3R_37()) {
     jj_scanpos = xsp;
-    if (jj_3R_32()) {
+    if (jj_3R_38()) {
     jj_scanpos = xsp;
-    if (jj_3R_33()) return true;
+    if (jj_3R_39()) return true;
     }
     }
     }
@@ -930,27 +930,27 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
 
   private boolean jj_3R_50() {
     if (jj_scan_token(30)) return true;
-    if (jj_3R_43()) return true;
+    if (jj_3R_42()) return true;
     return false;
   }
 
-  private boolean jj_3R_24() {
+  private boolean jj_3R_29() {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_34()) {
+    if (jj_3R_40()) {
     jj_scanpos = xsp;
-    if (jj_3R_35()) return true;
+    if (jj_3R_41()) return true;
     }
     return false;
   }
 
   private boolean jj_3R_49() {
     if (jj_scan_token(29)) return true;
-    if (jj_3R_43()) return true;
+    if (jj_3R_42()) return true;
     return false;
   }
 
-  private boolean jj_3R_44() {
+  private boolean jj_3R_43() {
     Token xsp;
     xsp = jj_scanpos;
     if (jj_3R_49()) {
@@ -984,7 +984,7 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
     return false;
   }
 
-  private boolean jj_3R_43() {
+  private boolean jj_3R_42() {
     if (jj_3R_9()) return true;
     Token xsp;
     while (true) {
@@ -994,58 +994,58 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
     return false;
   }
 
-  private boolean jj_3R_25() {
-    if (jj_3R_36()) return true;
+  private boolean jj_3R_19() {
+    if (jj_3R_21()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_37()) { jj_scanpos = xsp; break; }
+      if (jj_3R_22()) { jj_scanpos = xsp; break; }
     }
     return false;
   }
 
-  private boolean jj_3R_22() {
+  private boolean jj_3R_25() {
     if (jj_scan_token(33)) return true;
-    if (jj_3R_25()) return true;
+    if (jj_3R_19()) return true;
     if (jj_scan_token(35)) return true;
     return false;
   }
 
-  private boolean jj_3R_21() {
-    if (jj_3R_24()) return true;
+  private boolean jj_3R_24() {
+    if (jj_3R_29()) return true;
     return false;
   }
 
-  private boolean jj_3R_20() {
-    if (jj_3R_23()) return true;
+  private boolean jj_3R_23() {
+    if (jj_3R_28()) return true;
     return false;
   }
 
   private boolean jj_3R_60() {
     if (jj_scan_token(34)) return true;
-    if (jj_3R_38()) return true;
+    if (jj_3R_47()) return true;
     return false;
   }
 
-  private boolean jj_3R_19() {
+  private boolean jj_3R_20() {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_20()) {
+    if (jj_3R_23()) {
     jj_scanpos = xsp;
-    if (jj_3R_21()) {
+    if (jj_3R_24()) {
     jj_scanpos = xsp;
-    if (jj_3R_22()) return true;
+    if (jj_3R_25()) return true;
     }
     }
     return false;
   }
 
-  private boolean jj_3R_41() {
-    if (jj_3R_43()) return true;
+  private boolean jj_3R_30() {
+    if (jj_3R_42()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_44()) { jj_scanpos = xsp; break; }
+      if (jj_3R_43()) { jj_scanpos = xsp; break; }
     }
     return false;
   }
@@ -1054,7 +1054,7 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
     if (jj_scan_token(NOT)) return true;
     if (jj_scan_token(IN)) return true;
     if (jj_scan_token(33)) return true;
-    if (jj_3R_38()) return true;
+    if (jj_3R_47()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
@@ -1072,23 +1072,23 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
 
   private boolean jj_3R_59() {
     if (jj_scan_token(ESCAPE)) return true;
-    if (jj_3R_38()) return true;
+    if (jj_3R_47()) return true;
     return false;
   }
 
-  private boolean jj_3R_38() {
+  private boolean jj_3R_47() {
     if (jj_scan_token(STRING_LITERAL)) return true;
     return false;
   }
 
   private boolean jj_3R_15() {
-    if (jj_3R_19()) return true;
+    if (jj_3R_20()) return true;
     return false;
   }
 
   private boolean jj_3R_14() {
     if (jj_scan_token(NOT)) return true;
-    if (jj_3R_10()) return true;
+    if (jj_3R_19()) return true;
     return false;
   }
 
@@ -1169,7 +1169,7 @@ public class SelectorParser<E> implements 
SelectorParserConstants {
     throw generateParseException();
   }
 
-  static private final class LookaheadSuccess extends java.lang.Error { }
+  static private final class LookaheadSuccess extends Error { }
   final private LookaheadSuccess jj_ls = new LookaheadSuccess();
   private boolean jj_scan_token(int kind) {
     if (jj_scanpos == jj_lastpos) {
diff --git 
a/broker-core/src/main/java/org/apache/qpid/server/filter/selector/SelectorParserTokenManager.java
 
b/broker-core/src/main/java/org/apache/qpid/server/filter/selector/SelectorParserTokenManager.java
index 287f5d221e..73e0db2152 100644
--- 
a/broker-core/src/main/java/org/apache/qpid/server/filter/selector/SelectorParserTokenManager.java
+++ 
b/broker-core/src/main/java/org/apache/qpid/server/filter/selector/SelectorParserTokenManager.java
@@ -21,6 +21,17 @@
  */
 
 package org.apache.qpid.server.filter.selector;
+import java.io.StringReader;
+import java.util.ArrayList;
+import org.apache.qpid.server.filter.ArithmeticExpression;
+import org.apache.qpid.server.filter.BooleanExpression;
+import org.apache.qpid.server.filter.ComparisonExpression;
+import org.apache.qpid.server.filter.ConstantExpression;
+import org.apache.qpid.server.filter.Expression;
+import org.apache.qpid.server.filter.LogicExpression;
+import org.apache.qpid.server.filter.PropertyExpression;
+import org.apache.qpid.server.filter.PropertyExpressionFactory;
+import org.apache.qpid.server.filter.UnaryExpression;
 
 /** Token Manager. */
 public class SelectorParserTokenManager implements SelectorParserConstants
diff --git 
a/broker-core/src/main/java/org/apache/qpid/server/filter/selector/SimpleCharStream.java
 
b/broker-core/src/main/java/org/apache/qpid/server/filter/selector/SimpleCharStream.java
index 64b169034c..7e41554f43 100644
--- 
a/broker-core/src/main/java/org/apache/qpid/server/filter/selector/SimpleCharStream.java
+++ 
b/broker-core/src/main/java/org/apache/qpid/server/filter/selector/SimpleCharStream.java
@@ -489,4 +489,4 @@ public class SimpleCharStream
   }
 
 }
-/* JavaCC - OriginalChecksum=dcf3510e97e4ee9a841bdafac162a129 (do not edit 
this line) */
+/* JavaCC - OriginalChecksum=dd31548eee2e798f7cd0fab4448f1d95 (do not edit 
this line) */
diff --git 
a/broker-core/src/main/java/org/apache/qpid/server/filter/selector/Token.java 
b/broker-core/src/main/java/org/apache/qpid/server/filter/selector/Token.java
index 581cfd35a4..5a4d5681e7 100644
--- 
a/broker-core/src/main/java/org/apache/qpid/server/filter/selector/Token.java
+++ 
b/broker-core/src/main/java/org/apache/qpid/server/filter/selector/Token.java
@@ -118,7 +118,6 @@ public class Token implements java.io.Serializable {
   /**
    * Returns the image.
    */
-  @Override
   public String toString()
   {
     return image;
@@ -150,4 +149,4 @@ public class Token implements java.io.Serializable {
   }
 
 }
-/* JavaCC - OriginalChecksum=dfd1857bf2f000661cadfe9ef672245e (do not edit 
this line) */
+/* JavaCC - OriginalChecksum=181874db027eea8b35f565d8393a0afa (do not edit 
this line) */
diff --git 
a/broker-core/src/main/java/org/apache/qpid/server/filter/selector/TokenMgrError.java
 
b/broker-core/src/main/java/org/apache/qpid/server/filter/selector/TokenMgrError.java
index e26f37f6e6..f85eec77e7 100644
--- 
a/broker-core/src/main/java/org/apache/qpid/server/filter/selector/TokenMgrError.java
+++ 
b/broker-core/src/main/java/org/apache/qpid/server/filter/selector/TokenMgrError.java
@@ -142,7 +142,6 @@ public class TokenMgrError extends Error
    *
    * from this method for such cases in the release version of your parser.
    */
-  @Override
   public String getMessage() {
     return super.getMessage();
   }
@@ -166,4 +165,4 @@ public class TokenMgrError extends Error
     this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, 
curChar), reason);
   }
 }
-/* JavaCC - OriginalChecksum=795daaee93a15e0081e60f73df35399f (do not edit 
this line) */
+/* JavaCC - OriginalChecksum=dbdd2965cdf45ffc1a6fe0e4cb1331df (do not edit 
this line) */
diff --git 
a/broker-core/src/test/java/org/apache/qpid/server/filter/JMSSelectorFilterSyntaxTest.java
 
b/broker-core/src/test/java/org/apache/qpid/server/filter/JMSSelectorFilterSyntaxTest.java
new file mode 100644
index 0000000000..629b048a94
--- /dev/null
+++ 
b/broker-core/src/test/java/org/apache/qpid/server/filter/JMSSelectorFilterSyntaxTest.java
@@ -0,0 +1,319 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.server.filter;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.jupiter.api.Test;
+
+public class JMSSelectorFilterSyntaxTest
+{
+    @Test
+    public void equality() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+        when(message.getHeader("color")).thenReturn("red");
+        when(message.getHeader("price")).thenReturn(100);
+
+        assertTrue(new JMSSelectorFilter("color = 'red'").matches(message));
+        assertTrue(new JMSSelectorFilter("price = 100").matches(message));
+        assertFalse(new JMSSelectorFilter("color = 'blue'").matches(message));
+        assertFalse(new JMSSelectorFilter("price = 200").matches(message));
+    }
+
+    @Test
+    public void inequality() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+        when(message.getHeader("color")).thenReturn("red");
+        when(message.getHeader("price")).thenReturn(100);
+
+        assertTrue(new JMSSelectorFilter("color <> 'blue'").matches(message));
+        assertTrue(new JMSSelectorFilter("price <> 200").matches(message));
+        assertFalse(new JMSSelectorFilter("color <> 'red'").matches(message));
+        assertFalse(new JMSSelectorFilter("price <> 100").matches(message));
+    }
+
+    @Test
+    public void greaterThan() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+        when(message.getHeader("price")).thenReturn(100);
+
+        assertTrue(new JMSSelectorFilter("price > 10").matches(message));
+        assertFalse(new JMSSelectorFilter("price > 100").matches(message));
+    }
+
+    @Test
+    public void greaterThanOrEquals() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+        when(message.getHeader("price")).thenReturn(100);
+
+        assertTrue(new JMSSelectorFilter("price >= 10").matches(message));
+        assertTrue(new JMSSelectorFilter("price >= 100").matches(message));
+        assertFalse(new JMSSelectorFilter("price >= 200").matches(message));
+    }
+
+    @Test
+    public void lessThan() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+        when(message.getHeader("price")).thenReturn(100);
+
+        assertTrue(new JMSSelectorFilter("price < 110").matches(message));
+        assertFalse(new JMSSelectorFilter("price < 100").matches(message));
+    }
+
+    @Test
+    public void lessThanOrEquals() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+        when(message.getHeader("price")).thenReturn(100);
+
+        assertTrue(new JMSSelectorFilter("price <= 110").matches(message));
+        assertTrue(new JMSSelectorFilter("price <= 100").matches(message));
+        assertFalse(new JMSSelectorFilter("price <= 10").matches(message));
+    }
+
+    @Test
+    public void and() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+        when(message.getHeader("color")).thenReturn("red");
+        when(message.getHeader("price")).thenReturn(100);
+
+        assertTrue(new JMSSelectorFilter("color = 'red' and price = 
100").matches(message));
+        assertFalse(new JMSSelectorFilter("color = 'red' and price = 
200").matches(message));
+        assertFalse(new JMSSelectorFilter("color = 'blue' and price = 
100").matches(message));
+        assertFalse(new JMSSelectorFilter("color = 'blue' and price = 
200").matches(message));
+    }
+
+    @Test
+    public void or() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+        when(message.getHeader("color")).thenReturn("red");
+        when(message.getHeader("price")).thenReturn(100);
+
+        assertTrue(new JMSSelectorFilter("color = 'red' or price = 
100").matches(message));
+        assertTrue(new JMSSelectorFilter("color = 'red' or price = 
200").matches(message));
+        assertTrue(new JMSSelectorFilter("color = 'blue' or price = 
100").matches(message));
+        assertFalse(new JMSSelectorFilter("color = 'blue' or price = 
200").matches(message));
+    }
+
+    @Test
+    public void in() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+
+        when(message.getHeader("fruit")).thenReturn("apple");
+        assertTrue(new JMSSelectorFilter("fruit in ('apple', 'banana', 
'cherry')").matches(message));
+
+        when(message.getHeader("fruit")).thenReturn("banana");
+        assertTrue(new JMSSelectorFilter("fruit in ('apple', 'banana', 
'cherry')").matches(message));
+
+        when(message.getHeader("fruit")).thenReturn("cherry");
+        assertTrue(new JMSSelectorFilter("fruit in ('apple', 'banana', 
'cherry')").matches(message));
+
+        when(message.getHeader("fruit")).thenReturn("mango");
+        assertFalse(new JMSSelectorFilter("fruit in ('apple', 'banana', 
'cherry')").matches(message));
+    }
+
+    @Test
+    public void notIn() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+
+        when(message.getHeader("fruit")).thenReturn("apple");
+        assertFalse(new JMSSelectorFilter("fruit not in ('apple', 'banana', 
'cherry')").matches(message));
+        assertFalse(new JMSSelectorFilter("not (fruit in ('apple', 'banana', 
'cherry'))").matches(message));
+        assertFalse(new JMSSelectorFilter("not fruit in ('apple', 'banana', 
'cherry')").matches(message));
+
+        when(message.getHeader("fruit")).thenReturn("banana");
+        assertFalse(new JMSSelectorFilter("fruit not in ('apple', 'banana', 
'cherry')").matches(message));
+        assertFalse(new JMSSelectorFilter("not (fruit in ('apple', 'banana', 
'cherry'))").matches(message));
+        assertFalse(new JMSSelectorFilter("not fruit in ('apple', 'banana', 
'cherry')").matches(message));
+
+        when(message.getHeader("fruit")).thenReturn("cherry");
+        assertFalse(new JMSSelectorFilter("fruit not in ('apple', 'banana', 
'cherry')").matches(message));
+        assertFalse(new JMSSelectorFilter("not (fruit in ('apple', 'banana', 
'cherry'))").matches(message));
+        assertFalse(new JMSSelectorFilter("not fruit in ('apple', 'banana', 
'cherry')").matches(message));
+
+        when(message.getHeader("fruit")).thenReturn("mango");
+        assertTrue(new JMSSelectorFilter("fruit not in ('apple', 'banana', 
'cherry')").matches(message));
+        assertTrue(new JMSSelectorFilter("not (fruit in ('apple', 'banana', 
'cherry'))").matches(message));
+        assertTrue(new JMSSelectorFilter("not fruit in ('apple', 'banana', 
'cherry')").matches(message));
+    }
+
+    @Test
+    public void between() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+        when(message.getHeader("price")).thenReturn(100);
+
+        assertTrue(new JMSSelectorFilter("price between 90 and 
110").matches(message));
+        assertTrue(new JMSSelectorFilter("price between 100 and 
110").matches(message));
+        assertTrue(new JMSSelectorFilter("price between 90 and 
100").matches(message));
+        assertFalse(new JMSSelectorFilter("price between 110 and 
120").matches(message));
+    }
+
+    @Test
+    public void notBetween() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+        when(message.getHeader("price")).thenReturn(100);
+
+        assertFalse(new JMSSelectorFilter("price not between 90 and 
110").matches(message));
+        assertFalse(new JMSSelectorFilter("price not between 100 and 
110").matches(message));
+        assertFalse(new JMSSelectorFilter("price not between 90 and 
100").matches(message));
+        assertTrue(new JMSSelectorFilter("price not between 110 and 
120").matches(message));
+
+        assertFalse(new JMSSelectorFilter("not (price between 90 and 
110)").matches(message));
+        assertFalse(new JMSSelectorFilter("not (price between 100 and 
110)").matches(message));
+        assertFalse(new JMSSelectorFilter("not (price between 90 and 
100)").matches(message));
+        assertTrue(new JMSSelectorFilter("not (price between 110 and 
120)").matches(message));
+
+        assertFalse(new JMSSelectorFilter("not price between 90 and 
110").matches(message));
+        assertFalse(new JMSSelectorFilter("not price between 100 and 
110").matches(message));
+        assertFalse(new JMSSelectorFilter("not price between 90 and 
100").matches(message));
+        assertTrue(new JMSSelectorFilter("not price between 110 and 
120").matches(message));
+    }
+
+    @Test
+    public void like() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+
+        when(message.getHeader("entry")).thenReturn("bbb");
+        assertFalse(new JMSSelectorFilter("entry like 
'%aaa%'").matches(message));
+
+        when(message.getHeader("entry")).thenReturn("aaa");
+        assertTrue(new JMSSelectorFilter("entry like 
'%aaa%'").matches(message));
+    }
+
+    @Test
+    public void notLike() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+        when(message.getHeader("entry")).thenReturn("bbb");
+
+        assertTrue(new JMSSelectorFilter("entry NOT LIKE 
'%aaa%'").matches(message));
+        assertTrue(new JMSSelectorFilter("(entry NOT LIKE 
'%aaa%')").matches(message));
+
+        assertTrue(new JMSSelectorFilter("NOT (entry LIKE 
'%aaa%')").matches(message));
+        assertTrue(new JMSSelectorFilter("NOT entry LIKE 
'%aaa%'").matches(message));
+
+        when(message.getHeader("entry")).thenReturn("aaa");
+
+        assertFalse(new JMSSelectorFilter("entry NOT LIKE 
'%aaa%'").matches(message));
+        assertFalse(new JMSSelectorFilter("(entry NOT LIKE 
'%aaa%')").matches(message));
+
+        assertFalse(new JMSSelectorFilter("NOT (entry LIKE 
'%aaa%')").matches(message));
+        assertFalse(new JMSSelectorFilter("NOT entry LIKE 
'%aaa%'").matches(message));
+    }
+
+    @Test
+    public void isNull() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+        when(message.getHeader("entry")).thenReturn("aaa");
+
+        assertFalse(new JMSSelectorFilter("entry is null").matches(message));
+        assertTrue(new JMSSelectorFilter("another_entry is 
null").matches(message));
+    }
+
+    @Test
+    public void isNotNull() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+        when(message.getHeader("entry")).thenReturn("aaa");
+
+        assertTrue(new JMSSelectorFilter("entry is not 
null").matches(message));
+        assertTrue(new JMSSelectorFilter("not (entry is 
null)").matches(message));
+        assertTrue(new JMSSelectorFilter("not entry is 
null").matches(message));
+        assertFalse(new JMSSelectorFilter("another_entry is not 
null").matches(message));
+        assertFalse(new JMSSelectorFilter("not (another_entry is 
null)").matches(message));
+        assertFalse(new JMSSelectorFilter("not another_entry is 
null").matches(message));
+    }
+
+    @Test
+    public void arithmetic() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+        when(message.getHeader("size")).thenReturn(10);
+        when(message.getHeader("price")).thenReturn(100);
+
+        assertTrue(new JMSSelectorFilter("size + price = 
110").matches(message));
+        assertTrue(new JMSSelectorFilter("price - size = 
90").matches(message));
+        assertTrue(new JMSSelectorFilter("price / size = 
10").matches(message));
+        assertTrue(new JMSSelectorFilter("price * size = 
1000").matches(message));
+
+        assertTrue(new JMSSelectorFilter("size / 4 = 2.5").matches(message));
+        assertTrue(new JMSSelectorFilter("size / 4.0 = 2.5").matches(message));
+
+        assertTrue(new JMSSelectorFilter("size * 2 = 20.0").matches(message));
+        assertTrue(new JMSSelectorFilter("size * 2.0 = 
20.0").matches(message));
+    }
+
+    @Test
+    public void arithmeticOperatorsPrecedence() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+        when(message.getHeader("size")).thenReturn(10);
+        when(message.getHeader("price")).thenReturn(100);
+
+        assertTrue(new JMSSelectorFilter("1 + 1 * 10 = 11").matches(message));
+        assertTrue(new JMSSelectorFilter("(1 + 1) * 10 = 
20").matches(message));
+
+        assertTrue(new JMSSelectorFilter("1 + 1 / 10 = 1.1").matches(message));
+        assertTrue(new JMSSelectorFilter("(1 + 1) / 10 = 
0.2").matches(message));
+    }
+
+    @Test
+    public void logicOperatorsPrecedence() throws Exception
+    {
+        final Filterable message = mock(Filterable.class);
+
+        when(message.getHeader("a")).thenReturn(1);
+        when(message.getHeader("b")).thenReturn(2);
+        when(message.getHeader("c")).thenReturn(3);
+        assertTrue(new JMSSelectorFilter("a = 1 and b = 2 or c = 
3").matches(message));
+        assertFalse(new JMSSelectorFilter("not a = 1 and b = 
2").matches(message));
+        assertTrue(new JMSSelectorFilter("a = 1 and (b = 2 or c = 
3)").matches(message));
+        assertTrue(new JMSSelectorFilter("a = 1 and (b = 2 or c = 
4)").matches(message));
+        assertTrue(new JMSSelectorFilter("a = 1 and (b = 3 or c = 
3)").matches(message));
+        assertFalse(new JMSSelectorFilter("a = 1 and (b = 3 or c = 
4)").matches(message));
+        assertTrue(new JMSSelectorFilter("not (not a = 1)").matches(message));
+        assertTrue(new JMSSelectorFilter("not not a = 1").matches(message));
+
+        when(message.getHeader("a")).thenReturn(1);
+        when(message.getHeader("b")).thenReturn(2);
+        when(message.getHeader("c")).thenReturn(4);
+        assertTrue(new JMSSelectorFilter("a = 1 and b = 2 or c = 
3").matches(message));
+
+        when(message.getHeader("a")).thenReturn(1);
+        when(message.getHeader("b")).thenReturn(1);
+        when(message.getHeader("c")).thenReturn(3);
+        assertTrue(new JMSSelectorFilter("a = 1 and b = 2 or c = 
3").matches(message));
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to