/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (C) 2013 Regents of the University of California.
 * See COPYING for copyright and distribution information.
 */

#include "management/nfd-control-response.hpp"
#include "management/nfd-fib-management-options.hpp"

#include <boost/test/unit_test.hpp>
#include <boost/test/output_test_stream.hpp>

using namespace std;

namespace ndn {
namespace nfd {

BOOST_AUTO_TEST_SUITE(TestNfdControl)

const uint8_t TestControlResponse[] = {0x65, 0x17, 0x66, 0x02, 0x01, 0x94, 0x67, 0x11, 0x4e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64};

const uint8_t TestFibManagementOptions[] = {
  0x68, 0x1e, 0x03, 0x16, 0x04, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68,
  0x6f, 0x73, 0x74, 0x04, 0x03, 0x72, 0x65, 0x67, 0x04, 0x04, 0x74, 0x65,
  0x73, 0x74, 0x69, 0x01, 0x00, 0x6a, 0x01, 0x00
};

// ControlResponse

BOOST_AUTO_TEST_CASE (ControlResponseEncode)
{
  ControlResponse controlResponse(404, "Nothing not found");
  const Block &wire = controlResponse.wireEncode();

  BOOST_REQUIRE_EQUAL_COLLECTIONS(TestControlResponse, TestControlResponse+sizeof(TestControlResponse),
                                  wire.begin(), wire.end());
}

BOOST_AUTO_TEST_CASE (ControlResponseDecode)
{
  ControlResponse controlResponse;
  
  BOOST_REQUIRE_NO_THROW(controlResponse.wireDecode(Block(TestControlResponse, sizeof(TestControlResponse))));

  BOOST_REQUIRE_EQUAL(controlResponse.getCode(), 404);
  BOOST_REQUIRE_EQUAL(controlResponse.getText(), "Nothing not found");
}

// FibManagementOptions

BOOST_AUTO_TEST_CASE (FibManagementOptionsEncoding)
{
  Name n ("/localhost/reg/test");
  FibManagementOptions opt;

  opt.setName (n);
  opt.setFaceId (0);
  opt.setCost (0);

  const Block& blk = opt.wireEncode ();

  BOOST_REQUIRE_EQUAL_COLLECTIONS (TestFibManagementOptions,
                                   TestFibManagementOptions + sizeof (TestFibManagementOptions),
                                   blk.begin (), blk.end ());
}

BOOST_AUTO_TEST_CASE (FibManagementOptionsFastEncoding)
{
  Name n ("/localhost/reg/test");
  FibManagementOptions opt;

  opt.setName (n);
  opt.setFaceId (0);
  opt.setCost (0);

  EncodingBuffer blk;

  BOOST_REQUIRE_NO_THROW (opt.wireEncode (blk));

  BOOST_REQUIRE_EQUAL_COLLECTIONS (TestFibManagementOptions,
                                   TestFibManagementOptions + sizeof (TestFibManagementOptions),
                                   blk.begin (), blk.end ());

  EncodingBuffer blk2 (4);

  BOOST_REQUIRE_NO_THROW (opt.wireEncode (blk2));

  BOOST_REQUIRE_EQUAL_COLLECTIONS (TestFibManagementOptions,
                                   TestFibManagementOptions + sizeof (TestFibManagementOptions),
                                   blk2.begin (), blk2.end ());
}

BOOST_AUTO_TEST_CASE (FibManagementOptionsDecoding)
{
  Block blk (TestFibManagementOptions, sizeof (TestFibManagementOptions));
  Name n ("/localhost/reg/test");
  FibManagementOptions opt;

  BOOST_REQUIRE_NO_THROW (opt.wireDecode (blk));
  
  BOOST_CHECK_EQUAL (opt.getName (), n);
  BOOST_CHECK_EQUAL (opt.getFaceId (), 0);
  BOOST_CHECK_EQUAL (opt.getCost (), 0);
}


BOOST_AUTO_TEST_SUITE_END()

} // namespace nfd
} // namespace ndn
