1/*
2 * libjingle
3 * Copyright 2004 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 *  1. Redistributions of source code must retain the above copyright notice,
9 *     this list of conditions and the following disclaimer.
10 *  2. Redistributions in binary form must reproduce the above copyright notice,
11 *     this list of conditions and the following disclaimer in the documentation
12 *     and/or other materials provided with the distribution.
13 *  3. The name of the author may not be used to endorse or promote products
14 *     derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <string.h>
29
30#include <sstream>
31#include <deque>
32#include <map>
33
34#include "talk/base/base64.h"
35#include "talk/base/common.h"
36#include "talk/base/gunit.h"
37#include "talk/base/helpers.h"
38#include "talk/base/logging.h"
39#include "talk/base/natserver.h"
40#include "talk/base/natsocketfactory.h"
41#include "talk/base/stringencode.h"
42#include "talk/p2p/base/basicpacketsocketfactory.h"
43#include "talk/p2p/base/constants.h"
44#include "talk/p2p/base/parsing.h"
45#include "talk/p2p/base/portallocator.h"
46#include "talk/p2p/base/p2ptransport.h"
47#include "talk/p2p/base/relayport.h"
48#include "talk/p2p/base/relayserver.h"
49#include "talk/p2p/base/session.h"
50#include "talk/p2p/base/sessionclient.h"
51#include "talk/p2p/base/sessionmanager.h"
52#include "talk/p2p/base/stunport.h"
53#include "talk/p2p/base/stunserver.h"
54#include "talk/p2p/base/transportchannel.h"
55#include "talk/p2p/base/transportchannelproxy.h"
56#include "talk/p2p/base/udpport.h"
57#include "talk/xmpp/constants.h"
58
59using cricket::SignalingProtocol;
60using cricket::PROTOCOL_HYBRID;
61using cricket::PROTOCOL_JINGLE;
62using cricket::PROTOCOL_GINGLE;
63
64static const std::string kInitiator = "init@init.com";
65static const std::string kResponder = "resp@resp.com";
66// Expected from test random number generator.
67static const std::string kSessionId = "9254631414740579489";
68// TODO: When we need to test more than one transport type,
69// allow this to be injected like the content types are.
70static const std::string kTransportType = "http://www.google.com/transport/p2p";
71
72// Controls how long we wait for a session to send messages that we
73// expect, in milliseconds.  We put it high to avoid flaky tests.
74static const int kEventTimeout = 5000;
75
76static const int kNumPorts = 2;
77static const int kPort0 = 28653;
78static const int kPortStep = 5;
79
80int GetPort(int port_index) {
81  return kPort0 + (port_index * kPortStep);
82}
83
84std::string GetPortString(int port_index) {
85  return talk_base::ToString(GetPort(port_index));
86}
87
88// Only works for port_index < 10, which is fine for our purposes.
89std::string GetUsername(int port_index) {
90  return "username" + std::string(8, talk_base::ToString(port_index)[0]);
91}
92
93// Only works for port_index < 10, which is fine for our purposes.
94std::string GetPassword(int port_index) {
95  return "password" + std::string(8, talk_base::ToString(port_index)[0]);
96}
97
98std::string IqAck(const std::string& id,
99                  const std::string& from,
100                  const std::string& to) {
101  return "<cli:iq"
102      " to=\"" + to + "\""
103      " id=\"" + id + "\""
104      " type=\"result\""
105      " from=\"" + from + "\""
106      " xmlns:cli=\"jabber:client\""
107      "/>";
108}
109
110std::string IqSet(const std::string& id,
111                  const std::string& from,
112                  const std::string& to,
113                  const std::string& content) {
114  return "<cli:iq"
115      " to=\"" + to + "\""
116      " type=\"set\""
117      " from=\"" + from + "\""
118      " id=\"" + id + "\""
119      " xmlns:cli=\"jabber:client\""
120      ">"
121      + content +
122      "</cli:iq>";
123}
124
125std::string IqError(const std::string& id,
126                    const std::string& from,
127                    const std::string& to,
128                    const std::string& content) {
129  return "<cli:error"
130      " to=\"" + to + "\""
131      " type=\"error\""
132      " from=\"" + from + "\""
133      " id=\"" + id + "\""
134      " xmlns:cli=\"jabber:client\""
135      ">"
136      + content +
137      "</cli:error>";
138}
139
140std::string GingleSessionXml(const std::string& type,
141                             const std::string& content) {
142  return "<session"
143      " xmlns=\"http://www.google.com/session\""
144      " type=\"" + type + "\""
145      " id=\"" + kSessionId + "\""
146      " initiator=\"" + kInitiator + "\""
147      ">"
148      + content +
149      "</session>";
150}
151
152std::string GingleDescriptionXml(const std::string& content_type) {
153  return "<description"
154      " xmlns=\"" + content_type + "\""
155      "/>";
156}
157
158std::string P2pCandidateXml(const std::string& name, int port_index) {
159  // Port will update the rtcp username by +1 on the last character. So we need
160  // to compensate here. See Port::username_fragment() for detail.
161  std::string username = GetUsername(port_index);
162  // TODO: Use the component id instead of the channel name to
163  // determinte if we need to covert the username here.
164  if (name == "rtcp" || name == "video_rtcp" || name == "chanb") {
165    char next_ch = username[username.size() - 1];
166    ASSERT(username.size() > 0);
167    talk_base::Base64::GetNextBase64Char(next_ch, &next_ch);
168    username[username.size() - 1] = next_ch;
169  }
170  return "<candidate"
171      " name=\"" + name + "\""
172      " address=\"127.0.0.1\""
173      " port=\"" + GetPortString(port_index) + "\""
174      " preference=\"0.99\""
175      " username=\"" + username + "\""
176      " protocol=\"udp\""
177      " generation=\"0\""
178      " password=\"" + GetPassword(port_index) + "\""
179      " type=\"local\""
180      " network=\"network\""
181      "/>";
182}
183
184std::string JingleActionXml(const std::string& action,
185                            const std::string& content) {
186  return "<jingle"
187      " xmlns=\"urn:xmpp:jingle:1\""
188      " action=\"" + action + "\""
189      " sid=\"" + kSessionId + "\""
190      ">"
191      + content +
192      "</jingle>";
193}
194
195std::string JingleInitiateActionXml(const std::string& content) {
196  return "<jingle"
197      " xmlns=\"urn:xmpp:jingle:1\""
198      " action=\"session-initiate\""
199      " sid=\"" + kSessionId + "\""
200      " initiator=\"" + kInitiator + "\""
201      ">"
202      + content +
203      "</jingle>";
204}
205
206std::string JingleGroupInfoXml(const std::string& content_name_a,
207                               const std::string& content_name_b) {
208  std::string group_info = "<jin:group"
209      " type=\"BUNDLE\""
210      " xmlns:jin=\"google:jingle\""
211      ">";
212  if (!content_name_a.empty())
213    group_info += "<content name=\"" + content_name_a + "\""
214    "/>";
215  if (!content_name_b.empty())
216    group_info += "<content name=\"" + content_name_b + "\""
217    "/>";
218  group_info += "</jin:group>";
219  return group_info;
220}
221
222
223std::string JingleEmptyContentXml(const std::string& content_name,
224                                  const std::string& content_type,
225                                  const std::string& transport_type) {
226  return "<content"
227      " name=\"" + content_name + "\""
228      " creator=\"initiator\""
229      ">"
230      "<description"
231      " xmlns=\"" + content_type + "\""
232      "/>"
233      "<transport"
234      " xmlns=\"" + transport_type + "\""
235      "/>"
236      "</content>";
237}
238
239std::string JingleContentXml(const std::string& content_name,
240                             const std::string& content_type,
241                             const std::string& transport_type,
242                             const std::string& transport_main) {
243  std::string transport = transport_type.empty() ? "" :
244      "<transport"
245      " xmlns=\"" + transport_type + "\""
246      ">"
247      + transport_main +
248      "</transport>";
249
250  return"<content"
251      " name=\"" + content_name + "\""
252      " creator=\"initiator\""
253      ">"
254      "<description"
255      " xmlns=\"" + content_type + "\""
256      "/>"
257      + transport +
258      "</content>";
259}
260
261std::string JingleTransportContentXml(const std::string& content_name,
262                                      const std::string& transport_type,
263                                      const std::string& content) {
264  return "<content"
265      " name=\"" + content_name + "\""
266      " creator=\"initiator\""
267      ">"
268      "<transport"
269      " xmlns=\"" + transport_type + "\""
270      ">"
271      + content +
272      "</transport>"
273      "</content>";
274}
275
276std::string GingleInitiateXml(const std::string& content_type) {
277  return GingleSessionXml(
278      "initiate",
279      GingleDescriptionXml(content_type));
280}
281
282std::string JingleInitiateXml(const std::string& content_name_a,
283                              const std::string& content_type_a,
284                              const std::string& content_name_b,
285                              const std::string& content_type_b,
286                              bool bundle = false) {
287  std::string content_xml;
288  if (content_name_b.empty()) {
289    content_xml = JingleEmptyContentXml(
290        content_name_a, content_type_a, kTransportType);
291  } else {
292    content_xml = JingleEmptyContentXml(
293           content_name_a, content_type_a, kTransportType) +
294       JingleEmptyContentXml(
295           content_name_b, content_type_b, kTransportType);
296    if (bundle) {
297      content_xml += JingleGroupInfoXml(content_name_a, content_name_b);
298    }
299  }
300  return JingleInitiateActionXml(content_xml);
301}
302
303std::string GingleAcceptXml(const std::string& content_type) {
304  return GingleSessionXml(
305      "accept",
306      GingleDescriptionXml(content_type));
307}
308
309std::string JingleAcceptXml(const std::string& content_name_a,
310                            const std::string& content_type_a,
311                            const std::string& content_name_b,
312                            const std::string& content_type_b,
313                            bool bundle = false) {
314  std::string content_xml;
315  if (content_name_b.empty()) {
316    content_xml = JingleEmptyContentXml(
317        content_name_a, content_type_a, kTransportType);
318  } else {
319    content_xml = JingleEmptyContentXml(
320        content_name_a, content_type_a, kTransportType) +
321        JingleEmptyContentXml(
322            content_name_b, content_type_b, kTransportType);
323  }
324  if (bundle) {
325    content_xml += JingleGroupInfoXml(content_name_a, content_name_b);
326  }
327
328  return JingleActionXml("session-accept", content_xml);
329}
330
331std::string Gingle2CandidatesXml(const std::string& channel_name,
332                                 int port_index0,
333                                 int port_index1) {
334  return GingleSessionXml(
335      "candidates",
336      P2pCandidateXml(channel_name, port_index0) +
337      P2pCandidateXml(channel_name, port_index1));
338}
339
340std::string Gingle4CandidatesXml(const std::string& channel_name_a,
341                                 int port_index0,
342                                 int port_index1,
343                                 const std::string& channel_name_b,
344                                 int port_index2,
345                                 int port_index3) {
346  return GingleSessionXml(
347      "candidates",
348      P2pCandidateXml(channel_name_a, port_index0) +
349      P2pCandidateXml(channel_name_a, port_index1) +
350      P2pCandidateXml(channel_name_b, port_index2) +
351      P2pCandidateXml(channel_name_b, port_index3));
352}
353
354std::string Jingle2TransportInfoXml(const std::string& content_name,
355                                    const std::string& channel_name,
356                                    int port_index0,
357                                    int port_index1) {
358  return JingleActionXml(
359      "transport-info",
360      JingleTransportContentXml(
361          content_name, kTransportType,
362          P2pCandidateXml(channel_name, port_index0) +
363          P2pCandidateXml(channel_name, port_index1)));
364}
365
366std::string Jingle4TransportInfoXml(const std::string& content_name,
367                                    const std::string& channel_name_a,
368                                    int port_index0,
369                                    int port_index1,
370                                    const std::string& channel_name_b,
371                                    int port_index2,
372                                    int port_index3) {
373  return JingleActionXml(
374      "transport-info",
375      JingleTransportContentXml(
376          content_name, kTransportType,
377          P2pCandidateXml(channel_name_a, port_index0) +
378          P2pCandidateXml(channel_name_a, port_index1) +
379          P2pCandidateXml(channel_name_b, port_index2) +
380          P2pCandidateXml(channel_name_b, port_index3)));
381}
382
383std::string JingleDescriptionInfoXml(const std::string& content_name,
384                                     const std::string& content_type) {
385  return JingleActionXml(
386      "description-info",
387      JingleContentXml(content_name, content_type, "", ""));
388}
389
390std::string GingleRejectXml(const std::string& reason) {
391  return GingleSessionXml(
392      "reject",
393      "<" + reason + "/>");
394}
395
396std::string JingleTerminateXml(const std::string& reason) {
397    return JingleActionXml(
398        "session-terminate",
399        "<reason><" + reason + "/></reason>");
400}
401
402std::string GingleTerminateXml(const std::string& reason) {
403  return GingleSessionXml(
404      "terminate",
405      "<" + reason + "/>");
406}
407
408std::string GingleRedirectXml(const std::string& intitiate,
409                              const std::string& target) {
410  return intitiate +
411    "<error code=\"302\" type=\"modify\">"
412    "<redirect xmlns=\"http://www.google.com/session\">"
413    "xmpp:" + target +
414    "</redirect>"
415    "</error>";
416}
417
418std::string JingleRedirectXml(const std::string& intitiate,
419                              const std::string& target) {
420  return intitiate +
421    "<error code=\"302\" type=\"modify\">"
422    "<redirect xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">"
423    "xmpp:" + target +
424    "</redirect>"
425    "</error>";
426}
427
428std::string InitiateXml(SignalingProtocol protocol,
429                        const std::string& gingle_content_type,
430                        const std::string& content_name_a,
431                        const std::string& content_type_a,
432                        const std::string& content_name_b,
433                        const std::string& content_type_b,
434                        bool bundle = false) {
435  switch (protocol) {
436    case PROTOCOL_JINGLE:
437      return JingleInitiateXml(content_name_a, content_type_a,
438                               content_name_b, content_type_b,
439                               bundle);
440    case PROTOCOL_GINGLE:
441      return GingleInitiateXml(gingle_content_type);
442    case PROTOCOL_HYBRID:
443      return JingleInitiateXml(content_name_a, content_type_a,
444                               content_name_b, content_type_b) +
445          GingleInitiateXml(gingle_content_type);
446  }
447  return "";
448}
449
450std::string InitiateXml(SignalingProtocol protocol,
451                        const std::string& content_name,
452                        const std::string& content_type) {
453  return InitiateXml(protocol,
454                     content_type,
455                     content_name, content_type,
456                     "", "");
457}
458
459std::string AcceptXml(SignalingProtocol protocol,
460                      const std::string& gingle_content_type,
461                      const std::string& content_name_a,
462                      const std::string& content_type_a,
463                      const std::string& content_name_b,
464                      const std::string& content_type_b,
465                      bool bundle = false) {
466  switch (protocol) {
467    case PROTOCOL_JINGLE:
468      return JingleAcceptXml(content_name_a, content_type_a,
469                             content_name_b, content_type_b, bundle);
470    case PROTOCOL_GINGLE:
471      return GingleAcceptXml(gingle_content_type);
472    case PROTOCOL_HYBRID:
473      return
474          JingleAcceptXml(content_name_a, content_type_a,
475                          content_name_b, content_type_b) +
476          GingleAcceptXml(gingle_content_type);
477  }
478  return "";
479}
480
481
482std::string AcceptXml(SignalingProtocol protocol,
483                      const std::string& content_name,
484                      const std::string& content_type,
485                      bool bundle = false) {
486  return AcceptXml(protocol,
487                   content_type,
488                   content_name, content_type,
489                   "", "");
490}
491
492std::string TransportInfo2Xml(SignalingProtocol protocol,
493                              const std::string& content_name,
494                              const std::string& channel_name,
495                              int port_index0,
496                              int port_index1) {
497  switch (protocol) {
498    case PROTOCOL_JINGLE:
499      return Jingle2TransportInfoXml(
500          content_name,
501          channel_name, port_index0, port_index1);
502    case PROTOCOL_GINGLE:
503      return Gingle2CandidatesXml(
504          channel_name, port_index0, port_index1);
505    case PROTOCOL_HYBRID:
506      return
507          Jingle2TransportInfoXml(
508              content_name,
509              channel_name, port_index0, port_index1) +
510          Gingle2CandidatesXml(
511              channel_name, port_index0, port_index1);
512  }
513  return "";
514}
515
516std::string TransportInfo4Xml(SignalingProtocol protocol,
517                              const std::string& content_name,
518                              const std::string& channel_name_a,
519                              int port_index0,
520                              int port_index1,
521                              const std::string& channel_name_b,
522                              int port_index2,
523                              int port_index3) {
524  switch (protocol) {
525    case PROTOCOL_JINGLE:
526      return Jingle4TransportInfoXml(
527          content_name,
528          channel_name_a, port_index0, port_index1,
529          channel_name_b, port_index2, port_index3);
530    case PROTOCOL_GINGLE:
531      return Gingle4CandidatesXml(
532          channel_name_a, port_index0, port_index1,
533          channel_name_b, port_index2, port_index3);
534    case PROTOCOL_HYBRID:
535      return
536          Jingle4TransportInfoXml(
537              content_name,
538              channel_name_a, port_index0, port_index1,
539              channel_name_b, port_index2, port_index3) +
540          Gingle4CandidatesXml(
541              channel_name_a, port_index0, port_index1,
542              channel_name_b, port_index2, port_index3);
543  }
544  return "";
545}
546
547std::string RejectXml(SignalingProtocol protocol,
548                      const std::string& reason) {
549  switch (protocol) {
550    case PROTOCOL_JINGLE:
551      return JingleTerminateXml(reason);
552    case PROTOCOL_GINGLE:
553      return GingleRejectXml(reason);
554    case PROTOCOL_HYBRID:
555      return JingleTerminateXml(reason) +
556          GingleRejectXml(reason);
557  }
558  return "";
559}
560
561std::string TerminateXml(SignalingProtocol protocol,
562                         const std::string& reason) {
563  switch (protocol) {
564    case PROTOCOL_JINGLE:
565      return JingleTerminateXml(reason);
566    case PROTOCOL_GINGLE:
567      return GingleTerminateXml(reason);
568    case PROTOCOL_HYBRID:
569      return JingleTerminateXml(reason) +
570          GingleTerminateXml(reason);
571  }
572  return "";
573}
574
575std::string RedirectXml(SignalingProtocol protocol,
576                        const std::string& initiate,
577                        const std::string& target) {
578  switch (protocol) {
579    case PROTOCOL_JINGLE:
580      return JingleRedirectXml(initiate, target);
581    case PROTOCOL_GINGLE:
582      return GingleRedirectXml(initiate, target);
583    default:
584      break;
585  }
586  return "";
587}
588
589// TODO: Break out and join with fakeportallocator.h
590class TestPortAllocatorSession : public cricket::PortAllocatorSession {
591 public:
592  TestPortAllocatorSession(const std::string& content_name,
593                           int component,
594                           const std::string& ice_ufrag,
595                           const std::string& ice_pwd,
596                           const int port_offset)
597      : PortAllocatorSession(content_name, component, ice_ufrag, ice_pwd, 0),
598        port_offset_(port_offset),
599        ports_(kNumPorts),
600        address_("127.0.0.1", 0),
601        network_("network", "unittest",
602                 talk_base::IPAddress(INADDR_LOOPBACK), 8),
603        socket_factory_(talk_base::Thread::Current()),
604        running_(false),
605        port_(28653) {
606    network_.AddIP(address_.ipaddr());
607  }
608
609  ~TestPortAllocatorSession() {
610    for (size_t i = 0; i < ports_.size(); i++)
611      delete ports_[i];
612  }
613
614  virtual void StartGettingPorts() {
615    for (int i = 0; i < kNumPorts; i++) {
616      int index = port_offset_ + i;
617      ports_[i] = cricket::UDPPort::Create(
618          talk_base::Thread::Current(), &socket_factory_,
619          &network_, address_.ipaddr(), GetPort(index), GetPort(index),
620          GetUsername(index), GetPassword(index));
621      AddPort(ports_[i]);
622    }
623    running_ = true;
624  }
625
626  virtual void StopGettingPorts() { running_ = false; }
627  virtual bool IsGettingPorts() { return running_; }
628
629  void AddPort(cricket::Port* port) {
630    port->set_component(component_);
631    port->set_generation(0);
632    port->SignalDestroyed.connect(
633        this, &TestPortAllocatorSession::OnPortDestroyed);
634    port->SignalPortComplete.connect(
635        this, &TestPortAllocatorSession::OnPortComplete);
636    port->PrepareAddress();
637    SignalPortReady(this, port);
638  }
639
640  void OnPortDestroyed(cricket::PortInterface* port) {
641    for (size_t i = 0; i < ports_.size(); i++) {
642      if (ports_[i] == port)
643        ports_[i] = NULL;
644    }
645  }
646
647  void OnPortComplete(cricket::Port* port) {
648    SignalCandidatesReady(this, port->Candidates());
649  }
650
651 private:
652  int port_offset_;
653  std::vector<cricket::Port*> ports_;
654  talk_base::SocketAddress address_;
655  talk_base::Network network_;
656  talk_base::BasicPacketSocketFactory socket_factory_;
657  bool running_;
658  int port_;
659};
660
661class TestPortAllocator : public cricket::PortAllocator {
662 public:
663  TestPortAllocator() : port_offset_(0) {}
664
665  virtual cricket::PortAllocatorSession*
666  CreateSessionInternal(
667                const std::string& content_name,
668                int component,
669                const std::string& ice_ufrag,
670                const std::string& ice_pwd) {
671    port_offset_ += 2;
672    return new TestPortAllocatorSession(content_name, component,
673                                        ice_ufrag, ice_pwd, port_offset_ - 2);
674  }
675
676  int port_offset_;
677};
678
679class TestContentDescription : public cricket::ContentDescription {
680 public:
681  explicit TestContentDescription(const std::string& gingle_content_type,
682                                  const std::string& content_type)
683      : gingle_content_type(gingle_content_type),
684        content_type(content_type) {
685  }
686  virtual ContentDescription* Copy() const {
687    return new TestContentDescription(*this);
688  }
689
690  std::string gingle_content_type;
691  std::string content_type;
692};
693
694cricket::SessionDescription* NewTestSessionDescription(
695    const std::string gingle_content_type,
696    const std::string& content_name_a, const std::string& content_type_a,
697    const std::string& content_name_b, const std::string& content_type_b) {
698
699  cricket::SessionDescription* offer = new cricket::SessionDescription();
700  offer->AddContent(content_name_a, content_type_a,
701                    new TestContentDescription(gingle_content_type,
702                                               content_type_a));
703  cricket::TransportDescription desc(cricket::NS_GINGLE_P2P,
704                                     std::string(), std::string());
705  offer->AddTransportInfo(cricket::TransportInfo(content_name_a, desc));
706
707  if (content_name_a != content_name_b) {
708    offer->AddContent(content_name_b, content_type_b,
709                      new TestContentDescription(gingle_content_type,
710                                                 content_type_b));
711    offer->AddTransportInfo(cricket::TransportInfo(content_name_b, desc));
712  }
713  return offer;
714}
715
716cricket::SessionDescription* NewTestSessionDescription(
717    const std::string& content_name, const std::string& content_type) {
718
719  cricket::SessionDescription* offer = new cricket::SessionDescription();
720  offer->AddContent(content_name, content_type,
721                    new TestContentDescription(content_type,
722                                               content_type));
723  offer->AddTransportInfo(cricket::TransportInfo
724                          (content_name, cricket::TransportDescription(
725                          cricket::NS_GINGLE_P2P,
726                          std::string(), std::string())));
727  return offer;
728}
729
730struct TestSessionClient: public cricket::SessionClient,
731                          public sigslot::has_slots<> {
732 public:
733  TestSessionClient() {
734  }
735
736  ~TestSessionClient() {
737  }
738
739  virtual bool ParseContent(SignalingProtocol protocol,
740                            const buzz::XmlElement* elem,
741                            cricket::ContentDescription** content,
742                            cricket::ParseError* error) {
743    std::string content_type;
744    std::string gingle_content_type;
745    if (protocol == PROTOCOL_GINGLE) {
746      gingle_content_type = elem->Name().Namespace();
747    } else {
748      content_type = elem->Name().Namespace();
749    }
750
751    *content = new TestContentDescription(gingle_content_type, content_type);
752    return true;
753  }
754
755  virtual bool WriteContent(SignalingProtocol protocol,
756                            const cricket::ContentDescription* untyped_content,
757                            buzz::XmlElement** elem,
758                            cricket::WriteError* error) {
759    const TestContentDescription* content =
760        static_cast<const TestContentDescription*>(untyped_content);
761    std::string content_type = (protocol == PROTOCOL_GINGLE ?
762                                content->gingle_content_type :
763                                content->content_type);
764     *elem = new buzz::XmlElement(
765        buzz::QName(content_type, "description"), true);
766    return true;
767  }
768
769  void OnSessionCreate(cricket::Session* session, bool initiate) {
770  }
771
772  void OnSessionDestroy(cricket::Session* session) {
773  }
774};
775
776struct ChannelHandler : sigslot::has_slots<> {
777  explicit ChannelHandler(cricket::TransportChannel* p, const std::string& name)
778    : channel(p), last_readable(false), last_writable(false), data_count(0),
779      last_size(0), name(name) {
780    p->SignalReadableState.connect(this, &ChannelHandler::OnReadableState);
781    p->SignalWritableState.connect(this, &ChannelHandler::OnWritableState);
782    p->SignalReadPacket.connect(this, &ChannelHandler::OnReadPacket);
783  }
784
785  bool writable() const {
786    return last_writable && channel->writable();
787  }
788
789  bool readable() const {
790    return last_readable && channel->readable();
791  }
792
793  void OnReadableState(cricket::TransportChannel* p) {
794    EXPECT_EQ(channel, p);
795    last_readable = channel->readable();
796  }
797
798  void OnWritableState(cricket::TransportChannel* p) {
799    EXPECT_EQ(channel, p);
800    last_writable = channel->writable();
801  }
802
803  void OnReadPacket(cricket::TransportChannel* p, const char* buf,
804                    size_t size, const talk_base::PacketTime& time, int flags) {
805    if (memcmp(buf, name.c_str(), name.size()) != 0)
806      return;  // drop packet if packet doesn't belong to this channel. This
807               // can happen when transport channels are muxed together.
808    buf += name.size();  // Remove channel name from the message.
809    size -= name.size();  // Decrement size by channel name string size.
810    EXPECT_EQ(channel, p);
811    EXPECT_LE(size, sizeof(last_data));
812    data_count += 1;
813    last_size = size;
814    memcpy(last_data, buf, size);
815  }
816
817  void Send(const char* data, size_t size) {
818    talk_base::PacketOptions options;
819    std::string data_with_id(name);
820    data_with_id += data;
821    int result = channel->SendPacket(data_with_id.c_str(), data_with_id.size(),
822                                     options, 0);
823    EXPECT_EQ(static_cast<int>(data_with_id.size()), result);
824  }
825
826  cricket::TransportChannel* channel;
827  bool last_readable, last_writable;
828  int data_count;
829  char last_data[4096];
830  size_t last_size;
831  std::string name;
832};
833
834void PrintStanza(const std::string& message,
835                 const buzz::XmlElement* stanza) {
836  printf("%s: %s\n", message.c_str(), stanza->Str().c_str());
837}
838
839class TestClient : public sigslot::has_slots<> {
840 public:
841  // TODO: Add channel_component_a/b as inputs to the ctor.
842  TestClient(cricket::PortAllocator* port_allocator,
843             int* next_message_id,
844             const std::string& local_name,
845             SignalingProtocol start_protocol,
846             const std::string& content_type,
847             const std::string& content_name_a,
848             const std::string& channel_name_a,
849             const std::string& content_name_b,
850             const std::string& channel_name_b) {
851    Construct(port_allocator, next_message_id, local_name, start_protocol,
852              content_type, content_name_a, channel_name_a,
853              content_name_b, channel_name_b);
854  }
855
856  ~TestClient() {
857    if (session) {
858      session_manager->DestroySession(session);
859      EXPECT_EQ(1U, session_destroyed_count);
860    }
861    delete session_manager;
862    delete client;
863    for (std::deque<buzz::XmlElement*>::iterator it = sent_stanzas.begin();
864         it != sent_stanzas.end(); ++it) {
865      delete *it;
866    }
867  }
868
869  void Construct(cricket::PortAllocator* pa,
870                 int* message_id,
871                 const std::string& lname,
872                 SignalingProtocol protocol,
873                 const std::string& cont_type,
874                 const std::string& cont_name_a,
875                 const std::string& chan_name_a,
876                 const std::string& cont_name_b,
877                 const std::string& chan_name_b) {
878    port_allocator_ = pa;
879    next_message_id = message_id;
880    local_name = lname;
881    start_protocol = protocol;
882    content_type = cont_type;
883    content_name_a = cont_name_a;
884    channel_name_a = chan_name_a;
885    content_name_b = cont_name_b;
886    channel_name_b = chan_name_b;
887    session_created_count = 0;
888    session_destroyed_count = 0;
889    session_remote_description_update_count = 0;
890    new_local_description = false;
891    new_remote_description = false;
892    last_content_action = cricket::CA_OFFER;
893    last_content_source = cricket::CS_LOCAL;
894    session = NULL;
895    last_session_state = cricket::BaseSession::STATE_INIT;
896    blow_up_on_error = true;
897    error_count = 0;
898
899    session_manager = new cricket::SessionManager(port_allocator_);
900    session_manager->SignalSessionCreate.connect(
901        this, &TestClient::OnSessionCreate);
902    session_manager->SignalSessionDestroy.connect(
903        this, &TestClient::OnSessionDestroy);
904    session_manager->SignalOutgoingMessage.connect(
905        this, &TestClient::OnOutgoingMessage);
906
907    client = new TestSessionClient();
908    session_manager->AddClient(content_type, client);
909    EXPECT_EQ(client, session_manager->GetClient(content_type));
910  }
911
912  uint32 sent_stanza_count() const {
913    return static_cast<uint32>(sent_stanzas.size());
914  }
915
916  const buzz::XmlElement* stanza() const {
917    return last_expected_sent_stanza.get();
918  }
919
920  cricket::BaseSession::State session_state() const {
921    EXPECT_EQ(last_session_state, session->state());
922    return session->state();
923  }
924
925  void SetSessionState(cricket::BaseSession::State state) {
926    session->SetState(state);
927    EXPECT_EQ_WAIT(last_session_state, session->state(), kEventTimeout);
928  }
929
930  void CreateSession() {
931    session_manager->CreateSession(local_name, content_type);
932  }
933
934  void DeliverStanza(const buzz::XmlElement* stanza) {
935    session_manager->OnIncomingMessage(stanza);
936  }
937
938  void DeliverStanza(const std::string& str) {
939    buzz::XmlElement* stanza = buzz::XmlElement::ForStr(str);
940    session_manager->OnIncomingMessage(stanza);
941    delete stanza;
942  }
943
944  void DeliverAckToLastStanza() {
945    const buzz::XmlElement* orig_stanza = stanza();
946    const buzz::XmlElement* response_stanza =
947        buzz::XmlElement::ForStr(IqAck(orig_stanza->Attr(buzz::QN_IQ), "", ""));
948    session_manager->OnIncomingResponse(orig_stanza, response_stanza);
949    delete response_stanza;
950  }
951
952  void ExpectSentStanza(const std::string& expected) {
953    EXPECT_TRUE(!sent_stanzas.empty()) <<
954        "Found no stanza when expected " << expected;
955
956    last_expected_sent_stanza.reset(sent_stanzas.front());
957    sent_stanzas.pop_front();
958
959    std::string actual = last_expected_sent_stanza->Str();
960    EXPECT_EQ(expected, actual);
961  }
962
963  void SkipUnsentStanza() {
964    GetNextOutgoingMessageID();
965  }
966
967  bool HasTransport(const std::string& content_name) const {
968    ASSERT(session != NULL);
969    const cricket::Transport* transport = session->GetTransport(content_name);
970    return transport != NULL && (kTransportType == transport->type());
971  }
972
973  bool HasChannel(const std::string& content_name,
974                  int component) const {
975    ASSERT(session != NULL);
976    const cricket::TransportChannel* channel =
977        session->GetChannel(content_name, component);
978    return channel != NULL && (component == channel->component());
979  }
980
981  cricket::TransportChannel* GetChannel(const std::string& content_name,
982                                        int component) const {
983    ASSERT(session != NULL);
984    return session->GetChannel(content_name, component);
985  }
986
987  void OnSessionCreate(cricket::Session* created_session, bool initiate) {
988    session_created_count += 1;
989
990    session = created_session;
991    session->set_current_protocol(start_protocol);
992    session->SignalState.connect(this, &TestClient::OnSessionState);
993    session->SignalError.connect(this, &TestClient::OnSessionError);
994    session->SignalRemoteDescriptionUpdate.connect(
995        this, &TestClient::OnSessionRemoteDescriptionUpdate);
996    session->SignalNewLocalDescription.connect(
997        this, &TestClient::OnNewLocalDescription);
998    session->SignalNewRemoteDescription.connect(
999        this, &TestClient::OnNewRemoteDescription);
1000
1001    CreateChannels();
1002  }
1003
1004  void OnSessionDestroy(cricket::Session *session) {
1005    session_destroyed_count += 1;
1006  }
1007
1008  void OnSessionState(cricket::BaseSession* session,
1009                      cricket::BaseSession::State state) {
1010    // EXPECT_EQ does not allow use of this, hence the tmp variable.
1011    cricket::BaseSession* tmp = this->session;
1012    EXPECT_EQ(tmp, session);
1013    last_session_state = state;
1014  }
1015
1016  void OnSessionError(cricket::BaseSession* session,
1017                      cricket::BaseSession::Error error) {
1018    // EXPECT_EQ does not allow use of this, hence the tmp variable.
1019    cricket::BaseSession* tmp = this->session;
1020    EXPECT_EQ(tmp, session);
1021    if (blow_up_on_error) {
1022      EXPECT_TRUE(false);
1023    } else {
1024      error_count++;
1025    }
1026  }
1027
1028  void OnSessionRemoteDescriptionUpdate(cricket::BaseSession* session,
1029      const cricket::ContentInfos& contents) {
1030    session_remote_description_update_count++;
1031  }
1032
1033  void OnNewLocalDescription(cricket::BaseSession* session,
1034                             cricket::ContentAction action) {
1035    new_local_description = true;
1036    last_content_action = action;
1037    last_content_source = cricket::CS_LOCAL;
1038  }
1039
1040  void OnNewRemoteDescription(cricket::BaseSession* session,
1041                              cricket::ContentAction action) {
1042    new_remote_description = true;
1043    last_content_action = action;
1044    last_content_source = cricket::CS_REMOTE;
1045  }
1046
1047  void PrepareCandidates() {
1048    session_manager->OnSignalingReady();
1049  }
1050
1051  void OnOutgoingMessage(cricket::SessionManager* manager,
1052                         const buzz::XmlElement* stanza) {
1053    buzz::XmlElement* elem = new buzz::XmlElement(*stanza);
1054    EXPECT_TRUE(elem->Name() == buzz::QN_IQ);
1055    EXPECT_TRUE(elem->HasAttr(buzz::QN_TO));
1056    EXPECT_FALSE(elem->HasAttr(buzz::QN_FROM));
1057    EXPECT_TRUE(elem->HasAttr(buzz::QN_TYPE));
1058    EXPECT_TRUE((elem->Attr(buzz::QN_TYPE) == "set") ||
1059                (elem->Attr(buzz::QN_TYPE) == "result") ||
1060                (elem->Attr(buzz::QN_TYPE) == "error"));
1061
1062    elem->SetAttr(buzz::QN_FROM, local_name);
1063    if (elem->Attr(buzz::QN_TYPE) == "set") {
1064      EXPECT_FALSE(elem->HasAttr(buzz::QN_ID));
1065      elem->SetAttr(buzz::QN_ID, GetNextOutgoingMessageID());
1066    }
1067
1068    // Uncommenting this is useful for debugging.
1069    // PrintStanza("OutgoingMessage", elem);
1070    sent_stanzas.push_back(elem);
1071  }
1072
1073  std::string GetNextOutgoingMessageID() {
1074    int message_id = (*next_message_id)++;
1075    std::ostringstream ost;
1076    ost << message_id;
1077    return ost.str();
1078  }
1079
1080  void CreateChannels() {
1081    ASSERT(session != NULL);
1082    // We either have a single content with multiple components (RTP/RTCP), or
1083    // multiple contents with single components, but not both.
1084    int component_a = 1;
1085    int component_b = (content_name_a == content_name_b) ? 2 : 1;
1086    chan_a.reset(new ChannelHandler(
1087        session->CreateChannel(content_name_a, channel_name_a, component_a),
1088        channel_name_a));
1089    chan_b.reset(new ChannelHandler(
1090        session->CreateChannel(content_name_b, channel_name_b, component_b),
1091        channel_name_b));
1092  }
1093
1094  int* next_message_id;
1095  std::string local_name;
1096  SignalingProtocol start_protocol;
1097  std::string content_type;
1098  std::string content_name_a;
1099  std::string channel_name_a;
1100  std::string content_name_b;
1101  std::string channel_name_b;
1102
1103  uint32 session_created_count;
1104  uint32 session_destroyed_count;
1105  uint32 session_remote_description_update_count;
1106  bool new_local_description;
1107  bool new_remote_description;
1108  cricket::ContentAction last_content_action;
1109  cricket::ContentSource last_content_source;
1110  std::deque<buzz::XmlElement*> sent_stanzas;
1111  talk_base::scoped_ptr<buzz::XmlElement> last_expected_sent_stanza;
1112
1113  cricket::SessionManager* session_manager;
1114  TestSessionClient* client;
1115  cricket::PortAllocator* port_allocator_;
1116  cricket::Session* session;
1117  cricket::BaseSession::State last_session_state;
1118  talk_base::scoped_ptr<ChannelHandler> chan_a;
1119  talk_base::scoped_ptr<ChannelHandler> chan_b;
1120  bool blow_up_on_error;
1121  int error_count;
1122};
1123
1124class SessionTest : public testing::Test {
1125 protected:
1126  virtual void SetUp() {
1127    // Seed needed for each test to satisfy expectations.
1128    talk_base::SetRandomTestMode(true);
1129  }
1130
1131  virtual void TearDown() {
1132    talk_base::SetRandomTestMode(false);
1133  }
1134
1135  // Tests sending data between two clients, over two channels.
1136  void TestSendRecv(ChannelHandler* chan1a,
1137                    ChannelHandler* chan1b,
1138                    ChannelHandler* chan2a,
1139                    ChannelHandler* chan2b) {
1140    const char* dat1a = "spamspamspamspamspamspamspambakedbeansspam";
1141    const char* dat2a = "mapssnaebdekabmapsmapsmapsmapsmapsmapsmaps";
1142    const char* dat1b = "Lobster Thermidor a Crevette with a mornay sauce...";
1143    const char* dat2b = "...ecuas yanrom a htiw etteverC a rodimrehT retsboL";
1144
1145    for (int i = 0; i < 20; i++) {
1146      chan1a->Send(dat1a, strlen(dat1a));
1147      chan1b->Send(dat1b, strlen(dat1b));
1148      chan2a->Send(dat2a, strlen(dat2a));
1149      chan2b->Send(dat2b, strlen(dat2b));
1150
1151      EXPECT_EQ_WAIT(i + 1, chan1a->data_count, kEventTimeout);
1152      EXPECT_EQ_WAIT(i + 1, chan1b->data_count, kEventTimeout);
1153      EXPECT_EQ_WAIT(i + 1, chan2a->data_count, kEventTimeout);
1154      EXPECT_EQ_WAIT(i + 1, chan2b->data_count, kEventTimeout);
1155
1156      EXPECT_EQ(strlen(dat2a), chan1a->last_size);
1157      EXPECT_EQ(strlen(dat2b), chan1b->last_size);
1158      EXPECT_EQ(strlen(dat1a), chan2a->last_size);
1159      EXPECT_EQ(strlen(dat1b), chan2b->last_size);
1160
1161      EXPECT_EQ(0, memcmp(chan1a->last_data, dat2a, strlen(dat2a)));
1162      EXPECT_EQ(0, memcmp(chan1b->last_data, dat2b, strlen(dat2b)));
1163      EXPECT_EQ(0, memcmp(chan2a->last_data, dat1a, strlen(dat1a)));
1164      EXPECT_EQ(0, memcmp(chan2b->last_data, dat1b, strlen(dat1b)));
1165    }
1166  }
1167
1168  // Test an initiate from one client to another, each with
1169  // independent initial protocols.  Checks for the correct initiates,
1170  // candidates, and accept messages, and tests that working network
1171  // channels are established.
1172  void TestSession(SignalingProtocol initiator_protocol,
1173                   SignalingProtocol responder_protocol,
1174                   SignalingProtocol resulting_protocol,
1175                   const std::string& gingle_content_type,
1176                   const std::string& content_type,
1177                   const std::string& content_name_a,
1178                   const std::string& channel_name_a,
1179                   const std::string& content_name_b,
1180                   const std::string& channel_name_b,
1181                   const std::string& initiate_xml,
1182                   const std::string& transport_info_a_xml,
1183                   const std::string& transport_info_b_xml,
1184                   const std::string& transport_info_reply_a_xml,
1185                   const std::string& transport_info_reply_b_xml,
1186                   const std::string& accept_xml,
1187                   bool bundle = false) {
1188    talk_base::scoped_ptr<cricket::PortAllocator> allocator(
1189        new TestPortAllocator());
1190    int next_message_id = 0;
1191
1192    talk_base::scoped_ptr<TestClient> initiator(
1193        new TestClient(allocator.get(), &next_message_id,
1194                       kInitiator, initiator_protocol,
1195                       content_type,
1196                       content_name_a,  channel_name_a,
1197                       content_name_b,  channel_name_b));
1198    talk_base::scoped_ptr<TestClient> responder(
1199        new TestClient(allocator.get(), &next_message_id,
1200                       kResponder, responder_protocol,
1201                       content_type,
1202                       content_name_a,  channel_name_a,
1203                       content_name_b,  channel_name_b));
1204
1205    // Create Session and check channels and state.
1206    initiator->CreateSession();
1207    EXPECT_EQ(1U, initiator->session_created_count);
1208    EXPECT_EQ(kSessionId, initiator->session->id());
1209    EXPECT_EQ(initiator->session->local_name(), kInitiator);
1210    EXPECT_EQ(cricket::BaseSession::STATE_INIT,
1211              initiator->session_state());
1212
1213    // See comment in CreateChannels about how we choose component IDs.
1214    int component_a = 1;
1215    int component_b = (content_name_a == content_name_b) ? 2 : 1;
1216    EXPECT_TRUE(initiator->HasTransport(content_name_a));
1217    EXPECT_TRUE(initiator->HasChannel(content_name_a, component_a));
1218    EXPECT_TRUE(initiator->HasTransport(content_name_b));
1219    EXPECT_TRUE(initiator->HasChannel(content_name_b, component_b));
1220
1221    // Initiate and expect initiate message sent.
1222    cricket::SessionDescription* offer = NewTestSessionDescription(
1223        gingle_content_type,
1224        content_name_a, content_type,
1225        content_name_b, content_type);
1226    if (bundle) {
1227      cricket::ContentGroup group(cricket::GROUP_TYPE_BUNDLE);
1228      group.AddContentName(content_name_a);
1229      group.AddContentName(content_name_b);
1230      EXPECT_TRUE(group.HasContentName(content_name_a));
1231      EXPECT_TRUE(group.HasContentName(content_name_b));
1232      offer->AddGroup(group);
1233    }
1234    EXPECT_TRUE(initiator->session->Initiate(kResponder, offer));
1235    EXPECT_EQ(initiator->session->remote_name(), kResponder);
1236    EXPECT_EQ(initiator->session->local_description(), offer);
1237
1238    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1239    EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
1240              initiator->session_state());
1241
1242    initiator->ExpectSentStanza(
1243        IqSet("0", kInitiator, kResponder, initiate_xml));
1244
1245    // Deliver the initiate. Expect ack and session created with
1246    // transports.
1247    responder->DeliverStanza(initiator->stanza());
1248    responder->ExpectSentStanza(
1249        IqAck("0", kResponder, kInitiator));
1250    EXPECT_EQ(0U, responder->sent_stanza_count());
1251
1252    EXPECT_EQ(1U, responder->session_created_count);
1253    EXPECT_EQ(kSessionId, responder->session->id());
1254    EXPECT_EQ(responder->session->local_name(), kResponder);
1255    EXPECT_EQ(responder->session->remote_name(), kInitiator);
1256    EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE,
1257              responder->session_state());
1258
1259    EXPECT_TRUE(responder->HasTransport(content_name_a));
1260    EXPECT_TRUE(responder->HasChannel(content_name_a, component_a));
1261    EXPECT_TRUE(responder->HasTransport(content_name_b));
1262    EXPECT_TRUE(responder->HasChannel(content_name_b, component_b));
1263
1264    // Expect transport-info message from initiator.
1265    // But don't send candidates until initiate ack is received.
1266    initiator->PrepareCandidates();
1267    WAIT(initiator->sent_stanza_count() > 0, 100);
1268    EXPECT_EQ(0U, initiator->sent_stanza_count());
1269    initiator->DeliverAckToLastStanza();
1270    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1271    initiator->ExpectSentStanza(
1272        IqSet("1", kInitiator, kResponder, transport_info_a_xml));
1273
1274    // Deliver transport-info and expect ack.
1275    responder->DeliverStanza(initiator->stanza());
1276    responder->ExpectSentStanza(
1277        IqAck("1", kResponder, kInitiator));
1278
1279    if (!transport_info_b_xml.empty()) {
1280      // Expect second transport-info message from initiator.
1281      EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1282      initiator->ExpectSentStanza(
1283          IqSet("2", kInitiator, kResponder, transport_info_b_xml));
1284      EXPECT_EQ(0U, initiator->sent_stanza_count());
1285
1286      // Deliver second transport-info message and expect ack.
1287      responder->DeliverStanza(initiator->stanza());
1288      responder->ExpectSentStanza(
1289          IqAck("2", kResponder, kInitiator));
1290    } else {
1291      EXPECT_EQ(0U, initiator->sent_stanza_count());
1292      EXPECT_EQ(0U, responder->sent_stanza_count());
1293      initiator->SkipUnsentStanza();
1294    }
1295
1296    // Expect reply transport-info message from responder.
1297    responder->PrepareCandidates();
1298    EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout);
1299    responder->ExpectSentStanza(
1300        IqSet("3", kResponder, kInitiator, transport_info_reply_a_xml));
1301
1302    // Deliver reply transport-info and expect ack.
1303    initiator->DeliverStanza(responder->stanza());
1304    initiator->ExpectSentStanza(
1305        IqAck("3", kInitiator, kResponder));
1306
1307    if (!transport_info_reply_b_xml.empty()) {
1308      // Expect second reply transport-info message from responder.
1309      EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout);
1310      responder->ExpectSentStanza(
1311          IqSet("4", kResponder, kInitiator, transport_info_reply_b_xml));
1312      EXPECT_EQ(0U, responder->sent_stanza_count());
1313
1314      // Deliver second reply transport-info message and expect ack.
1315      initiator->DeliverStanza(responder->stanza());
1316      initiator->ExpectSentStanza(
1317          IqAck("4", kInitiator, kResponder));
1318      EXPECT_EQ(0U, initiator->sent_stanza_count());
1319    } else {
1320      EXPECT_EQ(0U, initiator->sent_stanza_count());
1321      EXPECT_EQ(0U, responder->sent_stanza_count());
1322      responder->SkipUnsentStanza();
1323    }
1324
1325    // The channels should be able to become writable at this point.  This
1326    // requires pinging, so it may take a little while.
1327    EXPECT_TRUE_WAIT(initiator->chan_a->writable() &&
1328                     initiator->chan_a->readable(), kEventTimeout);
1329    EXPECT_TRUE_WAIT(initiator->chan_b->writable() &&
1330                     initiator->chan_b->readable(), kEventTimeout);
1331    EXPECT_TRUE_WAIT(responder->chan_a->writable() &&
1332                     responder->chan_a->readable(), kEventTimeout);
1333    EXPECT_TRUE_WAIT(responder->chan_b->writable() &&
1334                     responder->chan_b->readable(), kEventTimeout);
1335
1336    // Accept the session and expect accept stanza.
1337    cricket::SessionDescription* answer = NewTestSessionDescription(
1338        gingle_content_type,
1339        content_name_a, content_type,
1340        content_name_b, content_type);
1341    if (bundle) {
1342      cricket::ContentGroup group(cricket::GROUP_TYPE_BUNDLE);
1343      group.AddContentName(content_name_a);
1344      group.AddContentName(content_name_b);
1345      EXPECT_TRUE(group.HasContentName(content_name_a));
1346      EXPECT_TRUE(group.HasContentName(content_name_b));
1347      answer->AddGroup(group);
1348    }
1349    EXPECT_TRUE(responder->session->Accept(answer));
1350    EXPECT_EQ(responder->session->local_description(), answer);
1351
1352    responder->ExpectSentStanza(
1353        IqSet("5", kResponder, kInitiator, accept_xml));
1354
1355    EXPECT_EQ(0U, responder->sent_stanza_count());
1356
1357    // Deliver the accept message and expect an ack.
1358    initiator->DeliverStanza(responder->stanza());
1359    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1360    initiator->ExpectSentStanza(
1361        IqAck("5", kInitiator, kResponder));
1362    EXPECT_EQ(0U, initiator->sent_stanza_count());
1363
1364    // Both sessions should be in progress and have functioning
1365    // channels.
1366    EXPECT_EQ(resulting_protocol, initiator->session->current_protocol());
1367    EXPECT_EQ(resulting_protocol, responder->session->current_protocol());
1368    EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
1369                   initiator->session_state(), kEventTimeout);
1370    EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
1371                   responder->session_state(), kEventTimeout);
1372    if (bundle) {
1373      cricket::TransportChannel* initiator_chan_a = initiator->chan_a->channel;
1374      cricket::TransportChannel* initiator_chan_b = initiator->chan_b->channel;
1375
1376      // Since we know these are TransportChannelProxy, type cast it.
1377      cricket::TransportChannelProxy* initiator_proxy_chan_a =
1378          static_cast<cricket::TransportChannelProxy*>(initiator_chan_a);
1379      cricket::TransportChannelProxy* initiator_proxy_chan_b =
1380              static_cast<cricket::TransportChannelProxy*>(initiator_chan_b);
1381      EXPECT_TRUE(initiator_proxy_chan_a->impl() != NULL);
1382      EXPECT_TRUE(initiator_proxy_chan_b->impl() != NULL);
1383      EXPECT_EQ(initiator_proxy_chan_a->impl(), initiator_proxy_chan_b->impl());
1384
1385      cricket::TransportChannel* responder_chan_a = responder->chan_a->channel;
1386      cricket::TransportChannel* responder_chan_b = responder->chan_b->channel;
1387
1388      // Since we know these are TransportChannelProxy, type cast it.
1389      cricket::TransportChannelProxy* responder_proxy_chan_a =
1390          static_cast<cricket::TransportChannelProxy*>(responder_chan_a);
1391      cricket::TransportChannelProxy* responder_proxy_chan_b =
1392              static_cast<cricket::TransportChannelProxy*>(responder_chan_b);
1393      EXPECT_TRUE(responder_proxy_chan_a->impl() != NULL);
1394      EXPECT_TRUE(responder_proxy_chan_b->impl() != NULL);
1395      EXPECT_EQ(responder_proxy_chan_a->impl(), responder_proxy_chan_b->impl());
1396    }
1397    TestSendRecv(initiator->chan_a.get(), initiator->chan_b.get(),
1398                 responder->chan_a.get(), responder->chan_b.get());
1399
1400    if (resulting_protocol == PROTOCOL_JINGLE) {
1401      // Deliver a description-info message to the initiator and check if the
1402      // content description changes.
1403      EXPECT_EQ(0U, initiator->session_remote_description_update_count);
1404
1405      const cricket::SessionDescription* old_session_desc =
1406          initiator->session->remote_description();
1407      const cricket::ContentInfo* old_content_a =
1408          old_session_desc->GetContentByName(content_name_a);
1409      const cricket::ContentDescription* old_content_desc_a =
1410          old_content_a->description;
1411      const cricket::ContentInfo* old_content_b =
1412          old_session_desc->GetContentByName(content_name_b);
1413      const cricket::ContentDescription* old_content_desc_b =
1414          old_content_b->description;
1415      EXPECT_TRUE(old_content_desc_a != NULL);
1416      EXPECT_TRUE(old_content_desc_b != NULL);
1417
1418      LOG(LS_INFO) << "A " << old_content_a->name;
1419      LOG(LS_INFO) << "B " << old_content_b->name;
1420
1421      std::string description_info_xml =
1422          JingleDescriptionInfoXml(content_name_a, content_type);
1423      initiator->DeliverStanza(
1424          IqSet("6", kResponder, kInitiator, description_info_xml));
1425      responder->SkipUnsentStanza();
1426      EXPECT_EQ(1U, initiator->session_remote_description_update_count);
1427
1428      const cricket::SessionDescription* new_session_desc =
1429          initiator->session->remote_description();
1430      const cricket::ContentInfo* new_content_a =
1431          new_session_desc->GetContentByName(content_name_a);
1432      const cricket::ContentDescription* new_content_desc_a =
1433          new_content_a->description;
1434      const cricket::ContentInfo* new_content_b =
1435          new_session_desc->GetContentByName(content_name_b);
1436      const cricket::ContentDescription* new_content_desc_b =
1437          new_content_b->description;
1438      EXPECT_TRUE(new_content_desc_a != NULL);
1439      EXPECT_TRUE(new_content_desc_b != NULL);
1440
1441      // TODO: We used to replace contents from an update, but
1442      // that no longer works with partial updates.  We need to figure out
1443      // a way to merge patial updates into contents.  For now, users of
1444      // Session should listen to SignalRemoteDescriptionUpdate and handle
1445      // updates.  They should not expect remote_description to be the
1446      // latest value.
1447      // See session.cc OnDescriptionInfoMessage.
1448
1449      // EXPECT_NE(old_content_desc_a, new_content_desc_a);
1450
1451      // if (content_name_a != content_name_b) {
1452      //   // If content_name_a != content_name_b, then b's content description
1453      //   // should not have changed since the description-info message only
1454      //   // contained an update for content_name_a.
1455      //   EXPECT_EQ(old_content_desc_b, new_content_desc_b);
1456      // }
1457
1458      EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1459      initiator->ExpectSentStanza(
1460          IqAck("6", kInitiator, kResponder));
1461      EXPECT_EQ(0U, initiator->sent_stanza_count());
1462    } else {
1463      responder->SkipUnsentStanza();
1464    }
1465
1466    initiator->session->Terminate();
1467    initiator->ExpectSentStanza(
1468        IqSet("7", kInitiator, kResponder,
1469              TerminateXml(resulting_protocol,
1470                           cricket::STR_TERMINATE_SUCCESS)));
1471
1472    responder->DeliverStanza(initiator->stanza());
1473    responder->ExpectSentStanza(
1474        IqAck("7", kResponder, kInitiator));
1475    EXPECT_EQ(cricket::BaseSession::STATE_SENTTERMINATE,
1476              initiator->session_state());
1477    EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDTERMINATE,
1478              responder->session_state());
1479  }
1480
1481  // Test an initiate with other content, called "main".
1482  void TestOtherContent(SignalingProtocol initiator_protocol,
1483                        SignalingProtocol responder_protocol,
1484                        SignalingProtocol resulting_protocol) {
1485    std::string content_name = "main";
1486    std::string content_type = "http://oink.splat/session";
1487    std::string content_name_a = content_name;
1488    std::string channel_name_a = "rtp";
1489    std::string content_name_b = content_name;
1490    std::string channel_name_b = "rtcp";
1491    std::string initiate_xml = InitiateXml(
1492        initiator_protocol,
1493        content_name_a, content_type);
1494    std::string transport_info_a_xml = TransportInfo4Xml(
1495        initiator_protocol, content_name,
1496        channel_name_a, 0, 1,
1497        channel_name_b, 2, 3);
1498    std::string transport_info_b_xml = "";
1499    std::string transport_info_reply_a_xml = TransportInfo4Xml(
1500        resulting_protocol, content_name,
1501        channel_name_a, 4, 5,
1502        channel_name_b, 6, 7);
1503    std::string transport_info_reply_b_xml = "";
1504    std::string accept_xml = AcceptXml(
1505        resulting_protocol,
1506        content_name_a, content_type);
1507
1508
1509    TestSession(initiator_protocol, responder_protocol, resulting_protocol,
1510                content_type,
1511                content_type,
1512                content_name_a, channel_name_a,
1513                content_name_b, channel_name_b,
1514                initiate_xml,
1515                transport_info_a_xml, transport_info_b_xml,
1516                transport_info_reply_a_xml, transport_info_reply_b_xml,
1517                accept_xml);
1518  }
1519
1520  // Test an initiate with audio content.
1521  void TestAudioContent(SignalingProtocol initiator_protocol,
1522                        SignalingProtocol responder_protocol,
1523                        SignalingProtocol resulting_protocol) {
1524    std::string gingle_content_type = cricket::NS_GINGLE_AUDIO;
1525    std::string content_name = cricket::CN_AUDIO;
1526    std::string content_type = cricket::NS_JINGLE_RTP;
1527    std::string channel_name_a = "rtp";
1528    std::string channel_name_b = "rtcp";
1529    std::string initiate_xml = InitiateXml(
1530        initiator_protocol,
1531        gingle_content_type,
1532        content_name, content_type,
1533        "", "");
1534    std::string transport_info_a_xml = TransportInfo4Xml(
1535        initiator_protocol, content_name,
1536        channel_name_a, 0, 1,
1537        channel_name_b, 2, 3);
1538    std::string transport_info_b_xml = "";
1539    std::string transport_info_reply_a_xml = TransportInfo4Xml(
1540        resulting_protocol, content_name,
1541        channel_name_a, 4, 5,
1542        channel_name_b, 6, 7);
1543    std::string transport_info_reply_b_xml = "";
1544    std::string accept_xml = AcceptXml(
1545        resulting_protocol,
1546        gingle_content_type,
1547        content_name, content_type,
1548        "", "");
1549
1550
1551    TestSession(initiator_protocol, responder_protocol, resulting_protocol,
1552                gingle_content_type,
1553                content_type,
1554                content_name, channel_name_a,
1555                content_name, channel_name_b,
1556                initiate_xml,
1557                transport_info_a_xml, transport_info_b_xml,
1558                transport_info_reply_a_xml, transport_info_reply_b_xml,
1559                accept_xml);
1560  }
1561
1562  // Since media content is "split" into two contents (audio and
1563  // video), we need to treat it special.
1564  void TestVideoContents(SignalingProtocol initiator_protocol,
1565                         SignalingProtocol responder_protocol,
1566                         SignalingProtocol resulting_protocol) {
1567    std::string content_type = cricket::NS_JINGLE_RTP;
1568    std::string gingle_content_type = cricket::NS_GINGLE_VIDEO;
1569    std::string content_name_a = cricket::CN_AUDIO;
1570    std::string channel_name_a = "rtp";
1571    std::string content_name_b = cricket::CN_VIDEO;
1572    std::string channel_name_b = "video_rtp";
1573
1574    std::string initiate_xml = InitiateXml(
1575        initiator_protocol,
1576        gingle_content_type,
1577        content_name_a, content_type,
1578        content_name_b, content_type);
1579    std::string transport_info_a_xml = TransportInfo2Xml(
1580        initiator_protocol, content_name_a,
1581        channel_name_a, 0, 1);
1582    std::string transport_info_b_xml = TransportInfo2Xml(
1583        initiator_protocol, content_name_b,
1584        channel_name_b, 2, 3);
1585    std::string transport_info_reply_a_xml = TransportInfo2Xml(
1586        resulting_protocol, content_name_a,
1587        channel_name_a, 4, 5);
1588    std::string transport_info_reply_b_xml = TransportInfo2Xml(
1589        resulting_protocol, content_name_b,
1590        channel_name_b, 6, 7);
1591    std::string accept_xml = AcceptXml(
1592        resulting_protocol,
1593        gingle_content_type,
1594        content_name_a, content_type,
1595        content_name_b, content_type);
1596
1597    TestSession(initiator_protocol, responder_protocol, resulting_protocol,
1598                gingle_content_type,
1599                content_type,
1600                content_name_a, channel_name_a,
1601                content_name_b, channel_name_b,
1602                initiate_xml,
1603                transport_info_a_xml, transport_info_b_xml,
1604                transport_info_reply_a_xml, transport_info_reply_b_xml,
1605                accept_xml);
1606  }
1607
1608  void TestBadRedirect(SignalingProtocol protocol) {
1609    std::string content_name = "main";
1610    std::string content_type = "http://oink.splat/session";
1611    std::string channel_name_a = "chana";
1612    std::string channel_name_b = "chanb";
1613    std::string initiate_xml = InitiateXml(
1614        protocol, content_name, content_type);
1615    std::string transport_info_xml = TransportInfo4Xml(
1616        protocol, content_name,
1617        channel_name_a, 0, 1,
1618        channel_name_b, 2, 3);
1619    std::string transport_info_reply_xml = TransportInfo4Xml(
1620        protocol, content_name,
1621        channel_name_a, 4, 5,
1622        channel_name_b, 6, 7);
1623    std::string accept_xml = AcceptXml(
1624        protocol, content_name, content_type);
1625    std::string responder_full = kResponder + "/full";
1626
1627    talk_base::scoped_ptr<cricket::PortAllocator> allocator(
1628        new TestPortAllocator());
1629    int next_message_id = 0;
1630
1631    talk_base::scoped_ptr<TestClient> initiator(
1632        new TestClient(allocator.get(), &next_message_id,
1633                       kInitiator, protocol,
1634                       content_type,
1635                       content_name, channel_name_a,
1636                       content_name, channel_name_b));
1637
1638    talk_base::scoped_ptr<TestClient> responder(
1639        new TestClient(allocator.get(), &next_message_id,
1640                       responder_full, protocol,
1641                       content_type,
1642                       content_name,  channel_name_a,
1643                       content_name,  channel_name_b));
1644
1645    // Create Session and check channels and state.
1646    initiator->CreateSession();
1647    EXPECT_EQ(1U, initiator->session_created_count);
1648    EXPECT_EQ(kSessionId, initiator->session->id());
1649    EXPECT_EQ(initiator->session->local_name(), kInitiator);
1650    EXPECT_EQ(cricket::BaseSession::STATE_INIT,
1651              initiator->session_state());
1652
1653    EXPECT_TRUE(initiator->HasChannel(content_name, 1));
1654    EXPECT_TRUE(initiator->HasChannel(content_name, 2));
1655
1656    // Initiate and expect initiate message sent.
1657    cricket::SessionDescription* offer = NewTestSessionDescription(
1658        content_name, content_type);
1659    EXPECT_TRUE(initiator->session->Initiate(kResponder, offer));
1660    EXPECT_EQ(initiator->session->remote_name(), kResponder);
1661    EXPECT_EQ(initiator->session->local_description(), offer);
1662
1663    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1664    EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
1665              initiator->session_state());
1666    initiator->ExpectSentStanza(
1667        IqSet("0", kInitiator, kResponder, initiate_xml));
1668
1669    // Expect transport-info message from initiator.
1670    initiator->DeliverAckToLastStanza();
1671    initiator->PrepareCandidates();
1672    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1673    initiator->ExpectSentStanza(
1674        IqSet("1", kInitiator, kResponder, transport_info_xml));
1675
1676    // Send an unauthorized redirect to the initiator and expect it be ignored.
1677    initiator->blow_up_on_error = false;
1678    const buzz::XmlElement* initiate_stanza = initiator->stanza();
1679    talk_base::scoped_ptr<buzz::XmlElement> redirect_stanza(
1680        buzz::XmlElement::ForStr(
1681            IqError("ER", kResponder, kInitiator,
1682                    RedirectXml(protocol, initiate_xml, "not@allowed.com"))));
1683    initiator->session_manager->OnFailedSend(
1684        initiate_stanza, redirect_stanza.get());
1685    EXPECT_EQ(initiator->session->remote_name(), kResponder);
1686    initiator->blow_up_on_error = true;
1687    EXPECT_EQ(initiator->error_count, 1);
1688  }
1689
1690  void TestGoodRedirect(SignalingProtocol protocol) {
1691    std::string content_name = "main";
1692    std::string content_type = "http://oink.splat/session";
1693    std::string channel_name_a = "chana";
1694    std::string channel_name_b = "chanb";
1695    std::string initiate_xml = InitiateXml(
1696        protocol, content_name, content_type);
1697    std::string transport_info_xml = TransportInfo4Xml(
1698        protocol, content_name,
1699        channel_name_a, 0, 1,
1700        channel_name_b, 2, 3);
1701    std::string transport_info_reply_xml = TransportInfo4Xml(
1702        protocol, content_name,
1703        channel_name_a, 4, 5,
1704        channel_name_b, 6, 7);
1705    std::string accept_xml = AcceptXml(
1706        protocol, content_name, content_type);
1707    std::string responder_full = kResponder + "/full";
1708
1709    talk_base::scoped_ptr<cricket::PortAllocator> allocator(
1710        new TestPortAllocator());
1711    int next_message_id = 0;
1712
1713    talk_base::scoped_ptr<TestClient> initiator(
1714        new TestClient(allocator.get(), &next_message_id,
1715                       kInitiator, protocol,
1716                       content_type,
1717                       content_name, channel_name_a,
1718                       content_name, channel_name_b));
1719
1720    talk_base::scoped_ptr<TestClient> responder(
1721        new TestClient(allocator.get(), &next_message_id,
1722                       responder_full, protocol,
1723                       content_type,
1724                       content_name,  channel_name_a,
1725                       content_name,  channel_name_b));
1726
1727    // Create Session and check channels and state.
1728    initiator->CreateSession();
1729    EXPECT_EQ(1U, initiator->session_created_count);
1730    EXPECT_EQ(kSessionId, initiator->session->id());
1731    EXPECT_EQ(initiator->session->local_name(), kInitiator);
1732    EXPECT_EQ(cricket::BaseSession::STATE_INIT,
1733              initiator->session_state());
1734
1735    EXPECT_TRUE(initiator->HasChannel(content_name, 1));
1736    EXPECT_TRUE(initiator->HasChannel(content_name, 2));
1737
1738    // Initiate and expect initiate message sent.
1739    cricket::SessionDescription* offer = NewTestSessionDescription(
1740        content_name, content_type);
1741    EXPECT_TRUE(initiator->session->Initiate(kResponder, offer));
1742    EXPECT_EQ(initiator->session->remote_name(), kResponder);
1743    EXPECT_EQ(initiator->session->local_description(), offer);
1744
1745    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1746    EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
1747              initiator->session_state());
1748    initiator->ExpectSentStanza(
1749        IqSet("0", kInitiator, kResponder, initiate_xml));
1750
1751    // Expect transport-info message from initiator.
1752    initiator->DeliverAckToLastStanza();
1753    initiator->PrepareCandidates();
1754    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1755    initiator->ExpectSentStanza(
1756        IqSet("1", kInitiator, kResponder, transport_info_xml));
1757
1758    // Send a redirect to the initiator and expect all of the message
1759    // to be resent.
1760    const buzz::XmlElement* initiate_stanza = initiator->stanza();
1761    talk_base::scoped_ptr<buzz::XmlElement> redirect_stanza(
1762        buzz::XmlElement::ForStr(
1763            IqError("ER2", kResponder, kInitiator,
1764                    RedirectXml(protocol, initiate_xml, responder_full))));
1765    initiator->session_manager->OnFailedSend(
1766        initiate_stanza, redirect_stanza.get());
1767    EXPECT_EQ(initiator->session->remote_name(), responder_full);
1768
1769    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1770    initiator->ExpectSentStanza(
1771        IqSet("2", kInitiator, responder_full, initiate_xml));
1772    initiator->ExpectSentStanza(
1773        IqSet("3", kInitiator, responder_full, transport_info_xml));
1774
1775    // Deliver the initiate. Expect ack and session created with
1776    // transports.
1777    responder->DeliverStanza(
1778        IqSet("2", kInitiator, responder_full, initiate_xml));
1779    responder->ExpectSentStanza(
1780        IqAck("2", responder_full, kInitiator));
1781    EXPECT_EQ(0U, responder->sent_stanza_count());
1782
1783    EXPECT_EQ(1U, responder->session_created_count);
1784    EXPECT_EQ(kSessionId, responder->session->id());
1785    EXPECT_EQ(responder->session->local_name(), responder_full);
1786    EXPECT_EQ(responder->session->remote_name(), kInitiator);
1787    EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE,
1788              responder->session_state());
1789
1790    EXPECT_TRUE(responder->HasChannel(content_name, 1));
1791    EXPECT_TRUE(responder->HasChannel(content_name, 2));
1792
1793    // Deliver transport-info and expect ack.
1794    responder->DeliverStanza(
1795        IqSet("3", kInitiator, responder_full, transport_info_xml));
1796    responder->ExpectSentStanza(
1797        IqAck("3", responder_full, kInitiator));
1798
1799    // Expect reply transport-infos sent to new remote JID
1800    responder->PrepareCandidates();
1801    EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout);
1802    responder->ExpectSentStanza(
1803        IqSet("4", responder_full, kInitiator, transport_info_reply_xml));
1804
1805    initiator->DeliverStanza(responder->stanza());
1806    initiator->ExpectSentStanza(
1807        IqAck("4", kInitiator, responder_full));
1808
1809    // The channels should be able to become writable at this point.  This
1810    // requires pinging, so it may take a little while.
1811    EXPECT_TRUE_WAIT(initiator->chan_a->writable() &&
1812                     initiator->chan_a->readable(), kEventTimeout);
1813    EXPECT_TRUE_WAIT(initiator->chan_b->writable() &&
1814                     initiator->chan_b->readable(), kEventTimeout);
1815    EXPECT_TRUE_WAIT(responder->chan_a->writable() &&
1816                     responder->chan_a->readable(), kEventTimeout);
1817    EXPECT_TRUE_WAIT(responder->chan_b->writable() &&
1818                     responder->chan_b->readable(), kEventTimeout);
1819
1820    // Accept the session and expect accept stanza.
1821    cricket::SessionDescription* answer = NewTestSessionDescription(
1822        content_name, content_type);
1823    EXPECT_TRUE(responder->session->Accept(answer));
1824    EXPECT_EQ(responder->session->local_description(), answer);
1825
1826    responder->ExpectSentStanza(
1827        IqSet("5", responder_full, kInitiator, accept_xml));
1828    EXPECT_EQ(0U, responder->sent_stanza_count());
1829
1830    // Deliver the accept message and expect an ack.
1831    initiator->DeliverStanza(responder->stanza());
1832    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1833    initiator->ExpectSentStanza(
1834        IqAck("5", kInitiator, responder_full));
1835    EXPECT_EQ(0U, initiator->sent_stanza_count());
1836
1837    // Both sessions should be in progress and have functioning
1838    // channels.
1839    EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
1840                   initiator->session_state(), kEventTimeout);
1841    EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
1842                   responder->session_state(), kEventTimeout);
1843    TestSendRecv(initiator->chan_a.get(), initiator->chan_b.get(),
1844                 responder->chan_a.get(), responder->chan_b.get());
1845  }
1846
1847  void TestCandidatesInInitiateAndAccept(const std::string& test_name) {
1848    std::string content_name = "main";
1849    std::string content_type = "http://oink.splat/session";
1850    std::string channel_name_a = "rtp";
1851    std::string channel_name_b = "rtcp";
1852    cricket::SignalingProtocol protocol = PROTOCOL_JINGLE;
1853
1854    talk_base::scoped_ptr<cricket::PortAllocator> allocator(
1855        new TestPortAllocator());
1856    int next_message_id = 0;
1857
1858    talk_base::scoped_ptr<TestClient> initiator(
1859        new TestClient(allocator.get(), &next_message_id,
1860                       kInitiator, protocol,
1861                       content_type,
1862                       content_name,  channel_name_a,
1863                       content_name,  channel_name_b));
1864
1865    talk_base::scoped_ptr<TestClient> responder(
1866        new TestClient(allocator.get(), &next_message_id,
1867                       kResponder, protocol,
1868                       content_type,
1869                       content_name,  channel_name_a,
1870                       content_name,  channel_name_b));
1871
1872    // Create Session and check channels and state.
1873    initiator->CreateSession();
1874    EXPECT_TRUE(initiator->HasTransport(content_name));
1875    EXPECT_TRUE(initiator->HasChannel(content_name, 1));
1876    EXPECT_TRUE(initiator->HasTransport(content_name));
1877    EXPECT_TRUE(initiator->HasChannel(content_name, 2));
1878
1879    // Initiate and expect initiate message sent.
1880    cricket::SessionDescription* offer = NewTestSessionDescription(
1881        content_name, content_type);
1882    EXPECT_TRUE(initiator->session->Initiate(kResponder, offer));
1883
1884    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1885    EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
1886              initiator->session_state());
1887    initiator->ExpectSentStanza(
1888        IqSet("0", kInitiator, kResponder,
1889              InitiateXml(protocol, content_name, content_type)));
1890
1891    // Fake the delivery the initiate and candidates together.
1892    responder->DeliverStanza(
1893        IqSet("A", kInitiator, kResponder,
1894            JingleInitiateActionXml(
1895                JingleContentXml(
1896                    content_name, content_type, kTransportType,
1897                    P2pCandidateXml(channel_name_a, 0) +
1898                    P2pCandidateXml(channel_name_a, 1) +
1899                    P2pCandidateXml(channel_name_b, 2) +
1900                    P2pCandidateXml(channel_name_b, 3)))));
1901    responder->ExpectSentStanza(
1902        IqAck("A", kResponder, kInitiator));
1903    EXPECT_EQ(0U, responder->sent_stanza_count());
1904
1905    EXPECT_EQ(1U, responder->session_created_count);
1906    EXPECT_EQ(kSessionId, responder->session->id());
1907    EXPECT_EQ(responder->session->local_name(), kResponder);
1908    EXPECT_EQ(responder->session->remote_name(), kInitiator);
1909    EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE,
1910              responder->session_state());
1911
1912    EXPECT_TRUE(responder->HasTransport(content_name));
1913    EXPECT_TRUE(responder->HasChannel(content_name, 1));
1914    EXPECT_TRUE(responder->HasTransport(content_name));
1915    EXPECT_TRUE(responder->HasChannel(content_name, 2));
1916
1917    // Expect transport-info message from initiator.
1918    // But don't send candidates until initiate ack is received.
1919    initiator->DeliverAckToLastStanza();
1920    initiator->PrepareCandidates();
1921    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1922    initiator->ExpectSentStanza(
1923        IqSet("1", kInitiator, kResponder,
1924              TransportInfo4Xml(protocol, content_name,
1925                                channel_name_a, 0, 1,
1926                                channel_name_b, 2, 3)));
1927
1928    responder->PrepareCandidates();
1929    EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout);
1930    responder->ExpectSentStanza(
1931        IqSet("2", kResponder, kInitiator,
1932              TransportInfo4Xml(protocol, content_name,
1933                                channel_name_a, 4, 5,
1934                                channel_name_b, 6, 7)));
1935
1936    // Accept the session and expect accept stanza.
1937    cricket::SessionDescription* answer = NewTestSessionDescription(
1938        content_name, content_type);
1939    EXPECT_TRUE(responder->session->Accept(answer));
1940
1941    responder->ExpectSentStanza(
1942        IqSet("3", kResponder, kInitiator,
1943              AcceptXml(protocol, content_name, content_type)));
1944    EXPECT_EQ(0U, responder->sent_stanza_count());
1945
1946    // Fake the delivery the accept and candidates together.
1947    initiator->DeliverStanza(
1948        IqSet("B", kResponder, kInitiator,
1949            JingleActionXml("session-accept",
1950                JingleContentXml(
1951                    content_name, content_type, kTransportType,
1952                    P2pCandidateXml(channel_name_a, 4) +
1953                    P2pCandidateXml(channel_name_a, 5) +
1954                    P2pCandidateXml(channel_name_b, 6) +
1955                    P2pCandidateXml(channel_name_b, 7)))));
1956    EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1957    initiator->ExpectSentStanza(
1958        IqAck("B", kInitiator, kResponder));
1959    EXPECT_EQ(0U, initiator->sent_stanza_count());
1960
1961    // The channels should be able to become writable at this point.  This
1962    // requires pinging, so it may take a little while.
1963    EXPECT_TRUE_WAIT(initiator->chan_a->writable() &&
1964                     initiator->chan_a->readable(), kEventTimeout);
1965    EXPECT_TRUE_WAIT(initiator->chan_b->writable() &&
1966                     initiator->chan_b->readable(), kEventTimeout);
1967    EXPECT_TRUE_WAIT(responder->chan_a->writable() &&
1968                     responder->chan_a->readable(), kEventTimeout);
1969    EXPECT_TRUE_WAIT(responder->chan_b->writable() &&
1970                     responder->chan_b->readable(), kEventTimeout);
1971
1972
1973    // Both sessions should be in progress and have functioning
1974    // channels.
1975    EXPECT_EQ(protocol, initiator->session->current_protocol());
1976    EXPECT_EQ(protocol, responder->session->current_protocol());
1977    EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
1978                   initiator->session_state(), kEventTimeout);
1979    EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
1980                   responder->session_state(), kEventTimeout);
1981    TestSendRecv(initiator->chan_a.get(), initiator->chan_b.get(),
1982                 responder->chan_a.get(), responder->chan_b.get());
1983  }
1984
1985  // Tests that when an initiator terminates right after initiate,
1986  // everything behaves correctly.
1987  void TestEarlyTerminationFromInitiator(SignalingProtocol protocol) {
1988    std::string content_name = "main";
1989    std::string content_type = "http://oink.splat/session";
1990
1991    talk_base::scoped_ptr<cricket::PortAllocator> allocator(
1992        new TestPortAllocator());
1993    int next_message_id = 0;
1994
1995    talk_base::scoped_ptr<TestClient> initiator(
1996        new TestClient(allocator.get(), &next_message_id,
1997                       kInitiator, protocol,
1998                       content_type,
1999                       content_name, "a",
2000                       content_name, "b"));
2001
2002    talk_base::scoped_ptr<TestClient> responder(
2003        new TestClient(allocator.get(), &next_message_id,
2004                       kResponder, protocol,
2005                       content_type,
2006                       content_name,  "a",
2007                       content_name,  "b"));
2008
2009    // Send initiate
2010    initiator->CreateSession();
2011    EXPECT_TRUE(initiator->session->Initiate(
2012        kResponder, NewTestSessionDescription(content_name, content_type)));
2013    initiator->ExpectSentStanza(
2014        IqSet("0", kInitiator, kResponder,
2015              InitiateXml(protocol, content_name, content_type)));
2016    EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
2017              initiator->session_state());
2018
2019    responder->DeliverStanza(initiator->stanza());
2020    responder->ExpectSentStanza(
2021        IqAck("0", kResponder, kInitiator));
2022    EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE,
2023              responder->session_state());
2024
2025    initiator->session->TerminateWithReason(cricket::STR_TERMINATE_ERROR);
2026    initiator->ExpectSentStanza(
2027        IqSet("1", kInitiator, kResponder,
2028              TerminateXml(protocol, cricket::STR_TERMINATE_ERROR)));
2029    EXPECT_EQ(cricket::BaseSession::STATE_SENTTERMINATE,
2030              initiator->session_state());
2031
2032    responder->DeliverStanza(initiator->stanza());
2033    responder->ExpectSentStanza(
2034        IqAck("1", kResponder, kInitiator));
2035    EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDTERMINATE,
2036              responder->session_state());
2037  }
2038
2039  // Tests that when the responder rejects, everything behaves
2040  // correctly.
2041  void TestRejection(SignalingProtocol protocol) {
2042    std::string content_name = "main";
2043    std::string content_type = "http://oink.splat/session";
2044
2045    talk_base::scoped_ptr<cricket::PortAllocator> allocator(
2046        new TestPortAllocator());
2047    int next_message_id = 0;
2048
2049    talk_base::scoped_ptr<TestClient> initiator(
2050        new TestClient(allocator.get(), &next_message_id,
2051                       kInitiator, protocol,
2052                       content_type,
2053                       content_name, "a",
2054                       content_name, "b"));
2055
2056    // Send initiate
2057    initiator->CreateSession();
2058    EXPECT_TRUE(initiator->session->Initiate(
2059        kResponder, NewTestSessionDescription(content_name, content_type)));
2060    initiator->ExpectSentStanza(
2061        IqSet("0", kInitiator, kResponder,
2062              InitiateXml(protocol, content_name, content_type)));
2063    EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
2064              initiator->session_state());
2065
2066    initiator->DeliverStanza(
2067        IqSet("1", kResponder, kInitiator,
2068              RejectXml(protocol, cricket::STR_TERMINATE_ERROR)));
2069    initiator->ExpectSentStanza(
2070        IqAck("1", kInitiator, kResponder));
2071    if (protocol == PROTOCOL_JINGLE) {
2072      EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDTERMINATE,
2073                initiator->session_state());
2074    } else {
2075      EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDREJECT,
2076                initiator->session_state());
2077    }
2078  }
2079
2080  void TestTransportMux() {
2081    SignalingProtocol initiator_protocol = PROTOCOL_JINGLE;
2082    SignalingProtocol responder_protocol = PROTOCOL_JINGLE;
2083    SignalingProtocol resulting_protocol = PROTOCOL_JINGLE;
2084    std::string content_type = cricket::NS_JINGLE_RTP;
2085    std::string gingle_content_type = cricket::NS_GINGLE_VIDEO;
2086    std::string content_name_a = cricket::CN_AUDIO;
2087    std::string channel_name_a = "rtp";
2088    std::string content_name_b = cricket::CN_VIDEO;
2089    std::string channel_name_b = "video_rtp";
2090
2091    std::string initiate_xml = InitiateXml(
2092        initiator_protocol,
2093        gingle_content_type,
2094        content_name_a, content_type,
2095        content_name_b, content_type, true);
2096    std::string transport_info_a_xml = TransportInfo2Xml(
2097        initiator_protocol, content_name_a,
2098        channel_name_a, 0, 1);
2099    std::string transport_info_b_xml = TransportInfo2Xml(
2100        initiator_protocol, content_name_b,
2101        channel_name_b, 2, 3);
2102    std::string transport_info_reply_a_xml = TransportInfo2Xml(
2103        resulting_protocol, content_name_a,
2104        channel_name_a, 4, 5);
2105    std::string transport_info_reply_b_xml = TransportInfo2Xml(
2106        resulting_protocol, content_name_b,
2107        channel_name_b, 6, 7);
2108    std::string accept_xml = AcceptXml(
2109        resulting_protocol,
2110        gingle_content_type,
2111        content_name_a, content_type,
2112        content_name_b, content_type, true);
2113
2114    TestSession(initiator_protocol, responder_protocol, resulting_protocol,
2115                gingle_content_type,
2116                content_type,
2117                content_name_a, channel_name_a,
2118                content_name_b, channel_name_b,
2119                initiate_xml,
2120                transport_info_a_xml, transport_info_b_xml,
2121                transport_info_reply_a_xml, transport_info_reply_b_xml,
2122                accept_xml,
2123                true);
2124  }
2125
2126  void TestSendDescriptionInfo() {
2127    talk_base::scoped_ptr<cricket::PortAllocator> allocator(
2128        new TestPortAllocator());
2129    int next_message_id = 0;
2130
2131    std::string content_name = "content-name";
2132    std::string content_type = "content-type";
2133    talk_base::scoped_ptr<TestClient> initiator(
2134        new TestClient(allocator.get(), &next_message_id,
2135                       kInitiator, PROTOCOL_JINGLE,
2136                       content_type,
2137                       content_name, "",
2138                       "",  ""));
2139
2140    initiator->CreateSession();
2141    cricket::SessionDescription* offer = NewTestSessionDescription(
2142        content_name, content_type);
2143    std::string initiate_xml = InitiateXml(
2144        PROTOCOL_JINGLE, content_name, content_type);
2145
2146    cricket::ContentInfos contents;
2147    TestContentDescription content(content_type, content_type);
2148    contents.push_back(
2149        cricket::ContentInfo(content_name, content_type, &content));
2150    std::string description_info_xml = JingleDescriptionInfoXml(
2151        content_name, content_type);
2152
2153    EXPECT_TRUE(initiator->session->Initiate(kResponder, offer));
2154    initiator->ExpectSentStanza(
2155        IqSet("0", kInitiator, kResponder, initiate_xml));
2156
2157    EXPECT_TRUE(initiator->session->SendDescriptionInfoMessage(contents));
2158    initiator->ExpectSentStanza(
2159        IqSet("1", kInitiator, kResponder, description_info_xml));
2160  }
2161
2162  void DoTestSignalNewDescription(
2163      TestClient* client,
2164      cricket::BaseSession::State state,
2165      cricket::ContentAction expected_content_action,
2166      cricket::ContentSource expected_content_source) {
2167    // Clean up before the new test.
2168    client->new_local_description = false;
2169    client->new_remote_description = false;
2170
2171    client->SetSessionState(state);
2172    EXPECT_EQ((expected_content_source == cricket::CS_LOCAL),
2173               client->new_local_description);
2174    EXPECT_EQ((expected_content_source == cricket::CS_REMOTE),
2175               client->new_remote_description);
2176    EXPECT_EQ(expected_content_action, client->last_content_action);
2177    EXPECT_EQ(expected_content_source, client->last_content_source);
2178  }
2179
2180  void TestCallerSignalNewDescription() {
2181    talk_base::scoped_ptr<cricket::PortAllocator> allocator(
2182        new TestPortAllocator());
2183    int next_message_id = 0;
2184
2185    std::string content_name = "content-name";
2186    std::string content_type = "content-type";
2187    talk_base::scoped_ptr<TestClient> initiator(
2188        new TestClient(allocator.get(), &next_message_id,
2189                       kInitiator, PROTOCOL_JINGLE,
2190                       content_type,
2191                       content_name, "",
2192                       "",  ""));
2193
2194    initiator->CreateSession();
2195
2196    // send offer -> send update offer ->
2197    // receive pr answer -> receive update pr answer ->
2198    // receive answer
2199    DoTestSignalNewDescription(
2200        initiator.get(), cricket::BaseSession::STATE_SENTINITIATE,
2201        cricket::CA_OFFER, cricket::CS_LOCAL);
2202
2203    DoTestSignalNewDescription(
2204        initiator.get(), cricket::BaseSession::STATE_SENTINITIATE,
2205        cricket::CA_OFFER, cricket::CS_LOCAL);
2206
2207    DoTestSignalNewDescription(
2208        initiator.get(), cricket::BaseSession::STATE_RECEIVEDPRACCEPT,
2209        cricket::CA_PRANSWER, cricket::CS_REMOTE);
2210
2211    DoTestSignalNewDescription(
2212        initiator.get(), cricket::BaseSession::STATE_RECEIVEDPRACCEPT,
2213        cricket::CA_PRANSWER, cricket::CS_REMOTE);
2214
2215    DoTestSignalNewDescription(
2216        initiator.get(), cricket::BaseSession::STATE_RECEIVEDACCEPT,
2217        cricket::CA_ANSWER, cricket::CS_REMOTE);
2218  }
2219
2220  void TestCalleeSignalNewDescription() {
2221    talk_base::scoped_ptr<cricket::PortAllocator> allocator(
2222        new TestPortAllocator());
2223    int next_message_id = 0;
2224
2225    std::string content_name = "content-name";
2226    std::string content_type = "content-type";
2227    talk_base::scoped_ptr<TestClient> initiator(
2228        new TestClient(allocator.get(), &next_message_id,
2229                       kInitiator, PROTOCOL_JINGLE,
2230                       content_type,
2231                       content_name, "",
2232                       "",  ""));
2233
2234    initiator->CreateSession();
2235
2236    // receive offer -> receive update offer ->
2237    // send pr answer -> send update pr answer ->
2238    // send answer
2239    DoTestSignalNewDescription(
2240        initiator.get(), cricket::BaseSession::STATE_RECEIVEDINITIATE,
2241        cricket::CA_OFFER, cricket::CS_REMOTE);
2242
2243    DoTestSignalNewDescription(
2244        initiator.get(), cricket::BaseSession::STATE_RECEIVEDINITIATE,
2245        cricket::CA_OFFER, cricket::CS_REMOTE);
2246
2247    DoTestSignalNewDescription(
2248        initiator.get(), cricket::BaseSession::STATE_SENTPRACCEPT,
2249        cricket::CA_PRANSWER, cricket::CS_LOCAL);
2250
2251    DoTestSignalNewDescription(
2252        initiator.get(), cricket::BaseSession::STATE_SENTPRACCEPT,
2253        cricket::CA_PRANSWER, cricket::CS_LOCAL);
2254
2255    DoTestSignalNewDescription(
2256        initiator.get(), cricket::BaseSession::STATE_SENTACCEPT,
2257        cricket::CA_ANSWER, cricket::CS_LOCAL);
2258  }
2259
2260  void TestGetTransportStats() {
2261    talk_base::scoped_ptr<cricket::PortAllocator> allocator(
2262        new TestPortAllocator());
2263    int next_message_id = 0;
2264
2265    std::string content_name = "content-name";
2266    std::string content_type = "content-type";
2267    talk_base::scoped_ptr<TestClient> initiator(
2268        new TestClient(allocator.get(), &next_message_id,
2269                       kInitiator, PROTOCOL_JINGLE,
2270                       content_type,
2271                       content_name, "",
2272                       "",  ""));
2273    initiator->CreateSession();
2274
2275    cricket::SessionStats stats;
2276    EXPECT_TRUE(initiator->session->GetStats(&stats));
2277    // At initiation, there are 2 transports.
2278    EXPECT_EQ(2ul, stats.proxy_to_transport.size());
2279    EXPECT_EQ(2ul, stats.transport_stats.size());
2280  }
2281};
2282
2283// For each of these, "X => Y = Z" means "if a client with protocol X
2284// initiates to a client with protocol Y, they end up speaking protocol Z.
2285
2286// Gingle => Gingle = Gingle (with other content)
2287TEST_F(SessionTest, GingleToGingleOtherContent) {
2288  TestOtherContent(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2289}
2290
2291// Gingle => Gingle = Gingle (with audio content)
2292TEST_F(SessionTest, GingleToGingleAudioContent) {
2293  TestAudioContent(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2294}
2295
2296// Gingle => Gingle = Gingle (with video contents)
2297TEST_F(SessionTest, GingleToGingleVideoContents) {
2298  TestVideoContents(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2299}
2300
2301// Jingle => Jingle = Jingle (with other content)
2302TEST_F(SessionTest, JingleToJingleOtherContent) {
2303  TestOtherContent(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2304}
2305
2306// Jingle => Jingle = Jingle (with audio content)
2307TEST_F(SessionTest, JingleToJingleAudioContent) {
2308  TestAudioContent(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2309}
2310
2311// Jingle => Jingle = Jingle (with video contents)
2312TEST_F(SessionTest, JingleToJingleVideoContents) {
2313  TestVideoContents(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2314}
2315
2316// Hybrid => Hybrid = Jingle (with other content)
2317TEST_F(SessionTest, HybridToHybridOtherContent) {
2318  TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2319}
2320
2321// Hybrid => Hybrid = Jingle (with audio content)
2322TEST_F(SessionTest, HybridToHybridAudioContent) {
2323  TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2324}
2325
2326// Hybrid => Hybrid = Jingle (with video contents)
2327TEST_F(SessionTest, HybridToHybridVideoContents) {
2328  TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2329}
2330
2331// Gingle => Hybrid = Gingle (with other content)
2332TEST_F(SessionTest, GingleToHybridOtherContent) {
2333  TestOtherContent(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE);
2334}
2335
2336// Gingle => Hybrid = Gingle (with audio content)
2337TEST_F(SessionTest, GingleToHybridAudioContent) {
2338  TestAudioContent(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE);
2339}
2340
2341// Gingle => Hybrid = Gingle (with video contents)
2342TEST_F(SessionTest, GingleToHybridVideoContents) {
2343  TestVideoContents(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE);
2344}
2345
2346// Jingle => Hybrid = Jingle (with other content)
2347TEST_F(SessionTest, JingleToHybridOtherContent) {
2348  TestOtherContent(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2349}
2350
2351// Jingle => Hybrid = Jingle (with audio content)
2352TEST_F(SessionTest, JingleToHybridAudioContent) {
2353  TestAudioContent(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2354}
2355
2356// Jingle => Hybrid = Jingle (with video contents)
2357TEST_F(SessionTest, JingleToHybridVideoContents) {
2358  TestVideoContents(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2359}
2360
2361// Hybrid => Gingle = Gingle (with other content)
2362TEST_F(SessionTest, HybridToGingleOtherContent) {
2363  TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2364}
2365
2366// Hybrid => Gingle = Gingle (with audio content)
2367TEST_F(SessionTest, HybridToGingleAudioContent) {
2368  TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2369}
2370
2371// Hybrid => Gingle = Gingle (with video contents)
2372TEST_F(SessionTest, HybridToGingleVideoContents) {
2373  TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2374}
2375
2376// Hybrid => Jingle = Jingle (with other content)
2377TEST_F(SessionTest, HybridToJingleOtherContent) {
2378  TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2379}
2380
2381// Hybrid => Jingle = Jingle (with audio content)
2382TEST_F(SessionTest, HybridToJingleAudioContent) {
2383  TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2384}
2385
2386// Hybrid => Jingle = Jingle (with video contents)
2387TEST_F(SessionTest, HybridToJingleVideoContents) {
2388  TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2389}
2390
2391TEST_F(SessionTest, GingleEarlyTerminationFromInitiator) {
2392  TestEarlyTerminationFromInitiator(PROTOCOL_GINGLE);
2393}
2394
2395TEST_F(SessionTest, JingleEarlyTerminationFromInitiator) {
2396  TestEarlyTerminationFromInitiator(PROTOCOL_JINGLE);
2397}
2398
2399TEST_F(SessionTest, HybridEarlyTerminationFromInitiator) {
2400  TestEarlyTerminationFromInitiator(PROTOCOL_HYBRID);
2401}
2402
2403TEST_F(SessionTest, GingleRejection) {
2404  TestRejection(PROTOCOL_GINGLE);
2405}
2406
2407TEST_F(SessionTest, JingleRejection) {
2408  TestRejection(PROTOCOL_JINGLE);
2409}
2410
2411TEST_F(SessionTest, GingleGoodRedirect) {
2412  TestGoodRedirect(PROTOCOL_GINGLE);
2413}
2414
2415TEST_F(SessionTest, JingleGoodRedirect) {
2416  TestGoodRedirect(PROTOCOL_JINGLE);
2417}
2418
2419TEST_F(SessionTest, GingleBadRedirect) {
2420  TestBadRedirect(PROTOCOL_GINGLE);
2421}
2422
2423TEST_F(SessionTest, JingleBadRedirect) {
2424  TestBadRedirect(PROTOCOL_JINGLE);
2425}
2426
2427TEST_F(SessionTest, TestCandidatesInInitiateAndAccept) {
2428  TestCandidatesInInitiateAndAccept("Candidates in initiate/accept");
2429}
2430
2431TEST_F(SessionTest, TestTransportMux) {
2432  TestTransportMux();
2433}
2434
2435TEST_F(SessionTest, TestSendDescriptionInfo) {
2436  TestSendDescriptionInfo();
2437}
2438
2439TEST_F(SessionTest, TestCallerSignalNewDescription) {
2440  TestCallerSignalNewDescription();
2441}
2442
2443TEST_F(SessionTest, TestCalleeSignalNewDescription) {
2444  TestCalleeSignalNewDescription();
2445}
2446
2447TEST_F(SessionTest, TestGetTransportStats) {
2448  TestGetTransportStats();
2449}
2450