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