Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/media/webrtc/signaling/gtest/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 226 kB image not shown  

Quelle  sdp_unittests.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */


#include <string>

#define GTEST_HAS_RTTI 0
#include "gtest/gtest.h"

#include "nss.h"
#include "ssl.h"

#include "sdp/RsdparsaSdpParser.h"
#include "sdp/SipccSdpParser.h"
#include "sdp/SdpMediaSection.h"
#include "sdp/SdpAttribute.h"
#include "sdp/ParsingResultComparer.h"

extern "C" {
#include "sipcc_sdp.h"
#include "sdp_private.h"
}

#ifdef CRLF
#  undef CRLF
#endif
#define CRLF "\r\n"

#define SKIP_TEST_WITH_RUST_PARSER      \
  if (!::testing::get<1>(GetParam())) { \
    return;                             \
  }
#define SKIP_TEST_WITH_SIPCC_PARSER \
  if (ResultsAreFromSipcc()) {      \
    return;                         \
  }

// If you want to see the SDP as it is parsed
// #define DEBUG_DISPLAY_SDP

using namespace mozilla;

namespace test {

class SdpTest : public ::testing::Test {
 public:
  SdpTest() : final_level_(0), sdp_ptr_(nullptr) {}

  ~SdpTest() { sdp_free_description(sdp_ptr_); }

  static void SetUpTestCase() {
    NSS_NoDB_Init(nullptr);
    NSS_SetDomesticPolicy();
  }

  void SetUp() {
    final_level_ = 0;
    sdp_ptr_ = nullptr;
  }

  static void TearDownTestCase() {}

  void ResetSdp() {
    if (!sdp_ptr_) {
      sdp_free_description(sdp_ptr_);
    }

    sdp_media_e supported_media[] = {
        SDP_MEDIA_AUDIO,      SDP_MEDIA_VIDEO,        SDP_MEDIA_APPLICATION,
        SDP_MEDIA_DATA,       SDP_MEDIA_CONTROL,      SDP_MEDIA_NAS_RADIUS,
        SDP_MEDIA_NAS_TACACS, SDP_MEDIA_NAS_DIAMETER, SDP_MEDIA_NAS_L2TP,
        SDP_MEDIA_NAS_LOGIN,  SDP_MEDIA_NAS_NONE,     SDP_MEDIA_IMAGE,
    };

    sdp_conf_options_t* config_p = sdp_init_config();
    unsigned int i;
    for (i = 0; i < sizeof(supported_media) / sizeof(sdp_media_e); i++) {
      sdp_media_supported(config_p, supported_media[i], true);
    }
    sdp_nettype_supported(config_p, SDP_NT_INTERNET, true);
    sdp_addrtype_supported(config_p, SDP_AT_IP4, true);
    sdp_addrtype_supported(config_p, SDP_AT_IP6, true);
    sdp_transport_supported(config_p, SDP_TRANSPORT_RTPSAVPF, true);
    sdp_transport_supported(config_p, SDP_TRANSPORT_UDPTL, true);
    sdp_require_session_name(config_p, false);

    sdp_ptr_ = sdp_init_description(config_p);
    if (!sdp_ptr_) {
      sdp_free_config(config_p);
    }
  }

  void ParseSdp(const std::string& sdp_str) {
    const char* buf = sdp_str.data();
    ResetSdp();
    ASSERT_EQ(sdp_parse(sdp_ptr_, buf, sdp_str.size()), SDP_SUCCESS);
  }

  void InitLocalSdp() {
    ResetSdp();
    ASSERT_EQ(sdp_set_version(sdp_ptr_, 0), SDP_SUCCESS);
    ASSERT_EQ(sdp_set_owner_username(sdp_ptr_, "-"), SDP_SUCCESS);
    ASSERT_EQ(sdp_set_owner_sessionid(sdp_ptr_, "132954853"), SDP_SUCCESS);
    ASSERT_EQ(sdp_set_owner_version(sdp_ptr_, "0"), SDP_SUCCESS);
    ASSERT_EQ(sdp_set_owner_network_type(sdp_ptr_, SDP_NT_INTERNET),
              SDP_SUCCESS);
    ASSERT_EQ(sdp_set_owner_address_type(sdp_ptr_, SDP_AT_IP4), SDP_SUCCESS);
    ASSERT_EQ(sdp_set_owner_address(sdp_ptr_, "198.51.100.7"), SDP_SUCCESS);
    ASSERT_EQ(sdp_set_session_name(sdp_ptr_, "SDP Unit Test"), SDP_SUCCESS);
    ASSERT_EQ(sdp_set_time_start(sdp_ptr_, "0"), SDP_SUCCESS);
    ASSERT_EQ(sdp_set_time_stop(sdp_ptr_, "0"), SDP_SUCCESS);
  }

  std::string SerializeSdp() {
    flex_string fs;
    flex_string_init(&fs);
    EXPECT_EQ(sdp_build(sdp_ptr_, &fs), SDP_SUCCESS);
    std::string body(fs.buffer);
    flex_string_free(&fs);
    return body;
  }

  // Returns "level" for new media section
  int AddNewMedia(sdp_media_e type) {
    final_level_++;
    EXPECT_EQ(sdp_insert_media_line(sdp_ptr_, final_level_), SDP_SUCCESS);
    EXPECT_EQ(sdp_set_conn_nettype(sdp_ptr_, final_level_, SDP_NT_INTERNET),
              SDP_SUCCESS);
    EXPECT_EQ(sdp_set_conn_addrtype(sdp_ptr_, final_level_, SDP_AT_IP4),
              SDP_SUCCESS);
    EXPECT_EQ(sdp_set_conn_address(sdp_ptr_, final_level_, "198.51.100.7"),
              SDP_SUCCESS);
    EXPECT_EQ(sdp_set_media_type(sdp_ptr_, final_level_, SDP_MEDIA_VIDEO),
              SDP_SUCCESS);
    EXPECT_EQ(
        sdp_set_media_transport(sdp_ptr_, final_level_, SDP_TRANSPORT_RTPAVP),
        SDP_SUCCESS);
    EXPECT_EQ(sdp_set_media_portnum(sdp_ptr_, final_level_, 12345, 0),
              SDP_SUCCESS);
    EXPECT_EQ(sdp_add_media_payload_type(sdp_ptr_, final_level_, 120,
                                         SDP_PAYLOAD_NUMERIC),
              SDP_SUCCESS);
    return final_level_;
  }

  uint16_t AddNewRtcpFbAck(int level, sdp_rtcp_fb_ack_type_e type,
                           uint16_t payload = SDP_ALL_PAYLOADS) {
    uint16_t inst_num = 0;
    EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_RTCP_FB, &inst_num),
              SDP_SUCCESS);
    EXPECT_EQ(
        sdp_attr_set_rtcp_fb_ack(sdp_ptr_, level, payload, inst_num, type),
        SDP_SUCCESS);
    return inst_num;
  }

  uint16_t AddNewRtcpFbNack(int level, sdp_rtcp_fb_nack_type_e type,
                            uint16_t payload = SDP_ALL_PAYLOADS) {
    uint16_t inst_num = 0;
    EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_RTCP_FB, &inst_num),
              SDP_SUCCESS);
    EXPECT_EQ(
        sdp_attr_set_rtcp_fb_nack(sdp_ptr_, level, payload, inst_num, type),
        SDP_SUCCESS);
    return inst_num;
  }

  uint16_t AddNewRtcpFbTrrInt(int level, uint32_t interval,
                              uint16_t payload = SDP_ALL_PAYLOADS) {
    uint16_t inst_num = 0;
    EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_RTCP_FB, &inst_num),
              SDP_SUCCESS);
    EXPECT_EQ(sdp_attr_set_rtcp_fb_trr_int(sdp_ptr_, level, payload, inst_num,
                                           interval),
              SDP_SUCCESS);
    return inst_num;
  }

  uint16_t AddNewRtcpFbRemb(int level, uint16_t payload = SDP_ALL_PAYLOADS) {
    uint16_t inst_num = 0;
    EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_RTCP_FB, &inst_num),
              SDP_SUCCESS);
    EXPECT_EQ(sdp_attr_set_rtcp_fb_remb(sdp_ptr_, level, payload, inst_num),
              SDP_SUCCESS);
    return inst_num;
  }

  uint16_t AddNewRtcpFbCcm(int level, sdp_rtcp_fb_ccm_type_e type,
                           uint16_t payload = SDP_ALL_PAYLOADS) {
    uint16_t inst_num = 0;
    EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_RTCP_FB, &inst_num),
              SDP_SUCCESS);
    EXPECT_EQ(
        sdp_attr_set_rtcp_fb_ccm(sdp_ptr_, level, payload, inst_num, type),
        SDP_SUCCESS);
    return inst_num;
  }
  uint16_t AddNewExtMap(int level, const char* uri) {
    uint16_t inst_num = 0;
    EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_EXTMAP, &inst_num),
              SDP_SUCCESS);
    EXPECT_EQ(sdp_attr_set_extmap(sdp_ptr_, level, inst_num, uri, inst_num),
              SDP_SUCCESS);
    return inst_num;
  }

  uint16_t AddNewFmtpMaxFs(int level, uint32_t max_fs) {
    uint16_t inst_num = 0;
    EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_FMTP, &inst_num),
              SDP_SUCCESS);
    EXPECT_EQ(sdp_attr_set_fmtp_payload_type(sdp_ptr_, level, 0, inst_num, 120),
              SDP_SUCCESS);
    EXPECT_EQ(sdp_attr_set_fmtp_max_fs(sdp_ptr_, level, 0, inst_num, max_fs),
              SDP_SUCCESS);
    return inst_num;
  }

  uint16_t AddNewFmtpMaxFr(int level, uint32_t max_fr) {
    uint16_t inst_num = 0;
    EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_FMTP, &inst_num),
              SDP_SUCCESS);
    EXPECT_EQ(sdp_attr_set_fmtp_payload_type(sdp_ptr_, level, 0, inst_num, 120),
              SDP_SUCCESS);
    EXPECT_EQ(sdp_attr_set_fmtp_max_fr(sdp_ptr_, level, 0, inst_num, max_fr),
              SDP_SUCCESS);
    return inst_num;
  }

  uint16_t AddNewFmtpMaxFsFr(int level, uint32_t max_fs, uint32_t max_fr) {
    uint16_t inst_num = 0;
    EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_FMTP, &inst_num),
              SDP_SUCCESS);
    EXPECT_EQ(sdp_attr_set_fmtp_payload_type(sdp_ptr_, level, 0, inst_num, 120),
              SDP_SUCCESS);
    EXPECT_EQ(sdp_attr_set_fmtp_max_fs(sdp_ptr_, level, 0, inst_num, max_fs),
              SDP_SUCCESS);
    EXPECT_EQ(sdp_attr_set_fmtp_max_fr(sdp_ptr_, level, 0, inst_num, max_fr),
              SDP_SUCCESS);
    return inst_num;
  }

 protected:
  int final_level_;
  sdp_t* sdp_ptr_;
};

MOZ_RUNINIT static const std::string kVideoSdp =
    "v=0\r\n"
    "o=- 4294967296 2 IN IP4 127.0.0.1\r\n"
    "s=SIP Call\r\n"
    "c=IN IP4 198.51.100.7\r\n"
    "t=0 0\r\n"
    "m=video 56436 RTP/SAVPF 120\r\n"
    "a=rtpmap:120 VP8/90000\r\n";

TEST_F(SdpTest, parseRtcpFbAckRpsi) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ack rpsi\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 1),
            SDP_RTCP_FB_ACK_RPSI);
}

TEST_F(SdpTest, parseRtcpFbAckApp) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ack app\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 1), SDP_RTCP_FB_ACK_APP);
}

TEST_F(SdpTest, parseRtcpFbAckAppFoo) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ack app foo\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 1), SDP_RTCP_FB_ACK_APP);
}

TEST_F(SdpTest, parseRtcpFbAckFooBar) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ack foo bar\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 1),
            SDP_RTCP_FB_ACK_UNKNOWN);
}

TEST_F(SdpTest, parseRtcpFbAckFooBarBaz) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ack foo bar baz\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 1),
            SDP_RTCP_FB_ACK_UNKNOWN);
}

TEST_F(SdpTest, parseRtcpFbNack) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 nack\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 1),
            SDP_RTCP_FB_NACK_BASIC);
}

TEST_F(SdpTest, parseRtcpFbNackPli) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 nack pli\r\n");
}

TEST_F(SdpTest, parseRtcpFbNackSli) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 nack sli\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 1),
            SDP_RTCP_FB_NACK_SLI);
}

TEST_F(SdpTest, parseRtcpFbNackRpsi) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 nack rpsi\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 1),
            SDP_RTCP_FB_NACK_RPSI);
}

TEST_F(SdpTest, parseRtcpFbNackApp) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 nack app\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 1),
            SDP_RTCP_FB_NACK_APP);
}

TEST_F(SdpTest, parseRtcpFbNackAppFoo) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 nack app foo\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 1),
            SDP_RTCP_FB_NACK_APP);
}

TEST_F(SdpTest, parseRtcpFbNackAppFooBar) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 nack app foo bar\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 1),
            SDP_RTCP_FB_NACK_APP);
}

TEST_F(SdpTest, parseRtcpFbNackFooBarBaz) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 nack foo bar baz\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 1),
            SDP_RTCP_FB_NACK_UNKNOWN);
}

TEST_F(SdpTest, parseRtcpFbRemb) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 goog-remb\r\n");
  ASSERT_EQ((bool)sdp_attr_get_rtcp_fb_remb_enabled(sdp_ptr_, 1, 120), true);
}

TEST_F(SdpTest, parseRtcpRbRembAllPt) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:* goog-remb\r\n");
  ASSERT_EQ(
      (bool)sdp_attr_get_rtcp_fb_remb_enabled(sdp_ptr_, 1, SDP_ALL_PAYLOADS),
      true);
}

TEST_F(SdpTest, parseRtcpFbTrrInt0) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 trr-int 0\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_trr_int(sdp_ptr_, 1, 120, 1), 0U);
}

TEST_F(SdpTest, parseRtcpFbTrrInt123) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 trr-int 123\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_trr_int(sdp_ptr_, 1, 120, 1), 123U);
}

TEST_F(SdpTest, parseRtcpFbCcmFir) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ccm fir\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 1), SDP_RTCP_FB_CCM_FIR);
}

TEST_F(SdpTest, parseRtcpFbCcmTmmbr) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ccm tmmbr\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 1),
            SDP_RTCP_FB_CCM_TMMBR);
}

TEST_F(SdpTest, parseRtcpFbCcmTmmbrSmaxpr) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ccm tmmbr smaxpr=456\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 1),
            SDP_RTCP_FB_CCM_TMMBR);
}

TEST_F(SdpTest, parseRtcpFbCcmTstr) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ccm tstr\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 1),
            SDP_RTCP_FB_CCM_TSTR);
}

TEST_F(SdpTest, parseRtcpFbCcmVbcm) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ccm vbcm 123 456 789\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 1),
            SDP_RTCP_FB_CCM_VBCM);
  // We don't currently parse out VBCM submessage types, since we don't have
  // any use for them.
}

TEST_F(SdpTest, parseRtcpFbCcmFoo) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ccm foo\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 1),
            SDP_RTCP_FB_CCM_UNKNOWN);
}

TEST_F(SdpTest, parseRtcpFbCcmFooBarBaz) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 ccm foo bar baz\r\n");
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 1),
            SDP_RTCP_FB_CCM_UNKNOWN);
}

TEST_F(SdpTest, parseRtcpFbFoo) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 foo\r\n");
}

TEST_F(SdpTest, parseRtcpFbFooBar) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 foo bar\r\n");
}

TEST_F(SdpTest, parseRtcpFbFooBarBaz) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:120 foo bar baz\r\n");
}

MOZ_RUNINIT static const std::string kVideoSdpWithUnknonwBrokenFtmp =
    "v=0\r\n"
    "o=- 4294967296 2 IN IP4 127.0.0.1\r\n"
    "s=SIP Call\r\n"
    "c=IN IP4 198.51.100.7\r\n"
    "t=0 0\r\n"
    "m=video 56436 RTP/SAVPF 120\r\n"
    "a=rtpmap:120 VP8/90000\r\n"
    "a=fmtp:122 unknown=10\n"
    "a=rtpmap:122 red/90000\r\n";

TEST_F(SdpTest, parseUnknownBrokenFtmp) {
  ParseSdp(kVideoSdpWithUnknonwBrokenFtmp);
}

TEST_F(SdpTest, parseRtcpFbKitchenSink) {
  ParseSdp(kVideoSdp +
           "a=rtcp-fb:120 ack rpsi\r\n"
           "a=rtcp-fb:120 ack app\r\n"
           "a=rtcp-fb:120 ack app foo\r\n"
           "a=rtcp-fb:120 ack foo bar\r\n"
           "a=rtcp-fb:120 ack foo bar baz\r\n"
           "a=rtcp-fb:120 nack\r\n"
           "a=rtcp-fb:120 nack pli\r\n"
           "a=rtcp-fb:120 nack sli\r\n"
           "a=rtcp-fb:120 nack rpsi\r\n"
           "a=rtcp-fb:120 nack app\r\n"
           "a=rtcp-fb:120 nack app foo\r\n"
           "a=rtcp-fb:120 nack app foo bar\r\n"
           "a=rtcp-fb:120 nack foo bar baz\r\n"
           "a=rtcp-fb:120 trr-int 0\r\n"
           "a=rtcp-fb:120 trr-int 123\r\n"
           "a=rtcp-fb:120 goog-remb\r\n"
           "a=rtcp-fb:120 ccm fir\r\n"
           "a=rtcp-fb:120 ccm tmmbr\r\n"
           "a=rtcp-fb:120 ccm tmmbr smaxpr=456\r\n"
           "a=rtcp-fb:120 ccm tstr\r\n"
           "a=rtcp-fb:120 ccm vbcm 123 456 789\r\n"
           "a=rtcp-fb:120 ccm foo\r\n"
           "a=rtcp-fb:120 ccm foo bar baz\r\n"
           "a=rtcp-fb:120 foo\r\n"
           "a=rtcp-fb:120 foo bar\r\n"
           "a=rtcp-fb:120 foo bar baz\r\n");

  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 1),
            SDP_RTCP_FB_ACK_RPSI);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 2), SDP_RTCP_FB_ACK_APP);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 3), SDP_RTCP_FB_ACK_APP);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 4),
            SDP_RTCP_FB_ACK_UNKNOWN);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 5),
            SDP_RTCP_FB_ACK_UNKNOWN);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, 120, 6),
            SDP_RTCP_FB_ACK_NOT_FOUND);

  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 1),
            SDP_RTCP_FB_NACK_BASIC);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 2),
            SDP_RTCP_FB_NACK_PLI);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 3),
            SDP_RTCP_FB_NACK_SLI);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 4),
            SDP_RTCP_FB_NACK_RPSI);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 5),
            SDP_RTCP_FB_NACK_APP);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 6),
            SDP_RTCP_FB_NACK_APP);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 7),
            SDP_RTCP_FB_NACK_APP);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 8),
            SDP_RTCP_FB_NACK_UNKNOWN);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 9),
            SDP_RTCP_FB_NACK_NOT_FOUND);

  ASSERT_EQ(sdp_attr_get_rtcp_fb_trr_int(sdp_ptr_, 1, 120, 1), 0U);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_trr_int(sdp_ptr_, 1, 120, 2), 123U);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_trr_int(sdp_ptr_, 1, 120, 3), 0xFFFFFFFF);

  ASSERT_EQ((bool)sdp_attr_get_rtcp_fb_remb_enabled(sdp_ptr_, 1, 120), true);
  ASSERT_EQ((bool)sdp_attr_get_rtcp_fb_remb_enabled(sdp_ptr_, 2, 120), false);

  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 1), SDP_RTCP_FB_CCM_FIR);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 2),
            SDP_RTCP_FB_CCM_TMMBR);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 3),
            SDP_RTCP_FB_CCM_TMMBR);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 4),
            SDP_RTCP_FB_CCM_TSTR);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 5),
            SDP_RTCP_FB_CCM_VBCM);
  // We don't currently parse out VBCM submessage types, since we don't have
  // any use for them.
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 6),
            SDP_RTCP_FB_CCM_UNKNOWN);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 7),
            SDP_RTCP_FB_CCM_UNKNOWN);
  ASSERT_EQ(sdp_attr_get_rtcp_fb_ccm(sdp_ptr_, 1, 120, 8),
            SDP_RTCP_FB_CCM_NOT_FOUND);
}

TEST_F(SdpTest, addRtcpFbAckRpsi) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbAck(level, SDP_RTCP_FB_ACK_RPSI, 120);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:120 ack rpsi\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbAckRpsiAllPt) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbAck(level, SDP_RTCP_FB_ACK_RPSI);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:* ack rpsi\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbAckApp) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbAck(level, SDP_RTCP_FB_ACK_APP, 120);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:120 ack app\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbAckAppAllPt) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbAck(level, SDP_RTCP_FB_ACK_APP);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:* ack app\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNack) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_BASIC, 120);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:120 nack\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNackAllPt) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_BASIC);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:* nack\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNackSli) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_SLI, 120);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:120 nack sli\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNackSliAllPt) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_SLI);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:* nack sli\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNackPli) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_PLI, 120);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:120 nack pli\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNackPliAllPt) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_PLI);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:* nack pli\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNackRpsi) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_RPSI, 120);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:120 nack rpsi\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNackRpsiAllPt) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_RPSI);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:* nack rpsi\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNackApp) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_APP, 120);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:120 nack app\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNackAppAllPt) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_APP);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:* nack app\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNackRai) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_RAI, 120);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:120 nack rai\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNackRaiAllPt) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_RAI);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:* nack rai\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNackTllei) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_TLLEI, 120);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:120 nack tllei\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNackTlleiAllPt) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_TLLEI);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:* nack tllei\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNackPslei) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_PSLEI, 120);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:120 nack pslei\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNackPsleiAllPt) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_PSLEI);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:* nack pslei\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNackEcn) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_ECN, 120);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:120 nack ecn\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNackEcnAllPt) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_ECN);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:* nack ecn\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbRemb) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbRemb(level, 120);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:120 goog-remb\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbRembAllPt) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbRemb(level);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:* goog-remb\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbTrrInt) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbTrrInt(level, 12345, 120);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:120 trr-int 12345\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbNackTrrIntAllPt) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbTrrInt(level, 0);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:* trr-int 0\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbCcmFir) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_FIR, 120);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:120 ccm fir\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbCcmFirAllPt) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_FIR);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:* ccm fir\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbCcmTmmbr) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_TMMBR, 120);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:120 ccm tmmbr\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbCcmTmmbrAllPt) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_TMMBR);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:* ccm tmmbr\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbCcmTstr) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_TSTR, 120);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:120 ccm tstr\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbCcmTstrAllPt) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_TSTR);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:* ccm tstr\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbCcmVbcm) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_VBCM, 120);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:120 ccm vbcm\r\n"), std::string::npos);
}

TEST_F(SdpTest, addRtcpFbCcmVbcmAllPt) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_VBCM);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=rtcp-fb:* ccm vbcm\r\n"), std::string::npos);
}

TEST_F(SdpTest, parseRtcpFbAllPayloads) {
  ParseSdp(kVideoSdp + "a=rtcp-fb:* ack rpsi\r\n");
  for (int i = 0; i < 128; i++) {
    ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, i, 1),
              SDP_RTCP_FB_ACK_RPSI);
  }
}
TEST_F(SdpTest, addExtMap) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewExtMap(level, SDP_EXTMAP_AUDIO_LEVEL);
  std::string body = SerializeSdp();
  ASSERT_NE(
      body.find("a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n"),
      std::string::npos);
}

TEST_F(SdpTest, parseExtMap) {
  ParseSdp(kVideoSdp +
           "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n");
  ASSERT_STREQ(sdp_attr_get_extmap_uri(sdp_ptr_, 1, 1), SDP_EXTMAP_AUDIO_LEVEL);
  ASSERT_EQ(sdp_attr_get_extmap_id(sdp_ptr_, 1, 1), 1);
}

TEST_F(SdpTest, parseFmtpBitrate) {
  ParseSdp(kVideoSdp + "a=fmtp:120 bitrate=400\r\n");
  ASSERT_EQ(400, sdp_attr_get_fmtp_bitrate_type(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpBitrateWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 bitrate=0\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE,
            sdp_attr_get_fmtp_bitrate_type(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpBitrateWith32001) {
  ParseSdp(kVideoSdp + "a=fmtp:120 bitrate=32001\r\n");
  ASSERT_EQ(32001, sdp_attr_get_fmtp_bitrate_type(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpBitrateWith4294967296) {
  ParseSdp(kVideoSdp + "a=fmtp:120 bitrate=4294967296\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE,
            sdp_attr_get_fmtp_bitrate_type(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpMode) {
  ParseSdp(kVideoSdp + "a=fmtp:120 mode=200\r\n");
  ASSERT_EQ(200U, sdp_attr_get_fmtp_mode_for_payload_type(sdp_ptr_, 1, 0, 120));
}

TEST_F(SdpTest, parseFmtpModeWith4294967295) {
  ParseSdp(kVideoSdp + "a=fmtp:120 mode=4294967295\r\n");
  ASSERT_EQ(4294967295,
            sdp_attr_get_fmtp_mode_for_payload_type(sdp_ptr_, 1, 0, 120));
}

TEST_F(SdpTest, parseFmtpModeWith4294967296) {
  ParseSdp(kVideoSdp + "a=fmtp:120 mode=4294967296\r\n");
  // returns 0 if not found
  ASSERT_EQ(0U, sdp_attr_get_fmtp_mode_for_payload_type(sdp_ptr_, 1, 0, 120));
}

TEST_F(SdpTest, parseFmtpQcif) {
  ParseSdp(kVideoSdp + "a=fmtp:120 qcif=20\r\n");
  ASSERT_EQ(20, sdp_attr_get_fmtp_qcif(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpQcifWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 qcif=0\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_qcif(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpQcifWith33) {
  ParseSdp(kVideoSdp + "a=fmtp:120 qcif=33\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_qcif(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpCif) {
  ParseSdp(kVideoSdp + "a=fmtp:120 cif=11\r\n");
  ASSERT_EQ(11, sdp_attr_get_fmtp_cif(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpCifWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 cif=0\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_cif(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpCifWith33) {
  ParseSdp(kVideoSdp + "a=fmtp:120 cif=33\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_cif(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpMaxbr) {
  ParseSdp(kVideoSdp + "a=fmtp:120 maxbr=21\r\n");
  ASSERT_EQ(21, sdp_attr_get_fmtp_maxbr(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpMaxbrWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 maxbr=0\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_maxbr(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpMaxbrWith65536) {
  ParseSdp(kVideoSdp + "a=fmtp:120 maxbr=65536\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_maxbr(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpSqcif) {
  ParseSdp(kVideoSdp + "a=fmtp:120 sqcif=6\r\n");
  ASSERT_EQ(6, sdp_attr_get_fmtp_sqcif(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpSqcifWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 sqcif=0\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_sqcif(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpSqcifWith33) {
  ParseSdp(kVideoSdp + "a=fmtp:120 sqcif=33\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_sqcif(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpCif4) {
  ParseSdp(kVideoSdp + "a=fmtp:120 cif4=11\r\n");
  ASSERT_EQ(11, sdp_attr_get_fmtp_cif4(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpCif4With0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 cif4=0\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_cif4(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpCif4With33) {
  ParseSdp(kVideoSdp + "a=fmtp:120 cif4=33\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_cif4(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpCif16) {
  ParseSdp(kVideoSdp + "a=fmtp:120 cif16=11\r\n");
  ASSERT_EQ(11, sdp_attr_get_fmtp_cif16(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpCif16With0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 cif16=0\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_cif16(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpCif16With33) {
  ParseSdp(kVideoSdp + "a=fmtp:120 cif16=33\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_cif16(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpBpp) {
  ParseSdp(kVideoSdp + "a=fmtp:120 bpp=7\r\n");
  ASSERT_EQ(7, sdp_attr_get_fmtp_bpp(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpBppWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 bpp=0\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_bpp(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpBppWith65536) {
  ParseSdp(kVideoSdp + "a=fmtp:120 bpp=65536\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_bpp(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpHrd) {
  ParseSdp(kVideoSdp + "a=fmtp:120 hrd=800\r\n");
  ASSERT_EQ(800, sdp_attr_get_fmtp_hrd(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpHrdWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 hrd=0\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_hrd(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpHrdWith65536) {
  ParseSdp(kVideoSdp + "a=fmtp:120 hrd=65536\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_hrd(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpProfile) {
  ParseSdp(kVideoSdp + "a=fmtp:120 profile=4\r\n");
  ASSERT_EQ(4, sdp_attr_get_fmtp_profile(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpProfileWith11) {
  ParseSdp(kVideoSdp + "a=fmtp:120 profile=11\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_profile(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpLevel) {
  ParseSdp(kVideoSdp + "a=fmtp:120 level=56\r\n");
  ASSERT_EQ(56, sdp_attr_get_fmtp_level(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpLevelWith101) {
  ParseSdp(kVideoSdp + "a=fmtp:120 level=101\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE, sdp_attr_get_fmtp_level(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpPacketizationMode) {
  ParseSdp(kVideoSdp + "a=fmtp:120 packetization-mode=1\r\n");
  uint16_t packetizationMode;
  ASSERT_EQ(SDP_SUCCESS,
            sdp_attr_get_fmtp_pack_mode(sdp_ptr_, 1, 0, 1, &packetizationMode));
  ASSERT_EQ(1, packetizationMode);
}

TEST_F(SdpTest, parseFmtpPacketizationModeWith3) {
  ParseSdp(kVideoSdp + "a=fmtp:120 packetization-mode=3\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_pack_mode(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpInterleavingDepth) {
  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-interleaving-depth=566\r\n");
  uint16_t interleavingDepth;
  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_interleaving_depth(
                             sdp_ptr_, 1, 0, 1, &interleavingDepth));
  ASSERT_EQ(566, interleavingDepth);
}

TEST_F(SdpTest, parseFmtpInterleavingDepthWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-interleaving-depth=0\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_interleaving_depth(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpInterleavingDepthWith65536) {
  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-interleaving-depth=65536\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_interleaving_depth(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpDeintBuf) {
  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-deint-buf-req=4294967295\r\n");
  uint32_t deintBuf;
  ASSERT_EQ(SDP_SUCCESS,
            sdp_attr_get_fmtp_deint_buf_req(sdp_ptr_, 1, 0, 1, &deintBuf));
  ASSERT_EQ(4294967295, deintBuf);
}

TEST_F(SdpTest, parseFmtpDeintBufWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-deint-buf-req=0\r\n");
  uint32_t deintBuf;
  ASSERT_EQ(SDP_SUCCESS,
            sdp_attr_get_fmtp_deint_buf_req(sdp_ptr_, 1, 0, 1, &deintBuf));
  ASSERT_EQ(0U, deintBuf);
}

TEST_F(SdpTest, parseFmtpDeintBufWith4294967296) {
  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-deint-buf-req=4294967296\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_deint_buf_req(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpMaxDonDiff) {
  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-max-don-diff=5678\r\n");
  uint32_t maxDonDiff;
  ASSERT_EQ(SDP_SUCCESS,
            sdp_attr_get_fmtp_max_don_diff(sdp_ptr_, 1, 0, 1, &maxDonDiff));
  ASSERT_EQ(5678U, maxDonDiff);
}

TEST_F(SdpTest, parseFmtpMaxDonDiffWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-max-don-diff=0\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_max_don_diff(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpMaxDonDiffWith4294967296) {
  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-max-don-diff=4294967296\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_max_don_diff(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpInitBufTime) {
  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-init-buf-time=4294967295\r\n");
  uint32_t initBufTime;
  ASSERT_EQ(SDP_SUCCESS,
            sdp_attr_get_fmtp_init_buf_time(sdp_ptr_, 1, 0, 1, &initBufTime));
  ASSERT_EQ(4294967295, initBufTime);
}

TEST_F(SdpTest, parseFmtpInitBufTimeWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-init-buf-time=0\r\n");
  uint32_t initBufTime;
  ASSERT_EQ(SDP_SUCCESS,
            sdp_attr_get_fmtp_init_buf_time(sdp_ptr_, 1, 0, 1, &initBufTime));
  ASSERT_EQ(0U, initBufTime);
}

TEST_F(SdpTest, parseFmtpInitBufTimeWith4294967296) {
  ParseSdp(kVideoSdp + "a=fmtp:120 sprop-init-buf-time=4294967296\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_init_buf_time(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpMaxMbps) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-mbps=46789\r\n");
  uint32_t maxMpbs;
  ASSERT_EQ(SDP_SUCCESS,
            sdp_attr_get_fmtp_max_mbps(sdp_ptr_, 1, 0, 1, &maxMpbs));
  ASSERT_EQ(46789U, maxMpbs);
}

TEST_F(SdpTest, parseFmtpMaxMbpsWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-mbps=0\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_max_mbps(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpMaxMbpsWith4294967296) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-mbps=4294967296\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_max_mbps(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpMaxCpb) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-cpb=47891\r\n");
  uint32_t maxCpb;
  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_max_cpb(sdp_ptr_, 1, 0, 1, &maxCpb));
  ASSERT_EQ(47891U, maxCpb);
}

TEST_F(SdpTest, parseFmtpMaxCpbWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-cpb=0\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_max_cpb(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpMaxCpbWith4294967296) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-cpb=4294967296\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_max_cpb(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpMaxDpb) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-dpb=47892\r\n");
  uint32_t maxDpb;
  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_max_dpb(sdp_ptr_, 1, 0, 1, &maxDpb));
  ASSERT_EQ(47892U, maxDpb);
}

TEST_F(SdpTest, parseFmtpMaxDpbWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-dpb=0\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_max_dpb(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpMaxDpbWith4294967296) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-dpb=4294967296\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_max_dpb(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpMaxBr) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-br=47893\r\n");
  uint32_t maxBr;
  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_max_br(sdp_ptr_, 1, 0, 1, &maxBr));
  ASSERT_EQ(47893U, maxBr);
}

TEST_F(SdpTest, parseFmtpMaxBrWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-br=0\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_max_br(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpMaxBrWith4294967296) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-br=4294967296\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_max_br(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpRedundantPicCap) {
  ParseSdp(kVideoSdp + "a=fmtp:120 redundant-pic-cap=1\r\n");
  ASSERT_EQ(1, sdp_attr_fmtp_is_redundant_pic_cap(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpRedundantPicCapWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 redundant-pic-cap=0\r\n");
  ASSERT_EQ(0, sdp_attr_fmtp_is_redundant_pic_cap(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpRedundantPicCapWith2) {
  ParseSdp(kVideoSdp + "a=fmtp:120 redundant-pic-cap=2\r\n");
  ASSERT_EQ(0, sdp_attr_fmtp_is_redundant_pic_cap(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpDeintBufCap) {
  ParseSdp(kVideoSdp + "a=fmtp:120 deint-buf-cap=4294967295\r\n");
  uint32_t deintBufCap;
  ASSERT_EQ(SDP_SUCCESS,
            sdp_attr_get_fmtp_deint_buf_cap(sdp_ptr_, 1, 0, 1, &deintBufCap));
  ASSERT_EQ(4294967295, deintBufCap);
}

TEST_F(SdpTest, parseFmtpDeintBufCapWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 deint-buf-cap=0\r\n");
  uint32_t deintBufCap;
  ASSERT_EQ(SDP_SUCCESS,
            sdp_attr_get_fmtp_deint_buf_cap(sdp_ptr_, 1, 0, 1, &deintBufCap));
  ASSERT_EQ(0U, deintBufCap);
}

TEST_F(SdpTest, parseFmtpDeintBufCapWith4294967296) {
  ParseSdp(kVideoSdp + "a=fmtp:120 deint-buf-cap=4294967296\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_deint_buf_cap(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpMaxRcmdNaluSize) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-rcmd-nalu-size=4294967295\r\n");
  uint32_t maxRcmdNaluSize;
  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_max_rcmd_nalu_size(
                             sdp_ptr_, 1, 0, 1, &maxRcmdNaluSize));
  ASSERT_EQ(4294967295, maxRcmdNaluSize);
}

TEST_F(SdpTest, parseFmtpMaxRcmdNaluSizeWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-rcmd-nalu-size=0\r\n");
  uint32_t maxRcmdNaluSize;
  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_max_rcmd_nalu_size(
                             sdp_ptr_, 1, 0, 1, &maxRcmdNaluSize));
  ASSERT_EQ(0U, maxRcmdNaluSize);
}

TEST_F(SdpTest, parseFmtpMaxRcmdNaluSizeWith4294967296) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-rcmd-nalu-size=4294967296\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_max_rcmd_nalu_size(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpParameterAdd) {
  ParseSdp(kVideoSdp + "a=fmtp:120 parameter-add=1\r\n");
  ASSERT_EQ(1, sdp_attr_fmtp_is_parameter_add(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpParameterAddWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 parameter-add=0\r\n");
  ASSERT_EQ(0, sdp_attr_fmtp_is_parameter_add(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpParameterAddWith2) {
  ParseSdp(kVideoSdp + "a=fmtp:120 parameter-add=2\r\n");
  ASSERT_EQ(0, sdp_attr_fmtp_is_parameter_add(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpAnnexK) {
  ParseSdp(kVideoSdp + "a=fmtp:120 K=566\r\n");
  ASSERT_EQ(566, sdp_attr_get_fmtp_annex_k_val(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpAnnexKWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 K=0\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE,
            sdp_attr_get_fmtp_annex_k_val(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpAnnexKWith65536) {
  ParseSdp(kVideoSdp + "a=fmtp:120 K=65536\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE,
            sdp_attr_get_fmtp_annex_k_val(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpAnnexN) {
  ParseSdp(kVideoSdp + "a=fmtp:120 N=4567\r\n");
  ASSERT_EQ(4567, sdp_attr_get_fmtp_annex_n_val(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpAnnexNWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 N=0\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE,
            sdp_attr_get_fmtp_annex_n_val(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpAnnexNWith65536) {
  ParseSdp(kVideoSdp + "a=fmtp:120 N=65536\r\n");
  ASSERT_EQ(SDP_INVALID_VALUE,
            sdp_attr_get_fmtp_annex_n_val(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpAnnexP) {
  ParseSdp(kVideoSdp + "a=fmtp:120 P=5678,2\r\n");
  ASSERT_EQ(5678, sdp_attr_get_fmtp_annex_p_picture_resize(sdp_ptr_, 1, 0, 1));
  ASSERT_EQ(2, sdp_attr_get_fmtp_annex_p_warp(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpAnnexPWithResize0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 P=0,3\r\n");
  ASSERT_EQ(0, sdp_attr_get_fmtp_annex_p_picture_resize(sdp_ptr_, 1, 0, 1));
  ASSERT_EQ(3, sdp_attr_get_fmtp_annex_p_warp(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpAnnexPWithResize65536) {
  ParseSdp(kVideoSdp + "a=fmtp:120 P=65536,4\r\n");
  ASSERT_EQ(0, sdp_attr_get_fmtp_annex_p_picture_resize(sdp_ptr_, 1, 0, 1));
  // if the first fails, the second will too.  Both default to 0 on failure.
  ASSERT_EQ(0, sdp_attr_get_fmtp_annex_p_warp(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpAnnexPWithWarp65536) {
  ParseSdp(kVideoSdp + "a=fmtp:120 P=346,65536\r\n");
  ASSERT_EQ(346, sdp_attr_get_fmtp_annex_p_picture_resize(sdp_ptr_, 1, 0, 1));
  ASSERT_EQ(0, sdp_attr_get_fmtp_annex_p_warp(sdp_ptr_, 1, 0, 1));
}

TEST_F(SdpTest, parseFmtpLevelAsymmetryAllowed) {
  ParseSdp(kVideoSdp + "a=fmtp:120 level-asymmetry-allowed=1\r\n");

  uint16_t levelAsymmetryAllowed;
  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_level_asymmetry_allowed(
                             sdp_ptr_, 1, 0, 1, &levelAsymmetryAllowed));
  ASSERT_EQ(1U, levelAsymmetryAllowed);
}

TEST_F(SdpTest, parseFmtpLevelAsymmetryAllowedWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 level-asymmetry-allowed=0\r\n");
  uint16_t levelAsymmetryAllowed;
  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_level_asymmetry_allowed(
                             sdp_ptr_, 1, 0, 1, &levelAsymmetryAllowed));
  ASSERT_EQ(0U, levelAsymmetryAllowed);
}

TEST_F(SdpTest, parseFmtpLevelAsymmetryAllowedWith2) {
  ParseSdp(kVideoSdp + "a=fmtp:120 level-asymmetry-allowed=2\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER, sdp_attr_get_fmtp_level_asymmetry_allowed(
                                       sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpMaxAverageBitrate) {
  ParseSdp(kVideoSdp + "a=fmtp:120 maxaveragebitrate=47893\r\n");
  uint32_t maxAverageBitrate;
  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_max_average_bitrate(
                             sdp_ptr_, 1, 0, 1, &maxAverageBitrate));
  ASSERT_EQ(47893U, maxAverageBitrate);
}

TEST_F(SdpTest, parseFmtpMaxAverageBitrateWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 maxaveragebitrate=0\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_max_average_bitrate(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpMaxAverageBitrateWith4294967296) {
  ParseSdp(kVideoSdp + "a=fmtp:120 maxaveragebitrate=4294967296\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_max_average_bitrate(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpUsedTx) {
  ParseSdp(kVideoSdp + "a=fmtp:120 usedtx=1\r\n");
  tinybool usedTx;
  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_usedtx(sdp_ptr_, 1, 0, 1, &usedTx));
  ASSERT_EQ(1, usedTx);
}

TEST_F(SdpTest, parseFmtpUsedTxWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 usedtx=0\r\n");
  tinybool usedTx;
  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_usedtx(sdp_ptr_, 1, 0, 1, &usedTx));
  ASSERT_EQ(0, usedTx);
}

TEST_F(SdpTest, parseFmtpUsedTxWith2) {
  ParseSdp(kVideoSdp + "a=fmtp:120 usedtx=2\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_usedtx(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpStereo) {
  ParseSdp(kVideoSdp + "a=fmtp:120 stereo=1\r\n");
  tinybool stereo;
  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_stereo(sdp_ptr_, 1, 0, 1, &stereo));
  ASSERT_EQ(1, stereo);
}

TEST_F(SdpTest, parseFmtpStereoWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 stereo=0\r\n");
  tinybool stereo;
  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_stereo(sdp_ptr_, 1, 0, 1, &stereo));
  ASSERT_EQ(0, stereo);
}

TEST_F(SdpTest, parseFmtpStereoWith2) {
  ParseSdp(kVideoSdp + "a=fmtp:120 stereo=2\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_stereo(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpUseInBandFec) {
  ParseSdp(kVideoSdp + "a=fmtp:120 useinbandfec=1\r\n");
  tinybool useInbandFec;
  ASSERT_EQ(SDP_SUCCESS,
            sdp_attr_get_fmtp_useinbandfec(sdp_ptr_, 1, 0, 1, &useInbandFec));
  ASSERT_EQ(1, useInbandFec);
}

TEST_F(SdpTest, parseFmtpUseInBandWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 useinbandfec=0\r\n");
  tinybool useInbandFec;
  ASSERT_EQ(SDP_SUCCESS,
            sdp_attr_get_fmtp_useinbandfec(sdp_ptr_, 1, 0, 1, &useInbandFec));
  ASSERT_EQ(0, useInbandFec);
}

TEST_F(SdpTest, parseFmtpUseInBandWith2) {
  ParseSdp(kVideoSdp + "a=fmtp:120 useinbandfec=2\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_useinbandfec(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpMaxCodedAudioBandwidth) {
  ParseSdp(kVideoSdp + "a=fmtp:120 maxcodedaudiobandwidth=abcdefg\r\n");
  char* maxCodedAudioBandwith =
      sdp_attr_get_fmtp_maxcodedaudiobandwidth(sdp_ptr_, 1, 0, 1);
  ASSERT_EQ(0, strcmp("abcdefg", maxCodedAudioBandwith));
}

TEST_F(SdpTest, parseFmtpMaxCodedAudioBandwidthBad) {
  ParseSdp(kVideoSdp + "a=fmtp:120 maxcodedaudiobandwidth=\r\n");
  char* maxCodedAudioBandwith =
      sdp_attr_get_fmtp_maxcodedaudiobandwidth(sdp_ptr_, 1, 0, 1);
  ASSERT_EQ(0, *maxCodedAudioBandwith);
}

TEST_F(SdpTest, parseFmtpCbr) {
  ParseSdp(kVideoSdp + "a=fmtp:120 cbr=1\r\n");
  tinybool cbr;
  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_cbr(sdp_ptr_, 1, 0, 1, &cbr));
  ASSERT_EQ(1, cbr);
}

TEST_F(SdpTest, parseFmtpCbrWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 cbr=0\r\n");
  tinybool cbr;
  ASSERT_EQ(SDP_SUCCESS, sdp_attr_get_fmtp_cbr(sdp_ptr_, 1, 0, 1, &cbr));
  ASSERT_EQ(0, cbr);
}

TEST_F(SdpTest, parseFmtpCbrWith2) {
  ParseSdp(kVideoSdp + "a=fmtp:120 cbr=2\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_cbr(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpMaxPlaybackRate) {
  ParseSdp(kVideoSdp + "a=fmtp:120 maxplaybackrate=47900\r\n");
  sdp_attr_t* attr_p = sdp_find_attr(sdp_ptr_, 1, 0, SDP_ATTR_FMTP, 1);
  ASSERT_NE(nullptr, attr_p);
  ASSERT_EQ(47900U, attr_p->attr.fmtp.maxplaybackrate);
}

TEST_F(SdpTest, parseFmtpMaxPlaybackRateWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 maxplaybackrate=0\r\n");
  sdp_attr_t* attr_p = sdp_find_attr(sdp_ptr_, 1, 0, SDP_ATTR_FMTP, 1);
  ASSERT_EQ(NULL, attr_p);
}

TEST_F(SdpTest, parseFmtpMaxPlaybackRateWith4294967296) {
  ParseSdp(kVideoSdp + "a=fmtp:120 maxplaybackrate=4294967296\r\n");
  sdp_attr_t* attr_p = sdp_find_attr(sdp_ptr_, 1, 0, SDP_ATTR_FMTP, 1);
  ASSERT_EQ(NULL, attr_p);
}

TEST_F(SdpTest, parseFmtpMaxFs) {
  uint32_t val = 0;
  ParseSdp(kVideoSdp + "a=fmtp:120 max-fs=300;max-fr=30\r\n");
  ASSERT_EQ(sdp_attr_get_fmtp_max_fs(sdp_ptr_, 1, 0, 1, &val), SDP_SUCCESS);
  ASSERT_EQ(val, 300U);
}
TEST_F(SdpTest, parseFmtpMaxFsWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-fs=0\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_max_fs(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpMaxFsWith4294967296) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-fs=4294967296\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_max_fs(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpMaxFr) {
  uint32_t val = 0;
  ParseSdp(kVideoSdp + "a=fmtp:120 max-fs=300;max-fr=30\r\n");
  ASSERT_EQ(sdp_attr_get_fmtp_max_fr(sdp_ptr_, 1, 0, 1, &val), SDP_SUCCESS);
  ASSERT_EQ(val, 30U);
}

TEST_F(SdpTest, parseFmtpMaxFrWith0) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-fr=0\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_max_fr(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, parseFmtpMaxFrWith4294967296) {
  ParseSdp(kVideoSdp + "a=fmtp:120 max-fr=4294967296\r\n");
  ASSERT_EQ(SDP_INVALID_PARAMETER,
            sdp_attr_get_fmtp_max_fr(sdp_ptr_, 1, 0, 1, nullptr));
}

TEST_F(SdpTest, addFmtpMaxFs) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewFmtpMaxFs(level, 300);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=fmtp:120 max-fs=300\r\n"), std::string::npos);
}

TEST_F(SdpTest, addFmtpMaxFr) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewFmtpMaxFr(level, 30);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=fmtp:120 max-fr=30\r\n"), std::string::npos);
}

TEST_F(SdpTest, addFmtpMaxFsFr) {
  InitLocalSdp();
  int level = AddNewMedia(SDP_MEDIA_VIDEO);
  AddNewFmtpMaxFsFr(level, 300, 30);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=fmtp:120 max-fs=300;max-fr=30\r\n"),
            std::string::npos);
}

MOZ_RUNINIT static const std::string kBrokenFmtp =
    "v=0\r\n"
    "o=- 4294967296 2 IN IP4 127.0.0.1\r\n"
    "s=SIP Call\r\n"
    "t=0 0\r\n"
    "m=video 56436 RTP/SAVPF 120\r\n"
    "c=IN IP4 198.51.100.7\r\n"
    "a=rtpmap:120 VP8/90000\r\n"
    /* Note: the \0 in this string triggered bz://1089207
     */

    "a=fmtp:120 max-fs=300;max\0fr=30";

TEST_F(SdpTest, parseBrokenFmtp) {
  uint32_t val = 0;
  const char* buf = kBrokenFmtp.data();
  ResetSdp();
  /* We need to manually invoke the parser here to be able to specify the length
   * of the string beyond the \0 in last line of the string.
   */

  ASSERT_EQ(sdp_parse(sdp_ptr_, buf, 165), SDP_SUCCESS);
  ASSERT_EQ(sdp_attr_get_fmtp_max_fs(sdp_ptr_, 1, 0, 1, &val),
            SDP_INVALID_PARAMETER);
}

TEST_F(SdpTest, addIceLite) {
  InitLocalSdp();
  uint16_t inst_num = 0;
  EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, SDP_SESSION_LEVEL, 0, SDP_ATTR_ICE_LITE,
                             &inst_num),
            SDP_SUCCESS);
  std::string body = SerializeSdp();
  ASSERT_NE(body.find("a=ice-lite\r\n"), std::string::npos);
}

TEST_F(SdpTest, parseIceLite) {
  std::string sdp =
      "v=0\r\n"
      "o=- 4294967296 2 IN IP4 127.0.0.1\r\n"
      "s=SIP Call\r\n"
      "t=0 0\r\n"
      "a=ice-lite\r\n";
  ParseSdp(sdp);
  ASSERT_TRUE(
      sdp_attr_is_present(sdp_ptr_, SDP_ATTR_ICE_LITE, SDP_SESSION_LEVEL, 0));
}

class NewSdpTest
    : public ::testing::Test,
      public ::testing::WithParamInterface< ::testing::tuple<boolbool> > {
 public:
  NewSdpTest() = default;

  void ParseSdp(const std::string& sdp, bool expectSuccess = true,
                bool expectEqual = true) {
    UniquePtr<SdpParser> firstParser(new RsdparsaSdpParser());
    UniquePtr<SdpParser> secondParser(new SipccSdpParser());
    if (::testing::get<1>(GetParam())) {
      firstParser.swap(secondParser);
    }
    mResults = firstParser->Parse(sdp);
#ifdef DEBUG_DISPLAY_SDP
    std::cout << firstParser->Name() << " Parsing SDP:" << std::endl;
    std::stringstream sdpStream(sdp);
    std::string line;
    size_t lineNumber = 0;
    while (std::getline(sdpStream, line, '\n')) {
      if (line.length() && line.back() == '\r') {
        line.pop_back();
      }
      lineNumber++;
      std::cout << std::setw(4) << lineNumber << " " << line << std::endl;
    }
#endif
    // Are we configured to do a parse and serialize before actually
    // running the test?
    if (::testing::get<0>(GetParam())) {
      if (expectSuccess) {
        ASSERT_TRUE(!!mResults->Sdp())
        << "Parse failed on first pass: " << SerializeParseErrors();
      }

      if (mResults->Sdp()) {
        std::stringstream os, os2;
        // Serialize and re-parse
        mResults->Sdp()->Serialize(os);
        const auto secondResults = secondParser->Parse(os.str());
        // Whether we expected the parse to work or not, it should
        // succeed the second time if it succeeded the first.
        ASSERT_TRUE(!!Sdp())
        << "Parse failed on second pass, SDP was: " << std::endl
        << os.str() << std::endl
        << "Errors were: " << IntSerializeParseErrors(secondResults);
        // Serialize again and compare
        secondResults->Sdp()->Serialize(os2);
        if (expectEqual) {
          ASSERT_EQ(os.str(), os2.str())
              << "FIRST IS " << mResults->ParserName() << ", SECOND IS "
              << secondResults->ParserName();
        } else {
          ASSERT_NE(os.str(), os2.str())
              << "FIRST IS " << mResults->ParserName() << ", SECOND IS "
              << secondResults->ParserName();
        }
      }
    }

    if (expectSuccess) {
      ASSERT_TRUE(!!mResults->Sdp())
      << "Parse failed: " << SerializeParseErrors();
      ASSERT_EQ(0U, ParseErrorCount())
          << "Got unexpected parse errors/warnings: " << SerializeParseErrors();
    }
  }
  const UniquePtr<class Sdp>& Sdp() const {
    static const UniquePtr<class Sdp> NO_SDP(nullptr);
    return mResults ? mResults->Sdp() : NO_SDP;
  }

  size_t ParseErrorCount() const { return mResults->Errors().size(); }
  size_t ParseWarningCount() const { return mResults->Warnings().size(); }

  std::string IntSerializeParseErrors(
      const UniquePtr<SdpParser::Results>& aResults) const {
    std::stringstream output;
    for (const auto& e : aResults->Errors()) {
      output << e.first << ": " << e.second << std::endl;
    }
    return output.str();
  }
  // For streaming parse errors
  std::string SerializeParseErrors() const {
    return IntSerializeParseErrors(mResults);
  }

  std::string IntSerializeParseWarnings(
      const UniquePtr<SdpParser::Results>& aResults) const {
    std::stringstream output;
    for (const auto& e : aResults->Warnings()) {
      output << e.first << ": " << e.second << std::endl;
    }
    return output.str();
  }

  std::string SerializeParseWarnings() const {
    return IntSerializeParseWarnings(mResults);
  }

  void CheckRtpmap(const std::string& expected_pt,
                   SdpRtpmapAttributeList::CodecType codec,
                   const std::string& name, uint32_t clock, uint16_t channels,
                   const std::string& search_pt,
                   const SdpRtpmapAttributeList& rtpmaps) const {
    ASSERT_TRUE(rtpmaps.HasEntry(search_pt));
    auto attr = rtpmaps.GetEntry(search_pt);
    ASSERT_EQ(expected_pt, attr.pt);
    ASSERT_EQ(codec, attr.codec);
    std::cout << "Codec = " << name << std::endl;
    ASSERT_EQ(name, attr.name);
    ASSERT_EQ(clock, attr.clock);
    ASSERT_EQ(channels, attr.channels);
  }

  void CheckSctpmap(const std::string& expected_pt, const std::string& name,
                    uint16_t streams, const std::string& search_pt,
                    const SdpSctpmapAttributeList& sctpmaps) const {
    ASSERT_TRUE(sctpmaps.HasEntry(search_pt));
    auto attr = sctpmaps.GetFirstEntry();
    ASSERT_EQ(expected_pt, search_pt);
    ASSERT_EQ(expected_pt, attr.pt);
    ASSERT_EQ(name, attr.name);
    ASSERT_EQ(streams, attr.streams);
  }

  void CheckRtcpFb(const SdpRtcpFbAttributeList::Feedback& feedback,
                   const std::string& pt, SdpRtcpFbAttributeList::Type type,
                   const std::string& first_parameter,
                   const std::string& extra = ""const {
    ASSERT_EQ(pt, feedback.pt);
    ASSERT_EQ(type, feedback.type);
    ASSERT_EQ(first_parameter, feedback.parameter);
    ASSERT_EQ(extra, feedback.extra);
  }

  void CheckDtmfFmtp(const std::string& expectedDtmfTones) const {
    ASSERT_TRUE(Sdp()->GetMediaSection(0).GetAttributeList().HasAttribute(
        SdpAttribute::kFmtpAttribute));
    auto audio_format_params =
        Sdp()->GetMediaSection(0).GetAttributeList().GetFmtp().mFmtps;
    ASSERT_EQ(2U, audio_format_params.size());

    ASSERT_EQ("101", audio_format_params[1].format);
    ASSERT_TRUE(!!audio_format_params[1].parameters);
    const SdpFmtpAttributeList::TelephoneEventParameters* te_parameters =
        static_cast<SdpFmtpAttributeList::TelephoneEventParameters*>(
            audio_format_params[1].parameters.get());
    ASSERT_NE(0U, te_parameters->dtmfTones.size());
    ASSERT_EQ(expectedDtmfTones, te_parameters->dtmfTones);
  }

  void CheckSerialize(const std::string& expected,
                      const SdpAttribute& attr) const {
    std::stringstream str;
    attr.Serialize(str);
    ASSERT_EQ(expected, str.str());
  }

  bool ResultsAreFromSipcc() const {
    return mResults && SipccSdpParser::IsNamed(mResults->ParserName());
  }

  mozilla::UniquePtr<SdpParser::Results> mResults;
};  // class NewSdpTest

TEST_P(NewSdpTest, CreateDestroy) {}

TEST_P(NewSdpTest, ParseEmpty) {
  ParseSdp(""false);
  ASSERT_FALSE(Sdp());
  ASSERT_NE(0U, ParseErrorCount()) << "Expected at least one parse error.";
}

MOZ_RUNINIT const std::string kBadSdp = "This is SDPARTA!!!!";

TEST_P(NewSdpTest, ParseGarbage) {
  ParseSdp(kBadSdp, false);
  ASSERT_FALSE(Sdp());
  ASSERT_NE(0U, ParseErrorCount()) << "Expected at least one parse error.";
}

TEST_P(NewSdpTest, ParseGarbageTwice) {
  ParseSdp(kBadSdp, false);
  ASSERT_FALSE(Sdp());
  size_t errorCount = ParseErrorCount();
  ASSERT_NE(0U, errorCount) << "Expected at least one parse error.";
  ParseSdp(kBadSdp, false);
  ASSERT_FALSE(Sdp());
  ASSERT_EQ(errorCount, ParseErrorCount())
      << "Expected same error count for same SDP.";
}

TEST_P(NewSdpTest, ParseMinimal) {
  ParseSdp(kVideoSdp);
  ASSERT_EQ(0U, ParseErrorCount())
      << "Got parse errors: " << SerializeParseErrors();
}

TEST_P(NewSdpTest, CheckOriginGetUsername) {
  ParseSdp(kVideoSdp);
  ASSERT_EQ("-", Sdp()->GetOrigin().GetUsername())
      << "Wrong username in origin";
}

TEST_P(NewSdpTest, CheckOriginGetSessionId) {
  ParseSdp(kVideoSdp);
  ASSERT_EQ(4294967296U, Sdp()->GetOrigin().GetSessionId())
      << "Wrong session id in origin";
}

TEST_P(NewSdpTest, CheckOriginGetSessionVersion) {
  ParseSdp(kVideoSdp);
  ASSERT_EQ(2U, Sdp()->GetOrigin().GetSessionVersion())
      << "Wrong version in origin";
}

TEST_P(NewSdpTest, CheckOriginGetAddrType) {
  ParseSdp(kVideoSdp);
  ASSERT_EQ(sdp::kIPv4, Sdp()->GetOrigin().GetAddrType())
      << "Wrong address type in origin";
}

TEST_P(NewSdpTest, CheckOriginGetAddress) {
  ParseSdp(kVideoSdp);
  ASSERT_EQ("127.0.0.1", Sdp()->GetOrigin().GetAddress())
      << "Wrong address in origin";
}

TEST_P(NewSdpTest, CheckGetMissingBandwidth) {
  ParseSdp(kVideoSdp);
  ASSERT_EQ(0U, Sdp()->GetBandwidth("CT")) << "Wrong bandwidth in session";
}

TEST_P(NewSdpTest, CheckGetBandwidth) {
  ParseSdp("v=0" CRLF "o=- 4294967296 2 IN IP4 127.0.0.1" CRLF "s=SIP Call" CRLF
           "c=IN IP4 198.51.100.7" CRLF "b=CT:5000" CRLF "b=FOOBAR:10" CRLF
           "b=AS:4" CRLF "t=0 0" CRLF "m=video 56436 RTP/SAVPF 120" CRLF
           "a=rtpmap:120 VP8/90000" CRLF,
           true, ::testing::get<1>(GetParam()));
  ASSERT_EQ(5000U, Sdp()->GetBandwidth("CT"))
      << "Wrong CT bandwidth in session";
  ASSERT_EQ(0U, Sdp()->GetBandwidth("FOOBAR"))
      << "Wrong FOOBAR bandwidth in session";
  ASSERT_EQ(4U, Sdp()->GetBandwidth("AS")) << "Wrong AS bandwidth in session";
}

TEST_P(NewSdpTest, CheckGetMediaSectionsCount) {
  ParseSdp(kVideoSdp);
  ASSERT_EQ(1U, Sdp()->GetMediaSectionCount())
      << "Wrong number of media sections";
}

TEST_P(NewSdpTest, CheckMediaSectionGetMediaType) {
  ParseSdp(kVideoSdp);
  ASSERT_EQ(SdpMediaSection::kVideo, Sdp()->GetMediaSection(0).GetMediaType())
      << "Wrong type for first media section";
}

TEST_P(NewSdpTest, CheckMediaSectionGetProtocol) {
  ParseSdp(kVideoSdp);
  ASSERT_EQ(SdpMediaSection::kRtpSavpf, Sdp()->GetMediaSection(0).GetProtocol())
      << "Wrong protocol for video";
}

TEST_P(NewSdpTest, CheckMediaSectionGetFormats) {
  ParseSdp(kVideoSdp);
  auto video_formats = Sdp()->GetMediaSection(0).GetFormats();
  ASSERT_EQ(1U, video_formats.size()) << "Wrong number of formats for video";
  ASSERT_EQ("120", video_formats[0]);
}

TEST_P(NewSdpTest, CheckMediaSectionGetPort) {
  ParseSdp(kVideoSdp);
  ASSERT_EQ(56436U, Sdp()->GetMediaSection(0).GetPort())
      << "Wrong port number in media section";
}

TEST_P(NewSdpTest, CheckMediaSectionGetMissingPortCount) {
  ParseSdp(kVideoSdp);
  ASSERT_EQ(0U, Sdp()->GetMediaSection(0).GetPortCount())
      << "Wrong port count in media section";
}

TEST_P(NewSdpTest, CheckMediaSectionGetPortCount) {
  ParseSdp(kVideoSdp + "m=audio 12345/2 RTP/SAVPF 0" CRLF
                       "a=rtpmap:0 PCMU/8000" CRLF);
  ASSERT_EQ(2U, Sdp()->GetMediaSectionCount())
      << "Wrong number of media sections";
  ASSERT_EQ(2U, Sdp()->GetMediaSection(1).GetPortCount())
      << "Wrong port count in media section";
}

TEST_P(NewSdpTest, CheckMediaSectionGetMissingBandwidth) {
  ParseSdp(kVideoSdp);
  ASSERT_EQ(0U, Sdp()->GetMediaSection(0).GetBandwidth("CT"))
      << "Wrong bandwidth in media section";
}

TEST_P(NewSdpTest, CheckMediaSectionGetBandwidth) {
  ParseSdp(
      "v=0\r\n"
      "o=- 4294967296 2 IN IP4 127.0.0.1\r\n"
      "s=SIP Call\r\n"
      "c=IN IP4 198.51.100.7\r\n"
      "t=0 0\r\n"
      "m=video 56436 RTP/SAVPF 120\r\n"
      "b=CT:1000\r\n"
      "a=rtpmap:120 VP8/90000\r\n");
  ASSERT_EQ(1000U, Sdp()->GetMediaSection(0).GetBandwidth("CT"))
      << "Wrong bandwidth in media section";
}

// Define a string that is 258 characters long. We use a long string here so
// that we can test that we are able to parse and handle a string longer than
// the default maximum length of 256 in sipcc.
#define ID_A "1234567890abcdef"
#define ID_B ID_A ID_A ID_A ID_A
#define LONG_IDENTITY ID_B ID_B ID_B ID_B "xx"

#define BASE64_DTLS_HELLO                                                     \
  "FgEAAAAAAAAAAAAAagEAAF4AAAAAAAAAXgEARI11KHx3QB6Ky"                         \
  "CKgoBj/kwjKrApkL8kiZLwIqBaJGT8AAAA2ADkAOAA1ABYAEwAKADMAMgAvAAcAZgAFAAQAYw" \
  "BiAGEAFQASAAkAZQBkAGAAFAARAAgABgADAQA="

// SDP from a basic A/V apprtc call FFX/FFX
MOZ_RUNINIT const std::vector<std::string> kBasicAudioVideoOfferLines = {
    "v=0",
    "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0",
    "s=SIP Call",
    "c=IN IP4 224.0.0.1/100/12",
    "t=0 0",
    "a=dtls-message:client " BASE64_DTLS_HELLO,
    "a=ice-ufrag:4a799b2e",
    "a=ice-pwd:e4cc12a910f106a0a744719425510e17",
    "a=ice-lite",
    "a=ice-options:trickle foo",
    "a=msid-semantic:WMS stream streama",
    "a=msid-semantic:foo stream",
    "a=fingerprint:sha-256 "
    "DF:2E:AC:8A:FD:0A:8E:99:BF:5D:E8:3C:E7:FA:FB:08:3B:3C:54:1D:D7:D4:05:77:"
    "A0:72:9B:14:08:6D:0F:4C",
    "a=identity:" LONG_IDENTITY,
    "a=group:BUNDLE first second",
    "a=group:BUNDLE third",
    "a=group:LS first third",
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=97 H=96 G=96

¤ Dauer der Verarbeitung: 0.17 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.