3 * Copyright 2004 Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
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.
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.
31 #include "talk/media/base/fakemediaengine.h"
32 #include "talk/media/base/testutils.h"
33 #include "talk/media/devices/fakedevicemanager.h"
34 #include "webrtc/p2p/base/constants.h"
35 #include "webrtc/p2p/client/basicportallocator.h"
36 #include "talk/session/media/mediasessionclient.h"
37 #include "webrtc/libjingle/xmllite/xmlbuilder.h"
38 #include "webrtc/libjingle/xmllite/xmlelement.h"
39 #include "webrtc/libjingle/xmllite/xmlprinter.h"
40 #include "webrtc/libjingle/xmpp/constants.h"
41 #include "webrtc/base/gunit.h"
42 #include "webrtc/base/logging.h"
43 #include "webrtc/base/scoped_ptr.h"
44 #include "webrtc/base/ssladapter.h"
46 using cricket::AudioCodec;
47 using cricket::AudioContentDescription;
49 using cricket::DataCodec;
50 using cricket::DataContentDescription;
51 using cricket::FeedbackParam;
52 using cricket::FeedbackParams;
53 using cricket::VideoCodec;
54 using cricket::VideoContentDescription;
56 // The codecs that our FakeMediaEngine will support. Order is important, since
57 // the tests check that our messages have codecs in the correct order.
58 static const cricket::AudioCodec kAudioCodecs[] = {
59 cricket::AudioCodec(103, "ISAC", 16000, -1, 1, 18),
60 cricket::AudioCodec(104, "ISAC", 32000, -1, 1, 17),
61 cricket::AudioCodec(119, "ISACLC", 16000, 40000, 1, 16),
62 cricket::AudioCodec(99, "speex", 16000, 22000, 1, 15),
63 cricket::AudioCodec(97, "IPCMWB", 16000, 80000, 1, 14),
64 cricket::AudioCodec(9, "G722", 8000, 64000, 1, 13),
65 cricket::AudioCodec(102, "iLBC", 8000, 13300, 1, 12),
66 cricket::AudioCodec(98, "speex", 8000, 11000, 1, 11),
67 cricket::AudioCodec(3, "GSM", 8000, 13000, 1, 10),
68 cricket::AudioCodec(100, "EG711U", 8000, 64000, 1, 9),
69 cricket::AudioCodec(101, "EG711A", 8000, 64000, 1, 8),
70 cricket::AudioCodec(0, "PCMU", 8000, 64000, 1, 7),
71 cricket::AudioCodec(8, "PCMA", 8000, 64000, 1, 6),
72 cricket::AudioCodec(126, "CN", 32000, 0, 1, 5),
73 cricket::AudioCodec(105, "CN", 16000, 0, 1, 4),
74 cricket::AudioCodec(13, "CN", 8000, 0, 1, 3),
75 cricket::AudioCodec(117, "red", 8000, 0, 1, 2),
76 cricket::AudioCodec(106, "telephone-event", 8000, 0, 1, 1)
79 // The codecs that our FakeMediaEngine will support with a different order of
81 static const cricket::AudioCodec kAudioCodecsDifferentPreference[] = {
82 cricket::AudioCodec(104, "ISAC", 32000, -1, 1, 17),
83 cricket::AudioCodec(97, "IPCMWB", 16000, 80000, 1, 14),
84 cricket::AudioCodec(9, "G722", 8000, 64000, 1, 13),
85 cricket::AudioCodec(119, "ISACLC", 16000, 40000, 1, 16),
86 cricket::AudioCodec(103, "ISAC", 16000, -1, 1, 18),
87 cricket::AudioCodec(99, "speex", 16000, 22000, 1, 15),
88 cricket::AudioCodec(100, "EG711U", 8000, 64000, 1, 9),
89 cricket::AudioCodec(101, "EG711A", 8000, 64000, 1, 8),
90 cricket::AudioCodec(0, "PCMU", 8000, 64000, 1, 7),
91 cricket::AudioCodec(8, "PCMA", 8000, 64000, 1, 6),
92 cricket::AudioCodec(102, "iLBC", 8000, 13300, 1, 12),
93 cricket::AudioCodec(3, "GSM", 8000, 13000, 1, 10),
94 cricket::AudioCodec(98, "speex", 8000, 11000, 1, 11),
95 cricket::AudioCodec(126, "CN", 32000, 0, 1, 5),
96 cricket::AudioCodec(105, "CN", 16000, 0, 1, 4),
97 cricket::AudioCodec(13, "CN", 8000, 0, 1, 3),
98 cricket::AudioCodec(117, "red", 8000, 0, 1, 2),
99 cricket::AudioCodec(106, "telephone-event", 8000, 0, 1, 1)
102 static const cricket::VideoCodec kVideoCodecs[] = {
103 cricket::VideoCodec(96, "H264-SVC", 320, 200, 30, 1)
106 static const cricket::DataCodec kDataCodecs[] = {
107 cricket::DataCodec(127, "google-data", 0)
110 const std::string kGingleCryptoOffer = \
111 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'> " \
113 " <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \
114 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
115 " <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \
116 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
117 "</rtp:encryption> ";
119 // Jingle offer does not have any <usage> element.
120 const std::string kJingleCryptoOffer = \
121 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'> " \
122 " <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \
123 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
124 " <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \
125 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
126 "</rtp:encryption> ";
129 const std::string kGingleRequiredCryptoOffer = \
130 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'> "\
132 " <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \
133 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
134 " <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \
135 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
136 "</rtp:encryption> ";
138 const std::string kJingleRequiredCryptoOffer = \
139 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'> "\
140 " <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \
141 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
142 " <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \
143 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
144 "</rtp:encryption> ";
147 const std::string kGingleUnsupportedCryptoOffer = \
148 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'> " \
150 " <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1'" \
151 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
152 " <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2'" \
153 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
154 "</rtp:encryption> ";
156 const std::string kJingleUnsupportedCryptoOffer = \
157 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'> " \
158 " <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1'" \
159 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
160 " <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2'" \
161 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
162 "</rtp:encryption> ";
165 // With unsupported but with required="true"
166 const std::string kGingleRequiredUnsupportedCryptoOffer = \
167 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'>" \
169 " <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1'" \
170 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
171 " <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2'" \
172 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
173 "</rtp:encryption> ";
175 const std::string kJingleRequiredUnsupportedCryptoOffer = \
176 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'>" \
177 " <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1' " \
178 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/> " \
179 " <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2' " \
180 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
181 "</rtp:encryption> ";
183 const std::string kGingleInitiate(
184 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
185 " to='user@domain.com/resource' type='set' id='123'> " \
186 " <session xmlns='http://www.google.com/session' type='initiate'" \
187 " id='abcdef' initiator='me@domain.com/resource'> " \
188 " <description xmlns='http://www.google.com/session/phone'> " \
189 " <payload-type xmlns='http://www.google.com/session/phone' " \
190 " id='103' name='ISAC' clockrate='16000' /> " \
191 " <payload-type xmlns='http://www.google.com/session/phone' " \
192 " id='104' name='ISAC' clockrate='32000' /> " \
193 " <payload-type xmlns='http://www.google.com/session/phone' " \
194 " id='119' name='ISACLC' clockrate='16000' bitrate='40000' /> " \
195 " <payload-type xmlns='http://www.google.com/session/phone' " \
196 " id='99' name='speex' clockrate='16000' bitrate='22000' /> " \
197 " <payload-type xmlns='http://www.google.com/session/phone' " \
198 " id='97' name='IPCMWB' clockrate='16000' bitrate='80000' /> " \
199 " <payload-type xmlns='http://www.google.com/session/phone' " \
200 " id='9' name='G722' clockrate='8000' bitrate='64000' /> " \
201 " <payload-type xmlns='http://www.google.com/session/phone' " \
202 " id='102' name='iLBC' clockrate='8000' bitrate='13300' />" \
203 " <payload-type xmlns='http://www.google.com/session/phone' " \
204 " id='98' name='speex' clockrate='8000' bitrate='11000' />" \
205 " <payload-type xmlns='http://www.google.com/session/phone' " \
206 " id='3' name='GSM' clockrate='8000' bitrate='13000' /> " \
207 " <payload-type xmlns='http://www.google.com/session/phone' " \
208 " id='100' name='EG711U' clockrate='8000' bitrate='64000' /> " \
209 " <payload-type xmlns='http://www.google.com/session/phone' " \
210 " id='101' name='EG711A' clockrate='8000' bitrate='64000' /> " \
211 " <payload-type xmlns='http://www.google.com/session/phone' " \
212 " id='0' name='PCMU' clockrate='8000' bitrate='64000' /> " \
213 " <payload-type xmlns='http://www.google.com/session/phone' " \
214 " id='8' name='PCMA' clockrate='8000' bitrate='64000' /> " \
215 " <payload-type xmlns='http://www.google.com/session/phone' " \
216 " id='126' name='CN' clockrate='32000' /> " \
217 " <payload-type xmlns='http://www.google.com/session/phone' " \
218 " id='105' name='CN' clockrate='16000' /> " \
219 " <payload-type xmlns='http://www.google.com/session/phone' " \
220 " id='13' name='CN' clockrate='8000' /> " \
221 " <payload-type xmlns='http://www.google.com/session/phone' " \
222 " id='117' name='red' clockrate='8000' /> " \
223 " <payload-type xmlns='http://www.google.com/session/phone' " \
224 " id='106' name='telephone-event' clockrate='8000' /> " \
229 const std::string kJingleInitiate(
230 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
231 " to='user@domain.com/resource' type='set' id='123'> " \
232 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
233 " sid='abcdef' initiator='me@domain.com/resource'> " \
234 " <content name='test audio'> " \
235 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
236 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
237 " <payload-type id='104' name='ISAC' clockrate='32000'/> " \
239 " id='119' name='ISACLC' clockrate='16000'> " \
240 " <parameter name='bitrate' value='40000'/> " \
241 " </payload-type> " \
243 " id='99' name='speex' clockrate='16000'> " \
244 " <parameter name='bitrate' value='22000'/> " \
245 " </payload-type> " \
247 " id='97' name='IPCMWB' clockrate='16000'> " \
248 " <parameter name='bitrate' value='80000'/> " \
249 " </payload-type> " \
251 " id='9' name='G722' clockrate='8000'> " \
252 " <parameter name='bitrate' value='64000'/> " \
253 " </payload-type> " \
255 " id='102' name='iLBC' clockrate='8000'> " \
256 " <parameter name='bitrate' value='13300'/> " \
257 " </payload-type> " \
259 " id='98' name='speex' clockrate='8000'> " \
260 " <parameter name='bitrate' value='11000'/> " \
261 " </payload-type> " \
263 " id='3' name='GSM' clockrate='8000'> " \
264 " <parameter name='bitrate' value='13000'/> " \
265 " </payload-type> " \
267 " id='100' name='EG711U' clockrate='8000'> " \
268 " <parameter name='bitrate' value='64000'/> " \
269 " </payload-type> " \
271 " id='101' name='EG711A' clockrate='8000'> " \
272 " <parameter name='bitrate' value='64000'/> " \
273 " </payload-type> " \
275 " id='0' name='PCMU' clockrate='8000'> " \
276 " <parameter name='bitrate' value='64000'/> " \
277 " </payload-type> " \
279 " id='8' name='PCMA' clockrate='8000'> " \
280 " <parameter name='bitrate' value='64000'/> " \
281 " </payload-type> " \
283 " id='126' name='CN' clockrate='32000' /> " \
285 " id='105' name='CN' clockrate='16000' /> " \
287 " id='13' name='CN' clockrate='8000' /> " \
289 " id='117' name='red' clockrate='8000' /> " \
291 " id='106' name='telephone-event' clockrate='8000' /> " \
293 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
298 const std::string kJingleInitiateWithRtcpFb(
299 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
300 " to='user@domain.com/resource' type='set' id='123'> " \
301 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
302 " sid='abcdef' initiator='me@domain.com/resource'> " \
303 " <content name='test audio'> " \
304 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
305 " <payload-type id='103' name='ISAC' clockrate='16000'> " \
306 " <rtcp-fb type='nack'/> " \
307 " </payload-type> " \
309 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
311 " <content name='test video'> " \
312 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
313 " <rtcp-fb type='nack'/> " \
314 " <payload-type id='99' name='H264-SVC'> " \
315 " <rtcp-fb type='ccm' subtype='fir'/> " \
316 " <parameter name='height' value='200'/> " \
317 " <parameter name='width' value='320'/> " \
318 " <parameter name='framerate' value='30'/> " \
319 " </payload-type> " \
321 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
323 " <content name='test data'> " \
324 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='data'> " \
325 " <rtcp-fb type='nack'/> " \
326 " <payload-type id='127' name='google-data'> " \
327 " </payload-type> " \
329 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
334 const std::string kGingleVideoInitiate(
335 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
336 " to='user@domain.com/resource' type='set' id='123'> " \
337 " <session xmlns='http://www.google.com/session' type='initiate'" \
338 " id='abcdef' initiator='me@domain.com/resource'> " \
339 " <description xmlns='http://www.google.com/session/video'> " \
340 " <payload-type xmlns='http://www.google.com/session/phone' " \
341 " id='103' name='ISAC' clockrate='16000' /> " \
342 " <payload-type xmlns='http://www.google.com/session/video' " \
343 " id='99' name='H264-SVC' framerate='30' " \
344 " height='200' width='320'/> " \
349 const std::string kJingleVideoInitiate(
350 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
351 " to='user@domain.com/resource' type='set' id='123'> " \
352 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
353 " sid='abcdef' initiator='me@domain.com/resource'> " \
354 " <content name='test audio'> " \
355 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
356 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
358 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
360 " <content name='test video'> " \
361 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
362 " <payload-type id='99' name='H264-SVC'> " \
363 " <parameter name='height' value='200'/> " \
364 " <parameter name='width' value='320'/> " \
365 " <parameter name='framerate' value='30'/> " \
366 " </payload-type> " \
368 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
373 const std::string kJingleVideoInitiateWithRtpData(
374 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
375 " to='user@domain.com/resource' type='set' id='123'> " \
376 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
377 " sid='abcdef' initiator='me@domain.com/resource'> " \
378 " <content name='test audio'> " \
379 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
380 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
382 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
384 " <content name='test video'> " \
385 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
386 " <payload-type id='99' name='H264-SVC'> " \
387 " <parameter name='height' value='200'/> " \
388 " <parameter name='width' value='320'/> " \
389 " <parameter name='framerate' value='30'/> " \
390 " </payload-type> " \
392 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
394 " <content name='test data'> " \
395 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='data'> " \
396 " <payload-type id='127' name='google-data'/> " \
399 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
404 const std::string kJingleVideoInitiateWithSctpData(
405 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
406 " to='user@domain.com/resource' type='set' id='123'> " \
407 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
408 " sid='abcdef' initiator='me@domain.com/resource'> " \
409 " <content name='test audio'> " \
410 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
411 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
413 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
415 " <content name='test video'> " \
416 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
417 " <payload-type id='99' name='H264-SVC'> " \
418 " <parameter name='height' value='200'/> " \
419 " <parameter name='width' value='320'/> " \
420 " <parameter name='framerate' value='30'/> " \
421 " </payload-type> " \
423 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
425 " <content name='test data'> " \
426 " <description xmlns='google:jingle:sctp' media='data'> " \
427 " <stream sid='1'/> " \
429 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
434 const std::string kJingleVideoInitiateWithBandwidth(
435 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
436 " to='user@domain.com/resource' type='set' id='123'> " \
437 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
438 " sid='abcdef' initiator='me@domain.com/resource'> " \
439 " <content name='test audio'> " \
440 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
441 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
443 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
445 " <content name='test video'> " \
446 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
447 " <payload-type id='99' name='H264-SVC'> " \
448 " <parameter name='height' value='200'/> " \
449 " <parameter name='width' value='320'/> " \
450 " <parameter name='framerate' value='30'/> " \
451 " </payload-type> " \
452 " <bandwidth type='AS'>42</bandwidth> " \
454 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
459 const std::string kJingleVideoInitiateWithRtcpMux(
460 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
461 " to='user@domain.com/resource' type='set' id='123'> " \
462 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
463 " sid='abcdef' initiator='me@domain.com/resource'> " \
464 " <content name='test audio'> " \
465 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
466 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
468 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
470 " <content name='test video'> " \
471 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
472 " <payload-type id='99' name='H264-SVC'> " \
473 " <parameter name='height' value='200'/> " \
474 " <parameter name='width' value='320'/> " \
475 " <parameter name='framerate' value='30'/> " \
476 " </payload-type> " \
479 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
484 // Initiate string with a combination of supported and unsupported codecs
485 // Should accept the supported ones
486 const std::string kGingleInitiateSomeUnsupported(
487 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
488 " to='user@domain.com/resource' type='set' id='123'> " \
489 " <session xmlns='http://www.google.com/session' type='initiate'" \
490 " id='abcdef' initiator='me@domain.com/resource'> " \
491 " <description xmlns='http://www.google.com/session/phone'> " \
492 " <payload-type xmlns='http://www.google.com/session/phone' " \
493 " id='103' name='ISAC' clockrate='16000' /> " \
494 " <payload-type xmlns='http://www.google.com/session/phone' " \
495 " id='97' name='ASDFDS' /> " \
496 " <payload-type xmlns='http://www.google.com/session/phone' " \
497 " id='102' name='1010' /> " \
498 " <payload-type xmlns='http://www.google.com/session/phone' " \
499 " id='107' name='DFAS' /> " \
500 " <payload-type xmlns='http://www.google.com/session/phone' " \
501 " id='100' name='EG711U' /> " \
502 " <payload-type xmlns='http://www.google.com/session/phone' " \
503 " id='101' name='EG711A' /> " \
504 " <payload-type xmlns='http://www.google.com/session/phone' " \
505 " id='0' name='PCMU' /> " \
506 " <payload-type xmlns='http://www.google.com/session/phone' " \
507 " id='110' name=':)' /> " \
508 " <payload-type xmlns='http://www.google.com/session/phone' " \
509 " id='13' name='CN' /> " \
514 const std::string kJingleInitiateSomeUnsupported(
515 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
516 " to='user@domain.com/resource' type='set' id='123'> " \
517 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
518 " sid='abcdef' initiator='me@domain.com/resource'> " \
519 " <content name='test audio'> " \
520 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
522 " id='103' name='ISAC' clockrate='16000' /> " \
524 " id='97' name='ASDFDS' /> " \
526 " id='102' name='1010' /> " \
528 " id='107' name='DFAS' /> " \
530 " id='100' name='EG711U' /> " \
532 " id='101' name='EG711A' /> " \
534 " id='0' name='PCMU' /> " \
536 " id='110' name=':)' /> " \
538 " id='13' name='CN' /> " \
540 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
545 const std::string kGingleVideoInitiateWithBandwidth(
546 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
547 " to='user@domain.com/resource' type='set' id='123'> " \
548 " <session xmlns='http://www.google.com/session' type='initiate'" \
549 " id='abcdef' initiator='me@domain.com/resource'> " \
550 " <description xmlns='http://www.google.com/session/video'> " \
551 " <payload-type xmlns='http://www.google.com/session/phone' " \
552 " id='103' name='ISAC' clockrate='16000' /> " \
553 " <payload-type xmlns='http://www.google.com/session/video' " \
554 " id='99' name='H264-SVC' framerate='30' " \
555 " height='200' width='320'/> " \
556 " <bandwidth type='AS'>42</bandwidth> " \
561 // Initiate string without any supported codecs. Should send a reject.
562 const std::string kGingleInitiateNoSupportedAudioCodecs(
563 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
564 " to='user@domain.com/resource' type='set' id='123'> " \
565 " <session xmlns='http://www.google.com/session' type='initiate'" \
566 " id='abcdef' initiator='me@domain.com/resource'> " \
567 " <description xmlns='http://www.google.com/session/phone'> " \
568 " <payload-type xmlns='http://www.google.com/session/phone' " \
569 " id='123' name='Supercodec6000' /> " \
574 const std::string kJingleInitiateNoSupportedAudioCodecs(
575 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
576 " to='user@domain.com/resource' type='set' id='123'> " \
577 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
578 " sid='abcdef' initiator='me@domain.com/resource'> " \
579 " <content name='test audio'> " \
580 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
582 " id='123' name='Supercodec6000' /> " \
584 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
589 // Initiate string without any codecs. Assumes ancient version of Cricket
590 // and tries a session with ISAC and PCMU
591 const std::string kGingleInitiateNoAudioCodecs(
592 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
593 " to='user@domain.com/resource' type='set' id='123'> " \
594 " <session xmlns='http://www.google.com/session' type='initiate'" \
595 " id='abcdef' initiator='me@domain.com/resource'> " \
596 " <description xmlns='http://www.google.com/session/phone'> " \
601 const std::string kJingleInitiateNoAudioCodecs(
602 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
603 " to='user@domain.com/resource' type='set' id='123'> " \
604 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
605 " sid='abcdef' initiator='me@domain.com/resource'> " \
606 " <content name='test audio'> " \
607 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
609 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
614 // The codecs are supported, but not at the given clockrates. Should send
616 const std::string kGingleInitiateWrongClockrates(
617 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
618 " to='user@domain.com/resource' type='set' id='123'> " \
619 " <session xmlns='http://www.google.com/session' type='initiate'" \
620 " id='abcdef' initiator='me@domain.com/resource'> " \
621 " <description xmlns='http://www.google.com/session/phone'> " \
622 " <payload-type xmlns='http://www.google.com/session/phone' " \
623 " id='103' name='ISAC' clockrate='8000'/> " \
624 " <payload-type xmlns='http://www.google.com/session/phone' " \
625 " id='97' name='IPCMWB' clockrate='1337'/> " \
626 " <payload-type xmlns='http://www.google.com/session/phone' " \
627 " id='102' name='iLBC' clockrate='1982' /> " \
632 const std::string kJingleInitiateWrongClockrates(
633 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
634 " to='user@domain.com/resource' type='set' id='123'> " \
635 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
636 " sid='abcdef' initiator='me@domain.com/resource'> " \
637 " <content name='test audio'> " \
638 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
640 " id='103' name='ISAC' clockrate='8000'/> " \
642 " id='97' name='IPCMWB' clockrate='1337'/> " \
644 " id='102' name='iLBC' clockrate='1982' /> " \
646 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
651 // The codecs are supported, but not with the given number of channels.
652 // Should send a reject.
653 const std::string kGingleInitiateWrongChannels(
654 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
655 " to='user@domain.com/resource' type='set' id='123'> " \
656 " <session xmlns='http://www.google.com/session' type='initiate'" \
657 " id='abcdef' initiator='me@domain.com/resource'> " \
658 " <description xmlns='http://www.google.com/session/phone'> " \
659 " <payload-type xmlns='http://www.google.com/session/phone' " \
660 " id='103' name='ISAC' channels='2'/> " \
661 " <payload-type xmlns='http://www.google.com/session/phone' " \
662 " id='97' name='IPCMWB' channels='3'/> " \
667 const std::string kJingleInitiateWrongChannels(
668 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
669 " to='user@domain.com/resource' type='set' id='123'> " \
670 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'> " \
671 " <content name='test audio'> " \
672 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
674 " id='103' name='ISAC' channels='2'/> " \
676 " id='97' name='IPCMWB' channels='3'/> " \
678 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
683 // Initiate with a dynamic codec not using webrtc default payload id. Should
684 // accept with provided payload id.
685 const std::string kGingleInitiateDynamicAudioCodecs(
686 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
687 " to='user@domain.com/resource' type='set' id='123'> " \
688 " <session xmlns='http://www.google.com/session' type='initiate'" \
689 " id='abcdef' initiator='me@domain.com/resource'> " \
690 " <description xmlns='http://www.google.com/session/phone'> " \
691 " <payload-type xmlns='http://www.google.com/session/phone' " \
692 " id='123' name='speex' clockrate='16000'/> " \
697 const std::string kJingleInitiateDynamicAudioCodecs(
698 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
699 " to='user@domain.com/resource' type='set' id='123'> " \
700 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
701 " sid='abcdef' initiator='me@domain.com/resource'> " \
702 " <content name='test audio'> " \
703 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
705 " id='123' name='speex' clockrate='16000'/> " \
707 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
712 // Initiate string with nothing but static codec id's. Should accept.
713 const std::string kGingleInitiateStaticAudioCodecs(
714 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
715 " to='user@domain.com/resource' type='set' id='123'> " \
716 " <session xmlns='http://www.google.com/session' type='initiate'" \
717 " id='abcdef' initiator='me@domain.com/resource'> " \
718 " <description xmlns='http://www.google.com/session/phone'> " \
719 " <payload-type xmlns='http://www.google.com/session/phone' " \
721 " <payload-type xmlns='http://www.google.com/session/phone' " \
723 " <payload-type xmlns='http://www.google.com/session/phone' " \
729 const std::string kJingleInitiateStaticAudioCodecs(
730 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
731 " to='user@domain.com/resource' type='set' id='123'> " \
732 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
733 " sid='abcdef' initiator='me@domain.com/resource'> " \
734 " <content name='test audio'> " \
735 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
736 " <payload-type id='3' /> " \
737 " <payload-type id='0' /> " \
738 " <payload-type id='8' /> " \
740 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
745 // Initiate with payload type-less codecs. Should reject.
746 const std::string kGingleInitiateNoPayloadTypes(
747 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
748 " to='user@domain.com/resource' type='set' id='123'> " \
749 " <session xmlns='http://www.google.com/session' type='initiate'" \
750 " id='abcdef' initiator='me@domain.com/resource'> " \
751 " <description xmlns='http://www.google.com/session/phone'> " \
752 " <payload-type xmlns='http://www.google.com/session/phone' " \
753 " name='ISAC' clockrate='16000'/> " \
758 const std::string kJingleInitiateNoPayloadTypes(
759 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
760 " to='user@domain.com/resource' type='set' id='123'> " \
761 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'> " \
762 " sid='abcdef' initiator='me@domain.com/resource'> " \
763 " <content name='test audio'> " \
764 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
765 " <payload-type name='ISAC' clockrate='16000'/> " \
767 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
772 // Initiate with unnamed dynamic codces. Should reject.
773 const std::string kGingleInitiateDynamicWithoutNames(
774 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
775 " to='user@domain.com/resource' type='set' id='123'> " \
776 " <session xmlns='http://www.google.com/session' type='initiate'" \
777 " id='abcdef' initiator='me@domain.com/resource'> " \
778 " <description xmlns='http://www.google.com/session/phone'> " \
779 " <payload-type xmlns='http://www.google.com/session/phone' " \
780 " id='100' clockrate='16000'/> " \
785 const std::string kJingleInitiateDynamicWithoutNames(
786 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
787 " to='user@domain.com/resource' type='set' id='123'> " \
788 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'> " \
789 " sid='abcdef' initiator='me@domain.com/resource'> " \
790 " <content name='test audio'> " \
791 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
792 " <payload-type id='100' clockrate='16000'/> " \
794 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
799 const uint32 kAudioSsrc = 4294967295U;
800 const uint32 kVideoSsrc = 87654321;
801 const uint32 kDataSsrc = 1010101;
802 // Note that this message does not specify a session ID. It must be populated
804 const std::string kGingleAcceptWithSsrcs(
805 "<iq xmlns='jabber:client' from='me@mydomain.com' " \
806 " to='user@domain.com/resource' type='set' id='150'> " \
807 " <session xmlns='http://www.google.com/session' type='accept' " \
808 " initiator='me@domain.com/resource'> " \
809 " <description xmlns='http://www.google.com/session/video'> " \
810 " <payload-type xmlns='http://www.google.com/session/phone' " \
811 " id='103' name='ISAC' clockrate='16000' /> " \
812 " <payload-type xmlns='http://www.google.com/session/phone' " \
813 " id='104' name='ISAC' clockrate='32000' /> " \
814 " <src-id xmlns='http://www.google.com/session/phone'> " \
815 " 4294967295</src-id> " \
816 " <src-id>87654321</src-id> " \
821 const std::string kJingleAcceptWithSsrcs(
822 "<iq xmlns='jabber:client' from='me@mydomain.com' " \
823 " to='user@domain.com/resource' type='set' id='150'> " \
824 " <jingle xmlns='urn:xmpp:jingle:1' action='session-accept' " \
825 " initiator='me@domain.com/resource'> " \
826 " <content name='audio'> " \
827 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
828 " media='audio' ssrc='4294967295'> " \
829 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
830 " <payload-type id='104' name='ISAC' clockrate='32000'/> " \
832 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
834 " <content name='video'> " \
835 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
836 " media='video' ssrc='87654321'> " \
838 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
843 const std::string kJingleAcceptWithRtpDataSsrcs(
844 "<iq xmlns='jabber:client' from='me@mydomain.com' " \
845 " to='user@domain.com/resource' type='set' id='150'> " \
846 " <jingle xmlns='urn:xmpp:jingle:1' action='session-accept' " \
847 " initiator='me@domain.com/resource'> " \
848 " <content name='audio'> " \
849 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
850 " media='audio' ssrc='4294967295'> " \
851 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
852 " <payload-type id='104' name='ISAC' clockrate='32000'/> " \
854 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
856 " <content name='video'> " \
857 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
858 " media='video' ssrc='87654321'> " \
860 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
862 " <content name='data'> " \
863 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
864 " media='data' ssrc='1010101'> " \
866 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
871 const std::string kJingleAcceptWithSctpData(
872 "<iq xmlns='jabber:client' from='me@mydomain.com' " \
873 " to='user@domain.com/resource' type='set' id='150'> " \
874 " <jingle xmlns='urn:xmpp:jingle:1' action='session-accept' " \
875 " initiator='me@domain.com/resource'> " \
876 " <content name='audio'> " \
877 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
878 " media='audio' ssrc='4294967295'> " \
879 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
880 " <payload-type id='104' name='ISAC' clockrate='32000'/> " \
882 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
884 " <content name='video'> " \
885 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
886 " media='video' ssrc='87654321'> " \
888 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
890 " <content name='data'> " \
891 " <description xmlns='google:jingle:sctp'> " \
892 " <stream sid='1'/> " \
894 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
899 std::string JingleView(const std::string& ssrc,
900 const std::string& width,
901 const std::string& height,
902 const std::string& framerate) {
903 // We have some slightly weird whitespace formatting to make the
904 // actual XML generated match the expected XML here.
907 " to='me@mydomain.com'"
909 " xmlns:cli='jabber:client'>"
911 " xmlns='urn:xmpp:jingle:1'"
912 " action='session-info'"
914 "<view xmlns='google:jingle'"
917 " ssrc='" + ssrc + "'>"
919 " width='" + width + "'"
920 " height='" + height + "'"
921 " framerate='" + framerate + "'"
928 std::string JingleStreamAdd(const std::string& content_name,
929 const std::string& nick,
930 const std::string& name,
931 const std::string& ssrc) {
934 " xmlns='jabber:client'"
935 " from='me@mydomain.com'"
936 " to='user@domain.com/resource'"
940 " xmlns='urn:xmpp:jingle:1'"
941 " action='description-info'>"
943 " xmlns='urn:xmpp:jingle:1'"
944 " name='" + content_name + "'>"
946 " xmlns='urn:xmpp:jingle:apps:rtp:1'"
947 " media='" + content_name + "'>"
949 " xmlns='google:jingle'>"
951 " nick='" + nick + "'"
952 " name='" + name + "'>"
953 " <ssrc>" + ssrc + "</ssrc>"
962 std::string JingleOutboundStreamRemove(const std::string& sid,
963 const std::string& content_name,
964 const std::string& name) {
967 " to='me@mydomain.com'"
969 " xmlns:cli='jabber:client'>"
971 " xmlns='urn:xmpp:jingle:1'"
972 " action='description-info'"
973 " sid='" + sid + "'>"
975 " name='" + content_name + "'"
976 " creator='initiator'>"
978 " xmlns='urn:xmpp:jingle:apps:rtp:1'"
979 " media='" + content_name + "'>"
981 " xmlns='google:jingle'>"
983 " name='" + name + "'>"
992 std::string JingleOutboundStreamAdd(const std::string& sid,
993 const std::string& content_name,
994 const std::string& name,
995 const std::string& ssrc) {
998 " to='me@mydomain.com'"
1000 " xmlns:cli='jabber:client'>"
1002 " xmlns='urn:xmpp:jingle:1'"
1003 " action='description-info'"
1004 " sid='" + sid + "'>"
1006 " name='" + content_name + "'"
1007 " creator='initiator'>"
1009 " xmlns='urn:xmpp:jingle:apps:rtp:1'"
1010 " media='" + content_name + "'>"
1012 " xmlns='google:jingle'>"
1014 " name='" + name + "'>"
1015 "<ssrc>" + ssrc + "</ssrc>"
1024 std::string JingleStreamAddWithoutSsrc(const std::string& content_name,
1025 const std::string& nick,
1026 const std::string& name) {
1029 " xmlns='jabber:client'"
1030 " from='me@mydomain.com'"
1031 " to='user@domain.com/resource'"
1035 " xmlns='urn:xmpp:jingle:1'"
1036 " action='description-info'>"
1038 " xmlns='urn:xmpp:jingle:1'"
1039 " name='" + content_name + "'>"
1041 " xmlns='urn:xmpp:jingle:apps:rtp:1'"
1042 " media='" + content_name + "'>"
1044 " xmlns='google:jingle'>"
1046 " nick='" + nick + "'"
1047 " name='" + name + "'>"
1056 std::string JingleStreamRemove(const std::string& content_name,
1057 const std::string& nick,
1058 const std::string& name) {
1061 " xmlns='jabber:client'"
1062 " from='me@mydomain.com'"
1063 " to='user@domain.com/resource'"
1067 " xmlns='urn:xmpp:jingle:1'"
1068 " action='description-info'>"
1070 " xmlns='urn:xmpp:jingle:1'"
1071 " name='" + content_name + "'>"
1073 " xmlns='urn:xmpp:jingle:apps:rtp:1'"
1074 " media='" + content_name + "'>"
1076 " xmlns='google:jingle'>"
1078 " nick='" + nick + "'"
1079 " name='" + name + "'/>"
1087 // Convenience function to get CallOptions that have audio enabled,
1088 // but not video or data.
1089 static cricket::CallOptions AudioCallOptions() {
1090 cricket::CallOptions options;
1091 options.recv_audio = true;
1092 options.recv_video = false;
1093 options.data_channel_type = cricket::DCT_NONE;
1097 // Convenience function to get CallOptions that have audio and video
1098 // enabled, but not data.
1099 static cricket::CallOptions VideoCallOptions() {
1100 cricket::CallOptions options;
1101 options.recv_audio = true;
1102 options.recv_video = true;
1103 options.data_channel_type = cricket::DCT_NONE;
1107 static buzz::XmlElement* CopyElement(const buzz::XmlElement* elem) {
1108 return new buzz::XmlElement(*elem);
1111 static std::string AddEncryption(std::string stanza, std::string encryption) {
1112 std::string::size_type pos = stanza.find("</description>");
1113 while (pos != std::string::npos) {
1114 stanza = stanza.insert(pos, encryption);
1115 pos = stanza.find("</description>", pos + encryption.length() + 1);
1120 static int IntFromJingleCodecParameter(const buzz::XmlElement* parameter,
1121 const std::string& expected_name) {
1123 const std::string& actual_name =
1124 parameter->Attr(cricket::QN_PAYLOADTYPE_PARAMETER_NAME);
1126 EXPECT_EQ(expected_name, actual_name)
1127 << "wrong parameter name. Expected '"
1128 << expected_name << "'. Actually '"
1129 << actual_name << "'.";
1131 return atoi(parameter->Attr(
1132 cricket::QN_PAYLOADTYPE_PARAMETER_VALUE).c_str());
1137 template <class CodecClass, class DescriptionClass>
1138 static void VerifyCodecFbParams(const FeedbackParams& expected,
1139 const DescriptionClass* desc) {
1140 if (!expected.params().empty()) {
1141 ASSERT_TRUE(desc != NULL);
1142 const std::vector<CodecClass> codecs = desc->codecs();
1143 for (size_t i = 0; i < codecs.size(); ++i) {
1144 EXPECT_EQ(expected, codecs[i].feedback_params);
1149 // Parses and extracts payload and codec info from test XML. Since
1150 // that XML will be in various contents (Gingle and Jingle), we need an
1151 // abstract parser with one concrete implementation per XML content.
1152 class MediaSessionTestParser {
1154 virtual buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) = 0;
1155 virtual buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) = 0;
1156 virtual buzz::XmlElement* NextContent(buzz::XmlElement* content) = 0;
1157 virtual buzz::XmlElement* PayloadTypeFromContent(
1158 buzz::XmlElement* content) = 0;
1159 virtual buzz::XmlElement* NextFromPayloadType(
1160 buzz::XmlElement* payload_type) = 0;
1161 virtual cricket::AudioCodec AudioCodecFromPayloadType(
1162 const buzz::XmlElement* payload_type) = 0;
1163 virtual cricket::VideoCodec VideoCodecFromPayloadType(
1164 const buzz::XmlElement* payload_type) = 0;
1165 virtual cricket::DataCodec DataCodecFromPayloadType(
1166 const buzz::XmlElement* payload_type) = 0;
1167 virtual buzz::XmlElement* EncryptionFromContent(
1168 buzz::XmlElement* content) = 0;
1169 virtual buzz::XmlElement* NextFromEncryption(
1170 buzz::XmlElement* encryption) = 0;
1171 virtual const buzz::XmlElement* BandwidthFromContent(
1172 buzz::XmlElement* content) = 0;
1173 virtual const buzz::XmlElement* RtcpMuxFromContent(
1174 buzz::XmlElement* content) = 0;
1175 virtual bool ActionIsTerminate(const buzz::XmlElement* action) = 0;
1176 virtual ~MediaSessionTestParser() {}
1179 class JingleSessionTestParser : public MediaSessionTestParser {
1181 JingleSessionTestParser() {}
1183 ~JingleSessionTestParser() {
1186 buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
1187 return stanza->FirstNamed(cricket::QN_JINGLE);
1190 buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) {
1191 // We need to be able to use multiple contents, but the action
1192 // gets deleted before we can call NextContent, so we need to
1193 // stash away a copy.
1194 action_.reset(CopyElement(action));
1195 return action_->FirstNamed(cricket::QN_JINGLE_CONTENT);
1198 buzz::XmlElement* NextContent(buzz::XmlElement* content) {
1199 // For some reason, content->NextNamed(cricket::QN_JINGLE_CONTENT)
1201 return action_->FirstNamed(cricket::QN_JINGLE_CONTENT)
1202 ->NextNamed(cricket::QN_JINGLE_CONTENT);
1205 buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* content) {
1206 buzz::XmlElement* content_desc =
1207 content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
1211 return content_desc->FirstNamed(cricket::QN_JINGLE_RTP_PAYLOADTYPE);
1214 buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
1215 return payload_type->NextNamed(cricket::QN_JINGLE_RTP_PAYLOADTYPE);
1218 void ParsePayloadTypeFeedbackParameters(const buzz::XmlElement* element,
1219 FeedbackParams* params) {
1220 const buzz::XmlElement* param =
1221 element->FirstNamed(cricket::QN_JINGLE_RTCP_FB);
1222 for (; param != NULL;
1223 param = param->NextNamed(cricket::QN_JINGLE_RTCP_FB)) {
1224 std::string type = param->Attr(cricket::QN_TYPE);
1225 std::string subtype = param->Attr(cricket::QN_SUBTYPE);
1226 if (!type.empty()) {
1227 params->Add(FeedbackParam(type, subtype));
1232 cricket::AudioCodec AudioCodecFromPayloadType(
1233 const buzz::XmlElement* payload_type) {
1235 if (payload_type->HasAttr(cricket::QN_ID))
1236 id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1239 if (payload_type->HasAttr(cricket::QN_NAME))
1240 name = payload_type->Attr(cricket::QN_NAME);
1243 if (payload_type->HasAttr(cricket::QN_CLOCKRATE))
1244 clockrate = atoi(payload_type->Attr(cricket::QN_CLOCKRATE).c_str());
1246 int bitrate = IntFromJingleCodecParameter(
1247 payload_type->FirstNamed(cricket::QN_PARAMETER), "bitrate");
1250 if (payload_type->HasAttr(cricket::QN_CHANNELS))
1251 channels = atoi(payload_type->Attr(
1252 cricket::QN_CHANNELS).c_str());
1254 AudioCodec codec = AudioCodec(id, name, clockrate, bitrate, channels, 0);
1255 ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params);
1259 cricket::VideoCodec VideoCodecFromPayloadType(
1260 const buzz::XmlElement* payload_type) {
1262 if (payload_type->HasAttr(cricket::QN_ID))
1263 id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1266 if (payload_type->HasAttr(cricket::QN_NAME))
1267 name = payload_type->Attr(cricket::QN_NAME);
1272 const buzz::XmlElement* param =
1273 payload_type->FirstNamed(cricket::QN_PARAMETER);
1275 width = IntFromJingleCodecParameter(param, "width");
1276 param = param->NextNamed(cricket::QN_PARAMETER);
1278 height = IntFromJingleCodecParameter(param, "height");
1279 param = param->NextNamed(cricket::QN_PARAMETER);
1281 framerate = IntFromJingleCodecParameter(param, "framerate");
1285 VideoCodec codec = VideoCodec(id, name, width, height, framerate, 0);
1286 ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params);
1290 cricket::DataCodec DataCodecFromPayloadType(
1291 const buzz::XmlElement* payload_type) {
1293 if (payload_type->HasAttr(cricket::QN_ID))
1294 id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1297 if (payload_type->HasAttr(cricket::QN_NAME))
1298 name = payload_type->Attr(cricket::QN_NAME);
1300 DataCodec codec = DataCodec(id, name, 0);
1301 ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params);
1305 bool ActionIsTerminate(const buzz::XmlElement* action) {
1306 return (action->HasAttr(cricket::QN_ACTION) &&
1307 action->Attr(cricket::QN_ACTION) == "session-terminate");
1310 buzz::XmlElement* EncryptionFromContent(buzz::XmlElement* content) {
1311 buzz::XmlElement* content_desc =
1312 content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
1316 return content_desc->FirstNamed(cricket::QN_ENCRYPTION);
1319 buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
1320 return encryption->NextNamed(cricket::QN_ENCRYPTION);
1323 const buzz::XmlElement* BandwidthFromContent(buzz::XmlElement* content) {
1324 buzz::XmlElement* content_desc =
1325 content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
1329 return content_desc->FirstNamed(cricket::QN_JINGLE_RTP_BANDWIDTH);
1332 const buzz::XmlElement* RtcpMuxFromContent(buzz::XmlElement* content) {
1333 return content->FirstNamed(cricket::QN_JINGLE_RTCP_MUX);
1337 rtc::scoped_ptr<buzz::XmlElement> action_;
1340 class GingleSessionTestParser : public MediaSessionTestParser {
1342 GingleSessionTestParser() : found_content_count_(0) {}
1344 buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
1345 return stanza->FirstNamed(cricket::QN_GINGLE_SESSION);
1348 buzz::XmlElement* ContentFromAction(buzz::XmlElement* session) {
1349 buzz::XmlElement* content =
1350 session->FirstNamed(cricket::QN_GINGLE_AUDIO_CONTENT);
1351 if (content == NULL)
1352 content = session->FirstNamed(cricket::QN_GINGLE_VIDEO_CONTENT);
1356 // Assumes contents are in order of audio, and then video.
1357 buzz::XmlElement* NextContent(buzz::XmlElement* content) {
1358 found_content_count_++;
1362 buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* content) {
1363 if (found_content_count_ > 0) {
1364 return content->FirstNamed(cricket::QN_GINGLE_VIDEO_PAYLOADTYPE);
1366 return content->FirstNamed(cricket::QN_GINGLE_AUDIO_PAYLOADTYPE);
1370 buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
1371 if (found_content_count_ > 0) {
1372 return payload_type->NextNamed(cricket::QN_GINGLE_VIDEO_PAYLOADTYPE);
1374 return payload_type->NextNamed(cricket::QN_GINGLE_AUDIO_PAYLOADTYPE);
1378 cricket::AudioCodec AudioCodecFromPayloadType(
1379 const buzz::XmlElement* payload_type) {
1381 if (payload_type->HasAttr(cricket::QN_ID))
1382 id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1385 if (payload_type->HasAttr(cricket::QN_NAME))
1386 name = payload_type->Attr(cricket::QN_NAME);
1389 if (payload_type->HasAttr(cricket::QN_CLOCKRATE))
1390 clockrate = atoi(payload_type->Attr(cricket::QN_CLOCKRATE).c_str());
1393 if (payload_type->HasAttr(cricket::QN_BITRATE))
1394 bitrate = atoi(payload_type->Attr(cricket::QN_BITRATE).c_str());
1397 if (payload_type->HasAttr(cricket::QN_CHANNELS))
1398 channels = atoi(payload_type->Attr(cricket::QN_CHANNELS).c_str());
1400 return cricket::AudioCodec(id, name, clockrate, bitrate, channels, 0);
1403 cricket::VideoCodec VideoCodecFromPayloadType(
1404 const buzz::XmlElement* payload_type) {
1406 if (payload_type->HasAttr(cricket::QN_ID))
1407 id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1410 if (payload_type->HasAttr(cricket::QN_NAME))
1411 name = payload_type->Attr(cricket::QN_NAME);
1414 if (payload_type->HasAttr(cricket::QN_WIDTH))
1415 width = atoi(payload_type->Attr(cricket::QN_WIDTH).c_str());
1418 if (payload_type->HasAttr(cricket::QN_HEIGHT))
1419 height = atoi(payload_type->Attr(cricket::QN_HEIGHT).c_str());
1422 if (payload_type->HasAttr(cricket::QN_FRAMERATE))
1423 framerate = atoi(payload_type->Attr(cricket::QN_FRAMERATE).c_str());
1425 return cricket::VideoCodec(id, name, width, height, framerate, 0);
1428 cricket::DataCodec DataCodecFromPayloadType(
1429 const buzz::XmlElement* payload_type) {
1430 // Gingle can't do data codecs.
1431 return cricket::DataCodec(0, "", 0);
1434 buzz::XmlElement* EncryptionFromContent(
1435 buzz::XmlElement* content) {
1436 return content->FirstNamed(cricket::QN_ENCRYPTION);
1439 buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
1440 return encryption->NextNamed(cricket::QN_ENCRYPTION);
1443 const buzz::XmlElement* BandwidthFromContent(buzz::XmlElement* content) {
1444 return content->FirstNamed(cricket::QN_GINGLE_VIDEO_BANDWIDTH);
1447 const buzz::XmlElement* RtcpMuxFromContent(buzz::XmlElement* content) {
1451 bool ActionIsTerminate(const buzz::XmlElement* session) {
1452 return (session->HasAttr(buzz::QN_TYPE) &&
1453 session->Attr(buzz::QN_TYPE) == "terminate");
1456 int found_content_count_;
1459 class MediaSessionClientTest : public sigslot::has_slots<> {
1461 explicit MediaSessionClientTest(MediaSessionTestParser* parser,
1462 cricket::SignalingProtocol initial_protocol) {
1463 nm_ = new rtc::BasicNetworkManager();
1464 pa_ = new cricket::BasicPortAllocator(nm_);
1465 sm_ = new cricket::SessionManager(pa_, NULL);
1466 fme_ = new cricket::FakeMediaEngine();
1467 fdme_ = new cricket::FakeDataEngine();
1469 FeedbackParams params_nack_fir;
1470 params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamCcm,
1471 cricket::kRtcpFbCcmParamFir));
1472 params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamNack));
1473 FeedbackParams params_nack;
1474 params_nack.Add(FeedbackParam(cricket::kRtcpFbParamNack));
1476 std::vector<cricket::AudioCodec>
1477 audio_codecs(kAudioCodecs, kAudioCodecs + ARRAY_SIZE(kAudioCodecs));
1478 SetCodecFeedbackParams(&audio_codecs, params_nack);
1479 fme_->SetAudioCodecs(audio_codecs);
1480 std::vector<cricket::VideoCodec>
1481 video_codecs(kVideoCodecs, kVideoCodecs + ARRAY_SIZE(kVideoCodecs));
1482 SetCodecFeedbackParams(&video_codecs, params_nack_fir);
1483 fme_->SetVideoCodecs(video_codecs);
1484 std::vector<cricket::DataCodec>
1485 data_codecs(kDataCodecs, kDataCodecs + ARRAY_SIZE(kDataCodecs));
1486 SetCodecFeedbackParams(&data_codecs, params_nack);
1487 fdme_->SetDataCodecs(data_codecs);
1489 client_ = new cricket::MediaSessionClient(
1490 buzz::Jid("user@domain.com/resource"), sm_,
1491 fme_, fdme_, new cricket::FakeDeviceManager());
1492 client_->session_manager()->SignalOutgoingMessage.connect(
1493 this, &MediaSessionClientTest::OnSendStanza);
1494 client_->session_manager()->SignalSessionCreate.connect(
1495 this, &MediaSessionClientTest::OnSessionCreate);
1496 client_->SignalCallCreate.connect(
1497 this, &MediaSessionClientTest::OnCallCreate);
1498 client_->SignalCallDestroy.connect(
1499 this, &MediaSessionClientTest::OnCallDestroy);
1503 initial_protocol_ = initial_protocol;
1504 expect_incoming_crypto_ = false;
1505 expect_outgoing_crypto_ = false;
1506 expected_video_bandwidth_ = cricket::kAutoBandwidth;
1507 expected_video_rtcp_mux_ = false;
1510 ~MediaSessionClientTest() {
1519 buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
1520 return parser_->ActionFromStanza(stanza);
1523 buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) {
1524 return parser_->ContentFromAction(action);
1527 buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* payload) {
1528 return parser_->PayloadTypeFromContent(payload);
1531 buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
1532 return parser_->NextFromPayloadType(payload_type);
1535 buzz::XmlElement* EncryptionFromContent(buzz::XmlElement* content) {
1536 return parser_->EncryptionFromContent(content);
1539 buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
1540 return parser_->NextFromEncryption(encryption);
1543 cricket::AudioCodec AudioCodecFromPayloadType(
1544 const buzz::XmlElement* payload_type) {
1545 return parser_->AudioCodecFromPayloadType(payload_type);
1548 cricket::VideoCodec VideoCodecFromPayloadType(
1549 const buzz::XmlElement* payload_type) {
1550 return parser_->VideoCodecFromPayloadType(payload_type);
1553 cricket::DataCodec DataCodecFromPayloadType(
1554 const buzz::XmlElement* payload_type) {
1555 return parser_->DataCodecFromPayloadType(payload_type);
1558 const AudioContentDescription* GetFirstAudioContentDescription(
1559 const cricket::SessionDescription* sdesc) {
1560 const cricket::ContentInfo* content =
1561 cricket::GetFirstAudioContent(sdesc);
1562 if (content == NULL)
1564 return static_cast<const AudioContentDescription*>(content->description);
1567 const cricket::VideoContentDescription* GetFirstVideoContentDescription(
1568 const cricket::SessionDescription* sdesc) {
1569 const cricket::ContentInfo* content =
1570 cricket::GetFirstVideoContent(sdesc);
1571 if (content == NULL)
1573 return static_cast<const cricket::VideoContentDescription*>(
1574 content->description);
1577 void CheckCryptoFromGoodIncomingInitiate(const cricket::Session* session) {
1578 ASSERT_TRUE(session != NULL);
1579 const AudioContentDescription* content =
1580 GetFirstAudioContentDescription(session->remote_description());
1581 ASSERT_TRUE(content != NULL);
1582 ASSERT_EQ(2U, content->cryptos().size());
1583 ASSERT_EQ(145, content->cryptos()[0].tag);
1584 ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", content->cryptos()[0].cipher_suite);
1585 ASSERT_EQ("inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9",
1586 content->cryptos()[0].key_params);
1587 ASSERT_EQ(51, content->cryptos()[1].tag);
1588 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", content->cryptos()[1].cipher_suite);
1589 ASSERT_EQ("inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy",
1590 content->cryptos()[1].key_params);
1593 void CheckCryptoForGoodOutgoingAccept(const cricket::Session* session) {
1594 const AudioContentDescription* content =
1595 GetFirstAudioContentDescription(session->local_description());
1596 ASSERT_EQ(1U, content->cryptos().size());
1597 ASSERT_EQ(145, content->cryptos()[0].tag);
1598 ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", content->cryptos()[0].cipher_suite);
1599 ASSERT_EQ(47U, content->cryptos()[0].key_params.size());
1602 void CheckBadCryptoFromIncomingInitiate(const cricket::Session* session) {
1603 const AudioContentDescription* content =
1604 GetFirstAudioContentDescription(session->remote_description());
1605 ASSERT_EQ(1U, content->cryptos().size());
1606 ASSERT_EQ(145, content->cryptos()[0].tag);
1607 ASSERT_EQ("NOT_SUPPORTED", content->cryptos()[0].cipher_suite);
1608 ASSERT_EQ("inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9",
1609 content->cryptos()[0].key_params);
1612 void CheckNoCryptoForOutgoingAccept(const cricket::Session* session) {
1613 const AudioContentDescription* content =
1614 GetFirstAudioContentDescription(session->local_description());
1615 ASSERT_TRUE(content->cryptos().empty());
1618 void CheckRtcpFb(const cricket::SessionDescription* sdesc) {
1619 VerifyCodecFbParams<AudioCodec>(expected_audio_fb_params_,
1620 GetFirstAudioContentDescription(sdesc));
1622 VerifyCodecFbParams<VideoCodec>(expected_video_fb_params_,
1623 GetFirstVideoContentDescription(sdesc));
1625 VerifyCodecFbParams<DataCodec>(expected_data_fb_params_,
1626 GetFirstDataContentDescription(sdesc));
1629 void CheckVideoBandwidth(int expected_bandwidth,
1630 const cricket::SessionDescription* sdesc) {
1631 const cricket::VideoContentDescription* video =
1632 GetFirstVideoContentDescription(sdesc);
1633 if (video != NULL) {
1634 ASSERT_EQ(expected_bandwidth, video->bandwidth());
1638 void CheckVideoRtcpMux(bool expected_video_rtcp_mux,
1639 const cricket::SessionDescription* sdesc) {
1640 const cricket::VideoContentDescription* video =
1641 GetFirstVideoContentDescription(sdesc);
1642 if (video != NULL) {
1643 ASSERT_EQ(expected_video_rtcp_mux, video->rtcp_mux());
1647 virtual void CheckRtpDataContent(buzz::XmlElement* content) {
1648 if (initial_protocol_) {
1649 // Gingle can not write out data content.
1653 buzz::XmlElement* e = PayloadTypeFromContent(content);
1654 ASSERT_TRUE(e != NULL);
1655 cricket::DataCodec codec = DataCodecFromPayloadType(e);
1656 EXPECT_EQ(127, codec.id);
1657 EXPECT_EQ("google-data", codec.name);
1658 EXPECT_EQ(expected_data_fb_params_, codec.feedback_params);
1660 CheckDataRtcpMux(true, call_->sessions()[0]->local_description());
1661 CheckDataRtcpMux(true, call_->sessions()[0]->remote_description());
1662 if (expect_outgoing_crypto_) {
1663 content = parser_->NextContent(content);
1664 buzz::XmlElement* encryption = EncryptionFromContent(content);
1665 ASSERT_TRUE(encryption != NULL);
1666 // TODO(pthatcher): Check encryption parameters?
1670 virtual void CheckSctpDataContent(buzz::XmlElement* content) {
1671 if (initial_protocol_) {
1672 // Gingle can not write out data content.
1676 buzz::XmlElement* payload_type = PayloadTypeFromContent(content);
1677 ASSERT_TRUE(payload_type == NULL);
1678 buzz::XmlElement* encryption = EncryptionFromContent(content);
1679 ASSERT_TRUE(encryption == NULL);
1680 // TODO(pthatcher): Check for <streams>.
1683 void CheckDataRtcpMux(bool expected_data_rtcp_mux,
1684 const cricket::SessionDescription* sdesc) {
1685 const cricket::DataContentDescription* data =
1686 GetFirstDataContentDescription(sdesc);
1688 ASSERT_EQ(expected_data_rtcp_mux, data->rtcp_mux());
1692 void CheckAudioSsrcForIncomingAccept(const cricket::Session* session) {
1693 const AudioContentDescription* audio =
1694 GetFirstAudioContentDescription(session->remote_description());
1695 ASSERT_TRUE(audio != NULL);
1696 ASSERT_EQ(kAudioSsrc, audio->first_ssrc());
1699 void CheckVideoSsrcForIncomingAccept(const cricket::Session* session) {
1700 const cricket::VideoContentDescription* video =
1701 GetFirstVideoContentDescription(session->remote_description());
1702 ASSERT_TRUE(video != NULL);
1703 ASSERT_EQ(kVideoSsrc, video->first_ssrc());
1706 void CheckDataSsrcForIncomingAccept(const cricket::Session* session) {
1707 const cricket::DataContentDescription* data =
1708 GetFirstDataContentDescription(session->remote_description());
1709 ASSERT_TRUE(data != NULL);
1710 ASSERT_EQ(kDataSsrc, data->first_ssrc());
1713 void TestGoodIncomingInitiate(const std::string& initiate_string,
1714 const cricket::CallOptions& options,
1715 buzz::XmlElement** element) {
1718 rtc::scoped_ptr<buzz::XmlElement> el(
1719 buzz::XmlElement::ForStr(initiate_string));
1720 client_->session_manager()->OnIncomingMessage(el.get());
1721 ASSERT_TRUE(call_ != NULL);
1722 ASSERT_TRUE(call_->sessions()[0] != NULL);
1723 ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE,
1724 call_->sessions()[0]->state());
1725 ASSERT_EQ(1U, stanzas_.size());
1726 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1727 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1728 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
1730 CheckVideoBandwidth(expected_video_bandwidth_,
1731 call_->sessions()[0]->remote_description());
1732 CheckVideoRtcpMux(expected_video_rtcp_mux_,
1733 call_->sessions()[0]->remote_description());
1734 CheckRtcpFb(call_->sessions()[0]->remote_description());
1735 if (expect_incoming_crypto_) {
1736 CheckCryptoFromGoodIncomingInitiate(call_->sessions()[0]);
1739 // TODO(pthatcher): Add tests for sending <bandwidth> in accept.
1740 call_->AcceptSession(call_->sessions()[0], options);
1741 ASSERT_EQ(cricket::Session::STATE_SENTACCEPT,
1742 call_->sessions()[0]->state());
1743 ASSERT_EQ(1U, stanzas_.size());
1744 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1745 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1746 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1748 buzz::XmlElement* e = ActionFromStanza(stanzas_[0]);
1749 ASSERT_TRUE(e != NULL);
1750 ASSERT_TRUE(ContentFromAction(e) != NULL);
1751 *element = CopyElement(ContentFromAction(e));
1752 ASSERT_TRUE(*element != NULL);
1754 if (expect_outgoing_crypto_) {
1755 CheckCryptoForGoodOutgoingAccept(call_->sessions()[0]);
1758 if (options.data_channel_type == cricket::DCT_RTP) {
1759 CheckDataRtcpMux(true, call_->sessions()[0]->local_description());
1760 CheckDataRtcpMux(true, call_->sessions()[0]->remote_description());
1761 // TODO(pthatcher): Check rtcpmux and crypto?
1765 ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE,
1766 call_->sessions()[0]->state());
1767 ASSERT_EQ(1U, stanzas_.size());
1768 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1769 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1770 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1771 e = ActionFromStanza(stanzas_[0]);
1772 ASSERT_TRUE(e != NULL);
1773 ASSERT_TRUE(parser_->ActionIsTerminate(e));
1777 void TestRejectOffer(const std::string &initiate_string,
1778 const cricket::CallOptions& options,
1779 buzz::XmlElement** element) {
1782 rtc::scoped_ptr<buzz::XmlElement> el(
1783 buzz::XmlElement::ForStr(initiate_string));
1784 client_->session_manager()->OnIncomingMessage(el.get());
1785 ASSERT_TRUE(call_ != NULL);
1786 ASSERT_TRUE(call_->sessions()[0] != NULL);
1787 ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE,
1788 call_->sessions()[0]->state());
1789 ASSERT_EQ(1U, stanzas_.size());
1790 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1791 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1792 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
1795 call_->AcceptSession(call_->sessions()[0], options);
1796 ASSERT_EQ(cricket::Session::STATE_SENTACCEPT,
1797 call_->sessions()[0]->state());
1798 ASSERT_EQ(1U, stanzas_.size());
1799 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1800 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1801 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1803 buzz::XmlElement* e = ActionFromStanza(stanzas_[0]);
1804 ASSERT_TRUE(e != NULL);
1805 ASSERT_TRUE(ContentFromAction(e) != NULL);
1806 *element = CopyElement(ContentFromAction(e));
1807 ASSERT_TRUE(*element != NULL);
1810 buzz::XmlElement* content = *element;
1811 // The NextContent method actually returns the second content. So we
1812 // can't handle the case when audio, video and data are all enabled. But
1813 // since we are testing rejection, it won't be the case.
1814 if (options.has_audio()) {
1815 ASSERT_TRUE(content != NULL);
1816 ASSERT_EQ("test audio", content->Attr(buzz::QName("", "name")));
1817 content = parser_->NextContent(content);
1820 if (options.has_video()) {
1821 ASSERT_TRUE(content != NULL);
1822 ASSERT_EQ("test video", content->Attr(buzz::QName("", "name")));
1823 content = parser_->NextContent(content);
1826 if (options.has_data()) {
1827 ASSERT_TRUE(content != NULL);
1828 ASSERT_EQ("test data", content->Attr(buzz::QName("", "name")));
1829 content = parser_->NextContent(content);
1833 ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE,
1834 call_->sessions()[0]->state());
1835 ASSERT_EQ(1U, stanzas_.size());
1836 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1837 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1838 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1839 e = ActionFromStanza(stanzas_[0]);
1840 ASSERT_TRUE(e != NULL);
1841 ASSERT_TRUE(parser_->ActionIsTerminate(e));
1845 void TestBadIncomingInitiate(const std::string& initiate_string) {
1846 rtc::scoped_ptr<buzz::XmlElement> el(
1847 buzz::XmlElement::ForStr(initiate_string));
1848 client_->session_manager()->OnIncomingMessage(el.get());
1849 ASSERT_TRUE(call_ != NULL);
1850 ASSERT_TRUE(call_->sessions()[0] != NULL);
1851 ASSERT_EQ(cricket::Session::STATE_SENTREJECT,
1852 call_->sessions()[0]->state());
1853 ASSERT_EQ(2U, stanzas_.size());
1854 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1855 ASSERT_TRUE(stanzas_[1]->HasAttr(buzz::QN_TYPE));
1856 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[1]->Attr(buzz::QN_TYPE));
1860 void VerifyAudioCodec(const AudioCodec& codec, int id,
1861 const std::string& name, int clockrate,
1862 int bitrate, int channels) {
1863 ASSERT_EQ(id, codec.id);
1864 ASSERT_EQ(name, codec.name);
1865 ASSERT_EQ(clockrate, codec.clockrate);
1866 ASSERT_EQ(bitrate, codec.bitrate);
1867 ASSERT_EQ(channels, codec.channels);
1868 ASSERT_EQ(expected_audio_fb_params_, codec.feedback_params);
1871 void TestGoodOutgoingInitiate(const cricket::CallOptions& options) {
1872 if (initial_protocol_ == cricket::PROTOCOL_JINGLE) {
1873 // rtcp fb is only implemented for jingle.
1877 client_->CreateCall();
1878 ASSERT_TRUE(call_ != NULL);
1879 call_->InitiateSession(buzz::Jid("me@mydomain.com"),
1880 buzz::Jid("me@mydomain.com"), options);
1881 ASSERT_TRUE(call_->sessions()[0] != NULL);
1882 ASSERT_EQ(cricket::Session::STATE_SENTINITIATE,
1883 call_->sessions()[0]->state());
1884 ASSERT_EQ(1U, stanzas_.size());
1885 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1886 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1887 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1888 buzz::XmlElement* action = ActionFromStanza(stanzas_[0]);
1889 ASSERT_TRUE(action != NULL);
1890 buzz::XmlElement* content = ContentFromAction(action);
1891 ASSERT_TRUE(content != NULL);
1893 buzz::XmlElement* e = PayloadTypeFromContent(content);
1894 ASSERT_TRUE(e != NULL);
1895 cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
1896 VerifyAudioCodec(codec, 103, "ISAC", 16000, 0, 1);
1898 e = NextFromPayloadType(e);
1899 ASSERT_TRUE(e != NULL);
1900 codec = AudioCodecFromPayloadType(e);
1901 VerifyAudioCodec(codec, 104, "ISAC", 32000, 0, 1);
1903 e = NextFromPayloadType(e);
1904 ASSERT_TRUE(e != NULL);
1905 codec = AudioCodecFromPayloadType(e);
1906 VerifyAudioCodec(codec, 119, "ISACLC", 16000, 40000, 1);
1908 e = NextFromPayloadType(e);
1909 ASSERT_TRUE(e != NULL);
1910 codec = AudioCodecFromPayloadType(e);
1911 VerifyAudioCodec(codec, 99, "speex", 16000, 22000, 1);
1913 e = NextFromPayloadType(e);
1914 ASSERT_TRUE(e != NULL);
1915 codec = AudioCodecFromPayloadType(e);
1916 VerifyAudioCodec(codec, 97, "IPCMWB", 16000, 80000, 1);
1918 e = NextFromPayloadType(e);
1919 ASSERT_TRUE(e != NULL);
1920 codec = AudioCodecFromPayloadType(e);
1921 VerifyAudioCodec(codec, 9, "G722", 8000, 64000, 1);
1923 e = NextFromPayloadType(e);
1924 ASSERT_TRUE(e != NULL);
1925 codec = AudioCodecFromPayloadType(e);
1926 VerifyAudioCodec(codec, 102, "iLBC", 8000, 13300, 1);
1928 e = NextFromPayloadType(e);
1929 ASSERT_TRUE(e != NULL);
1930 codec = AudioCodecFromPayloadType(e);
1931 VerifyAudioCodec(codec, 98, "speex", 8000, 11000, 1);
1933 e = NextFromPayloadType(e);
1934 ASSERT_TRUE(e != NULL);
1935 codec = AudioCodecFromPayloadType(e);
1936 VerifyAudioCodec(codec, 3, "GSM", 8000, 13000, 1);
1938 e = NextFromPayloadType(e);
1939 ASSERT_TRUE(e != NULL);
1940 codec = AudioCodecFromPayloadType(e);
1941 VerifyAudioCodec(codec, 100, "EG711U", 8000, 64000, 1);
1943 e = NextFromPayloadType(e);
1944 ASSERT_TRUE(e != NULL);
1945 codec = AudioCodecFromPayloadType(e);
1946 VerifyAudioCodec(codec, 101, "EG711A", 8000, 64000, 1);
1948 e = NextFromPayloadType(e);
1949 ASSERT_TRUE(e != NULL);
1950 codec = AudioCodecFromPayloadType(e);
1951 VerifyAudioCodec(codec, 0, "PCMU", 8000, 64000, 1);
1953 e = NextFromPayloadType(e);
1954 ASSERT_TRUE(e != NULL);
1955 codec = AudioCodecFromPayloadType(e);
1956 VerifyAudioCodec(codec, 8, "PCMA", 8000, 64000, 1);
1958 e = NextFromPayloadType(e);
1959 ASSERT_TRUE(e != NULL);
1960 codec = AudioCodecFromPayloadType(e);
1961 VerifyAudioCodec(codec, 126, "CN", 32000, 0, 1);
1963 e = NextFromPayloadType(e);
1964 ASSERT_TRUE(e != NULL);
1965 codec = AudioCodecFromPayloadType(e);
1966 VerifyAudioCodec(codec, 105, "CN", 16000, 0, 1);
1968 e = NextFromPayloadType(e);
1969 ASSERT_TRUE(e != NULL);
1970 codec = AudioCodecFromPayloadType(e);
1971 VerifyAudioCodec(codec, 13, "CN", 8000, 0, 1);
1973 e = NextFromPayloadType(e);
1974 ASSERT_TRUE(e != NULL);
1975 codec = AudioCodecFromPayloadType(e);
1976 VerifyAudioCodec(codec, 117, "red", 8000, 0, 1);
1978 e = NextFromPayloadType(e);
1979 ASSERT_TRUE(e != NULL);
1980 codec = AudioCodecFromPayloadType(e);
1981 VerifyAudioCodec(codec, 106, "telephone-event", 8000, 0, 1);
1983 e = NextFromPayloadType(e);
1984 ASSERT_TRUE(e == NULL);
1986 if (expect_outgoing_crypto_) {
1987 buzz::XmlElement* encryption = EncryptionFromContent(content);
1988 ASSERT_TRUE(encryption != NULL);
1990 if (client_->secure() == cricket::SEC_REQUIRED) {
1991 ASSERT_TRUE(cricket::GetXmlAttr(
1992 encryption, cricket::QN_ENCRYPTION_REQUIRED, false));
1995 if (content->Name().Namespace() == cricket::NS_GINGLE_AUDIO) {
1996 e = encryption->FirstNamed(cricket::QN_GINGLE_AUDIO_CRYPTO_USAGE);
1997 ASSERT_TRUE(e != NULL);
1999 e->NextNamed(cricket::QN_GINGLE_AUDIO_CRYPTO_USAGE) == NULL);
2001 e->FirstNamed(cricket::QN_GINGLE_VIDEO_CRYPTO_USAGE) == NULL);
2004 e = encryption->FirstNamed(cricket::QN_CRYPTO);
2005 ASSERT_TRUE(e != NULL);
2006 ASSERT_EQ("0", e->Attr(cricket::QN_CRYPTO_TAG));
2007 ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", e->Attr(cricket::QN_CRYPTO_SUITE));
2008 std::string key_0 = e->Attr(cricket::QN_CRYPTO_KEY_PARAMS);
2009 ASSERT_EQ(47U, key_0.length());
2010 ASSERT_EQ("inline:", key_0.substr(0, 7));
2012 e = e->NextNamed(cricket::QN_CRYPTO);
2013 ASSERT_TRUE(e != NULL);
2014 ASSERT_EQ("1", e->Attr(cricket::QN_CRYPTO_TAG));
2015 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", e->Attr(cricket::QN_CRYPTO_SUITE));
2016 std::string key_1 = e->Attr(cricket::QN_CRYPTO_KEY_PARAMS);
2017 ASSERT_EQ(47U, key_1.length());
2018 ASSERT_EQ("inline:", key_1.substr(0, 7));
2019 ASSERT_NE(key_0, key_1);
2021 encryption = NextFromEncryption(encryption);
2022 ASSERT_TRUE(encryption == NULL);
2025 if (options.has_video()) {
2026 CheckVideoBandwidth(options.video_bandwidth,
2027 call_->sessions()[0]->local_description());
2028 CheckVideoRtcpMux(expected_video_rtcp_mux_,
2029 call_->sessions()[0]->remote_description());
2030 content = parser_->NextContent(content);
2031 const buzz::XmlElement* bandwidth =
2032 parser_->BandwidthFromContent(content);
2033 if (options.video_bandwidth == cricket::kAutoBandwidth) {
2034 ASSERT_TRUE(bandwidth == NULL);
2036 ASSERT_TRUE(bandwidth != NULL);
2037 ASSERT_EQ("AS", bandwidth->Attr(buzz::QName("", "type")));
2038 ASSERT_EQ(rtc::ToString(options.video_bandwidth / 1000),
2039 bandwidth->BodyText());
2042 buzz::XmlElement* e = PayloadTypeFromContent(content);
2043 ASSERT_TRUE(e != NULL);
2044 VideoCodec codec = VideoCodecFromPayloadType(e);
2045 VideoCodec expected_codec = kVideoCodecs[0];
2046 expected_codec.preference = codec.preference;
2047 expected_codec.feedback_params = expected_video_fb_params_;
2048 EXPECT_EQ(expected_codec, codec);
2051 if (options.data_channel_type == cricket::DCT_RTP) {
2052 content = parser_->NextContent(content);
2053 CheckRtpDataContent(content);
2056 if (options.data_channel_type == cricket::DCT_SCTP) {
2057 content = parser_->NextContent(content);
2058 CheckSctpDataContent(content);
2064 void TestHasAllSupportedAudioCodecs(buzz::XmlElement* e) {
2065 ASSERT_TRUE(e != NULL);
2067 e = PayloadTypeFromContent(e);
2068 ASSERT_TRUE(e != NULL);
2069 cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2070 ASSERT_EQ(103, codec.id);
2071 ASSERT_EQ("ISAC", codec.name);
2072 ASSERT_EQ(16000, codec.clockrate);
2073 ASSERT_EQ(1, codec.channels);
2075 e = NextFromPayloadType(e);
2076 ASSERT_TRUE(e != NULL);
2077 codec = AudioCodecFromPayloadType(e);
2078 ASSERT_EQ(104, codec.id);
2079 ASSERT_EQ("ISAC", codec.name);
2080 ASSERT_EQ(32000, codec.clockrate);
2081 ASSERT_EQ(1, codec.channels);
2083 e = NextFromPayloadType(e);
2084 ASSERT_TRUE(e != NULL);
2085 codec = AudioCodecFromPayloadType(e);
2086 ASSERT_EQ(119, codec.id);
2087 ASSERT_EQ("ISACLC", codec.name);
2088 ASSERT_EQ(16000, codec.clockrate);
2089 ASSERT_EQ(40000, codec.bitrate);
2090 ASSERT_EQ(1, codec.channels);
2092 e = NextFromPayloadType(e);
2093 ASSERT_TRUE(e != NULL);
2094 codec = AudioCodecFromPayloadType(e);
2095 ASSERT_EQ(99, codec.id);
2096 ASSERT_EQ("speex", codec.name);
2097 ASSERT_EQ(16000, codec.clockrate);
2098 ASSERT_EQ(22000, codec.bitrate);
2099 ASSERT_EQ(1, codec.channels);
2101 e = NextFromPayloadType(e);
2102 ASSERT_TRUE(e != NULL);
2103 codec = AudioCodecFromPayloadType(e);
2104 ASSERT_EQ(97, codec.id);
2105 ASSERT_EQ("IPCMWB", codec.name);
2106 ASSERT_EQ(16000, codec.clockrate);
2107 ASSERT_EQ(80000, codec.bitrate);
2108 ASSERT_EQ(1, codec.channels);
2110 e = NextFromPayloadType(e);
2111 ASSERT_TRUE(e != NULL);
2112 codec = AudioCodecFromPayloadType(e);
2113 ASSERT_EQ(9, codec.id);
2114 ASSERT_EQ("G722", codec.name);
2115 ASSERT_EQ(8000, codec.clockrate);
2116 ASSERT_EQ(64000, codec.bitrate);
2117 ASSERT_EQ(1, codec.channels);
2119 e = NextFromPayloadType(e);
2120 ASSERT_TRUE(e != NULL);
2121 codec = AudioCodecFromPayloadType(e);
2122 ASSERT_EQ(102, codec.id);
2123 ASSERT_EQ("iLBC", codec.name);
2124 ASSERT_EQ(8000, codec.clockrate);
2125 ASSERT_EQ(13300, codec.bitrate);
2126 ASSERT_EQ(1, codec.channels);
2128 e = NextFromPayloadType(e);
2129 ASSERT_TRUE(e != NULL);
2130 codec = AudioCodecFromPayloadType(e);
2131 ASSERT_EQ(98, codec.id);
2132 ASSERT_EQ("speex", codec.name);
2133 ASSERT_EQ(8000, codec.clockrate);
2134 ASSERT_EQ(11000, codec.bitrate);
2135 ASSERT_EQ(1, codec.channels);
2137 e = NextFromPayloadType(e);
2138 ASSERT_TRUE(e != NULL);
2139 codec = AudioCodecFromPayloadType(e);
2140 ASSERT_EQ(3, codec.id);
2141 ASSERT_EQ("GSM", codec.name);
2142 ASSERT_EQ(8000, codec.clockrate);
2143 ASSERT_EQ(13000, codec.bitrate);
2144 ASSERT_EQ(1, codec.channels);
2146 e = NextFromPayloadType(e);
2147 ASSERT_TRUE(e != NULL);
2148 codec = AudioCodecFromPayloadType(e);
2149 ASSERT_EQ(100, codec.id);
2150 ASSERT_EQ("EG711U", codec.name);
2151 ASSERT_EQ(8000, codec.clockrate);
2152 ASSERT_EQ(64000, codec.bitrate);
2153 ASSERT_EQ(1, codec.channels);
2155 e = NextFromPayloadType(e);
2156 ASSERT_TRUE(e != NULL);
2157 codec = AudioCodecFromPayloadType(e);
2158 ASSERT_EQ(101, codec.id);
2159 ASSERT_EQ("EG711A", codec.name);
2160 ASSERT_EQ(8000, codec.clockrate);
2161 ASSERT_EQ(64000, codec.bitrate);
2162 ASSERT_EQ(1, codec.channels);
2164 e = NextFromPayloadType(e);
2165 ASSERT_TRUE(e != NULL);
2166 codec = AudioCodecFromPayloadType(e);
2167 ASSERT_EQ(0, codec.id);
2168 ASSERT_EQ("PCMU", codec.name);
2169 ASSERT_EQ(8000, codec.clockrate);
2170 ASSERT_EQ(64000, codec.bitrate);
2171 ASSERT_EQ(1, codec.channels);
2173 e = NextFromPayloadType(e);
2174 ASSERT_TRUE(e != NULL);
2175 codec = AudioCodecFromPayloadType(e);
2176 ASSERT_EQ(8, codec.id);
2177 ASSERT_EQ("PCMA", codec.name);
2178 ASSERT_EQ(8000, codec.clockrate);
2179 ASSERT_EQ(64000, codec.bitrate);
2180 ASSERT_EQ(1, codec.channels);
2182 e = NextFromPayloadType(e);
2183 ASSERT_TRUE(e != NULL);
2184 codec = AudioCodecFromPayloadType(e);
2185 ASSERT_EQ(126, codec.id);
2186 ASSERT_EQ("CN", codec.name);
2187 ASSERT_EQ(32000, codec.clockrate);
2188 ASSERT_EQ(1, codec.channels);
2190 e = NextFromPayloadType(e);
2191 ASSERT_TRUE(e != NULL);
2192 codec = AudioCodecFromPayloadType(e);
2193 ASSERT_EQ(105, codec.id);
2194 ASSERT_EQ("CN", codec.name);
2195 ASSERT_EQ(16000, codec.clockrate);
2196 ASSERT_EQ(1, codec.channels);
2198 e = NextFromPayloadType(e);
2199 ASSERT_TRUE(e != NULL);
2200 codec = AudioCodecFromPayloadType(e);
2201 ASSERT_EQ(13, codec.id);
2202 ASSERT_EQ("CN", codec.name);
2203 ASSERT_EQ(8000, codec.clockrate);
2204 ASSERT_EQ(1, codec.channels);
2206 e = NextFromPayloadType(e);
2207 ASSERT_TRUE(e != NULL);
2208 codec = AudioCodecFromPayloadType(e);
2209 ASSERT_EQ(117, codec.id);
2210 ASSERT_EQ("red", codec.name);
2211 ASSERT_EQ(8000, codec.clockrate);
2212 ASSERT_EQ(1, codec.channels);
2214 e = NextFromPayloadType(e);
2215 ASSERT_TRUE(e != NULL);
2216 codec = AudioCodecFromPayloadType(e);
2217 ASSERT_EQ(106, codec.id);
2218 ASSERT_EQ("telephone-event", codec.name);
2219 ASSERT_EQ(8000, codec.clockrate);
2220 ASSERT_EQ(1, codec.channels);
2222 e = NextFromPayloadType(e);
2223 ASSERT_TRUE(e == NULL);
2226 void TestCodecsOfVideoInitiate(buzz::XmlElement* content) {
2227 ASSERT_TRUE(content != NULL);
2228 buzz::XmlElement* payload_type = PayloadTypeFromContent(content);
2229 ASSERT_TRUE(payload_type != NULL);
2230 cricket::AudioCodec codec = AudioCodecFromPayloadType(payload_type);
2231 ASSERT_EQ(103, codec.id);
2232 ASSERT_EQ("ISAC", codec.name);
2233 ASSERT_EQ(16000, codec.clockrate);
2234 ASSERT_EQ(1, codec.channels);
2236 content = parser_->NextContent(content);
2237 ASSERT_TRUE(content != NULL);
2238 payload_type = PayloadTypeFromContent(content);
2239 ASSERT_TRUE(payload_type != NULL);
2240 cricket::VideoCodec vcodec =
2241 parser_->VideoCodecFromPayloadType(payload_type);
2242 ASSERT_EQ(99, vcodec.id);
2243 ASSERT_EQ("H264-SVC", vcodec.name);
2244 ASSERT_EQ(320, vcodec.width);
2245 ASSERT_EQ(200, vcodec.height);
2246 ASSERT_EQ(30, vcodec.framerate);
2249 void TestHasAudioCodecsFromInitiateSomeUnsupported(buzz::XmlElement* e) {
2250 ASSERT_TRUE(e != NULL);
2251 e = PayloadTypeFromContent(e);
2252 ASSERT_TRUE(e != NULL);
2254 cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2255 ASSERT_EQ(103, codec.id);
2256 ASSERT_EQ("ISAC", codec.name);
2257 ASSERT_EQ(16000, codec.clockrate);
2258 ASSERT_EQ(1, codec.channels);
2260 e = NextFromPayloadType(e);
2261 ASSERT_TRUE(e != NULL);
2262 codec = AudioCodecFromPayloadType(e);
2263 ASSERT_EQ(100, codec.id);
2264 ASSERT_EQ("EG711U", codec.name);
2266 e = NextFromPayloadType(e);
2267 ASSERT_TRUE(e != NULL);
2268 codec = AudioCodecFromPayloadType(e);
2269 ASSERT_EQ(101, codec.id);
2270 ASSERT_EQ("EG711A", codec.name);
2272 e = NextFromPayloadType(e);
2273 ASSERT_TRUE(e != NULL);
2274 codec = AudioCodecFromPayloadType(e);
2275 ASSERT_EQ(0, codec.id);
2276 ASSERT_EQ("PCMU", codec.name);
2278 e = NextFromPayloadType(e);
2279 ASSERT_TRUE(e != NULL);
2280 codec = AudioCodecFromPayloadType(e);
2281 ASSERT_EQ(13, codec.id);
2282 ASSERT_EQ("CN", codec.name);
2284 e = NextFromPayloadType(e);
2285 ASSERT_TRUE(e == NULL);
2288 void TestHasAudioCodecsFromInitiateDynamicAudioCodecs(
2289 buzz::XmlElement* e) {
2290 ASSERT_TRUE(e != NULL);
2291 e = PayloadTypeFromContent(e);
2292 ASSERT_TRUE(e != NULL);
2294 cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2295 ASSERT_EQ(123, codec.id);
2296 ASSERT_EQ(16000, codec.clockrate);
2297 ASSERT_EQ(1, codec.channels);
2299 e = NextFromPayloadType(e);
2300 ASSERT_TRUE(e == NULL);
2303 void TestHasDefaultAudioCodecs(buzz::XmlElement* e) {
2304 ASSERT_TRUE(e != NULL);
2305 e = PayloadTypeFromContent(e);
2306 ASSERT_TRUE(e != NULL);
2308 cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2309 ASSERT_EQ(103, codec.id);
2310 ASSERT_EQ("ISAC", codec.name);
2312 e = NextFromPayloadType(e);
2313 ASSERT_TRUE(e != NULL);
2314 codec = AudioCodecFromPayloadType(e);
2315 ASSERT_EQ(0, codec.id);
2316 ASSERT_EQ("PCMU", codec.name);
2318 e = NextFromPayloadType(e);
2319 ASSERT_TRUE(e == NULL);
2322 void TestHasAudioCodecsFromInitiateStaticAudioCodecs(
2323 buzz::XmlElement* e) {
2324 ASSERT_TRUE(e != NULL);
2325 e = PayloadTypeFromContent(e);
2326 ASSERT_TRUE(e != NULL);
2328 cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2329 ASSERT_EQ(3, codec.id);
2331 e = NextFromPayloadType(e);
2332 ASSERT_TRUE(e != NULL);
2333 codec = AudioCodecFromPayloadType(e);
2334 ASSERT_EQ(0, codec.id);
2336 e = NextFromPayloadType(e);
2337 ASSERT_TRUE(e != NULL);
2338 codec = AudioCodecFromPayloadType(e);
2339 ASSERT_EQ(8, codec.id);
2341 e = NextFromPayloadType(e);
2342 ASSERT_TRUE(e == NULL);
2345 void TestGingleInitiateWithUnsupportedCrypto(
2346 const std::string &initiate_string,
2347 buzz::XmlElement** element) {
2350 rtc::scoped_ptr<buzz::XmlElement> el(
2351 buzz::XmlElement::ForStr(initiate_string));
2352 client_->session_manager()->OnIncomingMessage(el.get());
2354 ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE,
2355 call_->sessions()[0]->state());
2357 CheckBadCryptoFromIncomingInitiate(call_->sessions()[0]);
2359 call_->AcceptSession(call_->sessions()[0], cricket::CallOptions());
2361 CheckNoCryptoForOutgoingAccept(call_->sessions()[0]);
2364 ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE,
2365 call_->sessions()[0]->state());
2369 void TestIncomingAcceptWithSsrcs(
2370 const std::string& accept_string,
2371 cricket::CallOptions& options) {
2372 client_->CreateCall();
2373 ASSERT_TRUE(call_ != NULL);
2375 call_->InitiateSession(buzz::Jid("me@mydomain.com"),
2376 buzz::Jid("me@mydomain.com"), options);
2377 ASSERT_TRUE(call_->sessions()[0] != NULL);
2378 ASSERT_EQ(cricket::Session::STATE_SENTINITIATE,
2379 call_->sessions()[0]->state());
2380 ASSERT_EQ(1U, stanzas_.size());
2381 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
2382 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
2383 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
2384 buzz::XmlElement* action = ActionFromStanza(stanzas_[0]);
2385 ASSERT_TRUE(action != NULL);
2386 buzz::XmlElement* content = ContentFromAction(action);
2387 ASSERT_TRUE(content != NULL);
2388 if (initial_protocol_ == cricket::PROTOCOL_JINGLE) {
2389 buzz::XmlElement* content_desc =
2390 content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
2391 ASSERT_TRUE(content_desc != NULL);
2392 ASSERT_EQ("", content_desc->Attr(cricket::QN_SSRC));
2396 // We need to insert the session ID into the session accept message.
2397 rtc::scoped_ptr<buzz::XmlElement> el(
2398 buzz::XmlElement::ForStr(accept_string));
2399 const std::string sid = call_->sessions()[0]->id();
2400 if (initial_protocol_ == cricket::PROTOCOL_JINGLE) {
2401 buzz::XmlElement* jingle = el->FirstNamed(cricket::QN_JINGLE);
2402 jingle->SetAttr(cricket::QN_SID, sid);
2404 buzz::XmlElement* session = el->FirstNamed(cricket::QN_GINGLE_SESSION);
2405 session->SetAttr(cricket::QN_ID, sid);
2408 client_->session_manager()->OnIncomingMessage(el.get());
2410 ASSERT_EQ(cricket::Session::STATE_RECEIVEDACCEPT,
2411 call_->sessions()[0]->state());
2412 ASSERT_EQ(1U, stanzas_.size());
2413 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
2414 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
2415 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
2418 CheckAudioSsrcForIncomingAccept(call_->sessions()[0]);
2419 CheckVideoSsrcForIncomingAccept(call_->sessions()[0]);
2420 if (options.data_channel_type == cricket::DCT_RTP) {
2421 CheckDataSsrcForIncomingAccept(call_->sessions()[0]);
2423 // TODO(pthatcher): Check kDataSid if DCT_SCTP.
2424 // const uint32 kDataSid = 0;
2427 size_t ClearStanzas() {
2428 size_t size = stanzas_.size();
2429 for (size_t i = 0; i < size; i++) {
2436 buzz::XmlElement* SetJingleSid(buzz::XmlElement* stanza) {
2437 buzz::XmlElement* jingle =
2438 stanza->FirstNamed(cricket::QN_JINGLE);
2439 jingle->SetAttr(cricket::QN_SID, call_->sessions()[0]->id());
2443 void TestSendVideoStreamUpdate() {
2444 cricket::CallOptions options = VideoCallOptions();
2445 options.is_muc = true;
2447 client_->CreateCall();
2448 call_->InitiateSession(buzz::Jid("me@mydomain.com"),
2449 buzz::Jid("me@mydomain.com"), options);
2452 cricket::StreamParams stream;
2453 stream.id = "test-stream";
2454 stream.ssrcs.push_back(1001);
2455 rtc::scoped_ptr<buzz::XmlElement> expected_stream_add(
2456 buzz::XmlElement::ForStr(
2457 JingleOutboundStreamAdd(
2458 call_->sessions()[0]->id(),
2459 "video", stream.id, "1001")));
2460 rtc::scoped_ptr<buzz::XmlElement> expected_stream_remove(
2461 buzz::XmlElement::ForStr(
2462 JingleOutboundStreamRemove(
2463 call_->sessions()[0]->id(),
2464 "video", stream.id)));
2466 call_->SendVideoStreamUpdate(call_->sessions()[0],
2467 call_->CreateVideoStreamUpdate(stream));
2468 ASSERT_EQ(1U, stanzas_.size());
2469 EXPECT_EQ(expected_stream_add->Str(), stanzas_[0]->Str());
2472 stream.ssrcs.clear();
2473 call_->SendVideoStreamUpdate(call_->sessions()[0],
2474 call_->CreateVideoStreamUpdate(stream));
2475 ASSERT_EQ(1U, stanzas_.size());
2476 EXPECT_EQ(expected_stream_remove->Str(), stanzas_[0]->Str());
2480 void TestStreamsUpdateAndViewRequests() {
2481 cricket::CallOptions options = VideoCallOptions();
2482 options.is_muc = true;
2484 client_->CreateCall();
2485 call_->InitiateSession(buzz::Jid("me@mydomain.com"),
2486 buzz::Jid("me@mydomain.com"), options);
2487 ASSERT_EQ(1U, ClearStanzas());
2488 ASSERT_EQ(0U, last_streams_added_.audio().size());
2489 ASSERT_EQ(0U, last_streams_added_.video().size());
2490 ASSERT_EQ(0U, last_streams_removed_.audio().size());
2491 ASSERT_EQ(0U, last_streams_removed_.video().size());
2493 rtc::scoped_ptr<buzz::XmlElement> accept_stanza(
2494 buzz::XmlElement::ForStr(kJingleAcceptWithSsrcs));
2495 SetJingleSid(accept_stanza.get());
2496 client_->session_manager()->OnIncomingMessage(accept_stanza.get());
2497 ASSERT_EQ(cricket::Session::STATE_RECEIVEDACCEPT,
2498 call_->sessions()[0]->state());
2499 ASSERT_EQ(1U, stanzas_.size());
2500 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
2502 // Need to clear the added streams, because they are populated when
2503 // receiving an accept message now.
2504 last_streams_added_.mutable_video()->clear();
2505 last_streams_added_.mutable_audio()->clear();
2507 call_->sessions()[0]->SetState(cricket::Session::STATE_INPROGRESS);
2509 rtc::scoped_ptr<buzz::XmlElement> streams_stanza(
2510 buzz::XmlElement::ForStr(
2511 JingleStreamAdd("video", "Bob", "video1", "ABC")));
2512 SetJingleSid(streams_stanza.get());
2513 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2514 // First one is ignored because of bad syntax.
2515 ASSERT_EQ(1U, stanzas_.size());
2516 // TODO(pthatcher): Figure out how to make this an ERROR rather than RESULT.
2517 ASSERT_EQ(std::string(buzz::STR_ERROR), stanzas_[0]->Attr(buzz::QN_TYPE));
2519 ASSERT_EQ(0U, last_streams_added_.audio().size());
2520 ASSERT_EQ(0U, last_streams_added_.video().size());
2521 ASSERT_EQ(0U, last_streams_removed_.audio().size());
2522 ASSERT_EQ(0U, last_streams_removed_.video().size());
2524 streams_stanza.reset(buzz::XmlElement::ForStr(
2525 JingleStreamAdd("audio", "Bob", "audio1", "1234")));
2526 SetJingleSid(streams_stanza.get());
2527 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2528 ASSERT_EQ(1U, last_streams_added_.audio().size());
2529 ASSERT_EQ("Bob", last_streams_added_.audio()[0].groupid);
2530 ASSERT_EQ(1U, last_streams_added_.audio()[0].ssrcs.size());
2531 ASSERT_EQ(1234U, last_streams_added_.audio()[0].first_ssrc());
2533 // Ignores adds without ssrcs.
2534 streams_stanza.reset(buzz::XmlElement::ForStr(
2535 JingleStreamAddWithoutSsrc("audio", "Bob", "audioX")));
2536 SetJingleSid(streams_stanza.get());
2537 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2538 ASSERT_EQ(1U, last_streams_added_.audio().size());
2539 ASSERT_EQ(1234U, last_streams_added_.audio()[0].first_ssrc());
2541 // Ignores stream updates with unknown content names. (Don't terminate).
2542 streams_stanza.reset(buzz::XmlElement::ForStr(
2543 JingleStreamAddWithoutSsrc("foo", "Bob", "foo")));
2544 SetJingleSid(streams_stanza.get());
2545 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2547 streams_stanza.reset(buzz::XmlElement::ForStr(
2548 JingleStreamAdd("audio", "Joe", "audio1", "2468")));
2549 SetJingleSid(streams_stanza.get());
2550 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2551 ASSERT_EQ(1U, last_streams_added_.audio().size());
2552 ASSERT_EQ("Joe", last_streams_added_.audio()[0].groupid);
2553 ASSERT_EQ(1U, last_streams_added_.audio()[0].ssrcs.size());
2554 ASSERT_EQ(2468U, last_streams_added_.audio()[0].first_ssrc());
2556 streams_stanza.reset(buzz::XmlElement::ForStr(
2557 JingleStreamAdd("video", "Bob", "video1", "5678")));
2558 SetJingleSid(streams_stanza.get());
2559 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2560 ASSERT_EQ(1U, last_streams_added_.video().size());
2561 ASSERT_EQ("Bob", last_streams_added_.video()[0].groupid);
2562 ASSERT_EQ(1U, last_streams_added_.video()[0].ssrcs.size());
2563 ASSERT_EQ(5678U, last_streams_added_.video()[0].first_ssrc());
2565 // We're testing that a "duplicate" is effectively ignored.
2566 last_streams_added_.mutable_video()->clear();
2567 last_streams_removed_.mutable_video()->clear();
2568 streams_stanza.reset(buzz::XmlElement::ForStr(
2569 JingleStreamAdd("video", "Bob", "video1", "5678")));
2570 SetJingleSid(streams_stanza.get());
2571 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2572 ASSERT_EQ(0U, last_streams_added_.video().size());
2573 ASSERT_EQ(0U, last_streams_removed_.video().size());
2575 streams_stanza.reset(buzz::XmlElement::ForStr(
2576 JingleStreamAdd("video", "Bob", "video2", "5679")));
2577 SetJingleSid(streams_stanza.get());
2578 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2579 ASSERT_EQ(1U, last_streams_added_.video().size());
2580 ASSERT_EQ("Bob", last_streams_added_.video()[0].groupid);
2581 ASSERT_EQ(1U, last_streams_added_.video()[0].ssrcs.size());
2582 ASSERT_EQ(5679U, last_streams_added_.video()[0].first_ssrc());
2584 cricket::FakeVoiceMediaChannel* voice_channel = fme_->GetVoiceChannel(0);
2585 ASSERT_TRUE(voice_channel != NULL);
2586 ASSERT_TRUE(voice_channel->HasRecvStream(1234U));
2587 ASSERT_TRUE(voice_channel->HasRecvStream(2468U));
2588 cricket::FakeVideoMediaChannel* video_channel = fme_->GetVideoChannel(0);
2589 ASSERT_TRUE(video_channel != NULL);
2590 ASSERT_TRUE(video_channel->HasRecvStream(5678U));
2593 cricket::ViewRequest viewRequest;
2594 cricket::StaticVideoView staticVideoView(
2595 cricket::StreamSelector(5678U), 640, 480, 30);
2596 viewRequest.static_video_views.push_back(staticVideoView);
2597 rtc::scoped_ptr<buzz::XmlElement> expected_view_elem(
2598 buzz::XmlElement::ForStr(JingleView("5678", "640", "480", "30")));
2599 SetJingleSid(expected_view_elem.get());
2602 call_->SendViewRequest(call_->sessions()[0], viewRequest));
2603 ASSERT_EQ(1U, stanzas_.size());
2604 ASSERT_EQ(expected_view_elem->Str(), stanzas_[0]->Str());
2607 streams_stanza.reset(buzz::XmlElement::ForStr(
2608 JingleStreamRemove("audio", "Bob", "audio1")));
2609 SetJingleSid(streams_stanza.get());
2610 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2611 ASSERT_EQ(1U, last_streams_removed_.audio().size());
2612 ASSERT_EQ(1U, last_streams_removed_.audio()[0].ssrcs.size());
2613 EXPECT_EQ(1234U, last_streams_removed_.audio()[0].first_ssrc());
2615 streams_stanza.reset(buzz::XmlElement::ForStr(
2616 JingleStreamRemove("video", "Bob", "video1")));
2617 SetJingleSid(streams_stanza.get());
2618 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2619 ASSERT_EQ(1U, last_streams_removed_.video().size());
2620 ASSERT_EQ(1U, last_streams_removed_.video()[0].ssrcs.size());
2621 EXPECT_EQ(5678U, last_streams_removed_.video()[0].first_ssrc());
2623 streams_stanza.reset(buzz::XmlElement::ForStr(
2624 JingleStreamRemove("video", "Bob", "video2")));
2625 SetJingleSid(streams_stanza.get());
2626 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2627 ASSERT_EQ(1U, last_streams_removed_.video().size());
2628 ASSERT_EQ(1U, last_streams_removed_.video()[0].ssrcs.size());
2629 EXPECT_EQ(5679U, last_streams_removed_.video()[0].first_ssrc());
2631 // Duplicate removal: should be ignored.
2632 last_streams_removed_.mutable_audio()->clear();
2633 streams_stanza.reset(buzz::XmlElement::ForStr(
2634 JingleStreamRemove("audio", "Bob", "audio1")));
2635 SetJingleSid(streams_stanza.get());
2636 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2637 ASSERT_EQ(0U, last_streams_removed_.audio().size());
2639 // Duplicate removal: should be ignored.
2640 last_streams_removed_.mutable_video()->clear();
2641 streams_stanza.reset(buzz::XmlElement::ForStr(
2642 JingleStreamRemove("video", "Bob", "video1")));
2643 SetJingleSid(streams_stanza.get());
2644 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2645 ASSERT_EQ(0U, last_streams_removed_.video().size());
2647 voice_channel = fme_->GetVoiceChannel(0);
2648 ASSERT_TRUE(voice_channel != NULL);
2649 ASSERT_FALSE(voice_channel->HasRecvStream(1234U));
2650 ASSERT_TRUE(voice_channel->HasRecvStream(2468U));
2651 video_channel = fme_->GetVideoChannel(0);
2652 ASSERT_TRUE(video_channel != NULL);
2653 ASSERT_FALSE(video_channel->HasRecvStream(5678U));
2655 // Fails because ssrc is now invalid.
2657 call_->SendViewRequest(call_->sessions()[0], viewRequest));
2662 void MakeSignalingSecure(cricket::SecurePolicy secure) {
2663 client_->set_secure(secure);
2666 void ExpectCrypto(cricket::SecurePolicy secure) {
2667 MakeSignalingSecure(secure);
2668 expect_incoming_crypto_ = true;
2670 expect_outgoing_crypto_ = true;
2674 void ExpectVideoBandwidth(int bandwidth) {
2675 expected_video_bandwidth_ = bandwidth;
2678 void ExpectVideoRtcpMux(bool rtcp_mux) {
2679 expected_video_rtcp_mux_ = rtcp_mux;
2683 void SetCodecFeedbackParams(std::vector<C>* codecs,
2684 const FeedbackParams& fb_params) {
2685 for (size_t i = 0; i < codecs->size(); ++i) {
2686 codecs->at(i).feedback_params = fb_params;
2690 void ExpectRtcpFb() {
2691 FeedbackParams params_nack_fir;
2692 params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamCcm,
2693 cricket::kRtcpFbCcmParamFir));
2694 params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamNack));
2696 FeedbackParams params_nack;
2697 params_nack.Add(FeedbackParam(cricket::kRtcpFbParamNack));
2699 expected_audio_fb_params_ = params_nack;
2700 expected_video_fb_params_ = params_nack_fir;
2701 expected_data_fb_params_ = params_nack;
2704 cricket::FakeMediaEngine* fme() { return fme_; }
2707 void OnSendStanza(cricket::SessionManager* manager,
2708 const buzz::XmlElement* stanza) {
2709 LOG(LS_INFO) << stanza->Str();
2710 stanzas_.push_back(new buzz::XmlElement(*stanza));
2713 void OnSessionCreate(cricket::Session* session, bool initiate) {
2714 session->set_current_protocol(initial_protocol_);
2717 void OnCallCreate(cricket::Call *call) {
2719 call->SignalMediaStreamsUpdate.connect(
2720 this, &MediaSessionClientTest::OnMediaStreamsUpdate);
2723 void OnCallDestroy(cricket::Call *call) {
2727 void OnMediaStreamsUpdate(cricket::Call *call,
2728 cricket::Session *session,
2729 const cricket::MediaStreams& added,
2730 const cricket::MediaStreams& removed) {
2731 last_streams_added_.CopyFrom(added);
2732 last_streams_removed_.CopyFrom(removed);
2735 rtc::NetworkManager* nm_;
2736 cricket::PortAllocator* pa_;
2737 cricket::SessionManager* sm_;
2738 cricket::FakeMediaEngine* fme_;
2739 cricket::FakeDataEngine* fdme_;
2740 cricket::MediaSessionClient* client_;
2742 cricket::Call* call_;
2743 std::vector<buzz::XmlElement* > stanzas_;
2744 MediaSessionTestParser* parser_;
2745 cricket::SignalingProtocol initial_protocol_;
2746 bool expect_incoming_crypto_;
2747 bool expect_outgoing_crypto_;
2748 int expected_video_bandwidth_;
2749 bool expected_video_rtcp_mux_;
2750 FeedbackParams expected_audio_fb_params_;
2751 FeedbackParams expected_video_fb_params_;
2752 FeedbackParams expected_data_fb_params_;
2753 cricket::MediaStreams last_streams_added_;
2754 cricket::MediaStreams last_streams_removed_;
2757 MediaSessionClientTest* GingleTest() {
2758 return new MediaSessionClientTest(new GingleSessionTestParser(),
2759 cricket::PROTOCOL_GINGLE);
2762 MediaSessionClientTest* JingleTest() {
2763 return new MediaSessionClientTest(new JingleSessionTestParser(),
2764 cricket::PROTOCOL_JINGLE);
2767 class MediaSessionTest : public ::testing::Test {};
2769 TEST_F(MediaSessionTest, JingleGoodInitiateWithRtcpFb) {
2770 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2771 rtc::scoped_ptr<buzz::XmlElement> elem;
2773 cricket::CallOptions options = VideoCallOptions();
2774 options.data_channel_type = cricket::DCT_SCTP;
2775 test->ExpectRtcpFb();
2776 test->TestGoodIncomingInitiate(
2777 kJingleInitiateWithRtcpFb, options, elem.use());
2780 TEST_F(MediaSessionTest, JingleGoodVideoInitiate) {
2781 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2782 rtc::scoped_ptr<buzz::XmlElement> elem;
2783 test->TestGoodIncomingInitiate(
2784 kJingleVideoInitiate, VideoCallOptions(), elem.use());
2785 test->TestCodecsOfVideoInitiate(elem.get());
2788 TEST_F(MediaSessionTest, JingleGoodVideoInitiateWithBandwidth) {
2789 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2790 rtc::scoped_ptr<buzz::XmlElement> elem;
2791 test->ExpectVideoBandwidth(42000);
2792 test->TestGoodIncomingInitiate(
2793 kJingleVideoInitiateWithBandwidth, VideoCallOptions(), elem.use());
2796 TEST_F(MediaSessionTest, JingleGoodVideoInitiateWithRtcpMux) {
2797 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2798 rtc::scoped_ptr<buzz::XmlElement> elem;
2799 test->ExpectVideoRtcpMux(true);
2800 test->TestGoodIncomingInitiate(
2801 kJingleVideoInitiateWithRtcpMux, VideoCallOptions(), elem.use());
2804 TEST_F(MediaSessionTest, JingleGoodVideoInitiateWithRtpData) {
2805 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2806 rtc::scoped_ptr<buzz::XmlElement> elem;
2807 cricket::CallOptions options = VideoCallOptions();
2808 options.data_channel_type = cricket::DCT_RTP;
2809 test->TestGoodIncomingInitiate(
2810 AddEncryption(kJingleVideoInitiateWithRtpData, kJingleCryptoOffer),
2815 TEST_F(MediaSessionTest, JingleGoodVideoInitiateWithSctpData) {
2816 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2817 rtc::scoped_ptr<buzz::XmlElement> elem;
2818 cricket::CallOptions options = VideoCallOptions();
2819 options.data_channel_type = cricket::DCT_SCTP;
2820 test->TestGoodIncomingInitiate(kJingleVideoInitiateWithSctpData,
2825 TEST_F(MediaSessionTest, JingleRejectAudio) {
2826 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2827 rtc::scoped_ptr<buzz::XmlElement> elem;
2828 cricket::CallOptions options = VideoCallOptions();
2829 options.recv_audio = false;
2830 options.data_channel_type = cricket::DCT_RTP;
2831 test->TestRejectOffer(kJingleVideoInitiateWithRtpData, options, elem.use());
2834 TEST_F(MediaSessionTest, JingleRejectVideo) {
2835 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2836 rtc::scoped_ptr<buzz::XmlElement> elem;
2837 cricket::CallOptions options = AudioCallOptions();
2838 options.data_channel_type = cricket::DCT_RTP;
2839 test->TestRejectOffer(kJingleVideoInitiateWithRtpData, options, elem.use());
2842 TEST_F(MediaSessionTest, JingleRejectData) {
2843 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2844 rtc::scoped_ptr<buzz::XmlElement> elem;
2845 test->TestRejectOffer(
2846 kJingleVideoInitiateWithRtpData, VideoCallOptions(), elem.use());
2849 TEST_F(MediaSessionTest, JingleRejectVideoAndData) {
2850 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2851 rtc::scoped_ptr<buzz::XmlElement> elem;
2852 test->TestRejectOffer(
2853 kJingleVideoInitiateWithRtpData, AudioCallOptions(), elem.use());
2856 TEST_F(MediaSessionTest, JingleGoodInitiateAllSupportedAudioCodecs) {
2857 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2858 rtc::scoped_ptr<buzz::XmlElement> elem;
2859 test->TestGoodIncomingInitiate(
2860 kJingleInitiate, AudioCallOptions(), elem.use());
2861 test->TestHasAllSupportedAudioCodecs(elem.get());
2864 // Changes the codecs that our FakeMediaEngine will support with a different
2865 // preference order than the incoming offer.
2866 // Verifies the answer accepts the preference order of the remote peer.
2867 TEST_F(MediaSessionTest, JingleGoodInitiateDifferentPreferenceAudioCodecs) {
2868 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2869 test->fme()->SetAudioCodecs(MAKE_VECTOR(kAudioCodecsDifferentPreference));
2870 rtc::scoped_ptr<buzz::XmlElement> elem;
2871 test->TestGoodIncomingInitiate(
2872 kJingleInitiate, AudioCallOptions(), elem.use());
2873 test->TestHasAllSupportedAudioCodecs(elem.get());
2876 TEST_F(MediaSessionTest, JingleGoodInitiateSomeUnsupportedAudioCodecs) {
2877 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2878 rtc::scoped_ptr<buzz::XmlElement> elem;
2879 test->TestGoodIncomingInitiate(
2880 kJingleInitiateSomeUnsupported, AudioCallOptions(), elem.use());
2881 test->TestHasAudioCodecsFromInitiateSomeUnsupported(elem.get());
2884 TEST_F(MediaSessionTest, JingleGoodInitiateDynamicAudioCodecs) {
2885 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2886 rtc::scoped_ptr<buzz::XmlElement> elem;
2887 test->TestGoodIncomingInitiate(
2888 kJingleInitiateDynamicAudioCodecs, AudioCallOptions(), elem.use());
2889 test->TestHasAudioCodecsFromInitiateDynamicAudioCodecs(elem.get());
2892 TEST_F(MediaSessionTest, JingleGoodInitiateStaticAudioCodecs) {
2893 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2894 rtc::scoped_ptr<buzz::XmlElement> elem;
2895 test->TestGoodIncomingInitiate(
2896 kJingleInitiateStaticAudioCodecs, AudioCallOptions(), elem.use());
2897 test->TestHasAudioCodecsFromInitiateStaticAudioCodecs(elem.get());
2900 TEST_F(MediaSessionTest, JingleBadInitiateNoAudioCodecs) {
2901 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2902 test->TestBadIncomingInitiate(kJingleInitiateNoAudioCodecs);
2905 TEST_F(MediaSessionTest, JingleBadInitiateNoSupportedAudioCodecs) {
2906 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2907 test->TestBadIncomingInitiate(kJingleInitiateNoSupportedAudioCodecs);
2910 TEST_F(MediaSessionTest, JingleBadInitiateWrongClockrates) {
2911 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2912 test->TestBadIncomingInitiate(kJingleInitiateWrongClockrates);
2915 TEST_F(MediaSessionTest, JingleBadInitiateWrongChannels) {
2916 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2917 test->TestBadIncomingInitiate(kJingleInitiateWrongChannels);
2920 TEST_F(MediaSessionTest, JingleBadInitiateNoPayloadTypes) {
2921 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2922 test->TestBadIncomingInitiate(kJingleInitiateNoPayloadTypes);
2925 TEST_F(MediaSessionTest, JingleBadInitiateDynamicWithoutNames) {
2926 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2927 test->TestBadIncomingInitiate(kJingleInitiateDynamicWithoutNames);
2930 TEST_F(MediaSessionTest, JingleGoodOutgoingInitiate) {
2931 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2932 test->TestGoodOutgoingInitiate(AudioCallOptions());
2935 TEST_F(MediaSessionTest, JingleGoodOutgoingInitiateWithBandwidth) {
2936 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2937 cricket::CallOptions options = VideoCallOptions();
2938 options.video_bandwidth = 42000;
2939 test->TestGoodOutgoingInitiate(options);
2942 TEST_F(MediaSessionTest, JingleGoodOutgoingInitiateWithRtcpMux) {
2943 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2944 cricket::CallOptions options = VideoCallOptions();
2945 options.rtcp_mux_enabled = true;
2946 test->TestGoodOutgoingInitiate(options);
2949 TEST_F(MediaSessionTest, JingleGoodOutgoingInitiateWithRtpData) {
2950 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2951 cricket::CallOptions options;
2952 options.data_channel_type = cricket::DCT_RTP;
2953 test->ExpectCrypto(cricket::SEC_ENABLED);
2954 test->TestGoodOutgoingInitiate(options);
2957 TEST_F(MediaSessionTest, JingleGoodOutgoingInitiateWithSctpData) {
2958 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2959 cricket::CallOptions options;
2960 options.data_channel_type = cricket::DCT_SCTP;
2961 test->TestGoodOutgoingInitiate(options);
2964 // Crypto related tests.
2966 // Offer has crypto but the session is not secured, just ignore it.
2967 TEST_F(MediaSessionTest, JingleInitiateWithCryptoIsIgnoredWhenNotSecured) {
2968 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2969 rtc::scoped_ptr<buzz::XmlElement> elem;
2970 test->TestGoodIncomingInitiate(
2971 AddEncryption(kJingleVideoInitiate, kJingleCryptoOffer),
2976 // Offer has crypto required but the session is not secure, fail.
2977 TEST_F(MediaSessionTest, JingleInitiateWithCryptoRequiredWhenNotSecured) {
2978 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2979 test->TestBadIncomingInitiate(AddEncryption(kJingleVideoInitiate,
2980 kJingleRequiredCryptoOffer));
2983 // Offer has no crypto but the session is secure required, fail.
2984 TEST_F(MediaSessionTest, JingleInitiateWithNoCryptoFailsWhenSecureRequired) {
2985 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2986 test->ExpectCrypto(cricket::SEC_REQUIRED);
2987 test->TestBadIncomingInitiate(kJingleInitiate);
2990 // Offer has crypto and session is secure, expect crypto in the answer.
2991 TEST_F(MediaSessionTest, JingleInitiateWithCryptoWhenSecureEnabled) {
2992 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2993 rtc::scoped_ptr<buzz::XmlElement> elem;
2994 test->ExpectCrypto(cricket::SEC_ENABLED);
2995 test->TestGoodIncomingInitiate(
2996 AddEncryption(kJingleVideoInitiate, kJingleCryptoOffer),
3001 // Offer has crypto and session is secure required, expect crypto in
3003 TEST_F(MediaSessionTest, JingleInitiateWithCryptoWhenSecureRequired) {
3004 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3005 rtc::scoped_ptr<buzz::XmlElement> elem;
3006 test->ExpectCrypto(cricket::SEC_REQUIRED);
3007 test->TestGoodIncomingInitiate(
3008 AddEncryption(kJingleVideoInitiate, kJingleCryptoOffer),
3013 // Offer has unsupported crypto and session is secure, no crypto in
3015 TEST_F(MediaSessionTest, JingleInitiateWithUnsupportedCrypto) {
3016 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3017 rtc::scoped_ptr<buzz::XmlElement> elem;
3018 test->MakeSignalingSecure(cricket::SEC_ENABLED);
3019 test->TestGoodIncomingInitiate(
3020 AddEncryption(kJingleInitiate, kJingleUnsupportedCryptoOffer),
3025 // Offer has unsupported REQUIRED crypto and session is not secure, fail.
3026 TEST_F(MediaSessionTest, JingleInitiateWithRequiredUnsupportedCrypto) {
3027 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3028 test->TestBadIncomingInitiate(
3029 AddEncryption(kJingleInitiate, kJingleRequiredUnsupportedCryptoOffer));
3032 // Offer has unsupported REQUIRED crypto and session is secure, fail.
3033 TEST_F(MediaSessionTest,
3034 JingleInitiateWithRequiredUnsupportedCryptoWhenSecure) {
3035 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3036 test->MakeSignalingSecure(cricket::SEC_ENABLED);
3037 test->TestBadIncomingInitiate(
3038 AddEncryption(kJingleInitiate, kJingleRequiredUnsupportedCryptoOffer));
3041 // Offer has unsupported REQUIRED crypto and session is required secure, fail.
3042 TEST_F(MediaSessionTest,
3043 JingleInitiateWithRequiredUnsupportedCryptoWhenSecureRequired) {
3044 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3045 test->MakeSignalingSecure(cricket::SEC_REQUIRED);
3046 test->TestBadIncomingInitiate(
3047 AddEncryption(kJingleInitiate, kJingleRequiredUnsupportedCryptoOffer));
3050 TEST_F(MediaSessionTest, JingleGoodOutgoingInitiateWithCrypto) {
3051 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3052 test->ExpectCrypto(cricket::SEC_ENABLED);
3053 test->TestGoodOutgoingInitiate(AudioCallOptions());
3056 TEST_F(MediaSessionTest, JingleGoodOutgoingInitiateWithCryptoRequired) {
3057 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3058 test->ExpectCrypto(cricket::SEC_REQUIRED);
3059 test->TestGoodOutgoingInitiate(AudioCallOptions());
3062 TEST_F(MediaSessionTest, JingleIncomingAcceptWithSsrcs) {
3063 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3064 cricket::CallOptions options = VideoCallOptions();
3065 options.is_muc = true;
3066 test->TestIncomingAcceptWithSsrcs(kJingleAcceptWithSsrcs, options);
3069 TEST_F(MediaSessionTest, JingleIncomingAcceptWithRtpDataSsrcs) {
3070 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3071 cricket::CallOptions options = VideoCallOptions();
3072 options.is_muc = true;
3073 options.data_channel_type = cricket::DCT_RTP;
3074 test->TestIncomingAcceptWithSsrcs(kJingleAcceptWithRtpDataSsrcs, options);
3077 TEST_F(MediaSessionTest, JingleIncomingAcceptWithSctpData) {
3078 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3079 cricket::CallOptions options = VideoCallOptions();
3080 options.is_muc = true;
3081 options.data_channel_type = cricket::DCT_SCTP;
3082 test->TestIncomingAcceptWithSsrcs(kJingleAcceptWithSctpData, options);
3085 TEST_F(MediaSessionTest, JingleStreamsUpdateAndView) {
3086 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3087 test->TestStreamsUpdateAndViewRequests();
3090 TEST_F(MediaSessionTest, JingleSendVideoStreamUpdate) {
3091 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3092 test->TestSendVideoStreamUpdate();
3097 TEST_F(MediaSessionTest, GingleGoodVideoInitiate) {
3098 rtc::scoped_ptr<buzz::XmlElement> elem;
3099 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3100 test->TestGoodIncomingInitiate(
3101 kGingleVideoInitiate, VideoCallOptions(), elem.use());
3102 test->TestCodecsOfVideoInitiate(elem.get());
3105 TEST_F(MediaSessionTest, GingleGoodVideoInitiateWithBandwidth) {
3106 rtc::scoped_ptr<buzz::XmlElement> elem;
3107 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3108 test->ExpectVideoBandwidth(42000);
3109 test->TestGoodIncomingInitiate(
3110 kGingleVideoInitiateWithBandwidth, VideoCallOptions(), elem.use());
3113 TEST_F(MediaSessionTest, GingleGoodInitiateAllSupportedAudioCodecs) {
3114 rtc::scoped_ptr<buzz::XmlElement> elem;
3115 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3116 test->TestGoodIncomingInitiate(
3117 kGingleInitiate, AudioCallOptions(), elem.use());
3118 test->TestHasAllSupportedAudioCodecs(elem.get());
3121 TEST_F(MediaSessionTest, GingleGoodInitiateAllSupportedAudioCodecsWithCrypto) {
3122 rtc::scoped_ptr<buzz::XmlElement> elem;
3123 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3124 test->ExpectCrypto(cricket::SEC_ENABLED);
3125 test->TestGoodIncomingInitiate(
3126 AddEncryption(kGingleInitiate, kGingleCryptoOffer),
3129 test->TestHasAllSupportedAudioCodecs(elem.get());
3132 // Changes the codecs that our FakeMediaEngine will support with a different
3133 // preference order than the incoming offer.
3134 // Verifies the answer accepts the preference order of the remote peer.
3135 TEST_F(MediaSessionTest, GingleGoodInitiateDifferentPreferenceAudioCodecs) {
3136 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3137 test->fme()->SetAudioCodecs(MAKE_VECTOR(kAudioCodecsDifferentPreference));
3138 rtc::scoped_ptr<buzz::XmlElement> elem;
3139 test->TestGoodIncomingInitiate(
3140 kGingleInitiate, AudioCallOptions(), elem.use());
3141 test->TestHasAllSupportedAudioCodecs(elem.get());
3144 TEST_F(MediaSessionTest, GingleGoodInitiateSomeUnsupportedAudioCodecs) {
3145 rtc::scoped_ptr<buzz::XmlElement> elem;
3146 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3147 test->TestGoodIncomingInitiate(
3148 kGingleInitiateSomeUnsupported, AudioCallOptions(), elem.use());
3149 test->TestHasAudioCodecsFromInitiateSomeUnsupported(elem.get());
3152 TEST_F(MediaSessionTest, GingleGoodInitiateDynamicAudioCodecs) {
3153 rtc::scoped_ptr<buzz::XmlElement> elem;
3154 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3155 test->TestGoodIncomingInitiate(
3156 kGingleInitiateDynamicAudioCodecs, AudioCallOptions(), elem.use());
3157 test->TestHasAudioCodecsFromInitiateDynamicAudioCodecs(elem.get());
3160 TEST_F(MediaSessionTest, GingleGoodInitiateStaticAudioCodecs) {
3161 rtc::scoped_ptr<buzz::XmlElement> elem;
3162 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3163 test->TestGoodIncomingInitiate(
3164 kGingleInitiateStaticAudioCodecs, AudioCallOptions(), elem.use());
3165 test->TestHasAudioCodecsFromInitiateStaticAudioCodecs(elem.get());
3168 TEST_F(MediaSessionTest, GingleGoodInitiateNoAudioCodecs) {
3169 rtc::scoped_ptr<buzz::XmlElement> elem;
3170 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3171 test->TestGoodIncomingInitiate(
3172 kGingleInitiateNoAudioCodecs, AudioCallOptions(), elem.use());
3173 test->TestHasDefaultAudioCodecs(elem.get());
3176 TEST_F(MediaSessionTest, GingleBadInitiateNoSupportedAudioCodecs) {
3177 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3178 test->TestBadIncomingInitiate(kGingleInitiateNoSupportedAudioCodecs);
3181 TEST_F(MediaSessionTest, GingleBadInitiateWrongClockrates) {
3182 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3183 test->TestBadIncomingInitiate(kGingleInitiateWrongClockrates);
3186 TEST_F(MediaSessionTest, GingleBadInitiateWrongChannels) {
3187 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3188 test->TestBadIncomingInitiate(kGingleInitiateWrongChannels);
3191 TEST_F(MediaSessionTest, GingleBadInitiateNoPayloadTypes) {
3192 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3193 test->TestBadIncomingInitiate(kGingleInitiateNoPayloadTypes);
3196 TEST_F(MediaSessionTest, GingleBadInitiateDynamicWithoutNames) {
3197 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3198 test->TestBadIncomingInitiate(kGingleInitiateDynamicWithoutNames);
3201 TEST_F(MediaSessionTest, GingleGoodOutgoingInitiate) {
3202 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3203 test->TestGoodOutgoingInitiate(AudioCallOptions());
3206 TEST_F(MediaSessionTest, GingleGoodOutgoingInitiateWithBandwidth) {
3207 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3208 cricket::CallOptions options = VideoCallOptions();
3209 options.video_bandwidth = 42000;
3210 test->TestGoodOutgoingInitiate(options);
3213 // Crypto related tests.
3215 // Offer has crypto but the session is not secured, just ignore it.
3216 TEST_F(MediaSessionTest, GingleInitiateWithCryptoIsIgnoredWhenNotSecured) {
3217 rtc::scoped_ptr<buzz::XmlElement> elem;
3218 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3219 test->TestGoodIncomingInitiate(
3220 AddEncryption(kGingleInitiate, kGingleCryptoOffer),
3225 // Offer has crypto required but the session is not secure, fail.
3226 TEST_F(MediaSessionTest, GingleInitiateWithCryptoRequiredWhenNotSecured) {
3227 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3228 test->TestBadIncomingInitiate(AddEncryption(kGingleInitiate,
3229 kGingleRequiredCryptoOffer));
3232 // Offer has no crypto but the session is secure required, fail.
3233 TEST_F(MediaSessionTest, GingleInitiateWithNoCryptoFailsWhenSecureRequired) {
3234 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3235 test->ExpectCrypto(cricket::SEC_REQUIRED);
3236 test->TestBadIncomingInitiate(kGingleInitiate);
3239 // Offer has crypto and session is secure, expect crypto in the answer.
3240 TEST_F(MediaSessionTest, GingleInitiateWithCryptoWhenSecureEnabled) {
3241 rtc::scoped_ptr<buzz::XmlElement> elem;
3242 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3243 test->ExpectCrypto(cricket::SEC_ENABLED);
3244 test->TestGoodIncomingInitiate(
3245 AddEncryption(kGingleInitiate, kGingleCryptoOffer),
3250 // Offer has crypto and session is secure required, expect crypto in
3252 TEST_F(MediaSessionTest, GingleInitiateWithCryptoWhenSecureRequired) {
3253 rtc::scoped_ptr<buzz::XmlElement> elem;
3254 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3255 test->ExpectCrypto(cricket::SEC_REQUIRED);
3256 test->TestGoodIncomingInitiate(
3257 AddEncryption(kGingleInitiate, kGingleCryptoOffer),
3262 // Offer has unsupported crypto and session is secure, no crypto in
3264 TEST_F(MediaSessionTest, GingleInitiateWithUnsupportedCrypto) {
3265 rtc::scoped_ptr<buzz::XmlElement> elem;
3266 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3267 test->MakeSignalingSecure(cricket::SEC_ENABLED);
3268 test->TestGoodIncomingInitiate(
3269 AddEncryption(kGingleInitiate, kGingleUnsupportedCryptoOffer),
3274 // Offer has unsupported REQUIRED crypto and session is not secure, fail.
3275 TEST_F(MediaSessionTest, GingleInitiateWithRequiredUnsupportedCrypto) {
3276 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3277 test->TestBadIncomingInitiate(
3278 AddEncryption(kGingleInitiate, kGingleRequiredUnsupportedCryptoOffer));
3281 // Offer has unsupported REQUIRED crypto and session is secure, fail.
3282 TEST_F(MediaSessionTest,
3283 GingleInitiateWithRequiredUnsupportedCryptoWhenSecure) {
3284 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3285 test->MakeSignalingSecure(cricket::SEC_ENABLED);
3286 test->TestBadIncomingInitiate(
3287 AddEncryption(kGingleInitiate, kGingleRequiredUnsupportedCryptoOffer));
3290 // Offer has unsupported REQUIRED crypto and session is required secure, fail.
3291 TEST_F(MediaSessionTest,
3292 GingleInitiateWithRequiredUnsupportedCryptoWhenSecureRequired) {
3293 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3294 test->MakeSignalingSecure(cricket::SEC_REQUIRED);
3295 test->TestBadIncomingInitiate(
3296 AddEncryption(kGingleInitiate, kGingleRequiredUnsupportedCryptoOffer));
3299 TEST_F(MediaSessionTest, GingleGoodOutgoingInitiateWithCrypto) {
3300 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3301 test->ExpectCrypto(cricket::SEC_ENABLED);
3302 test->TestGoodOutgoingInitiate(AudioCallOptions());
3305 TEST_F(MediaSessionTest, GingleGoodOutgoingInitiateWithCryptoRequired) {
3306 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3307 test->ExpectCrypto(cricket::SEC_REQUIRED);
3308 test->TestGoodOutgoingInitiate(AudioCallOptions());
3311 TEST_F(MediaSessionTest, GingleIncomingAcceptWithSsrcs) {
3312 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3313 cricket::CallOptions options = VideoCallOptions();
3314 options.is_muc = true;
3315 test->TestIncomingAcceptWithSsrcs(kGingleAcceptWithSsrcs, options);
3318 TEST_F(MediaSessionTest, GingleGoodOutgoingInitiateWithRtpData) {
3319 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3320 cricket::CallOptions options;
3321 options.data_channel_type = cricket::DCT_RTP;
3322 test->ExpectCrypto(cricket::SEC_ENABLED);
3323 test->TestGoodOutgoingInitiate(options);