1 /*-----------------------------------------------------------------------------
2 Name: TestLogin.cpp
3 Project: xmlBlaster.org
4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
5 Comment: Login/logout test for xmlBlaster
6 Version: $Id: TestLogin.cpp 14955 2006-03-20 12:40:31Z goetzger $
7 -----------------------------------------------------------------------------*/
8
9 /**
10 * This client does test login and logout.<br />
11 * login/logout combinations are checked with subscribe()/publish() calls
12 * <p />
13 * This client may be invoked multiple time on the same xmlBlaster server,
14 * as it cleans up everything after his tests are done.
15 * <p>
16 * Invoke examples:<br />
17 * <pre>
18 * java -jar lib/xmlBlaster.jar (Server)
19 *
20 * TestLogin (Client)
21 * </pre>
22 */
23
24 #include <string>
25 #include <client/protocol/corba/CorbaConnection.h>
26 #include <client/LoginQosWrapper.h>
27 #include <util/StopWatch.h>
28 #include <util/Global.h>
29 #include <client/I_Callback.h>
30 #include <iostream>
31
32 using namespace std;
33 using namespace org::xmlBlaster::util;
34 using namespace org::xmlBlaster::client::protocol::corba;
35
36 namespace org { namespace xmlBlaster {
37
38 class TestLogin : public virtual client::I_Callback {
39
40 private:
41 string me() {
42 return "Tim";
43 }
44
45 string publishReturnQos, secondOid_;
46 string oid_;
47 string senderName_, secondName_;
48 string senderContent_;
49 CorbaConnection *senderConnection_, *secondConnection_;
50 serverIdl::MessageUnit* msgUnit_; // a message to play with
51
52 int numReceived_; // error checking
53 string contentMime_;
54 string contentMimeExtended_;
55 util::StopWatch stopWatch_;
56 Global& global_;
57 util::I_Log& log_;
58
59 public:
60 /**
61 * Constructs the TestLogin object.
62 * <p />
63 * @param testName The name used in the test suite
64 * @param loginName The name to login to the xmlBlaster
65 * @param secondName The name to login to the xmlBlaster again
66 */
67 TestLogin(Global& global, const string &senderName,
68 const string &secondName) : stopWatch_(), global_(global),
69 log_(global.getLog("test"))
70 {
71 senderName_ = senderName;
72 secondName_ = secondName;
73 publishReturnQos = "";
74 secondOid_ = "SecondOid";
75 oid_ = "TestLogin";
76 numReceived_ = 0;
77 contentMime_ = "text/plain";
78 contentMimeExtended_ = "1.0";
79 msgUnit_ = 0;
80 senderConnection_ = secondConnection_ = 0;
81 }
82
83 ~TestLogin() {
84 delete senderConnection_;
85 delete secondConnection_;
86 delete msgUnit_;
87 }
88
89
90 /**
91 * This is the callback method (I_Callback) invoked from CorbaConnection
92 * informing the client in an asynchronous mode about a new message.
93 * <p />
94 * The raw CORBA-BlasterCallback.update() is unpacked and for each arrived
95 * message this update is called.
96 *
97 * @param sessionId The sessionId to authenticate the callback
98 * This sessionId was passed on subscription
99 * we can use it to decide if we trust this update()
100 * @param updateKey The arrived key
101 * @param content The arrived message content
102 * @param qos Quality of Service of the MessageUnit
103 * @return The status string
104 */
105 string update(const string &/*sessionId*/,
106 UpdateKey &/*updateKey*/,
107 const unsigned char * /*content*/, long /*contentSize*/,
108 UpdateQos &/*updateQos*/) {
109 if (log_.call()) log_.call(me(), "Receiving update of a message ...");
110 numReceived_++;
111 return "<qos><state id='OK'/></qos>";
112 }
113
114 /**
115 * Sets up the fixture. <p />
116 * Connect to xmlBlaster and login
117 */
118
119 void setUp(int args, char *argc[]) {
120 for (int ii=0; ii<args; ii++) {
121 if (strcmp(argc[ii], "-?")==0 || strcmp(argc[ii], "-h")==0 || strcmp(argc[ii], "-help")==0) {
122 usage();
123 exit(0);
124 }
125 }
126 try {
127 if (senderConnection_) delete senderConnection_;
128 senderConnection_ = new CorbaConnection(global_); // Find orb
129 string passwd = "secret";
130
131 LoginQosWrapper qosWrapper;
132 senderConnection_->login(senderName_, passwd, qosWrapper, this);
133
134 // Login to xmlBlaster
135 if (secondConnection_) delete secondConnection_;
136 secondConnection_ = new CorbaConnection(global_); // Find orb
137 secondConnection_->login(secondName_, passwd, qosWrapper, this);
138
139 // a sample message unit
140 string xmlKey = "<key oid='" + oid_ + "' contentMime='" +
141 contentMime_ + "' contentMimeExtended='" +
142 contentMimeExtended_ + "'>\n" +
143 " <TestLogin-AGENT> </TestLogin-AGENT> </key>";
144 senderContent_ = "Some content";
145 if (msgUnit_) delete msgUnit_;
146 msgUnit_ = new serverIdl::MessageUnit();
147 msgUnit_->xmlKey = xmlKey.c_str();
148 msgUnit_->content =
149 serverIdl::ContentType(senderContent_.length(),
150 senderContent_.length(),
151 (CORBA::Octet*)senderContent_.c_str());
152 }
153 catch (CORBA::Exception &e) {
154 log_.error(me(), to_string(e));
155 cerr << to_string(e);
156 usage();
157 }
158 }
159
160
161 /**
162 * Tears down the fixture.
163 * <p />
164 * cleaning up .... erase() the previous message OID and logout
165 */
166 void tearDown() {
167 string xmlKey = "<key oid='" + oid_ + "' queryType='EXACT'>\n</key>";
168 string qos = "<qos></qos>";
169 vector<string> strArr;
170 try {
171 strArr = senderConnection_->erase(xmlKey.c_str(), qos.c_str());
172 }
173 catch(serverIdl::XmlBlasterException &e) {
174 string msg = me() + "-tearDown()";
175 string txt = string("XmlBlasterException in erase(): ") + string(e.errorCodeStr) + string(": ") + string(e.message);
176 log_.error(msg, txt);
177 }
178 if (strArr.size() != 1) {
179 string txt = "Erased ";
180 txt += strArr.size() + " messages:";
181 log_.error(me(), txt);
182 }
183
184 xmlKey = "<key oid='" + secondOid_ + "' queryType='EXACT'>\n</key>";
185 qos = "<qos></qos>";
186 try {
187 strArr = senderConnection_->erase(xmlKey.c_str(), qos.c_str());
188 }
189 catch(serverIdl::XmlBlasterException &e) {
190
191 string msg = me() + "-tearDown()";
192 string txt = string("XmlBlasterException in erase(): ") + string(e.errorCodeStr) + string(": ") + string(e.message);
193 log_.error(msg, txt);
194 }
195 if (strArr.size() != 1) {
196 string txt = "Erased ";
197 txt += "many messages"; // change many with the number!!!!
198 log_.error(me(), txt);
199 }
200 senderConnection_->logout();
201 secondConnection_->logout();
202 }
203
204
205 public:
206 /**
207 * TEST: Subscribe to messages with XPATH.
208 * <p />
209 * The returned subscribeOid is checked
210 */
211 void testSubscribeXPath() {
212 if (log_.trace()) log_.trace(me(),"Subscribing using XPath syntax ...");
213
214 string xmlKey = "<key oid='' queryType='XPATH'>\n";
215 xmlKey += " //TestLogin-AGENT </key>";
216 string qos = "<qos></qos>";
217 numReceived_ = 0;
218 string subscribeOid = "";
219 try {
220 subscribeOid =
221 senderConnection_->subscribe(xmlKey.c_str(), qos.c_str());
222 string txt = "Success: Subscribe on ";
223 txt += subscribeOid + " done";
224 log_.info(me(), txt);
225 }
226 catch(serverIdl::XmlBlasterException &e) {
227 log_.warn(me() + "-testSubscribeXPath", string("XmlBlasterException: ") + string(e.errorCodeStr) + ": " + string(e.message));
228 string txt = string("subscribe - XmlBlasterException: ") + string(e.errorCodeStr) + ": " + string(e.message);
229 cerr << txt << endl;
230 assert(0);
231 }
232 if (subscribeOid == "") {
233 cerr << "returned null subscribeOid" << endl;
234 assert(0);
235 }
236 if (subscribeOid.length() < 1) {
237 cerr << "returned subscribeOid is empty" << endl;
238 assert(0);
239 }
240 }
241
242
243 /**
244 * TEST: Construct a message and publish it.
245 * <p />
246 * The returned publishOid is checked
247 * @param ptp Use the Point to Point style
248 */
249 void testPublish(bool ptp) {
250 if (log_.trace()) log_.trace(me(), "Publishing a message ...");
251
252 numReceived_ = 0;
253 string qos = "<qos></qos>";
254 if (ptp)
255 qos = "<qos>\n<destination>\n" + secondName_ +
256 "\n</destination>\n</qos>";
257 try {
258 msgUnit_->qos = qos.c_str();
259 publishReturnQos = senderConnection_->publish(*msgUnit_);
260 if (publishReturnQos.find(oid_) == string::npos) {
261 cerr << "oid is different" << endl;
262 assert(0);
263 }
264
265 }
266 catch(serverIdl::XmlBlasterException &e) {
267 log_.warn(me()+"-testPublish",
268 string("XmlBlasterException: ") + string(e.errorCodeStr) + ": " + string(e.message));
269 string msg = string("publish - XmlBlasterException: ") + string(e.errorCodeStr) + ": " + string(e.message);
270 cerr << msg << endl;
271 assert(0);
272 }
273
274 if (publishReturnQos == "") {
275 cerr << "returned publishOid == null" << endl;
276 assert(0);
277 }
278 if (publishReturnQos.length() < 1) {
279 cerr << "returned publishOid is zero in length";
280 assert(0);
281 }
282 }
283
284
285 /**
286 * TEST: Construct a message and publish it,<br />
287 * the previous XPath subscription should match and send an update.
288 */
289 void testLoginLogout(int args=0, char *argc[]=0) {
290 // test ordinary login
291 numReceived_ = 0;
292 testSubscribeXPath();
293 testPublish(false);
294 waitOnUpdate(1000L, 1); // message arrived?
295
296 // login again, without logout
297 setUp(args, argc);
298 testPublish(true); // sending directly PtP to 'receiver'
299 waitOnUpdate(1000L, 1); // message arrived?
300
301 // login again, without logout
302 setUp(args, argc);
303 testPublish(false);
304 stopWatch_.wait(1000L);
305 numReceived_ = 0;
306 testSubscribeXPath();
307 waitOnUpdate(1000L, 1);
308 // test publish from other user
309 numReceived_ = 0;
310 try {
311 // a sample message unit
312 string xmlKey = "<key oid='" + secondOid_ + "' contentMime='" +
313 contentMime_ + "' contentMimeExtended='" + contentMimeExtended_
314 + "'>\n" + " <TestLogin-AGENT>" + " </TestLogin-AGENT>"
315 + "</key>";
316 string content = "Some content";
317
318 serverIdl::MessageUnit secondMsg;
319 secondMsg.xmlKey = xmlKey.c_str();
320 secondMsg.content =
321 serverIdl::ContentType(content.length(),
322 content.length(),
323 (CORBA::Octet*)content.c_str());
324
325 secondMsg.qos = "<qos></qos>";
326 publishReturnQos = /*secondBlaster_*/
327 /*second*/ senderConnection_->publish(secondMsg);
328 }
329 catch(serverIdl::XmlBlasterException &e) {
330 log_.warn(me()+"-secondPublish", string("XmlBlasterException: ") + string(e.errorCodeStr) + ": " + string(e.message));
331 string msg = string("second - publish - XmlBlasterException: ") + string(e.errorCodeStr) + ": " + string(e.message);
332 cerr << msg << endl;
333 assert(0);
334 }
335 waitOnUpdate(1000L, 1); // message arrived?
336
337 if (publishReturnQos == "") {
338 cerr << "returned publishOid == null" << endl;
339 assert(0);
340 }
341 if (publishReturnQos.length() == 0) {
342 cerr << "returned publishOid" << endl;
343 assert(0);
344 }
345 // test logout with following subscribe()
346 senderConnection_->logout();
347 try {
348 msgUnit_->qos = "<qos></qos>";
349 publishReturnQos = /*xmlBlaster_*/
350 senderConnection_->publish(*msgUnit_);
351 cerr << "Didn't expect successful subscribe after logout";
352 assert(0);
353 }
354 catch(serverIdl::XmlBlasterException &e) {
355 log_.info(me(), string("Success: ") + string(e.errorCodeStr) + ": " + string(e.message));
356 }
357
358 stopWatch_.wait(1000L); // wait a second
359 if (numReceived_ != 0) {
360 cerr << "Didn't expect an update" << endl;
361 assert(0);
362 }
363
364 // login again
365 setUp(args, argc);
366
367 }
368
369
370 /**
371 * Little helper, waits until the wanted number of messages are arrived
372 * or returns when the given timeout occurs.
373 * <p />
374 * @param timeout in milliseconds
375 * @param numWait how many messages to wait
376 */
377 private:
378 void waitOnUpdate(long timeout, int numWait) {
379 long pollingInterval = 50L; // check every 0.05 seconds
380 if (timeout < 50L) pollingInterval = timeout / 10L;
381 long sum = 0L;
382 // check if too few are arriving
383 while (numReceived_ < numWait) {
384 stopWatch_.wait(pollingInterval);
385 sum += pollingInterval;
386 senderConnection_->orbPerformWork();
387 secondConnection_->orbPerformWork();
388 if (sum >= timeout) {
389 cerr << "Timeout of " << timeout << " occured without updatetimeout: " << timeout << " " << numWait << endl;
390 assert(0);
391 }
392 }
393
394 // check if too many are arriving
395 stopWatch_.wait(timeout);
396 if (numWait != numReceived_) {
397 cerr << "Wrong number of messages arrived ";
398 cerr << "expected: " << numWait << " received: ";
399 cerr << numReceived_ << endl;
400 assert(0);
401 }
402 numReceived_ = 0;
403 }
404 void usage()
405 {
406 Global& glob = Global::getInstance();
407 glob.initialize();
408 util::I_Log& log_ = glob.getLog("test");
409 log_.plain(me(), "----------------------------------------------------------");
410 log_.plain(me(), "Testing C++/CORBA access to xmlBlaster");
411 log_.plain(me(), "Usage:");
412 CorbaConnection::usage();
413 log_.usage();
414 log_.plain(me(), "Example:");
415 log_.plain(me(), " TestLogin -dispatch/connection/plugin/ior/iorFile /tmp/ior.dat -trace true");
416 log_.plain(me(), "----------------------------------------------------------");
417 }
418 };
419
420 }} // namespace
421
422
423
424
425
426 int main(int args, char *argc[]) {
427 // Init the XML platform
428 org::xmlBlaster::util::Object_Lifetime_Manager::init();
429 Global& glob = Global::getInstance();
430 glob.initialize(args, argc);
431 org::xmlBlaster::TestLogin *testSub = new org::xmlBlaster::TestLogin(glob, "Tim", "Joe");
432 testSub->setUp(args, argc);
433 testSub->testLoginLogout();
434 testSub->tearDown();
435 delete testSub;
436 // .exit(TestLogin.ME, "Good bye");
437 org::xmlBlaster::util::Object_Lifetime_Manager::fini();
438 return 0;
439 }
syntax highlighted by Code2HTML, v. 0.9.1