• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
44 using cricket::AudioCodec;
45 using cricket::AudioContentDescription;
46 using cricket::Codec;
47 using cricket::DataCodec;
48 using cricket::DataContentDescription;
49 using cricket::FeedbackParam;
50 using cricket::FeedbackParams;
51 using cricket::VideoCodec;
52 using 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.
56 static 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 
77 static const cricket::VideoCodec kVideoCodecs[] = {
78   cricket::VideoCodec(96, "H264-SVC", 320, 200, 30, 1)
79 };
80 
81 static const cricket::DataCodec kDataCodecs[] = {
82   cricket::DataCodec(127, "google-data", 0)
83 };
84 
85 const 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.
95 const 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 
104 const 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 
113 const 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 
122 const 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 
131 const 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"
141 const 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 
150 const 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 
158 const 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 
204 const 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.
275 const 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 
321 const 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 
390 const 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 
426 const 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 
441 const 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 
465 const 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 
496 const 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 
526 const 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 
551 const 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
578 const 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 
606 const 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 
637 const 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.
654 const 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 
666 const 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
683 const 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 
693 const 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.
708 const 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 
724 const 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.
745 const 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 
759 const 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.
777 const 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 
789 const 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.
805 const 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 
821 const 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.
838 const 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 
850 const 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.
865 const 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 
877 const 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 
891 const uint32 kAudioSsrc = 4294967295U;
892 const uint32 kVideoSsrc = 87654321;
893 const uint32 kDataSsrc = 1010101;
894 // Note that this message does not specify a session ID. It must be populated
895 // before use.
896 const 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 
913 const 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 
935 const 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 
963 const 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 
JingleView(const std::string & ssrc,const std::string & width,const std::string & height,const std::string & framerate)991 std::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 
JingleStreamAdd(const std::string & content_name,const std::string & nick,const std::string & name,const std::string & ssrc)1020 std::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 
JingleOutboundStreamRemove(const std::string & sid,const std::string & content_name,const std::string & name)1054 std::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 
JingleOutboundStreamAdd(const std::string & sid,const std::string & content_name,const std::string & name,const std::string & ssrc)1084 std::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 
JingleStreamAddWithoutSsrc(const std::string & content_name,const std::string & nick,const std::string & name)1116 std::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 
JingleStreamRemove(const std::string & content_name,const std::string & nick,const std::string & name)1148 std::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.
AudioCallOptions()1181 static 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.
VideoCallOptions()1191 static 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 
CopyElement(const buzz::XmlElement * elem)1199 static buzz::XmlElement* CopyElement(const buzz::XmlElement* elem) {
1200   return new buzz::XmlElement(*elem);
1201 }
1202 
AddEncryption(std::string stanza,std::string encryption)1203 static 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 
IntFromJingleCodecParameter(const buzz::XmlElement * parameter,const std::string & expected_name)1212 static 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 
1229 template <class CodecClass, class DescriptionClass>
VerifyCodecFbParams(const FeedbackParams & expected,const DescriptionClass * desc)1230 static 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.
1244 class 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;
~MediaSessionTestParser()1268   virtual ~MediaSessionTestParser() {}
1269 };
1270 
1271 class JingleSessionTestParser : public MediaSessionTestParser {
1272  public:
JingleSessionTestParser()1273   JingleSessionTestParser() {}
1274 
~JingleSessionTestParser()1275   ~JingleSessionTestParser() {
1276   }
1277 
ActionFromStanza(buzz::XmlElement * stanza)1278   buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
1279     return stanza->FirstNamed(cricket::QN_JINGLE);
1280   }
1281 
ContentFromAction(buzz::XmlElement * action)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 
NextContent(buzz::XmlElement * content)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 
PayloadTypeFromContent(buzz::XmlElement * content)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 
NextFromPayloadType(buzz::XmlElement * payload_type)1306   buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
1307     return payload_type->NextNamed(cricket::QN_JINGLE_RTP_PAYLOADTYPE);
1308   }
1309 
ParsePayloadTypeFeedbackParameters(const buzz::XmlElement * element,FeedbackParams * params)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 
AudioCodecFromPayloadType(const buzz::XmlElement * payload_type)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 
VideoCodecFromPayloadType(const buzz::XmlElement * payload_type)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 
DataCodecFromPayloadType(const buzz::XmlElement * payload_type)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 
ActionIsTerminate(const buzz::XmlElement * action)1397   bool ActionIsTerminate(const buzz::XmlElement* action) {
1398     return (action->HasAttr(cricket::QN_ACTION) &&
1399             action->Attr(cricket::QN_ACTION) == "session-terminate");
1400   }
1401 
EncryptionFromContent(buzz::XmlElement * content)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 
NextFromEncryption(buzz::XmlElement * encryption)1411   buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
1412     return encryption->NextNamed(cricket::QN_ENCRYPTION);
1413   }
1414 
BandwidthFromContent(buzz::XmlElement * content)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 
RtcpMuxFromContent(buzz::XmlElement * content)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 
1432 class GingleSessionTestParser : public MediaSessionTestParser {
1433  public:
GingleSessionTestParser()1434   GingleSessionTestParser() : found_content_count_(0) {}
1435 
ActionFromStanza(buzz::XmlElement * stanza)1436   buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
1437     return stanza->FirstNamed(cricket::QN_GINGLE_SESSION);
1438   }
1439 
ContentFromAction(buzz::XmlElement * session)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.
NextContent(buzz::XmlElement * content)1449   buzz::XmlElement* NextContent(buzz::XmlElement* content) {
1450     found_content_count_++;
1451     return content;
1452   }
1453 
PayloadTypeFromContent(buzz::XmlElement * content)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 
NextFromPayloadType(buzz::XmlElement * payload_type)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 
AudioCodecFromPayloadType(const buzz::XmlElement * payload_type)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 
VideoCodecFromPayloadType(const buzz::XmlElement * payload_type)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 
DataCodecFromPayloadType(const buzz::XmlElement * payload_type)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 
EncryptionFromContent(buzz::XmlElement * content)1526   buzz::XmlElement* EncryptionFromContent(
1527       buzz::XmlElement* content) {
1528     return content->FirstNamed(cricket::QN_ENCRYPTION);
1529   }
1530 
NextFromEncryption(buzz::XmlElement * encryption)1531   buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
1532     return encryption->NextNamed(cricket::QN_ENCRYPTION);
1533   }
1534 
BandwidthFromContent(buzz::XmlElement * content)1535   const buzz::XmlElement* BandwidthFromContent(buzz::XmlElement* content) {
1536     return content->FirstNamed(cricket::QN_GINGLE_VIDEO_BANDWIDTH);
1537   }
1538 
RtcpMuxFromContent(buzz::XmlElement * content)1539   const buzz::XmlElement* RtcpMuxFromContent(buzz::XmlElement* content) {
1540     return NULL;
1541   }
1542 
ActionIsTerminate(const buzz::XmlElement * session)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 
1551 class MediaSessionClientTest : public sigslot::has_slots<> {
1552  public:
MediaSessionClientTest(MediaSessionTestParser * parser,cricket::SignalingProtocol initial_protocol)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 
~MediaSessionClientTest()1602   ~MediaSessionClientTest() {
1603     delete client_;
1604     delete sm_;
1605     delete pa_;
1606     delete nm_;
1607     delete parser_;
1608     ClearStanzas();
1609   }
1610 
ActionFromStanza(buzz::XmlElement * stanza)1611   buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
1612     return parser_->ActionFromStanza(stanza);
1613   }
1614 
ContentFromAction(buzz::XmlElement * action)1615   buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) {
1616     return parser_->ContentFromAction(action);
1617   }
1618 
PayloadTypeFromContent(buzz::XmlElement * payload)1619   buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* payload) {
1620     return parser_->PayloadTypeFromContent(payload);
1621   }
1622 
NextFromPayloadType(buzz::XmlElement * payload_type)1623   buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
1624     return parser_->NextFromPayloadType(payload_type);
1625   }
1626 
EncryptionFromContent(buzz::XmlElement * content)1627   buzz::XmlElement* EncryptionFromContent(buzz::XmlElement* content) {
1628     return parser_->EncryptionFromContent(content);
1629   }
1630 
NextFromEncryption(buzz::XmlElement * encryption)1631   buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
1632     return parser_->NextFromEncryption(encryption);
1633   }
1634 
AudioCodecFromPayloadType(const buzz::XmlElement * payload_type)1635   cricket::AudioCodec AudioCodecFromPayloadType(
1636       const buzz::XmlElement* payload_type) {
1637     return parser_->AudioCodecFromPayloadType(payload_type);
1638   }
1639 
VideoCodecFromPayloadType(const buzz::XmlElement * payload_type)1640   cricket::VideoCodec VideoCodecFromPayloadType(
1641       const buzz::XmlElement* payload_type) {
1642     return parser_->VideoCodecFromPayloadType(payload_type);
1643   }
1644 
DataCodecFromPayloadType(const buzz::XmlElement * payload_type)1645   cricket::DataCodec DataCodecFromPayloadType(
1646       const buzz::XmlElement* payload_type) {
1647     return parser_->DataCodecFromPayloadType(payload_type);
1648   }
1649 
GetFirstAudioContentDescription(const cricket::SessionDescription * sdesc)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 
GetFirstVideoContentDescription(const cricket::SessionDescription * sdesc)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 
CheckCryptoFromGoodIncomingInitiate(const cricket::Session * session)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 
CheckCryptoForGoodOutgoingAccept(const cricket::Session * session)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 
CheckBadCryptoFromIncomingInitiate(const cricket::Session * session)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 
CheckNoCryptoForOutgoingAccept(const cricket::Session * session)1704   void CheckNoCryptoForOutgoingAccept(const cricket::Session* session) {
1705     const AudioContentDescription* content =
1706         GetFirstAudioContentDescription(session->local_description());
1707     ASSERT_TRUE(content->cryptos().empty());
1708   }
1709 
CheckRtcpFb(const cricket::SessionDescription * sdesc)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 
CheckVideoBandwidth(int expected_bandwidth,const cricket::SessionDescription * sdesc)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 
CheckVideoRtcpMux(bool expected_video_rtcp_mux,const cricket::SessionDescription * sdesc)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 
CheckRtpDataContent(buzz::XmlElement * content)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 
CheckSctpDataContent(buzz::XmlElement * content)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 
CheckDataRtcpMux(bool expected_data_rtcp_mux,const cricket::SessionDescription * sdesc)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 
CheckAudioSsrcForIncomingAccept(const cricket::Session * session)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 
CheckVideoSsrcForIncomingAccept(const cricket::Session * session)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 
CheckDataSsrcForIncomingAccept(const cricket::Session * session)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 
TestGoodIncomingInitiate(const std::string & initiate_string,const cricket::CallOptions & options,buzz::XmlElement ** element)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 
TestRejectOffer(const std::string & initiate_string,const cricket::CallOptions & options,buzz::XmlElement ** element)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 
TestBadIncomingInitiate(const std::string & initiate_string)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 
VerifyAudioCodec(const AudioCodec & codec,int id,const std::string & name,int clockrate,int bitrate,int channels)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 
TestGoodOutgoingInitiate(const cricket::CallOptions & options)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 
TestHasAllSupportedAudioCodecs(buzz::XmlElement * e)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 
TestCodecsOfVideoInitiate(buzz::XmlElement * content)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 
TestHasAudioCodecsFromInitiateSomeUnsupported(buzz::XmlElement * e)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 
TestHasAudioCodecsFromInitiateDynamicAudioCodecs(buzz::XmlElement * e)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 
TestHasDefaultAudioCodecs(buzz::XmlElement * e)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 
TestHasAudioCodecsFromInitiateStaticAudioCodecs(buzz::XmlElement * e)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 
TestGingleInitiateWithUnsupportedCrypto(const std::string & initiate_string,buzz::XmlElement ** element)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 
TestIncomingAcceptWithSsrcs(const std::string & accept_string,cricket::CallOptions & options)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 
ClearStanzas()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 
SetJingleSid(buzz::XmlElement * stanza)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 
TestSendVideoStreamUpdate()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 
TestStreamsUpdateAndViewRequests()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 
MakeSignalingSecure(cricket::SecurePolicy secure)2754   void MakeSignalingSecure(cricket::SecurePolicy secure) {
2755     client_->set_secure(secure);
2756   }
2757 
ExpectCrypto(cricket::SecurePolicy secure)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 
ExpectVideoBandwidth(int bandwidth)2766   void ExpectVideoBandwidth(int bandwidth) {
2767     expected_video_bandwidth_ = bandwidth;
2768   }
2769 
ExpectVideoRtcpMux(bool rtcp_mux)2770   void ExpectVideoRtcpMux(bool rtcp_mux) {
2771     expected_video_rtcp_mux_ = rtcp_mux;
2772   }
2773 
2774   template <class C>
SetCodecFeedbackParams(std::vector<C> * codecs,const FeedbackParams & fb_params)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 
ExpectRtcpFb()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:
OnSendStanza(cricket::SessionManager * manager,const buzz::XmlElement * stanza)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 
OnSessionCreate(cricket::Session * session,bool initiate)2803   void OnSessionCreate(cricket::Session* session, bool initiate) {
2804     session->set_current_protocol(initial_protocol_);
2805   }
2806 
OnCallCreate(cricket::Call * call)2807   void OnCallCreate(cricket::Call *call) {
2808     call_ = call;
2809     call->SignalMediaStreamsUpdate.connect(
2810         this, &MediaSessionClientTest::OnMediaStreamsUpdate);
2811   }
2812 
OnCallDestroy(cricket::Call * call)2813   void OnCallDestroy(cricket::Call *call) {
2814     call_ = NULL;
2815   }
2816 
OnMediaStreamsUpdate(cricket::Call * call,cricket::Session * session,const cricket::MediaStreams & added,const cricket::MediaStreams & removed)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 
GingleTest()2847 MediaSessionClientTest* GingleTest() {
2848   return new MediaSessionClientTest(new GingleSessionTestParser(),
2849                                     cricket::PROTOCOL_GINGLE);
2850 }
2851 
JingleTest()2852 MediaSessionClientTest* JingleTest() {
2853   return new MediaSessionClientTest(new JingleSessionTestParser(),
2854                                     cricket::PROTOCOL_JINGLE);
2855 }
2856 
TEST(MediaSessionTest,JingleGoodInitiateWithRtcpFb)2857 TEST(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 
TEST(MediaSessionTest,JingleGoodVideoInitiate)2868 TEST(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 
TEST(MediaSessionTest,JingleGoodVideoInitiateWithBandwidth)2876 TEST(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 
TEST(MediaSessionTest,JingleGoodVideoInitiateWithRtcpMux)2884 TEST(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 
TEST(MediaSessionTest,JingleGoodVideoInitiateWithRtpData)2892 TEST(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 
TEST(MediaSessionTest,JingleGoodVideoInitiateWithSctpData)2903 TEST(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 
TEST(MediaSessionTest,JingleRejectAudio)2913 TEST(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 
TEST(MediaSessionTest,JingleRejectVideo)2922 TEST(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 
TEST(MediaSessionTest,JingleRejectData)2930 TEST(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 
TEST(MediaSessionTest,JingleRejectVideoAndData)2937 TEST(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 
TEST(MediaSessionTest,JingleGoodInitiateAllSupportedAudioCodecs)2944 TEST(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 
TEST(MediaSessionTest,JingleGoodInitiateDifferentPreferenceAudioCodecs)2952 TEST(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 
TEST(MediaSessionTest,JingleGoodInitiateSomeUnsupportedAudioCodecs)2960 TEST(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 
TEST(MediaSessionTest,JingleGoodInitiateDynamicAudioCodecs)2968 TEST(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 
TEST(MediaSessionTest,JingleGoodInitiateStaticAudioCodecs)2976 TEST(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 
TEST(MediaSessionTest,JingleBadInitiateNoAudioCodecs)2984 TEST(MediaSessionTest, JingleBadInitiateNoAudioCodecs) {
2985   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2986   test->TestBadIncomingInitiate(kJingleInitiateNoAudioCodecs);
2987 }
2988 
TEST(MediaSessionTest,JingleBadInitiateNoSupportedAudioCodecs)2989 TEST(MediaSessionTest, JingleBadInitiateNoSupportedAudioCodecs) {
2990   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2991   test->TestBadIncomingInitiate(kJingleInitiateNoSupportedAudioCodecs);
2992 }
2993 
TEST(MediaSessionTest,JingleBadInitiateWrongClockrates)2994 TEST(MediaSessionTest, JingleBadInitiateWrongClockrates) {
2995   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
2996   test->TestBadIncomingInitiate(kJingleInitiateWrongClockrates);
2997 }
2998 
TEST(MediaSessionTest,JingleBadInitiateWrongChannels)2999 TEST(MediaSessionTest, JingleBadInitiateWrongChannels) {
3000   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3001   test->TestBadIncomingInitiate(kJingleInitiateWrongChannels);
3002 }
3003 
TEST(MediaSessionTest,JingleBadInitiateNoPayloadTypes)3004 TEST(MediaSessionTest, JingleBadInitiateNoPayloadTypes) {
3005   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3006   test->TestBadIncomingInitiate(kJingleInitiateNoPayloadTypes);
3007 }
3008 
TEST(MediaSessionTest,JingleBadInitiateDynamicWithoutNames)3009 TEST(MediaSessionTest, JingleBadInitiateDynamicWithoutNames) {
3010   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3011   test->TestBadIncomingInitiate(kJingleInitiateDynamicWithoutNames);
3012 }
3013 
TEST(MediaSessionTest,JingleGoodOutgoingInitiate)3014 TEST(MediaSessionTest, JingleGoodOutgoingInitiate) {
3015   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3016   test->TestGoodOutgoingInitiate(AudioCallOptions());
3017 }
3018 
TEST(MediaSessionTest,JingleGoodOutgoingInitiateWithBandwidth)3019 TEST(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 
TEST(MediaSessionTest,JingleGoodOutgoingInitiateWithRtcpMux)3026 TEST(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 
TEST(MediaSessionTest,JingleGoodOutgoingInitiateWithRtpData)3033 TEST(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 
TEST(MediaSessionTest,JingleGoodOutgoingInitiateWithSctpData)3041 TEST(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.
TEST(MediaSessionTest,JingleInitiateWithCryptoIsIgnoredWhenNotSecured)3051 TEST(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.
TEST(MediaSessionTest,JingleInitiateWithCryptoRequiredWhenNotSecured)3061 TEST(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.
TEST(MediaSessionTest,JingleInitiateWithNoCryptoFailsWhenSecureRequired)3068 TEST(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.
TEST(MediaSessionTest,JingleInitiateWithCryptoWhenSecureEnabled)3075 TEST(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.
TEST(MediaSessionTest,JingleInitiateWithCryptoWhenSecureRequired)3087 TEST(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.
TEST(MediaSessionTest,JingleInitiateWithUnsupportedCrypto)3099 TEST(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.
TEST(MediaSessionTest,JingleInitiateWithRequiredUnsupportedCrypto)3110 TEST(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.
TEST(MediaSessionTest,JingleInitiateWithRequiredUnsupportedCryptoWhenSecure)3117 TEST(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.
TEST(MediaSessionTest,JingleInitiateWithRequiredUnsupportedCryptoWhenSecureRequired)3125 TEST(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 
TEST(MediaSessionTest,JingleGoodOutgoingInitiateWithCrypto)3134 TEST(MediaSessionTest, JingleGoodOutgoingInitiateWithCrypto) {
3135   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3136   test->ExpectCrypto(cricket::SEC_ENABLED);
3137   test->TestGoodOutgoingInitiate(AudioCallOptions());
3138 }
3139 
TEST(MediaSessionTest,JingleGoodOutgoingInitiateWithCryptoRequired)3140 TEST(MediaSessionTest, JingleGoodOutgoingInitiateWithCryptoRequired) {
3141   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3142   test->ExpectCrypto(cricket::SEC_REQUIRED);
3143   test->TestGoodOutgoingInitiate(AudioCallOptions());
3144 }
3145 
TEST(MediaSessionTest,JingleIncomingAcceptWithSsrcs)3146 TEST(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 
TEST(MediaSessionTest,JingleIncomingAcceptWithRtpDataSsrcs)3153 TEST(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 
TEST(MediaSessionTest,JingleIncomingAcceptWithSctpData)3161 TEST(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 
TEST(MediaSessionTest,JingleStreamsUpdateAndView)3169 TEST(MediaSessionTest, JingleStreamsUpdateAndView) {
3170   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3171   test->TestStreamsUpdateAndViewRequests();
3172 }
3173 
TEST(MediaSessionTest,JingleSendVideoStreamUpdate)3174 TEST(MediaSessionTest, JingleSendVideoStreamUpdate) {
3175   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
3176   test->TestSendVideoStreamUpdate();
3177 }
3178 
3179 // Gingle tests
3180 
TEST(MediaSessionTest,GingleGoodVideoInitiate)3181 TEST(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 
TEST(MediaSessionTest,GingleGoodVideoInitiateWithBandwidth)3189 TEST(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 
TEST(MediaSessionTest,GingleGoodInitiateAllSupportedAudioCodecs)3197 TEST(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 
TEST(MediaSessionTest,GingleGoodInitiateAllSupportedAudioCodecsWithCrypto)3205 TEST(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 
TEST(MediaSessionTest,GingleGoodInitiateDifferentPreferenceAudioCodecs)3216 TEST(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 
TEST(MediaSessionTest,GingleGoodInitiateSomeUnsupportedAudioCodecs)3224 TEST(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 
TEST(MediaSessionTest,GingleGoodInitiateDynamicAudioCodecs)3232 TEST(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 
TEST(MediaSessionTest,GingleGoodInitiateStaticAudioCodecs)3240 TEST(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 
TEST(MediaSessionTest,GingleGoodInitiateNoAudioCodecs)3248 TEST(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 
TEST(MediaSessionTest,GingleBadInitiateNoSupportedAudioCodecs)3256 TEST(MediaSessionTest, GingleBadInitiateNoSupportedAudioCodecs) {
3257   talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3258   test->TestBadIncomingInitiate(kGingleInitiateNoSupportedAudioCodecs);
3259 }
3260 
TEST(MediaSessionTest,GingleBadInitiateWrongClockrates)3261 TEST(MediaSessionTest, GingleBadInitiateWrongClockrates) {
3262   talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3263   test->TestBadIncomingInitiate(kGingleInitiateWrongClockrates);
3264 }
3265 
TEST(MediaSessionTest,GingleBadInitiateWrongChannels)3266 TEST(MediaSessionTest, GingleBadInitiateWrongChannels) {
3267   talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3268   test->TestBadIncomingInitiate(kGingleInitiateWrongChannels);
3269 }
3270 
3271 
TEST(MediaSessionTest,GingleBadInitiateNoPayloadTypes)3272 TEST(MediaSessionTest, GingleBadInitiateNoPayloadTypes) {
3273   talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3274   test->TestBadIncomingInitiate(kGingleInitiateNoPayloadTypes);
3275 }
3276 
TEST(MediaSessionTest,GingleBadInitiateDynamicWithoutNames)3277 TEST(MediaSessionTest, GingleBadInitiateDynamicWithoutNames) {
3278   talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3279   test->TestBadIncomingInitiate(kGingleInitiateDynamicWithoutNames);
3280 }
3281 
TEST(MediaSessionTest,GingleGoodOutgoingInitiate)3282 TEST(MediaSessionTest, GingleGoodOutgoingInitiate) {
3283   talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3284   test->TestGoodOutgoingInitiate(AudioCallOptions());
3285 }
3286 
TEST(MediaSessionTest,GingleGoodOutgoingInitiateWithBandwidth)3287 TEST(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.
TEST(MediaSessionTest,GingleInitiateWithCryptoIsIgnoredWhenNotSecured)3297 TEST(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.
TEST(MediaSessionTest,GingleInitiateWithCryptoRequiredWhenNotSecured)3307 TEST(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.
TEST(MediaSessionTest,GingleInitiateWithNoCryptoFailsWhenSecureRequired)3314 TEST(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.
TEST(MediaSessionTest,GingleInitiateWithCryptoWhenSecureEnabled)3321 TEST(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.
TEST(MediaSessionTest,GingleInitiateWithCryptoWhenSecureRequired)3333 TEST(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.
TEST(MediaSessionTest,GingleInitiateWithUnsupportedCrypto)3345 TEST(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.
TEST(MediaSessionTest,GingleInitiateWithRequiredUnsupportedCrypto)3356 TEST(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.
TEST(MediaSessionTest,GingleInitiateWithRequiredUnsupportedCryptoWhenSecure)3363 TEST(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.
TEST(MediaSessionTest,GingleInitiateWithRequiredUnsupportedCryptoWhenSecureRequired)3371 TEST(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 
TEST(MediaSessionTest,GingleGoodOutgoingInitiateWithCrypto)3379 TEST(MediaSessionTest, GingleGoodOutgoingInitiateWithCrypto) {
3380   talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3381   test->ExpectCrypto(cricket::SEC_ENABLED);
3382   test->TestGoodOutgoingInitiate(AudioCallOptions());
3383 }
3384 
TEST(MediaSessionTest,GingleGoodOutgoingInitiateWithCryptoRequired)3385 TEST(MediaSessionTest, GingleGoodOutgoingInitiateWithCryptoRequired) {
3386   talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest());
3387   test->ExpectCrypto(cricket::SEC_REQUIRED);
3388   test->TestGoodOutgoingInitiate(AudioCallOptions());
3389 }
3390 
TEST(MediaSessionTest,GingleIncomingAcceptWithSsrcs)3391 TEST(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 
TEST(MediaSessionTest,GingleGoodOutgoingInitiateWithRtpData)3398 TEST(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