/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2016-2020, Regents of the University of California,
 *                          Colorado State University,
 *                          University Pierre & Marie Curie, Sorbonne University.
 *
 * 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/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 *
 * @author Chavoosh Ghasemi
 */

#include "tools/chunks/catchunks/discover-version.hpp"

#include "tests/test-common.hpp"
#include "tests/io-fixture.hpp"
#include "tests/key-chain-fixture.hpp"

#include <ndn-cxx/metadata-object.hpp>
#include <ndn-cxx/util/dummy-client-face.hpp>

namespace ndn {
namespace chunks {
namespace tests {

using namespace ndn::tests;

class DiscoverVersionFixture : public IoFixture, public KeyChainFixture
{
public:
  void
  run(const Name& prefix)
  {
    discover = make_unique<DiscoverVersion>(face, prefix, opt);
    discover->onDiscoverySuccess.connect([this] (const Name& versionedName) {
      isDiscoveryFinished = true;
      discoveredName = versionedName;
      if (!versionedName.empty() && versionedName[-1].isVersion())
        discoveredVersion = versionedName[-1].toVersion();
    });
    discover->onDiscoveryFailure.connect([this] (const std::string&) {
      isDiscoveryFinished = true;
    });

    discover->run();
    advanceClocks(1_ns);
  }

protected:
  const Name name = "/ndn/chunks/test";
  const uint64_t version = 1449227841747;
  util::DummyClientFace face{m_io};
  Options opt;
  unique_ptr<DiscoverVersion> discover;
  optional<Name> discoveredName;
  optional<uint64_t> discoveredVersion;
  bool isDiscoveryFinished = false;
};

BOOST_AUTO_TEST_SUITE(Chunks)
BOOST_FIXTURE_TEST_SUITE(TestDiscoverVersion, DiscoverVersionFixture)

BOOST_AUTO_TEST_CASE(Disabled)
{
  opt.disableVersionDiscovery = true;
  run(name);

  // no version discovery Interest is expressed
  BOOST_CHECK_EQUAL(face.sentInterests.size(), 0);

  BOOST_CHECK_EQUAL(discoveredName.value(), name);
  BOOST_CHECK_EQUAL(discoveredVersion.has_value(), false);
}

BOOST_AUTO_TEST_CASE(NameWithVersion)
{
  // start with a name that already contains a version component
  Name versionedName = Name(name).appendVersion(version);
  run(versionedName);

  // no version discovery Interest is expressed
  BOOST_CHECK_EQUAL(face.sentInterests.size(), 0);

  BOOST_CHECK_EQUAL(discoveredName.value(), versionedName);
  BOOST_CHECK_EQUAL(discoveredVersion.value(), version);
}

BOOST_AUTO_TEST_CASE(Success)
{
  run(name);

  BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);

  Interest discoveryInterest = MetadataObject::makeDiscoveryInterest(name);
  auto lastInterest = face.sentInterests.back();
  BOOST_CHECK_EQUAL(lastInterest.getName(), discoveryInterest.getName());

  // send back a metadata packet with a valid versioned name
  MetadataObject mobject;
  mobject.setVersionedName(Name(name).appendVersion(version));
  face.receive(mobject.makeData(lastInterest.getName(), m_keyChain));
  advanceClocks(1_ns);

  BOOST_CHECK_EQUAL(discoveredVersion.value(), version);
}

BOOST_AUTO_TEST_CASE(InvalidDiscoveredVersionedName)
{
  run(name);

  BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);

  // send back a metadata packet with an invalid versioned name
  MetadataObject mobject;
  mobject.setVersionedName(name);
  face.receive(mobject.makeData(face.sentInterests.back().getName(), m_keyChain));

  // finish discovery process without a resolved version number
  BOOST_CHECK_EQUAL(isDiscoveryFinished, true);
  BOOST_CHECK_EQUAL(discoveredName.has_value(), false);
  BOOST_CHECK_EQUAL(discoveredVersion.has_value(), false);
}

BOOST_AUTO_TEST_CASE(InvalidMetadataPacket)
{
  run(name);

  BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);

  // send back an invalid metadata packet
  Data data(face.sentInterests.back().getName());
  data.setFreshnessPeriod(1_s);
  data.setContentType(tlv::ContentType_Key);
  face.receive(signData(data));

  // finish discovery process without a resolved version number
  BOOST_CHECK_EQUAL(isDiscoveryFinished, true);
  BOOST_CHECK_EQUAL(discoveredName.has_value(), false);
  BOOST_CHECK_EQUAL(discoveredVersion.has_value(), false);
}

BOOST_AUTO_TEST_CASE(MaxRetriesExceeded)
{
  opt.maxRetriesOnTimeoutOrNack = 3;
  run(name);

  BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);

  // timeout or nack discovery Interests
  for (int retries = 0; retries < opt.maxRetriesOnTimeoutOrNack * 2; ++retries) {
    if (retries % 2 == 0) {
      advanceClocks(opt.interestLifetime);
    }
    else {
      face.receive(makeNack(face.sentInterests.back(), lp::NackReason::DUPLICATE));
      advanceClocks(1_ns);
    }

    BOOST_CHECK_EQUAL(isDiscoveryFinished, false);
    BOOST_REQUIRE_EQUAL(face.sentInterests.size(), retries + 2);
  }

  // timeout the last sent Interest
  advanceClocks(opt.interestLifetime);

  // finish discovery process without a resolved version number
  BOOST_CHECK_EQUAL(isDiscoveryFinished, true);
  BOOST_CHECK_EQUAL(discoveredName.has_value(), false);
  BOOST_CHECK_EQUAL(discoveredVersion.has_value(), false);
}

BOOST_AUTO_TEST_CASE(SuccessAfterNackAndTimeout)
{
  opt.maxRetriesOnTimeoutOrNack = 3;
  run(name);

  BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);

  // timeout or nack discovery Interests
  for (int retries = 0; retries < opt.maxRetriesOnTimeoutOrNack * 2; ++retries) {
    if (retries % 2 == 0) {
      advanceClocks(opt.interestLifetime);
    }
    else {
      face.receive(makeNack(face.sentInterests.back(), lp::NackReason::DUPLICATE));
      advanceClocks(1_ns);
    }

    BOOST_CHECK_EQUAL(isDiscoveryFinished, false);
    BOOST_REQUIRE_EQUAL(face.sentInterests.size(), retries + 2);
  }

  // satisfy the last Interest with a valid metadata packet
  MetadataObject mobject;
  mobject.setVersionedName(Name(name).appendVersion(version));
  face.receive(mobject.makeData(face.sentInterests.back().getName(), m_keyChain));
  advanceClocks(1_ns);

  BOOST_CHECK_EQUAL(discoveredVersion.value(), version);
}

BOOST_AUTO_TEST_SUITE_END() // TestDiscoverVersion
BOOST_AUTO_TEST_SUITE_END() // Chunks

} // namespace tests
} // namespace chunks
} // namespace ndn
