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