/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (C) 2014 Named Data Networking Project
 * See COPYING for copyright and distribution information.
 */

#include "face/ndnlp-sequence-generator.hpp"
#include "face/ndnlp-slicer.hpp"
#include "face/ndnlp-partial-message-store.hpp"

#include <boost/test/unit_test.hpp>

namespace nfd {

BOOST_AUTO_TEST_SUITE(FaceNdnlp)

BOOST_AUTO_TEST_CASE(SequenceBlock)
{
  ndnlp::SequenceBlock sb(0x8000, 2);
  BOOST_CHECK_EQUAL(sb.count(), 2);
  BOOST_CHECK_EQUAL(sb[0], 0x8000);
  BOOST_CHECK_EQUAL(sb[1], 0x8001);
  BOOST_CHECK_THROW(sb[2], std::out_of_range);
}

// sequence number can safely wrap around
BOOST_AUTO_TEST_CASE(SequenceBlockWrap)
{
  ndnlp::SequenceBlock sb(std::numeric_limits<uint64_t>::max(), 2);
  BOOST_CHECK_EQUAL(sb[0], std::numeric_limits<uint64_t>::max());
  BOOST_CHECK_EQUAL(sb[1], std::numeric_limits<uint64_t>::min());
  BOOST_CHECK_EQUAL(sb[1] - sb[0], 1);
}

BOOST_AUTO_TEST_CASE(SequenceGenerator)
{
  ndnlp::SequenceGenerator seqgen;

  ndnlp::SequenceBlock sb1 = seqgen.nextBlock(2);
  BOOST_CHECK_EQUAL(sb1.count(), 2);

  ndnlp::SequenceBlock sb2 = seqgen.nextBlock(1);
  BOOST_CHECK_NE(sb1[0], sb2[0]);
  BOOST_CHECK_NE(sb1[1], sb2[0]);
}

// slice a Block to one NDNLP packet
BOOST_AUTO_TEST_CASE(Slice1)
{
  uint8_t blockValue[60];
  memset(blockValue, 0xcc, sizeof(blockValue));
  Block block = ndn::dataBlock(0x01, blockValue, sizeof(blockValue));

  ndnlp::Slicer slicer(9000);
  ndnlp::PacketArray pa = slicer.slice(block);

  BOOST_REQUIRE_EQUAL(pa->size(), 1);

  const Block& pkt = pa->at(0);
  BOOST_CHECK_EQUAL(pkt.type(), static_cast<uint32_t>(tlv::NdnlpData));
  pkt.parse();

  const Block::element_container& elements = pkt.elements();
  BOOST_REQUIRE_EQUAL(elements.size(), 2);

  const Block& sequenceElement = elements[0];
  BOOST_CHECK_EQUAL(sequenceElement.type(), static_cast<uint32_t>(tlv::NdnlpSequence));
  BOOST_REQUIRE_EQUAL(sequenceElement.value_size(), sizeof(uint64_t));

  const Block& payloadElement = elements[1];
  BOOST_CHECK_EQUAL(payloadElement.type(), static_cast<uint32_t>(tlv::NdnlpPayload));
  size_t payloadSize = payloadElement.value_size();
  BOOST_CHECK_EQUAL(payloadSize, block.size());

  BOOST_CHECK_EQUAL_COLLECTIONS(payloadElement.value_begin(), payloadElement.value_end(),
                                block.begin(),                block.end());
}

// slice a Block to four NDNLP packets
BOOST_AUTO_TEST_CASE(Slice4)
{
  uint8_t blockValue[5050];
  memset(blockValue, 0xcc, sizeof(blockValue));
  Block block = ndn::dataBlock(0x01, blockValue, sizeof(blockValue));

  ndnlp::Slicer slicer(1500);
  ndnlp::PacketArray pa = slicer.slice(block);

  BOOST_REQUIRE_EQUAL(pa->size(), 4);

  uint64_t seq0 = 0xdddd;

  size_t totalPayloadSize = 0;

  for (size_t i = 0; i < 4; ++i) {
    const Block& pkt = pa->at(i);
    BOOST_CHECK_EQUAL(pkt.type(), static_cast<uint32_t>(tlv::NdnlpData));
    pkt.parse();

    const Block::element_container& elements = pkt.elements();
    BOOST_REQUIRE_EQUAL(elements.size(), 4);

    const Block& sequenceElement = elements[0];
    BOOST_CHECK_EQUAL(sequenceElement.type(), static_cast<uint32_t>(tlv::NdnlpSequence));
    BOOST_REQUIRE_EQUAL(sequenceElement.value_size(), sizeof(uint64_t));
    uint64_t seq = be64toh(*reinterpret_cast<const uint64_t*>(
                             &*sequenceElement.value_begin()));
    if (i == 0) {
      seq0 = seq;
    }
    BOOST_CHECK_EQUAL(seq, seq0 + i);

    const Block& fragIndexElement = elements[1];
    BOOST_CHECK_EQUAL(fragIndexElement.type(), static_cast<uint32_t>(tlv::NdnlpFragIndex));
    uint64_t fragIndex = ndn::readNonNegativeInteger(fragIndexElement);
    BOOST_CHECK_EQUAL(fragIndex, i);

    const Block& fragCountElement = elements[2];
    BOOST_CHECK_EQUAL(fragCountElement.type(), static_cast<uint32_t>(tlv::NdnlpFragCount));
    uint64_t fragCount = ndn::readNonNegativeInteger(fragCountElement);
    BOOST_CHECK_EQUAL(fragCount, 4);

    const Block& payloadElement = elements[3];
    BOOST_CHECK_EQUAL(payloadElement.type(), static_cast<uint32_t>(tlv::NdnlpPayload));
    size_t payloadSize = payloadElement.value_size();
    totalPayloadSize += payloadSize;
  }

  BOOST_CHECK_EQUAL(totalPayloadSize, block.size());
}

class ReassembleFixture
{
protected:
  ReassembleFixture()
    : m_scheduler(m_io)
    , m_slicer(1500)
    , m_partialMessageStore(m_scheduler)
  {
    m_partialMessageStore.onReceive += bind(&std::vector<Block>::push_back,
                                            &m_received, _1);
  }

  Block
  makeBlock(size_t valueLength)
  {
    uint8_t blockValue[valueLength];
    memset(blockValue, 0xcc, sizeof(blockValue));
    return ndn::dataBlock(0x01, blockValue, sizeof(blockValue));
  }

protected:
  boost::asio::io_service m_io;
  Scheduler m_scheduler;

  ndnlp::Slicer m_slicer;
  ndnlp::PartialMessageStore m_partialMessageStore;

  // received network layer packets
  std::vector<Block> m_received;
};

// reassemble one NDNLP packets into one Block
BOOST_FIXTURE_TEST_CASE(Reassemble1, ReassembleFixture)
{
  Block block = makeBlock(60);
  ndnlp::PacketArray pa = m_slicer.slice(block);
  BOOST_REQUIRE_EQUAL(pa->size(), 1);

  BOOST_CHECK_EQUAL(m_received.size(), 0);
  m_partialMessageStore.receiveNdnlpData(pa->at(0));

  BOOST_REQUIRE_EQUAL(m_received.size(), 1);
  BOOST_CHECK_EQUAL_COLLECTIONS(m_received.at(0).begin(), m_received.at(0).end(),
                                block.begin(),            block.end());
}

// reassemble four and two NDNLP packets into two Blocks
BOOST_FIXTURE_TEST_CASE(Reassemble4and2, ReassembleFixture)
{
  Block block = makeBlock(5050);
  ndnlp::PacketArray pa = m_slicer.slice(block);
  BOOST_REQUIRE_EQUAL(pa->size(), 4);

  Block block2 = makeBlock(2000);
  ndnlp::PacketArray pa2 = m_slicer.slice(block2);
  BOOST_REQUIRE_EQUAL(pa2->size(), 2);

  BOOST_CHECK_EQUAL(m_received.size(), 0);
  m_partialMessageStore.receiveNdnlpData(pa->at(0));
  BOOST_CHECK_EQUAL(m_received.size(), 0);
  m_partialMessageStore.receiveNdnlpData(pa->at(1));
  BOOST_CHECK_EQUAL(m_received.size(), 0);
  m_partialMessageStore.receiveNdnlpData(pa2->at(1));
  BOOST_CHECK_EQUAL(m_received.size(), 0);
  m_partialMessageStore.receiveNdnlpData(pa->at(1));
  BOOST_CHECK_EQUAL(m_received.size(), 0);
  m_partialMessageStore.receiveNdnlpData(pa2->at(0));
  BOOST_CHECK_EQUAL(m_received.size(), 1);
  m_partialMessageStore.receiveNdnlpData(pa->at(3));
  BOOST_CHECK_EQUAL(m_received.size(), 1);
  m_partialMessageStore.receiveNdnlpData(pa->at(2));

  BOOST_REQUIRE_EQUAL(m_received.size(), 2);
  BOOST_CHECK_EQUAL_COLLECTIONS(m_received.at(1).begin(), m_received.at(1).end(),
                                block.begin(),            block.end());
  BOOST_CHECK_EQUAL_COLLECTIONS(m_received.at(0).begin(), m_received.at(0).end(),
                                block2.begin(),           block2.end());
}

BOOST_AUTO_TEST_SUITE_END()

} // namespace nfd
