/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2016,  University of Memphis.
 *
 * This file is part of ndn-tools (Named Data Networking Essential Tools).
 * See AUTHORS.md for complete list of ndn-tools authors and contributors.
 *
 * ndn-tools is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * ndn-tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * ndn-tools, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "tools/dump/ndndump.hpp"

#include "tests/test-common.hpp"

#include <boost/test/output_test_stream.hpp>

#include <ndn-cxx/lp/packet.hpp>
#include <ndn-cxx/security/key-chain.hpp>
#include <ndn-cxx/util/ethernet.hpp>

namespace ndn {
namespace dump {
namespace tests {

using namespace ndn::tests;

class StdCoutRedirector
{
public:
  StdCoutRedirector(std::ostream& os)
  {
    // Redirect std::cout to the specified output stream
    originalBuffer = std::cout.rdbuf(os.rdbuf());
  }

  ~StdCoutRedirector()
  {
    // Revert state for std::cout
    std::cout.rdbuf(originalBuffer);
  }

private:
  std::streambuf* originalBuffer;
};

class NdnDumpFixture
{
protected:
  NdnDumpFixture()
  {
    dump.m_dataLinkType = DLT_EN10MB;
  }

  template <typename Packet>
  void
  receive(const Packet& packet)
  {
    ndn::EncodingBuffer buffer(packet.wireEncode());
    receive(buffer);
  }

  void
  receive(ndn::EncodingBuffer& buffer)
  {
    ndn::util::ethernet::Address host;

    // Ethernet header
    uint16_t frameType = htons(ndn::util::ethernet::ETHERTYPE_NDN);
    buffer.prependByteArray(reinterpret_cast<const uint8_t*>(&frameType),
                            ndn::util::ethernet::TYPE_LEN);
    buffer.prependByteArray(host.data(), host.size());
    buffer.prependByteArray(host.data(), host.size());

    pcap_pkthdr header{};
    header.len = buffer.size();

    {
      StdCoutRedirector redirect(output);
      dump.onCapturedPacket(&header, buffer.buf());
    }
  }

protected:
  Ndndump dump;
  boost::test_tools::output_test_stream output;
};

BOOST_FIXTURE_TEST_SUITE(NdnDump, NdnDumpFixture)

BOOST_AUTO_TEST_CASE(CaptureInterest)
{
  ndn::Interest interest("/test");
  interest.setNonce(0);

  this->receive(interest);

  const std::string expectedOutput =
    "0.000000 Tunnel Type: EthernetFrame, INTEREST: /test?ndn.Nonce=0\n";

  BOOST_CHECK(output.is_equal(expectedOutput));
}

BOOST_AUTO_TEST_CASE(CaptureData)
{
  ndn::security::KeyChain keyChain;

  ndn::Data data("/test");
  keyChain.sign(data);

  this->receive(data);

  const std::string expectedOutput = "0.000000 Tunnel Type: EthernetFrame, DATA: /test\n";

  BOOST_CHECK(output.is_equal(expectedOutput));
}

BOOST_AUTO_TEST_CASE(CaptureNack)
{
  ndn::Interest interest("/test");
  interest.setNonce(0);

  ndn::lp::Nack nack(interest);
  nack.setReason(ndn::lp::NackReason::DUPLICATE);

  lp::Packet lpPacket(interest.wireEncode());
  lpPacket.add<lp::NackField>(nack.getHeader());

  this->receive(lpPacket);

  const std::string expectedOutput =
    "0.000000 Tunnel Type: EthernetFrame, NACK: Duplicate, /test?ndn.Nonce=0\n";

  BOOST_CHECK(output.is_equal(expectedOutput));
}

BOOST_AUTO_TEST_CASE(CaptureLpFragment)
{
  const uint8_t data[10] = {
    0x06, 0x08, // Data packet
        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
  };

  ndn::Buffer buffer(data, 4);

  lp::Packet lpPacket;
  lpPacket.add<lp::FragmentField>(std::make_pair(buffer.begin(), buffer.end()));
  lpPacket.add<lp::FragIndexField>(0);
  lpPacket.add<lp::FragCountField>(2);
  lpPacket.add<lp::SequenceField>(1000);

  this->receive(lpPacket);

  const std::string expectedOutput =
    "0.000000 Tunnel Type: EthernetFrame, NDNLPv2-FRAGMENT\n";

  BOOST_CHECK(output.is_equal(expectedOutput));
}

BOOST_AUTO_TEST_CASE(CaptureIdlePacket)
{
  lp::Packet lpPacket;

  this->receive(lpPacket);

  const std::string expectedOutput =
    "0.000000 Tunnel Type: EthernetFrame, NDNLPv2-IDLE\n";

  BOOST_CHECK(output.is_equal(expectedOutput));
}

BOOST_AUTO_TEST_CASE(CaptureIncompletePacket)
{
  const uint8_t interest[] = {
  0x05, 0x0E, // Interest
    0x07, 0x06, // Name
      0x08, 0x04, // NameComponent
        0x74, 0x65, 0x73, 0x74,
    0x0a, 0x04, // Nonce
      0x00, 0x00, 0x00, 0x01
  };

  EncodingBuffer buffer;
  buffer.prependByteArray(interest, 4);

  this->receive(buffer);

  const std::string expectedOutput =
    "0.000000 Tunnel Type: EthernetFrame, INCOMPLETE-PACKET, size: 4\n";

  BOOST_CHECK(output.is_equal(expectedOutput));
}

BOOST_AUTO_TEST_CASE(CaptureUnknownNetworkPacket)
{
  EncodingBuffer buffer(ndn::encoding::makeEmptyBlock(tlv::Name));

  this->receive(buffer);

  const std::string expectedOutput =
    "0.000000 Tunnel Type: EthernetFrame, UNKNOWN-NETWORK-PACKET\n";

  BOOST_CHECK(output.is_equal(expectedOutput));
}

BOOST_AUTO_TEST_CASE(DumpPcapTrace)
{
  dump.inputFile = "tests/dump/nack.pcap";
  dump.pcapProgram = "";

  {
    StdCoutRedirector redirect(output);
    dump.run();
  }

  const std::string expectedOutput =
    "1456768916.467099 From: 1.0.0.1, To: 1.0.0.2, Tunnel Type: UDP, INTEREST: /producer/nack/congestion?ndn.MustBeFresh=1&ndn.Nonce=2581361680\n"
    "1456768916.567099 From: 1.0.0.1, To: 1.0.0.2, Tunnel Type: UDP, INTEREST: /producer/nack/duplicate?ndn.MustBeFresh=1&ndn.Nonce=4138343109\n"
    "1456768916.667099 From: 1.0.0.1, To: 1.0.0.2, Tunnel Type: UDP, INTEREST: /producer/nack/no-reason?ndn.MustBeFresh=1&ndn.Nonce=4034910304\n"
    "1456768916.767099 From: 1.0.0.2, To: 1.0.0.1, Tunnel Type: UDP, NACK: Congestion, /producer/nack/congestion?ndn.MustBeFresh=1&ndn.Nonce=2581361680\n"
    "1456768916.867099 From: 1.0.0.2, To: 1.0.0.1, Tunnel Type: UDP, NACK: Duplicate, /producer/nack/duplicate?ndn.MustBeFresh=1&ndn.Nonce=4138343109\n"
    "1456768916.967099 From: 1.0.0.2, To: 1.0.0.1, Tunnel Type: UDP, NACK: None, /producer/nack/no-reason?ndn.MustBeFresh=1&ndn.Nonce=4034910304\n"
    "1456768917.067099 From: 1.0.0.1, To: 1.0.0.2, Tunnel Type: TCP, INTEREST: /producer/nack/congestion?ndn.MustBeFresh=1&ndn.Nonce=3192497423\n"
    "1456768917.267099 From: 1.0.0.2, To: 1.0.0.1, Tunnel Type: TCP, NACK: Congestion, /producer/nack/congestion?ndn.MustBeFresh=1&ndn.Nonce=3192497423\n"
    "1456768917.367099 From: 1.0.0.1, To: 1.0.0.2, Tunnel Type: TCP, INTEREST: /producer/nack/duplicate?ndn.MustBeFresh=1&ndn.Nonce=522390724\n"
    "1456768917.567099 From: 1.0.0.2, To: 1.0.0.1, Tunnel Type: TCP, NACK: Duplicate, /producer/nack/duplicate?ndn.MustBeFresh=1&ndn.Nonce=522390724\n"
    "1456768917.767099 From: 1.0.0.2, To: 1.0.0.1, Tunnel Type: TCP, NACK: None, /producer/nack/no-reason?ndn.MustBeFresh=1&ndn.Nonce=2002441365\n"
    "1456768917.967099 From: 1.0.0.1, To: 1.0.0.2, Tunnel Type: TCP, INTEREST: /producer/nack/no-reason?ndn.MustBeFresh=1&ndn.Nonce=3776824408\n"
    "1456768918.067099 From: 1.0.0.2, To: 1.0.0.1, Tunnel Type: TCP, NACK: None, /producer/nack/no-reason?ndn.MustBeFresh=1&ndn.Nonce=3776824408\n";

  BOOST_CHECK(output.is_equal(expectedOutput));
}


BOOST_AUTO_TEST_SUITE_END()

} // namespace tests
} // namespace dump
} // namespace ndn
