Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / session / media / mediasessionclient_unittest.cc
1 /*
2  * libjingle
3  * Copyright 2004 Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <string>
29 #include <vector>
30
31 #include "talk/media/base/fakemediaengine.h"
32 #include "talk/media/base/testutils.h"
33 #include "talk/media/devices/fakedevicemanager.h"
34 #include "webrtc/p2p/base/constants.h"
35 #include "webrtc/p2p/client/basicportallocator.h"
36 #include "talk/session/media/mediasessionclient.h"
37 #include "webrtc/libjingle/xmllite/xmlbuilder.h"
38 #include "webrtc/libjingle/xmllite/xmlelement.h"
39 #include "webrtc/libjingle/xmllite/xmlprinter.h"
40 #include "webrtc/libjingle/xmpp/constants.h"
41 #include "webrtc/base/gunit.h"
42 #include "webrtc/base/logging.h"
43 #include "webrtc/base/scoped_ptr.h"
44 #include "webrtc/base/ssladapter.h"
45
46 using cricket::AudioCodec;
47 using cricket::AudioContentDescription;
48 using cricket::Codec;
49 using cricket::DataCodec;
50 using cricket::DataContentDescription;
51 using cricket::FeedbackParam;
52 using cricket::FeedbackParams;
53 using cricket::VideoCodec;
54 using cricket::VideoContentDescription;
55
56 // The codecs that our FakeMediaEngine will support. Order is important, since
57 // the tests check that our messages have codecs in the correct order.
58 static const cricket::AudioCodec kAudioCodecs[] = {
59   cricket::AudioCodec(103, "ISAC",   16000, -1,    1, 18),
60   cricket::AudioCodec(104, "ISAC",   32000, -1,    1, 17),
61   cricket::AudioCodec(119, "ISACLC", 16000, 40000, 1, 16),
62   cricket::AudioCodec(99,  "speex",  16000, 22000, 1, 15),
63   cricket::AudioCodec(97,  "IPCMWB", 16000, 80000, 1, 14),
64   cricket::AudioCodec(9,   "G722",   8000,  64000, 1, 13),
65   cricket::AudioCodec(102, "iLBC",   8000,  13300, 1, 12),
66   cricket::AudioCodec(98,  "speex",  8000,  11000, 1, 11),
67   cricket::AudioCodec(3,   "GSM",    8000,  13000, 1, 10),
68   cricket::AudioCodec(100, "EG711U", 8000,  64000, 1, 9),
69   cricket::AudioCodec(101, "EG711A", 8000,  64000, 1, 8),
70   cricket::AudioCodec(0,   "PCMU",   8000,  64000, 1, 7),
71   cricket::AudioCodec(8,   "PCMA",   8000,  64000, 1, 6),
72   cricket::AudioCodec(126, "CN",     32000, 0,     1, 5),
73   cricket::AudioCodec(105, "CN",     16000, 0,     1, 4),
74   cricket::AudioCodec(13,  "CN",     8000,  0,     1, 3),
75   cricket::AudioCodec(117, "red",    8000,  0,     1, 2),
76   cricket::AudioCodec(106, "telephone-event", 8000, 0, 1, 1)
77 };
78
79 // The codecs that our FakeMediaEngine will support with a different order of
80 // supported codecs.
81 static const cricket::AudioCodec kAudioCodecsDifferentPreference[] = {
82   cricket::AudioCodec(104, "ISAC",   32000, -1,    1, 17),
83   cricket::AudioCodec(97,  "IPCMWB", 16000, 80000, 1, 14),
84   cricket::AudioCodec(9,   "G722",   8000,  64000, 1, 13),
85   cricket::AudioCodec(119, "ISACLC", 16000, 40000, 1, 16),
86   cricket::AudioCodec(103, "ISAC",   16000, -1,    1, 18),
87   cricket::AudioCodec(99,  "speex",  16000, 22000, 1, 15),
88   cricket::AudioCodec(100, "EG711U", 8000,  64000, 1, 9),
89   cricket::AudioCodec(101, "EG711A", 8000,  64000, 1, 8),
90   cricket::AudioCodec(0,   "PCMU",   8000,  64000, 1, 7),
91   cricket::AudioCodec(8,   "PCMA",   8000,  64000, 1, 6),
92   cricket::AudioCodec(102, "iLBC",   8000,  13300, 1, 12),
93   cricket::AudioCodec(3,   "GSM",    8000,  13000, 1, 10),
94   cricket::AudioCodec(98,  "speex",  8000,  11000, 1, 11),
95   cricket::AudioCodec(126, "CN",     32000, 0,     1, 5),
96   cricket::AudioCodec(105, "CN",     16000, 0,     1, 4),
97   cricket::AudioCodec(13,  "CN",     8000,  0,     1, 3),
98   cricket::AudioCodec(117, "red",    8000,  0,     1, 2),
99   cricket::AudioCodec(106, "telephone-event", 8000, 0, 1, 1)
100 };
101
102 static const cricket::VideoCodec kVideoCodecs[] = {
103   cricket::VideoCodec(96, "H264-SVC", 320, 200, 30, 1)
104 };
105
106 static const cricket::DataCodec kDataCodecs[] = {
107   cricket::DataCodec(127, "google-data", 0)
108 };
109
110 const std::string kGingleCryptoOffer = \
111     "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'>   "  \
112     "  <usage/>                                                "  \
113     "  <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \
114     "  key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
115     "  <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \
116     "  key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
117     "</rtp:encryption>                                         ";
118
119 // Jingle offer does not have any <usage> element.
120 const std::string kJingleCryptoOffer = \
121     "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'>   "  \
122     "  <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \
123     "  key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
124     "  <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \
125     "  key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
126     "</rtp:encryption>                                         ";
127
128
129 const std::string kGingleRequiredCryptoOffer = \
130     "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'> "\
131     "  <usage/>                                                "  \
132     "  <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \
133     "  key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
134     "  <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \
135     "  key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
136     "</rtp:encryption>                                         ";
137
138 const std::string kJingleRequiredCryptoOffer = \
139     "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'> "\
140     "  <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \
141     "  key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
142     "  <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \
143     "  key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
144     "</rtp:encryption>                                         ";
145
146
147 const std::string kGingleUnsupportedCryptoOffer = \
148     "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'>   "  \
149     "  <usage/>                                                "  \
150     "  <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1'" \
151     "  key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
152     "  <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2'" \
153     "  key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
154     "</rtp:encryption>                                         ";
155
156 const std::string kJingleUnsupportedCryptoOffer =                 \
157     "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'>   "  \
158     "  <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1'" \
159     "  key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
160     "  <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2'" \
161     "  key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
162     "</rtp:encryption>                                         ";
163
164
165 // With unsupported but with required="true"
166 const std::string kGingleRequiredUnsupportedCryptoOffer =         \
167     "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'>" \
168     "  <usage/>                                                "  \
169     "  <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1'"      \
170     "  key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
171     "  <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2'" \
172     "  key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
173     "</rtp:encryption>                                         ";
174
175 const std::string kJingleRequiredUnsupportedCryptoOffer =                     \
176     "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'>" \
177     "  <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1'                 " \
178     "  key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>       " \
179     "  <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2'                  " \
180     "  key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>"        \
181     "</rtp:encryption>                                         ";
182
183 const std::string kGingleInitiate(
184      "<iq xmlns='jabber:client' from='me@domain.com/resource'         " \
185      "    to='user@domain.com/resource' type='set' id='123'>          " \
186      "  <session xmlns='http://www.google.com/session' type='initiate'" \
187      "    id='abcdef' initiator='me@domain.com/resource'>             " \
188      "    <description xmlns='http://www.google.com/session/phone'>   " \
189      "      <payload-type xmlns='http://www.google.com/session/phone' " \
190      "        id='103' name='ISAC' clockrate='16000' />               " \
191      "      <payload-type xmlns='http://www.google.com/session/phone' " \
192      "        id='104' name='ISAC' clockrate='32000' />               " \
193      "      <payload-type xmlns='http://www.google.com/session/phone' " \
194      "        id='119' name='ISACLC' clockrate='16000' bitrate='40000' />  " \
195      "      <payload-type xmlns='http://www.google.com/session/phone' " \
196      "        id='99' name='speex' clockrate='16000' bitrate='22000' />    " \
197      "      <payload-type xmlns='http://www.google.com/session/phone' " \
198      "        id='97' name='IPCMWB' clockrate='16000' bitrate='80000' />   " \
199      "      <payload-type xmlns='http://www.google.com/session/phone' " \
200      "        id='9' name='G722' clockrate='8000' bitrate='64000' /> " \
201      "      <payload-type xmlns='http://www.google.com/session/phone' " \
202      "        id='102' name='iLBC' clockrate='8000' bitrate='13300' />" \
203      "      <payload-type xmlns='http://www.google.com/session/phone' " \
204      "        id='98' name='speex' clockrate='8000' bitrate='11000' />" \
205      "      <payload-type xmlns='http://www.google.com/session/phone' " \
206      "        id='3' name='GSM' clockrate='8000' bitrate='13000' />   " \
207      "      <payload-type xmlns='http://www.google.com/session/phone' " \
208      "        id='100' name='EG711U' clockrate='8000' bitrate='64000' />   " \
209      "      <payload-type xmlns='http://www.google.com/session/phone' " \
210      "        id='101' name='EG711A' clockrate='8000' bitrate='64000' />   " \
211      "      <payload-type xmlns='http://www.google.com/session/phone' " \
212      "        id='0' name='PCMU' clockrate='8000' bitrate='64000' />  " \
213      "      <payload-type xmlns='http://www.google.com/session/phone' " \
214      "        id='8' name='PCMA' clockrate='8000' bitrate='64000' />  " \
215      "      <payload-type xmlns='http://www.google.com/session/phone' " \
216      "        id='126' name='CN' clockrate='32000' />                 " \
217      "      <payload-type xmlns='http://www.google.com/session/phone' " \
218      "        id='105' name='CN' clockrate='16000' />                 " \
219      "      <payload-type xmlns='http://www.google.com/session/phone' " \
220      "        id='13' name='CN' clockrate='8000' />                   " \
221      "      <payload-type xmlns='http://www.google.com/session/phone' " \
222      "        id='117' name='red' clockrate='8000' />                 " \
223      "      <payload-type xmlns='http://www.google.com/session/phone' " \
224      "        id='106' name='telephone-event' clockrate='8000' />     " \
225      "    </description>                                              " \
226      "  </session>                                                    " \
227      "</iq>                                                           ");
228
229 const std::string kJingleInitiate(
230      "<iq xmlns='jabber:client' from='me@domain.com/resource'           " \
231      "    to='user@domain.com/resource' type='set' id='123'>            " \
232      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
233      "          sid='abcdef' initiator='me@domain.com/resource'>        " \
234      "    <content name='test audio'>                                   " \
235      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
236      "        <payload-type id='103' name='ISAC' clockrate='16000'/>    " \
237      "        <payload-type id='104' name='ISAC' clockrate='32000'/>    " \
238      "        <payload-type                                             " \
239      "          id='119' name='ISACLC' clockrate='16000'>               " \
240      "          <parameter name='bitrate' value='40000'/>               " \
241      "        </payload-type>                                           " \
242      "        <payload-type                                             " \
243      "          id='99' name='speex' clockrate='16000'>                 " \
244      "          <parameter name='bitrate' value='22000'/>               " \
245      "        </payload-type>                                           " \
246      "        <payload-type                                             " \
247      "          id='97' name='IPCMWB' clockrate='16000'>                " \
248      "          <parameter name='bitrate' value='80000'/>               " \
249      "        </payload-type>                                           " \
250      "        <payload-type                                             " \
251      "          id='9' name='G722' clockrate='8000'>                   " \
252      "          <parameter name='bitrate' value='64000'/>               " \
253      "        </payload-type>                                           " \
254      "        <payload-type                                             " \
255      "          id='102' name='iLBC' clockrate='8000'>                  " \
256      "          <parameter name='bitrate' value='13300'/>               " \
257      "        </payload-type>                                           " \
258      "        <payload-type                                             " \
259      "          id='98' name='speex' clockrate='8000'>                  " \
260      "          <parameter name='bitrate' value='11000'/>               " \
261      "        </payload-type>                                           " \
262      "        <payload-type                                             " \
263      "          id='3' name='GSM' clockrate='8000'>                     " \
264      "          <parameter name='bitrate' value='13000'/>               " \
265      "        </payload-type>                                           " \
266      "        <payload-type                                             " \
267      "          id='100' name='EG711U' clockrate='8000'>                " \
268      "          <parameter name='bitrate' value='64000'/>               " \
269      "        </payload-type>                                           " \
270      "        <payload-type                                             " \
271      "          id='101' name='EG711A' clockrate='8000'>                " \
272      "          <parameter name='bitrate' value='64000'/>               " \
273      "        </payload-type>                                           " \
274      "        <payload-type                                             " \
275      "          id='0' name='PCMU' clockrate='8000'>                    " \
276      "          <parameter name='bitrate' value='64000'/>               " \
277      "        </payload-type>                                           " \
278      "        <payload-type                                             " \
279      "          id='8' name='PCMA' clockrate='8000'>                    " \
280      "          <parameter name='bitrate' value='64000'/>               " \
281      "        </payload-type>                                           " \
282      "        <payload-type                                             " \
283      "          id='126' name='CN' clockrate='32000' />                 " \
284      "        <payload-type                                             " \
285      "          id='105' name='CN' clockrate='16000' />                 " \
286      "        <payload-type                                             " \
287      "          id='13' name='CN' clockrate='8000' />                   " \
288      "        <payload-type                                             " \
289      "          id='117' name='red' clockrate='8000' />                 " \
290      "        <payload-type                                             " \
291      "          id='106' name='telephone-event' clockrate='8000' />     " \
292      "      </description>                                              " \
293      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>   " \
294      "    </content>                                                    " \
295      "  </jingle>                                                       " \
296      "</iq>                                                             ");
297
298 const std::string kJingleInitiateWithRtcpFb(
299      "<iq xmlns='jabber:client' from='me@domain.com/resource'           " \
300      "    to='user@domain.com/resource' type='set' id='123'>            " \
301      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
302      "         sid='abcdef' initiator='me@domain.com/resource'>         " \
303      "    <content name='test audio'>                                   " \
304      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
305      "        <payload-type id='103' name='ISAC' clockrate='16000'>     " \
306      "          <rtcp-fb type='nack'/>                                  " \
307      "        </payload-type>                                           " \
308      "      </description>                                              " \
309      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>   " \
310      "    </content>                                                    " \
311      "    <content name='test video'>                                   " \
312      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
313      "        <rtcp-fb type='nack'/>                                    " \
314      "        <payload-type id='99' name='H264-SVC'>                    " \
315      "          <rtcp-fb type='ccm' subtype='fir'/>                    " \
316      "          <parameter name='height' value='200'/>                  " \
317      "          <parameter name='width' value='320'/>                   " \
318      "          <parameter name='framerate' value='30'/>                " \
319      "        </payload-type>                                           " \
320      "      </description>                                              " \
321      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>   " \
322      "    </content>                                                    " \
323      "    <content name='test data'>                                    " \
324      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='data'> " \
325      "        <rtcp-fb type='nack'/>                                    " \
326      "        <payload-type id='127' name='google-data'>                " \
327      "        </payload-type>                                           " \
328      "      </description>                                              " \
329      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>   " \
330      "    </content>                                                    " \
331      "  </jingle>                                                       " \
332      "</iq>                                                             ");
333
334 const std::string kGingleVideoInitiate(
335      "<iq xmlns='jabber:client' from='me@domain.com/resource'         " \
336      "    to='user@domain.com/resource' type='set' id='123'>          " \
337      "  <session xmlns='http://www.google.com/session' type='initiate'" \
338      "    id='abcdef' initiator='me@domain.com/resource'>             " \
339      "    <description xmlns='http://www.google.com/session/video'>   " \
340      "      <payload-type xmlns='http://www.google.com/session/phone' " \
341      "        id='103' name='ISAC' clockrate='16000' />               " \
342      "      <payload-type xmlns='http://www.google.com/session/video' " \
343      "        id='99' name='H264-SVC' framerate='30'                  " \
344      "        height='200' width='320'/>                              " \
345      "    </description>                                              " \
346      "  </session>                                                    " \
347      "</iq>                                                           ");
348
349 const std::string kJingleVideoInitiate(
350      "<iq xmlns='jabber:client' from='me@domain.com/resource'           " \
351      "    to='user@domain.com/resource' type='set' id='123'>            " \
352      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
353      "          sid='abcdef' initiator='me@domain.com/resource'>        " \
354      "    <content name='test audio'>                                   " \
355      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
356      "        <payload-type id='103' name='ISAC' clockrate='16000'/>    " \
357      "      </description>                                              " \
358      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>   " \
359      "    </content>                                                    " \
360      "    <content name='test video'>                                   " \
361      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
362      "        <payload-type id='99' name='H264-SVC'>                    " \
363      "          <parameter name='height' value='200'/>                  " \
364      "          <parameter name='width' value='320'/>                   " \
365      "          <parameter name='framerate' value='30'/>                " \
366      "        </payload-type>                                           " \
367      "      </description>                                              " \
368      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>   " \
369      "    </content>                                                    " \
370      "  </jingle>                                                       " \
371      "</iq>                                                             ");
372
373 const std::string kJingleVideoInitiateWithRtpData(
374      "<iq xmlns='jabber:client' from='me@domain.com/resource'           " \
375      "    to='user@domain.com/resource' type='set' id='123'>            " \
376      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
377      "          sid='abcdef' initiator='me@domain.com/resource'>        " \
378      "    <content name='test audio'>                                   " \
379      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
380      "        <payload-type id='103' name='ISAC' clockrate='16000'/>    " \
381      "      </description>                                              " \
382      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>   " \
383      "    </content>                                                    " \
384      "    <content name='test video'>                                   " \
385      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
386      "        <payload-type id='99' name='H264-SVC'>                    " \
387      "          <parameter name='height' value='200'/>                  " \
388      "          <parameter name='width' value='320'/>                   " \
389      "          <parameter name='framerate' value='30'/>                " \
390      "        </payload-type>                                           " \
391      "      </description>                                              " \
392      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>   " \
393      "    </content>                                                    " \
394      "    <content name='test data'>                                    " \
395      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='data'> " \
396      "        <payload-type id='127' name='google-data'/>               " \
397      "        <rtcp-mux/>                                               " \
398      "      </description>                                              " \
399      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>   " \
400      "    </content>                                                    " \
401      "  </jingle>                                                       " \
402      "</iq>                                                             ");
403
404 const std::string kJingleVideoInitiateWithSctpData(
405      "<iq xmlns='jabber:client' from='me@domain.com/resource'           " \
406      "    to='user@domain.com/resource' type='set' id='123'>            " \
407      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
408      "          sid='abcdef' initiator='me@domain.com/resource'>        " \
409      "    <content name='test audio'>                                   " \
410      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
411      "        <payload-type id='103' name='ISAC' clockrate='16000'/>    " \
412      "      </description>                                              " \
413      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>   " \
414      "    </content>                                                    " \
415      "    <content name='test video'>                                   " \
416      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
417      "        <payload-type id='99' name='H264-SVC'>                    " \
418      "          <parameter name='height' value='200'/>                  " \
419      "          <parameter name='width' value='320'/>                   " \
420      "          <parameter name='framerate' value='30'/>                " \
421      "        </payload-type>                                           " \
422      "      </description>                                              " \
423      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>   " \
424      "    </content>                                                    " \
425      "    <content name='test data'>                                    " \
426      "      <description xmlns='google:jingle:sctp' media='data'>       " \
427      "        <stream sid='1'/>                                         " \
428      "      </description>                                              " \
429      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>   " \
430      "    </content>                                                    " \
431      "  </jingle>                                                       " \
432      "</iq>                                                             ");
433
434 const std::string kJingleVideoInitiateWithBandwidth(
435      "<iq xmlns='jabber:client' from='me@domain.com/resource'           " \
436      "    to='user@domain.com/resource' type='set' id='123'>            " \
437      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
438      "         sid='abcdef' initiator='me@domain.com/resource'>         " \
439      "    <content name='test audio'>                                   " \
440      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
441      "        <payload-type id='103' name='ISAC' clockrate='16000'/>    " \
442      "      </description>                                              " \
443      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>   " \
444      "    </content>                                                    " \
445      "    <content name='test video'>                                   " \
446      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
447      "        <payload-type id='99' name='H264-SVC'>                    " \
448      "          <parameter name='height' value='200'/>                  " \
449      "          <parameter name='width' value='320'/>                   " \
450      "          <parameter name='framerate' value='30'/>                " \
451      "        </payload-type>                                           " \
452      "        <bandwidth type='AS'>42</bandwidth>                       " \
453      "      </description>                                              " \
454      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>   " \
455      "    </content>                                                    " \
456      "  </jingle>                                                       " \
457      "</iq>                                                             ");
458
459 const std::string kJingleVideoInitiateWithRtcpMux(
460      "<iq xmlns='jabber:client' from='me@domain.com/resource'           " \
461      "    to='user@domain.com/resource' type='set' id='123'>            " \
462      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
463      "         sid='abcdef' initiator='me@domain.com/resource'>         " \
464      "    <content name='test audio'>                                   " \
465      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
466      "        <payload-type id='103' name='ISAC' clockrate='16000'/>    " \
467      "      </description>                                              " \
468      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>   " \
469      "    </content>                                                    " \
470      "    <content name='test video'>                                   " \
471      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
472      "        <payload-type id='99' name='H264-SVC'>                    " \
473      "          <parameter name='height' value='200'/>                  " \
474      "          <parameter name='width' value='320'/>                   " \
475      "          <parameter name='framerate' value='30'/>                " \
476      "        </payload-type>                                           " \
477      "        <rtcp-mux/>                                               " \
478      "      </description>                                              " \
479      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>   " \
480      "    </content>                                                    " \
481      "  </jingle>                                                       " \
482      "</iq>                                                             ");
483
484 // Initiate string with a combination of supported and unsupported codecs
485 // Should accept the supported ones
486 const std::string kGingleInitiateSomeUnsupported(
487      "<iq xmlns='jabber:client' from='me@domain.com/resource'         " \
488      "    to='user@domain.com/resource' type='set' id='123'>          " \
489      "  <session xmlns='http://www.google.com/session' type='initiate'" \
490      "    id='abcdef' initiator='me@domain.com/resource'>             " \
491      "    <description xmlns='http://www.google.com/session/phone'>   " \
492      "      <payload-type xmlns='http://www.google.com/session/phone' " \
493      "        id='103' name='ISAC' clockrate='16000' />               " \
494      "      <payload-type xmlns='http://www.google.com/session/phone' " \
495      "        id='97' name='ASDFDS' />                                " \
496      "      <payload-type xmlns='http://www.google.com/session/phone' " \
497      "        id='102' name='1010' />                                 " \
498      "      <payload-type xmlns='http://www.google.com/session/phone' " \
499      "        id='107' name='DFAS' />                                 " \
500      "      <payload-type xmlns='http://www.google.com/session/phone' " \
501      "        id='100' name='EG711U' />                               " \
502      "      <payload-type xmlns='http://www.google.com/session/phone' " \
503      "        id='101' name='EG711A' />                               " \
504      "      <payload-type xmlns='http://www.google.com/session/phone' " \
505      "        id='0' name='PCMU' />                                   " \
506      "      <payload-type xmlns='http://www.google.com/session/phone' " \
507      "        id='110' name=':)' />                                   " \
508      "      <payload-type xmlns='http://www.google.com/session/phone' " \
509      "        id='13' name='CN' />                                    " \
510      "    </description>                                              " \
511      "  </session>                                                    " \
512      "</iq>                                                           ");
513
514 const std::string kJingleInitiateSomeUnsupported(
515      "<iq xmlns='jabber:client' from='me@domain.com/resource'         " \
516      "    to='user@domain.com/resource' type='set' id='123'>          " \
517      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'   " \
518      "          sid='abcdef' initiator='me@domain.com/resource'>      " \
519      "    <content name='test audio'>                                 " \
520      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
521      "        <payload-type                                           " \
522      "          id='103' name='ISAC' clockrate='16000' />             " \
523      "        <payload-type                                           " \
524      "          id='97' name='ASDFDS' />                              " \
525      "        <payload-type                                           " \
526      "          id='102' name='1010' />                               " \
527      "        <payload-type                                           " \
528      "          id='107' name='DFAS' />                               " \
529      "        <payload-type                                           " \
530      "          id='100' name='EG711U' />                             " \
531      "        <payload-type                                           " \
532      "          id='101' name='EG711A' />                             " \
533      "        <payload-type                                           " \
534      "          id='0' name='PCMU' />                                 " \
535      "        <payload-type                                           " \
536      "          id='110' name=':)' />                                 " \
537      "        <payload-type                                           " \
538      "          id='13' name='CN' />                                  " \
539      "      </description>                                            " \
540      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
541      "    </content>                                                  " \
542      "  </jingle>                                                     " \
543      "</iq>                                                           ");
544
545 const std::string kGingleVideoInitiateWithBandwidth(
546      "<iq xmlns='jabber:client' from='me@domain.com/resource'         " \
547      "    to='user@domain.com/resource' type='set' id='123'>          " \
548      "  <session xmlns='http://www.google.com/session' type='initiate'" \
549      "    id='abcdef' initiator='me@domain.com/resource'>             " \
550      "    <description xmlns='http://www.google.com/session/video'>   " \
551      "      <payload-type xmlns='http://www.google.com/session/phone' " \
552      "        id='103' name='ISAC' clockrate='16000' />               " \
553      "      <payload-type xmlns='http://www.google.com/session/video' " \
554      "        id='99' name='H264-SVC' framerate='30'                  " \
555      "        height='200' width='320'/>                              " \
556      "      <bandwidth type='AS'>42</bandwidth>                       " \
557      "    </description>                                              " \
558      "  </session>                                                    " \
559      "</iq>                                                           ");
560
561 // Initiate string without any supported codecs. Should send a reject.
562 const std::string kGingleInitiateNoSupportedAudioCodecs(
563      "<iq xmlns='jabber:client' from='me@domain.com/resource'         " \
564      "    to='user@domain.com/resource' type='set' id='123'>          " \
565      "  <session xmlns='http://www.google.com/session' type='initiate'" \
566      "    id='abcdef' initiator='me@domain.com/resource'>             " \
567      "    <description xmlns='http://www.google.com/session/phone'>   " \
568      "      <payload-type xmlns='http://www.google.com/session/phone' " \
569      "        id='123' name='Supercodec6000' />                       " \
570      "    </description>                                              " \
571      "  </session>                                                    " \
572      "</iq>                                                           ");
573
574 const std::string kJingleInitiateNoSupportedAudioCodecs(
575      "<iq xmlns='jabber:client' from='me@domain.com/resource'         " \
576      "    to='user@domain.com/resource' type='set' id='123'>          " \
577      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'   " \
578      "          sid='abcdef' initiator='me@domain.com/resource'>      " \
579      "    <content name='test audio'>                                 " \
580      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
581      "        <payload-type                                           " \
582      "          id='123' name='Supercodec6000' />                     " \
583      "      </description>                                            " \
584      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>  " \
585      "    </content>                                                  " \
586      "  </jingle>                                                     " \
587      "</iq>                                                           ");
588
589 // Initiate string without any codecs. Assumes ancient version of Cricket
590 // and tries a session with ISAC and PCMU
591 const std::string kGingleInitiateNoAudioCodecs(
592      "<iq xmlns='jabber:client' from='me@domain.com/resource'         " \
593      "    to='user@domain.com/resource' type='set' id='123'>          " \
594      "  <session xmlns='http://www.google.com/session' type='initiate'" \
595      "    id='abcdef' initiator='me@domain.com/resource'>             " \
596      "    <description xmlns='http://www.google.com/session/phone'>   " \
597      "    </description>                                              " \
598      "  </session>                                                    " \
599      "</iq>                                                           ");
600
601 const std::string kJingleInitiateNoAudioCodecs(
602      "<iq xmlns='jabber:client' from='me@domain.com/resource'         " \
603      "    to='user@domain.com/resource' type='set' id='123'>          " \
604      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'   " \
605      "          sid='abcdef' initiator='me@domain.com/resource'>      " \
606      "    <content name='test audio'>                                 " \
607      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
608      "      </description>                                            " \
609      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>  " \
610      "    </content>                                                  " \
611      "  </jingle>                                                     " \
612      "</iq>                                                           ");
613
614 // The codecs are supported, but not at the given clockrates. Should send
615 // a reject.
616 const std::string kGingleInitiateWrongClockrates(
617      "<iq xmlns='jabber:client' from='me@domain.com/resource'         " \
618      "    to='user@domain.com/resource' type='set' id='123'>          " \
619      "  <session xmlns='http://www.google.com/session' type='initiate'" \
620      "    id='abcdef' initiator='me@domain.com/resource'>             " \
621      "    <description xmlns='http://www.google.com/session/phone'>   " \
622      "      <payload-type xmlns='http://www.google.com/session/phone' " \
623      "        id='103' name='ISAC' clockrate='8000'/>                 " \
624      "      <payload-type xmlns='http://www.google.com/session/phone' " \
625      "        id='97' name='IPCMWB' clockrate='1337'/>                " \
626      "      <payload-type xmlns='http://www.google.com/session/phone' " \
627      "        id='102' name='iLBC' clockrate='1982' />                " \
628      "    </description>                                              " \
629      "  </session>                                                    " \
630      "</iq>                                                           ");
631
632 const std::string kJingleInitiateWrongClockrates(
633      "<iq xmlns='jabber:client' from='me@domain.com/resource'           " \
634      "    to='user@domain.com/resource' type='set' id='123'>            " \
635      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
636      "          sid='abcdef' initiator='me@domain.com/resource'>        " \
637      "    <content name='test audio'>                                   " \
638      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
639      "        <payload-type                                             " \
640      "          id='103' name='ISAC' clockrate='8000'/>                 " \
641      "        <payload-type                                             " \
642      "          id='97' name='IPCMWB' clockrate='1337'/>                " \
643      "       <payload-type                                              " \
644      "          id='102' name='iLBC' clockrate='1982' />                " \
645      "      </description>                                              " \
646      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>  " \
647      "    </content>                                                    " \
648      "  </jingle>                                                       " \
649      "</iq>                                                             ");
650
651 // The codecs are supported, but not with the given number of channels.
652 // Should send a reject.
653 const std::string kGingleInitiateWrongChannels(
654      "<iq xmlns='jabber:client' from='me@domain.com/resource'         " \
655      "    to='user@domain.com/resource' type='set' id='123'>          " \
656      "  <session xmlns='http://www.google.com/session' type='initiate'" \
657      "    id='abcdef' initiator='me@domain.com/resource'>             " \
658      "    <description xmlns='http://www.google.com/session/phone'>   " \
659      "      <payload-type xmlns='http://www.google.com/session/phone' " \
660      "        id='103' name='ISAC' channels='2'/>                     " \
661      "      <payload-type xmlns='http://www.google.com/session/phone' " \
662      "        id='97' name='IPCMWB' channels='3'/>                    " \
663      "    </description>                                              " \
664      "  </session>                                                    " \
665      "</iq>                                                           ");
666
667 const std::string kJingleInitiateWrongChannels(
668      "<iq xmlns='jabber:client' from='me@domain.com/resource'           " \
669      "    to='user@domain.com/resource' type='set' id='123'>            " \
670      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'>    " \
671      "    <content name='test audio'>                                   " \
672      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
673      "        <payload-type                                             " \
674      "          id='103' name='ISAC' channels='2'/>                     " \
675      "        <payload-type                                             " \
676      "          id='97' name='IPCMWB' channels='3'/>                    " \
677      "      </description>                                              " \
678      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>   " \
679      "    </content>                                                    " \
680      "  </jingle>                                                       " \
681      "</iq>                                                             ");
682
683 // Initiate with a dynamic codec not using webrtc default payload id. Should
684 // accept with provided payload id.
685 const std::string kGingleInitiateDynamicAudioCodecs(
686      "<iq xmlns='jabber:client' from='me@domain.com/resource'         " \
687      "    to='user@domain.com/resource' type='set' id='123'>          " \
688      "  <session xmlns='http://www.google.com/session' type='initiate'" \
689      "    id='abcdef' initiator='me@domain.com/resource'>             " \
690      "    <description xmlns='http://www.google.com/session/phone'>   " \
691      "      <payload-type xmlns='http://www.google.com/session/phone' " \
692      "        id='123' name='speex' clockrate='16000'/>               " \
693      "    </description>                                              " \
694      "  </session>                                                    " \
695      "</iq>                                                           ");
696
697 const std::string kJingleInitiateDynamicAudioCodecs(
698      "<iq xmlns='jabber:client' from='me@domain.com/resource'           " \
699      "    to='user@domain.com/resource' type='set' id='123'>            " \
700      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
701      "          sid='abcdef' initiator='me@domain.com/resource'>        " \
702      "    <content name='test audio'>                                   " \
703      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
704      "        <payload-type                                             " \
705      "          id='123' name='speex' clockrate='16000'/>               " \
706      "      </description>                                              " \
707      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>   " \
708      "    </content>                                                    " \
709      "  </jingle>                                                       " \
710      "</iq>                                                             ");
711
712 // Initiate string with nothing but static codec id's. Should accept.
713 const std::string kGingleInitiateStaticAudioCodecs(
714      "<iq xmlns='jabber:client' from='me@domain.com/resource'         " \
715      "    to='user@domain.com/resource' type='set' id='123'>          " \
716      "  <session xmlns='http://www.google.com/session' type='initiate'" \
717      "    id='abcdef' initiator='me@domain.com/resource'>             " \
718      "    <description xmlns='http://www.google.com/session/phone'>   " \
719      "      <payload-type xmlns='http://www.google.com/session/phone' " \
720      "        id='3' />                                               " \
721      "      <payload-type xmlns='http://www.google.com/session/phone' " \
722      "        id='0' />                                               " \
723      "      <payload-type xmlns='http://www.google.com/session/phone' " \
724      "        id='8' />                                               " \
725      "    </description>                                              " \
726      "  </session>                                                    " \
727      "</iq>                                                           ");
728
729 const std::string kJingleInitiateStaticAudioCodecs(
730      "<iq xmlns='jabber:client' from='me@domain.com/resource'         " \
731      "    to='user@domain.com/resource' type='set' id='123'>          " \
732      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'   " \
733      "          sid='abcdef' initiator='me@domain.com/resource'>      " \
734      "    <content name='test audio'>                                 " \
735      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
736      "        <payload-type id='3' />                                 " \
737      "        <payload-type id='0' />                                 " \
738      "        <payload-type id='8' />                                 " \
739      "      </description>                                            " \
740      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
741      "    </content>                                                  " \
742      "  </jingle>                                                     " \
743      "</iq>                                                           ");
744
745 // Initiate with payload type-less codecs. Should reject.
746 const std::string kGingleInitiateNoPayloadTypes(
747      "<iq xmlns='jabber:client' from='me@domain.com/resource'         " \
748      "    to='user@domain.com/resource' type='set' id='123'>          " \
749      "  <session xmlns='http://www.google.com/session' type='initiate'" \
750      "    id='abcdef' initiator='me@domain.com/resource'>             " \
751      "    <description xmlns='http://www.google.com/session/phone'>   " \
752      "      <payload-type xmlns='http://www.google.com/session/phone' " \
753      "       name='ISAC' clockrate='16000'/>                          " \
754      "    </description>                                              " \
755      "  </session>                                                    " \
756      "</iq>                                                           ");
757
758 const std::string kJingleInitiateNoPayloadTypes(
759      "<iq xmlns='jabber:client' from='me@domain.com/resource'         " \
760      "    to='user@domain.com/resource' type='set' id='123'>          " \
761      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'>  " \
762      "          sid='abcdef' initiator='me@domain.com/resource'>      " \
763      "    <content name='test audio'>                                 " \
764      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
765      "        <payload-type  name='ISAC' clockrate='16000'/>          " \
766      "      </description>                                            " \
767      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
768      "    </content>                                                  " \
769      "  </jingle>                                                     " \
770      "</iq>                                                           ");
771
772 // Initiate with unnamed dynamic codces. Should reject.
773 const std::string kGingleInitiateDynamicWithoutNames(
774      "<iq xmlns='jabber:client' from='me@domain.com/resource'         " \
775      "    to='user@domain.com/resource' type='set' id='123'>          " \
776      "  <session xmlns='http://www.google.com/session' type='initiate'" \
777      "    id='abcdef' initiator='me@domain.com/resource'>             " \
778      "    <description xmlns='http://www.google.com/session/phone'>   " \
779      "      <payload-type xmlns='http://www.google.com/session/phone' " \
780      "       id='100' clockrate='16000'/>                             " \
781      "    </description>                                              " \
782      "  </session>                                                    " \
783      "</iq>                                                           ");
784
785 const std::string kJingleInitiateDynamicWithoutNames(
786      "<iq xmlns='jabber:client' from='me@domain.com/resource'         " \
787      "    to='user@domain.com/resource' type='set' id='123'>          " \
788      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'>  " \
789      "          sid='abcdef' initiator='me@domain.com/resource'>      " \
790      "    <content name='test audio'>                                 " \
791      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
792      "        <payload-type id='100' clockrate='16000'/>              " \
793      "      </description>                                            " \
794      "     <transport xmlns=\"http://www.google.com/transport/p2p\"/>  " \
795      "    </content>                                                  " \
796      "  </jingle>                                                     " \
797      "</iq>                                                           ");
798
799 const uint32 kAudioSsrc = 4294967295U;
800 const uint32 kVideoSsrc = 87654321;
801 const uint32 kDataSsrc = 1010101;
802 // Note that this message does not specify a session ID. It must be populated
803 // before use.
804 const std::string kGingleAcceptWithSsrcs(
805      "<iq xmlns='jabber:client' from='me@mydomain.com'                " \
806      "    to='user@domain.com/resource' type='set' id='150'>          " \
807      "  <session xmlns='http://www.google.com/session' type='accept'  " \
808      "    initiator='me@domain.com/resource'>                         " \
809      "    <description xmlns='http://www.google.com/session/video'>   " \
810      "      <payload-type xmlns='http://www.google.com/session/phone' " \
811      "        id='103' name='ISAC' clockrate='16000' />               " \
812      "      <payload-type xmlns='http://www.google.com/session/phone' " \
813      "        id='104' name='ISAC' clockrate='32000' />               " \
814      "      <src-id xmlns='http://www.google.com/session/phone'>      " \
815      "        4294967295</src-id>                                       " \
816      "      <src-id>87654321</src-id>                                 " \
817      "    </description>                                              " \
818      "  </session>                                                    " \
819      "</iq>                                                           ");
820
821 const std::string kJingleAcceptWithSsrcs(
822      "<iq xmlns='jabber:client' from='me@mydomain.com'                " \
823      "    to='user@domain.com/resource' type='set' id='150'>          " \
824      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-accept'     " \
825      "          initiator='me@domain.com/resource'>                   " \
826      "    <content name='audio'>                                      " \
827      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1'           " \
828      "          media='audio' ssrc='4294967295'>                      " \
829      "        <payload-type id='103' name='ISAC' clockrate='16000'/>  " \
830      "        <payload-type id='104' name='ISAC' clockrate='32000'/>  " \
831      "      </description>                                            " \
832      "     <transport xmlns='http://www.google.com/transport/p2p'/>   " \
833      "    </content>                                                  " \
834      "    <content name='video'>                                      " \
835      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1'           " \
836      "          media='video' ssrc='87654321'>                        " \
837      "      </description>                                            " \
838      "     <transport xmlns='http://www.google.com/transport/p2p'/>   " \
839      "    </content>                                                  " \
840      "  </jingle>                                                     " \
841      "</iq>                                                           ");
842
843 const std::string kJingleAcceptWithRtpDataSsrcs(
844      "<iq xmlns='jabber:client' from='me@mydomain.com'                " \
845      "    to='user@domain.com/resource' type='set' id='150'>          " \
846      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-accept'     " \
847      "          initiator='me@domain.com/resource'>                   " \
848      "    <content name='audio'>                                      " \
849      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1'           " \
850      "          media='audio' ssrc='4294967295'>                      " \
851      "        <payload-type id='103' name='ISAC' clockrate='16000'/>  " \
852      "        <payload-type id='104' name='ISAC' clockrate='32000'/>  " \
853      "      </description>                                            " \
854      "     <transport xmlns='http://www.google.com/transport/p2p'/>   " \
855      "    </content>                                                  " \
856      "    <content name='video'>                                      " \
857      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1'           " \
858      "          media='video' ssrc='87654321'>                        " \
859      "      </description>                                            " \
860      "     <transport xmlns='http://www.google.com/transport/p2p'/>   " \
861      "    </content>                                                  " \
862      "    <content name='data'>                                       " \
863      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1'           " \
864      "          media='data' ssrc='1010101'>                          " \
865      "      </description>                                            " \
866      "     <transport xmlns='http://www.google.com/transport/p2p'/>   " \
867      "    </content>                                                  " \
868      "  </jingle>                                                     " \
869      "</iq>                                                           ");
870
871 const std::string kJingleAcceptWithSctpData(
872      "<iq xmlns='jabber:client' from='me@mydomain.com'                " \
873      "    to='user@domain.com/resource' type='set' id='150'>          " \
874      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-accept'     " \
875      "          initiator='me@domain.com/resource'>                   " \
876      "    <content name='audio'>                                      " \
877      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1'           " \
878      "          media='audio' ssrc='4294967295'>                      " \
879      "        <payload-type id='103' name='ISAC' clockrate='16000'/>  " \
880      "        <payload-type id='104' name='ISAC' clockrate='32000'/>  " \
881      "      </description>                                            " \
882      "     <transport xmlns='http://www.google.com/transport/p2p'/>   " \
883      "    </content>                                                  " \
884      "    <content name='video'>                                      " \
885      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1'           " \
886      "          media='video' ssrc='87654321'>                        " \
887      "      </description>                                            " \
888      "     <transport xmlns='http://www.google.com/transport/p2p'/>   " \
889      "    </content>                                                  " \
890      "    <content name='data'>                                       " \
891      "      <description xmlns='google:jingle:sctp'>                  " \
892      "        <stream sid='1'/>                                       " \
893      "      </description>                                            " \
894      "     <transport xmlns='http://www.google.com/transport/p2p'/>   " \
895      "    </content>                                                  " \
896      "  </jingle>                                                     " \
897      "</iq>                                                           ");
898
899 std::string JingleView(const std::string& ssrc,
900                        const std::string& width,
901                        const std::string& height,
902                        const std::string& framerate) {
903   // We have some slightly weird whitespace formatting to make the
904   // actual XML generated match the expected XML here.
905   return \
906       "<cli:iq"
907       "  to='me@mydomain.com'"
908       "  type='set'"
909       "  xmlns:cli='jabber:client'>"
910         "<jingle"
911       "    xmlns='urn:xmpp:jingle:1'"
912       "    action='session-info'"
913       "    sid=''>"
914           "<view xmlns='google:jingle'"
915       "      name='video'"
916       "      type='static'"
917       "      ssrc='" + ssrc + "'>"
918             "<params"
919       "        width='" + width + "'"
920       "        height='" + height + "'"
921       "        framerate='" + framerate + "'"
922       "        preference='0'/>"
923           "</view>"
924         "</jingle>"
925       "</cli:iq>";
926 }
927
928 std::string JingleStreamAdd(const std::string& content_name,
929                             const std::string& nick,
930                             const std::string& name,
931                             const std::string& ssrc) {
932   return \
933       "<iq"
934       "  xmlns='jabber:client'"
935       "  from='me@mydomain.com'"
936       "  to='user@domain.com/resource'"
937       "  type='set'"
938       "  id='150'>"
939       "  <jingle"
940       "    xmlns='urn:xmpp:jingle:1'"
941       "    action='description-info'>"
942       "    <content"
943       "      xmlns='urn:xmpp:jingle:1'"
944       "      name='" + content_name + "'>"
945       "      <description"
946       "        xmlns='urn:xmpp:jingle:apps:rtp:1'"
947       "        media='" + content_name + "'>"
948       "        <streams"
949       "          xmlns='google:jingle'>"
950       "          <stream"
951       "            nick='" + nick + "'"
952       "            name='" + name + "'>"
953       "            <ssrc>"  + ssrc + "</ssrc>"
954       "          </stream>"
955       "        </streams>"
956       "      </description>"
957       "    </content>"
958       "  </jingle>"
959       "</iq>";
960 }
961
962 std::string JingleOutboundStreamRemove(const std::string& sid,
963                                        const std::string& content_name,
964                                        const std::string& name) {
965   return \
966       "<cli:iq"
967       " to='me@mydomain.com'"
968       " type='set'"
969       " xmlns:cli='jabber:client'>"
970       "<jingle"
971       " xmlns='urn:xmpp:jingle:1'"
972       " action='description-info'"
973       " sid='" + sid + "'>"
974       "<content"
975       " name='" + content_name + "'"
976       " creator='initiator'>"
977       "<description"
978       " xmlns='urn:xmpp:jingle:apps:rtp:1'"
979       " media='" + content_name + "'>"
980       "<streams"
981       " xmlns='google:jingle'>"
982       "<stream"
983       " name='" + name + "'>"
984       "</stream>"
985       "</streams>"
986       "</description>"
987       "</content>"
988       "</jingle>"
989       "</cli:iq>";
990 }
991
992 std::string JingleOutboundStreamAdd(const std::string& sid,
993                                     const std::string& content_name,
994                                     const std::string& name,
995                                     const std::string& ssrc) {
996   return \
997       "<cli:iq"
998       " to='me@mydomain.com'"
999       " type='set'"
1000       " xmlns:cli='jabber:client'>"
1001       "<jingle"
1002       " xmlns='urn:xmpp:jingle:1'"
1003       " action='description-info'"
1004       " sid='" + sid + "'>"
1005       "<content"
1006       " name='" + content_name + "'"
1007       " creator='initiator'>"
1008       "<description"
1009       " xmlns='urn:xmpp:jingle:apps:rtp:1'"
1010       " media='" + content_name + "'>"
1011       "<streams"
1012       " xmlns='google:jingle'>"
1013       "<stream"
1014       " name='" + name + "'>"
1015       "<ssrc>" + ssrc + "</ssrc>"
1016       "</stream>"
1017       "</streams>"
1018       "</description>"
1019       "</content>"
1020       "</jingle>"
1021       "</cli:iq>";
1022 }
1023
1024 std::string JingleStreamAddWithoutSsrc(const std::string& content_name,
1025                                        const std::string& nick,
1026                                        const std::string& name) {
1027   return \
1028       "<iq"
1029       "  xmlns='jabber:client'"
1030       "  from='me@mydomain.com'"
1031       "  to='user@domain.com/resource'"
1032       "  type='set'"
1033       "  id='150'>"
1034       "  <jingle"
1035       "    xmlns='urn:xmpp:jingle:1'"
1036       "    action='description-info'>"
1037       "    <content"
1038       "      xmlns='urn:xmpp:jingle:1'"
1039       "      name='" + content_name + "'>"
1040       "      <description"
1041       "        xmlns='urn:xmpp:jingle:apps:rtp:1'"
1042       "        media='" + content_name + "'>"
1043       "        <streams"
1044       "          xmlns='google:jingle'>"
1045       "          <stream"
1046       "            nick='" + nick + "'"
1047       "            name='" + name + "'>"
1048        "          </stream>"
1049       "        </streams>"
1050       "      </description>"
1051       "    </content>"
1052       "  </jingle>"
1053       "</iq>";
1054 }
1055
1056 std::string JingleStreamRemove(const std::string& content_name,
1057                                const std::string& nick,
1058                                const std::string& name) {
1059   return \
1060       "<iq"
1061       "  xmlns='jabber:client'"
1062       "  from='me@mydomain.com'"
1063       "  to='user@domain.com/resource'"
1064       "  type='set'"
1065       "  id='150'>"
1066       "  <jingle"
1067       "    xmlns='urn:xmpp:jingle:1'"
1068       "    action='description-info'>"
1069       "    <content"
1070       "      xmlns='urn:xmpp:jingle:1'"
1071       "      name='" + content_name + "'>"
1072       "      <description"
1073       "        xmlns='urn:xmpp:jingle:apps:rtp:1'"
1074       "        media='" + content_name + "'>"
1075       "        <streams"
1076       "          xmlns='google:jingle'>"
1077       "          <stream"
1078       "            nick='" + nick + "'"
1079       "            name='" + name + "'/>"
1080       "        </streams>"
1081       "      </description>"
1082       "    </content>"
1083       "  </jingle>"
1084       "</iq>";
1085 }
1086
1087 // Convenience function to get CallOptions that have audio enabled,
1088 // but not video or data.
1089 static cricket::CallOptions AudioCallOptions() {
1090   cricket::CallOptions options;
1091   options.recv_audio = true;
1092   options.recv_video = false;
1093   options.data_channel_type = cricket::DCT_NONE;
1094   return options;
1095 }
1096
1097 // Convenience function to get CallOptions that have audio and video
1098 // enabled, but not data.
1099 static cricket::CallOptions VideoCallOptions() {
1100   cricket::CallOptions options;
1101   options.recv_audio = true;
1102   options.recv_video = true;
1103   options.data_channel_type = cricket::DCT_NONE;
1104   return options;
1105 }
1106
1107 static buzz::XmlElement* CopyElement(const buzz::XmlElement* elem) {
1108   return new buzz::XmlElement(*elem);
1109 }
1110
1111 static std::string AddEncryption(std::string stanza, std::string encryption) {
1112   std::string::size_type pos = stanza.find("</description>");
1113   while (pos != std::string::npos) {
1114       stanza = stanza.insert(pos, encryption);
1115       pos = stanza.find("</description>", pos + encryption.length() + 1);
1116   }
1117   return stanza;
1118 }
1119
1120 static int IntFromJingleCodecParameter(const buzz::XmlElement* parameter,
1121                                        const std::string& expected_name) {
1122   if (parameter) {
1123     const std::string& actual_name =
1124         parameter->Attr(cricket::QN_PAYLOADTYPE_PARAMETER_NAME);
1125
1126     EXPECT_EQ(expected_name, actual_name)
1127         << "wrong parameter name.  Expected '"
1128         << expected_name << "'. Actually '"
1129         << actual_name << "'.";
1130
1131     return atoi(parameter->Attr(
1132         cricket::QN_PAYLOADTYPE_PARAMETER_VALUE).c_str());
1133   }
1134   return 0;
1135 }
1136
1137 template <class CodecClass, class DescriptionClass>
1138 static void VerifyCodecFbParams(const FeedbackParams& expected,
1139                                 const DescriptionClass* desc) {
1140   if (!expected.params().empty()) {
1141     ASSERT_TRUE(desc != NULL);
1142     const std::vector<CodecClass> codecs = desc->codecs();
1143     for (size_t i = 0; i < codecs.size(); ++i) {
1144       EXPECT_EQ(expected, codecs[i].feedback_params);
1145     }
1146   }
1147 }
1148
1149 // Parses and extracts payload and codec info from test XML.  Since
1150 // that XML will be in various contents (Gingle and Jingle), we need an
1151 // abstract parser with one concrete implementation per XML content.
1152 class MediaSessionTestParser {
1153  public:
1154   virtual buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) = 0;
1155   virtual buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) = 0;
1156   virtual buzz::XmlElement* NextContent(buzz::XmlElement* content) = 0;
1157   virtual buzz::XmlElement* PayloadTypeFromContent(
1158       buzz::XmlElement* content) = 0;
1159   virtual buzz::XmlElement* NextFromPayloadType(
1160       buzz::XmlElement* payload_type) = 0;
1161   virtual cricket::AudioCodec AudioCodecFromPayloadType(
1162       const buzz::XmlElement* payload_type) = 0;
1163   virtual cricket::VideoCodec VideoCodecFromPayloadType(
1164       const buzz::XmlElement* payload_type) = 0;
1165   virtual cricket::DataCodec DataCodecFromPayloadType(
1166       const buzz::XmlElement* payload_type) = 0;
1167   virtual buzz::XmlElement* EncryptionFromContent(
1168       buzz::XmlElement* content) = 0;
1169   virtual buzz::XmlElement* NextFromEncryption(
1170       buzz::XmlElement* encryption) = 0;
1171   virtual const buzz::XmlElement* BandwidthFromContent(
1172       buzz::XmlElement* content) = 0;
1173   virtual const buzz::XmlElement* RtcpMuxFromContent(
1174       buzz::XmlElement* content) = 0;
1175   virtual bool ActionIsTerminate(const buzz::XmlElement* action) = 0;
1176   virtual ~MediaSessionTestParser() {}
1177 };
1178
1179 class JingleSessionTestParser : public MediaSessionTestParser {
1180  public:
1181   JingleSessionTestParser() {}
1182
1183   ~JingleSessionTestParser() {
1184   }
1185
1186   buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
1187     return stanza->FirstNamed(cricket::QN_JINGLE);
1188   }
1189
1190   buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) {
1191     // We need to be able to use multiple contents, but the action
1192     // gets deleted before we can call NextContent, so we need to
1193     // stash away a copy.
1194     action_.reset(CopyElement(action));
1195     return action_->FirstNamed(cricket::QN_JINGLE_CONTENT);
1196   }
1197
1198   buzz::XmlElement* NextContent(buzz::XmlElement* content) {
1199     // For some reason, content->NextNamed(cricket::QN_JINGLE_CONTENT)
1200     // doesn't work.
1201     return action_->FirstNamed(cricket::QN_JINGLE_CONTENT)
1202         ->NextNamed(cricket::QN_JINGLE_CONTENT);
1203   }
1204
1205   buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* content) {
1206     buzz::XmlElement* content_desc =
1207         content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
1208     if (!content_desc)
1209       return NULL;
1210
1211     return content_desc->FirstNamed(cricket::QN_JINGLE_RTP_PAYLOADTYPE);
1212   }
1213
1214   buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
1215     return payload_type->NextNamed(cricket::QN_JINGLE_RTP_PAYLOADTYPE);
1216   }
1217
1218   void ParsePayloadTypeFeedbackParameters(const buzz::XmlElement* element,
1219                                           FeedbackParams* params) {
1220     const buzz::XmlElement* param =
1221         element->FirstNamed(cricket::QN_JINGLE_RTCP_FB);
1222     for (; param != NULL;
1223          param = param->NextNamed(cricket::QN_JINGLE_RTCP_FB)) {
1224       std::string type  = param->Attr(cricket::QN_TYPE);
1225       std::string subtype = param->Attr(cricket::QN_SUBTYPE);
1226       if (!type.empty()) {
1227         params->Add(FeedbackParam(type, subtype));
1228       }
1229     }
1230   }
1231
1232   cricket::AudioCodec AudioCodecFromPayloadType(
1233       const buzz::XmlElement* payload_type) {
1234     int id = 0;
1235     if (payload_type->HasAttr(cricket::QN_ID))
1236       id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1237
1238     std::string name;
1239     if (payload_type->HasAttr(cricket::QN_NAME))
1240       name = payload_type->Attr(cricket::QN_NAME);
1241
1242     int clockrate = 0;
1243     if (payload_type->HasAttr(cricket::QN_CLOCKRATE))
1244       clockrate = atoi(payload_type->Attr(cricket::QN_CLOCKRATE).c_str());
1245
1246     int bitrate = IntFromJingleCodecParameter(
1247         payload_type->FirstNamed(cricket::QN_PARAMETER), "bitrate");
1248
1249     int channels = 1;
1250     if (payload_type->HasAttr(cricket::QN_CHANNELS))
1251       channels = atoi(payload_type->Attr(
1252           cricket::QN_CHANNELS).c_str());
1253
1254     AudioCodec codec = AudioCodec(id, name, clockrate, bitrate, channels, 0);
1255     ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params);
1256     return codec;
1257   }
1258
1259   cricket::VideoCodec VideoCodecFromPayloadType(
1260       const buzz::XmlElement* payload_type) {
1261     int id = 0;
1262     if (payload_type->HasAttr(cricket::QN_ID))
1263       id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1264
1265     std::string name;
1266     if (payload_type->HasAttr(cricket::QN_NAME))
1267       name = payload_type->Attr(cricket::QN_NAME);
1268
1269     int width = 0;
1270     int height = 0;
1271     int framerate = 0;
1272     const buzz::XmlElement* param =
1273         payload_type->FirstNamed(cricket::QN_PARAMETER);
1274     if (param) {
1275       width = IntFromJingleCodecParameter(param, "width");
1276       param = param->NextNamed(cricket::QN_PARAMETER);
1277       if (param) {
1278         height = IntFromJingleCodecParameter(param, "height");
1279         param = param->NextNamed(cricket::QN_PARAMETER);
1280         if (param) {
1281           framerate = IntFromJingleCodecParameter(param, "framerate");
1282         }
1283       }
1284     }
1285     VideoCodec codec = VideoCodec(id, name, width, height, framerate, 0);
1286     ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params);
1287     return codec;
1288   }
1289
1290   cricket::DataCodec DataCodecFromPayloadType(
1291       const buzz::XmlElement* payload_type) {
1292     int id = 0;
1293     if (payload_type->HasAttr(cricket::QN_ID))
1294       id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1295
1296     std::string name;
1297     if (payload_type->HasAttr(cricket::QN_NAME))
1298       name = payload_type->Attr(cricket::QN_NAME);
1299
1300     DataCodec codec = DataCodec(id, name, 0);
1301     ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params);
1302     return codec;
1303   }
1304
1305   bool ActionIsTerminate(const buzz::XmlElement* action) {
1306     return (action->HasAttr(cricket::QN_ACTION) &&
1307             action->Attr(cricket::QN_ACTION) == "session-terminate");
1308   }
1309
1310   buzz::XmlElement* EncryptionFromContent(buzz::XmlElement* content) {
1311     buzz::XmlElement* content_desc =
1312         content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
1313     if (!content_desc)
1314       return NULL;
1315
1316     return content_desc->FirstNamed(cricket::QN_ENCRYPTION);
1317   }
1318
1319   buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
1320     return encryption->NextNamed(cricket::QN_ENCRYPTION);
1321   }
1322
1323   const buzz::XmlElement* BandwidthFromContent(buzz::XmlElement* content) {
1324     buzz::XmlElement* content_desc =
1325         content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
1326     if (!content_desc)
1327       return NULL;
1328
1329     return content_desc->FirstNamed(cricket::QN_JINGLE_RTP_BANDWIDTH);
1330   }
1331
1332   const buzz::XmlElement* RtcpMuxFromContent(buzz::XmlElement* content) {
1333     return content->FirstNamed(cricket::QN_JINGLE_RTCP_MUX);
1334   }
1335
1336  private:
1337   rtc::scoped_ptr<buzz::XmlElement> action_;
1338 };
1339
1340 class GingleSessionTestParser : public MediaSessionTestParser {
1341  public:
1342   GingleSessionTestParser() : found_content_count_(0) {}
1343
1344   buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
1345     return stanza->FirstNamed(cricket::QN_GINGLE_SESSION);
1346   }
1347
1348   buzz::XmlElement* ContentFromAction(buzz::XmlElement* session) {
1349     buzz::XmlElement* content =
1350         session->FirstNamed(cricket::QN_GINGLE_AUDIO_CONTENT);
1351     if (content == NULL)
1352       content = session->FirstNamed(cricket::QN_GINGLE_VIDEO_CONTENT);
1353     return content;
1354   }
1355
1356   // Assumes contents are in order of audio, and then video.
1357   buzz::XmlElement* NextContent(buzz::XmlElement* content) {
1358     found_content_count_++;
1359     return content;
1360   }
1361
1362   buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* content) {
1363     if (found_content_count_ > 0) {
1364       return content->FirstNamed(cricket::QN_GINGLE_VIDEO_PAYLOADTYPE);
1365     } else {
1366       return content->FirstNamed(cricket::QN_GINGLE_AUDIO_PAYLOADTYPE);
1367     }
1368   }
1369
1370   buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
1371     if (found_content_count_ > 0) {
1372       return payload_type->NextNamed(cricket::QN_GINGLE_VIDEO_PAYLOADTYPE);
1373     } else {
1374       return payload_type->NextNamed(cricket::QN_GINGLE_AUDIO_PAYLOADTYPE);
1375     }
1376   }
1377
1378   cricket::AudioCodec AudioCodecFromPayloadType(
1379       const buzz::XmlElement* payload_type) {
1380     int id = 0;
1381     if (payload_type->HasAttr(cricket::QN_ID))
1382       id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1383
1384     std::string name;
1385     if (payload_type->HasAttr(cricket::QN_NAME))
1386       name = payload_type->Attr(cricket::QN_NAME);
1387
1388     int clockrate = 0;
1389     if (payload_type->HasAttr(cricket::QN_CLOCKRATE))
1390       clockrate = atoi(payload_type->Attr(cricket::QN_CLOCKRATE).c_str());
1391
1392     int bitrate = 0;
1393     if (payload_type->HasAttr(cricket::QN_BITRATE))
1394       bitrate = atoi(payload_type->Attr(cricket::QN_BITRATE).c_str());
1395
1396     int channels = 1;
1397     if (payload_type->HasAttr(cricket::QN_CHANNELS))
1398       channels = atoi(payload_type->Attr(cricket::QN_CHANNELS).c_str());
1399
1400     return cricket::AudioCodec(id, name, clockrate, bitrate, channels, 0);
1401   }
1402
1403   cricket::VideoCodec VideoCodecFromPayloadType(
1404       const buzz::XmlElement* payload_type) {
1405     int id = 0;
1406     if (payload_type->HasAttr(cricket::QN_ID))
1407       id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
1408
1409     std::string name;
1410     if (payload_type->HasAttr(cricket::QN_NAME))
1411       name = payload_type->Attr(cricket::QN_NAME);
1412
1413     int width = 0;
1414     if (payload_type->HasAttr(cricket::QN_WIDTH))
1415       width = atoi(payload_type->Attr(cricket::QN_WIDTH).c_str());
1416
1417     int height = 0;
1418     if (payload_type->HasAttr(cricket::QN_HEIGHT))
1419       height = atoi(payload_type->Attr(cricket::QN_HEIGHT).c_str());
1420
1421     int framerate = 1;
1422     if (payload_type->HasAttr(cricket::QN_FRAMERATE))
1423       framerate = atoi(payload_type->Attr(cricket::QN_FRAMERATE).c_str());
1424
1425     return cricket::VideoCodec(id, name, width, height, framerate, 0);
1426   }
1427
1428   cricket::DataCodec DataCodecFromPayloadType(
1429       const buzz::XmlElement* payload_type) {
1430     // Gingle can't do data codecs.
1431     return cricket::DataCodec(0, "", 0);
1432   }
1433
1434   buzz::XmlElement* EncryptionFromContent(
1435       buzz::XmlElement* content) {
1436     return content->FirstNamed(cricket::QN_ENCRYPTION);
1437   }
1438
1439   buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
1440     return encryption->NextNamed(cricket::QN_ENCRYPTION);
1441   }
1442
1443   const buzz::XmlElement* BandwidthFromContent(buzz::XmlElement* content) {
1444     return content->FirstNamed(cricket::QN_GINGLE_VIDEO_BANDWIDTH);
1445   }
1446
1447   const buzz::XmlElement* RtcpMuxFromContent(buzz::XmlElement* content) {
1448     return NULL;
1449   }
1450
1451   bool ActionIsTerminate(const buzz::XmlElement* session) {
1452     return (session->HasAttr(buzz::QN_TYPE) &&
1453             session->Attr(buzz::QN_TYPE) == "terminate");
1454   }
1455
1456   int found_content_count_;
1457 };
1458
1459 class MediaSessionClientTest : public sigslot::has_slots<> {
1460  public:
1461   explicit MediaSessionClientTest(MediaSessionTestParser* parser,
1462                                   cricket::SignalingProtocol initial_protocol) {
1463     nm_ = new rtc::BasicNetworkManager();
1464     pa_ = new cricket::BasicPortAllocator(nm_);
1465     sm_ = new cricket::SessionManager(pa_, NULL);
1466     fme_ = new cricket::FakeMediaEngine();
1467     fdme_ = new cricket::FakeDataEngine();
1468
1469     FeedbackParams params_nack_fir;
1470     params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamCcm,
1471                                       cricket::kRtcpFbCcmParamFir));
1472     params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamNack));
1473     FeedbackParams params_nack;
1474     params_nack.Add(FeedbackParam(cricket::kRtcpFbParamNack));
1475
1476     std::vector<cricket::AudioCodec>
1477         audio_codecs(kAudioCodecs, kAudioCodecs + ARRAY_SIZE(kAudioCodecs));
1478     SetCodecFeedbackParams(&audio_codecs, params_nack);
1479     fme_->SetAudioCodecs(audio_codecs);
1480     std::vector<cricket::VideoCodec>
1481         video_codecs(kVideoCodecs, kVideoCodecs + ARRAY_SIZE(kVideoCodecs));
1482     SetCodecFeedbackParams(&video_codecs, params_nack_fir);
1483     fme_->SetVideoCodecs(video_codecs);
1484     std::vector<cricket::DataCodec>
1485         data_codecs(kDataCodecs, kDataCodecs + ARRAY_SIZE(kDataCodecs));
1486     SetCodecFeedbackParams(&data_codecs, params_nack);
1487     fdme_->SetDataCodecs(data_codecs);
1488
1489     client_ = new cricket::MediaSessionClient(
1490         buzz::Jid("user@domain.com/resource"), sm_,
1491         fme_, fdme_, new cricket::FakeDeviceManager());
1492     client_->session_manager()->SignalOutgoingMessage.connect(
1493         this, &MediaSessionClientTest::OnSendStanza);
1494     client_->session_manager()->SignalSessionCreate.connect(
1495         this, &MediaSessionClientTest::OnSessionCreate);
1496     client_->SignalCallCreate.connect(
1497         this, &MediaSessionClientTest::OnCallCreate);
1498     client_->SignalCallDestroy.connect(
1499         this, &MediaSessionClientTest::OnCallDestroy);
1500
1501     call_ = NULL;
1502     parser_ = parser;
1503     initial_protocol_ = initial_protocol;
1504     expect_incoming_crypto_ = false;
1505     expect_outgoing_crypto_ = false;
1506     expected_video_bandwidth_ = cricket::kAutoBandwidth;
1507     expected_video_rtcp_mux_ = false;
1508   }
1509
1510   ~MediaSessionClientTest() {
1511     delete client_;
1512     delete sm_;
1513     delete pa_;
1514     delete nm_;
1515     delete parser_;
1516     ClearStanzas();
1517   }
1518
1519   buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
1520     return parser_->ActionFromStanza(stanza);
1521   }
1522
1523   buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) {
1524     return parser_->ContentFromAction(action);
1525   }
1526
1527   buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* payload) {
1528     return parser_->PayloadTypeFromContent(payload);
1529   }
1530
1531   buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
1532     return parser_->NextFromPayloadType(payload_type);
1533   }
1534
1535   buzz::XmlElement* EncryptionFromContent(buzz::XmlElement* content) {
1536     return parser_->EncryptionFromContent(content);
1537   }
1538
1539   buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
1540     return parser_->NextFromEncryption(encryption);
1541   }
1542
1543   cricket::AudioCodec AudioCodecFromPayloadType(
1544       const buzz::XmlElement* payload_type) {
1545     return parser_->AudioCodecFromPayloadType(payload_type);
1546   }
1547
1548   cricket::VideoCodec VideoCodecFromPayloadType(
1549       const buzz::XmlElement* payload_type) {
1550     return parser_->VideoCodecFromPayloadType(payload_type);
1551   }
1552
1553   cricket::DataCodec DataCodecFromPayloadType(
1554       const buzz::XmlElement* payload_type) {
1555     return parser_->DataCodecFromPayloadType(payload_type);
1556   }
1557
1558   const AudioContentDescription* GetFirstAudioContentDescription(
1559       const cricket::SessionDescription* sdesc) {
1560     const cricket::ContentInfo* content =
1561         cricket::GetFirstAudioContent(sdesc);
1562     if (content == NULL)
1563       return NULL;
1564     return static_cast<const AudioContentDescription*>(content->description);
1565   }
1566
1567   const cricket::VideoContentDescription* GetFirstVideoContentDescription(
1568       const cricket::SessionDescription* sdesc) {
1569     const cricket::ContentInfo* content =
1570         cricket::GetFirstVideoContent(sdesc);
1571     if (content == NULL)
1572       return NULL;
1573     return static_cast<const cricket::VideoContentDescription*>(
1574         content->description);
1575   }
1576
1577   void CheckCryptoFromGoodIncomingInitiate(const cricket::Session* session) {
1578     ASSERT_TRUE(session != NULL);
1579     const AudioContentDescription* content =
1580         GetFirstAudioContentDescription(session->remote_description());
1581     ASSERT_TRUE(content != NULL);
1582     ASSERT_EQ(2U, content->cryptos().size());
1583     ASSERT_EQ(145, content->cryptos()[0].tag);
1584     ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", content->cryptos()[0].cipher_suite);
1585     ASSERT_EQ("inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9",
1586               content->cryptos()[0].key_params);
1587     ASSERT_EQ(51, content->cryptos()[1].tag);
1588     ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", content->cryptos()[1].cipher_suite);
1589     ASSERT_EQ("inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy",
1590               content->cryptos()[1].key_params);
1591   }
1592
1593   void CheckCryptoForGoodOutgoingAccept(const cricket::Session* session) {
1594     const AudioContentDescription* content =
1595         GetFirstAudioContentDescription(session->local_description());
1596     ASSERT_EQ(1U, content->cryptos().size());
1597     ASSERT_EQ(145, content->cryptos()[0].tag);
1598     ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", content->cryptos()[0].cipher_suite);
1599     ASSERT_EQ(47U, content->cryptos()[0].key_params.size());
1600   }
1601
1602   void CheckBadCryptoFromIncomingInitiate(const cricket::Session* session) {
1603     const AudioContentDescription* content =
1604         GetFirstAudioContentDescription(session->remote_description());
1605     ASSERT_EQ(1U, content->cryptos().size());
1606     ASSERT_EQ(145, content->cryptos()[0].tag);
1607     ASSERT_EQ("NOT_SUPPORTED", content->cryptos()[0].cipher_suite);
1608     ASSERT_EQ("inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9",
1609               content->cryptos()[0].key_params);
1610   }
1611
1612   void CheckNoCryptoForOutgoingAccept(const cricket::Session* session) {
1613     const AudioContentDescription* content =
1614         GetFirstAudioContentDescription(session->local_description());
1615     ASSERT_TRUE(content->cryptos().empty());
1616   }
1617
1618   void CheckRtcpFb(const cricket::SessionDescription* sdesc) {
1619     VerifyCodecFbParams<AudioCodec>(expected_audio_fb_params_,
1620                                     GetFirstAudioContentDescription(sdesc));
1621
1622     VerifyCodecFbParams<VideoCodec>(expected_video_fb_params_,
1623                                     GetFirstVideoContentDescription(sdesc));
1624
1625     VerifyCodecFbParams<DataCodec>(expected_data_fb_params_,
1626                                    GetFirstDataContentDescription(sdesc));
1627   }
1628
1629   void CheckVideoBandwidth(int expected_bandwidth,
1630                            const cricket::SessionDescription* sdesc) {
1631     const cricket::VideoContentDescription* video =
1632         GetFirstVideoContentDescription(sdesc);
1633     if (video != NULL) {
1634       ASSERT_EQ(expected_bandwidth, video->bandwidth());
1635     }
1636   }
1637
1638   void CheckVideoRtcpMux(bool expected_video_rtcp_mux,
1639                          const cricket::SessionDescription* sdesc) {
1640     const cricket::VideoContentDescription* video =
1641         GetFirstVideoContentDescription(sdesc);
1642     if (video != NULL) {
1643       ASSERT_EQ(expected_video_rtcp_mux, video->rtcp_mux());
1644     }
1645   }
1646
1647   virtual void CheckRtpDataContent(buzz::XmlElement* content) {
1648     if (initial_protocol_) {
1649       // Gingle can not write out data content.
1650       return;
1651     }
1652
1653     buzz::XmlElement* e = PayloadTypeFromContent(content);
1654     ASSERT_TRUE(e != NULL);
1655     cricket::DataCodec codec = DataCodecFromPayloadType(e);
1656     EXPECT_EQ(127, codec.id);
1657     EXPECT_EQ("google-data", codec.name);
1658     EXPECT_EQ(expected_data_fb_params_, codec.feedback_params);
1659
1660     CheckDataRtcpMux(true, call_->sessions()[0]->local_description());
1661     CheckDataRtcpMux(true, call_->sessions()[0]->remote_description());
1662     if (expect_outgoing_crypto_) {
1663       content = parser_->NextContent(content);
1664       buzz::XmlElement* encryption = EncryptionFromContent(content);
1665       ASSERT_TRUE(encryption != NULL);
1666       // TODO(pthatcher): Check encryption parameters?
1667     }
1668   }
1669
1670   virtual void CheckSctpDataContent(buzz::XmlElement* content) {
1671     if (initial_protocol_) {
1672       // Gingle can not write out data content.
1673       return;
1674     }
1675
1676     buzz::XmlElement* payload_type = PayloadTypeFromContent(content);
1677     ASSERT_TRUE(payload_type == NULL);
1678     buzz::XmlElement* encryption = EncryptionFromContent(content);
1679     ASSERT_TRUE(encryption == NULL);
1680     // TODO(pthatcher): Check for <streams>.
1681   }
1682
1683   void CheckDataRtcpMux(bool expected_data_rtcp_mux,
1684                         const cricket::SessionDescription* sdesc) {
1685     const cricket::DataContentDescription* data =
1686         GetFirstDataContentDescription(sdesc);
1687     if (data != NULL) {
1688       ASSERT_EQ(expected_data_rtcp_mux, data->rtcp_mux());
1689     }
1690   }
1691
1692   void CheckAudioSsrcForIncomingAccept(const cricket::Session* session) {
1693     const AudioContentDescription* audio =
1694         GetFirstAudioContentDescription(session->remote_description());
1695     ASSERT_TRUE(audio != NULL);
1696     ASSERT_EQ(kAudioSsrc, audio->first_ssrc());
1697   }
1698
1699   void CheckVideoSsrcForIncomingAccept(const cricket::Session* session) {
1700     const cricket::VideoContentDescription* video =
1701         GetFirstVideoContentDescription(session->remote_description());
1702     ASSERT_TRUE(video != NULL);
1703     ASSERT_EQ(kVideoSsrc, video->first_ssrc());
1704   }
1705
1706   void CheckDataSsrcForIncomingAccept(const cricket::Session* session) {
1707     const cricket::DataContentDescription* data =
1708         GetFirstDataContentDescription(session->remote_description());
1709     ASSERT_TRUE(data != NULL);
1710     ASSERT_EQ(kDataSsrc, data->first_ssrc());
1711   }
1712
1713   void TestGoodIncomingInitiate(const std::string& initiate_string,
1714                                 const cricket::CallOptions& options,
1715                                 buzz::XmlElement** element) {
1716     *element = NULL;
1717
1718     rtc::scoped_ptr<buzz::XmlElement> el(
1719         buzz::XmlElement::ForStr(initiate_string));
1720     client_->session_manager()->OnIncomingMessage(el.get());
1721     ASSERT_TRUE(call_ != NULL);
1722     ASSERT_TRUE(call_->sessions()[0] != NULL);
1723     ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE,
1724               call_->sessions()[0]->state());
1725     ASSERT_EQ(1U, stanzas_.size());
1726     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1727     ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1728     ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
1729     ClearStanzas();
1730     CheckVideoBandwidth(expected_video_bandwidth_,
1731                         call_->sessions()[0]->remote_description());
1732     CheckVideoRtcpMux(expected_video_rtcp_mux_,
1733                       call_->sessions()[0]->remote_description());
1734     CheckRtcpFb(call_->sessions()[0]->remote_description());
1735     if (expect_incoming_crypto_) {
1736       CheckCryptoFromGoodIncomingInitiate(call_->sessions()[0]);
1737     }
1738
1739     // TODO(pthatcher): Add tests for sending <bandwidth> in accept.
1740     call_->AcceptSession(call_->sessions()[0], options);
1741     ASSERT_EQ(cricket::Session::STATE_SENTACCEPT,
1742               call_->sessions()[0]->state());
1743     ASSERT_EQ(1U, stanzas_.size());
1744     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1745     ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1746     ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1747
1748     buzz::XmlElement* e = ActionFromStanza(stanzas_[0]);
1749     ASSERT_TRUE(e != NULL);
1750     ASSERT_TRUE(ContentFromAction(e) != NULL);
1751     *element = CopyElement(ContentFromAction(e));
1752     ASSERT_TRUE(*element != NULL);
1753     ClearStanzas();
1754     if (expect_outgoing_crypto_) {
1755       CheckCryptoForGoodOutgoingAccept(call_->sessions()[0]);
1756     }
1757
1758     if (options.data_channel_type == cricket::DCT_RTP) {
1759       CheckDataRtcpMux(true, call_->sessions()[0]->local_description());
1760       CheckDataRtcpMux(true, call_->sessions()[0]->remote_description());
1761       // TODO(pthatcher): Check rtcpmux and crypto?
1762     }
1763
1764     call_->Terminate();
1765     ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE,
1766               call_->sessions()[0]->state());
1767     ASSERT_EQ(1U, stanzas_.size());
1768     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1769     ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1770     ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1771     e = ActionFromStanza(stanzas_[0]);
1772     ASSERT_TRUE(e != NULL);
1773     ASSERT_TRUE(parser_->ActionIsTerminate(e));
1774     ClearStanzas();
1775   }
1776
1777   void TestRejectOffer(const std::string &initiate_string,
1778                        const cricket::CallOptions& options,
1779                        buzz::XmlElement** element) {
1780     *element = NULL;
1781
1782     rtc::scoped_ptr<buzz::XmlElement> el(
1783         buzz::XmlElement::ForStr(initiate_string));
1784     client_->session_manager()->OnIncomingMessage(el.get());
1785     ASSERT_TRUE(call_ != NULL);
1786     ASSERT_TRUE(call_->sessions()[0] != NULL);
1787     ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE,
1788               call_->sessions()[0]->state());
1789     ASSERT_EQ(1U, stanzas_.size());
1790     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1791     ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1792     ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
1793     ClearStanzas();
1794
1795     call_->AcceptSession(call_->sessions()[0], options);
1796     ASSERT_EQ(cricket::Session::STATE_SENTACCEPT,
1797               call_->sessions()[0]->state());
1798     ASSERT_EQ(1U, stanzas_.size());
1799     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1800     ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1801     ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1802
1803     buzz::XmlElement* e = ActionFromStanza(stanzas_[0]);
1804     ASSERT_TRUE(e != NULL);
1805     ASSERT_TRUE(ContentFromAction(e) != NULL);
1806     *element = CopyElement(ContentFromAction(e));
1807     ASSERT_TRUE(*element != NULL);
1808     ClearStanzas();
1809
1810     buzz::XmlElement* content = *element;
1811     // The NextContent method actually returns the second content. So we
1812     // can't handle the case when audio, video and data are all enabled. But
1813     // since we are testing rejection, it won't be the case.
1814     if (options.has_audio()) {
1815       ASSERT_TRUE(content != NULL);
1816       ASSERT_EQ("test audio", content->Attr(buzz::QName("", "name")));
1817       content = parser_->NextContent(content);
1818     }
1819
1820     if (options.has_video()) {
1821       ASSERT_TRUE(content != NULL);
1822       ASSERT_EQ("test video", content->Attr(buzz::QName("", "name")));
1823       content = parser_->NextContent(content);
1824     }
1825
1826     if (options.has_data()) {
1827       ASSERT_TRUE(content != NULL);
1828       ASSERT_EQ("test data", content->Attr(buzz::QName("", "name")));
1829       content = parser_->NextContent(content);
1830     }
1831
1832     call_->Terminate();
1833     ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE,
1834               call_->sessions()[0]->state());
1835     ASSERT_EQ(1U, stanzas_.size());
1836     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1837     ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1838     ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1839     e = ActionFromStanza(stanzas_[0]);
1840     ASSERT_TRUE(e != NULL);
1841     ASSERT_TRUE(parser_->ActionIsTerminate(e));
1842     ClearStanzas();
1843   }
1844
1845   void TestBadIncomingInitiate(const std::string& initiate_string) {
1846     rtc::scoped_ptr<buzz::XmlElement> el(
1847         buzz::XmlElement::ForStr(initiate_string));
1848     client_->session_manager()->OnIncomingMessage(el.get());
1849     ASSERT_TRUE(call_ != NULL);
1850     ASSERT_TRUE(call_->sessions()[0] != NULL);
1851     ASSERT_EQ(cricket::Session::STATE_SENTREJECT,
1852               call_->sessions()[0]->state());
1853     ASSERT_EQ(2U, stanzas_.size());
1854     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1855     ASSERT_TRUE(stanzas_[1]->HasAttr(buzz::QN_TYPE));
1856     ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[1]->Attr(buzz::QN_TYPE));
1857     ClearStanzas();
1858   }
1859
1860   void VerifyAudioCodec(const AudioCodec& codec, int id,
1861                         const std::string& name, int clockrate,
1862                         int bitrate, int channels) {
1863     ASSERT_EQ(id, codec.id);
1864     ASSERT_EQ(name, codec.name);
1865     ASSERT_EQ(clockrate, codec.clockrate);
1866     ASSERT_EQ(bitrate, codec.bitrate);
1867     ASSERT_EQ(channels, codec.channels);
1868     ASSERT_EQ(expected_audio_fb_params_, codec.feedback_params);
1869   }
1870
1871   void TestGoodOutgoingInitiate(const cricket::CallOptions& options) {
1872     if (initial_protocol_ == cricket::PROTOCOL_JINGLE) {
1873       // rtcp fb is only implemented for jingle.
1874       ExpectRtcpFb();
1875     }
1876
1877     client_->CreateCall();
1878     ASSERT_TRUE(call_ != NULL);
1879     call_->InitiateSession(buzz::Jid("me@mydomain.com"),
1880                            buzz::Jid("me@mydomain.com"), options);
1881     ASSERT_TRUE(call_->sessions()[0] != NULL);
1882     ASSERT_EQ(cricket::Session::STATE_SENTINITIATE,
1883               call_->sessions()[0]->state());
1884     ASSERT_EQ(1U, stanzas_.size());
1885     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
1886     ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
1887     ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
1888     buzz::XmlElement* action = ActionFromStanza(stanzas_[0]);
1889     ASSERT_TRUE(action != NULL);
1890     buzz::XmlElement* content = ContentFromAction(action);
1891     ASSERT_TRUE(content != NULL);
1892
1893     buzz::XmlElement* e = PayloadTypeFromContent(content);
1894     ASSERT_TRUE(e != NULL);
1895     cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
1896     VerifyAudioCodec(codec, 103, "ISAC", 16000, 0, 1);
1897
1898     e = NextFromPayloadType(e);
1899     ASSERT_TRUE(e != NULL);
1900     codec = AudioCodecFromPayloadType(e);
1901     VerifyAudioCodec(codec, 104, "ISAC", 32000, 0, 1);
1902
1903     e = NextFromPayloadType(e);
1904     ASSERT_TRUE(e != NULL);
1905     codec = AudioCodecFromPayloadType(e);
1906     VerifyAudioCodec(codec, 119, "ISACLC", 16000, 40000, 1);
1907
1908     e = NextFromPayloadType(e);
1909     ASSERT_TRUE(e != NULL);
1910     codec = AudioCodecFromPayloadType(e);
1911     VerifyAudioCodec(codec, 99, "speex", 16000, 22000, 1);
1912
1913     e = NextFromPayloadType(e);
1914     ASSERT_TRUE(e != NULL);
1915     codec = AudioCodecFromPayloadType(e);
1916     VerifyAudioCodec(codec, 97, "IPCMWB", 16000, 80000, 1);
1917
1918      e = NextFromPayloadType(e);
1919     ASSERT_TRUE(e != NULL);
1920     codec = AudioCodecFromPayloadType(e);
1921     VerifyAudioCodec(codec, 9, "G722", 8000, 64000, 1);
1922
1923     e = NextFromPayloadType(e);
1924     ASSERT_TRUE(e != NULL);
1925     codec = AudioCodecFromPayloadType(e);
1926     VerifyAudioCodec(codec, 102, "iLBC", 8000, 13300, 1);
1927
1928     e = NextFromPayloadType(e);
1929     ASSERT_TRUE(e != NULL);
1930     codec = AudioCodecFromPayloadType(e);
1931     VerifyAudioCodec(codec, 98, "speex", 8000, 11000, 1);
1932
1933     e = NextFromPayloadType(e);
1934     ASSERT_TRUE(e != NULL);
1935     codec = AudioCodecFromPayloadType(e);
1936     VerifyAudioCodec(codec, 3, "GSM", 8000, 13000, 1);
1937
1938     e = NextFromPayloadType(e);
1939     ASSERT_TRUE(e != NULL);
1940     codec = AudioCodecFromPayloadType(e);
1941     VerifyAudioCodec(codec, 100, "EG711U", 8000, 64000, 1);
1942
1943     e = NextFromPayloadType(e);
1944     ASSERT_TRUE(e != NULL);
1945     codec = AudioCodecFromPayloadType(e);
1946     VerifyAudioCodec(codec, 101, "EG711A", 8000, 64000, 1);
1947
1948     e = NextFromPayloadType(e);
1949     ASSERT_TRUE(e != NULL);
1950     codec = AudioCodecFromPayloadType(e);
1951     VerifyAudioCodec(codec, 0, "PCMU", 8000, 64000, 1);
1952
1953     e = NextFromPayloadType(e);
1954     ASSERT_TRUE(e != NULL);
1955     codec = AudioCodecFromPayloadType(e);
1956     VerifyAudioCodec(codec, 8, "PCMA", 8000, 64000, 1);
1957
1958     e = NextFromPayloadType(e);
1959     ASSERT_TRUE(e != NULL);
1960     codec = AudioCodecFromPayloadType(e);
1961     VerifyAudioCodec(codec, 126, "CN", 32000, 0, 1);
1962
1963     e = NextFromPayloadType(e);
1964     ASSERT_TRUE(e != NULL);
1965     codec = AudioCodecFromPayloadType(e);
1966     VerifyAudioCodec(codec, 105, "CN", 16000, 0, 1);
1967
1968     e = NextFromPayloadType(e);
1969     ASSERT_TRUE(e != NULL);
1970     codec = AudioCodecFromPayloadType(e);
1971     VerifyAudioCodec(codec, 13, "CN", 8000, 0, 1);
1972
1973     e = NextFromPayloadType(e);
1974     ASSERT_TRUE(e != NULL);
1975     codec = AudioCodecFromPayloadType(e);
1976     VerifyAudioCodec(codec, 117, "red", 8000, 0, 1);
1977
1978     e = NextFromPayloadType(e);
1979     ASSERT_TRUE(e != NULL);
1980     codec = AudioCodecFromPayloadType(e);
1981     VerifyAudioCodec(codec, 106, "telephone-event", 8000, 0, 1);
1982
1983     e = NextFromPayloadType(e);
1984     ASSERT_TRUE(e == NULL);
1985
1986     if (expect_outgoing_crypto_) {
1987       buzz::XmlElement* encryption = EncryptionFromContent(content);
1988       ASSERT_TRUE(encryption != NULL);
1989
1990       if (client_->secure() == cricket::SEC_REQUIRED) {
1991         ASSERT_TRUE(cricket::GetXmlAttr(
1992             encryption, cricket::QN_ENCRYPTION_REQUIRED, false));
1993       }
1994
1995       if (content->Name().Namespace() == cricket::NS_GINGLE_AUDIO) {
1996         e = encryption->FirstNamed(cricket::QN_GINGLE_AUDIO_CRYPTO_USAGE);
1997         ASSERT_TRUE(e != NULL);
1998         ASSERT_TRUE(
1999             e->NextNamed(cricket::QN_GINGLE_AUDIO_CRYPTO_USAGE) == NULL);
2000         ASSERT_TRUE(
2001             e->FirstNamed(cricket::QN_GINGLE_VIDEO_CRYPTO_USAGE) == NULL);
2002       }
2003
2004       e = encryption->FirstNamed(cricket::QN_CRYPTO);
2005       ASSERT_TRUE(e != NULL);
2006       ASSERT_EQ("0", e->Attr(cricket::QN_CRYPTO_TAG));
2007       ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", e->Attr(cricket::QN_CRYPTO_SUITE));
2008       std::string key_0 = e->Attr(cricket::QN_CRYPTO_KEY_PARAMS);
2009       ASSERT_EQ(47U, key_0.length());
2010       ASSERT_EQ("inline:", key_0.substr(0, 7));
2011
2012       e = e->NextNamed(cricket::QN_CRYPTO);
2013       ASSERT_TRUE(e != NULL);
2014       ASSERT_EQ("1", e->Attr(cricket::QN_CRYPTO_TAG));
2015       ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", e->Attr(cricket::QN_CRYPTO_SUITE));
2016       std::string key_1 = e->Attr(cricket::QN_CRYPTO_KEY_PARAMS);
2017       ASSERT_EQ(47U, key_1.length());
2018       ASSERT_EQ("inline:", key_1.substr(0, 7));
2019       ASSERT_NE(key_0, key_1);
2020
2021       encryption = NextFromEncryption(encryption);
2022       ASSERT_TRUE(encryption == NULL);
2023     }
2024
2025     if (options.has_video()) {
2026       CheckVideoBandwidth(options.video_bandwidth,
2027                           call_->sessions()[0]->local_description());
2028       CheckVideoRtcpMux(expected_video_rtcp_mux_,
2029                         call_->sessions()[0]->remote_description());
2030       content = parser_->NextContent(content);
2031       const buzz::XmlElement* bandwidth =
2032           parser_->BandwidthFromContent(content);
2033       if (options.video_bandwidth == cricket::kAutoBandwidth) {
2034         ASSERT_TRUE(bandwidth == NULL);
2035       } else {
2036         ASSERT_TRUE(bandwidth != NULL);
2037         ASSERT_EQ("AS", bandwidth->Attr(buzz::QName("", "type")));
2038         ASSERT_EQ(rtc::ToString(options.video_bandwidth / 1000),
2039                   bandwidth->BodyText());
2040       }
2041
2042       buzz::XmlElement* e = PayloadTypeFromContent(content);
2043       ASSERT_TRUE(e != NULL);
2044       VideoCodec codec = VideoCodecFromPayloadType(e);
2045       VideoCodec expected_codec = kVideoCodecs[0];
2046       expected_codec.preference = codec.preference;
2047       expected_codec.feedback_params = expected_video_fb_params_;
2048       EXPECT_EQ(expected_codec, codec);
2049     }
2050
2051     if (options.data_channel_type == cricket::DCT_RTP) {
2052       content = parser_->NextContent(content);
2053       CheckRtpDataContent(content);
2054     }
2055
2056     if (options.data_channel_type == cricket::DCT_SCTP) {
2057       content = parser_->NextContent(content);
2058       CheckSctpDataContent(content);
2059     }
2060
2061     ClearStanzas();
2062   }
2063
2064   void TestHasAllSupportedAudioCodecs(buzz::XmlElement* e) {
2065     ASSERT_TRUE(e != NULL);
2066
2067     e = PayloadTypeFromContent(e);
2068     ASSERT_TRUE(e != NULL);
2069     cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2070     ASSERT_EQ(103, codec.id);
2071     ASSERT_EQ("ISAC", codec.name);
2072     ASSERT_EQ(16000, codec.clockrate);
2073     ASSERT_EQ(1, codec.channels);
2074
2075     e = NextFromPayloadType(e);
2076     ASSERT_TRUE(e != NULL);
2077     codec = AudioCodecFromPayloadType(e);
2078     ASSERT_EQ(104, codec.id);
2079     ASSERT_EQ("ISAC", codec.name);
2080     ASSERT_EQ(32000, codec.clockrate);
2081     ASSERT_EQ(1, codec.channels);
2082
2083     e = NextFromPayloadType(e);
2084     ASSERT_TRUE(e != NULL);
2085     codec = AudioCodecFromPayloadType(e);
2086     ASSERT_EQ(119, codec.id);
2087     ASSERT_EQ("ISACLC", codec.name);
2088     ASSERT_EQ(16000, codec.clockrate);
2089     ASSERT_EQ(40000, codec.bitrate);
2090     ASSERT_EQ(1, codec.channels);
2091
2092     e = NextFromPayloadType(e);
2093     ASSERT_TRUE(e != NULL);
2094     codec = AudioCodecFromPayloadType(e);
2095     ASSERT_EQ(99, codec.id);
2096     ASSERT_EQ("speex", codec.name);
2097     ASSERT_EQ(16000, codec.clockrate);
2098     ASSERT_EQ(22000, codec.bitrate);
2099     ASSERT_EQ(1, codec.channels);
2100
2101     e = NextFromPayloadType(e);
2102     ASSERT_TRUE(e != NULL);
2103     codec = AudioCodecFromPayloadType(e);
2104     ASSERT_EQ(97, codec.id);
2105     ASSERT_EQ("IPCMWB", codec.name);
2106     ASSERT_EQ(16000, codec.clockrate);
2107     ASSERT_EQ(80000, codec.bitrate);
2108     ASSERT_EQ(1, codec.channels);
2109
2110     e = NextFromPayloadType(e);
2111     ASSERT_TRUE(e != NULL);
2112     codec = AudioCodecFromPayloadType(e);
2113     ASSERT_EQ(9, codec.id);
2114     ASSERT_EQ("G722", codec.name);
2115     ASSERT_EQ(8000, codec.clockrate);
2116     ASSERT_EQ(64000, codec.bitrate);
2117     ASSERT_EQ(1, codec.channels);
2118
2119     e = NextFromPayloadType(e);
2120     ASSERT_TRUE(e != NULL);
2121     codec = AudioCodecFromPayloadType(e);
2122     ASSERT_EQ(102, codec.id);
2123     ASSERT_EQ("iLBC", codec.name);
2124     ASSERT_EQ(8000, codec.clockrate);
2125     ASSERT_EQ(13300, codec.bitrate);
2126     ASSERT_EQ(1, codec.channels);
2127
2128     e = NextFromPayloadType(e);
2129     ASSERT_TRUE(e != NULL);
2130     codec = AudioCodecFromPayloadType(e);
2131     ASSERT_EQ(98, codec.id);
2132     ASSERT_EQ("speex", codec.name);
2133     ASSERT_EQ(8000, codec.clockrate);
2134     ASSERT_EQ(11000, codec.bitrate);
2135     ASSERT_EQ(1, codec.channels);
2136
2137     e = NextFromPayloadType(e);
2138     ASSERT_TRUE(e != NULL);
2139     codec = AudioCodecFromPayloadType(e);
2140     ASSERT_EQ(3, codec.id);
2141     ASSERT_EQ("GSM", codec.name);
2142     ASSERT_EQ(8000, codec.clockrate);
2143     ASSERT_EQ(13000, codec.bitrate);
2144     ASSERT_EQ(1, codec.channels);
2145
2146     e = NextFromPayloadType(e);
2147     ASSERT_TRUE(e != NULL);
2148     codec = AudioCodecFromPayloadType(e);
2149     ASSERT_EQ(100, codec.id);
2150     ASSERT_EQ("EG711U", codec.name);
2151     ASSERT_EQ(8000, codec.clockrate);
2152     ASSERT_EQ(64000, codec.bitrate);
2153     ASSERT_EQ(1, codec.channels);
2154
2155     e = NextFromPayloadType(e);
2156     ASSERT_TRUE(e != NULL);
2157     codec = AudioCodecFromPayloadType(e);
2158     ASSERT_EQ(101, codec.id);
2159     ASSERT_EQ("EG711A", codec.name);
2160     ASSERT_EQ(8000, codec.clockrate);
2161     ASSERT_EQ(64000, codec.bitrate);
2162     ASSERT_EQ(1, codec.channels);
2163
2164     e = NextFromPayloadType(e);
2165     ASSERT_TRUE(e != NULL);
2166     codec = AudioCodecFromPayloadType(e);
2167     ASSERT_EQ(0, codec.id);
2168     ASSERT_EQ("PCMU", codec.name);
2169     ASSERT_EQ(8000, codec.clockrate);
2170     ASSERT_EQ(64000, codec.bitrate);
2171     ASSERT_EQ(1, codec.channels);
2172
2173     e = NextFromPayloadType(e);
2174     ASSERT_TRUE(e != NULL);
2175     codec = AudioCodecFromPayloadType(e);
2176     ASSERT_EQ(8, codec.id);
2177     ASSERT_EQ("PCMA", codec.name);
2178     ASSERT_EQ(8000, codec.clockrate);
2179     ASSERT_EQ(64000, codec.bitrate);
2180     ASSERT_EQ(1, codec.channels);
2181
2182     e = NextFromPayloadType(e);
2183     ASSERT_TRUE(e != NULL);
2184     codec = AudioCodecFromPayloadType(e);
2185     ASSERT_EQ(126, codec.id);
2186     ASSERT_EQ("CN", codec.name);
2187     ASSERT_EQ(32000, codec.clockrate);
2188     ASSERT_EQ(1, codec.channels);
2189
2190     e = NextFromPayloadType(e);
2191     ASSERT_TRUE(e != NULL);
2192     codec = AudioCodecFromPayloadType(e);
2193     ASSERT_EQ(105, codec.id);
2194     ASSERT_EQ("CN", codec.name);
2195     ASSERT_EQ(16000, codec.clockrate);
2196     ASSERT_EQ(1, codec.channels);
2197
2198     e = NextFromPayloadType(e);
2199     ASSERT_TRUE(e != NULL);
2200     codec = AudioCodecFromPayloadType(e);
2201     ASSERT_EQ(13, codec.id);
2202     ASSERT_EQ("CN", codec.name);
2203     ASSERT_EQ(8000, codec.clockrate);
2204     ASSERT_EQ(1, codec.channels);
2205
2206     e = NextFromPayloadType(e);
2207     ASSERT_TRUE(e != NULL);
2208     codec = AudioCodecFromPayloadType(e);
2209     ASSERT_EQ(117, codec.id);
2210     ASSERT_EQ("red", codec.name);
2211     ASSERT_EQ(8000, codec.clockrate);
2212     ASSERT_EQ(1, codec.channels);
2213
2214     e = NextFromPayloadType(e);
2215     ASSERT_TRUE(e != NULL);
2216     codec = AudioCodecFromPayloadType(e);
2217     ASSERT_EQ(106, codec.id);
2218     ASSERT_EQ("telephone-event", codec.name);
2219     ASSERT_EQ(8000, codec.clockrate);
2220     ASSERT_EQ(1, codec.channels);
2221
2222     e = NextFromPayloadType(e);
2223     ASSERT_TRUE(e == NULL);
2224   }
2225
2226   void TestCodecsOfVideoInitiate(buzz::XmlElement* content) {
2227     ASSERT_TRUE(content != NULL);
2228     buzz::XmlElement* payload_type = PayloadTypeFromContent(content);
2229     ASSERT_TRUE(payload_type != NULL);
2230     cricket::AudioCodec codec = AudioCodecFromPayloadType(payload_type);
2231     ASSERT_EQ(103, codec.id);
2232     ASSERT_EQ("ISAC", codec.name);
2233     ASSERT_EQ(16000, codec.clockrate);
2234     ASSERT_EQ(1, codec.channels);
2235
2236     content = parser_->NextContent(content);
2237     ASSERT_TRUE(content != NULL);
2238     payload_type = PayloadTypeFromContent(content);
2239     ASSERT_TRUE(payload_type != NULL);
2240     cricket::VideoCodec vcodec =
2241         parser_->VideoCodecFromPayloadType(payload_type);
2242     ASSERT_EQ(99, vcodec.id);
2243     ASSERT_EQ("H264-SVC", vcodec.name);
2244     ASSERT_EQ(320, vcodec.width);
2245     ASSERT_EQ(200, vcodec.height);
2246     ASSERT_EQ(30, vcodec.framerate);
2247   }
2248
2249   void TestHasAudioCodecsFromInitiateSomeUnsupported(buzz::XmlElement* e) {
2250     ASSERT_TRUE(e != NULL);
2251     e = PayloadTypeFromContent(e);
2252     ASSERT_TRUE(e != NULL);
2253
2254     cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2255     ASSERT_EQ(103, codec.id);
2256     ASSERT_EQ("ISAC", codec.name);
2257     ASSERT_EQ(16000, codec.clockrate);
2258     ASSERT_EQ(1, codec.channels);
2259
2260     e = NextFromPayloadType(e);
2261     ASSERT_TRUE(e != NULL);
2262     codec = AudioCodecFromPayloadType(e);
2263     ASSERT_EQ(100, codec.id);
2264     ASSERT_EQ("EG711U", codec.name);
2265
2266     e = NextFromPayloadType(e);
2267     ASSERT_TRUE(e != NULL);
2268     codec = AudioCodecFromPayloadType(e);
2269     ASSERT_EQ(101, codec.id);
2270     ASSERT_EQ("EG711A", codec.name);
2271
2272     e = NextFromPayloadType(e);
2273     ASSERT_TRUE(e != NULL);
2274     codec = AudioCodecFromPayloadType(e);
2275     ASSERT_EQ(0, codec.id);
2276     ASSERT_EQ("PCMU", codec.name);
2277
2278     e = NextFromPayloadType(e);
2279     ASSERT_TRUE(e != NULL);
2280     codec = AudioCodecFromPayloadType(e);
2281     ASSERT_EQ(13, codec.id);
2282     ASSERT_EQ("CN", codec.name);
2283
2284     e = NextFromPayloadType(e);
2285     ASSERT_TRUE(e == NULL);
2286   }
2287
2288   void TestHasAudioCodecsFromInitiateDynamicAudioCodecs(
2289       buzz::XmlElement* e) {
2290     ASSERT_TRUE(e != NULL);
2291     e = PayloadTypeFromContent(e);
2292     ASSERT_TRUE(e != NULL);
2293
2294     cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2295     ASSERT_EQ(123, codec.id);
2296     ASSERT_EQ(16000, codec.clockrate);
2297     ASSERT_EQ(1, codec.channels);
2298
2299     e = NextFromPayloadType(e);
2300     ASSERT_TRUE(e == NULL);
2301   }
2302
2303   void TestHasDefaultAudioCodecs(buzz::XmlElement* e) {
2304     ASSERT_TRUE(e != NULL);
2305     e = PayloadTypeFromContent(e);
2306     ASSERT_TRUE(e != NULL);
2307
2308     cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2309     ASSERT_EQ(103, codec.id);
2310     ASSERT_EQ("ISAC", codec.name);
2311
2312     e = NextFromPayloadType(e);
2313     ASSERT_TRUE(e != NULL);
2314     codec = AudioCodecFromPayloadType(e);
2315     ASSERT_EQ(0, codec.id);
2316     ASSERT_EQ("PCMU", codec.name);
2317
2318     e = NextFromPayloadType(e);
2319     ASSERT_TRUE(e == NULL);
2320   }
2321
2322   void TestHasAudioCodecsFromInitiateStaticAudioCodecs(
2323       buzz::XmlElement* e) {
2324     ASSERT_TRUE(e != NULL);
2325     e = PayloadTypeFromContent(e);
2326     ASSERT_TRUE(e != NULL);
2327
2328     cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
2329     ASSERT_EQ(3, codec.id);
2330
2331     e = NextFromPayloadType(e);
2332     ASSERT_TRUE(e != NULL);
2333     codec = AudioCodecFromPayloadType(e);
2334     ASSERT_EQ(0, codec.id);
2335
2336     e = NextFromPayloadType(e);
2337     ASSERT_TRUE(e != NULL);
2338     codec = AudioCodecFromPayloadType(e);
2339     ASSERT_EQ(8, codec.id);
2340
2341     e = NextFromPayloadType(e);
2342     ASSERT_TRUE(e == NULL);
2343   }
2344
2345   void TestGingleInitiateWithUnsupportedCrypto(
2346       const std::string &initiate_string,
2347       buzz::XmlElement** element) {
2348     *element = NULL;
2349
2350     rtc::scoped_ptr<buzz::XmlElement> el(
2351         buzz::XmlElement::ForStr(initiate_string));
2352     client_->session_manager()->OnIncomingMessage(el.get());
2353
2354     ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE,
2355               call_->sessions()[0]->state());
2356     ClearStanzas();
2357     CheckBadCryptoFromIncomingInitiate(call_->sessions()[0]);
2358
2359     call_->AcceptSession(call_->sessions()[0], cricket::CallOptions());
2360     ClearStanzas();
2361     CheckNoCryptoForOutgoingAccept(call_->sessions()[0]);
2362
2363     call_->Terminate();
2364     ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE,
2365               call_->sessions()[0]->state());
2366     ClearStanzas();
2367   }
2368
2369   void TestIncomingAcceptWithSsrcs(
2370       const std::string& accept_string,
2371       cricket::CallOptions& options) {
2372     client_->CreateCall();
2373     ASSERT_TRUE(call_ != NULL);
2374
2375     call_->InitiateSession(buzz::Jid("me@mydomain.com"),
2376                            buzz::Jid("me@mydomain.com"), options);
2377     ASSERT_TRUE(call_->sessions()[0] != NULL);
2378     ASSERT_EQ(cricket::Session::STATE_SENTINITIATE,
2379               call_->sessions()[0]->state());
2380     ASSERT_EQ(1U, stanzas_.size());
2381     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
2382     ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
2383     ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
2384     buzz::XmlElement* action = ActionFromStanza(stanzas_[0]);
2385     ASSERT_TRUE(action != NULL);
2386     buzz::XmlElement* content = ContentFromAction(action);
2387     ASSERT_TRUE(content != NULL);
2388     if (initial_protocol_ == cricket::PROTOCOL_JINGLE) {
2389       buzz::XmlElement* content_desc =
2390           content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
2391       ASSERT_TRUE(content_desc != NULL);
2392       ASSERT_EQ("", content_desc->Attr(cricket::QN_SSRC));
2393     }
2394     ClearStanzas();
2395
2396     // We need to insert the session ID into the session accept message.
2397     rtc::scoped_ptr<buzz::XmlElement> el(
2398         buzz::XmlElement::ForStr(accept_string));
2399     const std::string sid = call_->sessions()[0]->id();
2400     if (initial_protocol_ == cricket::PROTOCOL_JINGLE) {
2401       buzz::XmlElement* jingle = el->FirstNamed(cricket::QN_JINGLE);
2402       jingle->SetAttr(cricket::QN_SID, sid);
2403     } else {
2404       buzz::XmlElement* session = el->FirstNamed(cricket::QN_GINGLE_SESSION);
2405       session->SetAttr(cricket::QN_ID, sid);
2406     }
2407
2408     client_->session_manager()->OnIncomingMessage(el.get());
2409
2410     ASSERT_EQ(cricket::Session::STATE_RECEIVEDACCEPT,
2411               call_->sessions()[0]->state());
2412     ASSERT_EQ(1U, stanzas_.size());
2413     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
2414     ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
2415     ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
2416     ClearStanzas();
2417
2418     CheckAudioSsrcForIncomingAccept(call_->sessions()[0]);
2419     CheckVideoSsrcForIncomingAccept(call_->sessions()[0]);
2420     if (options.data_channel_type == cricket::DCT_RTP) {
2421       CheckDataSsrcForIncomingAccept(call_->sessions()[0]);
2422     }
2423     // TODO(pthatcher): Check kDataSid if DCT_SCTP.
2424     // const uint32 kDataSid = 0;
2425   }
2426
2427   size_t ClearStanzas() {
2428     size_t size = stanzas_.size();
2429     for (size_t i = 0; i < size; i++) {
2430       delete stanzas_[i];
2431     }
2432     stanzas_.clear();
2433     return size;
2434   }
2435
2436   buzz::XmlElement* SetJingleSid(buzz::XmlElement* stanza) {
2437     buzz::XmlElement* jingle =
2438         stanza->FirstNamed(cricket::QN_JINGLE);
2439     jingle->SetAttr(cricket::QN_SID, call_->sessions()[0]->id());
2440     return stanza;
2441   }
2442
2443   void TestSendVideoStreamUpdate() {
2444     cricket::CallOptions options = VideoCallOptions();
2445     options.is_muc = true;
2446
2447     client_->CreateCall();
2448     call_->InitiateSession(buzz::Jid("me@mydomain.com"),
2449                            buzz::Jid("me@mydomain.com"), options);
2450     ClearStanzas();
2451
2452     cricket::StreamParams stream;
2453     stream.id = "test-stream";
2454     stream.ssrcs.push_back(1001);
2455     rtc::scoped_ptr<buzz::XmlElement> expected_stream_add(
2456         buzz::XmlElement::ForStr(
2457             JingleOutboundStreamAdd(
2458                 call_->sessions()[0]->id(),
2459                 "video", stream.id, "1001")));
2460     rtc::scoped_ptr<buzz::XmlElement> expected_stream_remove(
2461         buzz::XmlElement::ForStr(
2462             JingleOutboundStreamRemove(
2463                 call_->sessions()[0]->id(),
2464                 "video", stream.id)));
2465
2466     call_->SendVideoStreamUpdate(call_->sessions()[0],
2467                                  call_->CreateVideoStreamUpdate(stream));
2468     ASSERT_EQ(1U, stanzas_.size());
2469     EXPECT_EQ(expected_stream_add->Str(), stanzas_[0]->Str());
2470     ClearStanzas();
2471
2472     stream.ssrcs.clear();
2473     call_->SendVideoStreamUpdate(call_->sessions()[0],
2474                                  call_->CreateVideoStreamUpdate(stream));
2475     ASSERT_EQ(1U, stanzas_.size());
2476     EXPECT_EQ(expected_stream_remove->Str(), stanzas_[0]->Str());
2477     ClearStanzas();
2478   }
2479
2480   void TestStreamsUpdateAndViewRequests() {
2481     cricket::CallOptions options = VideoCallOptions();
2482     options.is_muc = true;
2483
2484     client_->CreateCall();
2485     call_->InitiateSession(buzz::Jid("me@mydomain.com"),
2486                            buzz::Jid("me@mydomain.com"), options);
2487     ASSERT_EQ(1U, ClearStanzas());
2488     ASSERT_EQ(0U, last_streams_added_.audio().size());
2489     ASSERT_EQ(0U, last_streams_added_.video().size());
2490     ASSERT_EQ(0U, last_streams_removed_.audio().size());
2491     ASSERT_EQ(0U, last_streams_removed_.video().size());
2492
2493     rtc::scoped_ptr<buzz::XmlElement> accept_stanza(
2494         buzz::XmlElement::ForStr(kJingleAcceptWithSsrcs));
2495     SetJingleSid(accept_stanza.get());
2496     client_->session_manager()->OnIncomingMessage(accept_stanza.get());
2497     ASSERT_EQ(cricket::Session::STATE_RECEIVEDACCEPT,
2498               call_->sessions()[0]->state());
2499     ASSERT_EQ(1U, stanzas_.size());
2500     ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
2501     ClearStanzas();
2502     // Need to clear the added streams, because they are populated when
2503     // receiving an accept message now.
2504     last_streams_added_.mutable_video()->clear();
2505     last_streams_added_.mutable_audio()->clear();
2506
2507     call_->sessions()[0]->SetState(cricket::Session::STATE_INPROGRESS);
2508
2509     rtc::scoped_ptr<buzz::XmlElement> streams_stanza(
2510         buzz::XmlElement::ForStr(
2511             JingleStreamAdd("video", "Bob", "video1", "ABC")));
2512     SetJingleSid(streams_stanza.get());
2513     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2514     // First one is ignored because of bad syntax.
2515     ASSERT_EQ(1U, stanzas_.size());
2516     // TODO(pthatcher): Figure out how to make this an ERROR rather than RESULT.
2517     ASSERT_EQ(std::string(buzz::STR_ERROR), stanzas_[0]->Attr(buzz::QN_TYPE));
2518     ClearStanzas();
2519     ASSERT_EQ(0U, last_streams_added_.audio().size());
2520     ASSERT_EQ(0U, last_streams_added_.video().size());
2521     ASSERT_EQ(0U, last_streams_removed_.audio().size());
2522     ASSERT_EQ(0U, last_streams_removed_.video().size());
2523
2524     streams_stanza.reset(buzz::XmlElement::ForStr(
2525         JingleStreamAdd("audio", "Bob", "audio1", "1234")));
2526     SetJingleSid(streams_stanza.get());
2527     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2528     ASSERT_EQ(1U, last_streams_added_.audio().size());
2529     ASSERT_EQ("Bob", last_streams_added_.audio()[0].groupid);
2530     ASSERT_EQ(1U, last_streams_added_.audio()[0].ssrcs.size());
2531     ASSERT_EQ(1234U, last_streams_added_.audio()[0].first_ssrc());
2532
2533     // Ignores adds without ssrcs.
2534     streams_stanza.reset(buzz::XmlElement::ForStr(
2535         JingleStreamAddWithoutSsrc("audio", "Bob", "audioX")));
2536     SetJingleSid(streams_stanza.get());
2537     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2538     ASSERT_EQ(1U, last_streams_added_.audio().size());
2539     ASSERT_EQ(1234U, last_streams_added_.audio()[0].first_ssrc());
2540
2541     // Ignores stream updates with unknown content names. (Don't terminate).
2542     streams_stanza.reset(buzz::XmlElement::ForStr(
2543         JingleStreamAddWithoutSsrc("foo", "Bob", "foo")));
2544     SetJingleSid(streams_stanza.get());
2545     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2546
2547     streams_stanza.reset(buzz::XmlElement::ForStr(
2548         JingleStreamAdd("audio", "Joe", "audio1", "2468")));
2549     SetJingleSid(streams_stanza.get());
2550     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2551     ASSERT_EQ(1U, last_streams_added_.audio().size());
2552     ASSERT_EQ("Joe", last_streams_added_.audio()[0].groupid);
2553     ASSERT_EQ(1U, last_streams_added_.audio()[0].ssrcs.size());
2554     ASSERT_EQ(2468U, last_streams_added_.audio()[0].first_ssrc());
2555
2556     streams_stanza.reset(buzz::XmlElement::ForStr(
2557         JingleStreamAdd("video", "Bob", "video1", "5678")));
2558     SetJingleSid(streams_stanza.get());
2559     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2560     ASSERT_EQ(1U, last_streams_added_.video().size());
2561     ASSERT_EQ("Bob", last_streams_added_.video()[0].groupid);
2562     ASSERT_EQ(1U, last_streams_added_.video()[0].ssrcs.size());
2563     ASSERT_EQ(5678U, last_streams_added_.video()[0].first_ssrc());
2564
2565     // We're testing that a "duplicate" is effectively ignored.
2566     last_streams_added_.mutable_video()->clear();
2567     last_streams_removed_.mutable_video()->clear();
2568     streams_stanza.reset(buzz::XmlElement::ForStr(
2569         JingleStreamAdd("video", "Bob", "video1", "5678")));
2570     SetJingleSid(streams_stanza.get());
2571     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2572     ASSERT_EQ(0U, last_streams_added_.video().size());
2573     ASSERT_EQ(0U, last_streams_removed_.video().size());
2574
2575     streams_stanza.reset(buzz::XmlElement::ForStr(
2576         JingleStreamAdd("video", "Bob", "video2", "5679")));
2577     SetJingleSid(streams_stanza.get());
2578     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2579     ASSERT_EQ(1U, last_streams_added_.video().size());
2580     ASSERT_EQ("Bob", last_streams_added_.video()[0].groupid);
2581     ASSERT_EQ(1U, last_streams_added_.video()[0].ssrcs.size());
2582     ASSERT_EQ(5679U, last_streams_added_.video()[0].first_ssrc());
2583
2584     cricket::FakeVoiceMediaChannel* voice_channel = fme_->GetVoiceChannel(0);
2585     ASSERT_TRUE(voice_channel != NULL);
2586     ASSERT_TRUE(voice_channel->HasRecvStream(1234U));
2587     ASSERT_TRUE(voice_channel->HasRecvStream(2468U));
2588     cricket::FakeVideoMediaChannel* video_channel = fme_->GetVideoChannel(0);
2589     ASSERT_TRUE(video_channel != NULL);
2590     ASSERT_TRUE(video_channel->HasRecvStream(5678U));
2591     ClearStanzas();
2592
2593     cricket::ViewRequest viewRequest;
2594     cricket::StaticVideoView staticVideoView(
2595         cricket::StreamSelector(5678U), 640, 480, 30);
2596     viewRequest.static_video_views.push_back(staticVideoView);
2597     rtc::scoped_ptr<buzz::XmlElement> expected_view_elem(
2598         buzz::XmlElement::ForStr(JingleView("5678", "640", "480", "30")));
2599     SetJingleSid(expected_view_elem.get());
2600
2601     ASSERT_TRUE(
2602         call_->SendViewRequest(call_->sessions()[0], viewRequest));
2603     ASSERT_EQ(1U, stanzas_.size());
2604     ASSERT_EQ(expected_view_elem->Str(), stanzas_[0]->Str());
2605     ClearStanzas();
2606
2607     streams_stanza.reset(buzz::XmlElement::ForStr(
2608         JingleStreamRemove("audio", "Bob", "audio1")));
2609     SetJingleSid(streams_stanza.get());
2610     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2611     ASSERT_EQ(1U, last_streams_removed_.audio().size());
2612     ASSERT_EQ(1U, last_streams_removed_.audio()[0].ssrcs.size());
2613     EXPECT_EQ(1234U, last_streams_removed_.audio()[0].first_ssrc());
2614
2615     streams_stanza.reset(buzz::XmlElement::ForStr(
2616         JingleStreamRemove("video", "Bob", "video1")));
2617     SetJingleSid(streams_stanza.get());
2618     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2619     ASSERT_EQ(1U, last_streams_removed_.video().size());
2620     ASSERT_EQ(1U, last_streams_removed_.video()[0].ssrcs.size());
2621     EXPECT_EQ(5678U, last_streams_removed_.video()[0].first_ssrc());
2622
2623     streams_stanza.reset(buzz::XmlElement::ForStr(
2624         JingleStreamRemove("video", "Bob", "video2")));
2625     SetJingleSid(streams_stanza.get());
2626     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2627     ASSERT_EQ(1U, last_streams_removed_.video().size());
2628     ASSERT_EQ(1U, last_streams_removed_.video()[0].ssrcs.size());
2629     EXPECT_EQ(5679U, last_streams_removed_.video()[0].first_ssrc());
2630
2631     // Duplicate removal: should be ignored.
2632     last_streams_removed_.mutable_audio()->clear();
2633     streams_stanza.reset(buzz::XmlElement::ForStr(
2634         JingleStreamRemove("audio", "Bob", "audio1")));
2635     SetJingleSid(streams_stanza.get());
2636     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2637     ASSERT_EQ(0U, last_streams_removed_.audio().size());
2638
2639     // Duplicate removal: should be ignored.
2640     last_streams_removed_.mutable_video()->clear();
2641     streams_stanza.reset(buzz::XmlElement::ForStr(
2642         JingleStreamRemove("video", "Bob", "video1")));
2643     SetJingleSid(streams_stanza.get());
2644     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
2645     ASSERT_EQ(0U, last_streams_removed_.video().size());
2646
2647     voice_channel = fme_->GetVoiceChannel(0);
2648     ASSERT_TRUE(voice_channel != NULL);
2649     ASSERT_FALSE(voice_channel->HasRecvStream(1234U));
2650     ASSERT_TRUE(voice_channel->HasRecvStream(2468U));
2651     video_channel = fme_->GetVideoChannel(0);
2652     ASSERT_TRUE(video_channel != NULL);
2653     ASSERT_FALSE(video_channel->HasRecvStream(5678U));
2654
2655     // Fails because ssrc is now invalid.
2656     ASSERT_FALSE(
2657         call_->SendViewRequest(call_->sessions()[0], viewRequest));
2658
2659     ClearStanzas();
2660   }
2661
2662   void MakeSignalingSecure(cricket::SecurePolicy secure) {
2663     client_->set_secure(secure);
2664   }
2665
2666   void ExpectCrypto(cricket::SecurePolicy secure) {
2667     MakeSignalingSecure(secure);
2668     expect_incoming_crypto_ = true;
2669 #ifdef HAVE_SRTP
2670     expect_outgoing_crypto_ = true;
2671 #endif
2672   }
2673
2674   void ExpectVideoBandwidth(int bandwidth) {
2675     expected_video_bandwidth_ = bandwidth;
2676   }
2677
2678   void ExpectVideoRtcpMux(bool rtcp_mux) {
2679     expected_video_rtcp_mux_ = rtcp_mux;
2680   }
2681
2682   template <class C>
2683   void SetCodecFeedbackParams(std::vector<C>* codecs,
2684                               const FeedbackParams& fb_params) {
2685     for (size_t i = 0; i < codecs->size(); ++i) {
2686       codecs->at(i).feedback_params = fb_params;
2687     }
2688   }
2689
2690   void ExpectRtcpFb() {
2691     FeedbackParams params_nack_fir;
2692     params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamCcm,
2693                                       cricket::kRtcpFbCcmParamFir));
2694     params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamNack));
2695
2696     FeedbackParams params_nack;
2697     params_nack.Add(FeedbackParam(cricket::kRtcpFbParamNack));
2698
2699     expected_audio_fb_params_ = params_nack;
2700     expected_video_fb_params_ = params_nack_fir;
2701     expected_data_fb_params_ = params_nack;
2702   }
2703
2704   cricket::FakeMediaEngine* fme() { return fme_; }
2705
2706  private:
2707   void OnSendStanza(cricket::SessionManager* manager,
2708                     const buzz::XmlElement* stanza) {
2709     LOG(LS_INFO) << stanza->Str();
2710     stanzas_.push_back(new buzz::XmlElement(*stanza));
2711   }
2712
2713   void OnSessionCreate(cricket::Session* session, bool initiate) {
2714     session->set_current_protocol(initial_protocol_);
2715   }
2716
2717   void OnCallCreate(cricket::Call *call) {
2718     call_ = call;
2719     call->SignalMediaStreamsUpdate.connect(
2720         this, &MediaSessionClientTest::OnMediaStreamsUpdate);
2721   }
2722
2723   void OnCallDestroy(cricket::Call *call) {
2724     call_ = NULL;
2725   }
2726
2727   void OnMediaStreamsUpdate(cricket::Call *call,
2728                             cricket::Session *session,
2729                             const cricket::MediaStreams& added,
2730                             const cricket::MediaStreams& removed) {
2731     last_streams_added_.CopyFrom(added);
2732     last_streams_removed_.CopyFrom(removed);
2733   }
2734
2735   rtc::NetworkManager* nm_;
2736   cricket::PortAllocator* pa_;
2737   cricket::SessionManager* sm_;
2738   cricket::FakeMediaEngine* fme_;
2739   cricket::FakeDataEngine* fdme_;
2740   cricket::MediaSessionClient* client_;
2741
2742   cricket::Call* call_;
2743   std::vector<buzz::XmlElement* > stanzas_;
2744   MediaSessionTestParser* parser_;
2745   cricket::SignalingProtocol initial_protocol_;
2746   bool expect_incoming_crypto_;
2747   bool expect_outgoing_crypto_;
2748   int expected_video_bandwidth_;
2749   bool expected_video_rtcp_mux_;
2750   FeedbackParams expected_audio_fb_params_;
2751   FeedbackParams expected_video_fb_params_;
2752   FeedbackParams expected_data_fb_params_;
2753   cricket::MediaStreams last_streams_added_;
2754   cricket::MediaStreams last_streams_removed_;
2755 };
2756
2757 MediaSessionClientTest* GingleTest() {
2758   return new MediaSessionClientTest(new GingleSessionTestParser(),
2759                                     cricket::PROTOCOL_GINGLE);
2760 }
2761
2762 MediaSessionClientTest* JingleTest() {
2763   return new MediaSessionClientTest(new JingleSessionTestParser(),
2764                                     cricket::PROTOCOL_JINGLE);
2765 }
2766
2767 class MediaSessionTest : public ::testing::Test {};
2768
2769 TEST_F(MediaSessionTest, JingleGoodInitiateWithRtcpFb) {
2770   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2771   rtc::scoped_ptr<buzz::XmlElement> elem;
2772
2773   cricket::CallOptions options = VideoCallOptions();
2774   options.data_channel_type = cricket::DCT_SCTP;
2775   test->ExpectRtcpFb();
2776   test->TestGoodIncomingInitiate(
2777       kJingleInitiateWithRtcpFb, options, elem.use());
2778 }
2779
2780 TEST_F(MediaSessionTest, JingleGoodVideoInitiate) {
2781   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2782   rtc::scoped_ptr<buzz::XmlElement> elem;
2783   test->TestGoodIncomingInitiate(
2784       kJingleVideoInitiate, VideoCallOptions(), elem.use());
2785   test->TestCodecsOfVideoInitiate(elem.get());
2786 }
2787
2788 TEST_F(MediaSessionTest, JingleGoodVideoInitiateWithBandwidth) {
2789   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2790   rtc::scoped_ptr<buzz::XmlElement> elem;
2791   test->ExpectVideoBandwidth(42000);
2792   test->TestGoodIncomingInitiate(
2793       kJingleVideoInitiateWithBandwidth, VideoCallOptions(), elem.use());
2794 }
2795
2796 TEST_F(MediaSessionTest, JingleGoodVideoInitiateWithRtcpMux) {
2797   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2798   rtc::scoped_ptr<buzz::XmlElement> elem;
2799   test->ExpectVideoRtcpMux(true);
2800   test->TestGoodIncomingInitiate(
2801       kJingleVideoInitiateWithRtcpMux, VideoCallOptions(), elem.use());
2802 }
2803
2804 TEST_F(MediaSessionTest, JingleGoodVideoInitiateWithRtpData) {
2805   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2806   rtc::scoped_ptr<buzz::XmlElement> elem;
2807   cricket::CallOptions options = VideoCallOptions();
2808   options.data_channel_type = cricket::DCT_RTP;
2809   test->TestGoodIncomingInitiate(
2810       AddEncryption(kJingleVideoInitiateWithRtpData, kJingleCryptoOffer),
2811       options,
2812       elem.use());
2813 }
2814
2815 TEST_F(MediaSessionTest, JingleGoodVideoInitiateWithSctpData) {
2816   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2817   rtc::scoped_ptr<buzz::XmlElement> elem;
2818   cricket::CallOptions options = VideoCallOptions();
2819   options.data_channel_type = cricket::DCT_SCTP;
2820   test->TestGoodIncomingInitiate(kJingleVideoInitiateWithSctpData,
2821                                  options,
2822                                  elem.use());
2823 }
2824
2825 TEST_F(MediaSessionTest, JingleRejectAudio) {
2826   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2827   rtc::scoped_ptr<buzz::XmlElement> elem;
2828   cricket::CallOptions options = VideoCallOptions();
2829   options.recv_audio = false;
2830   options.data_channel_type = cricket::DCT_RTP;
2831   test->TestRejectOffer(kJingleVideoInitiateWithRtpData, options, elem.use());
2832 }
2833
2834 TEST_F(MediaSessionTest, JingleRejectVideo) {
2835   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2836   rtc::scoped_ptr<buzz::XmlElement> elem;
2837   cricket::CallOptions options = AudioCallOptions();
2838   options.data_channel_type = cricket::DCT_RTP;
2839   test->TestRejectOffer(kJingleVideoInitiateWithRtpData, options, elem.use());
2840 }
2841
2842 TEST_F(MediaSessionTest, JingleRejectData) {
2843   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2844   rtc::scoped_ptr<buzz::XmlElement> elem;
2845   test->TestRejectOffer(
2846       kJingleVideoInitiateWithRtpData, VideoCallOptions(), elem.use());
2847 }
2848
2849 TEST_F(MediaSessionTest, JingleRejectVideoAndData) {
2850   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2851   rtc::scoped_ptr<buzz::XmlElement> elem;
2852   test->TestRejectOffer(
2853       kJingleVideoInitiateWithRtpData, AudioCallOptions(), elem.use());
2854 }
2855
2856 TEST_F(MediaSessionTest, JingleGoodInitiateAllSupportedAudioCodecs) {
2857   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2858   rtc::scoped_ptr<buzz::XmlElement> elem;
2859   test->TestGoodIncomingInitiate(
2860       kJingleInitiate, AudioCallOptions(), elem.use());
2861   test->TestHasAllSupportedAudioCodecs(elem.get());
2862 }
2863
2864 // Changes the codecs that our FakeMediaEngine will support with a different
2865 // preference order than the incoming offer.
2866 // Verifies the answer accepts the preference order of the remote peer.
2867 TEST_F(MediaSessionTest, JingleGoodInitiateDifferentPreferenceAudioCodecs) {
2868   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2869   test->fme()->SetAudioCodecs(MAKE_VECTOR(kAudioCodecsDifferentPreference));
2870   rtc::scoped_ptr<buzz::XmlElement> elem;
2871   test->TestGoodIncomingInitiate(
2872       kJingleInitiate, AudioCallOptions(), elem.use());
2873   test->TestHasAllSupportedAudioCodecs(elem.get());
2874 }
2875
2876 TEST_F(MediaSessionTest, JingleGoodInitiateSomeUnsupportedAudioCodecs) {
2877   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2878   rtc::scoped_ptr<buzz::XmlElement> elem;
2879   test->TestGoodIncomingInitiate(
2880       kJingleInitiateSomeUnsupported, AudioCallOptions(), elem.use());
2881   test->TestHasAudioCodecsFromInitiateSomeUnsupported(elem.get());
2882 }
2883
2884 TEST_F(MediaSessionTest, JingleGoodInitiateDynamicAudioCodecs) {
2885   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2886   rtc::scoped_ptr<buzz::XmlElement> elem;
2887   test->TestGoodIncomingInitiate(
2888       kJingleInitiateDynamicAudioCodecs, AudioCallOptions(), elem.use());
2889   test->TestHasAudioCodecsFromInitiateDynamicAudioCodecs(elem.get());
2890 }
2891
2892 TEST_F(MediaSessionTest, JingleGoodInitiateStaticAudioCodecs) {
2893   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2894   rtc::scoped_ptr<buzz::XmlElement> elem;
2895   test->TestGoodIncomingInitiate(
2896       kJingleInitiateStaticAudioCodecs, AudioCallOptions(), elem.use());
2897   test->TestHasAudioCodecsFromInitiateStaticAudioCodecs(elem.get());
2898 }
2899
2900 TEST_F(MediaSessionTest, JingleBadInitiateNoAudioCodecs) {
2901   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2902   test->TestBadIncomingInitiate(kJingleInitiateNoAudioCodecs);
2903 }
2904
2905 TEST_F(MediaSessionTest, JingleBadInitiateNoSupportedAudioCodecs) {
2906   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2907   test->TestBadIncomingInitiate(kJingleInitiateNoSupportedAudioCodecs);
2908 }
2909
2910 TEST_F(MediaSessionTest, JingleBadInitiateWrongClockrates) {
2911   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2912   test->TestBadIncomingInitiate(kJingleInitiateWrongClockrates);
2913 }
2914
2915 TEST_F(MediaSessionTest, JingleBadInitiateWrongChannels) {
2916   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2917   test->TestBadIncomingInitiate(kJingleInitiateWrongChannels);
2918 }
2919
2920 TEST_F(MediaSessionTest, JingleBadInitiateNoPayloadTypes) {
2921   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2922   test->TestBadIncomingInitiate(kJingleInitiateNoPayloadTypes);
2923 }
2924
2925 TEST_F(MediaSessionTest, JingleBadInitiateDynamicWithoutNames) {
2926   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2927   test->TestBadIncomingInitiate(kJingleInitiateDynamicWithoutNames);
2928 }
2929
2930 TEST_F(MediaSessionTest, JingleGoodOutgoingInitiate) {
2931   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2932   test->TestGoodOutgoingInitiate(AudioCallOptions());
2933 }
2934
2935 TEST_F(MediaSessionTest, JingleGoodOutgoingInitiateWithBandwidth) {
2936   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2937   cricket::CallOptions options = VideoCallOptions();
2938   options.video_bandwidth = 42000;
2939   test->TestGoodOutgoingInitiate(options);
2940 }
2941
2942 TEST_F(MediaSessionTest, JingleGoodOutgoingInitiateWithRtcpMux) {
2943   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2944   cricket::CallOptions options = VideoCallOptions();
2945   options.rtcp_mux_enabled = true;
2946   test->TestGoodOutgoingInitiate(options);
2947 }
2948
2949 TEST_F(MediaSessionTest, JingleGoodOutgoingInitiateWithRtpData) {
2950   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2951   cricket::CallOptions options;
2952   options.data_channel_type = cricket::DCT_RTP;
2953   test->ExpectCrypto(cricket::SEC_ENABLED);
2954   test->TestGoodOutgoingInitiate(options);
2955 }
2956
2957 TEST_F(MediaSessionTest, JingleGoodOutgoingInitiateWithSctpData) {
2958   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2959   cricket::CallOptions options;
2960   options.data_channel_type = cricket::DCT_SCTP;
2961   test->TestGoodOutgoingInitiate(options);
2962 }
2963
2964 // Crypto related tests.
2965
2966 // Offer has crypto but the session is not secured, just ignore it.
2967 TEST_F(MediaSessionTest, JingleInitiateWithCryptoIsIgnoredWhenNotSecured) {
2968   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2969   rtc::scoped_ptr<buzz::XmlElement> elem;
2970   test->TestGoodIncomingInitiate(
2971       AddEncryption(kJingleVideoInitiate, kJingleCryptoOffer),
2972       VideoCallOptions(),
2973       elem.use());
2974 }
2975
2976 // Offer has crypto required but the session is not secure, fail.
2977 TEST_F(MediaSessionTest, JingleInitiateWithCryptoRequiredWhenNotSecured) {
2978   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2979   test->TestBadIncomingInitiate(AddEncryption(kJingleVideoInitiate,
2980                                              kJingleRequiredCryptoOffer));
2981 }
2982
2983 // Offer has no crypto but the session is secure required, fail.
2984 TEST_F(MediaSessionTest, JingleInitiateWithNoCryptoFailsWhenSecureRequired) {
2985   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2986   test->ExpectCrypto(cricket::SEC_REQUIRED);
2987   test->TestBadIncomingInitiate(kJingleInitiate);
2988 }
2989
2990 // Offer has crypto and session is secure, expect crypto in the answer.
2991 TEST_F(MediaSessionTest, JingleInitiateWithCryptoWhenSecureEnabled) {
2992   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2993   rtc::scoped_ptr<buzz::XmlElement> elem;
2994   test->ExpectCrypto(cricket::SEC_ENABLED);
2995   test->TestGoodIncomingInitiate(
2996       AddEncryption(kJingleVideoInitiate, kJingleCryptoOffer),
2997       VideoCallOptions(),
2998       elem.use());
2999 }
3000
3001 // Offer has crypto and session is secure required, expect crypto in
3002 // the answer.
3003 TEST_F(MediaSessionTest, JingleInitiateWithCryptoWhenSecureRequired) {
3004   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3005   rtc::scoped_ptr<buzz::XmlElement> elem;
3006   test->ExpectCrypto(cricket::SEC_REQUIRED);
3007   test->TestGoodIncomingInitiate(
3008       AddEncryption(kJingleVideoInitiate, kJingleCryptoOffer),
3009       VideoCallOptions(),
3010       elem.use());
3011 }
3012
3013 // Offer has unsupported crypto and session is secure, no crypto in
3014 // the answer.
3015 TEST_F(MediaSessionTest, JingleInitiateWithUnsupportedCrypto) {
3016   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3017   rtc::scoped_ptr<buzz::XmlElement> elem;
3018   test->MakeSignalingSecure(cricket::SEC_ENABLED);
3019   test->TestGoodIncomingInitiate(
3020       AddEncryption(kJingleInitiate, kJingleUnsupportedCryptoOffer),
3021       VideoCallOptions(),
3022       elem.use());
3023 }
3024
3025 // Offer has unsupported REQUIRED crypto and session is not secure, fail.
3026 TEST_F(MediaSessionTest, JingleInitiateWithRequiredUnsupportedCrypto) {
3027   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3028   test->TestBadIncomingInitiate(
3029       AddEncryption(kJingleInitiate, kJingleRequiredUnsupportedCryptoOffer));
3030 }
3031
3032 // Offer has unsupported REQUIRED crypto and session is secure, fail.
3033 TEST_F(MediaSessionTest,
3034        JingleInitiateWithRequiredUnsupportedCryptoWhenSecure) {
3035   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3036   test->MakeSignalingSecure(cricket::SEC_ENABLED);
3037   test->TestBadIncomingInitiate(
3038       AddEncryption(kJingleInitiate, kJingleRequiredUnsupportedCryptoOffer));
3039 }
3040
3041 // Offer has unsupported REQUIRED crypto and session is required secure, fail.
3042 TEST_F(MediaSessionTest,
3043        JingleInitiateWithRequiredUnsupportedCryptoWhenSecureRequired) {
3044   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3045   test->MakeSignalingSecure(cricket::SEC_REQUIRED);
3046   test->TestBadIncomingInitiate(
3047       AddEncryption(kJingleInitiate, kJingleRequiredUnsupportedCryptoOffer));
3048 }
3049
3050 TEST_F(MediaSessionTest, JingleGoodOutgoingInitiateWithCrypto) {
3051   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3052   test->ExpectCrypto(cricket::SEC_ENABLED);
3053   test->TestGoodOutgoingInitiate(AudioCallOptions());
3054 }
3055
3056 TEST_F(MediaSessionTest, JingleGoodOutgoingInitiateWithCryptoRequired) {
3057   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3058   test->ExpectCrypto(cricket::SEC_REQUIRED);
3059   test->TestGoodOutgoingInitiate(AudioCallOptions());
3060 }
3061
3062 TEST_F(MediaSessionTest, JingleIncomingAcceptWithSsrcs) {
3063   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3064   cricket::CallOptions options = VideoCallOptions();
3065   options.is_muc = true;
3066   test->TestIncomingAcceptWithSsrcs(kJingleAcceptWithSsrcs, options);
3067 }
3068
3069 TEST_F(MediaSessionTest, JingleIncomingAcceptWithRtpDataSsrcs) {
3070   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3071   cricket::CallOptions options = VideoCallOptions();
3072   options.is_muc = true;
3073   options.data_channel_type = cricket::DCT_RTP;
3074   test->TestIncomingAcceptWithSsrcs(kJingleAcceptWithRtpDataSsrcs, options);
3075 }
3076
3077 TEST_F(MediaSessionTest, JingleIncomingAcceptWithSctpData) {
3078   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3079   cricket::CallOptions options = VideoCallOptions();
3080   options.is_muc = true;
3081   options.data_channel_type = cricket::DCT_SCTP;
3082   test->TestIncomingAcceptWithSsrcs(kJingleAcceptWithSctpData, options);
3083 }
3084
3085 TEST_F(MediaSessionTest, JingleStreamsUpdateAndView) {
3086   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3087   test->TestStreamsUpdateAndViewRequests();
3088 }
3089
3090 TEST_F(MediaSessionTest, JingleSendVideoStreamUpdate) {
3091   rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3092   test->TestSendVideoStreamUpdate();
3093 }
3094
3095 // Gingle tests
3096
3097 TEST_F(MediaSessionTest, GingleGoodVideoInitiate) {
3098   rtc::scoped_ptr<buzz::XmlElement> elem;
3099   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3100   test->TestGoodIncomingInitiate(
3101       kGingleVideoInitiate, VideoCallOptions(), elem.use());
3102   test->TestCodecsOfVideoInitiate(elem.get());
3103 }
3104
3105 TEST_F(MediaSessionTest, GingleGoodVideoInitiateWithBandwidth) {
3106   rtc::scoped_ptr<buzz::XmlElement> elem;
3107   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3108   test->ExpectVideoBandwidth(42000);
3109   test->TestGoodIncomingInitiate(
3110       kGingleVideoInitiateWithBandwidth, VideoCallOptions(), elem.use());
3111 }
3112
3113 TEST_F(MediaSessionTest, GingleGoodInitiateAllSupportedAudioCodecs) {
3114   rtc::scoped_ptr<buzz::XmlElement> elem;
3115   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3116   test->TestGoodIncomingInitiate(
3117       kGingleInitiate, AudioCallOptions(), elem.use());
3118   test->TestHasAllSupportedAudioCodecs(elem.get());
3119 }
3120
3121 TEST_F(MediaSessionTest, GingleGoodInitiateAllSupportedAudioCodecsWithCrypto) {
3122   rtc::scoped_ptr<buzz::XmlElement> elem;
3123   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3124   test->ExpectCrypto(cricket::SEC_ENABLED);
3125   test->TestGoodIncomingInitiate(
3126       AddEncryption(kGingleInitiate, kGingleCryptoOffer),
3127       AudioCallOptions(),
3128       elem.use());
3129   test->TestHasAllSupportedAudioCodecs(elem.get());
3130 }
3131
3132 // Changes the codecs that our FakeMediaEngine will support with a different
3133 // preference order than the incoming offer.
3134 // Verifies the answer accepts the preference order of the remote peer.
3135 TEST_F(MediaSessionTest, GingleGoodInitiateDifferentPreferenceAudioCodecs) {
3136   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3137   test->fme()->SetAudioCodecs(MAKE_VECTOR(kAudioCodecsDifferentPreference));
3138   rtc::scoped_ptr<buzz::XmlElement> elem;
3139   test->TestGoodIncomingInitiate(
3140       kGingleInitiate, AudioCallOptions(), elem.use());
3141   test->TestHasAllSupportedAudioCodecs(elem.get());
3142 }
3143
3144 TEST_F(MediaSessionTest, GingleGoodInitiateSomeUnsupportedAudioCodecs) {
3145   rtc::scoped_ptr<buzz::XmlElement> elem;
3146   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3147   test->TestGoodIncomingInitiate(
3148       kGingleInitiateSomeUnsupported, AudioCallOptions(), elem.use());
3149   test->TestHasAudioCodecsFromInitiateSomeUnsupported(elem.get());
3150 }
3151
3152 TEST_F(MediaSessionTest, GingleGoodInitiateDynamicAudioCodecs) {
3153   rtc::scoped_ptr<buzz::XmlElement> elem;
3154   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3155   test->TestGoodIncomingInitiate(
3156       kGingleInitiateDynamicAudioCodecs, AudioCallOptions(), elem.use());
3157   test->TestHasAudioCodecsFromInitiateDynamicAudioCodecs(elem.get());
3158 }
3159
3160 TEST_F(MediaSessionTest, GingleGoodInitiateStaticAudioCodecs) {
3161   rtc::scoped_ptr<buzz::XmlElement> elem;
3162   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3163   test->TestGoodIncomingInitiate(
3164       kGingleInitiateStaticAudioCodecs, AudioCallOptions(), elem.use());
3165   test->TestHasAudioCodecsFromInitiateStaticAudioCodecs(elem.get());
3166 }
3167
3168 TEST_F(MediaSessionTest, GingleGoodInitiateNoAudioCodecs) {
3169   rtc::scoped_ptr<buzz::XmlElement> elem;
3170   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3171   test->TestGoodIncomingInitiate(
3172       kGingleInitiateNoAudioCodecs, AudioCallOptions(), elem.use());
3173   test->TestHasDefaultAudioCodecs(elem.get());
3174 }
3175
3176 TEST_F(MediaSessionTest, GingleBadInitiateNoSupportedAudioCodecs) {
3177   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3178   test->TestBadIncomingInitiate(kGingleInitiateNoSupportedAudioCodecs);
3179 }
3180
3181 TEST_F(MediaSessionTest, GingleBadInitiateWrongClockrates) {
3182   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3183   test->TestBadIncomingInitiate(kGingleInitiateWrongClockrates);
3184 }
3185
3186 TEST_F(MediaSessionTest, GingleBadInitiateWrongChannels) {
3187   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3188   test->TestBadIncomingInitiate(kGingleInitiateWrongChannels);
3189 }
3190
3191 TEST_F(MediaSessionTest, GingleBadInitiateNoPayloadTypes) {
3192   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3193   test->TestBadIncomingInitiate(kGingleInitiateNoPayloadTypes);
3194 }
3195
3196 TEST_F(MediaSessionTest, GingleBadInitiateDynamicWithoutNames) {
3197   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3198   test->TestBadIncomingInitiate(kGingleInitiateDynamicWithoutNames);
3199 }
3200
3201 TEST_F(MediaSessionTest, GingleGoodOutgoingInitiate) {
3202   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3203   test->TestGoodOutgoingInitiate(AudioCallOptions());
3204 }
3205
3206 TEST_F(MediaSessionTest, GingleGoodOutgoingInitiateWithBandwidth) {
3207   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3208   cricket::CallOptions options = VideoCallOptions();
3209   options.video_bandwidth = 42000;
3210   test->TestGoodOutgoingInitiate(options);
3211 }
3212
3213 // Crypto related tests.
3214
3215 // Offer has crypto but the session is not secured, just ignore it.
3216 TEST_F(MediaSessionTest, GingleInitiateWithCryptoIsIgnoredWhenNotSecured) {
3217   rtc::scoped_ptr<buzz::XmlElement> elem;
3218   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3219   test->TestGoodIncomingInitiate(
3220       AddEncryption(kGingleInitiate, kGingleCryptoOffer),
3221       VideoCallOptions(),
3222       elem.use());
3223 }
3224
3225 // Offer has crypto required but the session is not secure, fail.
3226 TEST_F(MediaSessionTest, GingleInitiateWithCryptoRequiredWhenNotSecured) {
3227   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3228   test->TestBadIncomingInitiate(AddEncryption(kGingleInitiate,
3229                                              kGingleRequiredCryptoOffer));
3230 }
3231
3232 // Offer has no crypto but the session is secure required, fail.
3233 TEST_F(MediaSessionTest, GingleInitiateWithNoCryptoFailsWhenSecureRequired) {
3234   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3235   test->ExpectCrypto(cricket::SEC_REQUIRED);
3236   test->TestBadIncomingInitiate(kGingleInitiate);
3237 }
3238
3239 // Offer has crypto and session is secure, expect crypto in the answer.
3240 TEST_F(MediaSessionTest, GingleInitiateWithCryptoWhenSecureEnabled) {
3241   rtc::scoped_ptr<buzz::XmlElement> elem;
3242   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3243   test->ExpectCrypto(cricket::SEC_ENABLED);
3244   test->TestGoodIncomingInitiate(
3245       AddEncryption(kGingleInitiate, kGingleCryptoOffer),
3246       VideoCallOptions(),
3247       elem.use());
3248 }
3249
3250 // Offer has crypto and session is secure required, expect crypto in
3251 // the answer.
3252 TEST_F(MediaSessionTest, GingleInitiateWithCryptoWhenSecureRequired) {
3253   rtc::scoped_ptr<buzz::XmlElement> elem;
3254   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3255   test->ExpectCrypto(cricket::SEC_REQUIRED);
3256   test->TestGoodIncomingInitiate(
3257       AddEncryption(kGingleInitiate, kGingleCryptoOffer),
3258       VideoCallOptions(),
3259       elem.use());
3260 }
3261
3262 // Offer has unsupported crypto and session is secure, no crypto in
3263 // the answer.
3264 TEST_F(MediaSessionTest, GingleInitiateWithUnsupportedCrypto) {
3265   rtc::scoped_ptr<buzz::XmlElement> elem;
3266   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3267   test->MakeSignalingSecure(cricket::SEC_ENABLED);
3268   test->TestGoodIncomingInitiate(
3269       AddEncryption(kGingleInitiate, kGingleUnsupportedCryptoOffer),
3270       VideoCallOptions(),
3271       elem.use());
3272 }
3273
3274 // Offer has unsupported REQUIRED crypto and session is not secure, fail.
3275 TEST_F(MediaSessionTest, GingleInitiateWithRequiredUnsupportedCrypto) {
3276   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3277   test->TestBadIncomingInitiate(
3278       AddEncryption(kGingleInitiate, kGingleRequiredUnsupportedCryptoOffer));
3279 }
3280
3281 // Offer has unsupported REQUIRED crypto and session is secure, fail.
3282 TEST_F(MediaSessionTest,
3283        GingleInitiateWithRequiredUnsupportedCryptoWhenSecure) {
3284   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3285   test->MakeSignalingSecure(cricket::SEC_ENABLED);
3286   test->TestBadIncomingInitiate(
3287       AddEncryption(kGingleInitiate, kGingleRequiredUnsupportedCryptoOffer));
3288 }
3289
3290 // Offer has unsupported REQUIRED crypto and session is required secure, fail.
3291 TEST_F(MediaSessionTest,
3292        GingleInitiateWithRequiredUnsupportedCryptoWhenSecureRequired) {
3293   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3294   test->MakeSignalingSecure(cricket::SEC_REQUIRED);
3295   test->TestBadIncomingInitiate(
3296       AddEncryption(kGingleInitiate, kGingleRequiredUnsupportedCryptoOffer));
3297 }
3298
3299 TEST_F(MediaSessionTest, GingleGoodOutgoingInitiateWithCrypto) {
3300   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3301   test->ExpectCrypto(cricket::SEC_ENABLED);
3302   test->TestGoodOutgoingInitiate(AudioCallOptions());
3303 }
3304
3305 TEST_F(MediaSessionTest, GingleGoodOutgoingInitiateWithCryptoRequired) {
3306   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3307   test->ExpectCrypto(cricket::SEC_REQUIRED);
3308   test->TestGoodOutgoingInitiate(AudioCallOptions());
3309 }
3310
3311 TEST_F(MediaSessionTest, GingleIncomingAcceptWithSsrcs) {
3312   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3313   cricket::CallOptions options = VideoCallOptions();
3314   options.is_muc = true;
3315   test->TestIncomingAcceptWithSsrcs(kGingleAcceptWithSsrcs, options);
3316 }
3317
3318 TEST_F(MediaSessionTest, GingleGoodOutgoingInitiateWithRtpData) {
3319   rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3320   cricket::CallOptions options;
3321   options.data_channel_type = cricket::DCT_RTP;
3322   test->ExpectCrypto(cricket::SEC_ENABLED);
3323   test->TestGoodOutgoingInitiate(options);
3324 }