1c08bf18dd08cd1de9e36c2f62eeebb0b09645b9
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / p2p / base / session_unittest.cc
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
59 using cricket::SignalingProtocol;
60 using cricket::PROTOCOL_HYBRID;
61 using cricket::PROTOCOL_JINGLE;
62 using cricket::PROTOCOL_GINGLE;
63
64 static const std::string kInitiator = "init@init.com";
65 static const std::string kResponder = "resp@resp.com";
66 // Expected from test random number generator.
67 static 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.
70 static 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.
74 static const int kEventTimeout = 5000;
75
76 static const int kNumPorts = 2;
77 static const int kPort0 = 28653;
78 static const int kPortStep = 5;
79
80 int GetPort(int port_index) {
81   return kPort0 + (port_index * kPortStep);
82 }
83
84 std::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.
89 std::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.
94 std::string GetPassword(int port_index) {
95   return "password" + std::string(8, talk_base::ToString(port_index)[0]);
96 }
97
98 std::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
110 std::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
125 std::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
140 std::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
152 std::string GingleDescriptionXml(const std::string& content_type) {
153   return "<description"
154       " xmlns=\"" + content_type + "\""
155       "/>";
156 }
157
158 std::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
184 std::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
195 std::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
206 std::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
223 std::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
239 std::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
261 std::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
276 std::string GingleInitiateXml(const std::string& content_type) {
277   return GingleSessionXml(
278       "initiate",
279       GingleDescriptionXml(content_type));
280 }
281
282 std::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
303 std::string GingleAcceptXml(const std::string& content_type) {
304   return GingleSessionXml(
305       "accept",
306       GingleDescriptionXml(content_type));
307 }
308
309 std::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
331 std::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
340 std::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
354 std::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
366 std::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
383 std::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
390 std::string GingleRejectXml(const std::string& reason) {
391   return GingleSessionXml(
392       "reject",
393       "<" + reason + "/>");
394 }
395
396 std::string JingleTerminateXml(const std::string& reason) {
397     return JingleActionXml(
398         "session-terminate",
399         "<reason><" + reason + "/></reason>");
400 }
401
402 std::string GingleTerminateXml(const std::string& reason) {
403   return GingleSessionXml(
404       "terminate",
405       "<" + reason + "/>");
406 }
407
408 std::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
418 std::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
428 std::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
450 std::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
459 std::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
482 std::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
492 std::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
516 std::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
547 std::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
561 std::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
575 std::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
590 class 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
661 class 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
679 class 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
694 cricket::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
716 cricket::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
730 struct 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
776 struct 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
834 void PrintStanza(const std::string& message,
835                  const buzz::XmlElement* stanza) {
836   printf("%s: %s\n", message.c_str(), stanza->Str().c_str());
837 }
838
839 class 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
1124 class 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)
2287 TEST_F(SessionTest, GingleToGingleOtherContent) {
2288   TestOtherContent(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2289 }
2290
2291 // Gingle => Gingle = Gingle (with audio content)
2292 TEST_F(SessionTest, GingleToGingleAudioContent) {
2293   TestAudioContent(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2294 }
2295
2296 // Gingle => Gingle = Gingle (with video contents)
2297 TEST_F(SessionTest, GingleToGingleVideoContents) {
2298   TestVideoContents(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2299 }
2300
2301 // Jingle => Jingle = Jingle (with other content)
2302 TEST_F(SessionTest, JingleToJingleOtherContent) {
2303   TestOtherContent(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2304 }
2305
2306 // Jingle => Jingle = Jingle (with audio content)
2307 TEST_F(SessionTest, JingleToJingleAudioContent) {
2308   TestAudioContent(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2309 }
2310
2311 // Jingle => Jingle = Jingle (with video contents)
2312 TEST_F(SessionTest, JingleToJingleVideoContents) {
2313   TestVideoContents(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2314 }
2315
2316 // Hybrid => Hybrid = Jingle (with other content)
2317 TEST_F(SessionTest, HybridToHybridOtherContent) {
2318   TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2319 }
2320
2321 // Hybrid => Hybrid = Jingle (with audio content)
2322 TEST_F(SessionTest, HybridToHybridAudioContent) {
2323   TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2324 }
2325
2326 // Hybrid => Hybrid = Jingle (with video contents)
2327 TEST_F(SessionTest, HybridToHybridVideoContents) {
2328   TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2329 }
2330
2331 // Gingle => Hybrid = Gingle (with other content)
2332 TEST_F(SessionTest, GingleToHybridOtherContent) {
2333   TestOtherContent(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE);
2334 }
2335
2336 // Gingle => Hybrid = Gingle (with audio content)
2337 TEST_F(SessionTest, GingleToHybridAudioContent) {
2338   TestAudioContent(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE);
2339 }
2340
2341 // Gingle => Hybrid = Gingle (with video contents)
2342 TEST_F(SessionTest, GingleToHybridVideoContents) {
2343   TestVideoContents(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE);
2344 }
2345
2346 // Jingle => Hybrid = Jingle (with other content)
2347 TEST_F(SessionTest, JingleToHybridOtherContent) {
2348   TestOtherContent(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2349 }
2350
2351 // Jingle => Hybrid = Jingle (with audio content)
2352 TEST_F(SessionTest, JingleToHybridAudioContent) {
2353   TestAudioContent(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2354 }
2355
2356 // Jingle => Hybrid = Jingle (with video contents)
2357 TEST_F(SessionTest, JingleToHybridVideoContents) {
2358   TestVideoContents(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2359 }
2360
2361 // Hybrid => Gingle = Gingle (with other content)
2362 TEST_F(SessionTest, HybridToGingleOtherContent) {
2363   TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2364 }
2365
2366 // Hybrid => Gingle = Gingle (with audio content)
2367 TEST_F(SessionTest, HybridToGingleAudioContent) {
2368   TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2369 }
2370
2371 // Hybrid => Gingle = Gingle (with video contents)
2372 TEST_F(SessionTest, HybridToGingleVideoContents) {
2373   TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2374 }
2375
2376 // Hybrid => Jingle = Jingle (with other content)
2377 TEST_F(SessionTest, HybridToJingleOtherContent) {
2378   TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2379 }
2380
2381 // Hybrid => Jingle = Jingle (with audio content)
2382 TEST_F(SessionTest, HybridToJingleAudioContent) {
2383   TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2384 }
2385
2386 // Hybrid => Jingle = Jingle (with video contents)
2387 TEST_F(SessionTest, HybridToJingleVideoContents) {
2388   TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2389 }
2390
2391 TEST_F(SessionTest, GingleEarlyTerminationFromInitiator) {
2392   TestEarlyTerminationFromInitiator(PROTOCOL_GINGLE);
2393 }
2394
2395 TEST_F(SessionTest, JingleEarlyTerminationFromInitiator) {
2396   TestEarlyTerminationFromInitiator(PROTOCOL_JINGLE);
2397 }
2398
2399 TEST_F(SessionTest, HybridEarlyTerminationFromInitiator) {
2400   TestEarlyTerminationFromInitiator(PROTOCOL_HYBRID);
2401 }
2402
2403 TEST_F(SessionTest, GingleRejection) {
2404   TestRejection(PROTOCOL_GINGLE);
2405 }
2406
2407 TEST_F(SessionTest, JingleRejection) {
2408   TestRejection(PROTOCOL_JINGLE);
2409 }
2410
2411 TEST_F(SessionTest, GingleGoodRedirect) {
2412   TestGoodRedirect(PROTOCOL_GINGLE);
2413 }
2414
2415 TEST_F(SessionTest, JingleGoodRedirect) {
2416   TestGoodRedirect(PROTOCOL_JINGLE);
2417 }
2418
2419 TEST_F(SessionTest, GingleBadRedirect) {
2420   TestBadRedirect(PROTOCOL_GINGLE);
2421 }
2422
2423 TEST_F(SessionTest, JingleBadRedirect) {
2424   TestBadRedirect(PROTOCOL_JINGLE);
2425 }
2426
2427 TEST_F(SessionTest, TestCandidatesInInitiateAndAccept) {
2428   TestCandidatesInInitiateAndAccept("Candidates in initiate/accept");
2429 }
2430
2431 TEST_F(SessionTest, TestTransportMux) {
2432   TestTransportMux();
2433 }
2434
2435 TEST_F(SessionTest, TestSendDescriptionInfo) {
2436   TestSendDescriptionInfo();
2437 }
2438
2439 TEST_F(SessionTest, TestCallerSignalNewDescription) {
2440   TestCallerSignalNewDescription();
2441 }
2442
2443 TEST_F(SessionTest, TestCalleeSignalNewDescription) {
2444   TestCalleeSignalNewDescription();
2445 }
2446
2447 TEST_F(SessionTest, TestGetTransportStats) {
2448   TestGetTransportStats();
2449 }