1   /*** 
2    * 
3    * Copyright 2004 Hiram Chirino
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.filter;
19  
20  import junit.framework.TestCase;
21  import org.codehaus.activemq.filter.MultiExpressionEvaluator.ExpressionListener;
22  import org.codehaus.activemq.message.ActiveMQMessage;
23  import org.codehaus.activemq.selector.SelectorParser;
24  
25  import javax.jms.JMSException;
26  import javax.jms.Message;
27  import java.util.ArrayList;
28  import java.util.Iterator;
29  
30  /***
31   * Test cases for the MultiExpressionEvaluator class.
32   */
33  public class MultiExpressionEvaluatorTest extends TestCase {
34      MultiExpressionEvaluator evaluator = new MultiExpressionEvaluator();
35      ArrayList expressions = new ArrayList();
36  
37      /***
38       * @see junit.framework.TestCase#setUp()
39       */
40      protected void setUp() throws Exception {
41          // Add a few expressions that have matching nested expressions.
42          // Make sure that there are 3 more true expressions than false ones.
43          expressions.add(parseTrue("(3+4=7 AND 3+4=7) OR 1=10"));// true
44          expressions.add(parseTrue("(3+4=7 AND 3+4=7) AND 3+4=7"));// true
45          expressions.add(parseTrue("(3+4)*10=70"));// true
46  
47          expressions.add(parseTrue("((3+4=7 AND 3+4=7) OR 1=10) AND 10 BETWEEN 0 AND 100"));// true
48          expressions.add(parseFalse("(3+4)*5=70"));// false
49  
50          expressions.add(parseTrue("10 BETWEEN 0 AND 100"));// true
51          expressions.add(parseFalse("((3+4=7 OR 3+4=7) OR 1=10) AND 1=10"));// false
52      }
53  
54      /***
55       * @param string
56       * @return
57       */
58      private Expression parseTrue(String string) throws Exception {
59          Expression rc = parse(string);
60          assertEquals(rc.evaluate(new ActiveMQMessage()), Boolean.TRUE);
61          return rc;
62      }
63  
64      /***
65       * @param string
66       * @return
67       */
68      private Expression parseFalse(String string) throws Exception {
69          Expression rc = parse(string);
70          assertEquals(rc.evaluate(new ActiveMQMessage()), Boolean.FALSE);
71          return rc;
72      }
73  
74      protected Expression parse(String text) throws Exception {
75          ExpressionFilter filter = (ExpressionFilter) new SelectorParser()
76                  .parse(text);
77          return filter.getExpression();
78      }
79  
80      /***
81       * There are 3 expression that are true in the expressions list.
82       * test them all and see if the count is right.
83       */
84      public void testSimpleEvaluation() {
85  
86          final int hits[] = new int[]{0};
87          final boolean test[] = new boolean[]{true};
88  
89          for (Iterator i = expressions.iterator(); i.hasNext();) {
90              Expression expr = (Expression) i.next();
91              evaluator.addExpressionListner(expr, new ExpressionListener() {
92                  public void evaluateResultEvent(Expression selector,
93                                                  Message message, Object result) {
94                      if (result.equals(Boolean.TRUE)) {
95                          hits[0]++;
96                      }
97                      else {
98                          hits[0]--;
99                      }
100                 }
101             });
102         }
103 
104         evaluator.evaluate(new ActiveMQMessage());
105         assertTrue(hits[0] == 3);
106     }
107 
108     static final public int SPEED_TEST_ITERATIONS = 100000;
109 
110     public void testSpeedUsingMultiExpressionEvaluator() {
111         // setup
112         // Add all the expressions to the MultiExpressionEvaluator
113         for (Iterator i = expressions.iterator(); i.hasNext();) {
114             Expression expr = (Expression) i.next();
115             evaluator.addExpressionListner(expr, new ExpressionListener() {
116                 public void evaluateResultEvent(Expression selector, Message message, Object result) {
117                 }
118             });
119         }
120         ActiveMQMessage message = new ActiveMQMessage();
121 
122         // Now evaluate:
123         long start = System.currentTimeMillis();
124         for (int i = 0; i < SPEED_TEST_ITERATIONS; i++) {
125             evaluator.evaluate(message);
126         }
127         long end = System.currentTimeMillis();
128         printSpeedReport("Using MultiExpressionEvaluator", start, end);
129     }
130 
131     public void testSpeedNotUsingMultiExpressionEvaluator() {
132 
133         // setup
134         Expression expr[] = new Expression[expressions.size()];
135         expressions.toArray(expr);
136         ActiveMQMessage message = new ActiveMQMessage();
137 
138         // Now evaluate:
139         long start = System.currentTimeMillis();
140         for (int i = 0; i < SPEED_TEST_ITERATIONS; i++) {
141 
142             for (int j = 0; j < expr.length; j++) {
143                 try {
144                     expr[j].evaluate(message);
145                 }
146                 catch (JMSException e) {
147                 }
148             }
149         }
150 
151         long end = System.currentTimeMillis();
152         printSpeedReport("Not Using MultiExpressionEvaluator", start, end);
153     }
154 
155     /***
156      * @param string
157      * @param start
158      * @param end
159      */
160     private void printSpeedReport(String testName, long start, long end) {
161         System.out.println("Duration: " + testName + ": " + ((float) (end - start) / 1000.0) + " seconds.");
162         System.out.println("Evaluation Rate: " + testName + ": " + ((float) (SPEED_TEST_ITERATIONS * expressions.size()) / (float) (end - start)) + " evaluations/second.");
163     }
164 }