/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2013-2022 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/key-chain-fixture.hpp"

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

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

    auto id2 = m_keyChain.createIdentity("/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;
  size_t 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(make_span(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);

  // 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
