/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2013-2020 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library 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 Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, 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.
 */

#include "ndn-cxx/security/detail/certificate-bundle-decoder.hpp"

#include "tests/boost-test.hpp"
#include "tests/identity-management-fixture.hpp"

namespace ndn {
namespace security {
namespace detail {
namespace tests {

class CertificateBundleDecoderFixture : public ndn::tests::IdentityManagementFixture
{
protected:
  CertificateBundleDecoderFixture()
  {
    auto id1 = addIdentity("/hello/world1");
    auto cert1 = id1.getDefaultKey().getDefaultCertificate();
    certBlock1 = cert1.wireEncode();
    m_certs.push_back(certBlock1);

    auto id2 = addIdentity("/hello/world2");
    auto cert2 = id2.getDefaultKey().getDefaultCertificate();
    certBlock2 = cert2.wireEncode();
    m_certs.push_back(certBlock2);

    cbd.onCertDecoded.connect([this] (const Certificate& receivedCert) {
      BOOST_CHECK_EQUAL(receivedCert.wireEncode(), m_certs.at(nCertsCompleted));
      ++nCertsCompleted;
    });
  }

protected:
  CertificateBundleDecoder cbd;
  Block certBlock1;
  Block certBlock2;
  int nCertsCompleted = 0;

private:
  std::vector<Block> m_certs;
};

BOOST_AUTO_TEST_SUITE(Security)
BOOST_FIXTURE_TEST_SUITE(TestCertificateBundleDecoder, CertificateBundleDecoderFixture)

BOOST_AUTO_TEST_CASE(EmptySegment)
{
  BOOST_CHECK_EQUAL(cbd.hasError(), false);
  cbd.append(Block(tlv::Content));
  BOOST_CHECK_EQUAL(cbd.hasError(), false);
  BOOST_CHECK_EQUAL(nCertsCompleted, 0);
}

BOOST_AUTO_TEST_CASE(OneCertOneSegment)
{
  // Segment contains full certificate
  Data d;
  d.setContent(certBlock1);

  cbd.append(d.getContent());
  BOOST_CHECK_EQUAL(cbd.hasError(), false);
  BOOST_CHECK_EQUAL(nCertsCompleted, 1);
}

BOOST_AUTO_TEST_CASE(TwoCertsOneSegment)
{
  // Segment contains two full certificates
  auto buf = std::make_shared<Buffer>(certBlock1.begin(), certBlock1.end());
  buf->insert(buf->end(), certBlock2.begin(), certBlock2.end());
  Data d;
  d.setContent(std::move(buf));

  cbd.append(d.getContent());
  BOOST_CHECK_EQUAL(cbd.hasError(), false);
  BOOST_CHECK_EQUAL(nCertsCompleted, 2);
}

BOOST_AUTO_TEST_CASE(TwoCertsMultipleSegments)
{
  // First segment contains first 250 bytes of cert1
  Data d;
  d.setContent(certBlock1.wire(), 250);

  // Second segment contains the rest of cert1 and the first 100 bytes of cert2
  auto buf = std::make_shared<Buffer>(certBlock1.begin() + 250, certBlock1.end());
  buf->insert(buf->end(), certBlock2.begin(), certBlock2.begin() + 100);
  Data d2;
  d2.setContent(std::move(buf));

  // Third segment contains the rest of cert2
  Data d3;
  d3.setContent(std::make_shared<Buffer>(certBlock2.begin() + 100, certBlock2.end()));

  cbd.append(d.getContent());
  BOOST_CHECK_EQUAL(cbd.hasError(), false);
  BOOST_CHECK_EQUAL(nCertsCompleted, 0);

  cbd.append(d2.getContent());
  BOOST_CHECK_EQUAL(cbd.hasError(), false);
  BOOST_CHECK_EQUAL(nCertsCompleted, 1);

  cbd.append(d3.getContent());
  BOOST_CHECK_EQUAL(cbd.hasError(), false);
  BOOST_CHECK_EQUAL(nCertsCompleted, 2);
}

BOOST_AUTO_TEST_CASE(InvalidCert)
{
  // First segment contains all of cert1
  Data d;
  d.setContent(certBlock1);

  const uint8_t buf[] = {
    0x06, 0x20, // Data
          0x07, 0x11, // Name
                0x08, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, // GenericNameComponent 'hello'
                0x08, 0x01, 0x31, // GenericNameComponent '1'
                0x08, 0x05, 0x77, 0x6f, 0x72, 0x6c, 0x64, // GenericNameComponent 'world'
          0x14, 0x00, // MetaInfo empty
          0x15, 0x00, // Content empty
          0x16, 0x05, // SignatureInfo
                0x1b, 0x01, 0x01, // SignatureType RSA
                0x1c, 0x00, // KeyLocator empty
          0x17, 0x00 // SignatureValue empty
  };
  // Second segment contains non-Certificate data
  Data d2;
  d2.setContent(buf, sizeof(buf));

  // Third segment contains all of cert2
  Data d3;
  d3.setContent(certBlock2);

  cbd.append(d.getContent());
  BOOST_CHECK_EQUAL(cbd.hasError(), false);
  BOOST_CHECK_EQUAL(nCertsCompleted, 1);

  BOOST_CHECK_EXCEPTION(cbd.append(d2.getContent()), tlv::Error, [] (const auto& e) {
    return e.what() == "Name does not follow the naming convention for certificate"s;
  });
  BOOST_CHECK_EQUAL(cbd.hasError(), true);
  BOOST_CHECK_EQUAL(nCertsCompleted, 1);

  BOOST_CHECK_EXCEPTION(cbd.append(d3.getContent()), tlv::Error, [] (const auto& e) {
    return e.what() == "Unrecoverable decoding error"s;
  });
  BOOST_CHECK_EQUAL(cbd.hasError(), true);
  BOOST_CHECK_EQUAL(nCertsCompleted, 1);
}

BOOST_AUTO_TEST_CASE(UnrecognizedCritical)
{
  // First segment contains an unrecognized critical element
  Data d;
  d.setContent("050B07030102030A0404050607"_block);

  // Second segment contains cert1
  Data d2;
  d2.setContent(certBlock1);

  BOOST_CHECK_EXCEPTION(cbd.append(d.getContent()), tlv::Error, [] (const auto& e) {
    return e.what() == "Unrecognized element of critical type 5"s;
  });
  BOOST_CHECK_EQUAL(cbd.hasError(), true);
  BOOST_CHECK_EQUAL(nCertsCompleted, 0);

  BOOST_CHECK_EXCEPTION(cbd.append(d2.getContent()), tlv::Error, [] (const auto& e) {
    return e.what() == "Unrecoverable decoding error"s;
  });
  BOOST_CHECK_EQUAL(cbd.hasError(), true);
  BOOST_CHECK_EQUAL(nCertsCompleted, 0);
}

BOOST_AUTO_TEST_CASE(UnrecognizedNonCritical)
{
  // First segment contains an unrecognized non-critical element
  Data d;
  d.setContent("4202CAFE"_block);

  // Second segment contains cert1
  Data d2;
  d2.setContent(certBlock1);

  cbd.append(d.getContent());
  BOOST_CHECK_EQUAL(cbd.hasError(), false);
  BOOST_CHECK_EQUAL(nCertsCompleted, 0);

  cbd.append(d2.getContent());
  BOOST_CHECK_EQUAL(cbd.hasError(), false);
  BOOST_CHECK_EQUAL(nCertsCompleted, 1);
}

BOOST_AUTO_TEST_SUITE_END() // TestCertificateBundleEncoderDecoder
BOOST_AUTO_TEST_SUITE_END() // Security

} // namespace tests
} // namespace detail
} // namespace security
} // namespace ndn
