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