Home | History | Annotate | Download | only in media
      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 (at) domain.com/resource'         " \
    160      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    161      "  <session xmlns='http://www.google.com/session' type='initiate'" \
    162      "    id='abcdef' initiator='me (at) 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 (at) domain.com/resource'           " \
    206      "    to='user (at) domain.com/resource' type='set' id='123'>            " \
    207      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
    208      "          sid='abcdef' initiator='me (at) 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 (at) domain.com/resource'         " \
    277      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    278      "  <session xmlns='http://www.google.com/session' type='initiate'" \
    279      "    id='abcdef' initiator='me (at) 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 (at) domain.com/resource'           " \
    323      "    to='user (at) domain.com/resource' type='set' id='123'>            " \
    324      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
    325      "          sid='abcdef' initiator='me (at) 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 (at) domain.com/resource'           " \
    392      "    to='user (at) domain.com/resource' type='set' id='123'>            " \
    393      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
    394      "         sid='abcdef' initiator='me (at) 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 (at) domain.com/resource'         " \
    428      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    429      "  <session xmlns='http://www.google.com/session' type='initiate'" \
    430      "    id='abcdef' initiator='me (at) 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 (at) domain.com/resource'           " \
    443      "    to='user (at) domain.com/resource' type='set' id='123'>            " \
    444      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
    445      "          sid='abcdef' initiator='me (at) 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 (at) domain.com/resource'           " \
    467      "    to='user (at) domain.com/resource' type='set' id='123'>            " \
    468      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
    469      "          sid='abcdef' initiator='me (at) 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 (at) domain.com/resource'           " \
    498      "    to='user (at) domain.com/resource' type='set' id='123'>            " \
    499      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
    500      "          sid='abcdef' initiator='me (at) 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 (at) domain.com/resource'           " \
    528      "    to='user (at) domain.com/resource' type='set' id='123'>            " \
    529      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
    530      "         sid='abcdef' initiator='me (at) 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 (at) domain.com/resource'           " \
    553      "    to='user (at) domain.com/resource' type='set' id='123'>            " \
    554      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
    555      "         sid='abcdef' initiator='me (at) 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 (at) domain.com/resource'         " \
    580      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    581      "  <session xmlns='http://www.google.com/session' type='initiate'" \
    582      "    id='abcdef' initiator='me (at) 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 (at) domain.com/resource'         " \
    608      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    609      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'   " \
    610      "          sid='abcdef' initiator='me (at) 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 (at) domain.com/resource'         " \
    639      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    640      "  <session xmlns='http://www.google.com/session' type='initiate'" \
    641      "    id='abcdef' initiator='me (at) 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 (at) domain.com/resource'         " \
    656      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    657      "  <session xmlns='http://www.google.com/session' type='initiate'" \
    658      "    id='abcdef' initiator='me (at) 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 (at) domain.com/resource'         " \
    668      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    669      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'   " \
    670      "          sid='abcdef' initiator='me (at) 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 (at) domain.com/resource'         " \
    685      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    686      "  <session xmlns='http://www.google.com/session' type='initiate'" \
    687      "    id='abcdef' initiator='me (at) 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 (at) domain.com/resource'         " \
    695      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    696      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'   " \
    697      "          sid='abcdef' initiator='me (at) 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 (at) domain.com/resource'         " \
    710      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    711      "  <session xmlns='http://www.google.com/session' type='initiate'" \
    712      "    id='abcdef' initiator='me (at) 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 (at) domain.com/resource'           " \
    726      "    to='user (at) domain.com/resource' type='set' id='123'>            " \
    727      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
    728      "          sid='abcdef' initiator='me (at) 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 (at) domain.com/resource'         " \
    747      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    748      "  <session xmlns='http://www.google.com/session' type='initiate'" \
    749      "    id='abcdef' initiator='me (at) 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 (at) domain.com/resource'           " \
    761      "    to='user (at) 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 (at) domain.com/resource'         " \
    779      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    780      "  <session xmlns='http://www.google.com/session' type='initiate'" \
    781      "    id='abcdef' initiator='me (at) 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 (at) domain.com/resource'           " \
    791      "    to='user (at) domain.com/resource' type='set' id='123'>            " \
    792      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'     " \
    793      "          sid='abcdef' initiator='me (at) 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 (at) domain.com/resource'         " \
    807      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    808      "  <session xmlns='http://www.google.com/session' type='initiate'" \
    809      "    id='abcdef' initiator='me (at) 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 (at) domain.com/resource'         " \
    823      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    824      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'   " \
    825      "          sid='abcdef' initiator='me (at) 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 (at) domain.com/resource'         " \
    840      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    841      "  <session xmlns='http://www.google.com/session' type='initiate'" \
    842      "    id='abcdef' initiator='me (at) 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 (at) domain.com/resource'         " \
    852      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    853      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'>  " \
    854      "          sid='abcdef' initiator='me (at) 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 (at) domain.com/resource'         " \
    867      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    868      "  <session xmlns='http://www.google.com/session' type='initiate'" \
    869      "    id='abcdef' initiator='me (at) 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 (at) domain.com/resource'         " \
    879      "    to='user (at) domain.com/resource' type='set' id='123'>          " \
    880      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'>  " \
    881      "          sid='abcdef' initiator='me (at) 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 const uint32 kDataSid = 0;
    895 // Note that this message does not specify a session ID. It must be populated
    896 // before use.
    897 const std::string kGingleAcceptWithSsrcs(
    898      "<iq xmlns='jabber:client' from='me (at) mydomain.com'                " \
    899      "    to='user (at) domain.com/resource' type='set' id='150'>          " \
    900      "  <session xmlns='http://www.google.com/session' type='accept'  " \
    901      "    initiator='me (at) domain.com/resource'>                         " \
    902      "    <description xmlns='http://www.google.com/session/video'>   " \
    903      "      <payload-type xmlns='http://www.google.com/session/phone' " \
    904      "        id='103' name='ISAC' clockrate='16000' />               " \
    905      "      <payload-type xmlns='http://www.google.com/session/phone' " \
    906      "        id='104' name='ISAC' clockrate='32000' />               " \
    907      "      <src-id xmlns='http://www.google.com/session/phone'>      " \
    908      "        4294967295</src-id>                                       " \
    909      "      <src-id>87654321</src-id>                                 " \
    910      "    </description>                                              " \
    911      "  </session>                                                    " \
    912      "</iq>                                                           ");
    913 
    914 const std::string kJingleAcceptWithSsrcs(
    915      "<iq xmlns='jabber:client' from='me (at) mydomain.com'                " \
    916      "    to='user (at) domain.com/resource' type='set' id='150'>          " \
    917      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-accept'     " \
    918      "          initiator='me (at) domain.com/resource'>                   " \
    919      "    <content name='audio'>                                      " \
    920      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1'           " \
    921      "          media='audio' ssrc='4294967295'>                      " \
    922      "        <payload-type id='103' name='ISAC' clockrate='16000'/>  " \
    923      "        <payload-type id='104' name='ISAC' clockrate='32000'/>  " \
    924      "      </description>                                            " \
    925      "     <transport xmlns='http://www.google.com/transport/p2p'/>   " \
    926      "    </content>                                                  " \
    927      "    <content name='video'>                                      " \
    928      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1'           " \
    929      "          media='video' ssrc='87654321'>                        " \
    930      "      </description>                                            " \
    931      "     <transport xmlns='http://www.google.com/transport/p2p'/>   " \
    932      "    </content>                                                  " \
    933      "  </jingle>                                                     " \
    934      "</iq>                                                           ");
    935 
    936 const std::string kJingleAcceptWithRtpDataSsrcs(
    937      "<iq xmlns='jabber:client' from='me (at) mydomain.com'                " \
    938      "    to='user (at) domain.com/resource' type='set' id='150'>          " \
    939      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-accept'     " \
    940      "          initiator='me (at) domain.com/resource'>                   " \
    941      "    <content name='audio'>                                      " \
    942      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1'           " \
    943      "          media='audio' ssrc='4294967295'>                      " \
    944      "        <payload-type id='103' name='ISAC' clockrate='16000'/>  " \
    945      "        <payload-type id='104' name='ISAC' clockrate='32000'/>  " \
    946      "      </description>                                            " \
    947      "     <transport xmlns='http://www.google.com/transport/p2p'/>   " \
    948      "    </content>                                                  " \
    949      "    <content name='video'>                                      " \
    950      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1'           " \
    951      "          media='video' ssrc='87654321'>                        " \
    952      "      </description>                                            " \
    953      "     <transport xmlns='http://www.google.com/transport/p2p'/>   " \
    954      "    </content>                                                  " \
    955      "    <content name='data'>                                       " \
    956      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1'           " \
    957      "          media='data' ssrc='1010101'>                          " \
    958      "      </description>                                            " \
    959      "     <transport xmlns='http://www.google.com/transport/p2p'/>   " \
    960      "    </content>                                                  " \
    961      "  </jingle>                                                     " \
    962      "</iq>                                                           ");
    963 
    964 const std::string kJingleAcceptWithSctpData(
    965      "<iq xmlns='jabber:client' from='me (at) mydomain.com'                " \
    966      "    to='user (at) domain.com/resource' type='set' id='150'>          " \
    967      "  <jingle xmlns='urn:xmpp:jingle:1' action='session-accept'     " \
    968      "          initiator='me (at) domain.com/resource'>                   " \
    969      "    <content name='audio'>                                      " \
    970      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1'           " \
    971      "          media='audio' ssrc='4294967295'>                      " \
    972      "        <payload-type id='103' name='ISAC' clockrate='16000'/>  " \
    973      "        <payload-type id='104' name='ISAC' clockrate='32000'/>  " \
    974      "      </description>                                            " \
    975      "     <transport xmlns='http://www.google.com/transport/p2p'/>   " \
    976      "    </content>                                                  " \
    977      "    <content name='video'>                                      " \
    978      "      <description xmlns='urn:xmpp:jingle:apps:rtp:1'           " \
    979      "          media='video' ssrc='87654321'>                        " \
    980      "      </description>                                            " \
    981      "     <transport xmlns='http://www.google.com/transport/p2p'/>   " \
    982      "    </content>                                                  " \
    983      "    <content name='data'>                                       " \
    984      "      <description xmlns='google:jingle:sctp'>                  " \
    985      "        <stream sid='1'/>                                       " \
    986      "      </description>                                            " \
    987      "     <transport xmlns='http://www.google.com/transport/p2p'/>   " \
    988      "    </content>                                                  " \
    989      "  </jingle>                                                     " \
    990      "</iq>                                                           ");
    991 
    992 std::string JingleView(const std::string& ssrc,
    993                        const std::string& width,
    994                        const std::string& height,
    995                        const std::string& framerate) {
    996   // We have some slightly weird whitespace formatting to make the
    997   // actual XML generated match the expected XML here.
    998   return \
    999       "<cli:iq"
   1000       "  to='me (at) mydomain.com'"
   1001       "  type='set'"
   1002       "  xmlns:cli='jabber:client'>"
   1003         "<jingle"
   1004       "    xmlns='urn:xmpp:jingle:1'"
   1005       "    action='session-info'"
   1006       "    sid=''>"
   1007           "<view xmlns='google:jingle'"
   1008       "      name='video'"
   1009       "      type='static'"
   1010       "      ssrc='" + ssrc + "'>"
   1011             "<params"
   1012       "        width='" + width + "'"
   1013       "        height='" + height + "'"
   1014       "        framerate='" + framerate + "'"
   1015       "        preference='0'/>"
   1016           "</view>"
   1017         "</jingle>"
   1018       "</cli:iq>";
   1019 }
   1020 
   1021 std::string JingleStreamAdd(const std::string& content_name,
   1022                             const std::string& nick,
   1023                             const std::string& name,
   1024                             const std::string& ssrc) {
   1025   return \
   1026       "<iq"
   1027       "  xmlns='jabber:client'"
   1028       "  from='me (at) mydomain.com'"
   1029       "  to='user (at) domain.com/resource'"
   1030       "  type='set'"
   1031       "  id='150'>"
   1032       "  <jingle"
   1033       "    xmlns='urn:xmpp:jingle:1'"
   1034       "    action='description-info'>"
   1035       "    <content"
   1036       "      xmlns='urn:xmpp:jingle:1'"
   1037       "      name='" + content_name + "'>"
   1038       "      <description"
   1039       "        xmlns='urn:xmpp:jingle:apps:rtp:1'"
   1040       "        media='" + content_name + "'>"
   1041       "        <streams"
   1042       "          xmlns='google:jingle'>"
   1043       "          <stream"
   1044       "            nick='" + nick + "'"
   1045       "            name='" + name + "'>"
   1046       "            <ssrc>"  + ssrc + "</ssrc>"
   1047       "          </stream>"
   1048       "        </streams>"
   1049       "      </description>"
   1050       "    </content>"
   1051       "  </jingle>"
   1052       "</iq>";
   1053 }
   1054 
   1055 std::string JingleOutboundStreamRemove(const std::string& sid,
   1056                                        const std::string& content_name,
   1057                                        const std::string& name) {
   1058   return \
   1059       "<cli:iq"
   1060       " to='me (at) mydomain.com'"
   1061       " type='set'"
   1062       " xmlns:cli='jabber:client'>"
   1063       "<jingle"
   1064       " xmlns='urn:xmpp:jingle:1'"
   1065       " action='description-info'"
   1066       " sid='" + sid + "'>"
   1067       "<content"
   1068       " name='" + content_name + "'"
   1069       " creator='initiator'>"
   1070       "<description"
   1071       " xmlns='urn:xmpp:jingle:apps:rtp:1'"
   1072       " media='" + content_name + "'>"
   1073       "<streams"
   1074       " xmlns='google:jingle'>"
   1075       "<stream"
   1076       " name='" + name + "'>"
   1077       "</stream>"
   1078       "</streams>"
   1079       "</description>"
   1080       "</content>"
   1081       "</jingle>"
   1082       "</cli:iq>";
   1083 }
   1084 
   1085 std::string JingleOutboundStreamAdd(const std::string& sid,
   1086                                     const std::string& content_name,
   1087                                     const std::string& name,
   1088                                     const std::string& ssrc) {
   1089   return \
   1090       "<cli:iq"
   1091       " to='me (at) mydomain.com'"
   1092       " type='set'"
   1093       " xmlns:cli='jabber:client'>"
   1094       "<jingle"
   1095       " xmlns='urn:xmpp:jingle:1'"
   1096       " action='description-info'"
   1097       " sid='" + sid + "'>"
   1098       "<content"
   1099       " name='" + content_name + "'"
   1100       " creator='initiator'>"
   1101       "<description"
   1102       " xmlns='urn:xmpp:jingle:apps:rtp:1'"
   1103       " media='" + content_name + "'>"
   1104       "<streams"
   1105       " xmlns='google:jingle'>"
   1106       "<stream"
   1107       " name='" + name + "'>"
   1108       "<ssrc>" + ssrc + "</ssrc>"
   1109       "</stream>"
   1110       "</streams>"
   1111       "</description>"
   1112       "</content>"
   1113       "</jingle>"
   1114       "</cli:iq>";
   1115 }
   1116 
   1117 std::string JingleStreamAddWithoutSsrc(const std::string& content_name,
   1118                                        const std::string& nick,
   1119                                        const std::string& name) {
   1120   return \
   1121       "<iq"
   1122       "  xmlns='jabber:client'"
   1123       "  from='me (at) mydomain.com'"
   1124       "  to='user (at) domain.com/resource'"
   1125       "  type='set'"
   1126       "  id='150'>"
   1127       "  <jingle"
   1128       "    xmlns='urn:xmpp:jingle:1'"
   1129       "    action='description-info'>"
   1130       "    <content"
   1131       "      xmlns='urn:xmpp:jingle:1'"
   1132       "      name='" + content_name + "'>"
   1133       "      <description"
   1134       "        xmlns='urn:xmpp:jingle:apps:rtp:1'"
   1135       "        media='" + content_name + "'>"
   1136       "        <streams"
   1137       "          xmlns='google:jingle'>"
   1138       "          <stream"
   1139       "            nick='" + nick + "'"
   1140       "            name='" + name + "'>"
   1141        "          </stream>"
   1142       "        </streams>"
   1143       "      </description>"
   1144       "    </content>"
   1145       "  </jingle>"
   1146       "</iq>";
   1147 }
   1148 
   1149 std::string JingleStreamRemove(const std::string& content_name,
   1150                                const std::string& nick,
   1151                                const std::string& name) {
   1152   return \
   1153       "<iq"
   1154       "  xmlns='jabber:client'"
   1155       "  from='me (at) mydomain.com'"
   1156       "  to='user (at) domain.com/resource'"
   1157       "  type='set'"
   1158       "  id='150'>"
   1159       "  <jingle"
   1160       "    xmlns='urn:xmpp:jingle:1'"
   1161       "    action='description-info'>"
   1162       "    <content"
   1163       "      xmlns='urn:xmpp:jingle:1'"
   1164       "      name='" + content_name + "'>"
   1165       "      <description"
   1166       "        xmlns='urn:xmpp:jingle:apps:rtp:1'"
   1167       "        media='" + content_name + "'>"
   1168       "        <streams"
   1169       "          xmlns='google:jingle'>"
   1170       "          <stream"
   1171       "            nick='" + nick + "'"
   1172       "            name='" + name + "'/>"
   1173       "        </streams>"
   1174       "      </description>"
   1175       "    </content>"
   1176       "  </jingle>"
   1177       "</iq>";
   1178 }
   1179 
   1180 // Convenience function to get CallOptions that have audio enabled,
   1181 // but not video or data.
   1182 static cricket::CallOptions AudioCallOptions() {
   1183   cricket::CallOptions options;
   1184   options.has_audio = true;
   1185   options.has_video = false;
   1186   options.data_channel_type = cricket::DCT_NONE;
   1187   return options;
   1188 }
   1189 
   1190 // Convenience function to get CallOptions that have audio and video
   1191 // enabled, but not data.
   1192 static cricket::CallOptions VideoCallOptions() {
   1193   cricket::CallOptions options;
   1194   options.has_audio = true;
   1195   options.has_video = true;
   1196   options.data_channel_type = cricket::DCT_NONE;
   1197   return options;
   1198 }
   1199 
   1200 static buzz::XmlElement* CopyElement(const buzz::XmlElement* elem) {
   1201   return new buzz::XmlElement(*elem);
   1202 }
   1203 
   1204 static std::string AddEncryption(std::string stanza, std::string encryption) {
   1205   std::string::size_type pos = stanza.find("</description>");
   1206   while (pos != std::string::npos) {
   1207       stanza = stanza.insert(pos, encryption);
   1208       pos = stanza.find("</description>", pos + encryption.length() + 1);
   1209   }
   1210   return stanza;
   1211 }
   1212 
   1213 static int IntFromJingleCodecParameter(const buzz::XmlElement* parameter,
   1214                                        const std::string& expected_name) {
   1215   if (parameter) {
   1216     const std::string& actual_name =
   1217         parameter->Attr(cricket::QN_PAYLOADTYPE_PARAMETER_NAME);
   1218 
   1219     EXPECT_EQ(expected_name, actual_name)
   1220         << "wrong parameter name.  Expected '"
   1221         << expected_name << "'. Actually '"
   1222         << actual_name << "'.";
   1223 
   1224     return atoi(parameter->Attr(
   1225         cricket::QN_PAYLOADTYPE_PARAMETER_VALUE).c_str());
   1226   }
   1227   return 0;
   1228 }
   1229 
   1230 template <class CodecClass, class DescriptionClass>
   1231 static void VerifyCodecFbParams(const FeedbackParams& expected,
   1232                                 const DescriptionClass* desc) {
   1233   if (!expected.params().empty()) {
   1234     ASSERT_TRUE(desc != NULL);
   1235     const std::vector<CodecClass> codecs = desc->codecs();
   1236     for (size_t i = 0; i < codecs.size(); ++i) {
   1237       EXPECT_EQ(expected, codecs[i].feedback_params);
   1238     }
   1239   }
   1240 }
   1241 
   1242 // Parses and extracts payload and codec info from test XML.  Since
   1243 // that XML will be in various contents (Gingle and Jingle), we need an
   1244 // abstract parser with one concrete implementation per XML content.
   1245 class MediaSessionTestParser {
   1246  public:
   1247   virtual buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) = 0;
   1248   virtual buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) = 0;
   1249   virtual buzz::XmlElement* NextContent(buzz::XmlElement* content) = 0;
   1250   virtual buzz::XmlElement* PayloadTypeFromContent(
   1251       buzz::XmlElement* content) = 0;
   1252   virtual buzz::XmlElement* NextFromPayloadType(
   1253       buzz::XmlElement* payload_type) = 0;
   1254   virtual cricket::AudioCodec AudioCodecFromPayloadType(
   1255       const buzz::XmlElement* payload_type) = 0;
   1256   virtual cricket::VideoCodec VideoCodecFromPayloadType(
   1257       const buzz::XmlElement* payload_type) = 0;
   1258   virtual cricket::DataCodec DataCodecFromPayloadType(
   1259       const buzz::XmlElement* payload_type) = 0;
   1260   virtual buzz::XmlElement* EncryptionFromContent(
   1261       buzz::XmlElement* content) = 0;
   1262   virtual buzz::XmlElement* NextFromEncryption(
   1263       buzz::XmlElement* encryption) = 0;
   1264   virtual const buzz::XmlElement* BandwidthFromContent(
   1265       buzz::XmlElement* content) = 0;
   1266   virtual const buzz::XmlElement* RtcpMuxFromContent(
   1267       buzz::XmlElement* content) = 0;
   1268   virtual bool ActionIsTerminate(const buzz::XmlElement* action) = 0;
   1269   virtual ~MediaSessionTestParser() {}
   1270 };
   1271 
   1272 class JingleSessionTestParser : public MediaSessionTestParser {
   1273  public:
   1274   JingleSessionTestParser() {}
   1275 
   1276   ~JingleSessionTestParser() {
   1277   }
   1278 
   1279   buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
   1280     return stanza->FirstNamed(cricket::QN_JINGLE);
   1281   }
   1282 
   1283   buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) {
   1284     // We need to be able to use multiple contents, but the action
   1285     // gets deleted before we can call NextContent, so we need to
   1286     // stash away a copy.
   1287     action_.reset(CopyElement(action));
   1288     return action_->FirstNamed(cricket::QN_JINGLE_CONTENT);
   1289   }
   1290 
   1291   buzz::XmlElement* NextContent(buzz::XmlElement* content) {
   1292     // For some reason, content->NextNamed(cricket::QN_JINGLE_CONTENT)
   1293     // doesn't work.
   1294     return action_->FirstNamed(cricket::QN_JINGLE_CONTENT)
   1295         ->NextNamed(cricket::QN_JINGLE_CONTENT);
   1296   }
   1297 
   1298   buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* content) {
   1299     buzz::XmlElement* content_desc =
   1300         content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
   1301     if (!content_desc)
   1302       return NULL;
   1303 
   1304     return content_desc->FirstNamed(cricket::QN_JINGLE_RTP_PAYLOADTYPE);
   1305   }
   1306 
   1307   buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
   1308     return payload_type->NextNamed(cricket::QN_JINGLE_RTP_PAYLOADTYPE);
   1309   }
   1310 
   1311   void ParsePayloadTypeFeedbackParameters(const buzz::XmlElement* element,
   1312                                           FeedbackParams* params) {
   1313     const buzz::XmlElement* param =
   1314         element->FirstNamed(cricket::QN_JINGLE_RTCP_FB);
   1315     for (; param != NULL;
   1316          param = param->NextNamed(cricket::QN_JINGLE_RTCP_FB)) {
   1317       std::string type  = param->Attr(cricket::QN_TYPE);
   1318       std::string subtype = param->Attr(cricket::QN_SUBTYPE);
   1319       if (!type.empty()) {
   1320         params->Add(FeedbackParam(type, subtype));
   1321       }
   1322     }
   1323   }
   1324 
   1325   cricket::AudioCodec AudioCodecFromPayloadType(
   1326       const buzz::XmlElement* payload_type) {
   1327     int id = 0;
   1328     if (payload_type->HasAttr(cricket::QN_ID))
   1329       id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
   1330 
   1331     std::string name;
   1332     if (payload_type->HasAttr(cricket::QN_NAME))
   1333       name = payload_type->Attr(cricket::QN_NAME);
   1334 
   1335     int clockrate = 0;
   1336     if (payload_type->HasAttr(cricket::QN_CLOCKRATE))
   1337       clockrate = atoi(payload_type->Attr(cricket::QN_CLOCKRATE).c_str());
   1338 
   1339     int bitrate = IntFromJingleCodecParameter(
   1340         payload_type->FirstNamed(cricket::QN_PARAMETER), "bitrate");
   1341 
   1342     int channels = 1;
   1343     if (payload_type->HasAttr(cricket::QN_CHANNELS))
   1344       channels = atoi(payload_type->Attr(
   1345           cricket::QN_CHANNELS).c_str());
   1346 
   1347     AudioCodec codec = AudioCodec(id, name, clockrate, bitrate, channels, 0);
   1348     ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params);
   1349     return codec;
   1350   }
   1351 
   1352   cricket::VideoCodec VideoCodecFromPayloadType(
   1353       const buzz::XmlElement* payload_type) {
   1354     int id = 0;
   1355     if (payload_type->HasAttr(cricket::QN_ID))
   1356       id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
   1357 
   1358     std::string name;
   1359     if (payload_type->HasAttr(cricket::QN_NAME))
   1360       name = payload_type->Attr(cricket::QN_NAME);
   1361 
   1362     int width = 0;
   1363     int height = 0;
   1364     int framerate = 0;
   1365     const buzz::XmlElement* param =
   1366         payload_type->FirstNamed(cricket::QN_PARAMETER);
   1367     if (param) {
   1368       width = IntFromJingleCodecParameter(param, "width");
   1369       param = param->NextNamed(cricket::QN_PARAMETER);
   1370       if (param) {
   1371         height = IntFromJingleCodecParameter(param, "height");
   1372         param = param->NextNamed(cricket::QN_PARAMETER);
   1373         if (param) {
   1374           framerate = IntFromJingleCodecParameter(param, "framerate");
   1375         }
   1376       }
   1377     }
   1378     VideoCodec codec = VideoCodec(id, name, width, height, framerate, 0);
   1379     ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params);
   1380     return codec;
   1381   }
   1382 
   1383   cricket::DataCodec DataCodecFromPayloadType(
   1384       const buzz::XmlElement* payload_type) {
   1385     int id = 0;
   1386     if (payload_type->HasAttr(cricket::QN_ID))
   1387       id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
   1388 
   1389     std::string name;
   1390     if (payload_type->HasAttr(cricket::QN_NAME))
   1391       name = payload_type->Attr(cricket::QN_NAME);
   1392 
   1393     DataCodec codec = DataCodec(id, name, 0);
   1394     ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params);
   1395     return codec;
   1396   }
   1397 
   1398   bool ActionIsTerminate(const buzz::XmlElement* action) {
   1399     return (action->HasAttr(cricket::QN_ACTION) &&
   1400             action->Attr(cricket::QN_ACTION) == "session-terminate");
   1401   }
   1402 
   1403   buzz::XmlElement* EncryptionFromContent(buzz::XmlElement* content) {
   1404     buzz::XmlElement* content_desc =
   1405         content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
   1406     if (!content_desc)
   1407       return NULL;
   1408 
   1409     return content_desc->FirstNamed(cricket::QN_ENCRYPTION);
   1410   }
   1411 
   1412   buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
   1413     return encryption->NextNamed(cricket::QN_ENCRYPTION);
   1414   }
   1415 
   1416   const buzz::XmlElement* BandwidthFromContent(buzz::XmlElement* content) {
   1417     buzz::XmlElement* content_desc =
   1418         content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
   1419     if (!content_desc)
   1420       return NULL;
   1421 
   1422     return content_desc->FirstNamed(cricket::QN_JINGLE_RTP_BANDWIDTH);
   1423   }
   1424 
   1425   const buzz::XmlElement* RtcpMuxFromContent(buzz::XmlElement* content) {
   1426     return content->FirstNamed(cricket::QN_JINGLE_RTCP_MUX);
   1427   }
   1428 
   1429  private:
   1430   talk_base::scoped_ptr<buzz::XmlElement> action_;
   1431 };
   1432 
   1433 class GingleSessionTestParser : public MediaSessionTestParser {
   1434  public:
   1435   GingleSessionTestParser() : found_content_count_(0) {}
   1436 
   1437   buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
   1438     return stanza->FirstNamed(cricket::QN_GINGLE_SESSION);
   1439   }
   1440 
   1441   buzz::XmlElement* ContentFromAction(buzz::XmlElement* session) {
   1442     buzz::XmlElement* content =
   1443         session->FirstNamed(cricket::QN_GINGLE_AUDIO_CONTENT);
   1444     if (content == NULL)
   1445       content = session->FirstNamed(cricket::QN_GINGLE_VIDEO_CONTENT);
   1446     return content;
   1447   }
   1448 
   1449   // Assumes contents are in order of audio, and then video.
   1450   buzz::XmlElement* NextContent(buzz::XmlElement* content) {
   1451     found_content_count_++;
   1452     return content;
   1453   }
   1454 
   1455   buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* content) {
   1456     if (found_content_count_ > 0) {
   1457       return content->FirstNamed(cricket::QN_GINGLE_VIDEO_PAYLOADTYPE);
   1458     } else {
   1459       return content->FirstNamed(cricket::QN_GINGLE_AUDIO_PAYLOADTYPE);
   1460     }
   1461   }
   1462 
   1463   buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
   1464     if (found_content_count_ > 0) {
   1465       return payload_type->NextNamed(cricket::QN_GINGLE_VIDEO_PAYLOADTYPE);
   1466     } else {
   1467       return payload_type->NextNamed(cricket::QN_GINGLE_AUDIO_PAYLOADTYPE);
   1468     }
   1469   }
   1470 
   1471   cricket::AudioCodec AudioCodecFromPayloadType(
   1472       const buzz::XmlElement* payload_type) {
   1473     int id = 0;
   1474     if (payload_type->HasAttr(cricket::QN_ID))
   1475       id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
   1476 
   1477     std::string name;
   1478     if (payload_type->HasAttr(cricket::QN_NAME))
   1479       name = payload_type->Attr(cricket::QN_NAME);
   1480 
   1481     int clockrate = 0;
   1482     if (payload_type->HasAttr(cricket::QN_CLOCKRATE))
   1483       clockrate = atoi(payload_type->Attr(cricket::QN_CLOCKRATE).c_str());
   1484 
   1485     int bitrate = 0;
   1486     if (payload_type->HasAttr(cricket::QN_BITRATE))
   1487       bitrate = atoi(payload_type->Attr(cricket::QN_BITRATE).c_str());
   1488 
   1489     int channels = 1;
   1490     if (payload_type->HasAttr(cricket::QN_CHANNELS))
   1491       channels = atoi(payload_type->Attr(cricket::QN_CHANNELS).c_str());
   1492 
   1493     return cricket::AudioCodec(id, name, clockrate, bitrate, channels, 0);
   1494   }
   1495 
   1496   cricket::VideoCodec VideoCodecFromPayloadType(
   1497       const buzz::XmlElement* payload_type) {
   1498     int id = 0;
   1499     if (payload_type->HasAttr(cricket::QN_ID))
   1500       id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
   1501 
   1502     std::string name;
   1503     if (payload_type->HasAttr(cricket::QN_NAME))
   1504       name = payload_type->Attr(cricket::QN_NAME);
   1505 
   1506     int width = 0;
   1507     if (payload_type->HasAttr(cricket::QN_WIDTH))
   1508       width = atoi(payload_type->Attr(cricket::QN_WIDTH).c_str());
   1509 
   1510     int height = 0;
   1511     if (payload_type->HasAttr(cricket::QN_HEIGHT))
   1512       height = atoi(payload_type->Attr(cricket::QN_HEIGHT).c_str());
   1513 
   1514     int framerate = 1;
   1515     if (payload_type->HasAttr(cricket::QN_FRAMERATE))
   1516       framerate = atoi(payload_type->Attr(cricket::QN_FRAMERATE).c_str());
   1517 
   1518     return cricket::VideoCodec(id, name, width, height, framerate, 0);
   1519   }
   1520 
   1521   cricket::DataCodec DataCodecFromPayloadType(
   1522       const buzz::XmlElement* payload_type) {
   1523     // Gingle can't do data codecs.
   1524     return cricket::DataCodec(0, "", 0);
   1525   }
   1526 
   1527   buzz::XmlElement* EncryptionFromContent(
   1528       buzz::XmlElement* content) {
   1529     return content->FirstNamed(cricket::QN_ENCRYPTION);
   1530   }
   1531 
   1532   buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
   1533     return encryption->NextNamed(cricket::QN_ENCRYPTION);
   1534   }
   1535 
   1536   const buzz::XmlElement* BandwidthFromContent(buzz::XmlElement* content) {
   1537     return content->FirstNamed(cricket::QN_GINGLE_VIDEO_BANDWIDTH);
   1538   }
   1539 
   1540   const buzz::XmlElement* RtcpMuxFromContent(buzz::XmlElement* content) {
   1541     return NULL;
   1542   }
   1543 
   1544   bool ActionIsTerminate(const buzz::XmlElement* session) {
   1545     return (session->HasAttr(buzz::QN_TYPE) &&
   1546             session->Attr(buzz::QN_TYPE) == "terminate");
   1547   }
   1548 
   1549   int found_content_count_;
   1550 };
   1551 
   1552 class MediaSessionClientTest : public sigslot::has_slots<> {
   1553  public:
   1554   explicit MediaSessionClientTest(MediaSessionTestParser* parser,
   1555                                   cricket::SignalingProtocol initial_protocol) {
   1556     nm_ = new talk_base::BasicNetworkManager();
   1557     pa_ = new cricket::BasicPortAllocator(nm_);
   1558     sm_ = new cricket::SessionManager(pa_, NULL);
   1559     fme_ = new cricket::FakeMediaEngine();
   1560     fdme_ = new cricket::FakeDataEngine();
   1561 
   1562     FeedbackParams params_nack_fir;
   1563     params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamCcm,
   1564                                       cricket::kRtcpFbCcmParamFir));
   1565     params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamNack));
   1566     FeedbackParams params_nack;
   1567     params_nack.Add(FeedbackParam(cricket::kRtcpFbParamNack));
   1568 
   1569     std::vector<cricket::AudioCodec>
   1570         audio_codecs(kAudioCodecs, kAudioCodecs + ARRAY_SIZE(kAudioCodecs));
   1571     SetCodecFeedbackParams(&audio_codecs, params_nack);
   1572     fme_->SetAudioCodecs(audio_codecs);
   1573     std::vector<cricket::VideoCodec>
   1574         video_codecs(kVideoCodecs, kVideoCodecs + ARRAY_SIZE(kVideoCodecs));
   1575     SetCodecFeedbackParams(&video_codecs, params_nack_fir);
   1576     fme_->SetVideoCodecs(video_codecs);
   1577     std::vector<cricket::DataCodec>
   1578         data_codecs(kDataCodecs, kDataCodecs + ARRAY_SIZE(kDataCodecs));
   1579     SetCodecFeedbackParams(&data_codecs, params_nack);
   1580     fdme_->SetDataCodecs(data_codecs);
   1581 
   1582     client_ = new cricket::MediaSessionClient(
   1583         buzz::Jid("user (at) domain.com/resource"), sm_,
   1584         fme_, fdme_, new cricket::FakeDeviceManager());
   1585     client_->session_manager()->SignalOutgoingMessage.connect(
   1586         this, &MediaSessionClientTest::OnSendStanza);
   1587     client_->session_manager()->SignalSessionCreate.connect(
   1588         this, &MediaSessionClientTest::OnSessionCreate);
   1589     client_->SignalCallCreate.connect(
   1590         this, &MediaSessionClientTest::OnCallCreate);
   1591     client_->SignalCallDestroy.connect(
   1592         this, &MediaSessionClientTest::OnCallDestroy);
   1593 
   1594     call_ = NULL;
   1595     parser_ = parser;
   1596     initial_protocol_ = initial_protocol;
   1597     expect_incoming_crypto_ = false;
   1598     expect_outgoing_crypto_ = false;
   1599     expected_video_bandwidth_ = cricket::kAutoBandwidth;
   1600     expected_video_rtcp_mux_ = false;
   1601   }
   1602 
   1603   ~MediaSessionClientTest() {
   1604     delete client_;
   1605     delete sm_;
   1606     delete pa_;
   1607     delete nm_;
   1608     delete parser_;
   1609     ClearStanzas();
   1610   }
   1611 
   1612   buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
   1613     return parser_->ActionFromStanza(stanza);
   1614   }
   1615 
   1616   buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) {
   1617     return parser_->ContentFromAction(action);
   1618   }
   1619 
   1620   buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* payload) {
   1621     return parser_->PayloadTypeFromContent(payload);
   1622   }
   1623 
   1624   buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
   1625     return parser_->NextFromPayloadType(payload_type);
   1626   }
   1627 
   1628   buzz::XmlElement* EncryptionFromContent(buzz::XmlElement* content) {
   1629     return parser_->EncryptionFromContent(content);
   1630   }
   1631 
   1632   buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
   1633     return parser_->NextFromEncryption(encryption);
   1634   }
   1635 
   1636   cricket::AudioCodec AudioCodecFromPayloadType(
   1637       const buzz::XmlElement* payload_type) {
   1638     return parser_->AudioCodecFromPayloadType(payload_type);
   1639   }
   1640 
   1641   cricket::VideoCodec VideoCodecFromPayloadType(
   1642       const buzz::XmlElement* payload_type) {
   1643     return parser_->VideoCodecFromPayloadType(payload_type);
   1644   }
   1645 
   1646   cricket::DataCodec DataCodecFromPayloadType(
   1647       const buzz::XmlElement* payload_type) {
   1648     return parser_->DataCodecFromPayloadType(payload_type);
   1649   }
   1650 
   1651   const AudioContentDescription* GetFirstAudioContentDescription(
   1652       const cricket::SessionDescription* sdesc) {
   1653     const cricket::ContentInfo* content =
   1654         cricket::GetFirstAudioContent(sdesc);
   1655     if (content == NULL)
   1656       return NULL;
   1657     return static_cast<const AudioContentDescription*>(content->description);
   1658   }
   1659 
   1660   const cricket::VideoContentDescription* GetFirstVideoContentDescription(
   1661       const cricket::SessionDescription* sdesc) {
   1662     const cricket::ContentInfo* content =
   1663         cricket::GetFirstVideoContent(sdesc);
   1664     if (content == NULL)
   1665       return NULL;
   1666     return static_cast<const cricket::VideoContentDescription*>(
   1667         content->description);
   1668   }
   1669 
   1670   void CheckCryptoFromGoodIncomingInitiate(const cricket::Session* session) {
   1671     ASSERT_TRUE(session != NULL);
   1672     const AudioContentDescription* content =
   1673         GetFirstAudioContentDescription(session->remote_description());
   1674     ASSERT_TRUE(content != NULL);
   1675     ASSERT_EQ(2U, content->cryptos().size());
   1676     ASSERT_EQ(145, content->cryptos()[0].tag);
   1677     ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", content->cryptos()[0].cipher_suite);
   1678     ASSERT_EQ("inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9",
   1679               content->cryptos()[0].key_params);
   1680     ASSERT_EQ(51, content->cryptos()[1].tag);
   1681     ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", content->cryptos()[1].cipher_suite);
   1682     ASSERT_EQ("inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy",
   1683               content->cryptos()[1].key_params);
   1684   }
   1685 
   1686   void CheckCryptoForGoodOutgoingAccept(const cricket::Session* session) {
   1687     const AudioContentDescription* content =
   1688         GetFirstAudioContentDescription(session->local_description());
   1689     ASSERT_EQ(1U, content->cryptos().size());
   1690     ASSERT_EQ(145, content->cryptos()[0].tag);
   1691     ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", content->cryptos()[0].cipher_suite);
   1692     ASSERT_EQ(47U, content->cryptos()[0].key_params.size());
   1693   }
   1694 
   1695   void CheckBadCryptoFromIncomingInitiate(const cricket::Session* session) {
   1696     const AudioContentDescription* content =
   1697         GetFirstAudioContentDescription(session->remote_description());
   1698     ASSERT_EQ(1U, content->cryptos().size());
   1699     ASSERT_EQ(145, content->cryptos()[0].tag);
   1700     ASSERT_EQ("NOT_SUPPORTED", content->cryptos()[0].cipher_suite);
   1701     ASSERT_EQ("inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9",
   1702               content->cryptos()[0].key_params);
   1703   }
   1704 
   1705   void CheckNoCryptoForOutgoingAccept(const cricket::Session* session) {
   1706     const AudioContentDescription* content =
   1707         GetFirstAudioContentDescription(session->local_description());
   1708     ASSERT_TRUE(content->cryptos().empty());
   1709   }
   1710 
   1711   void CheckRtcpFb(const cricket::SessionDescription* sdesc) {
   1712     VerifyCodecFbParams<AudioCodec>(expected_audio_fb_params_,
   1713                                     GetFirstAudioContentDescription(sdesc));
   1714 
   1715     VerifyCodecFbParams<VideoCodec>(expected_video_fb_params_,
   1716                                     GetFirstVideoContentDescription(sdesc));
   1717 
   1718     VerifyCodecFbParams<DataCodec>(expected_data_fb_params_,
   1719                                    GetFirstDataContentDescription(sdesc));
   1720   }
   1721 
   1722   void CheckVideoBandwidth(int expected_bandwidth,
   1723                            const cricket::SessionDescription* sdesc) {
   1724     const cricket::VideoContentDescription* video =
   1725         GetFirstVideoContentDescription(sdesc);
   1726     if (video != NULL) {
   1727       ASSERT_EQ(expected_bandwidth, video->bandwidth());
   1728     }
   1729   }
   1730 
   1731   void CheckVideoRtcpMux(bool expected_video_rtcp_mux,
   1732                          const cricket::SessionDescription* sdesc) {
   1733     const cricket::VideoContentDescription* video =
   1734         GetFirstVideoContentDescription(sdesc);
   1735     if (video != NULL) {
   1736       ASSERT_EQ(expected_video_rtcp_mux, video->rtcp_mux());
   1737     }
   1738   }
   1739 
   1740   virtual void CheckRtpDataContent(buzz::XmlElement* content) {
   1741     if (initial_protocol_) {
   1742       // Gingle can not write out data content.
   1743       return;
   1744     }
   1745 
   1746     buzz::XmlElement* e = PayloadTypeFromContent(content);
   1747     ASSERT_TRUE(e != NULL);
   1748     cricket::DataCodec codec = DataCodecFromPayloadType(e);
   1749     EXPECT_EQ(127, codec.id);
   1750     EXPECT_EQ("google-data", codec.name);
   1751     EXPECT_EQ(expected_data_fb_params_, codec.feedback_params);
   1752 
   1753     CheckDataRtcpMux(true, call_->sessions()[0]->local_description());
   1754     CheckDataRtcpMux(true, call_->sessions()[0]->remote_description());
   1755     if (expect_outgoing_crypto_) {
   1756       content = parser_->NextContent(content);
   1757       buzz::XmlElement* encryption = EncryptionFromContent(content);
   1758       ASSERT_TRUE(encryption != NULL);
   1759       // TODO(pthatcher): Check encryption parameters?
   1760     }
   1761   }
   1762 
   1763   virtual void CheckSctpDataContent(buzz::XmlElement* content) {
   1764     if (initial_protocol_) {
   1765       // Gingle can not write out data content.
   1766       return;
   1767     }
   1768 
   1769     buzz::XmlElement* payload_type = PayloadTypeFromContent(content);
   1770     ASSERT_TRUE(payload_type == NULL);
   1771     buzz::XmlElement* encryption = EncryptionFromContent(content);
   1772     ASSERT_TRUE(encryption == NULL);
   1773     // TODO(pthatcher): Check for <streams>.
   1774   }
   1775 
   1776   void CheckDataRtcpMux(bool expected_data_rtcp_mux,
   1777                         const cricket::SessionDescription* sdesc) {
   1778     const cricket::DataContentDescription* data =
   1779         GetFirstDataContentDescription(sdesc);
   1780     if (data != NULL) {
   1781       ASSERT_EQ(expected_data_rtcp_mux, data->rtcp_mux());
   1782     }
   1783   }
   1784 
   1785   void CheckAudioSsrcForIncomingAccept(const cricket::Session* session) {
   1786     const AudioContentDescription* audio =
   1787         GetFirstAudioContentDescription(session->remote_description());
   1788     ASSERT_TRUE(audio != NULL);
   1789     ASSERT_EQ(kAudioSsrc, audio->first_ssrc());
   1790   }
   1791 
   1792   void CheckVideoSsrcForIncomingAccept(const cricket::Session* session) {
   1793     const cricket::VideoContentDescription* video =
   1794         GetFirstVideoContentDescription(session->remote_description());
   1795     ASSERT_TRUE(video != NULL);
   1796     ASSERT_EQ(kVideoSsrc, video->first_ssrc());
   1797   }
   1798 
   1799   void CheckDataSsrcForIncomingAccept(const cricket::Session* session) {
   1800     const cricket::DataContentDescription* data =
   1801         GetFirstDataContentDescription(session->remote_description());
   1802     ASSERT_TRUE(data != NULL);
   1803     ASSERT_EQ(kDataSsrc, data->first_ssrc());
   1804   }
   1805 
   1806   void TestGoodIncomingInitiate(const std::string& initiate_string,
   1807                                 const cricket::CallOptions& options,
   1808                                 buzz::XmlElement** element) {
   1809     *element = NULL;
   1810 
   1811     talk_base::scoped_ptr<buzz::XmlElement> el(
   1812         buzz::XmlElement::ForStr(initiate_string));
   1813     client_->session_manager()->OnIncomingMessage(el.get());
   1814     ASSERT_TRUE(call_ != NULL);
   1815     ASSERT_TRUE(call_->sessions()[0] != NULL);
   1816     ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE,
   1817               call_->sessions()[0]->state());
   1818     ASSERT_EQ(1U, stanzas_.size());
   1819     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
   1820     ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
   1821     ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
   1822     ClearStanzas();
   1823     CheckVideoBandwidth(expected_video_bandwidth_,
   1824                         call_->sessions()[0]->remote_description());
   1825     CheckVideoRtcpMux(expected_video_rtcp_mux_,
   1826                       call_->sessions()[0]->remote_description());
   1827     CheckRtcpFb(call_->sessions()[0]->remote_description());
   1828     if (expect_incoming_crypto_) {
   1829       CheckCryptoFromGoodIncomingInitiate(call_->sessions()[0]);
   1830     }
   1831 
   1832     // TODO(pthatcher): Add tests for sending <bandwidth> in accept.
   1833     call_->AcceptSession(call_->sessions()[0], options);
   1834     ASSERT_EQ(cricket::Session::STATE_SENTACCEPT,
   1835               call_->sessions()[0]->state());
   1836     ASSERT_EQ(1U, stanzas_.size());
   1837     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
   1838     ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
   1839     ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
   1840 
   1841     buzz::XmlElement* e = ActionFromStanza(stanzas_[0]);
   1842     ASSERT_TRUE(e != NULL);
   1843     ASSERT_TRUE(ContentFromAction(e) != NULL);
   1844     *element = CopyElement(ContentFromAction(e));
   1845     ASSERT_TRUE(*element != NULL);
   1846     ClearStanzas();
   1847     if (expect_outgoing_crypto_) {
   1848       CheckCryptoForGoodOutgoingAccept(call_->sessions()[0]);
   1849     }
   1850 
   1851     if (options.data_channel_type == cricket::DCT_RTP) {
   1852       CheckDataRtcpMux(true, call_->sessions()[0]->local_description());
   1853       CheckDataRtcpMux(true, call_->sessions()[0]->remote_description());
   1854       // TODO(pthatcher): Check rtcpmux and crypto?
   1855     }
   1856 
   1857     call_->Terminate();
   1858     ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE,
   1859               call_->sessions()[0]->state());
   1860     ASSERT_EQ(1U, stanzas_.size());
   1861     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
   1862     ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
   1863     ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
   1864     e = ActionFromStanza(stanzas_[0]);
   1865     ASSERT_TRUE(e != NULL);
   1866     ASSERT_TRUE(parser_->ActionIsTerminate(e));
   1867     ClearStanzas();
   1868   }
   1869 
   1870   void TestRejectOffer(const std::string &initiate_string,
   1871                        const cricket::CallOptions& options,
   1872                        buzz::XmlElement** element) {
   1873     *element = NULL;
   1874 
   1875     talk_base::scoped_ptr<buzz::XmlElement> el(
   1876         buzz::XmlElement::ForStr(initiate_string));
   1877     client_->session_manager()->OnIncomingMessage(el.get());
   1878     ASSERT_TRUE(call_ != NULL);
   1879     ASSERT_TRUE(call_->sessions()[0] != NULL);
   1880     ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE,
   1881               call_->sessions()[0]->state());
   1882     ASSERT_EQ(1U, stanzas_.size());
   1883     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
   1884     ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
   1885     ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
   1886     ClearStanzas();
   1887 
   1888     call_->AcceptSession(call_->sessions()[0], options);
   1889     ASSERT_EQ(cricket::Session::STATE_SENTACCEPT,
   1890               call_->sessions()[0]->state());
   1891     ASSERT_EQ(1U, stanzas_.size());
   1892     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
   1893     ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
   1894     ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
   1895 
   1896     buzz::XmlElement* e = ActionFromStanza(stanzas_[0]);
   1897     ASSERT_TRUE(e != NULL);
   1898     ASSERT_TRUE(ContentFromAction(e) != NULL);
   1899     *element = CopyElement(ContentFromAction(e));
   1900     ASSERT_TRUE(*element != NULL);
   1901     ClearStanzas();
   1902 
   1903     buzz::XmlElement* content = *element;
   1904     // The NextContent method actually returns the second content. So we
   1905     // can't handle the case when audio, video and data are all enabled. But
   1906     // since we are testing rejection, it won't be the case.
   1907     if (options.has_audio) {
   1908       ASSERT_TRUE(content != NULL);
   1909       ASSERT_EQ("test audio", content->Attr(buzz::QName("", "name")));
   1910       content = parser_->NextContent(content);
   1911     }
   1912 
   1913     if (options.has_video) {
   1914       ASSERT_TRUE(content != NULL);
   1915       ASSERT_EQ("test video", content->Attr(buzz::QName("", "name")));
   1916       content = parser_->NextContent(content);
   1917     }
   1918 
   1919     if (options.has_data()) {
   1920       ASSERT_TRUE(content != NULL);
   1921       ASSERT_EQ("test data", content->Attr(buzz::QName("", "name")));
   1922       content = parser_->NextContent(content);
   1923     }
   1924 
   1925     call_->Terminate();
   1926     ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE,
   1927               call_->sessions()[0]->state());
   1928     ASSERT_EQ(1U, stanzas_.size());
   1929     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
   1930     ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
   1931     ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
   1932     e = ActionFromStanza(stanzas_[0]);
   1933     ASSERT_TRUE(e != NULL);
   1934     ASSERT_TRUE(parser_->ActionIsTerminate(e));
   1935     ClearStanzas();
   1936   }
   1937 
   1938   void TestBadIncomingInitiate(const std::string& initiate_string) {
   1939     talk_base::scoped_ptr<buzz::XmlElement> el(
   1940         buzz::XmlElement::ForStr(initiate_string));
   1941     client_->session_manager()->OnIncomingMessage(el.get());
   1942     ASSERT_TRUE(call_ != NULL);
   1943     ASSERT_TRUE(call_->sessions()[0] != NULL);
   1944     ASSERT_EQ(cricket::Session::STATE_SENTREJECT,
   1945               call_->sessions()[0]->state());
   1946     ASSERT_EQ(2U, stanzas_.size());
   1947     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
   1948     ASSERT_TRUE(stanzas_[1]->HasAttr(buzz::QN_TYPE));
   1949     ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[1]->Attr(buzz::QN_TYPE));
   1950     ClearStanzas();
   1951   }
   1952 
   1953   void VerifyAudioCodec(const AudioCodec& codec, int id,
   1954                         const std::string& name, int clockrate,
   1955                         int bitrate, int channels) {
   1956     ASSERT_EQ(id, codec.id);
   1957     ASSERT_EQ(name, codec.name);
   1958     ASSERT_EQ(clockrate, codec.clockrate);
   1959     ASSERT_EQ(bitrate, codec.bitrate);
   1960     ASSERT_EQ(channels, codec.channels);
   1961     ASSERT_EQ(expected_audio_fb_params_, codec.feedback_params);
   1962   }
   1963 
   1964   void TestGoodOutgoingInitiate(const cricket::CallOptions& options) {
   1965     if (initial_protocol_ == cricket::PROTOCOL_JINGLE) {
   1966       // rtcp fb is only implemented for jingle.
   1967       ExpectRtcpFb();
   1968     }
   1969 
   1970     client_->CreateCall();
   1971     ASSERT_TRUE(call_ != NULL);
   1972     call_->InitiateSession(buzz::Jid("me (at) mydomain.com"),
   1973                            buzz::Jid("me (at) mydomain.com"), options);
   1974     ASSERT_TRUE(call_->sessions()[0] != NULL);
   1975     ASSERT_EQ(cricket::Session::STATE_SENTINITIATE,
   1976               call_->sessions()[0]->state());
   1977     ASSERT_EQ(1U, stanzas_.size());
   1978     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
   1979     ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
   1980     ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
   1981     buzz::XmlElement* action = ActionFromStanza(stanzas_[0]);
   1982     ASSERT_TRUE(action != NULL);
   1983     buzz::XmlElement* content = ContentFromAction(action);
   1984     ASSERT_TRUE(content != NULL);
   1985 
   1986     buzz::XmlElement* e = PayloadTypeFromContent(content);
   1987     ASSERT_TRUE(e != NULL);
   1988     cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
   1989     VerifyAudioCodec(codec, 103, "ISAC", 16000, 0, 1);
   1990 
   1991     e = NextFromPayloadType(e);
   1992     ASSERT_TRUE(e != NULL);
   1993     codec = AudioCodecFromPayloadType(e);
   1994     VerifyAudioCodec(codec, 104, "ISAC", 32000, 0, 1);
   1995 
   1996     e = NextFromPayloadType(e);
   1997     ASSERT_TRUE(e != NULL);
   1998     codec = AudioCodecFromPayloadType(e);
   1999     VerifyAudioCodec(codec, 119, "ISACLC", 16000, 40000, 1);
   2000 
   2001     e = NextFromPayloadType(e);
   2002     ASSERT_TRUE(e != NULL);
   2003     codec = AudioCodecFromPayloadType(e);
   2004     VerifyAudioCodec(codec, 99, "speex", 16000, 22000, 1);
   2005 
   2006     e = NextFromPayloadType(e);
   2007     ASSERT_TRUE(e != NULL);
   2008     codec = AudioCodecFromPayloadType(e);
   2009     VerifyAudioCodec(codec, 97, "IPCMWB", 16000, 80000, 1);
   2010 
   2011      e = NextFromPayloadType(e);
   2012     ASSERT_TRUE(e != NULL);
   2013     codec = AudioCodecFromPayloadType(e);
   2014     VerifyAudioCodec(codec, 9, "G722", 16000, 64000, 1);
   2015 
   2016     e = NextFromPayloadType(e);
   2017     ASSERT_TRUE(e != NULL);
   2018     codec = AudioCodecFromPayloadType(e);
   2019     VerifyAudioCodec(codec, 102, "iLBC", 8000, 13300, 1);
   2020 
   2021     e = NextFromPayloadType(e);
   2022     ASSERT_TRUE(e != NULL);
   2023     codec = AudioCodecFromPayloadType(e);
   2024     VerifyAudioCodec(codec, 98, "speex", 8000, 11000, 1);
   2025 
   2026     e = NextFromPayloadType(e);
   2027     ASSERT_TRUE(e != NULL);
   2028     codec = AudioCodecFromPayloadType(e);
   2029     VerifyAudioCodec(codec, 3, "GSM", 8000, 13000, 1);
   2030 
   2031     e = NextFromPayloadType(e);
   2032     ASSERT_TRUE(e != NULL);
   2033     codec = AudioCodecFromPayloadType(e);
   2034     VerifyAudioCodec(codec, 100, "EG711U", 8000, 64000, 1);
   2035 
   2036     e = NextFromPayloadType(e);
   2037     ASSERT_TRUE(e != NULL);
   2038     codec = AudioCodecFromPayloadType(e);
   2039     VerifyAudioCodec(codec, 101, "EG711A", 8000, 64000, 1);
   2040 
   2041     e = NextFromPayloadType(e);
   2042     ASSERT_TRUE(e != NULL);
   2043     codec = AudioCodecFromPayloadType(e);
   2044     VerifyAudioCodec(codec, 0, "PCMU", 8000, 64000, 1);
   2045 
   2046     e = NextFromPayloadType(e);
   2047     ASSERT_TRUE(e != NULL);
   2048     codec = AudioCodecFromPayloadType(e);
   2049     VerifyAudioCodec(codec, 8, "PCMA", 8000, 64000, 1);
   2050 
   2051     e = NextFromPayloadType(e);
   2052     ASSERT_TRUE(e != NULL);
   2053     codec = AudioCodecFromPayloadType(e);
   2054     VerifyAudioCodec(codec, 126, "CN", 32000, 0, 1);
   2055 
   2056     e = NextFromPayloadType(e);
   2057     ASSERT_TRUE(e != NULL);
   2058     codec = AudioCodecFromPayloadType(e);
   2059     VerifyAudioCodec(codec, 105, "CN", 16000, 0, 1);
   2060 
   2061     e = NextFromPayloadType(e);
   2062     ASSERT_TRUE(e != NULL);
   2063     codec = AudioCodecFromPayloadType(e);
   2064     VerifyAudioCodec(codec, 13, "CN", 8000, 0, 1);
   2065 
   2066     e = NextFromPayloadType(e);
   2067     ASSERT_TRUE(e != NULL);
   2068     codec = AudioCodecFromPayloadType(e);
   2069     VerifyAudioCodec(codec, 117, "red", 8000, 0, 1);
   2070 
   2071     e = NextFromPayloadType(e);
   2072     ASSERT_TRUE(e != NULL);
   2073     codec = AudioCodecFromPayloadType(e);
   2074     VerifyAudioCodec(codec, 106, "telephone-event", 8000, 0, 1);
   2075 
   2076     e = NextFromPayloadType(e);
   2077     ASSERT_TRUE(e == NULL);
   2078 
   2079     if (expect_outgoing_crypto_) {
   2080       buzz::XmlElement* encryption = EncryptionFromContent(content);
   2081       ASSERT_TRUE(encryption != NULL);
   2082 
   2083       if (client_->secure() == cricket::SEC_REQUIRED) {
   2084         ASSERT_TRUE(cricket::GetXmlAttr(
   2085             encryption, cricket::QN_ENCRYPTION_REQUIRED, false));
   2086       }
   2087 
   2088       if (content->Name().Namespace() == cricket::NS_GINGLE_AUDIO) {
   2089         e = encryption->FirstNamed(cricket::QN_GINGLE_AUDIO_CRYPTO_USAGE);
   2090         ASSERT_TRUE(e != NULL);
   2091         ASSERT_TRUE(
   2092             e->NextNamed(cricket::QN_GINGLE_AUDIO_CRYPTO_USAGE) == NULL);
   2093         ASSERT_TRUE(
   2094             e->FirstNamed(cricket::QN_GINGLE_VIDEO_CRYPTO_USAGE) == NULL);
   2095       }
   2096 
   2097       e = encryption->FirstNamed(cricket::QN_CRYPTO);
   2098       ASSERT_TRUE(e != NULL);
   2099       ASSERT_EQ("0", e->Attr(cricket::QN_CRYPTO_TAG));
   2100       ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", e->Attr(cricket::QN_CRYPTO_SUITE));
   2101       std::string key_0 = e->Attr(cricket::QN_CRYPTO_KEY_PARAMS);
   2102       ASSERT_EQ(47U, key_0.length());
   2103       ASSERT_EQ("inline:", key_0.substr(0, 7));
   2104 
   2105       e = e->NextNamed(cricket::QN_CRYPTO);
   2106       ASSERT_TRUE(e != NULL);
   2107       ASSERT_EQ("1", e->Attr(cricket::QN_CRYPTO_TAG));
   2108       ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", e->Attr(cricket::QN_CRYPTO_SUITE));
   2109       std::string key_1 = e->Attr(cricket::QN_CRYPTO_KEY_PARAMS);
   2110       ASSERT_EQ(47U, key_1.length());
   2111       ASSERT_EQ("inline:", key_1.substr(0, 7));
   2112       ASSERT_NE(key_0, key_1);
   2113 
   2114       encryption = NextFromEncryption(encryption);
   2115       ASSERT_TRUE(encryption == NULL);
   2116     }
   2117 
   2118     if (options.has_video) {
   2119       CheckVideoBandwidth(options.video_bandwidth,
   2120                           call_->sessions()[0]->local_description());
   2121       CheckVideoRtcpMux(expected_video_rtcp_mux_,
   2122                         call_->sessions()[0]->remote_description());
   2123       content = parser_->NextContent(content);
   2124       const buzz::XmlElement* bandwidth =
   2125           parser_->BandwidthFromContent(content);
   2126       if (options.video_bandwidth == cricket::kAutoBandwidth) {
   2127         ASSERT_TRUE(bandwidth == NULL);
   2128       } else {
   2129         ASSERT_TRUE(bandwidth != NULL);
   2130         ASSERT_EQ("AS", bandwidth->Attr(buzz::QName("", "type")));
   2131         ASSERT_EQ(talk_base::ToString(options.video_bandwidth / 1000),
   2132                   bandwidth->BodyText());
   2133       }
   2134 
   2135       buzz::XmlElement* e = PayloadTypeFromContent(content);
   2136       ASSERT_TRUE(e != NULL);
   2137       VideoCodec codec = VideoCodecFromPayloadType(e);
   2138       VideoCodec expected_codec = kVideoCodecs[0];
   2139       expected_codec.preference = codec.preference;
   2140       expected_codec.feedback_params = expected_video_fb_params_;
   2141       EXPECT_EQ(expected_codec, codec);
   2142     }
   2143 
   2144     if (options.data_channel_type == cricket::DCT_RTP) {
   2145       content = parser_->NextContent(content);
   2146       CheckRtpDataContent(content);
   2147     }
   2148 
   2149     if (options.data_channel_type == cricket::DCT_SCTP) {
   2150       content = parser_->NextContent(content);
   2151       CheckSctpDataContent(content);
   2152     }
   2153 
   2154     ClearStanzas();
   2155   }
   2156 
   2157   void TestHasAllSupportedAudioCodecs(buzz::XmlElement* e) {
   2158     ASSERT_TRUE(e != NULL);
   2159 
   2160     e = PayloadTypeFromContent(e);
   2161     ASSERT_TRUE(e != NULL);
   2162     cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
   2163     ASSERT_EQ(103, codec.id);
   2164     ASSERT_EQ("ISAC", codec.name);
   2165     ASSERT_EQ(16000, codec.clockrate);
   2166     ASSERT_EQ(1, codec.channels);
   2167 
   2168     e = NextFromPayloadType(e);
   2169     ASSERT_TRUE(e != NULL);
   2170     codec = AudioCodecFromPayloadType(e);
   2171     ASSERT_EQ(104, codec.id);
   2172     ASSERT_EQ("ISAC", codec.name);
   2173     ASSERT_EQ(32000, codec.clockrate);
   2174     ASSERT_EQ(1, codec.channels);
   2175 
   2176     e = NextFromPayloadType(e);
   2177     ASSERT_TRUE(e != NULL);
   2178     codec = AudioCodecFromPayloadType(e);
   2179     ASSERT_EQ(119, codec.id);
   2180     ASSERT_EQ("ISACLC", codec.name);
   2181     ASSERT_EQ(16000, codec.clockrate);
   2182     ASSERT_EQ(40000, codec.bitrate);
   2183     ASSERT_EQ(1, codec.channels);
   2184 
   2185     e = NextFromPayloadType(e);
   2186     ASSERT_TRUE(e != NULL);
   2187     codec = AudioCodecFromPayloadType(e);
   2188     ASSERT_EQ(99, codec.id);
   2189     ASSERT_EQ("speex", codec.name);
   2190     ASSERT_EQ(16000, codec.clockrate);
   2191     ASSERT_EQ(22000, codec.bitrate);
   2192     ASSERT_EQ(1, codec.channels);
   2193 
   2194     e = NextFromPayloadType(e);
   2195     ASSERT_TRUE(e != NULL);
   2196     codec = AudioCodecFromPayloadType(e);
   2197     ASSERT_EQ(97, codec.id);
   2198     ASSERT_EQ("IPCMWB", codec.name);
   2199     ASSERT_EQ(16000, codec.clockrate);
   2200     ASSERT_EQ(80000, codec.bitrate);
   2201     ASSERT_EQ(1, codec.channels);
   2202 
   2203     e = NextFromPayloadType(e);
   2204     ASSERT_TRUE(e != NULL);
   2205     codec = AudioCodecFromPayloadType(e);
   2206     ASSERT_EQ(9, codec.id);
   2207     ASSERT_EQ("G722", codec.name);
   2208     ASSERT_EQ(16000, codec.clockrate);
   2209     ASSERT_EQ(64000, codec.bitrate);
   2210     ASSERT_EQ(1, codec.channels);
   2211 
   2212     e = NextFromPayloadType(e);
   2213     ASSERT_TRUE(e != NULL);
   2214     codec = AudioCodecFromPayloadType(e);
   2215     ASSERT_EQ(102, codec.id);
   2216     ASSERT_EQ("iLBC", codec.name);
   2217     ASSERT_EQ(8000, codec.clockrate);
   2218     ASSERT_EQ(13300, codec.bitrate);
   2219     ASSERT_EQ(1, codec.channels);
   2220 
   2221     e = NextFromPayloadType(e);
   2222     ASSERT_TRUE(e != NULL);
   2223     codec = AudioCodecFromPayloadType(e);
   2224     ASSERT_EQ(98, codec.id);
   2225     ASSERT_EQ("speex", codec.name);
   2226     ASSERT_EQ(8000, codec.clockrate);
   2227     ASSERT_EQ(11000, codec.bitrate);
   2228     ASSERT_EQ(1, codec.channels);
   2229 
   2230     e = NextFromPayloadType(e);
   2231     ASSERT_TRUE(e != NULL);
   2232     codec = AudioCodecFromPayloadType(e);
   2233     ASSERT_EQ(3, codec.id);
   2234     ASSERT_EQ("GSM", codec.name);
   2235     ASSERT_EQ(8000, codec.clockrate);
   2236     ASSERT_EQ(13000, codec.bitrate);
   2237     ASSERT_EQ(1, codec.channels);
   2238 
   2239     e = NextFromPayloadType(e);
   2240     ASSERT_TRUE(e != NULL);
   2241     codec = AudioCodecFromPayloadType(e);
   2242     ASSERT_EQ(100, codec.id);
   2243     ASSERT_EQ("EG711U", codec.name);
   2244     ASSERT_EQ(8000, codec.clockrate);
   2245     ASSERT_EQ(64000, codec.bitrate);
   2246     ASSERT_EQ(1, codec.channels);
   2247 
   2248     e = NextFromPayloadType(e);
   2249     ASSERT_TRUE(e != NULL);
   2250     codec = AudioCodecFromPayloadType(e);
   2251     ASSERT_EQ(101, codec.id);
   2252     ASSERT_EQ("EG711A", codec.name);
   2253     ASSERT_EQ(8000, codec.clockrate);
   2254     ASSERT_EQ(64000, codec.bitrate);
   2255     ASSERT_EQ(1, codec.channels);
   2256 
   2257     e = NextFromPayloadType(e);
   2258     ASSERT_TRUE(e != NULL);
   2259     codec = AudioCodecFromPayloadType(e);
   2260     ASSERT_EQ(0, codec.id);
   2261     ASSERT_EQ("PCMU", codec.name);
   2262     ASSERT_EQ(8000, codec.clockrate);
   2263     ASSERT_EQ(64000, codec.bitrate);
   2264     ASSERT_EQ(1, codec.channels);
   2265 
   2266     e = NextFromPayloadType(e);
   2267     ASSERT_TRUE(e != NULL);
   2268     codec = AudioCodecFromPayloadType(e);
   2269     ASSERT_EQ(8, codec.id);
   2270     ASSERT_EQ("PCMA", codec.name);
   2271     ASSERT_EQ(8000, codec.clockrate);
   2272     ASSERT_EQ(64000, codec.bitrate);
   2273     ASSERT_EQ(1, codec.channels);
   2274 
   2275     e = NextFromPayloadType(e);
   2276     ASSERT_TRUE(e != NULL);
   2277     codec = AudioCodecFromPayloadType(e);
   2278     ASSERT_EQ(126, codec.id);
   2279     ASSERT_EQ("CN", codec.name);
   2280     ASSERT_EQ(32000, codec.clockrate);
   2281     ASSERT_EQ(1, codec.channels);
   2282 
   2283     e = NextFromPayloadType(e);
   2284     ASSERT_TRUE(e != NULL);
   2285     codec = AudioCodecFromPayloadType(e);
   2286     ASSERT_EQ(105, codec.id);
   2287     ASSERT_EQ("CN", codec.name);
   2288     ASSERT_EQ(16000, codec.clockrate);
   2289     ASSERT_EQ(1, codec.channels);
   2290 
   2291     e = NextFromPayloadType(e);
   2292     ASSERT_TRUE(e != NULL);
   2293     codec = AudioCodecFromPayloadType(e);
   2294     ASSERT_EQ(13, codec.id);
   2295     ASSERT_EQ("CN", codec.name);
   2296     ASSERT_EQ(8000, codec.clockrate);
   2297     ASSERT_EQ(1, codec.channels);
   2298 
   2299     e = NextFromPayloadType(e);
   2300     ASSERT_TRUE(e != NULL);
   2301     codec = AudioCodecFromPayloadType(e);
   2302     ASSERT_EQ(117, codec.id);
   2303     ASSERT_EQ("red", codec.name);
   2304     ASSERT_EQ(8000, codec.clockrate);
   2305     ASSERT_EQ(1, codec.channels);
   2306 
   2307     e = NextFromPayloadType(e);
   2308     ASSERT_TRUE(e != NULL);
   2309     codec = AudioCodecFromPayloadType(e);
   2310     ASSERT_EQ(106, codec.id);
   2311     ASSERT_EQ("telephone-event", codec.name);
   2312     ASSERT_EQ(8000, codec.clockrate);
   2313     ASSERT_EQ(1, codec.channels);
   2314 
   2315     e = NextFromPayloadType(e);
   2316     ASSERT_TRUE(e == NULL);
   2317   }
   2318 
   2319   void TestCodecsOfVideoInitiate(buzz::XmlElement* content) {
   2320     ASSERT_TRUE(content != NULL);
   2321     buzz::XmlElement* payload_type = PayloadTypeFromContent(content);
   2322     ASSERT_TRUE(payload_type != NULL);
   2323     cricket::AudioCodec codec = AudioCodecFromPayloadType(payload_type);
   2324     ASSERT_EQ(103, codec.id);
   2325     ASSERT_EQ("ISAC", codec.name);
   2326     ASSERT_EQ(16000, codec.clockrate);
   2327     ASSERT_EQ(1, codec.channels);
   2328 
   2329     content = parser_->NextContent(content);
   2330     ASSERT_TRUE(content != NULL);
   2331     payload_type = PayloadTypeFromContent(content);
   2332     ASSERT_TRUE(payload_type != NULL);
   2333     cricket::VideoCodec vcodec =
   2334         parser_->VideoCodecFromPayloadType(payload_type);
   2335     ASSERT_EQ(99, vcodec.id);
   2336     ASSERT_EQ("H264-SVC", vcodec.name);
   2337     ASSERT_EQ(320, vcodec.width);
   2338     ASSERT_EQ(200, vcodec.height);
   2339     ASSERT_EQ(30, vcodec.framerate);
   2340   }
   2341 
   2342   void TestHasAudioCodecsFromInitiateSomeUnsupported(buzz::XmlElement* e) {
   2343     ASSERT_TRUE(e != NULL);
   2344     e = PayloadTypeFromContent(e);
   2345     ASSERT_TRUE(e != NULL);
   2346 
   2347     cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
   2348     ASSERT_EQ(103, codec.id);
   2349     ASSERT_EQ("ISAC", codec.name);
   2350     ASSERT_EQ(16000, codec.clockrate);
   2351     ASSERT_EQ(1, codec.channels);
   2352 
   2353     e = NextFromPayloadType(e);
   2354     ASSERT_TRUE(e != NULL);
   2355     codec = AudioCodecFromPayloadType(e);
   2356     ASSERT_EQ(100, codec.id);
   2357     ASSERT_EQ("EG711U", codec.name);
   2358 
   2359     e = NextFromPayloadType(e);
   2360     ASSERT_TRUE(e != NULL);
   2361     codec = AudioCodecFromPayloadType(e);
   2362     ASSERT_EQ(101, codec.id);
   2363     ASSERT_EQ("EG711A", codec.name);
   2364 
   2365     e = NextFromPayloadType(e);
   2366     ASSERT_TRUE(e != NULL);
   2367     codec = AudioCodecFromPayloadType(e);
   2368     ASSERT_EQ(0, codec.id);
   2369     ASSERT_EQ("PCMU", codec.name);
   2370 
   2371     e = NextFromPayloadType(e);
   2372     ASSERT_TRUE(e != NULL);
   2373     codec = AudioCodecFromPayloadType(e);
   2374     ASSERT_EQ(13, codec.id);
   2375     ASSERT_EQ("CN", codec.name);
   2376 
   2377     e = NextFromPayloadType(e);
   2378     ASSERT_TRUE(e == NULL);
   2379   }
   2380 
   2381   void TestHasAudioCodecsFromInitiateDynamicAudioCodecs(
   2382       buzz::XmlElement* e) {
   2383     ASSERT_TRUE(e != NULL);
   2384     e = PayloadTypeFromContent(e);
   2385     ASSERT_TRUE(e != NULL);
   2386 
   2387     cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
   2388     ASSERT_EQ(123, codec.id);
   2389     ASSERT_EQ(16000, codec.clockrate);
   2390     ASSERT_EQ(1, codec.channels);
   2391 
   2392     e = NextFromPayloadType(e);
   2393     ASSERT_TRUE(e == NULL);
   2394   }
   2395 
   2396   void TestHasDefaultAudioCodecs(buzz::XmlElement* e) {
   2397     ASSERT_TRUE(e != NULL);
   2398     e = PayloadTypeFromContent(e);
   2399     ASSERT_TRUE(e != NULL);
   2400 
   2401     cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
   2402     ASSERT_EQ(103, codec.id);
   2403     ASSERT_EQ("ISAC", codec.name);
   2404 
   2405     e = NextFromPayloadType(e);
   2406     ASSERT_TRUE(e != NULL);
   2407     codec = AudioCodecFromPayloadType(e);
   2408     ASSERT_EQ(0, codec.id);
   2409     ASSERT_EQ("PCMU", codec.name);
   2410 
   2411     e = NextFromPayloadType(e);
   2412     ASSERT_TRUE(e == NULL);
   2413   }
   2414 
   2415   void TestHasAudioCodecsFromInitiateStaticAudioCodecs(
   2416       buzz::XmlElement* e) {
   2417     ASSERT_TRUE(e != NULL);
   2418     e = PayloadTypeFromContent(e);
   2419     ASSERT_TRUE(e != NULL);
   2420 
   2421     cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
   2422     ASSERT_EQ(3, codec.id);
   2423 
   2424     e = NextFromPayloadType(e);
   2425     ASSERT_TRUE(e != NULL);
   2426     codec = AudioCodecFromPayloadType(e);
   2427     ASSERT_EQ(0, codec.id);
   2428 
   2429     e = NextFromPayloadType(e);
   2430     ASSERT_TRUE(e != NULL);
   2431     codec = AudioCodecFromPayloadType(e);
   2432     ASSERT_EQ(8, codec.id);
   2433 
   2434     e = NextFromPayloadType(e);
   2435     ASSERT_TRUE(e == NULL);
   2436   }
   2437 
   2438   void TestGingleInitiateWithUnsupportedCrypto(
   2439       const std::string &initiate_string,
   2440       buzz::XmlElement** element) {
   2441     *element = NULL;
   2442 
   2443     talk_base::scoped_ptr<buzz::XmlElement> el(
   2444         buzz::XmlElement::ForStr(initiate_string));
   2445     client_->session_manager()->OnIncomingMessage(el.get());
   2446 
   2447     ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE,
   2448               call_->sessions()[0]->state());
   2449     ClearStanzas();
   2450     CheckBadCryptoFromIncomingInitiate(call_->sessions()[0]);
   2451 
   2452     call_->AcceptSession(call_->sessions()[0], cricket::CallOptions());
   2453     ClearStanzas();
   2454     CheckNoCryptoForOutgoingAccept(call_->sessions()[0]);
   2455 
   2456     call_->Terminate();
   2457     ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE,
   2458               call_->sessions()[0]->state());
   2459     ClearStanzas();
   2460   }
   2461 
   2462   void TestIncomingAcceptWithSsrcs(
   2463       const std::string& accept_string,
   2464       cricket::CallOptions& options) {
   2465     client_->CreateCall();
   2466     ASSERT_TRUE(call_ != NULL);
   2467 
   2468     call_->InitiateSession(buzz::Jid("me (at) mydomain.com"),
   2469                            buzz::Jid("me (at) mydomain.com"), options);
   2470     ASSERT_TRUE(call_->sessions()[0] != NULL);
   2471     ASSERT_EQ(cricket::Session::STATE_SENTINITIATE,
   2472               call_->sessions()[0]->state());
   2473     ASSERT_EQ(1U, stanzas_.size());
   2474     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
   2475     ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
   2476     ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
   2477     buzz::XmlElement* action = ActionFromStanza(stanzas_[0]);
   2478     ASSERT_TRUE(action != NULL);
   2479     buzz::XmlElement* content = ContentFromAction(action);
   2480     ASSERT_TRUE(content != NULL);
   2481     if (initial_protocol_ == cricket::PROTOCOL_JINGLE) {
   2482       buzz::XmlElement* content_desc =
   2483           content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
   2484       ASSERT_TRUE(content_desc != NULL);
   2485       ASSERT_EQ("", content_desc->Attr(cricket::QN_SSRC));
   2486     }
   2487     ClearStanzas();
   2488 
   2489     // We need to insert the session ID into the session accept message.
   2490     talk_base::scoped_ptr<buzz::XmlElement> el(
   2491         buzz::XmlElement::ForStr(accept_string));
   2492     const std::string sid = call_->sessions()[0]->id();
   2493     if (initial_protocol_ == cricket::PROTOCOL_JINGLE) {
   2494       buzz::XmlElement* jingle = el->FirstNamed(cricket::QN_JINGLE);
   2495       jingle->SetAttr(cricket::QN_SID, sid);
   2496     } else {
   2497       buzz::XmlElement* session = el->FirstNamed(cricket::QN_GINGLE_SESSION);
   2498       session->SetAttr(cricket::QN_ID, sid);
   2499     }
   2500 
   2501     client_->session_manager()->OnIncomingMessage(el.get());
   2502 
   2503     ASSERT_EQ(cricket::Session::STATE_RECEIVEDACCEPT,
   2504               call_->sessions()[0]->state());
   2505     ASSERT_EQ(1U, stanzas_.size());
   2506     ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
   2507     ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
   2508     ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
   2509     ClearStanzas();
   2510 
   2511     CheckAudioSsrcForIncomingAccept(call_->sessions()[0]);
   2512     CheckVideoSsrcForIncomingAccept(call_->sessions()[0]);
   2513     if (options.data_channel_type == cricket::DCT_RTP) {
   2514       CheckDataSsrcForIncomingAccept(call_->sessions()[0]);
   2515     }
   2516     // TODO(pthatcher): Check kDataSid if DCT_SCTP.
   2517   }
   2518 
   2519   size_t ClearStanzas() {
   2520     size_t size = stanzas_.size();
   2521     for (size_t i = 0; i < size; i++) {
   2522       delete stanzas_[i];
   2523     }
   2524     stanzas_.clear();
   2525     return size;
   2526   }
   2527 
   2528   buzz::XmlElement* SetJingleSid(buzz::XmlElement* stanza) {
   2529     buzz::XmlElement* jingle =
   2530         stanza->FirstNamed(cricket::QN_JINGLE);
   2531     jingle->SetAttr(cricket::QN_SID, call_->sessions()[0]->id());
   2532     return stanza;
   2533   }
   2534 
   2535   void TestSendVideoStreamUpdate() {
   2536     cricket::CallOptions options = VideoCallOptions();
   2537     options.is_muc = true;
   2538 
   2539     client_->CreateCall();
   2540     call_->InitiateSession(buzz::Jid("me (at) mydomain.com"),
   2541                            buzz::Jid("me (at) mydomain.com"), options);
   2542     ClearStanzas();
   2543 
   2544     cricket::StreamParams stream;
   2545     stream.id = "test-stream";
   2546     stream.ssrcs.push_back(1001);
   2547     talk_base::scoped_ptr<buzz::XmlElement> expected_stream_add(
   2548         buzz::XmlElement::ForStr(
   2549             JingleOutboundStreamAdd(
   2550                 call_->sessions()[0]->id(),
   2551                 "video", stream.id, "1001")));
   2552     talk_base::scoped_ptr<buzz::XmlElement> expected_stream_remove(
   2553         buzz::XmlElement::ForStr(
   2554             JingleOutboundStreamRemove(
   2555                 call_->sessions()[0]->id(),
   2556                 "video", stream.id)));
   2557 
   2558     call_->SendVideoStreamUpdate(call_->sessions()[0],
   2559                                  call_->CreateVideoStreamUpdate(stream));
   2560     ASSERT_EQ(1U, stanzas_.size());
   2561     EXPECT_EQ(expected_stream_add->Str(), stanzas_[0]->Str());
   2562     ClearStanzas();
   2563 
   2564     stream.ssrcs.clear();
   2565     call_->SendVideoStreamUpdate(call_->sessions()[0],
   2566                                  call_->CreateVideoStreamUpdate(stream));
   2567     ASSERT_EQ(1U, stanzas_.size());
   2568     EXPECT_EQ(expected_stream_remove->Str(), stanzas_[0]->Str());
   2569     ClearStanzas();
   2570   }
   2571 
   2572   void TestStreamsUpdateAndViewRequests() {
   2573     cricket::CallOptions options = VideoCallOptions();
   2574     options.is_muc = true;
   2575 
   2576     client_->CreateCall();
   2577     call_->InitiateSession(buzz::Jid("me (at) mydomain.com"),
   2578                            buzz::Jid("me (at) mydomain.com"), options);
   2579     ASSERT_EQ(1U, ClearStanzas());
   2580     ASSERT_EQ(0U, last_streams_added_.audio().size());
   2581     ASSERT_EQ(0U, last_streams_added_.video().size());
   2582     ASSERT_EQ(0U, last_streams_removed_.audio().size());
   2583     ASSERT_EQ(0U, last_streams_removed_.video().size());
   2584 
   2585     talk_base::scoped_ptr<buzz::XmlElement> accept_stanza(
   2586         buzz::XmlElement::ForStr(kJingleAcceptWithSsrcs));
   2587     SetJingleSid(accept_stanza.get());
   2588     client_->session_manager()->OnIncomingMessage(accept_stanza.get());
   2589     ASSERT_EQ(cricket::Session::STATE_RECEIVEDACCEPT,
   2590               call_->sessions()[0]->state());
   2591     ASSERT_EQ(1U, stanzas_.size());
   2592     ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
   2593     ClearStanzas();
   2594     // Need to clear the added streams, because they are populated when
   2595     // receiving an accept message now.
   2596     last_streams_added_.mutable_video()->clear();
   2597     last_streams_added_.mutable_audio()->clear();
   2598 
   2599     call_->sessions()[0]->SetState(cricket::Session::STATE_INPROGRESS);
   2600 
   2601     talk_base::scoped_ptr<buzz::XmlElement> streams_stanza(
   2602         buzz::XmlElement::ForStr(
   2603             JingleStreamAdd("video", "Bob", "video1", "ABC")));
   2604     SetJingleSid(streams_stanza.get());
   2605     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
   2606     // First one is ignored because of bad syntax.
   2607     ASSERT_EQ(1U, stanzas_.size());
   2608     // TODO(pthatcher): Figure out how to make this an ERROR rather than RESULT.
   2609     ASSERT_EQ(std::string(buzz::STR_ERROR), stanzas_[0]->Attr(buzz::QN_TYPE));
   2610     ClearStanzas();
   2611     ASSERT_EQ(0U, last_streams_added_.audio().size());
   2612     ASSERT_EQ(0U, last_streams_added_.video().size());
   2613     ASSERT_EQ(0U, last_streams_removed_.audio().size());
   2614     ASSERT_EQ(0U, last_streams_removed_.video().size());
   2615 
   2616     streams_stanza.reset(buzz::XmlElement::ForStr(
   2617         JingleStreamAdd("audio", "Bob", "audio1", "1234")));
   2618     SetJingleSid(streams_stanza.get());
   2619     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
   2620     ASSERT_EQ(1U, last_streams_added_.audio().size());
   2621     ASSERT_EQ("Bob", last_streams_added_.audio()[0].groupid);
   2622     ASSERT_EQ(1U, last_streams_added_.audio()[0].ssrcs.size());
   2623     ASSERT_EQ(1234U, last_streams_added_.audio()[0].first_ssrc());
   2624 
   2625     // Ignores adds without ssrcs.
   2626     streams_stanza.reset(buzz::XmlElement::ForStr(
   2627         JingleStreamAddWithoutSsrc("audio", "Bob", "audioX")));
   2628     SetJingleSid(streams_stanza.get());
   2629     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
   2630     ASSERT_EQ(1U, last_streams_added_.audio().size());
   2631     ASSERT_EQ(1234U, last_streams_added_.audio()[0].first_ssrc());
   2632 
   2633     // Ignores stream updates with unknown content names. (Don't terminate).
   2634     streams_stanza.reset(buzz::XmlElement::ForStr(
   2635         JingleStreamAddWithoutSsrc("foo", "Bob", "foo")));
   2636     SetJingleSid(streams_stanza.get());
   2637     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
   2638 
   2639     streams_stanza.reset(buzz::XmlElement::ForStr(
   2640         JingleStreamAdd("audio", "Joe", "audio1", "2468")));
   2641     SetJingleSid(streams_stanza.get());
   2642     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
   2643     ASSERT_EQ(1U, last_streams_added_.audio().size());
   2644     ASSERT_EQ("Joe", last_streams_added_.audio()[0].groupid);
   2645     ASSERT_EQ(1U, last_streams_added_.audio()[0].ssrcs.size());
   2646     ASSERT_EQ(2468U, last_streams_added_.audio()[0].first_ssrc());
   2647 
   2648     streams_stanza.reset(buzz::XmlElement::ForStr(
   2649         JingleStreamAdd("video", "Bob", "video1", "5678")));
   2650     SetJingleSid(streams_stanza.get());
   2651     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
   2652     ASSERT_EQ(1U, last_streams_added_.video().size());
   2653     ASSERT_EQ("Bob", last_streams_added_.video()[0].groupid);
   2654     ASSERT_EQ(1U, last_streams_added_.video()[0].ssrcs.size());
   2655     ASSERT_EQ(5678U, last_streams_added_.video()[0].first_ssrc());
   2656 
   2657     // We're testing that a "duplicate" is effectively ignored.
   2658     last_streams_added_.mutable_video()->clear();
   2659     last_streams_removed_.mutable_video()->clear();
   2660     streams_stanza.reset(buzz::XmlElement::ForStr(
   2661         JingleStreamAdd("video", "Bob", "video1", "5678")));
   2662     SetJingleSid(streams_stanza.get());
   2663     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
   2664     ASSERT_EQ(0U, last_streams_added_.video().size());
   2665     ASSERT_EQ(0U, last_streams_removed_.video().size());
   2666 
   2667     streams_stanza.reset(buzz::XmlElement::ForStr(
   2668         JingleStreamAdd("video", "Bob", "video2", "5679")));
   2669     SetJingleSid(streams_stanza.get());
   2670     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
   2671     ASSERT_EQ(1U, last_streams_added_.video().size());
   2672     ASSERT_EQ("Bob", last_streams_added_.video()[0].groupid);
   2673     ASSERT_EQ(1U, last_streams_added_.video()[0].ssrcs.size());
   2674     ASSERT_EQ(5679U, last_streams_added_.video()[0].first_ssrc());
   2675 
   2676     cricket::FakeVoiceMediaChannel* voice_channel = fme_->GetVoiceChannel(0);
   2677     ASSERT_TRUE(voice_channel != NULL);
   2678     ASSERT_TRUE(voice_channel->HasRecvStream(1234U));
   2679     ASSERT_TRUE(voice_channel->HasRecvStream(2468U));
   2680     cricket::FakeVideoMediaChannel* video_channel = fme_->GetVideoChannel(0);
   2681     ASSERT_TRUE(video_channel != NULL);
   2682     ASSERT_TRUE(video_channel->HasRecvStream(5678U));
   2683     ClearStanzas();
   2684 
   2685     cricket::ViewRequest viewRequest;
   2686     cricket::StaticVideoView staticVideoView(
   2687         cricket::StreamSelector(5678U), 640, 480, 30);
   2688     viewRequest.static_video_views.push_back(staticVideoView);
   2689     talk_base::scoped_ptr<buzz::XmlElement> expected_view_elem(
   2690         buzz::XmlElement::ForStr(JingleView("5678", "640", "480", "30")));
   2691     SetJingleSid(expected_view_elem.get());
   2692 
   2693     ASSERT_TRUE(
   2694         call_->SendViewRequest(call_->sessions()[0], viewRequest));
   2695     ASSERT_EQ(1U, stanzas_.size());
   2696     ASSERT_EQ(expected_view_elem->Str(), stanzas_[0]->Str());
   2697     ClearStanzas();
   2698 
   2699     streams_stanza.reset(buzz::XmlElement::ForStr(
   2700         JingleStreamRemove("audio", "Bob", "audio1")));
   2701     SetJingleSid(streams_stanza.get());
   2702     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
   2703     ASSERT_EQ(1U, last_streams_removed_.audio().size());
   2704     ASSERT_EQ(1U, last_streams_removed_.audio()[0].ssrcs.size());
   2705     EXPECT_EQ(1234U, last_streams_removed_.audio()[0].first_ssrc());
   2706 
   2707     streams_stanza.reset(buzz::XmlElement::ForStr(
   2708         JingleStreamRemove("video", "Bob", "video1")));
   2709     SetJingleSid(streams_stanza.get());
   2710     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
   2711     ASSERT_EQ(1U, last_streams_removed_.video().size());
   2712     ASSERT_EQ(1U, last_streams_removed_.video()[0].ssrcs.size());
   2713     EXPECT_EQ(5678U, last_streams_removed_.video()[0].first_ssrc());
   2714 
   2715     streams_stanza.reset(buzz::XmlElement::ForStr(
   2716         JingleStreamRemove("video", "Bob", "video2")));
   2717     SetJingleSid(streams_stanza.get());
   2718     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
   2719     ASSERT_EQ(1U, last_streams_removed_.video().size());
   2720     ASSERT_EQ(1U, last_streams_removed_.video()[0].ssrcs.size());
   2721     EXPECT_EQ(5679U, last_streams_removed_.video()[0].first_ssrc());
   2722 
   2723     // Duplicate removal: should be ignored.
   2724     last_streams_removed_.mutable_audio()->clear();
   2725     streams_stanza.reset(buzz::XmlElement::ForStr(
   2726         JingleStreamRemove("audio", "Bob", "audio1")));
   2727     SetJingleSid(streams_stanza.get());
   2728     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
   2729     ASSERT_EQ(0U, last_streams_removed_.audio().size());
   2730 
   2731     // Duplicate removal: should be ignored.
   2732     last_streams_removed_.mutable_video()->clear();
   2733     streams_stanza.reset(buzz::XmlElement::ForStr(
   2734         JingleStreamRemove("video", "Bob", "video1")));
   2735     SetJingleSid(streams_stanza.get());
   2736     client_->session_manager()->OnIncomingMessage(streams_stanza.get());
   2737     ASSERT_EQ(0U, last_streams_removed_.video().size());
   2738 
   2739     voice_channel = fme_->GetVoiceChannel(0);
   2740     ASSERT_TRUE(voice_channel != NULL);
   2741     ASSERT_FALSE(voice_channel->HasRecvStream(1234U));
   2742     ASSERT_TRUE(voice_channel->HasRecvStream(2468U));
   2743     video_channel = fme_->GetVideoChannel(0);
   2744     ASSERT_TRUE(video_channel != NULL);
   2745     ASSERT_FALSE(video_channel->HasRecvStream(5678U));
   2746 
   2747     // Fails because ssrc is now invalid.
   2748     ASSERT_FALSE(
   2749         call_->SendViewRequest(call_->sessions()[0], viewRequest));
   2750 
   2751     ClearStanzas();
   2752   }
   2753 
   2754   void MakeSignalingSecure(cricket::SecureMediaPolicy secure) {
   2755     client_->set_secure(secure);
   2756   }
   2757 
   2758   void ExpectCrypto(cricket::SecureMediaPolicy secure) {
   2759     MakeSignalingSecure(secure);
   2760     expect_incoming_crypto_ = true;
   2761 #ifdef HAVE_SRTP
   2762     expect_outgoing_crypto_ = true;
   2763 #endif
   2764   }
   2765 
   2766   void ExpectVideoBandwidth(int bandwidth) {
   2767     expected_video_bandwidth_ = bandwidth;
   2768   }
   2769 
   2770   void ExpectVideoRtcpMux(bool rtcp_mux) {
   2771     expected_video_rtcp_mux_ = rtcp_mux;
   2772   }
   2773 
   2774   template <class C>
   2775   void SetCodecFeedbackParams(std::vector<C>* codecs,
   2776                               const FeedbackParams& fb_params) {
   2777     for (size_t i = 0; i < codecs->size(); ++i) {
   2778       codecs->at(i).feedback_params = fb_params;
   2779     }
   2780   }
   2781 
   2782   void ExpectRtcpFb() {
   2783     FeedbackParams params_nack_fir;
   2784     params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamCcm,
   2785                                       cricket::kRtcpFbCcmParamFir));
   2786     params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamNack));
   2787 
   2788     FeedbackParams params_nack;
   2789     params_nack.Add(FeedbackParam(cricket::kRtcpFbParamNack));
   2790 
   2791     expected_audio_fb_params_ = params_nack;
   2792     expected_video_fb_params_ = params_nack_fir;
   2793     expected_data_fb_params_ = params_nack;
   2794   }
   2795 
   2796  private:
   2797   void OnSendStanza(cricket::SessionManager* manager,
   2798                     const buzz::XmlElement* stanza) {
   2799     LOG(LS_INFO) << stanza->Str();
   2800     stanzas_.push_back(new buzz::XmlElement(*stanza));
   2801   }
   2802 
   2803   void OnSessionCreate(cricket::Session* session, bool initiate) {
   2804     session->set_current_protocol(initial_protocol_);
   2805   }
   2806 
   2807   void OnCallCreate(cricket::Call *call) {
   2808     call_ = call;
   2809     call->SignalMediaStreamsUpdate.connect(
   2810         this, &MediaSessionClientTest::OnMediaStreamsUpdate);
   2811   }
   2812 
   2813   void OnCallDestroy(cricket::Call *call) {
   2814     call_ = NULL;
   2815   }
   2816 
   2817   void OnMediaStreamsUpdate(cricket::Call *call,
   2818                             cricket::Session *session,
   2819                             const cricket::MediaStreams& added,
   2820                             const cricket::MediaStreams& removed) {
   2821     last_streams_added_.CopyFrom(added);
   2822     last_streams_removed_.CopyFrom(removed);
   2823   }
   2824 
   2825   talk_base::NetworkManager* nm_;
   2826   cricket::PortAllocator* pa_;
   2827   cricket::SessionManager* sm_;
   2828   cricket::FakeMediaEngine* fme_;
   2829   cricket::FakeDataEngine* fdme_;
   2830   cricket::MediaSessionClient* client_;
   2831 
   2832   cricket::Call* call_;
   2833   std::vector<buzz::XmlElement* > stanzas_;
   2834   MediaSessionTestParser* parser_;
   2835   cricket::SignalingProtocol initial_protocol_;
   2836   bool expect_incoming_crypto_;
   2837   bool expect_outgoing_crypto_;
   2838   int expected_video_bandwidth_;
   2839   bool expected_video_rtcp_mux_;
   2840   FeedbackParams expected_audio_fb_params_;
   2841   FeedbackParams expected_video_fb_params_;
   2842   FeedbackParams expected_data_fb_params_;
   2843   cricket::MediaStreams last_streams_added_;
   2844   cricket::MediaStreams last_streams_removed_;
   2845 };
   2846 
   2847 MediaSessionClientTest* GingleTest() {
   2848   return new MediaSessionClientTest(new GingleSessionTestParser(),
   2849                                     cricket::PROTOCOL_GINGLE);
   2850 }
   2851 
   2852 MediaSessionClientTest* JingleTest() {
   2853   return new MediaSessionClientTest(new JingleSessionTestParser(),
   2854                                     cricket::PROTOCOL_JINGLE);
   2855 }
   2856 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   2984 TEST(MediaSessionTest, JingleBadInitiateNoAudioCodecs) {
   2985   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
   2986   test->TestBadIncomingInitiate(kJingleInitiateNoAudioCodecs);
   2987 }
   2988 
   2989 TEST(MediaSessionTest, JingleBadInitiateNoSupportedAudioCodecs) {
   2990   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
   2991   test->TestBadIncomingInitiate(kJingleInitiateNoSupportedAudioCodecs);
   2992 }
   2993 
   2994 TEST(MediaSessionTest, JingleBadInitiateWrongClockrates) {
   2995   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
   2996   test->TestBadIncomingInitiate(kJingleInitiateWrongClockrates);
   2997 }
   2998 
   2999 TEST(MediaSessionTest, JingleBadInitiateWrongChannels) {
   3000   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
   3001   test->TestBadIncomingInitiate(kJingleInitiateWrongChannels);
   3002 }
   3003 
   3004 TEST(MediaSessionTest, JingleBadInitiateNoPayloadTypes) {
   3005   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
   3006   test->TestBadIncomingInitiate(kJingleInitiateNoPayloadTypes);
   3007 }
   3008 
   3009 TEST(MediaSessionTest, JingleBadInitiateDynamicWithoutNames) {
   3010   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
   3011   test->TestBadIncomingInitiate(kJingleInitiateDynamicWithoutNames);
   3012 }
   3013 
   3014 TEST(MediaSessionTest, JingleGoodOutgoingInitiate) {
   3015   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
   3016   test->TestGoodOutgoingInitiate(AudioCallOptions());
   3017 }
   3018 
   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 
   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 
   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 
   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.
   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.
   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.
   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.
   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.
   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.
   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.
   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.
   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.
   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 
   3134 TEST(MediaSessionTest, JingleGoodOutgoingInitiateWithCrypto) {
   3135   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
   3136   test->ExpectCrypto(cricket::SEC_ENABLED);
   3137   test->TestGoodOutgoingInitiate(AudioCallOptions());
   3138 }
   3139 
   3140 TEST(MediaSessionTest, JingleGoodOutgoingInitiateWithCryptoRequired) {
   3141   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
   3142   test->ExpectCrypto(cricket::SEC_REQUIRED);
   3143   test->TestGoodOutgoingInitiate(AudioCallOptions());
   3144 }
   3145 
   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 
   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 
   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 
   3169 TEST(MediaSessionTest, JingleStreamsUpdateAndView) {
   3170   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
   3171   test->TestStreamsUpdateAndViewRequests();
   3172 }
   3173 
   3174 TEST(MediaSessionTest, JingleSendVideoStreamUpdate) {
   3175   talk_base::scoped_ptr<MediaSessionClientTest> test(JingleTest());
   3176   test->TestSendVideoStreamUpdate();
   3177 }
   3178 
   3179 // Gingle tests
   3180 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   3256 TEST(MediaSessionTest, GingleBadInitiateNoSupportedAudioCodecs) {
   3257   talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest());
   3258   test->TestBadIncomingInitiate(kGingleInitiateNoSupportedAudioCodecs);
   3259 }
   3260 
   3261 TEST(MediaSessionTest, GingleBadInitiateWrongClockrates) {
   3262   talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest());
   3263   test->TestBadIncomingInitiate(kGingleInitiateWrongClockrates);
   3264 }
   3265 
   3266 TEST(MediaSessionTest, GingleBadInitiateWrongChannels) {
   3267   talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest());
   3268   test->TestBadIncomingInitiate(kGingleInitiateWrongChannels);
   3269 }
   3270 
   3271 
   3272 TEST(MediaSessionTest, GingleBadInitiateNoPayloadTypes) {
   3273   talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest());
   3274   test->TestBadIncomingInitiate(kGingleInitiateNoPayloadTypes);
   3275 }
   3276 
   3277 TEST(MediaSessionTest, GingleBadInitiateDynamicWithoutNames) {
   3278   talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest());
   3279   test->TestBadIncomingInitiate(kGingleInitiateDynamicWithoutNames);
   3280 }
   3281 
   3282 TEST(MediaSessionTest, GingleGoodOutgoingInitiate) {
   3283   talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest());
   3284   test->TestGoodOutgoingInitiate(AudioCallOptions());
   3285 }
   3286 
   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.
   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.
   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.
   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.
   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.
   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.
   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.
   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.
   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.
   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 
   3379 TEST(MediaSessionTest, GingleGoodOutgoingInitiateWithCrypto) {
   3380   talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest());
   3381   test->ExpectCrypto(cricket::SEC_ENABLED);
   3382   test->TestGoodOutgoingInitiate(AudioCallOptions());
   3383 }
   3384 
   3385 TEST(MediaSessionTest, GingleGoodOutgoingInitiateWithCryptoRequired) {
   3386   talk_base::scoped_ptr<MediaSessionClientTest> test(GingleTest());
   3387   test->ExpectCrypto(cricket::SEC_REQUIRED);
   3388   test->TestGoodOutgoingInitiate(AudioCallOptions());
   3389 }
   3390 
   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 
   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