Home | History | Annotate | Download | only in xmpp
      1 /*
      2  *  Copyright 2011 The WebRTC Project Authors. All rights reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include <string>
     12 
     13 #include "webrtc/libjingle/xmllite/qname.h"
     14 #include "webrtc/libjingle/xmllite/xmlelement.h"
     15 #include "webrtc/libjingle/xmpp/constants.h"
     16 #include "webrtc/libjingle/xmpp/fakexmppclient.h"
     17 #include "webrtc/libjingle/xmpp/iqtask.h"
     18 #include "webrtc/libjingle/xmpp/jid.h"
     19 #include "webrtc/libjingle/xmpp/pubsubtasks.h"
     20 #include "webrtc/base/faketaskrunner.h"
     21 #include "webrtc/base/gunit.h"
     22 #include "webrtc/base/sigslot.h"
     23 
     24 struct HandledPubSubItem {
     25   std::string itemid;
     26   std::string payload;
     27 };
     28 
     29 class TestPubSubTasksListener : public sigslot::has_slots<> {
     30  public:
     31   TestPubSubTasksListener() : result_count(0), error_count(0) {}
     32 
     33   void OnReceiveUpdate(buzz::PubSubReceiveTask* task,
     34                        const std::vector<buzz::PubSubItem>& items) {
     35     OnItems(items);
     36   }
     37 
     38   void OnRequestResult(buzz::PubSubRequestTask* task,
     39                        const std::vector<buzz::PubSubItem>& items) {
     40     OnItems(items);
     41   }
     42 
     43   void OnItems(const std::vector<buzz::PubSubItem>& items) {
     44     for (std::vector<buzz::PubSubItem>::const_iterator item = items.begin();
     45          item != items.end(); ++item) {
     46       HandledPubSubItem handled_item;
     47       handled_item.itemid = item->itemid;
     48       if (item->elem->FirstElement() != NULL) {
     49         handled_item.payload = item->elem->FirstElement()->Str();
     50       }
     51       this->items.push_back(handled_item);
     52     }
     53   }
     54 
     55   void OnPublishResult(buzz::PubSubPublishTask* task) {
     56     ++result_count;
     57   }
     58 
     59   void OnRetractResult(buzz::PubSubRetractTask* task) {
     60     ++result_count;
     61   }
     62 
     63   void OnError(buzz::IqTask* task, const buzz::XmlElement* stanza) {
     64     ++error_count;
     65   }
     66 
     67   std::vector<HandledPubSubItem> items;
     68   int result_count;
     69   int error_count;
     70 };
     71 
     72 class PubSubTasksTest : public testing::Test {
     73  public:
     74   PubSubTasksTest() :
     75       pubsubjid("room (at) domain.com"),
     76       node("topic"),
     77       itemid("key") {
     78     runner.reset(new rtc::FakeTaskRunner());
     79     client = new buzz::FakeXmppClient(runner.get());
     80     listener.reset(new TestPubSubTasksListener());
     81   }
     82 
     83   rtc::scoped_ptr<rtc::FakeTaskRunner> runner;
     84   // Client deleted by deleting runner.
     85   buzz::FakeXmppClient* client;
     86   rtc::scoped_ptr<TestPubSubTasksListener> listener;
     87   buzz::Jid pubsubjid;
     88   std::string node;
     89   std::string itemid;
     90 };
     91 
     92 TEST_F(PubSubTasksTest, TestRequest) {
     93   buzz::PubSubRequestTask* task =
     94       new buzz::PubSubRequestTask(client, pubsubjid, node);
     95   task->SignalResult.connect(
     96       listener.get(), &TestPubSubTasksListener::OnRequestResult);
     97   task->Start();
     98 
     99   std::string expected_iq =
    100       "<cli:iq type=\"get\" to=\"room (at) domain.com\" id=\"0\" "
    101         "xmlns:cli=\"jabber:client\">"
    102         "<pub:pubsub xmlns:pub=\"http://jabber.org/protocol/pubsub\">"
    103           "<pub:items node=\"topic\"/>"
    104         "</pub:pubsub>"
    105       "</cli:iq>";
    106 
    107   ASSERT_EQ(1U, client->sent_stanzas().size());
    108   EXPECT_EQ(expected_iq, client->sent_stanzas()[0]->Str());
    109 
    110   std::string result_iq =
    111       "<iq xmlns='jabber:client' id='0' type='result' from='room (at) domain.com'>"
    112       "  <pubsub xmlns='http://jabber.org/protocol/pubsub'>"
    113       "    <items node='topic'>"
    114       "      <item id='key0'>"
    115       "        <value0/>"
    116       "      </item>"
    117       "      <item id='key1'>"
    118       "        <value1/>"
    119       "      </item>"
    120       "    </items>"
    121       "  </pubsub>"
    122       "</iq>";
    123 
    124   client->HandleStanza(buzz::XmlElement::ForStr(result_iq));
    125 
    126   ASSERT_EQ(2U, listener->items.size());
    127   EXPECT_EQ("key0", listener->items[0].itemid);
    128   EXPECT_EQ("<pub:value0 xmlns:pub=\"http://jabber.org/protocol/pubsub\"/>",
    129             listener->items[0].payload);
    130   EXPECT_EQ("key1", listener->items[1].itemid);
    131   EXPECT_EQ("<pub:value1 xmlns:pub=\"http://jabber.org/protocol/pubsub\"/>",
    132             listener->items[1].payload);
    133 }
    134 
    135 TEST_F(PubSubTasksTest, TestRequestError) {
    136   std::string result_iq =
    137       "<iq xmlns='jabber:client' id='0' type='error' from='room (at) domain.com'>"
    138       "  <error type='auth'>"
    139       "    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
    140       "  </error>"
    141       "</iq>";
    142 
    143   buzz::PubSubRequestTask* task =
    144       new buzz::PubSubRequestTask(client, pubsubjid, node);
    145   task->SignalResult.connect(
    146       listener.get(), &TestPubSubTasksListener::OnRequestResult);
    147   task->SignalError.connect(
    148       listener.get(), &TestPubSubTasksListener::OnError);
    149   task->Start();
    150   client->HandleStanza(buzz::XmlElement::ForStr(result_iq));
    151 
    152   EXPECT_EQ(0, listener->result_count);
    153   EXPECT_EQ(1, listener->error_count);
    154 }
    155 
    156 TEST_F(PubSubTasksTest, TestReceive) {
    157   std::string items_message =
    158       "<message xmlns='jabber:client' from='room (at) domain.com'>"
    159       "  <event xmlns='http://jabber.org/protocol/pubsub#event'>"
    160       "    <items node='topic'>"
    161       "      <item id='key0'>"
    162       "        <value0/>"
    163       "      </item>"
    164       "      <item id='key1'>"
    165       "        <value1/>"
    166       "      </item>"
    167       "    </items>"
    168       "  </event>"
    169       "</message>";
    170 
    171   buzz::PubSubReceiveTask* task =
    172       new buzz::PubSubReceiveTask(client, pubsubjid, node);
    173   task->SignalUpdate.connect(
    174       listener.get(), &TestPubSubTasksListener::OnReceiveUpdate);
    175   task->Start();
    176   client->HandleStanza(buzz::XmlElement::ForStr(items_message));
    177 
    178   ASSERT_EQ(2U, listener->items.size());
    179   EXPECT_EQ("key0", listener->items[0].itemid);
    180   EXPECT_EQ(
    181       "<eve:value0 xmlns:eve=\"http://jabber.org/protocol/pubsub#event\"/>",
    182       listener->items[0].payload);
    183   EXPECT_EQ("key1", listener->items[1].itemid);
    184   EXPECT_EQ(
    185       "<eve:value1 xmlns:eve=\"http://jabber.org/protocol/pubsub#event\"/>",
    186       listener->items[1].payload);
    187 }
    188 
    189 TEST_F(PubSubTasksTest, TestPublish) {
    190   buzz::XmlElement* payload =
    191       new buzz::XmlElement(buzz::QName(buzz::NS_PUBSUB, "value"));
    192   std::string expected_iq =
    193       "<cli:iq type=\"set\" to=\"room (at) domain.com\" id=\"0\" "
    194         "xmlns:cli=\"jabber:client\">"
    195         "<pubsub xmlns=\"http://jabber.org/protocol/pubsub\">"
    196           "<publish node=\"topic\">"
    197             "<item id=\"key\">"
    198               "<value/>"
    199             "</item>"
    200           "</publish>"
    201         "</pubsub>"
    202       "</cli:iq>";
    203 
    204   std::vector<buzz::XmlElement*> children;
    205   children.push_back(payload);
    206   buzz::PubSubPublishTask* task =
    207       new buzz::PubSubPublishTask(client, pubsubjid, node, itemid, children);
    208   task->SignalResult.connect(
    209       listener.get(), &TestPubSubTasksListener::OnPublishResult);
    210   task->Start();
    211 
    212   ASSERT_EQ(1U, client->sent_stanzas().size());
    213   EXPECT_EQ(expected_iq, client->sent_stanzas()[0]->Str());
    214 
    215   std::string result_iq =
    216       "<iq xmlns='jabber:client' id='0' type='result' from='room (at) domain.com'/>";
    217 
    218   client->HandleStanza(buzz::XmlElement::ForStr(result_iq));
    219 
    220   EXPECT_EQ(1, listener->result_count);
    221   EXPECT_EQ(0, listener->error_count);
    222 }
    223 
    224 TEST_F(PubSubTasksTest, TestPublishError) {
    225   buzz::XmlElement* payload =
    226       new buzz::XmlElement(buzz::QName(buzz::NS_PUBSUB, "value"));
    227 
    228   std::vector<buzz::XmlElement*> children;
    229   children.push_back(payload);
    230   buzz::PubSubPublishTask* task =
    231       new buzz::PubSubPublishTask(client, pubsubjid, node, itemid, children);
    232   task->SignalResult.connect(
    233       listener.get(), &TestPubSubTasksListener::OnPublishResult);
    234   task->SignalError.connect(
    235       listener.get(), &TestPubSubTasksListener::OnError);
    236   task->Start();
    237 
    238   std::string result_iq =
    239       "<iq xmlns='jabber:client' id='0' type='error' from='room (at) domain.com'>"
    240       "  <error type='auth'>"
    241       "    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
    242       "  </error>"
    243       "</iq>";
    244 
    245   client->HandleStanza(buzz::XmlElement::ForStr(result_iq));
    246 
    247   EXPECT_EQ(0, listener->result_count);
    248   EXPECT_EQ(1, listener->error_count);
    249 }
    250 
    251 TEST_F(PubSubTasksTest, TestRetract) {
    252   buzz::PubSubRetractTask* task =
    253       new buzz::PubSubRetractTask(client, pubsubjid, node, itemid);
    254   task->SignalResult.connect(
    255       listener.get(), &TestPubSubTasksListener::OnRetractResult);
    256   task->SignalError.connect(
    257       listener.get(), &TestPubSubTasksListener::OnError);
    258   task->Start();
    259 
    260   std::string expected_iq =
    261       "<cli:iq type=\"set\" to=\"room (at) domain.com\" id=\"0\" "
    262         "xmlns:cli=\"jabber:client\">"
    263         "<pubsub xmlns=\"http://jabber.org/protocol/pubsub\">"
    264           "<retract node=\"topic\" notify=\"true\">"
    265             "<item id=\"key\"/>"
    266           "</retract>"
    267         "</pubsub>"
    268       "</cli:iq>";
    269 
    270   ASSERT_EQ(1U, client->sent_stanzas().size());
    271   EXPECT_EQ(expected_iq, client->sent_stanzas()[0]->Str());
    272 
    273   std::string result_iq =
    274       "<iq xmlns='jabber:client' id='0' type='result' from='room (at) domain.com'/>";
    275 
    276   client->HandleStanza(buzz::XmlElement::ForStr(result_iq));
    277 
    278   EXPECT_EQ(1, listener->result_count);
    279   EXPECT_EQ(0, listener->error_count);
    280 }
    281