1   /*** 
2    * 
3    * Copyright 2004 Protique Ltd
4    * 
5    * Licensed under the Apache License, Version 2.0 (the "License"); 
6    * you may not use this file except in compliance with the License. 
7    * You may obtain a copy of the License at 
8    * 
9    * http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, 
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
14   * See the License for the specific language governing permissions and 
15   * limitations under the License. 
16   * 
17   **/
18  package org.codehaus.activemq.selector;
19  
20  import junit.framework.TestCase;
21  import org.codehaus.activemq.filter.Filter;
22  import org.codehaus.activemq.message.ActiveMQMessage;
23  import org.codehaus.activemq.message.ActiveMQTopic;
24  
25  import javax.jms.Destination;
26  import javax.jms.InvalidSelectorException;
27  import javax.jms.JMSException;
28  import javax.jms.Message;
29  
30  /***
31   * @version $Revision: 1.13 $
32   */
33  public class SelectorTest extends TestCase {
34  
35      public void testBasicSelectors() throws Exception {
36          Message message = createMessage();
37  
38          assertSelector(message, "name = 'James'", true);
39          assertSelector(message, "rank > 100", true);
40          assertSelector(message, "rank >= 123", true);
41          assertSelector(message, "rank >= 124", false);
42      }
43  
44      public void testAndSelectors() throws Exception {
45          Message message = createMessage();
46  
47          assertSelector(message, "name = 'James' and rank < 200", true);
48          assertSelector(message, "name = 'James' and rank > 200", false);
49          assertSelector(message, "name = 'Foo' and rank < 200", false);
50          assertSelector(message, "unknown = 'Foo' and anotherUnknown < 200", false);
51      }
52  
53      public void testOrSelectors() throws Exception {
54          Message message = createMessage();
55  
56          assertSelector(message, "name = 'James' or rank < 200", true);
57          assertSelector(message, "name = 'James' or rank > 200", true);
58          assertSelector(message, "name = 'Foo' or rank < 200", true);
59          assertSelector(message, "name = 'Foo' or rank > 200", false);
60          assertSelector(message, "unknown = 'Foo' or anotherUnknown < 200", false);
61      }
62  
63      public void testPlus() throws Exception {
64          Message message = createMessage();
65  
66          assertSelector(message, "rank + 2 = 125", true);
67          assertSelector(message, "(rank + 2) = 125", true);
68          assertSelector(message, "125 = (rank + 2)", true);
69          assertSelector(message, "rank + version = 125", true);
70          assertSelector(message, "rank + 2 < 124", false);
71          assertSelector(message, "name + '!' = 'James!'", true);
72      }
73  
74      public void testMinus() throws Exception {
75          Message message = createMessage();
76  
77          assertSelector(message, "rank - 2 = 121", true);
78          assertSelector(message, "rank - version = 121", true);
79          assertSelector(message, "rank - 2 > 122", false);
80      }
81  
82      public void testMultiply() throws Exception {
83          Message message = createMessage();
84  
85          assertSelector(message, "rank * 2 = 246", true);
86          assertSelector(message, "rank * version = 246", true);
87          assertSelector(message, "rank * 2 < 130", false);
88      }
89  
90      public void testDivide() throws Exception {
91          Message message = createMessage();
92  
93          assertSelector(message, "rank / version = 61.5", true);
94          assertSelector(message, "rank / 3 > 100.0", false);
95          assertSelector(message, "rank / 3 > 100", false);
96          assertSelector(message, "version / 2 = 1", true);
97  
98      }
99  
100     public void testBetween() throws Exception {
101         Message message = createMessage();
102 
103         assertSelector(message, "rank between 100 and 150", true);
104         assertSelector(message, "rank between 10 and 120", false);
105     }
106 
107     public void testIn() throws Exception {
108         Message message = createMessage();
109 
110         assertSelector(message, "name in ('James', 'Bob', 'Gromit')", true);
111         assertSelector(message, "name in ('Bob', 'James', 'Gromit')", true);
112         assertSelector(message, "name in ('Gromit', 'Bob', 'James')", true);
113 
114         assertSelector(message, "name in ('Gromit', 'Bob', 'Cheddar')", false);
115         assertSelector(message, "name not in ('Gromit', 'Bob', 'Cheddar')", true);
116     }
117 
118     public void testIsNull() throws Exception {
119         Message message = createMessage();
120 
121         assertSelector(message, "dummy is null", true);
122         assertSelector(message, "dummy is not null", false);
123         assertSelector(message, "name is not null", true);
124         assertSelector(message, "name is null", false);
125     }
126 
127     public void testFloatComparisons() throws Exception {
128         Message message = createMessage();
129         
130         // JMS 1.1 Section 3.8.1.1 : Approximate literals use the Java floating-point literal syntax. 
131         // We will use the java varible x to demo valid floating point syntaxs.
132         double x;
133         
134         // test decimals like x.x
135         x = 1.0;
136         x = -1.1;
137         x = 1.0E1;
138         x = 1.1E1;
139         x = -1.1E1;
140         assertSelector(message, "1.0 < 1.1", true);
141         assertSelector(message, "-1.1 < 1.0", true);
142         assertSelector(message, "1.0E1 < 1.1E1", true);
143         assertSelector(message, "-1.1E1 < 1.0E1", true);
144 
145         // test decimals like x.
146         x = 1.;
147         x = 1.E1;
148         assertSelector(message, "1. < 1.1", true);
149         assertSelector(message, "-1.1 < 1.", true);
150         assertSelector(message, "1.E1 < 1.1E1", true);
151         assertSelector(message, "-1.1E1 < 1.E1", true);
152         
153         // test decimals like .x
154         x = .5;
155         x = -.5;
156         x = .5E1;
157         assertSelector(message, ".1 < .5", true);
158         assertSelector(message, "-.5 < .1", true);
159         assertSelector(message, ".1E1 < .5E1", true);
160         assertSelector(message, "-.5E1 < .1E1", true);
161         
162         // test exponents
163         x = 4E10;
164         x = -4E10;
165         x = 5E+10;
166         x = 5E-10;
167         assertSelector(message, "4E10 < 5E10", true);
168         assertSelector(message, "5E8 < 5E10", true);
169         assertSelector(message, "-4E10 < 2E10", true);
170         assertSelector(message, "-5E8 < 2E2", true);
171         assertSelector(message, "4E+10 < 5E+10", true);
172         assertSelector(message, "4E-10 < 5E-10", true);
173     }
174 
175     public void testStringQuoteParsing() throws Exception {
176         Message message = createMessage();
177         assertSelector(message, "quote = '''In God We Trust'''", true);
178     }
179 
180     public void testLikeComparisons() throws Exception {
181         Message message = createMessage();
182 
183         assertSelector(message, "quote LIKE '''In G_d We Trust'''", true);
184         assertSelector(message, "quote LIKE '''In Gd_ We Trust'''", false);
185         assertSelector(message, "quote NOT LIKE '''In G_d We Trust'''", false);
186         assertSelector(message, "quote NOT LIKE '''In Gd_ We Trust'''", true);
187 
188         assertSelector(message, "foo LIKE '%oo'", true);
189         assertSelector(message, "foo LIKE '%ar'", false);
190         assertSelector(message, "foo NOT LIKE '%oo'", false);
191         assertSelector(message, "foo NOT LIKE '%ar'", true);
192 
193         assertSelector(message, "foo LIKE '!_%' ESCAPE '!'", true);
194         assertSelector(message, "quote LIKE '!_%' ESCAPE '!'", false);
195         assertSelector(message, "foo NOT LIKE '!_%' ESCAPE '!'", false);
196         assertSelector(message, "quote NOT LIKE '!_%' ESCAPE '!'", true);
197 
198         assertSelector(message, "punctuation LIKE '!#$&()*+,-./:;<=>?@[//]^`{|}~'", true);
199     }
200 
201     public void testInvalidSelector() throws Exception {
202         Message message = createMessage();
203         assertInvalidSelector(message, "3+5");
204         assertInvalidSelector(message, "True AND 3+5");
205         assertInvalidSelector(message, "=TEST 'test'");
206     }
207 
208     protected Message createMessage() throws JMSException {
209         Message message = createMessage("FOO.BAR");
210         message.setObjectProperty("name", "James");
211         message.setObjectProperty("location", "London");
212         message.setIntProperty("rank", 123);
213         message.setIntProperty("version", 2);
214         message.setStringProperty("quote", "'In God We Trust'");
215         message.setStringProperty("foo", "_foo");
216         message.setStringProperty("punctuation", "!#$&()*+,-./:;<=>?@[//]^`{|}~");
217 
218         return message;
219     }
220 
221 
222     protected void assertInvalidSelector(Message message, String text) throws JMSException {
223         try {
224             Filter selector = new SelectorParser().parse(text);
225             fail("Created a valid selector");
226         }
227         catch (InvalidSelectorException e) {
228         }
229     }
230 
231     protected void assertSelector(Message message, String text, boolean expected) throws JMSException {
232         Filter selector = new SelectorParser().parse(text);
233         assertTrue("Created a valid selector", selector != null);
234 
235         boolean value = selector.matches(message);
236 
237         assertEquals("Selector for: " + text, expected, value);
238     }
239 
240     protected Message createMessage(String subject) {
241         ActiveMQMessage message = new ActiveMQMessage();
242         message.setJMSDestination(createDestination(subject));
243         return message;
244     }
245 
246     protected Destination createDestination(String subject) {
247         return new ActiveMQTopic(subject);
248     }
249 }