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