tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

sdp_unittests.cpp (232510B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include <string>
      8 
      9 #define GTEST_HAS_RTTI 0
     10 #include "gtest/gtest.h"
     11 
     12 #include "nss.h"
     13 #include "ssl.h"
     14 
     15 #include "sdp/RsdparsaSdpParser.h"
     16 #include "sdp/SipccSdpParser.h"
     17 #include "sdp/SdpMediaSection.h"
     18 #include "sdp/SdpAttribute.h"
     19 #include "sdp/ParsingResultComparer.h"
     20 
     21 extern "C" {
     22 #include "sipcc_sdp.h"
     23 #include "sdp_private.h"
     24 }
     25 
     26 #ifdef CRLF
     27 #  undef CRLF
     28 #endif
     29 #define CRLF "\r\n"
     30 
     31 #define SKIP_TEST_WITH_RUST_PARSER      \
     32  if (!::testing::get<1>(GetParam())) { \
     33    return;                             \
     34  }
     35 #define SKIP_TEST_WITH_SIPCC_PARSER \
     36  if (ResultsAreFromSipcc()) {      \
     37    return;                         \
     38  }
     39 
     40 // If you want to see the SDP as it is parsed
     41 // #define DEBUG_DISPLAY_SDP
     42 
     43 using namespace mozilla;
     44 
     45 namespace test {
     46 
     47 class SdpTest : public ::testing::Test {
     48 public:
     49  SdpTest() : final_level_(0), sdp_ptr_(nullptr) {}
     50 
     51  ~SdpTest() { sdp_free_description(sdp_ptr_); }
     52 
     53  static void SetUpTestCase() {
     54    NSS_NoDB_Init(nullptr);
     55    NSS_SetDomesticPolicy();
     56  }
     57 
     58  void SetUp() {
     59    final_level_ = 0;
     60    sdp_ptr_ = nullptr;
     61  }
     62 
     63  static void TearDownTestCase() {}
     64 
     65  void ResetSdp() {
     66    if (!sdp_ptr_) {
     67      sdp_free_description(sdp_ptr_);
     68    }
     69 
     70    sdp_media_e supported_media[] = {
     71        SDP_MEDIA_AUDIO,      SDP_MEDIA_VIDEO,        SDP_MEDIA_APPLICATION,
     72        SDP_MEDIA_DATA,       SDP_MEDIA_CONTROL,      SDP_MEDIA_NAS_RADIUS,
     73        SDP_MEDIA_NAS_TACACS, SDP_MEDIA_NAS_DIAMETER, SDP_MEDIA_NAS_L2TP,
     74        SDP_MEDIA_NAS_LOGIN,  SDP_MEDIA_NAS_NONE,     SDP_MEDIA_IMAGE,
     75    };
     76 
     77    sdp_conf_options_t* config_p = sdp_init_config();
     78    unsigned int i;
     79    for (i = 0; i < sizeof(supported_media) / sizeof(sdp_media_e); i++) {
     80      sdp_media_supported(config_p, supported_media[i], true);
     81    }
     82    sdp_nettype_supported(config_p, SDP_NT_INTERNET, true);
     83    sdp_addrtype_supported(config_p, SDP_AT_IP4, true);
     84    sdp_addrtype_supported(config_p, SDP_AT_IP6, true);
     85    sdp_transport_supported(config_p, SDP_TRANSPORT_RTPSAVPF, true);
     86    sdp_transport_supported(config_p, SDP_TRANSPORT_UDPTL, true);
     87    sdp_require_session_name(config_p, false);
     88 
     89    sdp_ptr_ = sdp_init_description(config_p);
     90    if (!sdp_ptr_) {
     91      sdp_free_config(config_p);
     92    }
     93  }
     94 
     95  void ParseSdp(const std::string& sdp_str) {
     96    const char* buf = sdp_str.data();
     97    ResetSdp();
     98    ASSERT_EQ(sdp_parse(sdp_ptr_, buf, sdp_str.size()), SDP_SUCCESS);
     99  }
    100 
    101  void InitLocalSdp() {
    102    ResetSdp();
    103    ASSERT_EQ(sdp_set_version(sdp_ptr_, 0), SDP_SUCCESS);
    104    ASSERT_EQ(sdp_set_owner_username(sdp_ptr_, "-"), SDP_SUCCESS);
    105    ASSERT_EQ(sdp_set_owner_sessionid(sdp_ptr_, "132954853"), SDP_SUCCESS);
    106    ASSERT_EQ(sdp_set_owner_version(sdp_ptr_, "0"), SDP_SUCCESS);
    107    ASSERT_EQ(sdp_set_owner_network_type(sdp_ptr_, SDP_NT_INTERNET),
    108              SDP_SUCCESS);
    109    ASSERT_EQ(sdp_set_owner_address_type(sdp_ptr_, SDP_AT_IP4), SDP_SUCCESS);
    110    ASSERT_EQ(sdp_set_owner_address(sdp_ptr_, "198.51.100.7"), SDP_SUCCESS);
    111    ASSERT_EQ(sdp_set_session_name(sdp_ptr_, "SDP Unit Test"), SDP_SUCCESS);
    112    ASSERT_EQ(sdp_set_time_start(sdp_ptr_, "0"), SDP_SUCCESS);
    113    ASSERT_EQ(sdp_set_time_stop(sdp_ptr_, "0"), SDP_SUCCESS);
    114  }
    115 
    116  std::string SerializeSdp() {
    117    flex_string fs;
    118    flex_string_init(&fs);
    119    EXPECT_EQ(sdp_build(sdp_ptr_, &fs), SDP_SUCCESS);
    120    std::string body(fs.buffer);
    121    flex_string_free(&fs);
    122    return body;
    123  }
    124 
    125  // Returns "level" for new media section
    126  int AddNewMedia(sdp_media_e type) {
    127    final_level_++;
    128    EXPECT_EQ(sdp_insert_media_line(sdp_ptr_, final_level_), SDP_SUCCESS);
    129    EXPECT_EQ(sdp_set_conn_nettype(sdp_ptr_, final_level_, SDP_NT_INTERNET),
    130              SDP_SUCCESS);
    131    EXPECT_EQ(sdp_set_conn_addrtype(sdp_ptr_, final_level_, SDP_AT_IP4),
    132              SDP_SUCCESS);
    133    EXPECT_EQ(sdp_set_conn_address(sdp_ptr_, final_level_, "198.51.100.7"),
    134              SDP_SUCCESS);
    135    EXPECT_EQ(sdp_set_media_type(sdp_ptr_, final_level_, SDP_MEDIA_VIDEO),
    136              SDP_SUCCESS);
    137    EXPECT_EQ(
    138        sdp_set_media_transport(sdp_ptr_, final_level_, SDP_TRANSPORT_RTPAVP),
    139        SDP_SUCCESS);
    140    EXPECT_EQ(sdp_set_media_portnum(sdp_ptr_, final_level_, 12345, 0),
    141              SDP_SUCCESS);
    142    EXPECT_EQ(sdp_add_media_payload_type(sdp_ptr_, final_level_, 120,
    143                                         SDP_PAYLOAD_NUMERIC),
    144              SDP_SUCCESS);
    145    return final_level_;
    146  }
    147 
    148  uint16_t AddNewRtcpFbAck(int level, sdp_rtcp_fb_ack_type_e type,
    149                           uint16_t payload = SDP_ALL_PAYLOADS) {
    150    uint16_t inst_num = 0;
    151    EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_RTCP_FB, &inst_num),
    152              SDP_SUCCESS);
    153    EXPECT_EQ(
    154        sdp_attr_set_rtcp_fb_ack(sdp_ptr_, level, payload, inst_num, type),
    155        SDP_SUCCESS);
    156    return inst_num;
    157  }
    158 
    159  uint16_t AddNewRtcpFbNack(int level, sdp_rtcp_fb_nack_type_e type,
    160                            uint16_t payload = SDP_ALL_PAYLOADS) {
    161    uint16_t inst_num = 0;
    162    EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_RTCP_FB, &inst_num),
    163              SDP_SUCCESS);
    164    EXPECT_EQ(
    165        sdp_attr_set_rtcp_fb_nack(sdp_ptr_, level, payload, inst_num, type),
    166        SDP_SUCCESS);
    167    return inst_num;
    168  }
    169 
    170  uint16_t AddNewRtcpFbTrrInt(int level, uint32_t interval,
    171                              uint16_t payload = SDP_ALL_PAYLOADS) {
    172    uint16_t inst_num = 0;
    173    EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_RTCP_FB, &inst_num),
    174              SDP_SUCCESS);
    175    EXPECT_EQ(sdp_attr_set_rtcp_fb_trr_int(sdp_ptr_, level, payload, inst_num,
    176                                           interval),
    177              SDP_SUCCESS);
    178    return inst_num;
    179  }
    180 
    181  uint16_t AddNewRtcpFbRemb(int level, uint16_t payload = SDP_ALL_PAYLOADS) {
    182    uint16_t inst_num = 0;
    183    EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_RTCP_FB, &inst_num),
    184              SDP_SUCCESS);
    185    EXPECT_EQ(sdp_attr_set_rtcp_fb_remb(sdp_ptr_, level, payload, inst_num),
    186              SDP_SUCCESS);
    187    return inst_num;
    188  }
    189 
    190  uint16_t AddNewRtcpFbCcm(int level, sdp_rtcp_fb_ccm_type_e type,
    191                           uint16_t payload = SDP_ALL_PAYLOADS) {
    192    uint16_t inst_num = 0;
    193    EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_RTCP_FB, &inst_num),
    194              SDP_SUCCESS);
    195    EXPECT_EQ(
    196        sdp_attr_set_rtcp_fb_ccm(sdp_ptr_, level, payload, inst_num, type),
    197        SDP_SUCCESS);
    198    return inst_num;
    199  }
    200  uint16_t AddNewExtMap(int level, const char* uri) {
    201    uint16_t inst_num = 0;
    202    EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_EXTMAP, &inst_num),
    203              SDP_SUCCESS);
    204    EXPECT_EQ(sdp_attr_set_extmap(sdp_ptr_, level, inst_num, uri, inst_num),
    205              SDP_SUCCESS);
    206    return inst_num;
    207  }
    208 
    209  uint16_t AddNewFmtpMaxFs(int level, uint32_t max_fs) {
    210    uint16_t inst_num = 0;
    211    EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_FMTP, &inst_num),
    212              SDP_SUCCESS);
    213    EXPECT_EQ(sdp_attr_set_fmtp_payload_type(sdp_ptr_, level, 0, inst_num, 120),
    214              SDP_SUCCESS);
    215    EXPECT_EQ(sdp_attr_set_fmtp_max_fs(sdp_ptr_, level, 0, inst_num, max_fs),
    216              SDP_SUCCESS);
    217    return inst_num;
    218  }
    219 
    220  uint16_t AddNewFmtpMaxFr(int level, uint32_t max_fr) {
    221    uint16_t inst_num = 0;
    222    EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_FMTP, &inst_num),
    223              SDP_SUCCESS);
    224    EXPECT_EQ(sdp_attr_set_fmtp_payload_type(sdp_ptr_, level, 0, inst_num, 120),
    225              SDP_SUCCESS);
    226    EXPECT_EQ(sdp_attr_set_fmtp_max_fr(sdp_ptr_, level, 0, inst_num, max_fr),
    227              SDP_SUCCESS);
    228    return inst_num;
    229  }
    230 
    231  uint16_t AddNewFmtpMaxFsFr(int level, uint32_t max_fs, uint32_t max_fr) {
    232    uint16_t inst_num = 0;
    233    EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_FMTP, &inst_num),
    234              SDP_SUCCESS);
    235    EXPECT_EQ(sdp_attr_set_fmtp_payload_type(sdp_ptr_, level, 0, inst_num, 120),
    236              SDP_SUCCESS);
    237    EXPECT_EQ(sdp_attr_set_fmtp_max_fs(sdp_ptr_, level, 0, inst_num, max_fs),
    238              SDP_SUCCESS);
    239    EXPECT_EQ(sdp_attr_set_fmtp_max_fr(sdp_ptr_, level, 0, inst_num, max_fr),
    240              SDP_SUCCESS);
    241    return inst_num;
    242  }
    243 
    244 protected:
    245  int final_level_;
    246  sdp_t* sdp_ptr_;
    247 };
    248 
    249 MOZ_RUNINIT static const std::string kVideoSdp =
    250    "v=0\r\n"
    251    "o=- 4294967296 2 IN IP4 127.0.0.1\r\n"
    252    "s=SIP Call\r\n"
    253    "c=IN IP4 198.51.100.7\r\n"
    254    "t=0 0\r\n"
    255    "m=video 56436 RTP/SAVPF 120\r\n"
    256    "a=rtpmap:120 VP8/90000\r\n";
    257 
    258 TEST_F(SdpTest, parseRtcpFbAckRpsi) {
    259  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ack rpsi\r\n");
    260  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 1),
    261            SDP_RTCP_FB_ACK_RPSI);
    262 }
    263 
    264 TEST_F(SdpTest, parseRtcpFbAckApp) {
    265  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ack app\r\n");
    266  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 1), SDP_RTCP_FB_ACK_APP);
    267 }
    268 
    269 TEST_F(SdpTest, parseRtcpFbAckAppFoo) {
    270  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ack app foo\r\n");
    271  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 1), SDP_RTCP_FB_ACK_APP);
    272 }
    273 
    274 TEST_F(SdpTest, parseRtcpFbAckFooBar) {
    275  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ack foo bar\r\n");
    276  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 1),
    277            SDP_RTCP_FB_ACK_UNKNOWN);
    278 }
    279 
    280 TEST_F(SdpTest, parseRtcpFbAckFooBarBaz) {
    281  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ack foo bar baz\r\n");
    282  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 1),
    283            SDP_RTCP_FB_ACK_UNKNOWN);
    284 }
    285 
    286 TEST_F(SdpTest, parseRtcpFbNack) {
    287  ParseSdp(kVideoSdp + "a=rtcp-fb:120 nack\r\n");
    288  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 1),
    289            SDP_RTCP_FB_NACK_BASIC);
    290 }
    291 
    292 TEST_F(SdpTest, parseRtcpFbNackPli) {
    293  ParseSdp(kVideoSdp + "a=rtcp-fb:120 nack pli\r\n");
    294 }
    295 
    296 TEST_F(SdpTest, parseRtcpFbNackSli) {
    297  ParseSdp(kVideoSdp + "a=rtcp-fb:120 nack sli\r\n");
    298  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 1),
    299            SDP_RTCP_FB_NACK_SLI);
    300 }
    301 
    302 TEST_F(SdpTest, parseRtcpFbNackRpsi) {
    303  ParseSdp(kVideoSdp + "a=rtcp-fb:120 nack rpsi\r\n");
    304  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 1),
    305            SDP_RTCP_FB_NACK_RPSI);
    306 }
    307 
    308 TEST_F(SdpTest, parseRtcpFbNackApp) {
    309  ParseSdp(kVideoSdp + "a=rtcp-fb:120 nack app\r\n");
    310  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 1),
    311            SDP_RTCP_FB_NACK_APP);
    312 }
    313 
    314 TEST_F(SdpTest, parseRtcpFbNackAppFoo) {
    315  ParseSdp(kVideoSdp + "a=rtcp-fb:120 nack app foo\r\n");
    316  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 1),
    317            SDP_RTCP_FB_NACK_APP);
    318 }
    319 
    320 TEST_F(SdpTest, parseRtcpFbNackAppFooBar) {
    321  ParseSdp(kVideoSdp + "a=rtcp-fb:120 nack app foo bar\r\n");
    322  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 1),
    323            SDP_RTCP_FB_NACK_APP);
    324 }
    325 
    326 TEST_F(SdpTest, parseRtcpFbNackFooBarBaz) {
    327  ParseSdp(kVideoSdp + "a=rtcp-fb:120 nack foo bar baz\r\n");
    328  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 1),
    329            SDP_RTCP_FB_NACK_UNKNOWN);
    330 }
    331 
    332 TEST_F(SdpTest, parseRtcpFbRemb) {
    333  ParseSdp(kVideoSdp + "a=rtcp-fb:120 goog-remb\r\n");
    334  ASSERT_EQ((bool)sdp_attr_get_rtcp_fb_remb_enabled(sdp_ptr_, 1, 120), true);
    335 }
    336 
    337 TEST_F(SdpTest, parseRtcpRbRembAllPt) {
    338  ParseSdp(kVideoSdp + "a=rtcp-fb:* goog-remb\r\n");
    339  ASSERT_EQ(
    340      (bool)sdp_attr_get_rtcp_fb_remb_enabled(sdp_ptr_, 1, SDP_ALL_PAYLOADS),
    341      true);
    342 }
    343 
    344 TEST_F(SdpTest, parseRtcpFbTrrInt0) {
    345  ParseSdp(kVideoSdp + "a=rtcp-fb:120 trr-int 0\r\n");
    346  ASSERT_EQ(sdp_attr_get_rtcp_fb_trr_int(sdp_ptr_, 1, 120, 1), 0U);
    347 }
    348 
    349 TEST_F(SdpTest, parseRtcpFbTrrInt123) {
    350  ParseSdp(kVideoSdp + "a=rtcp-fb:120 trr-int 123\r\n");
    351  ASSERT_EQ(sdp_attr_get_rtcp_fb_trr_int(sdp_ptr_, 1, 120, 1), 123U);
    352 }
    353 
    354 TEST_F(SdpTest, parseRtcpFbCcmFir) {
    355  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ccm fir\r\n");
    356  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 1), SDP_RTCP_FB_CCM_FIR);
    357 }
    358 
    359 TEST_F(SdpTest, parseRtcpFbCcmTmmbr) {
    360  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ccm tmmbr\r\n");
    361  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 1),
    362            SDP_RTCP_FB_CCM_TMMBR);
    363 }
    364 
    365 TEST_F(SdpTest, parseRtcpFbCcmTmmbrSmaxpr) {
    366  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ccm tmmbr smaxpr=456\r\n");
    367  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 1),
    368            SDP_RTCP_FB_CCM_TMMBR);
    369 }
    370 
    371 TEST_F(SdpTest, parseRtcpFbCcmTstr) {
    372  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ccm tstr\r\n");
    373  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 1),
    374            SDP_RTCP_FB_CCM_TSTR);
    375 }
    376 
    377 TEST_F(SdpTest, parseRtcpFbCcmVbcm) {
    378  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ccm vbcm 123 456 789\r\n");
    379  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 1),
    380            SDP_RTCP_FB_CCM_VBCM);
    381  // We don't currently parse out VBCM submessage types, since we don't have
    382  // any use for them.
    383 }
    384 
    385 TEST_F(SdpTest, parseRtcpFbCcmFoo) {
    386  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ccm foo\r\n");
    387  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 1),
    388            SDP_RTCP_FB_CCM_UNKNOWN);
    389 }
    390 
    391 TEST_F(SdpTest, parseRtcpFbCcmFooBarBaz) {
    392  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ccm foo bar baz\r\n");
    393  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 1),
    394            SDP_RTCP_FB_CCM_UNKNOWN);
    395 }
    396 
    397 TEST_F(SdpTest, parseRtcpFbFoo) {
    398  ParseSdp(kVideoSdp + "a=rtcp-fb:120 foo\r\n");
    399 }
    400 
    401 TEST_F(SdpTest, parseRtcpFbFooBar) {
    402  ParseSdp(kVideoSdp + "a=rtcp-fb:120 foo bar\r\n");
    403 }
    404 
    405 TEST_F(SdpTest, parseRtcpFbFooBarBaz) {
    406  ParseSdp(kVideoSdp + "a=rtcp-fb:120 foo bar baz\r\n");
    407 }
    408 
    409 MOZ_RUNINIT static const std::string kVideoSdpWithUnknonwBrokenFtmp =
    410    "v=0\r\n"
    411    "o=- 4294967296 2 IN IP4 127.0.0.1\r\n"
    412    "s=SIP Call\r\n"
    413    "c=IN IP4 198.51.100.7\r\n"
    414    "t=0 0\r\n"
    415    "m=video 56436 RTP/SAVPF 120\r\n"
    416    "a=rtpmap:120 VP8/90000\r\n"
    417    "a=fmtp:122 unknown=10\n"
    418    "a=rtpmap:122 red/90000\r\n";
    419 
    420 TEST_F(SdpTest, parseUnknownBrokenFtmp) {
    421  ParseSdp(kVideoSdpWithUnknonwBrokenFtmp);
    422 }
    423 
    424 TEST_F(SdpTest, parseRtcpFbKitchenSink) {
    425  ParseSdp(kVideoSdp +
    426           "a=rtcp-fb:120 ack rpsi\r\n"
    427           "a=rtcp-fb:120 ack app\r\n"
    428           "a=rtcp-fb:120 ack app foo\r\n"
    429           "a=rtcp-fb:120 ack foo bar\r\n"
    430           "a=rtcp-fb:120 ack foo bar baz\r\n"
    431           "a=rtcp-fb:120 nack\r\n"
    432           "a=rtcp-fb:120 nack pli\r\n"
    433           "a=rtcp-fb:120 nack sli\r\n"
    434           "a=rtcp-fb:120 nack rpsi\r\n"
    435           "a=rtcp-fb:120 nack app\r\n"
    436           "a=rtcp-fb:120 nack app foo\r\n"
    437           "a=rtcp-fb:120 nack app foo bar\r\n"
    438           "a=rtcp-fb:120 nack foo bar baz\r\n"
    439           "a=rtcp-fb:120 trr-int 0\r\n"
    440           "a=rtcp-fb:120 trr-int 123\r\n"
    441           "a=rtcp-fb:120 goog-remb\r\n"
    442           "a=rtcp-fb:120 ccm fir\r\n"
    443           "a=rtcp-fb:120 ccm tmmbr\r\n"
    444           "a=rtcp-fb:120 ccm tmmbr smaxpr=456\r\n"
    445           "a=rtcp-fb:120 ccm tstr\r\n"
    446           "a=rtcp-fb:120 ccm vbcm 123 456 789\r\n"
    447           "a=rtcp-fb:120 ccm foo\r\n"
    448           "a=rtcp-fb:120 ccm foo bar baz\r\n"
    449           "a=rtcp-fb:120 foo\r\n"
    450           "a=rtcp-fb:120 foo bar\r\n"
    451           "a=rtcp-fb:120 foo bar baz\r\n");
    452 
    453  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 1),
    454            SDP_RTCP_FB_ACK_RPSI);
    455  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 2), SDP_RTCP_FB_ACK_APP);
    456  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 3), SDP_RTCP_FB_ACK_APP);
    457  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 4),
    458            SDP_RTCP_FB_ACK_UNKNOWN);
    459  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 5),
    460            SDP_RTCP_FB_ACK_UNKNOWN);
    461  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 6),
    462            SDP_RTCP_FB_ACK_NOT_FOUND);
    463 
    464  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 1),
    465            SDP_RTCP_FB_NACK_BASIC);
    466  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 2),
    467            SDP_RTCP_FB_NACK_PLI);
    468  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 3),
    469            SDP_RTCP_FB_NACK_SLI);
    470  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 4),
    471            SDP_RTCP_FB_NACK_RPSI);
    472  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 5),
    473            SDP_RTCP_FB_NACK_APP);
    474  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 6),
    475            SDP_RTCP_FB_NACK_APP);
    476  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 7),
    477            SDP_RTCP_FB_NACK_APP);
    478  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 8),
    479            SDP_RTCP_FB_NACK_UNKNOWN);
    480  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 9),
    481            SDP_RTCP_FB_NACK_NOT_FOUND);
    482 
    483  ASSERT_EQ(sdp_attr_get_rtcp_fb_trr_int(sdp_ptr_, 1, 120, 1), 0U);
    484  ASSERT_EQ(sdp_attr_get_rtcp_fb_trr_int(sdp_ptr_, 1, 120, 2), 123U);
    485  ASSERT_EQ(sdp_attr_get_rtcp_fb_trr_int(sdp_ptr_, 1, 120, 3), 0xFFFFFFFF);
    486 
    487  ASSERT_EQ((bool)sdp_attr_get_rtcp_fb_remb_enabled(sdp_ptr_, 1, 120), true);
    488  ASSERT_EQ((bool)sdp_attr_get_rtcp_fb_remb_enabled(sdp_ptr_, 2, 120), false);
    489 
    490  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 1), SDP_RTCP_FB_CCM_FIR);
    491  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 2),
    492            SDP_RTCP_FB_CCM_TMMBR);
    493  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 3),
    494            SDP_RTCP_FB_CCM_TMMBR);
    495  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 4),
    496            SDP_RTCP_FB_CCM_TSTR);
    497  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 5),
    498            SDP_RTCP_FB_CCM_VBCM);
    499  // We don't currently parse out VBCM submessage types, since we don't have
    500  // any use for them.
    501  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 6),
    502            SDP_RTCP_FB_CCM_UNKNOWN);
    503  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 7),
    504            SDP_RTCP_FB_CCM_UNKNOWN);
    505  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 8),
    506            SDP_RTCP_FB_CCM_NOT_FOUND);
    507 }
    508 
    509 TEST_F(SdpTest, addRtcpFbAckRpsi) {
    510  InitLocalSdp();
    511  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    512  AddNewRtcpFbAck(level, SDP_RTCP_FB_ACK_RPSI, 120);
    513  std::string body = SerializeSdp();
    514  ASSERT_NE(body.find("a=rtcp-fb:120 ack rpsi\r\n"), std::string::npos);
    515 }
    516 
    517 TEST_F(SdpTest, addRtcpFbAckRpsiAllPt) {
    518  InitLocalSdp();
    519  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    520  AddNewRtcpFbAck(level, SDP_RTCP_FB_ACK_RPSI);
    521  std::string body = SerializeSdp();
    522  ASSERT_NE(body.find("a=rtcp-fb:* ack rpsi\r\n"), std::string::npos);
    523 }
    524 
    525 TEST_F(SdpTest, addRtcpFbAckApp) {
    526  InitLocalSdp();
    527  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    528  AddNewRtcpFbAck(level, SDP_RTCP_FB_ACK_APP, 120);
    529  std::string body = SerializeSdp();
    530  ASSERT_NE(body.find("a=rtcp-fb:120 ack app\r\n"), std::string::npos);
    531 }
    532 
    533 TEST_F(SdpTest, addRtcpFbAckAppAllPt) {
    534  InitLocalSdp();
    535  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    536  AddNewRtcpFbAck(level, SDP_RTCP_FB_ACK_APP);
    537  std::string body = SerializeSdp();
    538  ASSERT_NE(body.find("a=rtcp-fb:* ack app\r\n"), std::string::npos);
    539 }
    540 
    541 TEST_F(SdpTest, addRtcpFbNack) {
    542  InitLocalSdp();
    543  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    544  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_BASIC, 120);
    545  std::string body = SerializeSdp();
    546  ASSERT_NE(body.find("a=rtcp-fb:120 nack\r\n"), std::string::npos);
    547 }
    548 
    549 TEST_F(SdpTest, addRtcpFbNackAllPt) {
    550  InitLocalSdp();
    551  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    552  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_BASIC);
    553  std::string body = SerializeSdp();
    554  ASSERT_NE(body.find("a=rtcp-fb:* nack\r\n"), std::string::npos);
    555 }
    556 
    557 TEST_F(SdpTest, addRtcpFbNackSli) {
    558  InitLocalSdp();
    559  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    560  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_SLI, 120);
    561  std::string body = SerializeSdp();
    562  ASSERT_NE(body.find("a=rtcp-fb:120 nack sli\r\n"), std::string::npos);
    563 }
    564 
    565 TEST_F(SdpTest, addRtcpFbNackSliAllPt) {
    566  InitLocalSdp();
    567  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    568  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_SLI);
    569  std::string body = SerializeSdp();
    570  ASSERT_NE(body.find("a=rtcp-fb:* nack sli\r\n"), std::string::npos);
    571 }
    572 
    573 TEST_F(SdpTest, addRtcpFbNackPli) {
    574  InitLocalSdp();
    575  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    576  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_PLI, 120);
    577  std::string body = SerializeSdp();
    578  ASSERT_NE(body.find("a=rtcp-fb:120 nack pli\r\n"), std::string::npos);
    579 }
    580 
    581 TEST_F(SdpTest, addRtcpFbNackPliAllPt) {
    582  InitLocalSdp();
    583  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    584  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_PLI);
    585  std::string body = SerializeSdp();
    586  ASSERT_NE(body.find("a=rtcp-fb:* nack pli\r\n"), std::string::npos);
    587 }
    588 
    589 TEST_F(SdpTest, addRtcpFbNackRpsi) {
    590  InitLocalSdp();
    591  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    592  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_RPSI, 120);
    593  std::string body = SerializeSdp();
    594  ASSERT_NE(body.find("a=rtcp-fb:120 nack rpsi\r\n"), std::string::npos);
    595 }
    596 
    597 TEST_F(SdpTest, addRtcpFbNackRpsiAllPt) {
    598  InitLocalSdp();
    599  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    600  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_RPSI);
    601  std::string body = SerializeSdp();
    602  ASSERT_NE(body.find("a=rtcp-fb:* nack rpsi\r\n"), std::string::npos);
    603 }
    604 
    605 TEST_F(SdpTest, addRtcpFbNackApp) {
    606  InitLocalSdp();
    607  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    608  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_APP, 120);
    609  std::string body = SerializeSdp();
    610  ASSERT_NE(body.find("a=rtcp-fb:120 nack app\r\n"), std::string::npos);
    611 }
    612 
    613 TEST_F(SdpTest, addRtcpFbNackAppAllPt) {
    614  InitLocalSdp();
    615  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    616  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_APP);
    617  std::string body = SerializeSdp();
    618  ASSERT_NE(body.find("a=rtcp-fb:* nack app\r\n"), std::string::npos);
    619 }
    620 
    621 TEST_F(SdpTest, addRtcpFbNackRai) {
    622  InitLocalSdp();
    623  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    624  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_RAI, 120);
    625  std::string body = SerializeSdp();
    626  ASSERT_NE(body.find("a=rtcp-fb:120 nack rai\r\n"), std::string::npos);
    627 }
    628 
    629 TEST_F(SdpTest, addRtcpFbNackRaiAllPt) {
    630  InitLocalSdp();
    631  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    632  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_RAI);
    633  std::string body = SerializeSdp();
    634  ASSERT_NE(body.find("a=rtcp-fb:* nack rai\r\n"), std::string::npos);
    635 }
    636 
    637 TEST_F(SdpTest, addRtcpFbNackTllei) {
    638  InitLocalSdp();
    639  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    640  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_TLLEI, 120);
    641  std::string body = SerializeSdp();
    642  ASSERT_NE(body.find("a=rtcp-fb:120 nack tllei\r\n"), std::string::npos);
    643 }
    644 
    645 TEST_F(SdpTest, addRtcpFbNackTlleiAllPt) {
    646  InitLocalSdp();
    647  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    648  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_TLLEI);
    649  std::string body = SerializeSdp();
    650  ASSERT_NE(body.find("a=rtcp-fb:* nack tllei\r\n"), std::string::npos);
    651 }
    652 
    653 TEST_F(SdpTest, addRtcpFbNackPslei) {
    654  InitLocalSdp();
    655  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    656  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_PSLEI, 120);
    657  std::string body = SerializeSdp();
    658  ASSERT_NE(body.find("a=rtcp-fb:120 nack pslei\r\n"), std::string::npos);
    659 }
    660 
    661 TEST_F(SdpTest, addRtcpFbNackPsleiAllPt) {
    662  InitLocalSdp();
    663  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    664  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_PSLEI);
    665  std::string body = SerializeSdp();
    666  ASSERT_NE(body.find("a=rtcp-fb:* nack pslei\r\n"), std::string::npos);
    667 }
    668 
    669 TEST_F(SdpTest, addRtcpFbNackEcn) {
    670  InitLocalSdp();
    671  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    672  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_ECN, 120);
    673  std::string body = SerializeSdp();
    674  ASSERT_NE(body.find("a=rtcp-fb:120 nack ecn\r\n"), std::string::npos);
    675 }
    676 
    677 TEST_F(SdpTest, addRtcpFbNackEcnAllPt) {
    678  InitLocalSdp();
    679  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    680  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_ECN);
    681  std::string body = SerializeSdp();
    682  ASSERT_NE(body.find("a=rtcp-fb:* nack ecn\r\n"), std::string::npos);
    683 }
    684 
    685 TEST_F(SdpTest, addRtcpFbRemb) {
    686  InitLocalSdp();
    687  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    688  AddNewRtcpFbRemb(level, 120);
    689  std::string body = SerializeSdp();
    690  ASSERT_NE(body.find("a=rtcp-fb:120 goog-remb\r\n"), std::string::npos);
    691 }
    692 
    693 TEST_F(SdpTest, addRtcpFbRembAllPt) {
    694  InitLocalSdp();
    695  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    696  AddNewRtcpFbRemb(level);
    697  std::string body = SerializeSdp();
    698  ASSERT_NE(body.find("a=rtcp-fb:* goog-remb\r\n"), std::string::npos);
    699 }
    700 
    701 TEST_F(SdpTest, addRtcpFbTrrInt) {
    702  InitLocalSdp();
    703  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    704  AddNewRtcpFbTrrInt(level, 12345, 120);
    705  std::string body = SerializeSdp();
    706  ASSERT_NE(body.find("a=rtcp-fb:120 trr-int 12345\r\n"), std::string::npos);
    707 }
    708 
    709 TEST_F(SdpTest, addRtcpFbNackTrrIntAllPt) {
    710  InitLocalSdp();
    711  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    712  AddNewRtcpFbTrrInt(level, 0);
    713  std::string body = SerializeSdp();
    714  ASSERT_NE(body.find("a=rtcp-fb:* trr-int 0\r\n"), std::string::npos);
    715 }
    716 
    717 TEST_F(SdpTest, addRtcpFbCcmFir) {
    718  InitLocalSdp();
    719  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    720  AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_FIR, 120);
    721  std::string body = SerializeSdp();
    722  ASSERT_NE(body.find("a=rtcp-fb:120 ccm fir\r\n"), std::string::npos);
    723 }
    724 
    725 TEST_F(SdpTest, addRtcpFbCcmFirAllPt) {
    726  InitLocalSdp();
    727  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    728  AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_FIR);
    729  std::string body = SerializeSdp();
    730  ASSERT_NE(body.find("a=rtcp-fb:* ccm fir\r\n"), std::string::npos);
    731 }
    732 
    733 TEST_F(SdpTest, addRtcpFbCcmTmmbr) {
    734  InitLocalSdp();
    735  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    736  AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_TMMBR, 120);
    737  std::string body = SerializeSdp();
    738  ASSERT_NE(body.find("a=rtcp-fb:120 ccm tmmbr\r\n"), std::string::npos);
    739 }
    740 
    741 TEST_F(SdpTest, addRtcpFbCcmTmmbrAllPt) {
    742  InitLocalSdp();
    743  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    744  AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_TMMBR);
    745  std::string body = SerializeSdp();
    746  ASSERT_NE(body.find("a=rtcp-fb:* ccm tmmbr\r\n"), std::string::npos);
    747 }
    748 
    749 TEST_F(SdpTest, addRtcpFbCcmTstr) {
    750  InitLocalSdp();
    751  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    752  AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_TSTR, 120);
    753  std::string body = SerializeSdp();
    754  ASSERT_NE(body.find("a=rtcp-fb:120 ccm tstr\r\n"), std::string::npos);
    755 }
    756 
    757 TEST_F(SdpTest, addRtcpFbCcmTstrAllPt) {
    758  InitLocalSdp();
    759  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    760  AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_TSTR);
    761  std::string body = SerializeSdp();
    762  ASSERT_NE(body.find("a=rtcp-fb:* ccm tstr\r\n"), std::string::npos);
    763 }
    764 
    765 TEST_F(SdpTest, addRtcpFbCcmVbcm) {
    766  InitLocalSdp();
    767  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    768  AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_VBCM, 120);
    769  std::string body = SerializeSdp();
    770  ASSERT_NE(body.find("a=rtcp-fb:120 ccm vbcm\r\n"), std::string::npos);
    771 }
    772 
    773 TEST_F(SdpTest, addRtcpFbCcmVbcmAllPt) {
    774  InitLocalSdp();
    775  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    776  AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_VBCM);
    777  std::string body = SerializeSdp();
    778  ASSERT_NE(body.find("a=rtcp-fb:* ccm vbcm\r\n"), std::string::npos);
    779 }
    780 
    781 TEST_F(SdpTest, parseRtcpFbAllPayloads) {
    782  ParseSdp(kVideoSdp + "a=rtcp-fb:* ack rpsi\r\n");
    783  for (int i = 0; i < 128; i++) {
    784    ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, i, 1),
    785              SDP_RTCP_FB_ACK_RPSI);
    786  }
    787 }
    788 TEST_F(SdpTest, addExtMap) {
    789  InitLocalSdp();
    790  int level = AddNewMedia(SDP_MEDIA_VIDEO);
    791  AddNewExtMap(level, SDP_EXTMAP_AUDIO_LEVEL);
    792  std::string body = SerializeSdp();
    793  ASSERT_NE(
    794      body.find("a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n"),
    795      std::string::npos);
    796 }
    797 
    798 TEST_F(SdpTest, parseExtMap) {
    799  ParseSdp(kVideoSdp +
    800           "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n");
    801  ASSERT_STREQ(sdp_attr_get_extmap_uri(sdp_ptr_, 1, 1), SDP_EXTMAP_AUDIO_LEVEL);
    802  ASSERT_EQ(sdp_attr_get_extmap_id(sdp_ptr_, 1, 1), 1);
    803 }
    804 
    805 TEST_F(SdpTest, parseFmtpBitrate) {
    806  ParseSdp(kVideoSdp + "a=fmtp:120 bitrate=400\r\n");
    807  ASSERT_EQ(400, sdp_attr_get_fmtp_bitrate_type(sdp_ptr_, 1, 0, 1));
    808 }
    809 
    810 TEST_F(SdpTest, parseFmtpBitrateWith0) {
    811  ParseSdp(kVideoSdp + "a=fmtp:120 bitrate=0\r\n");
    812  ASSERT_EQ(SDP_INVALID_VALUE,
    813            sdp_attr_get_fmtp_bitrate_type(sdp_ptr_, 1, 0, 1));
    814 }
    815 
    816 TEST_F(SdpTest, parseFmtpBitrateWith32001) {
    817  ParseSdp(kVideoSdp + "a=fmtp:120 bitrate=32001\r\n");
    818  ASSERT_EQ(32001, sdp_attr_get_fmtp_bitrate_type(sdp_ptr_, 1, 0, 1));
    819 }
    820 
    821 TEST_F(SdpTest, parseFmtpBitrateWith4294967296) {
    822  ParseSdp(kVideoSdp + "a=fmtp:120 bitrate=4294967296\r\n");
    823  ASSERT_EQ(SDP_INVALID_VALUE,
    824            sdp_attr_get_fmtp_bitrate_type(sdp_ptr_, 1, 0, 1));
    825 }
    826 
    827 TEST_F(SdpTest, parseFmtpMode) {
    828  ParseSdp(kVideoSdp + "a=fmtp:120 mode=200\r\n");
    829  ASSERT_EQ(200U, sdp_attr_get_fmtp_mode_for_payload_type(sdp_ptr_, 1, 0, 120));
    830 }
    831 
    832 TEST_F(SdpTest, parseFmtpModeWith4294967295) {
    833  ParseSdp(kVideoSdp + "a=fmtp:120 mode=4294967295\r\n");
    834  ASSERT_EQ(4294967295,
    835            sdp_attr_get_fmtp_mode_for_payload_type(sdp_ptr_, 1, 0, 120));
    836 }
    837 
    838 TEST_F(SdpTest, parseFmtpModeWith4294967296) {
    839  ParseSdp(kVideoSdp + "a=fmtp:120 mode=4294967296\r\n");
    840  // returns 0 if not found
    841  ASSERT_EQ(0U, sdp_attr_get_fmtp_mode_for_payload_type(sdp_ptr_, 1, 0, 120));
    842 }
    843 
    844 TEST_F(SdpTest, parseFmtpQcif) {
    845  ParseSdp(kVideoSdp + "a=fmtp:120 qcif=20\r\n");
    846  ASSERT_EQ(20, sdp_attr_get_fmtp_qcif(sdp_ptr_, 1, 0, 1));
    847 }
    848 
    849 TEST_F(SdpTest, parseFmtpQcifWith0) {
    850  ParseSdp(kVideoSdp + "a=fmtp:120 qcif=0\r\n");
    851  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_qcif(sdp_ptr_, 1, 0, 1));
    852 }
    853 
    854 TEST_F(SdpTest, parseFmtpQcifWith33) {
    855  ParseSdp(kVideoSdp + "a=fmtp:120 qcif=33\r\n");
    856  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_qcif(sdp_ptr_, 1, 0, 1));
    857 }
    858 
    859 TEST_F(SdpTest, parseFmtpCif) {
    860  ParseSdp(kVideoSdp + "a=fmtp:120 cif=11\r\n");
    861  ASSERT_EQ(11, sdp_attr_get_fmtp_cif(sdp_ptr_, 1, 0, 1));
    862 }
    863 
    864 TEST_F(SdpTest, parseFmtpCifWith0) {
    865  ParseSdp(kVideoSdp + "a=fmtp:120 cif=0\r\n");
    866  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_cif(sdp_ptr_, 1, 0, 1));
    867 }
    868 
    869 TEST_F(SdpTest, parseFmtpCifWith33) {
    870  ParseSdp(kVideoSdp + "a=fmtp:120 cif=33\r\n");
    871  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_cif(sdp_ptr_, 1, 0, 1));
    872 }
    873 
    874 TEST_F(SdpTest, parseFmtpMaxbr) {
    875  ParseSdp(kVideoSdp + "a=fmtp:120 maxbr=21\r\n");
    876  ASSERT_EQ(21, sdp_attr_get_fmtp_maxbr(sdp_ptr_, 1, 0, 1));
    877 }
    878 
    879 TEST_F(SdpTest, parseFmtpMaxbrWith0) {
    880  ParseSdp(kVideoSdp + "a=fmtp:120 maxbr=0\r\n");
    881  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_maxbr(sdp_ptr_, 1, 0, 1));
    882 }
    883 
    884 TEST_F(SdpTest, parseFmtpMaxbrWith65536) {
    885  ParseSdp(kVideoSdp + "a=fmtp:120 maxbr=65536\r\n");
    886  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_maxbr(sdp_ptr_, 1, 0, 1));
    887 }
    888 
    889 TEST_F(SdpTest, parseFmtpSqcif) {
    890  ParseSdp(kVideoSdp + "a=fmtp:120 sqcif=6\r\n");
    891  ASSERT_EQ(6, sdp_attr_get_fmtp_sqcif(sdp_ptr_, 1, 0, 1));
    892 }
    893 
    894 TEST_F(SdpTest, parseFmtpSqcifWith0) {
    895  ParseSdp(kVideoSdp + "a=fmtp:120 sqcif=0\r\n");
    896  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_sqcif(sdp_ptr_, 1, 0, 1));
    897 }
    898 
    899 TEST_F(SdpTest, parseFmtpSqcifWith33) {
    900  ParseSdp(kVideoSdp + "a=fmtp:120 sqcif=33\r\n");
    901  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_sqcif(sdp_ptr_, 1, 0, 1));
    902 }
    903 
    904 TEST_F(SdpTest, parseFmtpCif4) {
    905  ParseSdp(kVideoSdp + "a=fmtp:120 cif4=11\r\n");
    906  ASSERT_EQ(11, sdp_attr_get_fmtp_cif4(sdp_ptr_, 1, 0, 1));
    907 }
    908 
    909 TEST_F(SdpTest, parseFmtpCif4With0) {
    910  ParseSdp(kVideoSdp + "a=fmtp:120 cif4=0\r\n");
    911  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_cif4(sdp_ptr_, 1, 0, 1));
    912 }
    913 
    914 TEST_F(SdpTest, parseFmtpCif4With33) {
    915  ParseSdp(kVideoSdp + "a=fmtp:120 cif4=33\r\n");
    916  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_cif4(sdp_ptr_, 1, 0, 1));
    917 }
    918 
    919 TEST_F(SdpTest, parseFmtpCif16) {
    920  ParseSdp(kVideoSdp + "a=fmtp:120 cif16=11\r\n");
    921  ASSERT_EQ(11, sdp_attr_get_fmtp_cif16(sdp_ptr_, 1, 0, 1));
    922 }
    923 
    924 TEST_F(SdpTest, parseFmtpCif16With0) {
    925  ParseSdp(kVideoSdp + "a=fmtp:120 cif16=0\r\n");
    926  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_cif16(sdp_ptr_, 1, 0, 1));
    927 }
    928 
    929 TEST_F(SdpTest, parseFmtpCif16With33) {
    930  ParseSdp(kVideoSdp + "a=fmtp:120 cif16=33\r\n");
    931  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_cif16(sdp_ptr_, 1, 0, 1));
    932 }
    933 
    934 TEST_F(SdpTest, parseFmtpBpp) {
    935  ParseSdp(kVideoSdp + "a=fmtp:120 bpp=7\r\n");
    936  ASSERT_EQ(7, sdp_attr_get_fmtp_bpp(sdp_ptr_, 1, 0, 1));
    937 }
    938 
    939 TEST_F(SdpTest, parseFmtpBppWith0) {
    940  ParseSdp(kVideoSdp + "a=fmtp:120 bpp=0\r\n");
    941  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_bpp(sdp_ptr_, 1, 0, 1));
    942 }
    943 
    944 TEST_F(SdpTest, parseFmtpBppWith65536) {
    945  ParseSdp(kVideoSdp + "a=fmtp:120 bpp=65536\r\n");
    946  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_bpp(sdp_ptr_, 1, 0, 1));
    947 }
    948 
    949 TEST_F(SdpTest, parseFmtpHrd) {
    950  ParseSdp(kVideoSdp + "a=fmtp:120 hrd=800\r\n");
    951  ASSERT_EQ(800, sdp_attr_get_fmtp_hrd(sdp_ptr_, 1, 0, 1));
    952 }
    953 
    954 TEST_F(SdpTest, parseFmtpHrdWith0) {
    955  ParseSdp(kVideoSdp + "a=fmtp:120 hrd=0\r\n");
    956  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_hrd(sdp_ptr_, 1, 0, 1));
    957 }
    958 
    959 TEST_F(SdpTest, parseFmtpHrdWith65536) {
    960  ParseSdp(kVideoSdp + "a=fmtp:120 hrd=65536\r\n");
    961  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_hrd(sdp_ptr_, 1, 0, 1));
    962 }
    963 
    964 TEST_F(SdpTest, parseFmtpProfile) {
    965  ParseSdp(kVideoSdp + "a=fmtp:120 profile=4\r\n");
    966  ASSERT_EQ(4, sdp_attr_get_fmtp_profile(sdp_ptr_, 1, 0, 1));
    967 }
    968 
    969 TEST_F(SdpTest, parseFmtpProfileWith11) {
    970  ParseSdp(kVideoSdp + "a=fmtp:120 profile=11\r\n");
    971  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_profile(sdp_ptr_, 1, 0, 1));
    972 }
    973 
    974 TEST_F(SdpTest, parseFmtpLevel) {
    975  ParseSdp(kVideoSdp + "a=fmtp:120 level=56\r\n");
    976  ASSERT_EQ(56, sdp_attr_get_fmtp_level(sdp_ptr_, 1, 0, 1));
    977 }
    978 
    979 TEST_F(SdpTest, parseFmtpLevelWith101) {
    980  ParseSdp(kVideoSdp + "a=fmtp:120 level=101\r\n");
    981  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_level(sdp_ptr_, 1, 0, 1));
    982 }
    983 
    984 TEST_F(SdpTest, parseFmtpPacketizationMode) {
    985  ParseSdp(kVideoSdp + "a=fmtp:120 packetization-mode=1\r\n");
    986  uint16_t packetizationMode;
    987  ASSERT_EQ(SDP_SUCCESS,
    988            sdp_attr_get_fmtp_pack_mode(sdp_ptr_, 1, 0, 1, &packetizationMode));
    989  ASSERT_EQ(1, packetizationMode);
    990 }
    991 
    992 TEST_F(SdpTest, parseFmtpPacketizationModeWith3) {
    993  ParseSdp(kVideoSdp + "a=fmtp:120 packetization-mode=3\r\n");
    994  ASSERT_EQ(SDP_INVALID_PARAMETER,
    995            sdp_attr_get_fmtp_pack_mode(sdp_ptr_, 1, 0, 1, nullptr));
    996 }
    997 
    998 TEST_F(SdpTest, parseFmtpInterleavingDepth) {
    999  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-interleaving-depth=566\r\n");
   1000  uint16_t interleavingDepth;
   1001  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_interleaving_depth(
   1002                             sdp_ptr_, 1, 0, 1, &interleavingDepth));
   1003  ASSERT_EQ(566, interleavingDepth);
   1004 }
   1005 
   1006 TEST_F(SdpTest, parseFmtpInterleavingDepthWith0) {
   1007  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-interleaving-depth=0\r\n");
   1008  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1009            sdp_attr_get_fmtp_interleaving_depth(sdp_ptr_, 1, 0, 1, nullptr));
   1010 }
   1011 
   1012 TEST_F(SdpTest, parseFmtpInterleavingDepthWith65536) {
   1013  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-interleaving-depth=65536\r\n");
   1014  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1015            sdp_attr_get_fmtp_interleaving_depth(sdp_ptr_, 1, 0, 1, nullptr));
   1016 }
   1017 
   1018 TEST_F(SdpTest, parseFmtpDeintBuf) {
   1019  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-deint-buf-req=4294967295\r\n");
   1020  uint32_t deintBuf;
   1021  ASSERT_EQ(SDP_SUCCESS,
   1022            sdp_attr_get_fmtp_deint_buf_req(sdp_ptr_, 1, 0, 1, &deintBuf));
   1023  ASSERT_EQ(4294967295, deintBuf);
   1024 }
   1025 
   1026 TEST_F(SdpTest, parseFmtpDeintBufWith0) {
   1027  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-deint-buf-req=0\r\n");
   1028  uint32_t deintBuf;
   1029  ASSERT_EQ(SDP_SUCCESS,
   1030            sdp_attr_get_fmtp_deint_buf_req(sdp_ptr_, 1, 0, 1, &deintBuf));
   1031  ASSERT_EQ(0U, deintBuf);
   1032 }
   1033 
   1034 TEST_F(SdpTest, parseFmtpDeintBufWith4294967296) {
   1035  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-deint-buf-req=4294967296\r\n");
   1036  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1037            sdp_attr_get_fmtp_deint_buf_req(sdp_ptr_, 1, 0, 1, nullptr));
   1038 }
   1039 
   1040 TEST_F(SdpTest, parseFmtpMaxDonDiff) {
   1041  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-max-don-diff=5678\r\n");
   1042  uint32_t maxDonDiff;
   1043  ASSERT_EQ(SDP_SUCCESS,
   1044            sdp_attr_get_fmtp_max_don_diff(sdp_ptr_, 1, 0, 1, &maxDonDiff));
   1045  ASSERT_EQ(5678U, maxDonDiff);
   1046 }
   1047 
   1048 TEST_F(SdpTest, parseFmtpMaxDonDiffWith0) {
   1049  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-max-don-diff=0\r\n");
   1050  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1051            sdp_attr_get_fmtp_max_don_diff(sdp_ptr_, 1, 0, 1, nullptr));
   1052 }
   1053 
   1054 TEST_F(SdpTest, parseFmtpMaxDonDiffWith4294967296) {
   1055  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-max-don-diff=4294967296\r\n");
   1056  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1057            sdp_attr_get_fmtp_max_don_diff(sdp_ptr_, 1, 0, 1, nullptr));
   1058 }
   1059 
   1060 TEST_F(SdpTest, parseFmtpInitBufTime) {
   1061  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-init-buf-time=4294967295\r\n");
   1062  uint32_t initBufTime;
   1063  ASSERT_EQ(SDP_SUCCESS,
   1064            sdp_attr_get_fmtp_init_buf_time(sdp_ptr_, 1, 0, 1, &initBufTime));
   1065  ASSERT_EQ(4294967295, initBufTime);
   1066 }
   1067 
   1068 TEST_F(SdpTest, parseFmtpInitBufTimeWith0) {
   1069  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-init-buf-time=0\r\n");
   1070  uint32_t initBufTime;
   1071  ASSERT_EQ(SDP_SUCCESS,
   1072            sdp_attr_get_fmtp_init_buf_time(sdp_ptr_, 1, 0, 1, &initBufTime));
   1073  ASSERT_EQ(0U, initBufTime);
   1074 }
   1075 
   1076 TEST_F(SdpTest, parseFmtpInitBufTimeWith4294967296) {
   1077  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-init-buf-time=4294967296\r\n");
   1078  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1079            sdp_attr_get_fmtp_init_buf_time(sdp_ptr_, 1, 0, 1, nullptr));
   1080 }
   1081 
   1082 TEST_F(SdpTest, parseFmtpMaxMbps) {
   1083  ParseSdp(kVideoSdp + "a=fmtp:120 max-mbps=46789\r\n");
   1084  uint32_t maxMpbs;
   1085  ASSERT_EQ(SDP_SUCCESS,
   1086            sdp_attr_get_fmtp_max_mbps(sdp_ptr_, 1, 0, 1, &maxMpbs));
   1087  ASSERT_EQ(46789U, maxMpbs);
   1088 }
   1089 
   1090 TEST_F(SdpTest, parseFmtpMaxMbpsWith0) {
   1091  ParseSdp(kVideoSdp + "a=fmtp:120 max-mbps=0\r\n");
   1092  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1093            sdp_attr_get_fmtp_max_mbps(sdp_ptr_, 1, 0, 1, nullptr));
   1094 }
   1095 
   1096 TEST_F(SdpTest, parseFmtpMaxMbpsWith4294967296) {
   1097  ParseSdp(kVideoSdp + "a=fmtp:120 max-mbps=4294967296\r\n");
   1098  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1099            sdp_attr_get_fmtp_max_mbps(sdp_ptr_, 1, 0, 1, nullptr));
   1100 }
   1101 
   1102 TEST_F(SdpTest, parseFmtpMaxCpb) {
   1103  ParseSdp(kVideoSdp + "a=fmtp:120 max-cpb=47891\r\n");
   1104  uint32_t maxCpb;
   1105  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_max_cpb(sdp_ptr_, 1, 0, 1, &maxCpb));
   1106  ASSERT_EQ(47891U, maxCpb);
   1107 }
   1108 
   1109 TEST_F(SdpTest, parseFmtpMaxCpbWith0) {
   1110  ParseSdp(kVideoSdp + "a=fmtp:120 max-cpb=0\r\n");
   1111  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1112            sdp_attr_get_fmtp_max_cpb(sdp_ptr_, 1, 0, 1, nullptr));
   1113 }
   1114 
   1115 TEST_F(SdpTest, parseFmtpMaxCpbWith4294967296) {
   1116  ParseSdp(kVideoSdp + "a=fmtp:120 max-cpb=4294967296\r\n");
   1117  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1118            sdp_attr_get_fmtp_max_cpb(sdp_ptr_, 1, 0, 1, nullptr));
   1119 }
   1120 
   1121 TEST_F(SdpTest, parseFmtpMaxDpb) {
   1122  ParseSdp(kVideoSdp + "a=fmtp:120 max-dpb=47892\r\n");
   1123  uint32_t maxDpb;
   1124  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_max_dpb(sdp_ptr_, 1, 0, 1, &maxDpb));
   1125  ASSERT_EQ(47892U, maxDpb);
   1126 }
   1127 
   1128 TEST_F(SdpTest, parseFmtpMaxDpbWith0) {
   1129  ParseSdp(kVideoSdp + "a=fmtp:120 max-dpb=0\r\n");
   1130  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1131            sdp_attr_get_fmtp_max_dpb(sdp_ptr_, 1, 0, 1, nullptr));
   1132 }
   1133 
   1134 TEST_F(SdpTest, parseFmtpMaxDpbWith4294967296) {
   1135  ParseSdp(kVideoSdp + "a=fmtp:120 max-dpb=4294967296\r\n");
   1136  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1137            sdp_attr_get_fmtp_max_dpb(sdp_ptr_, 1, 0, 1, nullptr));
   1138 }
   1139 
   1140 TEST_F(SdpTest, parseFmtpMaxBr) {
   1141  ParseSdp(kVideoSdp + "a=fmtp:120 max-br=47893\r\n");
   1142  uint32_t maxBr;
   1143  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_max_br(sdp_ptr_, 1, 0, 1, &maxBr));
   1144  ASSERT_EQ(47893U, maxBr);
   1145 }
   1146 
   1147 TEST_F(SdpTest, parseFmtpMaxBrWith0) {
   1148  ParseSdp(kVideoSdp + "a=fmtp:120 max-br=0\r\n");
   1149  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1150            sdp_attr_get_fmtp_max_br(sdp_ptr_, 1, 0, 1, nullptr));
   1151 }
   1152 
   1153 TEST_F(SdpTest, parseFmtpMaxBrWith4294967296) {
   1154  ParseSdp(kVideoSdp + "a=fmtp:120 max-br=4294967296\r\n");
   1155  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1156            sdp_attr_get_fmtp_max_br(sdp_ptr_, 1, 0, 1, nullptr));
   1157 }
   1158 
   1159 TEST_F(SdpTest, parseFmtpRedundantPicCap) {
   1160  ParseSdp(kVideoSdp + "a=fmtp:120 redundant-pic-cap=1\r\n");
   1161  ASSERT_EQ(1, sdp_attr_fmtp_is_redundant_pic_cap(sdp_ptr_, 1, 0, 1));
   1162 }
   1163 
   1164 TEST_F(SdpTest, parseFmtpRedundantPicCapWith0) {
   1165  ParseSdp(kVideoSdp + "a=fmtp:120 redundant-pic-cap=0\r\n");
   1166  ASSERT_EQ(0, sdp_attr_fmtp_is_redundant_pic_cap(sdp_ptr_, 1, 0, 1));
   1167 }
   1168 
   1169 TEST_F(SdpTest, parseFmtpRedundantPicCapWith2) {
   1170  ParseSdp(kVideoSdp + "a=fmtp:120 redundant-pic-cap=2\r\n");
   1171  ASSERT_EQ(0, sdp_attr_fmtp_is_redundant_pic_cap(sdp_ptr_, 1, 0, 1));
   1172 }
   1173 
   1174 TEST_F(SdpTest, parseFmtpDeintBufCap) {
   1175  ParseSdp(kVideoSdp + "a=fmtp:120 deint-buf-cap=4294967295\r\n");
   1176  uint32_t deintBufCap;
   1177  ASSERT_EQ(SDP_SUCCESS,
   1178            sdp_attr_get_fmtp_deint_buf_cap(sdp_ptr_, 1, 0, 1, &deintBufCap));
   1179  ASSERT_EQ(4294967295, deintBufCap);
   1180 }
   1181 
   1182 TEST_F(SdpTest, parseFmtpDeintBufCapWith0) {
   1183  ParseSdp(kVideoSdp + "a=fmtp:120 deint-buf-cap=0\r\n");
   1184  uint32_t deintBufCap;
   1185  ASSERT_EQ(SDP_SUCCESS,
   1186            sdp_attr_get_fmtp_deint_buf_cap(sdp_ptr_, 1, 0, 1, &deintBufCap));
   1187  ASSERT_EQ(0U, deintBufCap);
   1188 }
   1189 
   1190 TEST_F(SdpTest, parseFmtpDeintBufCapWith4294967296) {
   1191  ParseSdp(kVideoSdp + "a=fmtp:120 deint-buf-cap=4294967296\r\n");
   1192  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1193            sdp_attr_get_fmtp_deint_buf_cap(sdp_ptr_, 1, 0, 1, nullptr));
   1194 }
   1195 
   1196 TEST_F(SdpTest, parseFmtpMaxRcmdNaluSize) {
   1197  ParseSdp(kVideoSdp + "a=fmtp:120 max-rcmd-nalu-size=4294967295\r\n");
   1198  uint32_t maxRcmdNaluSize;
   1199  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_max_rcmd_nalu_size(
   1200                             sdp_ptr_, 1, 0, 1, &maxRcmdNaluSize));
   1201  ASSERT_EQ(4294967295, maxRcmdNaluSize);
   1202 }
   1203 
   1204 TEST_F(SdpTest, parseFmtpMaxRcmdNaluSizeWith0) {
   1205  ParseSdp(kVideoSdp + "a=fmtp:120 max-rcmd-nalu-size=0\r\n");
   1206  uint32_t maxRcmdNaluSize;
   1207  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_max_rcmd_nalu_size(
   1208                             sdp_ptr_, 1, 0, 1, &maxRcmdNaluSize));
   1209  ASSERT_EQ(0U, maxRcmdNaluSize);
   1210 }
   1211 
   1212 TEST_F(SdpTest, parseFmtpMaxRcmdNaluSizeWith4294967296) {
   1213  ParseSdp(kVideoSdp + "a=fmtp:120 max-rcmd-nalu-size=4294967296\r\n");
   1214  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1215            sdp_attr_get_fmtp_max_rcmd_nalu_size(sdp_ptr_, 1, 0, 1, nullptr));
   1216 }
   1217 
   1218 TEST_F(SdpTest, parseFmtpParameterAdd) {
   1219  ParseSdp(kVideoSdp + "a=fmtp:120 parameter-add=1\r\n");
   1220  ASSERT_EQ(1, sdp_attr_fmtp_is_parameter_add(sdp_ptr_, 1, 0, 1));
   1221 }
   1222 
   1223 TEST_F(SdpTest, parseFmtpParameterAddWith0) {
   1224  ParseSdp(kVideoSdp + "a=fmtp:120 parameter-add=0\r\n");
   1225  ASSERT_EQ(0, sdp_attr_fmtp_is_parameter_add(sdp_ptr_, 1, 0, 1));
   1226 }
   1227 
   1228 TEST_F(SdpTest, parseFmtpParameterAddWith2) {
   1229  ParseSdp(kVideoSdp + "a=fmtp:120 parameter-add=2\r\n");
   1230  ASSERT_EQ(0, sdp_attr_fmtp_is_parameter_add(sdp_ptr_, 1, 0, 1));
   1231 }
   1232 
   1233 TEST_F(SdpTest, parseFmtpAnnexK) {
   1234  ParseSdp(kVideoSdp + "a=fmtp:120 K=566\r\n");
   1235  ASSERT_EQ(566, sdp_attr_get_fmtp_annex_k_val(sdp_ptr_, 1, 0, 1));
   1236 }
   1237 
   1238 TEST_F(SdpTest, parseFmtpAnnexKWith0) {
   1239  ParseSdp(kVideoSdp + "a=fmtp:120 K=0\r\n");
   1240  ASSERT_EQ(SDP_INVALID_VALUE,
   1241            sdp_attr_get_fmtp_annex_k_val(sdp_ptr_, 1, 0, 1));
   1242 }
   1243 
   1244 TEST_F(SdpTest, parseFmtpAnnexKWith65536) {
   1245  ParseSdp(kVideoSdp + "a=fmtp:120 K=65536\r\n");
   1246  ASSERT_EQ(SDP_INVALID_VALUE,
   1247            sdp_attr_get_fmtp_annex_k_val(sdp_ptr_, 1, 0, 1));
   1248 }
   1249 
   1250 TEST_F(SdpTest, parseFmtpAnnexN) {
   1251  ParseSdp(kVideoSdp + "a=fmtp:120 N=4567\r\n");
   1252  ASSERT_EQ(4567, sdp_attr_get_fmtp_annex_n_val(sdp_ptr_, 1, 0, 1));
   1253 }
   1254 
   1255 TEST_F(SdpTest, parseFmtpAnnexNWith0) {
   1256  ParseSdp(kVideoSdp + "a=fmtp:120 N=0\r\n");
   1257  ASSERT_EQ(SDP_INVALID_VALUE,
   1258            sdp_attr_get_fmtp_annex_n_val(sdp_ptr_, 1, 0, 1));
   1259 }
   1260 
   1261 TEST_F(SdpTest, parseFmtpAnnexNWith65536) {
   1262  ParseSdp(kVideoSdp + "a=fmtp:120 N=65536\r\n");
   1263  ASSERT_EQ(SDP_INVALID_VALUE,
   1264            sdp_attr_get_fmtp_annex_n_val(sdp_ptr_, 1, 0, 1));
   1265 }
   1266 
   1267 TEST_F(SdpTest, parseFmtpAnnexP) {
   1268  ParseSdp(kVideoSdp + "a=fmtp:120 P=5678,2\r\n");
   1269  ASSERT_EQ(5678, sdp_attr_get_fmtp_annex_p_picture_resize(sdp_ptr_, 1, 0, 1));
   1270  ASSERT_EQ(2, sdp_attr_get_fmtp_annex_p_warp(sdp_ptr_, 1, 0, 1));
   1271 }
   1272 
   1273 TEST_F(SdpTest, parseFmtpAnnexPWithResize0) {
   1274  ParseSdp(kVideoSdp + "a=fmtp:120 P=0,3\r\n");
   1275  ASSERT_EQ(0, sdp_attr_get_fmtp_annex_p_picture_resize(sdp_ptr_, 1, 0, 1));
   1276  ASSERT_EQ(3, sdp_attr_get_fmtp_annex_p_warp(sdp_ptr_, 1, 0, 1));
   1277 }
   1278 
   1279 TEST_F(SdpTest, parseFmtpAnnexPWithResize65536) {
   1280  ParseSdp(kVideoSdp + "a=fmtp:120 P=65536,4\r\n");
   1281  ASSERT_EQ(0, sdp_attr_get_fmtp_annex_p_picture_resize(sdp_ptr_, 1, 0, 1));
   1282  // if the first fails, the second will too.  Both default to 0 on failure.
   1283  ASSERT_EQ(0, sdp_attr_get_fmtp_annex_p_warp(sdp_ptr_, 1, 0, 1));
   1284 }
   1285 
   1286 TEST_F(SdpTest, parseFmtpAnnexPWithWarp65536) {
   1287  ParseSdp(kVideoSdp + "a=fmtp:120 P=346,65536\r\n");
   1288  ASSERT_EQ(346, sdp_attr_get_fmtp_annex_p_picture_resize(sdp_ptr_, 1, 0, 1));
   1289  ASSERT_EQ(0, sdp_attr_get_fmtp_annex_p_warp(sdp_ptr_, 1, 0, 1));
   1290 }
   1291 
   1292 TEST_F(SdpTest, parseFmtpLevelAsymmetryAllowed) {
   1293  ParseSdp(kVideoSdp + "a=fmtp:120 level-asymmetry-allowed=1\r\n");
   1294 
   1295  uint16_t levelAsymmetryAllowed;
   1296  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_level_asymmetry_allowed(
   1297                             sdp_ptr_, 1, 0, 1, &levelAsymmetryAllowed));
   1298  ASSERT_EQ(1U, levelAsymmetryAllowed);
   1299 }
   1300 
   1301 TEST_F(SdpTest, parseFmtpLevelAsymmetryAllowedWith0) {
   1302  ParseSdp(kVideoSdp + "a=fmtp:120 level-asymmetry-allowed=0\r\n");
   1303  uint16_t levelAsymmetryAllowed;
   1304  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_level_asymmetry_allowed(
   1305                             sdp_ptr_, 1, 0, 1, &levelAsymmetryAllowed));
   1306  ASSERT_EQ(0U, levelAsymmetryAllowed);
   1307 }
   1308 
   1309 TEST_F(SdpTest, parseFmtpLevelAsymmetryAllowedWith2) {
   1310  ParseSdp(kVideoSdp + "a=fmtp:120 level-asymmetry-allowed=2\r\n");
   1311  ASSERT_EQ(SDP_INVALID_PARAMETER, sdp_attr_get_fmtp_level_asymmetry_allowed(
   1312                                       sdp_ptr_, 1, 0, 1, nullptr));
   1313 }
   1314 
   1315 TEST_F(SdpTest, parseFmtpMaxAverageBitrate) {
   1316  ParseSdp(kVideoSdp + "a=fmtp:120 maxaveragebitrate=47893\r\n");
   1317  uint32_t maxAverageBitrate;
   1318  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_max_average_bitrate(
   1319                             sdp_ptr_, 1, 0, 1, &maxAverageBitrate));
   1320  ASSERT_EQ(47893U, maxAverageBitrate);
   1321 }
   1322 
   1323 TEST_F(SdpTest, parseFmtpMaxAverageBitrateWith0) {
   1324  ParseSdp(kVideoSdp + "a=fmtp:120 maxaveragebitrate=0\r\n");
   1325  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1326            sdp_attr_get_fmtp_max_average_bitrate(sdp_ptr_, 1, 0, 1, nullptr));
   1327 }
   1328 
   1329 TEST_F(SdpTest, parseFmtpMaxAverageBitrateWith4294967296) {
   1330  ParseSdp(kVideoSdp + "a=fmtp:120 maxaveragebitrate=4294967296\r\n");
   1331  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1332            sdp_attr_get_fmtp_max_average_bitrate(sdp_ptr_, 1, 0, 1, nullptr));
   1333 }
   1334 
   1335 TEST_F(SdpTest, parseFmtpUsedTx) {
   1336  ParseSdp(kVideoSdp + "a=fmtp:120 usedtx=1\r\n");
   1337  tinybool usedTx;
   1338  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_usedtx(sdp_ptr_, 1, 0, 1, &usedTx));
   1339  ASSERT_EQ(1, usedTx);
   1340 }
   1341 
   1342 TEST_F(SdpTest, parseFmtpUsedTxWith0) {
   1343  ParseSdp(kVideoSdp + "a=fmtp:120 usedtx=0\r\n");
   1344  tinybool usedTx;
   1345  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_usedtx(sdp_ptr_, 1, 0, 1, &usedTx));
   1346  ASSERT_EQ(0, usedTx);
   1347 }
   1348 
   1349 TEST_F(SdpTest, parseFmtpUsedTxWith2) {
   1350  ParseSdp(kVideoSdp + "a=fmtp:120 usedtx=2\r\n");
   1351  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1352            sdp_attr_get_fmtp_usedtx(sdp_ptr_, 1, 0, 1, nullptr));
   1353 }
   1354 
   1355 TEST_F(SdpTest, parseFmtpStereo) {
   1356  ParseSdp(kVideoSdp + "a=fmtp:120 stereo=1\r\n");
   1357  tinybool stereo;
   1358  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_stereo(sdp_ptr_, 1, 0, 1, &stereo));
   1359  ASSERT_EQ(1, stereo);
   1360 }
   1361 
   1362 TEST_F(SdpTest, parseFmtpStereoWith0) {
   1363  ParseSdp(kVideoSdp + "a=fmtp:120 stereo=0\r\n");
   1364  tinybool stereo;
   1365  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_stereo(sdp_ptr_, 1, 0, 1, &stereo));
   1366  ASSERT_EQ(0, stereo);
   1367 }
   1368 
   1369 TEST_F(SdpTest, parseFmtpStereoWith2) {
   1370  ParseSdp(kVideoSdp + "a=fmtp:120 stereo=2\r\n");
   1371  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1372            sdp_attr_get_fmtp_stereo(sdp_ptr_, 1, 0, 1, nullptr));
   1373 }
   1374 
   1375 TEST_F(SdpTest, parseFmtpUseInBandFec) {
   1376  ParseSdp(kVideoSdp + "a=fmtp:120 useinbandfec=1\r\n");
   1377  tinybool useInbandFec;
   1378  ASSERT_EQ(SDP_SUCCESS,
   1379            sdp_attr_get_fmtp_useinbandfec(sdp_ptr_, 1, 0, 1, &useInbandFec));
   1380  ASSERT_EQ(1, useInbandFec);
   1381 }
   1382 
   1383 TEST_F(SdpTest, parseFmtpUseInBandWith0) {
   1384  ParseSdp(kVideoSdp + "a=fmtp:120 useinbandfec=0\r\n");
   1385  tinybool useInbandFec;
   1386  ASSERT_EQ(SDP_SUCCESS,
   1387            sdp_attr_get_fmtp_useinbandfec(sdp_ptr_, 1, 0, 1, &useInbandFec));
   1388  ASSERT_EQ(0, useInbandFec);
   1389 }
   1390 
   1391 TEST_F(SdpTest, parseFmtpUseInBandWith2) {
   1392  ParseSdp(kVideoSdp + "a=fmtp:120 useinbandfec=2\r\n");
   1393  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1394            sdp_attr_get_fmtp_useinbandfec(sdp_ptr_, 1, 0, 1, nullptr));
   1395 }
   1396 
   1397 TEST_F(SdpTest, parseFmtpMaxCodedAudioBandwidth) {
   1398  ParseSdp(kVideoSdp + "a=fmtp:120 maxcodedaudiobandwidth=abcdefg\r\n");
   1399  char* maxCodedAudioBandwith =
   1400      sdp_attr_get_fmtp_maxcodedaudiobandwidth(sdp_ptr_, 1, 0, 1);
   1401  ASSERT_EQ(0, strcmp("abcdefg", maxCodedAudioBandwith));
   1402 }
   1403 
   1404 TEST_F(SdpTest, parseFmtpMaxCodedAudioBandwidthBad) {
   1405  ParseSdp(kVideoSdp + "a=fmtp:120 maxcodedaudiobandwidth=\r\n");
   1406  char* maxCodedAudioBandwith =
   1407      sdp_attr_get_fmtp_maxcodedaudiobandwidth(sdp_ptr_, 1, 0, 1);
   1408  ASSERT_EQ(0, *maxCodedAudioBandwith);
   1409 }
   1410 
   1411 TEST_F(SdpTest, parseFmtpCbr) {
   1412  ParseSdp(kVideoSdp + "a=fmtp:120 cbr=1\r\n");
   1413  tinybool cbr;
   1414  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_cbr(sdp_ptr_, 1, 0, 1, &cbr));
   1415  ASSERT_EQ(1, cbr);
   1416 }
   1417 
   1418 TEST_F(SdpTest, parseFmtpCbrWith0) {
   1419  ParseSdp(kVideoSdp + "a=fmtp:120 cbr=0\r\n");
   1420  tinybool cbr;
   1421  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_cbr(sdp_ptr_, 1, 0, 1, &cbr));
   1422  ASSERT_EQ(0, cbr);
   1423 }
   1424 
   1425 TEST_F(SdpTest, parseFmtpCbrWith2) {
   1426  ParseSdp(kVideoSdp + "a=fmtp:120 cbr=2\r\n");
   1427  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1428            sdp_attr_get_fmtp_cbr(sdp_ptr_, 1, 0, 1, nullptr));
   1429 }
   1430 
   1431 TEST_F(SdpTest, parseFmtpMaxPlaybackRate) {
   1432  ParseSdp(kVideoSdp + "a=fmtp:120 maxplaybackrate=47900\r\n");
   1433  sdp_attr_t* attr_p = sdp_find_attr(sdp_ptr_, 1, 0, SDP_ATTR_FMTP, 1);
   1434  ASSERT_NE(nullptr, attr_p);
   1435  ASSERT_EQ(47900U, attr_p->attr.fmtp.maxplaybackrate);
   1436 }
   1437 
   1438 TEST_F(SdpTest, parseFmtpMaxPlaybackRateWith0) {
   1439  ParseSdp(kVideoSdp + "a=fmtp:120 maxplaybackrate=0\r\n");
   1440  sdp_attr_t* attr_p = sdp_find_attr(sdp_ptr_, 1, 0, SDP_ATTR_FMTP, 1);
   1441  ASSERT_EQ(NULL, attr_p);
   1442 }
   1443 
   1444 TEST_F(SdpTest, parseFmtpMaxPlaybackRateWith4294967296) {
   1445  ParseSdp(kVideoSdp + "a=fmtp:120 maxplaybackrate=4294967296\r\n");
   1446  sdp_attr_t* attr_p = sdp_find_attr(sdp_ptr_, 1, 0, SDP_ATTR_FMTP, 1);
   1447  ASSERT_EQ(NULL, attr_p);
   1448 }
   1449 
   1450 TEST_F(SdpTest, parseFmtpMaxFs) {
   1451  uint32_t val = 0;
   1452  ParseSdp(kVideoSdp + "a=fmtp:120 max-fs=300;max-fr=30\r\n");
   1453  ASSERT_EQ(sdp_attr_get_fmtp_max_fs(sdp_ptr_, 1, 0, 1, &val), SDP_SUCCESS);
   1454  ASSERT_EQ(val, 300U);
   1455 }
   1456 TEST_F(SdpTest, parseFmtpMaxFsWith0) {
   1457  ParseSdp(kVideoSdp + "a=fmtp:120 max-fs=0\r\n");
   1458  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1459            sdp_attr_get_fmtp_max_fs(sdp_ptr_, 1, 0, 1, nullptr));
   1460 }
   1461 
   1462 TEST_F(SdpTest, parseFmtpMaxFsWith4294967296) {
   1463  ParseSdp(kVideoSdp + "a=fmtp:120 max-fs=4294967296\r\n");
   1464  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1465            sdp_attr_get_fmtp_max_fs(sdp_ptr_, 1, 0, 1, nullptr));
   1466 }
   1467 
   1468 TEST_F(SdpTest, parseFmtpMaxFr) {
   1469  uint32_t val = 0;
   1470  ParseSdp(kVideoSdp + "a=fmtp:120 max-fs=300;max-fr=30\r\n");
   1471  ASSERT_EQ(sdp_attr_get_fmtp_max_fr(sdp_ptr_, 1, 0, 1, &val), SDP_SUCCESS);
   1472  ASSERT_EQ(val, 30U);
   1473 }
   1474 
   1475 TEST_F(SdpTest, parseFmtpMaxFrWith0) {
   1476  ParseSdp(kVideoSdp + "a=fmtp:120 max-fr=0\r\n");
   1477  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1478            sdp_attr_get_fmtp_max_fr(sdp_ptr_, 1, 0, 1, nullptr));
   1479 }
   1480 
   1481 TEST_F(SdpTest, parseFmtpMaxFrWith4294967296) {
   1482  ParseSdp(kVideoSdp + "a=fmtp:120 max-fr=4294967296\r\n");
   1483  ASSERT_EQ(SDP_INVALID_PARAMETER,
   1484            sdp_attr_get_fmtp_max_fr(sdp_ptr_, 1, 0, 1, nullptr));
   1485 }
   1486 
   1487 TEST_F(SdpTest, addFmtpMaxFs) {
   1488  InitLocalSdp();
   1489  int level = AddNewMedia(SDP_MEDIA_VIDEO);
   1490  AddNewFmtpMaxFs(level, 300);
   1491  std::string body = SerializeSdp();
   1492  ASSERT_NE(body.find("a=fmtp:120 max-fs=300\r\n"), std::string::npos);
   1493 }
   1494 
   1495 TEST_F(SdpTest, addFmtpMaxFr) {
   1496  InitLocalSdp();
   1497  int level = AddNewMedia(SDP_MEDIA_VIDEO);
   1498  AddNewFmtpMaxFr(level, 30);
   1499  std::string body = SerializeSdp();
   1500  ASSERT_NE(body.find("a=fmtp:120 max-fr=30\r\n"), std::string::npos);
   1501 }
   1502 
   1503 TEST_F(SdpTest, addFmtpMaxFsFr) {
   1504  InitLocalSdp();
   1505  int level = AddNewMedia(SDP_MEDIA_VIDEO);
   1506  AddNewFmtpMaxFsFr(level, 300, 30);
   1507  std::string body = SerializeSdp();
   1508  ASSERT_NE(body.find("a=fmtp:120 max-fs=300;max-fr=30\r\n"),
   1509            std::string::npos);
   1510 }
   1511 
   1512 MOZ_RUNINIT static const std::string kBrokenFmtp =
   1513    "v=0\r\n"
   1514    "o=- 4294967296 2 IN IP4 127.0.0.1\r\n"
   1515    "s=SIP Call\r\n"
   1516    "t=0 0\r\n"
   1517    "m=video 56436 RTP/SAVPF 120\r\n"
   1518    "c=IN IP4 198.51.100.7\r\n"
   1519    "a=rtpmap:120 VP8/90000\r\n"
   1520    /* Note: the \0 in this string triggered bz://1089207
   1521     */
   1522    "a=fmtp:120 max-fs=300;max\0fr=30";
   1523 
   1524 TEST_F(SdpTest, parseBrokenFmtp) {
   1525  uint32_t val = 0;
   1526  const char* buf = kBrokenFmtp.data();
   1527  ResetSdp();
   1528  /* We need to manually invoke the parser here to be able to specify the length
   1529   * of the string beyond the \0 in last line of the string.
   1530   */
   1531  ASSERT_EQ(sdp_parse(sdp_ptr_, buf, 165), SDP_SUCCESS);
   1532  ASSERT_EQ(sdp_attr_get_fmtp_max_fs(sdp_ptr_, 1, 0, 1, &val),
   1533            SDP_INVALID_PARAMETER);
   1534 }
   1535 
   1536 TEST_F(SdpTest, addIceLite) {
   1537  InitLocalSdp();
   1538  uint16_t inst_num = 0;
   1539  EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, SDP_SESSION_LEVEL, 0, SDP_ATTR_ICE_LITE,
   1540                             &inst_num),
   1541            SDP_SUCCESS);
   1542  std::string body = SerializeSdp();
   1543  ASSERT_NE(body.find("a=ice-lite\r\n"), std::string::npos);
   1544 }
   1545 
   1546 TEST_F(SdpTest, parseIceLite) {
   1547  std::string sdp =
   1548      "v=0\r\n"
   1549      "o=- 4294967296 2 IN IP4 127.0.0.1\r\n"
   1550      "s=SIP Call\r\n"
   1551      "t=0 0\r\n"
   1552      "a=ice-lite\r\n";
   1553  ParseSdp(sdp);
   1554  ASSERT_TRUE(
   1555      sdp_attr_is_present(sdp_ptr_, SDP_ATTR_ICE_LITE, SDP_SESSION_LEVEL, 0));
   1556 }
   1557 
   1558 TEST_F(SdpTest, parseExtmapAllowMixed) {
   1559  std::string sdp =
   1560      "v=0\r\n"
   1561      "o=- 4294967296 2 IN IP4 127.0.0.1\r\n"
   1562      "s=SIP Call\r\n"
   1563      "t=0 0\r\n"
   1564      "a=extmap-allow-mixed\r\n";
   1565  ParseSdp(sdp);
   1566  ASSERT_TRUE(sdp_attr_is_present(sdp_ptr_, SDP_ATTR_EXTMAP_ALLOW_MIXED,
   1567                                  SDP_SESSION_LEVEL, 0));
   1568 }
   1569 
   1570 class NewSdpTest
   1571    : public ::testing::Test,
   1572      public ::testing::WithParamInterface< ::testing::tuple<bool, bool> > {
   1573 public:
   1574  NewSdpTest() = default;
   1575 
   1576  void ParseSdp(const std::string& sdp, bool expectSuccess = true,
   1577                bool expectEqual = true) {
   1578    UniquePtr<SdpParser> firstParser(new RsdparsaSdpParser());
   1579    UniquePtr<SdpParser> secondParser(new SipccSdpParser());
   1580    if (::testing::get<1>(GetParam())) {
   1581      firstParser.swap(secondParser);
   1582    }
   1583    mResults = firstParser->Parse(sdp);
   1584 #ifdef DEBUG_DISPLAY_SDP
   1585    std::cout << firstParser->Name() << " Parsing SDP:" << std::endl;
   1586    std::stringstream sdpStream(sdp);
   1587    std::string line;
   1588    size_t lineNumber = 0;
   1589    while (std::getline(sdpStream, line, '\n')) {
   1590      if (line.length() && line.back() == '\r') {
   1591        line.pop_back();
   1592      }
   1593      lineNumber++;
   1594      std::cout << std::setw(4) << lineNumber << " " << line << std::endl;
   1595    }
   1596 #endif
   1597    // Are we configured to do a parse and serialize before actually
   1598    // running the test?
   1599    if (::testing::get<0>(GetParam())) {
   1600      if (expectSuccess) {
   1601        ASSERT_TRUE(!!mResults->Sdp())
   1602        << "Parse failed on first pass: " << SerializeParseErrors();
   1603      }
   1604 
   1605      if (mResults->Sdp()) {
   1606        std::stringstream os, os2;
   1607        // Serialize and re-parse
   1608        mResults->Sdp()->Serialize(os);
   1609        const auto secondResults = secondParser->Parse(os.str());
   1610        // Whether we expected the parse to work or not, it should
   1611        // succeed the second time if it succeeded the first.
   1612        ASSERT_TRUE(!!Sdp())
   1613        << "Parse failed on second pass, SDP was: " << std::endl
   1614        << os.str() << std::endl
   1615        << "Errors were: " << IntSerializeParseErrors(secondResults);
   1616        // Serialize again and compare
   1617        secondResults->Sdp()->Serialize(os2);
   1618        if (expectEqual) {
   1619          ASSERT_EQ(os.str(), os2.str())
   1620              << "FIRST IS " << mResults->ParserName() << ", SECOND IS "
   1621              << secondResults->ParserName();
   1622        } else {
   1623          ASSERT_NE(os.str(), os2.str())
   1624              << "FIRST IS " << mResults->ParserName() << ", SECOND IS "
   1625              << secondResults->ParserName();
   1626        }
   1627      }
   1628    }
   1629 
   1630    if (expectSuccess) {
   1631      ASSERT_TRUE(!!mResults->Sdp())
   1632      << "Parse failed: " << SerializeParseErrors();
   1633      ASSERT_EQ(0U, ParseErrorCount())
   1634          << "Got unexpected parse errors/warnings: " << SerializeParseErrors();
   1635    }
   1636  }
   1637  const UniquePtr<class Sdp>& Sdp() const {
   1638    static const UniquePtr<class Sdp> NO_SDP(nullptr);
   1639    return mResults ? mResults->Sdp() : NO_SDP;
   1640  }
   1641 
   1642  size_t ParseErrorCount() const { return mResults->Errors().size(); }
   1643  size_t ParseWarningCount() const { return mResults->Warnings().size(); }
   1644 
   1645  std::string IntSerializeParseErrors(
   1646      const UniquePtr<SdpParser::Results>& aResults) const {
   1647    std::stringstream output;
   1648    for (const auto& e : aResults->Errors()) {
   1649      output << e.first << ": " << e.second << std::endl;
   1650    }
   1651    return output.str();
   1652  }
   1653  // For streaming parse errors
   1654  std::string SerializeParseErrors() const {
   1655    return IntSerializeParseErrors(mResults);
   1656  }
   1657 
   1658  std::string IntSerializeParseWarnings(
   1659      const UniquePtr<SdpParser::Results>& aResults) const {
   1660    std::stringstream output;
   1661    for (const auto& e : aResults->Warnings()) {
   1662      output << e.first << ": " << e.second << std::endl;
   1663    }
   1664    return output.str();
   1665  }
   1666 
   1667  std::string SerializeParseWarnings() const {
   1668    return IntSerializeParseWarnings(mResults);
   1669  }
   1670 
   1671  void CheckRtpmap(const std::string& expected_pt,
   1672                   SdpRtpmapAttributeList::CodecType codec,
   1673                   const std::string& name, uint32_t clock, uint16_t channels,
   1674                   const std::string& search_pt,
   1675                   const SdpRtpmapAttributeList& rtpmaps) const {
   1676    ASSERT_TRUE(rtpmaps.HasEntry(search_pt));
   1677    auto attr = rtpmaps.GetEntry(search_pt);
   1678    ASSERT_EQ(expected_pt, attr.pt);
   1679    ASSERT_EQ(codec, attr.codec);
   1680    std::cout << "Codec = " << name << std::endl;
   1681    ASSERT_EQ(name, attr.name);
   1682    ASSERT_EQ(clock, attr.clock);
   1683    ASSERT_EQ(channels, attr.channels);
   1684  }
   1685 
   1686  void CheckSctpmap(const std::string& expected_pt, const std::string& name,
   1687                    uint16_t streams, const std::string& search_pt,
   1688                    const SdpSctpmapAttributeList& sctpmaps) const {
   1689    ASSERT_TRUE(sctpmaps.HasEntry(search_pt));
   1690    auto attr = sctpmaps.GetFirstEntry();
   1691    ASSERT_EQ(expected_pt, search_pt);
   1692    ASSERT_EQ(expected_pt, attr.pt);
   1693    ASSERT_EQ(name, attr.name);
   1694    ASSERT_EQ(streams, attr.streams);
   1695  }
   1696 
   1697  void CheckRtcpFb(const SdpRtcpFbAttributeList::Feedback& feedback,
   1698                   const std::string& pt, SdpRtcpFbAttributeList::Type type,
   1699                   const std::string& first_parameter,
   1700                   const std::string& extra = "") const {
   1701    ASSERT_EQ(pt, feedback.pt);
   1702    ASSERT_EQ(type, feedback.type);
   1703    ASSERT_EQ(first_parameter, feedback.parameter);
   1704    ASSERT_EQ(extra, feedback.extra);
   1705  }
   1706 
   1707  void CheckDtmfFmtp(const std::string& expectedDtmfTones) const {
   1708    ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   1709        SdpAttribute::kFmtpAttribute));
   1710    auto audio_format_params =
   1711        Sdp()->GetMediaSection(0).GetAttributeList().GetFmtp().mFmtps;
   1712    ASSERT_EQ(2U, audio_format_params.size());
   1713 
   1714    ASSERT_EQ("101", audio_format_params[1].format);
   1715    ASSERT_TRUE(!!audio_format_params[1].parameters);
   1716    const SdpFmtpAttributeList::TelephoneEventParameters* te_parameters =
   1717        static_cast<SdpFmtpAttributeList::TelephoneEventParameters*>(
   1718            audio_format_params[1].parameters.get());
   1719    ASSERT_NE(0U, te_parameters->dtmfTones.size());
   1720    ASSERT_EQ(expectedDtmfTones, te_parameters->dtmfTones);
   1721  }
   1722 
   1723  void CheckSerialize(const std::string& expected,
   1724                      const SdpAttribute& attr) const {
   1725    std::stringstream str;
   1726    attr.Serialize(str);
   1727    ASSERT_EQ(expected, str.str());
   1728  }
   1729 
   1730  bool ResultsAreFromSipcc() const {
   1731    return mResults && SipccSdpParser::IsNamed(mResults->ParserName());
   1732  }
   1733 
   1734  mozilla::UniquePtr<SdpParser::Results> mResults;
   1735 };  // class NewSdpTest
   1736 
   1737 TEST_P(NewSdpTest, CreateDestroy) {}
   1738 
   1739 TEST_P(NewSdpTest, ParseEmpty) {
   1740  ParseSdp("", false);
   1741  ASSERT_FALSE(Sdp());
   1742  ASSERT_NE(0U, ParseErrorCount()) << "Expected at least one parse error.";
   1743 }
   1744 
   1745 MOZ_RUNINIT const std::string kBadSdp = "This is SDPARTA!!!!";
   1746 
   1747 TEST_P(NewSdpTest, ParseGarbage) {
   1748  ParseSdp(kBadSdp, false);
   1749  ASSERT_FALSE(Sdp());
   1750  ASSERT_NE(0U, ParseErrorCount()) << "Expected at least one parse error.";
   1751 }
   1752 
   1753 TEST_P(NewSdpTest, ParseGarbageTwice) {
   1754  ParseSdp(kBadSdp, false);
   1755  ASSERT_FALSE(Sdp());
   1756  size_t errorCount = ParseErrorCount();
   1757  ASSERT_NE(0U, errorCount) << "Expected at least one parse error.";
   1758  ParseSdp(kBadSdp, false);
   1759  ASSERT_FALSE(Sdp());
   1760  ASSERT_EQ(errorCount, ParseErrorCount())
   1761      << "Expected same error count for same SDP.";
   1762 }
   1763 
   1764 TEST_P(NewSdpTest, ParseMinimal) {
   1765  ParseSdp(kVideoSdp);
   1766  ASSERT_EQ(0U, ParseErrorCount())
   1767      << "Got parse errors: " << SerializeParseErrors();
   1768 }
   1769 
   1770 TEST_P(NewSdpTest, CheckOriginGetUsername) {
   1771  ParseSdp(kVideoSdp);
   1772  ASSERT_EQ("-", Sdp()->GetOrigin().GetUsername())
   1773      << "Wrong username in origin";
   1774 }
   1775 
   1776 TEST_P(NewSdpTest, CheckOriginGetSessionId) {
   1777  ParseSdp(kVideoSdp);
   1778  ASSERT_EQ(4294967296U, Sdp()->GetOrigin().GetSessionId())
   1779      << "Wrong session id in origin";
   1780 }
   1781 
   1782 TEST_P(NewSdpTest, CheckOriginGetSessionVersion) {
   1783  ParseSdp(kVideoSdp);
   1784  ASSERT_EQ(2U, Sdp()->GetOrigin().GetSessionVersion())
   1785      << "Wrong version in origin";
   1786 }
   1787 
   1788 TEST_P(NewSdpTest, CheckOriginGetAddrType) {
   1789  ParseSdp(kVideoSdp);
   1790  ASSERT_EQ(sdp::kIPv4, Sdp()->GetOrigin().GetAddrType())
   1791      << "Wrong address type in origin";
   1792 }
   1793 
   1794 TEST_P(NewSdpTest, CheckOriginGetAddress) {
   1795  ParseSdp(kVideoSdp);
   1796  ASSERT_EQ("127.0.0.1", Sdp()->GetOrigin().GetAddress())
   1797      << "Wrong address in origin";
   1798 }
   1799 
   1800 TEST_P(NewSdpTest, CheckGetMissingBandwidth) {
   1801  ParseSdp(kVideoSdp);
   1802  ASSERT_EQ(0U, Sdp()->GetBandwidth("CT")) << "Wrong bandwidth in session";
   1803 }
   1804 
   1805 TEST_P(NewSdpTest, CheckGetBandwidth) {
   1806  ParseSdp("v=0" CRLF "o=- 4294967296 2 IN IP4 127.0.0.1" CRLF "s=SIP Call" CRLF
   1807           "c=IN IP4 198.51.100.7" CRLF "b=CT:5000" CRLF "b=FOOBAR:10" CRLF
   1808           "b=AS:4" CRLF "t=0 0" CRLF "m=video 56436 RTP/SAVPF 120" CRLF
   1809           "a=rtpmap:120 VP8/90000" CRLF,
   1810           true, ::testing::get<1>(GetParam()));
   1811  ASSERT_EQ(5000U, Sdp()->GetBandwidth("CT"))
   1812      << "Wrong CT bandwidth in session";
   1813  ASSERT_EQ(0U, Sdp()->GetBandwidth("FOOBAR"))
   1814      << "Wrong FOOBAR bandwidth in session";
   1815  ASSERT_EQ(4U, Sdp()->GetBandwidth("AS")) << "Wrong AS bandwidth in session";
   1816 }
   1817 
   1818 TEST_P(NewSdpTest, CheckGetMediaSectionsCount) {
   1819  ParseSdp(kVideoSdp);
   1820  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   1821      << "Wrong number of media sections";
   1822 }
   1823 
   1824 TEST_P(NewSdpTest, CheckMediaSectionGetMediaType) {
   1825  ParseSdp(kVideoSdp);
   1826  ASSERT_EQ(SdpMediaSection::kVideo, Sdp()->GetMediaSection(0).GetMediaType())
   1827      << "Wrong type for first media section";
   1828 }
   1829 
   1830 TEST_P(NewSdpTest, CheckMediaSectionGetProtocol) {
   1831  ParseSdp(kVideoSdp);
   1832  ASSERT_EQ(SdpMediaSection::kRtpSavpf, Sdp()->GetMediaSection(0).GetProtocol())
   1833      << "Wrong protocol for video";
   1834 }
   1835 
   1836 TEST_P(NewSdpTest, CheckMediaSectionGetFormats) {
   1837  ParseSdp(kVideoSdp);
   1838  auto video_formats = Sdp()->GetMediaSection(0).GetFormats();
   1839  ASSERT_EQ(1U, video_formats.size()) << "Wrong number of formats for video";
   1840  ASSERT_EQ("120", video_formats[0]);
   1841 }
   1842 
   1843 TEST_P(NewSdpTest, CheckMediaSectionGetPort) {
   1844  ParseSdp(kVideoSdp);
   1845  ASSERT_EQ(56436U, Sdp()->GetMediaSection(0).GetPort())
   1846      << "Wrong port number in media section";
   1847 }
   1848 
   1849 TEST_P(NewSdpTest, CheckMediaSectionGetMissingPortCount) {
   1850  ParseSdp(kVideoSdp);
   1851  ASSERT_EQ(0U, Sdp()->GetMediaSection(0).GetPortCount())
   1852      << "Wrong port count in media section";
   1853 }
   1854 
   1855 TEST_P(NewSdpTest, CheckMediaSectionGetPortCount) {
   1856  ParseSdp(kVideoSdp + "m=audio 12345/2 RTP/SAVPF 0" CRLF
   1857                       "a=rtpmap:0 PCMU/8000" CRLF);
   1858  ASSERT_EQ(2U, Sdp()->GetMediaSectionCount())
   1859      << "Wrong number of media sections";
   1860  ASSERT_EQ(2U, Sdp()->GetMediaSection(1).GetPortCount())
   1861      << "Wrong port count in media section";
   1862 }
   1863 
   1864 TEST_P(NewSdpTest, CheckMediaSectionGetMissingBandwidth) {
   1865  ParseSdp(kVideoSdp);
   1866  ASSERT_EQ(0U, Sdp()->GetMediaSection(0).GetBandwidth("CT"))
   1867      << "Wrong bandwidth in media section";
   1868 }
   1869 
   1870 TEST_P(NewSdpTest, CheckMediaSectionGetBandwidth) {
   1871  ParseSdp(
   1872      "v=0\r\n"
   1873      "o=- 4294967296 2 IN IP4 127.0.0.1\r\n"
   1874      "s=SIP Call\r\n"
   1875      "c=IN IP4 198.51.100.7\r\n"
   1876      "t=0 0\r\n"
   1877      "m=video 56436 RTP/SAVPF 120\r\n"
   1878      "b=CT:1000\r\n"
   1879      "a=rtpmap:120 VP8/90000\r\n");
   1880  ASSERT_EQ(1000U, Sdp()->GetMediaSection(0).GetBandwidth("CT"))
   1881      << "Wrong bandwidth in media section";
   1882 }
   1883 
   1884 // Define a string that is 258 characters long. We use a long string here so
   1885 // that we can test that we are able to parse and handle a string longer than
   1886 // the default maximum length of 256 in sipcc.
   1887 #define ID_A "1234567890abcdef"
   1888 #define ID_B ID_A ID_A ID_A ID_A
   1889 #define LONG_IDENTITY ID_B ID_B ID_B ID_B "xx"
   1890 
   1891 #define BASE64_DTLS_HELLO                                                     \
   1892  "FgEAAAAAAAAAAAAAagEAAF4AAAAAAAAAXgEARI11KHx3QB6Ky"                         \
   1893  "CKgoBj/kwjKrApkL8kiZLwIqBaJGT8AAAA2ADkAOAA1ABYAEwAKADMAMgAvAAcAZgAFAAQAYw" \
   1894  "BiAGEAFQASAAkAZQBkAGAAFAARAAgABgADAQA="
   1895 
   1896 // SDP from a basic A/V apprtc call FFX/FFX
   1897 MOZ_RUNINIT const std::vector<std::string> kBasicAudioVideoOfferLines = {
   1898    "v=0",
   1899    "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0",
   1900    "s=SIP Call",
   1901    "c=IN IP4 224.0.0.1/100/12",
   1902    "t=0 0",
   1903    "a=dtls-message:client " BASE64_DTLS_HELLO,
   1904    "a=ice-ufrag:4a799b2e",
   1905    "a=ice-pwd:e4cc12a910f106a0a744719425510e17",
   1906    "a=ice-lite",
   1907    "a=ice-options:trickle foo",
   1908    "a=msid-semantic:WMS stream streama",
   1909    "a=msid-semantic:foo stream",
   1910    "a=fingerprint:sha-256 "
   1911    "DF:2E:AC:8A:FD:0A:8E:99:BF:5D:E8:3C:E7:FA:FB:08:3B:3C:54:1D:D7:D4:05:77:"
   1912    "A0:72:9B:14:08:6D:0F:4C",
   1913    "a=identity:" LONG_IDENTITY,
   1914    "a=group:BUNDLE first second",
   1915    "a=group:BUNDLE third",
   1916    "a=group:LS first third",
   1917    "m=audio 9 RTP/SAVPF 109 9 0 8 101",
   1918    "c=IN IP4 0.0.0.0",
   1919    "a=mid:first",
   1920    "a=rtpmap:109 opus/48000/2",
   1921    "a=fmtp:109 maxplaybackrate=32000;stereo=1",
   1922    "a=ptime:20",
   1923    "a=maxptime:20",
   1924    "a=rtpmap:9 G722/8000",
   1925    "a=rtpmap:0 PCMU/8000",
   1926    "a=rtpmap:8 PCMA/8000",
   1927    "a=rtpmap:101 telephone-event/8000",
   1928    "a=fmtp:101 0-15,66,32-34,67",
   1929    "a=ice-ufrag:00000000",
   1930    "a=ice-pwd:0000000000000000000000000000000",
   1931    "a=sendonly",
   1932    "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level",
   1933    "a=extmap-allow-mixed",
   1934    "a=setup:actpass",
   1935    "a=rtcp-mux",
   1936    "a=msid:stream track",
   1937    "a=candidate:0 1 UDP 2130379007 10.0.0.36 62453 typ host",
   1938    "a=candidate:2 1 UDP 1694236671 24.6.134.204 62453 typ srflx raddr "
   1939    "10.0.0.36 rport 62453",
   1940    "a=candidate:3 1 UDP 100401151 162.222.183.171 49761 typ relay raddr "
   1941    "162.222.183.171 rport 49761",
   1942    "a=candidate:6 1 UDP 16515071 162.222.183.171 51858 typ relay raddr "
   1943    "162.222.183.171 rport 51858",
   1944    "a=candidate:3 2 UDP 100401150 162.222.183.171 62454 typ relay raddr "
   1945    "162.222.183.171 rport 62454",
   1946    "a=candidate:2 2 UDP 1694236670 24.6.134.204 55428 typ srflx raddr "
   1947    "10.0.0.36 rport 55428",
   1948    "a=candidate:6 2 UDP 16515070 162.222.183.171 50340 typ relay raddr "
   1949    "162.222.183.171 rport 50340",
   1950    "a=candidate:0 2 UDP 2130379006 10.0.0.36 55428 typ host",
   1951    "a=rtcp:62454 IN IP4 162.222.183.171",
   1952    "a=end-of-candidates",
   1953    "a=ssrc:5150",
   1954    "m=video 9 RTP/SAVPF 120 121 122 123",
   1955    "c=IN IP6 ::1",
   1956    "a=fingerprint:sha-1 "
   1957    "DF:FA:FB:08:3B:3C:54:1D:D7:D4:05:77:A0:72:9B:14:08:6D:0F:4C",
   1958    "a=mid:second",
   1959    "a=rtpmap:120 VP8/90000",
   1960    "a=fmtp:120 max-fs=3600;max-fr=30",
   1961    "a=rtpmap:121 VP9/90000",
   1962    "a=fmtp:121 max-fs=3600;max-fr=30",
   1963    "a=rtpmap:122 red/90000",
   1964    "a=rtpmap:123 ulpfec/90000",
   1965    "a=fmtp:122 120/121/123",
   1966    "a=extmap-allow-mixed",
   1967    "a=recvonly",
   1968    "a=rtcp-fb:120 nack",
   1969    "a=rtcp-fb:120 nack pli",
   1970    "a=rtcp-fb:120 ccm fir",
   1971    "a=rtcp-fb:121 nack",
   1972    "a=rtcp-fb:121 nack pli",
   1973    "a=rtcp-fb:121 ccm fir",
   1974    "a=setup:active",
   1975    "a=rtcp-mux",
   1976    "a=msid:streama tracka",
   1977    "a=msid:streamb trackb",
   1978    "a=candidate:0 1 UDP 2130379007 10.0.0.36 59530 typ host",
   1979    "a=candidate:0 2 UDP 2130379006 10.0.0.36 64378 typ host",
   1980    "a=candidate:2 2 UDP 1694236670 24.6.134.204 64378 typ srflx raddr "
   1981    "10.0.0.36 rport 64378",
   1982    "a=candidate:6 2 UDP 16515070 162.222.183.171 64941 typ relay raddr "
   1983    "162.222.183.171 rport 64941",
   1984    "a=candidate:6 1 UDP 16515071 162.222.183.171 64800 typ relay raddr "
   1985    "162.222.183.171 rport 64800",
   1986    "a=candidate:2 1 UDP 1694236671 24.6.134.204 59530 typ srflx raddr "
   1987    "10.0.0.36 rport 59530",
   1988    "a=candidate:3 1 UDP 100401151 162.222.183.171 62935 typ relay raddr "
   1989    "162.222.183.171 rport 62935",
   1990    "a=candidate:3 2 UDP 100401150 162.222.183.171 61026 typ relay raddr "
   1991    "162.222.183.171 rport 61026",
   1992    "a=rtcp:61026",
   1993    "a=end-of-candidates",
   1994    "a=ssrc:1111 foo",
   1995    "a=ssrc:1111 foo:bar",
   1996    "a=ssrc:1111 msid:1d0cdb4e-5934-4f0f-9f88-40392cb60d31 "
   1997    "315b086a-5cb6-4221-89de-caf0b038c79d",
   1998    "a=imageattr:120 send * recv *",
   1999    "a=imageattr:121 send [x=640,y=480] recv [x=640,y=480]",
   2000    "a=rid:bar recv pt=120;max-width=800;max-height=600",
   2001    "a=rid:bar123 recv max-width=1920;max-height=1080",
   2002    "a=simulcast:recv bar;bar123",
   2003    "m=audio 9 RTP/SAVPF 0",
   2004    "a=mid:third",
   2005    "a=rtpmap:0 PCMU/8000",
   2006    "a=ice-options:foo bar",
   2007    "a=msid:noappdata",
   2008    "a=extmap-allow-mixed",
   2009    "a=bundle-only"};
   2010 
   2011 // SDP from a basic A/V apprtc call FFX/FFX
   2012 MOZ_RUNINIT const std::vector<std::string> kBasicAV1AudioVideoOfferLines = {
   2013    "v=0",
   2014    "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0",
   2015    "s=SIP Call",
   2016    "c=IN IP4 224.0.0.1/100/12",
   2017    "t=0 0",
   2018    "a=dtls-message:client " BASE64_DTLS_HELLO,
   2019    "a=ice-ufrag:4a799b2e",
   2020    "a=ice-pwd:e4cc12a910f106a0a744719425510e17",
   2021    "a=ice-lite",
   2022    "a=ice-options:trickle foo",
   2023    "a=msid-semantic:WMS stream streama",
   2024    "a=msid-semantic:foo stream",
   2025    "a=fingerprint:sha-256 "
   2026    "DF:2E:AC:8A:FD:0A:8E:99:BF:5D:E8:3C:E7:FA:FB:08:3B:3C:54:1D:D7:D4:05:77:"
   2027    "A0:72:9B:14:08:6D:0F:4C",
   2028    "a=identity:" LONG_IDENTITY,
   2029    "a=group:BUNDLE first second",
   2030    "a=group:BUNDLE third",
   2031    "a=group:LS first third",
   2032    "m=audio 9 RTP/SAVPF 109 9 0 8 101",
   2033    "c=IN IP4 0.0.0.0",
   2034    "a=mid:first",
   2035    "a=rtpmap:109 opus/48000/2",
   2036    "a=fmtp:109 maxplaybackrate=32000;stereo=1",
   2037    "a=ptime:20",
   2038    "a=maxptime:20",
   2039    "a=rtpmap:9 G722/8000",
   2040    "a=rtpmap:0 PCMU/8000",
   2041    "a=rtpmap:8 PCMA/8000",
   2042    "a=rtpmap:101 telephone-event/8000",
   2043    "a=fmtp:101 0-15,66,32-34,67",
   2044    "a=ice-ufrag:00000000",
   2045    "a=ice-pwd:0000000000000000000000000000000",
   2046    "a=sendonly",
   2047    "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level",
   2048    "a=extmap-allow-mixed",
   2049    "a=setup:actpass",
   2050    "a=rtcp-mux",
   2051    "a=msid:stream track",
   2052    "a=candidate:0 1 UDP 2130379007 10.0.0.36 62453 typ host",
   2053    "a=candidate:2 1 UDP 1694236671 24.6.134.204 62453 typ srflx raddr "
   2054    "10.0.0.36 rport 62453",
   2055    "a=candidate:3 1 UDP 100401151 162.222.183.171 49761 typ relay raddr "
   2056    "162.222.183.171 rport 49761",
   2057    "a=candidate:6 1 UDP 16515071 162.222.183.171 51858 typ relay raddr "
   2058    "162.222.183.171 rport 51858",
   2059    "a=candidate:3 2 UDP 100401150 162.222.183.171 62454 typ relay raddr "
   2060    "162.222.183.171 rport 62454",
   2061    "a=candidate:2 2 UDP 1694236670 24.6.134.204 55428 typ srflx raddr "
   2062    "10.0.0.36 rport 55428",
   2063    "a=candidate:6 2 UDP 16515070 162.222.183.171 50340 typ relay raddr "
   2064    "162.222.183.171 rport 50340",
   2065    "a=candidate:0 2 UDP 2130379006 10.0.0.36 55428 typ host",
   2066    "a=rtcp:62454 IN IP4 162.222.183.171",
   2067    "a=end-of-candidates",
   2068    "a=ssrc:5150",
   2069    "m=video 9 RTP/SAVPF 99 122 123",
   2070    "c=IN IP6 ::1",
   2071    "a=fingerprint:sha-1 "
   2072    "DF:FA:FB:08:3B:3C:54:1D:D7:D4:05:77:A0:72:9B:14:08:6D:0F:4C",
   2073    "a=mid:second",
   2074    "a=rtpmap:98 AV1/90000",
   2075    "a=extmap-allow-mixed",
   2076    "a=fmtp:98 profile=1;level-idx=1;tier=1;max-fs=3600;max-fr=30",
   2077    "a=rtpmap:122 red/90000",
   2078    "a=rtpmap:123 ulpfec/90000",
   2079    "a=fmtp:122 98/123",
   2080    "a=recvonly",
   2081    "a=rtcp-fb:98 nack",
   2082    "a=rtcp-fb:98 nack pli",
   2083    "a=rtcp-fb:98 ccm fir",
   2084    "a=rtcp-fb:121 nack",
   2085    "a=rtcp-fb:121 nack pli",
   2086    "a=rtcp-fb:121 ccm fir",
   2087    "a=setup:active",
   2088    "a=rtcp-mux",
   2089    "a=msid:streama tracka",
   2090    "a=msid:streamb trackb",
   2091    "a=candidate:0 1 UDP 2130379007 10.0.0.36 59530 typ host",
   2092    "a=candidate:0 2 UDP 2130379006 10.0.0.36 64378 typ host",
   2093    "a=candidate:2 2 UDP 1694236670 24.6.134.204 64378 typ srflx raddr "
   2094    "10.0.0.36 rport 64378",
   2095    "a=candidate:6 2 UDP 16515070 162.222.183.171 64941 typ relay raddr "
   2096    "162.222.183.171 rport 64941",
   2097    "a=candidate:6 1 UDP 16515071 162.222.183.171 64800 typ relay raddr "
   2098    "162.222.183.171 rport 64800",
   2099    "a=candidate:2 1 UDP 1694236671 24.6.134.204 59530 typ srflx raddr "
   2100    "10.0.0.36 rport 59530",
   2101    "a=candidate:3 1 UDP 100401151 162.222.183.171 62935 typ relay raddr "
   2102    "162.222.183.171 rport 62935",
   2103    "a=candidate:3 2 UDP 100401150 162.222.183.171 61026 typ relay raddr "
   2104    "162.222.183.171 rport 61026",
   2105    "a=rtcp:61026",
   2106    "a=end-of-candidates",
   2107    "a=ssrc:1111 foo",
   2108    "a=ssrc:1111 foo:bar",
   2109    "a=ssrc:1111 msid:1d0cdb4e-5934-4f0f-9f88-40392cb60d31 "
   2110    "315b086a-5cb6-4221-89de-caf0b038c79d",
   2111    "a=imageattr:120 send * recv *",
   2112    "a=imageattr:121 send [x=640,y=480] recv [x=640,y=480]",
   2113    "m=audio 9 RTP/SAVPF 0",
   2114    "a=mid:third",
   2115    "a=rtpmap:0 PCMU/8000",
   2116    "a=ice-options:foo bar",
   2117    "a=msid:noappdata",
   2118    "a=extmap-allow-mixed",
   2119    "a=bundle-only"};
   2120 
   2121 static std::string joinSdp(const std::vector<std::string>& aSdp,
   2122                           const std::string& aEndl) {
   2123  std::ostringstream result;
   2124  for (const auto& line : aSdp) {
   2125    result << line << aEndl;
   2126  }
   2127  // Extra endl!
   2128  result << aEndl;
   2129  return result.str();
   2130 }
   2131 
   2132 MOZ_RUNINIT const std::string kBasicAudioVideoOffer =
   2133    joinSdp(kBasicAudioVideoOfferLines, "\r\n");
   2134 
   2135 MOZ_RUNINIT const std::string kBasicAudioVideoOfferLinefeedOnly =
   2136    joinSdp(kBasicAudioVideoOfferLines, "\n");
   2137 
   2138 TEST_P(NewSdpTest, BasicAudioVideoSdpParse) { ParseSdp(kBasicAudioVideoOffer); }
   2139 
   2140 MOZ_RUNINIT const std::string kAv1AudioVideoOffer =
   2141    joinSdp(kBasicAudioVideoOfferLines, "\r\n");
   2142 
   2143 MOZ_RUNINIT const std::string kAv1AudioVideoOfferLinefeedOnly =
   2144    joinSdp(kBasicAudioVideoOfferLines, "\n");
   2145 
   2146 TEST_P(NewSdpTest, Av1AudioVideoSdpParse) { ParseSdp(kAv1AudioVideoOffer); }
   2147 
   2148 TEST_P(NewSdpTest, Av1AudioVideoSdpParseLinefeedOnly) {
   2149  ParseSdp(kAv1AudioVideoOfferLinefeedOnly);
   2150 }
   2151 
   2152 TEST_P(NewSdpTest, CheckRemoveFmtp) {
   2153  ParseSdp(kBasicAudioVideoOffer);
   2154  ASSERT_TRUE(!!Sdp())
   2155  << "Parse failed: " << SerializeParseErrors();
   2156  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   2157      << "Wrong number of media sections";
   2158 
   2159  SdpAttributeList& audioAttrList =
   2160      Sdp()->GetMediaSection(0).GetAttributeList();
   2161 
   2162  ASSERT_TRUE(audioAttrList.HasAttribute(SdpAttribute::kFmtpAttribute));
   2163  ASSERT_EQ(2U, audioAttrList.GetFmtp().mFmtps.size());
   2164  ASSERT_TRUE(Sdp()->GetMediaSection(0).FindFmtp("109"));
   2165  ASSERT_TRUE(Sdp()->GetMediaSection(0).FindFmtp("101"));
   2166 
   2167  Sdp()->GetMediaSection(0).RemoveFmtp("101");
   2168 
   2169  ASSERT_TRUE(audioAttrList.HasAttribute(SdpAttribute::kFmtpAttribute));
   2170  ASSERT_EQ(1U, audioAttrList.GetFmtp().mFmtps.size());
   2171  ASSERT_TRUE(Sdp()->GetMediaSection(0).FindFmtp("109"));
   2172  ASSERT_FALSE(Sdp()->GetMediaSection(0).FindFmtp("101"));
   2173 
   2174  Sdp()->GetMediaSection(0).RemoveFmtp("109");
   2175 
   2176  ASSERT_TRUE(audioAttrList.HasAttribute(SdpAttribute::kFmtpAttribute));
   2177  ASSERT_EQ(0U, audioAttrList.GetFmtp().mFmtps.size());
   2178  ASSERT_FALSE(Sdp()->GetMediaSection(0).FindFmtp("109"));
   2179  ASSERT_FALSE(Sdp()->GetMediaSection(0).FindFmtp("101"));
   2180 
   2181  // make sure we haven't disturbed the video fmtps
   2182  SdpAttributeList& videoAttrList =
   2183      Sdp()->GetMediaSection(1).GetAttributeList();
   2184  ASSERT_TRUE(videoAttrList.HasAttribute(SdpAttribute::kFmtpAttribute));
   2185  ASSERT_EQ(3U, videoAttrList.GetFmtp().mFmtps.size());
   2186  ASSERT_TRUE(Sdp()->GetMediaSection(1).FindFmtp("120"));
   2187  ASSERT_TRUE(Sdp()->GetMediaSection(1).FindFmtp("121"));
   2188  ASSERT_TRUE(Sdp()->GetMediaSection(1).FindFmtp("122"));
   2189 }
   2190 
   2191 TEST_P(NewSdpTest, CheckIceUfrag) {
   2192  ParseSdp(kBasicAudioVideoOffer);
   2193  ASSERT_TRUE(!!Sdp())
   2194  << "Parse failed: " << SerializeParseErrors();
   2195  ASSERT_TRUE(
   2196      Sdp()->GetAttributeList().HasAttribute(SdpAttribute::kIceUfragAttribute));
   2197  auto ice_ufrag = Sdp()->GetAttributeList().GetIceUfrag();
   2198  ASSERT_EQ("4a799b2e", ice_ufrag) << "Wrong ice-ufrag value";
   2199 
   2200  ice_ufrag = Sdp()->GetMediaSection(0).GetAttributeList().GetIceUfrag();
   2201  ASSERT_EQ("00000000", ice_ufrag) << "ice-ufrag isn't overridden";
   2202 
   2203  ice_ufrag = Sdp()->GetMediaSection(1).GetAttributeList().GetIceUfrag();
   2204  ASSERT_EQ("4a799b2e", ice_ufrag) << "ice-ufrag isn't carried to m-section";
   2205 }
   2206 
   2207 TEST_P(NewSdpTest, CheckIcePwd) {
   2208  ParseSdp(kBasicAudioVideoOffer);
   2209  ASSERT_TRUE(!!Sdp())
   2210  << "Parse failed: " << SerializeParseErrors();
   2211  ASSERT_TRUE(
   2212      Sdp()->GetAttributeList().HasAttribute(SdpAttribute::kIcePwdAttribute));
   2213  auto ice_pwd = Sdp()->GetAttributeList().GetIcePwd();
   2214  ASSERT_EQ("e4cc12a910f106a0a744719425510e17", ice_pwd)
   2215      << "Wrong ice-pwd value";
   2216 
   2217  ice_pwd = Sdp()->GetMediaSection(0).GetAttributeList().GetIcePwd();
   2218  ASSERT_EQ("0000000000000000000000000000000", ice_pwd)
   2219      << "ice-pwd isn't overridden";
   2220 
   2221  ice_pwd = Sdp()->GetMediaSection(1).GetAttributeList().GetIcePwd();
   2222  ASSERT_EQ("e4cc12a910f106a0a744719425510e17", ice_pwd)
   2223      << "ice-pwd isn't carried to m-section";
   2224 }
   2225 
   2226 TEST_P(NewSdpTest, CheckIceOptions) {
   2227  ParseSdp(kBasicAudioVideoOffer);
   2228  ASSERT_TRUE(!!Sdp())
   2229  << "Parse failed: " << SerializeParseErrors();
   2230  ASSERT_TRUE(Sdp()->GetAttributeList().HasAttribute(
   2231      SdpAttribute::kIceOptionsAttribute));
   2232  auto ice_options = Sdp()->GetAttributeList().GetIceOptions();
   2233  ASSERT_EQ(2U, ice_options.mValues.size()) << "Wrong ice-options size";
   2234  ASSERT_EQ("trickle", ice_options.mValues[0]) << "Wrong ice-options value";
   2235  ASSERT_EQ("foo", ice_options.mValues[1]) << "Wrong ice-options value";
   2236 
   2237  ASSERT_TRUE(Sdp()->GetMediaSection(2).GetAttributeList().HasAttribute(
   2238      SdpAttribute::kIceOptionsAttribute));
   2239  auto ice_options_media_level =
   2240      Sdp()->GetMediaSection(2).GetAttributeList().GetIceOptions();
   2241  ASSERT_EQ(2U, ice_options_media_level.mValues.size())
   2242      << "Wrong ice-options size";
   2243  ASSERT_EQ("foo", ice_options_media_level.mValues[0])
   2244      << "Wrong ice-options value";
   2245  ASSERT_EQ("bar", ice_options_media_level.mValues[1])
   2246      << "Wrong ice-options value";
   2247 }
   2248 
   2249 TEST_P(NewSdpTest, CheckFingerprint) {
   2250  ParseSdp(kBasicAudioVideoOffer);
   2251  ASSERT_TRUE(!!Sdp())
   2252  << "Parse failed: " << SerializeParseErrors();
   2253  ASSERT_TRUE(Sdp()->GetAttributeList().HasAttribute(
   2254      SdpAttribute::kFingerprintAttribute));
   2255  auto fingerprints = Sdp()->GetAttributeList().GetFingerprint();
   2256  ASSERT_EQ(1U, fingerprints.mFingerprints.size());
   2257  ASSERT_EQ(SdpFingerprintAttributeList::kSha256,
   2258            fingerprints.mFingerprints[0].hashFunc)
   2259      << "Wrong hash function";
   2260  ASSERT_EQ(
   2261      "DF:2E:AC:8A:FD:0A:8E:99:BF:5D:E8:3C:E7:FA:FB:08:"
   2262      "3B:3C:54:1D:D7:D4:05:77:A0:72:9B:14:08:6D:0F:4C",
   2263      SdpFingerprintAttributeList::FormatFingerprint(
   2264          fingerprints.mFingerprints[0].fingerprint))
   2265      << "Wrong fingerprint";
   2266  ASSERT_EQ(0xdfU, fingerprints.mFingerprints[0].fingerprint[0])
   2267      << "first fingerprint element is iffy";
   2268 
   2269  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount());
   2270 
   2271  // Fallback to session level
   2272  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   2273      SdpAttribute::kFingerprintAttribute));
   2274  fingerprints = Sdp()->GetMediaSection(0).GetAttributeList().GetFingerprint();
   2275  ASSERT_EQ(1U, fingerprints.mFingerprints.size());
   2276  ASSERT_EQ(SdpFingerprintAttributeList::kSha256,
   2277            fingerprints.mFingerprints[0].hashFunc)
   2278      << "Wrong hash function";
   2279  ASSERT_EQ(
   2280      "DF:2E:AC:8A:FD:0A:8E:99:BF:5D:E8:3C:E7:FA:FB:08:"
   2281      "3B:3C:54:1D:D7:D4:05:77:A0:72:9B:14:08:6D:0F:4C",
   2282      SdpFingerprintAttributeList::FormatFingerprint(
   2283          fingerprints.mFingerprints[0].fingerprint))
   2284      << "Wrong fingerprint";
   2285  ASSERT_EQ(0xdfU, fingerprints.mFingerprints[0].fingerprint[0])
   2286      << "first fingerprint element is iffy";
   2287 
   2288  // Media level
   2289  ASSERT_TRUE(Sdp()->GetMediaSection(1).GetAttributeList().HasAttribute(
   2290      SdpAttribute::kFingerprintAttribute));
   2291  fingerprints = Sdp()->GetMediaSection(1).GetAttributeList().GetFingerprint();
   2292  ASSERT_EQ(1U, fingerprints.mFingerprints.size());
   2293  ASSERT_EQ(SdpFingerprintAttributeList::kSha1,
   2294            fingerprints.mFingerprints[0].hashFunc)
   2295      << "Wrong hash function";
   2296  ASSERT_EQ(
   2297      "DF:FA:FB:08:3B:3C:54:1D:D7:D4:05:77:A0:72:9B:14:"
   2298      "08:6D:0F:4C",
   2299      SdpFingerprintAttributeList::FormatFingerprint(
   2300          fingerprints.mFingerprints[0].fingerprint))
   2301      << "Wrong fingerprint";
   2302  ASSERT_EQ(0xdfU, fingerprints.mFingerprints[0].fingerprint[0])
   2303      << "first fingerprint element is iffy";
   2304 }
   2305 
   2306 TEST_P(NewSdpTest, CheckIdentity) {
   2307  ParseSdp(kBasicAudioVideoOffer);
   2308  ASSERT_TRUE(!!Sdp())
   2309  << "Parse failed: " << SerializeParseErrors();
   2310  ASSERT_TRUE(
   2311      Sdp()->GetAttributeList().HasAttribute(SdpAttribute::kIdentityAttribute));
   2312  auto identity = Sdp()->GetAttributeList().GetIdentity();
   2313  ASSERT_EQ(LONG_IDENTITY, identity) << "Wrong identity assertion";
   2314 }
   2315 
   2316 TEST_P(NewSdpTest, CheckDtlsMessage) {
   2317  ParseSdp(kBasicAudioVideoOffer);
   2318  ASSERT_TRUE(!!Sdp())
   2319  << "Parse failed: " << SerializeParseErrors();
   2320  ASSERT_TRUE(Sdp()->GetAttributeList().HasAttribute(
   2321      SdpAttribute::kDtlsMessageAttribute));
   2322  auto dtls_message = Sdp()->GetAttributeList().GetDtlsMessage();
   2323  ASSERT_EQ(SdpDtlsMessageAttribute::kClient, dtls_message.mRole)
   2324      << "Wrong dtls-message role";
   2325  ASSERT_EQ(BASE64_DTLS_HELLO, dtls_message.mValue)
   2326      << "Wrong dtls-message value";
   2327 }
   2328 
   2329 TEST_P(NewSdpTest, CheckNumberOfMediaSections) {
   2330  ParseSdp(kBasicAudioVideoOffer);
   2331  ASSERT_TRUE(!!Sdp())
   2332  << "Parse failed: " << SerializeParseErrors();
   2333  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   2334      << "Wrong number of media sections";
   2335 }
   2336 
   2337 TEST_P(NewSdpTest, CheckMlines) {
   2338  ParseSdp(kBasicAudioVideoOffer);
   2339  ASSERT_TRUE(!!Sdp())
   2340  << "Parse failed: " << SerializeParseErrors();
   2341  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   2342      << "Wrong number of media sections";
   2343  ASSERT_EQ(SdpMediaSection::kAudio, Sdp()->GetMediaSection(0).GetMediaType())
   2344      << "Wrong type for first media section";
   2345  ASSERT_EQ(SdpMediaSection::kRtpSavpf, Sdp()->GetMediaSection(0).GetProtocol())
   2346      << "Wrong protocol for audio";
   2347  auto audio_formats = Sdp()->GetMediaSection(0).GetFormats();
   2348  ASSERT_EQ(5U, audio_formats.size()) << "Wrong number of formats for audio";
   2349  ASSERT_EQ("109", audio_formats[0]);
   2350  ASSERT_EQ("9", audio_formats[1]);
   2351  ASSERT_EQ("0", audio_formats[2]);
   2352  ASSERT_EQ("8", audio_formats[3]);
   2353  ASSERT_EQ("101", audio_formats[4]);
   2354 
   2355  ASSERT_EQ(SdpMediaSection::kVideo, Sdp()->GetMediaSection(1).GetMediaType())
   2356      << "Wrong type for second media section";
   2357  ASSERT_EQ(SdpMediaSection::kRtpSavpf, Sdp()->GetMediaSection(1).GetProtocol())
   2358      << "Wrong protocol for video";
   2359  auto video_formats = Sdp()->GetMediaSection(1).GetFormats();
   2360  ASSERT_EQ(4U, video_formats.size()) << "Wrong number of formats for video";
   2361  ASSERT_EQ("120", video_formats[0]);
   2362  ASSERT_EQ("121", video_formats[1]);
   2363  ASSERT_EQ("122", video_formats[2]);
   2364  ASSERT_EQ("123", video_formats[3]);
   2365 
   2366  ASSERT_EQ(SdpMediaSection::kAudio, Sdp()->GetMediaSection(2).GetMediaType())
   2367      << "Wrong type for third media section";
   2368 }
   2369 
   2370 TEST_P(NewSdpTest, CheckSetup) {
   2371  ParseSdp(kBasicAudioVideoOffer);
   2372  ASSERT_TRUE(!!Sdp())
   2373  << "Parse failed: " << SerializeParseErrors();
   2374  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   2375      << "Wrong number of media sections";
   2376 
   2377  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   2378      SdpAttribute::kSetupAttribute));
   2379  ASSERT_EQ(SdpSetupAttribute::kActpass,
   2380            Sdp()->GetMediaSection(0).GetAttributeList().GetSetup().mRole);
   2381  ASSERT_TRUE(Sdp()->GetMediaSection(1).GetAttributeList().HasAttribute(
   2382      SdpAttribute::kSetupAttribute));
   2383  ASSERT_EQ(SdpSetupAttribute::kActive,
   2384            Sdp()->GetMediaSection(1).GetAttributeList().GetSetup().mRole);
   2385  ASSERT_FALSE(Sdp()->GetMediaSection(2).GetAttributeList().HasAttribute(
   2386      SdpAttribute::kSetupAttribute));
   2387 }
   2388 
   2389 TEST_P(NewSdpTest, CheckSsrc) {
   2390  ParseSdp(kBasicAudioVideoOffer);
   2391  ASSERT_TRUE(!!Sdp())
   2392  << "Parse failed: " << SerializeParseErrors();
   2393  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   2394      << "Wrong number of media sections";
   2395 
   2396  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   2397      SdpAttribute::kSsrcAttribute));
   2398  auto ssrcs = Sdp()->GetMediaSection(0).GetAttributeList().GetSsrc().mSsrcs;
   2399  ASSERT_EQ(1U, ssrcs.size());
   2400  ASSERT_EQ(5150U, ssrcs[0].ssrc);
   2401  ASSERT_EQ("", ssrcs[0].attribute);
   2402 
   2403  ASSERT_TRUE(Sdp()->GetMediaSection(1).GetAttributeList().HasAttribute(
   2404      SdpAttribute::kSsrcAttribute));
   2405  ssrcs = Sdp()->GetMediaSection(1).GetAttributeList().GetSsrc().mSsrcs;
   2406  ASSERT_EQ(3U, ssrcs.size());
   2407  ASSERT_EQ(1111U, ssrcs[0].ssrc);
   2408  ASSERT_EQ("foo", ssrcs[0].attribute);
   2409  ASSERT_EQ(1111U, ssrcs[1].ssrc);
   2410  ASSERT_EQ("foo:bar", ssrcs[1].attribute);
   2411  ASSERT_EQ(1111U, ssrcs[2].ssrc);
   2412  ASSERT_EQ(
   2413      "msid:1d0cdb4e-5934-4f0f-9f88-40392cb60d31 "
   2414      "315b086a-5cb6-4221-89de-caf0b038c79d",
   2415      ssrcs[2].attribute);
   2416 }
   2417 
   2418 TEST_P(NewSdpTest, CheckRtpmap) {
   2419  ParseSdp(kBasicAudioVideoOffer);
   2420  ASSERT_TRUE(!!Sdp())
   2421  << "Parse failed: " << SerializeParseErrors();
   2422  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   2423      << "Wrong number of media sections";
   2424 
   2425  const SdpMediaSection& audiosec = Sdp()->GetMediaSection(0);
   2426  const SdpRtpmapAttributeList& rtpmap =
   2427      audiosec.GetAttributeList().GetRtpmap();
   2428  ASSERT_EQ(5U, rtpmap.mRtpmaps.size())
   2429      << "Wrong number of rtpmap attributes for audio";
   2430 
   2431  // Need to know name of type
   2432  CheckRtpmap("109", SdpRtpmapAttributeList::kOpus, "opus", 48000, 2,
   2433              audiosec.GetFormats()[0], rtpmap);
   2434 
   2435  CheckRtpmap("9", SdpRtpmapAttributeList::kG722, "G722", 8000, 1,
   2436              audiosec.GetFormats()[1], rtpmap);
   2437 
   2438  CheckRtpmap("0", SdpRtpmapAttributeList::kPCMU, "PCMU", 8000, 1,
   2439              audiosec.GetFormats()[2], rtpmap);
   2440 
   2441  CheckRtpmap("8", SdpRtpmapAttributeList::kPCMA, "PCMA", 8000, 1,
   2442              audiosec.GetFormats()[3], rtpmap);
   2443 
   2444  CheckRtpmap("101", SdpRtpmapAttributeList::kTelephoneEvent, "telephone-event",
   2445              8000, 1, audiosec.GetFormats()[4], rtpmap);
   2446 
   2447  const SdpMediaSection& videosec = Sdp()->GetMediaSection(1);
   2448  const SdpRtpmapAttributeList videoRtpmap =
   2449      videosec.GetAttributeList().GetRtpmap();
   2450  ASSERT_EQ(4U, videoRtpmap.mRtpmaps.size())
   2451      << "Wrong number of rtpmap attributes for video";
   2452 
   2453  CheckRtpmap("120", SdpRtpmapAttributeList::kVP8, "VP8", 90000, 0,
   2454              videosec.GetFormats()[0], videoRtpmap);
   2455 
   2456  CheckRtpmap("121", SdpRtpmapAttributeList::kVP9, "VP9", 90000, 0,
   2457              videosec.GetFormats()[1], videoRtpmap);
   2458 
   2459  CheckRtpmap("122", SdpRtpmapAttributeList::kRed, "red", 90000, 0,
   2460              videosec.GetFormats()[2], videoRtpmap);
   2461 
   2462  CheckRtpmap("123", SdpRtpmapAttributeList::kUlpfec, "ulpfec", 90000, 0,
   2463              videosec.GetFormats()[3], videoRtpmap);
   2464 }
   2465 
   2466 MOZ_RUNINIT static const std::string kAudioWithTelephoneEvent =
   2467    "v=0" CRLF "o=- 4294967296 2 IN IP4 127.0.0.1" CRLF "s=SIP Call" CRLF
   2468    "c=IN IP4 198.51.100.7" CRLF "t=0 0" CRLF
   2469    "m=audio 9 RTP/SAVPF 109 9 0 8 101" CRLF "c=IN IP4 0.0.0.0" CRLF
   2470    "a=mid:first" CRLF "a=rtpmap:109 opus/48000/2" CRLF
   2471    "a=fmtp:109 maxplaybackrate=32000;stereo=1" CRLF "a=ptime:20" CRLF
   2472    "a=maxptime:20" CRLF "a=rtpmap:9 G722/8000" CRLF "a=rtpmap:0 PCMU/8000" CRLF
   2473    "a=rtpmap:8 PCMA/8000" CRLF "a=rtpmap:101 telephone-event/8000" CRLF;
   2474 
   2475 TEST_P(NewSdpTest, CheckTelephoneEventNoFmtp) {
   2476  ParseSdp(kAudioWithTelephoneEvent);
   2477  ASSERT_TRUE(!!Sdp())
   2478  << "Parse failed: " << SerializeParseErrors();
   2479  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2480      << "Wrong number of media sections";
   2481 
   2482  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   2483      SdpAttribute::kFmtpAttribute));
   2484  auto audio_format_params =
   2485      Sdp()->GetMediaSection(0).GetAttributeList().GetFmtp().mFmtps;
   2486  ASSERT_EQ(1U, audio_format_params.size());
   2487 
   2488  // make sure we don't get a fmtp for codec 101
   2489  for (size_t i = 0; i < audio_format_params.size(); ++i) {
   2490    ASSERT_NE("101", audio_format_params[i].format);
   2491  }
   2492 }
   2493 
   2494 TEST_P(NewSdpTest, CheckTelephoneEventWithDefaultEvents) {
   2495  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 0-15" CRLF);
   2496  ASSERT_TRUE(!!Sdp())
   2497  << "Parse failed: " << SerializeParseErrors();
   2498  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2499      << "Wrong number of media sections";
   2500 
   2501  CheckDtmfFmtp("0-15");
   2502 }
   2503 
   2504 TEST_P(NewSdpTest, CheckTelephoneEventWithBadCharacter) {
   2505  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 0-5." CRLF);
   2506  ASSERT_TRUE(!!Sdp())
   2507  << "Parse failed: " << SerializeParseErrors();
   2508  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2509      << "Wrong number of media sections";
   2510 
   2511  CheckDtmfFmtp("0-15");
   2512 }
   2513 
   2514 TEST_P(NewSdpTest, CheckTelephoneEventIncludingCommas) {
   2515  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 0-15,66,67" CRLF);
   2516  ASSERT_TRUE(!!Sdp())
   2517  << "Parse failed: " << SerializeParseErrors();
   2518  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2519      << "Wrong number of media sections";
   2520 
   2521  CheckDtmfFmtp("0-15,66,67");
   2522 }
   2523 
   2524 TEST_P(NewSdpTest, CheckTelephoneEventComplexEvents) {
   2525  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 0,1,2-4,5-15,66,67" CRLF);
   2526  ASSERT_TRUE(!!Sdp())
   2527  << "Parse failed: " << SerializeParseErrors();
   2528  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2529      << "Wrong number of media sections";
   2530 
   2531  CheckDtmfFmtp("0,1,2-4,5-15,66,67");
   2532 }
   2533 
   2534 TEST_P(NewSdpTest, CheckTelephoneEventNoHyphen) {
   2535  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 5,6,7" CRLF);
   2536  ASSERT_TRUE(!!Sdp())
   2537  << "Parse failed: " << SerializeParseErrors();
   2538  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2539      << "Wrong number of media sections";
   2540 
   2541  CheckDtmfFmtp("5,6,7");
   2542 }
   2543 
   2544 TEST_P(NewSdpTest, CheckTelephoneEventOnlyZero) {
   2545  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 0" CRLF);
   2546  ASSERT_TRUE(!!Sdp())
   2547  << "Parse failed: " << SerializeParseErrors();
   2548  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2549      << "Wrong number of media sections";
   2550 
   2551  CheckDtmfFmtp("0");
   2552 }
   2553 
   2554 TEST_P(NewSdpTest, CheckTelephoneEventOnlyOne) {
   2555  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 1" CRLF);
   2556  ASSERT_TRUE(!!Sdp())
   2557  << "Parse failed: " << SerializeParseErrors();
   2558  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2559      << "Wrong number of media sections";
   2560 
   2561  CheckDtmfFmtp("1");
   2562 }
   2563 
   2564 TEST_P(NewSdpTest, CheckTelephoneEventBadThreeDigit) {
   2565  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 123" CRLF);
   2566  ASSERT_TRUE(!!Sdp())
   2567  << "Parse failed: " << SerializeParseErrors();
   2568  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2569      << "Wrong number of media sections";
   2570 
   2571  // check for the default dtmf tones
   2572  CheckDtmfFmtp("0-15");
   2573 }
   2574 
   2575 TEST_P(NewSdpTest, CheckTelephoneEventBadThreeDigitWithHyphen) {
   2576  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 0-123" CRLF);
   2577  ASSERT_TRUE(!!Sdp())
   2578  << "Parse failed: " << SerializeParseErrors();
   2579  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2580      << "Wrong number of media sections";
   2581 
   2582  // check for the default dtmf tones
   2583  CheckDtmfFmtp("0-15");
   2584 }
   2585 
   2586 TEST_P(NewSdpTest, CheckTelephoneEventBadLeadingHyphen) {
   2587  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 -12" CRLF);
   2588  ASSERT_TRUE(!!Sdp())
   2589  << "Parse failed: " << SerializeParseErrors();
   2590  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2591      << "Wrong number of media sections";
   2592 
   2593  // check for the default dtmf tones
   2594  CheckDtmfFmtp("0-15");
   2595 }
   2596 
   2597 TEST_P(NewSdpTest, CheckTelephoneEventBadTrailingHyphen) {
   2598  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 12-" CRLF, false);
   2599 }
   2600 
   2601 TEST_P(NewSdpTest, CheckTelephoneEventBadTrailingHyphenInMiddle) {
   2602  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 1,12-,4" CRLF, false);
   2603 }
   2604 
   2605 TEST_P(NewSdpTest, CheckTelephoneEventBadLeadingComma) {
   2606  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 ,2,3" CRLF);
   2607  ASSERT_TRUE(!!Sdp())
   2608  << "Parse failed: " << SerializeParseErrors();
   2609  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2610      << "Wrong number of media sections";
   2611 
   2612  // check for the default dtmf tones
   2613  CheckDtmfFmtp("0-15");
   2614 }
   2615 
   2616 TEST_P(NewSdpTest, CheckTelephoneEventBadMultipleLeadingComma) {
   2617  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 ,,,2,3" CRLF);
   2618  ASSERT_TRUE(!!Sdp())
   2619  << "Parse failed: " << SerializeParseErrors();
   2620  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2621      << "Wrong number of media sections";
   2622 
   2623  // check for the default dtmf tones
   2624  CheckDtmfFmtp("0-15");
   2625 }
   2626 
   2627 TEST_P(NewSdpTest, CheckTelephoneEventBadConsecutiveCommas) {
   2628  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 1,,,,,,,,3" CRLF);
   2629  ASSERT_TRUE(!!Sdp())
   2630  << "Parse failed: " << SerializeParseErrors();
   2631  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2632      << "Wrong number of media sections";
   2633 
   2634  // check for the default dtmf tones
   2635  CheckDtmfFmtp("0-15");
   2636 }
   2637 
   2638 TEST_P(NewSdpTest, CheckTelephoneEventBadTrailingComma) {
   2639  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 1,2,3," CRLF);
   2640  ASSERT_TRUE(!!Sdp())
   2641  << "Parse failed: " << SerializeParseErrors();
   2642  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2643      << "Wrong number of media sections";
   2644 
   2645  // check for the default dtmf tones
   2646  CheckDtmfFmtp("0-15");
   2647 }
   2648 
   2649 TEST_P(NewSdpTest, CheckTelephoneEventBadTwoHyphens) {
   2650  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 1-2-3" CRLF);
   2651  ASSERT_TRUE(!!Sdp())
   2652  << "Parse failed: " << SerializeParseErrors();
   2653  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2654      << "Wrong number of media sections";
   2655 
   2656  // check for the default dtmf tones
   2657  CheckDtmfFmtp("0-15");
   2658 }
   2659 
   2660 TEST_P(NewSdpTest, CheckTelephoneEventBadSixDigit) {
   2661  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 112233" CRLF);
   2662  ASSERT_TRUE(!!Sdp())
   2663  << "Parse failed: " << SerializeParseErrors();
   2664  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2665      << "Wrong number of media sections";
   2666 
   2667  // check for the default dtmf tones
   2668  CheckDtmfFmtp("0-15");
   2669 }
   2670 
   2671 TEST_P(NewSdpTest, CheckTelephoneEventBadRangeReversed) {
   2672  ParseSdp(kAudioWithTelephoneEvent + "a=fmtp:101 33-2" CRLF);
   2673  ASSERT_TRUE(!!Sdp())
   2674  << "Parse failed: " << SerializeParseErrors();
   2675  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2676      << "Wrong number of media sections";
   2677 
   2678  // check for the default dtmf tones
   2679  CheckDtmfFmtp("0-15");
   2680 }
   2681 
   2682 MOZ_RUNINIT static const std::string kVideoWithRedAndUlpfecSdp =
   2683    "v=0" CRLF "o=- 4294967296 2 IN IP4 127.0.0.1" CRLF "s=SIP Call" CRLF
   2684    "c=IN IP4 198.51.100.7" CRLF "t=0 0" CRLF
   2685    "m=video 9 RTP/SAVPF 97 120 121 122 123" CRLF "c=IN IP6 ::1" CRLF
   2686    "a=fingerprint:sha-1 "
   2687    "DF:FA:FB:08:3B:3C:54:1D:D7:D4:05:77:A0:72:9B:14:08:6D:0F:4C" CRLF
   2688    "a=rtpmap:97 H264/90000" CRLF "a=fmtp:97 profile-level-id=42a01e" CRLF
   2689    "a=rtpmap:120 VP8/90000" CRLF "a=fmtp:120 max-fs=3600;max-fr=30" CRLF
   2690    "a=rtpmap:121 VP9/90000" CRLF "a=fmtp:121 max-fs=3600;max-fr=30" CRLF
   2691    "a=rtpmap:122 red/90000" CRLF "a=rtpmap:123 ulpfec/90000" CRLF;
   2692 
   2693 TEST_P(NewSdpTest, CheckRedNoFmtp) {
   2694  ParseSdp(kVideoWithRedAndUlpfecSdp);
   2695  ASSERT_TRUE(!!Sdp())
   2696  << "Parse failed: " << SerializeParseErrors();
   2697  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2698      << "Wrong number of media sections";
   2699 
   2700  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   2701      SdpAttribute::kFmtpAttribute));
   2702  auto video_format_params =
   2703      Sdp()->GetMediaSection(0).GetAttributeList().GetFmtp().mFmtps;
   2704  ASSERT_EQ(3U, video_format_params.size());
   2705 
   2706  // make sure we don't get a fmtp for codec 122
   2707  for (size_t i = 0; i < video_format_params.size(); ++i) {
   2708    ASSERT_NE("122", video_format_params[i].format);
   2709  }
   2710 }
   2711 
   2712 TEST_P(NewSdpTest, CheckRedEmptyFmtp) {
   2713  // if serializing and re-parsing, we expect errors
   2714  if (::testing::get<0>(GetParam())) {
   2715    ParseSdp(kVideoWithRedAndUlpfecSdp + "a=fmtp:122" CRLF, false);
   2716  } else {
   2717    ParseSdp(kVideoWithRedAndUlpfecSdp + "a=fmtp:122" CRLF, false);
   2718 
   2719    if (ResultsAreFromSipcc()) {
   2720      ASSERT_NE(0U, ParseErrorCount());
   2721    } else {
   2722      // This is the branch for the rust parser to check for warnings, as the
   2723      // rust parser will give a warning at that point instead of an error.
   2724      ASSERT_NE(0U, ParseWarningCount());
   2725    }
   2726  }
   2727 
   2728  ASSERT_TRUE(!!Sdp())
   2729  << "Parse failed: " << SerializeParseErrors();
   2730  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2731      << "Wrong number of media sections";
   2732 
   2733  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   2734      SdpAttribute::kFmtpAttribute));
   2735  auto video_format_params =
   2736      Sdp()->GetMediaSection(0).GetAttributeList().GetFmtp().mFmtps;
   2737  ASSERT_EQ(3U, video_format_params.size());
   2738 
   2739  // make sure we don't get a fmtp for codec 122
   2740  for (size_t i = 0; i < video_format_params.size(); ++i) {
   2741    ASSERT_NE("122", video_format_params[i].format);
   2742  }
   2743 }
   2744 
   2745 TEST_P(NewSdpTest, CheckRedFmtpWith2Codecs) {
   2746  ParseSdp(kVideoWithRedAndUlpfecSdp + "a=fmtp:122 120/121" CRLF);
   2747  ASSERT_TRUE(!!Sdp())
   2748  << "Parse failed: " << SerializeParseErrors();
   2749  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2750      << "Wrong number of media sections";
   2751 
   2752  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   2753      SdpAttribute::kFmtpAttribute));
   2754  auto video_format_params =
   2755      Sdp()->GetMediaSection(0).GetAttributeList().GetFmtp().mFmtps;
   2756  ASSERT_EQ(4U, video_format_params.size());
   2757 
   2758  ASSERT_EQ("122", video_format_params[3].format);
   2759  ASSERT_TRUE(!!video_format_params[3].parameters);
   2760  ASSERT_EQ(SdpRtpmapAttributeList::kRed,
   2761            video_format_params[3].parameters->codec_type);
   2762  const SdpFmtpAttributeList::RedParameters* red_parameters(
   2763      static_cast<SdpFmtpAttributeList::RedParameters*>(
   2764          video_format_params[3].parameters.get()));
   2765  ASSERT_EQ(2U, red_parameters->encodings.size());
   2766  ASSERT_EQ(120U, red_parameters->encodings[0]);
   2767  ASSERT_EQ(121U, red_parameters->encodings[1]);
   2768 }
   2769 
   2770 TEST_P(NewSdpTest, CheckRedFmtpWith3Codecs) {
   2771  ParseSdp(kVideoWithRedAndUlpfecSdp + "a=fmtp:122 120/121/123" CRLF);
   2772  ASSERT_TRUE(!!Sdp())
   2773  << "Parse failed: " << SerializeParseErrors();
   2774  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
   2775      << "Wrong number of media sections";
   2776 
   2777  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   2778      SdpAttribute::kFmtpAttribute));
   2779  auto video_format_params =
   2780      Sdp()->GetMediaSection(0).GetAttributeList().GetFmtp().mFmtps;
   2781  ASSERT_EQ(4U, video_format_params.size());
   2782 
   2783  ASSERT_EQ("122", video_format_params[3].format);
   2784  ASSERT_TRUE(!!video_format_params[3].parameters);
   2785  ASSERT_EQ(SdpRtpmapAttributeList::kRed,
   2786            video_format_params[3].parameters->codec_type);
   2787  const SdpFmtpAttributeList::RedParameters* red_parameters(
   2788      static_cast<SdpFmtpAttributeList::RedParameters*>(
   2789          video_format_params[3].parameters.get()));
   2790  ASSERT_EQ(3U, red_parameters->encodings.size());
   2791  ASSERT_EQ(120U, red_parameters->encodings[0]);
   2792  ASSERT_EQ(121U, red_parameters->encodings[1]);
   2793  ASSERT_EQ(123U, red_parameters->encodings[2]);
   2794 }
   2795 
   2796 MOZ_RUNINIT const std::string kH264AudioVideoOffer =
   2797    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   2798    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   2799    "a=ice-ufrag:4a799b2e" CRLF
   2800    "a=ice-pwd:e4cc12a910f106a0a744719425510e17" CRLF "a=ice-lite" CRLF
   2801    "a=msid-semantic:WMS stream streama" CRLF
   2802    "a=fingerprint:sha-256 "
   2803    "DF:2E:AC:8A:FD:0A:8E:99:BF:5D:E8:3C:E7:FA:FB:08:3B:3C:54:1D:D7:D4:05:77:"
   2804    "A0:72:9B:14:08:6D:0F:4C" CRLF "a=group:BUNDLE first second" CRLF
   2805    "a=group:BUNDLE third" CRLF "a=group:LS first third" CRLF
   2806    "m=audio 9 RTP/SAVPF 109 9 0 8 101" CRLF "c=IN IP4 0.0.0.0" CRLF
   2807    "a=mid:first" CRLF "a=rtpmap:109 opus/48000/2" CRLF "a=ptime:20" CRLF
   2808    "a=maxptime:20" CRLF "a=rtpmap:9 G722/8000" CRLF "a=rtpmap:0 PCMU/8000" CRLF
   2809    "a=rtpmap:8 PCMA/8000" CRLF "a=rtpmap:101 telephone-event/8000" CRLF
   2810    "a=fmtp:109 maxplaybackrate=32000;stereo=1;useinbandfec=1" CRLF
   2811    "a=fmtp:101 0-15,66,32-34,67" CRLF "a=ice-ufrag:00000000" CRLF
   2812    "a=ice-pwd:0000000000000000000000000000000" CRLF "a=sendonly" CRLF
   2813    "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level" CRLF
   2814    "a=setup:actpass" CRLF "a=rtcp-mux" CRLF "a=msid:stream track" CRLF
   2815    "a=candidate:0 1 UDP 2130379007 10.0.0.36 62453 typ host" CRLF
   2816    "a=candidate:2 1 UDP 1694236671 24.6.134.204 62453 typ srflx raddr "
   2817    "10.0.0.36 rport 62453" CRLF
   2818    "a=candidate:3 1 UDP 100401151 162.222.183.171 49761 typ relay raddr "
   2819    "162.222.183.171 rport 49761" CRLF
   2820    "a=candidate:6 1 UDP 16515071 162.222.183.171 51858 typ relay raddr "
   2821    "162.222.183.171 rport 51858" CRLF
   2822    "a=candidate:3 2 UDP 100401150 162.222.183.171 62454 typ relay raddr "
   2823    "162.222.183.171 rport 62454" CRLF
   2824    "a=candidate:2 2 UDP 1694236670 24.6.134.204 55428 typ srflx raddr "
   2825    "10.0.0.36 rport 55428" CRLF
   2826    "a=candidate:6 2 UDP 16515070 162.222.183.171 50340 typ relay raddr "
   2827    "162.222.183.171 rport 50340" CRLF
   2828    "a=candidate:0 2 UDP 2130379006 10.0.0.36 55428 typ host" CRLF
   2829    "m=video 9 RTP/SAVPF 97 98 120" CRLF "c=IN IP6 ::1" CRLF "a=mid:second" CRLF
   2830    "a=rtpmap:97 H264/90000" CRLF "a=fmtp:97 profile-level-id=42a01e" CRLF
   2831    "a=rtpmap:98 H264/90000" CRLF
   2832    "a=fmtp:98 "
   2833    "PROFILE=0;LEVEL=0;parameter-add=1;profile-level-id=42a00d;packetization-"
   2834    "mode=1;level-asymmetry-allowed=1;max-mbps=42000;max-fs=1400;max-cpb=1000;"
   2835    "max-dpb=1000;max-br=180000;usedtx=0;stereo=0;useinbandfec=0;cbr=0" CRLF
   2836    "a=rtpmap:120 VP8/90000" CRLF "a=fmtp:120 max-fs=3601;max-fr=31" CRLF
   2837    "a=recvonly" CRLF "a=setup:active" CRLF "a=rtcp-mux" CRLF
   2838    "a=msid:streama tracka" CRLF "a=msid:streamb trackb" CRLF
   2839    "a=candidate:0 1 UDP 2130379007 10.0.0.36 59530 typ host" CRLF
   2840    "a=candidate:0 2 UDP 2130379006 10.0.0.36 64378 typ host" CRLF
   2841    "a=candidate:2 2 UDP 1694236670 24.6.134.204 64378 typ srflx raddr "
   2842    "10.0.0.36 rport 64378" CRLF
   2843    "a=candidate:6 2 UDP 16515070 162.222.183.171 64941 typ relay raddr "
   2844    "162.222.183.171 rport 64941" CRLF
   2845    "a=candidate:6 1 UDP 16515071 162.222.183.171 64800 typ relay raddr "
   2846    "162.222.183.171 rport 64800" CRLF
   2847    "a=candidate:2 1 UDP 1694236671 24.6.134.204 59530 typ srflx raddr "
   2848    "10.0.0.36 rport 59530" CRLF
   2849    "a=candidate:3 1 UDP 100401151 162.222.183.171 62935 typ relay raddr "
   2850    "162.222.183.171 rport 62935" CRLF
   2851    "a=candidate:3 2 UDP 100401150 162.222.183.171 61026 typ relay raddr "
   2852    "162.222.183.171 rport 61026" CRLF "m=audio 9 RTP/SAVPF 0" CRLF
   2853    "a=mid:third" CRLF "a=rtpmap:0 PCMU/8000" CRLF "a=msid:noappdata" CRLF;
   2854 
   2855 TEST_P(NewSdpTest, CheckFormatParameters) {
   2856  ParseSdp(kH264AudioVideoOffer);
   2857  ASSERT_TRUE(!!Sdp())
   2858  << "Parse failed: " << SerializeParseErrors();
   2859  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   2860      << "Wrong number of media sections";
   2861 
   2862  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   2863      SdpAttribute::kFmtpAttribute));
   2864  auto audio_format_params =
   2865      Sdp()->GetMediaSection(0).GetAttributeList().GetFmtp().mFmtps;
   2866  ASSERT_EQ(2U, audio_format_params.size());
   2867  ASSERT_EQ("109", audio_format_params[0].format);
   2868  ASSERT_TRUE(!!audio_format_params[0].parameters);
   2869  const SdpFmtpAttributeList::OpusParameters* opus_parameters =
   2870      static_cast<SdpFmtpAttributeList::OpusParameters*>(
   2871          audio_format_params[0].parameters.get());
   2872  ASSERT_EQ(32000U, opus_parameters->maxplaybackrate);
   2873  ASSERT_EQ(1U, opus_parameters->stereo);
   2874  ASSERT_EQ(1U, opus_parameters->useInBandFec);
   2875  ASSERT_EQ(0U, opus_parameters->maxAverageBitrate);
   2876  ASSERT_EQ(0U, opus_parameters->useDTX);
   2877  ASSERT_EQ(0U, opus_parameters->useCbr);
   2878  ASSERT_EQ(0U, opus_parameters->frameSizeMs);
   2879  ASSERT_EQ(0U, opus_parameters->minFrameSizeMs);
   2880  ASSERT_EQ(0U, opus_parameters->maxFrameSizeMs);
   2881  ASSERT_EQ("101", audio_format_params[1].format);
   2882  ASSERT_TRUE(!!audio_format_params[1].parameters);
   2883  const SdpFmtpAttributeList::TelephoneEventParameters* te_parameters =
   2884      static_cast<SdpFmtpAttributeList::TelephoneEventParameters*>(
   2885          audio_format_params[1].parameters.get());
   2886  ASSERT_NE(0U, te_parameters->dtmfTones.size());
   2887  ASSERT_EQ("0-15,66,32-34,67", te_parameters->dtmfTones);
   2888 
   2889  ASSERT_TRUE(Sdp()->GetMediaSection(1).GetAttributeList().HasAttribute(
   2890      SdpAttribute::kFmtpAttribute));
   2891  auto video_format_params =
   2892      Sdp()->GetMediaSection(1).GetAttributeList().GetFmtp().mFmtps;
   2893  ASSERT_EQ(3U, video_format_params.size());
   2894  ASSERT_EQ("97", video_format_params[0].format);
   2895  ASSERT_TRUE(!!video_format_params[0].parameters);
   2896  ASSERT_EQ(SdpRtpmapAttributeList::kH264,
   2897            video_format_params[0].parameters->codec_type);
   2898  const SdpFmtpAttributeList::H264Parameters* h264_parameters(
   2899      static_cast<SdpFmtpAttributeList::H264Parameters*>(
   2900          video_format_params[0].parameters.get()));
   2901  ASSERT_EQ((uint32_t)0x42a01e, h264_parameters->profile_level_id);
   2902  ASSERT_EQ(0U, h264_parameters->packetization_mode);
   2903  ASSERT_FALSE(static_cast<bool>(h264_parameters->level_asymmetry_allowed));
   2904  ASSERT_EQ(0U, h264_parameters->max_mbps);
   2905  ASSERT_EQ(0U, h264_parameters->max_fs);
   2906  ASSERT_EQ(0U, h264_parameters->max_cpb);
   2907  ASSERT_EQ(0U, h264_parameters->max_dpb);
   2908  ASSERT_EQ(0U, h264_parameters->max_br);
   2909 
   2910  ASSERT_EQ("98", video_format_params[1].format);
   2911  ASSERT_TRUE(!!video_format_params[1].parameters);
   2912  ASSERT_EQ(SdpRtpmapAttributeList::kH264,
   2913            video_format_params[1].parameters->codec_type);
   2914  h264_parameters = static_cast<SdpFmtpAttributeList::H264Parameters*>(
   2915      video_format_params[1].parameters.get());
   2916  ASSERT_EQ((uint32_t)0x42a00d, h264_parameters->profile_level_id);
   2917  ASSERT_EQ(1U, h264_parameters->packetization_mode);
   2918  ASSERT_TRUE(static_cast<bool>(h264_parameters->level_asymmetry_allowed));
   2919  ASSERT_EQ(42000U, h264_parameters->max_mbps);
   2920  ASSERT_EQ(1400U, h264_parameters->max_fs);
   2921  ASSERT_EQ(1000U, h264_parameters->max_cpb);
   2922  ASSERT_EQ(1000U, h264_parameters->max_dpb);
   2923  ASSERT_EQ(180000U, h264_parameters->max_br);
   2924 
   2925  ASSERT_EQ("120", video_format_params[2].format);
   2926  ASSERT_TRUE(!!video_format_params[2].parameters);
   2927  ASSERT_EQ(SdpRtpmapAttributeList::kVP8,
   2928            video_format_params[2].parameters->codec_type);
   2929  const SdpFmtpAttributeList::VP8Parameters* vp8_parameters =
   2930      static_cast<SdpFmtpAttributeList::VP8Parameters*>(
   2931          video_format_params[2].parameters.get());
   2932  ASSERT_EQ(3601U, vp8_parameters->max_fs);
   2933  ASSERT_EQ(31U, vp8_parameters->max_fr);
   2934 
   2935  ASSERT_FALSE(Sdp()->GetMediaSection(2).GetAttributeList().HasAttribute(
   2936      SdpAttribute::kFmtpAttribute));
   2937 }
   2938 
   2939 TEST_P(NewSdpTest, CheckPtime) {
   2940  ParseSdp(kBasicAudioVideoOffer);
   2941  ASSERT_EQ(20U, Sdp()->GetMediaSection(0).GetAttributeList().GetPtime());
   2942  ASSERT_FALSE(Sdp()->GetMediaSection(1).GetAttributeList().HasAttribute(
   2943      SdpAttribute::kPtimeAttribute));
   2944 }
   2945 
   2946 TEST_P(NewSdpTest, CheckFlags) {
   2947  ParseSdp(kBasicAudioVideoOffer);
   2948  ASSERT_TRUE(
   2949      Sdp()->GetAttributeList().HasAttribute(SdpAttribute::kIceLiteAttribute));
   2950  ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   2951      SdpAttribute::kIceLiteAttribute));
   2952  ASSERT_FALSE(Sdp()->GetMediaSection(1).GetAttributeList().HasAttribute(
   2953      SdpAttribute::kIceLiteAttribute));
   2954  ASSERT_FALSE(Sdp()->GetMediaSection(2).GetAttributeList().HasAttribute(
   2955      SdpAttribute::kIceLiteAttribute));
   2956 
   2957  ASSERT_FALSE(Sdp()->GetAttributeList().HasAttribute(
   2958      SdpAttribute::kExtmapAllowMixedAttribute));
   2959  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   2960      SdpAttribute::kExtmapAllowMixedAttribute));
   2961  ASSERT_TRUE(Sdp()->GetMediaSection(1).GetAttributeList().HasAttribute(
   2962      SdpAttribute::kExtmapAllowMixedAttribute));
   2963  ASSERT_TRUE(Sdp()->GetMediaSection(2).GetAttributeList().HasAttribute(
   2964      SdpAttribute::kExtmapAllowMixedAttribute));
   2965 
   2966  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   2967      SdpAttribute::kRtcpMuxAttribute));
   2968  ASSERT_FALSE(Sdp()->GetMediaSection(2).GetAttributeList().HasAttribute(
   2969      SdpAttribute::kRtcpMuxAttribute));
   2970 
   2971  ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   2972      SdpAttribute::kBundleOnlyAttribute));
   2973  ASSERT_TRUE(Sdp()->GetMediaSection(2).GetAttributeList().HasAttribute(
   2974      SdpAttribute::kBundleOnlyAttribute));
   2975 
   2976  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   2977      SdpAttribute::kEndOfCandidatesAttribute));
   2978  ASSERT_TRUE(Sdp()->GetMediaSection(1).GetAttributeList().HasAttribute(
   2979      SdpAttribute::kEndOfCandidatesAttribute));
   2980  ASSERT_FALSE(Sdp()->GetMediaSection(2).GetAttributeList().HasAttribute(
   2981      SdpAttribute::kEndOfCandidatesAttribute));
   2982 }
   2983 
   2984 TEST_P(NewSdpTest, CheckConnectionLines) {
   2985  ParseSdp(kBasicAudioVideoOffer);
   2986  ASSERT_TRUE(!!Sdp())
   2987  << "Parse failed: " << SerializeParseErrors();
   2988  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   2989      << "Wrong number of media sections";
   2990 
   2991  const SdpConnection& conn1 = Sdp()->GetMediaSection(0).GetConnection();
   2992  ASSERT_EQ(sdp::kIPv4, conn1.GetAddrType());
   2993  ASSERT_EQ("0.0.0.0", conn1.GetAddress());
   2994  ASSERT_EQ(0U, conn1.GetTtl());
   2995  ASSERT_EQ(0U, conn1.GetCount());
   2996 
   2997  const SdpConnection& conn2 = Sdp()->GetMediaSection(1).GetConnection();
   2998  ASSERT_EQ(sdp::kIPv6, conn2.GetAddrType());
   2999  ASSERT_EQ("::1", conn2.GetAddress());
   3000  ASSERT_EQ(0U, conn2.GetTtl());
   3001  ASSERT_EQ(0U, conn2.GetCount());
   3002 
   3003  // tests that we can fall through to session level as appropriate
   3004  const SdpConnection& conn3 = Sdp()->GetMediaSection(2).GetConnection();
   3005  ASSERT_EQ(sdp::kIPv4, conn3.GetAddrType());
   3006  ASSERT_EQ("224.0.0.1", conn3.GetAddress());
   3007  ASSERT_EQ(100U, conn3.GetTtl());
   3008  ASSERT_EQ(12U, conn3.GetCount());
   3009 }
   3010 
   3011 TEST_P(NewSdpTest, CheckDirections) {
   3012  ParseSdp(kBasicAudioVideoOffer);
   3013 
   3014  ASSERT_TRUE(!!Sdp())
   3015  << "Parse failed: " << SerializeParseErrors();
   3016  ASSERT_EQ(SdpDirectionAttribute::kSendonly,
   3017            Sdp()->GetMediaSection(0).GetAttributeList().GetDirection());
   3018  ASSERT_EQ(SdpDirectionAttribute::kRecvonly,
   3019            Sdp()->GetMediaSection(1).GetAttributeList().GetDirection());
   3020  ASSERT_EQ(SdpDirectionAttribute::kSendrecv,
   3021            Sdp()->GetMediaSection(2).GetAttributeList().GetDirection());
   3022 }
   3023 
   3024 TEST_P(NewSdpTest, CheckCandidates) {
   3025  ParseSdp(kBasicAudioVideoOffer);
   3026  ASSERT_TRUE(!!Sdp())
   3027  << "Parse failed: " << SerializeParseErrors();
   3028  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   3029      << "Wrong number of media sections";
   3030 
   3031  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3032      SdpAttribute::kCandidateAttribute));
   3033  auto audio_candidates =
   3034      Sdp()->GetMediaSection(0).GetAttributeList().GetCandidate();
   3035  ASSERT_EQ(8U, audio_candidates.size());
   3036  ASSERT_EQ("0 1 UDP 2130379007 10.0.0.36 62453 typ host", audio_candidates[0]);
   3037  ASSERT_EQ(
   3038      "2 1 UDP 1694236671 24.6.134.204 62453 typ srflx raddr 10.0.0.36 rport "
   3039      "62453",
   3040      audio_candidates[1]);
   3041  ASSERT_EQ(
   3042      "3 1 UDP 100401151 162.222.183.171 49761 typ relay raddr 162.222.183.171 "
   3043      "rport 49761",
   3044      audio_candidates[2]);
   3045  ASSERT_EQ(
   3046      "6 1 UDP 16515071 162.222.183.171 51858 typ relay raddr 162.222.183.171 "
   3047      "rport 51858",
   3048      audio_candidates[3]);
   3049  ASSERT_EQ(
   3050      "3 2 UDP 100401150 162.222.183.171 62454 typ relay raddr 162.222.183.171 "
   3051      "rport 62454",
   3052      audio_candidates[4]);
   3053  ASSERT_EQ(
   3054      "2 2 UDP 1694236670 24.6.134.204 55428 typ srflx raddr 10.0.0.36 rport "
   3055      "55428",
   3056      audio_candidates[5]);
   3057  ASSERT_EQ(
   3058      "6 2 UDP 16515070 162.222.183.171 50340 typ relay raddr 162.222.183.171 "
   3059      "rport 50340",
   3060      audio_candidates[6]);
   3061  ASSERT_EQ("0 2 UDP 2130379006 10.0.0.36 55428 typ host", audio_candidates[7]);
   3062 
   3063  ASSERT_TRUE(Sdp()->GetMediaSection(1).GetAttributeList().HasAttribute(
   3064      SdpAttribute::kCandidateAttribute));
   3065  auto video_candidates =
   3066      Sdp()->GetMediaSection(1).GetAttributeList().GetCandidate();
   3067  ASSERT_EQ(8U, video_candidates.size());
   3068  ASSERT_EQ("0 1 UDP 2130379007 10.0.0.36 59530 typ host", video_candidates[0]);
   3069  ASSERT_EQ("0 2 UDP 2130379006 10.0.0.36 64378 typ host", video_candidates[1]);
   3070  ASSERT_EQ(
   3071      "2 2 UDP 1694236670 24.6.134.204 64378 typ srflx raddr 10.0.0.36 rport "
   3072      "64378",
   3073      video_candidates[2]);
   3074  ASSERT_EQ(
   3075      "6 2 UDP 16515070 162.222.183.171 64941 typ relay raddr 162.222.183.171 "
   3076      "rport 64941",
   3077      video_candidates[3]);
   3078  ASSERT_EQ(
   3079      "6 1 UDP 16515071 162.222.183.171 64800 typ relay raddr 162.222.183.171 "
   3080      "rport 64800",
   3081      video_candidates[4]);
   3082  ASSERT_EQ(
   3083      "2 1 UDP 1694236671 24.6.134.204 59530 typ srflx raddr 10.0.0.36 rport "
   3084      "59530",
   3085      video_candidates[5]);
   3086  ASSERT_EQ(
   3087      "3 1 UDP 100401151 162.222.183.171 62935 typ relay raddr 162.222.183.171 "
   3088      "rport 62935",
   3089      video_candidates[6]);
   3090  ASSERT_EQ(
   3091      "3 2 UDP 100401150 162.222.183.171 61026 typ relay raddr 162.222.183.171 "
   3092      "rport 61026",
   3093      video_candidates[7]);
   3094 
   3095  ASSERT_FALSE(Sdp()->GetMediaSection(2).GetAttributeList().HasAttribute(
   3096      SdpAttribute::kCandidateAttribute));
   3097 }
   3098 
   3099 TEST_P(NewSdpTest, CheckMid) {
   3100  ParseSdp(kBasicAudioVideoOffer);
   3101  ASSERT_EQ("first", Sdp()->GetMediaSection(0).GetAttributeList().GetMid());
   3102  ASSERT_EQ("second", Sdp()->GetMediaSection(1).GetAttributeList().GetMid());
   3103  ASSERT_EQ("third", Sdp()->GetMediaSection(2).GetAttributeList().GetMid());
   3104 }
   3105 
   3106 TEST_P(NewSdpTest, CheckMsid) {
   3107  ParseSdp(kBasicAudioVideoOffer);
   3108  ASSERT_TRUE(Sdp()->GetAttributeList().HasAttribute(
   3109      SdpAttribute::kMsidSemanticAttribute));
   3110  auto semantics = Sdp()->GetAttributeList().GetMsidSemantic().mMsidSemantics;
   3111  ASSERT_EQ(2U, semantics.size());
   3112  ASSERT_EQ("WMS", semantics[0].semantic);
   3113  ASSERT_EQ(2U, semantics[0].msids.size());
   3114  ASSERT_EQ("stream", semantics[0].msids[0]);
   3115  ASSERT_EQ("streama", semantics[0].msids[1]);
   3116  ASSERT_EQ("foo", semantics[1].semantic);
   3117  ASSERT_EQ(1U, semantics[1].msids.size());
   3118  ASSERT_EQ("stream", semantics[1].msids[0]);
   3119 
   3120  const SdpMsidAttributeList& msids1 =
   3121      Sdp()->GetMediaSection(0).GetAttributeList().GetMsid();
   3122  ASSERT_EQ(1U, msids1.mMsids.size());
   3123  ASSERT_EQ("stream", msids1.mMsids[0].identifier);
   3124  ASSERT_EQ("track", msids1.mMsids[0].appdata);
   3125  const SdpMsidAttributeList& msids2 =
   3126      Sdp()->GetMediaSection(1).GetAttributeList().GetMsid();
   3127  ASSERT_EQ(2U, msids2.mMsids.size());
   3128  ASSERT_EQ("streama", msids2.mMsids[0].identifier);
   3129  ASSERT_EQ("tracka", msids2.mMsids[0].appdata);
   3130  ASSERT_EQ("streamb", msids2.mMsids[1].identifier);
   3131  ASSERT_EQ("trackb", msids2.mMsids[1].appdata);
   3132  const SdpMsidAttributeList& msids3 =
   3133      Sdp()->GetMediaSection(2).GetAttributeList().GetMsid();
   3134  ASSERT_EQ(1U, msids3.mMsids.size());
   3135  ASSERT_EQ("noappdata", msids3.mMsids[0].identifier);
   3136  ASSERT_EQ("", msids3.mMsids[0].appdata);
   3137 }
   3138 
   3139 TEST_P(NewSdpTest, CheckManyMsidSemantics) {
   3140  if (::testing::get<0>(GetParam())) {
   3141    return;
   3142  }
   3143  std::ostringstream msid;
   3144  msid << "a=msid-semantic: foo";
   3145  for (size_t i = 0; i < SDP_MAX_MEDIA_STREAMS + 1; ++i) {
   3146    msid << " " << i;
   3147  }
   3148  msid << CRLF;
   3149 
   3150  std::string offer =
   3151      "v=0" CRLF "o=- 4294967296 2 IN IP4 127.0.0.1" CRLF "s=SIP Call" CRLF
   3152      "c=IN IP4 198.51.100.7" CRLF "t=0 0" CRLF;
   3153  offer += msid.str();
   3154  offer += "m=video 56436 RTP/SAVPF 120" CRLF "b=CT:1000" CRLF
   3155           "a=rtpmap:120 VP8/90000" CRLF;
   3156 
   3157  ParseSdp(offer);
   3158  auto semantics = Sdp()->GetAttributeList().GetMsidSemantic().mMsidSemantics;
   3159  ASSERT_EQ(1U, semantics.size());
   3160 
   3161  // Only sipcc is limited by SDP_MAX_MEDIA_STREAMS, the Rust parser
   3162  // will parse all of the msids.
   3163  ASSERT_GE(semantics[0].msids.size(),
   3164            static_cast<size_t>(SDP_MAX_MEDIA_STREAMS));
   3165 }
   3166 
   3167 TEST_P(NewSdpTest, CheckRid) {
   3168  ParseSdp(kBasicAudioVideoOffer);
   3169  ASSERT_TRUE(!!Sdp());
   3170  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   3171      << "Wrong number of media sections";
   3172 
   3173  ASSERT_FALSE(
   3174      Sdp()->GetAttributeList().HasAttribute(SdpAttribute::kRidAttribute));
   3175  ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3176      SdpAttribute::kRidAttribute));
   3177  ASSERT_TRUE(Sdp()->GetMediaSection(1).GetAttributeList().HasAttribute(
   3178      SdpAttribute::kRidAttribute));
   3179  ASSERT_FALSE(Sdp()->GetMediaSection(2).GetAttributeList().HasAttribute(
   3180      SdpAttribute::kRidAttribute));
   3181 
   3182  const SdpRidAttributeList& rids =
   3183      Sdp()->GetMediaSection(1).GetAttributeList().GetRid();
   3184 
   3185  ASSERT_EQ(2U, rids.mRids.size());
   3186 
   3187  ASSERT_EQ("bar", rids.mRids[0].id);
   3188  ASSERT_EQ(sdp::kRecv, rids.mRids[0].direction);
   3189  ASSERT_EQ(1U, rids.mRids[0].formats.size());
   3190  ASSERT_EQ(120U, rids.mRids[0].formats[0]);
   3191  ASSERT_EQ(800U, rids.mRids[0].constraints.maxWidth);
   3192  ASSERT_EQ(600U, rids.mRids[0].constraints.maxHeight);
   3193 
   3194  ASSERT_EQ("bar123", rids.mRids[1].id);
   3195  ASSERT_EQ(sdp::kRecv, rids.mRids[1].direction);
   3196  ASSERT_EQ(0U, rids.mRids[1].formats.size());
   3197  ASSERT_EQ(1920U, rids.mRids[1].constraints.maxWidth);
   3198  ASSERT_EQ(1080U, rids.mRids[1].constraints.maxHeight);
   3199 }
   3200 
   3201 TEST_P(NewSdpTest, CheckMediaLevelIceUfrag) {
   3202  ParseSdp(kBasicAudioVideoOffer);
   3203  ASSERT_TRUE(!!Sdp())
   3204  << "Parse failed: " << SerializeParseErrors();
   3205  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   3206      << "Wrong number of media sections";
   3207 
   3208  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3209      SdpAttribute::kIceUfragAttribute, true));
   3210  ASSERT_EQ("00000000",
   3211            Sdp()->GetMediaSection(0).GetAttributeList().GetIceUfrag());
   3212 
   3213  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3214      SdpAttribute::kIceUfragAttribute, false));
   3215 
   3216  ASSERT_TRUE(Sdp()->GetMediaSection(1).GetAttributeList().HasAttribute(
   3217      SdpAttribute::kIceUfragAttribute, true));
   3218  ASSERT_EQ("4a799b2e",
   3219            Sdp()->GetMediaSection(1).GetAttributeList().GetIceUfrag());
   3220 }
   3221 
   3222 TEST_P(NewSdpTest, CheckMediaLevelIcePwd) {
   3223  ParseSdp(kBasicAudioVideoOffer);
   3224  ASSERT_TRUE(!!Sdp())
   3225  << "Parse failed: " << SerializeParseErrors();
   3226  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   3227      << "Wrong number of media sections";
   3228 
   3229  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3230      SdpAttribute::kIcePwdAttribute));
   3231  ASSERT_EQ("0000000000000000000000000000000",
   3232            Sdp()->GetMediaSection(0).GetAttributeList().GetIcePwd());
   3233 
   3234  ASSERT_TRUE(Sdp()->GetMediaSection(1).GetAttributeList().HasAttribute(
   3235      SdpAttribute::kIcePwdAttribute));
   3236  ASSERT_EQ("e4cc12a910f106a0a744719425510e17",
   3237            Sdp()->GetMediaSection(1).GetAttributeList().GetIcePwd());
   3238 }
   3239 
   3240 TEST_P(NewSdpTest, CheckGroups) {
   3241  ParseSdp(kBasicAudioVideoOffer);
   3242  const SdpGroupAttributeList& group = Sdp()->GetAttributeList().GetGroup();
   3243  const SdpGroupAttributeList::Group& group1 = group.mGroups[0];
   3244  ASSERT_EQ(SdpGroupAttributeList::kBundle, group1.semantics);
   3245  ASSERT_EQ(2U, group1.tags.size());
   3246  ASSERT_EQ("first", group1.tags[0]);
   3247  ASSERT_EQ("second", group1.tags[1]);
   3248 
   3249  const SdpGroupAttributeList::Group& group2 = group.mGroups[1];
   3250  ASSERT_EQ(SdpGroupAttributeList::kBundle, group2.semantics);
   3251  ASSERT_EQ(1U, group2.tags.size());
   3252  ASSERT_EQ("third", group2.tags[0]);
   3253 
   3254  const SdpGroupAttributeList::Group& group3 = group.mGroups[2];
   3255  ASSERT_EQ(SdpGroupAttributeList::kLs, group3.semantics);
   3256  ASSERT_EQ(2U, group3.tags.size());
   3257  ASSERT_EQ("first", group3.tags[0]);
   3258  ASSERT_EQ("third", group3.tags[1]);
   3259 }
   3260 
   3261 TEST_P(NewSdpTest, CheckManyGroups) {
   3262  std::ostringstream bundle;
   3263  bundle << "a=group:BUNDLE";
   3264  for (size_t i = 0; i < SDP_MAX_MEDIA_STREAMS + 1; ++i) {
   3265    bundle << " " << i;
   3266  }
   3267  bundle << CRLF;
   3268 
   3269  std::string offer =
   3270      "v=0" CRLF "o=- 4294967296 2 IN IP4 127.0.0.1" CRLF "s=SIP Call" CRLF
   3271      "c=IN IP4 198.51.100.7" CRLF "t=0 0" CRLF;
   3272  offer += bundle.str();
   3273  offer += "m=video 56436 RTP/SAVPF 120" CRLF "b=CT:1000" CRLF
   3274           "a=rtpmap:120 VP8/90000" CRLF;
   3275  // Rust will reserialize what Sipcc serializes to, but otherwise they will
   3276  // differ.
   3277  ParseSdp(offer, true,
   3278           ::testing::get<0>(GetParam()) && ::testing::get<1>(GetParam()));
   3279  const SdpGroupAttributeList& group = Sdp()->GetAttributeList().GetGroup();
   3280  const SdpGroupAttributeList::Group& group1 = group.mGroups[0];
   3281  ASSERT_EQ(SdpGroupAttributeList::kBundle, group1.semantics);
   3282 
   3283  // Only sipcc is limited by SDP_MAX_MEDIA_STREAMS, the Rust parser
   3284  // will parse all of the groups.
   3285  ASSERT_GE(group1.tags.size(), static_cast<size_t>(SDP_MAX_MEDIA_STREAMS));
   3286 }
   3287 
   3288 // SDP from a basic A/V call with data channel FFX/FFX
   3289 MOZ_RUNINIT const std::string kBasicAudioVideoDataOffer =
   3290    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 27987 0 IN IP4 0.0.0.0" CRLF
   3291    "s=SIP Call" CRLF "t=0 0" CRLF "a=ice-ufrag:8a39d2ae" CRLF
   3292    "a=ice-pwd:601d53aba51a318351b3ecf5ee00048f" CRLF
   3293    "a=fingerprint:sha-256 "
   3294    "30:FF:8E:2B:AC:9D:ED:70:18:10:67:C8:AE:9E:68:F3:86:53:51:B0:AC:31:B7:BE:"
   3295    "6D:CF:A4:2E:D3:6E:B4:28" CRLF "m=audio 9 RTP/SAVPF 109 9 0 8 101" CRLF
   3296    "c=IN IP4 0.0.0.0" CRLF "a=rtpmap:109 opus/48000/2" CRLF "a=ptime:20" CRLF
   3297    "a=rtpmap:9 G722/8000" CRLF "a=rtpmap:0 PCMU/8000" CRLF
   3298    "a=rtpmap:8 PCMA/8000" CRLF "a=rtpmap:101 telephone-event/8000" CRLF
   3299    "a=fmtp:101 0-15" CRLF "a=sendrecv" CRLF
   3300    "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level" CRLF
   3301    "a=extmap:2/sendonly some_extension" CRLF
   3302    "a=extmap:3 some_other_extension some_params some more params" CRLF
   3303    "a=setup:actpass" CRLF "a=rtcp-mux" CRLF
   3304    "m=video 9 RTP/SAVPF 120 126 97" CRLF "c=IN IP4 0.0.0.0" CRLF
   3305    "a=rtpmap:120 VP8/90000" CRLF "a=rtpmap:126 H264/90000" CRLF
   3306    "a=fmtp:126 profile-level-id=42e01f;packetization-mode=1" CRLF
   3307    "a=rtpmap:97 H264/90000" CRLF "a=fmtp:97 profile-level-id=42e01f" CRLF
   3308    "a=sendrecv" CRLF
   3309    // sipcc barfs on this, despite that it is valid syntax
   3310    // Do we care about fixing?
   3311    //"a=rtcp-fb:120 ack" CRLF // Should be ignored by sipcc
   3312    "a=rtcp-fb:120 ack rpsi" CRLF "a=rtcp-fb:120 ack app foo" CRLF
   3313    "a=rtcp-fb:120 ack foo" CRLF  // Should be ignored
   3314    "a=rtcp-fb:120 nack" CRLF "a=rtcp-fb:120 nack sli" CRLF
   3315    "a=rtcp-fb:120 nack pli" CRLF "a=rtcp-fb:120 nack rpsi" CRLF
   3316    "a=rtcp-fb:120 nack app foo" CRLF
   3317    "a=rtcp-fb:120 nack foo" CRLF  // Should be ignored
   3318    "a=rtcp-fb:120 ccm fir" CRLF "a=rtcp-fb:120 ccm tmmbr" CRLF
   3319    "a=rtcp-fb:120 ccm tstr" CRLF "a=rtcp-fb:120 ccm vbcm" CRLF
   3320    "a=rtcp-fb:120 ccm foo" CRLF  // Should be ignored
   3321    "a=rtcp-fb:120 trr-int 10" CRLF "a=rtcp-fb:120 goog-remb" CRLF
   3322    "a=rtcp-fb:120 foo" CRLF  // Should be ignored
   3323    "a=rtcp-fb:126 nack" CRLF "a=rtcp-fb:126 nack pli" CRLF
   3324    "a=rtcp-fb:126 ccm fir" CRLF "a=rtcp-fb:97 nack" CRLF
   3325    "a=rtcp-fb:97 nack pli" CRLF "a=rtcp-fb:97 ccm fir" CRLF
   3326    "a=rtcp-fb:* ccm tmmbr" CRLF "a=rtcp-fb:120 transport-cc" CRLF
   3327    "a=setup:actpass" CRLF "a=rtcp-mux" CRLF
   3328    "m=application 9 DTLS/SCTP 5000" CRLF "c=IN IP4 0.0.0.0" CRLF
   3329    "a=sctpmap:5000 webrtc-datachannel 16" CRLF "a=setup:actpass" CRLF;
   3330 
   3331 TEST_P(NewSdpTest, BasicAudioVideoDataSdpParse) {
   3332  ParseSdp(kBasicAudioVideoDataOffer, true);
   3333  ASSERT_EQ(0U, ParseErrorCount())
   3334      << "Got parse errors: " << SerializeParseErrors();
   3335 }
   3336 
   3337 TEST_P(NewSdpTest, CheckApplicationParameters) {
   3338  ParseSdp(kBasicAudioVideoDataOffer, true);
   3339  ASSERT_TRUE(!!Sdp());
   3340  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   3341      << "Wrong number of media sections";
   3342  ASSERT_EQ(SdpMediaSection::kAudio, Sdp()->GetMediaSection(0).GetMediaType())
   3343      << "Wrong type for first media section";
   3344  ASSERT_EQ(SdpMediaSection::kVideo, Sdp()->GetMediaSection(1).GetMediaType())
   3345      << "Wrong type for second media section";
   3346  ASSERT_EQ(SdpMediaSection::kApplication,
   3347            Sdp()->GetMediaSection(2).GetMediaType())
   3348      << "Wrong type for third media section";
   3349 
   3350  ASSERT_EQ(SdpMediaSection::kDtlsSctp, Sdp()->GetMediaSection(2).GetProtocol())
   3351      << "Wrong protocol for application";
   3352  auto app_formats = Sdp()->GetMediaSection(2).GetFormats();
   3353  ASSERT_EQ(1U, app_formats.size()) << "Wrong number of formats for audio";
   3354  ASSERT_EQ("5000", app_formats[0]);
   3355 
   3356  const SdpConnection& conn3 = Sdp()->GetMediaSection(2).GetConnection();
   3357  ASSERT_EQ(sdp::kIPv4, conn3.GetAddrType());
   3358  ASSERT_EQ("0.0.0.0", conn3.GetAddress());
   3359  ASSERT_EQ(0U, conn3.GetTtl());
   3360  ASSERT_EQ(0U, conn3.GetCount());
   3361 
   3362  ASSERT_TRUE(Sdp()->GetMediaSection(2).GetAttributeList().HasAttribute(
   3363      SdpAttribute::kSetupAttribute));
   3364  ASSERT_EQ(SdpSetupAttribute::kActpass,
   3365            Sdp()->GetMediaSection(2).GetAttributeList().GetSetup().mRole);
   3366 }
   3367 
   3368 TEST_P(NewSdpTest, CheckExtmap) {
   3369  ParseSdp(kBasicAudioVideoDataOffer, true);
   3370  ASSERT_TRUE(!!Sdp());
   3371  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   3372      << "Wrong number of media sections";
   3373 
   3374  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3375      SdpAttribute::kExtmapAttribute));
   3376 
   3377  auto extmaps =
   3378      Sdp()->GetMediaSection(0).GetAttributeList().GetExtmap().mExtmaps;
   3379  ASSERT_EQ(3U, extmaps.size());
   3380 
   3381  ASSERT_EQ(1U, extmaps[0].entry);
   3382  ASSERT_FALSE(extmaps[0].direction_specified);
   3383  ASSERT_EQ("urn:ietf:params:rtp-hdrext:ssrc-audio-level",
   3384            extmaps[0].extensionname);
   3385  ASSERT_EQ("", extmaps[0].extensionattributes);
   3386 
   3387  ASSERT_EQ(2U, extmaps[1].entry);
   3388  ASSERT_TRUE(extmaps[1].direction_specified);
   3389  ASSERT_EQ(SdpDirectionAttribute::kSendonly, extmaps[1].direction);
   3390  ASSERT_EQ("some_extension", extmaps[1].extensionname);
   3391  ASSERT_EQ("", extmaps[1].extensionattributes);
   3392 
   3393  ASSERT_EQ(3U, extmaps[2].entry);
   3394  ASSERT_FALSE(extmaps[2].direction_specified);
   3395  ASSERT_EQ("some_other_extension", extmaps[2].extensionname);
   3396  ASSERT_EQ("some_params some more params", extmaps[2].extensionattributes);
   3397 }
   3398 
   3399 TEST_P(NewSdpTest, CheckRtcpFb) {
   3400  ParseSdp(kBasicAudioVideoDataOffer, true);
   3401  ASSERT_TRUE(!!Sdp());
   3402  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   3403      << "Wrong number of media sections";
   3404 
   3405  auto& video_attrs = Sdp()->GetMediaSection(1).GetAttributeList();
   3406  ASSERT_TRUE(video_attrs.HasAttribute(SdpAttribute::kRtcpFbAttribute));
   3407  auto& rtcpfbs = video_attrs.GetRtcpFb().mFeedbacks;
   3408 
   3409  if (ResultsAreFromSipcc()) {
   3410    ASSERT_EQ(21U, rtcpfbs.size());
   3411  } else {
   3412    ASSERT_EQ("WEBRTCSDP", mResults->ParserName());
   3413    std::stringstream os;
   3414    Sdp()->Serialize(os);
   3415    // Reserialized results should be the same
   3416    if (::testing::get<1>(GetParam())) {
   3417      ASSERT_EQ(21U, rtcpfbs.size());
   3418    } else {
   3419      ASSERT_EQ(21U, rtcpfbs.size());
   3420    }
   3421  }
   3422 
   3423  CheckRtcpFb(rtcpfbs[0], "120", SdpRtcpFbAttributeList::kAck, "rpsi");
   3424  CheckRtcpFb(rtcpfbs[1], "120", SdpRtcpFbAttributeList::kAck, "app", "foo");
   3425  CheckRtcpFb(rtcpfbs[2], "120", SdpRtcpFbAttributeList::kNack, "");
   3426  CheckRtcpFb(rtcpfbs[3], "120", SdpRtcpFbAttributeList::kNack, "sli");
   3427  CheckRtcpFb(rtcpfbs[4], "120", SdpRtcpFbAttributeList::kNack, "pli");
   3428  CheckRtcpFb(rtcpfbs[5], "120", SdpRtcpFbAttributeList::kNack, "rpsi");
   3429  CheckRtcpFb(rtcpfbs[6], "120", SdpRtcpFbAttributeList::kNack, "app", "foo");
   3430  CheckRtcpFb(rtcpfbs[7], "120", SdpRtcpFbAttributeList::kCcm, "fir");
   3431  CheckRtcpFb(rtcpfbs[8], "120", SdpRtcpFbAttributeList::kCcm, "tmmbr");
   3432  CheckRtcpFb(rtcpfbs[9], "120", SdpRtcpFbAttributeList::kCcm, "tstr");
   3433  CheckRtcpFb(rtcpfbs[10], "120", SdpRtcpFbAttributeList::kCcm, "vbcm");
   3434  CheckRtcpFb(rtcpfbs[11], "120", SdpRtcpFbAttributeList::kTrrInt, "10");
   3435  CheckRtcpFb(rtcpfbs[12], "120", SdpRtcpFbAttributeList::kRemb, "");
   3436  CheckRtcpFb(rtcpfbs[13], "126", SdpRtcpFbAttributeList::kNack, "");
   3437  CheckRtcpFb(rtcpfbs[14], "126", SdpRtcpFbAttributeList::kNack, "pli");
   3438  CheckRtcpFb(rtcpfbs[15], "126", SdpRtcpFbAttributeList::kCcm, "fir");
   3439  CheckRtcpFb(rtcpfbs[16], "97", SdpRtcpFbAttributeList::kNack, "");
   3440  CheckRtcpFb(rtcpfbs[17], "97", SdpRtcpFbAttributeList::kNack, "pli");
   3441  CheckRtcpFb(rtcpfbs[18], "97", SdpRtcpFbAttributeList::kCcm, "fir");
   3442  CheckRtcpFb(rtcpfbs[19], "*", SdpRtcpFbAttributeList::kCcm, "tmmbr");
   3443  CheckRtcpFb(rtcpfbs[20], "120", SdpRtcpFbAttributeList::kTransportCC, "");
   3444 }
   3445 
   3446 TEST_P(NewSdpTest, CheckRtcp) {
   3447  ParseSdp(kBasicAudioVideoOffer);
   3448  ASSERT_TRUE(!!Sdp());
   3449  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   3450      << "Wrong number of media sections";
   3451 
   3452  ASSERT_FALSE(
   3453      Sdp()->GetAttributeList().HasAttribute(SdpAttribute::kRtcpAttribute));
   3454  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3455      SdpAttribute::kRtcpAttribute));
   3456  ASSERT_TRUE(Sdp()->GetMediaSection(1).GetAttributeList().HasAttribute(
   3457      SdpAttribute::kRtcpAttribute));
   3458  ASSERT_FALSE(Sdp()->GetMediaSection(2).GetAttributeList().HasAttribute(
   3459      SdpAttribute::kRtcpAttribute));
   3460 
   3461  auto& rtcpAttr_0 = Sdp()->GetMediaSection(0).GetAttributeList().GetRtcp();
   3462  ASSERT_EQ(62454U, rtcpAttr_0.mPort);
   3463  ASSERT_EQ(sdp::kInternet, rtcpAttr_0.mNetType);
   3464  ASSERT_EQ(sdp::kIPv4, rtcpAttr_0.mAddrType);
   3465  ASSERT_EQ("162.222.183.171", rtcpAttr_0.mAddress);
   3466 
   3467  auto& rtcpAttr_1 = Sdp()->GetMediaSection(1).GetAttributeList().GetRtcp();
   3468  ASSERT_EQ(61026U, rtcpAttr_1.mPort);
   3469  ASSERT_EQ("", rtcpAttr_1.mAddress);
   3470 }
   3471 
   3472 TEST_P(NewSdpTest, CheckImageattr) {
   3473  ParseSdp(kBasicAudioVideoOffer);
   3474  ASSERT_TRUE(!!Sdp());
   3475  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   3476      << "Wrong number of media sections";
   3477 
   3478  ASSERT_FALSE(Sdp()->GetAttributeList().HasAttribute(
   3479      SdpAttribute::kImageattrAttribute));
   3480  ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3481      SdpAttribute::kImageattrAttribute));
   3482  ASSERT_TRUE(Sdp()->GetMediaSection(1).GetAttributeList().HasAttribute(
   3483      SdpAttribute::kImageattrAttribute));
   3484  ASSERT_FALSE(Sdp()->GetMediaSection(2).GetAttributeList().HasAttribute(
   3485      SdpAttribute::kImageattrAttribute));
   3486 
   3487  const SdpImageattrAttributeList& imageattrs =
   3488      Sdp()->GetMediaSection(1).GetAttributeList().GetImageattr();
   3489 
   3490  ASSERT_EQ(2U, imageattrs.mImageattrs.size());
   3491  const SdpImageattrAttributeList::Imageattr& imageattr_0(
   3492      imageattrs.mImageattrs[0]);
   3493  ASSERT_TRUE(imageattr_0.pt.isSome());
   3494  ASSERT_EQ(120U, *imageattr_0.pt);
   3495  ASSERT_TRUE(imageattr_0.sendAll);
   3496  ASSERT_TRUE(imageattr_0.recvAll);
   3497 
   3498  const SdpImageattrAttributeList::Imageattr& imageattr_1(
   3499      imageattrs.mImageattrs[1]);
   3500  ASSERT_TRUE(imageattr_1.pt.isSome());
   3501  ASSERT_EQ(121U, *imageattr_1.pt);
   3502  ASSERT_FALSE(imageattr_1.sendAll);
   3503  ASSERT_FALSE(imageattr_1.recvAll);
   3504  ASSERT_EQ(1U, imageattr_1.sendSets.size());
   3505  ASSERT_EQ(1U, imageattr_1.sendSets[0].xRange.discreteValues.size());
   3506  ASSERT_EQ(640U, imageattr_1.sendSets[0].xRange.discreteValues.front());
   3507  ASSERT_EQ(1U, imageattr_1.sendSets[0].yRange.discreteValues.size());
   3508  ASSERT_EQ(480U, imageattr_1.sendSets[0].yRange.discreteValues.front());
   3509  ASSERT_EQ(1U, imageattr_1.recvSets.size());
   3510  ASSERT_EQ(1U, imageattr_1.recvSets[0].xRange.discreteValues.size());
   3511  ASSERT_EQ(640U, imageattr_1.recvSets[0].xRange.discreteValues.front());
   3512  ASSERT_EQ(1U, imageattr_1.recvSets[0].yRange.discreteValues.size());
   3513  ASSERT_EQ(480U, imageattr_1.recvSets[0].yRange.discreteValues.front());
   3514 }
   3515 
   3516 TEST_P(NewSdpTest, CheckSimulcast) {
   3517  ParseSdp(kBasicAudioVideoOffer);
   3518  ASSERT_TRUE(!!Sdp());
   3519  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   3520      << "Wrong number of media sections";
   3521 
   3522  ASSERT_FALSE(Sdp()->GetAttributeList().HasAttribute(
   3523      SdpAttribute::kSimulcastAttribute));
   3524  ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3525      SdpAttribute::kSimulcastAttribute));
   3526  ASSERT_TRUE(Sdp()->GetMediaSection(1).GetAttributeList().HasAttribute(
   3527      SdpAttribute::kSimulcastAttribute));
   3528  ASSERT_FALSE(Sdp()->GetMediaSection(2).GetAttributeList().HasAttribute(
   3529      SdpAttribute::kSimulcastAttribute));
   3530 
   3531  const SdpSimulcastAttribute& simulcast =
   3532      Sdp()->GetMediaSection(1).GetAttributeList().GetSimulcast();
   3533 
   3534  ASSERT_EQ(2U, simulcast.recvVersions.size());
   3535  ASSERT_EQ(0U, simulcast.sendVersions.size());
   3536  ASSERT_EQ(1U, simulcast.recvVersions[0].choices.size());
   3537  ASSERT_EQ("bar", simulcast.recvVersions[0].choices[0].rid);
   3538  ASSERT_EQ(1U, simulcast.recvVersions[1].choices.size());
   3539  ASSERT_EQ("bar123", simulcast.recvVersions[1].choices[0].rid);
   3540 }
   3541 
   3542 TEST_P(NewSdpTest, CheckSctpmap) {
   3543  ParseSdp(kBasicAudioVideoDataOffer);
   3544  ASSERT_TRUE(!!Sdp())
   3545  << "Parse failed: " << SerializeParseErrors();
   3546  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   3547      << "Wrong number of media sections";
   3548 
   3549  const SdpMediaSection& appsec = Sdp()->GetMediaSection(2);
   3550  ASSERT_TRUE(
   3551      appsec.GetAttributeList().HasAttribute(SdpAttribute::kSctpmapAttribute));
   3552  const SdpSctpmapAttributeList& sctpmap =
   3553      appsec.GetAttributeList().GetSctpmap();
   3554 
   3555  ASSERT_EQ(1U, sctpmap.mSctpmaps.size())
   3556      << "Wrong number of sctpmap attributes";
   3557  ASSERT_EQ(1U, appsec.GetFormats().size());
   3558 
   3559  // Need to know name of type
   3560  CheckSctpmap("5000", "webrtc-datachannel", 16, appsec.GetFormats()[0],
   3561               sctpmap);
   3562 }
   3563 
   3564 TEST_P(NewSdpTest, CheckMaxPtime) {
   3565  ParseSdp(kBasicAudioVideoOffer);
   3566  ASSERT_TRUE(!!Sdp())
   3567  << "Parse failed: " << SerializeParseErrors();
   3568  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   3569      << "Wrong number of media sections";
   3570 
   3571  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3572      SdpAttribute::kMaxptimeAttribute));
   3573  ASSERT_EQ(Sdp()->GetMediaSection(0).GetAttributeList().GetMaxptime(), 20U);
   3574 }
   3575 
   3576 MOZ_RUNINIT const std::string kNewSctpportOfferDraft21 =
   3577    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 27987 0 IN IP4 0.0.0.0" CRLF
   3578    "s=SIP Call" CRLF "t=0 0" CRLF "a=ice-ufrag:8a39d2ae" CRLF
   3579    "a=ice-pwd:601d53aba51a318351b3ecf5ee00048f" CRLF
   3580    "a=fingerprint:sha-256 "
   3581    "30:FF:8E:2B:AC:9D:ED:70:18:10:67:C8:AE:9E:68:F3:86:53:51:B0:AC:31:B7:BE:"
   3582    "6D:CF:A4:2E:D3:6E:B4:28" CRLF
   3583    "m=application 9 UDP/DTLS/SCTP webrtc-datachannel" CRLF
   3584    "c=IN IP4 0.0.0.0" CRLF "a=sctp-port:5000" CRLF
   3585    "a=max-message-size:10000" CRLF "a=setup:actpass" CRLF;
   3586 
   3587 TEST_P(NewSdpTest, NewSctpportSdpParse) {
   3588  ParseSdp(kNewSctpportOfferDraft21, false);
   3589 }
   3590 
   3591 INSTANTIATE_TEST_SUITE_P(RoundTripSerialize, NewSdpTest,
   3592                         ::testing::Combine(::testing::Bool(),
   3593                                            ::testing::Bool()));
   3594 
   3595 MOZ_RUNINIT const std::string kCandidateInSessionSDP =
   3596    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3597    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3598    "a=candidate:0 1 UDP 2130379007 10.0.0.36 62453 typ host" CRLF
   3599    "m=audio 9 RTP/SAVPF 109 9 0 8 101" CRLF "c=IN IP4 0.0.0.0" CRLF
   3600    "a=rtpmap:109 opus/48000/2" CRLF;
   3601 
   3602 // This may or may not parse, but if it does, the errant candidate attribute
   3603 // should be ignored.
   3604 TEST_P(NewSdpTest, CheckCandidateInSessionLevel) {
   3605  ParseSdp(kCandidateInSessionSDP, false);
   3606  if (Sdp()) {
   3607    ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3608        SdpAttribute::kCandidateAttribute));
   3609    ASSERT_FALSE(Sdp()->GetAttributeList().HasAttribute(
   3610        SdpAttribute::kCandidateAttribute));
   3611  }
   3612 }
   3613 
   3614 MOZ_RUNINIT const std::string kBundleOnlyInSessionSDP =
   3615    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3616    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3617    "a=bundle-only" CRLF "m=audio 9 RTP/SAVPF 109 9 0 8 101" CRLF
   3618    "c=IN IP4 0.0.0.0" CRLF "a=rtpmap:109 opus/48000/2" CRLF;
   3619 
   3620 // This may or may not parse, but if it does, the errant attribute
   3621 // should be ignored.
   3622 TEST_P(NewSdpTest, CheckBundleOnlyInSessionLevel) {
   3623  ParseSdp(kBundleOnlyInSessionSDP, false);
   3624  if (Sdp()) {
   3625    ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3626        SdpAttribute::kBundleOnlyAttribute));
   3627    ASSERT_FALSE(Sdp()->GetAttributeList().HasAttribute(
   3628        SdpAttribute::kBundleOnlyAttribute));
   3629  }
   3630 }
   3631 
   3632 MOZ_RUNINIT const std::string kFmtpInSessionSDP =
   3633    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3634    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3635    "a=fmtp:109 0-15" CRLF "m=audio 9 RTP/SAVPF 109 9 0 8 101" CRLF
   3636    "c=IN IP4 0.0.0.0" CRLF "a=rtpmap:109 opus/48000/2" CRLF;
   3637 
   3638 // This may or may not parse, but if it does, the errant attribute
   3639 // should be ignored.
   3640 TEST_P(NewSdpTest, CheckFmtpInSessionLevel) {
   3641  ParseSdp(kFmtpInSessionSDP, false);
   3642  if (Sdp()) {
   3643    ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3644        SdpAttribute::kFmtpAttribute));
   3645    ASSERT_FALSE(
   3646        Sdp()->GetAttributeList().HasAttribute(SdpAttribute::kFmtpAttribute));
   3647  }
   3648 }
   3649 
   3650 MOZ_RUNINIT const std::string kIceMismatchInSessionSDP =
   3651    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3652    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3653    "a=ice-mismatch" CRLF "m=audio 9 RTP/SAVPF 109 9 0 8 101" CRLF
   3654    "c=IN IP4 0.0.0.0" CRLF "a=rtpmap:109 opus/48000/2" CRLF;
   3655 
   3656 // This may or may not parse, but if it does, the errant attribute
   3657 // should be ignored.
   3658 TEST_P(NewSdpTest, CheckIceMismatchInSessionLevel) {
   3659  ParseSdp(kIceMismatchInSessionSDP, false);
   3660  if (Sdp()) {
   3661    ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3662        SdpAttribute::kIceMismatchAttribute));
   3663    ASSERT_FALSE(Sdp()->GetAttributeList().HasAttribute(
   3664        SdpAttribute::kIceMismatchAttribute));
   3665  }
   3666 }
   3667 
   3668 MOZ_RUNINIT const std::string kImageattrInSessionSDP =
   3669    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3670    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3671    "a=imageattr:120 send * recv *" CRLF "m=video 9 RTP/SAVPF 120" CRLF
   3672    "c=IN IP4 0.0.0.0" CRLF "a=rtpmap:120 VP8/90000" CRLF;
   3673 
   3674 // This may or may not parse, but if it does, the errant attribute
   3675 // should be ignored.
   3676 TEST_P(NewSdpTest, CheckImageattrInSessionLevel) {
   3677  ParseSdp(kImageattrInSessionSDP, false);
   3678  if (Sdp()) {
   3679    ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3680        SdpAttribute::kImageattrAttribute));
   3681    ASSERT_FALSE(Sdp()->GetAttributeList().HasAttribute(
   3682        SdpAttribute::kImageattrAttribute));
   3683  }
   3684 }
   3685 
   3686 MOZ_RUNINIT const std::string kLabelInSessionSDP =
   3687    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3688    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3689    "a=label:foobar" CRLF "m=video 9 RTP/SAVPF 120" CRLF "c=IN IP4 0.0.0.0" CRLF
   3690    "a=rtpmap:120 VP8/90000" CRLF;
   3691 
   3692 // This may or may not parse, but if it does, the errant attribute
   3693 // should be ignored.
   3694 TEST_P(NewSdpTest, CheckLabelInSessionLevel) {
   3695  ParseSdp(kLabelInSessionSDP, false);
   3696  if (Sdp()) {
   3697    ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3698        SdpAttribute::kLabelAttribute));
   3699    ASSERT_FALSE(
   3700        Sdp()->GetAttributeList().HasAttribute(SdpAttribute::kLabelAttribute));
   3701  }
   3702 }
   3703 
   3704 MOZ_RUNINIT const std::string kMaxptimeInSessionSDP =
   3705    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3706    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3707    "a=maxptime:100" CRLF "m=video 9 RTP/SAVPF 120" CRLF "c=IN IP4 0.0.0.0" CRLF
   3708    "a=rtpmap:120 VP8/90000" CRLF;
   3709 
   3710 // This may or may not parse, but if it does, the errant attribute
   3711 // should be ignored.
   3712 TEST_P(NewSdpTest, CheckMaxptimeInSessionLevel) {
   3713  ParseSdp(kMaxptimeInSessionSDP, false);
   3714  if (Sdp()) {
   3715    ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3716        SdpAttribute::kMaxptimeAttribute));
   3717    ASSERT_FALSE(Sdp()->GetAttributeList().HasAttribute(
   3718        SdpAttribute::kMaxptimeAttribute));
   3719  }
   3720 }
   3721 
   3722 MOZ_RUNINIT const std::string kMidInSessionSDP =
   3723    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3724    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3725    "a=mid:foobar" CRLF "m=video 9 RTP/SAVPF 120" CRLF "c=IN IP4 0.0.0.0" CRLF
   3726    "a=rtpmap:120 VP8/90000" CRLF;
   3727 
   3728 // This may or may not parse, but if it does, the errant attribute
   3729 // should be ignored.
   3730 TEST_P(NewSdpTest, CheckMidInSessionLevel) {
   3731  ParseSdp(kMidInSessionSDP, false);
   3732  if (Sdp()) {
   3733    ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3734        SdpAttribute::kMidAttribute));
   3735    ASSERT_FALSE(
   3736        Sdp()->GetAttributeList().HasAttribute(SdpAttribute::kMidAttribute));
   3737  }
   3738 }
   3739 
   3740 MOZ_RUNINIT const std::string kMsidInSessionSDP =
   3741    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3742    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3743    "a=msid:foobar" CRLF "m=video 9 RTP/SAVPF 120" CRLF "c=IN IP4 0.0.0.0" CRLF
   3744    "a=rtpmap:120 VP8/90000" CRLF;
   3745 
   3746 // This may or may not parse, but if it does, the errant attribute
   3747 // should be ignored.
   3748 TEST_P(NewSdpTest, CheckMsidInSessionLevel) {
   3749  ParseSdp(kMsidInSessionSDP, false);
   3750  if (Sdp()) {
   3751    ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3752        SdpAttribute::kMsidAttribute));
   3753    ASSERT_FALSE(
   3754        Sdp()->GetAttributeList().HasAttribute(SdpAttribute::kMsidAttribute));
   3755  }
   3756 }
   3757 
   3758 MOZ_RUNINIT const std::string kPtimeInSessionSDP =
   3759    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3760    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3761    "a=ptime:50" CRLF "m=video 9 RTP/SAVPF 120" CRLF "c=IN IP4 0.0.0.0" CRLF
   3762    "a=rtpmap:120 VP8/90000" CRLF;
   3763 
   3764 // This may or may not parse, but if it does, the errant attribute
   3765 // should be ignored.
   3766 TEST_P(NewSdpTest, CheckPtimeInSessionLevel) {
   3767  ParseSdp(kPtimeInSessionSDP, false);
   3768  if (Sdp()) {
   3769    ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3770        SdpAttribute::kPtimeAttribute));
   3771    ASSERT_FALSE(
   3772        Sdp()->GetAttributeList().HasAttribute(SdpAttribute::kPtimeAttribute));
   3773  }
   3774 }
   3775 
   3776 MOZ_RUNINIT const std::string kRemoteCandidatesInSessionSDP =
   3777    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3778    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3779    "a=remote-candidates:0 10.0.0.1 5555" CRLF "m=video 9 RTP/SAVPF 120" CRLF
   3780    "c=IN IP4 0.0.0.0" CRLF "a=rtpmap:120 VP8/90000" CRLF;
   3781 
   3782 // This may or may not parse, but if it does, the errant attribute
   3783 // should be ignored.
   3784 TEST_P(NewSdpTest, CheckRemoteCandidatesInSessionLevel) {
   3785  ParseSdp(kRemoteCandidatesInSessionSDP, false);
   3786  if (Sdp()) {
   3787    ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3788        SdpAttribute::kRemoteCandidatesAttribute));
   3789    ASSERT_FALSE(Sdp()->GetAttributeList().HasAttribute(
   3790        SdpAttribute::kRemoteCandidatesAttribute));
   3791  }
   3792 }
   3793 
   3794 MOZ_RUNINIT const std::string kRtcpInSessionSDP =
   3795    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3796    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3797    "a=rtcp:5555" CRLF "m=video 9 RTP/SAVPF 120" CRLF "c=IN IP4 0.0.0.0" CRLF
   3798    "a=rtpmap:120 VP8/90000" CRLF;
   3799 
   3800 // This may or may not parse, but if it does, the errant attribute
   3801 // should be ignored.
   3802 TEST_P(NewSdpTest, CheckRtcpInSessionLevel) {
   3803  ParseSdp(kRtcpInSessionSDP, false);
   3804  if (Sdp()) {
   3805    ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3806        SdpAttribute::kRtcpAttribute));
   3807    ASSERT_FALSE(
   3808        Sdp()->GetAttributeList().HasAttribute(SdpAttribute::kRtcpAttribute));
   3809  }
   3810 }
   3811 
   3812 MOZ_RUNINIT const std::string kRtcpFbInSessionSDP =
   3813    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3814    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3815    "a=rtcp-fb:120 nack" CRLF "m=video 9 RTP/SAVPF 120" CRLF
   3816    "c=IN IP4 0.0.0.0" CRLF "a=rtpmap:120 VP8/90000" CRLF;
   3817 
   3818 // This may or may not parse, but if it does, the errant attribute
   3819 // should be ignored.
   3820 TEST_P(NewSdpTest, CheckRtcpFbInSessionLevel) {
   3821  ParseSdp(kRtcpFbInSessionSDP, false, true);
   3822  if (Sdp()) {
   3823    ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3824        SdpAttribute::kRtcpFbAttribute));
   3825    ASSERT_FALSE(
   3826        Sdp()->GetAttributeList().HasAttribute(SdpAttribute::kRtcpFbAttribute));
   3827  }
   3828 }
   3829 
   3830 MOZ_RUNINIT const std::string kRtcpMuxInSessionSDP =
   3831    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3832    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3833    "a=rtcp-mux" CRLF "m=video 9 RTP/SAVPF 120" CRLF "c=IN IP4 0.0.0.0" CRLF
   3834    "a=rtpmap:120 VP8/90000" CRLF;
   3835 
   3836 // This may or may not parse, but if it does, the errant attribute
   3837 // should be ignored.
   3838 TEST_P(NewSdpTest, CheckRtcpMuxInSessionLevel) {
   3839  ParseSdp(kRtcpMuxInSessionSDP, false);
   3840  if (Sdp()) {
   3841    ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3842        SdpAttribute::kRtcpMuxAttribute));
   3843    ASSERT_FALSE(Sdp()->GetAttributeList().HasAttribute(
   3844        SdpAttribute::kRtcpMuxAttribute));
   3845  }
   3846 }
   3847 
   3848 MOZ_RUNINIT const std::string kRtcpRsizeInSessionSDP =
   3849    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3850    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3851    "a=rtcp-rsize" CRLF "m=video 9 RTP/SAVPF 120" CRLF "c=IN IP4 0.0.0.0" CRLF
   3852    "a=rtpmap:120 VP8/90000" CRLF;
   3853 
   3854 // This may or may not parse, but if it does, the errant attribute
   3855 // should be ignored.
   3856 TEST_P(NewSdpTest, CheckRtcpRsizeInSessionLevel) {
   3857  ParseSdp(kRtcpRsizeInSessionSDP, false);
   3858  if (Sdp()) {
   3859    ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3860        SdpAttribute::kRtcpRsizeAttribute));
   3861    ASSERT_FALSE(Sdp()->GetAttributeList().HasAttribute(
   3862        SdpAttribute::kRtcpRsizeAttribute));
   3863  }
   3864 }
   3865 
   3866 MOZ_RUNINIT const std::string kRtpmapInSessionSDP =
   3867    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3868    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3869    "a=rtpmap:120 VP8/90000" CRLF "m=video 9 RTP/SAVPF 120" CRLF
   3870    "c=IN IP4 0.0.0.0" CRLF;
   3871 
   3872 // This may or may not parse, but if it does, the errant attribute
   3873 // should be ignored.
   3874 TEST_P(NewSdpTest, CheckRtpmapInSessionLevel) {
   3875  ParseSdp(kRtpmapInSessionSDP, false);
   3876  if (Sdp()) {
   3877    ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3878        SdpAttribute::kRtpmapAttribute));
   3879    ASSERT_FALSE(
   3880        Sdp()->GetAttributeList().HasAttribute(SdpAttribute::kRtpmapAttribute));
   3881  }
   3882 }
   3883 
   3884 MOZ_RUNINIT const std::string kSctpmapInSessionSDP =
   3885    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3886    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3887    "a=sctpmap:5000" CRLF "m=video 9 RTP/SAVPF 120" CRLF "c=IN IP4 0.0.0.0" CRLF
   3888    "a=rtpmap:120 VP8/90000" CRLF;
   3889 
   3890 // This may or may not parse, but if it does, the errant attribute
   3891 // should be ignored.
   3892 TEST_P(NewSdpTest, CheckSctpmapInSessionLevel) {
   3893  ParseSdp(kSctpmapInSessionSDP, false);
   3894  if (Sdp()) {
   3895    ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3896        SdpAttribute::kSctpmapAttribute));
   3897    ASSERT_FALSE(Sdp()->GetAttributeList().HasAttribute(
   3898        SdpAttribute::kSctpmapAttribute));
   3899  }
   3900 }
   3901 
   3902 MOZ_RUNINIT const std::string kSsrcInSessionSDP =
   3903    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3904    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3905    "a=ssrc:5000" CRLF "m=video 9 RTP/SAVPF 120" CRLF "c=IN IP4 0.0.0.0" CRLF
   3906    "a=rtpmap:120 VP8/90000" CRLF;
   3907 
   3908 // This may or may not parse, but if it does, the errant attribute
   3909 // should be ignored.
   3910 TEST_P(NewSdpTest, CheckSsrcInSessionLevel) {
   3911  ParseSdp(kSsrcInSessionSDP, false);
   3912  if (Sdp()) {
   3913    ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   3914        SdpAttribute::kSsrcAttribute));
   3915    ASSERT_FALSE(
   3916        Sdp()->GetAttributeList().HasAttribute(SdpAttribute::kSsrcAttribute));
   3917  }
   3918 }
   3919 
   3920 MOZ_RUNINIT const std::string kMalformedImageattr =
   3921    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3922    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3923    "m=video 9 RTP/SAVPF 120" CRLF "c=IN IP4 0.0.0.0" CRLF
   3924    "a=rtpmap:120 VP8/90000" CRLF "a=imageattr:flob" CRLF;
   3925 
   3926 TEST_P(NewSdpTest, CheckMalformedImageattr) {
   3927  if (::testing::get<0>(GetParam())) {
   3928    // Don't do a parse/serialize before running this test
   3929    return;
   3930  }
   3931 
   3932  ParseSdp(kMalformedImageattr, false);
   3933  ASSERT_NE(0U, ParseErrorCount());
   3934 }
   3935 
   3936 TEST_P(NewSdpTest, ParseInvalidSimulcastNoSuchSendRid) {
   3937  ParseSdp("v=0" CRLF "o=- 4294967296 2 IN IP4 127.0.0.1" CRLF "s=SIP Call" CRLF
   3938           "c=IN IP4 198.51.100.7" CRLF "b=CT:5000" CRLF "t=0 0" CRLF
   3939           "m=video 56436 RTP/SAVPF 120" CRLF "a=rtpmap:120 VP8/90000" CRLF
   3940           "a=sendrecv" CRLF "a=simulcast:send 9" CRLF
   3941           "a=rid:9 recv max-width=800;max-height=600" CRLF,
   3942           false);
   3943  ASSERT_NE(0U, ParseErrorCount());
   3944 }
   3945 
   3946 TEST_P(NewSdpTest, ParseInvalidSimulcastNoSuchRecvRid) {
   3947  ParseSdp("v=0" CRLF "o=- 4294967296 2 IN IP4 127.0.0.1" CRLF "s=SIP Call" CRLF
   3948           "c=IN IP4 198.51.100.7" CRLF "b=CT:5000" CRLF "t=0 0" CRLF
   3949           "m=video 56436 RTP/SAVPF 120" CRLF "a=rtpmap:120 VP8/90000" CRLF
   3950           "a=sendrecv" CRLF "a=simulcast:recv 9" CRLF
   3951           "a=rid:9 send max-width=800;max-height=600" CRLF,
   3952           false);
   3953  ASSERT_NE(0U, ParseErrorCount());
   3954 }
   3955 
   3956 TEST_P(NewSdpTest, ParseSimulcastNotSending) {
   3957  ParseSdp("v=0" CRLF "o=- 4294967296 2 IN IP4 127.0.0.1" CRLF "s=SIP Call" CRLF
   3958           "c=IN IP4 198.51.100.7" CRLF "b=CT:5000" CRLF "t=0 0" CRLF
   3959           "m=video 56436 RTP/SAVPF 120" CRLF "a=rtpmap:120 VP8/90000" CRLF
   3960           "a=recvonly" CRLF "a=simulcast:send 120" CRLF "a=rid:120 send" CRLF,
   3961           false);
   3962  ASSERT_EQ(0U, ParseErrorCount());
   3963 }
   3964 
   3965 TEST_P(NewSdpTest, ParseSimulcastNotReceiving) {
   3966  ParseSdp("v=0" CRLF "o=- 4294967296 2 IN IP4 127.0.0.1" CRLF "s=SIP Call" CRLF
   3967           "c=IN IP4 198.51.100.7" CRLF "b=CT:5000" CRLF "t=0 0" CRLF
   3968           "m=video 56436 RTP/SAVPF 120" CRLF "a=rtpmap:120 VP8/90000" CRLF
   3969           "a=sendonly" CRLF "a=simulcast:recv 120" CRLF "a=rid:120 recv" CRLF,
   3970           false);
   3971  ASSERT_EQ(0U, ParseErrorCount());
   3972 }
   3973 
   3974 TEST_P(NewSdpTest, ParseInvalidRidNoSuchPt) {
   3975  SKIP_TEST_WITH_SIPCC_PARSER
   3976  ParseSdp("v=0" CRLF "o=- 4294967296 2 IN IP4 127.0.0.1" CRLF "s=SIP Call" CRLF
   3977           "c=IN IP4 198.51.100.7" CRLF "b=CT:5000" CRLF "t=0 0" CRLF
   3978           "m=video 56436 RTP/SAVPF 120" CRLF "a=rtpmap:120 VP8/90000" CRLF
   3979           "a=sendrecv" CRLF "a=simulcast:recv rid=9" CRLF
   3980           "a=rid:9 recv pt=101;max-width=800;max-height=600" CRLF,
   3981           false);
   3982  ASSERT_NE(0U, ParseErrorCount());
   3983 }
   3984 
   3985 MOZ_RUNINIT const std::string kNoAttributes =
   3986    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   3987    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   3988    "m=video 9 RTP/SAVPF 120" CRLF "c=IN IP4 0.0.0.0" CRLF
   3989    "a=rtpmap:120 VP8/90000" CRLF;
   3990 
   3991 TEST_P(NewSdpTest, CheckNoAttributes) {
   3992  ParseSdp(kNoAttributes);
   3993 
   3994  for (auto a = static_cast<size_t>(SdpAttribute::kFirstAttribute);
   3995       a <= static_cast<size_t>(SdpAttribute::kLastAttribute); ++a) {
   3996    SdpAttribute::AttributeType type =
   3997        static_cast<SdpAttribute::AttributeType>(a);
   3998 
   3999    // rtpmap is a special case right now, we throw parse errors if it is
   4000    // missing, and then insert one.
   4001    // direction is another special case that gets a default if not present
   4002    if (type != SdpAttribute::kRtpmapAttribute &&
   4003        type != SdpAttribute::kDirectionAttribute) {
   4004      ASSERT_FALSE(
   4005          Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(type))
   4006      << "Attribute " << a << " should not have been present at media level";
   4007      ASSERT_FALSE(Sdp()->GetAttributeList().HasAttribute(type))
   4008      << "Attribute " << a << " should not have been present at session level";
   4009    }
   4010  }
   4011 
   4012  ASSERT_FALSE(
   4013      Sdp()->GetAttributeList().HasAttribute(SdpAttribute::kRtpmapAttribute));
   4014 
   4015  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   4016      SdpAttribute::kDirectionAttribute));
   4017  ASSERT_EQ(SdpDirectionAttribute::kSendrecv,
   4018            Sdp()->GetMediaSection(0).GetAttributeList().GetDirection());
   4019  ASSERT_TRUE(Sdp()->GetAttributeList().HasAttribute(
   4020      SdpAttribute::kDirectionAttribute));
   4021  ASSERT_EQ(SdpDirectionAttribute::kSendrecv,
   4022            Sdp()->GetAttributeList().GetDirection());
   4023 }
   4024 
   4025 MOZ_RUNINIT const std::string kMediaLevelDtlsMessage =
   4026    "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   4027    "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   4028    "m=video 9 RTP/SAVPF 120" CRLF "c=IN IP4 0.0.0.0" CRLF
   4029    "a=dtls-message:client " BASE64_DTLS_HELLO CRLF
   4030    "a=rtpmap:120 VP8/90000" CRLF;
   4031 
   4032 TEST_P(NewSdpTest, CheckMediaLevelDtlsMessage) {
   4033  ParseSdp(kMediaLevelDtlsMessage);
   4034  ASSERT_TRUE(!!Sdp())
   4035  << "Parse failed: " << SerializeParseErrors();
   4036 
   4037  // dtls-message is not defined for use at the media level; we don't
   4038  // parse it
   4039  ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   4040      SdpAttribute::kDtlsMessageAttribute));
   4041 }
   4042 
   4043 TEST_P(NewSdpTest, CheckSetPort) {
   4044  // Parse any valid sdp with a media section
   4045  ParseSdp("v=0" CRLF "o=- 4294967296 2 IN IP4 127.0.0.1" CRLF "s=SIP Call" CRLF
   4046           "c=IN IP4 198.51.100.7" CRLF "b=CT:5000" CRLF "t=0 0" CRLF
   4047           "m=video 56436 RTP/SAVPF 120" CRLF "a=rtpmap:120 VP8/90000" CRLF
   4048           "a=sendonly" CRLF,
   4049           false);
   4050 
   4051  ASSERT_TRUE(!!Sdp())
   4052  << "Parse failed: " << SerializeParseErrors();
   4053 
   4054  constexpr unsigned int expectedParesPort = 56436;
   4055  unsigned int currentPort = Sdp()->GetMediaSection(0).GetPort();
   4056  ASSERT_EQ(expectedParesPort, currentPort);
   4057 
   4058  Sdp()->GetMediaSection(0).SetPort(currentPort + 1);
   4059  ASSERT_EQ(currentPort + 1, Sdp()->GetMediaSection(0).GetPort());
   4060 }
   4061 
   4062 TEST_P(NewSdpTest, CheckAddCodec) {
   4063  // Parse any valid sdp with a media section
   4064  ParseSdp("v=0" CRLF "o=- 4294967296 2 IN IP4 127.0.0.1" CRLF "s=SIP Call" CRLF
   4065           "c=IN IP4 198.51.100.7" CRLF "b=CT:5000" CRLF "t=0 0" CRLF
   4066           "m=video 56436 RTP/SAVPF 120" CRLF "a=rtpmap:120 VP8/90000" CRLF
   4067           "a=sendonly" CRLF);
   4068 
   4069  ASSERT_TRUE(!!Sdp())
   4070  << "Parse failed: " << SerializeParseErrors();
   4071  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount());
   4072 
   4073  ASSERT_EQ(1U, Sdp()->GetMediaSection(0).GetFormats().size());
   4074  ASSERT_EQ(
   4075      1U,
   4076      Sdp()->GetMediaSection(0).GetAttributeList().GetRtpmap().mRtpmaps.size());
   4077 
   4078  Sdp()->GetMediaSection(0).AddCodec("110", "opus", 48000, 2);
   4079 
   4080  ASSERT_EQ(2U, Sdp()->GetMediaSection(0).GetFormats().size());
   4081  const auto& rtpmaps =
   4082      Sdp()->GetMediaSection(0).GetAttributeList().GetRtpmap();
   4083  ASSERT_EQ(2U, rtpmaps.mRtpmaps.size());
   4084 
   4085  ASSERT_TRUE(rtpmaps.HasEntry("120"));
   4086  ASSERT_TRUE(rtpmaps.HasEntry("110"));
   4087  const auto aRtpmap = rtpmaps.GetEntry("110");
   4088  ASSERT_EQ(aRtpmap.pt, "110");
   4089  ASSERT_EQ(aRtpmap.codec, SdpRtpmapAttributeList::kOpus);
   4090  ASSERT_EQ(aRtpmap.name, "opus");
   4091  ASSERT_EQ(aRtpmap.clock, 48000U);
   4092  ASSERT_EQ(aRtpmap.channels, 2U);
   4093 }
   4094 
   4095 TEST_P(NewSdpTest, CheckClearCodecs) {
   4096  // Parse any valid sdp with a media section
   4097  ParseSdp("v=0" CRLF "o=- 4294967296 2 IN IP4 127.0.0.1" CRLF "s=SIP Call" CRLF
   4098           "c=IN IP4 198.51.100.7" CRLF "b=CT:5000" CRLF "t=0 0" CRLF
   4099           "m=video 56436 RTP/SAVPF 120 110" CRLF "a=rtpmap:120 VP8/90000" CRLF
   4100           "a=sendonly" CRLF "a=rtpmap:110 opus/48000" CRLF);
   4101  // SIPCC strips the channels on opus so the /2 was omitted
   4102 
   4103  ASSERT_TRUE(!!Sdp())
   4104  << "Parse failed: " << SerializeParseErrors();
   4105  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount());
   4106 
   4107  ASSERT_EQ(2U, Sdp()->GetMediaSection(0).GetFormats().size());
   4108  ASSERT_EQ(
   4109      2U,
   4110      Sdp()->GetMediaSection(0).GetAttributeList().GetRtpmap().mRtpmaps.size());
   4111 
   4112  Sdp()->GetMediaSection(0).ClearCodecs();
   4113 
   4114  ASSERT_EQ(0U, Sdp()->GetMediaSection(0).GetFormats().size());
   4115  ASSERT_FALSE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   4116      SdpAttribute::kRtpmapAttribute));
   4117 }
   4118 
   4119 TEST_P(NewSdpTest, CheckAddMediaSection) {
   4120  ParseSdp(kBasicAudioVideoOffer);
   4121 
   4122  ASSERT_TRUE(!!Sdp())
   4123  << "Parse failed: " << SerializeParseErrors();
   4124  ASSERT_EQ(3U, Sdp()->GetMediaSectionCount())
   4125      << "Wrong number of media sections";
   4126 
   4127  Sdp()->AddMediaSection(
   4128      SdpMediaSection::kVideo, SdpDirectionAttribute::Direction::kSendrecv,
   4129      58000, SdpMediaSection::kUdpDtlsSctp, sdp::kIPv4, "127.0.0.1");
   4130 
   4131  ASSERT_EQ(4U, Sdp()->GetMediaSectionCount())
   4132      << "Wrong number of media sections after adding media section";
   4133 
   4134  const SdpMediaSection& newMediaSection = Sdp()->GetMediaSection(3);
   4135 
   4136  ASSERT_EQ(SdpMediaSection::kVideo, newMediaSection.GetMediaType());
   4137  ASSERT_EQ(SdpDirectionAttribute::Direction::kSendrecv,
   4138            newMediaSection.GetDirectionAttribute().mValue);
   4139  ASSERT_EQ(58000U, newMediaSection.GetPort());
   4140  ASSERT_EQ(SdpMediaSection::kUdpDtlsSctp, newMediaSection.GetProtocol());
   4141  ASSERT_EQ(sdp::kIPv4, newMediaSection.GetConnection().GetAddrType());
   4142  ASSERT_EQ("127.0.0.1", newMediaSection.GetConnection().GetAddress());
   4143 
   4144  Sdp()->AddMediaSection(SdpMediaSection::kAudio,
   4145                         SdpDirectionAttribute::Direction::kSendonly, 14006,
   4146                         SdpMediaSection::kTcpDtlsRtpSavpf, sdp::kIPv6,
   4147                         "2607:f8b0:4004:801::2013");
   4148 
   4149  ASSERT_EQ(5U, Sdp()->GetMediaSectionCount())
   4150      << "Wrong number of media sections after adding media section";
   4151 
   4152  const SdpMediaSection& nextNewMediaSection = Sdp()->GetMediaSection(4);
   4153 
   4154  ASSERT_EQ(SdpMediaSection::kAudio, nextNewMediaSection.GetMediaType());
   4155  ASSERT_EQ(SdpDirectionAttribute::Direction::kSendonly,
   4156            nextNewMediaSection.GetDirectionAttribute().mValue);
   4157  ASSERT_EQ(14006U, nextNewMediaSection.GetPort());
   4158  ASSERT_EQ(SdpMediaSection::kTcpDtlsRtpSavpf,
   4159            nextNewMediaSection.GetProtocol());
   4160  ASSERT_EQ(sdp::kIPv6, nextNewMediaSection.GetConnection().GetAddrType());
   4161  ASSERT_EQ("2607:f8b0:4004:801::2013",
   4162            nextNewMediaSection.GetConnection().GetAddress());
   4163 
   4164  if (!ResultsAreFromSipcc()) {
   4165    // All following AddMediaSection calls are expected to fail
   4166    // SdpMediaSection::kDccpRtpAvp is expected to cause a failure
   4167    Sdp()->AddMediaSection(SdpMediaSection::kAudio,
   4168                           SdpDirectionAttribute::Direction::kSendonly, 14006,
   4169                           SdpMediaSection::kDccpRtpAvp, sdp::kIPv6,
   4170                           "2607:f8b0:4004:801::2013");
   4171    ASSERT_EQ(5U, Sdp()->GetMediaSectionCount())
   4172        << "Wrong number of media sections after adding media section";
   4173 
   4174    // sdp::kAddrTypeNone is expected to cause a failure
   4175    Sdp()->AddMediaSection(SdpMediaSection::kAudio,
   4176                           SdpDirectionAttribute::Direction::kSendonly, 14006,
   4177                           SdpMediaSection::kDtlsSctp, sdp::kAddrTypeNone,
   4178                           "2607:f8b0:4004:801::2013");
   4179    ASSERT_EQ(5U, Sdp()->GetMediaSectionCount())
   4180        << "Wrong number of media sections after adding media section";
   4181 
   4182    // "NOT:AN.IP.ADDRESS" is expected to cause a failure
   4183    Sdp()->AddMediaSection(SdpMediaSection::kAudio,
   4184                           SdpDirectionAttribute::Direction::kSendonly, 14006,
   4185                           SdpMediaSection::kTcpDtlsRtpSavpf, sdp::kIPv6,
   4186                           "NOT:AN.IP.ADDRESS");
   4187    ASSERT_EQ(5U, Sdp()->GetMediaSectionCount())
   4188        << "Wrong number of media sections after adding media section";
   4189  }
   4190 }
   4191 
   4192 TEST_P(NewSdpTest, CheckAddDataChannel_Draft05) {
   4193  // Parse any valid sdp with a media section
   4194  ParseSdp("v=0" CRLF "o=- 4294967296 2 IN IP4 127.0.0.1" CRLF "s=SIP Call" CRLF
   4195           "c=IN IP4 198.51.100.7" CRLF "b=CT:5000" CRLF "t=0 0" CRLF
   4196           "m=application 56436 DTLS/SCTP 5000" CRLF);
   4197 
   4198  ASSERT_TRUE(!!Sdp())
   4199  << "Parse failed: " << SerializeParseErrors();
   4200  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount());
   4201 
   4202  auto& mediaSection = Sdp()->GetMediaSection(0);
   4203  mediaSection.AddDataChannel("webrtc-datachannel", 6000, 16, 0);
   4204 
   4205  ASSERT_FALSE(mediaSection.GetAttributeList().HasAttribute(
   4206      SdpAttribute::kMaxMessageSizeAttribute));
   4207  ASSERT_TRUE(mediaSection.GetAttributeList().HasAttribute(
   4208      SdpAttribute::kSctpmapAttribute));
   4209  ASSERT_TRUE(mediaSection.GetAttributeList().GetSctpmap().HasEntry("6000"));
   4210  ASSERT_EQ(
   4211      16U,
   4212      mediaSection.GetAttributeList().GetSctpmap().GetFirstEntry().streams);
   4213  ASSERT_EQ("webrtc-datachannel",
   4214            mediaSection.GetAttributeList().GetSctpmap().GetFirstEntry().name);
   4215 
   4216  mediaSection.AddDataChannel("webrtc-datachannel", 15000, 8, 1800);
   4217 
   4218  ASSERT_TRUE(mediaSection.GetAttributeList().HasAttribute(
   4219      SdpAttribute::kMaxMessageSizeAttribute));
   4220  ASSERT_EQ(1800U, mediaSection.GetAttributeList().GetMaxMessageSize());
   4221  ASSERT_TRUE(mediaSection.GetAttributeList().HasAttribute(
   4222      SdpAttribute::kSctpmapAttribute));
   4223  ASSERT_TRUE(mediaSection.GetAttributeList().GetSctpmap().HasEntry("15000"));
   4224  ASSERT_EQ(
   4225      8U, mediaSection.GetAttributeList().GetSctpmap().GetFirstEntry().streams);
   4226 }
   4227 
   4228 TEST_P(NewSdpTest, CheckAddDataChannel) {
   4229  ParseSdp("v=0" CRLF "o=- 4294967296 2 IN IP4 127.0.0.1" CRLF "s=SIP Call" CRLF
   4230           "c=IN IP4 198.51.100.7" CRLF "b=CT:5000" CRLF "t=0 0" CRLF
   4231           "m=application 56436 UDP/DTLS/SCTP webrtc-datachannel" CRLF);
   4232 
   4233  ASSERT_TRUE(!!Sdp())
   4234  << "Parse failed: " << SerializeParseErrors();
   4235  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount());
   4236 
   4237  auto& mediaSection = Sdp()->GetMediaSection(0);
   4238  mediaSection.AddDataChannel("webrtc-datachannel", 6000, 16, 0);
   4239 
   4240  ASSERT_FALSE(mediaSection.GetAttributeList().HasAttribute(
   4241      SdpAttribute::kMaxMessageSizeAttribute));
   4242  ASSERT_TRUE(mediaSection.GetAttributeList().HasAttribute(
   4243      SdpAttribute::kSctpPortAttribute));
   4244  ASSERT_EQ(6000U, mediaSection.GetAttributeList().GetSctpPort());
   4245 
   4246  mediaSection.AddDataChannel("webrtc-datachannel", 15000, 8, 1800);
   4247 
   4248  ASSERT_TRUE(mediaSection.GetAttributeList().HasAttribute(
   4249      SdpAttribute::kMaxMessageSizeAttribute));
   4250  ASSERT_EQ(1800U, mediaSection.GetAttributeList().GetMaxMessageSize());
   4251  ASSERT_TRUE(mediaSection.GetAttributeList().HasAttribute(
   4252      SdpAttribute::kSctpPortAttribute));
   4253  ASSERT_EQ(15000U, mediaSection.GetAttributeList().GetSctpPort());
   4254 }
   4255 
   4256 TEST(NewSdpTestNoFixture, CheckParsingResultComparer)
   4257 {
   4258  auto check_comparison = [](const std::string sdp_string) {
   4259    SipccSdpParser sipccParser;
   4260    RsdparsaSdpParser rustParser;
   4261    auto print_errors =
   4262        [](const mozilla::UniquePtr<SdpParser::Results>& results,
   4263           const char* name) {
   4264          for (const auto& e : results->Errors()) {
   4265            std::cerr << name << " Line " << e.first << ": " << e.second;
   4266          }
   4267        };
   4268    auto sipccResults = sipccParser.Parse(sdp_string);
   4269    auto sipccSdp = std::move(sipccResults->Sdp());
   4270    print_errors(sipccResults, "sipcc");
   4271 
   4272    auto rustResults = rustParser.Parse(sdp_string);
   4273    auto rustSdp = std::move(rustResults->Sdp());
   4274    print_errors(rustResults, "webrtc-sdp");
   4275 
   4276    ParsingResultComparer comparer;
   4277    return sipccSdp && rustSdp
   4278               ? comparer.Compare(*rustSdp, *sipccSdp, sdp_string)
   4279               : false;
   4280  };
   4281 
   4282  ASSERT_TRUE(check_comparison(kBasicAudioVideoOffer));
   4283  ASSERT_TRUE(check_comparison(kBasicAudioVideoOfferLinefeedOnly));
   4284  ASSERT_TRUE(check_comparison(kH264AudioVideoOffer));
   4285 
   4286  // Check the Fmtp comprison
   4287  const std::string kBasicOpusFmtp1 =
   4288      "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   4289      "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   4290      "m=video 9 RTP/SAVPF 120" CRLF "a=rtpmap:120 opus/48000/1" CRLF
   4291      "a=fmtp:120 stereo=1;useinbandfec=1" CRLF;
   4292  ASSERT_TRUE(check_comparison(kBasicOpusFmtp1));
   4293 
   4294  const std::string kBasicOpusFmtp2 =
   4295      "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   4296      "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   4297      "m=video 9 RTP/SAVPF 120" CRLF "a=rtpmap:120 opus/48000" CRLF
   4298      "a=fmtp:120 useinbandfec=1;stereo=1;maxplaybackrate=32000" CRLF;
   4299  ASSERT_TRUE(check_comparison(kBasicOpusFmtp2));
   4300 
   4301  const std::string kBasicVP8Fmtp1 =
   4302      "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   4303      "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   4304      "m=video 9 RTP/SAVPF 120" CRLF "a=rtpmap:120 VP8/90000" CRLF
   4305      "a=fmtp:120 max-fs=3600;max-fr=60" CRLF;
   4306  ASSERT_TRUE(check_comparison(kBasicVP8Fmtp1));
   4307  //
   4308  const std::string kBasicVP8Fmtp2 =
   4309      "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   4310      "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   4311      "m=video 9 RTP/SAVPF 120" CRLF "a=rtpmap:120 VP8/90000" CRLF
   4312      "a=fmtp:120 max-fr=60;max-fs=3600" CRLF;
   4313  ASSERT_TRUE(check_comparison(kBasicVP8Fmtp2));
   4314 
   4315  const std::string kBasicH264Fmtp1 =
   4316      "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   4317      "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   4318      "m=video 9 RTP/SAVPF 120" CRLF "a=rtpmap:120 H264/90000" CRLF
   4319      "a=fmtp:120 profile-level-id=42a01e;level_asymmetry_allowed=1" CRLF;
   4320  ASSERT_TRUE(check_comparison(kBasicH264Fmtp1));
   4321 
   4322  const std::string kBasicH264Fmtp2 =
   4323      "v=0" CRLF "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
   4324      "s=SIP Call" CRLF "c=IN IP4 224.0.0.1/100/12" CRLF "t=0 0" CRLF
   4325      "m=video 9 RTP/SAVPF 120" CRLF "a=rtpmap:120 H264/90000" CRLF
   4326      "a=fmtp:120 "
   4327      "level_asymmetry_allowed=1;profile-level-id=42a01e;max_fs=3600" CRLF;
   4328  ASSERT_TRUE(check_comparison(kBasicH264Fmtp2));
   4329 }
   4330 
   4331 TEST(NewSdpTestNoFixture, CheckAttributeTypeSerialize)
   4332 {
   4333  for (auto a = static_cast<size_t>(SdpAttribute::kFirstAttribute);
   4334       a <= static_cast<size_t>(SdpAttribute::kLastAttribute); ++a) {
   4335    SdpAttribute::AttributeType type =
   4336        static_cast<SdpAttribute::AttributeType>(a);
   4337 
   4338    // Direction attributes are handled a little differently
   4339    if (type != SdpAttribute::kDirectionAttribute) {
   4340      std::ostringstream os;
   4341      os << type;
   4342      ASSERT_NE("", os.str());
   4343    }
   4344  }
   4345 }
   4346 
   4347 static SdpImageattrAttributeList::XYRange ParseXYRange(
   4348    const std::string& input) {
   4349  std::istringstream is(input + ",");
   4350  std::string error;
   4351  SdpImageattrAttributeList::XYRange range;
   4352  EXPECT_TRUE(range.Parse(is, &error)) << error;
   4353  EXPECT_EQ(',', is.get());
   4354  EXPECT_EQ(EOF, is.get());
   4355  return range;
   4356 }
   4357 
   4358 TEST(NewSdpTestNoFixture, CheckImageattrXYRangeParseValid)
   4359 {
   4360  {
   4361    SdpImageattrAttributeList::XYRange range(ParseXYRange("640"));
   4362    ASSERT_EQ(1U, range.discreteValues.size());
   4363    ASSERT_EQ(640U, range.discreteValues[0]);
   4364  }
   4365 
   4366  {
   4367    SdpImageattrAttributeList::XYRange range(ParseXYRange("[320,640]"));
   4368    ASSERT_EQ(2U, range.discreteValues.size());
   4369    ASSERT_EQ(320U, range.discreteValues[0]);
   4370    ASSERT_EQ(640U, range.discreteValues[1]);
   4371  }
   4372 
   4373  {
   4374    SdpImageattrAttributeList::XYRange range(ParseXYRange("[320,640,1024]"));
   4375    ASSERT_EQ(3U, range.discreteValues.size());
   4376    ASSERT_EQ(320U, range.discreteValues[0]);
   4377    ASSERT_EQ(640U, range.discreteValues[1]);
   4378    ASSERT_EQ(1024U, range.discreteValues[2]);
   4379  }
   4380 
   4381  {
   4382    SdpImageattrAttributeList::XYRange range(ParseXYRange("[320:640]"));
   4383    ASSERT_EQ(0U, range.discreteValues.size());
   4384    ASSERT_EQ(320U, range.min);
   4385    ASSERT_EQ(1U, range.step);
   4386    ASSERT_EQ(640U, range.max);
   4387  }
   4388 
   4389  {
   4390    SdpImageattrAttributeList::XYRange range(ParseXYRange("[320:16:640]"));
   4391    ASSERT_EQ(0U, range.discreteValues.size());
   4392    ASSERT_EQ(320U, range.min);
   4393    ASSERT_EQ(16U, range.step);
   4394    ASSERT_EQ(640U, range.max);
   4395  }
   4396 }
   4397 
   4398 template <typename T>
   4399 void ParseInvalid(const std::string& input, size_t last) {
   4400  std::istringstream is(input);
   4401  T parsed;
   4402  std::string error;
   4403  ASSERT_FALSE(parsed.Parse(is, &error))
   4404  << "\'" << input << "\' should not have parsed successfully";
   4405  is.clear();
   4406  ASSERT_EQ(last, static_cast<size_t>(is.tellg()))
   4407      << "Parse failed at unexpected location:" << std::endl
   4408      << input << std::endl
   4409      << std::string(is.tellg(), ' ') << "^" << std::endl;
   4410  // For a human to eyeball to make sure the error strings look sane
   4411  std::cout << "\"" << input << "\" - " << error << std::endl;
   4412 }
   4413 
   4414 TEST(NewSdpTestNoFixture, CheckImageattrXYRangeParseInvalid)
   4415 {
   4416  ParseInvalid<SdpImageattrAttributeList::XYRange>("[-1", 1);
   4417  ParseInvalid<SdpImageattrAttributeList::XYRange>("[-", 1);
   4418  ParseInvalid<SdpImageattrAttributeList::XYRange>("[-v", 1);
   4419  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640:-1", 5);
   4420  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640:16:-1", 8);
   4421  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640,-1", 5);
   4422  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640,-]", 5);
   4423  ParseInvalid<SdpImageattrAttributeList::XYRange>("-v", 0);
   4424  ParseInvalid<SdpImageattrAttributeList::XYRange>("-1", 0);
   4425  ParseInvalid<SdpImageattrAttributeList::XYRange>("", 0);
   4426  ParseInvalid<SdpImageattrAttributeList::XYRange>("[", 1);
   4427  ParseInvalid<SdpImageattrAttributeList::XYRange>("[v", 1);
   4428  ParseInvalid<SdpImageattrAttributeList::XYRange>("[", 1);
   4429  ParseInvalid<SdpImageattrAttributeList::XYRange>("[ 640", 1);
   4430  // It looks like the overflow detection only happens once the whole number
   4431  // is scanned...
   4432  ParseInvalid<SdpImageattrAttributeList::XYRange>("[99999999999999999:", 18);
   4433  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640", 4);
   4434  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640:", 5);
   4435  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640:v", 5);
   4436  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640:16", 7);
   4437  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640:16:", 8);
   4438  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640:16:v", 8);
   4439  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640:16:320]", 11);
   4440  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640:16:320", 11);
   4441  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640:16:320v", 11);
   4442  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640:1024", 9);
   4443  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640:320]", 8);
   4444  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640:1024v", 9);
   4445  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640,", 5);
   4446  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640,v", 5);
   4447  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640]", 4);
   4448  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640x", 4);
   4449  ParseInvalid<SdpImageattrAttributeList::XYRange>("[640,]", 5);
   4450  ParseInvalid<SdpImageattrAttributeList::XYRange>(" ", 0);
   4451  ParseInvalid<SdpImageattrAttributeList::XYRange>("v", 0);
   4452 }
   4453 
   4454 static SdpImageattrAttributeList::SRange ParseSRange(const std::string& input) {
   4455  std::istringstream is(input + ",");
   4456  std::string error;
   4457  SdpImageattrAttributeList::SRange range;
   4458  EXPECT_TRUE(range.Parse(is, &error)) << error;
   4459  EXPECT_EQ(',', is.get());
   4460  EXPECT_EQ(EOF, is.get());
   4461  return range;
   4462 }
   4463 
   4464 TEST(NewSdpTestNoFixture, CheckImageattrSRangeParseValid)
   4465 {
   4466  {
   4467    SdpImageattrAttributeList::SRange range(ParseSRange("0.1"));
   4468    ASSERT_EQ(1U, range.discreteValues.size());
   4469    ASSERT_FLOAT_EQ(0.1f, range.discreteValues[0]);
   4470  }
   4471 
   4472  {
   4473    SdpImageattrAttributeList::SRange range(ParseSRange("[0.1,0.2]"));
   4474    ASSERT_EQ(2U, range.discreteValues.size());
   4475    ASSERT_FLOAT_EQ(0.1f, range.discreteValues[0]);
   4476    ASSERT_FLOAT_EQ(0.2f, range.discreteValues[1]);
   4477  }
   4478 
   4479  {
   4480    SdpImageattrAttributeList::SRange range(ParseSRange("[0.1,0.2,0.3]"));
   4481    ASSERT_EQ(3U, range.discreteValues.size());
   4482    ASSERT_FLOAT_EQ(0.1f, range.discreteValues[0]);
   4483    ASSERT_FLOAT_EQ(0.2f, range.discreteValues[1]);
   4484    ASSERT_FLOAT_EQ(0.3f, range.discreteValues[2]);
   4485  }
   4486 
   4487  {
   4488    SdpImageattrAttributeList::SRange range(ParseSRange("[0.1-0.2]"));
   4489    ASSERT_EQ(0U, range.discreteValues.size());
   4490    ASSERT_FLOAT_EQ(0.1f, range.min);
   4491    ASSERT_FLOAT_EQ(0.2f, range.max);
   4492  }
   4493 }
   4494 
   4495 TEST(NewSdpTestNoFixture, CheckImageattrSRangeParseInvalid)
   4496 {
   4497  ParseInvalid<SdpImageattrAttributeList::SRange>("", 0);
   4498  ParseInvalid<SdpImageattrAttributeList::SRange>("[", 1);
   4499  ParseInvalid<SdpImageattrAttributeList::SRange>("[v", 1);
   4500  ParseInvalid<SdpImageattrAttributeList::SRange>("[-1", 1);
   4501  ParseInvalid<SdpImageattrAttributeList::SRange>("[", 1);
   4502  ParseInvalid<SdpImageattrAttributeList::SRange>("[-", 1);
   4503  ParseInvalid<SdpImageattrAttributeList::SRange>("[v", 1);
   4504  ParseInvalid<SdpImageattrAttributeList::SRange>("[ 0.2", 1);
   4505  ParseInvalid<SdpImageattrAttributeList::SRange>("[10.1-", 5);
   4506  ParseInvalid<SdpImageattrAttributeList::SRange>("[0.08-", 5);
   4507  ParseInvalid<SdpImageattrAttributeList::SRange>("[0.2", 4);
   4508  ParseInvalid<SdpImageattrAttributeList::SRange>("[0.2-", 5);
   4509  ParseInvalid<SdpImageattrAttributeList::SRange>("[0.2-v", 5);
   4510  ParseInvalid<SdpImageattrAttributeList::SRange>("[0.2--1", 5);
   4511  ParseInvalid<SdpImageattrAttributeList::SRange>("[0.2-0.3", 8);
   4512  ParseInvalid<SdpImageattrAttributeList::SRange>("[0.2-0.1]", 8);
   4513  ParseInvalid<SdpImageattrAttributeList::SRange>("[0.2-0.3v", 8);
   4514  ParseInvalid<SdpImageattrAttributeList::SRange>("[0.2,", 5);
   4515  ParseInvalid<SdpImageattrAttributeList::SRange>("[0.2,v", 5);
   4516  ParseInvalid<SdpImageattrAttributeList::SRange>("[0.2,-1", 5);
   4517  ParseInvalid<SdpImageattrAttributeList::SRange>("[0.2]", 4);
   4518  ParseInvalid<SdpImageattrAttributeList::SRange>("[0.2v", 4);
   4519  ParseInvalid<SdpImageattrAttributeList::SRange>("[0.2,]", 5);
   4520  ParseInvalid<SdpImageattrAttributeList::SRange>("[0.2,-]", 5);
   4521  ParseInvalid<SdpImageattrAttributeList::SRange>(" ", 0);
   4522  ParseInvalid<SdpImageattrAttributeList::SRange>("v", 0);
   4523  ParseInvalid<SdpImageattrAttributeList::SRange>("-v", 0);
   4524  ParseInvalid<SdpImageattrAttributeList::SRange>("-1", 0);
   4525 }
   4526 
   4527 static SdpImageattrAttributeList::PRange ParsePRange(const std::string& input) {
   4528  std::istringstream is(input + ",");
   4529  std::string error;
   4530  SdpImageattrAttributeList::PRange range;
   4531  EXPECT_TRUE(range.Parse(is, &error)) << error;
   4532  EXPECT_EQ(',', is.get());
   4533  EXPECT_EQ(EOF, is.get());
   4534  return range;
   4535 }
   4536 
   4537 TEST(NewSdpTestNoFixture, CheckImageattrPRangeParseValid)
   4538 {
   4539  SdpImageattrAttributeList::PRange range(ParsePRange("[0.1000-9.9999]"));
   4540  ASSERT_FLOAT_EQ(0.1f, range.min);
   4541  ASSERT_FLOAT_EQ(9.9999f, range.max);
   4542 }
   4543 
   4544 TEST(NewSdpTestNoFixture, CheckImageattrPRangeParseInvalid)
   4545 {
   4546  ParseInvalid<SdpImageattrAttributeList::PRange>("", 0);
   4547  ParseInvalid<SdpImageattrAttributeList::PRange>("[", 1);
   4548  ParseInvalid<SdpImageattrAttributeList::PRange>("[v", 1);
   4549  ParseInvalid<SdpImageattrAttributeList::PRange>("[-1", 1);
   4550  ParseInvalid<SdpImageattrAttributeList::PRange>("[", 1);
   4551  ParseInvalid<SdpImageattrAttributeList::PRange>("[-", 1);
   4552  ParseInvalid<SdpImageattrAttributeList::PRange>("[v", 1);
   4553  ParseInvalid<SdpImageattrAttributeList::PRange>("[ 0.2", 1);
   4554  ParseInvalid<SdpImageattrAttributeList::PRange>("[10.1-", 5);
   4555  ParseInvalid<SdpImageattrAttributeList::PRange>("[0.08-", 5);
   4556  ParseInvalid<SdpImageattrAttributeList::PRange>("[0.2", 4);
   4557  ParseInvalid<SdpImageattrAttributeList::PRange>("[0.2-", 5);
   4558  ParseInvalid<SdpImageattrAttributeList::PRange>("[0.2-v", 5);
   4559  ParseInvalid<SdpImageattrAttributeList::PRange>("[0.2--1", 5);
   4560  ParseInvalid<SdpImageattrAttributeList::PRange>("[0.2-0.3", 8);
   4561  ParseInvalid<SdpImageattrAttributeList::PRange>("[0.2-0.1]", 8);
   4562  ParseInvalid<SdpImageattrAttributeList::PRange>("[0.2-0.3v", 8);
   4563  ParseInvalid<SdpImageattrAttributeList::PRange>("[0.2,", 4);
   4564  ParseInvalid<SdpImageattrAttributeList::PRange>("[0.2:", 4);
   4565  ParseInvalid<SdpImageattrAttributeList::PRange>("[0.2]", 4);
   4566  ParseInvalid<SdpImageattrAttributeList::PRange>("[0.2v", 4);
   4567  ParseInvalid<SdpImageattrAttributeList::PRange>(" ", 0);
   4568  ParseInvalid<SdpImageattrAttributeList::PRange>("v", 0);
   4569  ParseInvalid<SdpImageattrAttributeList::PRange>("-x", 0);
   4570  ParseInvalid<SdpImageattrAttributeList::PRange>("-1", 0);
   4571 }
   4572 
   4573 static SdpImageattrAttributeList::Set ParseSet(const std::string& input) {
   4574  std::istringstream is(input + " ");
   4575  std::string error;
   4576  SdpImageattrAttributeList::Set set;
   4577  EXPECT_TRUE(set.Parse(is, &error)) << error;
   4578  EXPECT_EQ(' ', is.get());
   4579  EXPECT_EQ(EOF, is.get());
   4580  return set;
   4581 }
   4582 
   4583 TEST(NewSdpTestNoFixture, CheckImageattrSetParseValid)
   4584 {
   4585  {
   4586    SdpImageattrAttributeList::Set set(ParseSet("[x=320,y=240]"));
   4587    ASSERT_EQ(1U, set.xRange.discreteValues.size());
   4588    ASSERT_EQ(320U, set.xRange.discreteValues[0]);
   4589    ASSERT_EQ(1U, set.yRange.discreteValues.size());
   4590    ASSERT_EQ(240U, set.yRange.discreteValues[0]);
   4591    ASSERT_FALSE(set.sRange.IsSet());
   4592    ASSERT_FALSE(set.pRange.IsSet());
   4593    ASSERT_FLOAT_EQ(0.5f, set.qValue);
   4594  }
   4595 
   4596  {
   4597    SdpImageattrAttributeList::Set set(ParseSet("[X=320,Y=240]"));
   4598    ASSERT_EQ(1U, set.xRange.discreteValues.size());
   4599    ASSERT_EQ(320U, set.xRange.discreteValues[0]);
   4600    ASSERT_EQ(1U, set.yRange.discreteValues.size());
   4601    ASSERT_EQ(240U, set.yRange.discreteValues[0]);
   4602    ASSERT_FALSE(set.sRange.IsSet());
   4603    ASSERT_FALSE(set.pRange.IsSet());
   4604    ASSERT_FLOAT_EQ(0.5f, set.qValue);
   4605  }
   4606 
   4607  {
   4608    SdpImageattrAttributeList::Set set(ParseSet("[x=320,y=240,par=[0.1-0.2]]"));
   4609    ASSERT_EQ(1U, set.xRange.discreteValues.size());
   4610    ASSERT_EQ(320U, set.xRange.discreteValues[0]);
   4611    ASSERT_EQ(1U, set.yRange.discreteValues.size());
   4612    ASSERT_EQ(240U, set.yRange.discreteValues[0]);
   4613    ASSERT_FALSE(set.sRange.IsSet());
   4614    ASSERT_TRUE(set.pRange.IsSet());
   4615    ASSERT_FLOAT_EQ(0.1f, set.pRange.min);
   4616    ASSERT_FLOAT_EQ(0.2f, set.pRange.max);
   4617    ASSERT_FLOAT_EQ(0.5f, set.qValue);
   4618  }
   4619 
   4620  {
   4621    SdpImageattrAttributeList::Set set(ParseSet("[x=320,y=240,sar=[0.1-0.2]]"));
   4622    ASSERT_EQ(1U, set.xRange.discreteValues.size());
   4623    ASSERT_EQ(320U, set.xRange.discreteValues[0]);
   4624    ASSERT_EQ(1U, set.yRange.discreteValues.size());
   4625    ASSERT_EQ(240U, set.yRange.discreteValues[0]);
   4626    ASSERT_TRUE(set.sRange.IsSet());
   4627    ASSERT_FLOAT_EQ(0.1f, set.sRange.min);
   4628    ASSERT_FLOAT_EQ(0.2f, set.sRange.max);
   4629    ASSERT_FALSE(set.pRange.IsSet());
   4630    ASSERT_FLOAT_EQ(0.5f, set.qValue);
   4631  }
   4632 
   4633  {
   4634    SdpImageattrAttributeList::Set set(ParseSet("[x=320,y=240,q=0.1]"));
   4635    ASSERT_EQ(1U, set.xRange.discreteValues.size());
   4636    ASSERT_EQ(320U, set.xRange.discreteValues[0]);
   4637    ASSERT_EQ(1U, set.yRange.discreteValues.size());
   4638    ASSERT_EQ(240U, set.yRange.discreteValues[0]);
   4639    ASSERT_FALSE(set.sRange.IsSet());
   4640    ASSERT_FALSE(set.pRange.IsSet());
   4641    ASSERT_FLOAT_EQ(0.1f, set.qValue);
   4642  }
   4643 
   4644  {
   4645    SdpImageattrAttributeList::Set set(
   4646        ParseSet("[x=320,y=240,par=[0.1-0.2],sar=[0.3-0.4],q=0.6]"));
   4647    ASSERT_EQ(1U, set.xRange.discreteValues.size());
   4648    ASSERT_EQ(320U, set.xRange.discreteValues[0]);
   4649    ASSERT_EQ(1U, set.yRange.discreteValues.size());
   4650    ASSERT_EQ(240U, set.yRange.discreteValues[0]);
   4651    ASSERT_TRUE(set.sRange.IsSet());
   4652    ASSERT_FLOAT_EQ(0.3f, set.sRange.min);
   4653    ASSERT_FLOAT_EQ(0.4f, set.sRange.max);
   4654    ASSERT_TRUE(set.pRange.IsSet());
   4655    ASSERT_FLOAT_EQ(0.1f, set.pRange.min);
   4656    ASSERT_FLOAT_EQ(0.2f, set.pRange.max);
   4657    ASSERT_FLOAT_EQ(0.6f, set.qValue);
   4658  }
   4659 
   4660  {
   4661    SdpImageattrAttributeList::Set set(ParseSet("[x=320,y=240,foo=bar,q=0.1]"));
   4662    ASSERT_EQ(1U, set.xRange.discreteValues.size());
   4663    ASSERT_EQ(320U, set.xRange.discreteValues[0]);
   4664    ASSERT_EQ(1U, set.yRange.discreteValues.size());
   4665    ASSERT_EQ(240U, set.yRange.discreteValues[0]);
   4666    ASSERT_FALSE(set.sRange.IsSet());
   4667    ASSERT_FALSE(set.pRange.IsSet());
   4668    ASSERT_FLOAT_EQ(0.1f, set.qValue);
   4669  }
   4670 
   4671  {
   4672    SdpImageattrAttributeList::Set set(
   4673        ParseSet("[x=320,y=240,foo=bar,q=0.1,bar=baz]"));
   4674    ASSERT_EQ(1U, set.xRange.discreteValues.size());
   4675    ASSERT_EQ(320U, set.xRange.discreteValues[0]);
   4676    ASSERT_EQ(1U, set.yRange.discreteValues.size());
   4677    ASSERT_EQ(240U, set.yRange.discreteValues[0]);
   4678    ASSERT_FALSE(set.sRange.IsSet());
   4679    ASSERT_FALSE(set.pRange.IsSet());
   4680    ASSERT_FLOAT_EQ(0.1f, set.qValue);
   4681  }
   4682 
   4683  {
   4684    SdpImageattrAttributeList::Set set(
   4685        ParseSet("[x=320,y=240,foo=[bar],q=0.1,bar=[baz]]"));
   4686    ASSERT_EQ(1U, set.xRange.discreteValues.size());
   4687    ASSERT_EQ(320U, set.xRange.discreteValues[0]);
   4688    ASSERT_EQ(1U, set.yRange.discreteValues.size());
   4689    ASSERT_EQ(240U, set.yRange.discreteValues[0]);
   4690    ASSERT_FALSE(set.sRange.IsSet());
   4691    ASSERT_FALSE(set.pRange.IsSet());
   4692    ASSERT_FLOAT_EQ(0.1f, set.qValue);
   4693  }
   4694 
   4695  {
   4696    SdpImageattrAttributeList::Set set(
   4697        ParseSet("[x=320,y=240,foo=[par=foo,sar=bar],q=0.1,bar=[baz]]"));
   4698    ASSERT_EQ(1U, set.xRange.discreteValues.size());
   4699    ASSERT_EQ(320U, set.xRange.discreteValues[0]);
   4700    ASSERT_EQ(1U, set.yRange.discreteValues.size());
   4701    ASSERT_EQ(240U, set.yRange.discreteValues[0]);
   4702    ASSERT_FALSE(set.sRange.IsSet());
   4703    ASSERT_FALSE(set.pRange.IsSet());
   4704    ASSERT_FLOAT_EQ(0.1f, set.qValue);
   4705  }
   4706 }
   4707 
   4708 TEST(NewSdpTestNoFixture, CheckImageattrSetParseInvalid)
   4709 {
   4710  ParseInvalid<SdpImageattrAttributeList::Set>("", 0);
   4711  ParseInvalid<SdpImageattrAttributeList::Set>("x", 0);
   4712  ParseInvalid<SdpImageattrAttributeList::Set>("[", 1);
   4713  ParseInvalid<SdpImageattrAttributeList::Set>("[=", 2);
   4714  ParseInvalid<SdpImageattrAttributeList::Set>("[x", 2);
   4715  ParseInvalid<SdpImageattrAttributeList::Set>("[y=", 3);
   4716  ParseInvalid<SdpImageattrAttributeList::Set>("[x=[", 4);
   4717  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320", 6);
   4718  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320v", 6);
   4719  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,", 7);
   4720  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,=", 8);
   4721  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,x", 8);
   4722  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,x=", 9);
   4723  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,y=[", 10);
   4724  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,y=240", 12);
   4725  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,y=240x", 12);
   4726  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,y=240,", 13);
   4727  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,y=240,q=", 15);
   4728  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,y=240,q=v", 15);
   4729  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,y=240,q=0.5", 18);
   4730  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,y=240,q=0.5,", 19);
   4731  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,y=240,q=0.5,]", 20);
   4732  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,y=240,q=0.5,=]", 20);
   4733  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,y=240,q=0.5,sar=v]", 23);
   4734  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,y=240,q=0.5,q=0.4", 21);
   4735  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,y=240,sar=", 17);
   4736  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,y=240,sar=v", 17);
   4737  ParseInvalid<SdpImageattrAttributeList::Set>(
   4738      "[x=320,y=240,sar=[0.5-0.6],sar=[0.7-0.8]", 31);
   4739  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,y=240,par=", 17);
   4740  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,y=240,par=x", 17);
   4741  ParseInvalid<SdpImageattrAttributeList::Set>(
   4742      "[x=320,y=240,par=[0.5-0.6],par=[0.7-0.8]", 31);
   4743  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,y=240,foo=", 17);
   4744  ParseInvalid<SdpImageattrAttributeList::Set>("[x=320,y=240,foo=x", 18);
   4745 }
   4746 
   4747 static SdpImageattrAttributeList::Imageattr ParseImageattr(
   4748    const std::string& input) {
   4749  std::istringstream is(input);
   4750  std::string error;
   4751  SdpImageattrAttributeList::Imageattr imageattr;
   4752  EXPECT_TRUE(imageattr.Parse(is, &error)) << error;
   4753  EXPECT_TRUE(is.eof());
   4754  return imageattr;
   4755 }
   4756 
   4757 TEST(NewSdpTestNoFixture, CheckImageattrParseValid)
   4758 {
   4759  {
   4760    SdpImageattrAttributeList::Imageattr imageattr(ParseImageattr("* send *"));
   4761    ASSERT_FALSE(imageattr.pt.isSome());
   4762    ASSERT_TRUE(imageattr.sendAll);
   4763    ASSERT_TRUE(imageattr.sendSets.empty());
   4764    ASSERT_FALSE(imageattr.recvAll);
   4765    ASSERT_TRUE(imageattr.recvSets.empty());
   4766  }
   4767 
   4768  {
   4769    SdpImageattrAttributeList::Imageattr imageattr(ParseImageattr("* SEND *"));
   4770    ASSERT_FALSE(imageattr.pt.isSome());
   4771    ASSERT_TRUE(imageattr.sendAll);
   4772    ASSERT_TRUE(imageattr.sendSets.empty());
   4773    ASSERT_FALSE(imageattr.recvAll);
   4774    ASSERT_TRUE(imageattr.recvSets.empty());
   4775  }
   4776 
   4777  {
   4778    SdpImageattrAttributeList::Imageattr imageattr(ParseImageattr("* recv *"));
   4779    ASSERT_FALSE(imageattr.pt.isSome());
   4780    ASSERT_FALSE(imageattr.sendAll);
   4781    ASSERT_TRUE(imageattr.sendSets.empty());
   4782    ASSERT_TRUE(imageattr.recvAll);
   4783    ASSERT_TRUE(imageattr.recvSets.empty());
   4784  }
   4785 
   4786  {
   4787    SdpImageattrAttributeList::Imageattr imageattr(ParseImageattr("* RECV *"));
   4788    ASSERT_FALSE(imageattr.pt.isSome());
   4789    ASSERT_FALSE(imageattr.sendAll);
   4790    ASSERT_TRUE(imageattr.sendSets.empty());
   4791    ASSERT_TRUE(imageattr.recvAll);
   4792    ASSERT_TRUE(imageattr.recvSets.empty());
   4793  }
   4794 
   4795  {
   4796    SdpImageattrAttributeList::Imageattr imageattr(
   4797        ParseImageattr("* recv * send *"));
   4798    ASSERT_FALSE(imageattr.pt.isSome());
   4799    ASSERT_TRUE(imageattr.sendAll);
   4800    ASSERT_TRUE(imageattr.sendSets.empty());
   4801    ASSERT_TRUE(imageattr.recvAll);
   4802    ASSERT_TRUE(imageattr.recvSets.empty());
   4803  }
   4804 
   4805  {
   4806    SdpImageattrAttributeList::Imageattr imageattr(
   4807        ParseImageattr("* send * recv *"));
   4808    ASSERT_FALSE(imageattr.pt.isSome());
   4809    ASSERT_TRUE(imageattr.sendAll);
   4810    ASSERT_TRUE(imageattr.sendSets.empty());
   4811    ASSERT_TRUE(imageattr.recvAll);
   4812    ASSERT_TRUE(imageattr.recvSets.empty());
   4813  }
   4814 
   4815  {
   4816    SdpImageattrAttributeList::Imageattr imageattr(
   4817        ParseImageattr("8 send * recv *"));
   4818    ASSERT_EQ(8U, *imageattr.pt);
   4819    ASSERT_TRUE(imageattr.sendAll);
   4820    ASSERT_TRUE(imageattr.sendSets.empty());
   4821    ASSERT_TRUE(imageattr.recvAll);
   4822    ASSERT_TRUE(imageattr.recvSets.empty());
   4823  }
   4824 
   4825  {
   4826    SdpImageattrAttributeList::Imageattr imageattr(
   4827        ParseImageattr("8 send [x=320,y=240] recv *"));
   4828    ASSERT_EQ(8U, *imageattr.pt);
   4829    ASSERT_FALSE(imageattr.sendAll);
   4830    ASSERT_EQ(1U, imageattr.sendSets.size());
   4831    ASSERT_EQ(1U, imageattr.sendSets[0].xRange.discreteValues.size());
   4832    ASSERT_EQ(320U, imageattr.sendSets[0].xRange.discreteValues[0]);
   4833    ASSERT_EQ(1U, imageattr.sendSets[0].yRange.discreteValues.size());
   4834    ASSERT_EQ(240U, imageattr.sendSets[0].yRange.discreteValues[0]);
   4835    ASSERT_TRUE(imageattr.recvAll);
   4836    ASSERT_TRUE(imageattr.recvSets.empty());
   4837  }
   4838 
   4839  {
   4840    SdpImageattrAttributeList::Imageattr imageattr(
   4841        ParseImageattr("8 send [x=320,y=240] [x=640,y=480] recv *"));
   4842    ASSERT_EQ(8U, *imageattr.pt);
   4843    ASSERT_FALSE(imageattr.sendAll);
   4844    ASSERT_EQ(2U, imageattr.sendSets.size());
   4845    ASSERT_EQ(1U, imageattr.sendSets[0].xRange.discreteValues.size());
   4846    ASSERT_EQ(320U, imageattr.sendSets[0].xRange.discreteValues[0]);
   4847    ASSERT_EQ(1U, imageattr.sendSets[0].yRange.discreteValues.size());
   4848    ASSERT_EQ(240U, imageattr.sendSets[0].yRange.discreteValues[0]);
   4849    ASSERT_EQ(1U, imageattr.sendSets[1].xRange.discreteValues.size());
   4850    ASSERT_EQ(640U, imageattr.sendSets[1].xRange.discreteValues[0]);
   4851    ASSERT_EQ(1U, imageattr.sendSets[1].yRange.discreteValues.size());
   4852    ASSERT_EQ(480U, imageattr.sendSets[1].yRange.discreteValues[0]);
   4853    ASSERT_TRUE(imageattr.recvAll);
   4854    ASSERT_TRUE(imageattr.recvSets.empty());
   4855  }
   4856 
   4857  {
   4858    SdpImageattrAttributeList::Imageattr imageattr(
   4859        ParseImageattr("8 send * recv [x=320,y=240]"));
   4860    ASSERT_EQ(8U, *imageattr.pt);
   4861    ASSERT_FALSE(imageattr.recvAll);
   4862    ASSERT_EQ(1U, imageattr.recvSets.size());
   4863    ASSERT_EQ(1U, imageattr.recvSets[0].xRange.discreteValues.size());
   4864    ASSERT_EQ(320U, imageattr.recvSets[0].xRange.discreteValues[0]);
   4865    ASSERT_EQ(1U, imageattr.recvSets[0].yRange.discreteValues.size());
   4866    ASSERT_EQ(240U, imageattr.recvSets[0].yRange.discreteValues[0]);
   4867    ASSERT_TRUE(imageattr.sendAll);
   4868    ASSERT_TRUE(imageattr.sendSets.empty());
   4869  }
   4870 
   4871  {
   4872    SdpImageattrAttributeList::Imageattr imageattr(
   4873        ParseImageattr("8 send * recv [x=320,y=240] [x=640,y=480]"));
   4874    ASSERT_EQ(8U, *imageattr.pt);
   4875    ASSERT_FALSE(imageattr.recvAll);
   4876    ASSERT_EQ(2U, imageattr.recvSets.size());
   4877    ASSERT_EQ(1U, imageattr.recvSets[0].xRange.discreteValues.size());
   4878    ASSERT_EQ(320U, imageattr.recvSets[0].xRange.discreteValues[0]);
   4879    ASSERT_EQ(1U, imageattr.recvSets[0].yRange.discreteValues.size());
   4880    ASSERT_EQ(240U, imageattr.recvSets[0].yRange.discreteValues[0]);
   4881    ASSERT_EQ(1U, imageattr.recvSets[1].xRange.discreteValues.size());
   4882    ASSERT_EQ(640U, imageattr.recvSets[1].xRange.discreteValues[0]);
   4883    ASSERT_EQ(1U, imageattr.recvSets[1].yRange.discreteValues.size());
   4884    ASSERT_EQ(480U, imageattr.recvSets[1].yRange.discreteValues[0]);
   4885    ASSERT_TRUE(imageattr.sendAll);
   4886    ASSERT_TRUE(imageattr.sendSets.empty());
   4887  }
   4888 }
   4889 
   4890 TEST(NewSdpTestNoFixture, CheckImageattrParseInvalid)
   4891 {
   4892  ParseInvalid<SdpImageattrAttributeList::Imageattr>("", 0);
   4893  ParseInvalid<SdpImageattrAttributeList::Imageattr>(" ", 0);
   4894  ParseInvalid<SdpImageattrAttributeList::Imageattr>("-1", 0);
   4895  ParseInvalid<SdpImageattrAttributeList::Imageattr>("99999 ", 5);
   4896  ParseInvalid<SdpImageattrAttributeList::Imageattr>("*", 1);
   4897  ParseInvalid<SdpImageattrAttributeList::Imageattr>("* sen", 5);
   4898  ParseInvalid<SdpImageattrAttributeList::Imageattr>("* vcer *", 6);
   4899  ParseInvalid<SdpImageattrAttributeList::Imageattr>("* send x", 7);
   4900  ParseInvalid<SdpImageattrAttributeList::Imageattr>("* send [x=640,y=480] [",
   4901                                                     22);
   4902  ParseInvalid<SdpImageattrAttributeList::Imageattr>("* send * sen", 12);
   4903  ParseInvalid<SdpImageattrAttributeList::Imageattr>("* send * vcer *", 13);
   4904  ParseInvalid<SdpImageattrAttributeList::Imageattr>("* send * send *", 13);
   4905  ParseInvalid<SdpImageattrAttributeList::Imageattr>("* recv * recv *", 13);
   4906  ParseInvalid<SdpImageattrAttributeList::Imageattr>("* send * recv x", 14);
   4907  ParseInvalid<SdpImageattrAttributeList::Imageattr>(
   4908      "* send * recv [x=640,y=480] [", 29);
   4909  ParseInvalid<SdpImageattrAttributeList::Imageattr>(
   4910      "* send * recv [x=640,y=480] *", 28);
   4911  ParseInvalid<SdpImageattrAttributeList::Imageattr>(
   4912      "* send * recv [x=640,y=480] foobajooba", 28);
   4913 }
   4914 
   4915 TEST(NewSdpTestNoFixture, CheckImageattrXYRangeSerialization)
   4916 {
   4917  SdpImageattrAttributeList::XYRange range;
   4918  std::stringstream os;
   4919 
   4920  range.min = 320;
   4921  range.max = 640;
   4922  range.Serialize(os);
   4923  ASSERT_EQ("[320:640]", os.str());
   4924  os.str("");  // clear
   4925 
   4926  range.step = 16;
   4927  range.Serialize(os);
   4928  ASSERT_EQ("[320:16:640]", os.str());
   4929  os.str("");  // clear
   4930 
   4931  range.min = 0;
   4932  range.max = 0;
   4933  range.discreteValues.push_back(320);
   4934  range.Serialize(os);
   4935  ASSERT_EQ("320", os.str());
   4936  os.str("");
   4937 
   4938  range.discreteValues.push_back(640);
   4939  range.Serialize(os);
   4940  ASSERT_EQ("[320,640]", os.str());
   4941 }
   4942 
   4943 TEST(NewSdpTestNoFixture, CheckImageattrSRangeSerialization)
   4944 {
   4945  SdpImageattrAttributeList::SRange range;
   4946  std::ostringstream os;
   4947 
   4948  range.min = 0.1f;
   4949  range.max = 0.9999f;
   4950  range.Serialize(os);
   4951  ASSERT_EQ("[0.1000-0.9999]", os.str());
   4952  os.str("");
   4953 
   4954  range.min = 0.0f;
   4955  range.max = 0.0f;
   4956  range.discreteValues.push_back(0.1f);
   4957  range.Serialize(os);
   4958  ASSERT_EQ("0.1000", os.str());
   4959  os.str("");
   4960 
   4961  range.discreteValues.push_back(0.5f);
   4962  range.Serialize(os);
   4963  ASSERT_EQ("[0.1000,0.5000]", os.str());
   4964 }
   4965 
   4966 TEST(NewSdpTestNoFixture, CheckImageattrPRangeSerialization)
   4967 {
   4968  SdpImageattrAttributeList::PRange range;
   4969  std::ostringstream os;
   4970 
   4971  range.min = 0.1f;
   4972  range.max = 0.9999f;
   4973  range.Serialize(os);
   4974  ASSERT_EQ("[0.1000-0.9999]", os.str());
   4975 }
   4976 
   4977 TEST(NewSdpTestNoFixture, CheckImageattrSetSerialization)
   4978 {
   4979  SdpImageattrAttributeList::Set set;
   4980  std::ostringstream os;
   4981 
   4982  set.xRange.discreteValues.push_back(640);
   4983  set.yRange.discreteValues.push_back(480);
   4984  set.Serialize(os);
   4985  ASSERT_EQ("[x=640,y=480]", os.str());
   4986  os.str("");
   4987 
   4988  set.qValue = 0.00f;
   4989  set.Serialize(os);
   4990  ASSERT_EQ("[x=640,y=480,q=0.00]", os.str());
   4991  os.str("");
   4992 
   4993  set.qValue = 0.10f;
   4994  set.Serialize(os);
   4995  ASSERT_EQ("[x=640,y=480,q=0.10]", os.str());
   4996  os.str("");
   4997 
   4998  set.qValue = 1.00f;
   4999  set.Serialize(os);
   5000  ASSERT_EQ("[x=640,y=480,q=1.00]", os.str());
   5001  os.str("");
   5002 
   5003  set.sRange.discreteValues.push_back(1.1f);
   5004  set.Serialize(os);
   5005  ASSERT_EQ("[x=640,y=480,sar=1.1000,q=1.00]", os.str());
   5006  os.str("");
   5007 
   5008  set.pRange.min = 0.9f;
   5009  set.pRange.max = 1.1f;
   5010  set.Serialize(os);
   5011  ASSERT_EQ("[x=640,y=480,sar=1.1000,par=[0.9000-1.1000],q=1.00]", os.str());
   5012  os.str("");
   5013 }
   5014 
   5015 TEST(NewSdpTestNoFixture, CheckImageattrSerialization)
   5016 {
   5017  SdpImageattrAttributeList::Imageattr imageattr;
   5018  std::ostringstream os;
   5019 
   5020  imageattr.sendAll = true;
   5021  imageattr.pt = Some<uint16_t>(8U);
   5022  imageattr.Serialize(os);
   5023  ASSERT_EQ("8 send *", os.str());
   5024  os.str("");
   5025 
   5026  imageattr.pt.reset();
   5027  ;
   5028  imageattr.Serialize(os);
   5029  ASSERT_EQ("* send *", os.str());
   5030  os.str("");
   5031 
   5032  imageattr.sendAll = false;
   5033  imageattr.recvAll = true;
   5034  imageattr.Serialize(os);
   5035  ASSERT_EQ("* recv *", os.str());
   5036  os.str("");
   5037 
   5038  imageattr.sendAll = true;
   5039  imageattr.Serialize(os);
   5040  ASSERT_EQ("* send * recv *", os.str());
   5041  os.str("");
   5042 
   5043  imageattr.sendAll = false;
   5044  imageattr.sendSets.push_back(SdpImageattrAttributeList::Set());
   5045  imageattr.sendSets.back().xRange.discreteValues.push_back(320);
   5046  imageattr.sendSets.back().yRange.discreteValues.push_back(240);
   5047  imageattr.Serialize(os);
   5048  ASSERT_EQ("* send [x=320,y=240] recv *", os.str());
   5049  os.str("");
   5050 
   5051  imageattr.sendSets.push_back(SdpImageattrAttributeList::Set());
   5052  imageattr.sendSets.back().xRange.discreteValues.push_back(640);
   5053  imageattr.sendSets.back().yRange.discreteValues.push_back(480);
   5054  imageattr.Serialize(os);
   5055  ASSERT_EQ("* send [x=320,y=240] [x=640,y=480] recv *", os.str());
   5056  os.str("");
   5057 
   5058  imageattr.recvAll = false;
   5059  imageattr.recvSets.push_back(SdpImageattrAttributeList::Set());
   5060  imageattr.recvSets.back().xRange.discreteValues.push_back(320);
   5061  imageattr.recvSets.back().yRange.discreteValues.push_back(240);
   5062  imageattr.Serialize(os);
   5063  ASSERT_EQ("* send [x=320,y=240] [x=640,y=480] recv [x=320,y=240]", os.str());
   5064  os.str("");
   5065 
   5066  imageattr.recvSets.push_back(SdpImageattrAttributeList::Set());
   5067  imageattr.recvSets.back().xRange.discreteValues.push_back(640);
   5068  imageattr.recvSets.back().yRange.discreteValues.push_back(480);
   5069  imageattr.Serialize(os);
   5070  ASSERT_EQ(
   5071      "* send [x=320,y=240] [x=640,y=480] recv [x=320,y=240] [x=640,y=480]",
   5072      os.str());
   5073  os.str("");
   5074 }
   5075 
   5076 TEST(NewSdpTestNoFixture, CheckSimulcastVersionSerialize)
   5077 {
   5078  std::ostringstream os;
   5079 
   5080  SdpSimulcastAttribute::Version version;
   5081  version.choices.push_back(SdpSimulcastAttribute::Encoding("8", false));
   5082  version.Serialize(os);
   5083  ASSERT_EQ("8", os.str());
   5084  os.str("");
   5085 
   5086  version.choices.push_back(SdpSimulcastAttribute::Encoding("9", true));
   5087  version.Serialize(os);
   5088  ASSERT_EQ("8,~9", os.str());
   5089  os.str("");
   5090 
   5091  version.choices.push_back(SdpSimulcastAttribute::Encoding("0", false));
   5092  version.Serialize(os);
   5093  ASSERT_EQ("8,~9,0", os.str());
   5094  os.str("");
   5095 }
   5096 
   5097 static SdpSimulcastAttribute::Version ParseSimulcastVersion(
   5098    const std::string& input) {
   5099  std::istringstream is(input + ";");
   5100  std::string error;
   5101  SdpSimulcastAttribute::Version version;
   5102  EXPECT_TRUE(version.Parse(is, &error)) << error;
   5103  EXPECT_EQ(';', is.get());
   5104  EXPECT_EQ(EOF, is.get());
   5105  return version;
   5106 }
   5107 
   5108 TEST(NewSdpTestNoFixture, CheckSimulcastVersionValidParse)
   5109 {
   5110  {
   5111    SdpSimulcastAttribute::Version version(ParseSimulcastVersion("1"));
   5112    ASSERT_EQ(1U, version.choices.size());
   5113    ASSERT_EQ("1", version.choices[0].rid);
   5114    ASSERT_FALSE(version.choices[0].paused);
   5115  }
   5116 
   5117  {
   5118    SdpSimulcastAttribute::Version version(ParseSimulcastVersion("1,~2"));
   5119    ASSERT_EQ(2U, version.choices.size());
   5120    ASSERT_EQ("1", version.choices[0].rid);
   5121    ASSERT_EQ("2", version.choices[1].rid);
   5122    ASSERT_FALSE(version.choices[0].paused);
   5123    ASSERT_TRUE(version.choices[1].paused);
   5124  }
   5125 }
   5126 
   5127 TEST(NewSdpTestNoFixture, CheckSimulcastVersionInvalidParse)
   5128 {
   5129  ParseInvalid<SdpSimulcastAttribute::Version>("", 0);
   5130  ParseInvalid<SdpSimulcastAttribute::Version>(",", 0);
   5131  ParseInvalid<SdpSimulcastAttribute::Version>(";", 0);
   5132  ParseInvalid<SdpSimulcastAttribute::Version>(" ", 0);
   5133  ParseInvalid<SdpSimulcastAttribute::Version>("8,", 2);
   5134  ParseInvalid<SdpSimulcastAttribute::Version>("8, ", 2);
   5135  ParseInvalid<SdpSimulcastAttribute::Version>("8,,", 2);
   5136  ParseInvalid<SdpSimulcastAttribute::Version>("8,;", 2);
   5137 }
   5138 
   5139 TEST(NewSdpTestNoFixture, CheckSimulcastVersionsSerialize)
   5140 {
   5141  std::ostringstream os;
   5142 
   5143  SdpSimulcastAttribute::Versions versions;
   5144  versions.push_back(SdpSimulcastAttribute::Version());
   5145  versions.back().choices.push_back(
   5146      SdpSimulcastAttribute::Encoding("8", false));
   5147  versions.Serialize(os);
   5148  ASSERT_EQ("8", os.str());
   5149  os.str("");
   5150 
   5151  versions.push_back(SdpSimulcastAttribute::Version());
   5152  versions.Serialize(os);
   5153  ASSERT_EQ("8", os.str());
   5154  os.str("");
   5155 
   5156  versions.back().choices.push_back(SdpSimulcastAttribute::Encoding("9", true));
   5157  versions.Serialize(os);
   5158  ASSERT_EQ("8;~9", os.str());
   5159  os.str("");
   5160 
   5161  versions.push_back(SdpSimulcastAttribute::Version());
   5162  versions.back().choices.push_back(
   5163      SdpSimulcastAttribute::Encoding("0", false));
   5164  versions.Serialize(os);
   5165  ASSERT_EQ("8;~9;0", os.str());
   5166  os.str("");
   5167 }
   5168 
   5169 static SdpSimulcastAttribute::Versions ParseSimulcastVersions(
   5170    const std::string& input) {
   5171  std::istringstream is(input + " ");
   5172  std::string error;
   5173  SdpSimulcastAttribute::Versions list;
   5174  EXPECT_TRUE(list.Parse(is, &error)) << error;
   5175  EXPECT_EQ(' ', is.get());
   5176  EXPECT_EQ(EOF, is.get());
   5177  return list;
   5178 }
   5179 
   5180 TEST(NewSdpTestNoFixture, CheckSimulcastVersionsValidParse)
   5181 {
   5182  {
   5183    SdpSimulcastAttribute::Versions versions(ParseSimulcastVersions("8"));
   5184    ASSERT_EQ(1U, versions.size());
   5185    ASSERT_EQ(1U, versions[0].choices.size());
   5186    ASSERT_EQ("8", versions[0].choices[0].rid);
   5187    ASSERT_FALSE(versions[0].choices[0].paused);
   5188  }
   5189 
   5190  {
   5191    SdpSimulcastAttribute::Versions versions(ParseSimulcastVersions("~8,9"));
   5192    ASSERT_EQ(1U, versions.size());
   5193    ASSERT_EQ(2U, versions[0].choices.size());
   5194    ASSERT_EQ("8", versions[0].choices[0].rid);
   5195    ASSERT_EQ("9", versions[0].choices[1].rid);
   5196    ASSERT_TRUE(versions[0].choices[0].paused);
   5197    ASSERT_FALSE(versions[0].choices[1].paused);
   5198  }
   5199 
   5200  {
   5201    SdpSimulcastAttribute::Versions versions(ParseSimulcastVersions("8,9;~10"));
   5202    ASSERT_EQ(2U, versions.size());
   5203    ASSERT_EQ(2U, versions[0].choices.size());
   5204    ASSERT_EQ("8", versions[0].choices[0].rid);
   5205    ASSERT_EQ("9", versions[0].choices[1].rid);
   5206    ASSERT_FALSE(versions[0].choices[0].paused);
   5207    ASSERT_FALSE(versions[0].choices[1].paused);
   5208    ASSERT_EQ(1U, versions[1].choices.size());
   5209    ASSERT_EQ("10", versions[1].choices[0].rid);
   5210    ASSERT_TRUE(versions[1].choices[0].paused);
   5211  }
   5212 }
   5213 
   5214 TEST(NewSdpTestNoFixture, CheckSimulcastVersionsInvalidParse)
   5215 {
   5216  ParseInvalid<SdpSimulcastAttribute::Versions>("", 0);
   5217  ParseInvalid<SdpSimulcastAttribute::Versions>(";", 0);
   5218  ParseInvalid<SdpSimulcastAttribute::Versions>("8;", 2);
   5219  ParseInvalid<SdpSimulcastAttribute::Versions>("8;;", 2);
   5220 }
   5221 
   5222 TEST(NewSdpTestNoFixture, CheckSimulcastSerialize)
   5223 {
   5224  std::ostringstream os;
   5225 
   5226  SdpSimulcastAttribute simulcast;
   5227  simulcast.recvVersions.push_back(SdpSimulcastAttribute::Version());
   5228  simulcast.recvVersions.back().choices.push_back(
   5229      SdpSimulcastAttribute::Encoding("8", false));
   5230  simulcast.Serialize(os);
   5231  ASSERT_EQ("a=simulcast:recv 8" CRLF, os.str());
   5232  os.str("");
   5233 
   5234  simulcast.sendVersions.push_back(SdpSimulcastAttribute::Version());
   5235  simulcast.sendVersions.back().choices.push_back(
   5236      SdpSimulcastAttribute::Encoding("9", true));
   5237  simulcast.Serialize(os);
   5238  ASSERT_EQ("a=simulcast:send ~9 recv 8" CRLF, os.str());
   5239 }
   5240 
   5241 static SdpSimulcastAttribute ParseSimulcast(const std::string& input) {
   5242  std::istringstream is(input);
   5243  std::string error;
   5244  SdpSimulcastAttribute simulcast;
   5245  EXPECT_TRUE(simulcast.Parse(is, &error)) << error;
   5246  EXPECT_TRUE(is.eof());
   5247  return simulcast;
   5248 }
   5249 
   5250 TEST(NewSdpTestNoFixture, CheckSimulcastValidParse)
   5251 {
   5252  {
   5253    SdpSimulcastAttribute simulcast(ParseSimulcast("send 8"));
   5254    ASSERT_EQ(1U, simulcast.sendVersions.size());
   5255    ASSERT_EQ(1U, simulcast.sendVersions[0].choices.size());
   5256    ASSERT_EQ("8", simulcast.sendVersions[0].choices[0].rid);
   5257    ASSERT_FALSE(simulcast.sendVersions[0].choices[0].paused);
   5258    ASSERT_EQ(0U, simulcast.recvVersions.size());
   5259  }
   5260 
   5261  {
   5262    SdpSimulcastAttribute simulcast(ParseSimulcast(" SEND 8"));
   5263    ASSERT_EQ(1U, simulcast.sendVersions.size());
   5264    ASSERT_EQ(1U, simulcast.sendVersions[0].choices.size());
   5265    ASSERT_EQ("8", simulcast.sendVersions[0].choices[0].rid);
   5266    ASSERT_FALSE(simulcast.sendVersions[0].choices[0].paused);
   5267    ASSERT_EQ(0U, simulcast.recvVersions.size());
   5268  }
   5269 
   5270  {
   5271    SdpSimulcastAttribute simulcast(ParseSimulcast("recv 8"));
   5272    ASSERT_EQ(1U, simulcast.recvVersions.size());
   5273    ASSERT_EQ(1U, simulcast.recvVersions[0].choices.size());
   5274    ASSERT_EQ("8", simulcast.recvVersions[0].choices[0].rid);
   5275    ASSERT_FALSE(simulcast.recvVersions[0].choices[0].paused);
   5276    ASSERT_EQ(0U, simulcast.sendVersions.size());
   5277  }
   5278 
   5279  {
   5280    SdpSimulcastAttribute simulcast(
   5281        ParseSimulcast("send 8,9;~101;97,~98 recv 101,120;97"));
   5282    ASSERT_EQ(3U, simulcast.sendVersions.size());
   5283    ASSERT_EQ(2U, simulcast.sendVersions[0].choices.size());
   5284    ASSERT_EQ("8", simulcast.sendVersions[0].choices[0].rid);
   5285    ASSERT_EQ("9", simulcast.sendVersions[0].choices[1].rid);
   5286    ASSERT_FALSE(simulcast.sendVersions[0].choices[0].paused);
   5287    ASSERT_FALSE(simulcast.sendVersions[0].choices[1].paused);
   5288    ASSERT_EQ(1U, simulcast.sendVersions[1].choices.size());
   5289    ASSERT_EQ("101", simulcast.sendVersions[1].choices[0].rid);
   5290    ASSERT_TRUE(simulcast.sendVersions[1].choices[0].paused);
   5291    ASSERT_EQ(2U, simulcast.sendVersions[2].choices.size());
   5292    ASSERT_EQ("97", simulcast.sendVersions[2].choices[0].rid);
   5293    ASSERT_EQ("98", simulcast.sendVersions[2].choices[1].rid);
   5294    ASSERT_FALSE(simulcast.sendVersions[2].choices[0].paused);
   5295    ASSERT_TRUE(simulcast.sendVersions[2].choices[1].paused);
   5296 
   5297    ASSERT_EQ(2U, simulcast.recvVersions.size());
   5298    ASSERT_EQ(2U, simulcast.recvVersions[0].choices.size());
   5299    ASSERT_EQ("101", simulcast.recvVersions[0].choices[0].rid);
   5300    ASSERT_EQ("120", simulcast.recvVersions[0].choices[1].rid);
   5301    ASSERT_EQ(1U, simulcast.recvVersions[1].choices.size());
   5302    ASSERT_EQ("97", simulcast.recvVersions[1].choices[0].rid);
   5303  }
   5304 }
   5305 
   5306 TEST(NewSdpTestNoFixture, CheckSimulcastInvalidParse)
   5307 {
   5308  ParseInvalid<SdpSimulcastAttribute>("", 0);
   5309  ParseInvalid<SdpSimulcastAttribute>(" ", 1);
   5310  ParseInvalid<SdpSimulcastAttribute>("vcer ", 4);
   5311  ParseInvalid<SdpSimulcastAttribute>(" send 8 send ", 12);
   5312  ParseInvalid<SdpSimulcastAttribute>(" recv 8 recv ", 12);
   5313 }
   5314 
   5315 static SdpRidAttributeList::Rid ParseRid(const std::string& input) {
   5316  std::istringstream is(input);
   5317  std::string error;
   5318  SdpRidAttributeList::Rid rid;
   5319  EXPECT_TRUE(rid.Parse(is, &error)) << error;
   5320  EXPECT_TRUE(is.eof());
   5321  return rid;
   5322 }
   5323 
   5324 TEST(NewSdpTestNoFixture, CheckRidValidParse)
   5325 {
   5326  {
   5327    SdpRidAttributeList::Rid rid(ParseRid("1 send"));
   5328    ASSERT_EQ("1", rid.id);
   5329    ASSERT_EQ(sdp::kSend, rid.direction);
   5330    ASSERT_EQ(0U, rid.formats.size());
   5331    ASSERT_EQ(0U, rid.constraints.maxWidth);
   5332    ASSERT_EQ(0U, rid.constraints.maxHeight);
   5333    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5334    ASSERT_EQ(0U, rid.constraints.maxFs);
   5335    ASSERT_EQ(0U, rid.constraints.maxBr);
   5336    ASSERT_EQ(0U, rid.constraints.maxPps);
   5337    ASSERT_EQ(0U, rid.dependIds.size());
   5338  }
   5339 
   5340  {
   5341    SdpRidAttributeList::Rid rid(ParseRid("1 send pt=96;max-width=800"));
   5342    ASSERT_EQ("1", rid.id);
   5343    ASSERT_EQ(sdp::kSend, rid.direction);
   5344    ASSERT_EQ(1U, rid.formats.size());
   5345    ASSERT_EQ(96U, rid.formats[0]);
   5346    ASSERT_EQ(800U, rid.constraints.maxWidth);
   5347    ASSERT_EQ(0U, rid.constraints.maxHeight);
   5348    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5349    ASSERT_EQ(0U, rid.constraints.maxFs);
   5350    ASSERT_EQ(0U, rid.constraints.maxBr);
   5351    ASSERT_EQ(0U, rid.constraints.maxPps);
   5352    ASSERT_EQ(0U, rid.dependIds.size());
   5353  }
   5354 
   5355  {
   5356    SdpRidAttributeList::Rid rid(ParseRid("1 send pt=96,97,98;max-width=800"));
   5357    ASSERT_EQ("1", rid.id);
   5358    ASSERT_EQ(sdp::kSend, rid.direction);
   5359    ASSERT_EQ(3U, rid.formats.size());
   5360    ASSERT_EQ(96U, rid.formats[0]);
   5361    ASSERT_EQ(97U, rid.formats[1]);
   5362    ASSERT_EQ(98U, rid.formats[2]);
   5363    ASSERT_EQ(800U, rid.constraints.maxWidth);
   5364    ASSERT_EQ(0U, rid.constraints.maxHeight);
   5365    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5366    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5367    ASSERT_EQ(0U, rid.constraints.maxFs);
   5368    ASSERT_EQ(0U, rid.constraints.maxBr);
   5369    ASSERT_EQ(0U, rid.constraints.maxPps);
   5370    ASSERT_EQ(0U, rid.dependIds.size());
   5371  }
   5372 
   5373  {
   5374    SdpRidAttributeList::Rid rid(ParseRid("foo send"));
   5375    ASSERT_EQ(0U, rid.formats.size());
   5376    ASSERT_EQ(0U, rid.constraints.maxWidth);
   5377    ASSERT_EQ(0U, rid.constraints.maxHeight);
   5378    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5379    ASSERT_EQ(0U, rid.constraints.maxFs);
   5380    ASSERT_EQ(0U, rid.constraints.maxBr);
   5381    ASSERT_EQ(0U, rid.constraints.maxPps);
   5382    ASSERT_EQ(0U, rid.dependIds.size());
   5383  }
   5384 
   5385  {
   5386    SdpRidAttributeList::Rid rid(ParseRid("foo send pt=96"));
   5387    ASSERT_EQ(1U, rid.formats.size());
   5388    ASSERT_EQ(96U, rid.formats[0]);
   5389    ASSERT_EQ(0U, rid.constraints.maxWidth);
   5390    ASSERT_EQ(0U, rid.constraints.maxHeight);
   5391    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5392    ASSERT_EQ(0U, rid.constraints.maxFs);
   5393    ASSERT_EQ(0U, rid.constraints.maxBr);
   5394    ASSERT_EQ(0U, rid.constraints.maxPps);
   5395    ASSERT_EQ(0U, rid.dependIds.size());
   5396  }
   5397 
   5398  // This is not technically permitted by the BNF, but the parse code is simpler
   5399  // if we allow it. If we decide to stop allowing this, this will need to be
   5400  // converted to an invalid parse test-case.
   5401  {
   5402    SdpRidAttributeList::Rid rid(ParseRid("foo send max-br=30000;pt=96"));
   5403    ASSERT_EQ(1U, rid.formats.size());
   5404    ASSERT_EQ(96U, rid.formats[0]);
   5405    ASSERT_EQ(0U, rid.constraints.maxWidth);
   5406    ASSERT_EQ(0U, rid.constraints.maxHeight);
   5407    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5408    ASSERT_EQ(0U, rid.constraints.maxFs);
   5409    ASSERT_EQ(30000U, rid.constraints.maxBr);
   5410    ASSERT_EQ(0U, rid.constraints.maxPps);
   5411    ASSERT_EQ(0U, rid.dependIds.size());
   5412  }
   5413 
   5414  {
   5415    SdpRidAttributeList::Rid rid(ParseRid("foo send pt=96,97,98"));
   5416    ASSERT_EQ(3U, rid.formats.size());
   5417    ASSERT_EQ(96U, rid.formats[0]);
   5418    ASSERT_EQ(97U, rid.formats[1]);
   5419    ASSERT_EQ(98U, rid.formats[2]);
   5420    ASSERT_EQ(0U, rid.constraints.maxWidth);
   5421    ASSERT_EQ(0U, rid.constraints.maxHeight);
   5422    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5423    ASSERT_EQ(0U, rid.constraints.maxFs);
   5424    ASSERT_EQ(0U, rid.constraints.maxBr);
   5425    ASSERT_EQ(0U, rid.constraints.maxPps);
   5426    ASSERT_EQ(0U, rid.dependIds.size());
   5427  }
   5428 
   5429  {
   5430    SdpRidAttributeList::Rid rid(ParseRid("foo send max-width=800"));
   5431    ASSERT_EQ(0U, rid.formats.size());
   5432    ASSERT_EQ(800U, rid.constraints.maxWidth);
   5433    ASSERT_EQ(0U, rid.constraints.maxHeight);
   5434    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5435    ASSERT_EQ(0U, rid.constraints.maxFs);
   5436    ASSERT_EQ(0U, rid.constraints.maxBr);
   5437    ASSERT_EQ(0U, rid.constraints.maxPps);
   5438    ASSERT_EQ(0U, rid.dependIds.size());
   5439  }
   5440 
   5441  {
   5442    SdpRidAttributeList::Rid rid(ParseRid("foo send max-height=640"));
   5443    ASSERT_EQ(0U, rid.formats.size());
   5444    ASSERT_EQ(0U, rid.constraints.maxWidth);
   5445    ASSERT_EQ(640U, rid.constraints.maxHeight);
   5446    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5447    ASSERT_EQ(0U, rid.constraints.maxFs);
   5448    ASSERT_EQ(0U, rid.constraints.maxBr);
   5449    ASSERT_EQ(0U, rid.constraints.maxPps);
   5450    ASSERT_EQ(0U, rid.dependIds.size());
   5451  }
   5452 
   5453  {
   5454    SdpRidAttributeList::Rid rid(ParseRid("foo send max-fps=30"));
   5455    ASSERT_EQ(0U, rid.formats.size());
   5456    ASSERT_EQ(0U, rid.constraints.maxWidth);
   5457    ASSERT_EQ(0U, rid.constraints.maxHeight);
   5458    ASSERT_EQ(30.0, *rid.constraints.maxFps);
   5459    ASSERT_EQ(0U, rid.constraints.maxFs);
   5460    ASSERT_EQ(0U, rid.constraints.maxBr);
   5461    ASSERT_EQ(0U, rid.constraints.maxPps);
   5462    ASSERT_EQ(0U, rid.dependIds.size());
   5463  }
   5464 
   5465  {
   5466    SdpRidAttributeList::Rid rid(ParseRid("foo send max-fs=3600"));
   5467    ASSERT_EQ(0U, rid.formats.size());
   5468    ASSERT_EQ(0U, rid.constraints.maxWidth);
   5469    ASSERT_EQ(0U, rid.constraints.maxHeight);
   5470    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5471    ASSERT_EQ(3600U, rid.constraints.maxFs);
   5472    ASSERT_EQ(0U, rid.constraints.maxBr);
   5473    ASSERT_EQ(0U, rid.constraints.maxPps);
   5474    ASSERT_EQ(0U, rid.dependIds.size());
   5475  }
   5476 
   5477  {
   5478    SdpRidAttributeList::Rid rid(ParseRid("foo send max-br=30000"));
   5479    ASSERT_EQ(0U, rid.formats.size());
   5480    ASSERT_EQ(0U, rid.constraints.maxWidth);
   5481    ASSERT_EQ(0U, rid.constraints.maxHeight);
   5482    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5483    ASSERT_EQ(0U, rid.constraints.maxFs);
   5484    ASSERT_EQ(30000U, rid.constraints.maxBr);
   5485    ASSERT_EQ(0U, rid.constraints.maxPps);
   5486    ASSERT_EQ(0U, rid.dependIds.size());
   5487  }
   5488 
   5489  {
   5490    SdpRidAttributeList::Rid rid(ParseRid("foo send max-pps=9216000"));
   5491    ASSERT_EQ(0U, rid.formats.size());
   5492    ASSERT_EQ(0U, rid.constraints.maxWidth);
   5493    ASSERT_EQ(0U, rid.constraints.maxHeight);
   5494    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5495    ASSERT_EQ(0U, rid.constraints.maxFs);
   5496    ASSERT_EQ(0U, rid.constraints.maxBr);
   5497    ASSERT_EQ(9216000U, rid.constraints.maxPps);
   5498    ASSERT_EQ(0U, rid.dependIds.size());
   5499  }
   5500 
   5501  {
   5502    SdpRidAttributeList::Rid rid(ParseRid("foo send depend=foo"));
   5503    ASSERT_EQ(0U, rid.formats.size());
   5504    ASSERT_EQ(0U, rid.constraints.maxWidth);
   5505    ASSERT_EQ(0U, rid.constraints.maxHeight);
   5506    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5507    ASSERT_EQ(0U, rid.constraints.maxFs);
   5508    ASSERT_EQ(0U, rid.constraints.maxBr);
   5509    ASSERT_EQ(0U, rid.constraints.maxPps);
   5510    ASSERT_EQ(1U, rid.dependIds.size());
   5511    ASSERT_EQ("foo", rid.dependIds[0]);
   5512  }
   5513 
   5514  {
   5515    SdpRidAttributeList::Rid rid(ParseRid("foo send max-foo=20"));
   5516    ASSERT_EQ(0U, rid.formats.size());
   5517    ASSERT_EQ(0U, rid.constraints.maxWidth);
   5518    ASSERT_EQ(0U, rid.constraints.maxHeight);
   5519    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5520    ASSERT_EQ(0U, rid.constraints.maxFs);
   5521    ASSERT_EQ(0U, rid.constraints.maxBr);
   5522    ASSERT_EQ(0U, rid.constraints.maxPps);
   5523    ASSERT_EQ(0U, rid.dependIds.size());
   5524  }
   5525 
   5526  {
   5527    SdpRidAttributeList::Rid rid(ParseRid("foo send depend=foo,bar"));
   5528    ASSERT_EQ(0U, rid.formats.size());
   5529    ASSERT_EQ(0U, rid.constraints.maxWidth);
   5530    ASSERT_EQ(0U, rid.constraints.maxHeight);
   5531    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5532    ASSERT_EQ(0U, rid.constraints.maxFs);
   5533    ASSERT_EQ(0U, rid.constraints.maxBr);
   5534    ASSERT_EQ(0U, rid.constraints.maxPps);
   5535    ASSERT_EQ(2U, rid.dependIds.size());
   5536    ASSERT_EQ("foo", rid.dependIds[0]);
   5537    ASSERT_EQ("bar", rid.dependIds[1]);
   5538  }
   5539 
   5540  {
   5541    SdpRidAttributeList::Rid rid(
   5542        ParseRid("foo send max-width=800;max-height=600"));
   5543    ASSERT_EQ(0U, rid.formats.size());
   5544    ASSERT_EQ(800U, rid.constraints.maxWidth);
   5545    ASSERT_EQ(600U, rid.constraints.maxHeight);
   5546    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5547    ASSERT_EQ(0U, rid.constraints.maxFs);
   5548    ASSERT_EQ(0U, rid.constraints.maxBr);
   5549    ASSERT_EQ(0U, rid.constraints.maxPps);
   5550    ASSERT_EQ(0U, rid.dependIds.size());
   5551  }
   5552 
   5553  {
   5554    SdpRidAttributeList::Rid rid(
   5555        ParseRid("foo send pt=96,97;max-width=800;max-height=600"));
   5556    ASSERT_EQ(2U, rid.formats.size());
   5557    ASSERT_EQ(96U, rid.formats[0]);
   5558    ASSERT_EQ(97U, rid.formats[1]);
   5559    ASSERT_EQ(800U, rid.constraints.maxWidth);
   5560    ASSERT_EQ(600U, rid.constraints.maxHeight);
   5561    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5562    ASSERT_EQ(0U, rid.constraints.maxFs);
   5563    ASSERT_EQ(0U, rid.constraints.maxBr);
   5564    ASSERT_EQ(0U, rid.constraints.maxPps);
   5565    ASSERT_EQ(0U, rid.dependIds.size());
   5566  }
   5567 
   5568  {
   5569    SdpRidAttributeList::Rid rid(
   5570        ParseRid("foo send depend=foo,bar;max-width=800;max-height=600"));
   5571    ASSERT_EQ(0U, rid.formats.size());
   5572    ASSERT_EQ(800U, rid.constraints.maxWidth);
   5573    ASSERT_EQ(600U, rid.constraints.maxHeight);
   5574    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5575    ASSERT_EQ(0U, rid.constraints.maxFs);
   5576    ASSERT_EQ(0U, rid.constraints.maxBr);
   5577    ASSERT_EQ(0U, rid.constraints.maxPps);
   5578    ASSERT_EQ(2U, rid.dependIds.size());
   5579    ASSERT_EQ("foo", rid.dependIds[0]);
   5580    ASSERT_EQ("bar", rid.dependIds[1]);
   5581  }
   5582 
   5583  {
   5584    SdpRidAttributeList::Rid rid(
   5585        ParseRid("foo send max-foo=20;max-width=800;max-height=600"));
   5586    ASSERT_EQ(0U, rid.formats.size());
   5587    ASSERT_EQ(800U, rid.constraints.maxWidth);
   5588    ASSERT_EQ(600U, rid.constraints.maxHeight);
   5589    ASSERT_FALSE(rid.constraints.maxFps.isSome());
   5590    ASSERT_EQ(0U, rid.constraints.maxFs);
   5591    ASSERT_EQ(0U, rid.constraints.maxBr);
   5592    ASSERT_EQ(0U, rid.constraints.maxPps);
   5593    ASSERT_EQ(0U, rid.dependIds.size());
   5594  }
   5595 }
   5596 
   5597 TEST(NewSdpTestNoFixture, CheckRidInvalidParse)
   5598 {
   5599  ParseInvalid<SdpRidAttributeList::Rid>("", 0);
   5600  ParseInvalid<SdpRidAttributeList::Rid>(" ", 0);
   5601  ParseInvalid<SdpRidAttributeList::Rid>("foo", 3);
   5602  ParseInvalid<SdpRidAttributeList::Rid>("foo ", 4);
   5603  ParseInvalid<SdpRidAttributeList::Rid>("foo  ", 5);
   5604  ParseInvalid<SdpRidAttributeList::Rid>("foo bar", 7);
   5605  ParseInvalid<SdpRidAttributeList::Rid>("foo recv ", 9);
   5606  ParseInvalid<SdpRidAttributeList::Rid>("foo recv pt=", 12);
   5607  ParseInvalid<SdpRidAttributeList::Rid>(" ", 0);
   5608  ParseInvalid<SdpRidAttributeList::Rid>("foo send pt", 11);
   5609  ParseInvalid<SdpRidAttributeList::Rid>("foo send pt=", 12);
   5610  ParseInvalid<SdpRidAttributeList::Rid>("foo send pt=x", 12);
   5611  ParseInvalid<SdpRidAttributeList::Rid>("foo send pt=-1", 12);
   5612  ParseInvalid<SdpRidAttributeList::Rid>("foo send pt=96,", 15);
   5613  ParseInvalid<SdpRidAttributeList::Rid>("foo send pt=196", 15);
   5614  ParseInvalid<SdpRidAttributeList::Rid>("foo send max-width", 18);
   5615  ParseInvalid<SdpRidAttributeList::Rid>("foo send max-width=", 19);
   5616  ParseInvalid<SdpRidAttributeList::Rid>("foo send max-width=x", 19);
   5617  ParseInvalid<SdpRidAttributeList::Rid>("foo send max-width=-1", 19);
   5618  ParseInvalid<SdpRidAttributeList::Rid>("foo send max-width=800;", 23);
   5619  ParseInvalid<SdpRidAttributeList::Rid>("foo send max-width=800; ", 24);
   5620  ParseInvalid<SdpRidAttributeList::Rid>("foo send depend=", 16);
   5621  ParseInvalid<SdpRidAttributeList::Rid>("foo send depend=,", 16);
   5622  ParseInvalid<SdpRidAttributeList::Rid>("foo send depend=1,", 18);
   5623  ParseInvalid<SdpRidAttributeList::Rid>("0123456789az-_", 14);
   5624 }
   5625 
   5626 TEST(NewSdpTestNoFixture, CheckRidSerialize)
   5627 {
   5628  {
   5629    SdpRidAttributeList::Rid rid;
   5630    rid.id = "foo";
   5631    rid.direction = sdp::kSend;
   5632    std::ostringstream os;
   5633    rid.Serialize(os);
   5634    ASSERT_EQ("foo send", os.str());
   5635  }
   5636 
   5637  {
   5638    SdpRidAttributeList::Rid rid;
   5639    rid.id = "foo";
   5640    rid.direction = sdp::kSend;
   5641    std::ostringstream os;
   5642    rid.Serialize(os);
   5643    ASSERT_EQ("foo send", os.str());
   5644  }
   5645 
   5646  {
   5647    SdpRidAttributeList::Rid rid;
   5648    rid.id = "foo";
   5649    rid.direction = sdp::kSend;
   5650    rid.formats.push_back(96);
   5651    std::ostringstream os;
   5652    rid.Serialize(os);
   5653    ASSERT_EQ("foo send pt=96", os.str());
   5654  }
   5655 
   5656  {
   5657    SdpRidAttributeList::Rid rid;
   5658    rid.id = "foo";
   5659    rid.direction = sdp::kSend;
   5660    rid.formats.push_back(96);
   5661    rid.formats.push_back(97);
   5662    std::ostringstream os;
   5663    rid.Serialize(os);
   5664    ASSERT_EQ("foo send pt=96,97", os.str());
   5665  }
   5666 
   5667  {
   5668    SdpRidAttributeList::Rid rid;
   5669    rid.id = "foo";
   5670    rid.direction = sdp::kSend;
   5671    rid.constraints.maxWidth = 800;
   5672    std::ostringstream os;
   5673    rid.Serialize(os);
   5674    ASSERT_EQ("foo send max-width=800", os.str());
   5675  }
   5676 
   5677  {
   5678    SdpRidAttributeList::Rid rid;
   5679    rid.id = "foo";
   5680    rid.direction = sdp::kSend;
   5681    rid.constraints.maxHeight = 600;
   5682    std::ostringstream os;
   5683    rid.Serialize(os);
   5684    ASSERT_EQ("foo send max-height=600", os.str());
   5685  }
   5686 
   5687  {
   5688    SdpRidAttributeList::Rid rid;
   5689    rid.id = "foo";
   5690    rid.direction = sdp::kSend;
   5691    rid.constraints.maxFps = Some(30);
   5692    std::ostringstream os;
   5693    rid.Serialize(os);
   5694    ASSERT_EQ("foo send max-fps=30", os.str());
   5695  }
   5696 
   5697  {
   5698    SdpRidAttributeList::Rid rid;
   5699    rid.id = "foo";
   5700    rid.direction = sdp::kSend;
   5701    rid.constraints.maxFs = 3600;
   5702    std::ostringstream os;
   5703    rid.Serialize(os);
   5704    ASSERT_EQ("foo send max-fs=3600", os.str());
   5705  }
   5706 
   5707  {
   5708    SdpRidAttributeList::Rid rid;
   5709    rid.id = "foo";
   5710    rid.direction = sdp::kSend;
   5711    rid.constraints.maxBr = 30000;
   5712    std::ostringstream os;
   5713    rid.Serialize(os);
   5714    ASSERT_EQ("foo send max-br=30000", os.str());
   5715  }
   5716 
   5717  {
   5718    SdpRidAttributeList::Rid rid;
   5719    rid.id = "foo";
   5720    rid.direction = sdp::kSend;
   5721    rid.constraints.maxPps = 9216000;
   5722    std::ostringstream os;
   5723    rid.Serialize(os);
   5724    ASSERT_EQ("foo send max-pps=9216000", os.str());
   5725  }
   5726 
   5727  {
   5728    SdpRidAttributeList::Rid rid;
   5729    rid.id = "foo";
   5730    rid.direction = sdp::kSend;
   5731    rid.dependIds.push_back("foo");
   5732    std::ostringstream os;
   5733    rid.Serialize(os);
   5734    ASSERT_EQ("foo send depend=foo", os.str());
   5735  }
   5736 
   5737  {
   5738    SdpRidAttributeList::Rid rid;
   5739    rid.id = "foo";
   5740    rid.direction = sdp::kSend;
   5741    rid.dependIds.push_back("foo");
   5742    rid.dependIds.push_back("bar");
   5743    std::ostringstream os;
   5744    rid.Serialize(os);
   5745    ASSERT_EQ("foo send depend=foo,bar", os.str());
   5746  }
   5747 
   5748  {
   5749    SdpRidAttributeList::Rid rid;
   5750    rid.id = "foo";
   5751    rid.direction = sdp::kSend;
   5752    rid.formats.push_back(96);
   5753    rid.constraints.maxBr = 30000;
   5754    std::ostringstream os;
   5755    rid.Serialize(os);
   5756    ASSERT_EQ("foo send pt=96;max-br=30000", os.str());
   5757  }
   5758 }
   5759 
   5760 TEST_F(SdpTest, hugeSdp) {
   5761  std::string offer =
   5762      "v=0\r\n"
   5763      "o=- 1109973417102828257 2 IN IP4 127.0.0.1\r\n"
   5764      "s=-\r\n"
   5765      "t=0 0\r\n"
   5766      "a=group:BUNDLE audio video\r\n"
   5767      "a=msid-semantic: WMS 1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP\r\n"
   5768      "m=audio 32952 UDP/TLS/RTP/SAVPF 111 103 104 0 8 107 106 105 13 126\r\n"
   5769      "c=IN IP4 128.64.32.16\r\n"
   5770      "a=rtcp:32952 IN IP4 128.64.32.16\r\n"
   5771      "a=candidate:77142221 1 udp 2113937151 192.168.137.1 54081 typ host "
   5772      "generation 0\r\n"
   5773      "a=candidate:77142221 2 udp 2113937151 192.168.137.1 54081 typ host "
   5774      "generation 0\r\n"
   5775      "a=candidate:983072742 1 udp 2113937151 172.22.0.56 54082 typ host "
   5776      "generation 0\r\n"
   5777      "a=candidate:983072742 2 udp 2113937151 172.22.0.56 54082 typ host "
   5778      "generation 0\r\n"
   5779      "a=candidate:2245074553 1 udp 1845501695 32.64.128.1 62397 typ srflx "
   5780      "raddr 192.168.137.1 rport 54081 generation 0\r\n"
   5781      "a=candidate:2245074553 2 udp 1845501695 32.64.128.1 62397 typ srflx "
   5782      "raddr 192.168.137.1 rport 54081 generation 0\r\n"
   5783      "a=candidate:2479353907 1 udp 1845501695 32.64.128.1 54082 typ srflx "
   5784      "raddr 172.22.0.56 rport 54082 generation 0\r\n"
   5785      "a=candidate:2479353907 2 udp 1845501695 32.64.128.1 54082 typ srflx "
   5786      "raddr 172.22.0.56 rport 54082 generation 0\r\n"
   5787      "a=candidate:1243276349 1 tcp 1509957375 192.168.137.1 0 typ host "
   5788      "generation 0\r\n"
   5789      "a=candidate:1243276349 2 tcp 1509957375 192.168.137.1 0 typ host "
   5790      "generation 0\r\n"
   5791      "a=candidate:1947960086 1 tcp 1509957375 172.22.0.56 0 typ host "
   5792      "generation 0\r\n"
   5793      "a=candidate:1947960086 2 tcp 1509957375 172.22.0.56 0 typ host "
   5794      "generation 0\r\n"
   5795      "a=candidate:1808221584 1 udp 33562367 128.64.32.16 32952 typ relay "
   5796      "raddr 32.64.128.1 rport 62398 generation 0\r\n"
   5797      "a=candidate:1808221584 2 udp 33562367 128.64.32.16 32952 typ relay "
   5798      "raddr 32.64.128.1 rport 62398 generation 0\r\n"
   5799      "a=candidate:507872740 1 udp 33562367 128.64.32.16 40975 typ relay raddr "
   5800      "32.64.128.1 rport 54085 generation 0\r\n"
   5801      "a=candidate:507872740 2 udp 33562367 128.64.32.16 40975 typ relay raddr "
   5802      "32.64.128.1 rport 54085 generation 0\r\n"
   5803      "a=ice-ufrag:xQuJwjX3V3eMA81k\r\n"
   5804      "a=ice-pwd:ZUiRmjS2GDhG140p73dAsSVP\r\n"
   5805      "a=ice-options:google-ice\r\n"
   5806      "a=fingerprint:sha-256 "
   5807      "59:4A:8B:73:A7:73:53:71:88:D7:4D:58:28:0C:79:72:31:29:9B:05:37:DD:58:43:"
   5808      "C2:D4:85:A2:B3:66:38:7A\r\n"
   5809      "a=setup:active\r\n"
   5810      "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n"
   5811      "a=sendrecv\r\n"
   5812      "a=mid:audio\r\n"
   5813      "a=rtcp-mux\r\n"
   5814      "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
   5815      "inline:/U44g3ULdtapeiSg+T3n6dDLBKIjpOhb/NXAL/2b\r\n"
   5816      "a=rtpmap:111 opus/48000/2\r\n"
   5817      "a=fmtp:111 minptime=10\r\n"
   5818      "a=rtpmap:103 ISAC/16000\r\n"
   5819      "a=rtpmap:104 ISAC/32000\r\n"
   5820      "a=rtpmap:0 PCMU/8000\r\n"
   5821      "a=rtpmap:8 PCMA/8000\r\n"
   5822      "a=rtpmap:107 CN/48000\r\n"
   5823      "a=rtpmap:106 CN/32000\r\n"
   5824      "a=rtpmap:105 CN/16000\r\n"
   5825      "a=rtpmap:13 CN/8000\r\n"
   5826      "a=rtpmap:126 telephone-event/8000\r\n"
   5827      "a=maxptime:60\r\n"
   5828      "a=ssrc:2271517329 cname:mKDNt7SQf6pwDlIn\r\n"
   5829      "a=ssrc:2271517329 msid:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP "
   5830      "1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIPa0\r\n"
   5831      "a=ssrc:2271517329 mslabel:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP\r\n"
   5832      "a=ssrc:2271517329 label:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIPa0\r\n"
   5833      "m=video 32952 UDP/TLS/RTP/SAVPF 100 116 117\r\n"
   5834      "c=IN IP4 128.64.32.16\r\n"
   5835      "a=rtcp:32952 IN IP4 128.64.32.16\r\n"
   5836      "a=candidate:77142221 1 udp 2113937151 192.168.137.1 54081 typ host "
   5837      "generation 0\r\n"
   5838      "a=candidate:77142221 2 udp 2113937151 192.168.137.1 54081 typ host "
   5839      "generation 0\r\n"
   5840      "a=candidate:983072742 1 udp 2113937151 172.22.0.56 54082 typ host "
   5841      "generation 0\r\n"
   5842      "a=candidate:983072742 2 udp 2113937151 172.22.0.56 54082 typ host "
   5843      "generation 0\r\n"
   5844      "a=candidate:2245074553 1 udp 1845501695 32.64.128.1 62397 typ srflx "
   5845      "raddr 192.168.137.1 rport 54081 generation 0\r\n"
   5846      "a=candidate:2245074553 2 udp 1845501695 32.64.128.1 62397 typ srflx "
   5847      "raddr 192.168.137.1 rport 54081 generation 0\r\n"
   5848      "a=candidate:2479353907 1 udp 1845501695 32.64.128.1 54082 typ srflx "
   5849      "raddr 172.22.0.56 rport 54082 generation 0\r\n"
   5850      "a=candidate:2479353907 2 udp 1845501695 32.64.128.1 54082 typ srflx "
   5851      "raddr 172.22.0.56 rport 54082 generation 0\r\n"
   5852      "a=candidate:1243276349 1 tcp 1509957375 192.168.137.1 0 typ host "
   5853      "generation 0\r\n"
   5854      "a=candidate:1243276349 2 tcp 1509957375 192.168.137.1 0 typ host "
   5855      "generation 0\r\n"
   5856      "a=candidate:1947960086 1 tcp 1509957375 172.22.0.56 0 typ host "
   5857      "generation 0\r\n"
   5858      "a=candidate:1947960086 2 tcp 1509957375 172.22.0.56 0 typ host "
   5859      "generation 0\r\n"
   5860      "a=candidate:1808221584 1 udp 33562367 128.64.32.16 32952 typ relay "
   5861      "raddr 32.64.128.1 rport 62398 generation 0\r\n"
   5862      "a=candidate:1808221584 2 udp 33562367 128.64.32.16 32952 typ relay "
   5863      "raddr 32.64.128.1 rport 62398 generation 0\r\n"
   5864      "a=candidate:507872740 1 udp 33562367 128.64.32.16 40975 typ relay raddr "
   5865      "32.64.128.1 rport 54085 generation 0\r\n"
   5866      "a=candidate:507872740 2 udp 33562367 128.64.32.16 40975 typ relay raddr "
   5867      "32.64.128.1 rport 54085 generation 0\r\n"
   5868      "a=ice-ufrag:xQuJwjX3V3eMA81k\r\n"
   5869      "a=ice-pwd:ZUiRmjS2GDhG140p73dAsSVP\r\n"
   5870      "a=ice-options:google-ice\r\n"
   5871      "a=fingerprint:sha-256 "
   5872      "59:4A:8B:73:A7:73:53:71:88:D7:4D:58:28:0C:79:72:31:29:9B:05:37:DD:58:43:"
   5873      "C2:D4:85:A2:B3:66:38:7A\r\n"
   5874      "a=setup:active\r\n"
   5875      "a=extmap:2 urn:ietf:params:rtp-hdrext:toffset\r\n"
   5876      "a=extmap:3 "
   5877      "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\n"
   5878      "a=extmap:6 "
   5879      "http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\n"
   5880      "a=sendrecv\r\n"
   5881      "a=mid:video\r\n"
   5882      "a=rtcp-mux\r\n"
   5883      "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
   5884      "inline:/U44g3ULdtapeiSg+T3n6dDLBKIjpOhb/NXAL/2b\r\n"
   5885      "a=rtpmap:100 VP8/90000\r\n"
   5886      "a=rtcp-fb:100 ccm fir\r\n"
   5887      "a=rtcp-fb:100 nack\r\n"
   5888      "a=rtcp-fb:100 goog-remb\r\n"
   5889      "a=rtpmap:116 red/90000\r\n"
   5890      "a=rtpmap:117 ulpfec/90000\r\n"
   5891      "a=ssrc:54724160 cname:mKDNt7SQf6pwDlIn\r\n"
   5892      "a=ssrc:54724160 msid:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP "
   5893      "1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIPv0\r\n"
   5894      "a=ssrc:54724160 mslabel:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP\r\n"
   5895      "a=ssrc:54724160 label:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIPv0\r\n";
   5896 
   5897  ParseSdp(offer);
   5898 }
   5899 
   5900 TEST_P(NewSdpTest, CheckSsrcGroup) {
   5901  ParseSdp(kVideoSdp + "a=ssrc-group:\r\n", false);
   5902  ParseSdp(kVideoSdp + "a=ssrc-group:BLAH\r\n", false);
   5903  ParseSdp(kVideoSdp + "a=ssrc-group:FID\r\n", false);
   5904  ParseSdp(kVideoSdp + "a=ssrc-group:FID 1 2 3 four\r\n", false);
   5905  ParseSdp(kVideoSdp + "a=ssrc-group:FID 1\r\n");
   5906 
   5907  std::array<char, 8192> gigantic = {{0}};
   5908  gigantic.fill('A');
   5909  gigantic[gigantic.size() - 1] = 0;
   5910  ParseSdp(kVideoSdp + "a=ssrc-group:" + gigantic.data() + "\r\n", false);
   5911 
   5912  ParseSdp(kVideoSdp + "a=ssrc-group:fid 1\r\n");
   5913  ParseSdp(kVideoSdp + "a=ssrc-group:FID \r\n", false);
   5914  ParseSdp(kVideoSdp + "a=ssrc-group:FID 0\r\n");
   5915  ParseSdp(kVideoSdp + "a=ssrc-group:FID 9999999999\r\n", false);
   5916  ParseSdp(kVideoSdp + "a=ssrc-group:FID 99999999999999999999\r\n", false);
   5917  ParseSdp(kVideoSdp + "a=ssrc-group:FID 1twothree\r\n", false);
   5918  ParseSdp(kVideoSdp + "a=ssrc-group:FID -1\r\n", false);
   5919 
   5920  ParseSdp(kVideoSdp + "a=ssrc-group:FID 3156517279 2673335628\r\n");
   5921  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount());
   5922 
   5923  const SdpSsrcGroupAttributeList& group =
   5924      Sdp()->GetMediaSection(0).GetAttributeList().GetSsrcGroup();
   5925 
   5926  ASSERT_EQ(1U, group.mSsrcGroups.size());
   5927  ASSERT_EQ(SdpSsrcGroupAttributeList::Semantics::kFid,
   5928            group.mSsrcGroups[0].semantics);
   5929  ASSERT_EQ(2U, group.mSsrcGroups[0].ssrcs.size());
   5930  ASSERT_EQ(3156517279U, group.mSsrcGroups[0].ssrcs[0]);
   5931  ASSERT_EQ(2673335628U, group.mSsrcGroups[0].ssrcs[1]);
   5932 }
   5933 
   5934 TEST_P(NewSdpTest, CheckSsrcGroupSerialization) {
   5935  std::vector ssrcs = {3156517279U, 2673335628U};
   5936  {
   5937    SdpSsrcGroupAttributeList list;
   5938    list.PushEntry(SdpSsrcGroupAttributeList::Semantics::kFec, ssrcs);
   5939    CheckSerialize("a=ssrc-group:FEC 3156517279 2673335628\r\n", list);
   5940  }
   5941  {
   5942    SdpSsrcGroupAttributeList list;
   5943    list.PushEntry(SdpSsrcGroupAttributeList::Semantics::kFid, ssrcs);
   5944    CheckSerialize("a=ssrc-group:FID 3156517279 2673335628\r\n", list);
   5945  }
   5946  {
   5947    SdpSsrcGroupAttributeList list;
   5948    list.PushEntry(SdpSsrcGroupAttributeList::Semantics::kFecFr, ssrcs);
   5949    CheckSerialize("a=ssrc-group:FEC-FR 3156517279 2673335628\r\n", list);
   5950  }
   5951  {
   5952    SdpSsrcGroupAttributeList list;
   5953    list.PushEntry(SdpSsrcGroupAttributeList::Semantics::kDup, ssrcs);
   5954    CheckSerialize("a=ssrc-group:DUP 3156517279 2673335628\r\n", list);
   5955  }
   5956  {
   5957    SdpSsrcGroupAttributeList list;
   5958    list.PushEntry(SdpSsrcGroupAttributeList::Semantics::kSim, ssrcs);
   5959    CheckSerialize("a=ssrc-group:SIM 3156517279 2673335628\r\n", list);
   5960  }
   5961 }
   5962 
   5963 TEST_P(NewSdpTest, CheckRtxApt) {
   5964  ParseSdp(kVideoSdp + "a=rtpmap:96 rtx/90000\r\na=fmtp:96", false);
   5965  ParseSdp(kVideoSdp +
   5966           "a=rtpmap:96 rtx/90000\r\na=fmtp:96 apt=120; apt=124\r\n");
   5967  ParseSdp(kVideoSdp + "a=rtpmap:96 rtx/90000\r\na=fmtp:96 apt=", false);
   5968  ParseSdp(kVideoSdp + "a=rtpmap:96 rtx/90000\r\na=fmtp:96 apt=blah", false);
   5969  ParseSdp(kVideoSdp +
   5970               "a=rtpmap:96 rtx/90000\r\na=fmtp:96 "
   5971               "apt=999999999999999999999999999999",
   5972           false);
   5973  ParseSdp(kVideoSdp + "a=rtpmap:96 rtx/90000\r\na=fmtp:96 apt=-120\r\n",
   5974           false);
   5975  ParseSdp(kVideoSdp + "a=rtpmap:96 rtx/90000\r\na=fmtp:96 apt=1twenty\r\n",
   5976           false);
   5977  ParseSdp(kVideoSdp + "a=rtpmap:96 rtx/90000\r\na=fmtp:96 APT=120\r\n");
   5978 
   5979  ParseSdp(kVideoSdp + "a=rtpmap:96 rtx/90000\r\na=fmtp:96 apt=120\r\n");
   5980 
   5981  const SdpMediaSection& msec = Sdp()->GetMediaSection(0);
   5982  ASSERT_EQ(1U, msec.GetFormats().size());
   5983  ASSERT_EQ(2U, msec.GetAttributeList().GetRtpmap().mRtpmaps.size());
   5984  const SdpRtpmapAttributeList::Rtpmap& rtpmap =
   5985      msec.GetAttributeList().GetRtpmap().GetEntry("96");
   5986  ASSERT_EQ(rtpmap.pt, "96");
   5987  ASSERT_EQ(rtpmap.codec, SdpRtpmapAttributeList::CodecType::kRtx);
   5988  ASSERT_EQ(rtpmap.name, "rtx");
   5989  ASSERT_EQ(rtpmap.clock, 90000U);
   5990 
   5991  ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   5992      SdpAttribute::kFmtpAttribute));
   5993  const auto& format_params = msec.GetAttributeList().GetFmtp().mFmtps;
   5994  ASSERT_EQ(1U, format_params.size());
   5995  ASSERT_EQ("96", format_params[0].format);
   5996  ASSERT_EQ(SdpRtpmapAttributeList::CodecType::kRtx,
   5997            format_params[0].parameters->codec_type);
   5998  ASSERT_EQ(static_cast<uint8_t>(120),
   5999            static_cast<SdpFmtpAttributeList::RtxParameters*>(
   6000                format_params[0].parameters.get())
   6001                ->apt);
   6002  ASSERT_EQ(Nothing(), static_cast<SdpFmtpAttributeList::RtxParameters*>(
   6003                           format_params[0].parameters.get())
   6004                           ->rtx_time);
   6005 }
   6006 
   6007 TEST_P(NewSdpTest, CheckRtxAptRtxTime) {
   6008  ParseSdp(kVideoSdp + "a=rtpmap:96 rtx/90000\r\na=fmtp:96 apt=120;rtx-time=",
   6009           false);
   6010  ParseSdp(
   6011      kVideoSdp + "a=rtpmap:96 rtx/90000\r\na=fmtp:96 apt=120;rtx-time=blah",
   6012      false);
   6013  ParseSdp(kVideoSdp +
   6014               "a=rtpmap:96 rtx/90000\r\na=fmtp:96 "
   6015               "apt=120;rtx-time=9999999999999999999999999999999",
   6016           false);
   6017  ParseSdp(
   6018      kVideoSdp + "a=rtpmap:96 rtx/90000\r\na=fmtp:96 apt=120;rtx-time=-3000",
   6019      false);
   6020  ParseSdp(kVideoSdp +
   6021               "a=rtpmap:96 rtx/90000\r\na=fmtp:96 apt=120;rtx-time=3thousand",
   6022           false);
   6023 
   6024  {
   6025    ParseSdp(kVideoSdp +
   6026             "a=rtpmap:96 rtx/90000\r\na=fmtp:96 apt=120;RTX-TIME=3000\r\n");
   6027 
   6028    const SdpMediaSection& msec = Sdp()->GetMediaSection(0);
   6029    ASSERT_EQ(1U, msec.GetFormats().size());
   6030    ASSERT_EQ(2U, msec.GetAttributeList().GetRtpmap().mRtpmaps.size());
   6031    const SdpRtpmapAttributeList::Rtpmap& rtpmap =
   6032        msec.GetAttributeList().GetRtpmap().GetEntry("96");
   6033    ASSERT_EQ(rtpmap.pt, "96");
   6034    ASSERT_EQ(rtpmap.codec, SdpRtpmapAttributeList::CodecType::kRtx);
   6035    ASSERT_EQ(rtpmap.name, "rtx");
   6036    ASSERT_EQ(rtpmap.clock, 90000U);
   6037 
   6038    ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   6039        SdpAttribute::kFmtpAttribute));
   6040    const auto& format_params = msec.GetAttributeList().GetFmtp().mFmtps;
   6041    ASSERT_EQ(1U, format_params.size());
   6042    ASSERT_EQ("96", format_params[0].format);
   6043    ASSERT_EQ(SdpRtpmapAttributeList::CodecType::kRtx,
   6044              format_params[0].parameters->codec_type);
   6045    ASSERT_EQ(static_cast<uint8_t>(120),
   6046              static_cast<SdpFmtpAttributeList::RtxParameters*>(
   6047                  format_params[0].parameters.get())
   6048                  ->apt);
   6049    ASSERT_EQ(Some(3000U), static_cast<SdpFmtpAttributeList::RtxParameters*>(
   6050                               format_params[0].parameters.get())
   6051                               ->rtx_time);
   6052  }
   6053 
   6054  {
   6055    ParseSdp(kVideoSdp +
   6056             "a=rtpmap:96 rtx/90000\r\na=fmtp:96 "
   6057             "apt=120;rtx-time=3000;rtx-time=3300\r\n");
   6058 
   6059    const SdpMediaSection& msec = Sdp()->GetMediaSection(0);
   6060    ASSERT_EQ(1U, msec.GetFormats().size());
   6061    ASSERT_EQ(2U, msec.GetAttributeList().GetRtpmap().mRtpmaps.size());
   6062    const SdpRtpmapAttributeList::Rtpmap& rtpmap =
   6063        msec.GetAttributeList().GetRtpmap().GetEntry("96");
   6064    ASSERT_EQ(rtpmap.pt, "96");
   6065    ASSERT_EQ(rtpmap.codec, SdpRtpmapAttributeList::CodecType::kRtx);
   6066    ASSERT_EQ(rtpmap.name, "rtx");
   6067    ASSERT_EQ(rtpmap.clock, 90000U);
   6068 
   6069    ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   6070        SdpAttribute::kFmtpAttribute));
   6071    const auto& format_params = msec.GetAttributeList().GetFmtp().mFmtps;
   6072    ASSERT_EQ(1U, format_params.size());
   6073    ASSERT_EQ("96", format_params[0].format);
   6074    ASSERT_EQ(SdpRtpmapAttributeList::CodecType::kRtx,
   6075              format_params[0].parameters->codec_type);
   6076    ASSERT_EQ(static_cast<uint8_t>(120),
   6077              static_cast<SdpFmtpAttributeList::RtxParameters*>(
   6078                  format_params[0].parameters.get())
   6079                  ->apt);
   6080 
   6081    // Last rtx-time wins. This parameter is unused by our implementation
   6082    // anyway.
   6083    ASSERT_EQ(Some(3300U), static_cast<SdpFmtpAttributeList::RtxParameters*>(
   6084                               format_params[0].parameters.get())
   6085                               ->rtx_time);
   6086  }
   6087 
   6088  {
   6089    ParseSdp(kVideoSdp +
   6090             "a=rtpmap:96 rtx/90000\r\na=fmtp:96 apt=120;rtx-time=3000\r\n");
   6091 
   6092    const SdpMediaSection& msec = Sdp()->GetMediaSection(0);
   6093    ASSERT_EQ(1U, msec.GetFormats().size());
   6094    ASSERT_EQ(2U, msec.GetAttributeList().GetRtpmap().mRtpmaps.size());
   6095    const SdpRtpmapAttributeList::Rtpmap& rtpmap =
   6096        msec.GetAttributeList().GetRtpmap().GetEntry("96");
   6097    ASSERT_EQ(rtpmap.pt, "96");
   6098    ASSERT_EQ(rtpmap.codec, SdpRtpmapAttributeList::CodecType::kRtx);
   6099    ASSERT_EQ(rtpmap.name, "rtx");
   6100    ASSERT_EQ(rtpmap.clock, 90000U);
   6101 
   6102    ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
   6103        SdpAttribute::kFmtpAttribute));
   6104    const auto& format_params = msec.GetAttributeList().GetFmtp().mFmtps;
   6105    ASSERT_EQ(1U, format_params.size());
   6106    ASSERT_EQ("96", format_params[0].format);
   6107    ASSERT_EQ(SdpRtpmapAttributeList::CodecType::kRtx,
   6108              format_params[0].parameters->codec_type);
   6109    ASSERT_EQ(static_cast<uint8_t>(120),
   6110              static_cast<SdpFmtpAttributeList::RtxParameters*>(
   6111                  format_params[0].parameters.get())
   6112                  ->apt);
   6113    ASSERT_EQ(Some(3000U), static_cast<SdpFmtpAttributeList::RtxParameters*>(
   6114                               format_params[0].parameters.get())
   6115                               ->rtx_time);
   6116  }
   6117 }
   6118 
   6119 }  // End namespace test.