package org.jacorb.test.notification; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import java.util.Random; import org.jacorb.notification.IContainer; import org.jacorb.notification.TypedEventMessage; import org.jacorb.notification.filter.DefaultFilterFactoryDelegate; import org.jacorb.notification.filter.FilterFactoryImpl; import org.jacorb.test.notification.common.NotificationTestCase; import org.jacorb.test.notification.common.NotificationTestUtils; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.omg.CORBA.Any; import org.omg.CosNotification.EventType; import org.omg.CosNotification.Property; import org.omg.CosNotifyFilter.ConstraintExp; import org.omg.CosNotifyFilter.ConstraintInfo; import org.omg.CosNotifyFilter.Filter; import org.omg.CosNotifyFilter.FilterFactory; import org.omg.CosNotifyFilter.FilterFactoryHelper; import org.picocontainer.MutablePicoContainer; /** * @author Alphonse Bendt * @author John Farrell */ public class FilterTest extends NotificationTestCase { static final Random random_ = new Random(System.currentTimeMillis()); //////////////////////////////////////// FilterFactory factory_; Filter filter_; Any testPerson_; NotificationTestUtils testUtils_; FilterFactoryImpl factoryServant_; //////////////////////////////////////// //////////////////////////////////////// @Before public void setUp() throws Exception { IContainer container = new IContainer() { public MutablePicoContainer getContainer() { return getPicoContainer(); } public void destroy() { // no operation } }; factoryServant_ = new FilterFactoryImpl(getORB(), getPOA(), getConfiguration(), new DefaultFilterFactoryDelegate(container, getConfiguration())); factoryServant_.activate(); factory_ = FilterFactoryHelper.narrow(factoryServant_.activate()); testUtils_ = new NotificationTestUtils(getORB()); testPerson_ = testUtils_.getTestPersonAny(); filter_ = factory_.create_filter("EXTENDED_TCL"); } public void tearDownTest() throws Exception { factoryServant_.dispose(); } @Test public void testFalseMatch() throws Exception { ConstraintExp[] _constraintExp = new ConstraintExp[1]; EventType[] _eventType = new EventType[1]; _eventType[0] = new EventType("*", "*"); String _expression = "FALSE"; _constraintExp[0] = new ConstraintExp(_eventType, _expression); filter_.add_constraints(_constraintExp); assertFalse(filter_.match(testPerson_)); } /** * create remote filter object and invoke match operation on it */ @Test public void testMatch() throws Exception { ConstraintExp[] _constraintExp = new ConstraintExp[1]; EventType[] _eventType = new EventType[1]; _eventType[0] = new EventType("*", "*"); _constraintExp[0] = new ConstraintExp(_eventType, "$.first_name == 'firstname'"); filter_.add_constraints(_constraintExp); // this should match assertTrue(filter_.match(testPerson_)); } @Test public void testAccessNonExistingMember() throws Exception { EventType[] _eventType = new EventType[] { new EventType("*", "*") }; ConstraintExp[] _constraintExp = new ConstraintExp[] { new ConstraintExp(_eventType, "$not_exist == 3"), new ConstraintExp(_eventType, "TRUE"), }; filter_.add_constraints(_constraintExp); assertTrue(filter_.match(testPerson_)); } @Test public void testMatchEmptyFilter() throws Exception { assertTrue(!filter_.match(testPerson_)); } @Test public void testMatch_EventTypes_IsEmpty() throws Exception { ConstraintExp[] _constraintExp = new ConstraintExp[1]; EventType[] _eventType = new EventType[0]; _constraintExp[0] = new ConstraintExp(_eventType, "$.first_name == 'firstname'"); filter_.add_constraints(_constraintExp); // this should match assertTrue(filter_.match(testPerson_)); } @Test public void testMatch_EventType_IsEmptyString() throws Exception { ConstraintExp[] _constraintExp = new ConstraintExp[1]; EventType[] _eventType = new EventType[] { new EventType("", "") }; _constraintExp[0] = new ConstraintExp(_eventType, "$.first_name == 'firstname'"); filter_.add_constraints(_constraintExp); // this should match assertTrue(filter_.match(testPerson_)); } @Test public void testMatch_FilterString_IsEmpty() throws Exception { ConstraintExp[] _constraintExp = new ConstraintExp[1]; EventType[] _eventType = new EventType[] { new EventType("*", "*") }; _constraintExp[0] = new ConstraintExp(_eventType, ""); filter_.add_constraints(_constraintExp); // this should match assertTrue(filter_.match(testPerson_)); } @Test public void testMatchModify() throws Exception { ConstraintExp[] _constraintExp = new ConstraintExp[1]; EventType[] _eventType = new EventType[1]; _eventType[0] = new EventType("*", "*"); _constraintExp[0] = new ConstraintExp(_eventType, "$.first_name == 'something'"); ConstraintInfo[] _info = filter_.add_constraints(_constraintExp); // oops wrong assertTrue(!filter_.match(testPerson_)); // modify the filter _info[0].constraint_expression.constraint_expr = "$.first_name == 'firstname'"; filter_.modify_constraints(new int[0], _info); // this one should match assertTrue(filter_.match(testPerson_)); } @Test public void testConstraintGrammar() throws Exception { assertEquals("EXTENDED_TCL", filter_.constraint_grammar()); } @Test public void testAddConstraints() throws Exception { ConstraintExp[] _constraintExp = new ConstraintExp[1]; EventType[] _eventType = new EventType[1]; _eventType[0] = new EventType("domain", "name"); String _expression = "1 + 1"; _constraintExp[0] = new ConstraintExp(_eventType, _expression); ConstraintInfo[] _info = filter_.add_constraints(_constraintExp); assertTrue(_info.length == 1); assertTrue(_info[0].constraint_expression.event_types.length == 1); assertEquals(_expression, _info[0].constraint_expression.constraint_expr); assertEquals(_eventType[0].domain_name, _info[0].constraint_expression.event_types[0].domain_name); assertEquals(_eventType[0].type_name, _info[0].constraint_expression.event_types[0].type_name); } @Test public void testDeleteConstraints() throws Exception { ConstraintExp[] _constraintExp = new ConstraintExp[2]; EventType[] _eventType = new EventType[1]; _eventType[0] = new EventType("domain", "name"); String _expression = "1 + 1"; String _expression2 = "2 + 2"; _constraintExp[0] = new ConstraintExp(_eventType, _expression); _eventType[0] = new EventType("domain2", "name"); _constraintExp[1] = new ConstraintExp(_eventType, _expression2); ConstraintInfo[] _info = filter_.add_constraints(_constraintExp); assertTrue(_info.length == 2); assertTrue(_info[0].constraint_expression.event_types.length == 1); assertTrue(_info[1].constraint_expression.event_types.length == 1); int[] _delete = { _info[0].constraint_id }; filter_.modify_constraints(_delete, new ConstraintInfo[0]); ConstraintInfo[] _info2 = filter_.get_all_constraints(); assertTrue(_info2.length == 1); assertEquals(_info[1].constraint_id, _info2[0].constraint_id); assertEquals(_info[1].constraint_expression.constraint_expr, _info2[0].constraint_expression.constraint_expr); } /** * multithreaded test. Some Writers modify the Constraints of a Filter. Some Readers constantly * access the Filter. They should always get consistent data. */ @Test public void testModifyConcurrent() throws Exception { FilterRead _fr1 = new FilterRead(filter_, 100); FilterRead _fr2 = new FilterRead(filter_, 100); FilterRead _fr3 = new FilterRead(filter_, 100); FilterRead _fr4 = new FilterRead(filter_, 100); FilterModify _mod1 = new FilterModify(filter_, "true", 50); FilterModify _mod2 = new FilterModify(filter_, "false", 50); _fr1.start(); _fr2.start(); _fr3.start(); _fr4.start(); _mod1.start(); _mod2.start(); _fr1.join(); _fr2.join(); _fr3.join(); _fr4.join(); _mod1.join(); _mod2.join(); } @Test public void testMatchTyped() throws Exception { Property[] _props = new Property[] { new Property("operation", toAny("operationName")), new Property("value1", toAny(100)), new Property("value2", toAny(200)) }; ConstraintExp[] _constraintExp = new ConstraintExp[1]; EventType[] _eventType = new EventType[1]; _eventType[0] = new EventType("", "%TYPED"); String _expression = "$value1 > 50 and $value2 > 50"; _constraintExp[0] = new ConstraintExp(_eventType, _expression); filter_.add_constraints(_constraintExp); assertTrue(filter_.match_typed(_props)); } @Test public void testFilterTypedMessageEvent() throws Exception { TypedEventMessage _mesg = new TypedEventMessage(); String _domainName = "IDL:org.jacorb/org/jacorb/test/filter/Bla:1.0"; String _operationName = "blaOperation"; _mesg.setTypedEvent(_domainName, _operationName, new Property[] { new Property("param1", toAny("value1")), new Property("param2", toAny(100)) }); assertFalse(_mesg.match(filter_)); ConstraintExp[] _constraintExp = new ConstraintExp[1]; EventType[] _eventType = new EventType[1]; _eventType[0] = new EventType("", "%TYPED"); String _expression = "$event_type.domain_name == '" + _domainName + "' and $event_type.type_name == '" + _operationName + "' and $param2 > 50"; _constraintExp[0] = new ConstraintExp(_eventType, _expression); filter_.add_constraints(_constraintExp); assertTrue(_mesg.match(filter_)); } } ////////////////////////////////////////////////// class FilterRead extends Thread { Filter filter_; int iterations_; boolean lengthOk_ = true; boolean countOk_ = true; static int sCounter = 0; FilterRead() { super(); setDaemon(true); } FilterRead(Filter filter, int iterations) { super(); filter_ = filter; iterations_ = iterations; } public void run() { try { sleep(FilterTest.random_.nextInt(1000)); } catch (InterruptedException e) { // ignored } CounterMap _counter = new CounterMap(); for (int x = 0; x < iterations_; x++) { // constraint count should always be a multiple of 10 ConstraintInfo[] _info = filter_.get_all_constraints(); Assert.assertTrue(_info.length % 10 == 0); for (int y = 0; y < _info.length; y++) { _counter.incr(_info[y].constraint_expression.constraint_expr); } Iterator _i = _counter.allCounters(); // constraint type count should always be a multiple of 10 while (_i.hasNext()) { Counter _c = (Counter) _i.next(); Assert.assertTrue(_c.value() % 10 == 0); } _counter.reset(); try { Thread.sleep(FilterTest.random_.nextInt(110)); } catch (InterruptedException ie) { // ignored } } } } //////////////////////////////////////// class CounterMap { Map counters_ = new Hashtable(); public void incr(Object t) { Counter _c = (Counter) counters_.get(t); if (_c == null) { _c = new Counter(); counters_.put(t, _c); } _c.incr(); } public int value(Object t) { Counter _c = (Counter) counters_.get(t); if (_c == null) { return 0; } return _c.value(); } public void reset() { counters_.clear(); } Iterator allCounters() { return counters_.values().iterator(); } } //////////////////////////////////////// class Counter { int counter_ = 0; public void incr() { ++counter_; } public int value() { return counter_; } } class FilterModify extends Thread { Filter filter_; int iterations_ = 100; ConstraintExp[] constraintExp_; FilterModify(Filter filter, String expression, int iterations) { super(); setDaemon(true); filter_ = filter; iterations_ = iterations; constraintExp_ = new ConstraintExp[10]; EventType[] _eventType = new EventType[1]; _eventType[0] = new EventType("domain", expression); for (int x = 0; x < constraintExp_.length; x++) { constraintExp_[x] = new ConstraintExp(_eventType, expression); } } public void run() { try { sleep(FilterTest.random_.nextInt(1000)); } catch (InterruptedException e) { // ignored } ConstraintInfo[] _info = null; for (int x = 0; x < iterations_; x++) { try { if (_info != null) { int[] _toBeDeleted = new int[_info.length]; for (int y = 0; y < _info.length; y++) { _toBeDeleted[y] = _info[y].constraint_id; } // delete the constraints this thread added earlier filter_.modify_constraints(_toBeDeleted, new ConstraintInfo[0]); try { Thread.sleep(FilterTest.random_.nextInt(20)); } catch (InterruptedException ie) { // ignore } } // add some constraints _info = filter_.add_constraints(constraintExp_); try { Thread.sleep(FilterTest.random_.nextInt(200)); } catch (InterruptedException ie) { // ignore } } catch (Exception e) { e.printStackTrace(); Assert.fail(); } } } }