/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <map>

#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/test/rtp_file_reader.h"
#include "webrtc/test/testsupport/fileutils.h"

namespace webrtc {

class TestRtpFileReader : public ::testing::Test {
 public:
  void Init(const std::string& filename) {
    std::string filepath =
        test::ResourcePath("video_coding/" + filename, "rtp");
    rtp_packet_source_.reset(
        test::RtpFileReader::Create(test::RtpFileReader::kRtpDump, filepath));
    ASSERT_TRUE(rtp_packet_source_.get() != NULL);
  }

  int CountRtpPackets() {
    test::RtpFileReader::Packet packet;
    int c = 0;
    while (rtp_packet_source_->NextPacket(&packet))
      c++;
    return c;
  }

 private:
  scoped_ptr<test::RtpFileReader> rtp_packet_source_;
};

TEST_F(TestRtpFileReader, Test60Packets) {
  Init("pltype103");
  EXPECT_EQ(60, CountRtpPackets());
}

typedef std::map<uint32_t, int> PacketsPerSsrc;

class TestPcapFileReader : public ::testing::Test {
 public:
  void Init(const std::string& filename) {
    std::string filepath =
        test::ResourcePath("video_coding/" + filename, "pcap");
    rtp_packet_source_.reset(
        test::RtpFileReader::Create(test::RtpFileReader::kPcap, filepath));
    ASSERT_TRUE(rtp_packet_source_.get() != NULL);
  }

  int CountRtpPackets() {
    int c = 0;
    test::RtpFileReader::Packet packet;
    while (rtp_packet_source_->NextPacket(&packet))
      c++;
    return c;
  }

  PacketsPerSsrc CountRtpPacketsPerSsrc() {
    PacketsPerSsrc pps;
    test::RtpFileReader::Packet packet;
    while (rtp_packet_source_->NextPacket(&packet)) {
      RtpUtility::RtpHeaderParser rtp_header_parser(packet.data, packet.length);
      webrtc::RTPHeader header;
      if (!rtp_header_parser.RTCP() && rtp_header_parser.Parse(header, NULL)) {
        pps[header.ssrc]++;
      }
    }
    return pps;
  }

 private:
  scoped_ptr<test::RtpFileReader> rtp_packet_source_;
};

TEST_F(TestPcapFileReader, TestEthernetIIFrame) {
  Init("frame-ethernet-ii");
  EXPECT_EQ(368, CountRtpPackets());
}

TEST_F(TestPcapFileReader, TestLoopbackFrame) {
  Init("frame-loopback");
  EXPECT_EQ(491, CountRtpPackets());
}

TEST_F(TestPcapFileReader, TestTwoSsrc) {
  Init("ssrcs-2");
  PacketsPerSsrc pps = CountRtpPacketsPerSsrc();
  EXPECT_EQ(2UL, pps.size());
  EXPECT_EQ(370, pps[0x78d48f61]);
  EXPECT_EQ(60, pps[0xae94130b]);
}

TEST_F(TestPcapFileReader, TestThreeSsrc) {
  Init("ssrcs-3");
  PacketsPerSsrc pps = CountRtpPacketsPerSsrc();
  EXPECT_EQ(3UL, pps.size());
  EXPECT_EQ(162, pps[0x938c5eaa]);
  EXPECT_EQ(113, pps[0x59fe6ef0]);
  EXPECT_EQ(61, pps[0xed2bd2ac]);
}
}  // namespace webrtc
