Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(510)

Side by Side Diff: webrtc/libjingle/session/session_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698