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 "talk/p2p/base/constants.h"
35 #include "talk/p2p/client/basicportallocator.h"
36 #include "talk/session/media/mediasessionclient.h"
37 #include "talk/xmllite/xmlbuilder.h"
38 #include "talk/xmllite/xmlelement.h"
39 #include "talk/xmllite/xmlprinter.h"
40 #include "talk/xmpp/constants.h"
41 #include "webrtc/base/gunit.h"
42 #include "webrtc/base/logging.h"
43 #include "webrtc/base/scoped_ptr.h"
45 using cricket::AudioCodec;
46 using cricket::AudioContentDescription;
48 using cricket::DataCodec;
49 using cricket::DataContentDescription;
50 using cricket::FeedbackParam;
51 using cricket::FeedbackParams;
52 using cricket::VideoCodec;
53 using cricket::VideoContentDescription;
55 // The codecs that our FakeMediaEngine will support. Order is important, since
56 // the tests check that our messages have codecs in the correct order.
57 static const cricket::AudioCodec kAudioCodecs[] = {
58 cricket::AudioCodec(103, "ISAC", 16000, -1, 1, 18),
59 cricket::AudioCodec(104, "ISAC", 32000, -1, 1, 17),
60 cricket::AudioCodec(119, "ISACLC", 16000, 40000, 1, 16),
61 cricket::AudioCodec(99, "speex", 16000, 22000, 1, 15),
62 cricket::AudioCodec(97, "IPCMWB", 16000, 80000, 1, 14),
63 cricket::AudioCodec(9, "G722", 16000, 64000, 1, 13),
64 cricket::AudioCodec(102, "iLBC", 8000, 13300, 1, 12),
65 cricket::AudioCodec(98, "speex", 8000, 11000, 1, 11),
66 cricket::AudioCodec(3, "GSM", 8000, 13000, 1, 10),
67 cricket::AudioCodec(100, "EG711U", 8000, 64000, 1, 9),
68 cricket::AudioCodec(101, "EG711A", 8000, 64000, 1, 8),
69 cricket::AudioCodec(0, "PCMU", 8000, 64000, 1, 7),
70 cricket::AudioCodec(8, "PCMA", 8000, 64000, 1, 6),
71 cricket::AudioCodec(126, "CN", 32000, 0, 1, 5),
72 cricket::AudioCodec(105, "CN", 16000, 0, 1, 4),
73 cricket::AudioCodec(13, "CN", 8000, 0, 1, 3),
74 cricket::AudioCodec(117, "red", 8000, 0, 1, 2),
75 cricket::AudioCodec(106, "telephone-event", 8000, 0, 1, 1)
78 // The codecs that our FakeMediaEngine will support with a different order of
80 static const cricket::AudioCodec kAudioCodecsDifferentPreference[] = {
81 cricket::AudioCodec(104, "ISAC", 32000, -1, 1, 17),
82 cricket::AudioCodec(97, "IPCMWB", 16000, 80000, 1, 14),
83 cricket::AudioCodec(9, "G722", 16000, 64000, 1, 13),
84 cricket::AudioCodec(119, "ISACLC", 16000, 40000, 1, 16),
85 cricket::AudioCodec(103, "ISAC", 16000, -1, 1, 18),
86 cricket::AudioCodec(99, "speex", 16000, 22000, 1, 15),
87 cricket::AudioCodec(100, "EG711U", 8000, 64000, 1, 9),
88 cricket::AudioCodec(101, "EG711A", 8000, 64000, 1, 8),
89 cricket::AudioCodec(0, "PCMU", 8000, 64000, 1, 7),
90 cricket::AudioCodec(8, "PCMA", 8000, 64000, 1, 6),
91 cricket::AudioCodec(102, "iLBC", 8000, 13300, 1, 12),
92 cricket::AudioCodec(3, "GSM", 8000, 13000, 1, 10),
93 cricket::AudioCodec(98, "speex", 8000, 11000, 1, 11),
94 cricket::AudioCodec(126, "CN", 32000, 0, 1, 5),
95 cricket::AudioCodec(105, "CN", 16000, 0, 1, 4),
96 cricket::AudioCodec(13, "CN", 8000, 0, 1, 3),
97 cricket::AudioCodec(117, "red", 8000, 0, 1, 2),
98 cricket::AudioCodec(106, "telephone-event", 8000, 0, 1, 1)
101 static const cricket::VideoCodec kVideoCodecs[] = {
102 cricket::VideoCodec(96, "H264-SVC", 320, 200, 30, 1)
105 static const cricket::DataCodec kDataCodecs[] = {
106 cricket::DataCodec(127, "google-data", 0)
109 const std::string kGingleCryptoOffer = \
110 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'> " \
112 " <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \
113 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
114 " <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \
115 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
116 "</rtp:encryption> ";
118 // Jingle offer does not have any <usage> element.
119 const std::string kJingleCryptoOffer = \
120 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'> " \
121 " <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \
122 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
123 " <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \
124 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
125 "</rtp:encryption> ";
128 const std::string kGingleRequiredCryptoOffer = \
129 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'> "\
131 " <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \
132 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
133 " <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \
134 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
135 "</rtp:encryption> ";
137 const std::string kJingleRequiredCryptoOffer = \
138 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'> "\
139 " <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \
140 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
141 " <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \
142 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
143 "</rtp:encryption> ";
146 const std::string kGingleUnsupportedCryptoOffer = \
147 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'> " \
149 " <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1'" \
150 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
151 " <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2'" \
152 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
153 "</rtp:encryption> ";
155 const std::string kJingleUnsupportedCryptoOffer = \
156 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'> " \
157 " <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1'" \
158 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
159 " <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2'" \
160 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
161 "</rtp:encryption> ";
164 // With unsupported but with required="true"
165 const std::string kGingleRequiredUnsupportedCryptoOffer = \
166 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'>" \
168 " <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1'" \
169 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
170 " <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2'" \
171 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
172 "</rtp:encryption> ";
174 const std::string kJingleRequiredUnsupportedCryptoOffer = \
175 "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'>" \
176 " <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1' " \
177 " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/> " \
178 " <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2' " \
179 " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
180 "</rtp:encryption> ";
182 const std::string kGingleInitiate(
183 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
184 " to='user@domain.com/resource' type='set' id='123'> " \
185 " <session xmlns='http://www.google.com/session' type='initiate'" \
186 " id='abcdef' initiator='me@domain.com/resource'> " \
187 " <description xmlns='http://www.google.com/session/phone'> " \
188 " <payload-type xmlns='http://www.google.com/session/phone' " \
189 " id='103' name='ISAC' clockrate='16000' /> " \
190 " <payload-type xmlns='http://www.google.com/session/phone' " \
191 " id='104' name='ISAC' clockrate='32000' /> " \
192 " <payload-type xmlns='http://www.google.com/session/phone' " \
193 " id='119' name='ISACLC' clockrate='16000' bitrate='40000' /> " \
194 " <payload-type xmlns='http://www.google.com/session/phone' " \
195 " id='99' name='speex' clockrate='16000' bitrate='22000' /> " \
196 " <payload-type xmlns='http://www.google.com/session/phone' " \
197 " id='97' name='IPCMWB' clockrate='16000' bitrate='80000' /> " \
198 " <payload-type xmlns='http://www.google.com/session/phone' " \
199 " id='9' name='G722' clockrate='16000' bitrate='64000' /> " \
200 " <payload-type xmlns='http://www.google.com/session/phone' " \
201 " id='102' name='iLBC' clockrate='8000' bitrate='13300' />" \
202 " <payload-type xmlns='http://www.google.com/session/phone' " \
203 " id='98' name='speex' clockrate='8000' bitrate='11000' />" \
204 " <payload-type xmlns='http://www.google.com/session/phone' " \
205 " id='3' name='GSM' clockrate='8000' bitrate='13000' /> " \
206 " <payload-type xmlns='http://www.google.com/session/phone' " \
207 " id='100' name='EG711U' clockrate='8000' bitrate='64000' /> " \
208 " <payload-type xmlns='http://www.google.com/session/phone' " \
209 " id='101' name='EG711A' clockrate='8000' bitrate='64000' /> " \
210 " <payload-type xmlns='http://www.google.com/session/phone' " \
211 " id='0' name='PCMU' clockrate='8000' bitrate='64000' /> " \
212 " <payload-type xmlns='http://www.google.com/session/phone' " \
213 " id='8' name='PCMA' clockrate='8000' bitrate='64000' /> " \
214 " <payload-type xmlns='http://www.google.com/session/phone' " \
215 " id='126' name='CN' clockrate='32000' /> " \
216 " <payload-type xmlns='http://www.google.com/session/phone' " \
217 " id='105' name='CN' clockrate='16000' /> " \
218 " <payload-type xmlns='http://www.google.com/session/phone' " \
219 " id='13' name='CN' clockrate='8000' /> " \
220 " <payload-type xmlns='http://www.google.com/session/phone' " \
221 " id='117' name='red' clockrate='8000' /> " \
222 " <payload-type xmlns='http://www.google.com/session/phone' " \
223 " id='106' name='telephone-event' clockrate='8000' /> " \
228 const std::string kJingleInitiate(
229 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
230 " to='user@domain.com/resource' type='set' id='123'> " \
231 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
232 " sid='abcdef' initiator='me@domain.com/resource'> " \
233 " <content name='test audio'> " \
234 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
235 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
236 " <payload-type id='104' name='ISAC' clockrate='32000'/> " \
238 " id='119' name='ISACLC' clockrate='16000'> " \
239 " <parameter name='bitrate' value='40000'/> " \
240 " </payload-type> " \
242 " id='99' name='speex' clockrate='16000'> " \
243 " <parameter name='bitrate' value='22000'/> " \
244 " </payload-type> " \
246 " id='97' name='IPCMWB' clockrate='16000'> " \
247 " <parameter name='bitrate' value='80000'/> " \
248 " </payload-type> " \
250 " id='9' name='G722' clockrate='16000'> " \
251 " <parameter name='bitrate' value='64000'/> " \
252 " </payload-type> " \
254 " id='102' name='iLBC' clockrate='8000'> " \
255 " <parameter name='bitrate' value='13300'/> " \
256 " </payload-type> " \
258 " id='98' name='speex' clockrate='8000'> " \
259 " <parameter name='bitrate' value='11000'/> " \
260 " </payload-type> " \
262 " id='3' name='GSM' clockrate='8000'> " \
263 " <parameter name='bitrate' value='13000'/> " \
264 " </payload-type> " \
266 " id='100' name='EG711U' clockrate='8000'> " \
267 " <parameter name='bitrate' value='64000'/> " \
268 " </payload-type> " \
270 " id='101' name='EG711A' clockrate='8000'> " \
271 " <parameter name='bitrate' value='64000'/> " \
272 " </payload-type> " \
274 " id='0' name='PCMU' clockrate='8000'> " \
275 " <parameter name='bitrate' value='64000'/> " \
276 " </payload-type> " \
278 " id='8' name='PCMA' clockrate='8000'> " \
279 " <parameter name='bitrate' value='64000'/> " \
280 " </payload-type> " \
282 " id='126' name='CN' clockrate='32000' /> " \
284 " id='105' name='CN' clockrate='16000' /> " \
286 " id='13' name='CN' clockrate='8000' /> " \
288 " id='117' name='red' clockrate='8000' /> " \
290 " id='106' name='telephone-event' clockrate='8000' /> " \
292 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
297 const std::string kJingleInitiateWithRtcpFb(
298 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
299 " to='user@domain.com/resource' type='set' id='123'> " \
300 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
301 " sid='abcdef' initiator='me@domain.com/resource'> " \
302 " <content name='test audio'> " \
303 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
304 " <payload-type id='103' name='ISAC' clockrate='16000'> " \
305 " <rtcp-fb type='nack'/> " \
306 " </payload-type> " \
308 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
310 " <content name='test video'> " \
311 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
312 " <rtcp-fb type='nack'/> " \
313 " <payload-type id='99' name='H264-SVC'> " \
314 " <rtcp-fb type='ccm' subtype='fir'/> " \
315 " <parameter name='height' value='200'/> " \
316 " <parameter name='width' value='320'/> " \
317 " <parameter name='framerate' value='30'/> " \
318 " </payload-type> " \
320 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
322 " <content name='test data'> " \
323 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='data'> " \
324 " <rtcp-fb type='nack'/> " \
325 " <payload-type id='127' name='google-data'> " \
326 " </payload-type> " \
328 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
333 const std::string kGingleVideoInitiate(
334 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
335 " to='user@domain.com/resource' type='set' id='123'> " \
336 " <session xmlns='http://www.google.com/session' type='initiate'" \
337 " id='abcdef' initiator='me@domain.com/resource'> " \
338 " <description xmlns='http://www.google.com/session/video'> " \
339 " <payload-type xmlns='http://www.google.com/session/phone' " \
340 " id='103' name='ISAC' clockrate='16000' /> " \
341 " <payload-type xmlns='http://www.google.com/session/video' " \
342 " id='99' name='H264-SVC' framerate='30' " \
343 " height='200' width='320'/> " \
348 const std::string kJingleVideoInitiate(
349 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
350 " to='user@domain.com/resource' type='set' id='123'> " \
351 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
352 " sid='abcdef' initiator='me@domain.com/resource'> " \
353 " <content name='test audio'> " \
354 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
355 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
357 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
359 " <content name='test video'> " \
360 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
361 " <payload-type id='99' name='H264-SVC'> " \
362 " <parameter name='height' value='200'/> " \
363 " <parameter name='width' value='320'/> " \
364 " <parameter name='framerate' value='30'/> " \
365 " </payload-type> " \
367 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
372 const std::string kJingleVideoInitiateWithRtpData(
373 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
374 " to='user@domain.com/resource' type='set' id='123'> " \
375 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
376 " sid='abcdef' initiator='me@domain.com/resource'> " \
377 " <content name='test audio'> " \
378 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
379 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
381 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
383 " <content name='test video'> " \
384 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
385 " <payload-type id='99' name='H264-SVC'> " \
386 " <parameter name='height' value='200'/> " \
387 " <parameter name='width' value='320'/> " \
388 " <parameter name='framerate' value='30'/> " \
389 " </payload-type> " \
391 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
393 " <content name='test data'> " \
394 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='data'> " \
395 " <payload-type id='127' name='google-data'/> " \
398 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
403 const std::string kJingleVideoInitiateWithSctpData(
404 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
405 " to='user@domain.com/resource' type='set' id='123'> " \
406 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
407 " sid='abcdef' initiator='me@domain.com/resource'> " \
408 " <content name='test audio'> " \
409 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
410 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
412 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
414 " <content name='test video'> " \
415 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
416 " <payload-type id='99' name='H264-SVC'> " \
417 " <parameter name='height' value='200'/> " \
418 " <parameter name='width' value='320'/> " \
419 " <parameter name='framerate' value='30'/> " \
420 " </payload-type> " \
422 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
424 " <content name='test data'> " \
425 " <description xmlns='google:jingle:sctp' media='data'> " \
426 " <stream sid='1'/> " \
428 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
433 const std::string kJingleVideoInitiateWithBandwidth(
434 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
435 " to='user@domain.com/resource' type='set' id='123'> " \
436 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
437 " sid='abcdef' initiator='me@domain.com/resource'> " \
438 " <content name='test audio'> " \
439 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
440 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
442 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
444 " <content name='test video'> " \
445 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
446 " <payload-type id='99' name='H264-SVC'> " \
447 " <parameter name='height' value='200'/> " \
448 " <parameter name='width' value='320'/> " \
449 " <parameter name='framerate' value='30'/> " \
450 " </payload-type> " \
451 " <bandwidth type='AS'>42</bandwidth> " \
453 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
458 const std::string kJingleVideoInitiateWithRtcpMux(
459 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
460 " to='user@domain.com/resource' type='set' id='123'> " \
461 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
462 " sid='abcdef' initiator='me@domain.com/resource'> " \
463 " <content name='test audio'> " \
464 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
465 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
467 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
469 " <content name='test video'> " \
470 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
471 " <payload-type id='99' name='H264-SVC'> " \
472 " <parameter name='height' value='200'/> " \
473 " <parameter name='width' value='320'/> " \
474 " <parameter name='framerate' value='30'/> " \
475 " </payload-type> " \
478 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
483 // Initiate string with a combination of supported and unsupported codecs
484 // Should accept the supported ones
485 const std::string kGingleInitiateSomeUnsupported(
486 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
487 " to='user@domain.com/resource' type='set' id='123'> " \
488 " <session xmlns='http://www.google.com/session' type='initiate'" \
489 " id='abcdef' initiator='me@domain.com/resource'> " \
490 " <description xmlns='http://www.google.com/session/phone'> " \
491 " <payload-type xmlns='http://www.google.com/session/phone' " \
492 " id='103' name='ISAC' clockrate='16000' /> " \
493 " <payload-type xmlns='http://www.google.com/session/phone' " \
494 " id='97' name='ASDFDS' /> " \
495 " <payload-type xmlns='http://www.google.com/session/phone' " \
496 " id='102' name='1010' /> " \
497 " <payload-type xmlns='http://www.google.com/session/phone' " \
498 " id='107' name='DFAS' /> " \
499 " <payload-type xmlns='http://www.google.com/session/phone' " \
500 " id='100' name='EG711U' /> " \
501 " <payload-type xmlns='http://www.google.com/session/phone' " \
502 " id='101' name='EG711A' /> " \
503 " <payload-type xmlns='http://www.google.com/session/phone' " \
504 " id='0' name='PCMU' /> " \
505 " <payload-type xmlns='http://www.google.com/session/phone' " \
506 " id='110' name=':)' /> " \
507 " <payload-type xmlns='http://www.google.com/session/phone' " \
508 " id='13' name='CN' /> " \
513 const std::string kJingleInitiateSomeUnsupported(
514 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
515 " to='user@domain.com/resource' type='set' id='123'> " \
516 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
517 " sid='abcdef' initiator='me@domain.com/resource'> " \
518 " <content name='test audio'> " \
519 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
521 " id='103' name='ISAC' clockrate='16000' /> " \
523 " id='97' name='ASDFDS' /> " \
525 " id='102' name='1010' /> " \
527 " id='107' name='DFAS' /> " \
529 " id='100' name='EG711U' /> " \
531 " id='101' name='EG711A' /> " \
533 " id='0' name='PCMU' /> " \
535 " id='110' name=':)' /> " \
537 " id='13' name='CN' /> " \
539 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
544 const std::string kGingleVideoInitiateWithBandwidth(
545 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
546 " to='user@domain.com/resource' type='set' id='123'> " \
547 " <session xmlns='http://www.google.com/session' type='initiate'" \
548 " id='abcdef' initiator='me@domain.com/resource'> " \
549 " <description xmlns='http://www.google.com/session/video'> " \
550 " <payload-type xmlns='http://www.google.com/session/phone' " \
551 " id='103' name='ISAC' clockrate='16000' /> " \
552 " <payload-type xmlns='http://www.google.com/session/video' " \
553 " id='99' name='H264-SVC' framerate='30' " \
554 " height='200' width='320'/> " \
555 " <bandwidth type='AS'>42</bandwidth> " \
560 // Initiate string without any supported codecs. Should send a reject.
561 const std::string kGingleInitiateNoSupportedAudioCodecs(
562 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
563 " to='user@domain.com/resource' type='set' id='123'> " \
564 " <session xmlns='http://www.google.com/session' type='initiate'" \
565 " id='abcdef' initiator='me@domain.com/resource'> " \
566 " <description xmlns='http://www.google.com/session/phone'> " \
567 " <payload-type xmlns='http://www.google.com/session/phone' " \
568 " id='123' name='Supercodec6000' /> " \
573 const std::string kJingleInitiateNoSupportedAudioCodecs(
574 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
575 " to='user@domain.com/resource' type='set' id='123'> " \
576 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
577 " sid='abcdef' initiator='me@domain.com/resource'> " \
578 " <content name='test audio'> " \
579 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
581 " id='123' name='Supercodec6000' /> " \
583 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
588 // Initiate string without any codecs. Assumes ancient version of Cricket
589 // and tries a session with ISAC and PCMU
590 const std::string kGingleInitiateNoAudioCodecs(
591 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
592 " to='user@domain.com/resource' type='set' id='123'> " \
593 " <session xmlns='http://www.google.com/session' type='initiate'" \
594 " id='abcdef' initiator='me@domain.com/resource'> " \
595 " <description xmlns='http://www.google.com/session/phone'> " \
600 const std::string kJingleInitiateNoAudioCodecs(
601 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
602 " to='user@domain.com/resource' type='set' id='123'> " \
603 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
604 " sid='abcdef' initiator='me@domain.com/resource'> " \
605 " <content name='test audio'> " \
606 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
608 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
613 // The codecs are supported, but not at the given clockrates. Should send
615 const std::string kGingleInitiateWrongClockrates(
616 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
617 " to='user@domain.com/resource' type='set' id='123'> " \
618 " <session xmlns='http://www.google.com/session' type='initiate'" \
619 " id='abcdef' initiator='me@domain.com/resource'> " \
620 " <description xmlns='http://www.google.com/session/phone'> " \
621 " <payload-type xmlns='http://www.google.com/session/phone' " \
622 " id='103' name='ISAC' clockrate='8000'/> " \
623 " <payload-type xmlns='http://www.google.com/session/phone' " \
624 " id='97' name='IPCMWB' clockrate='1337'/> " \
625 " <payload-type xmlns='http://www.google.com/session/phone' " \
626 " id='102' name='iLBC' clockrate='1982' /> " \
631 const std::string kJingleInitiateWrongClockrates(
632 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
633 " to='user@domain.com/resource' type='set' id='123'> " \
634 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
635 " sid='abcdef' initiator='me@domain.com/resource'> " \
636 " <content name='test audio'> " \
637 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
639 " id='103' name='ISAC' clockrate='8000'/> " \
641 " id='97' name='IPCMWB' clockrate='1337'/> " \
643 " id='102' name='iLBC' clockrate='1982' /> " \
645 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
650 // The codecs are supported, but not with the given number of channels.
651 // Should send a reject.
652 const std::string kGingleInitiateWrongChannels(
653 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
654 " to='user@domain.com/resource' type='set' id='123'> " \
655 " <session xmlns='http://www.google.com/session' type='initiate'" \
656 " id='abcdef' initiator='me@domain.com/resource'> " \
657 " <description xmlns='http://www.google.com/session/phone'> " \
658 " <payload-type xmlns='http://www.google.com/session/phone' " \
659 " id='103' name='ISAC' channels='2'/> " \
660 " <payload-type xmlns='http://www.google.com/session/phone' " \
661 " id='97' name='IPCMWB' channels='3'/> " \
666 const std::string kJingleInitiateWrongChannels(
667 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
668 " to='user@domain.com/resource' type='set' id='123'> " \
669 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'> " \
670 " <content name='test audio'> " \
671 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
673 " id='103' name='ISAC' channels='2'/> " \
675 " id='97' name='IPCMWB' channels='3'/> " \
677 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
682 // Initiate with a dynamic codec not using webrtc default payload id. Should
683 // accept with provided payload id.
684 const std::string kGingleInitiateDynamicAudioCodecs(
685 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
686 " to='user@domain.com/resource' type='set' id='123'> " \
687 " <session xmlns='http://www.google.com/session' type='initiate'" \
688 " id='abcdef' initiator='me@domain.com/resource'> " \
689 " <description xmlns='http://www.google.com/session/phone'> " \
690 " <payload-type xmlns='http://www.google.com/session/phone' " \
691 " id='123' name='speex' clockrate='16000'/> " \
696 const std::string kJingleInitiateDynamicAudioCodecs(
697 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
698 " to='user@domain.com/resource' type='set' id='123'> " \
699 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
700 " sid='abcdef' initiator='me@domain.com/resource'> " \
701 " <content name='test audio'> " \
702 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
704 " id='123' name='speex' clockrate='16000'/> " \
706 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
711 // Initiate string with nothing but static codec id's. Should accept.
712 const std::string kGingleInitiateStaticAudioCodecs(
713 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
714 " to='user@domain.com/resource' type='set' id='123'> " \
715 " <session xmlns='http://www.google.com/session' type='initiate'" \
716 " id='abcdef' initiator='me@domain.com/resource'> " \
717 " <description xmlns='http://www.google.com/session/phone'> " \
718 " <payload-type xmlns='http://www.google.com/session/phone' " \
720 " <payload-type xmlns='http://www.google.com/session/phone' " \
722 " <payload-type xmlns='http://www.google.com/session/phone' " \
728 const std::string kJingleInitiateStaticAudioCodecs(
729 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
730 " to='user@domain.com/resource' type='set' id='123'> " \
731 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
732 " sid='abcdef' initiator='me@domain.com/resource'> " \
733 " <content name='test audio'> " \
734 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
735 " <payload-type id='3' /> " \
736 " <payload-type id='0' /> " \
737 " <payload-type id='8' /> " \
739 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
744 // Initiate with payload type-less codecs. Should reject.
745 const std::string kGingleInitiateNoPayloadTypes(
746 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
747 " to='user@domain.com/resource' type='set' id='123'> " \
748 " <session xmlns='http://www.google.com/session' type='initiate'" \
749 " id='abcdef' initiator='me@domain.com/resource'> " \
750 " <description xmlns='http://www.google.com/session/phone'> " \
751 " <payload-type xmlns='http://www.google.com/session/phone' " \
752 " name='ISAC' clockrate='16000'/> " \
757 const std::string kJingleInitiateNoPayloadTypes(
758 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
759 " to='user@domain.com/resource' type='set' id='123'> " \
760 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'> " \
761 " sid='abcdef' initiator='me@domain.com/resource'> " \
762 " <content name='test audio'> " \
763 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
764 " <payload-type name='ISAC' clockrate='16000'/> " \
766 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
771 // Initiate with unnamed dynamic codces. Should reject.
772 const std::string kGingleInitiateDynamicWithoutNames(
773 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
774 " to='user@domain.com/resource' type='set' id='123'> " \
775 " <session xmlns='http://www.google.com/session' type='initiate'" \
776 " id='abcdef' initiator='me@domain.com/resource'> " \
777 " <description xmlns='http://www.google.com/session/phone'> " \
778 " <payload-type xmlns='http://www.google.com/session/phone' " \
779 " id='100' clockrate='16000'/> " \
784 const std::string kJingleInitiateDynamicWithoutNames(
785 "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
786 " to='user@domain.com/resource' type='set' id='123'> " \
787 " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'> " \
788 " sid='abcdef' initiator='me@domain.com/resource'> " \
789 " <content name='test audio'> " \
790 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
791 " <payload-type id='100' clockrate='16000'/> " \
793 " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
798 const uint32 kAudioSsrc = 4294967295U;
799 const uint32 kVideoSsrc = 87654321;
800 const uint32 kDataSsrc = 1010101;
801 // Note that this message does not specify a session ID. It must be populated
803 const std::string kGingleAcceptWithSsrcs(
804 "<iq xmlns='jabber:client' from='me@mydomain.com' " \
805 " to='user@domain.com/resource' type='set' id='150'> " \
806 " <session xmlns='http://www.google.com/session' type='accept' " \
807 " initiator='me@domain.com/resource'> " \
808 " <description xmlns='http://www.google.com/session/video'> " \
809 " <payload-type xmlns='http://www.google.com/session/phone' " \
810 " id='103' name='ISAC' clockrate='16000' /> " \
811 " <payload-type xmlns='http://www.google.com/session/phone' " \
812 " id='104' name='ISAC' clockrate='32000' /> " \
813 " <src-id xmlns='http://www.google.com/session/phone'> " \
814 " 4294967295</src-id> " \
815 " <src-id>87654321</src-id> " \
820 const std::string kJingleAcceptWithSsrcs(
821 "<iq xmlns='jabber:client' from='me@mydomain.com' " \
822 " to='user@domain.com/resource' type='set' id='150'> " \
823 " <jingle xmlns='urn:xmpp:jingle:1' action='session-accept' " \
824 " initiator='me@domain.com/resource'> " \
825 " <content name='audio'> " \
826 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
827 " media='audio' ssrc='4294967295'> " \
828 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
829 " <payload-type id='104' name='ISAC' clockrate='32000'/> " \
831 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
833 " <content name='video'> " \
834 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
835 " media='video' ssrc='87654321'> " \
837 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
842 const std::string kJingleAcceptWithRtpDataSsrcs(
843 "<iq xmlns='jabber:client' from='me@mydomain.com' " \
844 " to='user@domain.com/resource' type='set' id='150'> " \
845 " <jingle xmlns='urn:xmpp:jingle:1' action='session-accept' " \
846 " initiator='me@domain.com/resource'> " \
847 " <content name='audio'> " \
848 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
849 " media='audio' ssrc='4294967295'> " \
850 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
851 " <payload-type id='104' name='ISAC' clockrate='32000'/> " \
853 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
855 " <content name='video'> " \
856 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
857 " media='video' ssrc='87654321'> " \
859 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
861 " <content name='data'> " \
862 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
863 " media='data' ssrc='1010101'> " \
865 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
870 const std::string kJingleAcceptWithSctpData(
871 "<iq xmlns='jabber:client' from='me@mydomain.com' " \
872 " to='user@domain.com/resource' type='set' id='150'> " \
873 " <jingle xmlns='urn:xmpp:jingle:1' action='session-accept' " \
874 " initiator='me@domain.com/resource'> " \
875 " <content name='audio'> " \
876 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
877 " media='audio' ssrc='4294967295'> " \
878 " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
879 " <payload-type id='104' name='ISAC' clockrate='32000'/> " \
881 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
883 " <content name='video'> " \
884 " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
885 " media='video' ssrc='87654321'> " \
887 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
889 " <content name='data'> " \
890 " <description xmlns='google:jingle:sctp'> " \
891 " <stream sid='1'/> " \
893 " <transport xmlns='http://www.google.com/transport/p2p'/> " \
898 std::string JingleView(const std::string& ssrc,
899 const std::string& width,
900 const std::string& height,
901 const std::string& framerate) {
902 // We have some slightly weird whitespace formatting to make the
903 // actual XML generated match the expected XML here.
906 " to='me@mydomain.com'"
908 " xmlns:cli='jabber:client'>"
910 " xmlns='urn:xmpp:jingle:1'"
911 " action='session-info'"
913 "<view xmlns='google:jingle'"
916 " ssrc='" + ssrc + "'>"
918 " width='" + width + "'"
919 " height='" + height + "'"
920 " framerate='" + framerate + "'"
927 std::string JingleStreamAdd(const std::string& content_name,
928 const std::string& nick,
929 const std::string& name,
930 const std::string& ssrc) {
933 " xmlns='jabber:client'"
934 " from='me@mydomain.com'"
935 " to='user@domain.com/resource'"
939 " xmlns='urn:xmpp:jingle:1'"
940 " action='description-info'>"
942 " xmlns='urn:xmpp:jingle:1'"
943 " name='" + content_name + "'>"
945 " xmlns='urn:xmpp:jingle:apps:rtp:1'"
946 " media='" + content_name + "'>"
948 " xmlns='google:jingle'>"
950 " nick='" + nick + "'"
951 " name='" + name + "'>"
952 " <ssrc>" + ssrc + "</ssrc>"
961 std::string JingleOutboundStreamRemove(const std::string& sid,
962 const std::string& content_name,
963 const std::string& name) {
966 " to='me@mydomain.com'"
968 " xmlns:cli='jabber:client'>"
970 " xmlns='urn:xmpp:jingle:1'"
971 " action='description-info'"
972 " sid='" + sid + "'>"
974 " name='" + content_name + "'"
975 " creator='initiator'>"
977 " xmlns='urn:xmpp:jingle:apps:rtp:1'"
978 " media='" + content_name + "'>"
980 " xmlns='google:jingle'>"
982 " name='" + name + "'>"
991 std::string JingleOutboundStreamAdd(const std::string& sid,
992 const std::string& content_name,
993 const std::string& name,
994 const std::string& ssrc) {
997 " to='me@mydomain.com'"
999 " xmlns:cli='jabber:client'>"
1001 " xmlns='urn:xmpp:jingle:1'"
1002 " action='description-info'"
1003 " sid='" + sid + "'>"
1005 " name='" + content_name + "'"
1006 " creator='initiator'>"
1008 " xmlns='urn:xmpp:jingle:apps:rtp:1'"
1009 " media='" + content_name + "'>"
1011 " xmlns='google:jingle'>"
1013 " name='" + name + "'>"
1014 "<ssrc>" + ssrc + "</ssrc>"
1023 std::string JingleStreamAddWithoutSsrc(const std::string& content_name,
1024 const std::string& nick,
1025 const std::string& name) {
1028 " xmlns='jabber:client'"
1029 " from='me@mydomain.com'"
1030 " to='user@domain.com/resource'"
1034 " xmlns='urn:xmpp:jingle:1'"
1035 " action='description-info'>"
1037 " xmlns='urn:xmpp:jingle:1'"
1038 " name='" + content_name + "'>"
1040 " xmlns='urn:xmpp:jingle:apps:rtp:1'"
1041 " media='" + content_name + "'>"
1043 " xmlns='google:jingle'>"
1045 " nick='" + nick + "'"
1046 " name='" + name + "'>"
1055 std::string JingleStreamRemove(const std::string& content_name,
1056 const std::string& nick,
1057 const std::string& name) {
1060 " xmlns='jabber:client'"
1061 " from='me@mydomain.com'"
1062 " to='user@domain.com/resource'"
1066 " xmlns='urn:xmpp:jingle:1'"
1067 " action='description-info'>"
1069 " xmlns='urn:xmpp:jingle:1'"
1070 " name='" + content_name + "'>"
1072 " xmlns='urn:xmpp:jingle:apps:rtp:1'"
1073 " media='" + content_name + "'>"
1075 " xmlns='google:jingle'>"
1077 " nick='" + nick + "'"
1078 " name='" + name + "'/>"
1086 // Convenience function to get CallOptions that have audio enabled,
1087 // but not video or data.
1088 static cricket::CallOptions AudioCallOptions() {
1089 cricket::CallOptions options;
1090 options.has_audio = true;
1091 options.has_video = false;
1092 options.data_channel_type = cricket::DCT_NONE;
1096 // Convenience function to get CallOptions that have audio and video
1097 // enabled, but not data.
1098 static cricket::CallOptions VideoCallOptions() {
1099 cricket::CallOptions options;
1100 options.has_audio = true;
1101 options.has_video = true;
1102 options.data_channel_type = cricket::DCT_NONE;
1106 static buzz::XmlElement* CopyElement(const buzz::XmlElement* elem) {
1107 return new buzz::XmlElement(*elem);
1110 static std::string AddEncryption(std::string stanza, std::string encryption) {
1111 std::string::size_type pos = stanza.find("</description>");
1112 while (pos != std::string::npos) {
1113 stanza = stanza.insert(pos, encryption);
1114 pos = stanza.find("</description>", pos + encryption.length() + 1);
1119 static int IntFromJingleCodecParameter(const buzz::XmlElement* parameter,
1120 const std::string& expected_name) {
1122 const std::string& actual_name =
1123 parameter->Attr(cricket::QN_PAYLOADTYPE_PARAMETER_NAME);
1125 EXPECT_EQ(expected_name, actual_name)
1126 << "wrong parameter name. Expected '"
1127 << expected_name << "'. Actually '"
1128 << actual_name << "'.";
1130 return atoi(parameter->Attr(
1131 cricket::QN_PAYLOADTYPE_PARAMETER_VALUE).c_str());
1136 template <class CodecClass, class DescriptionClass>
1137 static void VerifyCodecFbParams(const FeedbackParams& expected,
1138 const DescriptionClass* desc) {
1139 if (!expected.params().empty()) {
1140 ASSERT_TRUE(desc != NULL);
1141 const std::vector<CodecClass> codecs = desc->codecs();
1142 for (size_t i = 0; i < codecs.size(); ++i) {
1143 EXPECT_EQ(expected, codecs[i].feedback_params);
1148 // Parses and extracts payload and codec info from test XML. Since
1149 // that XML will be in various contents (Gingle and Jingle), we need an
1150 // abstract parser with one concrete implementation per XML content.
1151 class MediaSessionTestParser {
1153 virtual buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) = 0;
1154 virtual buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) = 0;
1155 virtual buzz::XmlElement* NextContent(buzz::XmlElement* content) = 0;
1156 virtual buzz::XmlElement* PayloadTypeFromContent(
1157 buzz::XmlElement* content) = 0;
1158 virtual buzz::XmlElement* NextFromPayloadType(
1159 buzz::XmlElement* payload_type) = 0;
1160 virtual cricket::AudioCodec AudioCodecFromPayloadType(
1161 const buzz::XmlElement* payload_type) = 0;
1162 virtual cricket::VideoCodec VideoCodecFromPayloadType(
1163 const buzz::XmlElement* payload_type) = 0;
1164 virtual cricket::DataCodec DataCodecFromPayloadType(
1165 const buzz::XmlElement* payload_type) = 0;
1166 virtual buzz::XmlElement* EncryptionFromContent(
1167 buzz::XmlElement* content) = 0;
1168 virtual buzz::XmlElement* NextFromEncryption(
1169 buzz::XmlElement* encryption) = 0;
1170 virtual const buzz::XmlElement* BandwidthFromContent(
1171 buzz::XmlElement* content) = 0;
1172 virtual const buzz::XmlElement* RtcpMuxFromContent(
1173 buzz::XmlElement* content) = 0;
1174 virtual bool ActionIsTerminate(const buzz::XmlElement* action) = 0;
1175 virtual ~MediaSessionTestParser() {}
1178 class JingleSessionTestParser : public MediaSessionTestParser {
1180 JingleSessionTestParser() {}
1182 ~JingleSessionTestParser() {
1185 buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
1186 return stanza->FirstNamed(cricket::QN_JINGLE);
1189 buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) {
1190 // We need to be able to use multiple contents, but the action
1191 // gets deleted before we can call NextContent, so we need to
1192 // stash away a copy.
1193 action_.reset(CopyElement(action));
1194 return action_->FirstNamed(cricket::QN_JINGLE_CONTENT);
1197 buzz::XmlElement* NextContent(buzz::XmlElement* content) {
1198 // For some reason, content->NextNamed(cricket::QN_JINGLE_CONTENT)
1200 return action_->FirstNamed(cricket::QN_JINGLE_CONTENT)
1201 ->NextNamed(cricket::QN_JINGLE_CONTENT);
1204 buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* content) {
1205 buzz::XmlElement* content_desc =
1206 content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
1210 return content_desc->FirstNamed(cricket::QN_JINGLE_RTP_PAYLOADTYPE);
1213 buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
1214 return payload_type->NextNamed(cricket::QN_JINGLE_RTP_PAYLOADTYPE);
1217 void ParsePayloadTypeFeedbackParameters(const buzz::XmlElement* element,
1218 FeedbackParams* params) {
1219 const buzz::XmlElement* param =
1220 element->FirstNamed(cricket::QN_JINGLE_RTCP_FB);
1221 for (; param != NULL;
1222 param = param->NextNamed(cricket::QN_JINGLE_RTCP_FB)) {
1223 std::string type = param->Attr(cricket::QN_TYPE);
1224 std::string subtype = param->Attr(cricket::QN_SUBTYPE);
1225 if (!type.empty()) {
1226 params->Add(FeedbackParam(type, subtype));
1231 cricket::AudioCodec AudioCodecFromPayloadType(
1232 const buzz::XmlElement* payload_type) {
1234 if (payload_type->HasAttr(cricket::QN_ID))
1235 id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1238 if (payload_type->HasAttr(cricket::QN_NAME))
1239 name = payload_type->Attr(cricket::QN_NAME);
1242 if (payload_type->HasAttr(cricket::QN_CLOCKRATE))
1243 clockrate = atoi(payload_type->Attr(cricket::QN_CLOCKRATE).c_str());
1245 int bitrate = IntFromJingleCodecParameter(
1246 payload_type->FirstNamed(cricket::QN_PARAMETER), "bitrate");
1249 if (payload_type->HasAttr(cricket::QN_CHANNELS))
1250 channels = atoi(payload_type->Attr(
1251 cricket::QN_CHANNELS).c_str());
1253 AudioCodec codec = AudioCodec(id, name, clockrate, bitrate, channels, 0);
1254 ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params);
1258 cricket::VideoCodec VideoCodecFromPayloadType(
1259 const buzz::XmlElement* payload_type) {
1261 if (payload_type->HasAttr(cricket::QN_ID))
1262 id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1265 if (payload_type->HasAttr(cricket::QN_NAME))
1266 name = payload_type->Attr(cricket::QN_NAME);
1271 const buzz::XmlElement* param =
1272 payload_type->FirstNamed(cricket::QN_PARAMETER);
1274 width = IntFromJingleCodecParameter(param, "width");
1275 param = param->NextNamed(cricket::QN_PARAMETER);
1277 height = IntFromJingleCodecParameter(param, "height");
1278 param = param->NextNamed(cricket::QN_PARAMETER);
1280 framerate = IntFromJingleCodecParameter(param, "framerate");
1284 VideoCodec codec = VideoCodec(id, name, width, height, framerate, 0);
1285 ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params);
1289 cricket::DataCodec DataCodecFromPayloadType(
1290 const buzz::XmlElement* payload_type) {
1292 if (payload_type->HasAttr(cricket::QN_ID))
1293 id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1296 if (payload_type->HasAttr(cricket::QN_NAME))
1297 name = payload_type->Attr(cricket::QN_NAME);
1299 DataCodec codec = DataCodec(id, name, 0);
1300 ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params);
1304 bool ActionIsTerminate(const buzz::XmlElement* action) {
1305 return (action->HasAttr(cricket::QN_ACTION) &&
1306 action->Attr(cricket::QN_ACTION) == "session-terminate");
1309 buzz::XmlElement* EncryptionFromContent(buzz::XmlElement* content) {
1310 buzz::XmlElement* content_desc =
1311 content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
1315 return content_desc->FirstNamed(cricket::QN_ENCRYPTION);
1318 buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
1319 return encryption->NextNamed(cricket::QN_ENCRYPTION);
1322 const buzz::XmlElement* BandwidthFromContent(buzz::XmlElement* content) {
1323 buzz::XmlElement* content_desc =
1324 content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
1328 return content_desc->FirstNamed(cricket::QN_JINGLE_RTP_BANDWIDTH);
1331 const buzz::XmlElement* RtcpMuxFromContent(buzz::XmlElement* content) {
1332 return content->FirstNamed(cricket::QN_JINGLE_RTCP_MUX);
1336 rtc::scoped_ptr<buzz::XmlElement> action_;
1339 class GingleSessionTestParser : public MediaSessionTestParser {
1341 GingleSessionTestParser() : found_content_count_(0) {}
1343 buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
1344 return stanza->FirstNamed(cricket::QN_GINGLE_SESSION);
1347 buzz::XmlElement* ContentFromAction(buzz::XmlElement* session) {
1348 buzz::XmlElement* content =
1349 session->FirstNamed(cricket::QN_GINGLE_AUDIO_CONTENT);
1350 if (content == NULL)
1351 content = session->FirstNamed(cricket::QN_GINGLE_VIDEO_CONTENT);
1355 // Assumes contents are in order of audio, and then video.
1356 buzz::XmlElement* NextContent(buzz::XmlElement* content) {
1357 found_content_count_++;
1361 buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* content) {
1362 if (found_content_count_ > 0) {
1363 return content->FirstNamed(cricket::QN_GINGLE_VIDEO_PAYLOADTYPE);
1365 return content->FirstNamed(cricket::QN_GINGLE_AUDIO_PAYLOADTYPE);
1369 buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
1370 if (found_content_count_ > 0) {
1371 return payload_type->NextNamed(cricket::QN_GINGLE_VIDEO_PAYLOADTYPE);
1373 return payload_type->NextNamed(cricket::QN_GINGLE_AUDIO_PAYLOADTYPE);
1377 cricket::AudioCodec AudioCodecFromPayloadType(
1378 const buzz::XmlElement* payload_type) {
1380 if (payload_type->HasAttr(cricket::QN_ID))
1381 id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1384 if (payload_type->HasAttr(cricket::QN_NAME))
1385 name = payload_type->Attr(cricket::QN_NAME);
1388 if (payload_type->HasAttr(cricket::QN_CLOCKRATE))
1389 clockrate = atoi(payload_type->Attr(cricket::QN_CLOCKRATE).c_str());
1392 if (payload_type->HasAttr(cricket::QN_BITRATE))
1393 bitrate = atoi(payload_type->Attr(cricket::QN_BITRATE).c_str());
1396 if (payload_type->HasAttr(cricket::QN_CHANNELS))
1397 channels = atoi(payload_type->Attr(cricket::QN_CHANNELS).c_str());
1399 return cricket::AudioCodec(id, name, clockrate, bitrate, channels, 0);
1402 cricket::VideoCodec VideoCodecFromPayloadType(
1403 const buzz::XmlElement* payload_type) {
1405 if (payload_type->HasAttr(cricket::QN_ID))
1406 id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1409 if (payload_type->HasAttr(cricket::QN_NAME))
1410 name = payload_type->Attr(cricket::QN_NAME);
1413 if (payload_type->HasAttr(cricket::QN_WIDTH))
1414 width = atoi(payload_type->Attr(cricket::QN_WIDTH).c_str());
1417 if (payload_type->HasAttr(cricket::QN_HEIGHT))
1418 height = atoi(payload_type->Attr(cricket::QN_HEIGHT).c_str());
1421 if (payload_type->HasAttr(cricket::QN_FRAMERATE))
1422 framerate = atoi(payload_type->Attr(cricket::QN_FRAMERATE).c_str());
1424 return cricket::VideoCodec(id, name, width, height, framerate, 0);
1427 cricket::DataCodec DataCodecFromPayloadType(
1428 const buzz::XmlElement* payload_type) {
1429 // Gingle can't do data codecs.
1430 return cricket::DataCodec(0, "", 0);
1433 buzz::XmlElement* EncryptionFromContent(
1434 buzz::XmlElement* content) {
1435 return content->FirstNamed(cricket::QN_ENCRYPTION);
1438 buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
1439 return encryption->NextNamed(cricket::QN_ENCRYPTION);
1442 const buzz::XmlElement* BandwidthFromContent(buzz::XmlElement* content) {
1443 return content->FirstNamed(cricket::QN_GINGLE_VIDEO_BANDWIDTH);
1446 const buzz::XmlElement* RtcpMuxFromContent(buzz::XmlElement* content) {
1450 bool ActionIsTerminate(const buzz::XmlElement* session) {
1451 return (session->HasAttr(buzz::QN_TYPE) &&
1452 session->Attr(buzz::QN_TYPE) == "terminate");
1455 int found_content_count_;
1458 class MediaSessionClientTest : public sigslot::has_slots<> {
1460 explicit MediaSessionClientTest(MediaSessionTestParser* parser,
1461 cricket::SignalingProtocol initial_protocol) {
1462 nm_ = new rtc::BasicNetworkManager();
1463 pa_ = new cricket::BasicPortAllocator(nm_);
1464 sm_ = new cricket::SessionManager(pa_, NULL);
1465 fme_ = new cricket::FakeMediaEngine();
1466 fdme_ = new cricket::FakeDataEngine();
1468 FeedbackParams params_nack_fir;
1469 params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamCcm,
1470 cricket::kRtcpFbCcmParamFir));
1471 params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamNack));
1472 FeedbackParams params_nack;
1473 params_nack.Add(FeedbackParam(cricket::kRtcpFbParamNack));
1475 std::vector<cricket::AudioCodec>
1476 audio_codecs(kAudioCodecs, kAudioCodecs + ARRAY_SIZE(kAudioCodecs));
1477 SetCodecFeedbackParams(&audio_codecs, params_nack);
1478 fme_->SetAudioCodecs(audio_codecs);
1479 std::vector<cricket::VideoCodec>
1480 video_codecs(kVideoCodecs, kVideoCodecs + ARRAY_SIZE(kVideoCodecs));
1481 SetCodecFeedbackParams(&video_codecs, params_nack_fir);
1482 fme_->SetVideoCodecs(video_codecs);
1483 std::vector<cricket::DataCodec>
1484 data_codecs(kDataCodecs, kDataCodecs + ARRAY_SIZE(kDataCodecs));
1485 SetCodecFeedbackParams(&data_codecs, params_nack);
1486 fdme_->SetDataCodecs(data_codecs);
1488 client_ = new cricket::MediaSessionClient(
1489 buzz::Jid("user@domain.com/resource"), sm_,
1490 fme_, fdme_, new cricket::FakeDeviceManager());
1491 client_->session_manager()->SignalOutgoingMessage.connect(
1492 this, &MediaSessionClientTest::OnSendStanza);
1493 client_->session_manager()->SignalSessionCreate.connect(
1494 this, &MediaSessionClientTest::OnSessionCreate);
1495 client_->SignalCallCreate.connect(
1496 this, &MediaSessionClientTest::OnCallCreate);
1497 client_->SignalCallDestroy.connect(
1498 this, &MediaSessionClientTest::OnCallDestroy);
1502 initial_protocol_ = initial_protocol;
1503 expect_incoming_crypto_ = false;
1504 expect_outgoing_crypto_ = false;
1505 expected_video_bandwidth_ = cricket::kAutoBandwidth;
1506 expected_video_rtcp_mux_ = false;
1509 ~MediaSessionClientTest() {
1518 buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
1519 return parser_->ActionFromStanza(stanza);
1522 buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) {
1523 return parser_->ContentFromAction(action);
1526 buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* payload) {
1527 return parser_->PayloadTypeFromContent(payload);
1530 buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
1531 return parser_->NextFromPayloadType(payload_type);
1534 buzz::XmlElement* EncryptionFromContent(buzz::XmlElement* content) {
1535 return parser_->EncryptionFromContent(content);
1538 buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
1539 return parser_->NextFromEncryption(encryption);
1542 cricket::AudioCodec AudioCodecFromPayloadType(
1543 const buzz::XmlElement* payload_type) {
1544 return parser_->AudioCodecFromPayloadType(payload_type);
1547 cricket::VideoCodec VideoCodecFromPayloadType(
1548 const buzz::XmlElement* payload_type) {
1549 return parser_->VideoCodecFromPayloadType(payload_type);
1552 cricket::DataCodec DataCodecFromPayloadType(
1553 const buzz::XmlElement* payload_type) {
1554 return parser_->DataCodecFromPayloadType(payload_type);
1557 const AudioContentDescription* GetFirstAudioContentDescription(
1558 const cricket::SessionDescription* sdesc) {
1559 const cricket::ContentInfo* content =
1560 cricket::GetFirstAudioContent(sdesc);
1561 if (content == NULL)
1563 return static_cast<const AudioContentDescription*>(content->description);
1566 const cricket::VideoContentDescription* GetFirstVideoContentDescription(
1567 const cricket::SessionDescription* sdesc) {
1568 const cricket::ContentInfo* content =
1569 cricket::GetFirstVideoContent(sdesc);
1570 if (content == NULL)
1572 return static_cast<const cricket::VideoContentDescription*>(
1573 content->description);
1576 void CheckCryptoFromGoodIncomingInitiate(const cricket::Session* session) {
1577 ASSERT_TRUE(session != NULL);
1578 const AudioContentDescription* content =
1579 GetFirstAudioContentDescription(session->remote_description());
1580 ASSERT_TRUE(content != NULL);
1581 ASSERT_EQ(2U, content->cryptos().size());
1582 ASSERT_EQ(145, content->cryptos()[0].tag);
1583 ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", content->cryptos()[0].cipher_suite);
1584 ASSERT_EQ("inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9",
1585 content->cryptos()[0].key_params);
1586 ASSERT_EQ(51, content->cryptos()[1].tag);
1587 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", content->cryptos()[1].cipher_suite);
1588 ASSERT_EQ("inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy",
1589 content->cryptos()[1].key_params);
1592 void CheckCryptoForGoodOutgoingAccept(const cricket::Session* session) {
1593 const AudioContentDescription* content =
1594 GetFirstAudioContentDescription(session->local_description());
1595 ASSERT_EQ(1U, content->cryptos().size());
1596 ASSERT_EQ(145, content->cryptos()[0].tag);
1597 ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", content->cryptos()[0].cipher_suite);
1598 ASSERT_EQ(47U, content->cryptos()[0].key_params.size());
1601 void CheckBadCryptoFromIncomingInitiate(const cricket::Session* session) {
1602 const AudioContentDescription* content =
1603 GetFirstAudioContentDescription(session->remote_description());
1604 ASSERT_EQ(1U, content->cryptos().size());
1605 ASSERT_EQ(145, content->cryptos()[0].tag);
1606 ASSERT_EQ("NOT_SUPPORTED", content->cryptos()[0].cipher_suite);
1607 ASSERT_EQ("inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9",
1608 content->cryptos()[0].key_params);
1611 void CheckNoCryptoForOutgoingAccept(const cricket::Session* session) {
1612 const AudioContentDescription* content =
1613 GetFirstAudioContentDescription(session->local_description());
1614 ASSERT_TRUE(content->cryptos().empty());
1617 void CheckRtcpFb(const cricket::SessionDescription* sdesc) {
1618 VerifyCodecFbParams<AudioCodec>(expected_audio_fb_params_,
1619 GetFirstAudioContentDescription(sdesc));
1621 VerifyCodecFbParams<VideoCodec>(expected_video_fb_params_,
1622 GetFirstVideoContentDescription(sdesc));
1624 VerifyCodecFbParams<DataCodec>(expected_data_fb_params_,
1625 GetFirstDataContentDescription(sdesc));
1628 void CheckVideoBandwidth(int expected_bandwidth,
1629 const cricket::SessionDescription* sdesc) {
1630 const cricket::VideoContentDescription* video =
1631 GetFirstVideoContentDescription(sdesc);
1632 if (video != NULL) {
1633 ASSERT_EQ(expected_bandwidth, video->bandwidth());
1637 void CheckVideoRtcpMux(bool expected_video_rtcp_mux,
1638 const cricket::SessionDescription* sdesc) {
1639 const cricket::VideoContentDescription* video =
1640 GetFirstVideoContentDescription(sdesc);
1641 if (video != NULL) {
1642 ASSERT_EQ(expected_video_rtcp_mux, video->rtcp_mux());
1646 virtual void CheckRtpDataContent(buzz::XmlElement* content) {
1647 if (initial_protocol_) {
1648 // Gingle can not write out data content.
1652 buzz::XmlElement* e = PayloadTypeFromContent(content);
1653 ASSERT_TRUE(e != NULL);
1654 cricket::DataCodec codec = DataCodecFromPayloadType(e);
1655 EXPECT_EQ(127, codec.id);
1656 EXPECT_EQ("google-data", codec.name);
1657 EXPECT_EQ(expected_data_fb_params_, codec.feedback_params);
1659 CheckDataRtcpMux(true, call_->sessions()[0]->local_description());
1660 CheckDataRtcpMux(true, call_->sessions()[0]->remote_description());
1661 if (expect_outgoing_crypto_) {
1662 content = parser_->NextContent(content);
1663 buzz::XmlElement* encryption = EncryptionFromContent(content);
1664 ASSERT_TRUE(encryption != NULL);
1665 // TODO(pthatcher): Check encryption parameters?
1669 virtual void CheckSctpDataContent(buzz::XmlElement* content) {
1670 if (initial_protocol_) {
1671 // Gingle can not write out data content.
1675 buzz::XmlElement* payload_type = PayloadTypeFromContent(content);
1676 ASSERT_TRUE(payload_type == NULL);
1677 buzz::XmlElement* encryption = EncryptionFromContent(content);
1678 ASSERT_TRUE(encryption == NULL);
1679 // TODO(pthatcher): Check for <streams>.
1682 void CheckDataRtcpMux(bool expected_data_rtcp_mux,
1683 const cricket::SessionDescription* sdesc) {
1684 const cricket::DataContentDescription* data =
1685 GetFirstDataContentDescription(sdesc);
1687 ASSERT_EQ(expected_data_rtcp_mux, data->rtcp_mux());
1691 void CheckAudioSsrcForIncomingAccept(const cricket::Session* session) {
1692 const AudioContentDescription* audio =
1693 GetFirstAudioContentDescription(session->remote_description());
1694 ASSERT_TRUE(audio != NULL);
1695 ASSERT_EQ(kAudioSsrc, audio->first_ssrc());
1698 void CheckVideoSsrcForIncomingAccept(const cricket::Session* session) {
1699 const cricket::VideoContentDescription* video =
1700 GetFirstVideoContentDescription(session->remote_description());
1701 ASSERT_TRUE(video != NULL);
1702 ASSERT_EQ(kVideoSsrc, video->first_ssrc());
1705 void CheckDataSsrcForIncomingAccept(const cricket::Session* session) {
1706 const cricket::DataContentDescription* data =
1707 GetFirstDataContentDescription(session->remote_description());
1708 ASSERT_TRUE(data != NULL);
1709 ASSERT_EQ(kDataSsrc, data->first_ssrc());
1712 void TestGoodIncomingInitiate(const std::string& initiate_string,
1713 const cricket::CallOptions& options,
1714 buzz::XmlElement** element) {
1717 rtc::scoped_ptr<buzz::XmlElement> el(
1718 buzz::XmlElement::ForStr(initiate_string));
1719 client_->session_manager()->OnIncomingMessage(el.get());
1720 ASSERT_TRUE(call_ != NULL);
1721 ASSERT_TRUE(call_->sessions()[0] != NULL);
1722 ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE,
1723 call_->sessions()[0]->state());
1724 ASSERT_EQ(1U, stanzas_.size());
1725 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1726 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1727 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
1729 CheckVideoBandwidth(expected_video_bandwidth_,
1730 call_->sessions()[0]->remote_description());
1731 CheckVideoRtcpMux(expected_video_rtcp_mux_,
1732 call_->sessions()[0]->remote_description());
1733 CheckRtcpFb(call_->sessions()[0]->remote_description());
1734 if (expect_incoming_crypto_) {
1735 CheckCryptoFromGoodIncomingInitiate(call_->sessions()[0]);
1738 // TODO(pthatcher): Add tests for sending <bandwidth> in accept.
1739 call_->AcceptSession(call_->sessions()[0], options);
1740 ASSERT_EQ(cricket::Session::STATE_SENTACCEPT,
1741 call_->sessions()[0]->state());
1742 ASSERT_EQ(1U, stanzas_.size());
1743 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1744 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1745 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1747 buzz::XmlElement* e = ActionFromStanza(stanzas_[0]);
1748 ASSERT_TRUE(e != NULL);
1749 ASSERT_TRUE(ContentFromAction(e) != NULL);
1750 *element = CopyElement(ContentFromAction(e));
1751 ASSERT_TRUE(*element != NULL);
1753 if (expect_outgoing_crypto_) {
1754 CheckCryptoForGoodOutgoingAccept(call_->sessions()[0]);
1757 if (options.data_channel_type == cricket::DCT_RTP) {
1758 CheckDataRtcpMux(true, call_->sessions()[0]->local_description());
1759 CheckDataRtcpMux(true, call_->sessions()[0]->remote_description());
1760 // TODO(pthatcher): Check rtcpmux and crypto?
1764 ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE,
1765 call_->sessions()[0]->state());
1766 ASSERT_EQ(1U, stanzas_.size());
1767 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1768 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1769 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1770 e = ActionFromStanza(stanzas_[0]);
1771 ASSERT_TRUE(e != NULL);
1772 ASSERT_TRUE(parser_->ActionIsTerminate(e));
1776 void TestRejectOffer(const std::string &initiate_string,
1777 const cricket::CallOptions& options,
1778 buzz::XmlElement** element) {
1781 rtc::scoped_ptr<buzz::XmlElement> el(
1782 buzz::XmlElement::ForStr(initiate_string));
1783 client_->session_manager()->OnIncomingMessage(el.get());
1784 ASSERT_TRUE(call_ != NULL);
1785 ASSERT_TRUE(call_->sessions()[0] != NULL);
1786 ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE,
1787 call_->sessions()[0]->state());
1788 ASSERT_EQ(1U, stanzas_.size());
1789 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1790 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1791 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
1794 call_->AcceptSession(call_->sessions()[0], options);
1795 ASSERT_EQ(cricket::Session::STATE_SENTACCEPT,
1796 call_->sessions()[0]->state());
1797 ASSERT_EQ(1U, stanzas_.size());
1798 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1799 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1800 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1802 buzz::XmlElement* e = ActionFromStanza(stanzas_[0]);
1803 ASSERT_TRUE(e != NULL);
1804 ASSERT_TRUE(ContentFromAction(e) != NULL);
1805 *element = CopyElement(ContentFromAction(e));
1806 ASSERT_TRUE(*element != NULL);
1809 buzz::XmlElement* content = *element;
1810 // The NextContent method actually returns the second content. So we
1811 // can't handle the case when audio, video and data are all enabled. But
1812 // since we are testing rejection, it won't be the case.
1813 if (options.has_audio) {
1814 ASSERT_TRUE(content != NULL);
1815 ASSERT_EQ("test audio", content->Attr(buzz::QName("", "name")));
1816 content = parser_->NextContent(content);
1819 if (options.has_video) {
1820 ASSERT_TRUE(content != NULL);
1821 ASSERT_EQ("test video", content->Attr(buzz::QName("", "name")));
1822 content = parser_->NextContent(content);
1825 if (options.has_data()) {
1826 ASSERT_TRUE(content != NULL);
1827 ASSERT_EQ("test data", content->Attr(buzz::QName("", "name")));
1828 content = parser_->NextContent(content);
1832 ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE,
1833 call_->sessions()[0]->state());
1834 ASSERT_EQ(1U, stanzas_.size());
1835 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1836 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1837 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1838 e = ActionFromStanza(stanzas_[0]);
1839 ASSERT_TRUE(e != NULL);
1840 ASSERT_TRUE(parser_->ActionIsTerminate(e));
1844 void TestBadIncomingInitiate(const std::string& initiate_string) {
1845 rtc::scoped_ptr<buzz::XmlElement> el(
1846 buzz::XmlElement::ForStr(initiate_string));
1847 client_->session_manager()->OnIncomingMessage(el.get());
1848 ASSERT_TRUE(call_ != NULL);
1849 ASSERT_TRUE(call_->sessions()[0] != NULL);
1850 ASSERT_EQ(cricket::Session::STATE_SENTREJECT,
1851 call_->sessions()[0]->state());
1852 ASSERT_EQ(2U, stanzas_.size());
1853 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1854 ASSERT_TRUE(stanzas_[1]->HasAttr(buzz::QN_TYPE));
1855 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[1]->Attr(buzz::QN_TYPE));
1859 void VerifyAudioCodec(const AudioCodec& codec, int id,
1860 const std::string& name, int clockrate,
1861 int bitrate, int channels) {
1862 ASSERT_EQ(id, codec.id);
1863 ASSERT_EQ(name, codec.name);
1864 ASSERT_EQ(clockrate, codec.clockrate);
1865 ASSERT_EQ(bitrate, codec.bitrate);
1866 ASSERT_EQ(channels, codec.channels);
1867 ASSERT_EQ(expected_audio_fb_params_, codec.feedback_params);
1870 void TestGoodOutgoingInitiate(const cricket::CallOptions& options) {
1871 if (initial_protocol_ == cricket::PROTOCOL_JINGLE) {
1872 // rtcp fb is only implemented for jingle.
1876 client_->CreateCall();
1877 ASSERT_TRUE(call_ != NULL);
1878 call_->InitiateSession(buzz::Jid("me@mydomain.com"),
1879 buzz::Jid("me@mydomain.com"), options);
1880 ASSERT_TRUE(call_->sessions()[0] != NULL);
1881 ASSERT_EQ(cricket::Session::STATE_SENTINITIATE,
1882 call_->sessions()[0]->state());
1883 ASSERT_EQ(1U, stanzas_.size());
1884 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1885 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1886 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1887 buzz::XmlElement* action = ActionFromStanza(stanzas_[0]);
1888 ASSERT_TRUE(action != NULL);
1889 buzz::XmlElement* content = ContentFromAction(action);
1890 ASSERT_TRUE(content != NULL);
1892 buzz::XmlElement* e = PayloadTypeFromContent(content);
1893 ASSERT_TRUE(e != NULL);
1894 cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
1895 VerifyAudioCodec(codec, 103, "ISAC", 16000, 0, 1);
1897 e = NextFromPayloadType(e);
1898 ASSERT_TRUE(e != NULL);
1899 codec = AudioCodecFromPayloadType(e);
1900 VerifyAudioCodec(codec, 104, "ISAC", 32000, 0, 1);
1902 e = NextFromPayloadType(e);
1903 ASSERT_TRUE(e != NULL);
1904 codec = AudioCodecFromPayloadType(e);
1905 VerifyAudioCodec(codec, 119, "ISACLC", 16000, 40000, 1);
1907 e = NextFromPayloadType(e);
1908 ASSERT_TRUE(e != NULL);
1909 codec = AudioCodecFromPayloadType(e);
1910 VerifyAudioCodec(codec, 99, "speex", 16000, 22000, 1);
1912 e = NextFromPayloadType(e);
1913 ASSERT_TRUE(e != NULL);
1914 codec = AudioCodecFromPayloadType(e);
1915 VerifyAudioCodec(codec, 97, "IPCMWB", 16000, 80000, 1);
1917 e = NextFromPayloadType(e);
1918 ASSERT_TRUE(e != NULL);
1919 codec = AudioCodecFromPayloadType(e);
1920 VerifyAudioCodec(codec, 9, "G722", 16000, 64000, 1);
1922 e = NextFromPayloadType(e);
1923 ASSERT_TRUE(e != NULL);
1924 codec = AudioCodecFromPayloadType(e);
1925 VerifyAudioCodec(codec, 102, "iLBC", 8000, 13300, 1);
1927 e = NextFromPayloadType(e);
1928 ASSERT_TRUE(e != NULL);
1929 codec = AudioCodecFromPayloadType(e);
1930 VerifyAudioCodec(codec, 98, "speex", 8000, 11000, 1);
1932 e = NextFromPayloadType(e);
1933 ASSERT_TRUE(e != NULL);
1934 codec = AudioCodecFromPayloadType(e);
1935 VerifyAudioCodec(codec, 3, "GSM", 8000, 13000, 1);
1937 e = NextFromPayloadType(e);
1938 ASSERT_TRUE(e != NULL);
1939 codec = AudioCodecFromPayloadType(e);
1940 VerifyAudioCodec(codec, 100, "EG711U", 8000, 64000, 1);
1942 e = NextFromPayloadType(e);
1943 ASSERT_TRUE(e != NULL);
1944 codec = AudioCodecFromPayloadType(e);
1945 VerifyAudioCodec(codec, 101, "EG711A", 8000, 64000, 1);
1947 e = NextFromPayloadType(e);
1948 ASSERT_TRUE(e != NULL);
1949 codec = AudioCodecFromPayloadType(e);
1950 VerifyAudioCodec(codec, 0, "PCMU", 8000, 64000, 1);
1952 e = NextFromPayloadType(e);
1953 ASSERT_TRUE(e != NULL);
1954 codec = AudioCodecFromPayloadType(e);
1955 VerifyAudioCodec(codec, 8, "PCMA", 8000, 64000, 1);
1957 e = NextFromPayloadType(e);
1958 ASSERT_TRUE(e != NULL);
1959 codec = AudioCodecFromPayloadType(e);
1960 VerifyAudioCodec(codec, 126, "CN", 32000, 0, 1);
1962 e = NextFromPayloadType(e);
1963 ASSERT_TRUE(e != NULL);
1964 codec = AudioCodecFromPayloadType(e);
1965 VerifyAudioCodec(codec, 105, "CN", 16000, 0, 1);
1967 e = NextFromPayloadType(e);
1968 ASSERT_TRUE(e != NULL);
1969 codec = AudioCodecFromPayloadType(e);
1970 VerifyAudioCodec(codec, 13, "CN", 8000, 0, 1);
1972 e = NextFromPayloadType(e);
1973 ASSERT_TRUE(e != NULL);
1974 codec = AudioCodecFromPayloadType(e);
1975 VerifyAudioCodec(codec, 117, "red", 8000, 0, 1);
1977 e = NextFromPayloadType(e);
1978 ASSERT_TRUE(e != NULL);
1979 codec = AudioCodecFromPayloadType(e);
1980 VerifyAudioCodec(codec, 106, "telephone-event", 8000, 0, 1);
1982 e = NextFromPayloadType(e);
1983 ASSERT_TRUE(e == NULL);
1985 if (expect_outgoing_crypto_) {
1986 buzz::XmlElement* encryption = EncryptionFromContent(content);
1987 ASSERT_TRUE(encryption != NULL);
1989 if (client_->secure() == cricket::SEC_REQUIRED) {
1990 ASSERT_TRUE(cricket::GetXmlAttr(
1991 encryption, cricket::QN_ENCRYPTION_REQUIRED, false));
1994 if (content->Name().Namespace() == cricket::NS_GINGLE_AUDIO) {
1995 e = encryption->FirstNamed(cricket::QN_GINGLE_AUDIO_CRYPTO_USAGE);
1996 ASSERT_TRUE(e != NULL);
1998 e->NextNamed(cricket::QN_GINGLE_AUDIO_CRYPTO_USAGE) == NULL);
2000 e->FirstNamed(cricket::QN_GINGLE_VIDEO_CRYPTO_USAGE) == NULL);
2003 e = encryption->FirstNamed(cricket::QN_CRYPTO);
2004 ASSERT_TRUE(e != NULL);
2005 ASSERT_EQ("0", e->Attr(cricket::QN_CRYPTO_TAG));
2006 ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", e->Attr(cricket::QN_CRYPTO_SUITE));
2007 std::string key_0 = e->Attr(cricket::QN_CRYPTO_KEY_PARAMS);
2008 ASSERT_EQ(47U, key_0.length());
2009 ASSERT_EQ("inline:", key_0.substr(0, 7));
2011 e = e->NextNamed(cricket::QN_CRYPTO);
2012 ASSERT_TRUE(e != NULL);
2013 ASSERT_EQ("1", e->Attr(cricket::QN_CRYPTO_TAG));
2014 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", e->Attr(cricket::QN_CRYPTO_SUITE));
2015 std::string key_1 = e->Attr(cricket::QN_CRYPTO_KEY_PARAMS);
2016 ASSERT_EQ(47U, key_1.length());
2017 ASSERT_EQ("inline:", key_1.substr(0, 7));
2018 ASSERT_NE(key_0, key_1);
2020 encryption = NextFromEncryption(encryption);
2021 ASSERT_TRUE(encryption == NULL);
2024 if (options.has_video) {
2025 CheckVideoBandwidth(options.video_bandwidth,
2026 call_->sessions()[0]->local_description());
2027 CheckVideoRtcpMux(expected_video_rtcp_mux_,
2028 call_->sessions()[0]->remote_description());
2029 content = parser_->NextContent(content);
2030 const buzz::XmlElement* bandwidth =
2031 parser_->BandwidthFromContent(content);
2032 if (options.video_bandwidth == cricket::kAutoBandwidth) {
2033 ASSERT_TRUE(bandwidth == NULL);
2035 ASSERT_TRUE(bandwidth != NULL);
2036 ASSERT_EQ("AS", bandwidth->Attr(buzz::QName("", "type")));
2037 ASSERT_EQ(rtc::ToString(options.video_bandwidth / 1000),
2038 bandwidth->BodyText());
2041 buzz::XmlElement* e = PayloadTypeFromContent(content);
2042 ASSERT_TRUE(e != NULL);
2043 VideoCodec codec = VideoCodecFromPayloadType(e);
2044 VideoCodec expected_codec = kVideoCodecs[0];
2045 expected_codec.preference = codec.preference;
2046 expected_codec.feedback_params = expected_video_fb_params_;
2047 EXPECT_EQ(expected_codec, codec);
2050 if (options.data_channel_type == cricket::DCT_RTP) {
2051 content = parser_->NextContent(content);
2052 CheckRtpDataContent(content);
2055 if (options.data_channel_type == cricket::DCT_SCTP) {
2056 content = parser_->NextContent(content);
2057 CheckSctpDataContent(content);
2063 void TestHasAllSupportedAudioCodecs(buzz::XmlElement* e) {
2064 ASSERT_TRUE(e != NULL);
2066 e = PayloadTypeFromContent(e);
2067 ASSERT_TRUE(e != NULL);
2068 cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2069 ASSERT_EQ(103, codec.id);
2070 ASSERT_EQ("ISAC", codec.name);
2071 ASSERT_EQ(16000, codec.clockrate);
2072 ASSERT_EQ(1, codec.channels);
2074 e = NextFromPayloadType(e);
2075 ASSERT_TRUE(e != NULL);
2076 codec = AudioCodecFromPayloadType(e);
2077 ASSERT_EQ(104, codec.id);
2078 ASSERT_EQ("ISAC", codec.name);
2079 ASSERT_EQ(32000, codec.clockrate);
2080 ASSERT_EQ(1, codec.channels);
2082 e = NextFromPayloadType(e);
2083 ASSERT_TRUE(e != NULL);
2084 codec = AudioCodecFromPayloadType(e);
2085 ASSERT_EQ(119, codec.id);
2086 ASSERT_EQ("ISACLC", codec.name);
2087 ASSERT_EQ(16000, codec.clockrate);
2088 ASSERT_EQ(40000, codec.bitrate);
2089 ASSERT_EQ(1, codec.channels);
2091 e = NextFromPayloadType(e);
2092 ASSERT_TRUE(e != NULL);
2093 codec = AudioCodecFromPayloadType(e);
2094 ASSERT_EQ(99, codec.id);
2095 ASSERT_EQ("speex", codec.name);
2096 ASSERT_EQ(16000, codec.clockrate);
2097 ASSERT_EQ(22000, codec.bitrate);
2098 ASSERT_EQ(1, codec.channels);
2100 e = NextFromPayloadType(e);
2101 ASSERT_TRUE(e != NULL);
2102 codec = AudioCodecFromPayloadType(e);
2103 ASSERT_EQ(97, codec.id);
2104 ASSERT_EQ("IPCMWB", codec.name);
2105 ASSERT_EQ(16000, codec.clockrate);
2106 ASSERT_EQ(80000, codec.bitrate);
2107 ASSERT_EQ(1, codec.channels);
2109 e = NextFromPayloadType(e);
2110 ASSERT_TRUE(e != NULL);
2111 codec = AudioCodecFromPayloadType(e);
2112 ASSERT_EQ(9, codec.id);
2113 ASSERT_EQ("G722", codec.name);
2114 ASSERT_EQ(16000, codec.clockrate);
2115 ASSERT_EQ(64000, codec.bitrate);
2116 ASSERT_EQ(1, codec.channels);
2118 e = NextFromPayloadType(e);
2119 ASSERT_TRUE(e != NULL);
2120 codec = AudioCodecFromPayloadType(e);
2121 ASSERT_EQ(102, codec.id);
2122 ASSERT_EQ("iLBC", codec.name);
2123 ASSERT_EQ(8000, codec.clockrate);
2124 ASSERT_EQ(13300, codec.bitrate);
2125 ASSERT_EQ(1, codec.channels);
2127 e = NextFromPayloadType(e);
2128 ASSERT_TRUE(e != NULL);
2129 codec = AudioCodecFromPayloadType(e);
2130 ASSERT_EQ(98, codec.id);
2131 ASSERT_EQ("speex", codec.name);
2132 ASSERT_EQ(8000, codec.clockrate);
2133 ASSERT_EQ(11000, codec.bitrate);
2134 ASSERT_EQ(1, codec.channels);
2136 e = NextFromPayloadType(e);
2137 ASSERT_TRUE(e != NULL);
2138 codec = AudioCodecFromPayloadType(e);
2139 ASSERT_EQ(3, codec.id);
2140 ASSERT_EQ("GSM", codec.name);
2141 ASSERT_EQ(8000, codec.clockrate);
2142 ASSERT_EQ(13000, codec.bitrate);
2143 ASSERT_EQ(1, codec.channels);
2145 e = NextFromPayloadType(e);
2146 ASSERT_TRUE(e != NULL);
2147 codec = AudioCodecFromPayloadType(e);
2148 ASSERT_EQ(100, codec.id);
2149 ASSERT_EQ("EG711U", codec.name);
2150 ASSERT_EQ(8000, codec.clockrate);
2151 ASSERT_EQ(64000, codec.bitrate);
2152 ASSERT_EQ(1, codec.channels);
2154 e = NextFromPayloadType(e);
2155 ASSERT_TRUE(e != NULL);
2156 codec = AudioCodecFromPayloadType(e);
2157 ASSERT_EQ(101, codec.id);
2158 ASSERT_EQ("EG711A", codec.name);
2159 ASSERT_EQ(8000, codec.clockrate);
2160 ASSERT_EQ(64000, codec.bitrate);
2161 ASSERT_EQ(1, codec.channels);
2163 e = NextFromPayloadType(e);
2164 ASSERT_TRUE(e != NULL);
2165 codec = AudioCodecFromPayloadType(e);
2166 ASSERT_EQ(0, codec.id);
2167 ASSERT_EQ("PCMU", codec.name);
2168 ASSERT_EQ(8000, codec.clockrate);
2169 ASSERT_EQ(64000, codec.bitrate);
2170 ASSERT_EQ(1, codec.channels);
2172 e = NextFromPayloadType(e);
2173 ASSERT_TRUE(e != NULL);
2174 codec = AudioCodecFromPayloadType(e);
2175 ASSERT_EQ(8, codec.id);
2176 ASSERT_EQ("PCMA", codec.name);
2177 ASSERT_EQ(8000, codec.clockrate);
2178 ASSERT_EQ(64000, codec.bitrate);
2179 ASSERT_EQ(1, codec.channels);
2181 e = NextFromPayloadType(e);
2182 ASSERT_TRUE(e != NULL);
2183 codec = AudioCodecFromPayloadType(e);
2184 ASSERT_EQ(126, codec.id);
2185 ASSERT_EQ("CN", codec.name);
2186 ASSERT_EQ(32000, codec.clockrate);
2187 ASSERT_EQ(1, codec.channels);
2189 e = NextFromPayloadType(e);
2190 ASSERT_TRUE(e != NULL);
2191 codec = AudioCodecFromPayloadType(e);
2192 ASSERT_EQ(105, codec.id);
2193 ASSERT_EQ("CN", codec.name);
2194 ASSERT_EQ(16000, codec.clockrate);
2195 ASSERT_EQ(1, codec.channels);
2197 e = NextFromPayloadType(e);
2198 ASSERT_TRUE(e != NULL);
2199 codec = AudioCodecFromPayloadType(e);
2200 ASSERT_EQ(13, codec.id);
2201 ASSERT_EQ("CN", codec.name);
2202 ASSERT_EQ(8000, codec.clockrate);
2203 ASSERT_EQ(1, codec.channels);
2205 e = NextFromPayloadType(e);
2206 ASSERT_TRUE(e != NULL);
2207 codec = AudioCodecFromPayloadType(e);
2208 ASSERT_EQ(117, codec.id);
2209 ASSERT_EQ("red", codec.name);
2210 ASSERT_EQ(8000, codec.clockrate);
2211 ASSERT_EQ(1, codec.channels);
2213 e = NextFromPayloadType(e);
2214 ASSERT_TRUE(e != NULL);
2215 codec = AudioCodecFromPayloadType(e);
2216 ASSERT_EQ(106, codec.id);
2217 ASSERT_EQ("telephone-event", codec.name);
2218 ASSERT_EQ(8000, codec.clockrate);
2219 ASSERT_EQ(1, codec.channels);
2221 e = NextFromPayloadType(e);
2222 ASSERT_TRUE(e == NULL);
2225 void TestCodecsOfVideoInitiate(buzz::XmlElement* content) {
2226 ASSERT_TRUE(content != NULL);
2227 buzz::XmlElement* payload_type = PayloadTypeFromContent(content);
2228 ASSERT_TRUE(payload_type != NULL);
2229 cricket::AudioCodec codec = AudioCodecFromPayloadType(payload_type);
2230 ASSERT_EQ(103, codec.id);
2231 ASSERT_EQ("ISAC", codec.name);
2232 ASSERT_EQ(16000, codec.clockrate);
2233 ASSERT_EQ(1, codec.channels);
2235 content = parser_->NextContent(content);
2236 ASSERT_TRUE(content != NULL);
2237 payload_type = PayloadTypeFromContent(content);
2238 ASSERT_TRUE(payload_type != NULL);
2239 cricket::VideoCodec vcodec =
2240 parser_->VideoCodecFromPayloadType(payload_type);
2241 ASSERT_EQ(99, vcodec.id);
2242 ASSERT_EQ("H264-SVC", vcodec.name);
2243 ASSERT_EQ(320, vcodec.width);
2244 ASSERT_EQ(200, vcodec.height);
2245 ASSERT_EQ(30, vcodec.framerate);
2248 void TestHasAudioCodecsFromInitiateSomeUnsupported(buzz::XmlElement* e) {
2249 ASSERT_TRUE(e != NULL);
2250 e = PayloadTypeFromContent(e);
2251 ASSERT_TRUE(e != NULL);
2253 cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2254 ASSERT_EQ(103, codec.id);
2255 ASSERT_EQ("ISAC", codec.name);
2256 ASSERT_EQ(16000, codec.clockrate);
2257 ASSERT_EQ(1, codec.channels);
2259 e = NextFromPayloadType(e);
2260 ASSERT_TRUE(e != NULL);
2261 codec = AudioCodecFromPayloadType(e);
2262 ASSERT_EQ(100, codec.id);
2263 ASSERT_EQ("EG711U", codec.name);
2265 e = NextFromPayloadType(e);
2266 ASSERT_TRUE(e != NULL);
2267 codec = AudioCodecFromPayloadType(e);
2268 ASSERT_EQ(101, codec.id);
2269 ASSERT_EQ("EG711A", codec.name);
2271 e = NextFromPayloadType(e);
2272 ASSERT_TRUE(e != NULL);
2273 codec = AudioCodecFromPayloadType(e);
2274 ASSERT_EQ(0, codec.id);
2275 ASSERT_EQ("PCMU", codec.name);
2277 e = NextFromPayloadType(e);
2278 ASSERT_TRUE(e != NULL);
2279 codec = AudioCodecFromPayloadType(e);
2280 ASSERT_EQ(13, codec.id);
2281 ASSERT_EQ("CN", codec.name);
2283 e = NextFromPayloadType(e);
2284 ASSERT_TRUE(e == NULL);
2287 void TestHasAudioCodecsFromInitiateDynamicAudioCodecs(
2288 buzz::XmlElement* e) {
2289 ASSERT_TRUE(e != NULL);
2290 e = PayloadTypeFromContent(e);
2291 ASSERT_TRUE(e != NULL);
2293 cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2294 ASSERT_EQ(123, codec.id);
2295 ASSERT_EQ(16000, codec.clockrate);
2296 ASSERT_EQ(1, codec.channels);
2298 e = NextFromPayloadType(e);
2299 ASSERT_TRUE(e == NULL);
2302 void TestHasDefaultAudioCodecs(buzz::XmlElement* e) {
2303 ASSERT_TRUE(e != NULL);
2304 e = PayloadTypeFromContent(e);
2305 ASSERT_TRUE(e != NULL);
2307 cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2308 ASSERT_EQ(103, codec.id);
2309 ASSERT_EQ("ISAC", codec.name);
2311 e = NextFromPayloadType(e);
2312 ASSERT_TRUE(e != NULL);
2313 codec = AudioCodecFromPayloadType(e);
2314 ASSERT_EQ(0, codec.id);
2315 ASSERT_EQ("PCMU", codec.name);
2317 e = NextFromPayloadType(e);
2318 ASSERT_TRUE(e == NULL);
2321 void TestHasAudioCodecsFromInitiateStaticAudioCodecs(
2322 buzz::XmlElement* e) {
2323 ASSERT_TRUE(e != NULL);
2324 e = PayloadTypeFromContent(e);
2325 ASSERT_TRUE(e != NULL);
2327 cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2328 ASSERT_EQ(3, codec.id);
2330 e = NextFromPayloadType(e);
2331 ASSERT_TRUE(e != NULL);
2332 codec = AudioCodecFromPayloadType(e);
2333 ASSERT_EQ(0, codec.id);
2335 e = NextFromPayloadType(e);
2336 ASSERT_TRUE(e != NULL);
2337 codec = AudioCodecFromPayloadType(e);
2338 ASSERT_EQ(8, codec.id);
2340 e = NextFromPayloadType(e);
2341 ASSERT_TRUE(e == NULL);
2344 void TestGingleInitiateWithUnsupportedCrypto(
2345 const std::string &initiate_string,
2346 buzz::XmlElement** element) {
2349 rtc::scoped_ptr<buzz::XmlElement> el(
2350 buzz::XmlElement::ForStr(initiate_string));
2351 client_->session_manager()->OnIncomingMessage(el.get());
2353 ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE,
2354 call_->sessions()[0]->state());
2356 CheckBadCryptoFromIncomingInitiate(call_->sessions()[0]);
2358 call_->AcceptSession(call_->sessions()[0], cricket::CallOptions());
2360 CheckNoCryptoForOutgoingAccept(call_->sessions()[0]);
2363 ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE,
2364 call_->sessions()[0]->state());
2368 void TestIncomingAcceptWithSsrcs(
2369 const std::string& accept_string,
2370 cricket::CallOptions& options) {
2371 client_->CreateCall();
2372 ASSERT_TRUE(call_ != NULL);
2374 call_->InitiateSession(buzz::Jid("me@mydomain.com"),
2375 buzz::Jid("me@mydomain.com"), options);
2376 ASSERT_TRUE(call_->sessions()[0] != NULL);
2377 ASSERT_EQ(cricket::Session::STATE_SENTINITIATE,
2378 call_->sessions()[0]->state());
2379 ASSERT_EQ(1U, stanzas_.size());
2380 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
2381 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
2382 ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
2383 buzz::XmlElement* action = ActionFromStanza(stanzas_[0]);
2384 ASSERT_TRUE(action != NULL);
2385 buzz::XmlElement* content = ContentFromAction(action);
2386 ASSERT_TRUE(content != NULL);
2387 if (initial_protocol_ == cricket::PROTOCOL_JINGLE) {
2388 buzz::XmlElement* content_desc =
2389 content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
2390 ASSERT_TRUE(content_desc != NULL);
2391 ASSERT_EQ("", content_desc->Attr(cricket::QN_SSRC));
2395 // We need to insert the session ID into the session accept message.
2396 rtc::scoped_ptr<buzz::XmlElement> el(
2397 buzz::XmlElement::ForStr(accept_string));
2398 const std::string sid = call_->sessions()[0]->id();
2399 if (initial_protocol_ == cricket::PROTOCOL_JINGLE) {
2400 buzz::XmlElement* jingle = el->FirstNamed(cricket::QN_JINGLE);
2401 jingle->SetAttr(cricket::QN_SID, sid);
2403 buzz::XmlElement* session = el->FirstNamed(cricket::QN_GINGLE_SESSION);
2404 session->SetAttr(cricket::QN_ID, sid);
2407 client_->session_manager()->OnIncomingMessage(el.get());
2409 ASSERT_EQ(cricket::Session::STATE_RECEIVEDACCEPT,
2410 call_->sessions()[0]->state());
2411 ASSERT_EQ(1U, stanzas_.size());
2412 ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
2413 ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
2414 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
2417 CheckAudioSsrcForIncomingAccept(call_->sessions()[0]);
2418 CheckVideoSsrcForIncomingAccept(call_->sessions()[0]);
2419 if (options.data_channel_type == cricket::DCT_RTP) {
2420 CheckDataSsrcForIncomingAccept(call_->sessions()[0]);
2422 // TODO(pthatcher): Check kDataSid if DCT_SCTP.
2423 // const uint32 kDataSid = 0;
2426 size_t ClearStanzas() {
2427 size_t size = stanzas_.size();
2428 for (size_t i = 0; i < size; i++) {
2435 buzz::XmlElement* SetJingleSid(buzz::XmlElement* stanza) {
2436 buzz::XmlElement* jingle =
2437 stanza->FirstNamed(cricket::QN_JINGLE);
2438 jingle->SetAttr(cricket::QN_SID, call_->sessions()[0]->id());
2442 void TestSendVideoStreamUpdate() {
2443 cricket::CallOptions options = VideoCallOptions();
2444 options.is_muc = true;
2446 client_->CreateCall();
2447 call_->InitiateSession(buzz::Jid("me@mydomain.com"),
2448 buzz::Jid("me@mydomain.com"), options);
2451 cricket::StreamParams stream;
2452 stream.id = "test-stream";
2453 stream.ssrcs.push_back(1001);
2454 rtc::scoped_ptr<buzz::XmlElement> expected_stream_add(
2455 buzz::XmlElement::ForStr(
2456 JingleOutboundStreamAdd(
2457 call_->sessions()[0]->id(),
2458 "video", stream.id, "1001")));
2459 rtc::scoped_ptr<buzz::XmlElement> expected_stream_remove(
2460 buzz::XmlElement::ForStr(
2461 JingleOutboundStreamRemove(
2462 call_->sessions()[0]->id(),
2463 "video", stream.id)));
2465 call_->SendVideoStreamUpdate(call_->sessions()[0],
2466 call_->CreateVideoStreamUpdate(stream));
2467 ASSERT_EQ(1U, stanzas_.size());
2468 EXPECT_EQ(expected_stream_add->Str(), stanzas_[0]->Str());
2471 stream.ssrcs.clear();
2472 call_->SendVideoStreamUpdate(call_->sessions()[0],
2473 call_->CreateVideoStreamUpdate(stream));
2474 ASSERT_EQ(1U, stanzas_.size());
2475 EXPECT_EQ(expected_stream_remove->Str(), stanzas_[0]->Str());
2479 void TestStreamsUpdateAndViewRequests() {
2480 cricket::CallOptions options = VideoCallOptions();
2481 options.is_muc = true;
2483 client_->CreateCall();
2484 call_->InitiateSession(buzz::Jid("me@mydomain.com"),
2485 buzz::Jid("me@mydomain.com"), options);
2486 ASSERT_EQ(1U, ClearStanzas());
2487 ASSERT_EQ(0U, last_streams_added_.audio().size());
2488 ASSERT_EQ(0U, last_streams_added_.video().size());
2489 ASSERT_EQ(0U, last_streams_removed_.audio().size());
2490 ASSERT_EQ(0U, last_streams_removed_.video().size());
2492 rtc::scoped_ptr<buzz::XmlElement> accept_stanza(
2493 buzz::XmlElement::ForStr(kJingleAcceptWithSsrcs));
2494 SetJingleSid(accept_stanza.get());
2495 client_->session_manager()->OnIncomingMessage(accept_stanza.get());
2496 ASSERT_EQ(cricket::Session::STATE_RECEIVEDACCEPT,
2497 call_->sessions()[0]->state());
2498 ASSERT_EQ(1U, stanzas_.size());
2499 ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
2501 // Need to clear the added streams, because they are populated when
2502 // receiving an accept message now.
2503 last_streams_added_.mutable_video()->clear();
2504 last_streams_added_.mutable_audio()->clear();
2506 call_->sessions()[0]->SetState(cricket::Session::STATE_INPROGRESS);
2508 rtc::scoped_ptr<buzz::XmlElement> streams_stanza(
2509 buzz::XmlElement::ForStr(
2510 JingleStreamAdd("video", "Bob", "video1", "ABC")));
2511 SetJingleSid(streams_stanza.get());
2512 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2513 // First one is ignored because of bad syntax.
2514 ASSERT_EQ(1U, stanzas_.size());
2515 // TODO(pthatcher): Figure out how to make this an ERROR rather than RESULT.
2516 ASSERT_EQ(std::string(buzz::STR_ERROR), stanzas_[0]->Attr(buzz::QN_TYPE));
2518 ASSERT_EQ(0U, last_streams_added_.audio().size());
2519 ASSERT_EQ(0U, last_streams_added_.video().size());
2520 ASSERT_EQ(0U, last_streams_removed_.audio().size());
2521 ASSERT_EQ(0U, last_streams_removed_.video().size());
2523 streams_stanza.reset(buzz::XmlElement::ForStr(
2524 JingleStreamAdd("audio", "Bob", "audio1", "1234")));
2525 SetJingleSid(streams_stanza.get());
2526 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2527 ASSERT_EQ(1U, last_streams_added_.audio().size());
2528 ASSERT_EQ("Bob", last_streams_added_.audio()[0].groupid);
2529 ASSERT_EQ(1U, last_streams_added_.audio()[0].ssrcs.size());
2530 ASSERT_EQ(1234U, last_streams_added_.audio()[0].first_ssrc());
2532 // Ignores adds without ssrcs.
2533 streams_stanza.reset(buzz::XmlElement::ForStr(
2534 JingleStreamAddWithoutSsrc("audio", "Bob", "audioX")));
2535 SetJingleSid(streams_stanza.get());
2536 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2537 ASSERT_EQ(1U, last_streams_added_.audio().size());
2538 ASSERT_EQ(1234U, last_streams_added_.audio()[0].first_ssrc());
2540 // Ignores stream updates with unknown content names. (Don't terminate).
2541 streams_stanza.reset(buzz::XmlElement::ForStr(
2542 JingleStreamAddWithoutSsrc("foo", "Bob", "foo")));
2543 SetJingleSid(streams_stanza.get());
2544 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2546 streams_stanza.reset(buzz::XmlElement::ForStr(
2547 JingleStreamAdd("audio", "Joe", "audio1", "2468")));
2548 SetJingleSid(streams_stanza.get());
2549 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2550 ASSERT_EQ(1U, last_streams_added_.audio().size());
2551 ASSERT_EQ("Joe", last_streams_added_.audio()[0].groupid);
2552 ASSERT_EQ(1U, last_streams_added_.audio()[0].ssrcs.size());
2553 ASSERT_EQ(2468U, last_streams_added_.audio()[0].first_ssrc());
2555 streams_stanza.reset(buzz::XmlElement::ForStr(
2556 JingleStreamAdd("video", "Bob", "video1", "5678")));
2557 SetJingleSid(streams_stanza.get());
2558 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2559 ASSERT_EQ(1U, last_streams_added_.video().size());
2560 ASSERT_EQ("Bob", last_streams_added_.video()[0].groupid);
2561 ASSERT_EQ(1U, last_streams_added_.video()[0].ssrcs.size());
2562 ASSERT_EQ(5678U, last_streams_added_.video()[0].first_ssrc());
2564 // We're testing that a "duplicate" is effectively ignored.
2565 last_streams_added_.mutable_video()->clear();
2566 last_streams_removed_.mutable_video()->clear();
2567 streams_stanza.reset(buzz::XmlElement::ForStr(
2568 JingleStreamAdd("video", "Bob", "video1", "5678")));
2569 SetJingleSid(streams_stanza.get());
2570 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2571 ASSERT_EQ(0U, last_streams_added_.video().size());
2572 ASSERT_EQ(0U, last_streams_removed_.video().size());
2574 streams_stanza.reset(buzz::XmlElement::ForStr(
2575 JingleStreamAdd("video", "Bob", "video2", "5679")));
2576 SetJingleSid(streams_stanza.get());
2577 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2578 ASSERT_EQ(1U, last_streams_added_.video().size());
2579 ASSERT_EQ("Bob", last_streams_added_.video()[0].groupid);
2580 ASSERT_EQ(1U, last_streams_added_.video()[0].ssrcs.size());
2581 ASSERT_EQ(5679U, last_streams_added_.video()[0].first_ssrc());
2583 cricket::FakeVoiceMediaChannel* voice_channel = fme_->GetVoiceChannel(0);
2584 ASSERT_TRUE(voice_channel != NULL);
2585 ASSERT_TRUE(voice_channel->HasRecvStream(1234U));
2586 ASSERT_TRUE(voice_channel->HasRecvStream(2468U));
2587 cricket::FakeVideoMediaChannel* video_channel = fme_->GetVideoChannel(0);
2588 ASSERT_TRUE(video_channel != NULL);
2589 ASSERT_TRUE(video_channel->HasRecvStream(5678U));
2592 cricket::ViewRequest viewRequest;
2593 cricket::StaticVideoView staticVideoView(
2594 cricket::StreamSelector(5678U), 640, 480, 30);
2595 viewRequest.static_video_views.push_back(staticVideoView);
2596 rtc::scoped_ptr<buzz::XmlElement> expected_view_elem(
2597 buzz::XmlElement::ForStr(JingleView("5678", "640", "480", "30")));
2598 SetJingleSid(expected_view_elem.get());
2601 call_->SendViewRequest(call_->sessions()[0], viewRequest));
2602 ASSERT_EQ(1U, stanzas_.size());
2603 ASSERT_EQ(expected_view_elem->Str(), stanzas_[0]->Str());
2606 streams_stanza.reset(buzz::XmlElement::ForStr(
2607 JingleStreamRemove("audio", "Bob", "audio1")));
2608 SetJingleSid(streams_stanza.get());
2609 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2610 ASSERT_EQ(1U, last_streams_removed_.audio().size());
2611 ASSERT_EQ(1U, last_streams_removed_.audio()[0].ssrcs.size());
2612 EXPECT_EQ(1234U, last_streams_removed_.audio()[0].first_ssrc());
2614 streams_stanza.reset(buzz::XmlElement::ForStr(
2615 JingleStreamRemove("video", "Bob", "video1")));
2616 SetJingleSid(streams_stanza.get());
2617 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2618 ASSERT_EQ(1U, last_streams_removed_.video().size());
2619 ASSERT_EQ(1U, last_streams_removed_.video()[0].ssrcs.size());
2620 EXPECT_EQ(5678U, last_streams_removed_.video()[0].first_ssrc());
2622 streams_stanza.reset(buzz::XmlElement::ForStr(
2623 JingleStreamRemove("video", "Bob", "video2")));
2624 SetJingleSid(streams_stanza.get());
2625 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2626 ASSERT_EQ(1U, last_streams_removed_.video().size());
2627 ASSERT_EQ(1U, last_streams_removed_.video()[0].ssrcs.size());
2628 EXPECT_EQ(5679U, last_streams_removed_.video()[0].first_ssrc());
2630 // Duplicate removal: should be ignored.
2631 last_streams_removed_.mutable_audio()->clear();
2632 streams_stanza.reset(buzz::XmlElement::ForStr(
2633 JingleStreamRemove("audio", "Bob", "audio1")));
2634 SetJingleSid(streams_stanza.get());
2635 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2636 ASSERT_EQ(0U, last_streams_removed_.audio().size());
2638 // Duplicate removal: should be ignored.
2639 last_streams_removed_.mutable_video()->clear();
2640 streams_stanza.reset(buzz::XmlElement::ForStr(
2641 JingleStreamRemove("video", "Bob", "video1")));
2642 SetJingleSid(streams_stanza.get());
2643 client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2644 ASSERT_EQ(0U, last_streams_removed_.video().size());
2646 voice_channel = fme_->GetVoiceChannel(0);
2647 ASSERT_TRUE(voice_channel != NULL);
2648 ASSERT_FALSE(voice_channel->HasRecvStream(1234U));
2649 ASSERT_TRUE(voice_channel->HasRecvStream(2468U));
2650 video_channel = fme_->GetVideoChannel(0);
2651 ASSERT_TRUE(video_channel != NULL);
2652 ASSERT_FALSE(video_channel->HasRecvStream(5678U));
2654 // Fails because ssrc is now invalid.
2656 call_->SendViewRequest(call_->sessions()[0], viewRequest));
2661 void MakeSignalingSecure(cricket::SecurePolicy secure) {
2662 client_->set_secure(secure);
2665 void ExpectCrypto(cricket::SecurePolicy secure) {
2666 MakeSignalingSecure(secure);
2667 expect_incoming_crypto_ = true;
2669 expect_outgoing_crypto_ = true;
2673 void ExpectVideoBandwidth(int bandwidth) {
2674 expected_video_bandwidth_ = bandwidth;
2677 void ExpectVideoRtcpMux(bool rtcp_mux) {
2678 expected_video_rtcp_mux_ = rtcp_mux;
2682 void SetCodecFeedbackParams(std::vector<C>* codecs,
2683 const FeedbackParams& fb_params) {
2684 for (size_t i = 0; i < codecs->size(); ++i) {
2685 codecs->at(i).feedback_params = fb_params;
2689 void ExpectRtcpFb() {
2690 FeedbackParams params_nack_fir;
2691 params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamCcm,
2692 cricket::kRtcpFbCcmParamFir));
2693 params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamNack));
2695 FeedbackParams params_nack;
2696 params_nack.Add(FeedbackParam(cricket::kRtcpFbParamNack));
2698 expected_audio_fb_params_ = params_nack;
2699 expected_video_fb_params_ = params_nack_fir;
2700 expected_data_fb_params_ = params_nack;
2703 cricket::FakeMediaEngine* fme() { return fme_; }
2706 void OnSendStanza(cricket::SessionManager* manager,
2707 const buzz::XmlElement* stanza) {
2708 LOG(LS_INFO) << stanza->Str();
2709 stanzas_.push_back(new buzz::XmlElement(*stanza));
2712 void OnSessionCreate(cricket::Session* session, bool initiate) {
2713 session->set_current_protocol(initial_protocol_);
2716 void OnCallCreate(cricket::Call *call) {
2718 call->SignalMediaStreamsUpdate.connect(
2719 this, &MediaSessionClientTest::OnMediaStreamsUpdate);
2722 void OnCallDestroy(cricket::Call *call) {
2726 void OnMediaStreamsUpdate(cricket::Call *call,
2727 cricket::Session *session,
2728 const cricket::MediaStreams& added,
2729 const cricket::MediaStreams& removed) {
2730 last_streams_added_.CopyFrom(added);
2731 last_streams_removed_.CopyFrom(removed);
2734 rtc::NetworkManager* nm_;
2735 cricket::PortAllocator* pa_;
2736 cricket::SessionManager* sm_;
2737 cricket::FakeMediaEngine* fme_;
2738 cricket::FakeDataEngine* fdme_;
2739 cricket::MediaSessionClient* client_;
2741 cricket::Call* call_;
2742 std::vector<buzz::XmlElement* > stanzas_;
2743 MediaSessionTestParser* parser_;
2744 cricket::SignalingProtocol initial_protocol_;
2745 bool expect_incoming_crypto_;
2746 bool expect_outgoing_crypto_;
2747 int expected_video_bandwidth_;
2748 bool expected_video_rtcp_mux_;
2749 FeedbackParams expected_audio_fb_params_;
2750 FeedbackParams expected_video_fb_params_;
2751 FeedbackParams expected_data_fb_params_;
2752 cricket::MediaStreams last_streams_added_;
2753 cricket::MediaStreams last_streams_removed_;
2756 MediaSessionClientTest* GingleTest() {
2757 return new MediaSessionClientTest(new GingleSessionTestParser(),
2758 cricket::PROTOCOL_GINGLE);
2761 MediaSessionClientTest* JingleTest() {
2762 return new MediaSessionClientTest(new JingleSessionTestParser(),
2763 cricket::PROTOCOL_JINGLE);
2766 TEST(MediaSessionTest, JingleGoodInitiateWithRtcpFb) {
2767 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2768 rtc::scoped_ptr<buzz::XmlElement> elem;
2770 cricket::CallOptions options = VideoCallOptions();
2771 options.data_channel_type = cricket::DCT_SCTP;
2772 test->ExpectRtcpFb();
2773 test->TestGoodIncomingInitiate(
2774 kJingleInitiateWithRtcpFb, options, elem.use());
2777 TEST(MediaSessionTest, JingleGoodVideoInitiate) {
2778 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2779 rtc::scoped_ptr<buzz::XmlElement> elem;
2780 test->TestGoodIncomingInitiate(
2781 kJingleVideoInitiate, VideoCallOptions(), elem.use());
2782 test->TestCodecsOfVideoInitiate(elem.get());
2785 TEST(MediaSessionTest, JingleGoodVideoInitiateWithBandwidth) {
2786 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2787 rtc::scoped_ptr<buzz::XmlElement> elem;
2788 test->ExpectVideoBandwidth(42000);
2789 test->TestGoodIncomingInitiate(
2790 kJingleVideoInitiateWithBandwidth, VideoCallOptions(), elem.use());
2793 TEST(MediaSessionTest, JingleGoodVideoInitiateWithRtcpMux) {
2794 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2795 rtc::scoped_ptr<buzz::XmlElement> elem;
2796 test->ExpectVideoRtcpMux(true);
2797 test->TestGoodIncomingInitiate(
2798 kJingleVideoInitiateWithRtcpMux, VideoCallOptions(), elem.use());
2801 TEST(MediaSessionTest, JingleGoodVideoInitiateWithRtpData) {
2802 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2803 rtc::scoped_ptr<buzz::XmlElement> elem;
2804 cricket::CallOptions options = VideoCallOptions();
2805 options.data_channel_type = cricket::DCT_RTP;
2806 test->TestGoodIncomingInitiate(
2807 AddEncryption(kJingleVideoInitiateWithRtpData, kJingleCryptoOffer),
2812 TEST(MediaSessionTest, JingleGoodVideoInitiateWithSctpData) {
2813 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2814 rtc::scoped_ptr<buzz::XmlElement> elem;
2815 cricket::CallOptions options = VideoCallOptions();
2816 options.data_channel_type = cricket::DCT_SCTP;
2817 test->TestGoodIncomingInitiate(kJingleVideoInitiateWithSctpData,
2822 TEST(MediaSessionTest, JingleRejectAudio) {
2823 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2824 rtc::scoped_ptr<buzz::XmlElement> elem;
2825 cricket::CallOptions options = VideoCallOptions();
2826 options.has_audio = false;
2827 options.data_channel_type = cricket::DCT_RTP;
2828 test->TestRejectOffer(kJingleVideoInitiateWithRtpData, options, elem.use());
2831 TEST(MediaSessionTest, JingleRejectVideo) {
2832 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2833 rtc::scoped_ptr<buzz::XmlElement> elem;
2834 cricket::CallOptions options = AudioCallOptions();
2835 options.data_channel_type = cricket::DCT_RTP;
2836 test->TestRejectOffer(kJingleVideoInitiateWithRtpData, options, elem.use());
2839 TEST(MediaSessionTest, JingleRejectData) {
2840 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2841 rtc::scoped_ptr<buzz::XmlElement> elem;
2842 test->TestRejectOffer(
2843 kJingleVideoInitiateWithRtpData, VideoCallOptions(), elem.use());
2846 TEST(MediaSessionTest, JingleRejectVideoAndData) {
2847 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2848 rtc::scoped_ptr<buzz::XmlElement> elem;
2849 test->TestRejectOffer(
2850 kJingleVideoInitiateWithRtpData, AudioCallOptions(), elem.use());
2853 TEST(MediaSessionTest, JingleGoodInitiateAllSupportedAudioCodecs) {
2854 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2855 rtc::scoped_ptr<buzz::XmlElement> elem;
2856 test->TestGoodIncomingInitiate(
2857 kJingleInitiate, AudioCallOptions(), elem.use());
2858 test->TestHasAllSupportedAudioCodecs(elem.get());
2861 // Changes the codecs that our FakeMediaEngine will support with a different
2862 // preference order than the incoming offer.
2863 // Verifies the answer accepts the preference order of the remote peer.
2864 TEST(MediaSessionTest, JingleGoodInitiateDifferentPreferenceAudioCodecs) {
2865 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2866 test->fme()->SetAudioCodecs(MAKE_VECTOR(kAudioCodecsDifferentPreference));
2867 rtc::scoped_ptr<buzz::XmlElement> elem;
2868 test->TestGoodIncomingInitiate(
2869 kJingleInitiate, AudioCallOptions(), elem.use());
2870 test->TestHasAllSupportedAudioCodecs(elem.get());
2873 TEST(MediaSessionTest, JingleGoodInitiateSomeUnsupportedAudioCodecs) {
2874 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2875 rtc::scoped_ptr<buzz::XmlElement> elem;
2876 test->TestGoodIncomingInitiate(
2877 kJingleInitiateSomeUnsupported, AudioCallOptions(), elem.use());
2878 test->TestHasAudioCodecsFromInitiateSomeUnsupported(elem.get());
2881 TEST(MediaSessionTest, JingleGoodInitiateDynamicAudioCodecs) {
2882 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2883 rtc::scoped_ptr<buzz::XmlElement> elem;
2884 test->TestGoodIncomingInitiate(
2885 kJingleInitiateDynamicAudioCodecs, AudioCallOptions(), elem.use());
2886 test->TestHasAudioCodecsFromInitiateDynamicAudioCodecs(elem.get());
2889 TEST(MediaSessionTest, JingleGoodInitiateStaticAudioCodecs) {
2890 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2891 rtc::scoped_ptr<buzz::XmlElement> elem;
2892 test->TestGoodIncomingInitiate(
2893 kJingleInitiateStaticAudioCodecs, AudioCallOptions(), elem.use());
2894 test->TestHasAudioCodecsFromInitiateStaticAudioCodecs(elem.get());
2897 TEST(MediaSessionTest, JingleBadInitiateNoAudioCodecs) {
2898 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2899 test->TestBadIncomingInitiate(kJingleInitiateNoAudioCodecs);
2902 TEST(MediaSessionTest, JingleBadInitiateNoSupportedAudioCodecs) {
2903 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2904 test->TestBadIncomingInitiate(kJingleInitiateNoSupportedAudioCodecs);
2907 TEST(MediaSessionTest, JingleBadInitiateWrongClockrates) {
2908 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2909 test->TestBadIncomingInitiate(kJingleInitiateWrongClockrates);
2912 TEST(MediaSessionTest, JingleBadInitiateWrongChannels) {
2913 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2914 test->TestBadIncomingInitiate(kJingleInitiateWrongChannels);
2917 TEST(MediaSessionTest, JingleBadInitiateNoPayloadTypes) {
2918 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2919 test->TestBadIncomingInitiate(kJingleInitiateNoPayloadTypes);
2922 TEST(MediaSessionTest, JingleBadInitiateDynamicWithoutNames) {
2923 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2924 test->TestBadIncomingInitiate(kJingleInitiateDynamicWithoutNames);
2927 TEST(MediaSessionTest, JingleGoodOutgoingInitiate) {
2928 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2929 test->TestGoodOutgoingInitiate(AudioCallOptions());
2932 TEST(MediaSessionTest, JingleGoodOutgoingInitiateWithBandwidth) {
2933 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2934 cricket::CallOptions options = VideoCallOptions();
2935 options.video_bandwidth = 42000;
2936 test->TestGoodOutgoingInitiate(options);
2939 TEST(MediaSessionTest, JingleGoodOutgoingInitiateWithRtcpMux) {
2940 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2941 cricket::CallOptions options = VideoCallOptions();
2942 options.rtcp_mux_enabled = true;
2943 test->TestGoodOutgoingInitiate(options);
2946 TEST(MediaSessionTest, JingleGoodOutgoingInitiateWithRtpData) {
2947 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2948 cricket::CallOptions options;
2949 options.data_channel_type = cricket::DCT_RTP;
2950 test->ExpectCrypto(cricket::SEC_ENABLED);
2951 test->TestGoodOutgoingInitiate(options);
2954 TEST(MediaSessionTest, JingleGoodOutgoingInitiateWithSctpData) {
2955 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2956 cricket::CallOptions options;
2957 options.data_channel_type = cricket::DCT_SCTP;
2958 test->TestGoodOutgoingInitiate(options);
2961 // Crypto related tests.
2963 // Offer has crypto but the session is not secured, just ignore it.
2964 TEST(MediaSessionTest, JingleInitiateWithCryptoIsIgnoredWhenNotSecured) {
2965 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2966 rtc::scoped_ptr<buzz::XmlElement> elem;
2967 test->TestGoodIncomingInitiate(
2968 AddEncryption(kJingleVideoInitiate, kJingleCryptoOffer),
2973 // Offer has crypto required but the session is not secure, fail.
2974 TEST(MediaSessionTest, JingleInitiateWithCryptoRequiredWhenNotSecured) {
2975 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2976 test->TestBadIncomingInitiate(AddEncryption(kJingleVideoInitiate,
2977 kJingleRequiredCryptoOffer));
2980 // Offer has no crypto but the session is secure required, fail.
2981 TEST(MediaSessionTest, JingleInitiateWithNoCryptoFailsWhenSecureRequired) {
2982 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2983 test->ExpectCrypto(cricket::SEC_REQUIRED);
2984 test->TestBadIncomingInitiate(kJingleInitiate);
2987 // Offer has crypto and session is secure, expect crypto in the answer.
2988 TEST(MediaSessionTest, JingleInitiateWithCryptoWhenSecureEnabled) {
2989 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2990 rtc::scoped_ptr<buzz::XmlElement> elem;
2991 test->ExpectCrypto(cricket::SEC_ENABLED);
2992 test->TestGoodIncomingInitiate(
2993 AddEncryption(kJingleVideoInitiate, kJingleCryptoOffer),
2998 // Offer has crypto and session is secure required, expect crypto in
3000 TEST(MediaSessionTest, JingleInitiateWithCryptoWhenSecureRequired) {
3001 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3002 rtc::scoped_ptr<buzz::XmlElement> elem;
3003 test->ExpectCrypto(cricket::SEC_REQUIRED);
3004 test->TestGoodIncomingInitiate(
3005 AddEncryption(kJingleVideoInitiate, kJingleCryptoOffer),
3010 // Offer has unsupported crypto and session is secure, no crypto in
3012 TEST(MediaSessionTest, JingleInitiateWithUnsupportedCrypto) {
3013 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3014 rtc::scoped_ptr<buzz::XmlElement> elem;
3015 test->MakeSignalingSecure(cricket::SEC_ENABLED);
3016 test->TestGoodIncomingInitiate(
3017 AddEncryption(kJingleInitiate, kJingleUnsupportedCryptoOffer),
3022 // Offer has unsupported REQUIRED crypto and session is not secure, fail.
3023 TEST(MediaSessionTest, JingleInitiateWithRequiredUnsupportedCrypto) {
3024 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3025 test->TestBadIncomingInitiate(
3026 AddEncryption(kJingleInitiate, kJingleRequiredUnsupportedCryptoOffer));
3029 // Offer has unsupported REQUIRED crypto and session is secure, fail.
3030 TEST(MediaSessionTest, JingleInitiateWithRequiredUnsupportedCryptoWhenSecure) {
3031 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3032 test->MakeSignalingSecure(cricket::SEC_ENABLED);
3033 test->TestBadIncomingInitiate(
3034 AddEncryption(kJingleInitiate, kJingleRequiredUnsupportedCryptoOffer));
3037 // Offer has unsupported REQUIRED crypto and session is required secure, fail.
3038 TEST(MediaSessionTest,
3039 JingleInitiateWithRequiredUnsupportedCryptoWhenSecureRequired) {
3040 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3041 test->MakeSignalingSecure(cricket::SEC_REQUIRED);
3042 test->TestBadIncomingInitiate(
3043 AddEncryption(kJingleInitiate, kJingleRequiredUnsupportedCryptoOffer));
3047 TEST(MediaSessionTest, JingleGoodOutgoingInitiateWithCrypto) {
3048 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3049 test->ExpectCrypto(cricket::SEC_ENABLED);
3050 test->TestGoodOutgoingInitiate(AudioCallOptions());
3053 TEST(MediaSessionTest, JingleGoodOutgoingInitiateWithCryptoRequired) {
3054 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3055 test->ExpectCrypto(cricket::SEC_REQUIRED);
3056 test->TestGoodOutgoingInitiate(AudioCallOptions());
3059 TEST(MediaSessionTest, JingleIncomingAcceptWithSsrcs) {
3060 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3061 cricket::CallOptions options = VideoCallOptions();
3062 options.is_muc = true;
3063 test->TestIncomingAcceptWithSsrcs(kJingleAcceptWithSsrcs, options);
3066 TEST(MediaSessionTest, JingleIncomingAcceptWithRtpDataSsrcs) {
3067 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3068 cricket::CallOptions options = VideoCallOptions();
3069 options.is_muc = true;
3070 options.data_channel_type = cricket::DCT_RTP;
3071 test->TestIncomingAcceptWithSsrcs(kJingleAcceptWithRtpDataSsrcs, options);
3074 TEST(MediaSessionTest, JingleIncomingAcceptWithSctpData) {
3075 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3076 cricket::CallOptions options = VideoCallOptions();
3077 options.is_muc = true;
3078 options.data_channel_type = cricket::DCT_SCTP;
3079 test->TestIncomingAcceptWithSsrcs(kJingleAcceptWithSctpData, options);
3082 TEST(MediaSessionTest, JingleStreamsUpdateAndView) {
3083 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3084 test->TestStreamsUpdateAndViewRequests();
3087 TEST(MediaSessionTest, JingleSendVideoStreamUpdate) {
3088 rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3089 test->TestSendVideoStreamUpdate();
3094 TEST(MediaSessionTest, GingleGoodVideoInitiate) {
3095 rtc::scoped_ptr<buzz::XmlElement> elem;
3096 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3097 test->TestGoodIncomingInitiate(
3098 kGingleVideoInitiate, VideoCallOptions(), elem.use());
3099 test->TestCodecsOfVideoInitiate(elem.get());
3102 TEST(MediaSessionTest, GingleGoodVideoInitiateWithBandwidth) {
3103 rtc::scoped_ptr<buzz::XmlElement> elem;
3104 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3105 test->ExpectVideoBandwidth(42000);
3106 test->TestGoodIncomingInitiate(
3107 kGingleVideoInitiateWithBandwidth, VideoCallOptions(), elem.use());
3110 TEST(MediaSessionTest, GingleGoodInitiateAllSupportedAudioCodecs) {
3111 rtc::scoped_ptr<buzz::XmlElement> elem;
3112 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3113 test->TestGoodIncomingInitiate(
3114 kGingleInitiate, AudioCallOptions(), elem.use());
3115 test->TestHasAllSupportedAudioCodecs(elem.get());
3118 TEST(MediaSessionTest, GingleGoodInitiateAllSupportedAudioCodecsWithCrypto) {
3119 rtc::scoped_ptr<buzz::XmlElement> elem;
3120 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3121 test->ExpectCrypto(cricket::SEC_ENABLED);
3122 test->TestGoodIncomingInitiate(
3123 AddEncryption(kGingleInitiate, kGingleCryptoOffer),
3126 test->TestHasAllSupportedAudioCodecs(elem.get());
3129 // Changes the codecs that our FakeMediaEngine will support with a different
3130 // preference order than the incoming offer.
3131 // Verifies the answer accepts the preference order of the remote peer.
3132 TEST(MediaSessionTest, GingleGoodInitiateDifferentPreferenceAudioCodecs) {
3133 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3134 test->fme()->SetAudioCodecs(MAKE_VECTOR(kAudioCodecsDifferentPreference));
3135 rtc::scoped_ptr<buzz::XmlElement> elem;
3136 test->TestGoodIncomingInitiate(
3137 kGingleInitiate, AudioCallOptions(), elem.use());
3138 test->TestHasAllSupportedAudioCodecs(elem.get());
3141 TEST(MediaSessionTest, GingleGoodInitiateSomeUnsupportedAudioCodecs) {
3142 rtc::scoped_ptr<buzz::XmlElement> elem;
3143 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3144 test->TestGoodIncomingInitiate(
3145 kGingleInitiateSomeUnsupported, AudioCallOptions(), elem.use());
3146 test->TestHasAudioCodecsFromInitiateSomeUnsupported(elem.get());
3149 TEST(MediaSessionTest, GingleGoodInitiateDynamicAudioCodecs) {
3150 rtc::scoped_ptr<buzz::XmlElement> elem;
3151 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3152 test->TestGoodIncomingInitiate(
3153 kGingleInitiateDynamicAudioCodecs, AudioCallOptions(), elem.use());
3154 test->TestHasAudioCodecsFromInitiateDynamicAudioCodecs(elem.get());
3157 TEST(MediaSessionTest, GingleGoodInitiateStaticAudioCodecs) {
3158 rtc::scoped_ptr<buzz::XmlElement> elem;
3159 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3160 test->TestGoodIncomingInitiate(
3161 kGingleInitiateStaticAudioCodecs, AudioCallOptions(), elem.use());
3162 test->TestHasAudioCodecsFromInitiateStaticAudioCodecs(elem.get());
3165 TEST(MediaSessionTest, GingleGoodInitiateNoAudioCodecs) {
3166 rtc::scoped_ptr<buzz::XmlElement> elem;
3167 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3168 test->TestGoodIncomingInitiate(
3169 kGingleInitiateNoAudioCodecs, AudioCallOptions(), elem.use());
3170 test->TestHasDefaultAudioCodecs(elem.get());
3173 TEST(MediaSessionTest, GingleBadInitiateNoSupportedAudioCodecs) {
3174 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3175 test->TestBadIncomingInitiate(kGingleInitiateNoSupportedAudioCodecs);
3178 TEST(MediaSessionTest, GingleBadInitiateWrongClockrates) {
3179 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3180 test->TestBadIncomingInitiate(kGingleInitiateWrongClockrates);
3183 TEST(MediaSessionTest, GingleBadInitiateWrongChannels) {
3184 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3185 test->TestBadIncomingInitiate(kGingleInitiateWrongChannels);
3189 TEST(MediaSessionTest, GingleBadInitiateNoPayloadTypes) {
3190 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3191 test->TestBadIncomingInitiate(kGingleInitiateNoPayloadTypes);
3194 TEST(MediaSessionTest, GingleBadInitiateDynamicWithoutNames) {
3195 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3196 test->TestBadIncomingInitiate(kGingleInitiateDynamicWithoutNames);
3199 TEST(MediaSessionTest, GingleGoodOutgoingInitiate) {
3200 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3201 test->TestGoodOutgoingInitiate(AudioCallOptions());
3204 TEST(MediaSessionTest, GingleGoodOutgoingInitiateWithBandwidth) {
3205 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3206 cricket::CallOptions options = VideoCallOptions();
3207 options.video_bandwidth = 42000;
3208 test->TestGoodOutgoingInitiate(options);
3211 // Crypto related tests.
3213 // Offer has crypto but the session is not secured, just ignore it.
3214 TEST(MediaSessionTest, GingleInitiateWithCryptoIsIgnoredWhenNotSecured) {
3215 rtc::scoped_ptr<buzz::XmlElement> elem;
3216 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3217 test->TestGoodIncomingInitiate(
3218 AddEncryption(kGingleInitiate, kGingleCryptoOffer),
3223 // Offer has crypto required but the session is not secure, fail.
3224 TEST(MediaSessionTest, GingleInitiateWithCryptoRequiredWhenNotSecured) {
3225 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3226 test->TestBadIncomingInitiate(AddEncryption(kGingleInitiate,
3227 kGingleRequiredCryptoOffer));
3230 // Offer has no crypto but the session is secure required, fail.
3231 TEST(MediaSessionTest, GingleInitiateWithNoCryptoFailsWhenSecureRequired) {
3232 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3233 test->ExpectCrypto(cricket::SEC_REQUIRED);
3234 test->TestBadIncomingInitiate(kGingleInitiate);
3237 // Offer has crypto and session is secure, expect crypto in the answer.
3238 TEST(MediaSessionTest, GingleInitiateWithCryptoWhenSecureEnabled) {
3239 rtc::scoped_ptr<buzz::XmlElement> elem;
3240 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3241 test->ExpectCrypto(cricket::SEC_ENABLED);
3242 test->TestGoodIncomingInitiate(
3243 AddEncryption(kGingleInitiate, kGingleCryptoOffer),
3248 // Offer has crypto and session is secure required, expect crypto in
3250 TEST(MediaSessionTest, GingleInitiateWithCryptoWhenSecureRequired) {
3251 rtc::scoped_ptr<buzz::XmlElement> elem;
3252 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3253 test->ExpectCrypto(cricket::SEC_REQUIRED);
3254 test->TestGoodIncomingInitiate(
3255 AddEncryption(kGingleInitiate, kGingleCryptoOffer),
3260 // Offer has unsupported crypto and session is secure, no crypto in
3262 TEST(MediaSessionTest, GingleInitiateWithUnsupportedCrypto) {
3263 rtc::scoped_ptr<buzz::XmlElement> elem;
3264 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3265 test->MakeSignalingSecure(cricket::SEC_ENABLED);
3266 test->TestGoodIncomingInitiate(
3267 AddEncryption(kGingleInitiate, kGingleUnsupportedCryptoOffer),
3272 // Offer has unsupported REQUIRED crypto and session is not secure, fail.
3273 TEST(MediaSessionTest, GingleInitiateWithRequiredUnsupportedCrypto) {
3274 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3275 test->TestBadIncomingInitiate(
3276 AddEncryption(kGingleInitiate, kGingleRequiredUnsupportedCryptoOffer));
3279 // Offer has unsupported REQUIRED crypto and session is secure, fail.
3280 TEST(MediaSessionTest, GingleInitiateWithRequiredUnsupportedCryptoWhenSecure) {
3281 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3282 test->MakeSignalingSecure(cricket::SEC_ENABLED);
3283 test->TestBadIncomingInitiate(
3284 AddEncryption(kGingleInitiate, kGingleRequiredUnsupportedCryptoOffer));
3287 // Offer has unsupported REQUIRED crypto and session is required secure, fail.
3288 TEST(MediaSessionTest,
3289 GingleInitiateWithRequiredUnsupportedCryptoWhenSecureRequired) {
3290 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3291 test->MakeSignalingSecure(cricket::SEC_REQUIRED);
3292 test->TestBadIncomingInitiate(
3293 AddEncryption(kGingleInitiate, kGingleRequiredUnsupportedCryptoOffer));
3296 TEST(MediaSessionTest, GingleGoodOutgoingInitiateWithCrypto) {
3297 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3298 test->ExpectCrypto(cricket::SEC_ENABLED);
3299 test->TestGoodOutgoingInitiate(AudioCallOptions());
3302 TEST(MediaSessionTest, GingleGoodOutgoingInitiateWithCryptoRequired) {
3303 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3304 test->ExpectCrypto(cricket::SEC_REQUIRED);
3305 test->TestGoodOutgoingInitiate(AudioCallOptions());
3308 TEST(MediaSessionTest, GingleIncomingAcceptWithSsrcs) {
3309 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3310 cricket::CallOptions options = VideoCallOptions();
3311 options.is_muc = true;
3312 test->TestIncomingAcceptWithSsrcs(kGingleAcceptWithSsrcs, options);
3315 TEST(MediaSessionTest, GingleGoodOutgoingInitiateWithRtpData) {
3316 rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3317 cricket::CallOptions options;
3318 options.data_channel_type = cricket::DCT_RTP;
3319 test->ExpectCrypto(cricket::SEC_ENABLED);
3320 test->TestGoodOutgoingInitiate(options);