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