1 /*------------------------------------------------------------------------------
2 Name: TestSubMultiSubscribe.java
3 Project: xmlBlaster.org
4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
5 ------------------------------------------------------------------------------*/
6 package org.xmlBlaster.test.qos;
7
8 import java.util.logging.Logger;
9 import java.util.logging.Level;
10 import org.xmlBlaster.util.Global;
11 import org.xmlBlaster.client.qos.ConnectQos;
12 import org.xmlBlaster.util.XmlBlasterException;
13 import org.xmlBlaster.util.def.Constants;
14 import org.xmlBlaster.client.I_XmlBlasterAccess;
15 import org.xmlBlaster.client.key.SubscribeKey;
16 import org.xmlBlaster.client.qos.SubscribeQos;
17 import org.xmlBlaster.client.key.UpdateKey;
18 import org.xmlBlaster.client.qos.UpdateQos;
19 import org.xmlBlaster.client.qos.EraseReturnQos;
20 import org.xmlBlaster.client.qos.SubscribeReturnQos;
21 import org.xmlBlaster.util.qos.AccessFilterQos;
22 import org.xmlBlaster.util.MsgUnit;
23
24 import org.xmlBlaster.test.Util;
25 import org.xmlBlaster.test.Msg;
26 import org.xmlBlaster.test.MsgInterceptor;
27
28 import junit.framework.*;
29
30
31 /**
32 * This client tests a subscribe() with multiSubscribe=false to avoid receiving
33 * duplicate updates from the same topic on multiple subscribes.
34 * <br />
35 * This client may be invoked multiple time on the same xmlBlaster server,
36 * as it cleans up everything after his tests are done.
37 * <p>
38 * Invoke examples:<br />
39 * <pre>
40 * java junit.textui.TestRunner org.xmlBlaster.test.qos.TestSubMultiSubscribe
41 * java junit.swingui.TestRunner -noloading org.xmlBlaster.test.qos.TestSubMultiSubscribe
42 * </pre>
43 * @see <a href="http://www.xmlblaster.org/xmlBlaster/doc/requirements/engine.qos.subscribe.multiSubscribe.html" target="others">interface subscribe requirement</a>
44 */
45 public class TestSubMultiSubscribe extends TestCase
46 {
47 private static String ME = "TestSubMultiSubscribe";
48 private final Global glob;
49 private static Logger log = Logger.getLogger(TestSubMultiSubscribe.class.getName());
50
51 private String subscribeId;
52 private final String myDomain = "myDomain";
53 private MsgInterceptor updateInterceptor;
54
55 private String publishOid = "HelloMessageMultiSub";
56 private I_XmlBlasterAccess connection;
57
58 /**
59 * Constructs the TestSubMultiSubscribe object.
60 * <p />
61 * @param testName The name used in the test suite
62 */
63 public TestSubMultiSubscribe(Global glob, String testName) {
64 super(testName);
65 this.glob = glob;
66
67 }
68
69 /**
70 * Sets up the fixture.
71 */
72 protected void setUp() {
73 this.subscribeId = null;
74 try {
75 connection = glob.getXmlBlasterAccess(); // Find orb
76 ConnectQos qos = new ConnectQos(glob);
77 this.updateInterceptor = new MsgInterceptor(glob,log, null);
78 connection.connect(qos, this.updateInterceptor);
79 }
80 catch (Exception e) {
81 log.severe("Login failed: " + e.toString());
82 e.printStackTrace();
83 fail("Login failed: " + e.toString());
84 }
85 }
86
87 /**
88 * Tears down the fixture.
89 * <p />
90 * cleaning up .... erase() the previous message OID and logout
91 */
92 protected void tearDown() {
93 if (this.connection != null) {
94 if (this.publishOid != null) {
95 String xmlKey = "<key oid='" + this.publishOid + "' queryType='EXACT'/>";
96 try {
97 EraseReturnQos[] arr = this.connection.erase(xmlKey, "<qos/>");
98 assertEquals("Erase", 1, arr.length);
99 } catch(XmlBlasterException e) { fail("Erase XmlBlasterException: " + e.getMessage()); }
100 }
101
102 this.connection.disconnect(null);
103 this.connection = null;
104 }
105 }
106
107 /**
108 * Subscribe multiple times to the same message with <multiSubscribe>false</multiSubscribe>
109 */
110 public void subscribe(String queryString, String queryType, AccessFilterQos aq, int numSub) {
111 if (log.isLoggable(Level.FINE)) log.fine("Subscribing ...");
112 try {
113 for(int i=0; i<numSub; i++) {
114 SubscribeKey key = new SubscribeKey(glob, queryString, queryType);
115 SubscribeQos qos = new SubscribeQos(glob);
116 qos.setMultiSubscribe(false);
117 if (aq != null) {
118 qos.addAccessFilter(aq);
119 }
120 SubscribeReturnQos ret = this.connection.subscribe(key.toXml(), qos.toXml());
121 log.info("Subscribe #" + i + " state=" + ret.getState() + " subscriptionId=" + ret.getSubscriptionId());
122 if (subscribeId == null) {
123 subscribeId = ret.getSubscriptionId();
124 assertEquals("", Constants.STATE_OK, ret.getState());
125 continue;
126 }
127 assertEquals("", subscribeId, ret.getSubscriptionId());
128 assertEquals("", Constants.STATE_WARN, ret.getState());
129 }
130 } catch(XmlBlasterException e) {
131 log.warning("XmlBlasterException: " + e.getMessage());
132 fail("subscribe - XmlBlasterException: " + e.getMessage());
133 }
134 }
135
136 /**
137 * Construct a message and publish it.
138 */
139 public void publish() {
140 if (log.isLoggable(Level.FINE)) log.fine("Publishing a message ...");
141
142 String xmlKey = "<key oid='" + publishOid + "' domain='"+myDomain+"'/>";
143 String senderContent = "Yeahh, i'm the new content";
144 String xmlQos = "<qos><clientProperty name='phone'>1200003</clientProperty></qos>";
145 try {
146 MsgUnit msgUnit = new MsgUnit(xmlKey, senderContent.getBytes(), xmlQos);
147 publishOid = connection.publish(msgUnit).getKeyOid();
148 log.info("Success: Publishing done, returned oid=" + publishOid);
149 } catch(XmlBlasterException e) {
150 log.warning("XmlBlasterException: " + e.getMessage());
151 fail("publish - XmlBlasterException: " + e.getMessage());
152 }
153
154 assertTrue("returned publishOid == null", publishOid != null);
155 assertTrue("returned publishOid", 0 != publishOid.length());
156 }
157
158 /**
159 * unSubscribe twice to same message.
160 */
161 public void unSubscribe() {
162 if (log.isLoggable(Level.FINE)) log.fine("unSubscribing ...");
163
164 String qos = "<qos/>";
165 try {
166 connection.unSubscribe("<key oid='" + subscribeId + "'/>", qos);
167 log.info("Success: unSubscribe 1 on " + subscribeId + " done");
168 } catch(XmlBlasterException e) {
169 log.warning("XmlBlasterException: " + e.getMessage());
170 fail("unSubscribe - XmlBlasterException: " + e.getMessage());
171 }
172 }
173
174 /**
175 * TEST: Construct a message and publish it,
176 * the first subscription shouldn't receive the message as local==false
177 */
178 public void testMultiSubscribeOid() {
179 log.info("testMultiSubscribeOid ...");
180
181 subscribe(publishOid, Constants.EXACT, null, 10); // there should be no Callback
182 assertEquals("", 0, this.updateInterceptor.waitOnUpdate(1000L, 0));
183
184 int numPub = 5;
185 for (int i=0; i<numPub; i++)
186 publish(); // We expect numPub updates only
187 assertEquals("", numPub, this.updateInterceptor.waitOnUpdate(1000L, publishOid, Constants.STATE_OK));
188 this.updateInterceptor.clear();
189
190 unSubscribe(); // One single unSubscribe should be enough
191
192 publish();
193 assertEquals("", 0, this.updateInterceptor.waitOnUpdate(1000L, 0));
194 }
195
196 /**
197 * TEST: Construct a message and publish it,
198 * the first subscription shouldn't receive the message as local==false
199 */
200 public void testMultiSubscribeXPath() {
201 log.info("testMultiSubscribeXPath ...");
202
203 subscribe("//key[@oid='"+publishOid+"']", Constants.XPATH, null, 10); // there should be no Callback
204 assertEquals("", 0, this.updateInterceptor.waitOnUpdate(1000L, 0));
205
206 int numPub = 5;
207 for (int i=0; i<numPub; i++)
208 publish(); // We expect numPub updates only
209 assertEquals("", numPub, this.updateInterceptor.waitOnUpdate(1000L, publishOid, Constants.STATE_OK));
210 this.updateInterceptor.clear();
211
212 unSubscribe(); // One single unSubscribe should be enough
213
214 publish();
215 assertEquals("", 0, this.updateInterceptor.waitOnUpdate(1000L, 0));
216 }
217
218 /**
219 * TEST: Change AccessFilter of SubscribeQos and test if reconfiguration works.
220 */
221 public void testSubscribeReconfigure() {
222 log.info("testSubscribeReconfigure ...");
223
224 final String filterType = "Sql92Filter";
225 final String filterVersion = "1.0";
226 String filterQuery = "phone LIKE '12%3'";
227
228 {
229 log.info("Matching accessFilter");
230 AccessFilterQos aq = new AccessFilterQos(glob, filterType, filterVersion, filterQuery);
231 subscribe("//key[@oid='"+publishOid+"']", Constants.XPATH, aq, 1);
232 assertEquals("", 0, this.updateInterceptor.waitOnUpdate(1000L, 0));
233
234 publish();
235 assertEquals("", 1, this.updateInterceptor.waitOnUpdate(1000L, publishOid, Constants.STATE_OK));
236 this.updateInterceptor.clear();
237 }
238
239 {
240 log.info("NOT matching accessFilter");
241 filterQuery = "phone LIKE '1XX%3'";
242 AccessFilterQos aq = new AccessFilterQos(glob, filterType, filterVersion, filterQuery);
243 subscribe("//key[@oid='"+publishOid+"']", Constants.XPATH, aq, 1);
244 assertEquals("", 0, this.updateInterceptor.waitOnUpdate(1000L, 0));
245
246 publish();
247 assertEquals("", 0, this.updateInterceptor.waitOnUpdate(1000L, 0));
248 this.updateInterceptor.clear();
249 }
250
251 {
252 log.info("Matching accessFilter");
253 filterQuery = "phone LIKE '12%3'";
254 AccessFilterQos aq = new AccessFilterQos(glob, filterType, filterVersion, filterQuery);
255 subscribe("//key[@oid='"+publishOid+"']", Constants.XPATH, aq, 1);
256 assertEquals("", 0, this.updateInterceptor.waitOnUpdate(1000L, 0));
257
258 publish();
259 assertEquals("", 1, this.updateInterceptor.waitOnUpdate(1000L, publishOid, Constants.STATE_OK));
260 this.updateInterceptor.clear();
261 }
262
263 unSubscribe(); // One single unSubscribe should be enough
264
265 publish();
266 assertEquals("", 0, this.updateInterceptor.waitOnUpdate(1000L, 0));
267 }
268
269 /**
270 * TEST: Construct a message and publish it,
271 * the first subscription shouldn't receive the message as local==false
272 */
273 public void testMultiSubscribeDomain() {
274 log.info("testMultiSubscribeDomain ...");
275
276 // For domain queries the topic must exist: Therefor publish one message to create it!
277 publish(); // We expect numPub updates only
278
279 subscribe(myDomain, Constants.DOMAIN, null, 10); // there should be no Callback
280 assertEquals("", 1, this.updateInterceptor.waitOnUpdate(1000L, 1));
281 this.updateInterceptor.clear();
282
283 int numPub = 5;
284 for (int i=0; i<numPub; i++)
285 publish(); // We expect numPub updates only
286 assertEquals("", numPub, this.updateInterceptor.waitOnUpdate(1000L, publishOid, Constants.STATE_OK));
287 this.updateInterceptor.clear();
288
289 unSubscribe(); // One single unSubscribe should be enough
290
291 publish();
292 assertEquals("", 0, this.updateInterceptor.waitOnUpdate(1000L, 0));
293 }
294
295 /**
296 * Method is used by TestRunner to load these tests
297 */
298 public static Test suite() {
299 TestSuite suite= new TestSuite();
300 suite.addTest(new TestSubMultiSubscribe(new Global(), "testMultiSubscribeOid"));
301 suite.addTest(new TestSubMultiSubscribe(new Global(), "testMultiSubscribeXPath"));
302 suite.addTest(new TestSubMultiSubscribe(new Global(), "testSubscribeReconfigure"));
303 suite.addTest(new TestSubMultiSubscribe(new Global(), "testMultiSubscribeDomain"));
304 return suite;
305 }
306
307 /**
308 * Invoke: java org.xmlBlaster.test.qos.TestSubMultiSubscribe
309 * @deprecated Use the TestRunner from the testsuite to run it:<p />
310 * <pre> java -Djava.compiler= junit.textui.TestRunner org.xmlBlaster.test.qos.TestSubMultiSubscribe</pre>
311 */
312 public static void main(String args[]) {
313 Global glob = new Global();
314 if (glob.init(args) != 0) {
315 System.err.println("Init failed");
316 System.exit(1);
317 }
318 TestSubMultiSubscribe testSub = new TestSubMultiSubscribe(glob, "TestSubMultiSubscribe");
319 testSub.setUp();
320 //testSub.testMultiSubscribeOid();
321 //testSub.testMultiSubscribeXPath();
322 testSub.testSubscribeReconfigure();
323 //testSub.testMultiSubscribeDomain();
324 testSub.tearDown();
325 }
326 }
syntax highlighted by Code2HTML, v. 0.9.1