/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2023,  Regents of the University of California,
 *                           Arizona Board of Regents,
 *                           Colorado State University,
 *                           University Pierre & Marie Curie, Sorbonne University,
 *                           Washington University in St. Louis,
 *                           Beijing Institute of Technology,
 *                           The University of Memphis.
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon).
 * See AUTHORS.md for complete list of NFD authors and contributors.
 *
 * NFD 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.
 *
 * NFD 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
 * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "websocket-transport-fixture.hpp"

#include <boost/mpl/vector.hpp>

namespace nfd::tests {

using namespace nfd::face;

BOOST_AUTO_TEST_SUITE(Face)
BOOST_FIXTURE_TEST_SUITE(TestWebSocketTransport, IpTransportFixture<WebSocketTransportFixture>)

using WebSocketTransportFixtures = boost::mpl::vector<
  GENERATE_IP_TRANSPORT_FIXTURE_INSTANTIATIONS(WebSocketTransportFixture)
>;

BOOST_FIXTURE_TEST_CASE_TEMPLATE(StaticProperties, T, WebSocketTransportFixtures, T)
{
  TRANSPORT_TEST_INIT();

  checkStaticPropertiesInitialized(*this->transport);

  BOOST_CHECK_EQUAL(this->transport->getLocalUri(), FaceUri(ip::tcp::endpoint(this->address, 20070), "ws"));
  BOOST_CHECK_EQUAL(this->transport->getRemoteUri(), FaceUri(this->remoteEp, "wsclient"));
  BOOST_CHECK_EQUAL(this->transport->getScope(),
                    this->addressScope == AddressScope::Loopback ? ndn::nfd::FACE_SCOPE_LOCAL
                                                                 : ndn::nfd::FACE_SCOPE_NON_LOCAL);
  BOOST_CHECK_EQUAL(this->transport->getPersistency(), ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
  BOOST_CHECK_EQUAL(this->transport->getLinkType(), ndn::nfd::LINK_TYPE_POINT_TO_POINT);
  BOOST_CHECK_EQUAL(this->transport->getMtu(), MTU_UNLIMITED);
  BOOST_CHECK_EQUAL(this->transport->getSendQueueCapacity(), QUEUE_UNSUPPORTED);
}

using StaticPropertiesV4MappedFixtures = boost::mpl::vector<
  IpTransportFixture<WebSocketTransportFixture, AddressFamily::V4, AddressScope::Loopback>,
  IpTransportFixture<WebSocketTransportFixture, AddressFamily::V4, AddressScope::Global>
>;

BOOST_FIXTURE_TEST_CASE_TEMPLATE(StaticPropertiesV4Mapped, T, StaticPropertiesV4MappedFixtures, T)
{
  TRANSPORT_TEST_CHECK_PRECONDITIONS();
  auto mappedAddr = ip::make_address_v6(ip::v4_mapped, this->address.to_v4());
  BOOST_REQUIRE(mappedAddr.is_v4_mapped());
  WebSocketTransportFixture::initialize(this->interface, mappedAddr);

  checkStaticPropertiesInitialized(*this->transport);

  BOOST_CHECK_EQUAL(this->transport->getLocalUri(), FaceUri(ip::tcp::endpoint(mappedAddr, 20070), "ws"));
  BOOST_CHECK_EQUAL(this->transport->getRemoteUri(), FaceUri(this->remoteEp, "wsclient"));
  BOOST_CHECK_EQUAL(this->transport->getScope(),
                    this->addressScope == AddressScope::Loopback ? ndn::nfd::FACE_SCOPE_LOCAL
                                                                 : ndn::nfd::FACE_SCOPE_NON_LOCAL);
  BOOST_CHECK_EQUAL(this->transport->getPersistency(), ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
  BOOST_CHECK_EQUAL(this->transport->getLinkType(), ndn::nfd::LINK_TYPE_POINT_TO_POINT);
  BOOST_CHECK_EQUAL(this->transport->getMtu(), MTU_UNLIMITED);
}

BOOST_AUTO_TEST_CASE(PersistencyChange)
{
  TRANSPORT_TEST_INIT();

  BOOST_CHECK_EQUAL(transport->canChangePersistencyTo(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND), true);
  BOOST_CHECK_EQUAL(transport->canChangePersistencyTo(ndn::nfd::FACE_PERSISTENCY_PERSISTENT), false);
  BOOST_CHECK_EQUAL(transport->canChangePersistencyTo(ndn::nfd::FACE_PERSISTENCY_PERMANENT), false);
}

BOOST_FIXTURE_TEST_CASE_TEMPLATE(PingPong, T, WebSocketTransportFixtures, T)
{
  TRANSPORT_TEST_INIT(500_ms, 300_ms);

  BOOST_CHECK_EQUAL(this->limitedIo.run(2, // clientHandlePing, serverHandlePong
                                        1500_ms), LimitedIo::EXCEED_OPS);

  BOOST_CHECK_EQUAL(this->transport->getState(), TransportState::UP);
  BOOST_CHECK_EQUAL(this->transport->getCounters().nOutPings, 1);
  BOOST_CHECK_EQUAL(this->transport->getCounters().nInPongs, 1);

  this->clientShouldPong = false;
  BOOST_CHECK_EQUAL(this->limitedIo.run(2, // clientHandlePing, serverHandlePongTimeout
                                        2_s), LimitedIo::EXCEED_OPS);

  BOOST_CHECK_MESSAGE(this->transport->getState() == TransportState::FAILED ||
                      this->transport->getState() == TransportState::CLOSED,
                      "expected FAILED or CLOSED state, actual state=" << this->transport->getState());
  BOOST_CHECK_EQUAL(this->transport->getCounters().nOutPings, 2);
  BOOST_CHECK_EQUAL(this->transport->getCounters().nInPongs, 1);
}

BOOST_FIXTURE_TEST_CASE_TEMPLATE(Send, T, WebSocketTransportFixtures, T)
{
  TRANSPORT_TEST_INIT();

  auto block1 = ndn::encoding::makeStringBlock(300, "hello");
  this->transport->send(block1);
  BOOST_CHECK_EQUAL(this->limitedIo.run(1, // clientHandleMessage
                                        1_s), LimitedIo::EXCEED_OPS);
  BOOST_CHECK_EQUAL(this->transport->getCounters().nOutPackets, 1);
  BOOST_CHECK_EQUAL(this->transport->getCounters().nOutBytes, block1.size());

  auto block2 = ndn::encoding::makeStringBlock(301, "world");
  this->transport->send(block2);
  BOOST_CHECK_EQUAL(this->limitedIo.run(1, // clientHandleMessage
                                        1_s), LimitedIo::EXCEED_OPS);
  BOOST_CHECK_EQUAL(this->transport->getCounters().nOutPackets, 2);
  BOOST_CHECK_EQUAL(this->transport->getCounters().nOutBytes, block1.size() + block2.size());

  BOOST_REQUIRE_EQUAL(this->clientReceivedMessages.size(), 2);
  BOOST_CHECK_EQUAL_COLLECTIONS(
    reinterpret_cast<const uint8_t*>(this->clientReceivedMessages[0].data()),
    reinterpret_cast<const uint8_t*>(this->clientReceivedMessages[0].data()) + this->clientReceivedMessages[0].size(),
    block1.begin(), block1.end());
  BOOST_CHECK_EQUAL_COLLECTIONS(
    reinterpret_cast<const uint8_t*>(this->clientReceivedMessages[1].data()),
    reinterpret_cast<const uint8_t*>(this->clientReceivedMessages[1].data()) + this->clientReceivedMessages[1].size(),
    block2.begin(), block2.end());
  BOOST_CHECK_EQUAL(this->transport->getState(), TransportState::UP);
}

BOOST_FIXTURE_TEST_CASE_TEMPLATE(ReceiveNormal, T, WebSocketTransportFixtures, T)
{
  TRANSPORT_TEST_INIT();

  auto pkt1 = ndn::encoding::makeStringBlock(300, "hello");
  this->client.send(this->clientHdl, pkt1.data(), pkt1.size(), websocketpp::frame::opcode::binary);
  BOOST_CHECK_EQUAL(this->limitedIo.run(1, // serverHandleMessage
                                        1_s), LimitedIo::EXCEED_OPS);

  BOOST_CHECK_EQUAL(this->transport->getCounters().nInPackets, 1);
  BOOST_CHECK_EQUAL(this->transport->getCounters().nInBytes, pkt1.size());

  auto pkt2 = ndn::encoding::makeStringBlock(301, "world!");
  this->client.send(this->clientHdl, pkt2.data(), pkt2.size(), websocketpp::frame::opcode::binary);
  BOOST_CHECK_EQUAL(this->limitedIo.run(1, // serverHandleMessage
                                        1_s), LimitedIo::EXCEED_OPS);

  BOOST_CHECK_EQUAL(this->transport->getCounters().nInPackets, 2);
  BOOST_CHECK_EQUAL(this->transport->getCounters().nInBytes, pkt1.size() + pkt2.size());
  BOOST_CHECK_EQUAL(this->transport->getState(), TransportState::UP);

  BOOST_REQUIRE_EQUAL(this->serverReceivedPackets->size(), 2);
  BOOST_CHECK(this->serverReceivedPackets->at(0).packet == pkt1);
  BOOST_CHECK(this->serverReceivedPackets->at(1).packet == pkt2);
  BOOST_CHECK(this->serverReceivedPackets->at(0).endpoint == EndpointId{});
  BOOST_CHECK(this->serverReceivedPackets->at(1).endpoint == EndpointId{});
}

BOOST_FIXTURE_TEST_CASE_TEMPLATE(ReceiveMalformed, T, WebSocketTransportFixtures, T)
{
  TRANSPORT_TEST_INIT();

  auto pkt1 = ndn::encoding::makeStringBlock(300, "hello");
  this->client.send(this->clientHdl, pkt1.data(), pkt1.size() - 1, // truncated
                    websocketpp::frame::opcode::binary);
  BOOST_CHECK_EQUAL(this->limitedIo.run(1, // serverHandleMessage
                                        1_s), LimitedIo::EXCEED_OPS);

  // bad packet is dropped
  BOOST_CHECK_EQUAL(this->transport->getState(), TransportState::UP);
  BOOST_CHECK_EQUAL(this->serverReceivedPackets->size(), 0);

  auto pkt2 = ndn::encoding::makeStringBlock(301, "world!");
  this->client.send(this->clientHdl, pkt2.data(), pkt2.size(), websocketpp::frame::opcode::binary);
  BOOST_CHECK_EQUAL(this->limitedIo.run(1, // serverHandleMessage
                                        1_s), LimitedIo::EXCEED_OPS);

  // next valid packet is still received normally
  BOOST_CHECK_EQUAL(this->transport->getState(), TransportState::UP);
  BOOST_REQUIRE_EQUAL(this->serverReceivedPackets->size(), 1);
  BOOST_CHECK(this->serverReceivedPackets->at(0).packet == pkt2);
}

BOOST_FIXTURE_TEST_CASE_TEMPLATE(Close, T, WebSocketTransportFixtures, T)
{
  TRANSPORT_TEST_INIT();

  int nStateChanges = 0;
  this->transport->afterStateChange.connect(
    [&nStateChanges] (auto oldState, auto newState) {
      switch (nStateChanges) {
      case 0:
        BOOST_CHECK_EQUAL(oldState, TransportState::UP);
        BOOST_CHECK_EQUAL(newState, TransportState::CLOSING);
        break;
      case 1:
        BOOST_CHECK_EQUAL(oldState, TransportState::CLOSING);
        BOOST_CHECK_EQUAL(newState, TransportState::CLOSED);
        break;
      default:
        BOOST_CHECK(false);
      }
      nStateChanges++;
    });

  this->transport->close();
  BOOST_CHECK_EQUAL(nStateChanges, 2);
}

BOOST_FIXTURE_TEST_CASE_TEMPLATE(RemoteClose, T, WebSocketTransportFixtures, T)
{
  TRANSPORT_TEST_INIT();

  int nStateChanges = 0;
  this->transport->afterStateChange.connect(
    [&nStateChanges] (auto oldState, auto newState) {
      switch (nStateChanges) {
      case 0:
        BOOST_CHECK_EQUAL(oldState, TransportState::UP);
        BOOST_CHECK_EQUAL(newState, TransportState::CLOSING);
        break;
      case 1:
        BOOST_CHECK_EQUAL(oldState, TransportState::CLOSING);
        BOOST_CHECK_EQUAL(newState, TransportState::CLOSED);
        break;
      default:
        BOOST_CHECK(false);
      }
      nStateChanges++;
    });

  this->client.close(this->clientHdl, websocketpp::close::status::going_away, "");
  BOOST_CHECK_EQUAL(this->limitedIo.run(1, // serverHandleClose
                                        1_s), LimitedIo::EXCEED_OPS);

  BOOST_CHECK_EQUAL(nStateChanges, 2);
}

BOOST_FIXTURE_TEST_CASE_TEMPLATE(SendQueueLength, T, WebSocketTransportFixtures, T)
{
  TRANSPORT_TEST_INIT();

  BOOST_CHECK_EQUAL(this->transport->getSendQueueLength(), QUEUE_UNSUPPORTED);
}

BOOST_AUTO_TEST_SUITE_END() // TestWebSocketTransport
BOOST_AUTO_TEST_SUITE_END() // Face

} // namespace nfd::tests
