Home | History | Annotate | Download | only in xmpp
      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/hangoutpubsubclient.h"
     11 #include "talk/xmpp/jid.h"
     12 #include "webrtc/base/faketaskrunner.h"
     13 #include "webrtc/base/gunit.h"
     14 #include "webrtc/base/sigslot.h"
     15 
     16 class TestHangoutPubSubListener : public sigslot::has_slots<> {
     17  public:
     18   TestHangoutPubSubListener() :
     19       request_error_count(0),
     20       publish_audio_mute_error_count(0),
     21       publish_video_mute_error_count(0),
     22       publish_video_pause_error_count(0),
     23       publish_presenter_error_count(0),
     24       publish_recording_error_count(0),
     25       remote_mute_error_count(0) {
     26   }
     27 
     28   void OnPresenterStateChange(
     29       const std::string& nick, bool was_presenting, bool is_presenting) {
     30     last_presenter_nick = nick;
     31     last_was_presenting = was_presenting;
     32     last_is_presenting = is_presenting;
     33   }
     34 
     35   void OnAudioMuteStateChange(
     36       const std::string& nick, bool was_muted, bool is_muted) {
     37     last_audio_muted_nick = nick;
     38     last_was_audio_muted = was_muted;
     39     last_is_audio_muted = is_muted;
     40   }
     41 
     42   void OnVideoMuteStateChange(
     43       const std::string& nick, bool was_muted, bool is_muted) {
     44     last_video_muted_nick = nick;
     45     last_was_video_muted = was_muted;
     46     last_is_video_muted = is_muted;
     47   }
     48 
     49   void OnVideoPauseStateChange(
     50       const std::string& nick, bool was_paused, bool is_paused) {
     51     last_video_paused_nick = nick;
     52     last_was_video_paused = was_paused;
     53     last_is_video_paused = is_paused;
     54   }
     55 
     56   void OnRecordingStateChange(
     57       const std::string& nick, bool was_recording, bool is_recording) {
     58     last_recording_nick = nick;
     59     last_was_recording = was_recording;
     60     last_is_recording = is_recording;
     61   }
     62 
     63   void OnRemoteMute(
     64       const std::string& mutee_nick,
     65       const std::string& muter_nick,
     66       bool should_mute_locally) {
     67     last_mutee_nick = mutee_nick;
     68     last_muter_nick = muter_nick;
     69     last_should_mute = should_mute_locally;
     70   }
     71 
     72   void OnMediaBlock(
     73       const std::string& blockee_nick,
     74       const std::string& blocker_nick) {
     75     last_blockee_nick = blockee_nick;
     76     last_blocker_nick = blocker_nick;
     77   }
     78 
     79   void OnRequestError(const std::string& node, const buzz::XmlElement* stanza) {
     80     ++request_error_count;
     81     request_error_node = node;
     82   }
     83 
     84   void OnPublishAudioMuteError(const std::string& task_id,
     85                                const buzz::XmlElement* stanza) {
     86     ++publish_audio_mute_error_count;
     87     error_task_id = task_id;
     88   }
     89 
     90   void OnPublishVideoMuteError(const std::string& task_id,
     91                                const buzz::XmlElement* stanza) {
     92     ++publish_video_mute_error_count;
     93     error_task_id = task_id;
     94   }
     95 
     96   void OnPublishVideoPauseError(const std::string& task_id,
     97                                const buzz::XmlElement* stanza) {
     98     ++publish_video_pause_error_count;
     99     error_task_id = task_id;
    100   }
    101 
    102   void OnPublishPresenterError(const std::string& task_id,
    103                                const buzz::XmlElement* stanza) {
    104     ++publish_presenter_error_count;
    105     error_task_id = task_id;
    106   }
    107 
    108   void OnPublishRecordingError(const std::string& task_id,
    109                                const buzz::XmlElement* stanza) {
    110     ++publish_recording_error_count;
    111     error_task_id = task_id;
    112   }
    113 
    114   void OnRemoteMuteResult(const std::string& task_id,
    115                           const std::string& mutee_nick) {
    116     result_task_id = task_id;
    117     remote_mute_mutee_nick = mutee_nick;
    118   }
    119 
    120   void OnRemoteMuteError(const std::string& task_id,
    121                          const std::string& mutee_nick,
    122                          const buzz::XmlElement* stanza) {
    123     ++remote_mute_error_count;
    124     error_task_id = task_id;
    125     remote_mute_mutee_nick = mutee_nick;
    126   }
    127 
    128   void OnMediaBlockResult(const std::string& task_id,
    129                           const std::string& blockee_nick) {
    130     result_task_id = task_id;
    131     media_blockee_nick = blockee_nick;
    132   }
    133 
    134   void OnMediaBlockError(const std::string& task_id,
    135                          const std::string& blockee_nick,
    136                          const buzz::XmlElement* stanza) {
    137     ++media_block_error_count;
    138     error_task_id = task_id;
    139     media_blockee_nick = blockee_nick;
    140   }
    141 
    142   std::string last_presenter_nick;
    143   bool last_is_presenting;
    144   bool last_was_presenting;
    145   std::string last_audio_muted_nick;
    146   bool last_is_audio_muted;
    147   bool last_was_audio_muted;
    148   std::string last_video_muted_nick;
    149   bool last_is_video_muted;
    150   bool last_was_video_muted;
    151   std::string last_video_paused_nick;
    152   bool last_is_video_paused;
    153   bool last_was_video_paused;
    154   std::string last_recording_nick;
    155   bool last_is_recording;
    156   bool last_was_recording;
    157   std::string last_mutee_nick;
    158   std::string last_muter_nick;
    159   bool last_should_mute;
    160   std::string last_blockee_nick;
    161   std::string last_blocker_nick;
    162 
    163   int request_error_count;
    164   std::string request_error_node;
    165   int publish_audio_mute_error_count;
    166   int publish_video_mute_error_count;
    167   int publish_video_pause_error_count;
    168   int publish_presenter_error_count;
    169   int publish_recording_error_count;
    170   int remote_mute_error_count;
    171   std::string result_task_id;
    172   std::string error_task_id;
    173   std::string remote_mute_mutee_nick;
    174   int media_block_error_count;
    175   std::string media_blockee_nick;
    176 };
    177 
    178 class HangoutPubSubClientTest : public testing::Test {
    179  public:
    180   HangoutPubSubClientTest() :
    181       pubsubjid("room (at) domain.com"),
    182       nick("me") {
    183 
    184     runner.reset(new rtc::FakeTaskRunner());
    185     xmpp_client = new buzz::FakeXmppClient(runner.get());
    186     client.reset(new buzz::HangoutPubSubClient(xmpp_client, pubsubjid, nick));
    187     listener.reset(new TestHangoutPubSubListener());
    188     client->SignalPresenterStateChange.connect(
    189         listener.get(), &TestHangoutPubSubListener::OnPresenterStateChange);
    190     client->SignalAudioMuteStateChange.connect(
    191         listener.get(), &TestHangoutPubSubListener::OnAudioMuteStateChange);
    192     client->SignalVideoMuteStateChange.connect(
    193         listener.get(), &TestHangoutPubSubListener::OnVideoMuteStateChange);
    194     client->SignalVideoPauseStateChange.connect(
    195         listener.get(), &TestHangoutPubSubListener::OnVideoPauseStateChange);
    196     client->SignalRecordingStateChange.connect(
    197         listener.get(), &TestHangoutPubSubListener::OnRecordingStateChange);
    198     client->SignalRemoteMute.connect(
    199         listener.get(), &TestHangoutPubSubListener::OnRemoteMute);
    200     client->SignalMediaBlock.connect(
    201         listener.get(), &TestHangoutPubSubListener::OnMediaBlock);
    202     client->SignalRequestError.connect(
    203         listener.get(), &TestHangoutPubSubListener::OnRequestError);
    204     client->SignalPublishAudioMuteError.connect(
    205         listener.get(), &TestHangoutPubSubListener::OnPublishAudioMuteError);
    206     client->SignalPublishVideoMuteError.connect(
    207         listener.get(), &TestHangoutPubSubListener::OnPublishVideoMuteError);
    208     client->SignalPublishVideoPauseError.connect(
    209         listener.get(), &TestHangoutPubSubListener::OnPublishVideoPauseError);
    210     client->SignalPublishPresenterError.connect(
    211         listener.get(), &TestHangoutPubSubListener::OnPublishPresenterError);
    212     client->SignalPublishRecordingError.connect(
    213         listener.get(), &TestHangoutPubSubListener::OnPublishRecordingError);
    214     client->SignalRemoteMuteResult.connect(
    215         listener.get(), &TestHangoutPubSubListener::OnRemoteMuteResult);
    216     client->SignalRemoteMuteError.connect(
    217         listener.get(), &TestHangoutPubSubListener::OnRemoteMuteError);
    218     client->SignalMediaBlockResult.connect(
    219         listener.get(), &TestHangoutPubSubListener::OnMediaBlockResult);
    220     client->SignalMediaBlockError.connect(
    221         listener.get(), &TestHangoutPubSubListener::OnMediaBlockError);
    222   }
    223 
    224   rtc::scoped_ptr<rtc::FakeTaskRunner> runner;
    225   // xmpp_client deleted by deleting runner.
    226   buzz::FakeXmppClient* xmpp_client;
    227   rtc::scoped_ptr<buzz::HangoutPubSubClient> client;
    228   rtc::scoped_ptr<TestHangoutPubSubListener> listener;
    229   buzz::Jid pubsubjid;
    230   std::string nick;
    231 };
    232 
    233 TEST_F(HangoutPubSubClientTest, TestRequest) {
    234   ASSERT_EQ(0U, xmpp_client->sent_stanzas().size());
    235 
    236   client->RequestAll();
    237   std::string expected_presenter_request =
    238       "<cli:iq type=\"get\" to=\"room (at) domain.com\" id=\"0\" "
    239         "xmlns:cli=\"jabber:client\">"
    240         "<pub:pubsub xmlns:pub=\"http://jabber.org/protocol/pubsub\">"
    241           "<pub:items node=\"google:presenter\"/>"
    242         "</pub:pubsub>"
    243       "</cli:iq>";
    244 
    245   std::string expected_media_request =
    246       "<cli:iq type=\"get\" to=\"room (at) domain.com\" id=\"0\" "
    247         "xmlns:cli=\"jabber:client\">"
    248         "<pub:pubsub xmlns:pub=\"http://jabber.org/protocol/pubsub\">"
    249           "<pub:items node=\"google:muc#media\"/>"
    250         "</pub:pubsub>"
    251       "</cli:iq>";
    252 
    253   ASSERT_EQ(2U, xmpp_client->sent_stanzas().size());
    254   EXPECT_EQ(expected_presenter_request, xmpp_client->sent_stanzas()[0]->Str());
    255   EXPECT_EQ(expected_media_request, xmpp_client->sent_stanzas()[1]->Str());
    256 
    257   std::string presenter_response =
    258       "<iq xmlns='jabber:client' id='0' type='result' from='room (at) domain.com'>"
    259       "  <pubsub xmlns='http://jabber.org/protocol/pubsub'>"
    260       "    <items node='google:presenter'>"
    261       "      <item id='12344'>"
    262       "        <presenter xmlns='google:presenter' nick='presenting-nick2'/>"
    263       "        <pre:presentation-item xmlns:pre='google:presenter'"
    264       "          pre:presentation-type='s'/>"
    265       "      </item>"
    266       "      <item id='12345'>"
    267       "        <presenter xmlns='google:presenter' nick='presenting-nick'/>"
    268       "        <pre:presentation-item xmlns:pre='google:presenter'"
    269       "          pre:presentation-type='o'/>"
    270       "      </item>"
    271       // Some clients are "bad" in that they'll jam multiple states in
    272       // all at once.  We have to deal with it.
    273       "      <item id='12346'>"
    274       "        <presenter xmlns='google:presenter' nick='presenting-nick'/>"
    275       "        <pre:presentation-item xmlns:pre='google:presenter'"
    276       "          pre:presentation-type='s'/>"
    277       "      </item>"
    278       "    </items>"
    279       "  </pubsub>"
    280       "</iq>";
    281 
    282   xmpp_client->HandleStanza(buzz::XmlElement::ForStr(presenter_response));
    283   EXPECT_EQ("presenting-nick", listener->last_presenter_nick);
    284   EXPECT_FALSE(listener->last_was_presenting);
    285   EXPECT_TRUE(listener->last_is_presenting);
    286 
    287   std::string media_response =
    288       "<iq xmlns='jabber:client' id='0' type='result' from='room (at) domain.com'>"
    289       "  <pubsub xmlns='http://jabber.org/protocol/pubsub'>"
    290       "    <items node='google:muc#media'>"
    291       "      <item id='audio-mute:muted-nick'>"
    292       "        <audio-mute nick='muted-nick' xmlns='google:muc#media'/>"
    293       "      </item>"
    294       "      <item id='video-mute:video-muted-nick'>"
    295       "        <video-mute nick='video-muted-nick' xmlns='google:muc#media'/>"
    296       "      </item>"
    297       "      <item id='video-pause:video-paused-nick'>"
    298       "        <video-pause nick='video-paused-nick' xmlns='google:muc#media'/>"
    299       "      </item>"
    300       "      <item id='recording:recording-nick'>"
    301       "        <recording nick='recording-nick' xmlns='google:muc#media'/>"
    302       "      </item>"
    303       "    </items>"
    304       "  </pubsub>"
    305       "</iq>";
    306 
    307   xmpp_client->HandleStanza(buzz::XmlElement::ForStr(media_response));
    308   EXPECT_EQ("muted-nick", listener->last_audio_muted_nick);
    309   EXPECT_FALSE(listener->last_was_audio_muted);
    310   EXPECT_TRUE(listener->last_is_audio_muted);
    311 
    312   EXPECT_EQ("video-muted-nick", listener->last_video_muted_nick);
    313   EXPECT_FALSE(listener->last_was_video_muted);
    314   EXPECT_TRUE(listener->last_is_video_muted);
    315 
    316   EXPECT_EQ("video-paused-nick", listener->last_video_paused_nick);
    317   EXPECT_FALSE(listener->last_was_video_paused);
    318   EXPECT_TRUE(listener->last_is_video_paused);
    319 
    320   EXPECT_EQ("recording-nick", listener->last_recording_nick);
    321   EXPECT_FALSE(listener->last_was_recording);
    322   EXPECT_TRUE(listener->last_is_recording);
    323 
    324   std::string incoming_presenter_resets_message =
    325       "<message xmlns='jabber:client' from='room (at) domain.com'>"
    326       "  <event xmlns='http://jabber.org/protocol/pubsub#event'>"
    327       "    <items node='google:presenter'>"
    328       "      <item id='12348'>"
    329       "        <presenter xmlns='google:presenter' nick='presenting-nick'/>"
    330       "        <pre:presentation-item xmlns:pre='google:presenter'"
    331       "          pre:presentation-type='o'/>"
    332       "      </item>"
    333       "    </items>"
    334       "  </event>"
    335       "</message>";
    336 
    337   xmpp_client->HandleStanza(
    338       buzz::XmlElement::ForStr(incoming_presenter_resets_message));
    339   EXPECT_EQ("presenting-nick", listener->last_presenter_nick);
    340   //EXPECT_TRUE(listener->last_was_presenting);
    341   EXPECT_FALSE(listener->last_is_presenting);
    342 
    343   std::string incoming_presenter_retracts_message =
    344       "<message xmlns='jabber:client' from='room (at) domain.com'>"
    345       "  <event xmlns='http://jabber.org/protocol/pubsub#event'>"
    346       "    <items node='google:presenter'>"
    347       "      <retract id='12344'/>"
    348       "    </items>"
    349       "  </event>"
    350       "</message>";
    351 
    352   xmpp_client->HandleStanza(
    353       buzz::XmlElement::ForStr(incoming_presenter_retracts_message));
    354   EXPECT_EQ("presenting-nick2", listener->last_presenter_nick);
    355   EXPECT_TRUE(listener->last_was_presenting);
    356   EXPECT_FALSE(listener->last_is_presenting);
    357 
    358   std::string incoming_media_retracts_message =
    359       "<message xmlns='jabber:client' from='room (at) domain.com'>"
    360       "  <event xmlns='http://jabber.org/protocol/pubsub#event'>"
    361       "    <items node='google:muc#media'>"
    362       "      <item id='audio-mute:muted-nick'>"
    363       "      </item>"
    364       "      <retract id='video-mute:video-muted-nick'/>"
    365       "      <retract id='video-pause:video-paused-nick'/>"
    366       "      <retract id='recording:recording-nick'/>"
    367       "    </items>"
    368       "  </event>"
    369       "</message>";
    370 
    371   xmpp_client->HandleStanza(
    372       buzz::XmlElement::ForStr(incoming_media_retracts_message));
    373   EXPECT_EQ("muted-nick", listener->last_audio_muted_nick);
    374   EXPECT_TRUE(listener->last_was_audio_muted);
    375   EXPECT_FALSE(listener->last_is_audio_muted);
    376 
    377   EXPECT_EQ("video-paused-nick", listener->last_video_paused_nick);
    378   EXPECT_TRUE(listener->last_was_video_paused);
    379   EXPECT_FALSE(listener->last_is_video_paused);
    380 
    381   EXPECT_EQ("recording-nick", listener->last_recording_nick);
    382   EXPECT_TRUE(listener->last_was_recording);
    383   EXPECT_FALSE(listener->last_is_recording);
    384 
    385   std::string incoming_presenter_changes_message =
    386       "<message xmlns='jabber:client' from='room (at) domain.com'>"
    387       "  <event xmlns='http://jabber.org/protocol/pubsub#event'>"
    388       "    <items node='google:presenter'>"
    389       "      <item id='presenting-nick2'>"
    390       "        <presenter xmlns='google:presenter' nick='presenting-nick2'/>"
    391       "        <pre:presentation-item xmlns:pre='google:presenter'"
    392       "          pre:presentation-type='s'/>"
    393       "      </item>"
    394       "    </items>"
    395       "  </event>"
    396       "</message>";
    397 
    398   xmpp_client->HandleStanza(
    399       buzz::XmlElement::ForStr(incoming_presenter_changes_message));
    400   EXPECT_EQ("presenting-nick2", listener->last_presenter_nick);
    401   EXPECT_FALSE(listener->last_was_presenting);
    402   EXPECT_TRUE(listener->last_is_presenting);
    403 
    404   xmpp_client->HandleStanza(
    405       buzz::XmlElement::ForStr(incoming_presenter_changes_message));
    406   EXPECT_EQ("presenting-nick2", listener->last_presenter_nick);
    407   EXPECT_TRUE(listener->last_was_presenting);
    408   EXPECT_TRUE(listener->last_is_presenting);
    409 
    410   std::string incoming_media_changes_message =
    411       "<message xmlns='jabber:client' from='room (at) domain.com'>"
    412       "  <event xmlns='http://jabber.org/protocol/pubsub#event'>"
    413       "    <items node='google:muc#media'>"
    414       "      <item id='audio-mute:muted-nick2'>"
    415       "        <audio-mute nick='muted-nick2' xmlns='google:muc#media'/>"
    416       "      </item>"
    417       "      <item id='video-pause:video-paused-nick2'>"
    418       "        <video-pause nick='video-paused-nick2' xmlns='google:muc#media'/>"
    419       "      </item>"
    420       "      <item id='recording:recording-nick2'>"
    421       "        <recording nick='recording-nick2' xmlns='google:muc#media'/>"
    422       "      </item>"
    423       "    </items>"
    424       "  </event>"
    425       "</message>";
    426 
    427   xmpp_client->HandleStanza(
    428       buzz::XmlElement::ForStr(incoming_media_changes_message));
    429   EXPECT_EQ("muted-nick2", listener->last_audio_muted_nick);
    430   EXPECT_FALSE(listener->last_was_audio_muted);
    431   EXPECT_TRUE(listener->last_is_audio_muted);
    432 
    433   EXPECT_EQ("video-paused-nick2", listener->last_video_paused_nick);
    434   EXPECT_FALSE(listener->last_was_video_paused);
    435   EXPECT_TRUE(listener->last_is_video_paused);
    436 
    437   EXPECT_EQ("recording-nick2", listener->last_recording_nick);
    438   EXPECT_FALSE(listener->last_was_recording);
    439   EXPECT_TRUE(listener->last_is_recording);
    440 
    441   std::string incoming_remote_mute_message =
    442       "<message xmlns='jabber:client' from='room (at) domain.com'>"
    443       "  <event xmlns='http://jabber.org/protocol/pubsub#event'>"
    444       "    <items node='google:muc#media'>"
    445       "      <item id='audio-mute:mutee' publisher='room (at) domain.com/muter'>"
    446       "        <audio-mute nick='mutee' xmlns='google:muc#media'/>"
    447       "      </item>"
    448       "    </items>"
    449       "  </event>"
    450       "</message>";
    451 
    452   listener->last_is_audio_muted = false;
    453   xmpp_client->HandleStanza(
    454       buzz::XmlElement::ForStr(incoming_remote_mute_message));
    455   EXPECT_EQ("mutee", listener->last_mutee_nick);
    456   EXPECT_EQ("muter", listener->last_muter_nick);
    457   EXPECT_FALSE(listener->last_should_mute);
    458   EXPECT_EQ("mutee", listener->last_audio_muted_nick);
    459   EXPECT_TRUE(listener->last_is_audio_muted);
    460 
    461   std::string incoming_remote_mute_me_message =
    462       "<message xmlns='jabber:client' from='room (at) domain.com'>"
    463       "  <event xmlns='http://jabber.org/protocol/pubsub#event'>"
    464       "    <items node='google:muc#media'>"
    465       "      <item id='audio-mute:me' publisher='room (at) domain.com/muter'>"
    466       "        <audio-mute nick='me' xmlns='google:muc#media'/>"
    467       "      </item>"
    468       "    </items>"
    469       "  </event>"
    470       "</message>";
    471 
    472   listener->last_is_audio_muted = false;
    473   xmpp_client->HandleStanza(
    474       buzz::XmlElement::ForStr(incoming_remote_mute_me_message));
    475   EXPECT_EQ("me", listener->last_mutee_nick);
    476   EXPECT_EQ("muter", listener->last_muter_nick);
    477   EXPECT_TRUE(listener->last_should_mute);
    478   EXPECT_EQ("me", listener->last_audio_muted_nick);
    479   EXPECT_TRUE(listener->last_is_audio_muted);
    480 
    481   std::string incoming_media_block_message =
    482       "<message xmlns='jabber:client' from='room (at) domain.com'>"
    483       "  <event xmlns='http://jabber.org/protocol/pubsub#event'>"
    484       "    <items node='google:muc#media'>"
    485       "      <item id='block:blocker:blockee'"
    486       "            publisher='room (at) domain.com/blocker'>"
    487       "        <block nick='blockee' xmlns='google:muc#media'/>"
    488       "      </item>"
    489       "    </items>"
    490       "  </event>"
    491       "</message>";
    492 
    493   xmpp_client->HandleStanza(
    494       buzz::XmlElement::ForStr(incoming_media_block_message));
    495   EXPECT_EQ("blockee", listener->last_blockee_nick);
    496   EXPECT_EQ("blocker", listener->last_blocker_nick);
    497 }
    498 
    499 TEST_F(HangoutPubSubClientTest, TestRequestError) {
    500   client->RequestAll();
    501   std::string result_iq =
    502       "<iq xmlns='jabber:client' id='0' type='error' from='room (at) domain.com'>"
    503       "  <error type='auth'>"
    504       "    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
    505       "  </error>"
    506       "</iq>";
    507 
    508   xmpp_client->HandleStanza(buzz::XmlElement::ForStr(result_iq));
    509   EXPECT_EQ(1, listener->request_error_count);
    510   EXPECT_EQ("google:presenter", listener->request_error_node);
    511 }
    512 
    513 TEST_F(HangoutPubSubClientTest, TestPublish) {
    514   client->PublishPresenterState(true);
    515   std::string expected_presenter_iq =
    516       "<cli:iq type=\"set\" to=\"room (at) domain.com\" id=\"0\" "
    517         "xmlns:cli=\"jabber:client\">"
    518         "<pubsub xmlns=\"http://jabber.org/protocol/pubsub\">"
    519           "<publish node=\"google:presenter\">"
    520             "<item id=\"me\">"
    521               "<presenter xmlns=\"google:presenter\""
    522               " nick=\"me\"/>"
    523               "<pre:presentation-item"
    524               " pre:presentation-type=\"s\" xmlns:pre=\"google:presenter\"/>"
    525             "</item>"
    526           "</publish>"
    527         "</pubsub>"
    528       "</cli:iq>";
    529 
    530   ASSERT_EQ(1U, xmpp_client->sent_stanzas().size());
    531   EXPECT_EQ(expected_presenter_iq,
    532             xmpp_client->sent_stanzas()[0]->Str());
    533 
    534   client->PublishAudioMuteState(true);
    535   std::string expected_audio_mute_iq =
    536       "<cli:iq type=\"set\" to=\"room (at) domain.com\" id=\"0\" "
    537         "xmlns:cli=\"jabber:client\">"
    538         "<pubsub xmlns=\"http://jabber.org/protocol/pubsub\">"
    539           "<publish node=\"google:muc#media\">"
    540             "<item id=\"audio-mute:me\">"
    541               "<audio-mute xmlns=\"google:muc#media\" nick=\"me\"/>"
    542             "</item>"
    543           "</publish>"
    544         "</pubsub>"
    545       "</cli:iq>";
    546 
    547   ASSERT_EQ(2U, xmpp_client->sent_stanzas().size());
    548   EXPECT_EQ(expected_audio_mute_iq, xmpp_client->sent_stanzas()[1]->Str());
    549 
    550   client->PublishVideoPauseState(true);
    551   std::string expected_video_pause_iq =
    552       "<cli:iq type=\"set\" to=\"room (at) domain.com\" id=\"0\" "
    553         "xmlns:cli=\"jabber:client\">"
    554         "<pubsub xmlns=\"http://jabber.org/protocol/pubsub\">"
    555           "<publish node=\"google:muc#media\">"
    556             "<item id=\"video-pause:me\">"
    557               "<video-pause xmlns=\"google:muc#media\" nick=\"me\"/>"
    558             "</item>"
    559           "</publish>"
    560         "</pubsub>"
    561       "</cli:iq>";
    562 
    563   ASSERT_EQ(3U, xmpp_client->sent_stanzas().size());
    564   EXPECT_EQ(expected_video_pause_iq, xmpp_client->sent_stanzas()[2]->Str());
    565 
    566   client->PublishRecordingState(true);
    567   std::string expected_recording_iq =
    568       "<cli:iq type=\"set\" to=\"room (at) domain.com\" id=\"0\" "
    569         "xmlns:cli=\"jabber:client\">"
    570         "<pubsub xmlns=\"http://jabber.org/protocol/pubsub\">"
    571           "<publish node=\"google:muc#media\">"
    572             "<item id=\"recording:me\">"
    573               "<recording xmlns=\"google:muc#media\" nick=\"me\"/>"
    574             "</item>"
    575           "</publish>"
    576         "</pubsub>"
    577       "</cli:iq>";
    578 
    579   ASSERT_EQ(4U, xmpp_client->sent_stanzas().size());
    580   EXPECT_EQ(expected_recording_iq, xmpp_client->sent_stanzas()[3]->Str());
    581 
    582   client->RemoteMute("mutee");
    583   std::string expected_remote_mute_iq =
    584       "<cli:iq type=\"set\" to=\"room (at) domain.com\" id=\"0\" "
    585         "xmlns:cli=\"jabber:client\">"
    586         "<pubsub xmlns=\"http://jabber.org/protocol/pubsub\">"
    587           "<publish node=\"google:muc#media\">"
    588             "<item id=\"audio-mute:mutee\">"
    589               "<audio-mute xmlns=\"google:muc#media\" nick=\"mutee\"/>"
    590             "</item>"
    591           "</publish>"
    592         "</pubsub>"
    593       "</cli:iq>";
    594 
    595   ASSERT_EQ(5U, xmpp_client->sent_stanzas().size());
    596   EXPECT_EQ(expected_remote_mute_iq, xmpp_client->sent_stanzas()[4]->Str());
    597 
    598   client->PublishPresenterState(false);
    599   std::string expected_presenter_retract_iq =
    600       "<cli:iq type=\"set\" to=\"room (at) domain.com\" id=\"0\" "
    601         "xmlns:cli=\"jabber:client\">"
    602         "<pubsub xmlns=\"http://jabber.org/protocol/pubsub\">"
    603           "<publish node=\"google:presenter\">"
    604             "<item id=\"me\">"
    605               "<presenter xmlns=\"google:presenter\""
    606               " nick=\"me\"/>"
    607               "<pre:presentation-item"
    608               " pre:presentation-type=\"o\" xmlns:pre=\"google:presenter\"/>"
    609             "</item>"
    610           "</publish>"
    611         "</pubsub>"
    612       "</cli:iq>";
    613 
    614   ASSERT_EQ(6U, xmpp_client->sent_stanzas().size());
    615   EXPECT_EQ(expected_presenter_retract_iq,
    616             xmpp_client->sent_stanzas()[5]->Str());
    617 
    618   client->PublishAudioMuteState(false);
    619   std::string expected_audio_mute_retract_iq =
    620       "<cli:iq type=\"set\" to=\"room (at) domain.com\" id=\"0\" "
    621         "xmlns:cli=\"jabber:client\">"
    622         "<pubsub xmlns=\"http://jabber.org/protocol/pubsub\">"
    623           "<retract node=\"google:muc#media\" notify=\"true\">"
    624             "<item id=\"audio-mute:me\"/>"
    625           "</retract>"
    626         "</pubsub>"
    627       "</cli:iq>";
    628 
    629   ASSERT_EQ(7U, xmpp_client->sent_stanzas().size());
    630   EXPECT_EQ(expected_audio_mute_retract_iq,
    631             xmpp_client->sent_stanzas()[6]->Str());
    632 
    633   client->PublishVideoPauseState(false);
    634   std::string expected_video_pause_retract_iq =
    635       "<cli:iq type=\"set\" to=\"room (at) domain.com\" id=\"0\" "
    636         "xmlns:cli=\"jabber:client\">"
    637         "<pubsub xmlns=\"http://jabber.org/protocol/pubsub\">"
    638           "<retract node=\"google:muc#media\" notify=\"true\">"
    639             "<item id=\"video-pause:me\"/>"
    640           "</retract>"
    641         "</pubsub>"
    642       "</cli:iq>";
    643 
    644   ASSERT_EQ(8U, xmpp_client->sent_stanzas().size());
    645   EXPECT_EQ(expected_video_pause_retract_iq,
    646             xmpp_client->sent_stanzas()[7]->Str());
    647 
    648   client->BlockMedia("blockee");
    649   std::string expected_media_block_iq =
    650       "<cli:iq type=\"set\" to=\"room (at) domain.com\" id=\"0\" "
    651         "xmlns:cli=\"jabber:client\">"
    652         "<pubsub xmlns=\"http://jabber.org/protocol/pubsub\">"
    653           "<publish node=\"google:muc#media\">"
    654             "<item id=\"block:me:blockee\">"
    655               "<block xmlns=\"google:muc#media\" nick=\"blockee\"/>"
    656             "</item>"
    657           "</publish>"
    658         "</pubsub>"
    659       "</cli:iq>";
    660 
    661   ASSERT_EQ(9U, xmpp_client->sent_stanzas().size());
    662   EXPECT_EQ(expected_media_block_iq, xmpp_client->sent_stanzas()[8]->Str());
    663 }
    664 
    665 TEST_F(HangoutPubSubClientTest, TestPublishPresenterError) {
    666   std::string result_iq =
    667       "<iq xmlns='jabber:client' id='0' type='error' from='room (at) domain.com'/>";
    668 
    669   client->PublishPresenterState(true);
    670   xmpp_client->HandleStanza(buzz::XmlElement::ForStr(result_iq));
    671   EXPECT_EQ(1, listener->publish_presenter_error_count);
    672   EXPECT_EQ("0", listener->error_task_id);
    673 }
    674 
    675 
    676 TEST_F(HangoutPubSubClientTest, TestPublishAudioMuteError) {
    677   std::string result_iq =
    678       "<iq xmlns='jabber:client' id='0' type='error' from='room (at) domain.com'/>";
    679 
    680   client->PublishAudioMuteState(true);
    681   xmpp_client->HandleStanza(buzz::XmlElement::ForStr(result_iq));
    682   EXPECT_EQ(1, listener->publish_audio_mute_error_count);
    683   EXPECT_EQ("0", listener->error_task_id);
    684 }
    685 
    686 TEST_F(HangoutPubSubClientTest, TestPublishVideoPauseError) {
    687   std::string result_iq =
    688       "<iq xmlns='jabber:client' id='0' type='error' from='room (at) domain.com'/>";
    689 
    690   client->PublishVideoPauseState(true);
    691   xmpp_client->HandleStanza(buzz::XmlElement::ForStr(result_iq));
    692   EXPECT_EQ(1, listener->publish_video_pause_error_count);
    693   EXPECT_EQ("0", listener->error_task_id);
    694 }
    695 
    696 TEST_F(HangoutPubSubClientTest, TestPublishRecordingError) {
    697   std::string result_iq =
    698       "<iq xmlns='jabber:client' id='0' type='error' from='room (at) domain.com'/>";
    699 
    700   client->PublishRecordingState(true);
    701   xmpp_client->HandleStanza(buzz::XmlElement::ForStr(result_iq));
    702   EXPECT_EQ(1, listener->publish_recording_error_count);
    703   EXPECT_EQ("0", listener->error_task_id);
    704 }
    705 
    706 TEST_F(HangoutPubSubClientTest, TestPublishRemoteMuteResult) {
    707   std::string result_iq =
    708       "<iq xmlns='jabber:client' id='0' type='result' from='room (at) domain.com'/>";
    709 
    710   client->RemoteMute("joe");
    711   xmpp_client->HandleStanza(buzz::XmlElement::ForStr(result_iq));
    712   EXPECT_EQ("joe", listener->remote_mute_mutee_nick);
    713   EXPECT_EQ("0", listener->result_task_id);
    714 }
    715 
    716 TEST_F(HangoutPubSubClientTest, TestRemoteMuteError) {
    717   std::string result_iq =
    718       "<iq xmlns='jabber:client' id='0' type='error' from='room (at) domain.com'/>";
    719 
    720   client->RemoteMute("joe");
    721   xmpp_client->HandleStanza(buzz::XmlElement::ForStr(result_iq));
    722   EXPECT_EQ(1, listener->remote_mute_error_count);
    723   EXPECT_EQ("joe", listener->remote_mute_mutee_nick);
    724   EXPECT_EQ("0", listener->error_task_id);
    725 }
    726 
    727 TEST_F(HangoutPubSubClientTest, TestPublishMediaBlockResult) {
    728   std::string result_iq =
    729       "<iq xmlns='jabber:client' id='0' type='result' from='room (at) domain.com'/>";
    730 
    731   client->BlockMedia("joe");
    732   xmpp_client->HandleStanza(buzz::XmlElement::ForStr(result_iq));
    733   EXPECT_EQ("joe", listener->media_blockee_nick);
    734   EXPECT_EQ("0", listener->result_task_id);
    735 }
    736 
    737 TEST_F(HangoutPubSubClientTest, TestMediaBlockError) {
    738   std::string result_iq =
    739       "<iq xmlns='jabber:client' id='0' type='error' from='room (at) domain.com'/>";
    740 
    741   client->BlockMedia("joe");
    742   xmpp_client->HandleStanza(buzz::XmlElement::ForStr(result_iq));
    743   EXPECT_EQ(1, listener->remote_mute_error_count);
    744   EXPECT_EQ("joe", listener->media_blockee_nick);
    745   EXPECT_EQ("0", listener->error_task_id);
    746 }
    747